From b068d26fad1de316de4d6357e38afcf2193f6e32 Mon Sep 17 00:00:00 2001 From: Liubov Batanina Date: Thu, 7 Feb 2019 11:52:27 +0300 Subject: [PATCH 01/21] Using IE backend for normalize layer tests --- modules/dnn/src/layers/normalize_bbox_layer.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/modules/dnn/src/layers/normalize_bbox_layer.cpp b/modules/dnn/src/layers/normalize_bbox_layer.cpp index 4766f1704e..b5d98e0054 100644 --- a/modules/dnn/src/layers/normalize_bbox_layer.cpp +++ b/modules/dnn/src/layers/normalize_bbox_layer.cpp @@ -65,16 +65,12 @@ public: { if (backendId == DNN_BACKEND_INFERENCE_ENGINE) { - if (pnorm != 2) + if (!(pnorm == 2 || pnorm == 1)) { return false; - if (!blobs.empty()) - return true; - if (preferableTarget == DNN_TARGET_MYRIAD) - return !acrossSpatial; - return startAxis == 1 && (!acrossSpatial || endAxis > 1); + } + return preferableTarget == DNN_TARGET_MYRIAD ? !acrossSpatial : startAxis == 1; } - else - return backendId == DNN_BACKEND_OPENCV; + return backendId == DNN_BACKEND_OPENCV; } bool getMemoryShapes(const std::vector &inputs, From 6b4becfd0397158a4686d0c13d6f98f4660f6301 Mon Sep 17 00:00:00 2001 From: Liubov Batanina Date: Mon, 11 Feb 2019 12:39:28 +0300 Subject: [PATCH 02/21] Enabled tests on IE backend --- modules/dnn/src/layers/normalize_bbox_layer.cpp | 2 +- modules/dnn/test/test_backends.cpp | 2 +- modules/dnn/test/test_torch_importer.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/dnn/src/layers/normalize_bbox_layer.cpp b/modules/dnn/src/layers/normalize_bbox_layer.cpp index b5d98e0054..53a5f407d0 100644 --- a/modules/dnn/src/layers/normalize_bbox_layer.cpp +++ b/modules/dnn/src/layers/normalize_bbox_layer.cpp @@ -65,7 +65,7 @@ public: { if (backendId == DNN_BACKEND_INFERENCE_ENGINE) { - if (!(pnorm == 2 || pnorm == 1)) { + if (pnorm != 2) { return false; } return preferableTarget == DNN_TARGET_MYRIAD ? !acrossSpatial : startAxis == 1; diff --git a/modules/dnn/test/test_backends.cpp b/modules/dnn/test/test_backends.cpp index 1d97cfc088..66e80a1fe9 100644 --- a/modules/dnn/test/test_backends.cpp +++ b/modules/dnn/test/test_backends.cpp @@ -226,7 +226,7 @@ TEST_P(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages) TEST_P(DNNTestNetwork, OpenFace) { #if defined(INF_ENGINE_RELEASE) -#if (INF_ENGINE_RELEASE < 2018030000 || INF_ENGINE_RELEASE == 2018050000) +#if (INF_ENGINE_RELEASE < 2018030000) if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) throw SkipTestException(""); #elif INF_ENGINE_RELEASE < 2018040000 diff --git a/modules/dnn/test/test_torch_importer.cpp b/modules/dnn/test/test_torch_importer.cpp index 046bd65b86..99695ca031 100644 --- a/modules/dnn/test/test_torch_importer.cpp +++ b/modules/dnn/test/test_torch_importer.cpp @@ -272,12 +272,12 @@ class Test_Torch_nets : public DNNTestLayer {}; TEST_P(Test_Torch_nets, OpenFace_accuracy) { -#if defined(INF_ENGINE_RELEASE) && (INF_ENGINE_RELEASE < 2018030000 || INF_ENGINE_RELEASE == 2018050000) +#if defined(INF_ENGINE_RELEASE) && (INF_ENGINE_RELEASE < 2018030000) if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) throw SkipTestException(""); #endif checkBackend(); - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16) + if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16 && INF_ENGINE_RELEASE != 2018050000) throw SkipTestException(""); const string model = findDataFile("dnn/openface_nn4.small2.v1.t7", false); From 21eb60f88bce4e9e4bedffcd28b29c75c404e788 Mon Sep 17 00:00:00 2001 From: Namgoo Lee Date: Tue, 12 Feb 2019 08:24:57 +0000 Subject: [PATCH 03/21] cudalegacy: Use safe block scan function --- .../src/cuda/NCVHaarObjectDetection.cu | 93 +------------- modules/cudalegacy/src/cuda/NPP_staging.cu | 116 +----------------- .../cudev/include/opencv2/cudev/warp/scan.hpp | 2 +- 3 files changed, 9 insertions(+), 202 deletions(-) diff --git a/modules/cudalegacy/src/cuda/NCVHaarObjectDetection.cu b/modules/cudalegacy/src/cuda/NCVHaarObjectDetection.cu index 1a32baa438..00b3fd297f 100644 --- a/modules/cudalegacy/src/cuda/NCVHaarObjectDetection.cu +++ b/modules/cudalegacy/src/cuda/NCVHaarObjectDetection.cu @@ -59,8 +59,7 @@ #include #include -#include "opencv2/core/cuda/warp.hpp" -#include "opencv2/core/cuda/warp_shuffle.hpp" +#include "opencv2/cudev.hpp" #include "opencv2/opencv_modules.hpp" @@ -77,92 +76,6 @@ #include "NCVAlg.hpp" -//============================================================================== -// -// BlockScan file -// -//============================================================================== - - -NCV_CT_ASSERT(K_WARP_SIZE == 32); //this is required for the manual unroll of the loop in warpScanInclusive - - -//Almost the same as naive scan1Inclusive, but doesn't need __syncthreads() -//assuming size <= WARP_SIZE and size is power of 2 -__device__ Ncv32u warpScanInclusive(Ncv32u idata, volatile Ncv32u *s_Data) -{ -#if __CUDA_ARCH__ >= 300 - const unsigned int laneId = cv::cuda::device::Warp::laneId(); - - // scan on shuffl functions - #pragma unroll - for (int i = 1; i <= (K_WARP_SIZE / 2); i *= 2) - { - const Ncv32u n = cv::cuda::device::shfl_up(idata, i); - if (laneId >= i) - idata += n; - } - - return idata; -#else - Ncv32u pos = 2 * threadIdx.x - (threadIdx.x & (K_WARP_SIZE - 1)); - s_Data[pos] = 0; - pos += K_WARP_SIZE; - s_Data[pos] = idata; - - s_Data[pos] += s_Data[pos - 1]; - s_Data[pos] += s_Data[pos - 2]; - s_Data[pos] += s_Data[pos - 4]; - s_Data[pos] += s_Data[pos - 8]; - s_Data[pos] += s_Data[pos - 16]; - - return s_Data[pos]; -#endif -} - -__device__ __forceinline__ Ncv32u warpScanExclusive(Ncv32u idata, volatile Ncv32u *s_Data) -{ - return warpScanInclusive(idata, s_Data) - idata; -} - -template -__device__ Ncv32u scan1Inclusive(Ncv32u idata, volatile Ncv32u *s_Data) -{ - if (tiNumScanThreads > K_WARP_SIZE) - { - //Bottom-level inclusive warp scan - Ncv32u warpResult = warpScanInclusive(idata, s_Data); - - //Save top elements of each warp for exclusive warp scan - //sync to wait for warp scans to complete (because s_Data is being overwritten) - __syncthreads(); - if( (threadIdx.x & (K_WARP_SIZE - 1)) == (K_WARP_SIZE - 1) ) - { - s_Data[threadIdx.x >> K_LOG2_WARP_SIZE] = warpResult; - } - - //wait for warp scans to complete - __syncthreads(); - - if( threadIdx.x < (tiNumScanThreads / K_WARP_SIZE) ) - { - //grab top warp elements - Ncv32u val = s_Data[threadIdx.x]; - //calculate exclusive scan and write back to shared memory - s_Data[threadIdx.x] = warpScanExclusive(val, s_Data); - } - - //return updated warp scans with exclusive scan results - __syncthreads(); - return warpResult + s_Data[threadIdx.x >> K_LOG2_WARP_SIZE]; - } - else - { - return warpScanInclusive(idata, s_Data); - } -} - - //============================================================================== // // HaarClassifierCascade file @@ -260,11 +173,11 @@ __device__ void compactBlockWriteOutAnchorParallel(Ncv32u threadPassFlag, Ncv32u { #if __CUDA_ARCH__ && __CUDA_ARCH__ >= 110 - __shared__ Ncv32u shmem[NUM_THREADS_ANCHORSPARALLEL * 2]; + __shared__ Ncv32u shmem[NUM_THREADS_ANCHORSPARALLEL]; __shared__ Ncv32u numPassed; __shared__ Ncv32u outMaskOffset; - Ncv32u incScan = scan1Inclusive(threadPassFlag, shmem); + Ncv32u incScan = cv::cudev::blockScanInclusive(threadPassFlag, shmem, threadIdx.x); __syncthreads(); if (threadIdx.x == NUM_THREADS_ANCHORSPARALLEL-1) diff --git a/modules/cudalegacy/src/cuda/NPP_staging.cu b/modules/cudalegacy/src/cuda/NPP_staging.cu index a96f44ff99..90880d56cc 100644 --- a/modules/cudalegacy/src/cuda/NPP_staging.cu +++ b/modules/cudalegacy/src/cuda/NPP_staging.cu @@ -45,8 +45,7 @@ #include #include -#include "opencv2/core/cuda/warp.hpp" -#include "opencv2/core/cuda/warp_shuffle.hpp" +#include "opencv2/cudev.hpp" #include "opencv2/cudalegacy/NPP_staging.hpp" @@ -81,111 +80,6 @@ cudaStream_t nppStSetActiveCUDAstream(cudaStream_t cudaStream) } -//============================================================================== -// -// BlockScan.cuh -// -//============================================================================== - - -NCV_CT_ASSERT(K_WARP_SIZE == 32); //this is required for the manual unroll of the loop in warpScanInclusive - - -//Almost the same as naive scan1Inclusive, but doesn't need __syncthreads() -//assuming size <= WARP_SIZE and size is power of 2 -template -inline __device__ T warpScanInclusive(T idata, volatile T *s_Data) -{ -#if __CUDA_ARCH__ >= 300 - const unsigned int laneId = cv::cuda::device::Warp::laneId(); - - // scan on shuffl functions - #pragma unroll - for (int i = 1; i <= (K_WARP_SIZE / 2); i *= 2) - { - const T n = cv::cuda::device::shfl_up(idata, i); - if (laneId >= i) - idata += n; - } - - return idata; -#else - Ncv32u pos = 2 * threadIdx.x - (threadIdx.x & (K_WARP_SIZE - 1)); - s_Data[pos] = 0; - pos += K_WARP_SIZE; - s_Data[pos] = idata; - - s_Data[pos] += s_Data[pos - 1]; - s_Data[pos] += s_Data[pos - 2]; - s_Data[pos] += s_Data[pos - 4]; - s_Data[pos] += s_Data[pos - 8]; - s_Data[pos] += s_Data[pos - 16]; - - return s_Data[pos]; -#endif -} -inline __device__ Ncv64u warpScanInclusive(Ncv64u idata, volatile Ncv64u *s_Data) -{ - Ncv32u pos = 2 * threadIdx.x - (threadIdx.x & (K_WARP_SIZE - 1)); - s_Data[pos] = 0; - pos += K_WARP_SIZE; - s_Data[pos] = idata; - - s_Data[pos] += s_Data[pos - 1]; - s_Data[pos] += s_Data[pos - 2]; - s_Data[pos] += s_Data[pos - 4]; - s_Data[pos] += s_Data[pos - 8]; - s_Data[pos] += s_Data[pos - 16]; - - return s_Data[pos]; -} - - -template -inline __device__ T warpScanExclusive(T idata, volatile T *s_Data) -{ - return warpScanInclusive(idata, s_Data) - idata; -} - - -template -inline __device__ T blockScanInclusive(T idata, volatile T *s_Data) -{ - if (tiNumScanThreads > K_WARP_SIZE) - { - //Bottom-level inclusive warp scan - T warpResult = warpScanInclusive(idata, s_Data); - - //Save top elements of each warp for exclusive warp scan - //sync to wait for warp scans to complete (because s_Data is being overwritten) - __syncthreads(); - if( (threadIdx.x & (K_WARP_SIZE - 1)) == (K_WARP_SIZE - 1) ) - { - s_Data[threadIdx.x >> K_LOG2_WARP_SIZE] = warpResult; - } - - //wait for warp scans to complete - __syncthreads(); - - if( threadIdx.x < (tiNumScanThreads / K_WARP_SIZE) ) - { - //grab top warp elements - T val = s_Data[threadIdx.x]; - //calculate exclusive scan and write back to shared memory - s_Data[threadIdx.x] = warpScanExclusive(val, s_Data); - } - - //return updated warp scans with exclusive scan results - __syncthreads(); - return warpResult + s_Data[threadIdx.x >> K_LOG2_WARP_SIZE]; - } - else - { - return warpScanInclusive(idata, s_Data); - } -} - - //============================================================================== // // IntegralImage.cu @@ -280,7 +174,7 @@ __global__ void scanRows(T_in *d_src, Ncv32u texOffs, Ncv32u srcWidth, Ncv32u sr Ncv32u numBuckets = (srcWidth + NUM_SCAN_THREADS - 1) >> LOG2_NUM_SCAN_THREADS; Ncv32u offsetX = 0; - __shared__ T_out shmem[NUM_SCAN_THREADS * 2]; + __shared__ T_out shmem[NUM_SCAN_THREADS]; __shared__ T_out carryElem; carryElem = 0; __syncthreads(); @@ -301,7 +195,7 @@ __global__ void scanRows(T_in *d_src, Ncv32u texOffs, Ncv32u srcWidth, Ncv32u sr curElemMod = _scanElemOp::scanElemOp(curElem); //inclusive scan - curScanElem = blockScanInclusive(curElemMod, shmem); + curScanElem = cv::cudev::blockScanInclusive(curElemMod, shmem, threadIdx.x); if (curElemOffs <= srcWidth) { @@ -1290,7 +1184,7 @@ __global__ void removePass1Scan(Ncv32u *d_src, Ncv32u srcLen, return; } - __shared__ Ncv32u shmem[NUM_REMOVE_THREADS * 2]; + __shared__ Ncv32u shmem[NUM_REMOVE_THREADS]; Ncv32u scanElem = 0; if (elemAddrIn < srcLen) @@ -1305,7 +1199,7 @@ __global__ void removePass1Scan(Ncv32u *d_src, Ncv32u srcLen, } } - Ncv32u localScanInc = blockScanInclusive(scanElem, shmem); + Ncv32u localScanInc = cv::cudev::blockScanInclusive(scanElem, shmem, threadIdx.x); __syncthreads(); if (elemAddrIn < srcLen) diff --git a/modules/cudev/include/opencv2/cudev/warp/scan.hpp b/modules/cudev/include/opencv2/cudev/warp/scan.hpp index bab462973f..c0afb552a9 100644 --- a/modules/cudev/include/opencv2/cudev/warp/scan.hpp +++ b/modules/cudev/include/opencv2/cudev/warp/scan.hpp @@ -98,7 +98,7 @@ __device__ T warpScanInclusive(T data, volatile T* smem, uint tid) #pragma unroll for (int i = 1; i <= (WARP_SIZE / 2); i *= 2) { - const T val = shfl_up(data, i); + const T val = __shfl_up(data, i, WARP_SIZE); if (laneId >= i) data += val; } From 5aceac6b93e3ee9508ea72f87012e3f5c4deb9a2 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 11 Feb 2019 16:13:55 +0300 Subject: [PATCH 04/21] core: clone sum.simd.hpp --- modules/core/src/{sum.cpp => sum.simd.hpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/core/src/{sum.cpp => sum.simd.hpp} (100%) diff --git a/modules/core/src/sum.cpp b/modules/core/src/sum.simd.hpp similarity index 100% rename from modules/core/src/sum.cpp rename to modules/core/src/sum.simd.hpp From 6e88bff3e3f413b5ee412975365757e6a840e9ab Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 11 Feb 2019 16:14:43 +0300 Subject: [PATCH 05/21] core: clone sum.dispatch.cpp --- modules/core/src/{sum.cpp => sum.dispatch.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/core/src/{sum.cpp => sum.dispatch.cpp} (100%) diff --git a/modules/core/src/sum.cpp b/modules/core/src/sum.dispatch.cpp similarity index 100% rename from modules/core/src/sum.cpp rename to modules/core/src/sum.dispatch.cpp From 094615b2c56f31e3a1a0d42799c802ebd7dca383 Mon Sep 17 00:00:00 2001 From: Stefan Dragnev Date: Tue, 12 Feb 2019 13:22:13 +0100 Subject: [PATCH 06/21] update libpng to 1.6.36 * re-enabled NEON routines for arm64 --- 3rdparty/libpng/CHANGES | 29 +- 3rdparty/libpng/CMakeLists.txt | 9 +- 3rdparty/libpng/LICENSE | 175 +++++----- 3rdparty/libpng/README | 111 +++---- 3rdparty/libpng/arm/arm_init.c | 3 +- 3rdparty/libpng/arm/filter_neon.S | 2 +- 3rdparty/libpng/arm/filter_neon_intrinsics.c | 27 +- 3rdparty/libpng/arm/palette_neon_intrinsics.c | 149 +++++++++ .../libpng/intel/filter_sse2_intrinsics.c | 37 +-- 3rdparty/libpng/intel/intel_init.c | 3 +- 3rdparty/libpng/png.c | 50 ++- 3rdparty/libpng/png.h | 303 ++++++++---------- 3rdparty/libpng/pngconf.h | 16 +- 3rdparty/libpng/pngdebug.h | 6 +- 3rdparty/libpng/pngerror.c | 12 +- 3rdparty/libpng/pngget.c | 6 +- 3rdparty/libpng/pnginfo.h | 6 +- 3rdparty/libpng/pnglibconf.h | 11 +- 3rdparty/libpng/pngmem.c | 6 +- 3rdparty/libpng/pngpread.c | 16 +- 3rdparty/libpng/pngpriv.h | 38 ++- 3rdparty/libpng/pngread.c | 32 +- 3rdparty/libpng/pngrio.c | 6 +- 3rdparty/libpng/pngrtran.c | 88 +++-- 3rdparty/libpng/pngrutil.c | 39 ++- 3rdparty/libpng/pngset.c | 12 +- 3rdparty/libpng/pngstruct.h | 10 +- 3rdparty/libpng/pngtrans.c | 12 +- 3rdparty/libpng/pngwio.c | 6 +- 3rdparty/libpng/pngwrite.c | 38 ++- 3rdparty/libpng/pngwtran.c | 11 +- 3rdparty/libpng/pngwutil.c | 38 +-- .../libpng/powerpc/filter_vsx_intrinsics.c | 15 +- 3rdparty/libpng/powerpc/powerpc_init.c | 3 +- 34 files changed, 749 insertions(+), 576 deletions(-) create mode 100644 3rdparty/libpng/arm/palette_neon_intrinsics.c diff --git a/3rdparty/libpng/CHANGES b/3rdparty/libpng/CHANGES index 0ed6a11872..bdd4480654 100644 --- a/3rdparty/libpng/CHANGES +++ b/3rdparty/libpng/CHANGES @@ -6063,9 +6063,34 @@ Version 1.6.35 [July 15, 2018] Added missing parentheses to a macro definition (suggested by "irwir" in GitHub issue #216) +Version 1.6.36 [December 1, 2018] + Optimized png_do_expand_palette for ARM processors. + Improved performance by around 10-22% on a recent ARM Chromebook. + (Contributed by Richard Townsend, ARM Holdings) + Fixed manipulation of machine-specific optimization options. + (Contributed by Vicki Pfau) + Used memcpy instead of manual pointer arithmetic on Intel SSE2. + (Contributed by Samuel Williams) + Fixed build errors with MSVC on ARM64. + (Contributed by Zhijie Liang) + Fixed detection of libm in CMakeLists. + (Contributed by Cameron Cawley) + Fixed incorrect creation of pkg-config file in CMakeLists. + (Contributed by Kyle Bentley) + Fixed the CMake build on Windows MSYS by avoiding symlinks. + Fixed a build warning on OpenBSD. + (Contributed by Theo Buehler) + Fixed various typos in comments. + (Contributed by "luz.paz") + Raised the minimum required CMake version from 3.0.2 to 3.1. + Removed yet more of the vestigial support for pre-ANSI C compilers. + Removed ancient makefiles for ancient systems that have been broken + across all previous libpng-1.6.x versions. + Removed the Y2K compliance statement and the export control + information. + Applied various code style and documentation fixes. + Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement to subscribe). - -Glenn R-P diff --git a/3rdparty/libpng/CMakeLists.txt b/3rdparty/libpng/CMakeLists.txt index 5a56bf93cc..9100cd20d6 100644 --- a/3rdparty/libpng/CMakeLists.txt +++ b/3rdparty/libpng/CMakeLists.txt @@ -29,8 +29,11 @@ file(GLOB lib_hdrs *.h) if(ARM OR AARCH64) - if(ENABLE_NEON AND NOT AARCH64) - list(APPEND lib_srcs arm/arm_init.c arm/filter_neon.S arm/filter_neon_intrinsics.c) + if(ENABLE_NEON) + if(NOT AARCH64) + list(APPEND lib_srcs arm/filter_neon.S) + endif() + list(APPEND lib_srcs arm/arm_init.c arm/filter_neon_intrinsics.c arm/palette_neon_intrinsics.c) add_definitions(-DPNG_ARM_NEON_OPT=2) else() add_definitions(-DPNG_ARM_NEON_OPT=0) # NEON assembler is not supported @@ -63,7 +66,7 @@ endif(MSVC) add_library(${PNG_LIBRARY} STATIC ${lib_srcs} ${lib_hdrs}) target_link_libraries(${PNG_LIBRARY} ${ZLIB_LIBRARIES}) -ocv_warnings_disable(CMAKE_C_FLAGS -Wundef -Wcast-align -Wimplicit-fallthrough) +ocv_warnings_disable(CMAKE_C_FLAGS -Wundef -Wcast-align -Wimplicit-fallthrough -Wunused-parameter -Wsign-compare) set_target_properties(${PNG_LIBRARY} PROPERTIES OUTPUT_NAME ${PNG_LIBRARY} diff --git a/3rdparty/libpng/LICENSE b/3rdparty/libpng/LICENSE index 6ee9c8f554..62ab8e48dc 100644 --- a/3rdparty/libpng/LICENSE +++ b/3rdparty/libpng/LICENSE @@ -1,14 +1,43 @@ +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE +========================================= -This copy of the libpng notices is provided for your convenience. In case of -any discrepancy between this copy and the notices in the file png.h that is -included in the libpng distribution, the latter shall prevail. +PNG Reference Library License version 2 +--------------------------------------- -COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + * Copyright (c) 1995-2018 The PNG Reference Library Authors. + * Copyright (c) 2018 Cosmin Truta. + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + * Copyright (c) 1996-1997 Andreas Dilger. + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. -If you modify libpng you may insert additional notices immediately following -this sentence. +The software is supplied "as is", without warranty of any kind, +express or implied, including, without limitation, the warranties +of merchantability, fitness for a particular purpose, title, and +non-infringement. In no even shall the Copyright owners, or +anyone distributing the software, be liable for any damages or +other liability, whether in contract, tort or otherwise, arising +from, out of, or in connection with the software, or the use or +other dealings in the software, even if advised of the possibility +of such damage. -This code is released under the libpng license. +Permission is hereby granted to use, copy, modify, and distribute +this software, or portions hereof, for any purpose, without fee, +subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you + use this software in a product, an acknowledgment in the product + documentation would be appreciated, but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + + +PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35) +----------------------------------------------------------------------- libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are @@ -16,38 +45,38 @@ derived from libpng-1.0.6, and are distributed according to the same disclaimer and license as libpng-1.0.6 with the following individuals added to the list of Contributing Authors: - Simon-Pierre Cadieux - Eric S. Raymond - Mans Rullgard - Cosmin Truta - Gilles Vollant - James Yu - Mandar Sahastrabuddhe - Google Inc. - Vadim Barkov + Simon-Pierre Cadieux + Eric S. Raymond + Mans Rullgard + Cosmin Truta + Gilles Vollant + James Yu + Mandar Sahastrabuddhe + Google Inc. + Vadim Barkov and with the following additions to the disclaimer: - There is no warranty against interference with your enjoyment of the - library or against infringement. There is no warranty that our - efforts or the library will fulfill any of your particular purposes - or needs. This library is provided with all faults, and the entire - risk of satisfactory quality, performance, accuracy, and effort is with - the user. + There is no warranty against interference with your enjoyment of + the library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is + with the user. Some files in the "contrib" directory and some configure-generated -files that are distributed with libpng have other copyright owners and +files that are distributed with libpng have other copyright owners, and are released under other open source licenses. libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from libpng-0.96, and are distributed according to the same disclaimer and -license as libpng-0.96, with the following individuals added to the list -of Contributing Authors: +license as libpng-0.96, with the following individuals added to the +list of Contributing Authors: - Tom Lane - Glenn Randers-Pehrson - Willem van Schaik + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik libpng versions 0.89, June 1996, through 0.96, May 1997, are Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, @@ -55,14 +84,14 @@ and are distributed according to the same disclaimer and license as libpng-0.88, with the following individuals added to the list of Contributing Authors: - John Bowler - Kevin Bracey - Sam Bushell - Magnus Holmgren - Greg Roelofs - Tom Tanner + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner -Some files in the "scripts" directory have other copyright owners +Some files in the "scripts" directory have other copyright owners, but are released under this license. libpng versions 0.5, May 1995, through 0.88, January 1996, are @@ -71,63 +100,35 @@ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. For the purposes of this copyright and license, "Contributing Authors" is defined as the following set of individuals: - Andreas Dilger - Dave Martindale - Guy Eric Schalnat - Paul Schmidt - Tim Wegner - -The PNG Reference Library is supplied "AS IS". The Contributing Authors -and Group 42, Inc. disclaim all warranties, expressed or implied, -including, without limitation, the warranties of merchantability and of -fitness for any purpose. The Contributing Authors and Group 42, Inc. -assume no liability for direct, indirect, incidental, special, exemplary, -or consequential damages, which may result from the use of the PNG -Reference Library, even if advised of the possibility of such damage. + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing +Authors and Group 42, Inc. disclaim all warranties, expressed or +implied, including, without limitation, the warranties of +merchantability and of fitness for any purpose. The Contributing +Authors and Group 42, Inc. assume no liability for direct, indirect, +incidental, special, exemplary, or consequential damages, which may +result from the use of the PNG Reference Library, even if advised of +the possibility of such damage. Permission is hereby granted to use, copy, modify, and distribute this source code, or portions hereof, for any purpose, without fee, subject to the following restrictions: - 1. The origin of this source code must not be misrepresented. - - 2. Altered versions must be plainly marked as such and must not - be misrepresented as being the original source. - - 3. This Copyright notice may not be removed or altered from any - source or altered source distribution. - -The Contributing Authors and Group 42, Inc. specifically permit, without -fee, and encourage the use of this source code as a component to -supporting the PNG file format in commercial products. If you use this -source code in a product, acknowledgment is not required but would be -appreciated. - -END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. - -TRADEMARK: - -The name "libpng" has not been registered by the Copyright owner -as a trademark in any jurisdiction. However, because libpng has -been distributed and maintained world-wide, continually since 1995, -the Copyright owner claims "common-law trademark protection" in any -jurisdiction where common-law trademark is recognized. - -OSI CERTIFICATION: - -Libpng is OSI Certified Open Source Software. OSI Certified Open Source is -a certification mark of the Open Source Initiative. OSI has not addressed -the additional disclaimers inserted at version 1.0.7. + 1. The origin of this source code must not be misrepresented. -EXPORT CONTROL: + 2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. -The Copyright owner believes that the Export Control Classification -Number (ECCN) for libpng is EAR99, which means not subject to export -controls or International Traffic in Arms Regulations (ITAR) because -it is open source, publicly available software, that does not contain -any encryption software. See the EAR, paragraphs 734.3(b)(3) and -734.7(b). + 3. This Copyright notice may not be removed or altered from any + source or altered source distribution. -Glenn Randers-Pehrson -glennrp at users.sourceforge.net -July 15, 2018 +The Contributing Authors and Group 42, Inc. specifically permit, +without fee, and encourage the use of this source code as a component +to supporting the PNG file format in commercial products. If you use +this source code in a product, acknowledgment is not required but would +be appreciated. diff --git a/3rdparty/libpng/README b/3rdparty/libpng/README index f098b27f39..e41e0f549b 100644 --- a/3rdparty/libpng/README +++ b/3rdparty/libpng/README @@ -1,15 +1,16 @@ -README for libpng version 1.6.35 - July 15, 2018 (shared library 16.0) -See the note about version numbers near the top of png.h +README for libpng version 1.6.36 - December 1, 2018 +=================================================== +See the note about version numbers near the top of png.h. See INSTALL for instructions on how to install libpng. Libpng comes in several distribution formats. Get libpng-*.tar.gz or -libpng-*.tar.xz or if you want UNIX-style line endings in the text files, -or lpng*.7z or lpng*.zip if you want DOS-style line endings. +libpng-*.tar.xz or if you want UNIX-style line endings in the text +files, or lpng*.7z or lpng*.zip if you want DOS-style line endings. Version 0.89 was the first official release of libpng. Don't let the -fact that it's the first release fool you. The libpng library has been in -extensive use and testing since mid-1995. By late 1997 it had +fact that it's the first release fool you. The libpng library has been +in extensive use and testing since mid-1995. By late 1997 it had finally gotten to the stage where there hadn't been significant changes to the API in some time, and people have a bad feeling about libraries with versions < 1.0. Version 1.0.0 was released in @@ -60,59 +61,37 @@ the library action on the detection of chunk CRC errors. It is possible to set different actions based on whether the CRC error occurred in a critical or an ancillary chunk. -The changes made to the library, and bugs fixed are based on discussions -on the PNG-implement mailing list and not on material submitted -privately to Guy, Andreas, or Glenn. They will forward any good -suggestions to the list. - -For a detailed description on using libpng, read libpng-manual.txt. For -examples of libpng in a program, see example.c and pngtest.c. For usage -information and restrictions (what little they are) on libpng, see -png.h. For a description on using zlib (the compression library used by -libpng) and zlib's restrictions, see zlib.h +For a detailed description on using libpng, read libpng-manual.txt. +For examples of libpng in a program, see example.c and pngtest.c. For +usage information and restrictions (what little they are) on libpng, +see png.h. For a description on using zlib (the compression library +used by libpng) and zlib's restrictions, see zlib.h I have included a general makefile, as well as several machine and -compiler specific ones, but you may have to modify one for your own needs. +compiler specific ones, but you may have to modify one for your own +needs. You should use zlib 1.0.4 or later to run this, but it MAY work with versions as old as zlib 0.95. Even so, there are bugs in older zlib versions which can cause the output of invalid compression streams for -some images. You will definitely need zlib 1.0.4 or later if you are -taking advantage of the MS-DOS "far" structure allocation for the small -and medium memory models. You should also note that zlib is a -compression library that is useful for more things than just PNG files. -You can use zlib as a drop-in replacement for fread() and fwrite() if -you are so inclined. +some images. + +You should also note that zlib is a compression library that is useful +for more things than just PNG files. You can use zlib as a drop-in +replacement for fread() and fwrite(), if you are so inclined. -zlib should be available at the same place that libpng is, or at zlib.net. +zlib should be available at the same place that libpng is, or at +https://zlib.net. You may also want a copy of the PNG specification. It is available as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find these at http://www.libpng.org/pub/png/pngdocs.html . This code is currently being archived at libpng.sourceforge.io in the -[DOWNLOAD] area, and at http://libpng.download/src . If you -can't find it in any of those places, e-mail me, and I'll help you find it. - -I am not a lawyer, but I believe that the Export Control Classification -Number (ECCN) for libpng is EAR99, which means not subject to export -controls or International Traffic in Arms Regulations (ITAR) because it -is open source, publicly available software, that does not contain any -encryption software. See the EAR, paragraphs 734.3(b)(3) and 734.7(b). - -If you have any code changes, requests, problems, etc., please e-mail -them to me. Also, I'd appreciate any make files or project files, -and any modifications you needed to make to get libpng to compile, -along with a #define variable to tell what compiler/system you are on. -If you needed to add transformations to libpng, or wish libpng would -provide the image in a different way, drop me a note (and code, if -possible), so I can consider supporting the transformation. -Finally, if you get any warning messages when compiling libpng -(note: not zlib), and they are easy to fix, I'd appreciate the -fix. Please mention "libpng" somewhere in the subject line. Thanks. - -This release was created and will be supported by myself (of course -based in a large way on Guy's and Andreas' earlier work), and the PNG +[DOWNLOAD] area, and at http://libpng.download/src . + +This release, based in a large way on Glenn's, Guy's and Andreas' +earlier work, was created and will be supported by myself and the PNG development group. Send comments/corrections/commendations to png-mng-implement at @@ -120,34 +99,21 @@ lists.sourceforge.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement to subscribe). -You can't reach Guy, the original libpng author, at the addresses -given in previous versions of this document. He and Andreas will -read mail addressed to the png-implement list, however. - -Please do not send general questions about PNG. Send them to -png-mng-misc at lists.sf.net (subscription required; visit +Send general questions about the PNG specification to png-mng-misc +at lists.sourceforge.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-misc to -subscribe). If you have a question about something -in the PNG specification that is related to using libpng, send it -to me. Send me any questions that start with "I was using libpng, -and ...". If in doubt, send questions to me. I'll bounce them -to others, if necessary. - -Please do not send suggestions on how to change PNG. We have -been discussing PNG for twenty years now, and it is official and -finished. If you have suggestions for libpng, however, I'll -gladly listen. Even if your suggestion is not used immediately, -it may be used later. +subscribe). Files in this distribution: ANNOUNCE => Announcement of this version, with recent changes + AUTHORS => List of contributing authors CHANGES => Description of changes between libpng versions KNOWNBUG => List of known bugs and deficiencies LICENSE => License to use and redistribute libpng README => This file TODO => Things not implemented in the current library - Y2KINFO => Statement of Y2K compliance + TRADEMARK => Trademark information example.c => Example code for using libpng functions libpng.3 => manual page for libpng (includes libpng-manual.txt) libpng-manual.txt => Description of libpng and its functions @@ -208,15 +174,10 @@ Files in this distribution: scripts => Directory containing scripts for building libpng: (see scripts/README.txt for the list of scripts) -Good luck, and happy coding. - --Glenn Randers-Pehrson (current maintainer, since 1998) - Internet: glennrp at users.sourceforge.net - --Andreas Eric Dilger (former maintainer, 1996-1997) - Internet: adilger at enel.ucalgary.ca - Web: http://www-mddsp.enel.ucalgary.ca/People/adilger/ +Good luck, and happy coding! --Guy Eric Schalnat (original author and former maintainer, 1995-1996) - (formerly of Group 42, Inc) - Internet: gschal at infinet.com + * Cosmin Truta (current maintainer, since 2018) + * Glenn Randers-Pehrson (former maintainer, 1998-2018) + * Andreas Eric Dilger (former maintainer, 1996-1997) + * Guy Eric Schalnat (original author and former maintainer, 1995-1996) + (formerly of Group 42, Inc.) diff --git a/3rdparty/libpng/arm/arm_init.c b/3rdparty/libpng/arm/arm_init.c index 02df812e77..a34ecdbef7 100644 --- a/3rdparty/libpng/arm/arm_init.c +++ b/3rdparty/libpng/arm/arm_init.c @@ -1,14 +1,15 @@ /* arm_init.c - NEON optimised filter functions * + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 2014,2016 Glenn Randers-Pehrson * Written by Mans Rullgard, 2011. - * Last changed in libpng 1.6.22 [May 26, 2016] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ + /* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are * called. */ diff --git a/3rdparty/libpng/arm/filter_neon.S b/3rdparty/libpng/arm/filter_neon.S index 000764cd21..2308aad13e 100644 --- a/3rdparty/libpng/arm/filter_neon.S +++ b/3rdparty/libpng/arm/filter_neon.S @@ -1,9 +1,9 @@ /* filter_neon.S - NEON optimised filter functions * + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 2014,2017 Glenn Randers-Pehrson * Written by Mans Rullgard, 2011. - * Last changed in libpng 1.6.31 [July 27, 2017] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer diff --git a/3rdparty/libpng/arm/filter_neon_intrinsics.c b/3rdparty/libpng/arm/filter_neon_intrinsics.c index ea7e356bcc..553c0be21c 100644 --- a/3rdparty/libpng/arm/filter_neon_intrinsics.c +++ b/3rdparty/libpng/arm/filter_neon_intrinsics.c @@ -1,12 +1,11 @@ /* filter_neon_intrinsics.c - NEON optimised filter functions * + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 2014,2016 Glenn Randers-Pehrson * Written by James Yu , October 2013. * Based on filter_neon.S, written by Mans Rullgard, 2011. * - * Last changed in libpng 1.6.22 [May 26, 2016] - * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h @@ -19,7 +18,11 @@ /* This code requires -mfpu=neon on the command line: */ #if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */ -#include +#if defined(_MSC_VER) && defined(_M_ARM64) +# include +#else +# include +#endif /* libpng row pointers are not necessarily aligned to any particular boundary, * however this code will only work with appropriate alignment. arm/arm_init.c @@ -33,6 +36,11 @@ * 'type'. This is written this way just to hide the GCC strict aliasing * warning; note that the code is safe because there never is an alias between * the input and output pointers. + * + * When compiling with MSVC ARM64, the png_ldr macro can't be passed directly + * to vst4_lane_u32, because of an internal compiler error inside MSVC. + * To avoid this compiler bug, we use a temporary variable (vdest_val) to store + * the result of png_ldr. */ #define png_ldr(type,pointer)\ (temp_pointer = png_ptr(type,pointer), *temp_pointer) @@ -125,12 +133,15 @@ png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row, uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp); uint8x8x4_t vrp = *vrpt; uint32x2x4_t *temp_pointer; + uint32x2x4_t vdest_val; vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]); vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]); vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]); vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]); - vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); + + vdest_val = png_ldr(uint32x2x4_t, &vdest); + vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0); } PNG_UNUSED(prev_row) @@ -223,6 +234,7 @@ png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row, uint8x8x4_t *vrpt, *vppt; uint8x8x4_t vrp, vpp; uint32x2x4_t *temp_pointer; + uint32x2x4_t vdest_val; vtmp = vld4_u32(png_ptr(uint32_t,rp)); vrpt = png_ptr(uint8x8x4_t,&vtmp); @@ -240,7 +252,8 @@ png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row, vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]); vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]); - vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); + vdest_val = png_ldr(uint32x2x4_t, &vdest); + vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0); } } @@ -359,6 +372,7 @@ png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row, uint8x8x4_t *vrpt, *vppt; uint8x8x4_t vrp, vpp; uint32x2x4_t *temp_pointer; + uint32x2x4_t vdest_val; vtmp = vld4_u32(png_ptr(uint32_t,rp)); vrpt = png_ptr(uint8x8x4_t,&vtmp); @@ -378,7 +392,8 @@ png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row, vlast = vpp.val[3]; - vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); + vdest_val = png_ldr(uint32x2x4_t, &vdest); + vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0); } } diff --git a/3rdparty/libpng/arm/palette_neon_intrinsics.c b/3rdparty/libpng/arm/palette_neon_intrinsics.c new file mode 100644 index 0000000000..fa02d6a8b3 --- /dev/null +++ b/3rdparty/libpng/arm/palette_neon_intrinsics.c @@ -0,0 +1,149 @@ + +/* palette_neon_intrinsics.c - NEON optimised palette expansion functions + * + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2017-2018 Arm Holdings. All rights reserved. + * Written by Richard Townsend , February 2017. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "../pngpriv.h" + +#if PNG_ARM_NEON_IMPLEMENTATION == 1 + +#if defined(_MSC_VER) && defined(_M_ARM64) +# include +#else +# include +#endif + +/* Build an RGBA palette from the RGB and separate alpha palettes. */ +void +png_riffle_palette_rgba(png_structrp png_ptr, png_row_infop row_info) +{ + png_const_colorp palette = png_ptr->palette; + png_bytep riffled_palette = png_ptr->riffled_palette; + png_const_bytep trans_alpha = png_ptr->trans_alpha; + int num_trans = png_ptr->num_trans; + int i; + + /* Initially black, opaque. */ + uint8x16x4_t w = {{ + vdupq_n_u8(0x00), + vdupq_n_u8(0x00), + vdupq_n_u8(0x00), + vdupq_n_u8(0xff), + }}; + + if (row_info->bit_depth != 8) + { + png_error(png_ptr, "bit_depth must be 8 for png_riffle_palette_rgba"); + return; + } + + /* First, riffle the RGB colours into a RGBA palette, the A value is + * set to opaque for now. + */ + for (i = 0; i < (1 << row_info->bit_depth); i += 16) + { + uint8x16x3_t v = vld3q_u8((png_const_bytep)(palette + i)); + w.val[0] = v.val[0]; + w.val[1] = v.val[1]; + w.val[2] = v.val[2]; + vst4q_u8(riffled_palette + (i << 2), w); + } + + /* Fix up the missing transparency values. */ + for (i = 0; i < num_trans; i++) + riffled_palette[(i << 2) + 3] = trans_alpha[i]; +} + +/* Expands a palettized row into RGBA. */ +int +png_do_expand_palette_neon_rgba(png_structrp png_ptr, png_row_infop row_info, + png_const_bytep row, png_bytepp ssp, png_bytepp ddp) +{ + png_uint_32 row_width = row_info->width; + const png_uint_32 *riffled_palette = + (const png_uint_32 *)png_ptr->riffled_palette; + const png_int_32 pixels_per_chunk = 4; + int i; + + if (row_width < pixels_per_chunk) + return 0; + + /* This function originally gets the last byte of the output row. + * The NEON part writes forward from a given position, so we have + * to seek this back by 4 pixels x 4 bytes. + */ + *ddp = *ddp - ((pixels_per_chunk * sizeof(png_uint_32)) - 1); + + for (i = 0; i < row_width; i += pixels_per_chunk) + { + uint32x4_t cur; + png_bytep sp = *ssp - i, dp = *ddp - (i << 2); + cur = vld1q_dup_u32 (riffled_palette + *(sp - 3)); + cur = vld1q_lane_u32(riffled_palette + *(sp - 2), cur, 1); + cur = vld1q_lane_u32(riffled_palette + *(sp - 1), cur, 2); + cur = vld1q_lane_u32(riffled_palette + *(sp - 0), cur, 3); + vst1q_u32((void *)dp, cur); + } + if (i != row_width) + { + /* Remove the amount that wasn't processed. */ + i -= pixels_per_chunk; + } + + /* Decrement output pointers. */ + *ssp = *ssp - i; + *ddp = *ddp - (i << 2); + return i; +} + +/* Expands a palettized row into RGB format. */ +int +png_do_expand_palette_neon_rgb(png_structrp png_ptr, png_row_infop row_info, + png_const_bytep row, png_bytepp ssp, png_bytepp ddp) +{ + png_uint_32 row_width = row_info->width; + png_const_bytep palette = (png_const_bytep)png_ptr->palette; + const png_uint_32 pixels_per_chunk = 8; + int i; + + if (row_width <= pixels_per_chunk) + return 0; + + /* Seeking this back by 8 pixels x 3 bytes. */ + *ddp = *ddp - ((pixels_per_chunk * sizeof(png_color)) - 1); + + for (i = 0; i < row_width; i += pixels_per_chunk) + { + uint8x8x3_t cur; + png_bytep sp = *ssp - i, dp = *ddp - ((i << 1) + i); + cur = vld3_dup_u8(palette + sizeof(png_color) * (*(sp - 7))); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 6)), cur, 1); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 5)), cur, 2); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 4)), cur, 3); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 3)), cur, 4); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 2)), cur, 5); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 1)), cur, 6); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 0)), cur, 7); + vst3_u8((void *)dp, cur); + } + + if (i != row_width) + { + /* Remove the amount that wasn't processed. */ + i -= pixels_per_chunk; + } + + /* Decrement output pointers. */ + *ssp = *ssp - i; + *ddp = *ddp - ((i << 1) + i); + return i; +} + +#endif /* PNG_ARM_NEON_IMPLEMENTATION */ diff --git a/3rdparty/libpng/intel/filter_sse2_intrinsics.c b/3rdparty/libpng/intel/filter_sse2_intrinsics.c index ef1fc7d6b8..f52aaa800a 100644 --- a/3rdparty/libpng/intel/filter_sse2_intrinsics.c +++ b/3rdparty/libpng/intel/filter_sse2_intrinsics.c @@ -1,12 +1,11 @@ /* filter_sse2_intrinsics.c - SSE2 optimized filter functions * + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 2016-2017 Glenn Randers-Pehrson * Written by Mike Klein and Matt Sarett * Derived from arm/filter_neon_intrinsics.c * - * Last changed in libpng 1.6.31 [July 27, 2017] - * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h @@ -29,39 +28,25 @@ */ static __m128i load4(const void* p) { - return _mm_cvtsi32_si128(*(const int*)p); + int tmp; + memcpy(&tmp, p, sizeof(tmp)); + return _mm_cvtsi32_si128(tmp); } static void store4(void* p, __m128i v) { - *(int*)p = _mm_cvtsi128_si32(v); + int tmp = _mm_cvtsi128_si32(v); + memcpy(p, &tmp, sizeof(int)); } static __m128i load3(const void* p) { - /* We'll load 2 bytes, then 1 byte, - * then mask them together, and finally load into SSE. - */ - const png_uint_16* p01 = (png_const_uint_16p)p; - const png_byte* p2 = (const png_byte*)(p01+1); - - png_uint_32 v012 = (png_uint_32)(*p01) - | (png_uint_32)(*p2) << 16; - return load4(&v012); + png_uint_32 tmp = 0; + memcpy(&tmp, p, 3); + return _mm_cvtsi32_si128(tmp); } static void store3(void* p, __m128i v) { - /* We'll pull from SSE as a 32-bit int, then write - * its bottom two bytes, then its third byte. - */ - png_uint_32 v012; - png_uint_16* p01; - png_byte* p2; - - store4(&v012, v); - - p01 = (png_uint_16p)p; - p2 = (png_byte*)(p01+1); - *p01 = (png_uint_16)v012; - *p2 = (png_byte)(v012 >> 16); + int tmp = _mm_cvtsi128_si32(v); + memcpy(p, &tmp, 3); } void png_read_filter_row_sub3_sse2(png_row_infop row_info, png_bytep row, diff --git a/3rdparty/libpng/intel/intel_init.c b/3rdparty/libpng/intel/intel_init.c index 8f08baf8c5..2f8168b7c4 100644 --- a/3rdparty/libpng/intel/intel_init.c +++ b/3rdparty/libpng/intel/intel_init.c @@ -1,12 +1,11 @@ /* intel_init.c - SSE2 optimized filter functions * + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 2016-2017 Glenn Randers-Pehrson * Written by Mike Klein and Matt Sarett, Google, Inc. * Derived from arm/arm_init.c * - * Last changed in libpng 1.6.29 [March 16, 2017] - * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h diff --git a/3rdparty/libpng/png.c b/3rdparty/libpng/png.c index a25afebcc8..3dce191d17 100644 --- a/3rdparty/libpng/png.c +++ b/3rdparty/libpng/png.c @@ -1,10 +1,10 @@ /* png.c - location for general purpose libpng functions * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -14,7 +14,7 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_35 Your_png_h_is_not_version_1_6_35; +typedef png_libpng_version_1_6_36 Your_png_h_is_not_version_1_6_36; #ifdef __GNUC__ /* The version tests may need to be added to, but the problem warning has @@ -736,7 +736,7 @@ png_save_int_32(png_bytep buf, png_int_32 i) int PNGAPI png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime) { - static PNG_CONST char short_months[12][4] = + static const char short_months[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; @@ -814,20 +814,14 @@ png_get_copyright(png_const_structrp png_ptr) #ifdef PNG_STRING_COPYRIGHT return PNG_STRING_COPYRIGHT #else -# ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.6.35 - July 15, 2018" PNG_STRING_NEWLINE \ + "libpng version 1.6.36" PNG_STRING_NEWLINE \ + "Copyright (c) 2018 Cosmin Truta" PNG_STRING_NEWLINE \ "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \ PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE; -# else - return "libpng version 1.6.35 - July 15, 2018\ - Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson\ - Copyright (c) 1996-1997 Andreas Dilger\ - Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; -# endif #endif } @@ -1121,7 +1115,7 @@ png_colorspace_set_gamma(png_const_structrp png_ptr, png_colorspacerp colorspace, png_fixed_point gAMA) { /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't - * occur. Since the fixed point representation is asymetrical it is + * occur. Since the fixed point representation is asymmetrical it is * possible for 1/gamma to overflow the limit of 21474 and this means the * gamma value must be at least 5/100000 and hence at most 20000.0. For * safety the limits here are a little narrower. The values are 0.00016 to @@ -3134,11 +3128,11 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size, /* The total output count (max) is now 4+precision */ /* Check for an exponent, if we don't need one we are - * done and just need to terminate the string. At - * this point exp_b10==(-1) is effectively a flag - it got - * to '-1' because of the decrement after outputting - * the decimal point above (the exponent required is - * *not* -1!) + * done and just need to terminate the string. At this + * point, exp_b10==(-1) is effectively a flag: it got + * to '-1' because of the decrement, after outputting + * the decimal point above. (The exponent required is + * *not* -1.) */ if (exp_b10 >= (-1) && exp_b10 <= 2) { @@ -3976,18 +3970,18 @@ png_gamma_correct(png_structrp png_ptr, unsigned int value, */ static void png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable, - PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) + unsigned int shift, png_fixed_point gamma_val) { /* Various values derived from 'shift': */ - PNG_CONST unsigned int num = 1U << (8U - shift); + unsigned int num = 1U << (8U - shift); #ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED /* CSE the division and work round wacky GCC warnings (see the comments * in png_gamma_8bit_correct for where these come from.) */ - PNG_CONST double fmax = 1./(((png_int_32)1 << (16U - shift))-1); + double fmax = 1.0 / (((png_int_32)1 << (16U - shift)) - 1); #endif - PNG_CONST unsigned int max = (1U << (16U - shift))-1U; - PNG_CONST unsigned int max_by_2 = 1U << (15U-shift); + unsigned int max = (1U << (16U - shift)) - 1U; + unsigned int max_by_2 = 1U << (15U - shift); unsigned int i; png_uint_16pp table = *ptable = @@ -4053,10 +4047,10 @@ png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable, */ static void png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable, - PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) + unsigned int shift, png_fixed_point gamma_val) { - PNG_CONST unsigned int num = 1U << (8U - shift); - PNG_CONST unsigned int max = (1U << (16U - shift))-1U; + unsigned int num = 1U << (8U - shift); + unsigned int max = (1U << (16U - shift))-1U; unsigned int i; png_uint_32 last; @@ -4121,7 +4115,7 @@ png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable, */ static void png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable, - PNG_CONST png_fixed_point gamma_val) + png_fixed_point gamma_val) { unsigned int i; png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256); diff --git a/3rdparty/libpng/png.h b/3rdparty/libpng/png.h index 19e464cc17..8e272a0553 100644 --- a/3rdparty/libpng/png.h +++ b/3rdparty/libpng/png.h @@ -1,29 +1,65 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.35, July 15, 2018 + * libpng version 1.6.36 - December 1, 2018 * + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * - * This code is released under the libpng license (See LICENSE, below) + * This code is released under the libpng license. (See LICENSE, below.) * * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.6.35, July 15, 2018: + * libpng versions 0.97, January 1998, through 1.6.35, July 2018: * Glenn Randers-Pehrson. + * libpng version 1.6.36, December 1, 2018: Cosmin Truta * See also "Contributing Authors", below. */ /* - * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE + * ========================================= + * + * PNG Reference Library License version 2 + * --------------------------------------- + * + * * Copyright (c) 1995-2018 The PNG Reference Library Authors. + * * Copyright (c) 2018 Cosmin Truta. + * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + * * Copyright (c) 1996-1997 Andreas Dilger. + * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * The software is supplied "as is", without warranty of any kind, + * express or implied, including, without limitation, the warranties + * of merchantability, fitness for a particular purpose, title, and + * non-infringement. In no even shall the Copyright owners, or + * anyone distributing the software, be liable for any damages or + * other liability, whether in contract, tort or otherwise, arising + * from, out of, or in connection with the software, or the use or + * other dealings in the software, even if advised of the possibility + * of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute + * this software, or portions hereof, for any purpose, without fee, + * subject to the following restrictions: * - * If you modify libpng you may insert additional notices immediately following - * this sentence. + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you + * use this software in a product, an acknowledgment in the product + * documentation would be appreciated, but is not required. * - * This code is released under the libpng license. + * 2. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * + * PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35) + * ----------------------------------------------------------------------- * * libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are @@ -31,38 +67,38 @@ * disclaimer and license as libpng-1.0.6 with the following individuals * added to the list of Contributing Authors: * - * Simon-Pierre Cadieux - * Eric S. Raymond - * Mans Rullgard - * Cosmin Truta - * Gilles Vollant - * James Yu - * Mandar Sahastrabuddhe - * Google Inc. - * Vadim Barkov + * Simon-Pierre Cadieux + * Eric S. Raymond + * Mans Rullgard + * Cosmin Truta + * Gilles Vollant + * James Yu + * Mandar Sahastrabuddhe + * Google Inc. + * Vadim Barkov * * and with the following additions to the disclaimer: * - * There is no warranty against interference with your enjoyment of the - * library or against infringement. There is no warranty that our - * efforts or the library will fulfill any of your particular purposes - * or needs. This library is provided with all faults, and the entire - * risk of satisfactory quality, performance, accuracy, and effort is with - * the user. + * There is no warranty against interference with your enjoyment of + * the library or against infringement. There is no warranty that our + * efforts or the library will fulfill any of your particular purposes + * or needs. This library is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is + * with the user. * * Some files in the "contrib" directory and some configure-generated - * files that are distributed with libpng have other copyright owners and + * files that are distributed with libpng have other copyright owners, and * are released under other open source licenses. * * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from * libpng-0.96, and are distributed according to the same disclaimer and - * license as libpng-0.96, with the following individuals added to the list - * of Contributing Authors: + * license as libpng-0.96, with the following individuals added to the + * list of Contributing Authors: * - * Tom Lane - * Glenn Randers-Pehrson - * Willem van Schaik + * Tom Lane + * Glenn Randers-Pehrson + * Willem van Schaik * * libpng versions 0.89, June 1996, through 0.96, May 1997, are * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, @@ -70,14 +106,14 @@ * libpng-0.88, with the following individuals added to the list of * Contributing Authors: * - * John Bowler - * Kevin Bracey - * Sam Bushell - * Magnus Holmgren - * Greg Roelofs - * Tom Tanner + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner * - * Some files in the "scripts" directory have other copyright owners + * Some files in the "scripts" directory have other copyright owners, * but are released under this license. * * libpng versions 0.5, May 1995, through 0.88, January 1996, are @@ -86,62 +122,49 @@ * For the purposes of this copyright and license, "Contributing Authors" * is defined as the following set of individuals: * - * Andreas Dilger - * Dave Martindale - * Guy Eric Schalnat - * Paul Schmidt - * Tim Wegner - * - * The PNG Reference Library is supplied "AS IS". The Contributing Authors - * and Group 42, Inc. disclaim all warranties, expressed or implied, - * including, without limitation, the warranties of merchantability and of - * fitness for any purpose. The Contributing Authors and Group 42, Inc. - * assume no liability for direct, indirect, incidental, special, exemplary, - * or consequential damages, which may result from the use of the PNG - * Reference Library, even if advised of the possibility of such damage. + * Andreas Dilger + * Dave Martindale + * Guy Eric Schalnat + * Paul Schmidt + * Tim Wegner + * + * The PNG Reference Library is supplied "AS IS". The Contributing + * Authors and Group 42, Inc. disclaim all warranties, expressed or + * implied, including, without limitation, the warranties of + * merchantability and of fitness for any purpose. The Contributing + * Authors and Group 42, Inc. assume no liability for direct, indirect, + * incidental, special, exemplary, or consequential damages, which may + * result from the use of the PNG Reference Library, even if advised of + * the possibility of such damage. * * Permission is hereby granted to use, copy, modify, and distribute this * source code, or portions hereof, for any purpose, without fee, subject * to the following restrictions: * - * 1. The origin of this source code must not be misrepresented. + * 1. The origin of this source code must not be misrepresented. * - * 2. Altered versions must be plainly marked as such and must not - * be misrepresented as being the original source. + * 2. Altered versions must be plainly marked as such and must not + * be misrepresented as being the original source. * - * 3. This Copyright notice may not be removed or altered from any - * source or altered source distribution. + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. * - * The Contributing Authors and Group 42, Inc. specifically permit, without - * fee, and encourage the use of this source code as a component to - * supporting the PNG file format in commercial products. If you use this - * source code in a product, acknowledgment is not required but would be - * appreciated. + * The Contributing Authors and Group 42, Inc. specifically permit, + * without fee, and encourage the use of this source code as a component + * to supporting the PNG file format in commercial products. If you use + * this source code in a product, acknowledgment is not required but would + * be appreciated. * * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. * - * TRADEMARK: + * TRADEMARK + * ========= * - * The name "libpng" has not been registered by the Copyright owner + * The name "libpng" has not been registered by the Copyright owners * as a trademark in any jurisdiction. However, because libpng has * been distributed and maintained world-wide, continually since 1995, - * the Copyright owner claims "common-law trademark protection" in any + * the Copyright owners claim "common-law trademark protection" in any * jurisdiction where common-law trademark is recognized. - * - * OSI CERTIFICATION: - * - * Libpng is OSI Certified Open Source Software. OSI Certified Open Source is - * a certification mark of the Open Source Initiative. OSI has not addressed - * the additional disclaimers inserted at version 1.0.7. - * - * EXPORT CONTROL: - * - * The Copyright owner believes that the Export Control Classification - * Number (ECCN) for libpng is EAR99, which means not subject to export - * controls or International Traffic in Arms Regulations (ITAR) because - * it is open source, publicly available software, that does not contain - * any encryption software. See the EAR, paragraphs 734.3(b)(3) and - * 734.7(b). */ /* @@ -207,23 +230,25 @@ * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) * 1.0.7 1 10007 (still compatible) * ... - * 1.0.19 10 10019 10.so.0.19[.0] + * 1.0.69 10 10069 10.so.0.69[.0] * ... - * 1.2.59 13 10257 12.so.0.59[.0] + * 1.2.59 13 10259 12.so.0.59[.0] * ... - * 1.5.30 15 10527 15.so.15.30[.0] + * 1.4.20 14 10420 14.so.0.20[.0] * ... - * 1.6.35 16 10635 16.so.16.35[.0] - * - * Henceforth the source version will match the shared-library major - * and minor numbers; the shared-library major version number will be - * used for changes in backward compatibility, as it is intended. The - * PNG_LIBPNG_VER macro, which is not used within libpng but is available - * for applications, is an unsigned integer of the form xyyzz corresponding - * to the source version x.y.z (leading zeros in y and z). Beta versions - * were given the previous public release number plus a letter, until - * version 1.0.6j; from then on they were given the upcoming public - * release number plus "betaNN" or "rcNN". + * 1.5.30 15 10530 15.so.15.30[.0] + * ... + * 1.6.36 16 10636 16.so.16.36[.0] + * + * Henceforth the source version will match the shared-library major and + * minor numbers; the shared-library major version number will be used for + * changes in backward compatibility, as it is intended. + * The PNG_LIBPNG_VER macro, which is not used within libpng but is + * available for applications, is an unsigned integer of the form XYYZZ + * corresponding to the source version X.Y.Z (leading zeros in Y and Z). + * Beta versions were given the previous public release number plus a + * letter, until version 1.0.6j; from then on they were given the upcoming + * public release number plus "betaNN" or "rcNN". * * Binary incompatibility exists only when applications make direct access * to the info_ptr or png_ptr members through png.h, and the compiled @@ -233,65 +258,8 @@ * in binary compatibility (e.g., when a new feature is added). * * See libpng.txt or libpng.3 for more information. The PNG specification - * is available as a W3C Recommendation and as an ISO Specification, - * */ #ifndef PNG_H @@ -309,8 +277,8 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.35" -#define PNG_HEADER_VERSION_STRING " libpng version 1.6.35 - July 15, 2018\n" +#define PNG_LIBPNG_VER_STRING "1.6.36" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.36 - December 1, 2018\n" #define PNG_LIBPNG_VER_SONUM 16 #define PNG_LIBPNG_VER_DLLNUM 16 @@ -318,13 +286,13 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 6 -#define PNG_LIBPNG_VER_RELEASE 35 +#define PNG_LIBPNG_VER_RELEASE 36 /* This should match the numeric part of the final component of * PNG_LIBPNG_VER_STRING, omitting any leading zero: */ -#define PNG_LIBPNG_VER_BUILD 02 +#define PNG_LIBPNG_VER_BUILD 0 /* Release Status */ #define PNG_LIBPNG_BUILD_ALPHA 1 @@ -341,15 +309,16 @@ #define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with PNG_LIBPNG_BUILD_PRIVATE */ -#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_BETA +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE -/* Careful here. At one time, Guy wanted to use 082, but that would be octal. - * We must not include leading zeros. - * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only - * version 1.0.0 was mis-numbered 100 instead of 10000). From - * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release +/* Careful here. At one time, Guy wanted to use 082, but that + * would be octal. We must not include leading zeros. + * Versions 0.7 through 1.0.0 were in the range 0 to 100 here + * (only version 1.0.0 was mis-numbered 100 instead of 10000). + * From version 1.0.1 it is: + * XXYYZZ, where XX=major, YY=minor, ZZ=release */ -#define PNG_LIBPNG_VER 10635 /* 1.6.35 */ +#define PNG_LIBPNG_VER 10636 /* 1.6.36 */ /* Library configuration: these options cannot be changed after * the library has been built. @@ -459,7 +428,7 @@ extern "C" { /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_6_35; +typedef char* png_libpng_version_1_6_36; /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. * @@ -2013,12 +1982,12 @@ PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr, png_inforp info_ptr, png_bytep *exif)); PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr, - png_inforp info_ptr, const png_bytep exif)); + png_inforp info_ptr, png_bytep exif)); PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr, png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif)); PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr, - png_inforp info_ptr, const png_uint_32 num_exif, const png_bytep exif)); + png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif)); #endif #ifdef PNG_gAMA_SUPPORTED @@ -2764,7 +2733,7 @@ typedef struct * * When the simplified API needs to convert between sRGB and linear colorspaces, * the actual sRGB transfer curve defined in the sRGB specification (see the - * article at https://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 + * article at ) is used, not the gamma=1/2.2 * approximation used elsewhere in libpng. * * When an alpha channel is present it is expected to denote pixel coverage @@ -2967,7 +2936,7 @@ typedef struct * 'flags' field of png_image. */ #define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 - /* This indicates the the RGB values of the in-memory bitmap do not + /* This indicates that the RGB values of the in-memory bitmap do not * correspond to the red, green and blue end-points defined by sRGB. */ diff --git a/3rdparty/libpng/pngconf.h b/3rdparty/libpng/pngconf.h index a4646bab85..5e641b2509 100644 --- a/3rdparty/libpng/pngconf.h +++ b/3rdparty/libpng/pngconf.h @@ -1,11 +1,12 @@ /* pngconf.h - machine configurable file for libpng * - * libpng version 1.6.35, July 15, 2018 + * libpng version 1.6.36 * + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -57,14 +58,13 @@ #endif /* PNG_BUILDING_SYMBOL_TABLE */ -/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using - * PNG_NO_CONST; this is no longer supported except for data declarations which - * apparently still cause problems in 2011 on some compilers. +/* Prior to 1.6.0, it was possible to turn off 'const' in declarations, + * using PNG_NO_CONST. This is no longer supported. */ #define PNG_CONST const /* backward compatibility only */ -/* This controls optimization of the reading of 16-bit and 32-bit values - * from PNG files. It can be set on a per-app-file basis - it +/* This controls optimization of the reading of 16-bit and 32-bit + * values from PNG files. It can be set on a per-app-file basis: it * just changes whether a macro is used when the function is called. * The library builder sets the default; if read functions are not * built into the library the macro implementation is forced on. diff --git a/3rdparty/libpng/pngdebug.h b/3rdparty/libpng/pngdebug.h index 15a7ed0c95..00d5a4569e 100644 --- a/3rdparty/libpng/pngdebug.h +++ b/3rdparty/libpng/pngdebug.h @@ -1,10 +1,10 @@ /* pngdebug.h - Debugging macros for libpng, also used in pngtest.c * - * Last changed in libpng 1.6.8 [December 19, 2013] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer diff --git a/3rdparty/libpng/pngerror.c b/3rdparty/libpng/pngerror.c index ad48bfb986..ec3a709b9d 100644 --- a/3rdparty/libpng/pngerror.c +++ b/3rdparty/libpng/pngerror.c @@ -1,10 +1,10 @@ /* pngerror.c - stub functions for i/o and memory allocation * - * Last changed in libpng 1.6.31 [July 27, 2017] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -425,7 +425,7 @@ png_app_error(png_const_structrp png_ptr, png_const_charp error_message) * if the character is invalid. */ #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) -static PNG_CONST char png_digit[16] = { +static const char png_digit[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; @@ -885,7 +885,7 @@ PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message), PNG_NORETURN) { - const png_const_structrp png_ptr = png_nonconst_ptr; + png_const_structrp png_ptr = png_nonconst_ptr; png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); /* An error is always logged here, overwriting anything (typically a warning) @@ -920,7 +920,7 @@ png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message), void /* PRIVATE */ PNGCBAPI png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message) { - const png_const_structrp png_ptr = png_nonconst_ptr; + png_const_structrp png_ptr = png_nonconst_ptr; png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); /* A warning is only logged if there is no prior warning or error. */ diff --git a/3rdparty/libpng/pngget.c b/3rdparty/libpng/pngget.c index 2325508f1d..5abf1efd9f 100644 --- a/3rdparty/libpng/pngget.c +++ b/3rdparty/libpng/pngget.c @@ -1,10 +1,10 @@ /* pngget.c - retrieval of values from info struct * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer diff --git a/3rdparty/libpng/pnginfo.h b/3rdparty/libpng/pnginfo.h index 2fcf868dac..1f98dedc42 100644 --- a/3rdparty/libpng/pnginfo.h +++ b/3rdparty/libpng/pnginfo.h @@ -1,10 +1,10 @@ /* pnginfo.h - header file for PNG reference library * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2013,2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer diff --git a/3rdparty/libpng/pnglibconf.h b/3rdparty/libpng/pnglibconf.h index 53b5e442c4..00340c678b 100644 --- a/3rdparty/libpng/pnglibconf.h +++ b/3rdparty/libpng/pnglibconf.h @@ -1,10 +1,9 @@ -/* libpng 1.6.34 STANDARD API DEFINITION */ - /* pnglibconf.h - library build configuration */ -/* Libpng version 1.6.34 - September 29, 2017 */ +/* libpng version 1.6.36 */ -/* Copyright (c) 1998-2017 Glenn Randers-Pehrson */ +/* Copyright (c) 2018 Cosmin Truta */ +/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ /* This code is released under the libpng license. */ /* For conditions of distribution and use, see the disclaimer */ @@ -20,8 +19,6 @@ #define PNG_ALIGNED_MEMORY_SUPPORTED /*#undef PNG_ARM_NEON_API_SUPPORTED*/ /*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ -/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/ -/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/ #define PNG_BENIGN_ERRORS_SUPPORTED #define PNG_BENIGN_READ_ERRORS_SUPPORTED /*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ @@ -46,6 +43,8 @@ #define PNG_IO_STATE_SUPPORTED #define PNG_MNG_FEATURES_SUPPORTED #define PNG_POINTER_INDEXING_SUPPORTED +/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/ +/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/ #define PNG_PROGRESSIVE_READ_SUPPORTED #define PNG_READ_16BIT_SUPPORTED #define PNG_READ_ALPHA_MODE_SUPPORTED diff --git a/3rdparty/libpng/pngmem.c b/3rdparty/libpng/pngmem.c index ff3ef7e88c..09ed9c1c99 100644 --- a/3rdparty/libpng/pngmem.c +++ b/3rdparty/libpng/pngmem.c @@ -1,10 +1,10 @@ /* pngmem.c - stub functions for memory allocation * - * Last changed in libpng 1.6.26 [October 20, 2016] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer diff --git a/3rdparty/libpng/pngpread.c b/3rdparty/libpng/pngpread.c index c4ba51c4d4..e283627b77 100644 --- a/3rdparty/libpng/pngpread.c +++ b/3rdparty/libpng/pngpread.c @@ -1,10 +1,10 @@ /* pngpread.c - read a png file in push mode * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -972,20 +972,20 @@ png_read_push_finish_row(png_structrp png_ptr) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + static const png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + static const png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + static const png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + static const png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; /* Height of interlace block. This is not currently used - if you need * it, uncomment it here and in png.h - static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; + static const png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; */ #endif diff --git a/3rdparty/libpng/pngpriv.h b/3rdparty/libpng/pngpriv.h index 3581f67919..973c3eac1f 100644 --- a/3rdparty/libpng/pngpriv.h +++ b/3rdparty/libpng/pngpriv.h @@ -1,10 +1,10 @@ /* pngpriv.h - private declarations for use inside libpng * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -174,7 +174,10 @@ # else /* !defined __ARM_NEON__ */ /* The 'intrinsics' code simply won't compile without this -mfpu=neon: */ -# define PNG_ARM_NEON_IMPLEMENTATION 2 +# if !defined(__aarch64__) + /* The assembler code currently does not work on ARM64 */ +# define PNG_ARM_NEON_IMPLEMENTATION 2 +# endif /* __aarch64__ */ # endif /* __ARM_NEON__ */ # endif /* !PNG_ARM_NEON_IMPLEMENTATION */ @@ -1534,10 +1537,10 @@ PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr, #endif PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_const_structrp png_ptr, - const png_uint_32 chunk_name),PNG_EMPTY); + png_uint_32 chunk_name),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_check_chunk_length,(png_const_structrp png_ptr, - const png_uint_32 chunk_length),PNG_EMPTY); + png_uint_32 chunk_length),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY); @@ -2114,6 +2117,29 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr, png_const_charp key, png_bytep new_key), PNG_EMPTY); +#if PNG_ARM_NEON_IMPLEMENTATION == 1 +PNG_INTERNAL_FUNCTION(void, + png_riffle_palette_rgba, + (png_structrp, png_row_infop), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, + png_do_expand_palette_neon_rgba, + (png_structrp, + png_row_infop, + png_const_bytep, + const png_bytepp, + const png_bytepp), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, + png_do_expand_palette_neon_rgb, + (png_structrp, + png_row_infop, + png_const_bytep, + const png_bytepp, + const png_bytepp), + PNG_EMPTY); +#endif + /* Maintainer: Put new private prototypes here ^ */ #include "pngdebug.h" diff --git a/3rdparty/libpng/pngread.c b/3rdparty/libpng/pngread.c index bff7503ee3..f8e762196e 100644 --- a/3rdparty/libpng/pngread.c +++ b/3rdparty/libpng/pngread.c @@ -1,10 +1,10 @@ /* pngread.c - read a PNG file * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -1621,7 +1621,7 @@ png_image_skip_unused_chunks(png_structrp png_ptr) * errors (which are unfortunately quite common.) */ { - static PNG_CONST png_byte chunks_to_process[] = { + static const png_byte chunks_to_process[] = { 98, 75, 71, 68, '\0', /* bKGD */ 99, 72, 82, 77, '\0', /* cHRM */ 103, 65, 77, 65, '\0', /* gAMA */ @@ -1758,9 +1758,9 @@ png_create_colormap_entry(png_image_read_control *display, png_uint_32 alpha, int encoding) { png_imagep image = display->image; - const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ? + int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ? P_LINEAR : P_sRGB; - const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && + int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && (red != green || green != blue); if (ip > 255) @@ -1869,13 +1869,13 @@ png_create_colormap_entry(png_image_read_control *display, /* Store the value. */ { # ifdef PNG_FORMAT_AFIRST_SUPPORTED - const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 && + int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 && (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; # else # define afirst 0 # endif # ifdef PNG_FORMAT_BGR_SUPPORTED - const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0; + int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0; # else # define bgr 0 # endif @@ -2085,11 +2085,11 @@ png_image_read_colormap(png_voidp argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, argument); - const png_imagep image = display->image; + png_imagep image = display->image; - const png_structrp png_ptr = image->opaque->png_ptr; - const png_uint_32 output_format = image->format; - const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ? + png_structrp png_ptr = image->opaque->png_ptr; + png_uint_32 output_format = image->format; + int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ? P_LINEAR : P_sRGB; unsigned int cmap_entries; @@ -2802,7 +2802,7 @@ png_image_read_colormap(png_voidp argument) unsigned int num_trans = png_ptr->num_trans; png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL; png_const_colorp colormap = png_ptr->palette; - const int do_background = trans != NULL && + int do_background = trans != NULL && (output_format & PNG_FORMAT_FLAG_ALPHA) == 0; unsigned int i; @@ -3946,7 +3946,7 @@ png_image_read_direct(png_voidp argument) */ if (linear != 0) { - PNG_CONST png_uint_16 le = 0x0001; + png_uint_16 le = 0x0001; if ((*(png_const_bytep) & le) != 0) png_set_swap(png_ptr); @@ -4108,7 +4108,7 @@ png_image_finish_read(png_imagep image, png_const_colorp background, * original PNG format because it may not occur in the output PNG format * and libpng deals with the issues of reading the original. */ - const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); + unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); /* The following checks just the 'row_stride' calculation to ensure it * fits in a signed 32-bit value. Because channels/components can be @@ -4119,7 +4119,7 @@ png_image_finish_read(png_imagep image, png_const_colorp background, if (image->width <= 0x7fffffffU/channels) /* no overflow */ { png_uint_32 check; - const png_uint_32 png_row_stride = image->width * channels; + png_uint_32 png_row_stride = image->width * channels; if (row_stride == 0) row_stride = (png_int_32)/*SAFE*/png_row_stride; diff --git a/3rdparty/libpng/pngrio.c b/3rdparty/libpng/pngrio.c index 372221483f..7946358101 100644 --- a/3rdparty/libpng/pngrio.c +++ b/3rdparty/libpng/pngrio.c @@ -1,10 +1,10 @@ /* pngrio.c - functions for data input * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer diff --git a/3rdparty/libpng/pngrtran.c b/3rdparty/libpng/pngrtran.c index 67d1f249a6..ccc58ce6f1 100644 --- a/3rdparty/libpng/pngrtran.c +++ b/3rdparty/libpng/pngrtran.c @@ -1,10 +1,10 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -18,6 +18,17 @@ #include "pngpriv.h" +#ifdef PNG_ARM_NEON_IMPLEMENTATION +# if PNG_ARM_NEON_IMPLEMENTATION == 1 +# define PNG_ARM_NEON_INTRINSICS_AVAILABLE +# if defined(_MSC_VER) && defined(_M_ARM64) +# include +# else +# include +# endif +# endif +#endif + #ifdef PNG_READ_SUPPORTED /* Set the action on getting a CRC error for an ancillary or critical chunk. */ @@ -2986,7 +2997,6 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) */ static int png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) - { int rgb_error = 0; @@ -2995,12 +3005,11 @@ png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 && (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0) { - PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; - PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; - PNG_CONST png_uint_32 bc = 32768 - rc - gc; - PNG_CONST png_uint_32 row_width = row_info->width; - PNG_CONST int have_alpha = - (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; + png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + png_uint_32 bc = 32768 - rc - gc; + png_uint_32 row_width = row_info->width; + int have_alpha = (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; if (row_info->bit_depth == 8) { @@ -4143,12 +4152,11 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) { if (row_info->bit_depth == 8) { - PNG_CONST png_bytep table = png_ptr->gamma_from_1; + png_bytep table = png_ptr->gamma_from_1; if (table != NULL) { - PNG_CONST int step = - (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; + int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; /* The alpha channel is the last component: */ row += step - 1; @@ -4162,13 +4170,12 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) else if (row_info->bit_depth == 16) { - PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1; - PNG_CONST int gamma_shift = png_ptr->gamma_shift; + png_uint_16pp table = png_ptr->gamma_16_from_1; + int gamma_shift = png_ptr->gamma_shift; if (table != NULL) { - PNG_CONST int step = - (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; + int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; /* The alpha channel is the last component: */ row += step - 2; @@ -4199,8 +4206,9 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) * upon whether you supply trans and num_trans. */ static void -png_do_expand_palette(png_row_infop row_info, png_bytep row, - png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) +png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info, + png_bytep row, png_const_colorp palette, png_const_bytep trans_alpha, + int num_trans) { int shift, value; png_bytep sp, dp; @@ -4304,14 +4312,25 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, sp = row + (size_t)row_width - 1; dp = row + ((size_t)row_width << 2) - 1; - for (i = 0; i < row_width; i++) + i = 0; +#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE + if (png_ptr->riffled_palette != NULL) + { + /* The RGBA optimization works with png_ptr->bit_depth == 8 + * but sometimes row_info->bit_depth has been changed to 8. + * In these cases, the palette hasn't been riffled. + */ + i = png_do_expand_palette_neon_rgba(png_ptr, row_info, row, + &sp, &dp); + } +#endif + + for (; i < row_width; i++) { if ((int)(*sp) >= num_trans) *dp-- = 0xff; - else *dp-- = trans_alpha[*sp]; - *dp-- = palette[*sp].blue; *dp-- = palette[*sp].green; *dp-- = palette[*sp].red; @@ -4328,8 +4347,13 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, { sp = row + (size_t)row_width - 1; dp = row + (size_t)(row_width * 3) - 1; + i = 0; +#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE + i = png_do_expand_palette_neon_rgb(png_ptr, row_info, row, + &sp, &dp); +#endif - for (i = 0; i < row_width; i++) + for (; i < row_width; i++) { *dp-- = palette[*sp].blue; *dp-- = palette[*sp].green; @@ -4743,8 +4767,22 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) { if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) { - png_do_expand_palette(row_info, png_ptr->row_buf + 1, - png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); +#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE + if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8)) + { + /* Allocate space for the decompressed full palette. */ + if (png_ptr->riffled_palette == NULL) + { + png_ptr->riffled_palette = png_malloc(png_ptr, 256*4); + if (png_ptr->riffled_palette == NULL) + png_error(png_ptr, "NULL row buffer"); + /* Build the RGBA palette. */ + png_riffle_palette_rgba(png_ptr, row_info); + } + } +#endif + png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1, + png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); } else diff --git a/3rdparty/libpng/pngrutil.c b/3rdparty/libpng/pngrutil.c index 7001f1976e..d5fa08c397 100644 --- a/3rdparty/libpng/pngrutil.c +++ b/3rdparty/libpng/pngrutil.c @@ -1,10 +1,10 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -1461,8 +1461,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { /* We have the ICC profile header; do the basic header checks. */ - const png_uint_32 profile_length = - png_get_uint_32(profile_header); + png_uint_32 profile_length = png_get_uint_32(profile_header); if (png_icc_check_length(png_ptr, &png_ptr->colorspace, keyword, profile_length) != 0) @@ -1479,8 +1478,8 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) * profile. The header check has already validated * that none of this stuff will overflow. */ - const png_uint_32 tag_count = png_get_uint_32( - profile_header+128); + png_uint_32 tag_count = + png_get_uint_32(profile_header + 128); png_bytep profile = png_read_buffer(png_ptr, profile_length, 2/*silent*/); @@ -3132,7 +3131,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, */ void /* PRIVATE */ -png_check_chunk_name(png_const_structrp png_ptr, const png_uint_32 chunk_name) +png_check_chunk_name(png_const_structrp png_ptr, png_uint_32 chunk_name) { int i; png_uint_32 cn=chunk_name; @@ -3151,7 +3150,7 @@ png_check_chunk_name(png_const_structrp png_ptr, const png_uint_32 chunk_name) } void /* PRIVATE */ -png_check_chunk_length(png_const_structrp png_ptr, const png_uint_32 length) +png_check_chunk_length(png_const_structrp png_ptr, png_uint_32 length) { png_alloc_size_t limit = PNG_UINT_31_MAX; @@ -3363,7 +3362,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) /* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and * then pass: */ - static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = + static const png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = { /* Little-endian byte masks for PACKSWAP */ { S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) }, @@ -3374,7 +3373,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) /* display_mask has only three entries for the odd passes, so index by * pass>>1. */ - static PNG_CONST png_uint_32 display_mask[2][3][3] = + static const png_uint_32 display_mask[2][3][3] = { /* Little-endian byte masks for PACKSWAP */ { B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) }, @@ -3687,7 +3686,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, { /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Offset to next interlace block */ - static PNG_CONST unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + static const unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; png_debug(1, "in png_do_read_interlace"); if (row != NULL && row_info != NULL) @@ -4329,16 +4328,16 @@ png_read_finish_row(png_structrp png_ptr) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; png_debug(1, "in png_read_finish_row"); png_ptr->row_number++; @@ -4394,16 +4393,16 @@ png_read_start_row(png_structrp png_ptr) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; unsigned int max_pixel_depth; size_t row_bytes; diff --git a/3rdparty/libpng/pngset.c b/3rdparty/libpng/pngset.c index 7cf54d9248..ec75dbe369 100644 --- a/3rdparty/libpng/pngset.c +++ b/3rdparty/libpng/pngset.c @@ -1,10 +1,10 @@ /* pngset.c - storage of image information into info struct * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -137,7 +137,7 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, #ifdef PNG_eXIf_SUPPORTED void PNGAPI png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr, - const png_bytep eXIf_buf) + png_bytep eXIf_buf) { png_warning(png_ptr, "png_set_eXIf does not work; use png_set_eXIf_1"); PNG_UNUSED(info_ptr) @@ -146,7 +146,7 @@ png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr, void PNGAPI png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr, - const png_uint_32 num_exif, const png_bytep eXIf_buf) + png_uint_32 num_exif, png_bytep eXIf_buf) { int i; @@ -1399,7 +1399,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep, /* Ignore all unknown chunks and all chunks recognized by * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND */ - static PNG_CONST png_byte chunks_to_ignore[] = { + static const png_byte chunks_to_ignore[] = { 98, 75, 71, 68, '\0', /* bKGD */ 99, 72, 82, 77, '\0', /* cHRM */ 101, 88, 73, 102, '\0', /* eXIf */ diff --git a/3rdparty/libpng/pngstruct.h b/3rdparty/libpng/pngstruct.h index 699e8ac68a..94a6d041ff 100644 --- a/3rdparty/libpng/pngstruct.h +++ b/3rdparty/libpng/pngstruct.h @@ -1,10 +1,10 @@ /* pngstruct.h - header file for PNG reference library * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -228,6 +228,10 @@ struct png_struct_def * big_row_buf; while writing it is separately * allocated. */ +#ifdef PNG_READ_EXPAND_SUPPORTED + /* Buffer to accelerate palette transformations. */ + png_bytep riffled_palette; +#endif #ifdef PNG_WRITE_FILTER_SUPPORTED png_bytep try_row; /* buffer to save trial row when filtering */ png_bytep tst_row; /* buffer to save best trial row when filtering */ diff --git a/3rdparty/libpng/pngtrans.c b/3rdparty/libpng/pngtrans.c index de84aa6d6b..1100f46ebe 100644 --- a/3rdparty/libpng/pngtrans.c +++ b/3rdparty/libpng/pngtrans.c @@ -1,10 +1,10 @@ /* pngtrans.c - transforms the data in a row (used by both readers and writers) * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -345,7 +345,7 @@ png_do_swap(png_row_infop row_info, png_bytep row) #endif #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) -static PNG_CONST png_byte onebppswaptable[256] = { +static const png_byte onebppswaptable[256] = { 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, @@ -380,7 +380,7 @@ static PNG_CONST png_byte onebppswaptable[256] = { 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF }; -static PNG_CONST png_byte twobppswaptable[256] = { +static const png_byte twobppswaptable[256] = { 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, @@ -415,7 +415,7 @@ static PNG_CONST png_byte twobppswaptable[256] = { 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF }; -static PNG_CONST png_byte fourbppswaptable[256] = { +static const png_byte fourbppswaptable[256] = { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, diff --git a/3rdparty/libpng/pngwio.c b/3rdparty/libpng/pngwio.c index e5391687a2..10e919dd03 100644 --- a/3rdparty/libpng/pngwio.c +++ b/3rdparty/libpng/pngwio.c @@ -1,10 +1,10 @@ /* pngwio.c - functions for data output * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2014,2016,2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer diff --git a/3rdparty/libpng/pngwrite.c b/3rdparty/libpng/pngwrite.c index 5bd87f373e..160c877d38 100644 --- a/3rdparty/libpng/pngwrite.c +++ b/3rdparty/libpng/pngwrite.c @@ -1,10 +1,10 @@ /* pngwrite.c - general routines to write a PNG file * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -469,7 +469,7 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr) #ifdef PNG_CONVERT_tIME_SUPPORTED void PNGAPI -png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime) +png_convert_from_struct_tm(png_timep ptime, const struct tm * ttime) { png_debug(1, "in png_convert_from_struct_tm"); @@ -948,6 +948,10 @@ png_write_destroy(png_structrp png_ptr) png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); png_free(png_ptr, png_ptr->row_buf); png_ptr->row_buf = NULL; +#ifdef PNG_READ_EXPANDED_SUPPORTED + png_free(png_ptr, png_ptr->riffled_palette); + png_ptr->riffled_palette = NULL; +#endif #ifdef PNG_WRITE_FILTER_SUPPORTED png_free(png_ptr, png_ptr->prev_row); png_free(png_ptr, png_ptr->try_row); @@ -1536,7 +1540,7 @@ png_write_image_16bit(png_voidp argument) display->first_row); png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row); png_uint_16p row_end; - const unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? + unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; int aindex = 0; png_uint_32 y = image->height; @@ -1573,7 +1577,7 @@ png_write_image_16bit(png_voidp argument) while (out_ptr < row_end) { - const png_uint_16 alpha = in_ptr[aindex]; + png_uint_16 alpha = in_ptr[aindex]; png_uint_32 reciprocal = 0; int c; @@ -1695,7 +1699,7 @@ png_write_image_8bit(png_voidp argument) display->first_row); png_bytep output_row = png_voidcast(png_bytep, display->local_row); png_uint_32 y = image->height; - const unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? + unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0) @@ -1783,25 +1787,25 @@ png_write_image_8bit(png_voidp argument) static void png_image_set_PLTE(png_image_write_control *display) { - const png_imagep image = display->image; + png_imagep image = display->image; const void *cmap = display->colormap; - const int entries = image->colormap_entries > 256 ? 256 : + int entries = image->colormap_entries > 256 ? 256 : (int)image->colormap_entries; /* NOTE: the caller must check for cmap != NULL and entries != 0 */ - const png_uint_32 format = image->format; - const unsigned int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); + png_uint_32 format = image->format; + unsigned int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); # if defined(PNG_FORMAT_BGR_SUPPORTED) &&\ defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED) - const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 && + int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 && (format & PNG_FORMAT_FLAG_ALPHA) != 0; # else # define afirst 0 # endif # ifdef PNG_FORMAT_BGR_SUPPORTED - const int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0; + int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0; # else # define bgr 0 # endif @@ -1951,12 +1955,12 @@ png_image_write_main(png_voidp argument) * and total image size to ensure that they are within the system limits. */ { - const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); + unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); if (image->width <= 0x7fffffffU/channels) /* no overflow */ { png_uint_32 check; - const png_uint_32 png_row_stride = image->width * channels; + png_uint_32 png_row_stride = image->width * channels; if (display->row_stride == 0) display->row_stride = (png_int_32)/*SAFE*/png_row_stride; @@ -2052,7 +2056,7 @@ png_image_write_main(png_voidp argument) */ if (write_16bit != 0) { - PNG_CONST png_uint_16 le = 0x0001; + png_uint_16 le = 0x0001; if ((*(png_const_bytep) & le) != 0) png_set_swap(png_ptr); @@ -2166,7 +2170,7 @@ image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, size_t size) { png_image_write_control *display = png_voidcast(png_image_write_control*, png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/); - const png_alloc_size_t ob = display->output_bytes; + png_alloc_size_t ob = display->output_bytes; /* Check for overflow; this should never happen: */ if (size <= ((png_alloc_size_t)-1) - ob) diff --git a/3rdparty/libpng/pngwtran.c b/3rdparty/libpng/pngwtran.c index 3a1e0a21d2..49a13c1e98 100644 --- a/3rdparty/libpng/pngwtran.c +++ b/3rdparty/libpng/pngwtran.c @@ -1,10 +1,10 @@ /* pngwtran.c - transforms the data in a row for PNG writers * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -254,8 +254,7 @@ png_do_shift(png_row_infop row_info, png_bytep row, for (i = 0; i < istop; i++, bp++) { - - const unsigned int c = i%channels; + unsigned int c = i%channels; int j; unsigned int v, out; @@ -283,7 +282,7 @@ png_do_shift(png_row_infop row_info, png_bytep row, for (bp = row, i = 0; i < istop; i++) { - const unsigned int c = i%channels; + unsigned int c = i%channels; int j; unsigned int value, v; diff --git a/3rdparty/libpng/pngwutil.c b/3rdparty/libpng/pngwutil.c index ab431e712c..16345e4c0b 100644 --- a/3rdparty/libpng/pngwutil.c +++ b/3rdparty/libpng/pngwutil.c @@ -1,10 +1,10 @@ /* pngwutil.c - utilities to write a PNG file * - * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -1893,16 +1893,16 @@ png_write_start_row(png_structrp png_ptr) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; #endif png_alloc_size_t buf_size; @@ -2008,16 +2008,16 @@ png_write_finish_row(png_structrp png_ptr) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; #endif png_debug(1, "in png_write_finish_row"); @@ -2098,10 +2098,10 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; png_debug(1, "in png_do_write_interlace"); @@ -2276,7 +2276,7 @@ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, #ifdef PNG_WRITE_FILTER_SUPPORTED static size_t /* PRIVATE */ -png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, +png_setup_sub_row(png_structrp png_ptr, png_uint_32 bpp, size_t row_bytes, size_t lmins) { png_bytep rp, dp, lp; @@ -2315,7 +2315,7 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, } static void /* PRIVATE */ -png_setup_sub_row_only(png_structrp png_ptr, const png_uint_32 bpp, +png_setup_sub_row_only(png_structrp png_ptr, png_uint_32 bpp, size_t row_bytes) { png_bytep rp, dp, lp; @@ -2380,7 +2380,7 @@ png_setup_up_row_only(png_structrp png_ptr, size_t row_bytes) } static size_t /* PRIVATE */ -png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, +png_setup_avg_row(png_structrp png_ptr, png_uint_32 bpp, size_t row_bytes, size_t lmins) { png_bytep rp, dp, pp, lp; @@ -2420,7 +2420,7 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, return (sum); } static void /* PRIVATE */ -png_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp, +png_setup_avg_row_only(png_structrp png_ptr, png_uint_32 bpp, size_t row_bytes) { png_bytep rp, dp, pp, lp; @@ -2442,7 +2442,7 @@ png_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp, } static size_t /* PRIVATE */ -png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, +png_setup_paeth_row(png_structrp png_ptr, png_uint_32 bpp, size_t row_bytes, size_t lmins) { png_bytep rp, dp, pp, cp, lp; @@ -2503,7 +2503,7 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, return (sum); } static void /* PRIVATE */ -png_setup_paeth_row_only(png_structrp png_ptr, const png_uint_32 bpp, +png_setup_paeth_row_only(png_structrp png_ptr, png_uint_32 bpp, size_t row_bytes) { png_bytep rp, dp, pp, cp, lp; diff --git a/3rdparty/libpng/powerpc/filter_vsx_intrinsics.c b/3rdparty/libpng/powerpc/filter_vsx_intrinsics.c index 39521cfc8a..01cf8800dc 100644 --- a/3rdparty/libpng/powerpc/filter_vsx_intrinsics.c +++ b/3rdparty/libpng/powerpc/filter_vsx_intrinsics.c @@ -1,13 +1,14 @@ /* filter_vsx_intrinsics.c - PowerPC optimised filter functions * + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 2017 Glenn Randers-Pehrson * Written by Vadim Barkov, 2017. - * Last changed in libpng 1.6.29 [March 16, 2017] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ + #include #include #include "../pngpriv.h" @@ -173,7 +174,7 @@ static const vector unsigned char VSX_SHORT_TO_CHAR4_3 = {16,16,16,16,16,16,16,1 void png_read_filter_row_sub4_vsx(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - const png_byte bpp = 4; + png_byte bpp = 4; vector unsigned char rp_vec; vector unsigned char part_vec; @@ -230,7 +231,7 @@ void png_read_filter_row_sub4_vsx(png_row_infop row_info, png_bytep row, void png_read_filter_row_sub3_vsx(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - const png_byte bpp = 3; + png_byte bpp = 3; vector unsigned char rp_vec; vector unsigned char part_vec; @@ -294,7 +295,7 @@ void png_read_filter_row_sub3_vsx(png_row_infop row_info, png_bytep row, void png_read_filter_row_avg4_vsx(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - const png_byte bpp = 4; + png_byte bpp = 4; vector unsigned char rp_vec; vector unsigned char pp_vec; @@ -381,7 +382,7 @@ void png_read_filter_row_avg4_vsx(png_row_infop row_info, png_bytep row, void png_read_filter_row_avg3_vsx(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - const png_byte bpp = 3; + png_byte bpp = 3; vector unsigned char rp_vec; vector unsigned char pp_vec; @@ -499,7 +500,7 @@ void png_read_filter_row_avg3_vsx(png_row_infop row_info, png_bytep row, void png_read_filter_row_paeth4_vsx(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - const png_byte bpp = 4; + png_byte bpp = 4; int a, b, c, pa, pb, pc, p; vector unsigned char rp_vec; @@ -619,7 +620,7 @@ void png_read_filter_row_paeth4_vsx(png_row_infop row_info, png_bytep row, void png_read_filter_row_paeth3_vsx(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - const png_byte bpp = 3; + png_byte bpp = 3; int a, b, c, pa, pb, pc, p; vector unsigned char rp_vec; diff --git a/3rdparty/libpng/powerpc/powerpc_init.c b/3rdparty/libpng/powerpc/powerpc_init.c index 07016177c5..54426c558e 100644 --- a/3rdparty/libpng/powerpc/powerpc_init.c +++ b/3rdparty/libpng/powerpc/powerpc_init.c @@ -1,14 +1,15 @@ /* powerpc_init.c - POWERPC optimised filter functions * + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 2017 Glenn Randers-Pehrson * Written by Vadim Barkov, 2017. - * Last changed in libpng 1.6.29 [March 16, 2017] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ + /* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are * called. */ From b40a7ffbe4a8a671643c5cc12282f2e74855d951 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 11 Feb 2019 16:21:49 +0300 Subject: [PATCH 07/21] core: dispatch sum --- modules/core/CMakeLists.txt | 1 + modules/core/src/sum.dispatch.cpp | 441 +----------------------------- modules/core/src/sum.simd.hpp | 240 +--------------- 3 files changed, 25 insertions(+), 657 deletions(-) diff --git a/modules/core/CMakeLists.txt b/modules/core/CMakeLists.txt index c4f073713c..bfa2fd1d98 100644 --- a/modules/core/CMakeLists.txt +++ b/modules/core/CMakeLists.txt @@ -5,6 +5,7 @@ ocv_add_dispatched_file(stat SSE4_2 AVX2) ocv_add_dispatched_file(arithm SSE2 SSE4_1 AVX2 VSX3) ocv_add_dispatched_file(convert SSE2 AVX2) ocv_add_dispatched_file(convert_scale SSE2 AVX2) +ocv_add_dispatched_file(sum SSE2 AVX2) # dispatching for accuracy tests ocv_add_dispatched_file_force_all(test_intrin128 TEST SSE2 SSE3 SSSE3 SSE4_1 SSE4_2 AVX FP16 AVX2) diff --git a/modules/core/src/sum.dispatch.cpp b/modules/core/src/sum.dispatch.cpp index 30cee85b4c..6ca5f9ded9 100644 --- a/modules/core/src/sum.dispatch.cpp +++ b/modules/core/src/sum.dispatch.cpp @@ -7,440 +7,17 @@ #include "opencl_kernels_core.hpp" #include "stat.hpp" -namespace cv -{ - -template -struct Sum_SIMD -{ - int operator () (const T *, const uchar *, ST *, int, int) const - { - return 0; - } -}; - -#if CV_SIMD - -template <> -struct Sum_SIMD -{ - int operator () (const uchar * src0, const uchar * mask, int * dst, int len, int cn) const - { - if (mask || (cn != 1 && cn != 2 && cn != 4)) - return 0; - len *= cn; - - int x = 0; - v_uint32 v_sum = vx_setzero_u32(); - - int len0 = len & -v_uint8::nlanes; - while (x < len0) - { - const int len_tmp = min(x + 256*v_uint16::nlanes, len0); - v_uint16 v_sum16 = vx_setzero_u16(); - for (; x < len_tmp; x += v_uint8::nlanes) - { - v_uint16 v_src0, v_src1; - v_expand(vx_load(src0 + x), v_src0, v_src1); - v_sum16 += v_src0 + v_src1; - } - v_uint32 v_half0, v_half1; - v_expand(v_sum16, v_half0, v_half1); - v_sum += v_half0 + v_half1; - } - if (x <= len - v_uint16::nlanes) - { - v_uint32 v_half0, v_half1; - v_expand(vx_load_expand(src0 + x), v_half0, v_half1); - v_sum += v_half0 + v_half1; - x += v_uint16::nlanes; - } - if (x <= len - v_uint32::nlanes) - { - v_sum += vx_load_expand_q(src0 + x); - x += v_uint32::nlanes; - } - - if (cn == 1) - *dst += v_reduce_sum(v_sum); - else - { - uint32_t CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[v_uint32::nlanes]; - v_store_aligned(ar, v_sum); - for (int i = 0; i < v_uint32::nlanes; ++i) - dst[i % cn] += ar[i]; - } - v_cleanup(); - - return x / cn; - } -}; - -template <> -struct Sum_SIMD -{ - int operator () (const schar * src0, const uchar * mask, int * dst, int len, int cn) const - { - if (mask || (cn != 1 && cn != 2 && cn != 4)) - return 0; - len *= cn; - - int x = 0; - v_int32 v_sum = vx_setzero_s32(); - - int len0 = len & -v_int8::nlanes; - while (x < len0) - { - const int len_tmp = min(x + 256*v_int16::nlanes, len0); - v_int16 v_sum16 = vx_setzero_s16(); - for (; x < len_tmp; x += v_int8::nlanes) - { - v_int16 v_src0, v_src1; - v_expand(vx_load(src0 + x), v_src0, v_src1); - v_sum16 += v_src0 + v_src1; - } - v_int32 v_half0, v_half1; - v_expand(v_sum16, v_half0, v_half1); - v_sum += v_half0 + v_half1; - } - if (x <= len - v_int16::nlanes) - { - v_int32 v_half0, v_half1; - v_expand(vx_load_expand(src0 + x), v_half0, v_half1); - v_sum += v_half0 + v_half1; - x += v_int16::nlanes; - } - if (x <= len - v_int32::nlanes) - { - v_sum += vx_load_expand_q(src0 + x); - x += v_int32::nlanes; - } - - if (cn == 1) - *dst += v_reduce_sum(v_sum); - else - { - int32_t CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[v_int32::nlanes]; - v_store_aligned(ar, v_sum); - for (int i = 0; i < v_int32::nlanes; ++i) - dst[i % cn] += ar[i]; - } - v_cleanup(); - - return x / cn; - } -}; - -template <> -struct Sum_SIMD -{ - int operator () (const ushort * src0, const uchar * mask, int * dst, int len, int cn) const - { - if (mask || (cn != 1 && cn != 2 && cn != 4)) - return 0; - len *= cn; - - int x = 0; - v_uint32 v_sum = vx_setzero_u32(); - - for (; x <= len - v_uint16::nlanes; x += v_uint16::nlanes) - { - v_uint32 v_src0, v_src1; - v_expand(vx_load(src0 + x), v_src0, v_src1); - v_sum += v_src0 + v_src1; - } - if (x <= len - v_uint32::nlanes) - { - v_sum += vx_load_expand(src0 + x); - x += v_uint32::nlanes; - } - - if (cn == 1) - *dst += v_reduce_sum(v_sum); - else - { - uint32_t CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[v_uint32::nlanes]; - v_store_aligned(ar, v_sum); - for (int i = 0; i < v_uint32::nlanes; ++i) - dst[i % cn] += ar[i]; - } - v_cleanup(); - - return x / cn; - } -}; - -template <> -struct Sum_SIMD -{ - int operator () (const short * src0, const uchar * mask, int * dst, int len, int cn) const - { - if (mask || (cn != 1 && cn != 2 && cn != 4)) - return 0; - len *= cn; - - int x = 0; - v_int32 v_sum = vx_setzero_s32(); - - for (; x <= len - v_int16::nlanes; x += v_int16::nlanes) - { - v_int32 v_src0, v_src1; - v_expand(vx_load(src0 + x), v_src0, v_src1); - v_sum += v_src0 + v_src1; - } - if (x <= len - v_int32::nlanes) - { - v_sum += vx_load_expand(src0 + x); - x += v_int32::nlanes; - } - - if (cn == 1) - *dst += v_reduce_sum(v_sum); - else - { - int32_t CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[v_int32::nlanes]; - v_store_aligned(ar, v_sum); - for (int i = 0; i < v_int32::nlanes; ++i) - dst[i % cn] += ar[i]; - } - v_cleanup(); - - return x / cn; - } -}; +#include "sum.simd.hpp" +#include "sum.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content -#if CV_SIMD_64F -template <> -struct Sum_SIMD -{ - int operator () (const int * src0, const uchar * mask, double * dst, int len, int cn) const - { - if (mask || (cn != 1 && cn != 2 && cn != 4)) - return 0; - len *= cn; - - int x = 0; - v_float64 v_sum0 = vx_setzero_f64(); - v_float64 v_sum1 = vx_setzero_f64(); - - for (; x <= len - 2 * v_int32::nlanes; x += 2 * v_int32::nlanes) - { - v_int32 v_src0 = vx_load(src0 + x); - v_int32 v_src1 = vx_load(src0 + x + v_int32::nlanes); - v_sum0 += v_cvt_f64(v_src0) + v_cvt_f64(v_src1); - v_sum1 += v_cvt_f64_high(v_src0) + v_cvt_f64_high(v_src1); - } - -#if CV_SIMD256 || CV_SIMD512 - double CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[v_float64::nlanes]; - v_store_aligned(ar, v_sum0 + v_sum1); - for (int i = 0; i < v_float64::nlanes; ++i) - dst[i % cn] += ar[i]; -#else - double CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[2 * v_float64::nlanes]; - v_store_aligned(ar, v_sum0); - v_store_aligned(ar + v_float64::nlanes, v_sum1); - for (int i = 0; i < 2 * v_float64::nlanes; ++i) - dst[i % cn] += ar[i]; -#endif - v_cleanup(); - - return x / cn; - } -}; - -template <> -struct Sum_SIMD -{ - int operator () (const float * src0, const uchar * mask, double * dst, int len, int cn) const - { - if (mask || (cn != 1 && cn != 2 && cn != 4)) - return 0; - len *= cn; - - int x = 0; - v_float64 v_sum0 = vx_setzero_f64(); - v_float64 v_sum1 = vx_setzero_f64(); - - for (; x <= len - 2 * v_float32::nlanes; x += 2 * v_float32::nlanes) - { - v_float32 v_src0 = vx_load(src0 + x); - v_float32 v_src1 = vx_load(src0 + x + v_float32::nlanes); - v_sum0 += v_cvt_f64(v_src0) + v_cvt_f64(v_src1); - v_sum1 += v_cvt_f64_high(v_src0) + v_cvt_f64_high(v_src1); - } - -#if CV_SIMD256 || CV_SIMD512 - double CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[v_float64::nlanes]; - v_store_aligned(ar, v_sum0 + v_sum1); - for (int i = 0; i < v_float64::nlanes; ++i) - dst[i % cn] += ar[i]; -#else - double CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[2 * v_float64::nlanes]; - v_store_aligned(ar, v_sum0); - v_store_aligned(ar + v_float64::nlanes, v_sum1); - for (int i = 0; i < 2 * v_float64::nlanes; ++i) - dst[i % cn] += ar[i]; -#endif - v_cleanup(); - - return x / cn; - } -}; -#endif -#endif - -template -static int sum_(const T* src0, const uchar* mask, ST* dst, int len, int cn ) +namespace cv { - const T* src = src0; - if( !mask ) - { - Sum_SIMD vop; - int i = vop(src0, mask, dst, len, cn), k = cn % 4; - src += i * cn; - - if( k == 1 ) - { - ST s0 = dst[0]; - - #if CV_ENABLE_UNROLLED - for(; i <= len - 4; i += 4, src += cn*4 ) - s0 += src[0] + src[cn] + src[cn*2] + src[cn*3]; - #endif - for( ; i < len; i++, src += cn ) - s0 += src[0]; - dst[0] = s0; - } - else if( k == 2 ) - { - ST s0 = dst[0], s1 = dst[1]; - for( ; i < len; i++, src += cn ) - { - s0 += src[0]; - s1 += src[1]; - } - dst[0] = s0; - dst[1] = s1; - } - else if( k == 3 ) - { - ST s0 = dst[0], s1 = dst[1], s2 = dst[2]; - for( ; i < len; i++, src += cn ) - { - s0 += src[0]; - s1 += src[1]; - s2 += src[2]; - } - dst[0] = s0; - dst[1] = s1; - dst[2] = s2; - } - - for( ; k < cn; k += 4 ) - { - src = src0 + i*cn + k; - ST s0 = dst[k], s1 = dst[k+1], s2 = dst[k+2], s3 = dst[k+3]; - for( ; i < len; i++, src += cn ) - { - s0 += src[0]; s1 += src[1]; - s2 += src[2]; s3 += src[3]; - } - dst[k] = s0; - dst[k+1] = s1; - dst[k+2] = s2; - dst[k+3] = s3; - } - return len; - } - - int i, nzm = 0; - if( cn == 1 ) - { - ST s = dst[0]; - for( i = 0; i < len; i++ ) - if( mask[i] ) - { - s += src[i]; - nzm++; - } - dst[0] = s; - } - else if( cn == 3 ) - { - ST s0 = dst[0], s1 = dst[1], s2 = dst[2]; - for( i = 0; i < len; i++, src += 3 ) - if( mask[i] ) - { - s0 += src[0]; - s1 += src[1]; - s2 += src[2]; - nzm++; - } - dst[0] = s0; - dst[1] = s1; - dst[2] = s2; - } - else - { - for( i = 0; i < len; i++, src += cn ) - if( mask[i] ) - { - int k = 0; - #if CV_ENABLE_UNROLLED - for( ; k <= cn - 4; k += 4 ) - { - ST s0, s1; - s0 = dst[k] + src[k]; - s1 = dst[k+1] + src[k+1]; - dst[k] = s0; dst[k+1] = s1; - s0 = dst[k+2] + src[k+2]; - s1 = dst[k+3] + src[k+3]; - dst[k+2] = s0; dst[k+3] = s1; - } - #endif - for( ; k < cn; k++ ) - dst[k] += src[k]; - nzm++; - } - } - return nzm; -} - - -static int sum8u( const uchar* src, const uchar* mask, int* dst, int len, int cn ) -{ return sum_(src, mask, dst, len, cn); } - -static int sum8s( const schar* src, const uchar* mask, int* dst, int len, int cn ) -{ return sum_(src, mask, dst, len, cn); } - -static int sum16u( const ushort* src, const uchar* mask, int* dst, int len, int cn ) -{ return sum_(src, mask, dst, len, cn); } - -static int sum16s( const short* src, const uchar* mask, int* dst, int len, int cn ) -{ return sum_(src, mask, dst, len, cn); } - -static int sum32s( const int* src, const uchar* mask, double* dst, int len, int cn ) -{ return sum_(src, mask, dst, len, cn); } - -static int sum32f( const float* src, const uchar* mask, double* dst, int len, int cn ) -{ return sum_(src, mask, dst, len, cn); } - -static int sum64f( const double* src, const uchar* mask, double* dst, int len, int cn ) -{ return sum_(src, mask, dst, len, cn); } SumFunc getSumFunc(int depth) { - static SumFunc sumTab[] = - { - (SumFunc)GET_OPTIMIZED(sum8u), (SumFunc)sum8s, - (SumFunc)sum16u, (SumFunc)sum16s, - (SumFunc)sum32s, - (SumFunc)GET_OPTIMIZED(sum32f), (SumFunc)sum64f, - 0 - }; - - return sumTab[depth]; + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(getSumFunc, (depth), + CV_CPU_DISPATCH_MODES_ALL); } #ifdef HAVE_OPENCL @@ -593,9 +170,7 @@ static bool ipp_sum(Mat &src, Scalar &_res) } #endif -} // cv:: - -cv::Scalar cv::sum( InputArray _src ) +Scalar sum(InputArray _src) { CV_INSTRUMENT_REGION(); @@ -660,3 +235,5 @@ cv::Scalar cv::sum( InputArray _src ) } return s; } + +} // namespace diff --git a/modules/core/src/sum.simd.hpp b/modules/core/src/sum.simd.hpp index 30cee85b4c..2232013b24 100644 --- a/modules/core/src/sum.simd.hpp +++ b/modules/core/src/sum.simd.hpp @@ -4,11 +4,14 @@ #include "precomp.hpp" -#include "opencl_kernels_core.hpp" #include "stat.hpp" -namespace cv -{ +namespace cv { +CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN + +SumFunc getSumFunc(int depth); + +#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY template struct Sum_SIMD @@ -409,25 +412,25 @@ static int sum_(const T* src0, const uchar* mask, ST* dst, int len, int cn ) static int sum8u( const uchar* src, const uchar* mask, int* dst, int len, int cn ) -{ return sum_(src, mask, dst, len, cn); } +{ CV_INSTRUMENT_REGION(); return sum_(src, mask, dst, len, cn); } static int sum8s( const schar* src, const uchar* mask, int* dst, int len, int cn ) -{ return sum_(src, mask, dst, len, cn); } +{ CV_INSTRUMENT_REGION(); return sum_(src, mask, dst, len, cn); } static int sum16u( const ushort* src, const uchar* mask, int* dst, int len, int cn ) -{ return sum_(src, mask, dst, len, cn); } +{ CV_INSTRUMENT_REGION(); return sum_(src, mask, dst, len, cn); } static int sum16s( const short* src, const uchar* mask, int* dst, int len, int cn ) -{ return sum_(src, mask, dst, len, cn); } +{ CV_INSTRUMENT_REGION(); return sum_(src, mask, dst, len, cn); } static int sum32s( const int* src, const uchar* mask, double* dst, int len, int cn ) -{ return sum_(src, mask, dst, len, cn); } +{ CV_INSTRUMENT_REGION(); return sum_(src, mask, dst, len, cn); } static int sum32f( const float* src, const uchar* mask, double* dst, int len, int cn ) -{ return sum_(src, mask, dst, len, cn); } +{ CV_INSTRUMENT_REGION(); return sum_(src, mask, dst, len, cn); } static int sum64f( const double* src, const uchar* mask, double* dst, int len, int cn ) -{ return sum_(src, mask, dst, len, cn); } +{ CV_INSTRUMENT_REGION(); return sum_(src, mask, dst, len, cn); } SumFunc getSumFunc(int depth) { @@ -443,220 +446,7 @@ SumFunc getSumFunc(int depth) return sumTab[depth]; } -#ifdef HAVE_OPENCL - -bool ocl_sum( InputArray _src, Scalar & res, int sum_op, InputArray _mask, - InputArray _src2, bool calc2, const Scalar & res2 ) -{ - CV_Assert(sum_op == OCL_OP_SUM || sum_op == OCL_OP_SUM_ABS || sum_op == OCL_OP_SUM_SQR); - - const ocl::Device & dev = ocl::Device::getDefault(); - bool doubleSupport = dev.doubleFPConfig() > 0, - haveMask = _mask.kind() != _InputArray::NONE, - haveSrc2 = _src2.kind() != _InputArray::NONE; - int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), - kercn = cn == 1 && !haveMask ? ocl::predictOptimalVectorWidth(_src, _src2) : 1, - mcn = std::max(cn, kercn); - CV_Assert(!haveSrc2 || _src2.type() == type); - int convert_cn = haveSrc2 ? mcn : cn; - - if ( (!doubleSupport && depth == CV_64F) || cn > 4 ) - return false; - - int ngroups = dev.maxComputeUnits(), dbsize = ngroups * (calc2 ? 2 : 1); - size_t wgs = dev.maxWorkGroupSize(); - - int ddepth = std::max(sum_op == OCL_OP_SUM_SQR ? CV_32F : CV_32S, depth), - dtype = CV_MAKE_TYPE(ddepth, cn); - CV_Assert(!haveMask || _mask.type() == CV_8UC1); - - int wgs2_aligned = 1; - while (wgs2_aligned < (int)wgs) - wgs2_aligned <<= 1; - wgs2_aligned >>= 1; - - static const char * const opMap[3] = { "OP_SUM", "OP_SUM_ABS", "OP_SUM_SQR" }; - char cvt[2][40]; - String opts = format("-D srcT=%s -D srcT1=%s -D dstT=%s -D dstTK=%s -D dstT1=%s -D ddepth=%d -D cn=%d" - " -D convertToDT=%s -D %s -D WGS=%d -D WGS2_ALIGNED=%d%s%s%s%s -D kercn=%d%s%s%s -D convertFromU=%s", - ocl::typeToStr(CV_MAKE_TYPE(depth, mcn)), ocl::typeToStr(depth), - ocl::typeToStr(dtype), ocl::typeToStr(CV_MAKE_TYPE(ddepth, mcn)), - ocl::typeToStr(ddepth), ddepth, cn, - ocl::convertTypeStr(depth, ddepth, mcn, cvt[0]), - opMap[sum_op], (int)wgs, wgs2_aligned, - doubleSupport ? " -D DOUBLE_SUPPORT" : "", - haveMask ? " -D HAVE_MASK" : "", - _src.isContinuous() ? " -D HAVE_SRC_CONT" : "", - haveMask && _mask.isContinuous() ? " -D HAVE_MASK_CONT" : "", kercn, - haveSrc2 ? " -D HAVE_SRC2" : "", calc2 ? " -D OP_CALC2" : "", - haveSrc2 && _src2.isContinuous() ? " -D HAVE_SRC2_CONT" : "", - depth <= CV_32S && ddepth == CV_32S ? ocl::convertTypeStr(CV_8U, ddepth, convert_cn, cvt[1]) : "noconvert"); - - ocl::Kernel k("reduce", ocl::core::reduce_oclsrc, opts); - if (k.empty()) - return false; - - UMat src = _src.getUMat(), src2 = _src2.getUMat(), - db(1, dbsize, dtype), mask = _mask.getUMat(); - - ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src), - dbarg = ocl::KernelArg::PtrWriteOnly(db), - maskarg = ocl::KernelArg::ReadOnlyNoSize(mask), - src2arg = ocl::KernelArg::ReadOnlyNoSize(src2); - - if (haveMask) - { - if (haveSrc2) - k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg, maskarg, src2arg); - else - k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg, maskarg); - } - else - { - if (haveSrc2) - k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg, src2arg); - else - k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg); - } - - size_t globalsize = ngroups * wgs; - if (k.run(1, &globalsize, &wgs, false)) - { - typedef Scalar (*part_sum)(Mat m); - part_sum funcs[3] = { ocl_part_sum, ocl_part_sum, ocl_part_sum }, - func = funcs[ddepth - CV_32S]; - - Mat mres = db.getMat(ACCESS_READ); - if (calc2) - const_cast(res2) = func(mres.colRange(ngroups, dbsize)); - - res = func(mres.colRange(0, ngroups)); - return true; - } - return false; -} - -#endif - -#ifdef HAVE_IPP -static bool ipp_sum(Mat &src, Scalar &_res) -{ - CV_INSTRUMENT_REGION_IPP(); - -#if IPP_VERSION_X100 >= 700 - int cn = src.channels(); - if (cn > 4) - return false; - size_t total_size = src.total(); - int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; - if( src.dims == 2 || (src.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) ) - { - IppiSize sz = { cols, rows }; - int type = src.type(); - typedef IppStatus (CV_STDCALL* ippiSumFuncHint)(const void*, int, IppiSize, double *, IppHintAlgorithm); - typedef IppStatus (CV_STDCALL* ippiSumFuncNoHint)(const void*, int, IppiSize, double *); - ippiSumFuncHint ippiSumHint = - type == CV_32FC1 ? (ippiSumFuncHint)ippiSum_32f_C1R : - type == CV_32FC3 ? (ippiSumFuncHint)ippiSum_32f_C3R : - type == CV_32FC4 ? (ippiSumFuncHint)ippiSum_32f_C4R : - 0; - ippiSumFuncNoHint ippiSum = - type == CV_8UC1 ? (ippiSumFuncNoHint)ippiSum_8u_C1R : - type == CV_8UC3 ? (ippiSumFuncNoHint)ippiSum_8u_C3R : - type == CV_8UC4 ? (ippiSumFuncNoHint)ippiSum_8u_C4R : - type == CV_16UC1 ? (ippiSumFuncNoHint)ippiSum_16u_C1R : - type == CV_16UC3 ? (ippiSumFuncNoHint)ippiSum_16u_C3R : - type == CV_16UC4 ? (ippiSumFuncNoHint)ippiSum_16u_C4R : - type == CV_16SC1 ? (ippiSumFuncNoHint)ippiSum_16s_C1R : - type == CV_16SC3 ? (ippiSumFuncNoHint)ippiSum_16s_C3R : - type == CV_16SC4 ? (ippiSumFuncNoHint)ippiSum_16s_C4R : - 0; - CV_Assert(!ippiSumHint || !ippiSum); - if( ippiSumHint || ippiSum ) - { - Ipp64f res[4]; - IppStatus ret = ippiSumHint ? - CV_INSTRUMENT_FUN_IPP(ippiSumHint, src.ptr(), (int)src.step[0], sz, res, ippAlgHintAccurate) : - CV_INSTRUMENT_FUN_IPP(ippiSum, src.ptr(), (int)src.step[0], sz, res); - if( ret >= 0 ) - { - for( int i = 0; i < cn; i++ ) - _res[i] = res[i]; - return true; - } - } - } -#else - CV_UNUSED(src); CV_UNUSED(_res); -#endif - return false; -} -#endif - -} // cv:: - -cv::Scalar cv::sum( InputArray _src ) -{ - CV_INSTRUMENT_REGION(); - -#if defined HAVE_OPENCL || defined HAVE_IPP - Scalar _res; -#endif - -#ifdef HAVE_OPENCL - CV_OCL_RUN_(OCL_PERFORMANCE_CHECK(_src.isUMat()) && _src.dims() <= 2, - ocl_sum(_src, _res, OCL_OP_SUM), - _res) #endif - Mat src = _src.getMat(); - CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_sum(src, _res), _res); - - int k, cn = src.channels(), depth = src.depth(); - SumFunc func = getSumFunc(depth); - CV_Assert( cn <= 4 && func != 0 ); - - const Mat* arrays[] = {&src, 0}; - uchar* ptrs[1] = {}; - NAryMatIterator it(arrays, ptrs); - Scalar s; - int total = (int)it.size, blockSize = total, intSumBlockSize = 0; - int j, count = 0; - AutoBuffer _buf; - int* buf = (int*)&s[0]; - size_t esz = 0; - bool blockSum = depth < CV_32S; - - if( blockSum ) - { - intSumBlockSize = depth <= CV_8S ? (1 << 23) : (1 << 15); - blockSize = std::min(blockSize, intSumBlockSize); - _buf.allocate(cn); - buf = _buf.data(); - - for( k = 0; k < cn; k++ ) - buf[k] = 0; - esz = src.elemSize(); - } - - for( size_t i = 0; i < it.nplanes; i++, ++it ) - { - for( j = 0; j < total; j += blockSize ) - { - int bsz = std::min(total - j, blockSize); - func( ptrs[0], 0, (uchar*)buf, bsz, cn ); - count += bsz; - if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) ) - { - for( k = 0; k < cn; k++ ) - { - s[k] += buf[k]; - buf[k] = 0; - } - count = 0; - } - ptrs[0] += bsz*esz; - } - } - return s; -} +CV_CPU_OPTIMIZATION_NAMESPACE_END +} // namespace From ff1ec6ccc6edb7dce92a9511be00c1bc62b01326 Mon Sep 17 00:00:00 2001 From: Stefan Dragnev Date: Tue, 12 Feb 2019 14:43:58 +0100 Subject: [PATCH 08/21] update to libtiff-4.0.10 --- 3rdparty/libtiff/CMakeLists.txt | 9 +- 3rdparty/libtiff/ChangeLog | 3913 +++++++++++++++++++++--- 3rdparty/libtiff/libport.h | 67 + 3rdparty/libtiff/snprintf.c | 2 +- 3rdparty/libtiff/t4.h | 2 - 3rdparty/libtiff/tif_aux.c | 2 - 3rdparty/libtiff/tif_close.c | 2 - 3rdparty/libtiff/tif_codec.c | 10 +- 3rdparty/libtiff/tif_color.c | 4 +- 3rdparty/libtiff/tif_compress.c | 2 - 3rdparty/libtiff/tif_config.h.cmake.in | 51 +- 3rdparty/libtiff/tif_dir.c | 29 +- 3rdparty/libtiff/tif_dir.h | 6 +- 3rdparty/libtiff/tif_dirinfo.c | 17 +- 3rdparty/libtiff/tif_dirread.c | 117 +- 3rdparty/libtiff/tif_dirwrite.c | 9 +- 3rdparty/libtiff/tif_dumpmode.c | 2 - 3rdparty/libtiff/tif_error.c | 2 - 3rdparty/libtiff/tif_extension.c | 2 - 3rdparty/libtiff/tif_fax3.c | 2 - 3rdparty/libtiff/tif_fax3.h | 2 - 3rdparty/libtiff/tif_flush.c | 2 - 3rdparty/libtiff/tif_getimage.c | 2 - 3rdparty/libtiff/tif_jbig.c | 34 +- 3rdparty/libtiff/tif_jpeg.c | 6 +- 3rdparty/libtiff/tif_luv.c | 12 +- 3rdparty/libtiff/tif_lzma.c | 11 +- 3rdparty/libtiff/tif_lzw.c | 32 +- 3rdparty/libtiff/tif_next.c | 2 - 3rdparty/libtiff/tif_ojpeg.c | 2 - 3rdparty/libtiff/tif_open.c | 2 - 3rdparty/libtiff/tif_packbits.c | 2 - 3rdparty/libtiff/tif_pixarlog.c | 2 - 3rdparty/libtiff/tif_predict.c | 2 - 3rdparty/libtiff/tif_predict.h | 6 +- 3rdparty/libtiff/tif_print.c | 12 +- 3rdparty/libtiff/tif_read.c | 13 +- 3rdparty/libtiff/tif_stream.cxx | 460 +-- 3rdparty/libtiff/tif_strip.c | 2 - 3rdparty/libtiff/tif_swab.c | 2 - 3rdparty/libtiff/tif_thunder.c | 2 - 3rdparty/libtiff/tif_tile.c | 2 - 3rdparty/libtiff/tif_unix.c | 2 - 3rdparty/libtiff/tif_version.c | 1 - 3rdparty/libtiff/tif_warning.c | 2 - 3rdparty/libtiff/tif_webp.c | 684 +++++ 3rdparty/libtiff/tif_win32.c | 41 - 3rdparty/libtiff/tif_write.c | 8 +- 3rdparty/libtiff/tif_zip.c | 2 - 3rdparty/libtiff/tif_zstd.c | 440 +++ 3rdparty/libtiff/tiff.h | 18 +- 3rdparty/libtiff/tiffconf.h.cmake.in | 9 - 3rdparty/libtiff/tiffio.h | 4 +- 3rdparty/libtiff/tiffio.hxx | 3 +- 3rdparty/libtiff/tiffiop.h | 15 +- 3rdparty/libtiff/tiffvers.h | 4 +- 56 files changed, 5168 insertions(+), 927 deletions(-) create mode 100644 3rdparty/libtiff/libport.h create mode 100644 3rdparty/libtiff/tif_webp.c create mode 100644 3rdparty/libtiff/tif_zstd.c diff --git a/3rdparty/libtiff/CMakeLists.txt b/3rdparty/libtiff/CMakeLists.txt index 7767cf49b5..2319b9853e 100644 --- a/3rdparty/libtiff/CMakeLists.txt +++ b/3rdparty/libtiff/CMakeLists.txt @@ -414,10 +414,11 @@ set(lib_srcs tif_tile.c tif_version.c tif_warning.c + tif_webp.c tif_write.c tif_zip.c + tif_zstd.c tif_stream.cxx - snprintf.c t4.h tif_dir.h tif_fax3.h @@ -432,6 +433,10 @@ set(lib_srcs "${CMAKE_CURRENT_BINARY_DIR}/tiffconf.h" ) +if(WIN32 AND NOT HAVE_SNPRINTF) + list(APPEND lib_srcs snprintf.c libport.h) +endif() + if(WIN32 AND NOT WINRT) list(APPEND lib_srcs tif_win32.c) else() @@ -444,7 +449,7 @@ ocv_warnings_disable(CMAKE_C_FLAGS -Wno-unused-but-set-variable -Wmissing-protot -Wimplicit-fallthrough ) ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter) # clang -ocv_warnings_disable(CMAKE_CXX_FLAGS -Wmissing-declarations -Wunused-parameter +ocv_warnings_disable(CMAKE_CXX_FLAGS -Wmissing-declarations -Wunused-parameter -Wmissing-prototypes -Wundef # tiffiop.h: #if __clang_major__ >= 4 ) ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4018 /wd4100 /wd4127 /wd4311 /wd4701 /wd4706) # vs2005 diff --git a/3rdparty/libtiff/ChangeLog b/3rdparty/libtiff/ChangeLog index 4eab3bba5b..1f50e20135 100644 --- a/3rdparty/libtiff/ChangeLog +++ b/3rdparty/libtiff/ChangeLog @@ -1,3 +1,3018 @@ +2018-11-10 Bob Friesenhahn + + * configure.ac: libtiff 4.0.10 released. + + Change COMPRESSION_ZSTD to 50000 and COMPRESSION_WEBP to 50001. + +2018-11-04 Bob Friesenhahn + + Added preliminary release notes for release 4.0.10. + +2018-11-03 Bob Friesenhahn + + tiff2pdf: Eliminate compiler warning about snprintf output truncation when formatting pdf_datetime. + +2018-11-03 Olivier Paquet + + Merge branch 'no_tif_platform_console' into 'master' + Remove builtin support for GUI warning and error message boxes + + See merge request libtiff/libtiff!24 + +2018-11-03 Bob Friesenhahn + + tiffcrop.c: Eliminate compiler warning about snprintf output truncation when formatting filenum. + + TWebPVGetField(): Add apparently missing break statement impacting TIFFTAG_WEBP_LOSSLESS. + + Eliminate compiler warnings about duplicate definitions of streq/strneq macros. + + Ignore generated files. + + Remove and ignore files which are a product of autogen.sh. + +2018-11-02 Bob Friesenhahn + + Fix TIFFErrorExt() formatting of size_t type for 32-bit compiles. + +2018-10-30 Even Rouault + + tiff2bw: avoid null pointer dereference in case of out of memory situation. Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2819 / CVE-2018-18661 + + tiffio.h: fix comment. + +2018-10-26 Even Rouault + + Merge branch 'header2' into 'master' + Fix 725279bd: Standalone tif_predict.h: tiff.h should be tiffiop.h + + See merge request libtiff/libtiff!41 + +2018-10-26 Kurt Schwehr + + Fix 725279bd: Standalone tif_predict.h: tiff.h should be tiffiop.h. + +2018-10-25 Even Rouault + + Merge branch 'headers' into 'master' + Add includes to headers to allow them to stand alone. + + See merge request libtiff/libtiff!40 + +2018-10-24 Kurt Schwehr + + Add includes to headers to allow them to stand alone. + This allows compilers that can do header stand alone header parsing + to process libtiff. + +2018-10-18 Even Rouault + + LZMAPreEncode: emit verbose error if lzma_stream_encoder() fails (typically because not enough memory available) + +2018-10-17 Even Rouault + + tif_webp.c: fix previous commit that broke scanline decoding. + + tif_webp.c: fix potential read outside libwebp buffer on corrupted images + +2018-10-14 Even Rouault + + Merge branch 'jbig_decode_overflow' into 'master' + JBIG: fix potential out-of-bounds write in JBIGDecode() + + See merge request libtiff/libtiff!38 + +2018-10-14 Even Rouault + + JBIG: fix potential out-of-bounds write in JBIGDecode() + JBIGDecode doesn't check if the user provided buffer is large enough + to store the JBIG decoded image, which can potentially cause out-of-bounds + write in the buffer. + This issue was reported and analyzed by Thomas Dullien. + + Also fixes a (harmless) potential use of uninitialized memory when + tif->tif_rawsize > tif->tif_rawcc + + And in case libtiff is compiled with CHUNKY_STRIP_READ_SUPPORT, make sure + that whole strip data is provided to JBIGDecode() + +2018-10-05 Even Rouault + + tif_webp.c: fix scanline reading/writing. + + WEBP codec: initialize nSamples in TWebPSetupDecode() and TWebPSetupEncode() + +2018-10-05 Even Rouault + + Merge branch 'tif_webp' into 'master' + webp support + + See merge request libtiff/libtiff!32 + +2018-10-05 Norman Barker + + webp in tiff. + +2018-09-17 Even Rouault + + Merge branch 'master' into 'master' + fix three potential vulnerabilities. + + See merge request libtiff/libtiff!33 + +2018-09-08 Young_X + + fix out-of-bound read on some tiled images. + + avoid potential int32 overflows in multiply_ms() + + only read/write TIFFTAG_GROUP3OPTIONS or TIFFTAG_GROUP4OPTIONS if compression is COMPRESSION_CCITTFAX3 or COMPRESSION_CCITTFAX4 + +2018-08-15 Even Rouault + + TIFFSetupStrips(): avoid potential uint32 overflow on 32-bit systems with large number of strips. Probably relates to http://bugzilla.maptools.org/show_bug.cgi?id=2788 / CVE-2018-10779 + +2018-08-07 Even Rouault + + ZSTD: fix flush issue that can cause endless loop in ZSTDEncode() + Fixes https://github.com/OSGeo/gdal/issues/833 + +2018-08-07 Even Rouault + + Merge branch 'fix_bug_2800' into 'master' + Fix libtiff 4.0.8 regression when reading LZW-compressed strips with scanline API + + See merge request libtiff/libtiff!31 + +2018-08-07 Even Rouault + + Fix libtiff 4.0.8 regression when reading LZW-compressed strips with scanline API + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2800 + +2018-07-05 Even Rouault + + Add tag and pseudo-tag definitions for ESRI LERC codec (out of tree codec whose source is at https://github.com/OSGeo/gdal/blob/master/gdal/frmts/gtiff/tif_lerc.c) + +2018-07-02 Even Rouault + + Fix TIFFTAG_ZSTD_LEVEL pseudo tag value to be > 65536, and the next one in the series + +2018-05-25 Stefan Weil + + Remove builtin support for GUI warning and error message boxes. + Now warnings always go to the console by default unless applications + define their own warning and error handlers. + + GUI applications (and Windows CE) are required to define such handlers. + +2018-05-12 Even Rouault + + LZWDecodeCompat(): fix potential index-out-of-bounds write. Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2780 / CVE-2018-8905 + The fix consists in using the similar code LZWDecode() to validate we + don't write outside of the output buffer. + + TIFFFetchNormalTag(): avoid (probably false positive) clang-tidy clang-analyzer-core.NullDereference warnings + + TIFFWriteDirectorySec: avoid assertion. Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2795. CVE-2018-10963 + +2018-05-04 Even Rouault + + tif_color.c: fix code comment. + +2018-04-17 Even Rouault + + Merge branch 'fuzzer-fix' into 'master' + remove a pointless multiplication and a variable that's not necessary + + See merge request libtiff/libtiff!29 + +2018-04-17 Paul Kehrer + + remove a pointless multiplication and a variable that's not necessary. + +2018-04-17 Even Rouault + + Merge branch 'ossfuzz' into 'master' + move oss-fuzz build script and fuzzer into libtiff tree + + See merge request libtiff/libtiff!28 + +2018-04-17 Paul Kehrer + + move oss-fuzz build script and fuzzer into libtiff tree. + +2018-04-14 Even Rouault + + _TIFFGetMaxColorChannels: update for LOGLUV, ITULAB and ICCLAB that have 3 color channels + +2018-04-12 Even Rouault + + Fix MSVC warning. + +2018-04-12 Even Rouault + + Merge branch 'master' into 'master' + Fix NULL pointer dereference in TIFFPrintDirectory (bugzilla 2778/CVE-2018-7456) + + See merge request libtiff/libtiff!27 + +2018-04-11 Hugo Lefeuvre + + Fix NULL pointer dereference in TIFFPrintDirectory. + The TIFFPrintDirectory function relies on the following assumptions, + supposed to be guaranteed by the specification: + + (a) A Transfer Function field is only present if the TIFF file has + photometric type < 3. + + (b) If SamplesPerPixel > Color Channels, then the ExtraSamples field + has count SamplesPerPixel - (Color Channels) and contains + information about supplementary channels. + + While respect of (a) and (b) are essential for the well functioning of + TIFFPrintDirectory, no checks are realized neither by the callee nor + by TIFFPrintDirectory itself. Hence, following scenarios might happen + and trigger the NULL pointer dereference: + + (1) TIFF File of photometric type 4 or more has illegal Transfer + Function field. + + (2) TIFF File has photometric type 3 or less and defines a + SamplesPerPixel field such that SamplesPerPixel > Color Channels + without defining all extra samples in the ExtraSamples fields. + + In this patch, we address both issues with respect of the following + principles: + + (A) In the case of (1), the defined transfer table should be printed + safely even if it isn't 'legal'. This allows us to avoid expensive + checks in TIFFPrintDirectory. Also, it is quite possible that + an alternative photometric type would be developed (not part of the + standard) and would allow definition of Transfer Table. We want + libtiff to be able to handle this scenario out of the box. + + (B) In the case of (2), the transfer table should be printed at its + right size, that is if TIFF file has photometric type Palette + then the transfer table should have one row and not three, even + if two extra samples are declared. + + In order to fulfill (A) we simply add a new 'i < 3' end condition to + the broken TIFFPrintDirectory loop. This makes sure that in any case + where (b) would be respected but not (a), everything stays fine. + + (B) is fulfilled by the loop condition + 'i < td->td_samplesperpixel - td->td_extrasamples'. This is enough as + long as (b) is respected. + + Naturally, we also make sure (b) is respected. This is done in the + TIFFReadDirectory function by making sure any non-color channel is + counted in ExtraSamples. + + This commit addresses CVE-2018-7456. + +2018-03-27 Even Rouault + + Merge branch 'tiffset-long8' into 'master' + tiffset: Add support for LONG8, SLONG8 and IFD8 field types + + See merge request libtiff/libtiff!25 + +2018-03-26 Roger Leigh + + port: Clean up NetBSD sources and headers to build standalone. + +2018-03-23 Roger Leigh + + port: Add strtol, strtoll and strtoull. + Also update strtoul. All use the same implementation from NetBSD libc. + + tiffset: Add support for LONG8, SLONG8 and IFD8 field types. + +2018-03-17 Even Rouault + + ChopUpSingleUncompressedStrip: avoid memory exhaustion (CVE-2017-11613) + Rework fix done in 3719385a3fac5cfb20b487619a5f08abbf967cf8 to work in more + cases like https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=6979. + Credit to OSS Fuzz + + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2724 + +2018-03-13 Even Rouault + + libtiff/tif_luv.c: rewrite loops in a more readable way (to avoid false positive reports like http://bugzilla.maptools.org/show_bug.cgi?id=2779) + +2018-03-13 Even Rouault + + Merge branch 'avoid_memory_exhaustion_in_ChopUpSingleUncompressedStrip' into 'master' + ChopUpSingleUncompressedStrip: avoid memory exhaustion (CVE-2017-11613) + + See merge request libtiff/libtiff!26 + +2018-03-11 Even Rouault + + ChopUpSingleUncompressedStrip: avoid memory exhaustion (CVE-2017-11613) + In ChopUpSingleUncompressedStrip(), if the computed number of strips is big + enough and we are in read only mode, validate that the file size is consistent + with that number of strips to avoid useless attempts at allocating a lot of + memory for the td_stripbytecount and td_stripoffset arrays. + + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2724 + +2018-03-10 Even Rouault + + Typo fix in comment. + +2018-03-03 Even Rouault + + Avoid warning with gcc 8 (partially revert 647b0e8c11ee11896f319b92cf110775f538d75c) + +2018-02-25 Even Rouault + + Merge branch 'typos' into 'master' + Fix some typos + + See merge request libtiff/libtiff!23 + +2018-02-24 Stefan Weil + + Fix some typos. + Most of them were found by codespell. + +2018-02-14 Even Rouault + + Typo fix in comment. + + Merge branch 'zstd' + + Add warning about COMPRESSION_ZSTD not being officialy registered. + +2018-02-14 Even Rouault + + Merge branch 'bug2772' into 'master' + Fix for bug 2772 + + See merge request libtiff/libtiff!20 + +2018-02-12 Nathan Baker + + Fix for bug 2772. + It is possible to craft a TIFF document where the IFD list is circular, + leading to an infinite loop while traversing the chain. The libtiff + directory reader has a failsafe that will break out of this loop after + reading 65535 directory entries, but it will continue processing, + consuming time and resources to process what is essentially a bogus TIFF + document. + + This change fixes the above behavior by breaking out of processing when + a TIFF document has >= 65535 directories and terminating with an error. + +2018-02-09 Even Rouault + + Merge branch 'libtiff-as-subdirectory-fixes' into 'master' + Prefer target_include_directories + + See merge request libtiff/libtiff!12 + +2018-02-06 Even Rouault + + Merge branch 'cmake-cleanups' into 'master' + Cmake cleanups + + See merge request libtiff/libtiff!11 + +2018-02-06 Even Rouault + + Merge branch 'check-right-cxx-variable' into 'master' + Check right cxx variable + + See merge request libtiff/libtiff!19 + +2018-02-06 Even Rouault + + Merge branch 'dont-leak-stream-open' into 'master' + Fix a memory leak in TIFFStreamOpen + + See merge request libtiff/libtiff!17 + +2018-02-06 Ben Boeckel + + cmake: check CXX_SUPPORT. + This variable is set in response to the `cxx` cache variable; use it + instead. + +2018-02-04 Olivier Paquet + + Merge branch 'warnings' into 'master' + Fix all compiler warnings for default build + + See merge request libtiff/libtiff!16 + +2018-02-04 Nathan Baker + + Fix all compiler warnings for default build. + +2018-01-30 Paul Kehrer + + tabs are hard. + +2018-01-29 Paul Kehrer + + use hard tabs like the rest of the project. + + Fix a memory leak in TIFFStreamOpen. + TIFFStreamOpen allocates a new tiff{o,i}s_data, but if TIFFClientOpen + fails then that struct is leaked. Delete it if the returned TIFF * is + null. + +2018-01-29 Kevin Funk + + Bump minimum required CMake version to v2.8.11. + Because we use the BUILD_INTERFACE generator expression + +2018-01-27 Even Rouault + + Merge branch 'patch-1' into 'master' + Update CMakeLists.txt for build fix on Windows + + See merge request libtiff/libtiff!14 + +2018-01-27 Even Rouault + + Merge branch 'patch-2' into 'master' + Update tiffgt.c for build fix on Windows + + See merge request libtiff/libtiff!13 + +2018-01-25 Olivier Paquet + + Merge branch 'bug2750' into 'master' + Add workaround to pal2rgb buffer overflow. + + See merge request libtiff/libtiff!15 + +2018-01-25 Nathan Baker + + Add workaround to pal2rgb buffer overflow. + +2018-01-23 Andrea + + Update tiffgt.c for build fix on Windows. + + Update CMakeLists.txt for build fix on Windows. + +2018-01-15 Even Rouault + + Merge branch 'has-attribute-check' into 'master' + tiffiop: use __has_attribute to detect the no_sanitize attribute + + See merge request libtiff/libtiff!10 + +2018-01-15 Ben Boeckel + + cmake: avoid setting hard-coded variables in the cache. + + cmake: avoid an unnecessary intermediate variable. + + cmake: avoid an unnecessary intermediate variable. + + cmake: avoid tautological logic. + + cmake: use check_symbol_exists. + This accounts for symbols being provided by macros. + + cmake: remove unused configure checks. + +2018-01-12 Kevin Funk + + Prefer target_include_directories. + When libtiff is included in a super project via a simple + `add_subdirectory(libtiff)`, this way the `tiff` library target has all + the necessary information to build against it. + + Note: The BUILD_INTERFACE generator expression feature requires at least + CMake v2.8.11 if I'm correct. + +2018-01-09 Ben Boeckel + + tiffiop: use __has_attribute to detect the no_sanitize attribute. + +2017-12-31 Even Rouault + + man/TIFFquery.3tiff: remove reference to non-existing TIFFReadStrip() function in TIFFIsByteSwapped() documentation. Patch by Eric Piel. Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2763 + + libtiff/tif_dir.c: _TIFFVGetField(): fix heap out-of-bounds access when requesting TIFFTAG_NUMBEROFINKS on a EXIF directory. Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2765. Reported by Google Autofuzz project + + libtiff/tif_print.c: TIFFPrintDirectory(): fix null pointer dereference on corrupted file. Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2770 + +2017-12-21 Even Rouault + + Add libzstd to gitlab-ci. + +2017-12-21 Even Rouault + + Add ZSTD compression codec. + From https://github.com/facebook/zstd + "Zstandard, or zstd as short version, is a fast lossless compression + algorithm, targeting real-time compression scenarios at zlib-level + and better compression ratios. It's backed by a very fast entropy stage, + provided by Huff0 and FSE library." + + We require libzstd >= 1.0.0 so as to be able to use streaming compression + and decompression methods. + + The default compression level we have selected is 9 (range goes from 1 to 22), + which experimentally offers equivalent or better compression ratio than + the default deflate/ZIP level of 6, and much faster compression. + + For example on a 6600x4400 16bit image, tiffcp -c zip runs in 10.7 seconds, + while tiffcp -c zstd runs in 5.3 seconds. Decompression time for zip is + 840 ms, and for zstd 650 ms. File size is 42735936 for zip, and + 42586822 for zstd. Similar findings on other images. + + On a 25894x16701 16bit image, + + Compression time Decompression time File size + + ZSTD 35 s 3.2 s 399 700 498 + ZIP/Deflate 1m 20 s 4.9 s 419 622 336 + +2017-12-10 Even Rouault + + Merge branch 'fix_cve-2017-9935' into 'master' + Fix CVE-2017-9935 + + See merge request libtiff/libtiff!7 + +2017-12-10 Brian May + + tiff2pdf: Fix apparent incorrect type for transfer table. + The standard says the transfer table contains unsigned 16 bit values, + I have no idea why we refer to them as floats. + +2017-12-10 Brian May + + tiff2pdf: Fix CVE-2017-9935. + Fix for http://bugzilla.maptools.org/show_bug.cgi?id=2704 + + This vulnerability - at least for the supplied test case - is because we + assume that a tiff will only have one transfer function that is the same + for all pages. This is not required by the TIFF standards. + + We than read the transfer function for every page. Depending on the + transfer function, we allocate either 2 or 4 bytes to the XREF buffer. + We allocate this memory after we read in the transfer function for the + page. + + For the first exploit - POC1, this file has 3 pages. For the first page + we allocate 2 extra extra XREF entries. Then for the next page 2 more + entries. Then for the last page the transfer function changes and we + allocate 4 more entries. + + When we read the file into memory, we assume we have 4 bytes extra for + each and every page (as per the last transfer function we read). Which + is not correct, we only have 2 bytes extra for the first 2 pages. As a + result, we end up writing past the end of the buffer. + + There are also some related issues that this also fixes. For example, + TIFFGetField can return uninitalized pointer values, and the logic to + detect a N=3 vs N=1 transfer function seemed rather strange. + + It is also strange that we declare the transfer functions to be of type + float, when the standard says they are unsigned 16 bit values. This is + fixed in another patch. + + This patch will check to ensure that the N value for every transfer + function is the same for every page. If this changes, we abort with an + error. In theory, we should perhaps check that the transfer function + itself is identical for every page, however we don't do that due to the + confusion of the type of the data in the transfer function. + +2017-12-10 Even Rouault + + Merge branch 'undef-warn-fixes' into 'master' + Fix a couple of harmless but annoying -Wundef warnings + + See merge request libtiff/libtiff!8 + +2017-12-07 Vadim Zeitlin + + Remove tests for undefined SIZEOF_VOIDP. + As configure never uses AC_CHECK_SIZEOF(void*), this symbol is never + defined and so it doesn't make sense to test it in the code, this just + results in -Wundef warnings if they're enabled. + + Avoid harmless -Wundef warnings for __clang_major__ + Check that we're using Clang before checking its version. + +2017-12-02 Even Rouault + + Merge branch 'remove_autogenerated_files' into 'master' + Remove autogenerated files + + See merge request libtiff/libtiff!5 + +2017-12-02 Bob Friesenhahn + + Merge branch 'tif_config_h_includes' into 'master' + 'tif_config.h' or 'tiffiop.h' must be included before any system header. + + See merge request libtiff/libtiff!6 + +2017-12-02 Bob Friesenhahn + + 'tif_config.h' or 'tiffio.h' must be included before any system header. + +2017-12-01 Even Rouault + + .gitignore: add patterns for build from root. + + Remove remaining .cvsignore files. + + Remove autoconf/automake generated files, and add them to .gitignore. + +2017-12-01 Olivier Paquet + + Merge branch 'makedistcheck' into 'master' + build/gitlab-ci and build/travis-ci: add a 'make dist' step in autoconf_build()… + + See merge request libtiff/libtiff!4 + +2017-12-01 Even Rouault + + build/gitlab-ci and build/travis-ci: add a 'make dist' step in autoconf_build() target, to check we are release-ready + +2017-12-01 Even Rouault + + Merge branch 'git_updates' into 'master' + CVS to Git updates + + See merge request libtiff/libtiff!2 + +2017-12-01 Even Rouault + + HOWTO-RELEASE: update to use signed tags. + + README.md: use markdown syntax for hyperlinks. + +2017-11-30 Even Rouault + + Add .gitignore. + + Regenerate autoconf files. + + Makefile.am: update to reflect removal of README.vms and README -> README.md + + Remove all $Id and $Headers comments with CVS versions. + + HOWTO-RELEASE: update for git. + + Remove outdated .cvsignore. + + Remove outdated commit script. + + Remove README.vms. + + Rename README as README.md, and update content. + + html/index.html: reflect change from CVS to gitlab. + +2017-11-30 Olivier Paquet + + Merge branch 'test-ci' into 'master' + Update CI configuration + + See merge request libtiff/libtiff!1 + +2017-11-23 Roger Leigh + + appveyor: Correct path for git clone and skip artefact archival. + +2017-11-22 Roger Leigh + + travis-ci: Remove unused matrix exclusion. + + Add gitlab-ci build support. + +2017-11-18 Bob Friesenhahn + + * configure.ac: libtiff 4.0.9 released. + + * html/v4.0.9.html: Add HTML file to document changes in libtiff + v4.0.9. + +2017-11-17 Even Rouault + + * libtiff/tif_aux.c, tif_getimage.c, tif_read.c: typo fixes in + comments. + +2017-11-02 Bob Friesenhahn + + * test/Makefile.am: Add some tests for tiff2bw. + +2017-11-01 Bob Friesenhahn + + * tools/tiff2bw.c (main): Free memory allocated in the tiff2bw + program. This is in response to the report associated with + CVE-2017-16232 but does not solve the extremely high memory usage + with the associated POC file. + +2017-10-29 Bob Friesenhahn + + * tools/tiff2pdf.c (t2p_sample_realize_palette): Fix possible + arithmetic overflow in bounds checking code and eliminate + comparison between signed and unsigned type. + + * tools/fax2tiff.c (_FAX_Client_Data): Pass FAX_Client_Data as the + client data. This client data is not used at all at the moment, + but it makes the most sense. Issue that the value of + client_data.fd was passed where a pointer is expected was reported + via email by Gerald Schade on Sun, 29 Oct 2017. + +2017-10-23 Even Rouault + + * libtiff/tif_getimage.c: avoid floating point division by zero in + initCIELabConversion() + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3733 + Credit to OSS Fuzz + +2017-10-17 Even Rouault + + * libtiff/tif_jpeg.c: add compatibility with libjpeg-turbo 1.5.2 that + honours max_memory_to_use > 0. + Cf https://github.com/libjpeg-turbo/libjpeg-turbo/issues/162 + +2017-10-10 Even Rouault + + * nmake.opt: support a DEBUG=1 option, so as to adjust OPTFLAGS and use + /MDd runtime in debug mode. + +2017-10-01 Even Rouault + + * tools/tiffset.c: fix setting a single value for the ExtraSamples tag + (and other tags with variable number of values). + So 'tiffset -s ExtraSamples 1 X'. This only worked + when setting 2 or more values, but not just one. + +2017-09-29 Even Rouault + + * libtiff/libtiff.def: add TIFFReadRGBAStripExt and TIFFReadRGBATileExt + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2735 + +2017-09-09 Even Rouault + + * libtiff/tif_dirread.c: add NULL check to avoid likely false positive + null-pointer dereference warning by CLang Static Analyzer. + +2017-09-07 Even Rouault + + * libtiff/tiffiop.h, tif_aux.c: redirect SeekOK() macro to a _TIFFSeekoK() + function that checks if the offset is not bigger than INT64_MAX, so as + to avoid a -1 error return code of TIFFSeekFile() to match a required + seek to UINT64_MAX/-1. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2726 + Adapted from proposal by Nicolas Ruff. + +2017-08-29 Even Rouault + + * libtiff/tif_jpeg.c: accept reading the last strip of a JPEG compressed + file if the codestream height is larger than the truncated height of the + strip. Emit a warning in this situation since this is non compliant. + +2017-08-28 Even Rouault + + * test/Makefile.am: add missing reference to images/quad-lzw-compat.tiff + to fix "make distcheck". Patch by Roger Leigh + +2017-08-23 Even Rouault + + * libtiff/tif_dirwrite.c: replace assertion to tag value not fitting + on uint32 when selecting the value of SubIFD tag by runtime check + (in TIFFWriteDirectoryTagSubifd()). + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2728 + Reported by team OWL337 + +2017-08-23 Even Rouault + + * libtiff/tif_dirwrite.c: replace assertion related to not finding the + SubIFD tag by runtime check (in TIFFWriteDirectorySec()) + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2727 + Reported by team OWL337 + +2017-07-24 Even Rouault + + * libtiff/tif_luv.c: further reduce memory requirements for temporary + buffer when RowsPerStrip >= image_length in LogLuvInitState() and + LogL16InitState(). + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2700 + Credit to OSS Fuzz + +2017-07-24 Even Rouault + + * libtiff/tif_getimage.c: fix fromskew computation when to-be-skipped + pixel number is not a multiple of the horizontal subsampling, and + also in some other cases. Impact putcontig8bitYCbCr44tile, + putcontig8bitYCbCr42tile, putcontig8bitYCbCr41tile, + putcontig8bitYCbCr21tile and putcontig8bitYCbCr12tile + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2637 (discovered + by Agostino Sarubbo) + and https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2691 (credit + to OSS Fuzz) + +2017-07-24 Even Rouault + + * libtiff/tif_getimage.c: gtTileContig() and gtTileSeparate(): + properly break from loops on error when stoponerr is set, instead + of going on iterating on row based loop. + +2017-07-18 Even Rouault + + * libtiff/tif_luv.c: LogLuvInitState(): avoid excessive memory + allocation when RowsPerStrip tag is missing. + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2683 + Credit to OSS-Fuzz + +2017-07-15 Even Rouault + + * libtiff/tif_read.c: add protection against excessive memory + allocation attempts in TIFFReadDirEntryArray() on short files. + Effective for mmap'ed case. And non-mmap'ed case, but restricted + to 64bit builds. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2675 + +2017-07-15 Even Rouault + + * libtiff/tif_read.c: in TIFFFetchStripThing(), only grow the + arrays that hold StripOffsets/StripByteCounts, when they are smaller + than the expected number of striles, up to 1 million striles, and + error out beyond. Can be tweaked by setting the environment variable + LIBTIFF_STRILE_ARRAY_MAX_RESIZE_COUNT. + This partially goes against a change added on 2002-12-17 to accept + those arrays of wrong sizes, but is needed to avoid denial of services. + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2350 + Credit to OSS Fuzz + +2017-07-15 Even Rouault + + * libtiff/tif_read.c: TIFFFillStrip() / TIFFFillTile(). + Complementary fix for http://bugzilla.maptools.org/show_bug.cgi?id=2708 + in the isMapped() case, so as to avoid excessive memory allocation + when we need a temporary buffer but the file is truncated. + +2017-07-15 Even Rouault + + * tools/tiff2pdf.c: prevent heap buffer overflow write in "Raw" + mode on PlanarConfig=Contig input images. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2715 + Reported by team OWL337 + +2017-07-11 Even Rouault + + * libtiff/tif_dir.c: avoid potential null pointer dereference in + _TIFFVGetField() on corrupted TIFFTAG_NUMBEROFINKS tag instance. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2713 + +2017-07-11 Even Rouault + + * libtiff/tif_lzw.c: fix potential out-of-buffer read on 1-byte LZW + strips. Crashing issue only on memory mapped files, where the strip + offset is the last byte of the file, and the file size is a multiple + of one page size on the CPU architecture (typically 4096). Credit + to myself :-) + +2017-07-11 Even Rouault + + * test/tiffcp-lzw-compat.sh, test/images/quad-lzw-compat.tiff: new files + to test old-style LZW decompression + * test/common.sh, Makefile.am, CMakeList.txt: updated with above + +2017-07-11 Even Rouault + + * refresh autoconf/make stuff with what is on Ubuntu 16.04 (minor changes) + +2017-07-11 Even Rouault + + * libtiff/tif_lzw.c: fix 4.0.8 regression in the decoding of old-style LZW + compressed files. + +2017-07-10 Even Rouault + + * libtiff/tif_pixarlog.c: avoid excessive memory allocation on decoding + when RowsPerStrip tag is not defined (and thus td_rowsperstrip == UINT_MAX) + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2554 + Credit to OSS Fuzz + +2017-07-04 Even Rouault + + * libtiff/tif_read.c, tiffiop.h: add a _TIFFReadEncodedTileAndAllocBuffer() + and _TIFFReadTileAndAllocBuffer() variants of TIFFReadEncodedTile() and + TIFFReadTile() that allocates the decoded buffer only after a first + successful TIFFFillTile(). This avoids excessive memory allocation + on corrupted files. + * libtiff/tif_getimage.c: use _TIFFReadTileAndAllocBuffer(). + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2470 + Credit to OSS Fuzz. + +2017-07-04 Even Rouault + + * libtiff/tif_error.c, tif_warning.c: correctly use va_list when both + an old-style and new-style warning/error handlers are installed. + Patch by Paavo Helde (sent on the mailing list) + +2017-07-02 Even Rouault + + * libtiff/tif_read.c: TIFFStartTile(): set tif_rawcc to + tif_rawdataloaded when it is set. Similarly to TIFFStartStrip(). + This issue was revealed by the change of 2017-06-30 in TIFFFileTile(), + limiting the number of bytes read. But it could probably have been hit + too in CHUNKY_STRIP_READ_SUPPORT mode previously ? + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2454 + Credit to OSS Fuzz + +2017-06-30 Even Rouault + + * man: update documentation regarding SubIFD tag and + TIFFSetSubDirectory() data type. + Patch by Eric Piel + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2671 + +2017-06-30 Even Rouault + + * libtiff/tif_dirwrite.c: in TIFFWriteDirectoryTagCheckedXXXX() + functions associated with LONG8/SLONG8 data type, replace assertion that + the file is BigTIFF, by a non-fatal error. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2712 + Reported by team OWL337 + +2017-06-30 Even Rouault + + * libtiff/tif_read.c, tiffiop.h: add a _TIFFReadEncodedStripAndAllocBuffer() + function, variant of TIFFReadEncodedStrip() that allocates the + decoded buffer only after a first successful TIFFFillStrip(). This avoids + excessive memory allocation on corrupted files. + * libtiff/tif_getimage.c: use _TIFFReadEncodedStripAndAllocBuffer(). + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2708 and + https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2433 . + Credit to OSS Fuzz + +2017-06-30 Even Rouault + + * libtiff/tif_read.c: TIFFFillTile(): add limitation to the number + of bytes read in case td_stripbytecount[strip] is bigger than + reasonable, so as to avoid excessive memory allocation (similarly to + what was done for TIFFFileStrip() on 2017-05-10) + +2017-06-29 Even Rouault + + * libtiff/tiffiop.h, libtiff/tif_jpeg.c, libtiff/tif_jpeg_12.c, + libtiff/tif_read.c: make TIFFReadScanline() works in + CHUNKY_STRIP_READ_SUPPORT mode with JPEG stream with multiple scans. + Also make configurable through a LIBTIFF_JPEG_MAX_ALLOWED_SCAN_NUMBER + environment variable the maximum number of scans allowed. Defaults to + 100. + +2017-06-27 Even Rouault + + * libtiff/tif_dirread.c: in TIFFReadDirEntryFloat(), check that a + double value can fit in a float before casting. Patch by Nicolas RUFF + +2017-06-26 Even Rouault + + * libtiff/tif_jbig.c: fix memory leak in error code path of JBIGDecode() + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2706 + Reported by team OWL337 + +2017-06-24 Even Rouault + + * libtiff/tif_jpeg.c: error out at decoding time if anticipated libjpeg + memory allocation is above 100 MB. libjpeg in case of multiple scans, + which is allowed even in baseline JPEG, if components are spread over several + scans and not interleavedin a single one, needs to allocate memory (or + backing store) for the whole strip/tile. + See http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf + This limitation may be overriden by setting the + LIBTIFF_ALLOW_LARGE_LIBJPEG_MEM_ALLOC environment variable, or recompiling + libtiff with a custom value of TIFF_LIBJPEG_LARGEST_MEM_ALLOC macro. + +2017-06-24 Even Rouault + + * libtiff/tif_jpeg.c: add anti-denial of service measure to avoid excessive + CPU consumption on progressive JPEGs with a huge number of scans. + See http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf + Note: only affects libtiff since 2014-12-29 where support of non-baseline JPEG + was added. + +2017-06-18 Even Rouault + + * libtiff/tiffiop.h: add TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW macro to + disable CLang warnings raised by -fsanitize=undefined,unsigned-integer-overflow + * libtiff/tif_predict.c: decorate legitimate functions where unsigned int + overflow occur with TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW + * libtiff/tif_dirread.c: avoid unsigned int overflow in EstimateStripByteCounts() + and BYTECOUNTLOOKSBAD when file is too short. + * libtiff/tif_jpeg.c: avoid (harmless) unsigned int overflow on tiled images. + * libtiff/tif_fax3.c: avoid unsigned int overflow in Fax3Encode2DRow(). Could + potentially be a bug with huge rows. + * libtiff/tif_getimage.c: avoid many (harmless) unsigned int overflows. + +2017-06-12 Even Rouault + + * libtiff/tif_dirread.c: TIFFFetchStripThing(): limit the number of items + read in StripOffsets/StripByteCounts tags to the number of strips to avoid + excessive memory allocation. + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2215 + Credit to OSS Fuzz + +2017-06-12 Even Rouault + + * libtiff/tif_dirread.c: fix regression of libtiff 4.0.8 in + ChopUpSingleUncompressedStrip() regarding update of newly single-strip + uncompressed files whose bytecount is 0. Before the change of 2016-12-03, + the condition bytecount==0 used to trigger an early exit/disabling of + strip chop. Re-introduce that in update mode. Otherwise this cause + later incorrect setting for the value of StripByCounts/StripOffsets. + ( https://trac.osgeo.org/gdal/ticket/6924 ) + +2017-06-10 Even Rouault + + * .appveyor.yml, .travis.yml, build/travis-ci: apply patches + 0001-ci-Travis-script-improvements.patch and + 0002-ci-Invoke-helper-script-via-shell.patch by Roger Leigh + (sent to mailing list) + +2017-06-08 Even Rouault + + * .travis.yml, build/travis-ci: new files from + 0001-ci-Add-Travis-support-for-Linux-builds-with-Autoconf.patch by + Roger Leigh (sent to mailing list on 2017-06-08) + This patch adds support for the Travis-CI service. + + * .appveyor.yml: new file from + 0002-ci-Add-AppVeyor-support.patch by Roger Leigh (sent to mailing + list on 2017-06-08) + This patch adds a .appveyor.yml file to the top-level. This allows + one to opt in to having a branch built on Windows with Cygwin, + MinGW and MSVC automatically when a branch is pushed to GitHub, + GitLab, BitBucket or any other supported git hosting service. + + * CMakeLists.txt, test/CMakeLists.txt, test/TiffTestCommon.cmake: apply + patch 0001-cmake-Improve-Cygwin-and-MingGW-test-support.patch from Roger + Leigh (sent to mailing list on 2017-06-08) + This patch makes the CMake build system support running the tests + with MinGW or Cygwin. + +2017-06-08 Even Rouault + + * libtiff/tif_swab.c: if DISABLE_CHECK_TIFFSWABMACROS is defined, do not do + the #ifdef TIFFSwabXXX checks. Make it easier for GDAL to rename the symbols + of its internal libtiff copy. + +2017-06-01 Even Rouault + + * libtiff/tif_dirinfo.c, tif_dirread.c: add _TIFFCheckFieldIsValidForCodec(), + and use it in TIFFReadDirectory() so as to ignore fields whose tag is a + codec-specified tag but this codec is not enabled. This avoids TIFFGetField() + to behave differently depending on whether the codec is enabled or not, and + thus can avoid stack based buffer overflows in a number of TIFF utilities + such as tiffsplit, tiffcmp, thumbnail, etc. + Patch derived from 0063-Handle-properly-CODEC-specific-tags.patch + (http://bugzilla.maptools.org/show_bug.cgi?id=2580) by Raphaël Hertzog. + Fixes: + http://bugzilla.maptools.org/show_bug.cgi?id=2580 + http://bugzilla.maptools.org/show_bug.cgi?id=2693 + http://bugzilla.maptools.org/show_bug.cgi?id=2625 (CVE-2016-10095) + http://bugzilla.maptools.org/show_bug.cgi?id=2564 (CVE-2015-7554) + http://bugzilla.maptools.org/show_bug.cgi?id=2561 (CVE-2016-5318) + http://bugzilla.maptools.org/show_bug.cgi?id=2499 (CVE-2014-8128) + http://bugzilla.maptools.org/show_bug.cgi?id=2441 + http://bugzilla.maptools.org/show_bug.cgi?id=2433 + +2017-05-29 Even Rouault + + * libtiff/tif_getimage.c: initYCbCrConversion(): stricter validation for + refBlackWhite coefficients values. To avoid invalid float->int32 conversion + (when refBlackWhite[0] == 2147483648.f) + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1907 + Credit to OSS Fuzz + +2017-05-29 Even Rouault + + * libtiff/tif_color.c: TIFFYCbCrToRGBInit(): stricter clamping to avoid + int32 overflow in TIFFYCbCrtoRGB(). + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1844 + Credit to OSS Fuzz + +2017-05-21 Bob Friesenhahn + + * configure.ac: libtiff 4.0.8 released. + + * html/v4.0.8.html: Add description of changes targeting the 4.0.8 + release. + +2017-05-20 Even Rouault + + * libtiff/tif_getimage.c: initYCbCrConversion(): stricter validation for + refBlackWhite coefficients values. To avoid invalid float->int32 conversion. + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1718 + Credit to OSS Fuzz + +2017-05-18 Even Rouault + + * libtiff/tif_getimage.c: initYCbCrConversion(): check luma[1] is not zero + to avoid division by zero. + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1665 + Credit to OSS Fuzz + +2017-05-17 Even Rouault + + * libtiff/tif_read.c: _TIFFVSetField(): fix outside range cast of double to + float. + Credit to Google Autofuzz project + +2017-05-17 Even Rouault + + * libtiff/tif_getimage.c: initYCbCrConversion(): add basic validation of + luma and refBlackWhite coefficients (just check they are not NaN for now), + to avoid potential float to int overflows. + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1663 + Credit to OSS Fuzz + +2017-05-17 Even Rouault + + * libtiff/tif_pixarlog.c: PixarLogDecode(): resync tif_rawcp with + next_in and tif_rawcc with avail_in at beginning and end of function, + similarly to what is done in LZWDecode(). Likely needed so that it + works properly with latest chnges in tif_read.c in CHUNKY_STRIP_READ_SUPPORT + mode. But untested... + +2017-05-17 Even Rouault + + * libtiff/tif_lzw.c: update dec_bitsleft at beginning of LZWDecode(), + and update tif_rawcc at end of LZWDecode(). This is needed to properly + work with the latest chnges in tif_read.c in CHUNKY_STRIP_READ_SUPPORT + mode. + +2017-05-14 Even Rouault + + * libtiff/tif_luv.c: LogL16InitState(): avoid excessive memory + allocation when RowsPerStrip tag is missing. + Credit to OSS-Fuzz (locally run, on GDAL) + +2017-05-14 Even Rouault + + * libtiff/tif_packbits.c: fix out-of-buffer read in PackBitsDecode() + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1563 + Credit to OSS-Fuzz + +2017-05-13 Even Rouault + + * libtiff/tif_pixarlog.c, tif_luv.c: avoid potential int32 + overflows in multiply_ms() and add_ms(). + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1558 + Credit to OSS-Fuzz + +2017-05-13 Even Rouault + + * libtiff/tif_color.c: avoid potential int32 overflow in + TIFFYCbCrToRGBInit() + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1533 + Credit to OSS-Fuzz + +2017-05-13 Even Rouault + + * libtiff/tif_read.c: update tif_rawcc in CHUNKY_STRIP_READ_SUPPORT + mode with tif_rawdataloaded when calling TIFFStartStrip() or + TIFFFillStripPartial(). This avoids reading beyond tif_rawdata + when bytecount > tif_rawdatasize. + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1545. + Credit to OSS-Fuzz + +2017-05-12 Even Rouault + + * libtiff/tif_read.c: TIFFFillStripPartial(): + avoid excessive memory allocation in case of shorten files. + Only effective on 64 bit builds. + Credit to OSS-Fuzz (locally run, on GDAL) + +2017-05-12 Even Rouault + + * libtiff/tif_read.c: TIFFFillStripPartial() / TIFFSeek(), + avoid potential integer overflows with read_ahead in + CHUNKY_STRIP_READ_SUPPORT mode. Should + especially occur on 32 bit platforms. + +2017-05-10 Even Rouault + + * libtiff/tif_read.c: TIFFFillStrip() and TIFFFillTile(): + avoid excessive memory allocation in case of shorten files. + Only effective on 64 bit builds and non-mapped cases. + Credit to OSS-Fuzz (locally run, on GDAL) + +2017-05-10 Even Rouault + + * libtiff/tif_zip.c, tif_pixarlog.c, tif_predict.c: fix memory + leak when the underlying codec (ZIP, PixarLog) succeeds its + setupdecode() method, but PredictorSetup fails. + Credit to OSS-Fuzz (locally run, on GDAL) + +2017-05-10 Even Rouault + + * libtiff/tif_read.c: TIFFFillStrip(): add limitation to the number + of bytes read in case td_stripbytecount[strip] is bigger than + reasonable, so as to avoid excessive memory allocation. + +2017-04-28 Even Rouault + + * tools/tiff2bw.c: close TIFF handle in error code path. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2677 + +2017-04-27 Even Rouault + + * litiff/tif_fax3.c: avoid crash in Fax3Close() on empty file. + Patch by Alan Coopersmith + complement by myself. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2673 + * tools/fax2tiff.c: emit appropriate message if the input file is + empty. Patch by Alan Coopersmith. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2672 + +2017-04-27 Even Rouault + + * libtiff/tif_ojpeg.c: fix potential memory leak in + OJPEGReadHeaderInfoSecTablesQTable, OJPEGReadHeaderInfoSecTablesDcTable + and OJPEGReadHeaderInfoSecTablesAcTable + Patch by Nicolás Peña. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2670 + +2017-04-27 Even Rouault + + * libtiff/tif_dirread.c: fix memory leak in non DEFER_STRILE_LOAD + mode (ie default) when there is both a StripOffsets and + TileOffsets tag, or a StripByteCounts and TileByteCounts + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2689 + * tools/tiff2ps.c: call TIFFClose() in error code paths. + +2017-02-25 Even Rouault + + * libtiff/tif_fax3.c, tif_predict.c, tif_getimage.c: fix GCC 7 + -Wimplicit-fallthrough warnings. + +2017-02-18 Even Rouault + + * libtiff/tif_pixarlog.c: fix memory leak in error code path of + PixarLogSetupDecode(). Patch by Nicolás Peña. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2665 + +2017-02-18 Even Rouault + + * libtiff/tif_lzw.c: in LZWPostEncode(), increase, if necessary, the + code bit-width after flushing the remaining code and before emitting + the EOI code. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=1982 + +2017-01-31 Even Rouault + + * libtiff/tif_jpeg.c: only run JPEGFixupTagsSubsampling() if the + YCbCrSubsampling tag is not explicitly present. This helps a bit to reduce + the I/O amount when te tag is present (especially on cloud hosted files). + +2017-01-14 Even Rouault + + * tools/raw2tiff.c: avoid integer division by zero. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2631 + +2017-01-12 Even Rouault + + * libtiff/tif_ojpeg.c: fix leak in OJPEGReadHeaderInfoSecTablesQTable, + OJPEGReadHeaderInfoSecTablesDcTable and OJPEGReadHeaderInfoSecTablesAcTable + when read fails. + Patch by Nicolás Peña. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2659 + +2017-01-11 Even Rouault + + * libtiff/tif_luv.c, tif_lzw.c, tif_packbits.c: return 0 in Encode + functions instead of -1 when TIFFFlushData1() fails. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2130 + +2017-01-11 Even Rouault + + * tools/tiffcp.c: error out cleanly in cpContig2SeparateByRow and + cpSeparate2ContigByRow if BitsPerSample != 8 to avoid heap based overflow. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2656 and + http://bugzilla.maptools.org/show_bug.cgi?id=2657 + +2017-01-11 Even Rouault + + * libtiff/tiffio.h, tif_unix.c, tif_win32.c, tif_vms.c: add _TIFFcalloc() + + * libtiff/tif_read.c: TIFFReadBufferSetup(): use _TIFFcalloc() to zero + initialize tif_rawdata. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2651 + +2017-01-11 Even Rouault + + * libtiff/tif_getimage.c: add explicit uint32 cast in putagreytile to + avoid UndefinedBehaviorSanitizer warning. + Patch by Nicolás Peña. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2658 + +2017-01-11 Even Rouault + + * libtiff/tif_read.c: avoid potential undefined behaviour on signed integer + addition in TIFFReadRawStrip1() in isMapped() case. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2650 + +2017-01-11 Even Rouault + + * libtiff/tif_jpeg.c: validate BitsPerSample in JPEGSetupEncode() to avoid + undefined behaviour caused by invalid shift exponent. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2648 + +2017-01-11 Even Rouault + + * libtiff/tif_dir.c, tif_dirread.c, tif_dirwrite.c: implement various clampings + of double to other data types to avoid undefined behaviour if the output range + isn't big enough to hold the input value. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2643 + http://bugzilla.maptools.org/show_bug.cgi?id=2642 + http://bugzilla.maptools.org/show_bug.cgi?id=2646 + http://bugzilla.maptools.org/show_bug.cgi?id=2647 + +2017-01-11 Even Rouault + + * libtiff/tif_dirread.c: avoid division by floating point 0 in + TIFFReadDirEntryCheckedRational() and TIFFReadDirEntryCheckedSrational(), + and return 0 in that case (instead of infinity as before presumably) + Apparently some sanitizers do not like those divisions by zero. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2644 + +2017-01-11 Even Rouault + + * libtiff/tif_dirwrite.c: in TIFFWriteDirectoryTagCheckedRational, replace + assertion by runtime check to error out if passed value is strictly + negative. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2535 + + * tools/tiffcrop.c: remove extraneous TIFFClose() in error code path, that + caused double free. + Related to http://bugzilla.maptools.org/show_bug.cgi?id=2535 + +2017-01-11 Even Rouault + + * libtiff/tif_jpeg.c: avoid integer division by zero in + JPEGSetupEncode() when horizontal or vertical sampling is set to 0. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2653 + +2017-01-03 Even Rouault + + * libtiff/tif_jpeg.c: increase libjpeg max memory usable to + 10 MB instead of libjpeg 1MB default. This helps when creating files + with "big" tile, without using libjpeg temporary files. + Related to https://trac.osgeo.org/gdal/ticket/6757 + +2016-12-20 Even Rouault + + * tools/tiff2pdf.c: avoid potential heap-based overflow in + t2p_readwrite_pdf_image_tile(). + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2640 + +2016-12-20 Even Rouault + + * tools/tiff2pdf.c: avoid potential invalid memory read in + t2p_writeproc. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2639 + +2016-12-20 Even Rouault + + * tools/tiff2pdf.c: fix wrong usage of memcpy() that can trigger + unspecified behaviour. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2638 + +2016-12-18 Even Rouault + + * libtiff/tif_getimage.c: fix potential memory leaks in error code + path of TIFFRGBAImageBegin(). + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2627 + +2016-12-18 Even Rouault + + * tools/tiff2pdf.c: prevent heap-based buffer overflow in -j mode + on a paletted image. Note: this fix errors out before the overflow + happens. There could probably be a better fix. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2635 + +2016-12-17 Even Rouault + + * libtiff/tiffio.h, libtiff/tif_getimage.c: add TIFFReadRGBAStripExt() + and TIFFReadRGBATileExt() variants of the functions without ext, with + an extra argument to control the stop_on_error behaviour. + +2016-12-17 Even Rouault + + * tools/tiff2ps.c: fix 2 heap-based buffer overflows (in PSDataBW + and PSDataColorContig). Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2633 and + http://bugzilla.maptools.org/show_bug.cgi?id=2634. + +2016-12-13 Even Rouault + + * libtiff/tif_fax3.h: revert change done on 2016-01-09 that made + Param member of TIFFFaxTabEnt structure a uint16 to reduce size of + the binary. It happens that the Hylafax software uses the tables that + follow this typedef (TIFFFaxMainTable, TIFFFaxWhiteTable, + TIFFFaxBlackTable), although they are not in a public libtiff header. + Raised by Lee Howard. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2636 + +2016-12-04 Even Rouault + + * html/man/Makefile.am: remove thumbnail.1.html and rgb2ycbcr.1.html + from installed pages since the corresponding utilities are no longer + installed. Reported by Havard Eidnes + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2606 + +2016-12-03 Even Rouault + + * libtiff/tif_write.c: fix misleading indentation as warned by GCC. + +2016-12-03 Even Rouault + + * tools/tiffcp.c: replace assert( (bps % 8) == 0 ) by a non assert check. + Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2605 + +2016-12-03 Even Rouault + + * tools/tiffcp.c: fix uint32 underflow/overflow that can cause heap-based + buffer overflow. + Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2610 + +2016-12-03 Even Rouault + + * tools/tiffcp.c: avoid potential division by zero is BitsPerSamples tag is + missing. + Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2607 + +2016-12-03 Even Rouault + + * man/Makefile.am: remove thumbnail.1 and rgb2ycbcr.1 from installed man + pages since the corresponding utilities are no longer installed. + Reported by Havard Eidnes + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2606 + +2016-12-03 Even Rouault + + * tools/tif_dir.c: when TIFFGetField(, TIFFTAG_NUMBEROFINKS, ) is called, + limit the return number of inks to SamplesPerPixel, so that code that parses + ink names doesn't go past the end of the buffer. + Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2599 + +2016-12-03 Even Rouault + + * tools/tiffcp.c: avoid potential division by zero is BitsPerSamples tag is + missing. + Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2597 + +2016-12-03 Even Rouault + + * tools/tiffinfo.c: fix null pointer dereference in -r mode when the image has + no StripByteCount tag. + Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2594 + +2016-12-03 Even Rouault + + * tools/tiffcrop.c: fix integer division by zero when BitsPerSample is missing. + Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2619 + +2016-12-03 Even Rouault + + * tools/tiffcrop.c: add 3 extra bytes at end of strip buffer in + readSeparateStripsIntoBuffer() to avoid read outside of heap allocated buffer. + Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2621 + +2016-12-03 Even Rouault + + * tools/tiffcrop.c: fix readContigStripsIntoBuffer() in -i (ignore) mode so + that the output buffer is correctly incremented to avoid write outside bounds. + Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2620 + +2016-12-03 Even Rouault + + * libtiff/tif_ojpeg.c: make OJPEGDecode() early exit in case of failure in + OJPEGPreDecode(). This will avoid a divide by zero, and potential other issues. + Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2611 + +2016-12-03 Even Rouault + + * libtiff/tif_dirread.c: modify ChopUpSingleUncompressedStrip() to + instanciate compute ntrips as TIFFhowmany_32(td->td_imagelength, rowsperstrip), + instead of a logic based on the total size of data. Which is faulty is + the total size of data is not sufficient to fill the whole image, and thus + results in reading outside of the StripByCounts/StripOffsets arrays when + using TIFFReadScanline(). + Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2608. + + * libtiff/tif_strip.c: revert the change in TIFFNumberOfStrips() done + for http://bugzilla.maptools.org/show_bug.cgi?id=2587 / CVE-2016-9273 since + the above change is a better fix that makes it unnecessary. + +2016-12-03 Even Rouault + + * libtiff/tif_pixarlog.c, libtiff/tif_luv.c: fix heap-based buffer + overflow on generation of PixarLog / LUV compressed files, with + ColorMap, TransferFunction attached and nasty plays with bitspersample. + The fix for LUV has not been tested, but suffers from the same kind + of issue of PixarLog. + Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2604 + +2016-12-02 Even Rouault + + * tools/tiffcp.c: avoid uint32 underflow in cpDecodedStrips that + can cause various issues, such as buffer overflows in the library. + Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2598 + +2016-12-02 Even Rouault + + * libtiff/tif_read.c, libtiff/tiffiop.h: fix uint32 overflow in + TIFFReadEncodedStrip() that caused an integer division by zero. + Reported by Agostino Sarubbo. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2596 + +2016-11-20 Even Rouault + + * libtiff/tif_getimage.c, libtiff/tif_open.c: add parenthesis to + fix cppcheck clarifyCalculation warnings + * libtiff/tif_predict.c, libtiff/tif_print.c: fix printf unsigned + vs signed formatting (cppcheck invalidPrintfArgType_uint warnings) + +2016-11-20 Bob Friesenhahn + + * tools/fax2tiff.c (main): Applied patch by Jörg Ahrens to fix + passing client data for Win32 builds using tif_win32.c + (USE_WIN32_FILEIO defined) for file I/O. Patch was provided via + email on November 20, 2016. + +2016-11-19 Bob Friesenhahn + + * libtiff 4.0.7 released. + + * configure.ac: Update for 4.0.7 release. + + * tools/tiffdump.c (ReadDirectory): Remove uint32 cast to + _TIFFmalloc() argument which resulted in Coverity report. Added + more mutiplication overflow checks. + +2016-11-18 Even Rouault + + * tools/tiffcrop.c: Fix memory leak in (recent) error code path. + Fixes Coverity 1394415. + +2016-11-17 Bob Friesenhahn + + * libtiff/tif_getimage.c: Fix some benign warnings which appear in + 64-bit compilation under Microsoft Visual Studio of the form + "Arithmetic overflow: 32-bit value is shifted, then cast to 64-bit + value. Results might not be an expected value.". Problem was + reported on November 16, 2016 on the tiff mailing list. + +2016-11-16 Even Rouault + + * libtiff/tif_dirread.c: in TIFFFetchNormalTag(), do not dereference + NULL pointer when values of tags with TIFF_SETGET_C16_ASCII / TIFF_SETGET_C32_ASCII + access are 0-byte arrays. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2593 (regression introduced + by previous fix done on 2016-11-11 for CVE-2016-9297). + Reported by Henri Salo. Assigned as CVE-2016-9448 + +2016-11-12 Bob Friesenhahn + + * tools/tiffinfo.c (TIFFReadContigTileData): Fix signed/unsigned + comparison warning. + (TIFFReadSeparateTileData): Fix signed/unsigned comparison + warning. + + * tools/tiffcrop.c (readContigTilesIntoBuffer): Fix + signed/unsigned comparison warning. + + * html/v4.0.7.html: Add a file to document the pending 4.0.7 + release. + +2016-11-11 Even Rouault + + * tools/tiff2pdf.c: avoid undefined behaviour related to overlapping + of source and destination buffer in memcpy() call in + t2p_sample_rgbaa_to_rgb() + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2577 + +2016-11-11 Even Rouault + + * tools/tiff2pdf.c: fix potential integer overflows on 32 bit builds + in t2p_read_tiff_size() + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2576 + +2016-11-11 Even Rouault + + * libtiff/tif_aux.c: fix crash in TIFFVGetFieldDefaulted() + when requesting Predictor tag and that the zip/lzw codec is not + configured. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2591 + +2016-11-11 Even Rouault + + * libtiff/tif_dirread.c: in TIFFFetchNormalTag(), make sure that + values of tags with TIFF_SETGET_C16_ASCII / TIFF_SETGET_C32_ASCII + access are null terminated, to avoid potential read outside buffer + in _TIFFPrintField(). + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2590 (CVE-2016-9297) + +2016-11-11 Even Rouault + + * libtiff/tif_dirread.c: reject images with OJPEG compression that + have no TileOffsets/StripOffsets tag, when OJPEG compression is + disabled. Prevent null pointer dereference in TIFFReadRawStrip1() + and other functions that expect td_stripbytecount to be non NULL. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2585 + +2016-11-11 Even Rouault + + * tools/tiffcrop.c: fix multiple uint32 overflows in + writeBufferToSeparateStrips(), writeBufferToContigTiles() and + writeBufferToSeparateTiles() that could cause heap buffer overflows. + Reported by Henri Salo from Nixu Corporation. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2592 (CVE-2016-9532) + +2016-11-10 Even Rouault + + * libtiff/tif_strip.c: make TIFFNumberOfStrips() return the td->td_nstrips + value when it is non-zero, instead of recomputing it. This is needed in + TIFF_STRIPCHOP mode where td_nstrips is modified. Fixes a read outsize of + array in tiffsplit (or other utilities using TIFFNumberOfStrips()). + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2587 (CVE-2016-9273) + +2016-11-04 Even Rouault + + * libtiff/tif_predic.c: fix memory leaks in error code paths added in + previous commit (fix for MSVR 35105) + +2016-10-31 Even Rouault + + * libtiff/tif_predict.h, libtiff/tif_predict.c: + Replace assertions by runtime checks to avoid assertions in debug mode, + or buffer overflows in release mode. Can happen when dealing with + unusual tile size like YCbCr with subsampling. Reported as MSVR 35105 + by Axel Souchet & Vishal Chauhan from the MSRC Vulnerabilities & Mitigations + team. + +2016-10-26 Even Rouault + + * tools/fax2tiff.c: fix segfault when specifying -r without + argument. Patch by Yuriy M. Kaminskiy. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2572 + +2016-10-25 Even Rouault + + * libtiff/tif_dir.c: discard values of SMinSampleValue and + SMaxSampleValue when they have been read and the value of + SamplesPerPixel is changed afterwards (like when reading a + OJPEG compressed image with a missing SamplesPerPixel tag, + and whose photometric is RGB or YCbCr, forcing SamplesPerPixel + being 3). Otherwise when rewriting the directory (for example + with tiffset, we will expect 3 values whereas the array had been + allocated with just one), thus causing a out of bound read access. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2500 + (CVE-2014-8127, duplicate: CVE-2016-3658) + + * libtiff/tif_dirwrite.c: avoid null pointer dereference on td_stripoffset + when writing directory, if FIELD_STRIPOFFSETS was artificially set + for a hack case in OJPEG case. + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2500 + (CVE-2014-8127, duplicate: CVE-2016-3658) + +2016-10-25 Even Rouault + + * tools/tiffinfo.c: fix out-of-bound read on some tiled images. + (http://bugzilla.maptools.org/show_bug.cgi?id=2517) + + * libtiff/tif_compress.c: make TIFFNoDecode() return 0 to indicate an + error and make upper level read routines treat it accordingly. + (linked to the test case of http://bugzilla.maptools.org/show_bug.cgi?id=2517) + +2016-10-14 Even Rouault + + * tools/tiffcrop.c: fix out-of-bound read of up to 3 bytes in + readContigTilesIntoBuffer(). Reported as MSVR 35092 by Axel Souchet + & Vishal Chauhan from the MSRC Vulnerabilities & Mitigations team. + +2016-10-09 Even Rouault + + * tools/tiff2pdf.c: fix write buffer overflow of 2 bytes on JPEG + compressed images. Reported by Tyler Bohan of Cisco Talos as + TALOS-CAN-0187 / CVE-2016-5652. + Also prevents writing 2 extra uninitialized bytes to the file stream. + +2016-10-08 Even Rouault + + * tools/tiffcp.c: fix out-of-bounds write on tiled images with odd + tile width vs image width. Reported as MSVR 35103 + by Axel Souchet and Vishal Chauhan from the MSRC Vulnerabilities & + Mitigations team. + +2016-10-08 Even Rouault + + * tools/tiff2pdf.c: fix read -largely- outsize of buffer in + t2p_readwrite_pdf_image_tile(), causing crash, when reading a + JPEG compressed image with TIFFTAG_JPEGTABLES length being one. + Reported as MSVR 35101 by Axel Souchet and Vishal Chauhan from + the MSRC Vulnerabilities & Mitigations team. CVE-2016-9453 + +2016-10-08 Even Rouault + + * tools/tiffcp.c: fix read of undefined variable in case of missing + required tags. Found on test case of MSVR 35100. + * tools/tiffcrop.c: fix read of undefined buffer in + readContigStripsIntoBuffer() due to uint16 overflow. Probably not a + security issue but I can be wrong. Reported as MSVR 35100 by Axel + Souchet from the MSRC Vulnerabilities & Mitigations team. + +2016-09-25 Bob Friesenhahn + + * html: Change as many remotesensing.org broken links to a working + URL as possible. + +2016-09-24 Bob Friesenhahn + + * libtiff/tif_getimage.c (TIFFRGBAImageOK): Reject attempts to + read floating point images. + + * libtiff/tif_predict.c (PredictorSetup): Enforce bits-per-sample + requirements of floating point predictor (3). Fixes CVE-2016-3622 + "Divide By Zero in the tiff2rgba tool." + +2016-09-23 Even Rouault + + * tools/tiffcrop.c: fix various out-of-bounds write vulnerabilities + in heap or stack allocated buffers. Reported as MSVR 35093, + MSVR 35096 and MSVR 35097. Discovered by Axel Souchet and Vishal + Chauhan from the MSRC Vulnerabilities & Mitigations team. + * tools/tiff2pdf.c: fix out-of-bounds write vulnerabilities in + heap allocate buffer in t2p_process_jpeg_strip(). Reported as MSVR + 35098. Discovered by Axel Souchet and Vishal Chauhan from the MSRC + Vulnerabilities & Mitigations team. + * libtiff/tif_pixarlog.c: fix out-of-bounds write vulnerabilities + in heap allocated buffers. Reported as MSVR 35094. Discovered by + Axel Souchet and Vishal Chauhan from the MSRC Vulnerabilities & + Mitigations team. + * libtiff/tif_write.c: fix issue in error code path of TIFFFlushData1() + that didn't reset the tif_rawcc and tif_rawcp members. I'm not + completely sure if that could happen in practice outside of the odd + behaviour of t2p_seekproc() of tiff2pdf). The report points that a + better fix could be to check the return value of TIFFFlushData1() in + places where it isn't done currently, but it seems this patch is enough. + Reported as MSVR 35095. Discovered by Axel Souchet & Vishal Chauhan & + Suha Can from the MSRC Vulnerabilities & Mitigations team. + +2016-09-20 Bob Friesenhahn + + * html/man/index.html: Comment out links to documentation for + abandoned utilities. + +2016-09-17 Even Rouault + + * libtiff/tif_lzma.c: typo fix in comment + +2016-09-04 Even Rouault + + * libtiff/*.c: fix warnings raised by clang 3.9 -Wcomma + +2016-09-03 Even Rouault + + * libtiff/tif_dirwrite.c, libtiff/tif_color.c: fix warnings raised + by GCC 5 / clang -Wfloat-conversion + +2016-08-16 Even Rouault + + * tools/tiffcrop.c: fix C99'ism. + +2016-08-15 Even Rouault + + * tools/tiff2bw.c: fix weight computation that could result of color + value overflow (no security implication). Fix bugzilla #2550. + Patch by Frank Freudenberg. + +2016-08-15 Even Rouault + + * tools/rgb2ycbcr.c: validate values of -v and -h parameters to + avoid potential divide by zero. Fixes CVE-2016-3623 (bugzilla #2569) + +2016-08-15 Even Rouault + + * tools/tiffcrop.c: Fix out-of-bounds write in loadImage(). + From patch libtiff-CVE-2016-3991.patch from + libtiff-4.0.3-25.el7_2.src.rpm by Nikola Forro (bugzilla #2543) + +2016-08-15 Even Rouault + + * libtiff/tif_pixarlog.c: Fix write buffer overflow in PixarLogEncode + if more input samples are provided than expected by PixarLogSetupEncode. + Idea based on libtiff-CVE-2016-3990.patch from + libtiff-4.0.3-25.el7_2.src.rpm by Nikola Forro, but with different and + simpler check. (bugzilla #2544) + +2016-08-15 Even Rouault + + * tools/tiff2rgba.c: Fix integer overflow in size of allocated + buffer, when -b mode is enabled, that could result in out-of-bounds + write. Based initially on patch tiff-CVE-2016-3945.patch from + libtiff-4.0.3-25.el7_2.src.rpm by Nikola Forro, with correction for + invalid tests that rejected valid files. (bugzilla #2545) + +2016-07-11 Even Rouault + + * tools/tiffcrop.c: Avoid access outside of stack allocated array + on a tiled separate TIFF with more than 8 samples per pixel. + Reported by Kaixiang Zhang of the Cloud Security Team, Qihoo 360 + (CVE-2016-5321 / CVE-2016-5323 , bugzilla #2558 / #2559) + +2016-07-10 Even Rouault + + * libtiff/tif_read.c: Fix out-of-bounds read on + memory-mapped files in TIFFReadRawStrip1() and TIFFReadRawTile1() + when stripoffset is beyond tmsize_t max value (reported by + Mathias Svensson) + +2016-07-10 Even Rouault + + * tools/tiffdump.c: fix a few misaligned 64-bit reads warned + by -fsanitize + +2016-07-03 Even Rouault + + * libtiff/tif_read.c: make TIFFReadEncodedStrip() and + TIFFReadEncodedTile() directly use user provided buffer when + no compression (and other conditions) to save a memcpy(). + + * libtiff/tif_write.c: make TIFFWriteEncodedStrip() and + TIFFWriteEncodedTile() directly use user provided buffer when + no compression to save a memcpy(). + +2016-07-01 Even Rouault + + * libtiff/tif_luv.c: validate that for COMPRESSION_SGILOG and + PHOTOMETRIC_LOGL, there is only one sample per pixel. Avoid + potential invalid memory write on corrupted/unexpected images when + using the TIFFRGBAImageBegin() interface (reported by + Clay Wood) + +2016-06-28 Even Rouault + + * libtiff/tif_pixarlog.c: fix potential buffer write overrun in + PixarLogDecode() on corrupted/unexpected images (reported by Mathias Svensson) + (CVE-2016-5875) + +2016-06-15 Bob Friesenhahn + + * libtiff/libtiff.def: Added _TIFFMultiply32 and _TIFFMultiply64 + to libtiff.def + +2016-06-05 Bob Friesenhahn + + * tools/Makefile.am: The libtiff tools bmp2tiff, gif2tiff, + ras2tiff, sgi2tiff, sgisv, and ycbcr are completely removed from + the distribution. The libtiff tools rgb2ycbcr and thumbnail are + only built in the build tree for testing. Old files are put in + new 'archive' subdirectory of the source repository, but not in + distribution archives. These changes are made in order to lessen + the maintenance burden. + +2016-05-10 Bob Friesenhahn + + * libtiff/tif_config.vc.h (HAVE_SNPRINTF): Add a '1' to the + HAVE_SNPRINTF definition.' + +2016-05-09 Bob Friesenhahn + + * libtiff/tif_config.vc.h (HAVE_SNPRINTF): Applied patch by Edward + Lam to define HAVE_SNPRINTF for Visual Studio 2015. + +2016-04-27 Even Rouault + + * libtiff/tif_dirread.c: when compiled with DEFER_STRILE_LOAD, + fix regression, introduced on 2014-12-23, when reading a one-strip + file without a StripByteCounts tag. GDAL #6490 + +2016-04-07 Bob Friesenhahn + + * html/bugs.html: Replace Andrey Kiselev with Bob Friesenhahn for + purposes of security issue reporting. + +2016-01-23 Even Rouault + + * libtiff/*: upstream typo fixes (mostly contributed by Kurt Schwehr) + coming from GDAL internal libtiff + +2016-01-09 Even Rouault + + * libtiff/tif_fax3.h: make Param member of TIFFFaxTabEnt structure + a uint16 to reduce size of the binary. + +2016-01-03 Even Rouault + + * libtiff/tif_read.c, tif_dirread.c: fix indentation issues raised + by GCC 6 -Wmisleading-indentation + +2015-12-27 Even Rouault + + * libtiff/tif_pixarlog.c: avoid zlib error messages to pass a NULL + string to %s formatter, which is undefined behaviour in sprintf(). + +2015-12-27 Even Rouault + + * libtiff/tif_next.c: fix potential out-of-bound write in NeXTDecode() + triggered by http://lcamtuf.coredump.cx/afl/vulns/libtiff5.tif + (bugzilla #2508) + +2015-12-27 Even Rouault + + * libtiff/tif_luv.c: fix potential out-of-bound writes in decode + functions in non debug builds by replacing assert()s by regular if + checks (bugzilla #2522). + Fix potential out-of-bound reads in case of short input data. + +2015-12-26 Even Rouault + + * libtiff/tif_getimage.c: fix out-of-bound reads in TIFFRGBAImage + interface in case of unsupported values of SamplesPerPixel/ExtraSamples + for LogLUV / CIELab. Add explicit call to TIFFRGBAImageOK() in + TIFFRGBAImageBegin(). Fix CVE-2015-8665 reported by limingxing and + CVE-2015-8683 reported by zzf of Alibaba. + +2015-12-21 Even Rouault + + * libtiff/tif_dirread.c: workaround false positive warning of Clang Static + Analyzer about null pointer dereference in TIFFCheckDirOffset(). + +2015-12-19 Even Rouault + + * libtiff/tif_fax3.c: remove dead assignment in Fax3PutEOLgdal(). Found + by Clang Static Analyzer + +2015-12-18 Even Rouault + + * libtiff/tif_dirwrite.c: fix truncation to 32 bit of file offsets in + TIFFLinkDirectory() and TIFFWriteDirectorySec() when aligning directory + offsets on a even offset (affects BigTIFF). This was a regression of the + changeset of 2015-10-19. + +2015-12-12 Even Rouault + + * libtiff/tif_write.c: TIFFWriteEncodedStrip() and TIFFWriteEncodedTile() + should return -1 in case of failure of tif_encodestrip() as documented + * libtiff/tif_dumpmode.c: DumpModeEncode() should return 0 in case of + failure so that the above mentionned functions detect the error. + +2015-12-06 Even Rouault + + * libtiff/uvcode.h: const'ify uv_code array + +2015-12-06 Even Rouault + + * libtiff/tif_dirinfo.c: const'ify tiffFields, exifFields, + tiffFieldArray and exifFieldArray arrays + +2015-12-06 Even Rouault + + * libtiff/tif_print.c: constify photoNames and orientNames arrays + +2015-12-06 Even Rouault + + * libtiff/tif_close.c, libtiff/tif_extension.c : rename link + variable to avoid -Wshadow warnings + +2015-11-22 Even Rouault + + * libtiff/*.c: fix typos in comments (patch by Kurt Schwehr) + +2015-11-22 Even Rouault + + * libtiff/*.c: fix MSVC warnings related to cast shortening and + assignment within conditional expression + +2015-11-18 Even Rouault + + * libtiff/*.c: fix clang -Wshorten-64-to-32 warnings + +2015-11-18 Even Rouault + + * libtiff/tif_dirread.c: initialize double* data at line 3693 to NULL + to please MSVC 2013 + +2015-11-17 Even Rouault + + * libtiff/tif_dirread.c: prevent reading ColorMap or TransferFunction + if BitsPerPixel > 24, so as to avoid huge memory allocation and file + read attempts + +2015-11-02 Even Rouault + + * libtiff/tif_dirread.c: remove duplicated assignment (reported by + Clang static analyzer) + +2015-10-28 Even Rouault + + * libtiff/tif_dir.c, libtiff/tif_dirinfo.c, libtiff/tif_compress.c, + libtiff/tif_jpeg_12.c: suppress warnings about 'no previous + declaration/prototype' + +2015-10-19 Even Rouault + + * libtiff/tiffiop.h, libtiff/tif_dirwrite.c: suffix constants by U to fix + 'warning: negative integer implicitly converted to unsigned type' warning + (part of -Wconversion) + +2015-10-17 Even Rouault + + * libtiff/tif_dir.c, libtiff/tif_dirread.c, libtiff/tif_getimage.c, + libtiff/tif_print.c: fix -Wshadow warnings (only in libtiff/) + +2015-09-12 Bob Friesenhahn + + * libtiff 4.0.6 released. + + * html/v4.0.6.html: Added release notes for 4.0.6. + +2015-09-06 Bob Friesenhahn + + * tools/tiffgt.c: Silence glut API deprecation warnings on MacOS + X. Patch by Roger Leigh. + + * Makefile.am: Added a 'coverity' rule to assist with Coverity + submissions. + + * tools/tiff2pdf.c: Fix compiler warning about unused function + when JPEG is not available. + + * tools/fax2ps.c (main): Detect failure to write to temporary + file. + +2015-09-05 Bob Friesenhahn + + * libtiff/tif_dirread.c (TIFFReadDirEntryCheckRangeSlongSlong8): + Change implementation so that it does not sometimes overflow the + range of a 32-bit int and to avoid a signed vs unsigned compare + compiler warning. + (TIFF_INT64_MAX): Avoid use of platform-specific large constants. + (TIFF_UINT32_MAX): Avoid use of platform-specific large constants. + +2015-09-01 Bob Friesenhahn + + * Makefile.am (distcheck-hook), configure.ac: Applied patches by + Roger Leigh (via tiff mailing list on 2015-09-01) to fix issue + with BSD make and to make use of cmake in 'distcheck' target + conditional on if cmake is available. + + * CMakeLists.txt, Makefile.am, configure.ac: Applied patches by + Roger Leigh (via tiff mailing list on 2015-09-01). + + CMake build is now included in 'distcheck' target. + + Builds with CMake 2.8.9 and newer. + + Tar is now resquested to use POSIX PAX format. + +2015-08-31 Bob Friesenhahn + + * CMakeLists.txt, libtiff/test/Makefile.am: Applied patches by + Roger Leigh (via tiff mailing list on 2015-08-31. + + CMake reads all version information directly from configure.ac to + avoid duplication of values. This basically greps over the file + for the LIBTIFF_* variables, then translates them to the form + needed for cmake. This includes the release version and libtool + shared library version information. + + Make shared/static library building configurable. Currently it + always builds shared libraries, with static libs having a _static + suffix (copying zlib, but it means it's got a non-standard name). + CMake has a -DBUILD_SHARED_LIBS=ON|OFF option to select one or the + other, which is now used instead. There's now a single "tiff" + target to build either shared or static as required, and all the + tests and tools are linked with this. Note: the Windows tests fail + when linked with a static libtiff (says: libtiff.dll not found). + Not really a regression since this was not tested up to this + point, and it's likely the unit tests haven't (ever?) been run on + Windows with a static libtiff, so there's some additional + portability issue here to address. Works fine on UNIX systems, + and fine on Windows with the default to build a DLL. + + Add a missing file which wasn't being distributed, causing unit + tests to fail. Note that "find . -name '*.cmake'" lists all the + CMake files which need distributing in addition to all the + CMakeLists.txt files (which now are distributed). + +2015-08-31 Even Rouault + + * libtiff/tif_predict.c: pedantic change to add explicit masking + with 0xff before casting to uchar in floating-point horizontal + differencing and accumulation routines. + +2015-08-31 Even Rouault + + * libtiff/tif_predict.c: fix generation of output with 16 bit + or 32 bit integer, when byte swapping is needed, in + horizontal predictor (#2521). Also fixes decoding when there is + a single pixel to code (unlikely case...) and byte swapping is + involved. + +2015-08-30 Even Rouault + + * libtiff/tif_lzw.c: make nextdata a unsigned type to avoid + undefined behaviour with shifts (gcc -fsanitize=shift) + +2015-08-30 Even Rouault + + * libtiff/tif_fax3.c, libtiff/tif_lzw.c, libtiff/tif_predict.c: + add explicit masking with 0xff before casting + to unsigned char (make icc -check=conversions happy) + + * libtiff/tif_predict.c: operate on unsigned datatypes when + computing/applying differences to avoid undefined behaviour of + signed types (C standard compliance) + +2015-08-30 Bob Friesenhahn + + * configure.ac: libtiff 4.0.5 released. + +2015-08-29 Bob Friesenhahn + + * CMakeLists.txt: Applied patch by Roger Leigh (via tiff mailing + list on 2015-08-29) to add ld-version-script option to cmake build + to match autoconf. Note: defaults to 'on' to be ABI-compatible by + default with common Linux distribution builds. Note that the + autoconf configure script defaults to 'off'. + + * html/build.html: Applied patch by Roger Leigh (via tiff mailing + list on 2015-08-29) to describe how to use CMake to build libtiff. + +2015-08-28 Bob Friesenhahn + + * html/v4.0.5.html: Added HTML file describing the changes which + will appear in the 4.0.5 release. + +2015-08-23 Bob Friesenhahn + + * libtiff/tiffiop.h: For MinGW comiles, make sure that build + supports necessary __MSVCRT_VERSION__ (at least at least 0x800). + Otherwise large files can not be supported for POSIX-style I/O. + + * tools/fax2tiff.c (main): Eliminate a compiler warning in 64-bit + builds about cast to thandle_t. + + * test/rewrite_tag.c (main): Does not require any arguments. + +2015-08-20 Bob Friesenhahn + + * tools/CMakeLists.txt, port/snprintf.c: Patch by Roger Leigh to + fix build issues when using Cmake due to Windows large file + changes. + +2015-08-18 Bob Friesenhahn + + * libtiff/tiffiop.h: First cut at supporting large files under + Microsoft Windows using tif_unix.c and the libtiff tools. This + only works if the Windows CDK is new enough to support the APIs + used (Visual C++ 2005 or later). Support for large files is not + actually tested yet. + +2015-08-15 Bob Friesenhahn + + * libtiff/tif_jpeg.c: Applied patch by Räisä Olli to assure that + client_data is initialized to a known value, and to report an + error on two memory allocation failures. + +2015-08-13 Bob Friesenhahn + + * CMakeLists.txt: Applied patch by Roger Leigh to fix libtiffxx + symbol versioning. Patch was mailed to libtiff list on Thu, 13 + Aug 2015. + +2015-07-04 Bob Friesenhahn + + * cmake: Add d suffix to debug libraries with MSVC. Patch #3 of 3 + by Roger Leigh posted to tiff list on Wed, 1 Jul 2015 15:58:20 + +0100. + + * cmake: Add extra warning flags. Patch #2 of 3 by Roger Leigh + posted to tiff list on Wed, 1 Jul 2015 15:58:20 +0100. + + * cmake: Correct snprintf fallback for VS2015. Patch #1 of 3 by + Roger Leigh posted to tiff list on Wed, 1 Jul 2015 15:58:20 +0100. + +2015-06-24 Bob Friesenhahn + + * CMakeLists.txt: Add CMake patchset by Roger Leigh as posted to + libtiff mailing list on Mon, 22 Jun 2015 21:21:01 +0100. Several + corrections to ensure that the autotools build still works were + added by me. I have not yet tested the build using 'cmake' or + MSVC with 'nmake'. + +2015-06-21 Bob Friesenhahn + + * test/Makefile.am: tiff2rgba-quad-tile.jpg.sh depends on the JPEG + library so only execute if JPEG is available. + + * libtiff 4.0.4 released. + + * configure.ac: Add a HAVE_FOO Automake conditional for each + add-on library. + + * test/Makefile.am (JPEG_DEPENDENT_CHECK_PROG): raw_decode + requires JPEG support to compile. Use Automake conditional to + only include it when JPEG support is available. + + * html/build.html: Try to improve the nmake-based VC++ build + description. + + * libtiff/tiffconf.vc.h: Build fixes based on testing. + + * libtiff/tif_config.vc.h: Build fixes based on testing. + + * libtiff/libtiff.def: TIFFRasterScanline does not exist so remove + export for it. + +2015-06-20 Bob Friesenhahn + + * libtiff/tif_config.vc.h: Make adjustments to match the new + definitions that configure produces, including for WIN64. Still + needs to be tested. + + * configure.ac: For 64-bit MinGW, fix SSIZE_FORMAT formatting + specifier. 64-bit MinGW supports 'long long' but support for + 'lld' is not assured by the run-time DLLs and so GCC warns. + Add TIFF_SIZE_T and TIFF_SIZE_FORMAT to provide a type definition + and printf format specifier to deal with printing values of + 'size_t' type. In particular, this was necessary for WIN64. + Added a configure test for if the system headers provide 'optarg' + (normal case) and block out the many explicit 'extern' statements + in the utilities. This was found to be necessary under Windows + when getopt is in a DLL and the symbols are already imported with + dllimport via standard header files. + + * test/raw_decode.c (XMD_H): Avoid conflicting typedefs for INT32 + and boolean in MinGW build due to including jpeglib.h. + + * test/rewrite_tag.c (main): Fix problem with location of variable + declaration. + + * libtiff/libtiff.def: Added exports for TIFFGetConfiguredCODECs, + TIFFReadRGBAImageOriented, TIFFSetCompressionScheme, + TIFFSwabArrayOfTriples, TIFFVGetFieldDefaulted, _TIFFCheckRealloc, + TIFFRasterScanline, TIFFSetErrorHandlerExt, + TIFFSetWarningHandlerExt, TIFFNumberOfDirectories, + TIFFCreateCustomDirectory, TIFFCreateEXIFDirectory, + TIFFWriteCustomDirectory, _TIFFRewriteField as recommended by + Roger Leigh and justified by use in libtiff tests, documentation, + and changelog notes. Also sorted symbol list and removed + duplicate entries. + +2015-06-16 Bob Friesenhahn + + * libtiff/tif_getimage.c: Fix four Coverity issues related to + unintended sign extension. + +2015-06-16 Even Rouault + + * libtiff/tif_unix.c: fix compilation with MSVC (fix by Jeff McKenna) + +2015-06-14 Lee Howard + + * libtiff/tif_unix.c: contribution from Vadim Zeitlin on + Bugzilla Bug #2510 fixes several harmless but still annoying + warnings + + * configure: contribution from Ludolf Holzheid on Bugzilla + Bug #2498. Adds an option to select the file I/O style on + Windows hosts. + + * libtiff/tif_getimage.c: contribution from Gary Cramblitt + on Bugzilla Bug #2409. Correct reading of certain tiled TIFFs. + + * configure, configure.ac: contribution from Marcos H. Woehrmann + on Bugzilla Bug #2405. Correct shell equality operator. + + * tools/tiffgt.c (raster_draw): contribution from Jay Berkenbilt + on Bugzilla Bug #2401. Appropriately call glFlush(). + + * tools/tiff2pdf.c: change ColorTransform from "0" to "1" + following Bugzilla Bug #2150. + +2015-06-13 Lee Howard + + * libtiff/tif_lzw.c: contribution from Andy Cave - decode + files that contain consecutive CODE_CLEAR codes. + + * tools/tiff2pdf.c: contribution from Antti S. Lankila on + Bugzilla Bug #2078. Suppress initial output of the header. + + * tools/tiff2pdf.c: contribution from Yuriy M. Kaminskiy - + Take care in using the return value from snprintf(). + + * tools/tiffcrop.c: contribution from Eduardo Robles Elvira - + correctly copy the compression tag from the source TIFF. + + * tools/tiff2ps.c: contribution from Eduardo Robles Elvira - + correct sizing and scaling problems with output document. + +2015-06-10 Bob Friesenhahn + + * libtiff/tif_jpeg.c (JPEGDecode): Split JPEGDecode() into two + clean implementations in order to avoid pre-processor hell. Only + one of the implementations is used in a given build. + +2015-06-08 Even Rouault + + * libtiff/tif_jpeg.c: Fix compilation in BITS_IN_JSAMPLE == 12 + case + +2015-06-07 Bob Friesenhahn + + * libtiff/tif_write.c (TIFFWriteEncodedStrip): Fix Coverity 715975 + "Division or modulo by zero". + (TIFFWriteEncodedTile): Fix Coverity 715976 and 715977 "Division + or modulo by zero". + (TIFFWriteRawStrip): Fix Coverity 715978 "Division or modulo by + zero". + (TIFFWriteScanline): Fix Coverity 715979 "Division or modulo by + zero". + + * libtiff/tif_read.c (TIFFStartTile): Fix Coverity 715973 and + 715974 "Division or modulo by zero". + +2015-05-31 Bob Friesenhahn + + * libtiff/tif_dir.c (TIFFNumberOfDirectories): Quiet Coverity + 1134470 "Logically dead code" by making the roll-over check + explicit. + + * libtiff/tif_luv.c (LogLuvDecodeTile): Fix Coverity 991227 + "Division or modulo by zero". + (LogLuvDecodeStrip): Fix Coverity 991239 "Division or modulo by + zero". + (LogLuvEncodeStrip): Fix Coverity 991240 "Division or modulo by + zero". + (LogLuvEncodeTile): Fix Coverity 991241 "Division or modulo by + zero". + + * libtiff/tif_dirread.c (TIFFReadDirEntryDoubleArray): Fix + Coverity 298626 "Logically dead code". + (TIFFReadDirEntryFloatArray): Fix Coverity 298627 "Logically dead + code". + (TIFFReadDirEntryIfd8Array): Fix Coverity 298628 "Logically dead + code". + (TIFFReadDirEntrySlong8Array): Fix Coverity 298629 "Logically dead + code" + + * libtiff/tif_dir.c (TIFFNumberOfDirectories): Don't depend on ++ + operator precedenc in evaluation. Might quench Coverity 1134470 + "Logically dead code". + + * libtiff/tif_jpeg.c (JPEGDecode): Fix Coverity 602597 "Operands + don't affect result". This change uses ifdefs to include + applicable code based on properties of libjpeg. Still needs to be + re-tested with 12-bit "6b" and "MK1". + +2015-05-30 Bob Friesenhahn + + * libtiff/tif_dirwrite.c (_TIFFRewriteField): Fix Coverity 1024310 + "Resource leak". + + * libtiff/tif_ojpeg.c (OJPEGReadHeaderInfoSecStreamDht): Fix + Coverity 601720 "Resource leak". + + * libtiff/tif_jpeg.c (JPEGCleanup): Fix Coverity 298624 + "Dereference before null check". + + * libtiff/tif_ojpeg.c (OJPEGReadBufferFill): Fix Coverity 603400 + "Missing break in switch". + + * contrib/addtiffo/tif_overview.c (TIFF_DownSample): Check buffer + size calculation for overflow. + + * contrib/addtiffo/addtiffo.c (main): Possibly address Coverity + 1024226 "Untrusted value as argument". + + * tools/gif2tiff.c (readgifimage): Fix Coverity 1024222 "Untrusted + value as argument". + (checksignature): Fix Coverity 1024894 "Ignoring number of bytes + read". + (readextension): Fix Coverity 1024893 "Ignoring number of bytes + read". + (readgifimage): Fix Coverity 1024890 "Ignoring number of bytes + read". + (readraster): Fix Coverity 1024891 "Ignoring number of bytes + read". + (readgifimage): Fix Coverity 1024892 "Ignoring number of bytes + read". + + * tools/tiff2pdf.c (t2p_readwrite_pdf_image): Fix Coverity 1024181 + "Structurally dead code". + + * tools/raw2tiff.c (main): Fix Coverity 1024887 "Unchecked return + value from library". + (guessSize): Fix Coverity 1024888 "Unchecked return value from + library". + (guessSize): Fix Coverity 1214162 "Ignoring number of bytes read". + (guessSize): Fix Coverity 1024889 "Unchecked return value from + library". + + * tools/tiff2pdf.c (t2p_readwrite_pdf_image): Fix Coverity 298621 + "Resource leak". + (t2p_readwrite_pdf_image): Fix Coverity 1024181 "Structurally dead + code". + (t2p_write_pdf): Fix Coverity 1227690 "Unused value". + +2015-05-29 Bob Friesenhahn + + * contrib/iptcutil/iptcutil.c (formatIPTC): Fix Coverity 1024468 + "Infinite loop". + (formatIPTC): Fix Coverity 1024727 "Truncated stdio return value". + (formatIPTC): Fix Coverity 1214240 "Untrusted loop bound". + +2015-05-28 Bob Friesenhahn + + * contrib/addtiffo/tif_ovrcache.c (TIFFCreateOvrCache): Fix + Coverity 298615 "Resource leak". + (TIFFGetOvrBlock): Fix Coverity 1024649 "Unintended sign + extension". + + * tools/bmp2tiff.c (main): Fix Coverity 1024225 "Untrusted value + as argument". + (main): Fix Coverity 1024678 "Unchecked return value from + library". + (main): Fix Coverity 1024679 "Unchecked return value from + library". + (main): Fix Coverity 1214160 "Ignoring number of bytes read". + + * contrib/addtiffo/tif_ovrcache.c (TIFFCreateOvrCache): Fix + Coverity 298615 "Resource leak". + + * tools/tiffcp.c: Fix Coverity 1024306, 1024307, 1024308, 1024309 + "Resource leak". + + * tools/tiffsplit.c (cpTiles): Fix Coverity 1024304 "Resource + leak". + (cpStrips): Fix Coverity 1024305 "Resource leak". + +2015-05-27 Bob Friesenhahn + + * tools/ras2tiff.c: Fix Sun Raster header definition to be safe + for 64-bit systems. Add some header validations. Should fix many + Coverity issues. + (main): Fix Coverity 1301206: "Integer handling issues (BAD_SHIFT)". + (main): Quiet Coverity 1024223 "Untrusted value as argument". + + * tools/tiffmedian.c (GetInputLine): Fix Coverity 1024795 "Nesting + level does not match indentation". + (get_histogram): Quiet Coverity 1024386 "Out-of-bounds read". + This was a benign mis-diagnosis but added code to enforce against + buffer overflow. + + * tools/tiffcrop.c (ROTATE_ANY): Fix Coverity 1294542 "Logical + vs. bitwise operator". + (readContigStripsIntoBuffer): Fix Coverity 1024545 "Division or + modulo by zero". + (readContigTilesIntoBuffer): Fix Coverity 1024586 "Logically dead + code". + (writeSingleSection): Fix Coverity 1024796 "Nesting level does not + match indentation". + (writeCroppedImage): Fix Coverity 1024797 "Nesting level does not + match indentation". + (loadImage): Fix Coverity 1299741 "Dereference before null check". + (loadImage): Fix Coverity 1299740 "Out-of-bounds write". + +2015-03-02 Even Rouault + + * tools/tiffdither.c: check memory allocations to avoid writing to + NULL pointer. Also check multiplication overflow. Fixes #2501, + CVE-2014-8128. Derived from patch by Petr Gajdos. + +2015-01-26 Even Rouault + + * add html/v4.0.4beta.html under version control + * HOWTO-RELEASE: write that cvs add html/vX.X.html must be used + +2015-01-26 Even Rouault + + * libtiff 4.0.4beta released + +2015-01-26 Even Rouault + + * automake: updated to 1.15 + * libtool: updated to 2.4.5 + +2015-01-22 Even Rouault + + * tools/tiff2pdf.c: Fix two crashes (oCERT-2014-013) + +2015-01-05 Frank Warmerdam + + * html/bugs.html: remove note about needing to email the tiff mailing + list administrator about being approved for membership, this appears + not to be true. + +2015-01-05 Olivier Paquet + + * tools/tiff2pdf.c: Fixed unsigned integer addition overflow detection. + +2015-01-03 Even Rouault + + * libtiff/tif_dirread.c: in TIFFCheckDirOffset(), avoid uint16 overflow + when reading more than 65535 directories, and effectively error out when + reaching that limit. + +2014-12-29 Even Rouault + + * libtiff/tif_jpeg.c: in JPEGFixupTags(), recognize SOF2, SOF9 and SOF10 + markers to avoid emitting a warning (even if, according to the TechNote, + there are admittedly unusual/not recommended or even forbidden variants, but + they do work well with libjpeg for SOF2, and with libjpeg-turbo for SOF2, + SOF9 and SOF10). + Define in_color_space and input_components to the right values in + JPEGSetupEncode(), before calling jpeg_set_defaults(), as specified by + libjpeg API documentation, so as to be compatible with mozjpeg library. + Note: the default settings of mozjpeg will produce progressive scans, which + is forbidden by the TechNote. + +2014-12-29 Even Rouault + + * libtiff/tif_getimage.c: move test on vertical value of YCbCr subsampling. + to avoid buffer leak (fix previous fix, found by Coverity scan) + +2014-12-29 Even Rouault + + * libtiff/tif_next.c: add new tests to check that we don't read outside of + the compressed input stream buffer. + + * libtiff/tif_getimage.c: in OJPEG case, fix checks on strile width/height + in the putcontig8bitYCbCr42tile, putcontig8bitYCbCr41tile and + putcontig8bitYCbCr21tile cases. + +2014-12-27 Even Rouault + + * libtiff/tif_dir.c: in TIFFDefaultDirectory(), reset any already existing + extented tags installed by user code through the extender mechaninm before + calling the extender callback (GDAL #5054) + +2014-12-26 Bob Friesenhahn + + * tools/tiffcrop.c: Fix warnings about variables set but not used. + + * contrib/iptcutil/iptcutil.c: Fix warnings about variables set + but not used. + + * tools/tiffgt.c: Fix warnings about unused parameters. + + * libtiff/tif_stream.cxx: Fix warnings about unused parameters. + +2014-12-25 Even Rouault + + * libtiff/tif_getimage.c, libtiff/tif_ojpeg.c, libtiff/tif_zip.c: fix + various typos found by Debian lintian tool (GDAL #5756) + +2014-12-24 Even Rouault + + * libtiff/tif_getimage.c: avoid divide by zero on invalid YCbCr subsampling. + http://bugzilla.maptools.org/show_bug.cgi?id=2235 + +2014-12-24 Even Rouault + + * tools/tiff2pdf.c: fix buffer overflow on some YCbCr JPEG compressed images. + http://bugzilla.maptools.org/show_bug.cgi?id=2445 + +2014-12-24 Even Rouault + + * tools/tiff2pdf.c: fix buffer overflow on YCbCr JPEG compressed image. + Derived from patch by Petr Gajdos, + http://bugzilla.maptools.org/show_bug.cgi?id=2443 + +2014-12-23 Even Rouault + + * libtiff/tif_dirread.c: In EstimateStripByteCounts(), check return code + of _TIFFFillStriles(). This solves crashing bug on corrupted + images generated by afl. + +2014-12-23 Even Rouault + + * libtiff/tif_read.c: fix several invalid comparisons of a uint64 value with + <= 0 by casting it to int64 first. This solves crashing bug on corrupted + images generated by afl. + +2014-12-21 Bob Friesenhahn + + * tools/tiffdump.c: Guard against arithmetic overflow when + calculating allocation buffer sizes. + +2014-12-21 Even Rouault + + * tools/tiff2bw.c: when Photometric=RGB, the utility only works if + SamplesPerPixel = 3. Enforce that + http://bugzilla.maptools.org/show_bug.cgi?id=2485 (CVE-2014-8127) + +2014-12-21 Even Rouault + + * tools/pal2rgb.c, tools/thumbnail.c: fix crash by disabling TIFFTAG_INKNAMES + copying. The right fix would be to properly copy it, but not worth the burden + for those esoteric utilities. + http://bugzilla.maptools.org/show_bug.cgi?id=2484 (CVE-2014-8127) + +2014-12-21 Even Rouault + + * tools/thumbnail.c: fix out-of-buffer write + http://bugzilla.maptools.org/show_bug.cgi?id=2489 (CVE-2014-8128) + +2014-12-21 Even Rouault + + * tools/thumbnail.c, tools/tiffcmp.c: only read/write TIFFTAG_GROUP3OPTIONS + or TIFFTAG_GROUP4OPTIONS if compression is COMPRESSION_CCITTFAX3 or + COMPRESSION_CCITTFAX4 + http://bugzilla.maptools.org/show_bug.cgi?id=2493 (CVE-2014-8128) + +2014-12-21 Even Rouault + + * libtiff/tif_next.c: check that BitsPerSample = 2. Fixes + http://bugzilla.maptools.org/show_bug.cgi?id=2487 (CVE-2014-8129) + +2014-12-21 Even Rouault + + * tools/tiff2pdf.c: check return code of TIFFGetField() when reading + TIFFTAG_SAMPLESPERPIXEL + +2014-12-21 Even Rouault + + * tools/tiffcp.c: fix crash when converting YCbCr JPEG-compressed to none. + Based on patch by Tomasz Buchert (http://bugzilla.maptools.org/show_bug.cgi?id=2480) + Description: fix for Debian bug #741451 + tiffcp crashes when converting JPEG-encoded TIFF to a different + encoding (like none or lzw). For example this will probably fail: + tiffcp -c none jpeg_encoded_file.tif output.tif + The reason is that when the input file contains JPEG data, + the tiffcp code forces conversion to RGB space. However, + the output normally inherits YCbCr subsampling parameters + from the input, which leads to a smaller working buffer + than necessary. The buffer is subsequently overrun inside + cpStripToTile() (called from writeBufferToContigTiles). + Note that the resulting TIFF file would be scrambled even + if tiffcp wouldn't crash, since the output file would contain + RGB data intepreted as subsampled YCbCr values. + This patch fixes the problem by forcing RGB space on the output + TIF if the input is JPEG-encoded and output is *not* JPEG-encoded. + Author: Tomasz Buchert + +2014-12-21 Even Rouault + + Fix various crasher bugs on fuzzed images. + * libtiff/tif_dir.c: TIFFSetField(): refuse to set negative values for + TIFFTAG_XRESOLUTION and TIFFTAG_YRESOLUTION that cause asserts when writing + the directory + * libtiff/tif_dirread.c: TIFFReadDirectory(): refuse to read ColorMap or + TransferFunction if BitsPerSample has not yet been read, otherwise reading + it later will cause user code to crash if BitsPerSample > 1 + * libtiff/tif_getimage.c: TIFFRGBAImageOK(): return FALSE if LOGLUV with + SamplesPerPixel != 3, or if CIELAB with SamplesPerPixel != 3 or BitsPerSample != 8 + * libtiff/tif_next.c: in the "run mode", use tilewidth for tiled images + instead of imagewidth to avoid crash + * tools/bmp2tiff.c: fix crash due to int overflow related to input BMP dimensions + * tools/tiff2pdf.c: fix crash due to invalid tile count (should likely be checked by + libtiff too). Detect invalid settings of BitsPerSample/SamplesPerPixel for CIELAB / ITULAB + * tools/tiffcrop.c: fix crash due to invalid TileWidth/TileHeight + * tools/tiffdump.c: fix crash due to overflow of entry count. + +2014-12-15 Even Rouault + + * libtiff/tif_jpeg.c: Fix regression introduced on 2010-05-07 that caused + all tiles/strips to include quantization tables even when the jpegtablesmode + had the JPEGTABLESMODE_QUANT bit set. + Also add explicit removal of Huffman tables when jpegtablesmode has the + JPEGTABLESMODE_HUFF bit set, which avoids Huffman tables to be emitted in the + first tile/strip (only useful in update scenarios. create-only was + fine) + +2014-12-09 Bob Friesenhahn + + * tools/tiff2pdf.c: Assure that memory size calculations for + _TIFFmalloc() do not overflow the range of tmsize_t. + +2014-12-07 Even Rouault + + * tools/thumbnail.c, tools/tiffcrop.c: "fix" heap read over-run found with + Valgrind and Address Sanitizer on test suite + +2014-12-07 Bob Friesenhahn + + * tools/tiff2pdf.c (t2p_read_tiff_init): TIFFTAG_TRANSFERFUNCTION + tag can return one channel, with the other two channels set to + NULL. The tiff2pdf code was expecting that other two channels + were duplicate pointers in the case where there is only one + channel. Detect this condition in order to avoid a crash, and + presumably perform correctly with just one channel. + +2014-12-06 Bob Friesenhahn + + * tools/tiffdump.c: Fix double-free bug. + +2014-11-27 Even Rouault + + * libtiff/tif_config.vc.h: no longer use "#define snprintf _snprintf" with + Visual Studio 2015 aka VC 14 aka MSVC 1900 + +2014-11-20 Even Rouault + + * libtiff/tif_lzw.c: prevent potential null dereference of + sp->dec_codetab in LZWPreDecode (bug #2459) + + * libtiff/tif_read.c: in TIFFReadBufferSetup(), avoid passing -1 size + to TIFFmalloc() if passed user buffer size is 0 (bug #2459) + + * libtiff/tif_ojpeg.c: make Coverity happier (not a bug, #2459) + + * libtiff/tif_dir.c: in _TIFFVGetField() and _TIFFVSetField(), make + Coverity happier (not a bug, #2459) + + * libtiff/tif_dirread.c: in TIFFFetchNormalTag(), make Coverity happier + (not a bug, #2459) + + * tools/tiff2pdf.c: close PDF file (bug #2479) + + * tools/fax2ps.c: check malloc()/realloc() result (bug #2470) + + * tools/tiffdump.c: detect cycle in TIFF directory chaining (bug #2463) + and avoid passing a NULL pointer to read() if seek() failed before (bug #2459) + + * tools/tiffcrop.c: fix segfault if bad value passed to -Z option + (bug #2459) and add missing va_end in dump_info (#2459) + + * tools/gif2tif.c: apply patch for CVE-2013-4243 (#2451) + +2014-11-20 Even Rouault + * libtiff/tif_jpeg.c: fix segfault in JPEGFixupTagsSubsampling() on + corrupted image where tif->tif_dir.td_stripoffset == NULL (bug #2471) + +2014-11-20 Even Rouault + * automake: updated to 1.14.1 + * libtool: updated to 2.4.3 + * HOWTO-RELEASE: small update about autotools building order + +2014-10-20 Olivier Paquet + * tools/tiff2pdf.c: Preserve input file directory order when pages + are tagged with the same page number. + +2014-08-31 Bob Friesenhahn + + * libtiff/tif_dirread.c (TIFFReadDirEntryOutputErr): Incorrect + count for tag should be a warning rather than an error since + errors terminate processing. + +2014-06-07 Bob Friesenhahn + + * tools/tiff2rgba.c (]): Fixed tiff2rgba usage message in that zip + was wrongly described. Fix suggested by Miguel Medalha. + +2014-05-06 Bob Friesenhahn + + * libtiff/tif_dirinfo.c (TIFFField) : Fix data type for + TIFFTAG_GLOBALPARAMETERSIFD tag. Patch by Steve Underwood. + Reviewed and forwarded by Lee Howard. + +2013-11-30 Frank Warmerdam + + * libtiff/tif_dir.c: fix last fix for TIFFNumberOfDirectories() + +2013-10-21 Frank Warmerdam + + * libtiff/tif_dir.c: generate error in case of directory count + overflow. + +2013-10-01 Frank Warmerdam + + * libtiff/tiff.h, libtiff/tif_dirinfo.c: add definitions for + TIFF/EP CFARepeatPatternDim and CFAPattern tags (bug #2457) + +2013-09-12 Bob Friesenhahn + + * libtiff/tif_dir.c (TIFFAdvanceDirectory): If nextdir is found to + be defective, then set it to zero before returning error in order + to terminate processing of truncated TIFF. Issue found and fix + suggested by Richard Nolde. + +2013-08-14 Frank Warmerdam + + * tools/gif2tiff.c: fix possible OOB write (#2452, CVE-2013-4244) + +2013-08-13 Frank Warmerdam + + * tools/gif2tiff.c: Be more careful about corrupt or + hostile input files (#2450, CVE-2013-4231) + + * tools/tiff2pdf.c: terminate after failure of allocating + ycbcr buffer (bug #2449, CVE-2013-4232) + +2013-07-09 Frank Warmerdam + + * tools/tiffinfo.c: Default various values fetched with + TIFFGetField() to avoid being uninitialized. + +2013-05-02 Tom Lane + + * tools/tiff2pdf.c: Rewrite JPEG marker parsing in + t2p_process_jpeg_strip to be at least marginally competent. The + approach is still fundamentally flawed, but at least now it won't + stomp all over memory when given bogus input. Fixes CVE-2013-1960. + +2013-05-02 Tom Lane + + * contrib/dbs/xtiff/xtiff.c, libtiff/tif_codec.c, + libtiff/tif_dirinfo.c, tools/rgb2ycbcr.c, tools/tiff2bw.c, + tools/tiff2pdf.c, tools/tiff2ps.c, tools/tiffcrop.c, + tools/tiffdither.c: Enlarge some fixed-size buffers that weren't + large enough, and eliminate substantially all uses of sprintf(buf, + ...) in favor of using snprintf(buf, sizeof(buf), ...), so as to + protect against overflow of fixed-size buffers. This responds in + particular to CVE-2013-1961 concerning overflow in tiff2pdf.c's + t2p_write_pdf_page(), but in general it seems like a good idea to + deprecate use of sprintf(). + +2013-03-29 Bob Friesenhahn + + * configure.ac: Applied patch by Brad Smith to improve pkg-config + static linking by adding -lm to Libs.private when needed. + +2013-03-05 Tom Lane + + * html/man/tiff2ps.1.html, html/man/tiffcp.1.html, + html/man/tiffdither.1.html, man/tiff2ps.1, man/tiffcp.1, + man/tiffdither.1, tools/tiff2ps.c, tools/tiffcp.c, + tools/tiffdither.c: Sync tool usage printouts and man pages with + reality (quite a few options had escaped being documented in one + or both places). Per an old report from Miroslav Vadkerti. + +2013-01-25 Bob Friesenhahn + + * tools/tiff2ps.c:Fix bug in auto rotate option code. Once a + rotation angle was set by the auto rotate check, it was retained + for all pages that followed instead ofa being retested for each + page. Patch by Richard Nolde. + +2013-01-18 Frank Warmerdam + + * libtiff/tif_write.c: tmsize_t related casting warning fixed for + 64bit linux. + + * libtiff/tif_read.c: uint64/tmsize_t change for MSVC warnings. + http://bugzilla.maptools.org/show_bug.cgi?id=2427 + +2012-12-20 Tom Lane + + * test/raw_decode.c: Relax raw_decode's pixel-value checks so that + it will pass with more versions of libjpeg. (There are at least + three in active use now, and JPEG_LIB_VERSION doesn't tell us + enough to uniquely identify expected results.) + +2012-12-12 Tom Lane + + * libtiff/tif_print.c: Fix TIFFPrintDirectory's handling of + field_passcount fields: it had the TIFF_VARIABLE and + TIFF_VARIABLE2 cases backwards. + +2012-12-10 Tom Lane + + * tools/ppm2tiff.c: Improve previous patch for CVE-2012-4564: + check the linebytes calculation too, get the max() calculation + straight, avoid redundant error messages, check for malloc + failure. + +2012-12-10 Tom Lane + + * libtiff/tif_pixarlog.c: Improve previous patch for CVE-2012-4447 + (to enlarge tbuf for possible partial stride at end) so that + overflow in the integer addition is detected. Per gripe from + Huzaifa Sidhpurwala. + +2012-12-03 Bob Friesenhahn + + * tools/tiffset.c: tiffset now supports a -u option to unset a + tag. Patch by Zach Baker. See + http://bugzilla.maptools.org/show_bug.cgi?id=2419 + +2012-11-18 Bob Friesenhahn + + * automake: Update Automake to 1.12.5 release. + + * libtiff/tif_{unix,vms,win32}.c (_TIFFmalloc): ANSI C does not + require malloc() to return NULL pointer if requested allocation + size is zero. Assure that _TIFFmalloc does. + +2012-11-01 Frank Warmerdam + + * tools/ppm2tiff.c: avoid zero size buffer vulnerability. + CVE-2012-4564 - Thanks to Huzaifa Sidhpurwala of the + Red Hat Security Response team for the fix. + +2012-10-18 Frank Warmerdam + + * tif_zip.c: Avoid crash on NULL error messages. + +2012-09-22 Bob Friesenhahn + + * libtiff 4.0.3 released. + +2012-09-20 Bob Friesenhahn + + * Makefile.am: Update to Automake 1.12.4 + +2012-08-19 Bob Friesenhahn + + * Makefile.in: Update to Automake 1.12.3 + + * libtiff{tiff.h, tif_print.c, tif_dirinfo.c, tif_dirread.c}: Add + some TIFF/FX support in libtiff. Add the tag definitions to + tiff.h. Add the related TIFF field definitions to tif_dirinfo.c, + and also fixes an error in a comment. Adds the photometric values + to tif_print.c, and fixes a bug. These changes are by Steve + Underwood. + +2012-08-13 Frank Warmerdam + + * libtiff/tif_write.c: Fix bug rewriting image tiles in a + compressed file: http://trac.osgeo.org/gdal/ticket/4771 + +2012-08-02 Frank Warmerdam + + * libtiff/tif_dirread.c: report error in case of mismatch value + counts for tags (ie. DotRange). + +2012-07-26 Tom Lane + + * libtiff/{tiffio.h, tif_dirinfo.c, libtiff.def}: Add six new + functions TIFFFieldTag(), TIFFFieldName(), TIFFFieldDataType(), + TIFFFieldPassCount(), TIFFFieldReadCount(), TIFFFieldWriteCount() + as external accessors for the opaque type TIFFField. + + * tools/tiffset.c: Make tiffset use the above functions instead of + relying on library private headers. + +2012-07-19 Tom Lane + + * tools/tiff2pdf.c: Fix two places where t2p_error didn't get set + after a malloc failure. No crash risk AFAICS, but the program + might not report exit code 1 as desired. h/t mancha@mac.hush.com + +2012-07-18 Tom Lane + + * tools/tiff2pdf.c: Fail when TIFFSetDirectory() fails. This + prevents core dumps or perhaps even arbitrary code execution when + processing a corrupt input file (CVE-2012-3401). + +2012-07-06 Bob Friesenhahn + + * test/raw_decode.c (main): Test fixes to work with IJG JPEG 7+. + IJG JPEG 7+ uses a different upsampling algorithm which produces + different numeric results. + + * libtiff/tif_jpeg.c (JPEGPreDecode): Patch from Even Rouault to + work with IJG JPEG 7+. + +2012-07-04 Bob Friesenhahn + + * test/raw_decode.c: Add changes so that test can run with build + directory outside of source directory. + +2012-07-02 Frank Warmerdam + + * libtiff/tif_jpeg.c: Fix handling when writing RGBA jpeg compressed + imagery (http://trac.osgeo.org/gdal/ticket/4732) + +2012-06-20 Frank Warmerdam + + * libtiff/tif_fax3.c: fix memory initialization of runs, only + partly done. + + * libtiff/tif_pixarlog.c: Make sure tbuf is large enough for one + full "stride" past the end. + +2012-06-19 Frank Warmerdam + + * libtiff/tif_packbits.c: fix read past end of data buffer. + 2012-06-15 Frank Warmerdam * libtiff 4.0.2 released. @@ -36,7 +3051,7 @@ * libtiff/tif_dir.c, tif_print.c : Remove FIELD_CUSTOM handling for PAGENUMBER, HALFTONEHINTS, and YCBCRSUBSAMPLING. Implement DOTRANGE - differently. This is to avoid using special TIFFGetField/TIFFSetField + differently. This is to avoid using special TIFFGetField/TIFFSetField rules for these fields in non-image directories (like EXIF). 2012-06-04 Frank Warmerdam @@ -112,7 +3127,7 @@ 2012-05-19 Bob Friesenhahn * man/TIFFGetField.3tiff: Correct the 'count' field type in the - example for how to retreive the value of unsupported tags. + example for how to retrieve the value of unsupported tags. 2012-03-30 Frank Warmerdam @@ -132,7 +3147,7 @@ 2012-01-31 Frank Warmerdam * libtiff/tif_dir.c, libtiff/tif_dirread.c: Extra caution around - assumption tag fetching is always successful. + assumption tag fetching is always successful. * libtiff/tif_jpeg.c: Extra caution for case where sp is NULL. @@ -168,7 +3183,7 @@ * libtiff/tif_dirread.c: fixes to deal with invalid files where _TIFFFillStriles() fails, and we try to chop up strips (gdal #4372) - * libtiff/tif_dirread.c: fix error reporting when there is no + * libtiff/tif_dirread.c: fix error reporting when there is no tag information struct and name (gdal #4373) 2011-10-22 Bob Friesenhahn @@ -213,11 +3228,11 @@ 2011-04-20 Frank Warmerdam - * libtiff/tif_dirinfo.c,tiffio.h: Remove the obsolete - TIFFMergeFieldInfo/TIFFFindFieldInfo/TIFFFindFieldInfoByName API. + * libtiff/tif_dirinfo.c,tiffio.h: Remove the obsolete + TIFFMergeFieldInfo/TIFFFindFieldInfo/TIFFFindFieldInfoByName API. http://bugzilla.maptools.org/show_bug.cgi?id=2315 - * libtiff/libtiff.def: add some missing (64bit) APIs. + * libtiff/libtiff.def: add some missing (64bit) APIs. http://bugzilla.maptools.org/show_bug.cgi?id=2316 2011-04-09 Bob Friesenhahn @@ -260,8 +3275,8 @@ 2011-03-21 Frank Warmerdam - * libtiff/tif_thunder.c: Correct potential buffer overflow with - thunder encoded files with wrong bitspersample set. The libtiff + * libtiff/tif_thunder.c: Correct potential buffer overflow with + thunder encoded files with wrong bitspersample set. The libtiff development team would like to thank Marin Barbella and TippingPoint's Zero Day Initiative for reporting this vulnerability (ZDI-CAN-1004, CVE-2011-1167). @@ -269,25 +3284,25 @@ 2011-03-10 Frank Warmerdam - * libtiff/tif_fax3.h: Fix to last change allowing zero length + * libtiff/tif_fax3.h: Fix to last change allowing zero length runs at the start of a scanline - needed for legal cases. 2011-03-02 Frank Warmerdam - * libtiff/tif_fax3.h: Protect against a fax VL(n) codeword commanding - a move left. Without this, a malicious input file can generate an - indefinitely large series of runs without a0 ever reaching the right + * libtiff/tif_fax3.h: Protect against a fax VL(n) codeword commanding + a move left. Without this, a malicious input file can generate an + indefinitely large series of runs without a0 ever reaching the right margin, thus overrunning our buffer of run lengths. Per CVE-2011-0192. - This is a modified version of a patch proposed by Drew Yao of Apple - Product Security. It adds an unexpected() report, and disallows the - equality case, since emitting a run without increasing a0 still allows + This is a modified version of a patch proposed by Drew Yao of Apple + Product Security. It adds an unexpected() report, and disallows the + equality case, since emitting a run without increasing a0 still allows buffer overrun. 2011-02-23 Frank Warmerdam * libtiff/tif_jpeg.c: avoid divide by zero in degenerate case (#2296) - * tools/tiff2rgba.c: close source file on error to make leak + * tools/tiff2rgba.c: close source file on error to make leak detection easier. * libtiff/tif_getimage.c: avoid leaks if TIFFRGBAImageBegin() fails. @@ -302,15 +3317,15 @@ 2011-02-18 Frank Warmerdam * configure.ac, configure: Added support for --enable-chunky-strip-read - configure option to enable the experimental feature from a couple - months ago for reading big strips in chunks. + configure option to enable the experimental feature from a couple + months ago for reading big strips in chunks. - * configure.ac, tif_read.c, tif_readdir.c, tif_dir.h, tiffiop.h, + * configure.ac, tif_read.c, tif_readdir.c, tif_dir.h, tiffiop.h, tif_write.c, tif_print.c, tif_jpeg.c, tif_dirwrite.c, tif_write.c: - Implement optional support for deferring the load of strip/tile + Implement optional support for deferring the load of strip/tile offset and size tags for optimized scanning of directories. Enabled with the --enable-defer-strile-load configure option (DEFER_STRILE_LOAD - #define in tif_config.h). + #define in tif_config.h). 2011-02-11 Frank Warmerdam @@ -319,7 +3334,7 @@ 2011-02-09 Frank Warmerdam * libtiff/tif_win32.c: avoid error/warning buffer overrun problem - with non-console (popup message) builds on win32. + with non-console (popup message) builds on win32. http://bugzilla.maptools.org/show_bug.cgi?id=2293 @@ -335,18 +3350,18 @@ 2011-01-06 Frank Warmerdam - * libtiff/tif_pixarlog.c: Note that tif_rawcc/tif_rawcp are not - maintained. + * libtiff/tif_pixarlog.c: Note that tif_rawcc/tif_rawcp are not + maintained. - * libtiff/tif_zip.c: Maintain tif_rawcc/tif_rawcp when decoding + * libtiff/tif_zip.c: Maintain tif_rawcc/tif_rawcp when decoding for CHUNKY_STRIP_READ_SUPPORT. * libtiff/tif_jpeg.c: ensure that rawcc and rawcp are maintained - during JPEGPreDecode and JPEGDecode calls. - * libtiff/tif_read.c: larger read ahead for CHUNKY_STRIP_READ_SUPPORT, - as compression formats like JPEG keep 16 lines interleaved in a sense - and might need to touch quite a bit of data. - + during JPEGPreDecode and JPEGDecode calls. + * libtiff/tif_read.c: larger read ahead for CHUNKY_STRIP_READ_SUPPORT, + as compression formats like JPEG keep 16 lines interleaved in a sense + and might need to touch quite a bit of data. + http://trac.osgeo.org/gdal/ticket/3894 2011-01-03 Lee Howard @@ -428,7 +3443,7 @@ 2010-12-12 Lee Howard - * tools/tiff2pdf.c: fix colors for images with RGBA + * tools/tiff2pdf.c: fix colors for images with RGBA interleaved data http://bugzilla.maptools.org/show_bug.cgi?id=2250 @@ -509,7 +3524,7 @@ 2010-10-21 Frank Warmerdam * tools/tiffinfo.c: avoid direct reference to _TIFFerrorHandler. - + * libtiff/tif_config.vc.h: define snprintf to _snprintf for tiff2pdf. * libtiff/libtiff.def: export _TIFFCheckMalloc for tools. @@ -610,11 +3625,11 @@ * libtiff/tif_dirinfo.c: Fix invocation of tag compare function (#2201) - * tools/tiff2pdf.c: Fix assorted bugs in tiff2pdf: missing "return" - in t2p_read_tiff_size() causes t2p->tiff_datasize to be set entirely - wrong for COMPRESSION_JPEG case, resulting in memory stomp if actual - size is larger. Also, there are a bunch of places that try to - memset() a malloc'd buffer before checking for malloc failure, which + * tools/tiff2pdf.c: Fix assorted bugs in tiff2pdf: missing "return" + in t2p_read_tiff_size() causes t2p->tiff_datasize to be set entirely + wrong for COMPRESSION_JPEG case, resulting in memory stomp if actual + size is larger. Also, there are a bunch of places that try to + memset() a malloc'd buffer before checking for malloc failure, which would result in core dump if there actually were a failure. (#2211) 2010-06-11 Bob Friesenhahn @@ -690,13 +3705,13 @@ 2010-05-07 Frank Warmerdam - * libtiff/tif_jpeg.c: Ensure that quality is always set in - JPEGPreEncode(), not just when we want to output local tables. + * libtiff/tif_jpeg.c: Ensure that quality is always set in + JPEGPreEncode(), not just when we want to output local tables. Otherwise the quality used during compression may not be right and might not match the tables in the tables tag. This bug only occurs when seeking between directories in the midst of writing blocks. http://trac.osgeo.org/gdal/ticket/3539 - + 2010-05-06 Andrey Kiselev * html/man/TIFFGetField.3tiff.html, html/man/TIFFSetField.3tiff.html: @@ -719,9 +3734,9 @@ 2010-04-21 Frank Warmerdam - * libtiff/tif_jpeg.c: avoid preparing jpeg tables everytime - JPEGSetupEncode() is called if the tables already seem to be - established. This prevents spurious updates and rewriting of + * libtiff/tif_jpeg.c: avoid preparing jpeg tables every time + JPEGSetupEncode() is called if the tables already seem to be + established. This prevents spurious updates and rewriting of directories with jpegtables when doing updates to existing images. http://trac.osgeo.org/gdal/ticket/3539 @@ -746,7 +3761,7 @@ 2010-04-02 Frank Warmerdam - * libtiff/tif_read.c (primarily): Add support for + * libtiff/tif_read.c (primarily): Add support for CHUNKY_STRIP_READ_SUPPORT where large strips are read in chunks for applications using TIFFReadScanline(). This is intended to make it more practical work with very @@ -775,11 +3790,11 @@ 2010-02-22 Lee Howard * libtiff/tif_jpeg.c: Do not generate a JPEGTables tag when creating - the JPEG TIFF as is is not required in order to prevent it from - being unused and filled with invalid data. (Leave it to be + the JPEG TIFF as is is not required in order to prevent it from + being unused and filled with invalid data. (Leave it to be generated by later activity.) http://bugzilla.maptools.org/show_bug.cgi?id=2135 - * tools/tiff2pdf.c: Write the JPEG SOI headers into the TIFF strip + * tools/tiff2pdf.c: Write the JPEG SOI headers into the TIFF strip data rather than skipping them. This fixes the ability to view in Acrobat Reader, Evince, and Ghostscript. http://bugzilla.maptools.org/show_bug.cgi?id=2135 @@ -790,7 +3805,7 @@ 2009-12-03 Frank Warmerdam * libtiff/tif_jpeg.c: Made JPEGDecodeRaw() check for buffer overruns. - Made so that when working with downsampled images a stub function + Made so that when working with downsampled images a stub function reporting an error is used for tif_decoderow. We cannot meaningfully support reading scanlines in this situation. (#1936) @@ -800,17 +3815,17 @@ 2009-11-30 Frank Warmerdam - * contrib/dbs/tiff-grayscale.c, contrib/tif-palette.c, + * contrib/dbs/tiff-grayscale.c, contrib/tif-palette.c, tools/ras2tiff.c: Fix resource leaks on error. http://bugzilla.maptools.org/show_bug.cgi?id=2121 - * libtiff/tif_{aux.c,dir.c,dir.h,dirinfo.c}: Return to handling + * libtiff/tif_{aux.c,dir.c,dir.h,dirinfo.c}: Return to handling TIFFTAG_REFERENCEBLACKWHITE as a field in the TIFF directory instead of as a custom(generic) field to avoid a potential reentrancy problem. http://bugzilla.maptools.org/show_bug.cgi?id=2125 - + * libtiff/tif_color.c, libtiff/tif_getimage.c, libtiff/tiffio.h, - man/TIFFcolor.3tiff: Make TIFFDisplay argument in TIFFCIELabToRGBInit + man/TIFFcolor.3tiff: Make TIFFDisplay argument in TIFFCIELabToRGBInit const, and display_sRGB static and const. http://bugzilla.maptools.org/show_bug.cgi?id=2124 @@ -872,7 +3887,7 @@ 2009-09-03 Frank Warmerdam * libtiff/tif_getimage.c: Fixed error recognition handling in RGBA - interface when stoponerror is set. + interface when stoponerror is set. http://bugzilla.maptools.org/show_bug.cgi?id=2071 2009-08-30 Bob Friesenhahn @@ -921,7 +3936,7 @@ * libtiff/tif_dirread.c (TIFFReadCustomDirectory): Apply patch from Jay Berkenbilt for "Bug 1895 - logic error in tif_dirread.c: - segfault after setting tdir_tag = IGNORE". + segfault after setting tdir_tag = IGNORE". http://bugzilla.maptools.org/show_bug.cgi?id=1895 2009-08-23 Bob Friesenhahn @@ -930,7 +3945,7 @@ tiffcrop.sh into a collection of many specific tests. Re-wrote all of the existing tests to be based on some simple shell functions. Make distcheck works again. - + Export certain variables (MAKE, MAKEFLAGS, MEMCHECK) to tests and added 'memcheck' and 'ptrcheck' targets to make it easy to run the tests under valgrind. @@ -964,7 +3979,7 @@ 1 on success instead of zero. http://bugzilla.maptools.org/show_bug.cgi?id=2069 - * libtiff/tif_lzw.c: back out patch from #2065 and apply patch from + * libtiff/tif_lzw.c: back out patch from #2065 and apply patch from #1085 for a better underflow fix that errors properly. http://bugzilla.maptools.org/show_bug.cgi?id=2065 http://bugzilla.maptools.org/show_bug.cgi?id=1985 @@ -976,13 +3991,13 @@ 2009-06-22 Frank Warmerdam - * libtiff/tif_lzw.c: Fix buffer underflow bug. + * libtiff/tif_lzw.c: Fix buffer underflow bug. http://bugzilla.maptools.org/show_bug.cgi?id=2065 2009-06-21 Frank Warmerdam * configure.ac, libtiff/tif_jpeg.c, libtiff/tif_jpeg_12.c: add support - for dual mode 8/12 bit jpeg support. + for dual mode 8/12 bit jpeg support. 2009-06-03 Frank Warmerdam @@ -999,7 +4014,7 @@ * libtiff/{tif_jpeg.c,tif_ojpeg.c,tif_getimage.c}: Fixed various error reports to use "%s" as format string. http://trac.osgeo.org/gdal/ticket/2976 - + 2009-03-12 Frank Warmerdam * libtiff/{tif_fax3.c,tif_jpeg.c,tif_ojpeg.c}: Fix printdir chaining @@ -1007,7 +4022,7 @@ 2009-02-12 Frank Warmerdam - * libtiff/tif_luv.c: Fix handling of tiled logluv images. + * libtiff/tif_luv.c: Fix handling of tiled logluv images. http://bugzilla.maptools.org/show_bug.cgi?id=2005 2009-02-09 Frank Warmerdam @@ -1023,17 +4038,17 @@ 2009-02-05 Frank Warmerdam * libtiff/tif_dirread.c: Re-incorporated a sanity check on tag size, - but at the 2GB boundary to avoid overflow on 32bit systems. + but at the 2GB boundary to avoid overflow on 32bit systems. http://bugzilla.maptools.org/show_bug.cgi?id=1993 * libtiff/tif_dirread.c: Remove some assertions that blow due to - corrupt files rather than in response to library internal - inconsistencies. + corrupt files rather than in response to library internal + inconsistencies. http://bugzilla.maptools.org/show_bug.cgi?id=1995 http://bugzilla.maptools.org/show_bug.cgi?id=1991 * libtiff/tif_dirread.c: Fixed testing for failed result from - TIFFReadDirectoryFindFieldInfo(). + TIFFReadDirectoryFindFieldInfo(). http://bugzilla.maptools.org/show_bug.cgi?id=1992 2009-01-23 Frank Warmerdam @@ -1042,17 +4057,17 @@ http://bugzilla.maptools.org/show_bug.cgi?id=1911 * libtiff/tif_dirwrite.c: Fix byte swapping of next directory offset. - + http://bugzilla.maptools.org/show_bug.cgi?id=1924 - * tools/tiffcrop.c: initialize xres/yres values. + * tools/tiffcrop.c: initialize xres/yres values. * test/*.sh - default ${srcdir} to local directory. - * test/common.sh - start verbose mode after common settings. + * test/common.sh - start verbose mode after common settings. - * libtiff/tif_dirinfo.c: Replace lfind() with local equivelent to - avoid type mismatches on different platforms. + * libtiff/tif_dirinfo.c: Replace lfind() with local equivalent to + avoid type mismatches on different platforms. http://bugzilla.maptools.org/show_bug.cgi?id=1889 2009-01-22 Frank Warmerdam @@ -1061,7 +4076,7 @@ tiffsplit.c}: avoid warnings, mostly 32bit/64bit casting issues. * port,tools: Introduce libport.h, and include in tools if NEED_LIBPORT - defined, primarily to reduce prototype warnings on windows. + defined, primarily to reduce prototype warnings on windows. * libtiff/tif_dirinfo.c,tif_dirread.c: Avoid warnings about unused parameters, and uninitialized variables. @@ -1109,7 +4124,7 @@ for TIFFError(), TIFFErrorExt(), TIFFWarning(), and TIFFWarningExt() in order to reveal bugs. - * Many fixes throughout to work better as a 64-bit build. + * Many fixes throughout to work better as a 64-bit build. 2008-12-30 Bob Friesenhahn @@ -1160,7 +4175,7 @@ 2008-10-09 Frank Warmerdam * libtiff/tif_jpeg.c: Add #ifdefs for changes needed if using - IPP enabled version of libjpeg from Intel. + IPP enabled version of libjpeg from Intel. http://bugzilla.maptools.org/show_bug.cgi?id=1951 2008-09-05 Andrey Kiselev @@ -1198,12 +4213,12 @@ * tools/tiffdump.c: When compiling for Microsoft Windows, apply consistent (__int64) casting when testing if _lseeki64 has - successfully seeked as requested. This is necessary for large + successfully sought as requested. This is necessary for large file support to work since off_t is only 32-bit. 2008-07-29 Frank Warmerdam - * tif_strip.c: Replace assertions related to samplesperpixel != 3 or + * tif_strip.c: Replace assertions related to samplesperpixel != 3 or the subsampling values not being 1, 2 or 4 (for jpeg compressed images) with control logic to return runtime errors (c/o Even Rouault) (#1927). @@ -1243,13 +4258,13 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2008-05-24 Frank Warmerdam - * tif_codec.c: Avoid NULL pointer dereferencing for exotic + * tif_codec.c: Avoid NULL pointer dereferencing for exotic compression codec codes. * tif_dirwrite.c: fix potential memory leak. * tif_dirread.c: Fix unchecked malloc result. - + 2008-05-24 Bob Friesenhahn * test {tiff2pdf.sh tiff2ps-EPS1.sh tiff2ps-PS1.sh tiff2ps-PS2.sh @@ -1283,7 +4298,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_dirinfo.c: Use TIFF_SETGET_ASCII for PIXAR_TEXTUREFORMAT and PIXAR_WRAPMODES instead of TIFF_SETGET_UNDEFINED. Not exactly clear - why this is needed. + why this is needed. 2008-05-09 Bob Friesenhahn @@ -1324,25 +4339,25 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2008-03-14 Frank Warmerdam * tif_dirread.c: Removed sanity checks on tags larger than 4MB in - TIFFReadDirEntryArray() since they are interfering with seemingly + TIFFReadDirEntryArray() since they are interfering with seemingly legitimate files. http://trac.osgeo.org/gdal/ticket/2005 2008-02-09 Joris Van Damme - * tif_dirread.c: Added handling for the case of number of values for - PageNumber tag different from 2 (previously resulted in an assert + * tif_dirread.c: Added handling for the case of number of values for + PageNumber tag different from 2 (previously resulted in an assert indicating lack of handling and was forgotten about) 2008-02-01 Frank Warmerdam - * libtiff/tif_jpeg.c: Do not try to fixup subsampling tags based on + * libtiff/tif_jpeg.c: Do not try to fixup subsampling tags based on the actual jpeg data stream if the first strip/tile has zero size. This is the case when GDAL creates a new file with zero sizes, closes and reopens it. 2008-01-07 Frank Warmerdam - * tools/tiff2ps.c: fix up 64bit issues (from Edward Lam). + * tools/tiff2ps.c: fix up 64bit issues (from Edward Lam). 2008-01-01 Frank Warmerdam @@ -1352,14 +4367,14 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic targets. * tools/tiffinfo.c, tools/tiffcmp.c, tools/gif2tiff.c, tools/bmp2tiff.c - tools/tiff2pdf.c: Fix 64-bit warnings when compiling under MSVC 2005 - (x64). + tools/tiff2pdf.c: Fix 64-bit warnings when compiling under MSVC 2005 + (x64). - * tools/tiffset.c: Changes to reflect the fact that TIFFFieldWithTag() + * tools/tiffset.c: Changes to reflect the fact that TIFFFieldWithTag() and TIFFFieldWithName() now return TIFFField pointers instead of TIFFFieldInfo pointers. - * tools/tiffdump.c: Added ssize_t typedef on Windows since it doesn't + * tools/tiffdump.c: Added ssize_t typedef on Windows since it doesn't exist. This makes it compile again on Windows * tif_aux.c, tif_getimage.c, tif_next.c, tif_predict.c, tif_win32.c, @@ -1370,19 +4385,19 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2007-12-31 Frank Warmerdam * tif_dirwrite.c: Added TIFFRewriteField(). This new function - rewrites one field "on disk" updating an existing directory + rewrites one field "on disk" updating an existing directory entry. Lots of limitations still... - * tiffiop.h, tif_write.c, tif_dirread.c, tif_flush.c: Keep track of - TIFF_DIRTYSTRIP separately from TIFF_DIRTYDIRECT to indicate that - the strip offset/size values are dirty but nothing else about the + * tiffiop.h, tif_write.c, tif_dirread.c, tif_flush.c: Keep track of + TIFF_DIRTYSTRIP separately from TIFF_DIRTYDIRECT to indicate that + the strip offset/size values are dirty but nothing else about the directory is dirty. In flush handle "just stripmaps dirty" as a - special case that just rewrites these values without otherwise - modifying the directory on disk using TIFFRewriteField(). + special case that just rewrites these values without otherwise + modifying the directory on disk using TIFFRewriteField(). We also modify logic so that in update mode the directory is not marked dirty on read, but only when something is changed. This - means we need to keep track of updates to the stripmap stuff in + means we need to keep track of updates to the stripmap stuff in TIFFAppendToStrip(). 2007-12-10 Frank Warmerdam @@ -1393,7 +4408,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2007-11-23 Frank Warmerdam * tif_dir.c, tif_dirread.c, tif_dirwrite.c, tif_read.c, tif_write.c, - tiffiop.h: Added TIFF_BUF4WRITE flag to indicate if contents of the + tiffiop.h: Added TIFF_BUF4WRITE flag to indicate if contents of the rawcp/rawcc buffer are for writing and thus may require flushing. Necessary to distinguish whether they need to be written to disk when in mixed read/write mode and doing a mixture of writing followed by @@ -1406,12 +4421,12 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2007-11-02 Frank Warmerdam - * tif_write.c: Rip out the fancy logic in TIFFAppendToStrip() for - establishing if an existing tile can be rewritten to the same location - by comparing the current size to all the other blocks in the same - directory. This is dangerous in many situations and can easily + * tif_write.c: Rip out the fancy logic in TIFFAppendToStrip() for + establishing if an existing tile can be rewritten to the same location + by comparing the current size to all the other blocks in the same + directory. This is dangerous in many situations and can easily corrupt a file. (observed in esoteric GDAL situation that's hard to - document). This change involves leaving the stripbytecount[] values + document). This change involves leaving the stripbytecount[] values unaltered till TIFFAppendToStrip(). Now we only write a block back to the same location it used to be at if the new data is the same size or smaller - otherwise we move it to the end of file. @@ -1419,30 +4434,30 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * tif_dirwrite.c: Try to avoid writing out a full readbuffer of tile data when writing the directory just because we have BEENWRITING at some point in the past. This was causing odd junk to be written out - in a tile of data when a single tile had an interleaving of reading - and writing with reading last. (highlighted by gdal - autotest/gcore/tif_write.py test 7. + in a tile of data when a single tile had an interleaving of reading + and writing with reading last. (highlighted by gdal + autotest/gcore/tif_write.py test 7. * tif_predict.c: use working buffer in PredictorEncodeTile to avoid - modifying callers buffer. + modifying callers buffer. http://trac.osgeo.org/gdal/ticket/1965 - * tif_predict.c/h: more fixes related to last item, keeping a + * tif_predict.c/h: more fixes related to last item, keeping a distinct pfunc for encode and decode cases as these were getting mixed up sometimes. http://trac.osgeo.org/gdal/ticket/1948 2007-11-01 Frank Warmerdam - * tif_predict.c/h, tif_lzw.c, tif_zip.c: Improvements so that + * tif_predict.c/h, tif_lzw.c, tif_zip.c: Improvements so that predictor based encoding and decoding works in read-write update - mode properly. + mode properly. http://trac.osgeo.org/gdal/ticket/1948 2007-10-24 Joris Van Damme - * tif_dirread.c: Fixed problem with bogus file triggering - assert(td->td_planarconfig == PLANARCONFIG_CONTIG) in + * tif_dirread.c: Fixed problem with bogus file triggering + assert(td->td_planarconfig == PLANARCONFIG_CONTIG) in ChopUpSingleUncompressedStrip 2007-10-22 Joris Van Damme @@ -1466,10 +4481,10 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2007-09-29 Joris Van Damme - * tif_dirread.c: Strip chopping interfered badly with uncompressed - subsampled images because it tried to divide subsampled rowblocks, - leading to all sorts of errors throughout the library for these - images. Fixed by making strip chopping divide in row counts that + * tif_dirread.c: Strip chopping interfered badly with uncompressed + subsampled images because it tried to divide subsampled rowblocks, + leading to all sorts of errors throughout the library for these + images. Fixed by making strip chopping divide in row counts that are a multiple of vertical subsampling value. 2007-09-28 Joris Van Damme @@ -1482,18 +4497,18 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * tif_dirread.c: Made calculation of td_maxsamplevalue more robust when dealing with large bitspersample values, shutting up purification - tools that warn about truncation, though it remains incorrect and + tools that warn about truncation, though it remains incorrect and indicates a conceptual problem there. - * tif_open.c: Moved early exit in case of 'h' flag (to disable reading - of first IFD) to proper place because it badly interfered with memory - mapping, resulting in mapping flag even with dummy mapping functions - that returned 0 whilst at the same time the mapping tif_size wasn't + * tif_open.c: Moved early exit in case of 'h' flag (to disable reading + of first IFD) to proper place because it badly interfered with memory + mapping, resulting in mapping flag even with dummy mapping functions + that returned 0 whilst at the same time the mapping tif_size wasn't set, thus resulting in continuous incorrect beyond-eof errors. 2007-09-24 Joris Van Damme - * tif_dirinfo.c: Fixed (MSVC) compiler reports about + * tif_dirinfo.c: Fixed (MSVC) compiler reports about inconsistent use of const in tiffFields and exifFields definition 2007-09-20 Frank Warmerdam @@ -1503,7 +4518,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic TIFFWriteDirectoryTagLongLong8Array() function was restructured accordingly. - * tif_dirread.c: Improvements to error reporting text in + * tif_dirread.c: Improvements to error reporting text in TIFFFetchDirectory(). 2007-09-19 Bob Friesenhahn @@ -1517,27 +4532,27 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2007-08-24 Frank Warmerdam * tif_dirwrite.c: Write the tif_nextdiroff value instead of a fixed - zero when writing directory contents to preserve the ability to + zero when writing directory contents to preserve the ability to rewrite directories in place, even in the middle of a directory chain. * tif_dirinfo.c: _TIFFMergeFields() now only merges in field definitions that are missing. Existing definitions are silently - ignored. + ignored. * tif_dirread.c: Add runtime error for fields for which no definition - is found (in addition to an assert for developers) in - TIFFFetchNormalTag(). Not sure if this is needed, but it seems + is found (in addition to an assert for developers) in + TIFFFetchNormalTag(). Not sure if this is needed, but it seems prudent. 2007-08-10 Joris Van Damme - * libtiff/tif_getimage.c: removed SubsamplingHor and SubsamplingVer + * libtiff/tif_getimage.c: removed SubsamplingHor and SubsamplingVer from _TIFFRGBAImage structure to revert unwanted ABI change. 2007-08-10 Joris Van Damme - * libtiff/tif_win32.c: use SetFilePointer instead of + * libtiff/tif_win32.c: use SetFilePointer instead of SetFilePointerEx, as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1580 @@ -1559,7 +4574,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_dirread.c: Handle the case of MSVC 6 when using 64-bit integer constants. - * libtiff/{Makefile.am, Makefile.v}: Do not distribute tiffconf.h, + * libtiff/{Makefile.am, Makefile.v}: Do not distribute tiffconf.h, remove tif_config.h/tiffconf.h during cleaning. As per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1573 @@ -1629,14 +4644,14 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic tif_win3.c}: Obsoleted portability stuff removed. * tools/tiff2ps.c: Added support 16-bit images as per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=1566 Patch from William Bader. * tools/tiff2pdf.c: Fix for TIFFTAG_JPEGTABLES tag fetching and significant upgrade of the whole utility as per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=1560 Now we don't need tiffiop.h in tiff2pdf anymore and will open output @@ -1654,7 +4669,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2007-06-25 Bob Friesenhahn * port/strtoull.c: New porting function in case strtoull() is not - available on the target system. + available on the target system. * configure.ac: Add configure support for determining sized types in a portable way and performing necessary substitutions in tif_config.h and tiffconf.h. Updated tiff.h to use the new @@ -1671,7 +4686,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/{tif_dir.h, tif_dirread.c, tif_dirinfo.c, tif_jpeg.c, tif_fax3.c, tif_jbig.c, tif_luv.c, tif_ojpeg.c, tif_pixarlog.c, tif_predict.c, tif_zip.c}: Finally fix bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=1274 by introducing _TIFFMergeFieldInfo() returning integer error status @@ -1682,7 +4697,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2007-04-07 Frank Warmerdam - * contrib/addtiffo/tif_overview.c: Fix problems with odd sized output + * contrib/addtiffo/tif_overview.c: Fix problems with odd sized output blocks in TIFF_DownSample_Subsampled() (bug 1542). 2007-04-06 Frank Warmerdam @@ -1690,15 +4705,15 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_jpeg.c: Changed JPEGInitializeLibJPEG() so that it will convert from decompressor to compressor or compress to decompress if required by the force arguments. This works around a problem in - where the JPEGFixupTestSubsampling() may cause a decompressor to + where the JPEGFixupTestSubsampling() may cause a decompressor to be setup on a directory when later a compressor is required with the - force flag set. Occurs with the addtiffo program for instance. + force flag set. Occurs with the addtiffo program for instance. 2007-04-06 Andrey Kiselev * tools/tiffcrop.c, man/tiffcrop.1: Significant update in functionality from Richard Nolde. As per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=1525 2007-03-28 Frank Warmerdam @@ -1710,15 +4725,15 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * start of BigTIFF upgrade - CVS HEAD unstable until further notice 2007-03-07 Joris Van Damme - + * libtiff/tif_getimage.c: workaround for 'Fractional scanline' error reading OJPEG images with rowsperstrip that is not a multiple of vertical subsampling factor. This bug is mentioned in: http://bugzilla.remotesensing.org/show_bug.cgi?id=1390 - http://www.asmail.be/msg0054766825.html + http://www.asmail.be/msg0054766825.html 2007-03-07 Joris Van Damme - + * libtiff/tif_win32.c: made inclusion of windows.h unconditional * libtiff/tif_win32.c: replaced preprocessor indication for consiously @@ -1768,14 +4783,14 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic larger than 2GB. Fixes bug http://bugzilla.remotesensing.org/show_bug.cgi?id=890 - + Idea submitted by Matt Hancher. 2007-01-31 Andrey Kiselev * tools/tif2rgba.c: This utility does not work properly on big-endian architectures. It was fixed including the bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=1149 2007-01-15 Mateusz Loskot @@ -1792,15 +4807,15 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2006-11-19 Frank Warmerdam - * libtiff/tif_write.c: TIFFAppendToStrip() - clear sorted flag if - we move a strip. - http://bugzilla.remotesensing.org/show_bug.cgi?id=1359 + * libtiff/tif_write.c: TIFFAppendToStrip() - clear sorted flag if + we move a strip. + http://bugzilla.remotesensing.org/show_bug.cgi?id=1359 2006-10-13 Andrey Kiselev * libtiff/tif_dir.c: More fixes for vulnerabilities, reported in Gentoo bug (): - + http://bugs.gentoo.org/show_bug.cgi?id=142383 * libtiff/contrib/dbs/xtiff/xtiff.c: Make xtiff utility compilable. @@ -1834,12 +4849,12 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_lzw.c, libtiff/tif_zip.c: Fixed problems with mixing encoding and decoding on the same read-write TIFF handle. The LZW code can now maintain encode and decode state at the same time. The - ZIP code will switch back and forth as needed. + ZIP code will switch back and forth as needed. http://bugzilla.remotesensing.org/show_bug.cgi?id=757 2006-09-20 Frank Warmerdam - * libtiff: Rename config.h.vc and tif_config.h.vc to config.vc.h and + * libtiff: Rename config.h.vc and tif_config.h.vc to config.vc.h and tif_config.vc.h for easier identification by folks using an IDE. 2006-07-25 Frank Warmerdam @@ -1854,7 +4869,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2006-07-12 Frank Warmerdam - * tif_dirwrite.c: make sure to use uint32 for wordcount in + * tif_dirwrite.c: make sure to use uint32 for wordcount in TIFFWriteNormanTag if writecount is VARIABLE2 for ASCII fields. It already seems to have been done for other field types. Needed for "tiffset" on files with geotiff ascii text. @@ -1882,9 +4897,9 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2006-06-17 Frank Warmerdam * tif_readdir.c: Added case in EstimateStripByteCounts() for tiled - files. Modified TIFFReadDirectory() to not invoke + files. Modified TIFFReadDirectory() to not invoke EstimateStripByteCounts() for case where entry 0 and 1 are unequal - but one of them is zero. + but one of them is zero. http://bugzilla.remotesensing.org/show_bug.cgi?id=1204 2006-06-08 Andrey Kiselev @@ -1912,7 +4927,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * {configure, configure.ac, libtiff/tif_jbig.c, tools/tiffcp.c}: Added support for JBIG compression scheme (34661 code) contributed by Lee Howard. As per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=896 * configure, configure.ac: OJPEG support enabled by default. @@ -1951,7 +4966,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2006-04-18 Frank Warmerdam * nmake.opt: use /EHsc for VS2005 compatibility. Also define - _CRT_SECURE_NO_DEPRECATE to avoid noise on VS2005. + _CRT_SECURE_NO_DEPRECATE to avoid noise on VS2005. 2006-04-12 Joris Van Damme @@ -1959,7 +4974,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic non-subsampled YCbCr (i.e. separate YCbCr with subsampling [1,1]) 2006-04-11 Joris Van Damme - + * libtiff/tif_getimage.c: Revision of all RGB(A) put routines - Conversion of unassociated alpha to associated alpha now done with more performant LUT, and calculation more correct @@ -1968,21 +4983,21 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic - Bugfix of handling of 16bit RGB with unassociated alpha 2006-04-11 Joris Van Damme - - * libtiff/tif_getimage.c: - - When there is no alpha, gtTileSeparate and gtStripSeparate allocated - buffer for alpha strile and filled it, only to never read it back. + + * libtiff/tif_getimage.c: + - When there is no alpha, gtTileSeparate and gtStripSeparate allocated + buffer for alpha strile and filled it, only to never read it back. Removed allocation and fill. - - Minor rename of vars in gtTileSeparate and gtStripSeparate + - Minor rename of vars in gtTileSeparate and gtStripSeparate anticipating planned functionality extension 2006-04-08 Joris Van Damme - * libtiff/tif_getimage.c: renamed pickTileContigCase to PickContigCase - and pickTileSeparateCase to PickSeparateCase as both work on strips as + * libtiff/tif_getimage.c: renamed pickTileContigCase to PickContigCase + and pickTileSeparateCase to PickSeparateCase as both work on strips as well - * libtiff/tif_getimage.c: moved img->get selection from + * libtiff/tif_getimage.c: moved img->get selection from TIFFRGBAImageBegin into PickContigCase and PickSeparateCase to create logical hook for planned functionality extension @@ -1993,10 +5008,10 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2006-04-07 Joris Van Damme - * libtiff/tif_getimage.c: replaced usage of TIFFScanlineSize in + * libtiff/tif_getimage.c: replaced usage of TIFFScanlineSize in gtStripContig with TIFFNewScanlineSize so as to fix buggy behaviour - on subsampled images - this ought to get sorted when we feel brave - enough to replace TIFFScanlineSize alltogether + on subsampled images - this ought to get sorted when we feel brave + enough to replace TIFFScanlineSize altogether * libtiff/tif_ojpeg.c: fixed bug in OJPEGReadSkip @@ -2004,13 +5019,13 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tiffio.h: added new type tstrile_t - * libtiff/tif_dir.h: changed types of td_stripsperimage and td_nstrips - to new tstrile_t, types of td_stripoffset and td_stripbytecount to + * libtiff/tif_dir.h: changed types of td_stripsperimage and td_nstrips + to new tstrile_t, types of td_stripoffset and td_stripbytecount to toff_t* * libtiff/tif_ojpeg.c: totally new implementation - * libtiff/tif_dirread.c: added several hacks to suit new support of + * libtiff/tif_dirread.c: added several hacks to suit new support of OJPEG * libtiff/tif_getimage.c: removed TIFFTAG_JPEGCOLORMODE handling @@ -2050,7 +5065,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_getimage.c: added putcontig8bitYCbCr12tile - * libtiff/tif_read.c: added support for new TIFF_NOREADRAW flag to + * libtiff/tif_read.c: added support for new TIFF_NOREADRAW flag to prepare the path for new tif_ojpeg.c 2006-03-23 Andrey Kiselev @@ -2166,7 +5181,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_write.c: Small code rearrangement in TIFFWriteScanline() to avoid crash as per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=1081. 2006-02-26 Andrey Kiselev @@ -2216,7 +5231,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2006-02-07 Frank Warmerdam * tools/tiff2pdf.c: Fixed support for non-YCbCr encoded JPEG - compressed TIFF files, per submission from Dan Cobra. + compressed TIFF files, per submission from Dan Cobra. 2006-02-07 Andrey Kiselev @@ -2248,7 +5263,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_dirread.c: Use _TIFFGetExifFieldInfo() instead of _TIFFGetFieldInfo() in TIFFReadEXIFDirectory() call as per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=1026. 2006-01-23 Andrey Kiselev @@ -2314,7 +5329,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2005-12-26 Andrey Kiselev - * libtiff/{tif_dir.c, tif_dir.h, tif_dirread.c, tif_dirinfo.c}: + * libtiff/{tif_dir.c, tif_dir.h, tif_dirread.c, tif_dirinfo.c}: tiffFieldInfo and exifFieldInfo arrays definitions moved back to tif_dirinfo.c; added _TIFFGetFieldInfo() and _TIFFGetExifFieldInfo() private functions to retrieve FieldInfo arrays. @@ -2341,10 +5356,10 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2005-12-23 Joris Van Damme - * libtiff/tiffio.h: fixed typo that potentially resulted in + * libtiff/tiffio.h: fixed typo that potentially resulted in redefininition of USE_WIN32_FILEIO - * libtiff/*: Added more 'dual-mode' error handling: Done TIFFWarning + * libtiff/*: Added more 'dual-mode' error handling: Done TIFFWarning calls in core LibTiff. 2005-12-21 Andrey Kiselev @@ -2354,10 +5369,10 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2005-12-21 Joris Van Damme - * libtiff/*, contrib/*: Added 'dual-mode' error handling, enabling + * libtiff/*, contrib/*: Added 'dual-mode' error handling, enabling newer code to get context indicator in error handler and still - remain compatible with older code: Done TIFFError calls everywhere - except in tools + remain compatible with older code: Done TIFFError calls everywhere + except in tools 2005-12-20 Andrey Kiselev @@ -2430,7 +5445,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic http://bugzilla.remotesensing.org/show_bug.cgi?id=1002 * .cvsignore: many files added, and a few update according - to suggestion of Brad HArds on tiff mailing list. + to suggestion of Brad HArds on tiff mailing list. 2005-11-03 Frank Warmerdam @@ -2455,7 +5470,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic http://bugzilla.remotesensing.org/show_bug.cgi?id=946 * tools/bmp2tiff.c: Fixed possible integer overflow error as per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=965 * libtiff/tif_dirinfo.c: Make XResolution, YResolution and @@ -2465,7 +5480,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * tools/tiffsplit.c: Copy fax related fields over splitted parts as per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=983 2005-10-21 Frank Warmerdam @@ -2521,7 +5536,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_dir.c: When prefreeing tv->value in TIFFSetFieldV also set it to NULL to avoid double free when re-setting custom - string fields as per: + string fields as per: http://bugzilla.remotesensing.org/show_bug.cgi?id=922 @@ -2557,7 +5572,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic http://bugzilla.remotesensing.org/show_bug.cgi?id=831 Remove TIFFFetchExtraSamples() function, use TIFFFetchNormalTag() - instead. + instead. * libtiff/tiffconf.h.in: One more attempt to fix the AIX bug @@ -2654,7 +5669,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2005-06-03 Andrey Kiselev - * libtiff/tif_open.c: Replace runtime endianess check with the compile + * libtiff/tif_open.c: Replace runtime endianness check with the compile time one. * libtiff/tif_predict.c: Floating point predictor now works on @@ -2728,7 +5743,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2005-05-22 Frank Warmerdam - * libtiff/tif_dirread.c: Changed the code that computes + * libtiff/tif_dirread.c: Changed the code that computes stripbytecount[0] if it appears bogus to ignore if stripoffset[0] is zero. This is a common case with GDAL indicating a "null" tile/strip. @@ -2738,8 +5753,8 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2005-05-06 Frank Warmerdam - * libtiff/tif_dirread.c: Applied similar change to - TIFFFetchPerSampleLongs and TIFFFetchPerSampleAnys. + * libtiff/tif_dirread.c: Applied similar change to + TIFFFetchPerSampleLongs and TIFFFetchPerSampleAnys. http://bugzilla.remotesensing.org/show_bug.cgi?id=843 @@ -2789,7 +5804,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * man/TIFFSetField.3tiff: Fixed definition of the TIFFTAG_INKNAMES tag as per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=816 2005-03-30 Andrey Kiselev @@ -2899,7 +5914,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tiffio.h: Move TIFFOpenW() function into the extern "C"{} block as per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=763 2005-02-03 Bob Friesenhahn @@ -2920,7 +5935,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic http://bugzilla.remotesensing.org/show_bug.cgi?id=320 * tools/tiff2ps.c: Fixed problem with page sizes as per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=742 2005-01-31 Bob Friesenhahn @@ -2961,7 +5976,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic TIFFRGBAImageBegin() as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=739 - + 2005-01-12 Andrey Kiselev * libtiff/tif_jpeg.c: Added ability to read/write the fax specific @@ -2990,7 +6005,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tiff.h: Restore back the workaround for AIX Visual Age C compiler to avoid double definition of BSD types as per bug - http://bugzilla.remotesensing.org/show_bug.cgi?id=39 + http://bugzilla.remotesensing.org/show_bug.cgi?id=39 * libtiff/Makefile.am: Place the C++ stream API in the separate library called libtiffxx to avoid unneeded dependencies. Probably @@ -3014,7 +6029,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_getimage.c: More fixes for multiple-alpha-channelled RGB-images as per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=713 @@ -3050,7 +6065,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2004-12-15 Frank Warmerdam * libtiff/tif_getimage.c: #define A1 bracketing for clean build on - SunPro compiler. + SunPro compiler. 2004-12-11 Bob Friesenhahn @@ -3062,7 +6077,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_dirwrite.c: Always write TIFFTAG_SUBIFD using LONG type as per bugs - + http://bugzilla.remotesensing.org/show_bug.cgi?id=703 and @@ -3082,9 +6097,9 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_config.in.vc: Removed unneded definitions for read/open/close/lseek functions to fix the - + http://bugzilla.remotesensing.org/show_bug.cgi?id=680 - + 2004-12-03 Andrey Kiselev * libtiff/{tif_dir.c, tif_dirread.c}: Remove TIFFReassignTagToIgnore() @@ -3120,7 +6135,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2004-11-26 Frank Warmerdam - * libtiff/makefile.vc: make it easier to rename the libtiff DLL. + * libtiff/makefile.vc: make it easier to rename the libtiff DLL. 2004-11-24 Andrey Kiselev @@ -3217,7 +6232,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=648 - + * libtiff/{tif_jpeg.c, tif_ojpeg.c}: TIFFTAG_JPEGTABLES should have uint32 count. Use this type everywhere. @@ -3230,7 +6245,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * tools/tiff2rgba.c: removed extra newlines in usage message. 2004-10-30 Andrey Kiselev - + * libtiff/tif_dirwrite.c: Improvements in tag writing code. * tools/tiff2ps.c: Fixed wrong variable data type when read Position @@ -3245,7 +6260,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_fax3.c: Fixed case with the wrong decode routines choosing when the incorrect Group4Options tag set. As per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=323 * libtiff/tif_dirwrite.c: Fixed problem with passing count variable of @@ -3264,7 +6279,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * tools/tiff2pdf.c: added casts to avoid warnings. * libtiff/libtiff.def: Added several more entry points required - to link fax2tiff.c against the DLL on windows. + to link fax2tiff.c against the DLL on windows. 2004-10-27 Andrey Kiselev @@ -3335,7 +6350,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2004-10-08 Frank Warmerdam * libtiff/tif_dirinfo.c: Fix bug with tif_foundfield and reallocation - of tif_fieldinfo. + of tif_fieldinfo. http://bugzilla.remotesensing.org/show_bug.cgi?id=630 @@ -3367,7 +6382,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2004-09-30 Frank Warmerdam - * libtiff/tif_dirinfo.c: changed type of XMLPacket (tag 700) to + * libtiff/tif_dirinfo.c: changed type of XMLPacket (tag 700) to TIFFTAG_BYTE instead of TIFFTAG_UNDEFINED to comply with the info in the Adobe XMP Specification. @@ -3387,7 +6402,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2004-09-26 Andrey Kiselev * libtiff/{tif_dir.h, tif_dir.c, tif_dirread.c, tif_write.c}: - Optimize checking for the strip bounds. + Optimize checking for the strip bounds. * libtiff/{tif_dirread.c, tif_strip.c}: TIFFScanlineSize() and TIFFRasterScanlineSize() functions report zero in the case of integer @@ -3538,7 +6553,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic here http://www.asmail.be/msg0054799560.html - + for details. * tools/fax2tiff.c: Use the new functions in the code. @@ -3666,11 +6681,11 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * tools/tiffsplit.c: Fixed problem with unproperly written multibyte files. Now output files will be written using the same byte order flag as in the input image. See - + http://bugzilla.remotesensing.org/show_bug.cgi?id=574 - + for details. - + 2004-05-19 Frank Warmerdam * libtiff/tif_print.c: added (untested) support for printing @@ -3682,7 +6697,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_fax3.c: Avoid reading CCITT compression options if compression type mismatches. See - + http://bugzilla.remotesensing.org/show_bug.cgi?id=565 2004-04-30 Andrey Kiselev @@ -3727,7 +6742,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2004-04-04 Frank Warmerdam * libtiff/tif_open.c: close clientdata if TIFFClientOpen() fails - via bad2. + via bad2. 2004-03-26 Andrey Kiselev @@ -3754,10 +6769,10 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2004-02-26 Andrey Kiselev - * tools/tiffsplit.c: Copy JPEGTables tag contents for JPEG compressed + * tools/tiffsplit.c: Copy JPEGTables tag contents for JPEG compressed images. Reported by Artem Mirolubov. - * libtiff/tif_dirread.c: Fixed problem with handling TIFF_UNDEFINED + * libtiff/tif_dirread.c: Fixed problem with handling TIFF_UNDEFINED tag type in TIFFFetchNormalTag() as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=508 @@ -3779,8 +6794,8 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2004-01-30 Frank Warmerdam * libtiff/libtiff.def: Added TIFFCurrentDirOffset, TIFFWriteCheck, - TIFFRGBAImageOK, and TIFFNumberOfDirectories as suggested by - Scott Reynolds. + TIFFRGBAImageOK, and TIFFNumberOfDirectories as suggested by + Scott Reynolds. 2004-01-29 Andrey Kiselev @@ -3798,7 +6813,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic file if TIFFFdOpen() failed as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=468 - + * libtiff/tif_open.c: More fixes for http://bugzilla.remotesensing.org/show_bug.cgi?id=468 @@ -3822,7 +6837,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_dirwrite.c: Fixed handling of writable ASCII tags that are field_passcount=TRUE properly. Arguably anonymous custom tags should be declared as passcount=FALSE, but I don't want to change - that without a careful review. + that without a careful review. 2004-01-20 Andrey Kiselev @@ -3985,8 +7000,8 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2003-11-17 Frank Warmerdam - * tif_dirread.c: do not mark all anonymously defined tags to be - IGNOREd. + * tif_dirread.c: do not mark all anonymously defined tags to be + IGNOREd. 2003-11-17 Andrey Kiselev @@ -3996,7 +7011,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2003-11-16 Andrey Kiselev * libtiff/{tiff.h, tif_dirinfo.c}: Added support for IFD (13) - datatype, intruduced in "Adobe PageMaker TIFF Tech. Notes". + datatype, introduced in "Adobe PageMaker TIFF Tech. Notes". 2003-11-15 Frank Warmerdam @@ -4026,15 +7041,15 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2003-11-09 Frank Warmerdam - * libtiff/tif_tile.c: remove spurious use of "s" (sample) in the + * libtiff/tif_tile.c: remove spurious use of "s" (sample) in the planarconfig_contig case in TIFFComputeTile(). http://bugzilla.remotesensing.org/show_bug.cgi?id=387 2003-11-09 Andrey Kiselev - + * libtiff/tiffiop.h: New macros: TIFFmax, TIFFmin and TIFFrint. - + 2003-11-07 Andrey Kiselev * libtiff/{tiffio.h, tif_strip.c}, man/{TIFFstrip.3t, libtiff.3t}: @@ -4101,11 +7116,11 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic function TIFFReadRGBAImageOriented() implemented to retrieve raster array with user-specified origin position as suggested by Jason Frank. See - + http://bugzilla.remotesensing.org/show_bug.cgi?id=322 for details. - + * tools/tiff2rgba.c: Switched to use TIFFReadRGBAImageOriented() instead of TIFFReadRGBAImage(). @@ -4186,9 +7201,9 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic encoded write functions use tif_postdecode() to apply byte order swapping (swab) to the application passed data buffer if the same would be done when reading. This allows us to write pixel data with - more than 8 bits per sample to existing files of a non-native byte + more than 8 bits per sample to existing files of a non-native byte order. One side effect of this change is the applications buffer - itself is altered in this case by the act of writing. + itself is altered in this case by the act of writing. http://bugzilla.remotesensing.org/show_bug.cgi?id=171 @@ -4214,9 +7229,9 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2003-07-08 Frank Warmerdam * tif_aux.c, tif_codec.c, tif_dir.c, tif_dirread.c, tif_extension.c, - tif_fax3.c, tif_getimage.c, tif_luv.c, tif_lzw.c, tif_next.c, + tif_fax3.c, tif_getimage.c, tif_luv.c, tif_lzw.c, tif_next.c, tif_packbits.c, tif_predict.c, tif_print.c, tif_swab.c, tif_thunder.c: - avoid casting warning at /W4. + avoid casting warning at /W4. 2003-07-03 Andrey Kiselev @@ -4238,11 +7253,11 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_dirinfo.c: TIFFDataWidth() returns 0 in case of unknown data type. - + 2003-06-19 Frank Warmerdam * libtiff/tif_print.c: fixed some serious bugs when printing - custom tags ... almost certain to crash. + custom tags ... almost certain to crash. * libtiff/tif_dirread.c: Don't ignore custom fields that are autodefined. Not sure how this got to be like this. @@ -4253,12 +7268,12 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * tools/tiffcmp.c, man/tiffcmp.1: Fixed problem with unused data comparing as per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=349 `-z' option now can be used to set the number of reported different bytes. - + 2003-06-09 Andrey Kiselev * tools/tiffcp.c, man/tiffcp.1: Added possibility to specify value -1 @@ -4284,7 +7299,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2003-05-25 Andrey Kiselev * tools/fax2tiff.c: Page numbering fixed, as per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=341 2003-05-20 Andrey Kiselev @@ -4307,7 +7322,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * contrib/ojpeg/{Makefile.in, jdhuff.h, jinclude.h, ojpeg.c, README}, configure, Makefile.in: Improved libtiff compilation with OJPEG - support. Now no need for patching IJG JPEG library, hack requred by + support. Now no need for patching IJG JPEG library, hack required by libtiff will be compiled and used in-place. Implemented with suggestion and help from Bill Allombert, Debian's libjpeg maintainer. @@ -4350,7 +7365,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * tools/tiffcp.c: Fixed problem with colorspace conversion for JPEG encoded images. See bug entries - + http://bugzilla.remotesensing.org/show_bug.cgi?id=275 and @@ -4411,16 +7426,16 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_jpeg.c: Modified to defer initialization of jpeg library so that we can check if there is already any tile/strip data - before deciding between creating a compressor or a decompressor. + before deciding between creating a compressor or a decompressor. 2003-01-31 Frank Warmerdam * libtiff/tif_write.c: TIFFWriteCheck() now fails if the image is - a pre-existing compressed image. That is, image writing to + a pre-existing compressed image. That is, image writing to pre-existing compressed images is not allowed. * libtiff/tif_open.c: Removed error if opening a compressed file - in update mode. + in update mode. http://bugzilla.remotesensing.org/show_bug.cgi?id=198 @@ -4433,16 +7448,16 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * cut 3.6.0 Beta release. 2002-12-20 Andrey Kiselev - + * tools/fax2ps.c, man/fax2ps.1: Page size was determined in wrong way as per bug - + http://bugzilla.remotesensing.org/show_bug.cgi?id=239 2002-12-17 Frank Warmerdam - * libtiff/tif_dirread.c: Allow wrong sized arrays in - TIFFFetchStripThing(). + * libtiff/tif_dirread.c: Allow wrong sized arrays in + TIFFFetchStripThing(). http://bugzilla.remotesensing.org/show_bug.cgi?id=49 @@ -4456,7 +7471,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_dir.c: fixed bug with resetting an existing custom field value. - * libtiff/tif_dir.c: Fixed potential problem with ascii "custom" + * libtiff/tif_dir.c: Fixed potential problem with ascii "custom" tags in TIFFVGetField() ... added missing break. 2002-10-14 Frank Warmerdam @@ -4468,11 +7483,11 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic the eps by redefining the colorimage operator will get messed up. Patch supplied by William Bader. - * Makefile.in: added tif_extension.c to file list as per + * Makefile.in: added tif_extension.c to file list as per http://bugzilla.remotesensing.org/show_bug.cgi?id=218. 2002-10-11 Andrey Kiselev - + * configure, config.site, libtiff/{tif_unix.c, Makefile.in}: Fix for large files (>2GiB) supporting. New option in the config.site: LARGEFILE="yes". Should be enough for I/O of the large files. @@ -4504,13 +7519,13 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2002-10-06 Frank Warmerdam * libtiff/tif_jpeg.c: fixed problem with boolean defined with wrong - size on windows. Use #define boolean hack. + size on windows. Use #define boolean hack. http://bugzilla.remotesensing.org/show_bug.cgi?id=188 * libtiff/tiff.h: Don't do special type handling in tiff.h unless USING_VISUALAGE is defined. - + http://bugzilla.remotesensing.org/show_bug.cgi?id=39 2002-10-03 Frank Warmerdam @@ -4521,30 +7536,30 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_dirread.c: Another fix for the fetching SBYTE arrays by the TIFFFetchByteArray() function. Should finally resolve - + http://bugzilla.remotesensing.org/show_bug.cgi?id=52 - + * configure: Set -DPIXARLOG_SUPPORT option along with -DZIP_SUPPORT * html/Makefile.in: New targets added: html and groffhtml for producing HTML representations of the manual pages automatically. html target uses man2html tool, groffhtml uses groff tool. - + 2002-09-29 Frank Warmerdam * configure, libtiff/Makefile.in: Added SCO OpenServer 5.0.6 support - from John H. DuBois III. + from John H. DuBois III. 2002-09-15 Andrey Kiselev * Makefile.in, /man/{raw2tiff.1, Makefile.in, libtiff.3}: Added manual page for raw2tiff(1) tool. - + 2002-09-12 Andrey Kiselev * /libtiff/{tiffio.h, tif_dir.h}: TIFFDataWidth() declaration moved to the tiffio.h header file. - + * Makefile.in, /man/{TIFFDataWidth.3t, Makefile.in, libtiff.3}: Added manual page for TIFFDataWidth() function @@ -4554,8 +7569,8 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic as per http://bugzilla.remotesensing.org/show_bug.cgi?id=196. * tools/tiff2ps.c: Don't emit BeginData/EndData DSC comments - since we are unable to properly include the amount to skip. - + since we are unable to properly include the amount to skip. + http://bugzilla.remotesensing.org/show_bug.cgi?id=80 2002-09-02 Andrey Kiselev @@ -4565,7 +7580,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic http://bugzilla.remotesensing.org/show_bug.cgi?id=52 2002-08-22 Andrey Kiselev - + * /libtiff/tif_dirinfo.c: Further additions to free custom fields in _TIFFSetupFieldInfo() function. See http://bugzilla.remotesensing.org/show_bug.cgi?id=169 for details. @@ -4574,14 +7589,14 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic LZWDecode() and LZWDecodeCompat(). Fixes http://bugzilla.remotesensing.org/show_bug.cgi?id=190 and http://bugzilla.remotesensing.org/show_bug.cgi?id=100 - + * /libtiff/tif_lzw.c: Added check for valid code lengths in LZWDecode() and LZWDecodeCompat(). Fixes http://bugzilla.remotesensing.org/show_bug.cgi?id=115 2002-08-16 Andrey Kiselev - + * /libtiff/{Makefile.vc, libtiff.def}: Missed declarations added. @@ -4592,7 +7607,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic http://bugzilla.remotesensing.org/show_bug.cgi?id=177 - * tif_dir.h: changed FIELD_CODEC to 66 from 64 to avoid overlap + * tif_dir.h: changed FIELD_CODEC to 66 from 64 to avoid overlap with FIELD_CUSTOM as mentioned in bug 169. * tif_close.c: added logic to free dynamically created anonymous @@ -4601,31 +7616,31 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic http://bugzilla.remotesensing.org/show_bug.cgi?id=169 2002-08-10 Andrey Kiselev - + * /tools/{raw2tiff.c, Makefile.in, Makefile.lcc, Makefile.vc}: New tool: raw2tiff --- raw images to TIFF converter. No manual page yet. 2002-07-31 Frank Warmerdam - * libtiff/tif_jpeg.c: Fixed problem with setting of nrows in + * libtiff/tif_jpeg.c: Fixed problem with setting of nrows in JPEGDecode() as per bugzilla bug (issue 1): http://bugzilla.remotesensing.org/show_bug.cgi?id=129 * libtiff/{tif_jpeg.c,tif_strip.c,tif_print.c}: Hacked tif_jpeg.c to fetch TIFFTAG_YCBCRSUBSAMPLING from the jpeg data stream if it isn't - present in the tiff tags. + present in the tiff tags. http://bugzilla.remotesensing.org/show_bug.cgi?id=168 * libtiff/tif_read.c, libtiff/tif_write.c: TIFFReadScanline() and TIFFWriteScanline() now set tif_row explicitly in case the codec has - fooled with the value. + fooled with the value. http://bugzilla.remotesensing.org/show_bug.cgi?id=129 2002-06-22 Andrey Kiselev - + * /tools/tiff2ps.c: Added workaround for some software that may crash when last strip of image contains fewer number of scanlines than specified by the `/Height' variable. See @@ -4641,8 +7656,8 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2002-06-11 Frank Warmerdam - * libtiff/contrib/win95: renamed to contrib/win_dib. Added new - Tiffile.cpp example of converting TIFF files into a DIB on Win32. + * libtiff/contrib/win95: renamed to contrib/win_dib. Added new + Tiffile.cpp example of converting TIFF files into a DIB on Win32. This one is described in: http://bugzilla.remotesensing.org/show_bug.cgi?id=143 @@ -4658,21 +7673,21 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic http://bugzilla.remotesensing.org/show_bug.cgi?id=131 2002-04-26 Andrey Kiselev - + * libtiff/libtiff.def: Added missed declaration. - + 2002-04-22 Andrey Kiselev - + * tools/fax2tiff.c: Updated to reflect latest changes in libtiff. Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=125 2002-04-20 Andrey Kiselev - + * libtiff/tif_open.c: Pointers to custom procedures in TIFFClientOpen() are checked to be not NULL-pointers. - + 2002-04-18 Andrey Kiselev - + * libtiff/libtiff.def: Added missed declarations. * libtiff/tif_pixarlog.c: Updated for using tif_tagmethods structure. @@ -4682,14 +7697,14 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_lzw.c: Additional checks for data integrity introduced. Should finally close http://bugzilla.remotesensing.org/show_bug.cgi?id=100 - + 2002-04-10 Andrey Kiselev * tools/tiff2ps: Division by zero fixed. Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=88 2002-04-09 Andrey Kiselev - + * libtiff/: tif_dirwrite.c, tif_write.c, tiffio.h: TIFFCheckpointDirectory() routine added. Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=124 @@ -4721,7 +7736,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic replaced by warnings. Now libtiff should read corrupted LZW-compressed files by skipping bad strips. Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=100 - + 2002-04-03 Frank Warmerdam * libtiff/tif_dirwrite.c: Removed some dead code. @@ -4743,18 +7758,18 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic http://bugzilla.remotesensing.org/show_bug.cgi?id=111 - * tif_print.c: Fixed so that ASCII FIELD_CUSTOM values with + * tif_print.c: Fixed so that ASCII FIELD_CUSTOM values with passcount set FALSE can be printed (such as TIFFTAG_SOFTWARE). - * libtiff/tif_dir.c,tif_dirinfo.c,tif_dir.h,tif_ojpeg.c: modified so + * libtiff/tif_dir.c,tif_dirinfo.c,tif_dir.h,tif_ojpeg.c: modified so that TIFFTAG_SOFTWARE uses FIELD_CUSTOM as an example. 2002-03-26 Dwight Kelly * libtiff/: tiff.h, tif_dir.c, tif_dir.h, tif_dirinfo.c, tif_dirread.c, tif_dirwrite.c: Added get/put code for new tag XMLPACKET as defined - in Adobe XMP Technote. Added missing INKSET tag value from TIFF 6.0 spec - INKSET_MULTIINK (=2). Added missing tags from Adobe TIFF technotes: + in Adobe XMP Technote. Added missing INKSET tag value from TIFF 6.0 spec + INKSET_MULTIINK (=2). Added missing tags from Adobe TIFF technotes: CLIPPATH, XCLIPPATHUNITS, YCLIPPATHUNITS, OPIIMAGEID, OPIPROXY and INDEXED. Added PHOTOMETRIC tag value from TIFF technote 4 ICCLAB (=9). @@ -4813,7 +7828,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic http://bugzilla.remotesensing.org/show_bug.cgi?id=94 - * man/Makefile.in: Patch DESTDIR handling + * man/Makefile.in: Patch DESTDIR handling http://bugzilla.remotesensing.org/show_bug.cgi?id=95 @@ -4851,9 +7866,9 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2002-01-04 Frank Warmerdam - * libtiff/tif_jpeg.c: fixed computation of segment_width for - tiles files to avoid error about it not matching the - cinfo.d.image_width values ("JPEGPreDecode: Improper JPEG strip/tile + * libtiff/tif_jpeg.c: fixed computation of segment_width for + tiles files to avoid error about it not matching the + cinfo.d.image_width values ("JPEGPreDecode: Improper JPEG strip/tile size.") for ITIFF files. Apparently the problem was incorporated since 3.5.5, presumably during the OJPEG/JPEG work recently. @@ -4863,7 +7878,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic http://bugzilla.remotesensing.org/show_bug.cgi?id=94 - * libtiff/tif_getimage.c: If DEFAULT_EXTRASAMPLE_AS_ALPHA is 1 + * libtiff/tif_getimage.c: If DEFAULT_EXTRASAMPLE_AS_ALPHA is 1 (defined in tiffconf.h - 1 by default) then the RGBA interface will assume that a fourth extra sample is ASSOCALPHA if the EXTRASAMPLE value isn't set for it. This changes the behaviour of @@ -4875,9 +7890,9 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2001-12-12 Frank Warmerdam - * libtiff/tif_jpeg.c: allow jpeg data stream sampling values to - override those from tiff directory. This makes this work with - ImageGear generated files. + * libtiff/tif_jpeg.c: allow jpeg data stream sampling values to + override those from tiff directory. This makes this work with + ImageGear generated files. 2001-12-07 Frank Warmerdam @@ -4890,7 +7905,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * Reissue 3.5.7 release. * libtiff/mkversion.c: Fix output of TIFF_VERSION to be - YYYYMMDD so that it is increasing over time. + YYYYMMDD so that it is increasing over time. * Makefile.in: Ensure that tiffvers.h is regenerated in the make release target. @@ -4915,8 +7930,8 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2001-10-10 Frank Warmerdam - * libtiff/tiff.h: I have created COMPRESSION_CCITT_T4, - COMPRESSION_CCITT_T6, TIFFTAG_T4OPTIONS and TIFFTAG_T6OPTIONS aliases + * libtiff/tiff.h: I have created COMPRESSION_CCITT_T4, + COMPRESSION_CCITT_T6, TIFFTAG_T4OPTIONS and TIFFTAG_T6OPTIONS aliases in keeping with TIFF 6.0 standard in tiff.h http://bugzilla.remotesensing.org/show_bug.cgi?id=83 @@ -4936,10 +7951,10 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic error about LZW not being available. * libtiff/tif_dir.c: propagate failure to initialize compression - back from TIFFSetField() as an error status, so applications can + back from TIFFSetField() as an error status, so applications can detect failure. - * libtiff/tif_dir.c: removed the auto replacement of + * libtiff/tif_dir.c: removed the auto replacement of COMPRESSION_LZW with COMPRESSION_NONE in _TIFFVSetField(). * Removed Makefile, tools/Makefile, port/install.sh, man/Makefile @@ -4947,7 +7962,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2001-09-22 Frank Warmerdam - * libtiff/tif_ojpeg.c: new update from Scott. + * libtiff/tif_ojpeg.c: new update from Scott. 2001-09-09 Frank Warmerdam @@ -4966,7 +7981,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic http://bugzilla.remotesensing.org/show_bug.cgi?id=47 - * tools/tiff2ps.c: added OJPEG YCbCr to RGB support. + * tools/tiff2ps.c: added OJPEG YCbCr to RGB support. * libtiff/tif_ojpeg.c: Applied substantial patch from Scott. @@ -4975,14 +7990,14 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_packbits.c: fixed memory overrun error. http://bugzilla.remotesensing.org/show_bug.cgi?id=77 - + 2001-08-31 Frank Warmerdam * libtiff/tif_getimage.c: relax handling of contig case where there are extra samples that are supposed to be ignored. This - should now work for 8bit greyscale or palletted images. + should now work for 8bit greyscale or palletted images. - http://bugzilla.remotesensing.org/show_bug.cgi?id=75 + http://bugzilla.remotesensing.org/show_bug.cgi?id=75 2001-08-28 Frank Warmerdam @@ -4995,15 +8010,15 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_getimage.c: Use memmove() instead of TIFFmemcpy() in TIFFReadRGBATile() to avoid issues in cases of overlapping - buffers. See Bug 69 in Bugzilla. + buffers. See Bug 69 in Bugzilla. http://bugzilla.remotesensing.org/show_bug.cgi?id=69 - + * tools/tiff2rgba.c: fixed getopt() call so that -b works again. 2001-08-09 Frank Warmerdam - * libtiff/tiff.h, libtiff/tif_fax3.c: added check for __LP64__ + * libtiff/tiff.h, libtiff/tif_fax3.c: added check for __LP64__ when checking for 64 bit architectures as per bugzilla bug 67. 2001-07-27 Frank Warmerdam @@ -5013,7 +8028,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2001-07-20 Frank Warmerdam - * libtiff/tif_jpeg.c: Define HAVE_BOOLEAN on windows if RPCNDR.H + * libtiff/tif_jpeg.c: Define HAVE_BOOLEAN on windows if RPCNDR.H has been included. 2001-07-19 Frank Warmerdam @@ -5025,11 +8040,11 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_ojpeg.c: updates from Scott. Handles colors much better. Now depends on having patched libjpeg as per - patch in contrib/ojpeg/*. + patch in contrib/ojpeg/*. 2001-07-17 Frank Warmerdam - * */Makefile.in: added DESTDIR support. + * */Makefile.in: added DESTDIR support. http://bugzilla.remotesensing.org/show_bug.cgi?id=60 @@ -5037,20 +8052,20 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * configure, libtiff/Makefile.in: applied OpenBSD patches as per: - + http://bugzilla.remotesensing.org/show_bug.cgi?id=61 2001-06-28 Frank Warmerdam * libtiff/tif_getimage.c: Fixed so that failure is properly - reported by gtTileContig, gtStripContig, gtTileSeparate and + reported by gtTileContig, gtStripContig, gtTileSeparate and gtStripSeparate. See http://bugzilla.remotesensing.org/show_bug.cgi?id=51 - * tiffcmp.c: Fixed multi samples per pixel support for ContigCompare. + * tiffcmp.c: Fixed multi samples per pixel support for ContigCompare. Updated bug section of tiffcmp.1 to note tiled file issues. - + See http://bugzilla.remotesensing.org/show_bug.cgi?id=53 2001-06-22 Frank Warmerdam @@ -5091,10 +8106,10 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2001-05-08 Frank Warmerdam - * libtiff/tif_dirinfo.c: moved pixar and copyright flags to + * libtiff/tif_dirinfo.c: moved pixar and copyright flags to ensure everything is in order. - * libtiff/libtiff.def: added TIFFCreateDirectory and + * libtiff/libtiff.def: added TIFFCreateDirectory and TIFFDefaultStripSize as per: http://bugzilla.remotesensing.org/show_bug.cgi?id=46 @@ -5103,10 +8118,10 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_dirinfo.c: Modified the TIFF_BYTE definition for TIFFTAG_PHOTOSHOP to use a writecount of TIFF_VARIABLE2 (-3) to - force use of uint32 counts instead of short counts. + force use of uint32 counts instead of short counts. * libtiff/tif_dirwrite.c: Added support for TIFF_VARIABLE2 in the - case of writing TIFF_BYTE/TIFF_SBYTE fields. + case of writing TIFF_BYTE/TIFF_SBYTE fields. http://bugzilla.remotesensing.org/show_bug.cgi?id=43 @@ -5142,20 +8157,20 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic with the inttypes.h include file on AIX. See http://bugzilla.remotesensing.org/show_bug.cgi?id=39 - + * VERSION: update to 3.5.7 beta in preparation for release. * configure/config.site: modified to check if -lm is needed for MACHDEPLIBS if not supplied by config.site. Needed for Darwin. - * config.guess: updated wholesale to an FSF version apparently - from 1998 (as opposed to 1994). This is mainly inspired by + * config.guess: updated wholesale to an FSF version apparently + from 1998 (as opposed to 1994). This is mainly inspired by providing for MacOS X support. 2001-03-29 Frank Warmerdam * configure, Makefile.in, etc: added support for OPTIMIZER being - set from config.site. + set from config.site. 2001-03-28 Frank Warmerdam @@ -5165,7 +8180,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic sizes. It fixes two problems: Without scaling (-S) the fax is now centered on the page size specified - with -H and/or -W. Before, fax2ps was using an obscure and practially + with -H and/or -W. Before, fax2ps was using an obscure and practically useless algorithm to allocate the image relative to Letter sized paper which sometime sled to useless whitespace on the paper, while at the same time cutting of the faxes printable area at the opposite border. @@ -5174,7 +8189,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic (in particular short ones) print properly. See http://bugzilla.remotesensing.org/show_bug.cgi?id=35 - + * tiff2ps.c/tiff2ps.1: Substantial changes to tiff2ps by Bruce A. Mallett. See check message for detailed information on all the changes, including a faster encoder, fixes for level @@ -5182,7 +8197,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2001-03-27 Frank Warmerdam - * libtiff/tiffio.h: Changed "#if LOGLUV_PUBLIC" to + * libtiff/tiffio.h: Changed "#if LOGLUV_PUBLIC" to "#ifdef LOGLUV_PUBLIC" so it will work with VisualAge on AIX. http://bugzilla.remotesensing.org/show_bug.cgi?id=39 @@ -5194,7 +8209,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2001-03-13 Frank Warmerdam - * tif_getimage.c: Added support for 16bit minisblack/miniswhite + * tif_getimage.c: Added support for 16bit minisblack/miniswhite images in RGBA interface. 2001-03-02 Frank Warmerdam @@ -5205,29 +8220,29 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * Brent Roman contributed updated tiffcp utility (and tiffcp.1) with support for extracting subimages with the ,n syntax, and also - adding the -b bias removal flag. + adding the -b bias removal flag. 2001-02-16 Frank Warmerdam * libtiff/libtiff.def: Brent Roman submitted new version adding - serveral missing entry points. + serveral missing entry points. * libtiff/tif_dirinfo.c: don't declare tiffFieldInfo static on VMS. - Some sort of weird VMS thing. + Some sort of weird VMS thing. http://bugzilla.remotesensing.org/show_bug.cgi?id=31 - * tif_luv.c/tiff.h/tiffio.h: - New version of TIFF LogLuv (SGILOG) modules contributed by Greg Ward + * tif_luv.c/tiff.h/tiffio.h: + New version of TIFF LogLuv (SGILOG) modules contributed by Greg Ward (greg@shutterfly.com). He writes: 1) I improved the gamut-mapping function in tif_luv.c for imaginary - colors, because some images were being super-saturated on the input + colors, because some images were being super-saturated on the input side and this resulted in some strange color shifts in the output. 2) I added a psuedotag in tiff.h to control random dithering during - LogLuv encoding. This is turned off by default for 32-bit LogLuv and - on for 24-bit LogLuv output. Dithering improves the average color + LogLuv encoding. This is turned off by default for 32-bit LogLuv and + on for 24-bit LogLuv output. Dithering improves the average color accuracy over the image. 3) I added a #define for LOG_LUV_PUBLIC, which is enabled by default in @@ -5240,20 +8255,20 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2001-01-23 Frank Warmerdam * tif_fax3.c: keep rw_mode flag internal to fax3 state to remember - whether we are encoding or decoding. This is to ensure graceful + whether we are encoding or decoding. This is to ensure graceful recovery if TIFFClientOpen() discovers an attempt to open a compressed - file for "r+" access, and subsequently close it, as it resets the + file for "r+" access, and subsequently close it, as it resets the tif_mode flag to O_RDONLY in this case to avoid writes, confusing the compressor's concept of whether it is in encode or decode mode. -2001-01-08 Mike Welles +2001-01-08 Mike Welles * Makefile.in: Now cleaning up after itself after creating the .tar.gz and .zip - + 2001-01-07 Frank Warmerdam * html/libtiff.html: Fixed arguments in example for TIFFRGBAImageGet() - as per bug report by Patrick Connor. + as per bug report by Patrick Connor. 2000-12-28 Frank Warmerdam @@ -5261,12 +8276,12 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * Fixed libtiff/makefile.vc to make tiffvers.h not version.h. -2000-12-22 Mike Welles +2000-12-22 Mike Welles * added link to CVS mirror from index.html - - * updated html/internals.html to note that LZW compression is - not supported by default. - + + * updated html/internals.html to note that LZW compression is + not supported by default. + 2000-12-22 Frank Warmerdam * updated html/libtiff.html to not point at Niles' old JPL web site @@ -5278,19 +8293,19 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic Leonard Rosenthol . May interfere with correct building on older systems. If so, please let me know. -2000-12-19 Mike Welles +2000-12-19 Mike Welles - * Took out LZW Encoding from tif_lzw.c + * Took out LZW Encoding from tif_lzw.c * Created HOWTO-RELEASE * Created html/v3.5.6.html * updated index.html - + 2000-12-01 Frank Warmerdam - * Added patches for EOFB support in tif_fax3.c and tif_fax3.h. + * Added patches for EOFB support in tif_fax3.c and tif_fax3.h. Patches supplied by Frank Cringle Example file at: ftp://ftp.remotesensing.org/pub/libtiff/eofb_396.tif @@ -5304,30 +8319,30 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic targets so libtiff.so will be built with an explicit dependency on libm.so. - * libtiff/Makefile.in: Use softlinks to link libtiff.so.3 to - libtiff.so.3.5.5. + * libtiff/Makefile.in: Use softlinks to link libtiff.so.3 to + libtiff.so.3.5.5. - * libtiff/Makefile.in & configure: Remove all references to the ALPHA - file, or ALPHA version logic. Added stuff about DIST_POINT in + * libtiff/Makefile.in & configure: Remove all references to the ALPHA + file, or ALPHA version logic. Added stuff about DIST_POINT in place of DIST_TYPE and the alpha release number stuff. 2000-11-22 Frank Warmerdam * I have applied a patch from Steffen Moeller to - the configure script so that it now accepts the --prefix, and - --exec-prefix directives. + the configure script so that it now accepts the --prefix, and + --exec-prefix directives. 2000-11-13 Frank Warmerdam - * I have made a variety of modifications in an effort to ensure the + * I have made a variety of modifications in an effort to ensure the TIFFLIB_VERSION macro is automatically generated from the RELEASE-DATE - file which seems to be updated regularly. + file which seems to be updated regularly. - o mkversion.c now reads RELEASE-DATE and emits TIFFLIB_VERSION in - version include file. - o renamed version.h to tiffvers.h because we now have to install it - with the public libtiff include files. - o include tiffvers.h in tiffio.h. + o mkversion.c now reads RELEASE-DATE and emits TIFFLIB_VERSION in + version include file. + o renamed version.h to tiffvers.h because we now have to install it + with the public libtiff include files. + o include tiffvers.h in tiffio.h. o updated tif_version.c to use tiffvers.h. o Updated Makefile.in accordingly. @@ -5341,13 +8356,13 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic See http://bugzilla.remotesensing.org/show_bug.cgi?id=20 Some patches from Rick LaMont of Dot C Software. - * Modified tif_packbits.c encoder to avoid compressing more + * Modified tif_packbits.c encoder to avoid compressing more data than provided if rowsize doesn't factor into provided data (such as occurs for YCbCr). 2000-10-19 Frank Warmerdam - * tools/rgb2ycbcr.c: fixed output strip size to account for vertical + * tools/rgb2ycbcr.c: fixed output strip size to account for vertical roundup if rows_per_strip not a multiple of vertical sample size. 2000-10-16 Frank Warmerdam @@ -5363,8 +8378,8 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2000-10-12 Frank Warmerdam * Modified tiff2bw to ensure portions add to 100%, and that - white is properly recovered. - + white is properly recovered. + See bug http://bugzilla.remotesensing.org/show_bug.cgi?id=15 Patch c/o Stanislav Brabec @@ -5378,26 +8393,26 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic 2000-09-27 Frank Warmerdam - * Added GNULDdso target an`d switched linux and freebsd to use it. + * Added GNULDdso target an`d switched linux and freebsd to use it. 2000-09-26 Frank Warmerdam * Applied patch for 0x0000 sequences in tif_fax3.h's definition - of EXPAND1D() as per bug 11 (from Roman). + of EXPAND1D() as per bug 11 (from Roman). 2000-09-25 Frank Warmerdam * Fixed tiffcomp.h to avoid win32 stuff if unix #defined, to improve cygwin compatibility. * Applied patch from Roman Shpount to tif_fax3.c. This seems to - be a proper fix to the buffer sizing problem. See + be a proper fix to the buffer sizing problem. See http://bugzilla.remotesensing.org/show_bug.cgi?id=11 * Fixed tif_getimage.c to fix overrun bug with YCbCr images without downsampling. http://bugzilla.remotesensing.org/show_bug.cgi?id=10 Thanks to Nick Lamb for reporting the bug and proving the patch. - + 2000-09-18 Frank Warmerdam * Fixed tif_jpeg.c so avoid destroying the decompressor before @@ -5427,15 +8442,15 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * Tentatively added support for SAMPLEFORMAT_COMPLEXIEEEFP, and SAMPLEFORMAT_COMPLEXINT. -2000-07-13 Mike Welles +2000-07-13 Mike Welles + + * index.html, bugs.html: added bugzilla info. - * index.html, bugs.html: added bugzilla info. - 2000-07-12 Frank Warmerdam * tif_read.c: fix subtle bug with determining the number of rows for strips that are the last strip in a separation but - not the last strip of all in TIFFReadEncodedStrip(). + not the last strip of all in TIFFReadEncodedStrip(). * Applied 16/32 bit fix to tif_fax3.c. Fix supplied by Peter Skarpetis @@ -5457,7 +8472,7 @@ btiff/tif_win32.c: Replace custom Win32 memory api with generic * libtiff/tif_dirread.c: Don't use estimate strip byte count for one tile/strip images with an offset, and byte count of zero. These - could be "unpopulated" images. + could be "unpopulated" images. 2000-04-18 Frank Warmerdam @@ -5472,17 +8487,17 @@ Tue Apr 18 16:18:08 2000 Frank Warmerdam 2000-04-12 Mike Welles * configure: Fixed stupid mistake in libc6 test on Linux -2000-04-04 Mike Welles +2000-04-04 Mike Welles * tif_win32.c: Applied patch to fix overreads and ovverwrites - caught by BoundsChecker. From Arvan Pritchard - (untested). - - * tif_getimage.c: Applied patch to silence VC6 warnings. From + caught by BoundsChecker. From Arvan Pritchard + (untested). + + * tif_getimage.c: Applied patch to silence VC6 warnings. From Arvan Pritchard - - * tif_lzw.c: Applied patch to silence VC6 warnings. From + + * tif_lzw.c: Applied patch to silence VC6 warnings. From Arvan Pritchard - + 2000-03-28 Frank Warmerdam * Added contrib/stream (stream io) code submitted by Avi Bleiweiss. @@ -5492,34 +8507,34 @@ Tue Apr 18 16:18:08 2000 Frank Warmerdam * fax2ps: Fixed mixup of width and height in bounding box statement as per submission by Nalin Dahyabhai . -2000-03-27 Mike Welles +2000-03-27 Mike Welles - * fax2ps: Modified printruns to take uint32 instead of uint16. - Patch courtesy of Bernt Herd - -2000-03-20 Mike Welles + * fax2ps: Modified printruns to take uint32 instead of uint16. + Patch courtesy of Bernt Herd + +2000-03-20 Mike Welles - * configure: added test for libc6 for linux targets. Bug reported by + * configure: added test for libc6 for linux targets. Bug reported by Stanislav Brabec - * Added 3.5 docs to html/Makefile.in. + * Added 3.5 docs to html/Makefile.in. Thanks to Stanislav Brabec - * configure: fixed bugs in sed scripts - (applied sed script s:/@:s;@:;s:/s;;:;: to configure). + * configure: fixed bugs in sed scripts + (applied sed script s:/@:s;@:;s:/s;;:;: to configure). fix submitted to Stanislav Brabec - * tools/iptcutil was not in files list, and wasn't being + * tools/iptcutil was not in files list, and wasn't being added to tar archive. Updated Makefile.in. 2000-03-17 Frank Warmerdam * tif_fax3.c: Fixed serious bug introduced during the uint16->uint32 - conversion for the run arrays. + conversion for the run arrays. 2000-03-03 Frank Warmerdam - * Set td_sampleformat default to SAMPLEFORMAT_UINT instead of + * Set td_sampleformat default to SAMPLEFORMAT_UINT instead of SAMPLEFORMAT_VOID in TIFFDefaultDirectory() in tif_dir.c. 2000-03-02 Frank Warmerdam @@ -5540,20 +8555,20 @@ Tue Feb 15 22:01:05 2000 Frank Warmerdam set to 1, and added default (off) setting in tiffconf.h. This should eventually be set by the configure script somehow. - The original work on all these 2-4GB changes was done by + The original work on all these 2-4GB changes was done by Peter Smith (psmith@creo.com). * Modified tif_win32.c to support 2-4GB seeks. * tentatively changed toff_t to be unsigned instead of signed to - facilitate support for 2-4GB files. + facilitate support for 2-4GB files. * Updated a variety of files to use toff_t. Fixed some mixups between toff_t and tsize_t. Fri Jan 28 10:13:49 2000 Frank Warmerdam - * Largely reimplemented contrib/addtiffo to avoid temp files, + * Largely reimplemented contrib/addtiffo to avoid temp files, updating the TIFF file in place. Fixed a few other bugs to. * Set tif_rawdatasize to zero when freeing raw data buffer in @@ -5562,7 +8577,7 @@ Fri Jan 28 10:13:49 2000 Frank Warmerdam * Enabled "REWRITE_HACK" in tif_write.c by default. * Fix bug in tif_write.c when switching between reading one directory - and writing to another. + and writing to another. * Made TIFFWriteCheck() public, and added TIFFCreateDirectory() @@ -5574,41 +8589,41 @@ Tue Jan 4 13:39:00 2000 Frank Warmerdam * Added libtiff/libtiff.def to TIFFILES distribution list. -Mon Dec 27 12:13:39 EST 1999 Mike Welles +Mon Dec 27 12:13:39 EST 1999 Mike Welles - * Created lzw compression kit, as a new module (libtiff-lzw-compression-kit). + * Created lzw compression kit, as a new module (libtiff-lzw-compression-kit). * Altered descriptions in tools to reflect "by default" lzw not supported - * Updated index.html to note lzw compression kit. - + * Updated index.html to note lzw compression kit. + Tue Dec 21 14:01:51 1999 Frank Warmerdam - * Added fax3sm_winnt.c to distribution list in Makefile.in. + * Added fax3sm_winnt.c to distribution list in Makefile.in. Tue Dec 21 11:04:45 EST 1999 Mike Welles *** 3.5.4 release *** - - * Aadded Pixar tag support. Contributed by Phil Beffery - * Made one more change to tif_dir.c for removal of LZW compression. Also added notice - when LZW compression invoked. + * Aadded Pixar tag support. Contributed by Phil Beffery + + * Made one more change to tif_dir.c for removal of LZW compression. Also added notice + when LZW compression invoked. * Changed default compression in tools to TIFF_PACKBITS, and changed usage descriptions in tools to reflect removal of LZW compression - + Mon Dec 20 18:39:02 EST 1999 Mike Welles - * Fixed bug that caused LZW (non) compression to segfault. Added - warning about LZW compression removed being removed, and why. + * Fixed bug that caused LZW (non) compression to segfault. Added + warning about LZW compression removed being removed, and why. + + * Added nostrip to install in tools/Makefile.in so that debugging + symbols are kept. - * Added nostrip to install in tools/Makefile.in so that debugging - symbols are kept. - Tue Dec 7 12:04:47 EST 1999 Mike Welles - * Added patch from Ivo Penzar , - supporting Adobe ZIP deflate. Untested. - + * Added patch from Ivo Penzar , + supporting Adobe ZIP deflate. Untested. + Sat Dec 4 15:47:11 1999 Frank Warmerdam * Made Packbits the default compression in tools/tiff2rgba.c instead @@ -5618,12 +8633,12 @@ Tue Nov 30 14:41:43 1999 Frank Warmerdam *** 3.5 * Added tif_luv to contrib/djgpp/Makefile.lib. -Tue Nov 30 14:15:32 EST 1999 Mike Welles +Tue Nov 30 14:15:32 EST 1999 Mike Welles - * Added zip creation to relase makefile target + * Added zip creation to relase makefile target + + * Added html for TIFFWriteTile.3t man page. - * Added html for TIFFWriteTile.3t man page. - Tue Nov 30 09:20:16 1999 Frank Warmerdam * Added some changes to tif_write.c to support rewriting existing @@ -5636,26 +8651,26 @@ Mon Nov 29 11:43:42 1999 Frank Warmerdam Sun Nov 28 20:36:18 1999 Frank Warmerdam - * Added notes on use of makefile.vc in build.html, and fixed + * Added notes on use of makefile.vc in build.html, and fixed email subscription address. -199-11-28 Mike Welles +199-11-28 Mike Welles - * Fixed apocalypse-inducing y2k bug in contrib/ras/ras2tiff.c + * Fixed apocalypse-inducing y2k bug in contrib/ras/ras2tiff.c * Did some casts cleaning up to reduce compiler warnings in tif_fax3.c, - from Bruce Carmeron -- modifications of - changes made by Frank (sun cc still complained on cast). + from Bruce Carmeron -- modifications of + changes made by Frank (sun cc still complained on cast). * Added tiffconf.h to install target per request from Bill Radcliffe : "We need a way for ImageMagick to know features have been compiled into the TIFF library in order to - handle things properly". - + handle things properly". + Sat Nov 27 16:49:21 1999 Frank Warmerdam * fixed various VC++ warnings as suggested by Gilles Vollant - . + . Wed Nov 24 12:08:16 1999 Frank Warmerdam @@ -5664,59 +8679,59 @@ Wed Nov 24 12:08:16 1999 Frank Warmerdam 1999-11-22 Mike Welles * HTML-ized the man pages, added to html/man - - * Removed LZW Compression to comply with Unisys patent extortion. - -1999-09-29 Mike Welles - * Corrected one remaining 16 -> 32 bit value in tif_fax3.c, - From Ivo Penzar + * Corrected one remaining 16 -> 32 bit value in tif_fax3.c, + From Ivo Penzar - + 1999-09-26 Mike Welles *** 3.5.2 release *** - * Corrected alpha versioning. + * Corrected alpha versioning. - * Removed distinction between alpha and release targets in Makefile.in. + * Removed distinction between alpha and release targets in Makefile.in. - * added release.stamp target, which tags cvs tree, and updates + * added release.stamp target, which tags cvs tree, and updates "RELEASE-DATE" - * added releasediff target, which diffs tree with source as of + * added releasediff target, which diffs tree with source as of date in "RELEASE-DATE" - - * Ticked up version to 3.5.2 (alpha 01 -- but I think we'll moving - away from alpha/non-alpha distinctions). - * updated html to reflect release - + * Ticked up version to 3.5.2 (alpha 01 -- but I think we'll moving + away from alpha/non-alpha distinctions). + + * updated html to reflect release + 1999-09-23 * Set O_BINARY for tif_unix.c open() ... used on cygwin for instance. * Added CYGWIN case in configure. -Fri Sep 17 00:13:51 CEST 1999 Mike Welles +Fri Sep 17 00:13:51 CEST 1999 Mike Welles + + * Applied Francois Dagand's patch to handle fax decompression bug. + (sizes >= 65536 were failing) - * Applied Francois Dagand's patch to handle fax decompression bug. - (sizes >= 65536 were failing) - Tue Sep 14 21:31:43 1999 Frank Warmerdam - * Applied "a" mode fix to tif_win32.c/TIFFOpen() as suggested + * Applied "a" mode fix to tif_win32.c/TIFFOpen() as suggested by Christopher Lawton Wed Sep 8 08:19:18 1999 Frank Warmerdam - * Added IRIX/gcc, and OSF/1 4.x support on behalf of + * Added IRIX/gcc, and OSF/1 4.x support on behalf of Albert Chin-A-Young - * Added TIFFReassignTagToIgnore() API on behalf of + * Added TIFFReassignTagToIgnore() API on behalf of Bruce Cameron . Man page still pending. Wed Aug 25 11:39:07 1999 Frank Warmerdam - * Added test target in Makefile, test_pics.sh script and pics/*.rpt + * Added test target in Makefile, test_pics.sh script and pics/*.rpt files to provide for a rudimentary testsuite. * Added contrib/tags back from old distribution ... fixed up a bit. @@ -5724,7 +8739,7 @@ Wed Aug 25 11:39:07 1999 Frank Warmerdam 1999-08-16 * Added simple makefile.vc makefiles for building with MS VC++ - on Windows NT/98/95 in console mode. Stuff in contrib/win* make give + on Windows NT/98/95 in console mode. Stuff in contrib/win* make give better solutions for some users. Mon Aug 16 21:52:11 1999 Frank Warmerdam @@ -5734,20 +8749,20 @@ Mon Aug 16 21:52:11 1999 Frank Warmerdam 1999-08-16 Michael L. Welles - * Updated html/index.html with anon CVS instructions. + * Updated html/index.html with anon CVS instructions. Mon Aug 16 13:18:41 1999 Frank Warmerdam - * pre-remove so link before softlink in LINUXdso action in + * pre-remove so link before softlink in LINUXdso action in libtiff/Makefile.in to avoid failure on LINUXdso builds other than the first. * Fixed problem with cvtcmap() in tif_getimage.c modifying the colormaps owned by the TIFF handle itself when trying to fixup wrong (eight bit) colormaps. Corrected by maintaining a private copy of - the colormap. + the colormap. - * Added TIFFReadRGBATile()/TIFFReadRGBAStrip() support in + * Added TIFFReadRGBATile()/TIFFReadRGBAStrip() support in tif_getimage.c. * CVS Repository placed at remotesensing.org. ChangeLog added. diff --git a/3rdparty/libtiff/libport.h b/3rdparty/libtiff/libport.h new file mode 100644 index 0000000000..ff26263829 --- /dev/null +++ b/3rdparty/libtiff/libport.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2009 Frank Warmerdam + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _LIBPORT_ +#define _LIBPORT_ + +int getopt(int argc, char * const argv[], const char *optstring); +extern char *optarg; +extern int opterr; +extern int optind; +extern int optopt; + +int strcasecmp(const char *s1, const char *s2); + +#ifndef HAVE_GETOPT +# define HAVE_GETOPT 1 +#endif + +#if HAVE_STRTOL +long strtol(const char *nptr, char **endptr, int base); +#endif +#if HAVE_STRTOLL +long long strtoll(const char *nptr, char **endptr, int base); +#endif +#if HAVE_STRTOUL +unsigned long strtoul(const char *nptr, char **endptr, int base); +#endif +#if HAVE_STRTOULL +unsigned long long strtoull(const char *nptr, char **endptr, int base); +#endif + +#if 0 +void * +lfind(const void *key, const void *base, size_t *nmemb, size_t size, + int(*compar)(const void *, const void *)); +#endif + +#if !defined(HAVE_SNPRINTF) +#undef vsnprintf +#define vsnprintf _TIFF_vsnprintf_f + +#undef snprintf +#define snprintf _TIFF_snprintf_f +int snprintf(char* str, size_t size, const char* format, ...); +#endif + +#endif /* ndef _LIBPORT_ */ diff --git a/3rdparty/libtiff/snprintf.c b/3rdparty/libtiff/snprintf.c index c46a6a8ba4..1c4ac08786 100644 --- a/3rdparty/libtiff/snprintf.c +++ b/3rdparty/libtiff/snprintf.c @@ -9,6 +9,7 @@ #include #include +#include "libport.h" int _TIFF_vsnprintf_f(char* str, size_t size, const char* format, va_list ap) { @@ -35,4 +36,3 @@ int _TIFF_snprintf_f(char* str, size_t size, const char* format, ...) } #endif // _MSC_VER - diff --git a/3rdparty/libtiff/t4.h b/3rdparty/libtiff/t4.h index b908f54f09..fb0951a16f 100644 --- a/3rdparty/libtiff/t4.h +++ b/3rdparty/libtiff/t4.h @@ -1,5 +1,3 @@ -/* $Id: t4.h,v 1.3 2010-03-10 18:56:48 bfriesen Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_aux.c b/3rdparty/libtiff/tif_aux.c index 10b8d00c25..4ece162faa 100644 --- a/3rdparty/libtiff/tif_aux.c +++ b/3rdparty/libtiff/tif_aux.c @@ -1,5 +1,3 @@ -/* $Id: tif_aux.c,v 1.31 2017-11-17 20:21:00 erouault Exp $ */ - /* * Copyright (c) 1991-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_close.c b/3rdparty/libtiff/tif_close.c index a0cb661311..e4228df9c9 100644 --- a/3rdparty/libtiff/tif_close.c +++ b/3rdparty/libtiff/tif_close.c @@ -1,5 +1,3 @@ -/* $Id: tif_close.c,v 1.21 2016-01-23 21:20:34 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_codec.c b/3rdparty/libtiff/tif_codec.c index 7cb46f6304..b6c04f01d7 100644 --- a/3rdparty/libtiff/tif_codec.c +++ b/3rdparty/libtiff/tif_codec.c @@ -1,5 +1,3 @@ -/* $Id: tif_codec.c,v 1.17 2015-08-19 02:31:04 bfriesen Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -72,6 +70,12 @@ static int NotConfigured(TIFF*, int); #ifndef LZMA_SUPPORT #define TIFFInitLZMA NotConfigured #endif +#ifndef ZSTD_SUPPORT +#define TIFFInitZSTD NotConfigured +#endif +#ifndef WEBP_SUPPORT +#define TIFFInitWebP NotConfigured +#endif /* * Compression schemes statically built into the library. @@ -99,6 +103,8 @@ TIFFCodec _TIFFBuiltinCODECS[] = { { "SGILog", COMPRESSION_SGILOG, TIFFInitSGILog }, { "SGILog24", COMPRESSION_SGILOG24, TIFFInitSGILog }, { "LZMA", COMPRESSION_LZMA, TIFFInitLZMA }, + { "ZSTD", COMPRESSION_ZSTD, TIFFInitZSTD }, + { "WEBP", COMPRESSION_WEBP, TIFFInitWebP }, { NULL, 0, NULL } }; diff --git a/3rdparty/libtiff/tif_color.c b/3rdparty/libtiff/tif_color.c index 71cafcde6c..8fae40ea4b 100644 --- a/3rdparty/libtiff/tif_color.c +++ b/3rdparty/libtiff/tif_color.c @@ -1,5 +1,3 @@ -/* $Id: tif_color.c,v 1.24 2017-05-29 10:12:54 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -168,7 +166,7 @@ TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab, } /* - * Convert color value from the YCbCr space to CIE XYZ. + * Convert color value from the YCbCr space to RGB. * The colorspace conversion algorithm comes from the IJG v5a code; * see below for more information on how it works. */ diff --git a/3rdparty/libtiff/tif_compress.c b/3rdparty/libtiff/tif_compress.c index b571d19545..8130ef08ef 100644 --- a/3rdparty/libtiff/tif_compress.c +++ b/3rdparty/libtiff/tif_compress.c @@ -1,5 +1,3 @@ -/* $Id: tif_compress.c,v 1.25 2016-10-25 20:04:22 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_config.h.cmake.in b/3rdparty/libtiff/tif_config.h.cmake.in index 492636ec92..2414460338 100644 --- a/3rdparty/libtiff/tif_config.h.cmake.in +++ b/3rdparty/libtiff/tif_config.h.cmake.in @@ -26,9 +26,6 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_FCNTL_H 1 -/* Define to 1 if you have the `floor' function. */ -#cmakedefine HAVE_FLOOR 1 - /* Define to 1 if you have the `getopt' function. */ #cmakedefine HAVE_GETOPT 1 @@ -50,30 +47,12 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_IO_H 1 -/* Define to 1 if you have the `isascii' function. */ -#cmakedefine HAVE_ISASCII 1 - /* Define to 1 if you have the `jbg_newlen' function. */ #cmakedefine HAVE_JBG_NEWLEN 1 /* Define to 1 if you have the `lfind' function. */ #cmakedefine HAVE_LFIND 1 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_LIMITS_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_MALLOC_H 1 - -/* Define to 1 if you have the `memmove' function. */ -#cmakedefine HAVE_MEMMOVE 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `memset' function. */ -#cmakedefine HAVE_MEMSET 1 - /* Define to 1 if you have the `mmap' function. */ #cmakedefine HAVE_MMAP 1 @@ -83,9 +62,6 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_OPENGL_GL_H 1 -/* Define to 1 if you have the `pow' function. */ -#cmakedefine HAVE_POW 1 - /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SEARCH_H 1 @@ -95,33 +71,24 @@ /* Define to 1 if you have the `snprintf' function. */ #cmakedefine HAVE_SNPRINTF 1 -/* Define to 1 if you have the `sqrt' function. */ -#cmakedefine HAVE_SQRT 1 - /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDINT_H 1 /* Define to 1 if you have the `strcasecmp' function. */ #cmakedefine HAVE_STRCASECMP 1 -/* Define to 1 if you have the `strchr' function. */ -#cmakedefine HAVE_STRCHR 1 - /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STRING_H 1 -/* Define to 1 if you have the `strrchr' function. */ -#cmakedefine HAVE_STRRCHR 1 - -/* Define to 1 if you have the `strstr' function. */ -#cmakedefine HAVE_STRSTR 1 - /* Define to 1 if you have the `strtol' function. */ #cmakedefine HAVE_STRTOL 1 +/* Define to 1 if you have the `strtoll' function. */ +#cmakedefine HAVE_STRTOLL 1 + /* Define to 1 if you have the `strtoul' function. */ #cmakedefine HAVE_STRTOUL 1 @@ -146,6 +113,12 @@ /* Support LZMA2 compression */ #cmakedefine LZMA_SUPPORT 1 +/* Support ZSTD compression */ +#cmakedefine ZSTD_SUPPORT 1 + +/* Support WEBP compression */ +#cmakedefine WEBP_SUPPORT 1 + /* Name of package */ #define PACKAGE "@PACKAGE_NAME@" @@ -176,9 +149,6 @@ /* The size of `signed long long', as computed by sizeof. */ #define SIZEOF_SIGNED_LONG_LONG @SIZEOF_SIGNED_LONG_LONG@ -/* The size of `signed short', as computed by sizeof. */ -#define SIZEOF_SIGNED_SHORT @SIZEOF_SIGNED_SHORT@ - /* The size of `unsigned char *', as computed by sizeof. */ #define SIZEOF_UNSIGNED_CHAR_P @SIZEOF_UNSIGNED_CHAR_P@ @@ -245,6 +215,9 @@ # endif #endif +/* Number of bits in a file offset, on hosts where this is settable. */ +#define _FILE_OFFSET_BITS @FILE_OFFSET_BITS@ + /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus diff --git a/3rdparty/libtiff/tif_dir.c b/3rdparty/libtiff/tif_dir.c index f00f8080a2..6f0b48798b 100644 --- a/3rdparty/libtiff/tif_dir.c +++ b/3rdparty/libtiff/tif_dir.c @@ -1,5 +1,3 @@ -/* $Id: tif_dir.c,v 1.131 2017-07-11 21:38:04 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -863,14 +861,24 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY); if( fip == NULL ) /* cannot happen since TIFFGetField() already checks it */ return 0; + + /* + * We want to force the custom code to be used for custom + * fields even if the tag happens to match a well known + * one - important for reinterpreted handling of standard + * tag values in custom directories (i.e. EXIF) + */ + if (fip->field_bit == FIELD_CUSTOM) { + standard_tag = 0; + } - if( tag == TIFFTAG_NUMBEROFINKS ) + if( standard_tag == TIFFTAG_NUMBEROFINKS ) { int i; for (i = 0; i < td->td_customValueCount; i++) { uint16 val; TIFFTagValue *tv = td->td_customValues + i; - if (tv->info->field_tag != tag) + if (tv->info->field_tag != standard_tag) continue; if( tv->value == NULL ) return 0; @@ -892,16 +900,6 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) return 0; } - /* - * We want to force the custom code to be used for custom - * fields even if the tag happens to match a well known - * one - important for reinterpreted handling of standard - * tag values in custom directories (i.e. EXIF) - */ - if (fip->field_bit == FIELD_CUSTOM) { - standard_tag = 0; - } - switch (standard_tag) { case TIFFTAG_SUBFILETYPE: *va_arg(ap, uint32*) = td->td_subfiletype; @@ -1067,6 +1065,9 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) if (td->td_samplesperpixel - td->td_extrasamples > 1) { *va_arg(ap, uint16**) = td->td_transferfunction[1]; *va_arg(ap, uint16**) = td->td_transferfunction[2]; + } else { + *va_arg(ap, uint16**) = NULL; + *va_arg(ap, uint16**) = NULL; } break; case TIFFTAG_REFERENCEBLACKWHITE: diff --git a/3rdparty/libtiff/tif_dir.h b/3rdparty/libtiff/tif_dir.h index 5a38076733..b2f5e69488 100644 --- a/3rdparty/libtiff/tif_dir.h +++ b/3rdparty/libtiff/tif_dir.h @@ -1,5 +1,3 @@ -/* $Id: tif_dir.h,v 1.55 2017-06-01 12:44:04 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -26,6 +24,10 @@ #ifndef _TIFFDIR_ #define _TIFFDIR_ + +#include "tiff.h" +#include "tiffio.h" + /* * ``Library-private'' Directory-related Definitions. */ diff --git a/3rdparty/libtiff/tif_dirinfo.c b/3rdparty/libtiff/tif_dirinfo.c index 4904f540e5..e1f6b23e9a 100644 --- a/3rdparty/libtiff/tif_dirinfo.c +++ b/3rdparty/libtiff/tif_dirinfo.c @@ -1,5 +1,3 @@ -/* $Id: tif_dirinfo.c,v 1.127 2017-06-01 12:44:04 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -979,6 +977,8 @@ _TIFFCheckFieldIsValidForCodec(TIFF *tif, ttag_t tag) case TIFFTAG_CONSECUTIVEBADFAXLINES: case TIFFTAG_GROUP3OPTIONS: case TIFFTAG_GROUP4OPTIONS: + /* LERC */ + case TIFFTAG_LERC_PARAMETERS: break; default: return 1; @@ -1054,7 +1054,18 @@ _TIFFCheckFieldIsValidForCodec(TIFF *tif, ttag_t tag) if (tag == TIFFTAG_PREDICTOR) return 1; break; - + case COMPRESSION_ZSTD: + if (tag == TIFFTAG_PREDICTOR) + return 1; + break; + case COMPRESSION_LERC: + if (tag == TIFFTAG_LERC_PARAMETERS) + return 1; + break; + case COMPRESSION_WEBP: + if (tag == TIFFTAG_PREDICTOR) + return 1; + break; } return 0; } diff --git a/3rdparty/libtiff/tif_dirread.c b/3rdparty/libtiff/tif_dirread.c index 5e62e81315..e80a3b13e8 100644 --- a/3rdparty/libtiff/tif_dirread.c +++ b/3rdparty/libtiff/tif_dirread.c @@ -1,5 +1,3 @@ -/* $Id: tif_dirread.c,v 1.218 2017-09-09 21:44:42 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -167,6 +165,7 @@ static int TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uin static int TIFFFetchSubjectDistance(TIFF*, TIFFDirEntry*); static void ChopUpSingleUncompressedStrip(TIFF*); static uint64 TIFFReadUInt64(const uint8 *value); +static int _TIFFGetMaxColorChannels(uint16 photometric); static int _TIFFFillStrilesInternal( TIFF *tif, int loadStripByteCount ); @@ -776,7 +775,7 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8(TIFF* tif, TIFFDirEntry* di static enum TIFFReadDirEntryErr TIFFReadDirEntryDataAndRealloc( TIFF* tif, uint64 offset, tmsize_t size, void** pdest) { -#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8 +#if SIZEOF_SIZE_T == 8 tmsize_t threshold = INITIAL_THRESHOLD; #endif tmsize_t already_read = 0; @@ -797,7 +796,7 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryDataAndRealloc( void* new_dest; tmsize_t bytes_read; tmsize_t to_read = size - already_read; -#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8 +#if SIZEOF_SIZE_T == 8 if( to_read >= threshold && threshold < MAX_THRESHOLD ) { to_read = threshold; @@ -3506,6 +3505,35 @@ static void TIFFReadDirEntryOutputErr(TIFF* tif, enum TIFFReadDirEntryErr err, c } } +/* + * Return the maximum number of color channels specified for a given photometric + * type. 0 is returned if photometric type isn't supported or no default value + * is defined by the specification. + */ +static int _TIFFGetMaxColorChannels( uint16 photometric ) +{ + switch (photometric) { + case PHOTOMETRIC_PALETTE: + case PHOTOMETRIC_MINISWHITE: + case PHOTOMETRIC_MINISBLACK: + return 1; + case PHOTOMETRIC_YCBCR: + case PHOTOMETRIC_RGB: + case PHOTOMETRIC_CIELAB: + case PHOTOMETRIC_LOGLUV: + case PHOTOMETRIC_ITULAB: + case PHOTOMETRIC_ICCLAB: + return 3; + case PHOTOMETRIC_SEPARATED: + case PHOTOMETRIC_MASK: + return 4; + case PHOTOMETRIC_LOGL: + case PHOTOMETRIC_CFA: + default: + return 0; + } +} + /* * Read the next TIFF directory from a file and convert it to the internal * format. We read directories sequentially. @@ -3522,6 +3550,7 @@ TIFFReadDirectory(TIFF* tif) uint32 fii=FAILED_FII; toff_t nextdiroff; int bitspersample_read = FALSE; + int color_channels; tif->tif_diroff=tif->tif_nextdiroff; if (!TIFFCheckDirOffset(tif,tif->tif_nextdiroff)) @@ -4026,6 +4055,37 @@ TIFFReadDirectory(TIFF* tif) } } } + + /* + * Make sure all non-color channels are extrasamples. + * If it's not the case, define them as such. + */ + color_channels = _TIFFGetMaxColorChannels(tif->tif_dir.td_photometric); + if (color_channels && tif->tif_dir.td_samplesperpixel - tif->tif_dir.td_extrasamples > color_channels) { + uint16 old_extrasamples; + uint16 *new_sampleinfo; + + TIFFWarningExt(tif->tif_clientdata,module, "Sum of Photometric type-related " + "color channels and ExtraSamples doesn't match SamplesPerPixel. " + "Defining non-color channels as ExtraSamples."); + + old_extrasamples = tif->tif_dir.td_extrasamples; + tif->tif_dir.td_extrasamples = (uint16) (tif->tif_dir.td_samplesperpixel - color_channels); + + // sampleinfo should contain information relative to these new extra samples + new_sampleinfo = (uint16*) _TIFFcalloc(tif->tif_dir.td_extrasamples, sizeof(uint16)); + if (!new_sampleinfo) { + TIFFErrorExt(tif->tif_clientdata, module, "Failed to allocate memory for " + "temporary new sampleinfo array (%d 16 bit elements)", + tif->tif_dir.td_extrasamples); + goto bad; + } + + memcpy(new_sampleinfo, tif->tif_dir.td_sampleinfo, old_extrasamples * sizeof(uint16)); + _TIFFsetShortArray(&tif->tif_dir.td_sampleinfo, new_sampleinfo, tif->tif_dir.td_extrasamples); + _TIFFfree(new_sampleinfo); + } + /* * Verify Palette image has a Colormap. */ @@ -4881,17 +4941,18 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover) err=TIFFReadDirEntryByteArray(tif,dp,&data); if (err==TIFFReadDirEntryErrOk) { - uint8* ma; - uint32 mb; + uint32 mb = 0; int n; - ma=data; - mb=0; - while (mb<(uint32)dp->tdir_count) + if (data != NULL) { - if (*ma==0) - break; - ma++; - mb++; + uint8* ma = data; + while (mb<(uint32)dp->tdir_count) + { + if (*ma==0) + break; + ma++; + mb++; + } } if (mb+1<(uint32)dp->tdir_count) TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" contains null byte in value; value incorrectly truncated during reading due to implementation limitations",fip->field_name); @@ -5141,11 +5202,11 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover) if (err==TIFFReadDirEntryErrOk) { int m; - if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' ) - { - TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name); - data[dp->tdir_count-1] = '\0'; - } + if( data != 0 && dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' ) + { + TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name); + data[dp->tdir_count-1] = '\0'; + } m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); if (data!=0) _TIFFfree(data); @@ -5318,11 +5379,11 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover) if (err==TIFFReadDirEntryErrOk) { int m; - if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' ) - { - TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name); - data[dp->tdir_count-1] = '\0'; - } + if( data != 0 && dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' ) + { + TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name); + data[dp->tdir_count-1] = '\0'; + } m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); if (data!=0) _TIFFfree(data); @@ -5698,6 +5759,16 @@ ChopUpSingleUncompressedStrip(TIFF* tif) 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 && + (offset >= TIFFGetFileSize(tif) || + stripbytes > (TIFFGetFileSize(tif) - offset) / (nstrips - 1)) ) + { + return; + } + newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64), "for chopped \"StripByteCounts\" array"); newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64), diff --git a/3rdparty/libtiff/tif_dirwrite.c b/3rdparty/libtiff/tif_dirwrite.c index c68d6d21d6..c15a28dbd8 100644 --- a/3rdparty/libtiff/tif_dirwrite.c +++ b/3rdparty/libtiff/tif_dirwrite.c @@ -1,5 +1,3 @@ -/* $Id: tif_dirwrite.c,v 1.89 2017-08-23 13:33:42 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -697,8 +695,11 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff) } break; default: - assert(0); /* we should never get here */ - break; + TIFFErrorExt(tif->tif_clientdata,module, + "Cannot write tag %d (%s)", + TIFFFieldTag(o), + o->field_name ? o->field_name : "unknown"); + goto bad; } } } diff --git a/3rdparty/libtiff/tif_dumpmode.c b/3rdparty/libtiff/tif_dumpmode.c index a6a94c04d5..4a0b07f504 100644 --- a/3rdparty/libtiff/tif_dumpmode.c +++ b/3rdparty/libtiff/tif_dumpmode.c @@ -1,5 +1,3 @@ -/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_dumpmode.c,v 1.15 2015-12-12 18:04:26 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_error.c b/3rdparty/libtiff/tif_error.c index 47516b4f59..651168f7dc 100644 --- a/3rdparty/libtiff/tif_error.c +++ b/3rdparty/libtiff/tif_error.c @@ -1,5 +1,3 @@ -/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_error.c,v 1.6 2017-07-04 12:54:42 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_extension.c b/3rdparty/libtiff/tif_extension.c index 39fab4c7ba..87d3cfcbc7 100644 --- a/3rdparty/libtiff/tif_extension.c +++ b/3rdparty/libtiff/tif_extension.c @@ -1,5 +1,3 @@ -/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_extension.c,v 1.8 2015-12-06 11:13:43 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_fax3.c b/3rdparty/libtiff/tif_fax3.c index 5fd514118c..d11c968444 100644 --- a/3rdparty/libtiff/tif_fax3.c +++ b/3rdparty/libtiff/tif_fax3.c @@ -1,5 +1,3 @@ -/* $Id: tif_fax3.c,v 1.81 2017-06-18 10:31:50 erouault Exp $ */ - /* * Copyright (c) 1990-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_fax3.h b/3rdparty/libtiff/tif_fax3.h index 8a435059c7..abadcd97a2 100644 --- a/3rdparty/libtiff/tif_fax3.h +++ b/3rdparty/libtiff/tif_fax3.h @@ -1,5 +1,3 @@ -/* $Id: tif_fax3.h,v 1.13 2016-12-14 18:36:27 faxguy Exp $ */ - /* * Copyright (c) 1990-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_flush.c b/3rdparty/libtiff/tif_flush.c index fd14e4cdae..881fac5121 100644 --- a/3rdparty/libtiff/tif_flush.c +++ b/3rdparty/libtiff/tif_flush.c @@ -1,5 +1,3 @@ -/* $Id: tif_flush.c,v 1.9 2010-03-31 06:40:10 fwarmerdam Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_getimage.c b/3rdparty/libtiff/tif_getimage.c index fc554ccab3..6a9d5a7c0c 100644 --- a/3rdparty/libtiff/tif_getimage.c +++ b/3rdparty/libtiff/tif_getimage.c @@ -1,5 +1,3 @@ -/* $Id: tif_getimage.c,v 1.114 2017-11-17 20:21:00 erouault Exp $ */ - /* * Copyright (c) 1991-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_jbig.c b/3rdparty/libtiff/tif_jbig.c index 7a14dd9ab0..7ffe8851e8 100644 --- a/3rdparty/libtiff/tif_jbig.c +++ b/3rdparty/libtiff/tif_jbig.c @@ -1,5 +1,3 @@ -/* $Id: tif_jbig.c,v 1.16 2017-06-26 15:20:00 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -53,17 +51,18 @@ static int JBIGDecode(TIFF* tif, uint8* buffer, tmsize_t size, uint16 s) struct jbg_dec_state decoder; int decodeStatus = 0; unsigned char* pImage = NULL; - (void) size, (void) s; + unsigned long decodedSize; + (void) s; if (isFillOrder(tif, tif->tif_dir.td_fillorder)) { - TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdatasize); + TIFFReverseBits(tif->tif_rawcp, tif->tif_rawcc); } jbg_dec_init(&decoder); #if defined(HAVE_JBG_NEWLEN) - jbg_newlen(tif->tif_rawdata, (size_t)tif->tif_rawdatasize); + jbg_newlen(tif->tif_rawcp, (size_t)tif->tif_rawcc); /* * I do not check the return status of jbg_newlen because even if this * function fails it does not necessarily mean that decoding the image @@ -76,8 +75,8 @@ static int JBIGDecode(TIFF* tif, uint8* buffer, tmsize_t size, uint16 s) */ #endif /* HAVE_JBG_NEWLEN */ - decodeStatus = jbg_dec_in(&decoder, (unsigned char*)tif->tif_rawdata, - (size_t)tif->tif_rawdatasize, NULL); + decodeStatus = jbg_dec_in(&decoder, (unsigned char*)tif->tif_rawcp, + (size_t)tif->tif_rawcc, NULL); if (JBG_EOK != decodeStatus) { /* @@ -98,9 +97,28 @@ static int JBIGDecode(TIFF* tif, uint8* buffer, tmsize_t size, uint16 s) return 0; } + decodedSize = jbg_dec_getsize(&decoder); + if( (tmsize_t)decodedSize < size ) + { + TIFFWarningExt(tif->tif_clientdata, "JBIG", + "Only decoded %lu bytes, whereas %lu requested", + decodedSize, (unsigned long)size); + } + else if( (tmsize_t)decodedSize > size ) + { + TIFFErrorExt(tif->tif_clientdata, "JBIG", + "Decoded %lu bytes, whereas %lu were requested", + decodedSize, (unsigned long)size); + jbg_dec_free(&decoder); + return 0; + } pImage = jbg_dec_getimage(&decoder, 0); - _TIFFmemcpy(buffer, pImage, jbg_dec_getsize(&decoder)); + _TIFFmemcpy(buffer, pImage, decodedSize); jbg_dec_free(&decoder); + + tif->tif_rawcp += tif->tif_rawcc; + tif->tif_rawcc = 0; + return 1; } diff --git a/3rdparty/libtiff/tif_jpeg.c b/3rdparty/libtiff/tif_jpeg.c index 0fbdb3548a..f2ddc331a0 100644 --- a/3rdparty/libtiff/tif_jpeg.c +++ b/3rdparty/libtiff/tif_jpeg.c @@ -1,5 +1,3 @@ -/* $Id: tif_jpeg.c,v 1.134 2017-10-17 19:04:47 erouault Exp $ */ - /* * Copyright (c) 1994-1997 Sam Leffler * Copyright (c) 1994-1997 Silicon Graphics, Inc. @@ -27,9 +25,9 @@ #define WIN32_LEAN_AND_MEAN #define VC_EXTRALEAN +#include "tiffiop.h" #include -#include "tiffiop.h" #ifdef JPEG_SUPPORT /* @@ -76,7 +74,7 @@ int TIFFJPEGIsFullStripRequired_12(TIFF* tif); "JPEGLib: JPEG parameter struct mismatch: library thinks size is 432, caller expects 464" - For such users we wil fix the problem here. See install.doc file from + For such users we will fix the problem here. See install.doc file from the JPEG library distribution for details. */ diff --git a/3rdparty/libtiff/tif_luv.c b/3rdparty/libtiff/tif_luv.c index 4b25244bff..aa35ea07d1 100644 --- a/3rdparty/libtiff/tif_luv.c +++ b/3rdparty/libtiff/tif_luv.c @@ -1,5 +1,3 @@ -/* $Id: tif_luv.c,v 1.49 2017-07-24 12:47:30 erouault Exp $ */ - /* * Copyright (c) 1997 Greg Ward Larson * Copyright (c) 1997 Silicon Graphics, Inc. @@ -215,7 +213,7 @@ LogL16Decode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) bp = (unsigned char*) tif->tif_rawcp; cc = tif->tif_rawcc; /* get each byte string */ - for (shft = 2*8; (shft -= 8) >= 0; ) { + for (shft = 8; shft >= 0; shft -=8) { for (i = 0; i < npixels && cc > 0; ) { if (*bp >= 128) { /* run */ if( cc < 2 ) @@ -349,7 +347,7 @@ LogLuvDecode32(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) bp = (unsigned char*) tif->tif_rawcp; cc = tif->tif_rawcc; /* get each byte string */ - for (shft = 4*8; (shft -= 8) >= 0; ) { + for (shft = 24; shft >= 0; shft -=8) { for (i = 0; i < npixels && cc > 0; ) { if (*bp >= 128) { /* run */ if( cc < 2 ) @@ -467,7 +465,7 @@ LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) /* compress each byte string */ op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; - for (shft = 2*8; (shft -= 8) >= 0; ) + for (shft = 8; shft >= 0; shft -=8) { for (i = 0; i < npixels; i += rc) { if (occ < 4) { tif->tif_rawcp = op; @@ -522,6 +520,7 @@ LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) } else rc = 0; } + } tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; @@ -618,7 +617,7 @@ LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) /* compress each byte string */ op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; - for (shft = 4*8; (shft -= 8) >= 0; ) + for (shft = 24; shft >= 0; shft -=8) { for (i = 0; i < npixels; i += rc) { if (occ < 4) { tif->tif_rawcp = op; @@ -673,6 +672,7 @@ LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) } else rc = 0; } + } tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; diff --git a/3rdparty/libtiff/tif_lzma.c b/3rdparty/libtiff/tif_lzma.c index 80fc394245..3f6096b62a 100644 --- a/3rdparty/libtiff/tif_lzma.c +++ b/3rdparty/libtiff/tif_lzma.c @@ -1,5 +1,3 @@ -/* $Id: tif_lzma.c,v 1.6 2016-09-17 09:18:59 erouault Exp $ */ - /* * Copyright (c) 2010, Andrey Kiselev * @@ -249,6 +247,7 @@ LZMAPreEncode(TIFF* tif, uint16 s) { static const char module[] = "LZMAPreEncode"; LZMAState *sp = EncoderState(tif); + lzma_ret ret; (void) s; assert(sp != NULL); @@ -262,7 +261,13 @@ LZMAPreEncode(TIFF* tif, uint16 s) "Liblzma cannot deal with buffers this size"); return 0; } - return (lzma_stream_encoder(&sp->stream, sp->filters, sp->check) == LZMA_OK); + ret = lzma_stream_encoder(&sp->stream, sp->filters, sp->check); + if (ret != LZMA_OK) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error in lzma_stream_encoder(): %s", LZMAStrerror(ret)); + return 0; + } + return 1; } /* diff --git a/3rdparty/libtiff/tif_lzw.c b/3rdparty/libtiff/tif_lzw.c index bc8f9c84a6..ac685dd740 100644 --- a/3rdparty/libtiff/tif_lzw.c +++ b/3rdparty/libtiff/tif_lzw.c @@ -1,5 +1,3 @@ -/* $Id: tif_lzw.c,v 1.57 2017-07-11 10:54:29 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -135,6 +133,7 @@ typedef struct { long dec_restart; /* restart count */ #ifdef LZW_CHECKEOS uint64 dec_bitsleft; /* available bits in raw data */ + tmsize_t old_tif_rawcc; /* value of tif_rawcc at the end of the previous TIFLZWDecode() call */ #endif decodeFunc dec_decode; /* regular or backwards compatible */ code_t* dec_codep; /* current recognized code */ @@ -320,6 +319,7 @@ LZWPreDecode(TIFF* tif, uint16 s) sp->dec_nbitsmask = MAXCODE(BITS_MIN); #ifdef LZW_CHECKEOS sp->dec_bitsleft = 0; + sp->old_tif_rawcc = 0; #endif sp->dec_free_entp = sp->dec_codetab + CODE_FIRST; /* @@ -427,7 +427,7 @@ LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) bp = (unsigned char *)tif->tif_rawcp; #ifdef LZW_CHECKEOS - sp->dec_bitsleft = (((uint64)tif->tif_rawcc) << 3); + sp->dec_bitsleft += (((uint64)tif->tif_rawcc - sp->old_tif_rawcc) << 3); #endif nbits = sp->lzw_nbits; nextdata = sp->lzw_nextdata; @@ -555,6 +555,9 @@ LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) tif->tif_rawcc -= (tmsize_t)( (uint8*) bp - tif->tif_rawcp ); tif->tif_rawcp = (uint8*) bp; +#ifdef LZW_CHECKEOS + sp->old_tif_rawcc = tif->tif_rawcc; +#endif sp->lzw_nbits = (unsigned short) nbits; sp->lzw_nextdata = nextdata; sp->lzw_nextbits = nextbits; @@ -604,6 +607,7 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) char *tp; unsigned char *bp; int code, nbits; + int len; long nextbits, nextdata, nbitsmask; code_t *codep, *free_entp, *maxcodep, *oldcodep; @@ -657,7 +661,7 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) bp = (unsigned char *)tif->tif_rawcp; #ifdef LZW_CHECKEOS - sp->dec_bitsleft = (((uint64)tif->tif_rawcc) << 3); + sp->dec_bitsleft += (((uint64)tif->tif_rawcc - sp->old_tif_rawcc) << 3); #endif nbits = sp->lzw_nbits; nextdata = sp->lzw_nextdata; @@ -755,13 +759,18 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) } while (--occ); break; } - assert(occ >= codep->length); - op += codep->length; - occ -= codep->length; - tp = op; + len = codep->length; + tp = op + len; do { - *--tp = codep->value; - } while( (codep = codep->next) != NULL ); + int t; + --tp; + t = codep->value; + codep = codep->next; + *tp = (char)t; + } while (codep && tp > op); + assert(occ >= len); + op += len; + occ -= len; } else { *op++ = (char)code; occ--; @@ -770,6 +779,9 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) tif->tif_rawcc -= (tmsize_t)( (uint8*) bp - tif->tif_rawcp ); tif->tif_rawcp = (uint8*) bp; +#ifdef LZW_CHECKEOS + sp->old_tif_rawcc = tif->tif_rawcc; +#endif sp->lzw_nbits = (unsigned short)nbits; sp->lzw_nextdata = nextdata; sp->lzw_nextbits = nextbits; diff --git a/3rdparty/libtiff/tif_next.c b/3rdparty/libtiff/tif_next.c index 08211788ac..0ba61aed3a 100644 --- a/3rdparty/libtiff/tif_next.c +++ b/3rdparty/libtiff/tif_next.c @@ -1,5 +1,3 @@ -/* $Id: tif_next.c,v 1.19 2016-09-04 21:32:56 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_ojpeg.c b/3rdparty/libtiff/tif_ojpeg.c index 92ed1fa19e..27385d8c47 100644 --- a/3rdparty/libtiff/tif_ojpeg.c +++ b/3rdparty/libtiff/tif_ojpeg.c @@ -1,5 +1,3 @@ -/* $Id: tif_ojpeg.c,v 1.69 2017-04-27 17:29:26 erouault Exp $ */ - /* WARNING: The type of JPEG encapsulation defined by the TIFF Version 6.0 specification is now totally obsolete and deprecated for new applications and images. This file was was created solely in order to read unconverted images diff --git a/3rdparty/libtiff/tif_open.c b/3rdparty/libtiff/tif_open.c index a7279e1ea0..c574c452aa 100644 --- a/3rdparty/libtiff/tif_open.c +++ b/3rdparty/libtiff/tif_open.c @@ -1,5 +1,3 @@ -/* $Id: tif_open.c,v 1.48 2016-11-20 22:29:47 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_packbits.c b/3rdparty/libtiff/tif_packbits.c index 18904b0137..a8f29e8757 100644 --- a/3rdparty/libtiff/tif_packbits.c +++ b/3rdparty/libtiff/tif_packbits.c @@ -1,5 +1,3 @@ -/* $Id: tif_packbits.c,v 1.26 2017-05-14 02:26:07 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_pixarlog.c b/3rdparty/libtiff/tif_pixarlog.c index 979858da9c..7438d69215 100644 --- a/3rdparty/libtiff/tif_pixarlog.c +++ b/3rdparty/libtiff/tif_pixarlog.c @@ -1,5 +1,3 @@ -/* $Id: tif_pixarlog.c,v 1.54 2017-07-10 10:40:28 erouault Exp $ */ - /* * Copyright (c) 1996-1997 Sam Leffler * Copyright (c) 1996 Pixar diff --git a/3rdparty/libtiff/tif_predict.c b/3rdparty/libtiff/tif_predict.c index 9ae1f57a65..b775663a7b 100644 --- a/3rdparty/libtiff/tif_predict.c +++ b/3rdparty/libtiff/tif_predict.c @@ -1,5 +1,3 @@ -/* $Id: tif_predict.c,v 1.44 2017-06-18 10:31:50 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_predict.h b/3rdparty/libtiff/tif_predict.h index 6c68e21acb..a326b9b8f8 100644 --- a/3rdparty/libtiff/tif_predict.h +++ b/3rdparty/libtiff/tif_predict.h @@ -1,5 +1,3 @@ -/* $Id: tif_predict.h,v 1.9 2016-10-31 17:24:26 erouault Exp $ */ - /* * Copyright (c) 1995-1997 Sam Leffler * Copyright (c) 1995-1997 Silicon Graphics, Inc. @@ -26,6 +24,10 @@ #ifndef _TIFFPREDICT_ #define _TIFFPREDICT_ + +#include "tiffio.h" +#include "tiffiop.h" + /* * ``Library-private'' Support for the Predictor Tag */ diff --git a/3rdparty/libtiff/tif_print.c b/3rdparty/libtiff/tif_print.c index 24d4b98a68..1d86adbf05 100644 --- a/3rdparty/libtiff/tif_print.c +++ b/3rdparty/libtiff/tif_print.c @@ -1,5 +1,3 @@ -/* $Id: tif_print.c,v 1.65 2016-11-20 22:31:22 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -546,7 +544,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) uint16 i; fprintf(fd, " %2ld: %5u", l, td->td_transferfunction[0][l]); - for (i = 1; i < td->td_samplesperpixel; i++) + for (i = 1; i < td->td_samplesperpixel - td->td_extrasamples && i < 3; i++) fprintf(fd, " %5u", td->td_transferfunction[i][l]); fputc('\n', fd); @@ -667,13 +665,13 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) fprintf(fd, " %3lu: [%8I64u, %8I64u]\n", (unsigned long) s, - (unsigned __int64) td->td_stripoffset[s], - (unsigned __int64) td->td_stripbytecount[s]); + td->td_stripoffset ? (unsigned __int64) td->td_stripoffset[s] : 0, + td->td_stripbytecount ? (unsigned __int64) td->td_stripbytecount[s] : 0); #else fprintf(fd, " %3lu: [%8llu, %8llu]\n", (unsigned long) s, - (unsigned long long) td->td_stripoffset[s], - (unsigned long long) td->td_stripbytecount[s]); + td->td_stripoffset ? (unsigned long long) td->td_stripoffset[s] : 0, + td->td_stripbytecount ? (unsigned long long) td->td_stripbytecount[s] : 0); #endif } } diff --git a/3rdparty/libtiff/tif_read.c b/3rdparty/libtiff/tif_read.c index 2ba985a749..e63810cc78 100644 --- a/3rdparty/libtiff/tif_read.c +++ b/3rdparty/libtiff/tif_read.c @@ -1,5 +1,3 @@ -/* $Id: tif_read.c,v 1.66 2017-11-17 20:21:00 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -58,7 +56,7 @@ static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size, int is_strip, uint32 strip_or_tile, const char* module ) { -#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8 +#if SIZEOF_SIZE_T == 8 tmsize_t threshold = INITIAL_THRESHOLD; #endif tmsize_t already_read = 0; @@ -73,7 +71,7 @@ static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size, { tmsize_t bytes_read; tmsize_t to_read = size - already_read; -#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8 +#if SIZEOF_SIZE_T == 8 if( to_read >= threshold && threshold < MAX_THRESHOLD && already_read + to_read + rawdata_offset > tif->tif_rawdatasize ) { @@ -348,6 +346,13 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample ) return 0; whole_strip = tif->tif_dir.td_stripbytecount[strip] < 10 || isMapped(tif); + if( td->td_compression == COMPRESSION_LERC || + td->td_compression == COMPRESSION_JBIG ) + { + /* Ideally plugins should have a way to declare they don't support + * chunk strip */ + whole_strip = 1; + } #else whole_strip = 1; #endif diff --git a/3rdparty/libtiff/tif_stream.cxx b/3rdparty/libtiff/tif_stream.cxx index 02eaf936a6..7f640a9c0a 100644 --- a/3rdparty/libtiff/tif_stream.cxx +++ b/3rdparty/libtiff/tif_stream.cxx @@ -1,26 +1,24 @@ -/* $Id: tif_stream.cxx,v 1.11 2010-12-11 23:12:29 faxguy Exp $ */ - /* * Copyright (c) 1988-1996 Sam Leffler * Copyright (c) 1991-1996 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -28,7 +26,6 @@ * TIFF Library UNIX-specific Routines. */ #include "tiffiop.h" -#include "tiffio.hxx" #include #ifndef __VMS @@ -81,30 +78,30 @@ struct tiffos_data; extern "C" { - static tmsize_t _tiffosReadProc(thandle_t, void*, tmsize_t); - static tmsize_t _tiffisReadProc(thandle_t fd, void* buf, tmsize_t size); - static tmsize_t _tiffosWriteProc(thandle_t fd, void* buf, tmsize_t size); - static tmsize_t _tiffisWriteProc(thandle_t, void*, tmsize_t); - static uint64 _tiffosSeekProc(thandle_t fd, uint64 off, int whence); - static uint64 _tiffisSeekProc(thandle_t fd, uint64 off, int whence); - static uint64 _tiffosSizeProc(thandle_t fd); - static uint64 _tiffisSizeProc(thandle_t fd); - static int _tiffosCloseProc(thandle_t fd); - static int _tiffisCloseProc(thandle_t fd); - static int _tiffDummyMapProc(thandle_t , void** base, toff_t* size ); - static void _tiffDummyUnmapProc(thandle_t , void* base, toff_t size ); - static TIFF* _tiffStreamOpen(const char* name, const char* mode, void *fd); + static tmsize_t _tiffosReadProc(thandle_t, void*, tmsize_t); + static tmsize_t _tiffisReadProc(thandle_t fd, void* buf, tmsize_t size); + static tmsize_t _tiffosWriteProc(thandle_t fd, void* buf, tmsize_t size); + static tmsize_t _tiffisWriteProc(thandle_t, void*, tmsize_t); + static uint64 _tiffosSeekProc(thandle_t fd, uint64 off, int whence); + static uint64 _tiffisSeekProc(thandle_t fd, uint64 off, int whence); + static uint64 _tiffosSizeProc(thandle_t fd); + static uint64 _tiffisSizeProc(thandle_t fd); + static int _tiffosCloseProc(thandle_t fd); + static int _tiffisCloseProc(thandle_t fd); + static int _tiffDummyMapProc(thandle_t , void** base, toff_t* size ); + static void _tiffDummyUnmapProc(thandle_t , void* base, toff_t size ); + static TIFF* _tiffStreamOpen(const char* name, const char* mode, void *fd); struct tiffis_data { - istream *stream; + istream *stream; ios::pos_type start_pos; }; struct tiffos_data { - ostream *stream; - ios::pos_type start_pos; + ostream *stream; + ios::pos_type start_pos; }; static tmsize_t @@ -131,222 +128,226 @@ _tiffisReadProc(thandle_t fd, void* buf, tmsize_t size) static tmsize_t _tiffosWriteProc(thandle_t fd, void* buf, tmsize_t size) { - tiffos_data *data = reinterpret_cast(fd); - ostream *os = data->stream; - ios::pos_type pos = os->tellp(); + tiffos_data *data = reinterpret_cast(fd); + ostream *os = data->stream; + ios::pos_type pos = os->tellp(); // Verify that type does not overflow. streamsize request_size = size; if (static_cast(request_size) != size) return static_cast(-1); - os->write(reinterpret_cast(buf), request_size); + os->write(reinterpret_cast(buf), request_size); - return static_cast(os->tellp() - pos); + return static_cast(os->tellp() - pos); } static tmsize_t _tiffisWriteProc(thandle_t, void*, tmsize_t) { - return 0; + return 0; } static uint64 _tiffosSeekProc(thandle_t fd, uint64 off, int whence) { - tiffos_data *data = reinterpret_cast(fd); - ostream *os = data->stream; - - // if the stream has already failed, don't do anything - if( os->fail() ) - return static_cast(-1); - - switch(whence) { - case SEEK_SET: - { - // Compute 64-bit offset - uint64 new_offset = static_cast(data->start_pos) + off; - - // Verify that value does not overflow - ios::off_type offset = static_cast(new_offset); - if (static_cast(offset) != new_offset) - return static_cast(-1); - - os->seekp(offset, ios::beg); - break; - } - case SEEK_CUR: - { - // Verify that value does not overflow - ios::off_type offset = static_cast(off); - if (static_cast(offset) != off) - return static_cast(-1); - - os->seekp(offset, ios::cur); - break; - } - case SEEK_END: - { - // Verify that value does not overflow - ios::off_type offset = static_cast(off); - if (static_cast(offset) != off) - return static_cast(-1); - - os->seekp(offset, ios::end); - break; - } - } - - // Attempt to workaround problems with seeking past the end of the - // stream. ofstream doesn't have a problem with this but - // ostrstream/ostringstream does. In that situation, add intermediate - // '\0' characters. - if( os->fail() ) { + tiffos_data *data = reinterpret_cast(fd); + ostream *os = data->stream; + + // if the stream has already failed, don't do anything + if( os->fail() ) + return static_cast(-1); + + switch(whence) { + case SEEK_SET: + { + // Compute 64-bit offset + uint64 new_offset = static_cast(data->start_pos) + off; + + // Verify that value does not overflow + ios::off_type offset = static_cast(new_offset); + if (static_cast(offset) != new_offset) + return static_cast(-1); + + os->seekp(offset, ios::beg); + break; + } + case SEEK_CUR: + { + // Verify that value does not overflow + ios::off_type offset = static_cast(off); + if (static_cast(offset) != off) + return static_cast(-1); + + os->seekp(offset, ios::cur); + break; + } + case SEEK_END: + { + // Verify that value does not overflow + ios::off_type offset = static_cast(off); + if (static_cast(offset) != off) + return static_cast(-1); + + os->seekp(offset, ios::end); + break; + } + } + + // Attempt to workaround problems with seeking past the end of the + // stream. ofstream doesn't have a problem with this but + // ostrstream/ostringstream does. In that situation, add intermediate + // '\0' characters. + if( os->fail() ) { #ifdef __VMS - int old_state; + int old_state; #else - ios::iostate old_state; + ios::iostate old_state; #endif - ios::pos_type origin; + ios::pos_type origin; - old_state = os->rdstate(); - // reset the fail bit or else tellp() won't work below - os->clear(os->rdstate() & ~ios::failbit); - switch( whence ) { - case SEEK_SET: + old_state = os->rdstate(); + // reset the fail bit or else tellp() won't work below + os->clear(os->rdstate() & ~ios::failbit); + switch( whence ) { + case SEEK_SET: default: - origin = data->start_pos; - break; - case SEEK_CUR: - origin = os->tellp(); - break; - case SEEK_END: - os->seekp(0, ios::end); - origin = os->tellp(); - break; - } - // restore original stream state - os->clear(old_state); - - // only do something if desired seek position is valid - if( (static_cast(origin) + off) > static_cast(data->start_pos) ) { - uint64 num_fill; - - // clear the fail bit - os->clear(os->rdstate() & ~ios::failbit); - - // extend the stream to the expected size - os->seekp(0, ios::end); - num_fill = (static_cast(origin)) + off - os->tellp(); - for( uint64 i = 0; i < num_fill; i++ ) - os->put('\0'); - - // retry the seek - os->seekp(static_cast(static_cast(origin) + off), ios::beg); - } - } - - return static_cast(os->tellp()); + origin = data->start_pos; + break; + case SEEK_CUR: + origin = os->tellp(); + break; + case SEEK_END: + os->seekp(0, ios::end); + origin = os->tellp(); + break; + } + // restore original stream state + os->clear(old_state); + + // only do something if desired seek position is valid + if( (static_cast(origin) + off) > static_cast(data->start_pos) ) { + uint64 num_fill; + + // clear the fail bit + os->clear(os->rdstate() & ~ios::failbit); + + // extend the stream to the expected size + os->seekp(0, ios::end); + num_fill = (static_cast(origin)) + off - os->tellp(); + for( uint64 i = 0; i < num_fill; i++ ) + os->put('\0'); + + // retry the seek + os->seekp(static_cast(static_cast(origin) + off), ios::beg); + } + } + + return static_cast(os->tellp()); } static uint64 _tiffisSeekProc(thandle_t fd, uint64 off, int whence) { - tiffis_data *data = reinterpret_cast(fd); - - switch(whence) { - case SEEK_SET: - { - // Compute 64-bit offset - uint64 new_offset = static_cast(data->start_pos) + off; - - // Verify that value does not overflow - ios::off_type offset = static_cast(new_offset); - if (static_cast(offset) != new_offset) - return static_cast(-1); - - data->stream->seekg(offset, ios::beg); - break; - } - case SEEK_CUR: - { - // Verify that value does not overflow - ios::off_type offset = static_cast(off); - if (static_cast(offset) != off) - return static_cast(-1); - - data->stream->seekg(offset, ios::cur); - break; - } - case SEEK_END: - { - // Verify that value does not overflow - ios::off_type offset = static_cast(off); - if (static_cast(offset) != off) - return static_cast(-1); - - data->stream->seekg(offset, ios::end); - break; - } - } - - return (uint64) (data->stream->tellg() - data->start_pos); + tiffis_data *data = reinterpret_cast(fd); + + switch(whence) { + case SEEK_SET: + { + // Compute 64-bit offset + uint64 new_offset = static_cast(data->start_pos) + off; + + // Verify that value does not overflow + ios::off_type offset = static_cast(new_offset); + if (static_cast(offset) != new_offset) + return static_cast(-1); + + data->stream->seekg(offset, ios::beg); + break; + } + case SEEK_CUR: + { + // Verify that value does not overflow + ios::off_type offset = static_cast(off); + if (static_cast(offset) != off) + return static_cast(-1); + + data->stream->seekg(offset, ios::cur); + break; + } + case SEEK_END: + { + // Verify that value does not overflow + ios::off_type offset = static_cast(off); + if (static_cast(offset) != off) + return static_cast(-1); + + data->stream->seekg(offset, ios::end); + break; + } + } + + return (uint64) (data->stream->tellg() - data->start_pos); } static uint64 _tiffosSizeProc(thandle_t fd) { - tiffos_data *data = reinterpret_cast(fd); - ostream *os = data->stream; - ios::pos_type pos = os->tellp(); - ios::pos_type len; + tiffos_data *data = reinterpret_cast(fd); + ostream *os = data->stream; + ios::pos_type pos = os->tellp(); + ios::pos_type len; - os->seekp(0, ios::end); - len = os->tellp(); - os->seekp(pos); + os->seekp(0, ios::end); + len = os->tellp(); + os->seekp(pos); - return (uint64) len; + return (uint64) len; } static uint64 _tiffisSizeProc(thandle_t fd) { - tiffis_data *data = reinterpret_cast(fd); - ios::pos_type pos = data->stream->tellg(); - ios::pos_type len; + tiffis_data *data = reinterpret_cast(fd); + ios::pos_type pos = data->stream->tellg(); + ios::pos_type len; - data->stream->seekg(0, ios::end); - len = data->stream->tellg(); - data->stream->seekg(pos); + data->stream->seekg(0, ios::end); + len = data->stream->tellg(); + data->stream->seekg(pos); - return (uint64) len; + return (uint64) len; } static int _tiffosCloseProc(thandle_t fd) { - // Our stream was not allocated by us, so it shouldn't be closed by us. - delete reinterpret_cast(fd); - return 0; + // Our stream was not allocated by us, so it shouldn't be closed by us. + delete reinterpret_cast(fd); + return 0; } static int _tiffisCloseProc(thandle_t fd) { - // Our stream was not allocated by us, so it shouldn't be closed by us. - delete reinterpret_cast(fd); - return 0; + // Our stream was not allocated by us, so it shouldn't be closed by us. + delete reinterpret_cast(fd); + return 0; } static int _tiffDummyMapProc(thandle_t , void** base, toff_t* size ) { - return (0); + (void) base; + (void) size; + return (0); } static void _tiffDummyUnmapProc(thandle_t , void* base, toff_t size ) { + (void) base; + (void) size; } /* @@ -355,40 +356,46 @@ _tiffDummyUnmapProc(thandle_t , void* base, toff_t size ) static TIFF* _tiffStreamOpen(const char* name, const char* mode, void *fd) { - TIFF* tif; + TIFF* tif; - if( strchr(mode, 'w') ) { - tiffos_data *data = new tiffos_data; - data->stream = reinterpret_cast(fd); - data->start_pos = data->stream->tellp(); + if( strchr(mode, 'w') ) { + tiffos_data *data = new tiffos_data; + data->stream = reinterpret_cast(fd); + data->start_pos = data->stream->tellp(); - // Open for writing. - tif = TIFFClientOpen(name, mode, - reinterpret_cast(data), - _tiffosReadProc, + // Open for writing. + tif = TIFFClientOpen(name, mode, + reinterpret_cast(data), + _tiffosReadProc, _tiffosWriteProc, - _tiffosSeekProc, + _tiffosSeekProc, _tiffosCloseProc, - _tiffosSizeProc, - _tiffDummyMapProc, + _tiffosSizeProc, + _tiffDummyMapProc, _tiffDummyUnmapProc); - } else { - tiffis_data *data = new tiffis_data; - data->stream = reinterpret_cast(fd); - data->start_pos = data->stream->tellg(); - // Open for reading. - tif = TIFFClientOpen(name, mode, - reinterpret_cast(data), - _tiffisReadProc, + if (!tif) { + delete data; + } + } else { + tiffis_data *data = new tiffis_data; + data->stream = reinterpret_cast(fd); + data->start_pos = data->stream->tellg(); + // Open for reading. + tif = TIFFClientOpen(name, mode, + reinterpret_cast(data), + _tiffisReadProc, _tiffisWriteProc, - _tiffisSeekProc, + _tiffisSeekProc, _tiffisCloseProc, - _tiffisSizeProc, - _tiffDummyMapProc, + _tiffisSizeProc, + _tiffDummyMapProc, _tiffDummyUnmapProc); - } + if (!tif) { + delete data; + } + } - return (tif); + return (tif); } } /* extern "C" */ @@ -396,31 +403,32 @@ _tiffStreamOpen(const char* name, const char* mode, void *fd) TIFF* TIFFStreamOpen(const char* name, ostream *os) { - // If os is either a ostrstream or ostringstream, and has no data - // written to it yet, then tellp() will return -1 which will break us. - // We workaround this by writing out a dummy character and - // then seek back to the beginning. - if( !os->fail() && static_cast(os->tellp()) < 0 ) { - *os << '\0'; - os->seekp(0); - } - - // NB: We don't support mapped files with streams so add 'm' - return _tiffStreamOpen(name, "wm", os); + // If os is either a ostrstream or ostringstream, and has no data + // written to it yet, then tellp() will return -1 which will break us. + // We workaround this by writing out a dummy character and + // then seek back to the beginning. + if( !os->fail() && static_cast(os->tellp()) < 0 ) { + *os << '\0'; + os->seekp(0); + } + + // NB: We don't support mapped files with streams so add 'm' + return _tiffStreamOpen(name, "wm", os); } TIFF* TIFFStreamOpen(const char* name, istream *is) { - // NB: We don't support mapped files with streams so add 'm' - return _tiffStreamOpen(name, "rm", is); + // NB: We don't support mapped files with streams so add 'm' + return _tiffStreamOpen(name, "rm", is); } /* vim: set ts=8 sts=8 sw=8 noet: */ /* - Local Variables: - mode: c - indent-tabs-mode: true - c-basic-offset: 8 - End: -*/ + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ + diff --git a/3rdparty/libtiff/tif_strip.c b/3rdparty/libtiff/tif_strip.c index 6e9f2ef6dd..5b76fba56d 100644 --- a/3rdparty/libtiff/tif_strip.c +++ b/3rdparty/libtiff/tif_strip.c @@ -1,5 +1,3 @@ -/* $Id: tif_strip.c,v 1.38 2016-12-03 11:02:15 erouault Exp $ */ - /* * Copyright (c) 1991-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_swab.c b/3rdparty/libtiff/tif_swab.c index 4b2e5f16d7..b174ba69c0 100644 --- a/3rdparty/libtiff/tif_swab.c +++ b/3rdparty/libtiff/tif_swab.c @@ -1,5 +1,3 @@ -/* $Id: tif_swab.c,v 1.15 2017-06-08 16:39:50 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_thunder.c b/3rdparty/libtiff/tif_thunder.c index 183199de76..2388dbb66b 100644 --- a/3rdparty/libtiff/tif_thunder.c +++ b/3rdparty/libtiff/tif_thunder.c @@ -1,5 +1,3 @@ -/* $Id: tif_thunder.c,v 1.13 2016-09-04 21:32:56 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_tile.c b/3rdparty/libtiff/tif_tile.c index 388e168ac6..58fe9354a3 100644 --- a/3rdparty/libtiff/tif_tile.c +++ b/3rdparty/libtiff/tif_tile.c @@ -1,5 +1,3 @@ -/* $Id: tif_tile.c,v 1.24 2015-06-07 22:35:40 bfriesen Exp $ */ - /* * Copyright (c) 1991-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_unix.c b/3rdparty/libtiff/tif_unix.c index 80c437cfa3..874f1feb26 100644 --- a/3rdparty/libtiff/tif_unix.c +++ b/3rdparty/libtiff/tif_unix.c @@ -1,5 +1,3 @@ -/* $Id: tif_unix.c,v 1.28 2017-01-11 19:02:49 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_version.c b/3rdparty/libtiff/tif_version.c index f92c843d88..60875bbf09 100644 --- a/3rdparty/libtiff/tif_version.c +++ b/3rdparty/libtiff/tif_version.c @@ -1,4 +1,3 @@ -/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_version.c,v 1.3 2010-03-10 18:56:49 bfriesen Exp $ */ /* * Copyright (c) 1992-1997 Sam Leffler * Copyright (c) 1992-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_warning.c b/3rdparty/libtiff/tif_warning.c index dc79f14455..c482785c29 100644 --- a/3rdparty/libtiff/tif_warning.c +++ b/3rdparty/libtiff/tif_warning.c @@ -1,5 +1,3 @@ -/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_warning.c,v 1.4 2017-07-04 12:54:42 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_webp.c b/3rdparty/libtiff/tif_webp.c new file mode 100644 index 0000000000..a002f481da --- /dev/null +++ b/3rdparty/libtiff/tif_webp.c @@ -0,0 +1,684 @@ +/* +* Copyright (c) 2018, Mapbox +* Author: +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, provided +* that (i) the above copyright notices and this permission notice appear in +* all copies of the software and related documentation, and (ii) the names of +* Sam Leffler and Silicon Graphics may not be used in any advertising or +* publicity relating to the software without the specific, prior written +* permission of Sam Leffler and Silicon Graphics. +* +* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, +* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +* +* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR +* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, +* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF +* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +* OF THIS SOFTWARE. +*/ + +#include "tiffiop.h" +#ifdef WEBP_SUPPORT +/* + * TIFF Library. + * + * WEBP Compression Support + * + */ + +#include "webp/decode.h" +#include "webp/encode.h" + +#include + +#define LSTATE_INIT_DECODE 0x01 +#define LSTATE_INIT_ENCODE 0x02 +/* + * State block for each open TIFF + * file using WEBP compression/decompression. + */ +typedef struct { + uint16 nSamples; /* number of samples per pixel */ + + int lossless; /* lossy/lossless compression */ + int quality_level; /* compression level */ + WebPPicture sPicture; /* WebP Picture */ + WebPConfig sEncoderConfig; /* WebP encoder config */ + uint8* pBuffer; /* buffer to hold raw data on encoding */ + unsigned int buffer_offset; /* current offset into the buffer */ + unsigned int buffer_size; + + WebPIDecoder* psDecoder; /* WebPIDecoder */ + WebPDecBuffer sDecBuffer; /* Decoder buffer */ + int last_y; /* Last row decoded */ + + int state; /* state flags */ + + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ +} WebPState; + +#define LState(tif) ((WebPState*) (tif)->tif_data) +#define DecoderState(tif) LState(tif) +#define EncoderState(tif) LState(tif) + +static int TWebPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s); +static int TWebPDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s); + +static +int TWebPDatasetWriter(const uint8_t* data, size_t data_size, + const WebPPicture* const picture) +{ + static const char module[] = "TWebPDatasetWriter"; + TIFF* tif = (TIFF*)(picture->custom_ptr); + + if ( (tif->tif_rawcc + (tmsize_t)data_size) > tif->tif_rawdatasize ) { + TIFFErrorExt(tif->tif_clientdata, module, + "Buffer too small by " TIFF_SIZE_FORMAT " bytes.", + (size_t) (tif->tif_rawcc + data_size - tif->tif_rawdatasize)); + return 0; + } else { + _TIFFmemcpy(tif->tif_rawcp, data, data_size); + tif->tif_rawcc += data_size; + tif->tif_rawcp += data_size; + return 1; + } +} + +/* + * Encode a chunk of pixels. + */ +static int +TWebPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) +{ + static const char module[] = "TWebPEncode"; + WebPState *sp = EncoderState(tif); + (void) s; + + assert(sp != NULL); + assert(sp->state == LSTATE_INIT_ENCODE); + + if( (uint64)sp->buffer_offset + + (uint64)cc > sp->buffer_size ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Too many bytes to be written"); + return 0; + } + + memcpy(sp->pBuffer + sp->buffer_offset, + bp, cc); + sp->buffer_offset += (unsigned)cc; + + return 1; + +} + +static int +TWebPDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) +{ + static const char module[] = "WebPDecode"; + VP8StatusCode status = VP8_STATUS_OK; + WebPState *sp = DecoderState(tif); + (void) s; + + assert(sp != NULL); + assert(sp->state == LSTATE_INIT_DECODE); + + if (occ % sp->sDecBuffer.u.RGBA.stride) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Fractional scanlines cannot be read"); + return 0; + } + + status = WebPIAppend(sp->psDecoder, tif->tif_rawcp, tif->tif_rawcc); + + if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) { + if (status == VP8_STATUS_INVALID_PARAM) { + TIFFErrorExt(tif->tif_clientdata, module, + "Invalid parameter used."); + } else if (status == VP8_STATUS_OUT_OF_MEMORY) { + TIFFErrorExt(tif->tif_clientdata, module, + "Out of memory."); + } else { + TIFFErrorExt(tif->tif_clientdata, module, + "Unrecognized error."); + } + return 0; + } else { + int current_y, stride; + uint8_t* buf; + + /* Returns the RGB/A image decoded so far */ + buf = WebPIDecGetRGB(sp->psDecoder, ¤t_y, NULL, NULL, &stride); + + if ((buf != NULL) && + (occ <= stride * (current_y - sp->last_y))) { + memcpy(op, + buf + (sp->last_y * stride), + occ); + + tif->tif_rawcp += tif->tif_rawcc; + tif->tif_rawcc = 0; + sp->last_y += occ / sp->sDecBuffer.u.RGBA.stride; + return 1; + } else { + TIFFErrorExt(tif->tif_clientdata, module, "Unable to decode WebP data."); + return 0; + } + } +} + +static int +TWebPFixupTags(TIFF* tif) +{ + (void) tif; + if (tif->tif_dir.td_planarconfig != PLANARCONFIG_CONTIG) { + static const char module[] = "TWebPFixupTags"; + TIFFErrorExt(tif->tif_clientdata, module, + "TIFF WEBP requires data to be stored contiguously in RGB e.g. RGBRGBRGB " +#if WEBP_ENCODER_ABI_VERSION >= 0x0100 + "or RGBARGBARGBA" +#endif + ); + return 0; + } + return 1; +} + +static int +TWebPSetupDecode(TIFF* tif) +{ + static const char module[] = "WebPSetupDecode"; + uint16 nBitsPerSample = tif->tif_dir.td_bitspersample; + uint16 sampleFormat = tif->tif_dir.td_sampleformat; + + WebPState* sp = DecoderState(tif); + assert(sp != NULL); + + sp->nSamples = tif->tif_dir.td_samplesperpixel; + + /* check band count */ + if ( sp->nSamples != 3 +#if WEBP_ENCODER_ABI_VERSION >= 0x0100 + && sp->nSamples != 4 +#endif + ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "WEBP driver doesn't support %d bands. Must be 3 (RGB) " + #if WEBP_ENCODER_ABI_VERSION >= 0x0100 + "or 4 (RGBA) " + #endif + "bands.", + sp->nSamples ); + return 0; + } + + /* check bits per sample and data type */ + if ((nBitsPerSample != 8) && (sampleFormat != 1)) { + TIFFErrorExt(tif->tif_clientdata, module, + "WEBP driver requires 8 bit unsigned data"); + return 0; + } + + /* if we were last encoding, terminate this mode */ + if (sp->state & LSTATE_INIT_ENCODE) { + WebPPictureFree(&sp->sPicture); + if (sp->pBuffer != NULL) { + _TIFFfree(sp->pBuffer); + sp->pBuffer = NULL; + } + sp->buffer_offset = 0; + sp->state = 0; + } + + sp->state |= LSTATE_INIT_DECODE; + + return 1; +} + +/* +* Setup state for decoding a strip. +*/ +static int +TWebPPreDecode(TIFF* tif, uint16 s) +{ + static const char module[] = "TWebPPreDecode"; + uint32 segment_width, segment_height; + WebPState* sp = DecoderState(tif); + TIFFDirectory* td = &tif->tif_dir; + (void) s; + assert(sp != NULL); + + if (isTiled(tif)) { + segment_width = td->td_tilewidth; + segment_height = td->td_tilelength; + } else { + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (segment_height > td->td_rowsperstrip) + segment_height = td->td_rowsperstrip; + } + + if( (sp->state & LSTATE_INIT_DECODE) == 0 ) + tif->tif_setupdecode(tif); + + if (sp->psDecoder != NULL) { + WebPIDelete(sp->psDecoder); + WebPFreeDecBuffer(&sp->sDecBuffer); + sp->psDecoder = NULL; + } + + sp->last_y = 0; + + WebPInitDecBuffer(&sp->sDecBuffer); + + sp->sDecBuffer.is_external_memory = 0; + sp->sDecBuffer.width = segment_width; + sp->sDecBuffer.height = segment_height; + sp->sDecBuffer.u.RGBA.stride = segment_width * sp->nSamples; + sp->sDecBuffer.u.RGBA.size = segment_width * sp->nSamples * segment_height; + + if (sp->nSamples > 3) { + sp->sDecBuffer.colorspace = MODE_RGBA; + } else { + sp->sDecBuffer.colorspace = MODE_RGB; + } + + sp->psDecoder = WebPINewDecoder(&sp->sDecBuffer); + + if (sp->psDecoder == NULL) { + TIFFErrorExt(tif->tif_clientdata, module, + "Unable to allocate WebP decoder."); + return 0; + } + + return 1; +} + +static int +TWebPSetupEncode(TIFF* tif) +{ + static const char module[] = "WebPSetupEncode"; + uint16 nBitsPerSample = tif->tif_dir.td_bitspersample; + uint16 sampleFormat = tif->tif_dir.td_sampleformat; + + WebPState* sp = EncoderState(tif); + assert(sp != NULL); + + sp->nSamples = tif->tif_dir.td_samplesperpixel; + + /* check band count */ + if ( sp->nSamples != 3 +#if WEBP_ENCODER_ABI_VERSION >= 0x0100 + && sp->nSamples != 4 +#endif + ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "WEBP driver doesn't support %d bands. Must be 3 (RGB) " +#if WEBP_ENCODER_ABI_VERSION >= 0x0100 + "or 4 (RGBA) " +#endif + "bands.", + sp->nSamples ); + return 0; + } + + /* check bits per sample and data type */ + if ((nBitsPerSample != 8) && (sampleFormat != 1)) { + TIFFErrorExt(tif->tif_clientdata, module, + "WEBP driver requires 8 bit unsigned data"); + return 0; + } + + if (sp->state & LSTATE_INIT_DECODE) { + WebPIDelete(sp->psDecoder); + WebPFreeDecBuffer(&sp->sDecBuffer); + sp->psDecoder = NULL; + sp->last_y = 0; + sp->state = 0; + } + + sp->state |= LSTATE_INIT_ENCODE; + + if (!WebPConfigInitInternal(&sp->sEncoderConfig, WEBP_PRESET_DEFAULT, + sp->quality_level, + WEBP_ENCODER_ABI_VERSION)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error creating WebP encoder configuration."); + return 0; + } + +#if WEBP_ENCODER_ABI_VERSION >= 0x0100 + sp->sEncoderConfig.lossless = sp->lossless; +#endif + + if (!WebPValidateConfig(&sp->sEncoderConfig)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error with WebP encoder configuration."); + return 0; + } + + if (!WebPPictureInit(&sp->sPicture)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error initializing WebP picture."); + return 0; + } + + return 1; +} + +/* +* Reset encoding state at the start of a strip. +*/ +static int +TWebPPreEncode(TIFF* tif, uint16 s) +{ + static const char module[] = "TWebPPreEncode"; + uint32 segment_width, segment_height; + WebPState *sp = EncoderState(tif); + TIFFDirectory* td = &tif->tif_dir; + + (void) s; + + assert(sp != NULL); + if( sp->state != LSTATE_INIT_ENCODE ) + tif->tif_setupencode(tif); + + /* + * Set encoding parameters for this strip/tile. + */ + if (isTiled(tif)) { + segment_width = td->td_tilewidth; + segment_height = td->td_tilelength; + } else { + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (segment_height > td->td_rowsperstrip) + segment_height = td->td_rowsperstrip; + } + + if( segment_width > 16383 || segment_height > 16383 ) { + TIFFErrorExt(tif->tif_clientdata, module, + "WEBP maximum image dimensions are 16383 x 16383."); + return 0; + } + + /* set up buffer for raw data */ + /* given above check and that nSamples <= 4, buffer_size is <= 1 GB */ + sp->buffer_size = segment_width * segment_height * sp->nSamples; + sp->pBuffer = _TIFFmalloc(sp->buffer_size); + if( !sp->pBuffer) { + TIFFErrorExt(tif->tif_clientdata, module, "Cannot allocate buffer"); + return 0; + } + sp->buffer_offset = 0; + + sp->sPicture.width = segment_width; + sp->sPicture.height = segment_height; + sp->sPicture.writer = TWebPDatasetWriter; + sp->sPicture.custom_ptr = tif; + + return 1; +} + +/* +* Finish off an encoded strip by flushing it. +*/ +static int +TWebPPostEncode(TIFF* tif) +{ + static const char module[] = "WebPPostEncode"; + int64_t stride; + WebPState *sp = EncoderState(tif); + assert(sp != NULL); + + assert(sp->state == LSTATE_INIT_ENCODE); + + stride = (int64_t)sp->sPicture.width * sp->nSamples; + +#if WEBP_ENCODER_ABI_VERSION >= 0x0100 + if (sp->nSamples == 4) { + if (!WebPPictureImportRGBA(&sp->sPicture, sp->pBuffer, (int)stride)) { + TIFFErrorExt(tif->tif_clientdata, module, + "WebPPictureImportRGBA() failed" ); + return 0; + } + } + else +#endif + if (!WebPPictureImportRGB(&sp->sPicture, sp->pBuffer, (int)stride)) { + TIFFErrorExt(tif->tif_clientdata, module, + "WebPPictureImportRGB() failed"); + return 0; + } + + if (!WebPEncode(&sp->sEncoderConfig, &sp->sPicture)) { + +#if WEBP_ENCODER_ABI_VERSION >= 0x0100 + const char* pszErrorMsg = NULL; + switch(sp->sPicture.error_code) { + case VP8_ENC_ERROR_OUT_OF_MEMORY: + pszErrorMsg = "Out of memory"; break; + case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY: + pszErrorMsg = "Out of memory while flushing bits"; break; + case VP8_ENC_ERROR_NULL_PARAMETER: + pszErrorMsg = "A pointer parameter is NULL"; break; + case VP8_ENC_ERROR_INVALID_CONFIGURATION: + pszErrorMsg = "Configuration is invalid"; break; + case VP8_ENC_ERROR_BAD_DIMENSION: + pszErrorMsg = "Picture has invalid width/height"; break; + case VP8_ENC_ERROR_PARTITION0_OVERFLOW: + pszErrorMsg = "Partition is bigger than 512k. Try using less " + "SEGMENTS, or increase PARTITION_LIMIT value"; + break; + case VP8_ENC_ERROR_PARTITION_OVERFLOW: + pszErrorMsg = "Partition is bigger than 16M"; + break; + case VP8_ENC_ERROR_BAD_WRITE: + pszErrorMsg = "Error while fludshing bytes"; break; + case VP8_ENC_ERROR_FILE_TOO_BIG: + pszErrorMsg = "File is bigger than 4G"; break; + case VP8_ENC_ERROR_USER_ABORT: + pszErrorMsg = "User interrupted"; + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, + "WebPEncode returned an unknown error code: %d", + sp->sPicture.error_code); + pszErrorMsg = "Unknown WebP error type."; + break; + } + TIFFErrorExt(tif->tif_clientdata, module, + "WebPEncode() failed : %s", pszErrorMsg); +#else + TIFFErrorExt(tif->tif_clientdata, module, + "Error in WebPEncode()"); +#endif + return 0; + } + + sp->sPicture.custom_ptr = NULL; + + if (!TIFFFlushData1(tif)) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Error flushing TIFF WebP encoder."); + return 0; + } + + return 1; +} + +static void +TWebPCleanup(TIFF* tif) +{ + WebPState* sp = LState(tif); + + assert(sp != 0); + + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; + + if (sp->state & LSTATE_INIT_ENCODE) { + WebPPictureFree(&sp->sPicture); + } + + if (sp->psDecoder != NULL) { + WebPIDelete(sp->psDecoder); + WebPFreeDecBuffer(&sp->sDecBuffer); + sp->psDecoder = NULL; + sp->last_y = 0; + } + + if (sp->pBuffer != NULL) { + _TIFFfree(sp->pBuffer); + sp->pBuffer = NULL; + } + + if (tif->tif_data) { + _TIFFfree(tif->tif_data); + tif->tif_data = NULL; + } + + _TIFFSetDefaultCompressionState(tif); +} + +static int +TWebPVSetField(TIFF* tif, uint32 tag, va_list ap) +{ + static const char module[] = "WebPVSetField"; + WebPState* sp = LState(tif); + + switch (tag) { + case TIFFTAG_WEBP_LEVEL: + sp->quality_level = (int) va_arg(ap, int); + if( sp->quality_level <= 0 || + sp->quality_level > 100.0f ) { + TIFFWarningExt(tif->tif_clientdata, module, + "WEBP_LEVEL should be between 1 and 100"); + } + return 1; + case TIFFTAG_WEBP_LOSSLESS: + #if WEBP_ENCODER_ABI_VERSION >= 0x0100 + sp->lossless = va_arg(ap, int); + return 1; + #else + TIFFErrorExt(tif->tif_clientdata, module, + "Need to upgrade WEBP driver, this version doesn't support " + "lossless compression."); + return 0; + #endif + default: + return (*sp->vsetparent)(tif, tag, ap); + } + /*NOTREACHED*/ +} + +static int +TWebPVGetField(TIFF* tif, uint32 tag, va_list ap) +{ + WebPState* sp = LState(tif); + + switch (tag) { + case TIFFTAG_WEBP_LEVEL: + *va_arg(ap, int*) = sp->quality_level; + break; + case TIFFTAG_WEBP_LOSSLESS: + *va_arg(ap, int*) = sp->lossless; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return 1; +} + +static const TIFFField TWebPFields[] = { + { TIFFTAG_WEBP_LEVEL, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, + TIFF_SETGET_UNDEFINED, + FIELD_PSEUDO, TRUE, FALSE, "WEBP quality", NULL }, + { TIFFTAG_WEBP_LOSSLESS, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, + TIFF_SETGET_UNDEFINED, + FIELD_PSEUDO, TRUE, FALSE, "WEBP lossless/lossy", NULL + }, +}; + +int +TIFFInitWebP(TIFF* tif, int scheme) +{ + static const char module[] = "TIFFInitWebP"; + WebPState* sp; + + assert( scheme == COMPRESSION_WEBP ); + + /* + * Merge codec-specific tag information. + */ + if ( !_TIFFMergeFields(tif, TWebPFields, TIFFArrayCount(TWebPFields)) ) { + TIFFErrorExt(tif->tif_clientdata, module, + "Merging WebP codec-specific tags failed"); + return 0; + } + + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (uint8*) _TIFFmalloc(sizeof(WebPState)); + if (tif->tif_data == NULL) + goto bad; + sp = LState(tif); + + /* + * Override parent get/set field methods. + */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = TWebPVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = TWebPVSetField; /* hook for codec tags */ + + /* Default values for codec-specific fields */ + sp->quality_level = 75.0f; /* default comp. level */ + sp->lossless = 0; /* default to false */ + sp->state = 0; + sp->nSamples = 0; + sp->psDecoder = NULL; + sp->last_y = 0; + + sp->buffer_offset = 0; + sp->pBuffer = NULL; + + /* + * Install codec methods. + * Notes: + * encoderow is not supported + */ + tif->tif_fixuptags = TWebPFixupTags; + tif->tif_setupdecode = TWebPSetupDecode; + tif->tif_predecode = TWebPPreDecode; + tif->tif_decoderow = TWebPDecode; + tif->tif_decodestrip = TWebPDecode; + tif->tif_decodetile = TWebPDecode; + tif->tif_setupencode = TWebPSetupEncode; + tif->tif_preencode = TWebPPreEncode; + tif->tif_postencode = TWebPPostEncode; + tif->tif_encoderow = TWebPEncode; + tif->tif_encodestrip = TWebPEncode; + tif->tif_encodetile = TWebPEncode; + tif->tif_cleanup = TWebPCleanup; + + return 1; +bad: + TIFFErrorExt(tif->tif_clientdata, module, + "No space for WebP state block"); + return 0; +} + +#endif /* WEBP_SUPPORT */ diff --git a/3rdparty/libtiff/tif_win32.c b/3rdparty/libtiff/tif_win32.c index 090baed871..088880e7c4 100644 --- a/3rdparty/libtiff/tif_win32.c +++ b/3rdparty/libtiff/tif_win32.c @@ -1,5 +1,3 @@ -/* $Id: tif_win32.c,v 1.42 2017-01-11 19:02:49 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -407,60 +405,21 @@ _TIFFmemcmp(const void* p1, const void* p2, tmsize_t c) static void Win32WarningHandler(const char* module, const char* fmt, va_list ap) { -#ifndef TIF_PLATFORM_CONSOLE - LPTSTR szTitle; - LPTSTR szTmp; - LPCTSTR szTitleText = "%s Warning"; - LPCTSTR szDefaultModule = "LIBTIFF"; - LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module; - SIZE_T nBufSize = (strlen(szTmpModule) + - strlen(szTitleText) + strlen(fmt) + 256)*sizeof(char); - - if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, nBufSize)) == NULL) - return; - sprintf(szTitle, szTitleText, szTmpModule); - szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char); - vsnprintf(szTmp, nBufSize-(strlen(szTitle)+2)*sizeof(char), fmt, ap); - MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONINFORMATION); - LocalFree(szTitle); - - return; -#else if (module != NULL) fprintf(stderr, "%s: ", module); fprintf(stderr, "Warning, "); vfprintf(stderr, fmt, ap); fprintf(stderr, ".\n"); -#endif } TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler; static void Win32ErrorHandler(const char* module, const char* fmt, va_list ap) { -#ifndef TIF_PLATFORM_CONSOLE - LPTSTR szTitle; - LPTSTR szTmp; - LPCTSTR szTitleText = "%s Error"; - LPCTSTR szDefaultModule = "LIBTIFF"; - LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module; - SIZE_T nBufSize = (strlen(szTmpModule) + - strlen(szTitleText) + strlen(fmt) + 256)*sizeof(char); - - if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, nBufSize)) == NULL) - return; - sprintf(szTitle, szTitleText, szTmpModule); - szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char); - vsnprintf(szTmp, nBufSize-(strlen(szTitle)+2)*sizeof(char), fmt, ap); - MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION); - LocalFree(szTitle); - return; -#else if (module != NULL) fprintf(stderr, "%s: ", module); vfprintf(stderr, fmt, ap); fprintf(stderr, ".\n"); -#endif } TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler; diff --git a/3rdparty/libtiff/tif_write.c b/3rdparty/libtiff/tif_write.c index 4c216ec200..a31ecd12c1 100644 --- a/3rdparty/libtiff/tif_write.c +++ b/3rdparty/libtiff/tif_write.c @@ -1,5 +1,3 @@ -/* $Id: tif_write.c,v 1.46 2016-12-03 21:57:44 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -540,9 +538,11 @@ TIFFSetupStrips(TIFF* tif) if (td->td_planarconfig == PLANARCONFIG_SEPARATE) td->td_stripsperimage /= td->td_samplesperpixel; td->td_stripoffset = (uint64 *) - _TIFFmalloc(td->td_nstrips * sizeof (uint64)); + _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64), + "for \"StripOffsets\" array"); td->td_stripbytecount = (uint64 *) - _TIFFmalloc(td->td_nstrips * sizeof (uint64)); + _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64), + "for \"StripByteCounts\" array"); if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) return (0); /* diff --git a/3rdparty/libtiff/tif_zip.c b/3rdparty/libtiff/tif_zip.c index 42943fbb14..9d4bceb179 100644 --- a/3rdparty/libtiff/tif_zip.c +++ b/3rdparty/libtiff/tif_zip.c @@ -1,5 +1,3 @@ -/* $Id: tif_zip.c,v 1.37 2017-05-10 15:21:16 erouault Exp $ */ - /* * Copyright (c) 1995-1997 Sam Leffler * Copyright (c) 1995-1997 Silicon Graphics, Inc. diff --git a/3rdparty/libtiff/tif_zstd.c b/3rdparty/libtiff/tif_zstd.c new file mode 100644 index 0000000000..21c935e2da --- /dev/null +++ b/3rdparty/libtiff/tif_zstd.c @@ -0,0 +1,440 @@ +/* +* Copyright (c) 2017, Planet Labs +* Author: +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, provided +* that (i) the above copyright notices and this permission notice appear in +* all copies of the software and related documentation, and (ii) the names of +* Sam Leffler and Silicon Graphics may not be used in any advertising or +* publicity relating to the software without the specific, prior written +* permission of Sam Leffler and Silicon Graphics. +* +* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, +* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +* +* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR +* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, +* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF +* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +* OF THIS SOFTWARE. +*/ + +#include "tiffiop.h" +#ifdef ZSTD_SUPPORT +/* +* TIFF Library. +* +* ZSTD Compression Support +* +*/ + +#include "tif_predict.h" +#include "zstd.h" + +#include + +/* +* State block for each open TIFF file using ZSTD compression/decompression. +*/ +typedef struct { + TIFFPredictorState predict; + ZSTD_DStream* dstream; + ZSTD_CStream* cstream; + int compression_level; /* compression level */ + ZSTD_outBuffer out_buffer; + int state; /* state flags */ +#define LSTATE_INIT_DECODE 0x01 +#define LSTATE_INIT_ENCODE 0x02 + + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ +} ZSTDState; + +#define LState(tif) ((ZSTDState*) (tif)->tif_data) +#define DecoderState(tif) LState(tif) +#define EncoderState(tif) LState(tif) + +static int ZSTDEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s); +static int ZSTDDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s); + +static int +ZSTDFixupTags(TIFF* tif) +{ + (void) tif; + return 1; +} + +static int +ZSTDSetupDecode(TIFF* tif) +{ + ZSTDState* sp = DecoderState(tif); + + assert(sp != NULL); + + /* if we were last encoding, terminate this mode */ + if (sp->state & LSTATE_INIT_ENCODE) { + ZSTD_freeCStream(sp->cstream); + sp->cstream = NULL; + sp->state = 0; + } + + sp->state |= LSTATE_INIT_DECODE; + return 1; +} + +/* +* Setup state for decoding a strip. +*/ +static int +ZSTDPreDecode(TIFF* tif, uint16 s) +{ + static const char module[] = "ZSTDPreDecode"; + ZSTDState* sp = DecoderState(tif); + size_t zstd_ret; + + (void) s; + assert(sp != NULL); + + if( (sp->state & LSTATE_INIT_DECODE) == 0 ) + tif->tif_setupdecode(tif); + + if( sp->dstream ) + { + ZSTD_freeDStream(sp->dstream); + sp->dstream = NULL; + } + + sp->dstream = ZSTD_createDStream(); + if( sp->dstream == NULL ) { + TIFFErrorExt(tif->tif_clientdata, module, + "Cannot allocate decompression stream"); + return 0; + } + zstd_ret = ZSTD_initDStream(sp->dstream); + if( ZSTD_isError(zstd_ret) ) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error in ZSTD_initDStream(): %s", + ZSTD_getErrorName(zstd_ret)); + return 0; + } + + return 1; +} + +static int +ZSTDDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) +{ + static const char module[] = "ZSTDDecode"; + ZSTDState* sp = DecoderState(tif); + ZSTD_inBuffer in_buffer; + ZSTD_outBuffer out_buffer; + size_t zstd_ret; + + (void) s; + assert(sp != NULL); + assert(sp->state == LSTATE_INIT_DECODE); + + in_buffer.src = tif->tif_rawcp; + in_buffer.size = (size_t) tif->tif_rawcc; + in_buffer.pos = 0; + + out_buffer.dst = op; + out_buffer.size = (size_t) occ; + out_buffer.pos = 0; + + do { + zstd_ret = ZSTD_decompressStream(sp->dstream, &out_buffer, + &in_buffer); + if( ZSTD_isError(zstd_ret) ) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error in ZSTD_decompressStream(): %s", + ZSTD_getErrorName(zstd_ret)); + return 0; + } + } while( zstd_ret != 0 && + in_buffer.pos < in_buffer.size && + out_buffer.pos < out_buffer.size ); + + if (out_buffer.pos < (size_t)occ) { + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data at scanline %lu (short %lu bytes)", + (unsigned long) tif->tif_row, + (unsigned long) (size_t)occ - out_buffer.pos); + return 0; + } + + tif->tif_rawcp += in_buffer.pos; + tif->tif_rawcc -= in_buffer.pos; + + return 1; +} + +static int +ZSTDSetupEncode(TIFF* tif) +{ + ZSTDState* sp = EncoderState(tif); + + assert(sp != NULL); + if (sp->state & LSTATE_INIT_DECODE) { + ZSTD_freeDStream(sp->dstream); + sp->dstream = NULL; + sp->state = 0; + } + + sp->state |= LSTATE_INIT_ENCODE; + return 1; +} + +/* +* Reset encoding state at the start of a strip. +*/ +static int +ZSTDPreEncode(TIFF* tif, uint16 s) +{ + static const char module[] = "ZSTDPreEncode"; + ZSTDState *sp = EncoderState(tif); + size_t zstd_ret; + + (void) s; + assert(sp != NULL); + if( sp->state != LSTATE_INIT_ENCODE ) + tif->tif_setupencode(tif); + + if (sp->cstream) { + ZSTD_freeCStream(sp->cstream); + sp->cstream = NULL; + } + sp->cstream = ZSTD_createCStream(); + if( sp->cstream == NULL ) { + TIFFErrorExt(tif->tif_clientdata, module, + "Cannot allocate compression stream"); + return 0; + } + + zstd_ret = ZSTD_initCStream(sp->cstream, sp->compression_level); + if( ZSTD_isError(zstd_ret) ) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error in ZSTD_initCStream(): %s", + ZSTD_getErrorName(zstd_ret)); + return 0; + } + + sp->out_buffer.dst = tif->tif_rawdata; + sp->out_buffer.size = (size_t)tif->tif_rawdatasize; + sp->out_buffer.pos = 0; + + return 1; +} + +/* +* Encode a chunk of pixels. +*/ +static int +ZSTDEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) +{ + static const char module[] = "ZSTDEncode"; + ZSTDState *sp = EncoderState(tif); + ZSTD_inBuffer in_buffer; + size_t zstd_ret; + + assert(sp != NULL); + assert(sp->state == LSTATE_INIT_ENCODE); + + (void) s; + + in_buffer.src = bp; + in_buffer.size = (size_t)cc; + in_buffer.pos = 0; + + do { + zstd_ret = ZSTD_compressStream(sp->cstream, &sp->out_buffer, + &in_buffer); + if( ZSTD_isError(zstd_ret) ) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error in ZSTD_compressStream(): %s", + ZSTD_getErrorName(zstd_ret)); + return 0; + } + if( sp->out_buffer.pos == sp->out_buffer.size ) { + tif->tif_rawcc = tif->tif_rawdatasize; + TIFFFlushData1(tif); + sp->out_buffer.dst = tif->tif_rawcp; + sp->out_buffer.pos = 0; + } + } while( in_buffer.pos < in_buffer.size ); + + return 1; +} + +/* +* Finish off an encoded strip by flushing it. +*/ +static int +ZSTDPostEncode(TIFF* tif) +{ + static const char module[] = "ZSTDPostEncode"; + ZSTDState *sp = EncoderState(tif); + size_t zstd_ret; + + do { + zstd_ret = ZSTD_endStream(sp->cstream, &sp->out_buffer); + if( ZSTD_isError(zstd_ret) ) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error in ZSTD_endStream(): %s", + ZSTD_getErrorName(zstd_ret)); + return 0; + } + if( sp->out_buffer.pos > 0 ) { + tif->tif_rawcc = sp->out_buffer.pos; + TIFFFlushData1(tif); + sp->out_buffer.dst = tif->tif_rawcp; + sp->out_buffer.pos = 0; + } + } while (zstd_ret != 0); + return 1; +} + +static void +ZSTDCleanup(TIFF* tif) +{ + ZSTDState* sp = LState(tif); + + assert(sp != 0); + + (void)TIFFPredictorCleanup(tif); + + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; + + if (sp->dstream) { + ZSTD_freeDStream(sp->dstream); + sp->dstream = NULL; + } + if (sp->cstream) { + ZSTD_freeCStream(sp->cstream); + sp->cstream = NULL; + } + _TIFFfree(sp); + tif->tif_data = NULL; + + _TIFFSetDefaultCompressionState(tif); +} + +static int +ZSTDVSetField(TIFF* tif, uint32 tag, va_list ap) +{ + static const char module[] = "ZSTDVSetField"; + ZSTDState* sp = LState(tif); + + switch (tag) { + case TIFFTAG_ZSTD_LEVEL: + sp->compression_level = (int) va_arg(ap, int); + if( sp->compression_level <= 0 || + sp->compression_level > ZSTD_maxCLevel() ) + { + TIFFWarningExt(tif->tif_clientdata, module, + "ZSTD_LEVEL should be between 1 and %d", + ZSTD_maxCLevel()); + } + return 1; + default: + return (*sp->vsetparent)(tif, tag, ap); + } + /*NOTREACHED*/ +} + +static int +ZSTDVGetField(TIFF* tif, uint32 tag, va_list ap) +{ + ZSTDState* sp = LState(tif); + + switch (tag) { + case TIFFTAG_ZSTD_LEVEL: + *va_arg(ap, int*) = sp->compression_level; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return 1; +} + +static const TIFFField ZSTDFields[] = { + { TIFFTAG_ZSTD_LEVEL, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, + TIFF_SETGET_UNDEFINED, + FIELD_PSEUDO, TRUE, FALSE, "ZSTD compression_level", NULL }, +}; + +int +TIFFInitZSTD(TIFF* tif, int scheme) +{ + static const char module[] = "TIFFInitZSTD"; + ZSTDState* sp; + + assert( scheme == COMPRESSION_ZSTD ); + + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFields(tif, ZSTDFields, TIFFArrayCount(ZSTDFields))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Merging ZSTD codec-specific tags failed"); + return 0; + } + + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (uint8*) _TIFFmalloc(sizeof(ZSTDState)); + if (tif->tif_data == NULL) + goto bad; + sp = LState(tif); + + /* + * Override parent get/set field methods. + */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = ZSTDVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = ZSTDVSetField; /* hook for codec tags */ + + /* Default values for codec-specific fields */ + sp->compression_level = 9; /* default comp. level */ + sp->state = 0; + sp->dstream = 0; + sp->cstream = 0; + sp->out_buffer.dst = NULL; + sp->out_buffer.size = 0; + sp->out_buffer.pos = 0; + + /* + * Install codec methods. + */ + tif->tif_fixuptags = ZSTDFixupTags; + tif->tif_setupdecode = ZSTDSetupDecode; + tif->tif_predecode = ZSTDPreDecode; + tif->tif_decoderow = ZSTDDecode; + tif->tif_decodestrip = ZSTDDecode; + tif->tif_decodetile = ZSTDDecode; + tif->tif_setupencode = ZSTDSetupEncode; + tif->tif_preencode = ZSTDPreEncode; + tif->tif_postencode = ZSTDPostEncode; + tif->tif_encoderow = ZSTDEncode; + tif->tif_encodestrip = ZSTDEncode; + tif->tif_encodetile = ZSTDEncode; + tif->tif_cleanup = ZSTDCleanup; + /* + * Setup predictor setup. + */ + (void) TIFFPredictorInit(tif); + return 1; +bad: + TIFFErrorExt(tif->tif_clientdata, module, + "No space for ZSTD state block"); + return 0; +} +#endif /* ZSTD_SUPPORT */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tiff.h b/3rdparty/libtiff/tiff.h index fb39634c4b..5b0a0c90f6 100644 --- a/3rdparty/libtiff/tiff.h +++ b/3rdparty/libtiff/tiff.h @@ -1,5 +1,3 @@ -/* $Id: tiff.h,v 1.70 2016-01-23 21:20:34 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -189,7 +187,11 @@ typedef enum { #define COMPRESSION_SGILOG 34676 /* SGI Log Luminance RLE */ #define COMPRESSION_SGILOG24 34677 /* SGI Log 24-bit packed */ #define COMPRESSION_JP2000 34712 /* Leadtools JPEG2000 */ +#define COMPRESSION_LERC 34887 /* ESRI Lerc codec: https://github.com/Esri/lerc */ +/* compression codes 34887-34889 are reserved for ESRI */ #define COMPRESSION_LZMA 34925 /* LZMA2 */ +#define COMPRESSION_ZSTD 50000 /* ZSTD: WARNING not registered in Adobe-maintained registry */ +#define COMPRESSION_WEBP 50001 /* WEBP: WARNING not registered in Adobe-maintained registry */ #define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */ #define PHOTOMETRIC_MINISWHITE 0 /* min value is white */ #define PHOTOMETRIC_MINISBLACK 1 /* min value is black */ @@ -450,6 +452,8 @@ typedef enum { /* tag 34929 is a private tag registered to FedEx */ #define TIFFTAG_FEDEX_EDR 34929 /* unknown use */ #define TIFFTAG_INTEROPERABILITYIFD 40965 /* Pointer to Interoperability private directory */ +/* tags 50674 to 50677 are reserved for ESRI */ +#define TIFFTAG_LERC_PARAMETERS 50674 /* Stores LERC version and additional compression method */ /* Adobe Digital Negative (DNG) format tags */ #define TIFFTAG_DNGVERSION 50706 /* &DNG version number */ #define TIFFTAG_DNGBACKWARDVERSION 50707 /* &DNG compatibility version */ @@ -603,6 +607,16 @@ typedef enum { #define TIFFTAG_PERSAMPLE 65563 /* interface for per sample tags */ #define PERSAMPLE_MERGED 0 /* present as a single value */ #define PERSAMPLE_MULTI 1 /* present as multiple values */ +#define TIFFTAG_ZSTD_LEVEL 65564 /* ZSTD compression level */ +#define TIFFTAG_LERC_VERSION 65565 /* LERC version */ +#define LERC_VERSION_2_4 4 +#define TIFFTAG_LERC_ADD_COMPRESSION 65566 /* LERC additional compression */ +#define LERC_ADD_COMPRESSION_NONE 0 +#define LERC_ADD_COMPRESSION_DEFLATE 1 +#define LERC_ADD_COMPRESSION_ZSTD 2 +#define TIFFTAG_LERC_MAXZERROR 65567 /* LERC maximum error */ +#define TIFFTAG_WEBP_LEVEL 65568 /* WebP compression level: WARNING not registered in Adobe-maintained registry */ +#define TIFFTAG_WEBP_LOSSLESS 65569 /* WebP lossless/lossy : WARNING not registered in Adobe-maintained registry */ /* * EXIF tags diff --git a/3rdparty/libtiff/tiffconf.h.cmake.in b/3rdparty/libtiff/tiffconf.h.cmake.in index de8a807eb1..59542f1e8c 100644 --- a/3rdparty/libtiff/tiffconf.h.cmake.in +++ b/3rdparty/libtiff/tiffconf.h.cmake.in @@ -40,15 +40,6 @@ /* Pointer difference type */ #define TIFF_PTRDIFF_T @TIFF_PTRDIFF_T@ -/* Define to 1 if the system has the type `int16'. */ -#cmakedefine HAVE_INT16 1 - -/* Define to 1 if the system has the type `int32'. */ -#cmakedefine HAVE_INT32 1 - -/* Define to 1 if the system has the type `int8'. */ -#cmakedefine HAVE_INT8 1 - /* Compatibility stuff. */ /* Define as 0 or 1 according to the floating point format suported by the diff --git a/3rdparty/libtiff/tiffio.h b/3rdparty/libtiff/tiffio.h index ef61b5c06a..31c2e676e7 100644 --- a/3rdparty/libtiff/tiffio.h +++ b/3rdparty/libtiff/tiffio.h @@ -1,5 +1,3 @@ -/* $Id: tiffio.h,v 1.94 2017-01-11 19:02:49 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -52,7 +50,7 @@ typedef struct tiff TIFF; * promoted type (i.e. one of int, unsigned int, pointer, * or double) and because we defined pseudo-tags that are * outside the range of legal Aldus-assigned tags. - * NB: tsize_t is int32 and not uint32 because some functions + * NB: tsize_t is signed and not unsigned because some functions * return -1. * NB: toff_t is not off_t for many reasons; TIFFs max out at * 32-bit file offsets, and BigTIFF maxes out at 64-bit diff --git a/3rdparty/libtiff/tiffio.hxx b/3rdparty/libtiff/tiffio.hxx index ed994f1156..df2cbbceb7 100644 --- a/3rdparty/libtiff/tiffio.hxx +++ b/3rdparty/libtiff/tiffio.hxx @@ -1,5 +1,3 @@ -/* $Id: tiffio.hxx,v 1.3 2010-06-08 18:55:15 bfriesen Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -33,6 +31,7 @@ #include #include "tiff.h" +#include "tiffio.h" extern TIFF* TIFFStreamOpen(const char*, std::ostream *); extern TIFF* TIFFStreamOpen(const char*, std::istream *); diff --git a/3rdparty/libtiff/tiffiop.h b/3rdparty/libtiff/tiffiop.h index daa291c083..186c291f5d 100644 --- a/3rdparty/libtiff/tiffiop.h +++ b/3rdparty/libtiff/tiffiop.h @@ -1,5 +1,3 @@ -/* $Id: tiffiop.h,v 1.95 2017-09-07 14:02:52 erouault Exp $ */ - /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. @@ -72,6 +70,7 @@ extern int snprintf(char* str, size_t size, const char* format, ...); #endif #define streq(a,b) (strcmp(a,b) == 0) +#define strneq(a,b,n) (strncmp(a,b,n) == 0) #ifndef TRUE #define TRUE 1 @@ -314,11 +313,15 @@ typedef size_t TIFFIOSize_t; #define _TIFF_off_t off_t #endif -#if __clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ >= 8) +#if defined(__has_attribute) && defined(__clang__) +#if __has_attribute(no_sanitize) #define TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW __attribute__((no_sanitize("unsigned-integer-overflow"))) #else #define TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW #endif +#else +#define TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW +#endif #if defined(__cplusplus) @@ -424,6 +427,12 @@ extern int TIFFInitSGILog(TIFF*, int); #ifdef LZMA_SUPPORT extern int TIFFInitLZMA(TIFF*, int); #endif +#ifdef ZSTD_SUPPORT +extern int TIFFInitZSTD(TIFF*, int); +#endif +#ifdef WEBP_SUPPORT +extern int TIFFInitWebP(TIFF*, int); +#endif #ifdef VMS extern const TIFFCodec _TIFFBuiltinCODECS[]; #else diff --git a/3rdparty/libtiff/tiffvers.h b/3rdparty/libtiff/tiffvers.h index 7c415740f6..403d61be04 100644 --- a/3rdparty/libtiff/tiffvers.h +++ b/3rdparty/libtiff/tiffvers.h @@ -1,4 +1,4 @@ -#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.9\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc." +#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.10\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc." /* * This define can be used in code that requires * compilation-related definitions specific to a @@ -6,4 +6,4 @@ * version checking should be done based on the * string returned by TIFFGetVersion. */ -#define TIFFLIB_VERSION 20171118 +#define TIFFLIB_VERSION 20181110 From 183c0fcab199b32774d1e4f1261f8b3a4d12777f Mon Sep 17 00:00:00 2001 From: Liubov Batanina Date: Wed, 13 Feb 2019 15:59:51 +0300 Subject: [PATCH 09/21] Changed condition for resize and lrn layers --- modules/dnn/perf/perf_net.cpp | 3 +-- modules/dnn/src/layers/lrn_layer.cpp | 2 +- modules/dnn/src/layers/normalize_bbox_layer.cpp | 4 ++-- modules/dnn/src/layers/resize_layer.cpp | 5 ++--- modules/dnn/test/test_backends.cpp | 2 +- modules/dnn/test/test_tf_importer.cpp | 2 -- modules/dnn/test/test_torch_importer.cpp | 4 +--- 7 files changed, 8 insertions(+), 14 deletions(-) diff --git a/modules/dnn/perf/perf_net.cpp b/modules/dnn/perf/perf_net.cpp index d06689a7fb..54388fda34 100644 --- a/modules/dnn/perf/perf_net.cpp +++ b/modules/dnn/perf/perf_net.cpp @@ -124,8 +124,7 @@ PERF_TEST_P_(DNNTestNetwork, SSD) PERF_TEST_P_(DNNTestNetwork, OpenFace) { if (backend == DNN_BACKEND_HALIDE || - (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16) || - (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)) + (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)) throw SkipTestException(""); processNet("dnn/openface_nn4.small2.v1.t7", "", "", Mat(cv::Size(96, 96), CV_32FC3)); diff --git a/modules/dnn/src/layers/lrn_layer.cpp b/modules/dnn/src/layers/lrn_layer.cpp index f34faff338..145793959b 100644 --- a/modules/dnn/src/layers/lrn_layer.cpp +++ b/modules/dnn/src/layers/lrn_layer.cpp @@ -92,7 +92,7 @@ public: { return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_HALIDE || - (backendId == DNN_BACKEND_INFERENCE_ENGINE && (preferableTarget != DNN_TARGET_MYRIAD || type == CHANNEL_NRM)); + backendId == DNN_BACKEND_INFERENCE_ENGINE; } #ifdef HAVE_OPENCL diff --git a/modules/dnn/src/layers/normalize_bbox_layer.cpp b/modules/dnn/src/layers/normalize_bbox_layer.cpp index 53a5f407d0..9a3162859a 100644 --- a/modules/dnn/src/layers/normalize_bbox_layer.cpp +++ b/modules/dnn/src/layers/normalize_bbox_layer.cpp @@ -65,9 +65,9 @@ public: { if (backendId == DNN_BACKEND_INFERENCE_ENGINE) { - if (pnorm != 2) { + if (pnorm != 2) return false; - } + return preferableTarget == DNN_TARGET_MYRIAD ? !acrossSpatial : startAxis == 1; } return backendId == DNN_BACKEND_OPENCV; diff --git a/modules/dnn/src/layers/resize_layer.cpp b/modules/dnn/src/layers/resize_layer.cpp index 03d806ad2c..249b689341 100644 --- a/modules/dnn/src/layers/resize_layer.cpp +++ b/modules/dnn/src/layers/resize_layer.cpp @@ -54,12 +54,11 @@ public: #ifdef HAVE_INF_ENGINE if (backendId == DNN_BACKEND_INFERENCE_ENGINE) { - return (interpolation == "nearest" && preferableTarget != DNN_TARGET_MYRIAD) || + return (interpolation == "nearest" && scaleWidth == scaleHeight) || (interpolation == "bilinear" && INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R4)); } - else #endif - return backendId == DNN_BACKEND_OPENCV; + return backendId == DNN_BACKEND_OPENCV; } virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE diff --git a/modules/dnn/test/test_backends.cpp b/modules/dnn/test/test_backends.cpp index 66e80a1fe9..1d97cfc088 100644 --- a/modules/dnn/test/test_backends.cpp +++ b/modules/dnn/test/test_backends.cpp @@ -226,7 +226,7 @@ TEST_P(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages) TEST_P(DNNTestNetwork, OpenFace) { #if defined(INF_ENGINE_RELEASE) -#if (INF_ENGINE_RELEASE < 2018030000) +#if (INF_ENGINE_RELEASE < 2018030000 || INF_ENGINE_RELEASE == 2018050000) if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) throw SkipTestException(""); #elif INF_ENGINE_RELEASE < 2018040000 diff --git a/modules/dnn/test/test_tf_importer.cpp b/modules/dnn/test/test_tf_importer.cpp index 7ddda7f03a..b722ffc964 100644 --- a/modules/dnn/test/test_tf_importer.cpp +++ b/modules/dnn/test/test_tf_importer.cpp @@ -558,8 +558,6 @@ TEST_P(Test_TensorFlow_layers, split) TEST_P(Test_TensorFlow_layers, resize_nearest_neighbor) { - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_MYRIAD) - throw SkipTestException(""); runTensorFlowNet("resize_nearest_neighbor"); runTensorFlowNet("keras_upsampling2d"); } diff --git a/modules/dnn/test/test_torch_importer.cpp b/modules/dnn/test/test_torch_importer.cpp index 99695ca031..547e9f775e 100644 --- a/modules/dnn/test/test_torch_importer.cpp +++ b/modules/dnn/test/test_torch_importer.cpp @@ -272,13 +272,11 @@ class Test_Torch_nets : public DNNTestLayer {}; TEST_P(Test_Torch_nets, OpenFace_accuracy) { -#if defined(INF_ENGINE_RELEASE) && (INF_ENGINE_RELEASE < 2018030000) +#if defined(INF_ENGINE_RELEASE) && (INF_ENGINE_RELEASE < 2018030000 || INF_ENGINE_RELEASE == 2018050000) if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD) throw SkipTestException(""); #endif checkBackend(); - if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16 && INF_ENGINE_RELEASE != 2018050000) - throw SkipTestException(""); const string model = findDataFile("dnn/openface_nn4.small2.v1.t7", false); Net net = readNetFromTorch(model); From af8a3a0b66cbd99d5965a40635676130880aee1a Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 13 Feb 2019 15:55:02 +0300 Subject: [PATCH 10/21] core: clone count_non_zero.simd.hpp --- modules/core/src/{count_non_zero.cpp => count_non_zero.simd.hpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/core/src/{count_non_zero.cpp => count_non_zero.simd.hpp} (100%) diff --git a/modules/core/src/count_non_zero.cpp b/modules/core/src/count_non_zero.simd.hpp similarity index 100% rename from modules/core/src/count_non_zero.cpp rename to modules/core/src/count_non_zero.simd.hpp From 439e43a027bc223634edae95994309ab0bec3ff4 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 13 Feb 2019 15:55:42 +0300 Subject: [PATCH 11/21] core: clone count_non_zero.dispatch.cpp --- .../core/src/{count_non_zero.cpp => count_non_zero.dispatch.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/core/src/{count_non_zero.cpp => count_non_zero.dispatch.cpp} (100%) diff --git a/modules/core/src/count_non_zero.cpp b/modules/core/src/count_non_zero.dispatch.cpp similarity index 100% rename from modules/core/src/count_non_zero.cpp rename to modules/core/src/count_non_zero.dispatch.cpp From e3633ec4a2d0ce7158c5336738c6ec262a80fa78 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 13 Feb 2019 18:27:55 +0300 Subject: [PATCH 12/21] core: dispatch count_non_zero --- modules/core/CMakeLists.txt | 1 + modules/core/src/count_non_zero.dispatch.cpp | 192 +------------------ modules/core/src/count_non_zero.simd.hpp | 178 ++--------------- 3 files changed, 24 insertions(+), 347 deletions(-) diff --git a/modules/core/CMakeLists.txt b/modules/core/CMakeLists.txt index bfa2fd1d98..9559783d94 100644 --- a/modules/core/CMakeLists.txt +++ b/modules/core/CMakeLists.txt @@ -5,6 +5,7 @@ ocv_add_dispatched_file(stat SSE4_2 AVX2) ocv_add_dispatched_file(arithm SSE2 SSE4_1 AVX2 VSX3) ocv_add_dispatched_file(convert SSE2 AVX2) ocv_add_dispatched_file(convert_scale SSE2 AVX2) +ocv_add_dispatched_file(count_non_zero SSE2 AVX2) ocv_add_dispatched_file(sum SSE2 AVX2) # dispatching for accuracy tests diff --git a/modules/core/src/count_non_zero.dispatch.cpp b/modules/core/src/count_non_zero.dispatch.cpp index 202e7b846d..d0ce1ef989 100644 --- a/modules/core/src/count_non_zero.dispatch.cpp +++ b/modules/core/src/count_non_zero.dispatch.cpp @@ -7,190 +7,18 @@ #include "opencl_kernels_core.hpp" #include "stat.hpp" -namespace cv { - -template -static int countNonZero_(const T* src, int len ) -{ - int i=0, nz = 0; - #if CV_ENABLE_UNROLLED - for(; i <= len - 4; i += 4 ) - nz += (src[i] != 0) + (src[i+1] != 0) + (src[i+2] != 0) + (src[i+3] != 0); - #endif - for( ; i < len; i++ ) - nz += src[i] != 0; - return nz; -} - -static int countNonZero8u( const uchar* src, int len ) -{ - int i=0, nz = 0; -#if CV_SIMD - int len0 = len & -v_uint8::nlanes; - v_uint8 v_zero = vx_setzero_u8(); - v_uint8 v_one = vx_setall_u8(1); - - v_uint32 v_sum32 = vx_setzero_u32(); - while (i < len0) - { - v_uint16 v_sum16 = vx_setzero_u16(); - int j = i; - while (j < std::min(len0, i + 65280 * v_uint16::nlanes)) - { - v_uint8 v_sum8 = vx_setzero_u8(); - int k = j; - for (; k < std::min(len0, j + 255 * v_uint8::nlanes); k += v_uint8::nlanes) - v_sum8 += v_one & (vx_load(src + k) == v_zero); - v_uint16 part1, part2; - v_expand(v_sum8, part1, part2); - v_sum16 += part1 + part2; - j = k; - } - v_uint32 part1, part2; - v_expand(v_sum16, part1, part2); - v_sum32 += part1 + part2; - i = j; - } - nz = i - v_reduce_sum(v_sum32); - v_cleanup(); -#endif - for( ; i < len; i++ ) - nz += src[i] != 0; - return nz; -} - -static int countNonZero16u( const ushort* src, int len ) -{ - int i = 0, nz = 0; -#if CV_SIMD - int len0 = len & -v_int8::nlanes; - v_uint16 v_zero = vx_setzero_u16(); - v_int8 v_one = vx_setall_s8(1); - - v_int32 v_sum32 = vx_setzero_s32(); - while (i < len0) - { - v_int16 v_sum16 = vx_setzero_s16(); - int j = i; - while (j < std::min(len0, i + 32766 * v_int16::nlanes)) - { - v_int8 v_sum8 = vx_setzero_s8(); - int k = j; - for (; k < std::min(len0, j + 127 * v_int8::nlanes); k += v_int8::nlanes) - v_sum8 += v_one & v_pack(v_reinterpret_as_s16(vx_load(src + k) == v_zero), v_reinterpret_as_s16(vx_load(src + k + v_uint16::nlanes) == v_zero)); - v_int16 part1, part2; - v_expand(v_sum8, part1, part2); - v_sum16 += part1 + part2; - j = k; - } - v_int32 part1, part2; - v_expand(v_sum16, part1, part2); - v_sum32 += part1 + part2; - i = j; - } - nz = i - v_reduce_sum(v_sum32); - v_cleanup(); -#endif - return nz + countNonZero_(src + i, len - i); -} - -static int countNonZero32s( const int* src, int len ) -{ - int i = 0, nz = 0; -#if CV_SIMD - int len0 = len & -v_int8::nlanes; - v_int32 v_zero = vx_setzero_s32(); - v_int8 v_one = vx_setall_s8(1); - - v_int32 v_sum32 = vx_setzero_s32(); - while (i < len0) - { - v_int16 v_sum16 = vx_setzero_s16(); - int j = i; - while (j < std::min(len0, i + 32766 * v_int16::nlanes)) - { - v_int8 v_sum8 = vx_setzero_s8(); - int k = j; - for (; k < std::min(len0, j + 127 * v_int8::nlanes); k += v_int8::nlanes) - v_sum8 += v_one & v_pack( - v_pack(vx_load(src + k ) == v_zero, vx_load(src + k + v_int32::nlanes) == v_zero), - v_pack(vx_load(src + k + 2*v_int32::nlanes) == v_zero, vx_load(src + k + 3*v_int32::nlanes) == v_zero) - ); - v_int16 part1, part2; - v_expand(v_sum8, part1, part2); - v_sum16 += part1 + part2; - j = k; - } - v_int32 part1, part2; - v_expand(v_sum16, part1, part2); - v_sum32 += part1 + part2; - i = j; - } - nz = i - v_reduce_sum(v_sum32); - v_cleanup(); -#endif - return nz + countNonZero_(src + i, len - i); -} - -static int countNonZero32f( const float* src, int len ) -{ - int i = 0, nz = 0; -#if CV_SIMD - int len0 = len & -v_int8::nlanes; - v_float32 v_zero = vx_setzero_f32(); - v_int8 v_one = vx_setall_s8(1); - - v_int32 v_sum32 = vx_setzero_s32(); - while (i < len0) - { - v_int16 v_sum16 = vx_setzero_s16(); - int j = i; - while (j < std::min(len0, i + 32766 * v_int16::nlanes)) - { - v_int8 v_sum8 = vx_setzero_s8(); - int k = j; - for (; k < std::min(len0, j + 127 * v_int8::nlanes); k += v_int8::nlanes) - v_sum8 += v_one & v_pack( - v_pack(v_reinterpret_as_s32(vx_load(src + k ) == v_zero), v_reinterpret_as_s32(vx_load(src + k + v_float32::nlanes) == v_zero)), - v_pack(v_reinterpret_as_s32(vx_load(src + k + 2*v_float32::nlanes) == v_zero), v_reinterpret_as_s32(vx_load(src + k + 3*v_float32::nlanes) == v_zero)) - ); - v_int16 part1, part2; - v_expand(v_sum8, part1, part2); - v_sum16 += part1 + part2; - j = k; - } - v_int32 part1, part2; - v_expand(v_sum16, part1, part2); - v_sum32 += part1 + part2; - i = j; - } - nz = i - v_reduce_sum(v_sum32); - v_cleanup(); -#endif - return nz + countNonZero_(src + i, len - i); -} - -static int countNonZero64f( const double* src, int len ) -{ - return countNonZero_(src, len); -} +#include "count_non_zero.simd.hpp" +#include "count_non_zero.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content -typedef int (*CountNonZeroFunc)(const uchar*, int); +namespace cv { static CountNonZeroFunc getCountNonZeroTab(int depth) { - static CountNonZeroFunc countNonZeroTab[] = - { - (CountNonZeroFunc)GET_OPTIMIZED(countNonZero8u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero8u), - (CountNonZeroFunc)GET_OPTIMIZED(countNonZero16u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero16u), - (CountNonZeroFunc)GET_OPTIMIZED(countNonZero32s), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero32f), - (CountNonZeroFunc)GET_OPTIMIZED(countNonZero64f), 0 - }; - - return countNonZeroTab[depth]; + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(getCountNonZeroTab, (depth), + CV_CPU_DISPATCH_MODES_ALL); } - #ifdef HAVE_OPENCL static bool ocl_countNonZero( InputArray _src, int & res ) { @@ -288,9 +116,7 @@ static bool ipp_countNonZero( Mat &src, int &res ) } #endif -} // cv:: - -int cv::countNonZero( InputArray _src ) +int countNonZero(InputArray _src) { CV_INSTRUMENT_REGION(); @@ -324,7 +150,7 @@ int cv::countNonZero( InputArray _src ) return nz; } -void cv::findNonZero( InputArray _src, OutputArray _idx ) +void findNonZero(InputArray _src, OutputArray _idx) { CV_INSTRUMENT_REGION(); @@ -351,3 +177,5 @@ void cv::findNonZero( InputArray _src, OutputArray _idx ) *idx_ptr++ = Point(j, i); } } + +} // namespace diff --git a/modules/core/src/count_non_zero.simd.hpp b/modules/core/src/count_non_zero.simd.hpp index 202e7b846d..4c01c08850 100644 --- a/modules/core/src/count_non_zero.simd.hpp +++ b/modules/core/src/count_non_zero.simd.hpp @@ -2,13 +2,20 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html - #include "precomp.hpp" -#include "opencl_kernels_core.hpp" -#include "stat.hpp" namespace cv { +typedef int (*CountNonZeroFunc)(const uchar*, int); + + +CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN + +CountNonZeroFunc getCountNonZeroTab(int depth); + + +#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY + template static int countNonZero_(const T* src, int len ) { @@ -175,9 +182,7 @@ static int countNonZero64f( const double* src, int len ) return countNonZero_(src, len); } -typedef int (*CountNonZeroFunc)(const uchar*, int); - -static CountNonZeroFunc getCountNonZeroTab(int depth) +CountNonZeroFunc getCountNonZeroTab(int depth) { static CountNonZeroFunc countNonZeroTab[] = { @@ -190,164 +195,7 @@ static CountNonZeroFunc getCountNonZeroTab(int depth) return countNonZeroTab[depth]; } - -#ifdef HAVE_OPENCL -static bool ocl_countNonZero( InputArray _src, int & res ) -{ - int type = _src.type(), depth = CV_MAT_DEPTH(type), kercn = ocl::predictOptimalVectorWidth(_src); - bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; - - if (depth == CV_64F && !doubleSupport) - return false; - - int dbsize = ocl::Device::getDefault().maxComputeUnits(); - size_t wgs = ocl::Device::getDefault().maxWorkGroupSize(); - - int wgs2_aligned = 1; - while (wgs2_aligned < (int)wgs) - wgs2_aligned <<= 1; - wgs2_aligned >>= 1; - - ocl::Kernel k("reduce", ocl::core::reduce_oclsrc, - format("-D srcT=%s -D srcT1=%s -D cn=1 -D OP_COUNT_NON_ZERO" - " -D WGS=%d -D kercn=%d -D WGS2_ALIGNED=%d%s%s", - ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)), - ocl::typeToStr(depth), (int)wgs, kercn, - wgs2_aligned, doubleSupport ? " -D DOUBLE_SUPPORT" : "", - _src.isContinuous() ? " -D HAVE_SRC_CONT" : "")); - if (k.empty()) - return false; - - UMat src = _src.getUMat(), db(1, dbsize, CV_32SC1); - k.args(ocl::KernelArg::ReadOnlyNoSize(src), src.cols, (int)src.total(), - dbsize, ocl::KernelArg::PtrWriteOnly(db)); - - size_t globalsize = dbsize * wgs; - if (k.run(1, &globalsize, &wgs, true)) - return res = saturate_cast(cv::sum(db.getMat(ACCESS_READ))[0]), true; - return false; -} -#endif - -#if defined HAVE_IPP -static bool ipp_countNonZero( Mat &src, int &res ) -{ - CV_INSTRUMENT_REGION_IPP(); - -#if IPP_VERSION_X100 < 201801 - // Poor performance of SSE42 - if(cv::ipp::getIppTopFeatures() == ippCPUID_SSE42) - return false; -#endif - - Ipp32s count = 0; - int depth = src.depth(); - - if(src.dims <= 2) - { - IppStatus status; - IppiSize size = {src.cols*src.channels(), src.rows}; - - if(depth == CV_8U) - status = CV_INSTRUMENT_FUN_IPP(ippiCountInRange_8u_C1R, (const Ipp8u *)src.ptr(), (int)src.step, size, &count, 0, 0); - else if(depth == CV_32F) - status = CV_INSTRUMENT_FUN_IPP(ippiCountInRange_32f_C1R, (const Ipp32f *)src.ptr(), (int)src.step, size, &count, 0, 0); - else - return false; - - if(status < 0) - return false; - - res = size.width*size.height - count; - } - else - { - IppStatus status; - const Mat *arrays[] = {&src, NULL}; - Mat planes[1]; - NAryMatIterator it(arrays, planes, 1); - IppiSize size = {(int)it.size*src.channels(), 1}; - res = 0; - for (size_t i = 0; i < it.nplanes; i++, ++it) - { - if(depth == CV_8U) - status = CV_INSTRUMENT_FUN_IPP(ippiCountInRange_8u_C1R, it.planes->ptr(), (int)it.planes->step, size, &count, 0, 0); - else if(depth == CV_32F) - status = CV_INSTRUMENT_FUN_IPP(ippiCountInRange_32f_C1R, it.planes->ptr(), (int)it.planes->step, size, &count, 0, 0); - else - return false; - - if(status < 0 || (int)it.planes->total()*src.channels() < count) - return false; - - res += (int)it.planes->total()*src.channels() - count; - } - } - - return true; -} -#endif - -} // cv:: - -int cv::countNonZero( InputArray _src ) -{ - CV_INSTRUMENT_REGION(); - - int type = _src.type(), cn = CV_MAT_CN(type); - CV_Assert( cn == 1 ); - -#if defined HAVE_OPENCL || defined HAVE_IPP - int res = -1; -#endif - -#ifdef HAVE_OPENCL - CV_OCL_RUN_(OCL_PERFORMANCE_CHECK(_src.isUMat()) && _src.dims() <= 2, - ocl_countNonZero(_src, res), - res) #endif - Mat src = _src.getMat(); - CV_IPP_RUN_FAST(ipp_countNonZero(src, res), res); - - CountNonZeroFunc func = getCountNonZeroTab(src.depth()); - CV_Assert( func != 0 ); - - const Mat* arrays[] = {&src, 0}; - uchar* ptrs[1] = {}; - NAryMatIterator it(arrays, ptrs); - int total = (int)it.size, nz = 0; - - for( size_t i = 0; i < it.nplanes; i++, ++it ) - nz += func( ptrs[0], total ); - - return nz; -} - -void cv::findNonZero( InputArray _src, OutputArray _idx ) -{ - CV_INSTRUMENT_REGION(); - - Mat src = _src.getMat(); - CV_Assert( src.type() == CV_8UC1 ); - int n = countNonZero(src); - if( n == 0 ) - { - _idx.release(); - return; - } - if( _idx.kind() == _InputArray::MAT && !_idx.getMatRef().isContinuous() ) - _idx.release(); - _idx.create(n, 1, CV_32SC2); - Mat idx = _idx.getMat(); - CV_Assert(idx.isContinuous()); - Point* idx_ptr = idx.ptr(); - - for( int i = 0; i < src.rows; i++ ) - { - const uchar* bin_ptr = src.ptr(i); - for( int j = 0; j < src.cols; j++ ) - if( bin_ptr[j] ) - *idx_ptr++ = Point(j, i); - } -} +CV_CPU_OPTIMIZATION_NAMESPACE_END +} // namespace From 3aaf8dfd1120599e1a73b4a4b2d8ff75343d8b00 Mon Sep 17 00:00:00 2001 From: Nicolae Rosia Date: Wed, 30 Jan 2019 17:43:23 +0200 Subject: [PATCH 13/21] cmake: allow FFmpeg linking on Android details: https://github.com/opencv/opencv/pull/13726 In order to help CMake and PkgConfig find FFmpeg you need to: 1) export `PKG_CONFIG_LIBDIR=${SYSROOT}` where `SYSROOT=${ANDROID_NDK}/sysroot` 2) Add `-DCMAKE_PREFIX_PATH=${FFMPEG_INSTALL_PREFIX}` 3) Append `-DCMAKE_FIND_ROOT_PATH=${FFMPEG_INSTALL_PREFIX}` --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 930e48c787..641594b00c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -255,8 +255,8 @@ OCV_OPTION(WITH_EIGEN "Include Eigen2/Eigen3 support" (NOT CV_DISABLE_OPTIMIZATI OCV_OPTION(WITH_VFW "Include Video for Windows support (deprecated, consider using MSMF)" OFF VISIBLE_IF WIN32 VERIFY HAVE_VFW) -OCV_OPTION(WITH_FFMPEG "Include FFMPEG support" ON - VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT +OCV_OPTION(WITH_FFMPEG "Include FFMPEG support" (NOT ANDROID) + VISIBLE_IF NOT IOS AND NOT WINRT VERIFY HAVE_FFMPEG) OCV_OPTION(WITH_GSTREAMER "Include Gstreamer support" ON VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT From b769ad2c236c17f9f6db1648e77210377b9e7007 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 14 Feb 2019 15:09:28 +0300 Subject: [PATCH 14/21] core: clone matmul.simd.hpp --- modules/core/src/{matmul.cpp => matmul.simd.hpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/core/src/{matmul.cpp => matmul.simd.hpp} (100%) diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.simd.hpp similarity index 100% rename from modules/core/src/matmul.cpp rename to modules/core/src/matmul.simd.hpp From dcee7b16050eeb3962a917f7bd8e99523bd178ee Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 14 Feb 2019 15:10:11 +0300 Subject: [PATCH 15/21] core: clone matmul.dispatch.cpp --- modules/core/src/{matmul.cpp => matmul.dispatch.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/core/src/{matmul.cpp => matmul.dispatch.cpp} (100%) diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.dispatch.cpp similarity index 100% rename from modules/core/src/matmul.cpp rename to modules/core/src/matmul.dispatch.cpp From 1a961660d8da692cf6cf80061ba9f689375195e9 Mon Sep 17 00:00:00 2001 From: Namgoo Lee Date: Mon, 18 Feb 2019 03:10:05 +0000 Subject: [PATCH 16/21] cuda::StereoBM - fix hanging and racing issue - Fix hanging issue on 2080 Ti - Fix racing issue --- modules/cudastereo/src/cuda/stereobm.cu | 107 ++++++++++++++++-------- 1 file changed, 72 insertions(+), 35 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereobm.cu b/modules/cudastereo/src/cuda/stereobm.cu index ccc6737ffa..7c72f76e38 100644 --- a/modules/cudastereo/src/cuda/stereobm.cu +++ b/modules/cudastereo/src/cuda/stereobm.cu @@ -71,48 +71,54 @@ namespace cv { namespace cuda { namespace device } template - __device__ unsigned int CalcSSD(volatile unsigned int *col_ssd_cache, volatile unsigned int *col_ssd) + __device__ unsigned int CalcSSD(volatile unsigned int *col_ssd_cache, volatile unsigned int *col_ssd, const int X) { unsigned int cache = 0; unsigned int cache2 = 0; - for(int i = 1; i <= RADIUS; i++) - cache += col_ssd[i]; + if (X < cwidth - RADIUS) + { + for(int i = 1; i <= RADIUS; i++) + cache += col_ssd[i]; - col_ssd_cache[0] = cache; + col_ssd_cache[0] = cache; + } __syncthreads(); - if (threadIdx.x < BLOCK_W - RADIUS) - cache2 = col_ssd_cache[RADIUS]; - else - for(int i = RADIUS + 1; i < (2 * RADIUS + 1); i++) - cache2 += col_ssd[i]; + if (X < cwidth - RADIUS) + { + if (threadIdx.x < BLOCK_W - RADIUS) + cache2 = col_ssd_cache[RADIUS]; + else + for(int i = RADIUS + 1; i < (2 * RADIUS + 1); i++) + cache2 += col_ssd[i]; + } return col_ssd[0] + cache + cache2; } template - __device__ uint2 MinSSD(volatile unsigned int *col_ssd_cache, volatile unsigned int *col_ssd) + __device__ uint2 MinSSD(volatile unsigned int *col_ssd_cache, volatile unsigned int *col_ssd, const int X) { unsigned int ssd[N_DISPARITIES]; //See above: #define COL_SSD_SIZE (BLOCK_W + 2 * RADIUS) - ssd[0] = CalcSSD(col_ssd_cache, col_ssd + 0 * (BLOCK_W + 2 * RADIUS)); + ssd[0] = CalcSSD(col_ssd_cache, col_ssd + 0 * (BLOCK_W + 2 * RADIUS), X); __syncthreads(); - ssd[1] = CalcSSD(col_ssd_cache, col_ssd + 1 * (BLOCK_W + 2 * RADIUS)); + ssd[1] = CalcSSD(col_ssd_cache, col_ssd + 1 * (BLOCK_W + 2 * RADIUS), X); __syncthreads(); - ssd[2] = CalcSSD(col_ssd_cache, col_ssd + 2 * (BLOCK_W + 2 * RADIUS)); + ssd[2] = CalcSSD(col_ssd_cache, col_ssd + 2 * (BLOCK_W + 2 * RADIUS), X); __syncthreads(); - ssd[3] = CalcSSD(col_ssd_cache, col_ssd + 3 * (BLOCK_W + 2 * RADIUS)); + ssd[3] = CalcSSD(col_ssd_cache, col_ssd + 3 * (BLOCK_W + 2 * RADIUS), X); __syncthreads(); - ssd[4] = CalcSSD(col_ssd_cache, col_ssd + 4 * (BLOCK_W + 2 * RADIUS)); + ssd[4] = CalcSSD(col_ssd_cache, col_ssd + 4 * (BLOCK_W + 2 * RADIUS), X); __syncthreads(); - ssd[5] = CalcSSD(col_ssd_cache, col_ssd + 5 * (BLOCK_W + 2 * RADIUS)); + ssd[5] = CalcSSD(col_ssd_cache, col_ssd + 5 * (BLOCK_W + 2 * RADIUS), X); __syncthreads(); - ssd[6] = CalcSSD(col_ssd_cache, col_ssd + 6 * (BLOCK_W + 2 * RADIUS)); + ssd[6] = CalcSSD(col_ssd_cache, col_ssd + 6 * (BLOCK_W + 2 * RADIUS), X); __syncthreads(); - ssd[7] = CalcSSD(col_ssd_cache, col_ssd + 7 * (BLOCK_W + 2 * RADIUS)); + ssd[7] = CalcSSD(col_ssd_cache, col_ssd + 7 * (BLOCK_W + 2 * RADIUS), X); int mssd = ::min(::min(::min(ssd[0], ssd[1]), ::min(ssd[4], ssd[5])), ::min(::min(ssd[2], ssd[3]), ::min(ssd[6], ssd[7]))); @@ -243,12 +249,12 @@ namespace cv { namespace cuda { namespace device unsigned int* minSSDImage = cminSSDImage + X + Y * cminSSD_step; unsigned char* disparImage = disp.data + X + Y * disp.step; - /* if (X < cwidth) - { - unsigned int *minSSDImage_end = minSSDImage + min(ROWSperTHREAD, cheight - Y) * minssd_step; - for(uint *ptr = minSSDImage; ptr != minSSDImage_end; ptr += minssd_step ) - *ptr = 0xFFFFFFFF; - }*/ + //if (X < cwidth) + //{ + // unsigned int *minSSDImage_end = minSSDImage + min(ROWSperTHREAD, cheight - Y) * minssd_step; + // for(uint *ptr = minSSDImage; ptr != minSSDImage_end; ptr += minssd_step ) + // *ptr = 0xFFFFFFFF; + //} int end_row = ::min(ROWSperTHREAD, cheight - Y - RADIUS); int y_tex; int x_tex = X - RADIUS; @@ -268,13 +274,27 @@ namespace cv { namespace cuda { namespace device __syncthreads(); //before MinSSD function - if (X < cwidth - RADIUS && Y < cheight - RADIUS) + if (Y < cheight - RADIUS) { - uint2 minSSD = MinSSD(col_ssd_cache + threadIdx.x, col_ssd); - if (minSSD.x < minSSDImage[0]) + uint2 minSSD = MinSSD(col_ssd_cache + threadIdx.x, col_ssd, X); + + // For threads that do not satisfy the if condition below("X < cwidth - RADIUS"), previously + // computed "minSSD" value, which is the result of "MinSSD" function call, is not used at all. + // + // However, since the "MinSSD" function has "__syncthreads" call in its body, those threads + // must also call "MinSSD" to avoid deadlock. (#13850) + // + // From CUDA 9, using "__syncwarp" with proper mask value instead of using "__syncthreads" + // could be an option, but the shared memory access pattern does not allow this option, + // resulting in race condition. (Checked via "cuda-memcheck --tool racecheck") + + if (X < cwidth - RADIUS) { - disparImage[0] = (unsigned char)(d + minSSD.y); - minSSDImage[0] = minSSD.x; + if (minSSD.x < minSSDImage[0]) + { + disparImage[0] = (unsigned char)(d + minSSD.y); + minSSDImage[0] = minSSD.x; + } } } @@ -295,17 +315,34 @@ namespace cv { namespace cuda { namespace device __syncthreads(); //before MinSSD function - if (X < cwidth - RADIUS && row < cheight - RADIUS - Y) + if (row < cheight - RADIUS - Y) { - int idx = row * cminSSD_step; - uint2 minSSD = MinSSD(col_ssd_cache + threadIdx.x, col_ssd); - if (minSSD.x < minSSDImage[idx]) + uint2 minSSD = MinSSD(col_ssd_cache + threadIdx.x, col_ssd, X); + + // For threads that do not satisfy the if condition below("X < cwidth - RADIUS"), previously + // computed "minSSD" value, which is the result of "MinSSD" function call, is not used at all. + // + // However, since the "MinSSD" function has "__syncthreads" call in its body, those threads + // must also call "MinSSD" to avoid deadlock. (#13850) + // + // From CUDA 9, using "__syncwarp" with proper mask value instead of using "__syncthreads" + // could be an option, but the shared memory access pattern does not allow this option, + // resulting in race condition. (Checked via "cuda-memcheck --tool racecheck") + + if (X < cwidth - RADIUS) { - disparImage[disp.step * row] = (unsigned char)(d + minSSD.y); - minSSDImage[idx] = minSSD.x; + int idx = row * cminSSD_step; + if (minSSD.x < minSSDImage[idx]) + { + disparImage[disp.step * row] = (unsigned char)(d + minSSD.y); + minSSDImage[idx] = minSSD.x; + } } } } // for row loop + + __syncthreads(); // before initializing shared memory at the beginning of next loop + } // for d loop } From cd66f6e3db101bdcf1406ec3604592662c6aebef Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 14 Feb 2019 16:00:17 +0300 Subject: [PATCH 17/21] core: dispatch matmul - gemm: keep baseline only (lapack is 10x+ faster, lets reduce binary size) - transform / distTransform - scaleAdd (32f/64f only) - Mahalanobis: keep baseline only (no perf tests) - mulTransposed: keep baseline only (no perf tests) - dot --- modules/core/CMakeLists.txt | 1 + .../include/opencv2/core/cv_cpu_dispatch.h | 1 + modules/core/src/matmul.dispatch.cpp | 2687 ++--------------- modules/core/src/matmul.simd.hpp | 1318 ++------ 4 files changed, 370 insertions(+), 3637 deletions(-) diff --git a/modules/core/CMakeLists.txt b/modules/core/CMakeLists.txt index 9559783d94..9d7a925dd0 100644 --- a/modules/core/CMakeLists.txt +++ b/modules/core/CMakeLists.txt @@ -6,6 +6,7 @@ ocv_add_dispatched_file(arithm SSE2 SSE4_1 AVX2 VSX3) ocv_add_dispatched_file(convert SSE2 AVX2) ocv_add_dispatched_file(convert_scale SSE2 AVX2) ocv_add_dispatched_file(count_non_zero SSE2 AVX2) +ocv_add_dispatched_file(matmul SSE2 AVX2) ocv_add_dispatched_file(sum SSE2 AVX2) # dispatching for accuracy tests diff --git a/modules/core/include/opencv2/core/cv_cpu_dispatch.h b/modules/core/include/opencv2/core/cv_cpu_dispatch.h index 57aa0ce2fb..08909f8b28 100644 --- a/modules/core/include/opencv2/core/cv_cpu_dispatch.h +++ b/modules/core/include/opencv2/core/cv_cpu_dispatch.h @@ -15,6 +15,7 @@ #define CV_CPU_OPTIMIZATION_NAMESPACE cpu_baseline #define CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN namespace cpu_baseline { #define CV_CPU_OPTIMIZATION_NAMESPACE_END } +#define CV_CPU_BASELINE_MODE 1 #endif diff --git a/modules/core/src/matmul.dispatch.cpp b/modules/core/src/matmul.dispatch.cpp index 19ab907c9e..6fcdb4c700 100644 --- a/modules/core/src/matmul.dispatch.cpp +++ b/modules/core/src/matmul.dispatch.cpp @@ -41,13 +41,15 @@ // //M*/ -#include #include "precomp.hpp" #include "opencl_kernels_core.hpp" #include "opencv2/core/opencl/runtime/opencl_clamdblas.hpp" #include "opencv2/core/opencl/runtime/opencl_core.hpp" #include "intel_gpu_gemm.inl.hpp" +#include "matmul.simd.hpp" +#include "matmul.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content + namespace cv { @@ -55,646 +57,6 @@ namespace cv * GEMM * \****************************************************************************************/ -static void -GEMM_CopyBlock( const uchar* src, size_t src_step, - uchar* dst, size_t dst_step, - Size size, size_t pix_size ) -{ - int j; - size.width *= (int)(pix_size / sizeof(int)); - - for( ; size.height--; src += src_step, dst += dst_step ) - { - j=0; - #if CV_ENABLE_UNROLLED - for( ; j <= size.width - 4; j += 4 ) - { - int t0 = ((const int*)src)[j]; - int t1 = ((const int*)src)[j+1]; - ((int*)dst)[j] = t0; - ((int*)dst)[j+1] = t1; - t0 = ((const int*)src)[j+2]; - t1 = ((const int*)src)[j+3]; - ((int*)dst)[j+2] = t0; - ((int*)dst)[j+3] = t1; - } - #endif - for( ; j < size.width; j++ ) - ((int*)dst)[j] = ((const int*)src)[j]; - } -} - - -static void -GEMM_TransposeBlock( const uchar* src, size_t src_step, - uchar* dst, size_t dst_step, - Size size, size_t pix_size ) -{ - int i, j; - for( i = 0; i < size.width; i++, dst += dst_step, src += pix_size ) - { - const uchar* _src = src; - switch( pix_size ) - { - case sizeof(int): - for( j = 0; j < size.height; j++, _src += src_step ) - ((int*)dst)[j] = ((int*)_src)[0]; - break; - case sizeof(int)*2: - for( j = 0; j < size.height*2; j += 2, _src += src_step ) - { - int t0 = ((int*)_src)[0]; - int t1 = ((int*)_src)[1]; - ((int*)dst)[j] = t0; - ((int*)dst)[j+1] = t1; - } - break; - case sizeof(int)*4: - for( j = 0; j < size.height*4; j += 4, _src += src_step ) - { - int t0 = ((int*)_src)[0]; - int t1 = ((int*)_src)[1]; - ((int*)dst)[j] = t0; - ((int*)dst)[j+1] = t1; - t0 = ((int*)_src)[2]; - t1 = ((int*)_src)[3]; - ((int*)dst)[j+2] = t0; - ((int*)dst)[j+3] = t1; - } - break; - default: - assert(0); - return; - } - } -} - - -template static void -GEMMSingleMul( const T* a_data, size_t a_step, - const T* b_data, size_t b_step, - const T* c_data, size_t c_step, - T* d_data, size_t d_step, - Size a_size, Size d_size, - double alpha, double beta, int flags ) -{ - int i, j, k, n = a_size.width, m = d_size.width, drows = d_size.height; - const T *_a_data = a_data, *_b_data = b_data, *_c_data = c_data; - cv::AutoBuffer _a_buf; - T* a_buf = 0; - size_t a_step0, a_step1, c_step0, c_step1, t_step; - - a_step /= sizeof(a_data[0]); - b_step /= sizeof(b_data[0]); - c_step /= sizeof(c_data[0]); - d_step /= sizeof(d_data[0]); - a_step0 = a_step; - a_step1 = 1; - - if( !c_data ) - c_step0 = c_step1 = 0; - else if( !(flags & GEMM_3_T) ) - c_step0 = c_step, c_step1 = 1; - else - c_step0 = 1, c_step1 = c_step; - - if( flags & GEMM_1_T ) - { - CV_SWAP( a_step0, a_step1, t_step ); - n = a_size.height; - if( a_step > 1 && n > 1 ) - { - _a_buf.allocate(n); - a_buf = _a_buf.data(); - } - } - - if( n == 1 ) /* external product */ - { - cv::AutoBuffer _b_buf; - T* b_buf = 0; - - if( a_step > 1 && a_size.height > 1 ) - { - _a_buf.allocate(drows); - a_buf = _a_buf.data(); - for( k = 0; k < drows; k++ ) - a_buf[k] = a_data[a_step*k]; - a_data = a_buf; - } - - if( b_step > 1 ) - { - _b_buf.allocate(d_size.width); - b_buf = _b_buf.data(); - for( j = 0; j < d_size.width; j++ ) - b_buf[j] = b_data[j*b_step]; - b_data = b_buf; - } - - for( i = 0; i < drows; i++, _c_data += c_step0, d_data += d_step ) - { - WT al = WT(a_data[i])*alpha; - c_data = _c_data; - for( j = 0; j <= d_size.width - 2; j += 2, c_data += 2*c_step1 ) - { - WT s0 = al*WT(b_data[j]); - WT s1 = al*WT(b_data[j+1]); - if( !c_data ) - { - d_data[j] = T(s0); - d_data[j+1] = T(s1); - } - else - { - d_data[j] = T(s0 + WT(c_data[0])*beta); - d_data[j+1] = T(s1 + WT(c_data[c_step1])*beta); - } - } - - for( ; j < d_size.width; j++, c_data += c_step1 ) - { - WT s0 = al*WT(b_data[j]); - if( !c_data ) - d_data[j] = T(s0); - else - d_data[j] = T(s0 + WT(c_data[0])*beta); - } - } - } - else if( flags & GEMM_2_T ) /* A * Bt */ - { - for( i = 0; i < drows; i++, _a_data += a_step0, _c_data += c_step0, d_data += d_step ) - { - a_data = _a_data; - b_data = _b_data; - c_data = _c_data; - - if( a_buf ) - { - for( k = 0; k < n; k++ ) - a_buf[k] = a_data[a_step1*k]; - a_data = a_buf; - } - - for( j = 0; j < d_size.width; j++, b_data += b_step, - c_data += c_step1 ) - { - WT s0(0), s1(0), s2(0), s3(0); - k = 0; - #if CV_ENABLE_UNROLLED - for( ; k <= n - 4; k += 4 ) - { - s0 += WT(a_data[k])*WT(b_data[k]); - s1 += WT(a_data[k+1])*WT(b_data[k+1]); - s2 += WT(a_data[k+2])*WT(b_data[k+2]); - s3 += WT(a_data[k+3])*WT(b_data[k+3]); - } - #endif - for( ; k < n; k++ ) - s0 += WT(a_data[k])*WT(b_data[k]); - s0 = (s0+s1+s2+s3)*alpha; - - if( !c_data ) - d_data[j] = T(s0); - else - d_data[j] = T(s0 + WT(c_data[0])*beta); - } - } - } - else if( d_size.width*sizeof(d_data[0]) <= 1600 ) - { - for( i = 0; i < drows; i++, _a_data += a_step0, - _c_data += c_step0, - d_data += d_step ) - { - a_data = _a_data, c_data = _c_data; - - if( a_buf ) - { - for( k = 0; k < n; k++ ) - a_buf[k] = a_data[a_step1*k]; - a_data = a_buf; - } - - for( j = 0; j <= m - 4; j += 4, c_data += 4*c_step1 ) - { - const T* b = _b_data + j; - WT s0(0), s1(0), s2(0), s3(0); - - for( k = 0; k < n; k++, b += b_step ) - { - WT a(a_data[k]); - s0 += a * WT(b[0]); s1 += a * WT(b[1]); - s2 += a * WT(b[2]); s3 += a * WT(b[3]); - } - - if( !c_data ) - { - d_data[j] = T(s0*alpha); - d_data[j+1] = T(s1*alpha); - d_data[j+2] = T(s2*alpha); - d_data[j+3] = T(s3*alpha); - } - else - { - s0 = s0*alpha; s1 = s1*alpha; - s2 = s2*alpha; s3 = s3*alpha; - d_data[j] = T(s0 + WT(c_data[0])*beta); - d_data[j+1] = T(s1 + WT(c_data[c_step1])*beta); - d_data[j+2] = T(s2 + WT(c_data[c_step1*2])*beta); - d_data[j+3] = T(s3 + WT(c_data[c_step1*3])*beta); - } - } - - for( ; j < m; j++, c_data += c_step1 ) - { - const T* b = _b_data + j; - WT s0(0); - - for( k = 0; k < n; k++, b += b_step ) - s0 += WT(a_data[k]) * WT(b[0]); - - s0 = s0*alpha; - if( !c_data ) - d_data[j] = T(s0); - else - d_data[j] = T(s0 + WT(c_data[0])*beta); - } - } - } - else - { - cv::AutoBuffer _d_buf(m); - WT* d_buf = _d_buf.data(); - - for( i = 0; i < drows; i++, _a_data += a_step0, _c_data += c_step0, d_data += d_step ) - { - a_data = _a_data; - b_data = _b_data; - c_data = _c_data; - - if( a_buf ) - { - for( k = 0; k < n; k++ ) - a_buf[k] = _a_data[a_step1*k]; - a_data = a_buf; - } - - for( j = 0; j < m; j++ ) - d_buf[j] = WT(0); - - for( k = 0; k < n; k++, b_data += b_step ) - { - WT al(a_data[k]); - j=0; - #if CV_ENABLE_UNROLLED - for(; j <= m - 4; j += 4 ) - { - WT t0 = d_buf[j] + WT(b_data[j])*al; - WT t1 = d_buf[j+1] + WT(b_data[j+1])*al; - d_buf[j] = t0; - d_buf[j+1] = t1; - t0 = d_buf[j+2] + WT(b_data[j+2])*al; - t1 = d_buf[j+3] + WT(b_data[j+3])*al; - d_buf[j+2] = t0; - d_buf[j+3] = t1; - } - #endif - for( ; j < m; j++ ) - d_buf[j] += WT(b_data[j])*al; - } - - if( !c_data ) - for( j = 0; j < m; j++ ) - d_data[j] = T(d_buf[j]*alpha); - else - for( j = 0; j < m; j++, c_data += c_step1 ) - { - WT t = d_buf[j]*alpha; - d_data[j] = T(t + WT(c_data[0])*beta); - } - } - } -} - - -template static void -GEMMBlockMul( const T* a_data, size_t a_step, - const T* b_data, size_t b_step, - WT* d_data, size_t d_step, - Size a_size, Size d_size, int flags ) -{ - int i, j, k, n = a_size.width, m = d_size.width; - const T *_a_data = a_data, *_b_data = b_data; - cv::AutoBuffer _a_buf; - T* a_buf = 0; - size_t a_step0, a_step1, t_step; - int do_acc = flags & 16; - - a_step /= sizeof(a_data[0]); - b_step /= sizeof(b_data[0]); - d_step /= sizeof(d_data[0]); - - a_step0 = a_step; - a_step1 = 1; - - if( flags & GEMM_1_T ) - { - CV_SWAP( a_step0, a_step1, t_step ); - n = a_size.height; - _a_buf.allocate(n); - a_buf = _a_buf.data(); - } - - if( flags & GEMM_2_T ) - { - /* second operand is transposed */ - for( i = 0; i < d_size.height; i++, _a_data += a_step0, d_data += d_step ) - { - a_data = _a_data; b_data = _b_data; - - if( a_buf ) - { - for( k = 0; k < n; k++ ) - a_buf[k] = a_data[a_step1*k]; - a_data = a_buf; - } - - for( j = 0; j < d_size.width; j++, b_data += b_step ) - { - WT s0 = do_acc ? d_data[j]:WT(0), s1(0); - for( k = 0; k <= n - 2; k += 2 ) - { - s0 += WT(a_data[k])*WT(b_data[k]); - s1 += WT(a_data[k+1])*WT(b_data[k+1]); - } - - for( ; k < n; k++ ) - s0 += WT(a_data[k])*WT(b_data[k]); - - d_data[j] = s0 + s1; - } - } - } - else - { - for( i = 0; i < d_size.height; i++, _a_data += a_step0, d_data += d_step ) - { - a_data = _a_data, b_data = _b_data; - - if( a_buf ) - { - for( k = 0; k < n; k++ ) - a_buf[k] = a_data[a_step1*k]; - a_data = a_buf; - } - - for( j = 0; j <= m - 4; j += 4 ) - { - WT s0, s1, s2, s3; - const T* b = b_data + j; - - if( do_acc ) - { - s0 = d_data[j]; s1 = d_data[j+1]; - s2 = d_data[j+2]; s3 = d_data[j+3]; - } - else - s0 = s1 = s2 = s3 = WT(0); - - for( k = 0; k < n; k++, b += b_step ) - { - WT a(a_data[k]); - s0 += a * WT(b[0]); s1 += a * WT(b[1]); - s2 += a * WT(b[2]); s3 += a * WT(b[3]); - } - - d_data[j] = s0; d_data[j+1] = s1; - d_data[j+2] = s2; d_data[j+3] = s3; - } - - for( ; j < m; j++ ) - { - const T* b = b_data + j; - WT s0 = do_acc ? d_data[j] : WT(0); - - for( k = 0; k < n; k++, b += b_step ) - s0 += WT(a_data[k]) * WT(b[0]); - - d_data[j] = s0; - } - } - } -} - - -template static void -GEMMStore( const T* c_data, size_t c_step, - const WT* d_buf, size_t d_buf_step, - T* d_data, size_t d_step, Size d_size, - double alpha, double beta, int flags ) -{ - const T* _c_data = c_data; - int j; - size_t c_step0, c_step1; - - c_step /= sizeof(c_data[0]); - d_buf_step /= sizeof(d_buf[0]); - d_step /= sizeof(d_data[0]); - - if( !c_data ) - c_step0 = c_step1 = 0; - else if( !(flags & GEMM_3_T) ) - c_step0 = c_step, c_step1 = 1; - else - c_step0 = 1, c_step1 = c_step; - - for( ; d_size.height--; _c_data += c_step0, d_buf += d_buf_step, d_data += d_step ) - { - if( _c_data ) - { - c_data = _c_data; - j=0; - #if CV_ENABLE_UNROLLED - for(; j <= d_size.width - 4; j += 4, c_data += 4*c_step1 ) - { - WT t0 = alpha*d_buf[j]; - WT t1 = alpha*d_buf[j+1]; - t0 += beta*WT(c_data[0]); - t1 += beta*WT(c_data[c_step1]); - d_data[j] = T(t0); - d_data[j+1] = T(t1); - t0 = alpha*d_buf[j+2]; - t1 = alpha*d_buf[j+3]; - t0 += beta*WT(c_data[c_step1*2]); - t1 += beta*WT(c_data[c_step1*3]); - d_data[j+2] = T(t0); - d_data[j+3] = T(t1); - } - #endif - for( ; j < d_size.width; j++, c_data += c_step1 ) - { - WT t0 = alpha*d_buf[j]; - d_data[j] = T(t0 + WT(c_data[0])*beta); - } - } - else - { - j = 0; - #if CV_ENABLE_UNROLLED - for( ; j <= d_size.width - 4; j += 4 ) - { - WT t0 = alpha*d_buf[j]; - WT t1 = alpha*d_buf[j+1]; - d_data[j] = T(t0); - d_data[j+1] = T(t1); - t0 = alpha*d_buf[j+2]; - t1 = alpha*d_buf[j+3]; - d_data[j+2] = T(t0); - d_data[j+3] = T(t1); - } - #endif - for( ; j < d_size.width; j++ ) - d_data[j] = T(alpha*d_buf[j]); - } - } -} - - -typedef void (*GEMMSingleMulFunc)( const void* src1, size_t step1, - const void* src2, size_t step2, const void* src3, size_t step3, - void* dst, size_t dststep, Size srcsize, Size dstsize, - double alpha, double beta, int flags ); - -typedef void (*GEMMBlockMulFunc)( const void* src1, size_t step1, - const void* src2, size_t step2, void* dst, size_t dststep, - Size srcsize, Size dstsize, int flags ); - -typedef void (*GEMMStoreFunc)( const void* src1, size_t step1, - const void* src2, size_t step2, void* dst, size_t dststep, - Size dstsize, double alpha, double beta, int flags ); - -static void GEMMSingleMul_32f( const float* a_data, size_t a_step, - const float* b_data, size_t b_step, - const float* c_data, size_t c_step, - float* d_data, size_t d_step, - Size a_size, Size d_size, - double alpha, double beta, int flags ) -{ - GEMMSingleMul(a_data, a_step, b_data, b_step, c_data, - c_step, d_data, d_step, a_size, d_size, - alpha, beta, flags); -} - -static void GEMMSingleMul_64f( const double* a_data, size_t a_step, - const double* b_data, size_t b_step, - const double* c_data, size_t c_step, - double* d_data, size_t d_step, - Size a_size, Size d_size, - double alpha, double beta, int flags ) -{ - GEMMSingleMul(a_data, a_step, b_data, b_step, c_data, - c_step, d_data, d_step, a_size, d_size, - alpha, beta, flags); -} - - -static void GEMMSingleMul_32fc( const Complexf* a_data, size_t a_step, - const Complexf* b_data, size_t b_step, - const Complexf* c_data, size_t c_step, - Complexf* d_data, size_t d_step, - Size a_size, Size d_size, - double alpha, double beta, int flags ) -{ - GEMMSingleMul(a_data, a_step, b_data, b_step, c_data, - c_step, d_data, d_step, a_size, d_size, - alpha, beta, flags); -} - -static void GEMMSingleMul_64fc( const Complexd* a_data, size_t a_step, - const Complexd* b_data, size_t b_step, - const Complexd* c_data, size_t c_step, - Complexd* d_data, size_t d_step, - Size a_size, Size d_size, - double alpha, double beta, int flags ) -{ - GEMMSingleMul(a_data, a_step, b_data, b_step, c_data, - c_step, d_data, d_step, a_size, d_size, - alpha, beta, flags); -} - -static void GEMMBlockMul_32f( const float* a_data, size_t a_step, - const float* b_data, size_t b_step, - double* d_data, size_t d_step, - Size a_size, Size d_size, int flags ) -{ - GEMMBlockMul(a_data, a_step, b_data, b_step, d_data, d_step, a_size, d_size, flags); -} - - -static void GEMMBlockMul_64f( const double* a_data, size_t a_step, - const double* b_data, size_t b_step, - double* d_data, size_t d_step, - Size a_size, Size d_size, int flags ) -{ - GEMMBlockMul(a_data, a_step, b_data, b_step, d_data, d_step, a_size, d_size, flags); -} - - -static void GEMMBlockMul_32fc( const Complexf* a_data, size_t a_step, - const Complexf* b_data, size_t b_step, - Complexd* d_data, size_t d_step, - Size a_size, Size d_size, int flags ) -{ - GEMMBlockMul(a_data, a_step, b_data, b_step, d_data, d_step, a_size, d_size, flags); -} - - -static void GEMMBlockMul_64fc( const Complexd* a_data, size_t a_step, - const Complexd* b_data, size_t b_step, - Complexd* d_data, size_t d_step, - Size a_size, Size d_size, int flags ) -{ - GEMMBlockMul(a_data, a_step, b_data, b_step, d_data, d_step, a_size, d_size, flags); -} - - -static void GEMMStore_32f( const float* c_data, size_t c_step, - const double* d_buf, size_t d_buf_step, - float* d_data, size_t d_step, Size d_size, - double alpha, double beta, int flags ) -{ - GEMMStore(c_data, c_step, d_buf, d_buf_step, d_data, d_step, d_size, alpha, beta, flags); -} - - -static void GEMMStore_64f( const double* c_data, size_t c_step, - const double* d_buf, size_t d_buf_step, - double* d_data, size_t d_step, Size d_size, - double alpha, double beta, int flags ) -{ - GEMMStore(c_data, c_step, d_buf, d_buf_step, d_data, d_step, d_size, alpha, beta, flags); -} - - -static void GEMMStore_32fc( const Complexf* c_data, size_t c_step, - const Complexd* d_buf, size_t d_buf_step, - Complexf* d_data, size_t d_step, Size d_size, - double alpha, double beta, int flags ) -{ - GEMMStore(c_data, c_step, d_buf, d_buf_step, d_data, d_step, d_size, alpha, beta, flags); -} - - -static void GEMMStore_64fc( const Complexd* c_data, size_t c_step, - const Complexd* d_buf, size_t d_buf_step, - Complexd* d_data, size_t d_step, Size d_size, - double alpha, double beta, int flags ) -{ - GEMMStore(c_data, c_step, d_buf, d_buf_step, d_data, d_step, d_size, alpha, beta, flags); -} - #ifdef HAVE_CLAMDBLAS static bool ocl_gemm_amdblas( InputArray matA, InputArray matB, double alpha, @@ -893,708 +255,125 @@ static bool ocl_gemm( InputArray matA, InputArray matB, double alpha, } #endif -static void gemmImpl( Mat A, Mat B, double alpha, - Mat C, double beta, Mat D, int flags ) + +namespace hal { + +void gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags) +{ + CV_INSTRUMENT_REGION(); + CALL_HAL(gemm32f, cv_hal_gemm32f, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) +#ifdef CV_GEMM_BASELINE_ONLY + CV_CPU_CALL_BASELINE(gemm32f, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags)); +#else + CV_CPU_DISPATCH(gemm32f, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags), + CV_CPU_DISPATCH_MODES_ALL); +#endif +} + +void gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags) +{ + CV_INSTRUMENT_REGION(); + CALL_HAL(gemm64f, cv_hal_gemm64f, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) +#ifdef CV_GEMM_BASELINE_ONLY + CV_CPU_CALL_BASELINE(gemm64f, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags)); +#else + CV_CPU_DISPATCH(gemm64f, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags), + CV_CPU_DISPATCH_MODES_ALL); +#endif +} + +void gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags) +{ + CV_INSTRUMENT_REGION(); + CALL_HAL(gemm32fc, cv_hal_gemm32fc, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) +#ifdef CV_GEMM_BASELINE_ONLY + CV_CPU_CALL_BASELINE(gemm32fc, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags)); +#else + CV_CPU_DISPATCH(gemm32fc, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags), + CV_CPU_DISPATCH_MODES_ALL); +#endif +} + +void gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags) { CV_INSTRUMENT_REGION(); + CALL_HAL(gemm64fc, cv_hal_gemm64fc, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) +#ifdef CV_GEMM_BASELINE_ONLY + CV_CPU_CALL_BASELINE(gemm64fc, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags)); +#else + CV_CPU_DISPATCH(gemm64fc, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags), + CV_CPU_DISPATCH_MODES_ALL); +#endif +} + +} // namespace hal - const int block_lin_size = 128; - const int block_size = block_lin_size * block_lin_size; +void gemm(InputArray matA, InputArray matB, double alpha, + InputArray matC, double beta, OutputArray _matD, int flags) +{ +#ifdef HAVE_CLAMDBLAS + CV_OCL_RUN(ocl::haveAmdBlas() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2 && _matD.isUMat() && + matA.cols() > 20 && matA.rows() > 20 && matB.cols() > 20, // since it works incorrect for small sizes + ocl_gemm_amdblas(matA, matB, alpha, matC, beta, _matD, flags)) +#endif - static double zero[] = {0,0,0,0}; - static float zerof[] = {0,0,0,0}; +#ifdef HAVE_OPENCL + CV_OCL_RUN(_matD.isUMat() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2, + ocl_gemm(matA, matB, alpha, matC, beta, _matD, flags)) +#endif + Mat A = matA.getMat(), B = matB.getMat(), C = beta != 0.0 ? matC.getMat() : Mat(); Size a_size = A.size(), d_size; - int i, len = 0, type = A.type(); + int len = 0, type = A.type(); + + CV_Assert_N( type == B.type(), (type == CV_32FC1 || type == CV_64FC1 || type == CV_32FC2 || type == CV_64FC2) ); switch( flags & (GEMM_1_T|GEMM_2_T) ) { case 0: d_size = Size( B.cols, a_size.height ); len = B.rows; + CV_Assert( a_size.width == len ); break; case 1: d_size = Size( B.cols, a_size.width ); len = B.rows; + CV_Assert( a_size.height == len ); break; case 2: d_size = Size( B.rows, a_size.height ); len = B.cols; + CV_Assert( a_size.width == len ); break; case 3: d_size = Size( B.rows, a_size.width ); len = B.cols; + CV_Assert( a_size.height == len ); break; } - if( flags == 0 && 2 <= len && len <= 4 && (len == d_size.width || len == d_size.height) ) + if( !C.empty() ) { - if( type == CV_32F ) - { - float* d = D.ptr(); - const float *a = A.ptr(), - *b = B.ptr(), - *c = (const float*)C.data; - size_t d_step = D.step/sizeof(d[0]), - a_step = A.step/sizeof(a[0]), - b_step = B.step/sizeof(b[0]), - c_step = C.data ? C.step/sizeof(c[0]) : 0; - - if( !c ) - c = zerof; - - switch( len ) - { - case 2: - if( len == d_size.width && b != d ) - { - for( i = 0; i < d_size.height; i++, d += d_step, a += a_step, c += c_step ) - { - float t0 = a[0]*b[0] + a[1]*b[b_step]; - float t1 = a[0]*b[1] + a[1]*b[b_step+1]; - d[0] = (float)(t0*alpha + c[0]*beta); - d[1] = (float)(t1*alpha + c[1]*beta); - } - } - else if( a != d ) - { - int c_step0 = 1; - if( c == zerof ) - { - c_step0 = 0; - c_step = 1; - } - - for( i = 0; i < d_size.width; i++, d++, b++, c += c_step0 ) - { - float t0 = a[0]*b[0] + a[1]*b[b_step]; - float t1 = a[a_step]*b[0] + a[a_step+1]*b[b_step]; - d[0] = (float)(t0*alpha + c[0]*beta); - d[d_step] = (float)(t1*alpha + c[c_step]*beta); - } - } - else - break; - return; - case 3: - if( len == d_size.width && b != d ) - { - for( i = 0; i < d_size.height; i++, d += d_step, a += a_step, c += c_step ) - { - float t0 = a[0]*b[0] + a[1]*b[b_step] + a[2]*b[b_step*2]; - float t1 = a[0]*b[1] + a[1]*b[b_step+1] + a[2]*b[b_step*2+1]; - float t2 = a[0]*b[2] + a[1]*b[b_step+2] + a[2]*b[b_step*2+2]; - d[0] = (float)(t0*alpha + c[0]*beta); - d[1] = (float)(t1*alpha + c[1]*beta); - d[2] = (float)(t2*alpha + c[2]*beta); - } - } - else if( a != d ) - { - int c_step0 = 1; - if( c == zerof ) - { - c_step0 = 0; - c_step = 1; - } - - for( i = 0; i < d_size.width; i++, d++, b++, c += c_step0 ) - { - float t0 = a[0]*b[0] + a[1]*b[b_step] + a[2]*b[b_step*2]; - float t1 = a[a_step]*b[0] + a[a_step+1]*b[b_step] + a[a_step+2]*b[b_step*2]; - float t2 = a[a_step*2]*b[0] + a[a_step*2+1]*b[b_step] + a[a_step*2+2]*b[b_step*2]; - - d[0] = (float)(t0*alpha + c[0]*beta); - d[d_step] = (float)(t1*alpha + c[c_step]*beta); - d[d_step*2] = (float)(t2*alpha + c[c_step*2]*beta); - } - } - else - break; - return; - case 4: - if( len == d_size.width && b != d ) - { - for( i = 0; i < d_size.height; i++, d += d_step, a += a_step, c += c_step ) - { - float t0 = a[0]*b[0] + a[1]*b[b_step] + a[2]*b[b_step*2] + a[3]*b[b_step*3]; - float t1 = a[0]*b[1] + a[1]*b[b_step+1] + a[2]*b[b_step*2+1] + a[3]*b[b_step*3+1]; - float t2 = a[0]*b[2] + a[1]*b[b_step+2] + a[2]*b[b_step*2+2] + a[3]*b[b_step*3+2]; - float t3 = a[0]*b[3] + a[1]*b[b_step+3] + a[2]*b[b_step*2+3] + a[3]*b[b_step*3+3]; - d[0] = (float)(t0*alpha + c[0]*beta); - d[1] = (float)(t1*alpha + c[1]*beta); - d[2] = (float)(t2*alpha + c[2]*beta); - d[3] = (float)(t3*alpha + c[3]*beta); - } - } - else if( len <= 16 && a != d ) - { - int c_step0 = 1; - if( c == zerof ) - { - c_step0 = 0; - c_step = 1; - } - - for( i = 0; i < d_size.width; i++, d++, b++, c += c_step0 ) - { - float t0 = a[0]*b[0] + a[1]*b[b_step] + a[2]*b[b_step*2] + a[3]*b[b_step*3]; - float t1 = a[a_step]*b[0] + a[a_step+1]*b[b_step] + - a[a_step+2]*b[b_step*2] + a[a_step+3]*b[b_step*3]; - float t2 = a[a_step*2]*b[0] + a[a_step*2+1]*b[b_step] + - a[a_step*2+2]*b[b_step*2] + a[a_step*2+3]*b[b_step*3]; - float t3 = a[a_step*3]*b[0] + a[a_step*3+1]*b[b_step] + - a[a_step*3+2]*b[b_step*2] + a[a_step*3+3]*b[b_step*3]; - d[0] = (float)(t0*alpha + c[0]*beta); - d[d_step] = (float)(t1*alpha + c[c_step]*beta); - d[d_step*2] = (float)(t2*alpha + c[c_step*2]*beta); - d[d_step*3] = (float)(t3*alpha + c[c_step*3]*beta); - } - } - else - break; - return; - } - } - - if( type == CV_64F ) - { - double* d = D.ptr(); - const double *a = A.ptr(), - *b = B.ptr(), - *c = (const double*)C.data; - size_t d_step = D.step/sizeof(d[0]), - a_step = A.step/sizeof(a[0]), - b_step = B.step/sizeof(b[0]), - c_step = C.data ? C.step/sizeof(c[0]) : 0; - if( !c ) - c = zero; - - switch( len ) - { - case 2: - if( len == d_size.width && b != d ) - { - for( i = 0; i < d_size.height; i++, d += d_step, a += a_step, c += c_step ) - { - double t0 = a[0]*b[0] + a[1]*b[b_step]; - double t1 = a[0]*b[1] + a[1]*b[b_step+1]; - d[0] = t0*alpha + c[0]*beta; - d[1] = t1*alpha + c[1]*beta; - } - } - else if( a != d ) - { - int c_step0 = 1; - if( c == zero ) - { - c_step0 = 0; - c_step = 1; - } - - for( i = 0; i < d_size.width; i++, d++, b++, c += c_step0 ) - { - double t0 = a[0]*b[0] + a[1]*b[b_step]; - double t1 = a[a_step]*b[0] + a[a_step+1]*b[b_step]; - d[0] = t0*alpha + c[0]*beta; - d[d_step] = t1*alpha + c[c_step]*beta; - } - } - else - break; - return; - case 3: - if( len == d_size.width && b != d ) - { - for( i = 0; i < d_size.height; i++, d += d_step, a += a_step, c += c_step ) - { - double t0 = a[0]*b[0] + a[1]*b[b_step] + a[2]*b[b_step*2]; - double t1 = a[0]*b[1] + a[1]*b[b_step+1] + a[2]*b[b_step*2+1]; - double t2 = a[0]*b[2] + a[1]*b[b_step+2] + a[2]*b[b_step*2+2]; - d[0] = t0*alpha + c[0]*beta; - d[1] = t1*alpha + c[1]*beta; - d[2] = t2*alpha + c[2]*beta; - } - } - else if( a != d ) - { - int c_step0 = 1; - if( c == zero ) - { - c_step0 = 0; - c_step = 1; - } - - for( i = 0; i < d_size.width; i++, d++, b++, c += c_step0 ) - { - double t0 = a[0]*b[0] + a[1]*b[b_step] + a[2]*b[b_step*2]; - double t1 = a[a_step]*b[0] + a[a_step+1]*b[b_step] + a[a_step+2]*b[b_step*2]; - double t2 = a[a_step*2]*b[0] + a[a_step*2+1]*b[b_step] + a[a_step*2+2]*b[b_step*2]; - - d[0] = t0*alpha + c[0]*beta; - d[d_step] = t1*alpha + c[c_step]*beta; - d[d_step*2] = t2*alpha + c[c_step*2]*beta; - } - } - else - break; - return; - case 4: - if( len == d_size.width && b != d ) - { - for( i = 0; i < d_size.height; i++, d += d_step, a += a_step, c += c_step ) - { - double t0 = a[0]*b[0] + a[1]*b[b_step] + a[2]*b[b_step*2] + a[3]*b[b_step*3]; - double t1 = a[0]*b[1] + a[1]*b[b_step+1] + a[2]*b[b_step*2+1] + a[3]*b[b_step*3+1]; - double t2 = a[0]*b[2] + a[1]*b[b_step+2] + a[2]*b[b_step*2+2] + a[3]*b[b_step*3+2]; - double t3 = a[0]*b[3] + a[1]*b[b_step+3] + a[2]*b[b_step*2+3] + a[3]*b[b_step*3+3]; - d[0] = t0*alpha + c[0]*beta; - d[1] = t1*alpha + c[1]*beta; - d[2] = t2*alpha + c[2]*beta; - d[3] = t3*alpha + c[3]*beta; - } - } - else if( d_size.width <= 16 && a != d ) - { - int c_step0 = 1; - if( c == zero ) - { - c_step0 = 0; - c_step = 1; - } - - for( i = 0; i < d_size.width; i++, d++, b++, c += c_step0 ) - { - double t0 = a[0]*b[0] + a[1]*b[b_step] + a[2]*b[b_step*2] + a[3]*b[b_step*3]; - double t1 = a[a_step]*b[0] + a[a_step+1]*b[b_step] + - a[a_step+2]*b[b_step*2] + a[a_step+3]*b[b_step*3]; - double t2 = a[a_step*2]*b[0] + a[a_step*2+1]*b[b_step] + - a[a_step*2+2]*b[b_step*2] + a[a_step*2+3]*b[b_step*3]; - double t3 = a[a_step*3]*b[0] + a[a_step*3+1]*b[b_step] + - a[a_step*3+2]*b[b_step*2] + a[a_step*3+3]*b[b_step*3]; - d[0] = t0*alpha + c[0]*beta; - d[d_step] = t1*alpha + c[c_step]*beta; - d[d_step*2] = t2*alpha + c[c_step*2]*beta; - d[d_step*3] = t3*alpha + c[c_step*3]*beta; - } - } - else - break; - return; - } - } + CV_Assert_N( C.type() == type, + (((flags&GEMM_3_T) == 0 && C.rows == d_size.height && C.cols == d_size.width) || + ((flags&GEMM_3_T) != 0 && C.rows == d_size.width && C.cols == d_size.height))); } + _matD.create( d_size.height, d_size.width, type ); + Mat D = _matD.getMat(); + if( (flags & GEMM_3_T) != 0 && C.data == D.data ) { - size_t b_step = B.step; - GEMMSingleMulFunc singleMulFunc; - GEMMBlockMulFunc blockMulFunc; - GEMMStoreFunc storeFunc; - Mat *matD = &D; - const uchar* Cdata = C.data; - size_t Cstep = C.data ? (size_t)C.step : 0; - AutoBuffer buf; - - if( type == CV_32FC1 ) - { - singleMulFunc = (GEMMSingleMulFunc)GEMMSingleMul_32f; - blockMulFunc = (GEMMBlockMulFunc)GEMMBlockMul_32f; - storeFunc = (GEMMStoreFunc)GEMMStore_32f; - } - else if( type == CV_64FC1 ) - { - singleMulFunc = (GEMMSingleMulFunc)GEMMSingleMul_64f; - blockMulFunc = (GEMMBlockMulFunc)GEMMBlockMul_64f; - storeFunc = (GEMMStoreFunc)GEMMStore_64f; - } - else if( type == CV_32FC2 ) - { - singleMulFunc = (GEMMSingleMulFunc)GEMMSingleMul_32fc; - blockMulFunc = (GEMMBlockMulFunc)GEMMBlockMul_32fc; - storeFunc = (GEMMStoreFunc)GEMMStore_32fc; - } - else - { - CV_Assert( type == CV_64FC2 ); - singleMulFunc = (GEMMSingleMulFunc)GEMMSingleMul_64fc; - blockMulFunc = (GEMMBlockMulFunc)GEMMBlockMul_64fc; - storeFunc = (GEMMStoreFunc)GEMMStore_64fc; - } - - if( (d_size.width == 1 || len == 1) && !(flags & GEMM_2_T) && B.isContinuous() ) - { - b_step = d_size.width == 1 ? 0 : CV_ELEM_SIZE(type); - flags |= GEMM_2_T; - } - - /*if( (d_size.width | d_size.height | len) >= 16 && icvBLAS_GEMM_32f_p != 0 ) - { - blas_func = type == CV_32FC1 ? (icvBLAS_GEMM_32f_t)icvBLAS_GEMM_32f_p : - type == CV_64FC1 ? (icvBLAS_GEMM_32f_t)icvBLAS_GEMM_64f_p : - type == CV_32FC2 ? (icvBLAS_GEMM_32f_t)icvBLAS_GEMM_32fc_p : - type == CV_64FC2 ? (icvBLAS_GEMM_32f_t)icvBLAS_GEMM_64fc_p : 0; - } - - if( blas_func ) - { - const char* transa = flags & GEMM_1_T ? "t" : "n"; - const char* transb = flags & GEMM_2_T ? "t" : "n"; - int lda, ldb, ldd; - - if( C->data.ptr ) - { - if( C->data.ptr != D->data.ptr ) - { - if( !(flags & GEMM_3_T) ) - cvCopy( C, D ); - else - cvTranspose( C, D ); - } - } - - if( CV_MAT_DEPTH(type) == CV_32F ) - { - Complex32f _alpha, _beta; - - lda = A->step/sizeof(float); - ldb = b_step/sizeof(float); - ldd = D->step/sizeof(float); - _alpha.re = (float)alpha; - _alpha.im = 0; - _beta.re = C->data.ptr ? (float)beta : 0; - _beta.im = 0; - if( CV_MAT_CN(type) == 2 ) - lda /= 2, ldb /= 2, ldd /= 2; - - blas_func( transb, transa, &d_size.width, &d_size.height, &len, - &_alpha, B->data.ptr, &ldb, A->data.ptr, &lda, - &_beta, D->data.ptr, &ldd ); - } - else - { - CvComplex64f _alpha, _beta; - - lda = A->step/sizeof(double); - ldb = b_step/sizeof(double); - ldd = D->step/sizeof(double); - _alpha.re = alpha; - _alpha.im = 0; - _beta.re = C->data.ptr ? beta : 0; - _beta.im = 0; - if( CV_MAT_CN(type) == 2 ) - lda /= 2, ldb /= 2, ldd /= 2; - - blas_func( transb, transa, &d_size.width, &d_size.height, &len, - &_alpha, B->data.ptr, &ldb, A->data.ptr, &lda, - &_beta, D->data.ptr, &ldd ); - } - } - else*/ if( ((d_size.height <= block_lin_size/2 || d_size.width <= block_lin_size/2) && - len <= 10000) || len <= 10 || - (d_size.width <= block_lin_size && - d_size.height <= block_lin_size && len <= block_lin_size) ) - { - singleMulFunc( A.ptr(), A.step, B.ptr(), b_step, Cdata, Cstep, - matD->ptr(), matD->step, a_size, d_size, alpha, beta, flags ); - } - else - { - int is_a_t = flags & GEMM_1_T; - int is_b_t = flags & GEMM_2_T; - int elem_size = CV_ELEM_SIZE(type); - int dk0_1, dk0_2; - size_t a_buf_size = 0, b_buf_size, d_buf_size; - uchar* a_buf = 0; - uchar* b_buf = 0; - uchar* d_buf = 0; - int j, k, di = 0, dj = 0, dk = 0; - int dm0, dn0, dk0; - size_t a_step0, a_step1, b_step0, b_step1, c_step0, c_step1; - int work_elem_size = elem_size << (CV_MAT_DEPTH(type) == CV_32F ? 1 : 0); - - if( !is_a_t ) - a_step0 = A.step, a_step1 = elem_size; - else - a_step0 = elem_size, a_step1 = A.step; - - if( !is_b_t ) - b_step0 = b_step, b_step1 = elem_size; - else - b_step0 = elem_size, b_step1 = b_step; - - if( C.empty() ) - { - c_step0 = c_step1 = 0; - flags &= ~GEMM_3_T; - } - else if( !(flags & GEMM_3_T) ) - c_step0 = C.step, c_step1 = elem_size; - else - c_step0 = elem_size, c_step1 = C.step; - - dm0 = std::min( block_lin_size, d_size.height ); - dn0 = std::min( block_lin_size, d_size.width ); - dk0_1 = block_size / dm0; - dk0_2 = block_size / dn0; - dk0 = std::min( dk0_1, dk0_2 ); - dk0 = std::min( dk0, len ); - if( dk0*dm0 > block_size ) - dm0 = block_size / dk0; - if( dk0*dn0 > block_size ) - dn0 = block_size / dk0; - - dk0_1 = (dn0+dn0/8+2) & -2; - b_buf_size = (size_t)(dk0+dk0/8+1)*dk0_1*elem_size; - d_buf_size = (size_t)(dk0+dk0/8+1)*dk0_1*work_elem_size; - - if( is_a_t ) - { - a_buf_size = (size_t)(dm0+dm0/8+1)*((dk0+dk0/8+2)&-2)*elem_size; - flags &= ~GEMM_1_T; - } - - buf.allocate(d_buf_size + b_buf_size + a_buf_size); - d_buf = buf.data(); - b_buf = d_buf + d_buf_size; - - if( is_a_t ) - a_buf = b_buf + b_buf_size; - - for( i = 0; i < d_size.height; i += di ) - { - di = dm0; - if( i + di >= d_size.height || 8*(i + di) + di > 8*d_size.height ) - di = d_size.height - i; - - for( j = 0; j < d_size.width; j += dj ) - { - uchar* _d = matD->ptr() + i*matD->step + j*elem_size; - const uchar* _c = Cdata + i*c_step0 + j*c_step1; - size_t _d_step = matD->step; - dj = dn0; - - if( j + dj >= d_size.width || 8*(j + dj) + dj > 8*d_size.width ) - dj = d_size.width - j; - - flags &= 15; - if( dk0 < len ) - { - _d = d_buf; - _d_step = dj*work_elem_size; - } - - for( k = 0; k < len; k += dk ) - { - const uchar* _a = A.ptr() + i*a_step0 + k*a_step1; - size_t _a_step = A.step; - const uchar* _b = B.ptr() + k*b_step0 + j*b_step1; - size_t _b_step = b_step; - Size a_bl_size; - - dk = dk0; - if( k + dk >= len || 8*(k + dk) + dk > 8*len ) - dk = len - k; - - if( !is_a_t ) - a_bl_size.width = dk, a_bl_size.height = di; - else - a_bl_size.width = di, a_bl_size.height = dk; - - if( a_buf && is_a_t ) - { - _a_step = dk*elem_size; - GEMM_TransposeBlock( _a, A.step, a_buf, _a_step, a_bl_size, elem_size ); - std::swap( a_bl_size.width, a_bl_size.height ); - _a = a_buf; - } - - if( dj < d_size.width ) - { - Size b_size; - if( !is_b_t ) - b_size.width = dj, b_size.height = dk; - else - b_size.width = dk, b_size.height = dj; - - _b_step = b_size.width*elem_size; - GEMM_CopyBlock( _b, b_step, b_buf, _b_step, b_size, elem_size ); - _b = b_buf; - } - - if( dk0 < len ) - blockMulFunc( _a, _a_step, _b, _b_step, _d, _d_step, - a_bl_size, Size(dj,di), flags ); - else - singleMulFunc( _a, _a_step, _b, _b_step, _c, Cstep, - _d, _d_step, a_bl_size, Size(dj,di), alpha, beta, flags ); - flags |= 16; - } - - if( dk0 < len ) - storeFunc( _c, Cstep, _d, _d_step, - matD->ptr(i) + j*elem_size, - matD->step, Size(dj,di), alpha, beta, flags ); - } - } - } - } -} - -template inline static void -callGemmImpl(const fptype *src1, size_t src1_step, const fptype *src2, size_t src2_step, fptype alpha, - const fptype *src3, size_t src3_step, fptype beta, fptype *dst, size_t dst_step, int m_a, int n_a, int n_d, int flags, int type) -{ - CV_StaticAssert(GEMM_1_T == CV_HAL_GEMM_1_T, "Incompatible GEMM_1_T flag in HAL"); - CV_StaticAssert(GEMM_2_T == CV_HAL_GEMM_2_T, "Incompatible GEMM_2_T flag in HAL"); - CV_StaticAssert(GEMM_3_T == CV_HAL_GEMM_3_T, "Incompatible GEMM_3_T flag in HAL"); - - int b_m, b_n, c_m, c_n, m_d; - - if(flags & GEMM_2_T) - { - b_m = n_d; - if(flags & GEMM_1_T ) - { - b_n = m_a; - m_d = n_a; - } - else - { - b_n = n_a; - m_d = m_a; - } - } - else - { - b_n = n_d; - if(flags & GEMM_1_T ) - { - b_m = m_a; - m_d = n_a; - } - else - { - m_d = m_a; - b_m = n_a; - } - } - - if(flags & GEMM_3_T) - { - c_m = n_d; - c_n = m_d; - } - else - { - c_m = m_d; - c_n = n_d; - } - - Mat A, B, C; - if(src1 != NULL) - A = Mat(m_a, n_a, type, (void*)src1, src1_step); - if(src2 != NULL) - B = Mat(b_m, b_n, type, (void*)src2, src2_step); - if(src3 != NULL && beta != 0.0) - C = Mat(c_m, c_n, type, (void*)src3, src3_step); - Mat D(m_d, n_d, type, (void*)dst, dst_step); - - gemmImpl(A, B, alpha, C, beta, D, flags); -} - -} - -void cv::hal::gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step, - float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, - int m_a, int n_a, int n_d, int flags) -{ - - CALL_HAL(gemm32f, cv_hal_gemm32f, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) - callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_32F); -} - -void cv::hal::gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step, - double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, - int m_a, int n_a, int n_d, int flags) -{ - CALL_HAL(gemm64f, cv_hal_gemm64f, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) - callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_64F); -} - -CV_EXPORTS void cv::hal::gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step, - float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, - int m_a, int n_a, int n_d, int flags) -{ - CALL_HAL(gemm32fc, cv_hal_gemm32fc, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) - callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_32FC2); -} - -CV_EXPORTS void cv::hal::gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step, - double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, - int m_a, int n_a, int n_d, int flags) -{ - CALL_HAL(gemm64fc, cv_hal_gemm64fc, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) - callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_64FC2); -} - -void cv::gemm( InputArray matA, InputArray matB, double alpha, - InputArray matC, double beta, OutputArray _matD, int flags ) -{ -#ifdef HAVE_CLAMDBLAS - CV_OCL_RUN(ocl::haveAmdBlas() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2 && _matD.isUMat() && - matA.cols() > 20 && matA.rows() > 20 && matB.cols() > 20, // since it works incorrect for small sizes - ocl_gemm_amdblas(matA, matB, alpha, matC, beta, _matD, flags)) -#endif - -#ifdef HAVE_OPENCL - CV_OCL_RUN(_matD.isUMat() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2, - ocl_gemm(matA, matB, alpha, matC, beta, _matD, flags)) -#endif - - Mat A = matA.getMat(), B = matB.getMat(), C = beta != 0.0 ? matC.getMat() : Mat(); - Size a_size = A.size(), d_size; - int len = 0, type = A.type(); - - CV_Assert_N( type == B.type(), (type == CV_32FC1 || type == CV_64FC1 || type == CV_32FC2 || type == CV_64FC2) ); - - switch( flags & (GEMM_1_T|GEMM_2_T) ) - { - case 0: - d_size = Size( B.cols, a_size.height ); - len = B.rows; - CV_Assert( a_size.width == len ); - break; - case 1: - d_size = Size( B.cols, a_size.width ); - len = B.rows; - CV_Assert( a_size.height == len ); - break; - case 2: - d_size = Size( B.rows, a_size.height ); - len = B.cols; - CV_Assert( a_size.width == len ); - break; - case 3: - d_size = Size( B.rows, a_size.width ); - len = B.cols; - CV_Assert( a_size.height == len ); - break; - } - - if( !C.empty() ) - { - CV_Assert_N( C.type() == type, - (((flags&GEMM_3_T) == 0 && C.rows == d_size.height && C.cols == d_size.width) || - ((flags&GEMM_3_T) != 0 && C.rows == d_size.width && C.cols == d_size.height))); - } - - _matD.create( d_size.height, d_size.width, type ); - Mat D = _matD.getMat(); - if( (flags & GEMM_3_T) != 0 && C.data == D.data ) - { - transpose( C, C ); - flags &= ~GEMM_3_T; - } + transpose( C, C ); + flags &= ~GEMM_3_T; + } Mat *DProxyPtr = &D, DProxy; if( D.data == A.data || D.data == B.data ) @@ -1631,457 +410,27 @@ void cv::gemm( InputArray matA, InputArray matB, double alpha, DProxyPtr->copyTo(D); } + + /****************************************************************************************\ * Transform * \****************************************************************************************/ -namespace cv -{ - -template static void -transform_( const T* src, T* dst, const WT* m, int len, int scn, int dcn ) -{ - int x; - - if( scn == 2 && dcn == 2 ) - { - for( x = 0; x < len*2; x += 2 ) - { - WT v0 = src[x], v1 = src[x+1]; - T t0 = saturate_cast(m[0]*v0 + m[1]*v1 + m[2]); - T t1 = saturate_cast(m[3]*v0 + m[4]*v1 + m[5]); - dst[x] = t0; dst[x+1] = t1; - } - } - else if( scn == 3 && dcn == 3 ) - { - for( x = 0; x < len*3; x += 3 ) - { - WT v0 = src[x], v1 = src[x+1], v2 = src[x+2]; - T t0 = saturate_cast(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]); - T t1 = saturate_cast(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]); - T t2 = saturate_cast(m[8]*v0 + m[9]*v1 + m[10]*v2 + m[11]); - dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2; - } - } - else if( scn == 3 && dcn == 1 ) - { - for( x = 0; x < len; x++, src += 3 ) - dst[x] = saturate_cast(m[0]*src[0] + m[1]*src[1] + m[2]*src[2] + m[3]); - } - else if( scn == 4 && dcn == 4 ) - { - for( x = 0; x < len*4; x += 4 ) - { - WT v0 = src[x], v1 = src[x+1], v2 = src[x+2], v3 = src[x+3]; - T t0 = saturate_cast(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]*v3 + m[4]); - T t1 = saturate_cast(m[5]*v0 + m[6]*v1 + m[7]*v2 + m[8]*v3 + m[9]); - dst[x] = t0; dst[x+1] = t1; - t0 = saturate_cast(m[10]*v0 + m[11]*v1 + m[12]*v2 + m[13]*v3 + m[14]); - t1 = saturate_cast(m[15]*v0 + m[16]*v1 + m[17]*v2 + m[18]*v3 + m[19]); - dst[x+2] = t0; dst[x+3] = t1; - } - } - else - { - for( x = 0; x < len; x++, src += scn, dst += dcn ) - { - const WT* _m = m; - int j, k; - for( j = 0; j < dcn; j++, _m += scn + 1 ) - { - WT s = _m[scn]; - for( k = 0; k < scn; k++ ) - s += _m[k]*src[k]; - dst[j] = saturate_cast(s); - } - } - } -} - -#if CV_SIMD128 && !defined(__aarch64__) -static inline void -load3x3Matrix(const float* m, v_float32x4& m0, v_float32x4& m1, v_float32x4& m2, v_float32x4& m3) -{ - m0 = v_float32x4(m[0], m[4], m[8], 0); - m1 = v_float32x4(m[1], m[5], m[9], 0); - m2 = v_float32x4(m[2], m[6], m[10], 0); - m3 = v_float32x4(m[3], m[7], m[11], 0); -} -#endif - -#if CV_SIMD128 -static inline v_int16x8 -v_matmulvec(const v_int16x8 &v0, const v_int16x8 &m0, const v_int16x8 &m1, const v_int16x8 &m2, const v_int32x4 &m3, const int BITS) -{ - // v0 : 0 b0 g0 r0 b1 g1 r1 ? - v_int32x4 t0 = v_dotprod(v0, m0); // a0 b0 a1 b1 - v_int32x4 t1 = v_dotprod(v0, m1); // c0 d0 c1 d1 - v_int32x4 t2 = v_dotprod(v0, m2); // e0 f0 e1 f1 - v_int32x4 t3 = v_setzero_s32(); - v_int32x4 s0, s1, s2, s3; - v_transpose4x4(t0, t1, t2, t3, s0, s1, s2, s3); - s0 = s0 + s1 + m3; // B0 G0 R0 ? - s2 = s2 + s3 + m3; // B1 G1 R1 ? - - s0 = s0 >> BITS; - s2 = s2 >> BITS; - - v_int16x8 result = v_pack(s0, v_setzero_s32()); // B0 G0 R0 0 0 0 0 0 - result = v_reinterpret_as_s16(v_reinterpret_as_s64(result) << 16); // 0 B0 G0 R0 0 0 0 0 - result = result | v_pack(v_setzero_s32(), s2); // 0 B0 G0 R0 B1 G1 R1 0 - return result; -} -#endif - -static void -transform_8u( const uchar* src, uchar* dst, const float* m, int len, int scn, int dcn ) -{ -#if CV_SIMD128 - const int BITS = 10, SCALE = 1 << BITS; - const float MAX_M = (float)(1 << (15 - BITS)); - - if( hasSIMD128() && scn == 3 && dcn == 3 && - std::abs(m[0]) < MAX_M && std::abs(m[1]) < MAX_M && std::abs(m[2]) < MAX_M && std::abs(m[3]) < MAX_M*256 && - std::abs(m[4]) < MAX_M && std::abs(m[5]) < MAX_M && std::abs(m[6]) < MAX_M && std::abs(m[7]) < MAX_M*256 && - std::abs(m[8]) < MAX_M && std::abs(m[9]) < MAX_M && std::abs(m[10]) < MAX_M && std::abs(m[11]) < MAX_M*256 ) - { - const int nChannels = 3; - const int cWidth = v_int16x8::nlanes; - // faster fixed-point transformation - short m00 = saturate_cast(m[0]*SCALE), m01 = saturate_cast(m[1]*SCALE), - m02 = saturate_cast(m[2]*SCALE), m10 = saturate_cast(m[4]*SCALE), - m11 = saturate_cast(m[5]*SCALE), m12 = saturate_cast(m[6]*SCALE), - m20 = saturate_cast(m[8]*SCALE), m21 = saturate_cast(m[9]*SCALE), - m22 = saturate_cast(m[10]*SCALE); - int m03 = saturate_cast((m[3]+0.5f)*SCALE), m13 = saturate_cast((m[7]+0.5f)*SCALE ), - m23 = saturate_cast((m[11]+0.5f)*SCALE); - - v_int16x8 m0 = v_int16x8(0, m00, m01, m02, m00, m01, m02, 0); - v_int16x8 m1 = v_int16x8(0, m10, m11, m12, m10, m11, m12, 0); - v_int16x8 m2 = v_int16x8(0, m20, m21, m22, m20, m21, m22, 0); - v_int32x4 m3 = v_int32x4(m03, m13, m23, 0); - int x = 0; - - for (; x <= (len - cWidth) * nChannels; x += cWidth * nChannels) - { - // load 8 pixels - v_int16x8 v0 = v_reinterpret_as_s16(v_load_expand(src + x)); - v_int16x8 v1 = v_reinterpret_as_s16(v_load_expand(src + x + cWidth)); - v_int16x8 v2 = v_reinterpret_as_s16(v_load_expand(src + x + cWidth * 2)); - v_int16x8 v3; - - // rotate and pack - v3 = v_rotate_right<1>(v2); // 0 b6 g6 r6 b7 g7 r7 0 - v2 = v_rotate_left <5>(v2, v1); // 0 b4 g4 r4 b5 g5 r5 0 - v1 = v_rotate_left <3>(v1, v0); // 0 b2 g2 r2 b3 g3 r3 0 - v0 = v_rotate_left <1>(v0); // 0 b0 g0 r0 b1 g1 r1 0 - - // multiply with matrix and normalize - v0 = v_matmulvec(v0, m0, m1, m2, m3, BITS); // 0 B0 G0 R0 B1 G1 R1 0 - v1 = v_matmulvec(v1, m0, m1, m2, m3, BITS); // 0 B2 G2 R2 B3 G3 R3 0 - v2 = v_matmulvec(v2, m0, m1, m2, m3, BITS); // 0 B4 G4 R4 B5 G5 R5 0 - v3 = v_matmulvec(v3, m0, m1, m2, m3, BITS); // 0 B6 G6 R6 B7 G7 R7 0 - - // narrow down as uint8x16 - v_uint8x16 z0 = v_pack_u(v0, v_setzero_s16()); // 0 B0 G0 R0 B1 G1 R1 0 0 0 0 0 0 0 0 0 - v_uint8x16 z1 = v_pack_u(v1, v_setzero_s16()); // 0 B2 G2 R2 B3 G3 R3 0 0 0 0 0 0 0 0 0 - v_uint8x16 z2 = v_pack_u(v2, v_setzero_s16()); // 0 B4 G4 R4 B5 G5 R5 0 0 0 0 0 0 0 0 0 - v_uint8x16 z3 = v_pack_u(v3, v_setzero_s16()); // 0 B6 G6 R6 B7 G7 R7 0 0 0 0 0 0 0 0 0 - - // rotate and pack - z0 = v_reinterpret_as_u8(v_reinterpret_as_u64(z0) >> 8) | v_reinterpret_as_u8(v_reinterpret_as_u64(z1) << 40); // B0 G0 R0 B1 G1 R1 B2 G2 0 0 0 0 0 0 0 0 - z1 = v_reinterpret_as_u8(v_reinterpret_as_u64(z1) >> 24) | v_reinterpret_as_u8(v_reinterpret_as_u64(z2) << 24); // R2 B3 G3 R3 B4 G4 R4 B5 0 0 0 0 0 0 0 0 - z2 = v_reinterpret_as_u8(v_reinterpret_as_u64(z2) >> 40) | v_reinterpret_as_u8(v_reinterpret_as_u64(z3) << 8); // G5 R6 B6 G6 R6 B7 G7 R7 0 0 0 0 0 0 0 0 - - // store on memory - v_store_low(dst + x, z0); - v_store_low(dst + x + cWidth, z1); - v_store_low(dst + x + cWidth * 2, z2); - } - - for( ; x < len * nChannels; x += nChannels ) - { - int v0 = src[x], v1 = src[x+1], v2 = src[x+2]; - uchar t0 = saturate_cast((m00*v0 + m01*v1 + m02*v2 + m03)>>BITS); - uchar t1 = saturate_cast((m10*v0 + m11*v1 + m12*v2 + m13)>>BITS); - uchar t2 = saturate_cast((m20*v0 + m21*v1 + m22*v2 + m23)>>BITS); - dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2; - } - return; - } -#endif - - transform_(src, dst, m, len, scn, dcn); -} - -static void -transform_16u( const ushort* src, ushort* dst, const float* m, int len, int scn, int dcn ) -{ -#if CV_SIMD128 && !defined(__aarch64__) - if( hasSIMD128() && scn == 3 && dcn == 3 ) - { - const int nChannels = 3; - const int cWidth = v_float32x4::nlanes; - v_int16x8 delta = v_int16x8(0, -32768, -32768, -32768, -32768, -32768, -32768, 0); - v_float32x4 m0, m1, m2, m3; - load3x3Matrix(m, m0, m1, m2, m3); - m3 -= v_float32x4(32768.f, 32768.f, 32768.f, 0.f); - - int x = 0; - for( ; x <= (len - cWidth) * nChannels; x += cWidth * nChannels ) - { - // load 4 pixels - v_uint16x8 v0_16 = v_load(src + x); // b0 g0 r0 b1 g1 r1 b2 g2 - v_uint16x8 v2_16 = v_load_low(src + x + cWidth * 2); // r2 b3 g3 r3 ? ? ? ? - - // expand to 4 vectors - v_uint32x4 v0_32, v1_32, v2_32, v3_32, dummy_32; - v_expand(v_rotate_right<3>(v0_16), v1_32, dummy_32); // b1 g1 r1 - v_expand(v_rotate_right<1>(v2_16), v3_32, dummy_32); // b3 g3 r3 - v_expand(v_rotate_right<6>(v0_16, v2_16), v2_32, dummy_32); // b2 g2 r2 - v_expand(v0_16, v0_32, dummy_32); // b0 g0 r0 - - // convert to float32x4 - v_float32x4 x0 = v_cvt_f32(v_reinterpret_as_s32(v0_32)); // b0 g0 r0 - v_float32x4 x1 = v_cvt_f32(v_reinterpret_as_s32(v1_32)); // b1 g1 r1 - v_float32x4 x2 = v_cvt_f32(v_reinterpret_as_s32(v2_32)); // b2 g2 r2 - v_float32x4 x3 = v_cvt_f32(v_reinterpret_as_s32(v3_32)); // b3 g3 r3 - - // multiply and convert back to int32x4 - v_int32x4 y0, y1, y2, y3; - y0 = v_round(v_matmuladd(x0, m0, m1, m2, m3)); // B0 G0 R0 - y1 = v_round(v_matmuladd(x1, m0, m1, m2, m3)); // B1 G1 R1 - y2 = v_round(v_matmuladd(x2, m0, m1, m2, m3)); // B2 G2 R2 - y3 = v_round(v_matmuladd(x3, m0, m1, m2, m3)); // B3 G3 R3 - - // narrow down to int16x8 - v_int16x8 v0 = v_add_wrap(v_pack(v_rotate_left<1>(y0), y1), delta); // 0 B0 G0 R0 B1 G1 R1 0 - v_int16x8 v2 = v_add_wrap(v_pack(v_rotate_left<1>(y2), y3), delta); // 0 B2 G2 R2 B3 G3 R3 0 - - // rotate and pack - v0 = v_rotate_right<1>(v0) | v_rotate_left<5>(v2); // B0 G0 R0 B1 G1 R1 B2 G2 - v2 = v_rotate_right<3>(v2); // R2 B3 G3 R3 0 0 0 0 - - // store 4 pixels - v_store(dst + x, v_reinterpret_as_u16(v0)); - v_store_low(dst + x + cWidth * 2, v_reinterpret_as_u16(v2)); - } - - for( ; x < len * nChannels; x += nChannels ) - { - float v0 = src[x], v1 = src[x + 1], v2 = src[x + 2]; - ushort t0 = saturate_cast(m[0] * v0 + m[1] * v1 + m[2] * v2 + m[3]); - ushort t1 = saturate_cast(m[4] * v0 + m[5] * v1 + m[6] * v2 + m[7]); - ushort t2 = saturate_cast(m[8] * v0 + m[9] * v1 + m[10] * v2 + m[11]); - dst[x] = t0; dst[x + 1] = t1; dst[x + 2] = t2; - } - return; - } -#endif - - transform_(src, dst, m, len, scn, dcn); -} - -static void -transform_32f( const float* src, float* dst, const float* m, int len, int scn, int dcn ) -{ -#if CV_SIMD128 && !defined(__aarch64__) - if( hasSIMD128() ) - { - int x = 0; - if( scn == 3 && dcn == 3 ) - { - const int cWidth = 3; - v_float32x4 m0, m1, m2, m3; - load3x3Matrix(m, m0, m1, m2, m3); - - for( ; x < (len - 1)*cWidth; x += cWidth ) - { - v_float32x4 x0 = v_load(src + x); - v_float32x4 y0 = v_matmuladd(x0, m0, m1, m2, m3); - v_store_low(dst + x, y0); - dst[x + 2] = v_combine_high(y0, y0).get0(); - } - - for( ; x < len*cWidth; x += cWidth ) - { - float v0 = src[x], v1 = src[x+1], v2 = src[x+2]; - float t0 = saturate_cast(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]); - float t1 = saturate_cast(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]); - float t2 = saturate_cast(m[8]*v0 + m[9]*v1 + m[10]*v2 + m[11]); - dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2; - } - return; - } - - if( scn == 4 && dcn == 4 ) - { - const int cWidth = 4; - v_float32x4 m0 = v_float32x4(m[0], m[5], m[10], m[15]); - v_float32x4 m1 = v_float32x4(m[1], m[6], m[11], m[16]); - v_float32x4 m2 = v_float32x4(m[2], m[7], m[12], m[17]); - v_float32x4 m3 = v_float32x4(m[3], m[8], m[13], m[18]); - v_float32x4 m4 = v_float32x4(m[4], m[9], m[14], m[19]); - - for( ; x < len*cWidth; x += cWidth ) - { - v_float32x4 x0 = v_load(src + x); - v_float32x4 y0 = v_matmul(x0, m0, m1, m2, m3) + m4; - v_store(dst + x, y0); - } - return; - } - } -#endif - - transform_(src, dst, m, len, scn, dcn); -} - - -static void -transform_8s(const schar* src, schar* dst, const float* m, int len, int scn, int dcn) -{ - transform_(src, dst, m, len, scn, dcn); -} - -static void -transform_16s(const short* src, short* dst, const float* m, int len, int scn, int dcn) -{ - transform_(src, dst, m, len, scn, dcn); -} - -static void -transform_32s(const int* src, int* dst, const double* m, int len, int scn, int dcn) -{ - transform_(src, dst, m, len, scn, dcn); -} - -static void -transform_64f(const double* src, double* dst, const double* m, int len, int scn, int dcn) -{ - transform_(src, dst, m, len, scn, dcn); -} - -template static void -diagtransform_( const T* src, T* dst, const WT* m, int len, int cn, int ) -{ - int x; - - if( cn == 2 ) - { - for( x = 0; x < len*2; x += 2 ) - { - T t0 = saturate_cast(m[0]*src[x] + m[2]); - T t1 = saturate_cast(m[4]*src[x+1] + m[5]); - dst[x] = t0; dst[x+1] = t1; - } - } - else if( cn == 3 ) - { - for( x = 0; x < len*3; x += 3 ) - { - T t0 = saturate_cast(m[0]*src[x] + m[3]); - T t1 = saturate_cast(m[5]*src[x+1] + m[7]); - T t2 = saturate_cast(m[10]*src[x+2] + m[11]); - dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2; - } - } - else if( cn == 4 ) - { - for( x = 0; x < len*4; x += 4 ) - { - T t0 = saturate_cast(m[0]*src[x] + m[4]); - T t1 = saturate_cast(m[6]*src[x+1] + m[9]); - dst[x] = t0; dst[x+1] = t1; - t0 = saturate_cast(m[12]*src[x+2] + m[14]); - t1 = saturate_cast(m[18]*src[x+3] + m[19]); - dst[x+2] = t0; dst[x+3] = t1; - } - } - else - { - for( x = 0; x < len; x++, src += cn, dst += cn ) - { - const WT* _m = m; - for( int j = 0; j < cn; j++, _m += cn + 1 ) - dst[j] = saturate_cast(src[j]*_m[j] + _m[cn]); - } - } -} - -static void -diagtransform_8u(const uchar* src, uchar* dst, const float* m, int len, int scn, int dcn) -{ - diagtransform_(src, dst, m, len, scn, dcn); -} - -static void -diagtransform_8s(const schar* src, schar* dst, const float* m, int len, int scn, int dcn) -{ - diagtransform_(src, dst, m, len, scn, dcn); -} - -static void -diagtransform_16u(const ushort* src, ushort* dst, const float* m, int len, int scn, int dcn) -{ - diagtransform_(src, dst, m, len, scn, dcn); -} - -static void -diagtransform_16s(const short* src, short* dst, const float* m, int len, int scn, int dcn) -{ - diagtransform_(src, dst, m, len, scn, dcn); -} - -static void -diagtransform_32s(const int* src, int* dst, const double* m, int len, int scn, int dcn) -{ - diagtransform_(src, dst, m, len, scn, dcn); -} - -static void -diagtransform_32f(const float* src, float* dst, const float* m, int len, int scn, int dcn) -{ - diagtransform_(src, dst, m, len, scn, dcn); -} - -static void -diagtransform_64f(const double* src, double* dst, const double* m, int len, int scn, int dcn) -{ - diagtransform_(src, dst, m, len, scn, dcn); -} - - -typedef void (*TransformFunc)( const uchar* src, uchar* dst, const uchar* m, int, int, int ); - static TransformFunc getTransformFunc(int depth) { - static TransformFunc transformTab[] = - { - (TransformFunc)transform_8u, (TransformFunc)transform_8s, (TransformFunc)transform_16u, - (TransformFunc)transform_16s, (TransformFunc)transform_32s, (TransformFunc)transform_32f, - (TransformFunc)transform_64f, 0 - }; - - return transformTab[depth]; + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(getTransformFunc, (depth), + CV_CPU_DISPATCH_MODES_ALL); } static TransformFunc getDiagTransformFunc(int depth) { - static TransformFunc diagTransformTab[] = - { - (TransformFunc)diagtransform_8u, (TransformFunc)diagtransform_8s, (TransformFunc)diagtransform_16u, - (TransformFunc)diagtransform_16s, (TransformFunc)diagtransform_32s, (TransformFunc)diagtransform_32f, - (TransformFunc)diagtransform_64f, 0 - }; - - return diagTransformTab[depth]; -} - + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(getDiagTransformFunc, (depth), + CV_CPU_DISPATCH_MODES_ALL); } -void cv::transform( InputArray _src, OutputArray _dst, InputArray _mtx ) +void transform(InputArray _src, OutputArray _dst, InputArray _mtx) { CV_INSTRUMENT_REGION(); @@ -2126,142 +475,48 @@ void cv::transform( InputArray _src, OutputArray _dst, InputArray _mtx ) if( mtype == CV_32F ) alpha = m.at(0), beta = m.at(1); else - alpha = m.at(0), beta = m.at(1); - src.convertTo(dst, dst.type(), alpha, beta); - return; - } - - for( i = 0, isDiag = true; isDiag && i < scn; i++ ) - { - for( j = 0; isDiag && j < scn; j++ ) - { - double v = mtype == CV_32F ? m.at(i, j) : m.at(i, j); - if( i != j && fabs(v) > eps ) - isDiag = false; - } - } - } - - TransformFunc func = isDiag ? getDiagTransformFunc(depth): getTransformFunc(depth); - CV_Assert( func != 0 ); - - const Mat* arrays[] = {&src, &dst, 0}; - uchar* ptrs[2] = {}; - NAryMatIterator it(arrays, ptrs); - size_t i, total = it.size; - - for( i = 0; i < it.nplanes; i++, ++it ) - func( ptrs[0], ptrs[1], (uchar*)mbuf, (int)total, scn, dcn ); -} - -/****************************************************************************************\ -* Perspective Transform * -\****************************************************************************************/ - -namespace cv -{ - -template static void -perspectiveTransform_( const T* src, T* dst, const double* m, int len, int scn, int dcn ) -{ - const double eps = FLT_EPSILON; - int i; - - if( scn == 2 && dcn == 2 ) - { - for( i = 0; i < len*2; i += 2 ) - { - T x = src[i], y = src[i + 1]; - double w = x*m[6] + y*m[7] + m[8]; - - if( fabs(w) > eps ) - { - w = 1./w; - dst[i] = (T)((x*m[0] + y*m[1] + m[2])*w); - dst[i+1] = (T)((x*m[3] + y*m[4] + m[5])*w); - } - else - dst[i] = dst[i+1] = (T)0; - } - } - else if( scn == 3 && dcn == 3 ) - { - for( i = 0; i < len*3; i += 3 ) - { - T x = src[i], y = src[i + 1], z = src[i + 2]; - double w = x*m[12] + y*m[13] + z*m[14] + m[15]; - - if( fabs(w) > eps ) - { - w = 1./w; - dst[i] = (T)((x*m[0] + y*m[1] + z*m[2] + m[3]) * w); - dst[i+1] = (T)((x*m[4] + y*m[5] + z*m[6] + m[7]) * w); - dst[i+2] = (T)((x*m[8] + y*m[9] + z*m[10] + m[11]) * w); - } - else - dst[i] = dst[i+1] = dst[i+2] = (T)0; - } - } - else if( scn == 3 && dcn == 2 ) - { - for( i = 0; i < len; i++, src += 3, dst += 2 ) - { - T x = src[0], y = src[1], z = src[2]; - double w = x*m[8] + y*m[9] + z*m[10] + m[11]; - - if( fabs(w) > eps ) - { - w = 1./w; - dst[0] = (T)((x*m[0] + y*m[1] + z*m[2] + m[3])*w); - dst[1] = (T)((x*m[4] + y*m[5] + z*m[6] + m[7])*w); - } - else - dst[0] = dst[1] = (T)0; + alpha = m.at(0), beta = m.at(1); + src.convertTo(dst, dst.type(), alpha, beta); + return; } - } - else - { - for( i = 0; i < len; i++, src += scn, dst += dcn ) + + for( i = 0, isDiag = true; isDiag && i < scn; i++ ) { - const double* _m = m + dcn*(scn + 1); - double w = _m[scn]; - int j, k; - for( k = 0; k < scn; k++ ) - w += _m[k]*src[k]; - if( fabs(w) > eps ) + for( j = 0; isDiag && j < scn; j++ ) { - _m = m; - for( j = 0; j < dcn; j++, _m += scn + 1 ) - { - double s = _m[scn]; - for( k = 0; k < scn; k++ ) - s += _m[k]*src[k]; - dst[j] = (T)(s*w); - } + double v = mtype == CV_32F ? m.at(i, j) : m.at(i, j); + if( i != j && fabs(v) > eps ) + isDiag = false; } - else - for( j = 0; j < dcn; j++ ) - dst[j] = 0; } } -} + TransformFunc func = isDiag ? getDiagTransformFunc(depth): getTransformFunc(depth); + CV_Assert( func != 0 ); + + const Mat* arrays[] = {&src, &dst, 0}; + uchar* ptrs[2] = {}; + NAryMatIterator it(arrays, ptrs); + size_t i, total = it.size; -static void -perspectiveTransform_32f(const float* src, float* dst, const double* m, int len, int scn, int dcn) -{ - perspectiveTransform_(src, dst, m, len, scn, dcn); + for( i = 0; i < it.nplanes; i++, ++it ) + func( ptrs[0], ptrs[1], (uchar*)mbuf, (int)total, scn, dcn ); } -static void -perspectiveTransform_64f(const double* src, double* dst, const double* m, int len, int scn, int dcn) -{ - perspectiveTransform_(src, dst, m, len, scn, dcn); -} + +/****************************************************************************************\ +* Perspective Transform * +\****************************************************************************************/ + +static TransformFunc getPerspectiveTransform(int depth) +{ + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(getPerspectiveTransform, (depth), + CV_CPU_DISPATCH_MODES_ALL); } -void cv::perspectiveTransform( InputArray _src, OutputArray _dst, InputArray _mtx ) +void perspectiveTransform(InputArray _src, OutputArray _dst, InputArray _mtx) { CV_INSTRUMENT_REGION(); @@ -2286,9 +541,7 @@ void cv::perspectiveTransform( InputArray _src, OutputArray _dst, InputArray _mt m = tmp; } - TransformFunc func = depth == CV_32F ? - (TransformFunc)perspectiveTransform_32f : - (TransformFunc)perspectiveTransform_64f; + TransformFunc func = getPerspectiveTransform(depth); CV_Assert( func != 0 ); const Mat* arrays[] = {&src, &dst, 0}; @@ -2304,44 +557,6 @@ void cv::perspectiveTransform( InputArray _src, OutputArray _dst, InputArray _mt * ScaleAdd * \****************************************************************************************/ -namespace cv -{ - -static void scaleAdd_32f(const float* src1, const float* src2, float* dst, - int len, float* _alpha) -{ - float alpha = *_alpha; - int i = 0; -#if CV_SIMD - v_float32 v_alpha = vx_setall_f32(alpha); - const int cWidth = v_float32::nlanes; - for (; i <= len - cWidth; i += cWidth) - v_store(dst + i, v_muladd(vx_load(src1 + i), v_alpha, vx_load(src2 + i))); - vx_cleanup(); -#endif - for (; i < len; i++) - dst[i] = src1[i] * alpha + src2[i]; -} - - -static void scaleAdd_64f(const double* src1, const double* src2, double* dst, - int len, double* _alpha) -{ - double alpha = *_alpha; - int i = 0; -#if CV_SIMD_64F - v_float64 a2 = vx_setall_f64(alpha); - const int cWidth = v_float64::nlanes; - for (; i <= len - cWidth; i += cWidth) - v_store(dst + i, v_muladd(vx_load(src1 + i), a2, vx_load(src2 + i))); - vx_cleanup(); -#endif - for (; i < len; i++) - dst[i] = src1[i] * alpha + src2[i]; -} - -typedef void (*ScaleAddFunc)(const uchar* src1, const uchar* src2, uchar* dst, int len, const void* alpha); - #ifdef HAVE_OPENCL static bool ocl_scaleAdd( InputArray _src1, double alpha, InputArray _src2, OutputArray _dst, int type ) @@ -2390,9 +605,14 @@ static bool ocl_scaleAdd( InputArray _src1, double alpha, InputArray _src2, Outp #endif +static ScaleAddFunc getScaleAddFunc(int depth) +{ + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(getScaleAddFunc, (depth), + CV_CPU_DISPATCH_MODES_ALL); } -void cv::scaleAdd( InputArray _src1, double alpha, InputArray _src2, OutputArray _dst ) +void scaleAdd(InputArray _src1, double alpha, InputArray _src2, OutputArray _dst) { CV_INSTRUMENT_REGION(); @@ -2417,7 +637,8 @@ void cv::scaleAdd( InputArray _src1, double alpha, InputArray _src2, OutputArray float falpha = (float)alpha; void* palpha = depth == CV_32F ? (void*)&falpha : (void*)α - ScaleAddFunc func = depth == CV_32F ? (ScaleAddFunc)scaleAdd_32f : (ScaleAddFunc)scaleAdd_64f; + ScaleAddFunc func = getScaleAddFunc(depth); + CV_Assert(func); if (src1.isContinuous() && src2.isContinuous() && dst.isContinuous()) { @@ -2439,7 +660,7 @@ void cv::scaleAdd( InputArray _src1, double alpha, InputArray _src2, OutputArray * Covariation Matrix * \****************************************************************************************/ -void cv::calcCovarMatrix( const Mat* data, int nsamples, Mat& covar, Mat& _mean, int flags, int ctype ) +void calcCovarMatrix( const Mat* data, int nsamples, Mat& covar, Mat& _mean, int flags, int ctype ) { CV_INSTRUMENT_REGION(); @@ -2481,7 +702,7 @@ void cv::calcCovarMatrix( const Mat* data, int nsamples, Mat& covar, Mat& _mean, _mean = mean.reshape(1, size.height); } -void cv::calcCovarMatrix( InputArray _src, OutputArray _covar, InputOutputArray _mean, int flags, int ctype ) +void calcCovarMatrix( InputArray _src, OutputArray _covar, InputOutputArray _mean, int flags, int ctype ) { CV_INSTRUMENT_REGION(); @@ -2566,20 +787,33 @@ void cv::calcCovarMatrix( InputArray _src, OutputArray _covar, InputOutputArray mean, (flags & CV_COVAR_SCALE) != 0 ? 1./nsamples : 1, ctype ); } + + /****************************************************************************************\ * Mahalanobis * \****************************************************************************************/ -double cv::Mahalanobis( InputArray _v1, InputArray _v2, InputArray _icovar ) +static MahalanobisImplFunc getMahalanobisImplFunc(int depth) +{ +#ifdef CV_MAHALANOBIS_BASELINE_ONLY + CV_CPU_CALL_BASELINE(getMahalanobisImplFunc, (depth)); +#else + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(getMahalanobisImplFunc, (depth), + CV_CPU_DISPATCH_MODES_ALL); +#endif +} + + +double Mahalanobis(InputArray _v1, InputArray _v2, InputArray _icovar) { CV_INSTRUMENT_REGION(); Mat v1 = _v1.getMat(), v2 = _v2.getMat(), icovar = _icovar.getMat(); int type = v1.type(), depth = v1.depth(); Size sz = v1.size(); - int i, j, len = sz.width*sz.height*v1.channels(); + int len = sz.width*sz.height*v1.channels(); AutoBuffer buf(len); - double result = 0; CV_Assert_N( type == v2.type(), type == icovar.type(), sz == v2.size(), len == icovar.rows && len == icovar.cols ); @@ -2591,278 +825,32 @@ double cv::Mahalanobis( InputArray _v1, InputArray _v2, InputArray _icovar ) sz.height = 1; } - if( depth == CV_32F ) - { - const float* src1 = v1.ptr(); - const float* src2 = v2.ptr(); - size_t step1 = v1.step/sizeof(src1[0]); - size_t step2 = v2.step/sizeof(src2[0]); - double* diff = buf.data(); - const float* mat = icovar.ptr(); - size_t matstep = icovar.step/sizeof(mat[0]); - - for( ; sz.height--; src1 += step1, src2 += step2, diff += sz.width ) - { - for( i = 0; i < sz.width; i++ ) - diff[i] = src1[i] - src2[i]; - } - - diff = buf.data(); - for( i = 0; i < len; i++, mat += matstep ) - { - double row_sum = 0; - j = 0; - #if CV_ENABLE_UNROLLED - for(; j <= len - 4; j += 4 ) - row_sum += diff[j]*mat[j] + diff[j+1]*mat[j+1] + - diff[j+2]*mat[j+2] + diff[j+3]*mat[j+3]; - #endif - for( ; j < len; j++ ) - row_sum += diff[j]*mat[j]; - result += row_sum * diff[i]; - } - } - else if( depth == CV_64F ) - { - const double* src1 = v1.ptr(); - const double* src2 = v2.ptr(); - size_t step1 = v1.step/sizeof(src1[0]); - size_t step2 = v2.step/sizeof(src2[0]); - double* diff = buf.data(); - const double* mat = icovar.ptr(); - size_t matstep = icovar.step/sizeof(mat[0]); - - for( ; sz.height--; src1 += step1, src2 += step2, diff += sz.width ) - { - for( i = 0; i < sz.width; i++ ) - diff[i] = src1[i] - src2[i]; - } - - diff = buf.data(); - for( i = 0; i < len; i++, mat += matstep ) - { - double row_sum = 0; - j = 0; - #if CV_ENABLE_UNROLLED - for(; j <= len - 4; j += 4 ) - row_sum += diff[j]*mat[j] + diff[j+1]*mat[j+1] + - diff[j+2]*mat[j+2] + diff[j+3]*mat[j+3]; - #endif - for( ; j < len; j++ ) - row_sum += diff[j]*mat[j]; - result += row_sum * diff[i]; - } - } - else - CV_Error( CV_StsUnsupportedFormat, "" ); + MahalanobisImplFunc func = getMahalanobisImplFunc(depth); + CV_Assert(func); + double result = func(v1, v2, icovar, buf.data(), len); return std::sqrt(result); } + + /****************************************************************************************\ * MulTransposed * \****************************************************************************************/ -namespace cv -{ - -template static void -MulTransposedR( const Mat& srcmat, Mat& dstmat, const Mat& deltamat, double scale ) -{ - int i, j, k; - const sT* src = srcmat.ptr(); - dT* dst = dstmat.ptr
(); - const dT* delta = deltamat.ptr
(); - size_t srcstep = srcmat.step/sizeof(src[0]); - size_t dststep = dstmat.step/sizeof(dst[0]); - size_t deltastep = deltamat.rows > 1 ? deltamat.step/sizeof(delta[0]) : 0; - int delta_cols = deltamat.cols; - Size size = srcmat.size(); - dT* tdst = dst; - dT* col_buf = 0; - dT* delta_buf = 0; - int buf_size = size.height*sizeof(dT); - AutoBuffer buf; - - if( delta && delta_cols < size.width ) - { - assert( delta_cols == 1 ); - buf_size *= 5; - } - buf.allocate(buf_size); - col_buf = (dT*)buf.data(); - - if( delta && delta_cols < size.width ) - { - delta_buf = col_buf + size.height; - for( i = 0; i < size.height; i++ ) - delta_buf[i*4] = delta_buf[i*4+1] = - delta_buf[i*4+2] = delta_buf[i*4+3] = delta[i*deltastep]; - delta = delta_buf; - deltastep = deltastep ? 4 : 0; - } - - if( !delta ) - for( i = 0; i < size.width; i++, tdst += dststep ) - { - for( k = 0; k < size.height; k++ ) - col_buf[k] = src[k*srcstep+i]; - - for( j = i; j <= size.width - 4; j += 4 ) - { - double s0 = 0, s1 = 0, s2 = 0, s3 = 0; - const sT *tsrc = src + j; - - for( k = 0; k < size.height; k++, tsrc += srcstep ) - { - double a = col_buf[k]; - s0 += a * tsrc[0]; - s1 += a * tsrc[1]; - s2 += a * tsrc[2]; - s3 += a * tsrc[3]; - } - - tdst[j] = (dT)(s0*scale); - tdst[j+1] = (dT)(s1*scale); - tdst[j+2] = (dT)(s2*scale); - tdst[j+3] = (dT)(s3*scale); - } - - for( ; j < size.width; j++ ) - { - double s0 = 0; - const sT *tsrc = src + j; - - for( k = 0; k < size.height; k++, tsrc += srcstep ) - s0 += (double)col_buf[k] * tsrc[0]; - - tdst[j] = (dT)(s0*scale); - } - } - else - for( i = 0; i < size.width; i++, tdst += dststep ) - { - if( !delta_buf ) - for( k = 0; k < size.height; k++ ) - col_buf[k] = src[k*srcstep+i] - delta[k*deltastep+i]; - else - for( k = 0; k < size.height; k++ ) - col_buf[k] = src[k*srcstep+i] - delta_buf[k*deltastep]; - - for( j = i; j <= size.width - 4; j += 4 ) - { - double s0 = 0, s1 = 0, s2 = 0, s3 = 0; - const sT *tsrc = src + j; - const dT *d = delta_buf ? delta_buf : delta + j; - - for( k = 0; k < size.height; k++, tsrc+=srcstep, d+=deltastep ) - { - double a = col_buf[k]; - s0 += a * (tsrc[0] - d[0]); - s1 += a * (tsrc[1] - d[1]); - s2 += a * (tsrc[2] - d[2]); - s3 += a * (tsrc[3] - d[3]); - } - - tdst[j] = (dT)(s0*scale); - tdst[j+1] = (dT)(s1*scale); - tdst[j+2] = (dT)(s2*scale); - tdst[j+3] = (dT)(s3*scale); - } - - for( ; j < size.width; j++ ) - { - double s0 = 0; - const sT *tsrc = src + j; - const dT *d = delta_buf ? delta_buf : delta + j; - - for( k = 0; k < size.height; k++, tsrc+=srcstep, d+=deltastep ) - s0 += (double)col_buf[k] * (tsrc[0] - d[0]); - - tdst[j] = (dT)(s0*scale); - } - } -} - - -template static void -MulTransposedL( const Mat& srcmat, Mat& dstmat, const Mat& deltamat, double scale ) +static MulTransposedFunc getMulTransposedFunc(int stype, int dtype, bool ata) { - int i, j, k; - const sT* src = srcmat.ptr(); - dT* dst = dstmat.ptr
(); - const dT* delta = deltamat.ptr
(); - size_t srcstep = srcmat.step/sizeof(src[0]); - size_t dststep = dstmat.step/sizeof(dst[0]); - size_t deltastep = deltamat.rows > 1 ? deltamat.step/sizeof(delta[0]) : 0; - int delta_cols = deltamat.cols; - Size size = srcmat.size(); - dT* tdst = dst; - - if( !delta ) - for( i = 0; i < size.height; i++, tdst += dststep ) - for( j = i; j < size.height; j++ ) - { - double s = 0; - const sT *tsrc1 = src + i*srcstep; - const sT *tsrc2 = src + j*srcstep; - - for( k = 0; k <= size.width - 4; k += 4 ) - s += (double)tsrc1[k]*tsrc2[k] + (double)tsrc1[k+1]*tsrc2[k+1] + - (double)tsrc1[k+2]*tsrc2[k+2] + (double)tsrc1[k+3]*tsrc2[k+3]; - for( ; k < size.width; k++ ) - s += (double)tsrc1[k] * tsrc2[k]; - tdst[j] = (dT)(s*scale); - } - else - { - dT delta_buf[4]; - int delta_shift = delta_cols == size.width ? 4 : 0; - AutoBuffer buf(size.width*sizeof(dT)); - dT* row_buf = (dT*)buf.data(); - - for( i = 0; i < size.height; i++, tdst += dststep ) - { - const sT *tsrc1 = src + i*srcstep; - const dT *tdelta1 = delta + i*deltastep; - - if( delta_cols < size.width ) - for( k = 0; k < size.width; k++ ) - row_buf[k] = tsrc1[k] - tdelta1[0]; - else - for( k = 0; k < size.width; k++ ) - row_buf[k] = tsrc1[k] - tdelta1[k]; - - for( j = i; j < size.height; j++ ) - { - double s = 0; - const sT *tsrc2 = src + j*srcstep; - const dT *tdelta2 = delta + j*deltastep; - if( delta_cols < size.width ) - { - delta_buf[0] = delta_buf[1] = - delta_buf[2] = delta_buf[3] = tdelta2[0]; - tdelta2 = delta_buf; - } - for( k = 0; k <= size.width-4; k += 4, tdelta2 += delta_shift ) - s += (double)row_buf[k]*(tsrc2[k] - tdelta2[0]) + - (double)row_buf[k+1]*(tsrc2[k+1] - tdelta2[1]) + - (double)row_buf[k+2]*(tsrc2[k+2] - tdelta2[2]) + - (double)row_buf[k+3]*(tsrc2[k+3] - tdelta2[3]); - for( ; k < size.width; k++, tdelta2++ ) - s += (double)row_buf[k]*(tsrc2[k] - tdelta2[0]); - tdst[j] = (dT)(s*scale); - } - } - } -} - -typedef void (*MulTransposedFunc)(const Mat& src, Mat& dst, const Mat& delta, double scale); - +#ifdef CV_MULTRANSPOSED_BASELINE_ONLY + CV_CPU_CALL_BASELINE(getMulTransposedFunc, (stype, dtype, ata)); +#else + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(getMulTransposedFunc, (stype, dtype, ata), + CV_CPU_DISPATCH_MODES_ALL); +#endif } -void cv::mulTransposed( InputArray _src, OutputArray _dst, bool ata, - InputArray _delta, double scale, int dtype ) +void mulTransposed(InputArray _src, OutputArray _dst, bool ata, + InputArray _delta, double scale, int dtype) { CV_INSTRUMENT_REGION(); @@ -2906,70 +894,7 @@ void cv::mulTransposed( InputArray _src, OutputArray _dst, bool ata, } else { - MulTransposedFunc func = 0; - if(stype == CV_8U && dtype == CV_32F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_8U && dtype == CV_64F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_16U && dtype == CV_32F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_16U && dtype == CV_64F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_16S && dtype == CV_32F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_16S && dtype == CV_64F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_32F && dtype == CV_32F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_32F && dtype == CV_64F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_64F && dtype == CV_64F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } + MulTransposedFunc func = getMulTransposedFunc(stype, dtype, ata); if( !func ) CV_Error( CV_StsUnsupportedFormat, "" ); @@ -2982,273 +907,49 @@ void cv::mulTransposed( InputArray _src, OutputArray _dst, bool ata, * Dot Product * \****************************************************************************************/ -namespace cv -{ - -template double -dotProd_(const T* src1, const T* src2, int len) -{ - int i = 0; - double result = 0; - - #if CV_ENABLE_UNROLLED - for( ; i <= len - 4; i += 4 ) - result += (double)src1[i]*src2[i] + (double)src1[i+1]*src2[i+1] + - (double)src1[i+2]*src2[i+2] + (double)src1[i+3]*src2[i+3]; - #endif - for( ; i < len; i++ ) - result += (double)src1[i]*src2[i]; - - return result; -} - - static double dotProd_8u(const uchar* src1, const uchar* src2, int len) { - double r = 0; -#if ARITHM_USE_IPP - CV_IPP_RUN(IPP_VERSION_X100 > 201800 || cv::ipp::getIppTopFeatures() != ippCPUID_SSE42, CV_INSTRUMENT_FUN_IPP(ippiDotProd_8u64f_C1R, src1, len*sizeof(uchar), src2, len*sizeof(uchar), ippiSize(len, 1), &r) >= 0, r); -#endif - int i = 0; - -#if CV_SIMD - int len0 = len & -v_uint16::nlanes, blockSize0 = (1 << 15), blockSize; - - while (i < len0) - { - blockSize = std::min(len0 - i, blockSize0); - v_int32 v_sum = vx_setzero_s32(); - const int cWidth = v_uint16::nlanes; - - int j = 0; - for (; j <= blockSize - cWidth * 2; j += cWidth * 2) - { - v_uint16 v_src10, v_src20, v_src11, v_src21; - v_expand(vx_load(src1 + j), v_src10, v_src11); - v_expand(vx_load(src2 + j), v_src20, v_src21); - - v_sum += v_dotprod(v_reinterpret_as_s16(v_src10), v_reinterpret_as_s16(v_src20)); - v_sum += v_dotprod(v_reinterpret_as_s16(v_src11), v_reinterpret_as_s16(v_src21)); - } - - for (; j <= blockSize - cWidth; j += cWidth) - { - v_int16 v_src10 = v_reinterpret_as_s16(vx_load_expand(src1 + j)); - v_int16 v_src20 = v_reinterpret_as_s16(vx_load_expand(src2 + j)); - - v_sum += v_dotprod(v_src10, v_src20); - } - r += (double)v_reduce_sum(v_sum); - - src1 += blockSize; - src2 += blockSize; - i += blockSize; - } - vx_cleanup(); -#elif CV_NEON - if( cv::checkHardwareSupport(CV_CPU_NEON) ) - { - int len0 = len & -8, blockSize0 = (1 << 15), blockSize; - uint32x4_t v_zero = vdupq_n_u32(0u); - CV_DECL_ALIGNED(16) uint buf[4]; - - while( i < len0 ) - { - blockSize = std::min(len0 - i, blockSize0); - uint32x4_t v_sum = v_zero; - - int j = 0; - for( ; j <= blockSize - 16; j += 16 ) - { - uint8x16_t v_src1 = vld1q_u8(src1 + j), v_src2 = vld1q_u8(src2 + j); - - uint16x8_t v_src10 = vmovl_u8(vget_low_u8(v_src1)), v_src20 = vmovl_u8(vget_low_u8(v_src2)); - v_sum = vmlal_u16(v_sum, vget_low_u16(v_src10), vget_low_u16(v_src20)); - v_sum = vmlal_u16(v_sum, vget_high_u16(v_src10), vget_high_u16(v_src20)); - - v_src10 = vmovl_u8(vget_high_u8(v_src1)); - v_src20 = vmovl_u8(vget_high_u8(v_src2)); - v_sum = vmlal_u16(v_sum, vget_low_u16(v_src10), vget_low_u16(v_src20)); - v_sum = vmlal_u16(v_sum, vget_high_u16(v_src10), vget_high_u16(v_src20)); - } - - for( ; j <= blockSize - 8; j += 8 ) - { - uint16x8_t v_src1 = vmovl_u8(vld1_u8(src1 + j)), v_src2 = vmovl_u8(vld1_u8(src2 + j)); - v_sum = vmlal_u16(v_sum, vget_low_u16(v_src1), vget_low_u16(v_src2)); - v_sum = vmlal_u16(v_sum, vget_high_u16(v_src1), vget_high_u16(v_src2)); - } - - vst1q_u32(buf, v_sum); - r += buf[0] + buf[1] + buf[2] + buf[3]; - - src1 += blockSize; - src2 += blockSize; - i += blockSize; - } - } -#endif - return r + dotProd_(src1, src2, len - i); + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(dotProd_8u, (src1, src2, len), + CV_CPU_DISPATCH_MODES_ALL); } - - static double dotProd_8s(const schar* src1, const schar* src2, int len) { - double r = 0.0; - int i = 0; - -#if CV_SIMD - int len0 = len & -v_int16::nlanes, blockSize0 = (1 << 14), blockSize; - - while (i < len0) - { - blockSize = std::min(len0 - i, blockSize0); - v_int32 v_sum = vx_setzero_s32(); - const int cWidth = v_int16::nlanes; - - int j = 0; - for (; j <= blockSize - cWidth * 2; j += cWidth * 2) - { - v_int16 v_src10, v_src20, v_src11, v_src21; - v_expand(vx_load(src1 + j), v_src10, v_src11); - v_expand(vx_load(src2 + j), v_src20, v_src21); - - v_sum += v_dotprod(v_src10, v_src20); - v_sum += v_dotprod(v_src11, v_src21); - } - - for (; j <= blockSize - cWidth; j += cWidth) - { - v_int16 v_src10 = vx_load_expand(src1 + j); - v_int16 v_src20 = vx_load_expand(src2 + j); - - v_sum += v_dotprod(v_src10, v_src20); - } - r += (double)v_reduce_sum(v_sum); - - src1 += blockSize; - src2 += blockSize; - i += blockSize; - } - vx_cleanup(); -#elif CV_NEON - if( cv::checkHardwareSupport(CV_CPU_NEON) ) - { - int len0 = len & -8, blockSize0 = (1 << 14), blockSize; - int32x4_t v_zero = vdupq_n_s32(0); - CV_DECL_ALIGNED(16) int buf[4]; - - while( i < len0 ) - { - blockSize = std::min(len0 - i, blockSize0); - int32x4_t v_sum = v_zero; - - int j = 0; - for( ; j <= blockSize - 16; j += 16 ) - { - int8x16_t v_src1 = vld1q_s8(src1 + j), v_src2 = vld1q_s8(src2 + j); - - int16x8_t v_src10 = vmovl_s8(vget_low_s8(v_src1)), v_src20 = vmovl_s8(vget_low_s8(v_src2)); - v_sum = vmlal_s16(v_sum, vget_low_s16(v_src10), vget_low_s16(v_src20)); - v_sum = vmlal_s16(v_sum, vget_high_s16(v_src10), vget_high_s16(v_src20)); - - v_src10 = vmovl_s8(vget_high_s8(v_src1)); - v_src20 = vmovl_s8(vget_high_s8(v_src2)); - v_sum = vmlal_s16(v_sum, vget_low_s16(v_src10), vget_low_s16(v_src20)); - v_sum = vmlal_s16(v_sum, vget_high_s16(v_src10), vget_high_s16(v_src20)); - } - - for( ; j <= blockSize - 8; j += 8 ) - { - int16x8_t v_src1 = vmovl_s8(vld1_s8(src1 + j)), v_src2 = vmovl_s8(vld1_s8(src2 + j)); - v_sum = vmlal_s16(v_sum, vget_low_s16(v_src1), vget_low_s16(v_src2)); - v_sum = vmlal_s16(v_sum, vget_high_s16(v_src1), vget_high_s16(v_src2)); - } - - vst1q_s32(buf, v_sum); - r += buf[0] + buf[1] + buf[2] + buf[3]; - - src1 += blockSize; - src2 += blockSize; - i += blockSize; - } - } -#endif - - return r + dotProd_(src1, src2, len - i); + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(dotProd_8s, (src1, src2, len), + CV_CPU_DISPATCH_MODES_ALL); } - static double dotProd_16u(const ushort* src1, const ushort* src2, int len) { -#if ARITHM_USE_IPP - double r = 0; - CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiDotProd_16u64f_C1R, src1, len*sizeof(ushort), src2, len*sizeof(ushort), ippiSize(len, 1), &r) >= 0, r); -#endif - return dotProd_(src1, src2, len); + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(dotProd_16u, (src1, src2, len), + CV_CPU_DISPATCH_MODES_ALL); } - static double dotProd_16s(const short* src1, const short* src2, int len) { -#if ARITHM_USE_IPP && (IPP_VERSION_X100 != 900) // bug in IPP 9.0.0 - double r = 0; - CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiDotProd_16s64f_C1R, src1, len*sizeof(short), src2, len*sizeof(short), ippiSize(len, 1), &r) >= 0, r); -#endif - return dotProd_(src1, src2, len); + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(dotProd_16s, (src1, src2, len), + CV_CPU_DISPATCH_MODES_ALL); } - static double dotProd_32s(const int* src1, const int* src2, int len) { -#if ARITHM_USE_IPP - double r = 0; - CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiDotProd_32s64f_C1R, src1, len*sizeof(int), src2, len*sizeof(int), ippiSize(len, 1), &r) >= 0, r); -#endif - return dotProd_(src1, src2, len); + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(dotProd_32s, (src1, src2, len), + CV_CPU_DISPATCH_MODES_ALL); } - static double dotProd_32f(const float* src1, const float* src2, int len) { - double r = 0.0; - -#if ARITHM_USE_IPP - CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiDotProd_32f64f_C1R, src1, len*sizeof(float), src2, len*sizeof(float), ippiSize(len, 1), &r, ippAlgHintFast) >= 0, r); -#endif - int i = 0; - -#if CV_SIMD - int len0 = len & -v_float32::nlanes, blockSize0 = (1 << 13), blockSize; - - while (i < len0) - { - blockSize = std::min(len0 - i, blockSize0); - v_float32 v_sum = vx_setzero_f32(); - - int j = 0; - int cWidth = v_float32::nlanes; - for (; j <= blockSize - cWidth; j += cWidth) - v_sum = v_muladd(vx_load(src1 + j), vx_load(src2 + j), v_sum); - - r += v_reduce_sum(v_sum); - - src1 += blockSize; - src2 += blockSize; - i += blockSize; - } - vx_cleanup(); -#endif - return r + dotProd_(src1, src2, len - i); + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(dotProd_32f, (src1, src2, len), + CV_CPU_DISPATCH_MODES_ALL); } - static double dotProd_64f(const double* src1, const double* src2, int len) { -#if ARITHM_USE_IPP - double r = 0; - CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippsDotProd_64f, src1, src2, len, &r) >= 0, r); -#endif - - return dotProd_(src1, src2, len); + CV_INSTRUMENT_REGION(); + CV_CPU_DISPATCH(dotProd_64f, (src1, src2, len), + CV_CPU_DISPATCH_MODES_ALL); } - typedef double (*DotProdFunc)(const uchar* src1, const uchar* src2, int len); static DotProdFunc getDotProdFunc(int depth) @@ -3292,7 +993,7 @@ double Mat::dot(InputArray _mat) const return r; } -} +} // namespace cv:: /****************************************************************************************\ * Earlier API * diff --git a/modules/core/src/matmul.simd.hpp b/modules/core/src/matmul.simd.hpp index 19ab907c9e..760bf39e0f 100644 --- a/modules/core/src/matmul.simd.hpp +++ b/modules/core/src/matmul.simd.hpp @@ -41,16 +41,62 @@ // //M*/ -#include #include "precomp.hpp" -#include "opencl_kernels_core.hpp" -#include "opencv2/core/opencl/runtime/opencl_clamdblas.hpp" -#include "opencv2/core/opencl/runtime/opencl_core.hpp" -#include "intel_gpu_gemm.inl.hpp" -namespace cv -{ +#ifdef HAVE_LAPACK +#define CV_GEMM_BASELINE_ONLY +#endif +#define CV_MAHALANOBIS_BASELINE_ONLY +#define CV_MULTRANSPOSED_BASELINE_ONLY + +namespace cv { + +// forward declarations +typedef void (*TransformFunc)(const uchar* src, uchar* dst, const uchar* m, int len, int scn, int dcn); +typedef void (*ScaleAddFunc)(const uchar* src1, const uchar* src2, uchar* dst, int len, const void* alpha); +typedef void (*MulTransposedFunc)(const Mat& src, const/*preallocated*/ Mat& dst, const Mat& delta, double scale); +typedef double (*MahalanobisImplFunc)(const Mat& v1, const Mat& v2, const Mat& icovar, double *diff_buffer /*[len]*/, int len /*=v1.total()*/); + +CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN + +// forward declarations + +void gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags); +void gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags); +void gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags); +void gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags); + +TransformFunc getTransformFunc(int depth); +TransformFunc getDiagTransformFunc(int depth); +TransformFunc getPerspectiveTransform(int depth); + +ScaleAddFunc getScaleAddFunc(int depth); + +MahalanobisImplFunc getMahalanobisImplFunc(int depth); + +MulTransposedFunc getMulTransposedFunc(int stype, int dtype, bool ata); + +double dotProd_8u(const uchar* src1, const uchar* src2, int len); +double dotProd_8s(const schar* src1, const schar* src2, int len); +double dotProd_16u(const ushort* src1, const ushort* src2, int len); +double dotProd_16s(const short* src1, const short* src2, int len); +double dotProd_32s(const int* src1, const int* src2, int len); +double dotProd_32f(const float* src1, const float* src2, int len); +double dotProd_64f(const double* src1, const double* src2, int len); + + +#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY + +#if !defined(CV_GEMM_BASELINE_ONLY) || defined(CV_CPU_BASELINE_MODE) /****************************************************************************************\ * GEMM * \****************************************************************************************/ @@ -695,204 +741,6 @@ static void GEMMStore_64fc( const Complexd* c_data, size_t c_step, GEMMStore(c_data, c_step, d_buf, d_buf_step, d_data, d_step, d_size, alpha, beta, flags); } -#ifdef HAVE_CLAMDBLAS - -static bool ocl_gemm_amdblas( InputArray matA, InputArray matB, double alpha, - InputArray matC, double beta, OutputArray matD, int flags ) -{ - int type = matA.type(), esz = CV_ELEM_SIZE(type); - bool haveC = matC.kind() != cv::_InputArray::NONE; - Size sizeA = matA.size(), sizeB = matB.size(), sizeC = haveC ? matC.size() : Size(0, 0); - bool atrans = (flags & GEMM_1_T) != 0, btrans = (flags & GEMM_2_T) != 0, ctrans = (flags & GEMM_3_T) != 0; - - if (atrans) - sizeA = Size(sizeA.height, sizeA.width); - if (btrans) - sizeB = Size(sizeB.height, sizeB.width); - if (haveC && ctrans) - sizeC = Size(sizeC.height, sizeC.width); - - Size sizeD(sizeB.width, sizeA.height); - - CV_Assert( matB.type() == type && (!haveC || matC.type() == type) ); - CV_Assert( sizeA.width == sizeB.height && (!haveC || sizeC == sizeD) ); - - matD.create(sizeD, type); - if ( matA.offset() % esz != 0 || matA.step() % esz != 0 || - matB.offset() % esz != 0 || matB.step() % esz != 0 || - (haveC && (matC.offset() % esz != 0 || matC.step() % esz != 0)) ) - return false; - - UMat A = matA.getUMat(), B = matB.getUMat(), D = matD.getUMat(); - if (!ocl::internal::isCLBuffer(A) || !ocl::internal::isCLBuffer(B) || !ocl::internal::isCLBuffer(D)) - { - return false; - } - if (haveC) - { - UMat C = matC.getUMat(); - if (!ocl::internal::isCLBuffer(C)) - return false; - } - if (haveC) - ctrans ? transpose(matC, D) : matC.copyTo(D); - else - D.setTo(Scalar::all(0)); - - int M = sizeD.height, N = sizeD.width, K = sizeA.width; - int lda = (int)A.step / esz, ldb = (int)B.step / esz, ldc = (int)D.step / esz; - int offa = (int)A.offset / esz, offb = (int)B.offset / esz, offc = (int)D.offset / esz; - - cl_command_queue clq = (cl_command_queue)ocl::Queue::getDefault().ptr(); - clAmdBlasTranspose transA = atrans ? clAmdBlasTrans : clAmdBlasNoTrans; - clAmdBlasTranspose transB = btrans ? clAmdBlasTrans : clAmdBlasNoTrans; - clAmdBlasOrder order = clAmdBlasRowMajor; - clAmdBlasStatus status = clAmdBlasSuccess; - - if (type == CV_32FC1) - status = clAmdBlasSgemmEx(order, transA, transB, M, N, K, - (cl_float)alpha, (const cl_mem)A.handle(ACCESS_READ), offa, lda, - (const cl_mem)B.handle(ACCESS_READ), offb, ldb, - (cl_float)beta, (cl_mem)D.handle(ACCESS_RW), offc, ldc, - 1, &clq, 0, NULL, NULL); - else if (type == CV_64FC1) - status = clAmdBlasDgemmEx(order, transA, transB, M, N, K, - alpha, (const cl_mem)A.handle(ACCESS_READ), offa, lda, - (const cl_mem)B.handle(ACCESS_READ), offb, ldb, - beta, (cl_mem)D.handle(ACCESS_RW), offc, ldc, - 1, &clq, 0, NULL, NULL); - else if (type == CV_32FC2) - { - cl_float2 alpha_2 = { { (cl_float)alpha, 0 } }; - cl_float2 beta_2 = { { (cl_float)beta, 0 } }; - status = clAmdBlasCgemmEx(order, transA, transB, M, N, K, - alpha_2, (const cl_mem)A.handle(ACCESS_READ), offa, lda, - (const cl_mem)B.handle(ACCESS_READ), offb, ldb, - beta_2, (cl_mem)D.handle(ACCESS_RW), offc, ldc, - 1, &clq, 0, NULL, NULL); - } - else if (type == CV_64FC2) - { - cl_double2 alpha_2 = { { alpha, 0 } }; - cl_double2 beta_2 = { { beta, 0 } }; - status = clAmdBlasZgemmEx(order, transA, transB, M, N, K, - alpha_2, (const cl_mem)A.handle(ACCESS_READ), offa, lda, - (const cl_mem)B.handle(ACCESS_READ), offb, ldb, - beta_2, (cl_mem)D.handle(ACCESS_RW), offc, ldc, - 1, &clq, 0, NULL, NULL); - } - else - CV_Error(Error::StsUnsupportedFormat, ""); - - return status == clAmdBlasSuccess; -} - -#endif - -#ifdef HAVE_OPENCL -static bool ocl_gemm( InputArray matA, InputArray matB, double alpha, - InputArray matC, double beta, OutputArray matD, int flags ) -{ - int depth = matA.depth(), cn = matA.channels(); - int type = CV_MAKETYPE(depth, cn); - - CV_Assert_N( type == matB.type(), (type == CV_32FC1 || type == CV_64FC1 || type == CV_32FC2 || type == CV_64FC2) ); - - const ocl::Device & dev = ocl::Device::getDefault(); - bool doubleSupport = dev.doubleFPConfig() > 0; - - if (!doubleSupport && depth == CV_64F) - return false; - - bool haveC = matC.kind() != cv::_InputArray::NONE; - Size sizeA = matA.size(), sizeB = matB.size(), sizeC = haveC ? matC.size() : Size(0, 0); - bool atrans = (flags & GEMM_1_T) != 0, btrans = (flags & GEMM_2_T) != 0, ctrans = (flags & GEMM_3_T) != 0; - - CV_Assert( !haveC || matC.type() == type ); - - Size sizeD(((btrans)? sizeB.height : sizeB.width), - ((atrans)? sizeA.width : sizeA.height)); - matD.create(sizeD, type); - - UMat A = matA.getUMat(), B = matB.getUMat(), D = matD.getUMat(); - - - if (!dev.intelSubgroupsSupport() || (depth == CV_64F) || cn != 1) - { - String opts; - - if (atrans) - sizeA = Size(sizeA.height, sizeA.width); - if (btrans) - sizeB = Size(sizeB.height, sizeB.width); - if (haveC && ctrans) - sizeC = Size(sizeC.height, sizeC.width); - - CV_Assert( sizeA.width == sizeB.height && (!haveC || sizeC == sizeD) ); - - int max_wg_size = (int)dev.maxWorkGroupSize(); - int block_size = (max_wg_size / (32*cn) < 32) ? (max_wg_size / (16*cn) < 16) ? (max_wg_size / (8*cn) < 8) ? 1 : 8 : 16 : 32; - - if (atrans) - A = A.t(); - - if (btrans) - B = B.t(); - - if (haveC) - ctrans ? transpose(matC, D) : matC.copyTo(D); - - int vectorWidths[] = { 4, 4, 2, 2, 1, 4, cn, -1 }; - int kercn = ocl::checkOptimalVectorWidth(vectorWidths, B, D); - - opts += format(" -D T=%s -D T1=%s -D WT=%s -D cn=%d -D kercn=%d -D LOCAL_SIZE=%d%s%s%s", - ocl::typeToStr(type), ocl::typeToStr(depth), ocl::typeToStr(CV_MAKETYPE(depth, kercn)), - cn, kercn, block_size, - (sizeA.width % block_size !=0) ? " -D NO_MULT" : "", - haveC ? " -D HAVE_C" : "", - doubleSupport ? " -D DOUBLE_SUPPORT" : ""); - - ocl::Kernel k("gemm", cv::ocl::core::gemm_oclsrc, opts); - if (k.empty()) - return false; - - if (depth == CV_64F) - k.args(ocl::KernelArg::ReadOnlyNoSize(A), - ocl::KernelArg::ReadOnlyNoSize(B, cn, kercn), - ocl::KernelArg::ReadWrite(D, cn, kercn), - sizeA.width, alpha, beta); - else - k.args(ocl::KernelArg::ReadOnlyNoSize(A), - ocl::KernelArg::ReadOnlyNoSize(B, cn, kercn), - ocl::KernelArg::ReadWrite(D, cn, kercn), - sizeA.width, (float)alpha, (float)beta); - - size_t globalsize[2] = { (size_t)sizeD.width * cn / kercn, (size_t)sizeD.height}; - size_t localsize[2] = { (size_t)block_size, (size_t)block_size}; - - return k.run(2, globalsize, block_size!=1 ? localsize : NULL, false); - } - else - { - if (haveC && beta != 0.0) - { - ctrans ? transpose(matC, D) : matC.copyTo(D); - } - else - { - beta = 0.0; - } - - return intel_gpu_gemm(A, sizeA, - B, sizeB, - D, sizeD, - alpha, - beta, - atrans, btrans); - } -} -#endif - static void gemmImpl( Mat A, Mat B, double alpha, Mat C, double beta, Mat D, int flags ) { @@ -1502,142 +1350,46 @@ callGemmImpl(const fptype *src1, size_t src1_step, const fptype *src2, size_t sr gemmImpl(A, B, alpha, C, beta, D, flags); } -} - -void cv::hal::gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step, - float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, - int m_a, int n_a, int n_d, int flags) +void gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags) { - - CALL_HAL(gemm32f, cv_hal_gemm32f, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) + CV_INSTRUMENT_REGION(); callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_32F); } -void cv::hal::gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step, - double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, - int m_a, int n_a, int n_d, int flags) +void gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags) { - CALL_HAL(gemm64f, cv_hal_gemm64f, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) + CV_INSTRUMENT_REGION(); callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_64F); } -CV_EXPORTS void cv::hal::gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step, - float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, - int m_a, int n_a, int n_d, int flags) +void gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags) { - CALL_HAL(gemm32fc, cv_hal_gemm32fc, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) + CV_INSTRUMENT_REGION(); callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_32FC2); } -CV_EXPORTS void cv::hal::gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step, - double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, - int m_a, int n_a, int n_d, int flags) +void gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m_a, int n_a, int n_d, int flags) { - CALL_HAL(gemm64fc, cv_hal_gemm64fc, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags) + CV_INSTRUMENT_REGION(); callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_64FC2); } -void cv::gemm( InputArray matA, InputArray matB, double alpha, - InputArray matC, double beta, OutputArray _matD, int flags ) -{ -#ifdef HAVE_CLAMDBLAS - CV_OCL_RUN(ocl::haveAmdBlas() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2 && _matD.isUMat() && - matA.cols() > 20 && matA.rows() > 20 && matB.cols() > 20, // since it works incorrect for small sizes - ocl_gemm_amdblas(matA, matB, alpha, matC, beta, _matD, flags)) -#endif +#endif // !defined(CV_GEMM_BASELINE_ONLY) || defined(CV_CPU_BASELINE_MODE) -#ifdef HAVE_OPENCL - CV_OCL_RUN(_matD.isUMat() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2, - ocl_gemm(matA, matB, alpha, matC, beta, _matD, flags)) -#endif - - Mat A = matA.getMat(), B = matB.getMat(), C = beta != 0.0 ? matC.getMat() : Mat(); - Size a_size = A.size(), d_size; - int len = 0, type = A.type(); - - CV_Assert_N( type == B.type(), (type == CV_32FC1 || type == CV_64FC1 || type == CV_32FC2 || type == CV_64FC2) ); - - switch( flags & (GEMM_1_T|GEMM_2_T) ) - { - case 0: - d_size = Size( B.cols, a_size.height ); - len = B.rows; - CV_Assert( a_size.width == len ); - break; - case 1: - d_size = Size( B.cols, a_size.width ); - len = B.rows; - CV_Assert( a_size.height == len ); - break; - case 2: - d_size = Size( B.rows, a_size.height ); - len = B.cols; - CV_Assert( a_size.width == len ); - break; - case 3: - d_size = Size( B.rows, a_size.width ); - len = B.cols; - CV_Assert( a_size.height == len ); - break; - } - - if( !C.empty() ) - { - CV_Assert_N( C.type() == type, - (((flags&GEMM_3_T) == 0 && C.rows == d_size.height && C.cols == d_size.width) || - ((flags&GEMM_3_T) != 0 && C.rows == d_size.width && C.cols == d_size.height))); - } - - _matD.create( d_size.height, d_size.width, type ); - Mat D = _matD.getMat(); - if( (flags & GEMM_3_T) != 0 && C.data == D.data ) - { - transpose( C, C ); - flags &= ~GEMM_3_T; - } - - Mat *DProxyPtr = &D, DProxy; - if( D.data == A.data || D.data == B.data ) - { - DProxy = Mat(d_size.height, d_size.width, D.type()); - DProxyPtr = &DProxy; - } - - if( type == CV_32FC1 ) - hal::gemm32f(A.ptr(), A.step, B.ptr(), B.step, static_cast(alpha), - C.ptr(), C.step, static_cast(beta), - DProxyPtr->ptr(), DProxyPtr->step, - a_size.height, a_size.width, DProxyPtr->cols, flags); - else if( type == CV_64FC1 ) - hal::gemm64f(A.ptr(), A.step, B.ptr(), B.step, alpha, - C.ptr(), C.step, beta, - DProxyPtr->ptr(), DProxyPtr->step, - a_size.height, a_size.width, DProxyPtr->cols, flags); - else if( type == CV_32FC2 ) - hal::gemm32fc(A.ptr(), A.step, B.ptr(), B.step, static_cast(alpha), - C.ptr(), C.step, static_cast(beta), - DProxyPtr->ptr(), DProxyPtr->step, - a_size.height, a_size.width, DProxyPtr->cols, flags); - else - { - CV_Assert( type == CV_64FC2 ); - hal::gemm64fc(A.ptr(), A.step, B.ptr(), B.step, alpha, - C.ptr(), C.step, beta, - D.ptr(), D.step, - a_size.height, a_size.width, DProxyPtr->cols, flags); - } - if(DProxyPtr != &D) - DProxyPtr->copyTo(D); -} /****************************************************************************************\ * Transform * \****************************************************************************************/ -namespace cv -{ - template static void transform_( const T* src, T* dst, const WT* m, int len, int scn, int dcn ) { @@ -2053,9 +1805,7 @@ diagtransform_64f(const double* src, double* dst, const double* m, int len, int } -typedef void (*TransformFunc)( const uchar* src, uchar* dst, const uchar* m, int, int, int ); - -static TransformFunc getTransformFunc(int depth) +TransformFunc getTransformFunc(int depth) { static TransformFunc transformTab[] = { @@ -2067,7 +1817,7 @@ static TransformFunc getTransformFunc(int depth) return transformTab[depth]; } -static TransformFunc getDiagTransformFunc(int depth) +TransformFunc getDiagTransformFunc(int depth) { static TransformFunc diagTransformTab[] = { @@ -2079,88 +1829,12 @@ static TransformFunc getDiagTransformFunc(int depth) return diagTransformTab[depth]; } -} - -void cv::transform( InputArray _src, OutputArray _dst, InputArray _mtx ) -{ - CV_INSTRUMENT_REGION(); - - Mat src = _src.getMat(), m = _mtx.getMat(); - int depth = src.depth(), scn = src.channels(), dcn = m.rows; - CV_Assert( scn == m.cols || scn + 1 == m.cols ); - bool isDiag = false; - - _dst.create( src.size(), CV_MAKETYPE(depth, dcn) ); - Mat dst = _dst.getMat(); - - int mtype = depth == CV_32S || depth == CV_64F ? CV_64F : CV_32F; - AutoBuffer _mbuf; - double* mbuf; - - if( !m.isContinuous() || m.type() != mtype || m.cols != scn + 1 ) - { - _mbuf.allocate(dcn*(scn+1)); - mbuf = _mbuf.data(); - Mat tmp(dcn, scn+1, mtype, mbuf); - memset(tmp.ptr(), 0, tmp.total()*tmp.elemSize()); - if( m.cols == scn+1 ) - m.convertTo(tmp, mtype); - else - { - Mat tmppart = tmp.colRange(0, m.cols); - m.convertTo(tmppart, mtype); - } - m = tmp; - } - else - mbuf = m.ptr(); - - if( scn == dcn ) - { - int i, j; - double eps = mtype == CV_32F ? FLT_EPSILON : DBL_EPSILON; - - if( scn == 1 ) - { - double alpha, beta; - if( mtype == CV_32F ) - alpha = m.at(0), beta = m.at(1); - else - alpha = m.at(0), beta = m.at(1); - src.convertTo(dst, dst.type(), alpha, beta); - return; - } - - for( i = 0, isDiag = true; isDiag && i < scn; i++ ) - { - for( j = 0; isDiag && j < scn; j++ ) - { - double v = mtype == CV_32F ? m.at(i, j) : m.at(i, j); - if( i != j && fabs(v) > eps ) - isDiag = false; - } - } - } - - TransformFunc func = isDiag ? getDiagTransformFunc(depth): getTransformFunc(depth); - CV_Assert( func != 0 ); - const Mat* arrays[] = {&src, &dst, 0}; - uchar* ptrs[2] = {}; - NAryMatIterator it(arrays, ptrs); - size_t i, total = it.size; - - for( i = 0; i < it.nplanes; i++, ++it ) - func( ptrs[0], ptrs[1], (uchar*)mbuf, (int)total, scn, dcn ); -} /****************************************************************************************\ * Perspective Transform * \****************************************************************************************/ -namespace cv -{ - template static void perspectiveTransform_( const T* src, T* dst, const double* m, int len, int scn, int dcn ) { @@ -2246,7 +1920,6 @@ perspectiveTransform_( const T* src, T* dst, const double* m, int len, int scn, } } - static void perspectiveTransform_32f(const float* src, float* dst, const double* m, int len, int scn, int dcn) { @@ -2259,54 +1932,21 @@ perspectiveTransform_64f(const double* src, double* dst, const double* m, int le perspectiveTransform_(src, dst, m, len, scn, dcn); } -} - -void cv::perspectiveTransform( InputArray _src, OutputArray _dst, InputArray _mtx ) +TransformFunc getPerspectiveTransform(int depth) { - CV_INSTRUMENT_REGION(); - - Mat src = _src.getMat(), m = _mtx.getMat(); - int depth = src.depth(), scn = src.channels(), dcn = m.rows-1; - CV_Assert( scn + 1 == m.cols ); - CV_Assert( depth == CV_32F || depth == CV_64F ); - - _dst.create( src.size(), CV_MAKETYPE(depth, dcn) ); - Mat dst = _dst.getMat(); - - const int mtype = CV_64F; - AutoBuffer _mbuf; - double* mbuf = m.ptr(); - - if( !m.isContinuous() || m.type() != mtype ) - { - _mbuf.allocate((dcn+1)*(scn+1)); - mbuf = _mbuf.data(); - Mat tmp(dcn+1, scn+1, mtype, mbuf); - m.convertTo(tmp, mtype); - m = tmp; - } - - TransformFunc func = depth == CV_32F ? - (TransformFunc)perspectiveTransform_32f : - (TransformFunc)perspectiveTransform_64f; - CV_Assert( func != 0 ); + if (depth == CV_32F) + return (TransformFunc)perspectiveTransform_32f; + if (depth == CV_64F) + return (TransformFunc)perspectiveTransform_64f; + CV_Assert(0 && "Not supported"); +} - const Mat* arrays[] = {&src, &dst, 0}; - uchar* ptrs[2] = {}; - NAryMatIterator it(arrays, ptrs); - size_t i, total = it.size; - for( i = 0; i < it.nplanes; i++, ++it ) - func( ptrs[0], ptrs[1], (uchar*)mbuf, (int)total, scn, dcn ); -} /****************************************************************************************\ * ScaleAdd * \****************************************************************************************/ -namespace cv -{ - static void scaleAdd_32f(const float* src1, const float* src2, float* dst, int len, float* _alpha) { @@ -2340,338 +1980,90 @@ static void scaleAdd_64f(const double* src1, const double* src2, double* dst, dst[i] = src1[i] * alpha + src2[i]; } -typedef void (*ScaleAddFunc)(const uchar* src1, const uchar* src2, uchar* dst, int len, const void* alpha); - -#ifdef HAVE_OPENCL - -static bool ocl_scaleAdd( InputArray _src1, double alpha, InputArray _src2, OutputArray _dst, int type ) +ScaleAddFunc getScaleAddFunc(int depth) { - const ocl::Device & d = ocl::Device::getDefault(); - - bool doubleSupport = d.doubleFPConfig() > 0; - Size size = _src1.size(); - int depth = CV_MAT_DEPTH(type); - if ( (!doubleSupport && depth == CV_64F) || size != _src2.size() ) - return false; - - _dst.create(size, type); - int cn = CV_MAT_CN(type), wdepth = std::max(depth, CV_32F); - int kercn = ocl::predictOptimalVectorWidthMax(_src1, _src2, _dst), - rowsPerWI = d.isIntel() ? 4 : 1; - - char cvt[2][50]; - ocl::Kernel k("KF", ocl::core::arithm_oclsrc, - format("-D OP_SCALE_ADD -D BINARY_OP -D dstT=%s -D DEPTH_dst=%d -D workT=%s -D convertToWT1=%s" - " -D srcT1=dstT -D srcT2=dstT -D convertToDT=%s -D workT1=%s" - " -D wdepth=%d%s -D rowsPerWI=%d", - ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)), depth, - ocl::typeToStr(CV_MAKE_TYPE(wdepth, kercn)), - ocl::convertTypeStr(depth, wdepth, kercn, cvt[0]), - ocl::convertTypeStr(wdepth, depth, kercn, cvt[1]), - ocl::typeToStr(wdepth), wdepth, - doubleSupport ? " -D DOUBLE_SUPPORT" : "", rowsPerWI)); - if (k.empty()) - return false; - - UMat src1 = _src1.getUMat(), src2 = _src2.getUMat(), dst = _dst.getUMat(); - - ocl::KernelArg src1arg = ocl::KernelArg::ReadOnlyNoSize(src1), - src2arg = ocl::KernelArg::ReadOnlyNoSize(src2), - dstarg = ocl::KernelArg::WriteOnly(dst, cn, kercn); - - if (wdepth == CV_32F) - k.args(src1arg, src2arg, dstarg, (float)alpha); - else - k.args(src1arg, src2arg, dstarg, alpha); - - size_t globalsize[2] = { (size_t)dst.cols * cn / kercn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; - return k.run(2, globalsize, NULL, false); + if (depth == CV_32F) + return (ScaleAddFunc)scaleAdd_32f; + if (depth == CV_64F) + return (ScaleAddFunc)scaleAdd_64f; + CV_Assert(0 && "Not supported"); } -#endif - -} - -void cv::scaleAdd( InputArray _src1, double alpha, InputArray _src2, OutputArray _dst ) -{ - CV_INSTRUMENT_REGION(); - - int type = _src1.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); - CV_Assert( type == _src2.type() ); - - CV_OCL_RUN(_src1.dims() <= 2 && _src2.dims() <= 2 && _dst.isUMat(), - ocl_scaleAdd(_src1, alpha, _src2, _dst, type)) - - if( depth < CV_32F ) - { - addWeighted(_src1, alpha, _src2, 1, 0, _dst, depth); - return; - } - - Mat src1 = _src1.getMat(), src2 = _src2.getMat(); - CV_Assert(src1.size == src2.size); - - _dst.create(src1.dims, src1.size, type); - Mat dst = _dst.getMat(); - - float falpha = (float)alpha; - void* palpha = depth == CV_32F ? (void*)&falpha : (void*)α - - ScaleAddFunc func = depth == CV_32F ? (ScaleAddFunc)scaleAdd_32f : (ScaleAddFunc)scaleAdd_64f; - - if (src1.isContinuous() && src2.isContinuous() && dst.isContinuous()) - { - size_t len = src1.total()*cn; - func(src1.ptr(), src2.ptr(), dst.ptr(), (int)len, palpha); - return; - } - - const Mat* arrays[] = {&src1, &src2, &dst, 0}; - uchar* ptrs[3] = {}; - NAryMatIterator it(arrays, ptrs); - size_t i, len = it.size*cn; - - for( i = 0; i < it.nplanes; i++, ++it ) - func( ptrs[0], ptrs[1], ptrs[2], (int)len, palpha ); -} - -/****************************************************************************************\ -* Covariation Matrix * -\****************************************************************************************/ - -void cv::calcCovarMatrix( const Mat* data, int nsamples, Mat& covar, Mat& _mean, int flags, int ctype ) -{ - CV_INSTRUMENT_REGION(); - - CV_Assert_N( data, nsamples > 0 ); - Size size = data[0].size(); - int sz = size.width * size.height, esz = (int)data[0].elemSize(); - int type = data[0].type(); - Mat mean; - ctype = std::max(std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), _mean.depth()), CV_32F); - - if( (flags & CV_COVAR_USE_AVG) != 0 ) - { - CV_Assert( _mean.size() == size ); - if( _mean.isContinuous() && _mean.type() == ctype ) - mean = _mean.reshape(1, 1); - else - { - _mean.convertTo(mean, ctype); - mean = mean.reshape(1, 1); - } - } - - Mat _data(nsamples, sz, type); - - for( int i = 0; i < nsamples; i++ ) - { - CV_Assert_N( data[i].size() == size, data[i].type() == type ); - if( data[i].isContinuous() ) - memcpy( _data.ptr(i), data[i].ptr(), sz*esz ); - else - { - Mat dataRow(size.height, size.width, type, _data.ptr(i)); - data[i].copyTo(dataRow); - } - } - - calcCovarMatrix( _data, covar, mean, (flags & ~(CV_COVAR_ROWS|CV_COVAR_COLS)) | CV_COVAR_ROWS, ctype ); - if( (flags & CV_COVAR_USE_AVG) == 0 ) - _mean = mean.reshape(1, size.height); -} - -void cv::calcCovarMatrix( InputArray _src, OutputArray _covar, InputOutputArray _mean, int flags, int ctype ) -{ - CV_INSTRUMENT_REGION(); - - if(_src.kind() == _InputArray::STD_VECTOR_MAT || _src.kind() == _InputArray::STD_ARRAY_MAT) - { - std::vector src; - _src.getMatVector(src); - - CV_Assert( src.size() > 0 ); - - Size size = src[0].size(); - int type = src[0].type(); - - ctype = std::max(std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), _mean.depth()), CV_32F); - - Mat _data(static_cast(src.size()), size.area(), type); - - int i = 0; - for(std::vector::iterator each = src.begin(); each != src.end(); ++each, ++i ) - { - CV_Assert_N( (*each).size() == size, (*each).type() == type ); - Mat dataRow(size.height, size.width, type, _data.ptr(i)); - (*each).copyTo(dataRow); - } - - Mat mean; - if( (flags & CV_COVAR_USE_AVG) != 0 ) - { - CV_Assert( _mean.size() == size ); - - if( mean.type() != ctype ) - { - mean = _mean.getMat(); - _mean.create(mean.size(), ctype); - Mat tmp = _mean.getMat(); - mean.convertTo(tmp, ctype); - mean = tmp; - } - - mean = _mean.getMat().reshape(1, 1); - } - - calcCovarMatrix( _data, _covar, mean, (flags & ~(CV_COVAR_ROWS|CV_COVAR_COLS)) | CV_COVAR_ROWS, ctype ); - - if( (flags & CV_COVAR_USE_AVG) == 0 ) - { - mean = mean.reshape(1, size.height); - mean.copyTo(_mean); - } - return; - } - - Mat data = _src.getMat(), mean; - CV_Assert( ((flags & CV_COVAR_ROWS) != 0) ^ ((flags & CV_COVAR_COLS) != 0) ); - bool takeRows = (flags & CV_COVAR_ROWS) != 0; - int type = data.type(); - int nsamples = takeRows ? data.rows : data.cols; - CV_Assert( nsamples > 0 ); - Size size = takeRows ? Size(data.cols, 1) : Size(1, data.rows); - - if( (flags & CV_COVAR_USE_AVG) != 0 ) - { - mean = _mean.getMat(); - ctype = std::max(std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), mean.depth()), CV_32F); - CV_Assert( mean.size() == size ); - if( mean.type() != ctype ) - { - _mean.create(mean.size(), ctype); - Mat tmp = _mean.getMat(); - mean.convertTo(tmp, ctype); - mean = tmp; - } - } - else - { - ctype = std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), CV_32F); - reduce( _src, _mean, takeRows ? 0 : 1, CV_REDUCE_AVG, ctype ); - mean = _mean.getMat(); - } - mulTransposed( data, _covar, ((flags & CV_COVAR_NORMAL) == 0) ^ takeRows, - mean, (flags & CV_COVAR_SCALE) != 0 ? 1./nsamples : 1, ctype ); -} /****************************************************************************************\ * Mahalanobis * \****************************************************************************************/ -double cv::Mahalanobis( InputArray _v1, InputArray _v2, InputArray _icovar ) +template static inline +double MahalanobisImpl(const Mat& v1, const Mat& v2, const Mat& icovar, double *diff_buffer /*[len]*/, int len /*=v1.total()*/) { CV_INSTRUMENT_REGION(); - Mat v1 = _v1.getMat(), v2 = _v2.getMat(), icovar = _icovar.getMat(); - int type = v1.type(), depth = v1.depth(); Size sz = v1.size(); - int i, j, len = sz.width*sz.height*v1.channels(); - AutoBuffer buf(len); double result = 0; - CV_Assert_N( type == v2.type(), type == icovar.type(), - sz == v2.size(), len == icovar.rows && len == icovar.cols ); - sz.width *= v1.channels(); - if( v1.isContinuous() && v2.isContinuous() ) + if (v1.isContinuous() && v2.isContinuous()) { sz.width *= sz.height; sz.height = 1; } - if( depth == CV_32F ) - { - const float* src1 = v1.ptr(); - const float* src2 = v2.ptr(); - size_t step1 = v1.step/sizeof(src1[0]); - size_t step2 = v2.step/sizeof(src2[0]); - double* diff = buf.data(); - const float* mat = icovar.ptr(); - size_t matstep = icovar.step/sizeof(mat[0]); - - for( ; sz.height--; src1 += step1, src2 += step2, diff += sz.width ) - { - for( i = 0; i < sz.width; i++ ) - diff[i] = src1[i] - src2[i]; - } - - diff = buf.data(); - for( i = 0; i < len; i++, mat += matstep ) - { - double row_sum = 0; - j = 0; - #if CV_ENABLE_UNROLLED - for(; j <= len - 4; j += 4 ) - row_sum += diff[j]*mat[j] + diff[j+1]*mat[j+1] + - diff[j+2]*mat[j+2] + diff[j+3]*mat[j+3]; - #endif - for( ; j < len; j++ ) - row_sum += diff[j]*mat[j]; - result += row_sum * diff[i]; - } - } - else if( depth == CV_64F ) { - const double* src1 = v1.ptr(); - const double* src2 = v2.ptr(); + const T* src1 = v1.ptr(); + const T* src2 = v2.ptr(); size_t step1 = v1.step/sizeof(src1[0]); size_t step2 = v2.step/sizeof(src2[0]); - double* diff = buf.data(); - const double* mat = icovar.ptr(); + double* diff = diff_buffer; + const T* mat = icovar.ptr(); size_t matstep = icovar.step/sizeof(mat[0]); - for( ; sz.height--; src1 += step1, src2 += step2, diff += sz.width ) + for (; sz.height--; src1 += step1, src2 += step2, diff += sz.width) { - for( i = 0; i < sz.width; i++ ) + for (int i = 0; i < sz.width; i++) diff[i] = src1[i] - src2[i]; } - diff = buf.data(); - for( i = 0; i < len; i++, mat += matstep ) + diff = diff_buffer; + for (int i = 0; i < len; i++, mat += matstep) { double row_sum = 0; - j = 0; - #if CV_ENABLE_UNROLLED + int j = 0; +#if CV_ENABLE_UNROLLED for(; j <= len - 4; j += 4 ) row_sum += diff[j]*mat[j] + diff[j+1]*mat[j+1] + diff[j+2]*mat[j+2] + diff[j+3]*mat[j+3]; - #endif - for( ; j < len; j++ ) +#endif + for (; j < len; j++) row_sum += diff[j]*mat[j]; result += row_sum * diff[i]; } } - else - CV_Error( CV_StsUnsupportedFormat, "" ); + return result; +} - return std::sqrt(result); +MahalanobisImplFunc getMahalanobisImplFunc(int depth) +{ + if (depth == CV_32F) + return (MahalanobisImplFunc)MahalanobisImpl; + if (depth == CV_64F) + return (MahalanobisImplFunc)MahalanobisImpl; + CV_Assert(0 && "Not supported"); } + +#if !defined(CV_MULTRANSPOSED_BASELINE_ONLY) || defined(CV_CPU_BASELINE_MODE) /****************************************************************************************\ * MulTransposed * \****************************************************************************************/ -namespace cv -{ - template static void -MulTransposedR( const Mat& srcmat, Mat& dstmat, const Mat& deltamat, double scale ) +MulTransposedR(const Mat& srcmat, const Mat& dstmat, const Mat& deltamat, double scale) { int i, j, k; const sT* src = srcmat.ptr(); - dT* dst = dstmat.ptr
(); + dT* dst = (dT*)dstmat.ptr
(); const dT* delta = deltamat.ptr
(); size_t srcstep = srcmat.step/sizeof(src[0]); size_t dststep = dstmat.step/sizeof(dst[0]); @@ -2786,11 +2178,11 @@ MulTransposedR( const Mat& srcmat, Mat& dstmat, const Mat& deltamat, double scal template static void -MulTransposedL( const Mat& srcmat, Mat& dstmat, const Mat& deltamat, double scale ) +MulTransposedL(const Mat& srcmat, const Mat& dstmat, const Mat& deltamat, double scale) { int i, j, k; const sT* src = srcmat.ptr(); - dT* dst = dstmat.ptr
(); + dT* dst = (dT*)dstmat.ptr
(); const dT* delta = deltamat.ptr
(); size_t srcstep = srcmat.step/sizeof(src[0]); size_t dststep = dstmat.step/sizeof(dst[0]); @@ -2857,145 +2249,75 @@ MulTransposedL( const Mat& srcmat, Mat& dstmat, const Mat& deltamat, double scal } } -typedef void (*MulTransposedFunc)(const Mat& src, Mat& dst, const Mat& delta, double scale); - -} - -void cv::mulTransposed( InputArray _src, OutputArray _dst, bool ata, - InputArray _delta, double scale, int dtype ) +MulTransposedFunc getMulTransposedFunc(int stype, int dtype, bool ata) { - CV_INSTRUMENT_REGION(); - - Mat src = _src.getMat(), delta = _delta.getMat(); - const int gemm_level = 100; // boundary above which GEMM is faster. - int stype = src.type(); - dtype = std::max(std::max(CV_MAT_DEPTH(dtype >= 0 ? dtype : stype), delta.depth()), CV_32F); - CV_Assert( src.channels() == 1 ); - - if( !delta.empty() ) + MulTransposedFunc func = NULL; + if (stype == CV_8U && dtype == CV_32F) { - CV_Assert_N( delta.channels() == 1, - (delta.rows == src.rows || delta.rows == 1), - (delta.cols == src.cols || delta.cols == 1)); - if( delta.type() != dtype ) - delta.convertTo(delta, dtype); + func = ata ? MulTransposedR + : MulTransposedL; } - - int dsize = ata ? src.cols : src.rows; - _dst.create( dsize, dsize, dtype ); - Mat dst = _dst.getMat(); - - if( src.data == dst.data || (stype == dtype && - (dst.cols >= gemm_level && dst.rows >= gemm_level && - src.cols >= gemm_level && src.rows >= gemm_level))) + else if (stype == CV_8U && dtype == CV_64F) { - Mat src2; - const Mat* tsrc = &src; - if( !delta.empty() ) - { - if( delta.size() == src.size() ) - subtract( src, delta, src2 ); - else - { - repeat(delta, src.rows/delta.rows, src.cols/delta.cols, src2); - subtract( src, src2, src2 ); - } - tsrc = &src2; - } - gemm( *tsrc, *tsrc, scale, Mat(), 0, dst, ata ? GEMM_1_T : GEMM_2_T ); + func = ata ? MulTransposedR + : MulTransposedL; } - else + else if(stype == CV_16U && dtype == CV_32F) { - MulTransposedFunc func = 0; - if(stype == CV_8U && dtype == CV_32F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_8U && dtype == CV_64F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_16U && dtype == CV_32F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_16U && dtype == CV_64F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_16S && dtype == CV_32F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_16S && dtype == CV_64F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_32F && dtype == CV_32F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_32F && dtype == CV_64F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - else if(stype == CV_64F && dtype == CV_64F) - { - if(ata) - func = MulTransposedR; - else - func = MulTransposedL; - } - if( !func ) - CV_Error( CV_StsUnsupportedFormat, "" ); - - func( src, dst, delta, scale ); - completeSymm( dst, false ); + func = ata ? MulTransposedR + : MulTransposedL; + } + else if(stype == CV_16U && dtype == CV_64F) + { + func = ata ? MulTransposedR + : MulTransposedL; + } + else if(stype == CV_16S && dtype == CV_32F) + { + func = ata ? MulTransposedR + : MulTransposedL; + } + else if(stype == CV_16S && dtype == CV_64F) + { + func = ata ? MulTransposedR + : MulTransposedL; + } + else if(stype == CV_32F && dtype == CV_32F) + { + func = ata ? MulTransposedR + : MulTransposedL; } + else if(stype == CV_32F && dtype == CV_64F) + { + func = ata ? MulTransposedR + : MulTransposedL; + } + else if(stype == CV_64F && dtype == CV_64F) + { + func = ata ? MulTransposedR + : MulTransposedL; + } + CV_Assert(func && "Not supported"); + return func; } +#endif // !defined(CV_MULTRANSPOSED_BASELINE_ONLY) || defined(CV_CPU_BASELINE_MODE) + /****************************************************************************************\ * Dot Product * \****************************************************************************************/ -namespace cv -{ - -template double -dotProd_(const T* src1, const T* src2, int len) +template static inline +double dotProd_(const T* src1, const T* src2, int len) { int i = 0; double result = 0; - #if CV_ENABLE_UNROLLED +#if CV_ENABLE_UNROLLED for( ; i <= len - 4; i += 4 ) result += (double)src1[i]*src2[i] + (double)src1[i+1]*src2[i+1] + (double)src1[i+2]*src2[i+2] + (double)src1[i+3]*src2[i+3]; - #endif +#endif for( ; i < len; i++ ) result += (double)src1[i]*src2[i]; @@ -3003,12 +2325,9 @@ dotProd_(const T* src1, const T* src2, int len) } -static double dotProd_8u(const uchar* src1, const uchar* src2, int len) +double dotProd_8u(const uchar* src1, const uchar* src2, int len) { double r = 0; -#if ARITHM_USE_IPP - CV_IPP_RUN(IPP_VERSION_X100 > 201800 || cv::ipp::getIppTopFeatures() != ippCPUID_SSE42, CV_INSTRUMENT_FUN_IPP(ippiDotProd_8u64f_C1R, src1, len*sizeof(uchar), src2, len*sizeof(uchar), ippiSize(len, 1), &r) >= 0, r); -#endif int i = 0; #if CV_SIMD @@ -3092,7 +2411,7 @@ static double dotProd_8u(const uchar* src1, const uchar* src2, int len) } -static double dotProd_8s(const schar* src1, const schar* src2, int len) +double dotProd_8s(const schar* src1, const schar* src2, int len) { double r = 0.0; int i = 0; @@ -3178,40 +2497,24 @@ static double dotProd_8s(const schar* src1, const schar* src2, int len) return r + dotProd_(src1, src2, len - i); } -static double dotProd_16u(const ushort* src1, const ushort* src2, int len) +double dotProd_16u(const ushort* src1, const ushort* src2, int len) { -#if ARITHM_USE_IPP - double r = 0; - CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiDotProd_16u64f_C1R, src1, len*sizeof(ushort), src2, len*sizeof(ushort), ippiSize(len, 1), &r) >= 0, r); -#endif return dotProd_(src1, src2, len); } -static double dotProd_16s(const short* src1, const short* src2, int len) +double dotProd_16s(const short* src1, const short* src2, int len) { -#if ARITHM_USE_IPP && (IPP_VERSION_X100 != 900) // bug in IPP 9.0.0 - double r = 0; - CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiDotProd_16s64f_C1R, src1, len*sizeof(short), src2, len*sizeof(short), ippiSize(len, 1), &r) >= 0, r); -#endif return dotProd_(src1, src2, len); } -static double dotProd_32s(const int* src1, const int* src2, int len) +double dotProd_32s(const int* src1, const int* src2, int len) { -#if ARITHM_USE_IPP - double r = 0; - CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiDotProd_32s64f_C1R, src1, len*sizeof(int), src2, len*sizeof(int), ippiSize(len, 1), &r) >= 0, r); -#endif return dotProd_(src1, src2, len); } -static double dotProd_32f(const float* src1, const float* src2, int len) +double dotProd_32f(const float* src1, const float* src2, int len) { double r = 0.0; - -#if ARITHM_USE_IPP - CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiDotProd_32f64f_C1R, src1, len*sizeof(float), src2, len*sizeof(float), ippiSize(len, 1), &r, ippAlgHintFast) >= 0, r); -#endif int i = 0; #if CV_SIMD @@ -3238,284 +2541,11 @@ static double dotProd_32f(const float* src1, const float* src2, int len) return r + dotProd_(src1, src2, len - i); } -static double dotProd_64f(const double* src1, const double* src2, int len) +double dotProd_64f(const double* src1, const double* src2, int len) { -#if ARITHM_USE_IPP - double r = 0; - CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippsDotProd_64f, src1, src2, len, &r) >= 0, r); -#endif - return dotProd_(src1, src2, len); } - -typedef double (*DotProdFunc)(const uchar* src1, const uchar* src2, int len); - -static DotProdFunc getDotProdFunc(int depth) -{ - static DotProdFunc dotProdTab[] = - { - (DotProdFunc)GET_OPTIMIZED(dotProd_8u), (DotProdFunc)GET_OPTIMIZED(dotProd_8s), - (DotProdFunc)dotProd_16u, (DotProdFunc)dotProd_16s, - (DotProdFunc)dotProd_32s, (DotProdFunc)GET_OPTIMIZED(dotProd_32f), - (DotProdFunc)dotProd_64f, 0 - }; - - return dotProdTab[depth]; -} - -double Mat::dot(InputArray _mat) const -{ - CV_INSTRUMENT_REGION(); - - Mat mat = _mat.getMat(); - int cn = channels(); - DotProdFunc func = getDotProdFunc(depth()); - CV_Assert_N( mat.type() == type(), mat.size == size, func != 0 ); - - if( isContinuous() && mat.isContinuous() ) - { - size_t len = total()*cn; - if( len == (size_t)(int)len ) - return func(data, mat.data, (int)len); - } - - const Mat* arrays[] = {this, &mat, 0}; - uchar* ptrs[2] = {}; - NAryMatIterator it(arrays, ptrs); - int len = (int)(it.size*cn); - double r = 0; - - for( size_t i = 0; i < it.nplanes; i++, ++it ) - r += func( ptrs[0], ptrs[1], len ); - - return r; -} - -} - -/****************************************************************************************\ -* Earlier API * -\****************************************************************************************/ - -CV_IMPL void cvGEMM( const CvArr* Aarr, const CvArr* Barr, double alpha, - const CvArr* Carr, double beta, CvArr* Darr, int flags ) -{ - cv::Mat A = cv::cvarrToMat(Aarr), B = cv::cvarrToMat(Barr); - cv::Mat C, D = cv::cvarrToMat(Darr); - - if( Carr ) - C = cv::cvarrToMat(Carr); - - CV_Assert_N( (D.rows == ((flags & CV_GEMM_A_T) == 0 ? A.rows : A.cols)), - (D.cols == ((flags & CV_GEMM_B_T) == 0 ? B.cols : B.rows)), - D.type() == A.type() ); - - gemm( A, B, alpha, C, beta, D, flags ); -} - - -CV_IMPL void -cvTransform( const CvArr* srcarr, CvArr* dstarr, - const CvMat* transmat, const CvMat* shiftvec ) -{ - cv::Mat m = cv::cvarrToMat(transmat), src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr); - - if( shiftvec ) - { - cv::Mat v = cv::cvarrToMat(shiftvec).reshape(1,m.rows), - _m(m.rows, m.cols + 1, m.type()), m1 = _m.colRange(0,m.cols), v1 = _m.col(m.cols); - m.convertTo(m1, m1.type()); - v.convertTo(v1, v1.type()); - m = _m; - } - - CV_Assert_N( dst.depth() == src.depth(), dst.channels() == m.rows ); - cv::transform( src, dst, m ); -} - - -CV_IMPL void -cvPerspectiveTransform( const CvArr* srcarr, CvArr* dstarr, const CvMat* mat ) -{ - cv::Mat m = cv::cvarrToMat(mat), src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr); - - CV_Assert_N( dst.type() == src.type(), dst.channels() == m.rows-1 ); - cv::perspectiveTransform( src, dst, m ); -} - - -CV_IMPL void cvScaleAdd( const CvArr* srcarr1, CvScalar scale, - const CvArr* srcarr2, CvArr* dstarr ) -{ - cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr); - - CV_Assert_N( src1.size == dst.size, src1.type() == dst.type() ); - cv::scaleAdd( src1, scale.val[0], cv::cvarrToMat(srcarr2), dst ); -} - - -CV_IMPL void -cvCalcCovarMatrix( const CvArr** vecarr, int count, - CvArr* covarr, CvArr* avgarr, int flags ) -{ - cv::Mat cov0 = cv::cvarrToMat(covarr), cov = cov0, mean0, mean; - CV_Assert_N( vecarr != 0, count >= 1 ); - - if( avgarr ) - mean = mean0 = cv::cvarrToMat(avgarr); - - if( (flags & CV_COVAR_COLS) != 0 || (flags & CV_COVAR_ROWS) != 0 ) - { - - cv::Mat data = cv::cvarrToMat(vecarr[0]); - cv::calcCovarMatrix( data, cov, mean, flags, cov.type() ); - } - else - { - std::vector data(count); - for( int i = 0; i < count; i++ ) - data[i] = cv::cvarrToMat(vecarr[i]); - cv::calcCovarMatrix( &data[0], count, cov, mean, flags, cov.type() ); - } - - if( mean.data != mean0.data && mean0.data ) - mean.convertTo(mean0, mean0.type()); - - if( cov.data != cov0.data ) - cov.convertTo(cov0, cov0.type()); -} - - -CV_IMPL double -cvMahalanobis( const CvArr* srcAarr, const CvArr* srcBarr, const CvArr* matarr ) -{ - return cv::Mahalanobis(cv::cvarrToMat(srcAarr), - cv::cvarrToMat(srcBarr), cv::cvarrToMat(matarr)); -} - -CV_IMPL void -cvMulTransposed( const CvArr* srcarr, CvArr* dstarr, - int order, const CvArr* deltaarr, double scale ) -{ - cv::Mat src = cv::cvarrToMat(srcarr), dst0 = cv::cvarrToMat(dstarr), dst = dst0, delta; - if( deltaarr ) - delta = cv::cvarrToMat(deltaarr); - cv::mulTransposed( src, dst, order != 0, delta, scale, dst.type()); - if( dst.data != dst0.data ) - dst.convertTo(dst0, dst0.type()); -} - -CV_IMPL double cvDotProduct( const CvArr* srcAarr, const CvArr* srcBarr ) -{ - return cv::cvarrToMat(srcAarr).dot(cv::cvarrToMat(srcBarr)); -} - - -CV_IMPL void -cvCalcPCA( const CvArr* data_arr, CvArr* avg_arr, CvArr* eigenvals, CvArr* eigenvects, int flags ) -{ - cv::Mat data = cv::cvarrToMat(data_arr), mean0 = cv::cvarrToMat(avg_arr); - cv::Mat evals0 = cv::cvarrToMat(eigenvals), evects0 = cv::cvarrToMat(eigenvects); - cv::Mat mean = mean0, evals = evals0, evects = evects0; - - cv::PCA pca; - pca.mean = mean; - pca.eigenvalues = evals; - pca.eigenvectors = evects; - - pca(data, (flags & CV_PCA_USE_AVG) ? mean : cv::Mat(), - flags, !evals.empty() ? evals.rows + evals.cols - 1 : 0); - - if( pca.mean.size() == mean.size() ) - pca.mean.convertTo( mean, mean.type() ); - else - { - cv::Mat temp; pca.mean.convertTo( temp, mean.type() ); - transpose( temp, mean ); - } - - evals = pca.eigenvalues; - evects = pca.eigenvectors; - int ecount0 = evals0.cols + evals0.rows - 1; - int ecount = evals.cols + evals.rows - 1; - - CV_Assert_N( (evals0.cols == 1 || evals0.rows == 1), - ecount0 <= ecount, - evects0.cols == evects.cols, - evects0.rows == ecount0 ); - - cv::Mat temp = evals0; - if( evals.rows == 1 ) - evals.colRange(0, ecount0).convertTo(temp, evals0.type()); - else - evals.rowRange(0, ecount0).convertTo(temp, evals0.type()); - if( temp.data != evals0.data ) - transpose(temp, evals0); - evects.rowRange(0, ecount0).convertTo( evects0, evects0.type() ); - - // otherwise some datatype's or size's were incorrect, so the output arrays have been reallocated - CV_Assert( mean0.data == mean.data ); -} - - -CV_IMPL void -cvProjectPCA( const CvArr* data_arr, const CvArr* avg_arr, - const CvArr* eigenvects, CvArr* result_arr ) -{ - cv::Mat data = cv::cvarrToMat(data_arr), mean = cv::cvarrToMat(avg_arr); - cv::Mat evects = cv::cvarrToMat(eigenvects), dst0 = cv::cvarrToMat(result_arr), dst = dst0; - - cv::PCA pca; - pca.mean = mean; - int n; - if( mean.rows == 1 ) - { - CV_Assert_N(dst.cols <= evects.rows, dst.rows == data.rows); - n = dst.cols; - } - else - { - CV_Assert_N(dst.rows <= evects.rows, dst.cols == data.cols); - n = dst.rows; - } - pca.eigenvectors = evects.rowRange(0, n); - - cv::Mat result = pca.project(data); - if( result.cols != dst.cols ) - result = result.reshape(1, 1); - result.convertTo(dst, dst.type()); - - CV_Assert(dst0.data == dst.data); -} - - -CV_IMPL void -cvBackProjectPCA( const CvArr* proj_arr, const CvArr* avg_arr, - const CvArr* eigenvects, CvArr* result_arr ) -{ - cv::Mat data = cv::cvarrToMat(proj_arr), mean = cv::cvarrToMat(avg_arr); - cv::Mat evects = cv::cvarrToMat(eigenvects), dst0 = cv::cvarrToMat(result_arr), dst = dst0; - - cv::PCA pca; - pca.mean = mean; - int n; - if( mean.rows == 1 ) - { - CV_Assert_N(data.cols <= evects.rows, dst.rows == data.rows); - n = data.cols; - } - else - { - CV_Assert_N(data.rows <= evects.rows, dst.cols == data.cols); - n = data.rows; - } - pca.eigenvectors = evects.rowRange(0, n); - - cv::Mat result = pca.backProject(data); - result.convertTo(dst, dst.type()); - - CV_Assert(dst0.data == dst.data); -} - -/* End of file. */ +#endif +CV_CPU_OPTIMIZATION_NAMESPACE_END +} // namespace \ No newline at end of file From 3c92d40f6e86f1eaf85ead9842be637c7ec802de Mon Sep 17 00:00:00 2001 From: catree Date: Thu, 14 Feb 2019 18:50:01 +0100 Subject: [PATCH 18/21] Fix arguments parsing. Add possibility to choose between different features type. Add keypoints matching visualization. Auto format code. --- .../src/CsvReader.cpp | 2 +- .../real_time_pose_estimation/src/CsvReader.h | 42 +- .../src/CsvWriter.cpp | 57 +- .../real_time_pose_estimation/src/CsvWriter.h | 16 +- .../real_time_pose_estimation/src/Mesh.cpp | 46 +- .../real_time_pose_estimation/src/Mesh.h | 58 +- .../real_time_pose_estimation/src/Model.cpp | 72 +- .../real_time_pose_estimation/src/Model.h | 65 +- .../src/ModelRegistration.cpp | 21 +- .../src/ModelRegistration.h | 37 +- .../src/PnPProblem.cpp | 390 ++++----- .../src/PnPProblem.h | 52 +- .../src/RobustMatcher.cpp | 192 +++-- .../src/RobustMatcher.h | 101 ++- .../real_time_pose_estimation/src/Utils.cpp | 463 ++++++---- .../real_time_pose_estimation/src/Utils.h | 5 + .../src/main_detection.cpp | 810 +++++++++--------- .../src/main_registration.cpp | 395 +++++---- 18 files changed, 1490 insertions(+), 1334 deletions(-) diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvReader.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvReader.cpp index c69751740b..1461877ef6 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvReader.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvReader.cpp @@ -1,7 +1,7 @@ #include "CsvReader.h" /** The default constructor of the CSV reader Class */ -CsvReader::CsvReader(const string &path, const char &separator){ +CsvReader::CsvReader(const string &path, char separator){ _file.open(path.c_str(), ifstream::in); _separator = separator; } diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvReader.h b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvReader.h index 3e8c498960..cf54cb740c 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvReader.h +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvReader.h @@ -11,30 +11,30 @@ using namespace cv; class CsvReader { public: - /** - * The default constructor of the CSV reader Class. - * The default separator is ' ' (empty space) - * - * @param path - The path of the file to read - * @param separator - The separator character between words per line - * @return - */ - CsvReader(const string &path, const char &separator = ' '); + /** + * The default constructor of the CSV reader Class. + * The default separator is ' ' (empty space) + * + * @param path - The path of the file to read + * @param separator - The separator character between words per line + * @return + */ + CsvReader(const string &path, char separator = ' '); - /** - * Read a plane text file with .ply format - * - * @param list_vertex - The container of the vertices list of the mesh - * @param list_triangle - The container of the triangles list of the mesh - * @return - */ - void readPLY(vector &list_vertex, vector > &list_triangles); + /** + * Read a plane text file with .ply format + * + * @param list_vertex - The container of the vertices list of the mesh + * @param list_triangle - The container of the triangles list of the mesh + * @return + */ + void readPLY(vector &list_vertex, vector > &list_triangles); private: - /** The current stream file for the reader */ - ifstream _file; - /** The separator character between words for each line */ - char _separator; + /** The current stream file for the reader */ + ifstream _file; + /** The separator character between words for each line */ + char _separator; }; #endif diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvWriter.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvWriter.cpp index a64fb69130..10d0df479e 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvWriter.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvWriter.cpp @@ -1,48 +1,45 @@ #include "CsvWriter.h" CsvWriter::CsvWriter(const string &path, const string &separator){ - _file.open(path.c_str(), ofstream::out); - _isFirstTerm = true; - _separator = separator; + _file.open(path.c_str(), ofstream::out); + _isFirstTerm = true; + _separator = separator; } CsvWriter::~CsvWriter() { - _file.flush(); - _file.close(); + _file.flush(); + _file.close(); } void CsvWriter::writeXYZ(const vector &list_points3d) { - string x, y, z; - for(unsigned int i = 0; i < list_points3d.size(); ++i) - { - x = FloatToString(list_points3d[i].x); - y = FloatToString(list_points3d[i].y); - z = FloatToString(list_points3d[i].z); - - _file << x << _separator << y << _separator << z << std::endl; - } + for(size_t i = 0; i < list_points3d.size(); ++i) + { + string x = FloatToString(list_points3d[i].x); + string y = FloatToString(list_points3d[i].y); + string z = FloatToString(list_points3d[i].z); + _file << x << _separator << y << _separator << z << std::endl; + } } void CsvWriter::writeUVXYZ(const vector &list_points3d, const vector &list_points2d, const Mat &descriptors) { - string u, v, x, y, z, descriptor_str; - for(unsigned int i = 0; i < list_points3d.size(); ++i) - { - u = FloatToString(list_points2d[i].x); - v = FloatToString(list_points2d[i].y); - x = FloatToString(list_points3d[i].x); - y = FloatToString(list_points3d[i].y); - z = FloatToString(list_points3d[i].z); - - _file << u << _separator << v << _separator << x << _separator << y << _separator << z; - - for(int j = 0; j < 32; ++j) + for(size_t i = 0; i < list_points3d.size(); ++i) { - descriptor_str = FloatToString(descriptors.at(i,j)); - _file << _separator << descriptor_str; + string u = FloatToString(list_points2d[i].x); + string v = FloatToString(list_points2d[i].y); + string x = FloatToString(list_points3d[i].x); + string y = FloatToString(list_points3d[i].y); + string z = FloatToString(list_points3d[i].z); + + _file << u << _separator << v << _separator << x << _separator << y << _separator << z; + + for(int j = 0; j < 32; ++j) + { + string descriptor_str = FloatToString(descriptors.at((int)i,j)); + _file << _separator << descriptor_str; + } + _file << std::endl; } - _file << std::endl; - } } diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvWriter.h b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvWriter.h index 06314bbd89..499fb115ec 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvWriter.h +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/CsvWriter.h @@ -1,5 +1,5 @@ #ifndef CSVWRITER_H -#define CSVWRITER_H +#define CSVWRITER_H #include #include @@ -11,15 +11,15 @@ using namespace cv; class CsvWriter { public: - CsvWriter(const string &path, const string &separator = " "); - ~CsvWriter(); - void writeXYZ(const vector &list_points3d); - void writeUVXYZ(const vector &list_points3d, const vector &list_points2d, const Mat &descriptors); + CsvWriter(const string &path, const string &separator = " "); + ~CsvWriter(); + void writeXYZ(const vector &list_points3d); + void writeUVXYZ(const vector &list_points3d, const vector &list_points2d, const Mat &descriptors); private: - ofstream _file; - string _separator; - bool _isFirstTerm; + ofstream _file; + string _separator; + bool _isFirstTerm; }; #endif diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Mesh.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Mesh.cpp index e6c84c47a7..2228b6e9d9 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Mesh.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Mesh.cpp @@ -14,15 +14,15 @@ // --------------------------------------------------- // /** The custom constructor of the Triangle Class */ -Triangle::Triangle(int id, cv::Point3f V0, cv::Point3f V1, cv::Point3f V2) +Triangle::Triangle(const cv::Point3f& V0, const cv::Point3f& V1, const cv::Point3f& V2) : + v0_(V0), v1_(V1), v2_(V2) { - id_ = id; v0_ = V0; v1_ = V1; v2_ = V2; } /** The default destructor of the Class */ Triangle::~Triangle() { - // TODO Auto-generated destructor stub + // TODO Auto-generated destructor stub } @@ -31,14 +31,15 @@ Triangle::~Triangle() // --------------------------------------------------- // /** The custom constructor of the Ray Class */ -Ray::Ray(cv::Point3f P0, cv::Point3f P1) { - p0_ = P0; p1_ = P1; +Ray::Ray(const cv::Point3f& P0, const cv::Point3f& P1) : + p0_(P0), p1_(P1) +{ } /** The default destructor of the Class */ Ray::~Ray() { - // TODO Auto-generated destructor stub + // TODO Auto-generated destructor stub } @@ -47,36 +48,31 @@ Ray::~Ray() // --------------------------------------------------- // /** The default constructor of the ObjectMesh Class */ -Mesh::Mesh() : list_vertex_(0) , list_triangles_(0) +Mesh::Mesh() : num_vertices_(0), num_triangles_(0), + list_vertex_(0) , list_triangles_(0) { - id_ = 0; - num_vertexs_ = 0; - num_triangles_ = 0; } /** The default destructor of the ObjectMesh Class */ Mesh::~Mesh() { - // TODO Auto-generated destructor stub + // TODO Auto-generated destructor stub } - /** Load a CSV with *.ply format **/ -void Mesh::load(const std::string path) +void Mesh::load(const std::string& path) { + // Create the reader + CsvReader csvReader(path); - // Create the reader - CsvReader csvReader(path); - - // Clear previous data - list_vertex_.clear(); - list_triangles_.clear(); - - // Read from .ply file - csvReader.readPLY(list_vertex_, list_triangles_); + // Clear previous data + list_vertex_.clear(); + list_triangles_.clear(); - // Update mesh attributes - num_vertexs_ = (int)list_vertex_.size(); - num_triangles_ = (int)list_triangles_.size(); + // Read from .ply file + csvReader.readPLY(list_vertex_, list_triangles_); + // Update mesh attributes + num_vertices_ = (int)list_vertex_.size(); + num_triangles_ = (int)list_triangles_.size(); } diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Mesh.h b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Mesh.h index 2ca625d3c3..40f8b7d492 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Mesh.h +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Mesh.h @@ -19,18 +19,16 @@ class Triangle { public: - explicit Triangle(int id, cv::Point3f V0, cv::Point3f V1, cv::Point3f V2); - virtual ~Triangle(); + explicit Triangle(const cv::Point3f& V0, const cv::Point3f& V1, const cv::Point3f& V2); + virtual ~Triangle(); - cv::Point3f getV0() const { return v0_; } - cv::Point3f getV1() const { return v1_; } - cv::Point3f getV2() const { return v2_; } + cv::Point3f getV0() const { return v0_; } + cv::Point3f getV1() const { return v1_; } + cv::Point3f getV2() const { return v2_; } private: - /** The identifier number of the triangle */ - int id_; - /** The three vertices that defines the triangle */ - cv::Point3f v0_, v1_, v2_; + /** The three vertices that defines the triangle */ + cv::Point3f v0_, v1_, v2_; }; @@ -41,15 +39,15 @@ private: class Ray { public: - explicit Ray(cv::Point3f P0, cv::Point3f P1); - virtual ~Ray(); + explicit Ray(const cv::Point3f& P0, const cv::Point3f& P1); + virtual ~Ray(); - cv::Point3f getP0() { return p0_; } - cv::Point3f getP1() { return p1_; } + cv::Point3f getP0() { return p0_; } + cv::Point3f getP1() { return p1_; } private: - /** The two points that defines the ray */ - cv::Point3f p0_, p1_; + /** The two points that defines the ray */ + cv::Point3f p0_, p1_; }; @@ -61,26 +59,24 @@ class Mesh { public: - Mesh(); - virtual ~Mesh(); + Mesh(); + virtual ~Mesh(); - std::vector > getTrianglesList() const { return list_triangles_; } - cv::Point3f getVertex(int pos) const { return list_vertex_[pos]; } - int getNumVertices() const { return num_vertexs_; } + std::vector > getTrianglesList() const { return list_triangles_; } + cv::Point3f getVertex(int pos) const { return list_vertex_[pos]; } + int getNumVertices() const { return num_vertices_; } - void load(const std::string path_file); + void load(const std::string& path_file); private: - /** The identification number of the mesh */ - int id_; - /** The current number of vertices in the mesh */ - int num_vertexs_; - /** The current number of triangles in the mesh */ - int num_triangles_; - /* The list of triangles of the mesh */ - std::vector list_vertex_; - /* The list of triangles of the mesh */ - std::vector > list_triangles_; + /** The current number of vertices in the mesh */ + int num_vertices_; + /** The current number of triangles in the mesh */ + int num_triangles_; + /* The list of triangles of the mesh */ + std::vector list_vertex_; + /* The list of triangles of the mesh */ + std::vector > list_triangles_; }; #endif /* OBJECTMESH_H_ */ diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Model.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Model.cpp index 3256cef057..e2dc2a8a37 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Model.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Model.cpp @@ -8,66 +8,76 @@ #include "Model.h" #include "CsvWriter.h" -Model::Model() : list_points2d_in_(0), list_points2d_out_(0), list_points3d_in_(0) +Model::Model() : n_correspondences_(0), list_points2d_in_(0), list_points2d_out_(0), list_points3d_in_(0), training_img_path_() { - n_correspondences_ = 0; } Model::~Model() { - // TODO Auto-generated destructor stub + // TODO Auto-generated destructor stub } void Model::add_correspondence(const cv::Point2f &point2d, const cv::Point3f &point3d) { - list_points2d_in_.push_back(point2d); - list_points3d_in_.push_back(point3d); - n_correspondences_++; + list_points2d_in_.push_back(point2d); + list_points3d_in_.push_back(point3d); + n_correspondences_++; } void Model::add_outlier(const cv::Point2f &point2d) { - list_points2d_out_.push_back(point2d); + list_points2d_out_.push_back(point2d); } void Model::add_descriptor(const cv::Mat &descriptor) { - descriptors_.push_back(descriptor); + descriptors_.push_back(descriptor); } void Model::add_keypoint(const cv::KeyPoint &kp) { - list_keypoints_.push_back(kp); + list_keypoints_.push_back(kp); } +void Model::set_trainingImagePath(const std::string &path) +{ + training_img_path_ = path; +} -/** Save a CSV file and fill the object mesh */ -void Model::save(const std::string path) +/** Save a YAML file and fill the object mesh */ +void Model::save(const std::string &path) { - cv::Mat points3dmatrix = cv::Mat(list_points3d_in_); - cv::Mat points2dmatrix = cv::Mat(list_points2d_in_); - //cv::Mat keyPointmatrix = cv::Mat(list_keypoints_); + cv::Mat points3dmatrix = cv::Mat(list_points3d_in_); + cv::Mat points2dmatrix = cv::Mat(list_points2d_in_); - cv::FileStorage storage(path, cv::FileStorage::WRITE); - storage << "points_3d" << points3dmatrix; - storage << "points_2d" << points2dmatrix; - storage << "keypoints" << list_keypoints_; - storage << "descriptors" << descriptors_; + cv::FileStorage storage(path, cv::FileStorage::WRITE); + storage << "points_3d" << points3dmatrix; + storage << "points_2d" << points2dmatrix; + storage << "keypoints" << list_keypoints_; + storage << "descriptors" << descriptors_; + storage << "training_image_path" << training_img_path_; - storage.release(); + storage.release(); } /** Load a YAML file using OpenCv functions **/ -void Model::load(const std::string path) +void Model::load(const std::string &path) { - cv::Mat points3d_mat; - - cv::FileStorage storage(path, cv::FileStorage::READ); - storage["points_3d"] >> points3d_mat; - storage["descriptors"] >> descriptors_; - - points3d_mat.copyTo(list_points3d_in_); - - storage.release(); - + cv::Mat points3d_mat; + + cv::FileStorage storage(path, cv::FileStorage::READ); + storage["points_3d"] >> points3d_mat; + storage["descriptors"] >> descriptors_; + if (!storage["keypoints"].empty()) + { + storage["keypoints"] >> list_keypoints_; + } + if (!storage["training_image_path"].empty()) + { + storage["training_image_path"] >> training_img_path_; + } + + points3d_mat.copyTo(list_points3d_in_); + + storage.release(); } diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Model.h b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Model.h index 79af18f0fb..7380af5d0e 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Model.h +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Model.h @@ -15,40 +15,41 @@ class Model { public: - Model(); - virtual ~Model(); - - std::vector get_points2d_in() const { return list_points2d_in_; } - std::vector get_points2d_out() const { return list_points2d_out_; } - std::vector get_points3d() const { return list_points3d_in_; } - std::vector get_keypoints() const { return list_keypoints_; } - cv::Mat get_descriptors() const { return descriptors_; } - int get_numDescriptors() const { return descriptors_.rows; } - - - void add_correspondence(const cv::Point2f &point2d, const cv::Point3f &point3d); - void add_outlier(const cv::Point2f &point2d); - void add_descriptor(const cv::Mat &descriptor); - void add_keypoint(const cv::KeyPoint &kp); - - - void save(const std::string path); - void load(const std::string path); - + Model(); + virtual ~Model(); + + std::vector get_points2d_in() const { return list_points2d_in_; } + std::vector get_points2d_out() const { return list_points2d_out_; } + std::vector get_points3d() const { return list_points3d_in_; } + std::vector get_keypoints() const { return list_keypoints_; } + cv::Mat get_descriptors() const { return descriptors_; } + int get_numDescriptors() const { return descriptors_.rows; } + std::string get_trainingImagePath() const { return training_img_path_; } + + void add_correspondence(const cv::Point2f &point2d, const cv::Point3f &point3d); + void add_outlier(const cv::Point2f &point2d); + void add_descriptor(const cv::Mat &descriptor); + void add_keypoint(const cv::KeyPoint &kp); + void set_trainingImagePath(const std::string &path); + + void save(const std::string &path); + void load(const std::string &path); private: - /** The current number of correspondecnes */ - int n_correspondences_; - /** The list of 2D points on the model surface */ - std::vector list_keypoints_; - /** The list of 2D points on the model surface */ - std::vector list_points2d_in_; - /** The list of 2D points outside the model surface */ - std::vector list_points2d_out_; - /** The list of 3D points on the model surface */ - std::vector list_points3d_in_; - /** The list of 2D points descriptors */ - cv::Mat descriptors_; + /** The current number of correspondecnes */ + int n_correspondences_; + /** The list of 2D points on the model surface */ + std::vector list_keypoints_; + /** The list of 2D points on the model surface */ + std::vector list_points2d_in_; + /** The list of 2D points outside the model surface */ + std::vector list_points2d_out_; + /** The list of 3D points on the model surface */ + std::vector list_points3d_in_; + /** The list of 2D points descriptors */ + cv::Mat descriptors_; + /** Path to the training image */ + std::string training_img_path_; }; #endif /* OBJECTMODEL_H_ */ diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/ModelRegistration.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/ModelRegistration.cpp index e8da885685..8690a345b2 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/ModelRegistration.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/ModelRegistration.cpp @@ -7,29 +7,28 @@ #include "ModelRegistration.h" -ModelRegistration::ModelRegistration() +ModelRegistration::ModelRegistration() : n_registrations_(0), max_registrations_(0), + list_points2d_(), list_points3d_() { - n_registrations_ = 0; - max_registrations_ = 0; } ModelRegistration::~ModelRegistration() { - // TODO Auto-generated destructor stub + // TODO Auto-generated destructor stub } void ModelRegistration::registerPoint(const cv::Point2f &point2d, const cv::Point3f &point3d) - { - // add correspondence at the end of the vector +{ + // add correspondence at the end of the vector list_points2d_.push_back(point2d); list_points3d_.push_back(point3d); n_registrations_++; - } +} void ModelRegistration::reset() { - n_registrations_ = 0; - max_registrations_ = 0; - list_points2d_.clear(); - list_points3d_.clear(); + n_registrations_ = 0; + max_registrations_ = 0; + list_points2d_.clear(); + list_points3d_.clear(); } diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/ModelRegistration.h b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/ModelRegistration.h index 7491ede45a..350f56d871 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/ModelRegistration.h +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/ModelRegistration.h @@ -14,30 +14,29 @@ class ModelRegistration { public: + ModelRegistration(); + virtual ~ModelRegistration(); - ModelRegistration(); - virtual ~ModelRegistration(); + void setNumMax(int n) { max_registrations_ = n; } - void setNumMax(int n) { max_registrations_ = n; } + std::vector get_points2d() const { return list_points2d_; } + std::vector get_points3d() const { return list_points3d_; } + int getNumMax() const { return max_registrations_; } + int getNumRegist() const { return n_registrations_; } - std::vector get_points2d() const { return list_points2d_; } - std::vector get_points3d() const { return list_points3d_; } - int getNumMax() const { return max_registrations_; } - int getNumRegist() const { return n_registrations_; } - - bool is_registrable() const { return (n_registrations_ < max_registrations_); } - void registerPoint(const cv::Point2f &point2d, const cv::Point3f &point3d); - void reset(); + bool is_registrable() const { return (n_registrations_ < max_registrations_); } + void registerPoint(const cv::Point2f &point2d, const cv::Point3f &point3d); + void reset(); private: -/** The current number of registered points */ -int n_registrations_; -/** The total number of points to register */ -int max_registrations_; -/** The list of 2D points to register the model */ -std::vector list_points2d_; -/** The list of 3D points to register the model */ -std::vector list_points3d_; + /** The current number of registered points */ + int n_registrations_; + /** The total number of points to register */ + int max_registrations_; + /** The list of 2D points to register the model */ + std::vector list_points2d_; + /** The list of 3D points to register the model */ + std::vector list_points3d_; }; #endif /* MODELREGISTRATION_H_ */ diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/PnPProblem.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/PnPProblem.cpp index a53250ab86..c99b0eca05 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/PnPProblem.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/PnPProblem.cpp @@ -13,122 +13,112 @@ #include -/* Functions headers */ -cv::Point3f CROSS(cv::Point3f v1, cv::Point3f v2); -double DOT(cv::Point3f v1, cv::Point3f v2); -cv::Point3f SUB(cv::Point3f v1, cv::Point3f v2); -cv::Point3f get_nearest_3D_point(std::vector &points_list, cv::Point3f origin); - - /* Functions for Möller-Trumbore intersection algorithm */ - -cv::Point3f CROSS(cv::Point3f v1, cv::Point3f v2) +static cv::Point3f CROSS(cv::Point3f v1, cv::Point3f v2) { - cv::Point3f tmp_p; - tmp_p.x = v1.y*v2.z - v1.z*v2.y; - tmp_p.y = v1.z*v2.x - v1.x*v2.z; - tmp_p.z = v1.x*v2.y - v1.y*v2.x; - return tmp_p; + cv::Point3f tmp_p; + tmp_p.x = v1.y*v2.z - v1.z*v2.y; + tmp_p.y = v1.z*v2.x - v1.x*v2.z; + tmp_p.z = v1.x*v2.y - v1.y*v2.x; + return tmp_p; } -double DOT(cv::Point3f v1, cv::Point3f v2) +static double DOT(cv::Point3f v1, cv::Point3f v2) { - return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; + return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; } -cv::Point3f SUB(cv::Point3f v1, cv::Point3f v2) +static cv::Point3f SUB(cv::Point3f v1, cv::Point3f v2) { - cv::Point3f tmp_p; - tmp_p.x = v1.x - v2.x; - tmp_p.y = v1.y - v2.y; - tmp_p.z = v1.z - v2.z; - return tmp_p; + cv::Point3f tmp_p; + tmp_p.x = v1.x - v2.x; + tmp_p.y = v1.y - v2.y; + tmp_p.z = v1.z - v2.z; + return tmp_p; } -/* End functions for Möller-Trumbore intersection algorithm - * */ +/* End functions for Möller-Trumbore intersection algorithm */ // Function to get the nearest 3D point to the Ray origin -cv::Point3f get_nearest_3D_point(std::vector &points_list, cv::Point3f origin) +static cv::Point3f get_nearest_3D_point(std::vector &points_list, cv::Point3f origin) { - cv::Point3f p1 = points_list[0]; - cv::Point3f p2 = points_list[1]; - - double d1 = std::sqrt( std::pow(p1.x-origin.x, 2) + std::pow(p1.y-origin.y, 2) + std::pow(p1.z-origin.z, 2) ); - double d2 = std::sqrt( std::pow(p2.x-origin.x, 2) + std::pow(p2.y-origin.y, 2) + std::pow(p2.z-origin.z, 2) ); - - if(d1 < d2) - { - return p1; - } - else - { - return p2; - } + cv::Point3f p1 = points_list[0]; + cv::Point3f p2 = points_list[1]; + + double d1 = std::sqrt( std::pow(p1.x-origin.x, 2) + std::pow(p1.y-origin.y, 2) + std::pow(p1.z-origin.z, 2) ); + double d2 = std::sqrt( std::pow(p2.x-origin.x, 2) + std::pow(p2.y-origin.y, 2) + std::pow(p2.z-origin.z, 2) ); + + if(d1 < d2) + { + return p1; + } + else + { + return p2; + } } // Custom constructor given the intrinsic camera parameters PnPProblem::PnPProblem(const double params[]) { - _A_matrix = cv::Mat::zeros(3, 3, CV_64FC1); // intrinsic camera parameters - _A_matrix.at(0, 0) = params[0]; // [ fx 0 cx ] - _A_matrix.at(1, 1) = params[1]; // [ 0 fy cy ] - _A_matrix.at(0, 2) = params[2]; // [ 0 0 1 ] - _A_matrix.at(1, 2) = params[3]; - _A_matrix.at(2, 2) = 1; - _R_matrix = cv::Mat::zeros(3, 3, CV_64FC1); // rotation matrix - _t_matrix = cv::Mat::zeros(3, 1, CV_64FC1); // translation matrix - _P_matrix = cv::Mat::zeros(3, 4, CV_64FC1); // rotation-translation matrix + A_matrix_ = cv::Mat::zeros(3, 3, CV_64FC1); // intrinsic camera parameters + A_matrix_.at(0, 0) = params[0]; // [ fx 0 cx ] + A_matrix_.at(1, 1) = params[1]; // [ 0 fy cy ] + A_matrix_.at(0, 2) = params[2]; // [ 0 0 1 ] + A_matrix_.at(1, 2) = params[3]; + A_matrix_.at(2, 2) = 1; + R_matrix_ = cv::Mat::zeros(3, 3, CV_64FC1); // rotation matrix + t_matrix_ = cv::Mat::zeros(3, 1, CV_64FC1); // translation matrix + P_matrix_ = cv::Mat::zeros(3, 4, CV_64FC1); // rotation-translation matrix } PnPProblem::~PnPProblem() { - // TODO Auto-generated destructor stub + // TODO Auto-generated destructor stub } void PnPProblem::set_P_matrix( const cv::Mat &R_matrix, const cv::Mat &t_matrix) { - // Rotation-Translation Matrix Definition - _P_matrix.at(0,0) = R_matrix.at(0,0); - _P_matrix.at(0,1) = R_matrix.at(0,1); - _P_matrix.at(0,2) = R_matrix.at(0,2); - _P_matrix.at(1,0) = R_matrix.at(1,0); - _P_matrix.at(1,1) = R_matrix.at(1,1); - _P_matrix.at(1,2) = R_matrix.at(1,2); - _P_matrix.at(2,0) = R_matrix.at(2,0); - _P_matrix.at(2,1) = R_matrix.at(2,1); - _P_matrix.at(2,2) = R_matrix.at(2,2); - _P_matrix.at(0,3) = t_matrix.at(0); - _P_matrix.at(1,3) = t_matrix.at(1); - _P_matrix.at(2,3) = t_matrix.at(2); + // Rotation-Translation Matrix Definition + P_matrix_.at(0,0) = R_matrix.at(0,0); + P_matrix_.at(0,1) = R_matrix.at(0,1); + P_matrix_.at(0,2) = R_matrix.at(0,2); + P_matrix_.at(1,0) = R_matrix.at(1,0); + P_matrix_.at(1,1) = R_matrix.at(1,1); + P_matrix_.at(1,2) = R_matrix.at(1,2); + P_matrix_.at(2,0) = R_matrix.at(2,0); + P_matrix_.at(2,1) = R_matrix.at(2,1); + P_matrix_.at(2,2) = R_matrix.at(2,2); + P_matrix_.at(0,3) = t_matrix.at(0); + P_matrix_.at(1,3) = t_matrix.at(1); + P_matrix_.at(2,3) = t_matrix.at(2); } - // Estimate the pose given a list of 2D/3D correspondences and the method to use bool PnPProblem::estimatePose( const std::vector &list_points3d, const std::vector &list_points2d, int flags) { - cv::Mat distCoeffs = cv::Mat::zeros(4, 1, CV_64FC1); - cv::Mat rvec = cv::Mat::zeros(3, 1, CV_64FC1); - cv::Mat tvec = cv::Mat::zeros(3, 1, CV_64FC1); + cv::Mat distCoeffs = cv::Mat::zeros(4, 1, CV_64FC1); + cv::Mat rvec = cv::Mat::zeros(3, 1, CV_64FC1); + cv::Mat tvec = cv::Mat::zeros(3, 1, CV_64FC1); - bool useExtrinsicGuess = false; + bool useExtrinsicGuess = false; - // Pose estimation - bool correspondence = cv::solvePnP( list_points3d, list_points2d, _A_matrix, distCoeffs, rvec, tvec, - useExtrinsicGuess, flags); + // Pose estimation + bool correspondence = cv::solvePnP( list_points3d, list_points2d, A_matrix_, distCoeffs, rvec, tvec, + useExtrinsicGuess, flags); - // Transforms Rotation Vector to Matrix - Rodrigues(rvec,_R_matrix); - _t_matrix = tvec; + // Transforms Rotation Vector to Matrix + Rodrigues(rvec, R_matrix_); + t_matrix_ = tvec; - // Set projection matrix - this->set_P_matrix(_R_matrix, _t_matrix); + // Set projection matrix + this->set_P_matrix(R_matrix_, t_matrix_); - return correspondence; + return correspondence; } // Estimate the pose given a list of 2D/3D correspondences with RANSAC and the method to use @@ -138,182 +128,180 @@ void PnPProblem::estimatePoseRANSAC( const std::vector &list_points int flags, cv::Mat &inliers, int iterationsCount, // PnP method; inliers container float reprojectionError, double confidence ) // Ransac parameters { - cv::Mat distCoeffs = cv::Mat::zeros(4, 1, CV_64FC1); // vector of distortion coefficients - cv::Mat rvec = cv::Mat::zeros(3, 1, CV_64FC1); // output rotation vector - cv::Mat tvec = cv::Mat::zeros(3, 1, CV_64FC1); // output translation vector + cv::Mat distCoeffs = cv::Mat::zeros(4, 1, CV_64FC1); // vector of distortion coefficients + cv::Mat rvec = cv::Mat::zeros(3, 1, CV_64FC1); // output rotation vector + cv::Mat tvec = cv::Mat::zeros(3, 1, CV_64FC1); // output translation vector - bool useExtrinsicGuess = false; // if true the function uses the provided rvec and tvec values as - // initial approximations of the rotation and translation vectors + bool useExtrinsicGuess = false; // if true the function uses the provided rvec and tvec values as + // initial approximations of the rotation and translation vectors - cv::solvePnPRansac( list_points3d, list_points2d, _A_matrix, distCoeffs, rvec, tvec, - useExtrinsicGuess, iterationsCount, reprojectionError, confidence, - inliers, flags ); + cv::solvePnPRansac( list_points3d, list_points2d, A_matrix_, distCoeffs, rvec, tvec, + useExtrinsicGuess, iterationsCount, reprojectionError, confidence, + inliers, flags ); - Rodrigues(rvec,_R_matrix); // converts Rotation Vector to Matrix - _t_matrix = tvec; // set translation matrix + Rodrigues(rvec, R_matrix_); // converts Rotation Vector to Matrix + t_matrix_ = tvec; // set translation matrix - this->set_P_matrix(_R_matrix, _t_matrix); // set rotation-translation matrix + this->set_P_matrix(R_matrix_, t_matrix_); // set rotation-translation matrix } // Given the mesh, backproject the 3D points to 2D to verify the pose estimation std::vector PnPProblem::verify_points(Mesh *mesh) { - std::vector verified_points_2d; - for( int i = 0; i < mesh->getNumVertices(); i++) - { - cv::Point3f point3d = mesh->getVertex(i); - cv::Point2f point2d = this->backproject3DPoint(point3d); - verified_points_2d.push_back(point2d); - } - - return verified_points_2d; -} + std::vector verified_points_2d; + for( int i = 0; i < mesh->getNumVertices(); i++) + { + cv::Point3f point3d = mesh->getVertex(i); + cv::Point2f point2d = this->backproject3DPoint(point3d); + verified_points_2d.push_back(point2d); + } + return verified_points_2d; +} // Backproject a 3D point to 2D using the estimated pose parameters - cv::Point2f PnPProblem::backproject3DPoint(const cv::Point3f &point3d) { - // 3D point vector [x y z 1]' - cv::Mat point3d_vec = cv::Mat(4, 1, CV_64FC1); - point3d_vec.at(0) = point3d.x; - point3d_vec.at(1) = point3d.y; - point3d_vec.at(2) = point3d.z; - point3d_vec.at(3) = 1; - - // 2D point vector [u v 1]' - cv::Mat point2d_vec = cv::Mat(4, 1, CV_64FC1); - point2d_vec = _A_matrix * _P_matrix * point3d_vec; - - // Normalization of [u v]' - cv::Point2f point2d; - point2d.x = (float)(point2d_vec.at(0) / point2d_vec.at(2)); - point2d.y = (float)(point2d_vec.at(1) / point2d_vec.at(2)); - - return point2d; + // 3D point vector [x y z 1]' + cv::Mat point3d_vec = cv::Mat(4, 1, CV_64FC1); + point3d_vec.at(0) = point3d.x; + point3d_vec.at(1) = point3d.y; + point3d_vec.at(2) = point3d.z; + point3d_vec.at(3) = 1; + + // 2D point vector [u v 1]' + cv::Mat point2d_vec = cv::Mat(4, 1, CV_64FC1); + point2d_vec = A_matrix_ * P_matrix_ * point3d_vec; + + // Normalization of [u v]' + cv::Point2f point2d; + point2d.x = (float)(point2d_vec.at(0) / point2d_vec.at(2)); + point2d.y = (float)(point2d_vec.at(1) / point2d_vec.at(2)); + + return point2d; } // Back project a 2D point to 3D and returns if it's on the object surface bool PnPProblem::backproject2DPoint(const Mesh *mesh, const cv::Point2f &point2d, cv::Point3f &point3d) { - // Triangles list of the object mesh - std::vector > triangles_list = mesh->getTrianglesList(); + // Triangles list of the object mesh + std::vector > triangles_list = mesh->getTrianglesList(); - double lambda = 8; - double u = point2d.x; - double v = point2d.y; + double lambda = 8; + double u = point2d.x; + double v = point2d.y; - // Point in vector form - cv::Mat point2d_vec = cv::Mat::ones(3, 1, CV_64F); // 3x1 - point2d_vec.at(0) = u * lambda; - point2d_vec.at(1) = v * lambda; - point2d_vec.at(2) = lambda; + // Point in vector form + cv::Mat point2d_vec = cv::Mat::ones(3, 1, CV_64F); // 3x1 + point2d_vec.at(0) = u * lambda; + point2d_vec.at(1) = v * lambda; + point2d_vec.at(2) = lambda; - // Point in camera coordinates - cv::Mat X_c = _A_matrix.inv() * point2d_vec ; // 3x1 + // Point in camera coordinates + cv::Mat X_c = A_matrix_.inv() * point2d_vec ; // 3x1 - // Point in world coordinates - cv::Mat X_w = _R_matrix.inv() * ( X_c - _t_matrix ); // 3x1 + // Point in world coordinates + cv::Mat X_w = R_matrix_.inv() * ( X_c - t_matrix_ ); // 3x1 - // Center of projection - cv::Mat C_op = cv::Mat(_R_matrix.inv()).mul(-1) * _t_matrix; // 3x1 + // Center of projection + cv::Mat C_op = cv::Mat(R_matrix_.inv()).mul(-1) * t_matrix_; // 3x1 - // Ray direction vector - cv::Mat ray = X_w - C_op; // 3x1 - ray = ray / cv::norm(ray); // 3x1 + // Ray direction vector + cv::Mat ray = X_w - C_op; // 3x1 + ray = ray / cv::norm(ray); // 3x1 - // Set up Ray - Ray R((cv::Point3f)C_op, (cv::Point3f)ray); + // Set up Ray + Ray R((cv::Point3f)C_op, (cv::Point3f)ray); - // A vector to store the intersections found - std::vector intersections_list; + // A vector to store the intersections found + std::vector intersections_list; - // Loop for all the triangles and check the intersection - for (unsigned int i = 0; i < triangles_list.size(); i++) - { - cv::Point3f V0 = mesh->getVertex(triangles_list[i][0]); - cv::Point3f V1 = mesh->getVertex(triangles_list[i][1]); - cv::Point3f V2 = mesh->getVertex(triangles_list[i][2]); - - Triangle T(i, V0, V1, V2); + // Loop for all the triangles and check the intersection + for (unsigned int i = 0; i < triangles_list.size(); i++) + { + cv::Point3f V0 = mesh->getVertex(triangles_list[i][0]); + cv::Point3f V1 = mesh->getVertex(triangles_list[i][1]); + cv::Point3f V2 = mesh->getVertex(triangles_list[i][2]); + + Triangle T(V0, V1, V2); + + double out; + if(this->intersect_MollerTrumbore(R, T, &out)) + { + cv::Point3f tmp_pt = R.getP0() + out*R.getP1(); // P = O + t*D + intersections_list.push_back(tmp_pt); + } + } - double out; - if(this->intersect_MollerTrumbore(R, T, &out)) + // If there are intersection, find the nearest one + if (!intersections_list.empty()) { - cv::Point3f tmp_pt = R.getP0() + out*R.getP1(); // P = O + t*D - intersections_list.push_back(tmp_pt); + point3d = get_nearest_3D_point(intersections_list, R.getP0()); + return true; + } + else + { + return false; } - } - - // If there are intersection, find the nearest one - if (!intersections_list.empty()) - { - point3d = get_nearest_3D_point(intersections_list, R.getP0()); - return true; - } - else - { - return false; - } } // Möller-Trumbore intersection algorithm bool PnPProblem::intersect_MollerTrumbore(Ray &Ray, Triangle &Triangle, double *out) { - const double EPSILON = 0.000001; + const double EPSILON = 0.000001; - cv::Point3f e1, e2; - cv::Point3f P, Q, T; - double det, inv_det, u, v; - double t; + cv::Point3f e1, e2; + cv::Point3f P, Q, T; + double det, inv_det, u, v; + double t; - cv::Point3f V1 = Triangle.getV0(); // Triangle vertices - cv::Point3f V2 = Triangle.getV1(); - cv::Point3f V3 = Triangle.getV2(); + cv::Point3f V1 = Triangle.getV0(); // Triangle vertices + cv::Point3f V2 = Triangle.getV1(); + cv::Point3f V3 = Triangle.getV2(); - cv::Point3f O = Ray.getP0(); // Ray origin - cv::Point3f D = Ray.getP1(); // Ray direction + cv::Point3f O = Ray.getP0(); // Ray origin + cv::Point3f D = Ray.getP1(); // Ray direction - //Find vectors for two edges sharing V1 - e1 = SUB(V2, V1); - e2 = SUB(V3, V1); + //Find vectors for two edges sharing V1 + e1 = SUB(V2, V1); + e2 = SUB(V3, V1); - // Begin calculation determinant - also used to calculate U parameter - P = CROSS(D, e2); + // Begin calculation determinant - also used to calculate U parameter + P = CROSS(D, e2); - // If determinant is near zero, ray lie in plane of triangle - det = DOT(e1, P); + // If determinant is near zero, ray lie in plane of triangle + det = DOT(e1, P); - //NOT CULLING - if(det > -EPSILON && det < EPSILON) return false; - inv_det = 1.f / det; + //NOT CULLING + if(det > -EPSILON && det < EPSILON) return false; + inv_det = 1.f / det; - //calculate distance from V1 to ray origin - T = SUB(O, V1); + //calculate distance from V1 to ray origin + T = SUB(O, V1); - //Calculate u parameter and test bound - u = DOT(T, P) * inv_det; + //Calculate u parameter and test bound + u = DOT(T, P) * inv_det; - //The intersection lies outside of the triangle - if(u < 0.f || u > 1.f) return false; + //The intersection lies outside of the triangle + if(u < 0.f || u > 1.f) return false; - //Prepare to test v parameter - Q = CROSS(T, e1); + //Prepare to test v parameter + Q = CROSS(T, e1); - //Calculate V parameter and test bound - v = DOT(D, Q) * inv_det; + //Calculate V parameter and test bound + v = DOT(D, Q) * inv_det; - //The intersection lies outside of the triangle - if(v < 0.f || u + v > 1.f) return false; + //The intersection lies outside of the triangle + if(v < 0.f || u + v > 1.f) return false; - t = DOT(e2, Q) * inv_det; + t = DOT(e2, Q) * inv_det; - if(t > EPSILON) { //ray intersection - *out = t; - return true; - } + if(t > EPSILON) { //ray intersection + *out = t; + return true; + } - // No hit, no win - return false; + // No hit, no win + return false; } diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/PnPProblem.h b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/PnPProblem.h index 63d47c4993..b0bb31f2c7 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/PnPProblem.h +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/PnPProblem.h @@ -18,41 +18,35 @@ class PnPProblem { - public: - explicit PnPProblem(const double param[]); // custom constructor - virtual ~PnPProblem(); + explicit PnPProblem(const double param[]); // custom constructor + virtual ~PnPProblem(); - bool backproject2DPoint(const Mesh *mesh, const cv::Point2f &point2d, cv::Point3f &point3d); - bool intersect_MollerTrumbore(Ray &R, Triangle &T, double *out); - std::vector verify_points(Mesh *mesh); - cv::Point2f backproject3DPoint(const cv::Point3f &point3d); - bool estimatePose(const std::vector &list_points3d, const std::vector &list_points2d, int flags); - void estimatePoseRANSAC( const std::vector &list_points3d, const std::vector &list_points2d, - int flags, cv::Mat &inliers, - int iterationsCount, float reprojectionError, double confidence ); + bool backproject2DPoint(const Mesh *mesh, const cv::Point2f &point2d, cv::Point3f &point3d); + bool intersect_MollerTrumbore(Ray &R, Triangle &T, double *out); + std::vector verify_points(Mesh *mesh); + cv::Point2f backproject3DPoint(const cv::Point3f &point3d); + bool estimatePose(const std::vector &list_points3d, const std::vector &list_points2d, int flags); + void estimatePoseRANSAC( const std::vector &list_points3d, const std::vector &list_points2d, + int flags, cv::Mat &inliers, + int iterationsCount, float reprojectionError, double confidence ); - cv::Mat get_A_matrix() const { return _A_matrix; } - cv::Mat get_R_matrix() const { return _R_matrix; } - cv::Mat get_t_matrix() const { return _t_matrix; } - cv::Mat get_P_matrix() const { return _P_matrix; } + cv::Mat get_A_matrix() const { return A_matrix_; } + cv::Mat get_R_matrix() const { return R_matrix_; } + cv::Mat get_t_matrix() const { return t_matrix_; } + cv::Mat get_P_matrix() const { return P_matrix_; } - void set_P_matrix( const cv::Mat &R_matrix, const cv::Mat &t_matrix); + void set_P_matrix( const cv::Mat &R_matrix, const cv::Mat &t_matrix); private: - /** The calibration matrix */ - cv::Mat _A_matrix; - /** The computed rotation matrix */ - cv::Mat _R_matrix; - /** The computed translation matrix */ - cv::Mat _t_matrix; - /** The computed projection matrix */ - cv::Mat _P_matrix; + /** The calibration matrix */ + cv::Mat A_matrix_; + /** The computed rotation matrix */ + cv::Mat R_matrix_; + /** The computed translation matrix */ + cv::Mat t_matrix_; + /** The computed projection matrix */ + cv::Mat P_matrix_; }; -// Functions for Möller-Trumbore intersection algorithm -cv::Point3f CROSS(cv::Point3f v1, cv::Point3f v2); -double DOT(cv::Point3f v1, cv::Point3f v2); -cv::Point3f SUB(cv::Point3f v1, cv::Point3f v2); - #endif /* PNPPROBLEM_H_ */ diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/RobustMatcher.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/RobustMatcher.cpp index 862bdd18b2..2cded40667 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/RobustMatcher.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/RobustMatcher.cpp @@ -12,141 +12,143 @@ RobustMatcher::~RobustMatcher() { - // TODO Auto-generated destructor stub + // TODO Auto-generated destructor stub } void RobustMatcher::computeKeyPoints( const cv::Mat& image, std::vector& keypoints) { - detector_->detect(image, keypoints); + detector_->detect(image, keypoints); } void RobustMatcher::computeDescriptors( const cv::Mat& image, std::vector& keypoints, cv::Mat& descriptors) { - extractor_->compute(image, keypoints, descriptors); + extractor_->compute(image, keypoints, descriptors); } int RobustMatcher::ratioTest(std::vector > &matches) { - int removed = 0; - // for all matches - for ( std::vector >::iterator - matchIterator= matches.begin(); matchIterator!= matches.end(); ++matchIterator) - { - // if 2 NN has been identified - if (matchIterator->size() > 1) + int removed = 0; + // for all matches + for ( std::vector >::iterator + matchIterator= matches.begin(); matchIterator!= matches.end(); ++matchIterator) { - // check distance ratio - if ((*matchIterator)[0].distance / (*matchIterator)[1].distance > ratio_) - { - matchIterator->clear(); // remove match - removed++; - } - } - else - { // does not have 2 neighbours - matchIterator->clear(); // remove match - removed++; + // if 2 NN has been identified + if (matchIterator->size() > 1) + { + // check distance ratio + if ((*matchIterator)[0].distance / (*matchIterator)[1].distance > ratio_) + { + matchIterator->clear(); // remove match + removed++; + } + } + else + { // does not have 2 neighbours + matchIterator->clear(); // remove match + removed++; + } } - } - return removed; + return removed; } void RobustMatcher::symmetryTest( const std::vector >& matches1, - const std::vector >& matches2, - std::vector& symMatches ) + const std::vector >& matches2, + std::vector& symMatches ) { - - // for all matches image 1 -> image 2 - for (std::vector >::const_iterator - matchIterator1 = matches1.begin(); matchIterator1 != matches1.end(); ++matchIterator1) - { - - // ignore deleted matches - if (matchIterator1->empty() || matchIterator1->size() < 2) - continue; - - // for all matches image 2 -> image 1 - for (std::vector >::const_iterator - matchIterator2 = matches2.begin(); matchIterator2 != matches2.end(); ++matchIterator2) - { + // for all matches image 1 -> image 2 + for (std::vector >::const_iterator + matchIterator1 = matches1.begin(); matchIterator1 != matches1.end(); ++matchIterator1) + { // ignore deleted matches - if (matchIterator2->empty() || matchIterator2->size() < 2) - continue; - - // Match symmetry test - if ((*matchIterator1)[0].queryIdx == - (*matchIterator2)[0].trainIdx && - (*matchIterator2)[0].queryIdx == - (*matchIterator1)[0].trainIdx) + if (matchIterator1->empty() || matchIterator1->size() < 2) + continue; + + // for all matches image 2 -> image 1 + for (std::vector >::const_iterator + matchIterator2 = matches2.begin(); matchIterator2 != matches2.end(); ++matchIterator2) { - // add symmetrical match - symMatches.push_back( - cv::DMatch((*matchIterator1)[0].queryIdx, - (*matchIterator1)[0].trainIdx, - (*matchIterator1)[0].distance)); - break; // next match in image 1 -> image 2 + // ignore deleted matches + if (matchIterator2->empty() || matchIterator2->size() < 2) + continue; + + // Match symmetry test + if ((*matchIterator1)[0].queryIdx == (*matchIterator2)[0].trainIdx && + (*matchIterator2)[0].queryIdx == (*matchIterator1)[0].trainIdx) + { + // add symmetrical match + symMatches.push_back(cv::DMatch((*matchIterator1)[0].queryIdx, + (*matchIterator1)[0].trainIdx, (*matchIterator1)[0].distance)); + break; // next match in image 1 -> image 2 + } } - } - } - + } } void RobustMatcher::robustMatch( const cv::Mat& frame, std::vector& good_matches, - std::vector& keypoints_frame, const cv::Mat& descriptors_model ) + std::vector& keypoints_frame, const cv::Mat& descriptors_model, + const std::vector& keypoints_model) { + // 1a. Detection of the ORB features + this->computeKeyPoints(frame, keypoints_frame); - // 1a. Detection of the ORB features - this->computeKeyPoints(frame, keypoints_frame); - - // 1b. Extraction of the ORB descriptors - cv::Mat descriptors_frame; - this->computeDescriptors(frame, keypoints_frame, descriptors_frame); + // 1b. Extraction of the ORB descriptors + cv::Mat descriptors_frame; + this->computeDescriptors(frame, keypoints_frame, descriptors_frame); - // 2. Match the two image descriptors - std::vector > matches12, matches21; + // 2. Match the two image descriptors + std::vector > matches12, matches21; - // 2a. From image 1 to image 2 - matcher_->knnMatch(descriptors_frame, descriptors_model, matches12, 2); // return 2 nearest neighbours + // 2a. From image 1 to image 2 + matcher_->knnMatch(descriptors_frame, descriptors_model, matches12, 2); // return 2 nearest neighbours - // 2b. From image 2 to image 1 - matcher_->knnMatch(descriptors_model, descriptors_frame, matches21, 2); // return 2 nearest neighbours + // 2b. From image 2 to image 1 + matcher_->knnMatch(descriptors_model, descriptors_frame, matches21, 2); // return 2 nearest neighbours - // 3. Remove matches for which NN ratio is > than threshold - // clean image 1 -> image 2 matches - ratioTest(matches12); - // clean image 2 -> image 1 matches - ratioTest(matches21); + // 3. Remove matches for which NN ratio is > than threshold + // clean image 1 -> image 2 matches + ratioTest(matches12); + // clean image 2 -> image 1 matches + ratioTest(matches21); - // 4. Remove non-symmetrical matches - symmetryTest(matches12, matches21, good_matches); + // 4. Remove non-symmetrical matches + symmetryTest(matches12, matches21, good_matches); + if (!training_img_.empty() && !keypoints_model.empty()) + { + cv::drawMatches(frame, keypoints_frame, training_img_, keypoints_model, good_matches, img_matching_); + } } void RobustMatcher::fastRobustMatch( const cv::Mat& frame, std::vector& good_matches, - std::vector& keypoints_frame, - const cv::Mat& descriptors_model ) + std::vector& keypoints_frame, + const cv::Mat& descriptors_model, + const std::vector& keypoints_model) { - good_matches.clear(); + good_matches.clear(); - // 1a. Detection of the ORB features - this->computeKeyPoints(frame, keypoints_frame); + // 1a. Detection of the ORB features + this->computeKeyPoints(frame, keypoints_frame); - // 1b. Extraction of the ORB descriptors - cv::Mat descriptors_frame; - this->computeDescriptors(frame, keypoints_frame, descriptors_frame); + // 1b. Extraction of the ORB descriptors + cv::Mat descriptors_frame; + this->computeDescriptors(frame, keypoints_frame, descriptors_frame); - // 2. Match the two image descriptors - std::vector > matches; - matcher_->knnMatch(descriptors_frame, descriptors_model, matches, 2); + // 2. Match the two image descriptors + std::vector > matches; + matcher_->knnMatch(descriptors_frame, descriptors_model, matches, 2); - // 3. Remove matches for which NN ratio is > than threshold - ratioTest(matches); + // 3. Remove matches for which NN ratio is > than threshold + ratioTest(matches); - // 4. Fill good matches container - for ( std::vector >::iterator - matchIterator= matches.begin(); matchIterator!= matches.end(); ++matchIterator) - { - if (!matchIterator->empty()) good_matches.push_back((*matchIterator)[0]); - } + // 4. Fill good matches container + for ( std::vector >::iterator + matchIterator= matches.begin(); matchIterator!= matches.end(); ++matchIterator) + { + if (!matchIterator->empty()) good_matches.push_back((*matchIterator)[0]); + } + if (!training_img_.empty() && !keypoints_model.empty()) + { + cv::drawMatches(frame, keypoints_frame, training_img_, keypoints_model, good_matches, img_matching_); + } } diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/RobustMatcher.h b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/RobustMatcher.h index 82aab2008e..152dd7cdc9 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/RobustMatcher.h +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/RobustMatcher.h @@ -16,66 +16,77 @@ class RobustMatcher { public: - RobustMatcher() : ratio_(0.8f) - { - // ORB is the default feature - detector_ = cv::ORB::create(); - extractor_ = cv::ORB::create(); + RobustMatcher() : detector_(), extractor_(), matcher_(), + ratio_(0.8f), training_img_(), img_matching_() + { + // ORB is the default feature + detector_ = cv::ORB::create(); + extractor_ = cv::ORB::create(); - // BruteFroce matcher with Norm Hamming is the default matcher - matcher_ = cv::makePtr((int)cv::NORM_HAMMING, false); + // BruteFroce matcher with Norm Hamming is the default matcher + matcher_ = cv::makePtr((int)cv::NORM_HAMMING, false); - } - virtual ~RobustMatcher(); + } + virtual ~RobustMatcher(); - // Set the feature detector - void setFeatureDetector(const cv::Ptr& detect) { detector_ = detect; } + // Set the feature detector + void setFeatureDetector(const cv::Ptr& detect) { detector_ = detect; } - // Set the descriptor extractor - void setDescriptorExtractor(const cv::Ptr& desc) { extractor_ = desc; } + // Set the descriptor extractor + void setDescriptorExtractor(const cv::Ptr& desc) { extractor_ = desc; } - // Set the matcher - void setDescriptorMatcher(const cv::Ptr& match) { matcher_ = match; } + // Set the matcher + void setDescriptorMatcher(const cv::Ptr& match) { matcher_ = match; } - // Compute the keypoints of an image - void computeKeyPoints( const cv::Mat& image, std::vector& keypoints); + // Compute the keypoints of an image + void computeKeyPoints( const cv::Mat& image, std::vector& keypoints); - // Compute the descriptors of an image given its keypoints - void computeDescriptors( const cv::Mat& image, std::vector& keypoints, cv::Mat& descriptors); + // Compute the descriptors of an image given its keypoints + void computeDescriptors( const cv::Mat& image, std::vector& keypoints, cv::Mat& descriptors); - // Set ratio parameter for the ratio test - void setRatio( float rat) { ratio_ = rat; } + cv::Mat getImageMatching() const { return img_matching_; } - // Clear matches for which NN ratio is > than threshold - // return the number of removed points - // (corresponding entries being cleared, - // i.e. size will be 0) - int ratioTest(std::vector > &matches); + // Set ratio parameter for the ratio test + void setRatio( float rat) { ratio_ = rat; } - // Insert symmetrical matches in symMatches vector - void symmetryTest( const std::vector >& matches1, - const std::vector >& matches2, - std::vector& symMatches ); + void setTrainingImage(const cv::Mat &img) { training_img_ = img; } - // Match feature points using ratio and symmetry test - void robustMatch( const cv::Mat& frame, std::vector& good_matches, + // Clear matches for which NN ratio is > than threshold + // return the number of removed points + // (corresponding entries being cleared, + // i.e. size will be 0) + int ratioTest(std::vector > &matches); + + // Insert symmetrical matches in symMatches vector + void symmetryTest( const std::vector >& matches1, + const std::vector >& matches2, + std::vector& symMatches ); + + // Match feature points using ratio and symmetry test + void robustMatch( const cv::Mat& frame, std::vector& good_matches, std::vector& keypoints_frame, - const cv::Mat& descriptors_model ); + const cv::Mat& descriptors_model, + const std::vector& keypoints_model); - // Match feature points using ratio test - void fastRobustMatch( const cv::Mat& frame, std::vector& good_matches, - std::vector& keypoints_frame, - const cv::Mat& descriptors_model ); + // Match feature points using ratio test + void fastRobustMatch( const cv::Mat& frame, std::vector& good_matches, + std::vector& keypoints_frame, + const cv::Mat& descriptors_model, + const std::vector& keypoints_model); private: - // pointer to the feature point detector object - cv::Ptr detector_; - // pointer to the feature descriptor extractor object - cv::Ptr extractor_; - // pointer to the matcher object - cv::Ptr matcher_; - // max ratio between 1st and 2nd NN - float ratio_; + // pointer to the feature point detector object + cv::Ptr detector_; + // pointer to the feature descriptor extractor object + cv::Ptr extractor_; + // pointer to the matcher object + cv::Ptr matcher_; + // max ratio between 1st and 2nd NN + float ratio_; + // training image + cv::Mat training_img_; + // matching image + cv::Mat img_matching_; }; #endif /* ROBUSTMATCHER_H_ */ diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.cpp index 1945a2eb8b..23ea221eb4 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.cpp @@ -11,178 +11,180 @@ #include "ModelRegistration.h" #include "Utils.h" +#include #include #include +#include +#if defined (HAVE_OPENCV_XFEATURES2D) +#include +#endif // For text -int fontFace = cv::FONT_ITALIC; -double fontScale = 0.75; -int thickness_font = 2; +const int fontFace = cv::FONT_ITALIC; +const double fontScale = 0.75; +const int thickness_font = 2; // For circles -int lineType = 8; -int radius = 4; -double thickness_circ = -1; +const int lineType = 8; +const int radius = 4; // Draw a text with the question point void drawQuestion(cv::Mat image, cv::Point3f point, cv::Scalar color) { - std::string x = IntToString((int)point.x); - std::string y = IntToString((int)point.y); - std::string z = IntToString((int)point.z); + std::string x = IntToString((int)point.x); + std::string y = IntToString((int)point.y); + std::string z = IntToString((int)point.z); - std::string text = " Where is point (" + x + "," + y + "," + z + ") ?"; - cv::putText(image, text, cv::Point(25,50), fontFace, fontScale, color, thickness_font, 8); + std::string text = " Where is point (" + x + "," + y + "," + z + ") ?"; + cv::putText(image, text, cv::Point(25,50), fontFace, fontScale, color, thickness_font, 8); } // Draw a text with the number of entered points void drawText(cv::Mat image, std::string text, cv::Scalar color) { - cv::putText(image, text, cv::Point(25,50), fontFace, fontScale, color, thickness_font, 8); + cv::putText(image, text, cv::Point(25,50), fontFace, fontScale, color, thickness_font, 8); } // Draw a text with the number of entered points void drawText2(cv::Mat image, std::string text, cv::Scalar color) { - cv::putText(image, text, cv::Point(25,75), fontFace, fontScale, color, thickness_font, 8); + cv::putText(image, text, cv::Point(25,75), fontFace, fontScale, color, thickness_font, 8); } // Draw a text with the frame ratio void drawFPS(cv::Mat image, double fps, cv::Scalar color) { - std::string fps_str = IntToString((int)fps); - std::string text = fps_str + " FPS"; - cv::putText(image, text, cv::Point(500,50), fontFace, fontScale, color, thickness_font, 8); + std::string fps_str = cv::format("%.2f FPS", fps); + cv::putText(image, fps_str, cv::Point(500,50), fontFace, fontScale, color, thickness_font, 8); } // Draw a text with the frame ratio void drawConfidence(cv::Mat image, double confidence, cv::Scalar color) { - std::string conf_str = IntToString((int)confidence); - std::string text = conf_str + " %"; - cv::putText(image, text, cv::Point(500,75), fontFace, fontScale, color, thickness_font, 8); + std::string conf_str = IntToString((int)confidence); + std::string text = conf_str + " %"; + cv::putText(image, text, cv::Point(500,75), fontFace, fontScale, color, thickness_font, 8); } // Draw a text with the number of entered points void drawCounter(cv::Mat image, int n, int n_max, cv::Scalar color) { - std::string n_str = IntToString(n); - std::string n_max_str = IntToString(n_max); - std::string text = n_str + " of " + n_max_str + " points"; - cv::putText(image, text, cv::Point(500,50), fontFace, fontScale, color, thickness_font, 8); + std::string n_str = IntToString(n); + std::string n_max_str = IntToString(n_max); + std::string text = n_str + " of " + n_max_str + " points"; + cv::putText(image, text, cv::Point(500,50), fontFace, fontScale, color, thickness_font, 8); } // Draw the points and the coordinates void drawPoints(cv::Mat image, std::vector &list_points_2d, std::vector &list_points_3d, cv::Scalar color) { - for (unsigned int i = 0; i < list_points_2d.size(); ++i) - { - cv::Point2f point_2d = list_points_2d[i]; - cv::Point3f point_3d = list_points_3d[i]; - - // Draw Selected points - cv::circle(image, point_2d, radius, color, -1, lineType ); - - std::string idx = IntToString(i+1); - std::string x = IntToString((int)point_3d.x); - std::string y = IntToString((int)point_3d.y); - std::string z = IntToString((int)point_3d.z); - std::string text = "P" + idx + " (" + x + "," + y + "," + z +")"; - - point_2d.x = point_2d.x + 10; - point_2d.y = point_2d.y - 10; - cv::putText(image, text, point_2d, fontFace, fontScale*0.5, color, thickness_font, 8); - } + for (unsigned int i = 0; i < list_points_2d.size(); ++i) + { + cv::Point2f point_2d = list_points_2d[i]; + cv::Point3f point_3d = list_points_3d[i]; + + // Draw Selected points + cv::circle(image, point_2d, radius, color, -1, lineType ); + + std::string idx = IntToString(i+1); + std::string x = IntToString((int)point_3d.x); + std::string y = IntToString((int)point_3d.y); + std::string z = IntToString((int)point_3d.z); + std::string text = "P" + idx + " (" + x + "," + y + "," + z +")"; + + point_2d.x = point_2d.x + 10; + point_2d.y = point_2d.y - 10; + cv::putText(image, text, point_2d, fontFace, fontScale*0.5, color, thickness_font, 8); + } } // Draw only the 2D points void draw2DPoints(cv::Mat image, std::vector &list_points, cv::Scalar color) { - for( size_t i = 0; i < list_points.size(); i++) - { - cv::Point2f point_2d = list_points[i]; + for( size_t i = 0; i < list_points.size(); i++) + { + cv::Point2f point_2d = list_points[i]; - // Draw Selected points - cv::circle(image, point_2d, radius, color, -1, lineType ); - } + // Draw Selected points + cv::circle(image, point_2d, radius, color, -1, lineType ); + } } // Draw an arrow into the image void drawArrow(cv::Mat image, cv::Point2i p, cv::Point2i q, cv::Scalar color, int arrowMagnitude, int thickness, int line_type, int shift) { - //Draw the principle line - cv::line(image, p, q, color, thickness, line_type, shift); - const double PI = CV_PI; - //compute the angle alpha - double angle = atan2((double)p.y-q.y, (double)p.x-q.x); - //compute the coordinates of the first segment - p.x = (int) ( q.x + arrowMagnitude * cos(angle + PI/4)); - p.y = (int) ( q.y + arrowMagnitude * sin(angle + PI/4)); - //Draw the first segment - cv::line(image, p, q, color, thickness, line_type, shift); - //compute the coordinates of the second segment - p.x = (int) ( q.x + arrowMagnitude * cos(angle - PI/4)); - p.y = (int) ( q.y + arrowMagnitude * sin(angle - PI/4)); - //Draw the second segment - cv::line(image, p, q, color, thickness, line_type, shift); + //Draw the principle line + cv::line(image, p, q, color, thickness, line_type, shift); + const double PI = CV_PI; + //compute the angle alpha + double angle = atan2((double)p.y-q.y, (double)p.x-q.x); + //compute the coordinates of the first segment + p.x = (int) ( q.x + arrowMagnitude * cos(angle + PI/4)); + p.y = (int) ( q.y + arrowMagnitude * sin(angle + PI/4)); + //Draw the first segment + cv::line(image, p, q, color, thickness, line_type, shift); + //compute the coordinates of the second segment + p.x = (int) ( q.x + arrowMagnitude * cos(angle - PI/4)); + p.y = (int) ( q.y + arrowMagnitude * sin(angle - PI/4)); + //Draw the second segment + cv::line(image, p, q, color, thickness, line_type, shift); } // Draw the 3D coordinate axes void draw3DCoordinateAxes(cv::Mat image, const std::vector &list_points2d) { - cv::Scalar red(0, 0, 255); - cv::Scalar green(0,255,0); - cv::Scalar blue(255,0,0); - cv::Scalar black(0,0,0); - - cv::Point2i origin = list_points2d[0]; - cv::Point2i pointX = list_points2d[1]; - cv::Point2i pointY = list_points2d[2]; - cv::Point2i pointZ = list_points2d[3]; - - drawArrow(image, origin, pointX, red, 9, 2); - drawArrow(image, origin, pointY, blue, 9, 2); - drawArrow(image, origin, pointZ, green, 9, 2); - cv::circle(image, origin, radius/2, black, -1, lineType ); - + cv::Scalar red(0, 0, 255); + cv::Scalar green(0,255,0); + cv::Scalar blue(255,0,0); + cv::Scalar black(0,0,0); + + cv::Point2i origin = list_points2d[0]; + cv::Point2i pointX = list_points2d[1]; + cv::Point2i pointY = list_points2d[2]; + cv::Point2i pointZ = list_points2d[3]; + + drawArrow(image, origin, pointX, red, 9, 2); + drawArrow(image, origin, pointY, green, 9, 2); + drawArrow(image, origin, pointZ, blue, 9, 2); + cv::circle(image, origin, radius/2, black, -1, lineType ); } // Draw the object mesh void drawObjectMesh(cv::Mat image, const Mesh *mesh, PnPProblem *pnpProblem, cv::Scalar color) { - std::vector > list_triangles = mesh->getTrianglesList(); - for( size_t i = 0; i < list_triangles.size(); i++) - { - std::vector tmp_triangle = list_triangles.at(i); - - cv::Point3f point_3d_0 = mesh->getVertex(tmp_triangle[0]); - cv::Point3f point_3d_1 = mesh->getVertex(tmp_triangle[1]); - cv::Point3f point_3d_2 = mesh->getVertex(tmp_triangle[2]); - - cv::Point2f point_2d_0 = pnpProblem->backproject3DPoint(point_3d_0); - cv::Point2f point_2d_1 = pnpProblem->backproject3DPoint(point_3d_1); - cv::Point2f point_2d_2 = pnpProblem->backproject3DPoint(point_3d_2); - - cv::line(image, point_2d_0, point_2d_1, color, 1); - cv::line(image, point_2d_1, point_2d_2, color, 1); - cv::line(image, point_2d_2, point_2d_0, color, 1); - } + std::vector > list_triangles = mesh->getTrianglesList(); + for( size_t i = 0; i < list_triangles.size(); i++) + { + std::vector tmp_triangle = list_triangles.at(i); + + cv::Point3f point_3d_0 = mesh->getVertex(tmp_triangle[0]); + cv::Point3f point_3d_1 = mesh->getVertex(tmp_triangle[1]); + cv::Point3f point_3d_2 = mesh->getVertex(tmp_triangle[2]); + + cv::Point2f point_2d_0 = pnpProblem->backproject3DPoint(point_3d_0); + cv::Point2f point_2d_1 = pnpProblem->backproject3DPoint(point_3d_1); + cv::Point2f point_2d_2 = pnpProblem->backproject3DPoint(point_3d_2); + + cv::line(image, point_2d_0, point_2d_1, color, 1); + cv::line(image, point_2d_1, point_2d_2, color, 1); + cv::line(image, point_2d_2, point_2d_0, color, 1); + } } // Computes the norm of the translation error double get_translation_error(const cv::Mat &t_true, const cv::Mat &t) { - return cv::norm( t_true - t ); + return cv::norm( t_true - t ); } // Computes the norm of the rotation error double get_rotation_error(const cv::Mat &R_true, const cv::Mat &R) { - cv::Mat error_vec, error_mat; - error_mat = -R_true * R.t(); - cv::Rodrigues(error_mat, error_vec); + cv::Mat error_vec, error_mat; + error_mat = -R_true * R.t(); + cv::Rodrigues(error_mat, error_vec); - return cv::norm(error_vec); + return cv::norm(error_vec); } // Converts a given Rotation Matrix to Euler angles @@ -191,41 +193,41 @@ double get_rotation_error(const cv::Mat &R_true, const cv::Mat &R) // https://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToEuler/index.htm cv::Mat rot2euler(const cv::Mat & rotationMatrix) { - cv::Mat euler(3,1,CV_64F); - - double m00 = rotationMatrix.at(0,0); - double m02 = rotationMatrix.at(0,2); - double m10 = rotationMatrix.at(1,0); - double m11 = rotationMatrix.at(1,1); - double m12 = rotationMatrix.at(1,2); - double m20 = rotationMatrix.at(2,0); - double m22 = rotationMatrix.at(2,2); - - double bank, attitude, heading; - - // Assuming the angles are in radians. - if (m10 > 0.998) { // singularity at north pole - bank = 0; - attitude = CV_PI/2; - heading = atan2(m02,m22); - } - else if (m10 < -0.998) { // singularity at south pole - bank = 0; - attitude = -CV_PI/2; - heading = atan2(m02,m22); - } - else - { - bank = atan2(-m12,m11); - attitude = asin(m10); - heading = atan2(-m20,m00); - } - - euler.at(0) = bank; - euler.at(1) = attitude; - euler.at(2) = heading; - - return euler; + cv::Mat euler(3,1,CV_64F); + + double m00 = rotationMatrix.at(0,0); + double m02 = rotationMatrix.at(0,2); + double m10 = rotationMatrix.at(1,0); + double m11 = rotationMatrix.at(1,1); + double m12 = rotationMatrix.at(1,2); + double m20 = rotationMatrix.at(2,0); + double m22 = rotationMatrix.at(2,2); + + double bank, attitude, heading; + + // Assuming the angles are in radians. + if (m10 > 0.998) { // singularity at north pole + bank = 0; + attitude = CV_PI/2; + heading = atan2(m02,m22); + } + else if (m10 < -0.998) { // singularity at south pole + bank = 0; + attitude = -CV_PI/2; + heading = atan2(m02,m22); + } + else + { + bank = atan2(-m12,m11); + attitude = asin(m10); + heading = atan2(-m20,m00); + } + + euler.at(0) = bank; + euler.at(1) = attitude; + euler.at(2) = heading; + + return euler; } // Converts a given Euler angles to Rotation Matrix @@ -234,65 +236,166 @@ cv::Mat rot2euler(const cv::Mat & rotationMatrix) // https://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm cv::Mat euler2rot(const cv::Mat & euler) { - cv::Mat rotationMatrix(3,3,CV_64F); - - double bank = euler.at(0); - double attitude = euler.at(1); - double heading = euler.at(2); - - // Assuming the angles are in radians. - double ch = cos(heading); - double sh = sin(heading); - double ca = cos(attitude); - double sa = sin(attitude); - double cb = cos(bank); - double sb = sin(bank); - - double m00, m01, m02, m10, m11, m12, m20, m21, m22; - - m00 = ch * ca; - m01 = sh*sb - ch*sa*cb; - m02 = ch*sa*sb + sh*cb; - m10 = sa; - m11 = ca*cb; - m12 = -ca*sb; - m20 = -sh*ca; - m21 = sh*sa*cb + ch*sb; - m22 = -sh*sa*sb + ch*cb; - - rotationMatrix.at(0,0) = m00; - rotationMatrix.at(0,1) = m01; - rotationMatrix.at(0,2) = m02; - rotationMatrix.at(1,0) = m10; - rotationMatrix.at(1,1) = m11; - rotationMatrix.at(1,2) = m12; - rotationMatrix.at(2,0) = m20; - rotationMatrix.at(2,1) = m21; - rotationMatrix.at(2,2) = m22; - - return rotationMatrix; + cv::Mat rotationMatrix(3,3,CV_64F); + + double bank = euler.at(0); + double attitude = euler.at(1); + double heading = euler.at(2); + + // Assuming the angles are in radians. + double ch = cos(heading); + double sh = sin(heading); + double ca = cos(attitude); + double sa = sin(attitude); + double cb = cos(bank); + double sb = sin(bank); + + double m00, m01, m02, m10, m11, m12, m20, m21, m22; + + m00 = ch * ca; + m01 = sh*sb - ch*sa*cb; + m02 = ch*sa*sb + sh*cb; + m10 = sa; + m11 = ca*cb; + m12 = -ca*sb; + m20 = -sh*ca; + m21 = sh*sa*cb + ch*sb; + m22 = -sh*sa*sb + ch*cb; + + rotationMatrix.at(0,0) = m00; + rotationMatrix.at(0,1) = m01; + rotationMatrix.at(0,2) = m02; + rotationMatrix.at(1,0) = m10; + rotationMatrix.at(1,1) = m11; + rotationMatrix.at(1,2) = m12; + rotationMatrix.at(2,0) = m20; + rotationMatrix.at(2,1) = m21; + rotationMatrix.at(2,2) = m22; + + return rotationMatrix; } // Converts a given string to an integer int StringToInt ( const std::string &Text ) { - std::istringstream ss(Text); - int result; - return ss >> result ? result : 0; + std::istringstream ss(Text); + int result; + return ss >> result ? result : 0; } // Converts a given float to a string std::string FloatToString ( float Number ) { - std::ostringstream ss; - ss << Number; - return ss.str(); + std::ostringstream ss; + ss << Number; + return ss.str(); } // Converts a given integer to a string std::string IntToString ( int Number ) { - std::ostringstream ss; - ss << Number; - return ss.str(); + std::ostringstream ss; + ss << Number; + return ss.str(); +} + +void createFeatures(const std::string &featureName, int numKeypoints, cv::Ptr &detector, cv::Ptr &descriptor) +{ + if (featureName == "ORB") + { + detector = cv::ORB::create(numKeypoints); + descriptor = cv::ORB::create(numKeypoints); + } + else if (featureName == "KAZE") + { + detector = cv::KAZE::create(); + descriptor = cv::KAZE::create(); + } + else if (featureName == "AKAZE") + { + detector = cv::AKAZE::create(); + descriptor = cv::AKAZE::create(); + } + else if (featureName == "BRISK") + { + detector = cv::BRISK::create(); + descriptor = cv::BRISK::create(); + } + else if (featureName == "SIFT") + { +#if defined (OPENCV_ENABLE_NONFREE) && defined (HAVE_OPENCV_XFEATURES2D) + detector = cv::xfeatures2d::SIFT::create(); + descriptor = cv::xfeatures2d::SIFT::create(); +#else + std::cout << "xfeatures2d module is not available or nonfree is not enabled." << std::endl; + std::cout << "Default to ORB." << std::endl; + detector = cv::ORB::create(numKeypoints); + descriptor = cv::ORB::create(numKeypoints); +#endif + } + else if (featureName == "SURF") + { +#if defined (OPENCV_ENABLE_NONFREE) && defined (HAVE_OPENCV_XFEATURES2D) + detector = cv::xfeatures2d::SURF::create(100, 4, 3, true); //extended=true + descriptor = cv::xfeatures2d::SURF::create(100, 4, 3, true); //extended=true +#else + std::cout << "xfeatures2d module is not available or nonfree is not enabled." << std::endl; + std::cout << "Default to ORB." << std::endl; + detector = cv::ORB::create(numKeypoints); + descriptor = cv::ORB::create(numKeypoints); +#endif + } + else if (featureName == "BINBOOST") + { +#if defined (HAVE_OPENCV_XFEATURES2D) + detector = cv::KAZE::create(); + descriptor = cv::xfeatures2d::BoostDesc::create(); +#else + std::cout << "xfeatures2d module is not available." << std::endl; + std::cout << "Default to ORB." << std::endl; + detector = cv::ORB::create(numKeypoints); + descriptor = cv::ORB::create(numKeypoints); +#endif + } + else if (featureName == "VGG") + { +#if defined (HAVE_OPENCV_XFEATURES2D) + detector = cv::KAZE::create(); + descriptor = cv::xfeatures2d::VGG::create(); +#else + std::cout << "xfeatures2d module is not available." << std::endl; + std::cout << "Default to ORB." << std::endl; + detector = cv::ORB::create(numKeypoints); + descriptor = cv::ORB::create(numKeypoints); +#endif + } +} + +cv::Ptr createMatcher(const std::string &featureName, bool useFLANN) +{ + if (featureName == "ORB" || featureName == "BRISK" || featureName == "AKAZE" || featureName == "BINBOOST") + { + if (useFLANN) + { + cv::Ptr indexParams = cv::makePtr(6, 12, 1); // instantiate LSH index parameters + cv::Ptr searchParams = cv::makePtr(50); // instantiate flann search parameters + return cv::makePtr(indexParams, searchParams); + } + else + { + return cv::DescriptorMatcher::create("BruteForce-Hamming"); + } + + } + else + { + if (useFLANN) + { + return cv::DescriptorMatcher::create("FlannBased"); + } + else + { + return cv::DescriptorMatcher::create("BruteForce"); + } + } } diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.h b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.h index 8a3763a569..18a5985548 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.h +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.h @@ -10,6 +10,7 @@ #include +#include #include "PnPProblem.h" // Draw a text with the question point @@ -66,4 +67,8 @@ std::string FloatToString ( float Number ); // Converts a given integer to a string std::string IntToString ( int Number ); +void createFeatures(const std::string &featureName, int numKeypoints, cv::Ptr &detector, cv::Ptr &descriptor); + +cv::Ptr createMatcher(const std::string &featureName, bool useFLANN); + #endif /* UTILS_H_ */ diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_detection.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_detection.cpp index 7d6ab999fe..8313d56c76 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_detection.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_detection.cpp @@ -1,9 +1,8 @@ // C++ #include -#include // OpenCV #include -#include +#include #include #include #include @@ -21,451 +20,482 @@ using namespace cv; using namespace std; -string tutorial_path = "../../samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/"; // path to tutorial - -string video_read_path = tutorial_path + "Data/box.mp4"; // recorded video -string yml_read_path = tutorial_path + "Data/cookies_ORB.yml"; // 3dpts + descriptors -string ply_read_path = tutorial_path + "Data/box.ply"; // mesh - -// Intrinsic camera parameters: UVC WEBCAM -double f = 55; // focal length in mm -double sx = 22.3, sy = 14.9; // sensor size -double width = 640, height = 480; // image size - -double params_WEBCAM[] = { width*f/sx, // fx - height*f/sy, // fy - width/2, // cx - height/2}; // cy - -// Some basic colors -Scalar red(0, 0, 255); -Scalar green(0,255,0); -Scalar blue(255,0,0); -Scalar yellow(0,255,255); - - -// Robust Matcher parameters -int numKeyPoints = 2000; // number of detected keypoints -float ratioTest = 0.70f; // ratio test -bool fast_match = true; // fastRobustMatch() or robustMatch() - -// RANSAC parameters -int iterationsCount = 500; // number of Ransac iterations. -float reprojectionError = 2.0; // maximum allowed distance to consider it an inlier. -double confidence = 0.95; // ransac successful confidence. - -// Kalman Filter parameters -int minInliersKalman = 30; // Kalman threshold updating - -// PnP parameters -int pnpMethod = SOLVEPNP_ITERATIVE; - - /** Functions headers **/ void help(); void initKalmanFilter( KalmanFilter &KF, int nStates, int nMeasurements, int nInputs, double dt); +void predictKalmanFilter( KalmanFilter &KF, Mat &translation_predicted, Mat &rotation_predicted ); void updateKalmanFilter( KalmanFilter &KF, Mat &measurements, Mat &translation_estimated, Mat &rotation_estimated ); void fillMeasurements( Mat &measurements, const Mat &translation_measured, const Mat &rotation_measured); - /** Main program **/ int main(int argc, char *argv[]) { - - help(); - - const String keys = - "{help h | | print this message }" - "{video v | | path to recorded video }" - "{model | | path to yml model }" - "{mesh | | path to ply mesh }" - "{keypoints k |2000 | number of keypoints to detect }" - "{ratio r |0.7 | threshold for ratio test }" - "{iterations it |500 | RANSAC maximum iterations count }" - "{error e |2.0 | RANSAC reprojection error }" - "{confidence c |0.95 | RANSAC confidence }" - "{inliers in |30 | minimum inliers for Kalman update }" - "{method pnp |0 | PnP method: (0) ITERATIVE - (1) EPNP - (2) P3P - (3) DLS}" - "{fast f |true | use of robust fast match }" - ; - CommandLineParser parser(argc, argv, keys); - - if (parser.has("help")) - { - parser.printMessage(); - return 0; - } - else - { - video_read_path = parser.get("video").size() > 0 ? parser.get("video") : video_read_path; - yml_read_path = parser.get("model").size() > 0 ? parser.get("model") : yml_read_path; - ply_read_path = parser.get("mesh").size() > 0 ? parser.get("mesh") : ply_read_path; - numKeyPoints = !parser.has("keypoints") ? parser.get("keypoints") : numKeyPoints; - ratioTest = !parser.has("ratio") ? parser.get("ratio") : ratioTest; - fast_match = !parser.has("fast") ? parser.get("fast") : fast_match; - iterationsCount = !parser.has("iterations") ? parser.get("iterations") : iterationsCount; - reprojectionError = !parser.has("error") ? parser.get("error") : reprojectionError; - confidence = !parser.has("confidence") ? parser.get("confidence") : confidence; - minInliersKalman = !parser.has("inliers") ? parser.get("inliers") : minInliersKalman; - pnpMethod = !parser.has("method") ? parser.get("method") : pnpMethod; - } - - PnPProblem pnp_detection(params_WEBCAM); - PnPProblem pnp_detection_est(params_WEBCAM); - - Model model; // instantiate Model object - model.load(yml_read_path); // load a 3D textured object model - - Mesh mesh; // instantiate Mesh object - mesh.load(ply_read_path); // load an object mesh - - RobustMatcher rmatcher; // instantiate RobustMatcher - - Ptr orb = ORB::create(); - - rmatcher.setFeatureDetector(orb); // set feature detector - rmatcher.setDescriptorExtractor(orb); // set descriptor extractor - - Ptr indexParams = makePtr(6, 12, 1); // instantiate LSH index parameters - Ptr searchParams = makePtr(50); // instantiate flann search parameters - - // instantiate FlannBased matcher - Ptr matcher = makePtr(indexParams, searchParams); - rmatcher.setDescriptorMatcher(matcher); // set matcher - rmatcher.setRatio(ratioTest); // set ratio test parameter - - KalmanFilter KF; // instantiate Kalman Filter - int nStates = 18; // the number of states - int nMeasurements = 6; // the number of measured states - int nInputs = 0; // the number of control actions - double dt = 0.125; // time between measurements (1/FPS) - - initKalmanFilter(KF, nStates, nMeasurements, nInputs, dt); // init function - Mat measurements(nMeasurements, 1, CV_64F); measurements.setTo(Scalar(0)); - bool good_measurement = false; - - - // Get the MODEL INFO - vector list_points3d_model = model.get_points3d(); // list with model 3D coordinates - Mat descriptors_model = model.get_descriptors(); // list with descriptors of each 3D coordinate - - - // Create & Open Window - namedWindow("REAL TIME DEMO", WINDOW_KEEPRATIO); - - - VideoCapture cap; // instantiate VideoCapture - cap.open(video_read_path); // open a recorded video - - if(!cap.isOpened()) // check if we succeeded - { - cout << "Could not open the camera device" << endl; - return -1; - } - - // start and end times - time_t start, end; - - // fps calculated using number of frames / seconds - // floating point seconds elapsed since start - double fps, sec; - - // frame counter - int counter = 0; - - // start the clock - time(&start); - - Mat frame, frame_vis; - - while(cap.read(frame) && (char)waitKey(30) != 27) // capture frame until ESC is pressed - { - - frame_vis = frame.clone(); // refresh visualisation frame - - - // -- Step 1: Robust matching between model descriptors and scene descriptors - - vector good_matches; // to obtain the 3D points of the model - vector keypoints_scene; // to obtain the 2D points of the scene - - - if(fast_match) + help(); + + const String keys = + "{help h | | print this message }" + "{video v | | path to recorded video }" + "{model | | path to yml model }" + "{mesh | | path to ply mesh }" + "{keypoints k |2000 | number of keypoints to detect }" + "{ratio r |0.7 | threshold for ratio test }" + "{iterations it |500 | RANSAC maximum iterations count }" + "{error e |6.0 | RANSAC reprojection error }" + "{confidence c |0.99 | RANSAC confidence }" + "{inliers in |30 | minimum inliers for Kalman update }" + "{method pnp |0 | PnP method: (0) ITERATIVE - (1) EPNP - (2) P3P - (3) DLS - (5) AP3P}" + "{fast f |true | use of robust fast match }" + "{feature |ORB | feature name (ORB, KAZE, AKAZE, BRISK, SIFT, SURF, BINBOOST, VGG) }" + "{FLANN |false | use FLANN library for descriptors matching }" + "{save | | path to the directory where to save the image results }" + "{displayFiltered |false | display filtered pose (from Kalman filter) }" + ; + CommandLineParser parser(argc, argv, keys); + + string video_read_path = samples::findFile("samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/Data/box.mp4"); // recorded video + string yml_read_path = samples::findFile("samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/Data/cookies_ORB.yml"); // 3dpts + descriptors + string ply_read_path = samples::findFile("samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/Data/box.ply"); // mesh + + // Intrinsic camera parameters: UVC WEBCAM + double f = 55; // focal length in mm + double sx = 22.3, sy = 14.9; // sensor size + double width = 640, height = 480; // image size + + double params_WEBCAM[] = { width*f/sx, // fx + height*f/sy, // fy + width/2, // cx + height/2}; // cy + + // Some basic colors + Scalar red(0, 0, 255); + Scalar green(0,255,0); + Scalar blue(255,0,0); + Scalar yellow(0,255,255); + + // Robust Matcher parameters + int numKeyPoints = 2000; // number of detected keypoints + float ratioTest = 0.70f; // ratio test + bool fast_match = true; // fastRobustMatch() or robustMatch() + + // RANSAC parameters + int iterationsCount = 500; // number of Ransac iterations. + float reprojectionError = 6.0; // maximum allowed distance to consider it an inlier. + double confidence = 0.99; // ransac successful confidence. + + // Kalman Filter parameters + int minInliersKalman = 30; // Kalman threshold updating + + // PnP parameters + int pnpMethod = SOLVEPNP_ITERATIVE; + string featureName = "ORB"; + bool useFLANN = false; + + // Save results + string saveDirectory = ""; + Mat frameSave; + int frameCount = 0; + + bool displayFilteredPose = false; + + if (parser.has("help")) { - rmatcher.fastRobustMatch(frame, good_matches, keypoints_scene, descriptors_model); + parser.printMessage(); + return 0; } else { - rmatcher.robustMatch(frame, good_matches, keypoints_scene, descriptors_model); + video_read_path = parser.get("video").size() > 0 ? parser.get("video") : video_read_path; + yml_read_path = parser.get("model").size() > 0 ? parser.get("model") : yml_read_path; + ply_read_path = parser.get("mesh").size() > 0 ? parser.get("mesh") : ply_read_path; + numKeyPoints = parser.has("keypoints") ? parser.get("keypoints") : numKeyPoints; + ratioTest = parser.has("ratio") ? parser.get("ratio") : ratioTest; + fast_match = parser.has("fast") ? parser.get("fast") : fast_match; + iterationsCount = parser.has("iterations") ? parser.get("iterations") : iterationsCount; + reprojectionError = parser.has("error") ? parser.get("error") : reprojectionError; + confidence = parser.has("confidence") ? parser.get("confidence") : confidence; + minInliersKalman = parser.has("inliers") ? parser.get("inliers") : minInliersKalman; + pnpMethod = parser.has("method") ? parser.get("method") : pnpMethod; + featureName = parser.has("feature") ? parser.get("feature") : featureName; + useFLANN = parser.has("FLANN") ? parser.get("FLANN") : useFLANN; + saveDirectory = parser.has("save") ? parser.get("save") : saveDirectory; + displayFilteredPose = parser.has("displayFiltered") ? parser.get("displayFiltered") : displayFilteredPose; } - - // -- Step 2: Find out the 2D/3D correspondences - - vector list_points3d_model_match; // container for the model 3D coordinates found in the scene - vector list_points2d_scene_match; // container for the model 2D coordinates found in the scene - - for(unsigned int match_index = 0; match_index < good_matches.size(); ++match_index) + std::cout << "Video: " << video_read_path << std::endl; + std::cout << "Training data: " << yml_read_path << std::endl; + std::cout << "CAD model: " << ply_read_path << std::endl; + std::cout << "Ratio test threshold: " << ratioTest << std::endl; + std::cout << "Fast match(no symmetry test)?: " << fast_match << std::endl; + std::cout << "RANSAC number of iterations: " << iterationsCount << std::endl; + std::cout << "RANSAC reprojection error: " << reprojectionError << std::endl; + std::cout << "RANSAC confidence threshold: " << confidence << std::endl; + std::cout << "Kalman number of inliers: " << minInliersKalman << std::endl; + std::cout << "PnP method: " << pnpMethod << std::endl; + std::cout << "Feature: " << featureName << std::endl; + std::cout << "Number of keypoints for ORB: " << numKeyPoints << std::endl; + std::cout << "Use FLANN-based matching? " << useFLANN << std::endl; + std::cout << "Save directory: " << saveDirectory << std::endl; + std::cout << "Display filtered pose from Kalman filter? " << displayFilteredPose << std::endl; + + PnPProblem pnp_detection(params_WEBCAM); + PnPProblem pnp_detection_est(params_WEBCAM); + + Model model; // instantiate Model object + model.load(yml_read_path); // load a 3D textured object model + + Mesh mesh; // instantiate Mesh object + mesh.load(ply_read_path); // load an object mesh + + RobustMatcher rmatcher; // instantiate RobustMatcher + + Ptr detector, descriptor; + createFeatures(featureName, numKeyPoints, detector, descriptor); + rmatcher.setFeatureDetector(detector); // set feature detector + rmatcher.setDescriptorExtractor(descriptor); // set descriptor extractor + rmatcher.setDescriptorMatcher(createMatcher(featureName, useFLANN)); // set matcher + rmatcher.setRatio(ratioTest); // set ratio test parameter + if (!model.get_trainingImagePath().empty()) { - Point3f point3d_model = list_points3d_model[ good_matches[match_index].trainIdx ]; // 3D point from model - Point2f point2d_scene = keypoints_scene[ good_matches[match_index].queryIdx ].pt; // 2D point from the scene - list_points3d_model_match.push_back(point3d_model); // add 3D point - list_points2d_scene_match.push_back(point2d_scene); // add 2D point + Mat trainingImg = imread(model.get_trainingImagePath()); + rmatcher.setTrainingImage(trainingImg); } - // Draw outliers - draw2DPoints(frame_vis, list_points2d_scene_match, red); - - - Mat inliers_idx; - vector list_points2d_inliers; - - if(good_matches.size() >= 4) // OpenCV requires solvePnPRANSAC to minimally have 4 set of points - { - - // -- Step 3: Estimate the pose using RANSAC approach - pnp_detection.estimatePoseRANSAC( list_points3d_model_match, list_points2d_scene_match, - pnpMethod, inliers_idx, - iterationsCount, reprojectionError, confidence ); - - // -- Step 4: Catch the inliers keypoints to draw - for(int inliers_index = 0; inliers_index < inliers_idx.rows; ++inliers_index) - { - int n = inliers_idx.at(inliers_index); // i-inlier - Point2f point2d = list_points2d_scene_match[n]; // i-inlier point 2D - list_points2d_inliers.push_back(point2d); // add i-inlier to list - } - - // Draw inliers points 2D - draw2DPoints(frame_vis, list_points2d_inliers, blue); + KalmanFilter KF; // instantiate Kalman Filter + int nStates = 18; // the number of states + int nMeasurements = 6; // the number of measured states + int nInputs = 0; // the number of control actions + double dt = 0.125; // time between measurements (1/FPS) + initKalmanFilter(KF, nStates, nMeasurements, nInputs, dt); // init function + Mat measurements(nMeasurements, 1, CV_64FC1); measurements.setTo(Scalar(0)); + bool good_measurement = false; - // -- Step 5: Kalman Filter + // Get the MODEL INFO + vector list_points3d_model = model.get_points3d(); // list with model 3D coordinates + Mat descriptors_model = model.get_descriptors(); // list with descriptors of each 3D coordinate + vector keypoints_model = model.get_keypoints(); - good_measurement = false; + // Create & Open Window + namedWindow("REAL TIME DEMO", WINDOW_KEEPRATIO); - // GOOD MEASUREMENT - if( inliers_idx.rows >= minInliersKalman ) - { + VideoCapture cap; // instantiate VideoCapture + cap.open(video_read_path); // open a recorded video - // Get the measured translation - Mat translation_measured(3, 1, CV_64F); - translation_measured = pnp_detection.get_t_matrix(); - - // Get the measured rotation - Mat rotation_measured(3, 3, CV_64F); - rotation_measured = pnp_detection.get_R_matrix(); - - // fill the measurements vector - fillMeasurements(measurements, translation_measured, rotation_measured); - - good_measurement = true; - - } - - // Instantiate estimated translation and rotation - Mat translation_estimated(3, 1, CV_64F); - Mat rotation_estimated(3, 3, CV_64F); - - // update the Kalman filter with good measurements - updateKalmanFilter( KF, measurements, - translation_estimated, rotation_estimated); - - - // -- Step 6: Set estimated projection matrix - pnp_detection_est.set_P_matrix(rotation_estimated, translation_estimated); - - } - - // -- Step X: Draw pose - - if(good_measurement) + if(!cap.isOpened()) // check if we succeeded { - drawObjectMesh(frame_vis, &mesh, &pnp_detection, green); // draw current pose + cout << "Could not open the camera device" << endl; + return -1; } - else + + if (!saveDirectory.empty()) { - drawObjectMesh(frame_vis, &mesh, &pnp_detection_est, yellow); // draw estimated pose + if (!cv::utils::fs::exists(saveDirectory)) + { + std::cout << "Create directory: " << saveDirectory << std::endl; + cv::utils::fs::createDirectories(saveDirectory); + } } - float l = 5; - vector pose_points2d; - pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,0,0))); // axis center - pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(l,0,0))); // axis x - pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,l,0))); // axis y - pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,0,l))); // axis z - draw3DCoordinateAxes(frame_vis, pose_points2d); // draw axes - - // FRAME RATE - - // see how much time has elapsed - time(&end); - - // calculate current FPS - ++counter; - sec = difftime (end, start); - - fps = counter / sec; - - drawFPS(frame_vis, fps, yellow); // frame ratio - double detection_ratio = ((double)inliers_idx.rows/(double)good_matches.size())*100; - drawConfidence(frame_vis, detection_ratio, yellow); - + // Measure elapsed time + TickMeter tm; - // -- Step X: Draw some debugging text - - // Draw some debug text - int inliers_int = inliers_idx.rows; - int outliers_int = (int)good_matches.size() - inliers_int; - string inliers_str = IntToString(inliers_int); - string outliers_str = IntToString(outliers_int); - string n = IntToString((int)good_matches.size()); - string text = "Found " + inliers_str + " of " + n + " matches"; - string text2 = "Inliers: " + inliers_str + " - Outliers: " + outliers_str; - - drawText(frame_vis, text, green); - drawText2(frame_vis, text2, red); - - imshow("REAL TIME DEMO", frame_vis); - } - - // Close and Destroy Window - destroyWindow("REAL TIME DEMO"); + Mat frame, frame_vis, frame_matching; + while(cap.read(frame) && (char)waitKey(30) != 27) // capture frame until ESC is pressed + { + tm.reset(); + tm.start(); + frame_vis = frame.clone(); // refresh visualisation frame + + // -- Step 1: Robust matching between model descriptors and scene descriptors + vector good_matches; // to obtain the 3D points of the model + vector keypoints_scene; // to obtain the 2D points of the scene + + if(fast_match) + { + rmatcher.fastRobustMatch(frame, good_matches, keypoints_scene, descriptors_model, keypoints_model); + } + else + { + rmatcher.robustMatch(frame, good_matches, keypoints_scene, descriptors_model, keypoints_model); + } + + frame_matching = rmatcher.getImageMatching(); + if (!frame_matching.empty()) + { + imshow("Keypoints matching", frame_matching); + } + + // -- Step 2: Find out the 2D/3D correspondences + vector list_points3d_model_match; // container for the model 3D coordinates found in the scene + vector list_points2d_scene_match; // container for the model 2D coordinates found in the scene + + for(unsigned int match_index = 0; match_index < good_matches.size(); ++match_index) + { + Point3f point3d_model = list_points3d_model[ good_matches[match_index].trainIdx ]; // 3D point from model + Point2f point2d_scene = keypoints_scene[ good_matches[match_index].queryIdx ].pt; // 2D point from the scene + list_points3d_model_match.push_back(point3d_model); // add 3D point + list_points2d_scene_match.push_back(point2d_scene); // add 2D point + } + + // Draw outliers + draw2DPoints(frame_vis, list_points2d_scene_match, red); + + Mat inliers_idx; + vector list_points2d_inliers; + + // Instantiate estimated translation and rotation + good_measurement = false; + + if(good_matches.size() >= 4) // OpenCV requires solvePnPRANSAC to minimally have 4 set of points + { + // -- Step 3: Estimate the pose using RANSAC approach + pnp_detection.estimatePoseRANSAC( list_points3d_model_match, list_points2d_scene_match, + pnpMethod, inliers_idx, + iterationsCount, reprojectionError, confidence ); + + // -- Step 4: Catch the inliers keypoints to draw + for(int inliers_index = 0; inliers_index < inliers_idx.rows; ++inliers_index) + { + int n = inliers_idx.at(inliers_index); // i-inlier + Point2f point2d = list_points2d_scene_match[n]; // i-inlier point 2D + list_points2d_inliers.push_back(point2d); // add i-inlier to list + } + + // Draw inliers points 2D + draw2DPoints(frame_vis, list_points2d_inliers, blue); + + // -- Step 5: Kalman Filter + + // GOOD MEASUREMENT + if( inliers_idx.rows >= minInliersKalman ) + { + // Get the measured translation + Mat translation_measured = pnp_detection.get_t_matrix(); + + // Get the measured rotation + Mat rotation_measured = pnp_detection.get_R_matrix(); + + // fill the measurements vector + fillMeasurements(measurements, translation_measured, rotation_measured); + good_measurement = true; + } + + // update the Kalman filter with good measurements, otherwise with previous valid measurements + Mat translation_estimated(3, 1, CV_64FC1); + Mat rotation_estimated(3, 3, CV_64FC1); + updateKalmanFilter( KF, measurements, + translation_estimated, rotation_estimated); + + // -- Step 6: Set estimated projection matrix + pnp_detection_est.set_P_matrix(rotation_estimated, translation_estimated); + } + + // -- Step X: Draw pose and coordinate frame + float l = 5; + vector pose_points2d; + if (!good_measurement || displayFilteredPose) + { + drawObjectMesh(frame_vis, &mesh, &pnp_detection_est, yellow); // draw estimated pose + + pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,0,0))); // axis center + pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(l,0,0))); // axis x + pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,l,0))); // axis y + pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,0,l))); // axis z + draw3DCoordinateAxes(frame_vis, pose_points2d); // draw axes + } + else + { + drawObjectMesh(frame_vis, &mesh, &pnp_detection, green); // draw current pose + + pose_points2d.push_back(pnp_detection.backproject3DPoint(Point3f(0,0,0))); // axis center + pose_points2d.push_back(pnp_detection.backproject3DPoint(Point3f(l,0,0))); // axis x + pose_points2d.push_back(pnp_detection.backproject3DPoint(Point3f(0,l,0))); // axis y + pose_points2d.push_back(pnp_detection.backproject3DPoint(Point3f(0,0,l))); // axis z + draw3DCoordinateAxes(frame_vis, pose_points2d); // draw axes + } + + // FRAME RATE + // see how much time has elapsed + tm.stop(); + + // calculate current FPS + double fps = 1.0 / tm.getTimeSec(); + + drawFPS(frame_vis, fps, yellow); // frame ratio + double detection_ratio = ((double)inliers_idx.rows/(double)good_matches.size())*100; + drawConfidence(frame_vis, detection_ratio, yellow); + + // -- Step X: Draw some debugging text + // Draw some debug text + int inliers_int = inliers_idx.rows; + int outliers_int = (int)good_matches.size() - inliers_int; + string inliers_str = IntToString(inliers_int); + string outliers_str = IntToString(outliers_int); + string n = IntToString((int)good_matches.size()); + string text = "Found " + inliers_str + " of " + n + " matches"; + string text2 = "Inliers: " + inliers_str + " - Outliers: " + outliers_str; + + drawText(frame_vis, text, green); + drawText2(frame_vis, text2, red); + + imshow("REAL TIME DEMO", frame_vis); + + if (!saveDirectory.empty()) + { + const int widthSave = !frame_matching.empty() ? frame_matching.cols : frame_vis.cols; + const int heightSave = !frame_matching.empty() ? frame_matching.rows + frame_vis.rows : frame_vis.rows; + frameSave = Mat::zeros(heightSave, widthSave, CV_8UC3); + if (!frame_matching.empty()) + { + int startX = (int)((widthSave - frame_vis.cols) / 2.0); + Mat roi = frameSave(Rect(startX, 0, frame_vis.cols, frame_vis.rows)); + frame_vis.copyTo(roi); + + roi = frameSave(Rect(0, frame_vis.rows, frame_matching.cols, frame_matching.rows)); + frame_matching.copyTo(roi); + } + else + { + frame_vis.copyTo(frameSave); + } + + string saveFilename = format(string(saveDirectory + "/image_%04d.png").c_str(), frameCount); + imwrite(saveFilename, frameSave); + frameCount++; + } + } - cout << "GOODBYE ..." << endl; + // Close and Destroy Window + destroyWindow("REAL TIME DEMO"); + cout << "GOODBYE ..." << endl; } /**********************************************************************************************************/ void help() { -cout -<< "--------------------------------------------------------------------------" << endl -<< "This program shows how to detect an object given its 3D textured model. You can choose to " -<< "use a recorded video or the webcam." << endl -<< "Usage:" << endl -<< "./cpp-tutorial-pnp_detection -help" << endl -<< "Keys:" << endl -<< "'esc' - to quit." << endl -<< "--------------------------------------------------------------------------" << endl -<< endl; + cout + << "--------------------------------------------------------------------------" << endl + << "This program shows how to detect an object given its 3D textured model. You can choose to " + << "use a recorded video or the webcam." << endl + << "Usage:" << endl + << "./cpp-tutorial-pnp_detection -help" << endl + << "Keys:" << endl + << "'esc' - to quit." << endl + << "--------------------------------------------------------------------------" << endl + << endl; } /**********************************************************************************************************/ void initKalmanFilter(KalmanFilter &KF, int nStates, int nMeasurements, int nInputs, double dt) { - - KF.init(nStates, nMeasurements, nInputs, CV_64F); // init Kalman Filter - - setIdentity(KF.processNoiseCov, Scalar::all(1e-5)); // set process noise - setIdentity(KF.measurementNoiseCov, Scalar::all(1e-2)); // set measurement noise - setIdentity(KF.errorCovPost, Scalar::all(1)); // error covariance - - - /** DYNAMIC MODEL **/ - - // [1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0 0 0] - // [0 1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0 0] - // [0 0 1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0] - // [0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0 0 0] - // [0 0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0 0] - // [0 0 0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0] - // [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] - // [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0] - // [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] - // [0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2 0 0] - // [0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2 0] - // [0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2] - // [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0] - // [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0] - // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt] - // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] - // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0] - // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1] - - // position - KF.transitionMatrix.at(0,3) = dt; - KF.transitionMatrix.at(1,4) = dt; - KF.transitionMatrix.at(2,5) = dt; - KF.transitionMatrix.at(3,6) = dt; - KF.transitionMatrix.at(4,7) = dt; - KF.transitionMatrix.at(5,8) = dt; - KF.transitionMatrix.at(0,6) = 0.5*pow(dt,2); - KF.transitionMatrix.at(1,7) = 0.5*pow(dt,2); - KF.transitionMatrix.at(2,8) = 0.5*pow(dt,2); - - // orientation - KF.transitionMatrix.at(9,12) = dt; - KF.transitionMatrix.at(10,13) = dt; - KF.transitionMatrix.at(11,14) = dt; - KF.transitionMatrix.at(12,15) = dt; - KF.transitionMatrix.at(13,16) = dt; - KF.transitionMatrix.at(14,17) = dt; - KF.transitionMatrix.at(9,15) = 0.5*pow(dt,2); - KF.transitionMatrix.at(10,16) = 0.5*pow(dt,2); - KF.transitionMatrix.at(11,17) = 0.5*pow(dt,2); - - - /** MEASUREMENT MODEL **/ - - // [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] - // [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] - // [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] - // [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0] - // [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] - // [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0] - - KF.measurementMatrix.at(0,0) = 1; // x - KF.measurementMatrix.at(1,1) = 1; // y - KF.measurementMatrix.at(2,2) = 1; // z - KF.measurementMatrix.at(3,9) = 1; // roll - KF.measurementMatrix.at(4,10) = 1; // pitch - KF.measurementMatrix.at(5,11) = 1; // yaw - + KF.init(nStates, nMeasurements, nInputs, CV_64F); // init Kalman Filter + + setIdentity(KF.processNoiseCov, Scalar::all(1e-5)); // set process noise + setIdentity(KF.measurementNoiseCov, Scalar::all(1e-2)); // set measurement noise + setIdentity(KF.errorCovPost, Scalar::all(1)); // error covariance + + /** DYNAMIC MODEL **/ + + // [1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0 0 0] + // [0 1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0 0] + // [0 0 1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0] + // [0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0 0 0] + // [0 0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0 0] + // [0 0 0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0] + // [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] + // [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0] + // [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] + // [0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2 0 0] + // [0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2 0] + // [0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2] + // [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0] + // [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0] + // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt] + // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] + // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0] + // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1] + + // position + KF.transitionMatrix.at(0,3) = dt; + KF.transitionMatrix.at(1,4) = dt; + KF.transitionMatrix.at(2,5) = dt; + KF.transitionMatrix.at(3,6) = dt; + KF.transitionMatrix.at(4,7) = dt; + KF.transitionMatrix.at(5,8) = dt; + KF.transitionMatrix.at(0,6) = 0.5*pow(dt,2); + KF.transitionMatrix.at(1,7) = 0.5*pow(dt,2); + KF.transitionMatrix.at(2,8) = 0.5*pow(dt,2); + + // orientation + KF.transitionMatrix.at(9,12) = dt; + KF.transitionMatrix.at(10,13) = dt; + KF.transitionMatrix.at(11,14) = dt; + KF.transitionMatrix.at(12,15) = dt; + KF.transitionMatrix.at(13,16) = dt; + KF.transitionMatrix.at(14,17) = dt; + KF.transitionMatrix.at(9,15) = 0.5*pow(dt,2); + KF.transitionMatrix.at(10,16) = 0.5*pow(dt,2); + KF.transitionMatrix.at(11,17) = 0.5*pow(dt,2); + + + /** MEASUREMENT MODEL **/ + + // [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] + // [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] + // [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] + // [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0] + // [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] + // [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0] + + KF.measurementMatrix.at(0,0) = 1; // x + KF.measurementMatrix.at(1,1) = 1; // y + KF.measurementMatrix.at(2,2) = 1; // z + KF.measurementMatrix.at(3,9) = 1; // roll + KF.measurementMatrix.at(4,10) = 1; // pitch + KF.measurementMatrix.at(5,11) = 1; // yaw } /**********************************************************************************************************/ void updateKalmanFilter( KalmanFilter &KF, Mat &measurement, Mat &translation_estimated, Mat &rotation_estimated ) { + // First predict, to update the internal statePre variable + Mat prediction = KF.predict(); - // First predict, to update the internal statePre variable - Mat prediction = KF.predict(); - - // The "correct" phase that is going to use the predicted value and our measurement - Mat estimated = KF.correct(measurement); - - // Estimated translation - translation_estimated.at(0) = estimated.at(0); - translation_estimated.at(1) = estimated.at(1); - translation_estimated.at(2) = estimated.at(2); + // The "correct" phase that is going to use the predicted value and our measurement + Mat estimated = KF.correct(measurement); - // Estimated euler angles - Mat eulers_estimated(3, 1, CV_64F); - eulers_estimated.at(0) = estimated.at(9); - eulers_estimated.at(1) = estimated.at(10); - eulers_estimated.at(2) = estimated.at(11); + // Estimated translation + translation_estimated.at(0) = estimated.at(0); + translation_estimated.at(1) = estimated.at(1); + translation_estimated.at(2) = estimated.at(2); - // Convert estimated quaternion to rotation matrix - rotation_estimated = euler2rot(eulers_estimated); + // Estimated euler angles + Mat eulers_estimated(3, 1, CV_64F); + eulers_estimated.at(0) = estimated.at(9); + eulers_estimated.at(1) = estimated.at(10); + eulers_estimated.at(2) = estimated.at(11); + // Convert estimated quaternion to rotation matrix + rotation_estimated = euler2rot(eulers_estimated); } /**********************************************************************************************************/ void fillMeasurements( Mat &measurements, const Mat &translation_measured, const Mat &rotation_measured) { - // Convert rotation matrix to euler angles - Mat measured_eulers(3, 1, CV_64F); - measured_eulers = rot2euler(rotation_measured); - - // Set measurement to predict - measurements.at(0) = translation_measured.at(0); // x - measurements.at(1) = translation_measured.at(1); // y - measurements.at(2) = translation_measured.at(2); // z - measurements.at(3) = measured_eulers.at(0); // roll - measurements.at(4) = measured_eulers.at(1); // pitch - measurements.at(5) = measured_eulers.at(2); // yaw + // Convert rotation matrix to euler angles + Mat measured_eulers(3, 1, CV_64F); + measured_eulers = rot2euler(rotation_measured); + + // Set measurement to predict + measurements.at(0) = translation_measured.at(0); // x + measurements.at(1) = translation_measured.at(1); // y + measurements.at(2) = translation_measured.at(2); // z + measurements.at(3) = measured_eulers.at(0); // roll + measurements.at(4) = measured_eulers.at(1); // pitch + measurements.at(5) = measured_eulers.at(2); // yaw } diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_registration.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_registration.cpp index 5ddb83f0da..31ffb2e01e 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_registration.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_registration.cpp @@ -18,34 +18,22 @@ using namespace std; /** GLOBAL VARIABLES **/ -string tutorial_path = "../../samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/"; // path to tutorial - -string img_path = tutorial_path + "Data/resized_IMG_3875.JPG"; // image to register -string ply_read_path = tutorial_path + "Data/box.ply"; // object mesh -string write_path = tutorial_path + "Data/cookies_ORB.yml"; // output file - // Boolean the know if the registration it's done bool end_registration = false; // Intrinsic camera parameters: UVC WEBCAM -double f = 45; // focal length in mm -double sx = 22.3, sy = 14.9; -double width = 2592, height = 1944; -double params_CANON[] = { width*f/sx, // fx - height*f/sy, // fy - width/2, // cx - height/2}; // cy +const double f = 45; // focal length in mm +const double sx = 22.3, sy = 14.9; +const double width = 2592, height = 1944; +const double params_CANON[] = { width*f/sx, // fx + height*f/sy, // fy + width/2, // cx + height/2}; // cy // Setup the points to register in the image // In the order of the *.ply file and starting at 1 -int n = 8; -int pts[] = {1, 2, 3, 4, 5, 6, 7, 8}; // 3 -> 4 - -// Some basic colors -Scalar red(0, 0, 255); -Scalar green(0,255,0); -Scalar blue(255,0,0); -Scalar yellow(0,255,255); +const int n = 8; +const int pts[] = {1, 2, 3, 4, 5, 6, 7, 8}; // 3 -> 4 /* * CREATE MODEL REGISTRATION OBJECT @@ -58,211 +46,248 @@ Model model; Mesh mesh; PnPProblem pnp_registration(params_CANON); -/** Functions headers **/ -void help(); +/**********************************************************************************************************/ +static void help() +{ + cout + << "--------------------------------------------------------------------------" << endl + << "This program shows how to create your 3D textured model. " << endl + << "Usage:" << endl + << "./cpp-tutorial-pnp_registration" << endl + << "--------------------------------------------------------------------------" << endl + << endl; +} // Mouse events for model registration static void onMouseModelRegistration( int event, int x, int y, int, void* ) { - if ( event == EVENT_LBUTTONUP ) - { - int n_regist = registration.getNumRegist(); - int n_vertex = pts[n_regist]; - - Point2f point_2d = Point2f((float)x,(float)y); - Point3f point_3d = mesh.getVertex(n_vertex-1); - - bool is_registrable = registration.is_registrable(); - if (is_registrable) - { - registration.registerPoint(point_2d, point_3d); - if( registration.getNumRegist() == registration.getNumMax() ) end_registration = true; - } - } + if ( event == EVENT_LBUTTONUP ) + { + bool is_registrable = registration.is_registrable(); + if (is_registrable) + { + int n_regist = registration.getNumRegist(); + int n_vertex = pts[n_regist]; + + Point2f point_2d = Point2f((float)x,(float)y); + Point3f point_3d = mesh.getVertex(n_vertex-1); + + registration.registerPoint(point_2d, point_3d); + if( registration.getNumRegist() == registration.getNumMax() ) end_registration = true; + } + } } /** Main program **/ -int main() +int main(int argc, char *argv[]) { - - help(); - - // load a mesh given the *.ply file path - mesh.load(ply_read_path); - - // set parameters - int numKeyPoints = 10000; - - //Instantiate robust matcher: detector, extractor, matcher - RobustMatcher rmatcher; - Ptr detector = ORB::create(numKeyPoints); - rmatcher.setFeatureDetector(detector); - - /** GROUND TRUTH OF THE FIRST IMAGE **/ - - // Create & Open Window - namedWindow("MODEL REGISTRATION", WINDOW_KEEPRATIO); - - // Set up the mouse events - setMouseCallback("MODEL REGISTRATION", onMouseModelRegistration, 0 ); - - // Open the image to register - Mat img_in = imread(img_path, IMREAD_COLOR); - Mat img_vis = img_in.clone(); - - if (!img_in.data) { - cout << "Could not open or find the image" << endl; - return -1; - } - - // Set the number of points to register - int num_registrations = n; - registration.setNumMax(num_registrations); - - cout << "Click the box corners ..." << endl; - cout << "Waiting ..." << endl; - - // Loop until all the points are registered - while ( waitKey(30) < 0 ) - { - // Refresh debug image - img_vis = img_in.clone(); - - // Current registered points - vector list_points2d = registration.get_points2d(); - vector list_points3d = registration.get_points3d(); - - // Draw current registered points - drawPoints(img_vis, list_points2d, list_points3d, red); - - // If the registration is not finished, draw which 3D point we have to register. - // If the registration is finished, breaks the loop. - if (!end_registration) + help(); + + const String keys = + "{help h | | print this message }" + "{image i | | path to input image }" + "{model | | path to output yml model }" + "{mesh | | path to ply mesh }" + "{keypoints k |2000 | number of keypoints to detect (only for ORB) }" + "{feature |ORB | feature name (ORB, KAZE, AKAZE, BRISK, SIFT, SURF, BINBOOST, VGG) }" + ; + CommandLineParser parser(argc, argv, keys); + + string img_path = samples::findFile("samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/Data/resized_IMG_3875.JPG"); // image to register + string ply_read_path = samples::findFile("samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/Data/box.ply"); // object mesh + string write_path = samples::findFile("samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/Data/cookies_ORB.yml"); // output file + int numKeyPoints = 2000; + string featureName = "ORB"; + + if (parser.has("help")) { - // Draw debug text - int n_regist = registration.getNumRegist(); - int n_vertex = pts[n_regist]; - Point3f current_poin3d = mesh.getVertex(n_vertex-1); - - drawQuestion(img_vis, current_poin3d, green); - drawCounter(img_vis, registration.getNumRegist(), registration.getNumMax(), red); + parser.printMessage(); + return 0; } else { - // Draw debug text - drawText(img_vis, "END REGISTRATION", green); - drawCounter(img_vis, registration.getNumRegist(), registration.getNumMax(), green); - break; + img_path = parser.get("image").size() > 0 ? parser.get("image") : img_path; + ply_read_path = parser.get("mesh").size() > 0 ? parser.get("mesh") : ply_read_path; + write_path = parser.get("model").size() > 0 ? parser.get("model") : write_path; + numKeyPoints = parser.has("keypoints") ? parser.get("keypoints") : numKeyPoints; + featureName = parser.has("feature") ? parser.get("feature") : featureName; } - // Show the image - imshow("MODEL REGISTRATION", img_vis); - } - - /** COMPUTE CAMERA POSE **/ + std::cout << "Input image: " << img_path << std::endl; + std::cout << "CAD model: " << ply_read_path << std::endl; + std::cout << "Output training file: " << write_path << std::endl; + std::cout << "Feature: " << featureName << std::endl; + std::cout << "Number of keypoints for ORB: " << numKeyPoints << std::endl; - cout << "COMPUTING POSE ..." << endl; + // load a mesh given the *.ply file path + mesh.load(ply_read_path); - // The list of registered points - vector list_points2d = registration.get_points2d(); - vector list_points3d = registration.get_points3d(); + //Instantiate robust matcher: detector, extractor, matcher + RobustMatcher rmatcher; + Ptr detector, descriptor; + createFeatures(featureName, numKeyPoints, detector, descriptor); + rmatcher.setFeatureDetector(detector); + rmatcher.setDescriptorExtractor(descriptor); - // Estimate pose given the registered points - bool is_correspondence = pnp_registration.estimatePose(list_points3d, list_points2d, SOLVEPNP_ITERATIVE); - if ( is_correspondence ) - { - cout << "Correspondence found" << endl; - // Compute all the 2D points of the mesh to verify the algorithm and draw it - vector list_points2d_mesh = pnp_registration.verify_points(&mesh); - draw2DPoints(img_vis, list_points2d_mesh, green); + /** GROUND TRUTH OF THE FIRST IMAGE **/ - } else { - cout << "Correspondence not found" << endl << endl; - } + // Create & Open Window + namedWindow("MODEL REGISTRATION", WINDOW_KEEPRATIO); - // Show the image - imshow("MODEL REGISTRATION", img_vis); + // Set up the mouse events + setMouseCallback("MODEL REGISTRATION", onMouseModelRegistration, 0); - // Show image until ESC pressed - waitKey(0); + // Open the image to register + Mat img_in = imread(img_path, IMREAD_COLOR); + Mat img_vis; + if (img_in.empty()) { + cout << "Could not open or find the image" << endl; + return -1; + } - /** COMPUTE 3D of the image Keypoints **/ + // Set the number of points to register + int num_registrations = n; + registration.setNumMax(num_registrations); - // Containers for keypoints and descriptors of the model - vector keypoints_model; - Mat descriptors; + cout << "Click the box corners ..." << endl; + cout << "Waiting ..." << endl; - // Compute keypoints and descriptors - rmatcher.computeKeyPoints(img_in, keypoints_model); - rmatcher.computeDescriptors(img_in, keypoints_model, descriptors); + // Some basic colors + const Scalar red(0, 0, 255); + const Scalar green(0,255,0); + const Scalar blue(255,0,0); + const Scalar yellow(0,255,255); - // Check if keypoints are on the surface of the registration image and add to the model - for (unsigned int i = 0; i < keypoints_model.size(); ++i) { - Point2f point2d(keypoints_model[i].pt); - Point3f point3d; - bool on_surface = pnp_registration.backproject2DPoint(&mesh, point2d, point3d); - if (on_surface) + // Loop until all the points are registered + while ( waitKey(30) < 0 ) { - model.add_correspondence(point2d, point3d); - model.add_descriptor(descriptors.row(i)); - model.add_keypoint(keypoints_model[i]); + // Refresh debug image + img_vis = img_in.clone(); + + // Current registered points + vector list_points2d = registration.get_points2d(); + vector list_points3d = registration.get_points3d(); + + // Draw current registered points + drawPoints(img_vis, list_points2d, list_points3d, red); + + // If the registration is not finished, draw which 3D point we have to register. + // If the registration is finished, breaks the loop. + if (!end_registration) + { + // Draw debug text + int n_regist = registration.getNumRegist(); + int n_vertex = pts[n_regist]; + Point3f current_poin3d = mesh.getVertex(n_vertex-1); + + drawQuestion(img_vis, current_poin3d, green); + drawCounter(img_vis, registration.getNumRegist(), registration.getNumMax(), red); + } + else + { + // Draw debug text + drawText(img_vis, "END REGISTRATION", green); + drawCounter(img_vis, registration.getNumRegist(), registration.getNumMax(), green); + break; + } + + // Show the image + imshow("MODEL REGISTRATION", img_vis); } - else + + /** COMPUTE CAMERA POSE **/ + + cout << "COMPUTING POSE ..." << endl; + + // The list of registered points + vector list_points2d = registration.get_points2d(); + vector list_points3d = registration.get_points3d(); + + // Estimate pose given the registered points + bool is_correspondence = pnp_registration.estimatePose(list_points3d, list_points2d, SOLVEPNP_ITERATIVE); + if ( is_correspondence ) { - model.add_outlier(point2d); + cout << "Correspondence found" << endl; + + // Compute all the 2D points of the mesh to verify the algorithm and draw it + vector list_points2d_mesh = pnp_registration.verify_points(&mesh); + draw2DPoints(img_vis, list_points2d_mesh, green); + } else { + cout << "Correspondence not found" << endl << endl; } - } - // save the model into a *.yaml file - model.save(write_path); + // Show the image + imshow("MODEL REGISTRATION", img_vis); - // Out image - img_vis = img_in.clone(); + // Show image until ESC pressed + waitKey(0); + + + /** COMPUTE 3D of the image Keypoints **/ + + // Containers for keypoints and descriptors of the model + vector keypoints_model; + Mat descriptors; + + // Compute keypoints and descriptors + rmatcher.computeKeyPoints(img_in, keypoints_model); + rmatcher.computeDescriptors(img_in, keypoints_model, descriptors); + + // Check if keypoints are on the surface of the registration image and add to the model + for (unsigned int i = 0; i < keypoints_model.size(); ++i) { + Point2f point2d(keypoints_model[i].pt); + Point3f point3d; + bool on_surface = pnp_registration.backproject2DPoint(&mesh, point2d, point3d); + if (on_surface) + { + model.add_correspondence(point2d, point3d); + model.add_descriptor(descriptors.row(i)); + model.add_keypoint(keypoints_model[i]); + } + else + { + model.add_outlier(point2d); + } + } - // The list of the points2d of the model - vector list_points_in = model.get_points2d_in(); - vector list_points_out = model.get_points2d_out(); + model.set_trainingImagePath(img_path); + // save the model into a *.yaml file + model.save(write_path); - // Draw some debug text - string num = IntToString((int)list_points_in.size()); - string text = "There are " + num + " inliers"; - drawText(img_vis, text, green); + // Out image + img_vis = img_in.clone(); - // Draw some debug text - num = IntToString((int)list_points_out.size()); - text = "There are " + num + " outliers"; - drawText2(img_vis, text, red); + // The list of the points2d of the model + vector list_points_in = model.get_points2d_in(); + vector list_points_out = model.get_points2d_out(); - // Draw the object mesh - drawObjectMesh(img_vis, &mesh, &pnp_registration, blue); + // Draw some debug text + string num = IntToString((int)list_points_in.size()); + string text = "There are " + num + " inliers"; + drawText(img_vis, text, green); - // Draw found keypoints depending on if are or not on the surface - draw2DPoints(img_vis, list_points_in, green); - draw2DPoints(img_vis, list_points_out, red); + // Draw some debug text + num = IntToString((int)list_points_out.size()); + text = "There are " + num + " outliers"; + drawText2(img_vis, text, red); - // Show the image - imshow("MODEL REGISTRATION", img_vis); + // Draw the object mesh + drawObjectMesh(img_vis, &mesh, &pnp_registration, blue); - // Wait until ESC pressed - waitKey(0); + // Draw found keypoints depending on if are or not on the surface + draw2DPoints(img_vis, list_points_in, green); + draw2DPoints(img_vis, list_points_out, red); - // Close and Destroy Window - destroyWindow("MODEL REGISTRATION"); + // Show the image + imshow("MODEL REGISTRATION", img_vis); - cout << "GOODBYE" << endl; + // Wait until ESC pressed + waitKey(0); -} + // Close and Destroy Window + destroyWindow("MODEL REGISTRATION"); -/**********************************************************************************************************/ -void help() -{ - cout - << "--------------------------------------------------------------------------" << endl - << "This program shows how to create your 3D textured model. " << endl - << "Usage:" << endl - << "./cpp-tutorial-pnp_registration" << endl - << "--------------------------------------------------------------------------" << endl - << endl; + cout << "GOODBYE" << endl; } From 9e94212eacac73d83372d2c3764d63e5af9454a7 Mon Sep 17 00:00:00 2001 From: LaurentBerger Date: Mon, 18 Feb 2019 17:15:05 +0100 Subject: [PATCH 19/21] Solves bug 13853 --- modules/photo/include/opencv2/photo.hpp | 4 ++-- modules/photo/src/tonemap.cpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 7ceb97e27b..1606d787de 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -328,8 +328,8 @@ class CV_EXPORTS_W Tonemap : public Algorithm public: /** @brief Tonemaps image - @param src source image - 32-bit 3-channel Mat - @param dst destination image - 32-bit 3-channel Mat with values in [0, 1] range + @param src source image - CV_32FC3 Mat (float 32 bits 3 channels) + @param dst destination image - CV_32FC3 Mat with values in [0, 1] range */ CV_WRAP virtual void process(InputArray src, OutputArray dst) = 0; diff --git a/modules/photo/src/tonemap.cpp b/modules/photo/src/tonemap.cpp index a02c6ad829..0c9275040b 100644 --- a/modules/photo/src/tonemap.cpp +++ b/modules/photo/src/tonemap.cpp @@ -66,6 +66,7 @@ public: Mat src = _src.getMat(); CV_Assert(!src.empty()); + CV_Assert(_src.dims() == 2 && _src.type() == CV_32FC3); _dst.create(src.size(), CV_32FC3); Mat dst = _dst.getMat(); From ca5976e3d4c5c868b8c542fd5109732d319155b2 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Thu, 14 Feb 2019 13:30:30 +0300 Subject: [PATCH 20/21] Fix IE backend considering future changes. --- modules/dnn/src/dnn.cpp | 20 ++--- modules/dnn/src/layers/batch_norm_layer.cpp | 7 +- modules/dnn/src/layers/blank_layer.cpp | 4 +- modules/dnn/src/layers/convolution_layer.cpp | 15 ++-- modules/dnn/src/layers/elementwise_layers.cpp | 6 +- .../dnn/src/layers/fully_connected_layer.cpp | 7 +- .../dnn/src/layers/normalize_bbox_layer.cpp | 2 +- modules/dnn/src/layers/prior_box_layer.cpp | 6 +- modules/dnn/src/layers/scale_layer.cpp | 10 +-- modules/dnn/src/op_inf_engine.cpp | 75 ++++++++++++++++++- modules/dnn/src/op_inf_engine.hpp | 6 +- modules/dnn/test/test_halide_layers.cpp | 3 +- 12 files changed, 113 insertions(+), 48 deletions(-) diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index fc5548cd8d..5b65a6c50a 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -730,9 +730,9 @@ struct DataLayer : public Layer biases->set(biasesVec); #if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5) - InferenceEngine::Builder::ScaleShiftLayer ieLayer(name); - ieLayer.setWeights(weights); - ieLayer.setBiases(biases); + InferenceEngine::Builder::Layer ieLayer = InferenceEngine::Builder::ScaleShiftLayer(name); + addConstantData("weights", weights, ieLayer); + addConstantData("biases", biases, ieLayer); #else InferenceEngine::LayerParams lp; lp.name = name; @@ -1638,25 +1638,15 @@ struct Net::Impl preferableTarget == DNN_TARGET_FPGA) && !fused) { #if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R5) - bool hasWeights = false; for (const std::string& name : {"weights", "biases"}) { auto it = ieNode->layer.getParameters().find(name); if (it != ieNode->layer.getParameters().end()) { - InferenceEngine::Blob::CPtr bp = it->second.as(); - it->second = (InferenceEngine::Blob::CPtr)convertFp16(std::const_pointer_cast(bp)); - hasWeights = true; + InferenceEngine::Blob::Ptr bp = it->second.as(); + it->second = convertFp16(std::const_pointer_cast(bp)); } } - if (!hasWeights) - { - InferenceEngine::Blob::Ptr blob = InferenceEngine::make_shared_blob( - InferenceEngine::Precision::FP16, - InferenceEngine::Layout::C, {1}); - blob->allocate(); - ieNode->layer.getParameters()["weights"] = (InferenceEngine::Blob::CPtr)blob; - } #else auto& blobs = ieNode->layer.getConstantData(); if (blobs.empty()) diff --git a/modules/dnn/src/layers/batch_norm_layer.cpp b/modules/dnn/src/layers/batch_norm_layer.cpp index 522d0229ba..4c69c247c4 100644 --- a/modules/dnn/src/layers/batch_norm_layer.cpp +++ b/modules/dnn/src/layers/batch_norm_layer.cpp @@ -350,11 +350,10 @@ public: { #ifdef HAVE_INF_ENGINE #if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5) - InferenceEngine::Builder::ScaleShiftLayer ieLayer(name); - + InferenceEngine::Builder::Layer ieLayer = InferenceEngine::Builder::ScaleShiftLayer(name); const size_t numChannels = weights_.total(); - ieLayer.setWeights(wrapToInfEngineBlob(weights_, {numChannels}, InferenceEngine::Layout::C)); - ieLayer.setBiases(wrapToInfEngineBlob(bias_, {numChannels}, InferenceEngine::Layout::C)); + addConstantData("weights", wrapToInfEngineBlob(weights_, {numChannels}, InferenceEngine::Layout::C), ieLayer); + addConstantData("biases", wrapToInfEngineBlob(bias_, {numChannels}, InferenceEngine::Layout::C), ieLayer); return Ptr(new InfEngineBackendNode(ieLayer)); #else InferenceEngine::LayerParams lp; diff --git a/modules/dnn/src/layers/blank_layer.cpp b/modules/dnn/src/layers/blank_layer.cpp index 96336808a0..c3a68a2a42 100644 --- a/modules/dnn/src/layers/blank_layer.cpp +++ b/modules/dnn/src/layers/blank_layer.cpp @@ -125,7 +125,9 @@ public: ieLayer.getParameters()["axis"] = input->dims.size() - 1; ieLayer.getParameters()["out_sizes"] = input->dims[0]; } - ieLayer.setInputPorts(std::vector(1)); + std::vector shape(input->dims); + std::reverse(shape.begin(), shape.end()); + ieLayer.setInputPorts({InferenceEngine::Port(shape)}); ieLayer.setOutputPorts(std::vector(1)); return Ptr(new InfEngineBackendNode(ieLayer)); #else diff --git a/modules/dnn/src/layers/convolution_layer.cpp b/modules/dnn/src/layers/convolution_layer.cpp index 31665d7dcc..60611b52b2 100644 --- a/modules/dnn/src/layers/convolution_layer.cpp +++ b/modules/dnn/src/layers/convolution_layer.cpp @@ -493,11 +493,11 @@ public: ieLayer.setGroup((size_t)group); ieLayer.setOutDepth((size_t)outCn); - ieLayer.setWeights(ieWeights); + InferenceEngine::Builder::Layer l = ieLayer; + addConstantData("weights", ieWeights, l); if (ieBiases) - ieLayer.setBiases(ieBiases); + addConstantData("biases", ieBiases, l); - InferenceEngine::Builder::Layer l = ieLayer; if (!padMode.empty()) l.getParameters()["auto_pad"] = padMode == "VALID" ? std::string("valid") : std::string("same_upper"); @@ -1725,12 +1725,11 @@ public: ieLayer.setGroup((size_t)group); ieLayer.setOutDepth((size_t)numOutput); - ieLayer.setWeights(wrapToInfEngineBlob(blobs[0], InferenceEngine::Layout::OIHW)); + InferenceEngine::Builder::Layer l = ieLayer; + addConstantData("weights", wrapToInfEngineBlob(blobs[0], InferenceEngine::Layout::OIHW), l); if (hasBias()) - { - ieLayer.setBiases(wrapToInfEngineBlob(blobs[1], {(size_t)numOutput}, InferenceEngine::Layout::C)); - } - return Ptr(new InfEngineBackendNode(ieLayer)); + addConstantData("biases", wrapToInfEngineBlob(blobs[1], {(size_t)numOutput}, InferenceEngine::Layout::C), l); + return Ptr(new InfEngineBackendNode(l)); #else const int outGroupCn = blobs[0].size[1]; // Weights are in IOHW layout const int group = numOutput / outGroupCn; diff --git a/modules/dnn/src/layers/elementwise_layers.cpp b/modules/dnn/src/layers/elementwise_layers.cpp index b2e0621d6d..a18cce6fa9 100644 --- a/modules/dnn/src/layers/elementwise_layers.cpp +++ b/modules/dnn/src/layers/elementwise_layers.cpp @@ -1134,10 +1134,10 @@ struct ChannelsPReLUFunctor #if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5) InferenceEngine::Builder::Layer initInfEngineBuilderAPI() { - InferenceEngine::Builder::PReLULayer ieLayer(""); + InferenceEngine::Builder::Layer l = InferenceEngine::Builder::PReLULayer(""); const size_t numChannels = scale.total(); - ieLayer.setWeights(wrapToInfEngineBlob(scale, {numChannels}, InferenceEngine::Layout::C)); - return ieLayer; + addConstantData("weights", wrapToInfEngineBlob(scale, {numChannels}, InferenceEngine::Layout::C), l); + return l; } #else InferenceEngine::CNNLayerPtr initInfEngine(InferenceEngine::LayerParams& lp) diff --git a/modules/dnn/src/layers/fully_connected_layer.cpp b/modules/dnn/src/layers/fully_connected_layer.cpp index 3a71a872fe..dcfa7d1dac 100644 --- a/modules/dnn/src/layers/fully_connected_layer.cpp +++ b/modules/dnn/src/layers/fully_connected_layer.cpp @@ -448,11 +448,12 @@ public: const int outNum = blobs[0].size[0]; ieLayer.setOutputNum(outNum); - ieLayer.setWeights(wrapToInfEngineBlob(blobs[0], {(size_t)blobs[0].size[0], (size_t)blobs[0].size[1], 1, 1}, InferenceEngine::Layout::OIHW)); + InferenceEngine::Builder::Layer l = ieLayer; + addConstantData("weights", wrapToInfEngineBlob(blobs[0], {(size_t)blobs[0].size[0], (size_t)blobs[0].size[1], 1, 1}, InferenceEngine::Layout::OIHW), l); if (blobs.size() > 1) - ieLayer.setBiases(wrapToInfEngineBlob(blobs[1], {(size_t)outNum}, InferenceEngine::Layout::C)); + addConstantData("biases", wrapToInfEngineBlob(blobs[1], {(size_t)outNum}, InferenceEngine::Layout::C), l); - return Ptr(new InfEngineBackendNode(ieLayer)); + return Ptr(new InfEngineBackendNode(l)); #else InferenceEngine::LayerParams lp; lp.name = name; diff --git a/modules/dnn/src/layers/normalize_bbox_layer.cpp b/modules/dnn/src/layers/normalize_bbox_layer.cpp index 8e21f116e4..cf968f823f 100644 --- a/modules/dnn/src/layers/normalize_bbox_layer.cpp +++ b/modules/dnn/src/layers/normalize_bbox_layer.cpp @@ -295,7 +295,7 @@ public: l.getParameters()["channel_shared"] = blobs[0].total() == 1; } #if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R5) - l.getParameters()["weights"] = (InferenceEngine::Blob::CPtr)weights; + l.getParameters()["weights"] = weights; #else l.addConstantData("weights", weights); #endif diff --git a/modules/dnn/src/layers/prior_box_layer.cpp b/modules/dnn/src/layers/prior_box_layer.cpp index ac11fe7ada..b2907b7b8b 100644 --- a/modules/dnn/src/layers/prior_box_layer.cpp +++ b/modules/dnn/src/layers/prior_box_layer.cpp @@ -524,12 +524,12 @@ public: if (_stepX == _stepY) { l.getParameters()["step"] = _stepX; - l.getParameters()["step_h"] = 0.0; - l.getParameters()["step_w"] = 0.0; + l.getParameters()["step_h"] = 0.0f; + l.getParameters()["step_w"] = 0.0f; } else { - l.getParameters()["step"] = 0.0; + l.getParameters()["step"] = 0.0f; l.getParameters()["step_h"] = _stepY; l.getParameters()["step_w"] = _stepX; } diff --git a/modules/dnn/src/layers/scale_layer.cpp b/modules/dnn/src/layers/scale_layer.cpp index a11fd379a2..d911905d36 100644 --- a/modules/dnn/src/layers/scale_layer.cpp +++ b/modules/dnn/src/layers/scale_layer.cpp @@ -198,13 +198,13 @@ public: { #ifdef HAVE_INF_ENGINE #if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5) - InferenceEngine::Builder::ScaleShiftLayer ieLayer(name); + InferenceEngine::Builder::Layer l = InferenceEngine::Builder::ScaleShiftLayer(name); CV_Assert(!blobs.empty()); const size_t numChannels = blobs[0].total(); if (hasWeights) { - ieLayer.setWeights(wrapToInfEngineBlob(blobs[0], {numChannels}, InferenceEngine::Layout::C)); + addConstantData("weights", wrapToInfEngineBlob(blobs[0], {numChannels}, InferenceEngine::Layout::C), l); } else { @@ -214,11 +214,11 @@ public: std::vector ones(numChannels, 1); weights->set(ones); - ieLayer.setWeights(weights); + addConstantData("weights", weights, l); } if (hasBias) - ieLayer.setBiases(wrapToInfEngineBlob(blobs.back(), {numChannels}, InferenceEngine::Layout::C)); - return Ptr(new InfEngineBackendNode(ieLayer)); + addConstantData("biases", wrapToInfEngineBlob(blobs.back(), {numChannels}, InferenceEngine::Layout::C), l); + return Ptr(new InfEngineBackendNode(l)); #else InferenceEngine::LayerParams lp; lp.name = name; diff --git a/modules/dnn/src/op_inf_engine.cpp b/modules/dnn/src/op_inf_engine.cpp index a452064337..ddaab41cdc 100644 --- a/modules/dnn/src/op_inf_engine.cpp +++ b/modules/dnn/src/op_inf_engine.cpp @@ -18,6 +18,11 @@ namespace cv { namespace dnn { #ifdef HAVE_INF_ENGINE +// For networks with input layer which has an empty name, IE generates a name id[some_number]. +// OpenCV lets users use an empty input name and to prevent unexpected naming, +// we can use some predefined name. +static std::string kDefaultInpLayerName = "empty_inp_layer_name"; + #if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5) InfEngineBackendNode::InfEngineBackendNode(const InferenceEngine::Builder::Layer& _layer) : BackendNode(DNN_BACKEND_INFERENCE_ENGINE), layer(_layer) {} @@ -90,7 +95,7 @@ void InfEngineBackendNet::connect(const std::vector >& input it = layers.find(inpName); if (it == layers.end()) { - InferenceEngine::Builder::InputLayer inpLayer(inpName); + InferenceEngine::Builder::InputLayer inpLayer(!inpName.empty() ? inpName : kDefaultInpLayerName); std::vector shape(inp->blob->dims()); std::reverse(shape.begin(), shape.end()); @@ -119,6 +124,14 @@ void InfEngineBackendNet::init(int targetId) for (int id : unconnectedLayersIds) { InferenceEngine::Builder::OutputLayer outLayer("myconv1"); +#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R5) + // Inference Engine determines network precision by ports. + InferenceEngine::Precision p = (targetId == DNN_TARGET_MYRIAD || + targetId == DNN_TARGET_OPENCL_FP16) ? + InferenceEngine::Precision::FP16 : + InferenceEngine::Precision::FP32; + outLayer.setPort(InferenceEngine::Port({}, p)); +#endif netBuilder.addLayer({InferenceEngine::PortInfo(id)}, outLayer); } cnn = InferenceEngine::CNNNetwork(InferenceEngine::Builder::convertToICNNNetwork(netBuilder.build())); @@ -167,12 +180,56 @@ void InfEngineBackendNet::init(int targetId) initPlugin(cnn); } -void InfEngineBackendNet::addLayer(const InferenceEngine::Builder::Layer& layer) +void InfEngineBackendNet::addLayer(InferenceEngine::Builder::Layer& layer) { +#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R5) + // Add weights to network and connect them after input blobs. + std::map& params = layer.getParameters(); + std::vector blobsIds; + std::vector portIds; + for (const std::string& name : {"weights", "biases"}) + { + bool asInput = false; + int portId = 0; + for (int i = 0; i < layer.getInputPorts().size(); ++i) + { + const auto& port = layer.getInputPorts()[i]; + auto it = port.getParameters().find("type"); + if (it != port.getParameters().end() && it->second == name) + { + portId = i; + asInput = true; + break; + } + } + + if (!asInput) + continue; + + auto it = params.find(name); + if (it != params.end()) + { + InferenceEngine::Blob::Ptr blob = it->second.as(); + params.erase(it); + int blobId = netBuilder.addLayer(InferenceEngine::Builder::ConstLayer(name).setData(blob)); + blobsIds.push_back(blobId); + portIds.push_back(portId); + } + } +#endif + int id = netBuilder.addLayer(layer); const std::string& layerName = layer.getName(); CV_Assert(layers.insert({layerName, id}).second); unconnectedLayersIds.insert(id); + +#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R5) + // By default, all the weights are connected to last ports ids. + for (int i = 0; i < blobsIds.size(); ++i) + { + netBuilder.connect((size_t)blobsIds[i], {(size_t)id, portIds[i]}); + } +#endif } void InfEngineBackendNet::addOutput(const std::string& name) @@ -705,7 +762,7 @@ void InfEngineBackendNet::addBlobs(const std::vector >& ptrs { std::string name = wrapper->dataPtr->name; #if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5) - name = name.empty() ? "id1" : name; // TODO: drop the magic input name. + name = name.empty() ? kDefaultInpLayerName : name; #endif allBlobs.insert({name, wrapper->blob}); } @@ -776,6 +833,18 @@ InferenceEngine::Blob::Ptr convertFp16(const InferenceEngine::Blob::Ptr& blob) return halfs; } +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5) +void addConstantData(const std::string& name, InferenceEngine::Blob::Ptr data, + InferenceEngine::Builder::Layer& l) +{ +#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R5) + l.getParameters()[name] = data; +#else + l.addConstantData(name, data); +#endif +} +#endif + #endif // HAVE_INF_ENGINE bool haveInfEngine() diff --git a/modules/dnn/src/op_inf_engine.hpp b/modules/dnn/src/op_inf_engine.hpp index e912725296..ac72c0c69c 100644 --- a/modules/dnn/src/op_inf_engine.hpp +++ b/modules/dnn/src/op_inf_engine.hpp @@ -162,7 +162,7 @@ public: InfEngineBackendNet(InferenceEngine::CNNNetwork& net); - void addLayer(const InferenceEngine::Builder::Layer& layer); + void addLayer(InferenceEngine::Builder::Layer& layer); void addOutput(const std::string& name); @@ -255,6 +255,10 @@ Mat infEngineBlobToMat(const InferenceEngine::Blob::Ptr& blob); // Allocates memory for a new blob. InferenceEngine::Blob::Ptr convertFp16(const InferenceEngine::Blob::Ptr& blob); +#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5) +void addConstantData(const std::string& name, InferenceEngine::Blob::Ptr data, InferenceEngine::Builder::Layer& l); +#endif + // This is a fake class to run networks from Model Optimizer. Objects of that // class simulate responses of layers are imported by OpenCV and supported by // Inference Engine. The main difference is that they do not perform forward pass. diff --git a/modules/dnn/test/test_halide_layers.cpp b/modules/dnn/test/test_halide_layers.cpp index 879dd7bbf0..92af2e94ee 100644 --- a/modules/dnn/test/test_halide_layers.cpp +++ b/modules/dnn/test/test_halide_layers.cpp @@ -695,7 +695,8 @@ TEST_P(Eltwise, Accuracy) Target targetId = get<1>(get<4>(GetParam())); #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE > 2018050000 - if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_OPENCL) + if (backendId == DNN_BACKEND_INFERENCE_ENGINE && + (targetId == DNN_TARGET_OPENCL || targetId == DNN_TARGET_OPENCL_FP16)) throw SkipTestException(""); #endif From 7c72e095faf7f824fc43c0f481c066091d30a683 Mon Sep 17 00:00:00 2001 From: Lindsay Roberts Date: Tue, 19 Feb 2019 14:42:15 +0200 Subject: [PATCH 21/21] Fix Flann compilation under nvcc + NEON All includes in core/cv_cpu_dispatch.h are protected by an ifndef __CUDACC__ to prevent attempting to use neon intrinsics when compiling cuda kernels (.cu) -- this prevents hard errors such as error: identifier "__builtin_neon_qi" is undefined Add this same protection to flann/dist.h to fix compilation involving flann.hpp. --- modules/flann/include/opencv2/flann/dist.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/flann/include/opencv2/flann/dist.h b/modules/flann/include/opencv2/flann/dist.h index a65e712aed..2bb4fc947a 100644 --- a/modules/flann/include/opencv2/flann/dist.h +++ b/modules/flann/include/opencv2/flann/dist.h @@ -47,7 +47,7 @@ typedef unsigned __int64 uint64_t; # include #endif -#ifdef __ARM_NEON__ +#if defined(__ARM_NEON__) && !defined(__CUDACC__) # include "arm_neon.h" #endif @@ -425,7 +425,7 @@ struct Hamming ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const { ResultType result = 0; -#ifdef __ARM_NEON__ +#if defined(__ARM_NEON__) && !defined(__CUDACC__) { uint32x4_t bits = vmovq_n_u32(0); for (size_t i = 0; i < size; i += 16) {