Merge branch 4.x

This commit is contained in:
Alexander Smorkalov 2025-08-27 15:50:00 +03:00
commit d1a5723864
69 changed files with 7807 additions and 768 deletions

201
3rdparty/dlpack/LICENSE vendored Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017 by Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

366
3rdparty/dlpack/include/dlpack/dlpack.h vendored Normal file
View File

@ -0,0 +1,366 @@
/*!
* Copyright (c) 2017 by Contributors
* \file dlpack.h
* \brief The common header of DLPack.
*/
#ifndef DLPACK_DLPACK_H_
#define DLPACK_DLPACK_H_
/**
* \brief Compatibility with C++
*/
#ifdef __cplusplus
#define DLPACK_EXTERN_C extern "C"
#else
#define DLPACK_EXTERN_C
#endif
/*! \brief The current major version of dlpack */
#define DLPACK_MAJOR_VERSION 1
/*! \brief The current minor version of dlpack */
#define DLPACK_MINOR_VERSION 1
/*! \brief DLPACK_DLL prefix for windows */
#ifdef _WIN32
#ifdef DLPACK_EXPORTS
#define DLPACK_DLL __declspec(dllexport)
#else
#define DLPACK_DLL __declspec(dllimport)
#endif
#else
#define DLPACK_DLL
#endif
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/*!
* \brief The DLPack version.
*
* A change in major version indicates that we have changed the
* data layout of the ABI - DLManagedTensorVersioned.
*
* A change in minor version indicates that we have added new
* code, such as a new device type, but the ABI is kept the same.
*
* If an obtained DLPack tensor has a major version that disagrees
* with the version number specified in this header file
* (i.e. major != DLPACK_MAJOR_VERSION), the consumer must call the deleter
* (and it is safe to do so). It is not safe to access any other fields
* as the memory layout will have changed.
*
* In the case of a minor version mismatch, the tensor can be safely used as
* long as the consumer knows how to interpret all fields. Minor version
* updates indicate the addition of enumeration values.
*/
typedef struct {
/*! \brief DLPack major version. */
uint32_t major;
/*! \brief DLPack minor version. */
uint32_t minor;
} DLPackVersion;
/*!
* \brief The device type in DLDevice.
*/
#ifdef __cplusplus
typedef enum : int32_t {
#else
typedef enum {
#endif
/*! \brief CPU device */
kDLCPU = 1,
/*! \brief CUDA GPU device */
kDLCUDA = 2,
/*!
* \brief Pinned CUDA CPU memory by cudaMallocHost
*/
kDLCUDAHost = 3,
/*! \brief OpenCL devices. */
kDLOpenCL = 4,
/*! \brief Vulkan buffer for next generation graphics. */
kDLVulkan = 7,
/*! \brief Metal for Apple GPU. */
kDLMetal = 8,
/*! \brief Verilog simulator buffer */
kDLVPI = 9,
/*! \brief ROCm GPUs for AMD GPUs */
kDLROCM = 10,
/*!
* \brief Pinned ROCm CPU memory allocated by hipMallocHost
*/
kDLROCMHost = 11,
/*!
* \brief Reserved extension device type,
* used for quickly test extension device
* The semantics can differ depending on the implementation.
*/
kDLExtDev = 12,
/*!
* \brief CUDA managed/unified memory allocated by cudaMallocManaged
*/
kDLCUDAManaged = 13,
/*!
* \brief Unified shared memory allocated on a oneAPI non-partititioned
* device. Call to oneAPI runtime is required to determine the device
* type, the USM allocation type and the sycl context it is bound to.
*
*/
kDLOneAPI = 14,
/*! \brief GPU support for next generation WebGPU standard. */
kDLWebGPU = 15,
/*! \brief Qualcomm Hexagon DSP */
kDLHexagon = 16,
/*! \brief Microsoft MAIA devices */
kDLMAIA = 17,
} DLDeviceType;
/*!
* \brief A Device for Tensor and operator.
*/
typedef struct {
/*! \brief The device type used in the device. */
DLDeviceType device_type;
/*!
* \brief The device index.
* For vanilla CPU memory, pinned memory, or managed memory, this is set to 0.
*/
int32_t device_id;
} DLDevice;
/*!
* \brief The type code options DLDataType.
*/
typedef enum {
/*! \brief signed integer */
kDLInt = 0U,
/*! \brief unsigned integer */
kDLUInt = 1U,
/*! \brief IEEE floating point */
kDLFloat = 2U,
/*!
* \brief Opaque handle type, reserved for testing purposes.
* Frameworks need to agree on the handle data type for the exchange to be well-defined.
*/
kDLOpaqueHandle = 3U,
/*! \brief bfloat16 */
kDLBfloat = 4U,
/*!
* \brief complex number
* (C/C++/Python layout: compact struct per complex number)
*/
kDLComplex = 5U,
/*! \brief boolean */
kDLBool = 6U,
/*! \brief FP8 data types */
kDLFloat8_e3m4 = 7U,
kDLFloat8_e4m3 = 8U,
kDLFloat8_e4m3b11fnuz = 9U,
kDLFloat8_e4m3fn = 10U,
kDLFloat8_e4m3fnuz = 11U,
kDLFloat8_e5m2 = 12U,
kDLFloat8_e5m2fnuz = 13U,
kDLFloat8_e8m0fnu = 14U,
/*! \brief FP6 data types
* Setting bits != 6 is currently unspecified, and the producer must ensure it is set
* while the consumer must stop importing if the value is unexpected.
*/
kDLFloat6_e2m3fn = 15U,
kDLFloat6_e3m2fn = 16U,
/*! \brief FP4 data types
* Setting bits != 4 is currently unspecified, and the producer must ensure it is set
* while the consumer must stop importing if the value is unexpected.
*/
kDLFloat4_e2m1fn = 17U,
} DLDataTypeCode;
/*!
* \brief The data type the tensor can hold. The data type is assumed to follow the
* native endian-ness. An explicit error message should be raised when attempting to
* export an array with non-native endianness
*
* Examples
* - float: type_code = 2, bits = 32, lanes = 1
* - float4(vectorized 4 float): type_code = 2, bits = 32, lanes = 4
* - int8: type_code = 0, bits = 8, lanes = 1
* - std::complex<float>: type_code = 5, bits = 64, lanes = 1
* - bool: type_code = 6, bits = 8, lanes = 1 (as per common array library convention, the underlying storage size of bool is 8 bits)
* - float8_e4m3: type_code = 8, bits = 8, lanes = 1 (packed in memory)
* - float6_e3m2fn: type_code = 16, bits = 6, lanes = 1 (packed in memory)
* - float4_e2m1fn: type_code = 17, bits = 4, lanes = 1 (packed in memory)
*
* When a sub-byte type is packed, DLPack requires the data to be in little bit-endian, i.e.,
* for a packed data set D ((D >> (i * bits)) && bit_mask) stores the i-th element.
*/
typedef struct {
/*!
* \brief Type code of base types.
* We keep it uint8_t instead of DLDataTypeCode for minimal memory
* footprint, but the value should be one of DLDataTypeCode enum values.
* */
uint8_t code;
/*!
* \brief Number of bits, common choices are 8, 16, 32.
*/
uint8_t bits;
/*! \brief Number of lanes in the type, used for vector types. */
uint16_t lanes;
} DLDataType;
/*!
* \brief Plain C Tensor object, does not manage memory.
*/
typedef struct {
/*!
* \brief The data pointer points to the allocated data. This will be CUDA
* device pointer or cl_mem handle in OpenCL. It may be opaque on some device
* types. This pointer is always aligned to 256 bytes as in CUDA. The
* `byte_offset` field should be used to point to the beginning of the data.
*
* Note that as of Nov 2021, multiply libraries (CuPy, PyTorch, TensorFlow,
* TVM, perhaps others) do not adhere to this 256 byte aligment requirement
* on CPU/CUDA/ROCm, and always use `byte_offset=0`. This must be fixed
* (after which this note will be updated); at the moment it is recommended
* to not rely on the data pointer being correctly aligned.
*
* For given DLTensor, the size of memory required to store the contents of
* data is calculated as follows:
*
* \code{.c}
* static inline size_t GetDataSize(const DLTensor* t) {
* size_t size = 1;
* for (tvm_index_t i = 0; i < t->ndim; ++i) {
* size *= t->shape[i];
* }
* size *= (t->dtype.bits * t->dtype.lanes + 7) / 8;
* return size;
* }
* \endcode
*
* Note that if the tensor is of size zero, then the data pointer should be
* set to `NULL`.
*/
void* data;
/*! \brief The device of the tensor */
DLDevice device;
/*! \brief Number of dimensions */
int32_t ndim;
/*! \brief The data type of the pointer*/
DLDataType dtype;
/*! \brief The shape of the tensor */
int64_t* shape;
/*!
* \brief strides of the tensor (in number of elements, not bytes)
* can be NULL, indicating tensor is compact and row-majored.
*/
int64_t* strides;
/*! \brief The offset in bytes to the beginning pointer to data */
uint64_t byte_offset;
} DLTensor;
/*!
* \brief C Tensor object, manage memory of DLTensor. This data structure is
* intended to facilitate the borrowing of DLTensor by another framework. It is
* not meant to transfer the tensor. When the borrowing framework doesn't need
* the tensor, it should call the deleter to notify the host that the resource
* is no longer needed.
*
* \note This data structure is used as Legacy DLManagedTensor
* in DLPack exchange and is deprecated after DLPack v0.8
* Use DLManagedTensorVersioned instead.
* This data structure may get renamed or deleted in future versions.
*
* \sa DLManagedTensorVersioned
*/
typedef struct DLManagedTensor {
/*! \brief DLTensor which is being memory managed */
DLTensor dl_tensor;
/*! \brief the context of the original host framework of DLManagedTensor in
* which DLManagedTensor is used in the framework. It can also be NULL.
*/
void * manager_ctx;
/*!
* \brief Destructor - this should be called
* to destruct the manager_ctx which backs the DLManagedTensor. It can be
* NULL if there is no way for the caller to provide a reasonable destructor.
* The destructor deletes the argument self as well.
*/
void (*deleter)(struct DLManagedTensor * self);
} DLManagedTensor;
// bit masks used in in the DLManagedTensorVersioned
/*! \brief bit mask to indicate that the tensor is read only. */
#define DLPACK_FLAG_BITMASK_READ_ONLY (1UL << 0UL)
/*!
* \brief bit mask to indicate that the tensor is a copy made by the producer.
*
* If set, the tensor is considered solely owned throughout its lifetime by the
* consumer, until the producer-provided deleter is invoked.
*/
#define DLPACK_FLAG_BITMASK_IS_COPIED (1UL << 1UL)
/*
* \brief bit mask to indicate that whether a sub-byte type is packed or padded.
*
* The default for sub-byte types (ex: fp4/fp6) is assumed packed. This flag can
* be set by the producer to signal that a tensor of sub-byte type is padded.
*/
#define DLPACK_FLAG_BITMASK_IS_SUBBYTE_TYPE_PADDED (1UL << 2UL)
/*!
* \brief A versioned and managed C Tensor object, manage memory of DLTensor.
*
* This data structure is intended to facilitate the borrowing of DLTensor by
* another framework. It is not meant to transfer the tensor. When the borrowing
* framework doesn't need the tensor, it should call the deleter to notify the
* host that the resource is no longer needed.
*
* \note This is the current standard DLPack exchange data structure.
*/
struct DLManagedTensorVersioned {
/*!
* \brief The API and ABI version of the current managed Tensor
*/
DLPackVersion version;
/*!
* \brief the context of the original host framework.
*
* Stores DLManagedTensorVersioned is used in the
* framework. It can also be NULL.
*/
void *manager_ctx;
/*!
* \brief Destructor.
*
* This should be called to destruct manager_ctx which holds the DLManagedTensorVersioned.
* It can be NULL if there is no way for the caller to provide a reasonable
* destructor. The destructor deletes the argument self as well.
*/
void (*deleter)(struct DLManagedTensorVersioned *self);
/*!
* \brief Additional bitmask flags information about the tensor.
*
* By default the flags should be set to 0.
*
* \note Future ABI changes should keep everything until this field
* stable, to ensure that deleter can be correctly called.
*
* \sa DLPACK_FLAG_BITMASK_READ_ONLY
* \sa DLPACK_FLAG_BITMASK_IS_COPIED
*/
uint64_t flags;
/*! \brief DLTensor which is being memory managed */
DLTensor dl_tensor;
};
#ifdef __cplusplus
} // DLPACK_EXTERN_C
#endif
#endif // DLPACK_DLPACK_H_

View File

@ -2,7 +2,7 @@ function(download_ippicv root_var)
set(${root_var} "" PARENT_SCOPE)
# Commit SHA in the opencv_3rdparty repo
set(IPPICV_COMMIT "767426b2a40a011eb2fa7f44c677c13e60e205ad")
set(IPPICV_COMMIT "c934a2a15a6df020446ac3dfa07e3acf72b63a8f")
# Define actual ICV versions
if(APPLE)
set(IPPICV_COMMIT "0cc4aa06bf2bef4b05d237c69a5a96b9cd0cb85a")
@ -14,8 +14,8 @@ function(download_ippicv root_var)
set(OPENCV_ICV_PLATFORM "linux")
set(OPENCV_ICV_PACKAGE_SUBDIR "ippicv_lnx")
if(X86_64)
set(OPENCV_ICV_NAME "ippicv_2022.1.0_lnx_intel64_20250130_general.tgz")
set(OPENCV_ICV_HASH "98ff71fc242d52db9cc538388e502f57")
set(OPENCV_ICV_NAME "ippicv_2022.2.0_lnx_intel64_20250730_general.tgz")
set(OPENCV_ICV_HASH "55d18247d8ef707f009b94f69d77b948")
else()
if(ANDROID)
set(IPPICV_COMMIT "c7c6d527dde5fee7cb914ee9e4e20f7436aab3a1")
@ -31,8 +31,8 @@ function(download_ippicv root_var)
set(OPENCV_ICV_PLATFORM "windows")
set(OPENCV_ICV_PACKAGE_SUBDIR "ippicv_win")
if(X86_64)
set(OPENCV_ICV_NAME "ippicv_2022.1.0_win_intel64_20250130_general.zip")
set(OPENCV_ICV_HASH "67a611ab22410f392239bddff6f91df7")
set(OPENCV_ICV_NAME "ippicv_2022.2.0_win_intel64_20250730_general.zip")
set(OPENCV_ICV_HASH "7c0973976ab0716bc33f03a76a50017f")
else()
set(IPPICV_COMMIT "7f55c0c26be418d494615afca15218566775c725")
set(OPENCV_ICV_NAME "ippicv_2021.12.0_win_ia32_20240425_general.zip")

View File

@ -358,7 +358,7 @@ if(LIBLZMA_LIBRARIES)
endif()
set(LIBTIFF_MAJOR_VERSION "4")
set(LIBTIFF_MINOR_VERSION "6")
set(LIBTIFF_MINOR_VERSION "7")
set(LIBTIFF_MICRO_VERSION "0")
set(LIBTIFF_VERSION "${LIBTIFF_MAJOR_VERSION}.${LIBTIFF_MINOR_VERSION}.${LIBTIFF_MICRO_VERSION}")
file(READ "RELEASE-DATE" LIBTIFF_RELEASE_DATE content)

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
20230908
20240911

View File

@ -385,53 +385,6 @@ int TIFFGetFieldDefaulted(TIFF *tif, uint32_t tag, ...)
return (ok);
}
struct _Int64Parts
{
int32_t low, high;
};
typedef union
{
struct _Int64Parts part;
int64_t value;
} _Int64;
float _TIFFUInt64ToFloat(uint64_t ui64)
{
_Int64 i;
i.value = ui64;
if (i.part.high >= 0)
{
return (float)i.value;
}
else
{
long double df;
df = (long double)i.value;
df += 18446744073709551616.0; /* adding 2**64 */
return (float)df;
}
}
double _TIFFUInt64ToDouble(uint64_t ui64)
{
_Int64 i;
i.value = ui64;
if (i.part.high >= 0)
{
return (double)i.value;
}
else
{
long double df;
df = (long double)i.value;
df += 18446744073709551616.0; /* adding 2**64 */
return (double)df;
}
}
float _TIFFClampDoubleToFloat(double val)
{
if (val > FLT_MAX)

View File

@ -110,6 +110,14 @@ void TIFFCleanup(TIFF *tif)
_TIFFfreeExt(tif, tif->tif_fieldscompat);
}
if (tif->tif_cur_cumulated_mem_alloc != 0)
{
TIFFErrorExtR(tif, "TIFFCleanup",
"tif_cur_cumulated_mem_alloc = %" PRIu64 " whereas it "
"should be 0",
(uint64_t)tif->tif_cur_cumulated_mem_alloc);
}
_TIFFfreeExt(NULL, tif);
}

View File

@ -89,7 +89,7 @@ void TIFFCIELab16ToXYZ(TIFFCIELabToRGB *cielab, uint32_t l, int32_t a,
void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
uint32_t *r, uint32_t *g, uint32_t *b)
{
int i;
size_t i;
float Yr, Yg, Yb;
float *matrix = &cielab->display.d_mat[0][0];
@ -109,16 +109,16 @@ void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
Yb = TIFFmin(Yb, cielab->display.d_YCB);
/* Turn luminosity to colour value. */
i = (int)((Yr - cielab->display.d_Y0R) / cielab->rstep);
i = TIFFmin(cielab->range, i);
i = (size_t)((Yr - cielab->display.d_Y0R) / cielab->rstep);
i = TIFFmin((size_t)cielab->range, i);
*r = RINT(cielab->Yr2r[i]);
i = (int)((Yg - cielab->display.d_Y0G) / cielab->gstep);
i = TIFFmin(cielab->range, i);
i = (size_t)((Yg - cielab->display.d_Y0G) / cielab->gstep);
i = TIFFmin((size_t)cielab->range, i);
*g = RINT(cielab->Yg2g[i]);
i = (int)((Yb - cielab->display.d_Y0B) / cielab->bstep);
i = TIFFmin(cielab->range, i);
i = (size_t)((Yb - cielab->display.d_Y0B) / cielab->bstep);
i = TIFFmin((size_t)cielab->range, i);
*b = RINT(cielab->Yb2b[i]);
/* Clip output. */
@ -135,7 +135,7 @@ void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display,
float *refWhite)
{
int i;
size_t i;
double dfGamma;
cielab->range = CIELABTORGB_TABLE_RANGE;
@ -146,7 +146,7 @@ int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display,
dfGamma = 1.0 / cielab->display.d_gammaR;
cielab->rstep =
(cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
for (i = 0; i <= cielab->range; i++)
for (i = 0; i <= (size_t)cielab->range; i++)
{
cielab->Yr2r[i] = cielab->display.d_Vrwr *
((float)pow((double)i / cielab->range, dfGamma));
@ -156,7 +156,7 @@ int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display,
dfGamma = 1.0 / cielab->display.d_gammaG;
cielab->gstep =
(cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
for (i = 0; i <= cielab->range; i++)
for (i = 0; i <= (size_t)cielab->range; i++)
{
cielab->Yg2g[i] = cielab->display.d_Vrwg *
((float)pow((double)i / cielab->range, dfGamma));
@ -166,7 +166,7 @@ int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display,
dfGamma = 1.0 / cielab->display.d_gammaB;
cielab->bstep =
(cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
for (i = 0; i <= cielab->range; i++)
for (i = 0; i <= (size_t)cielab->range; i++)
{
cielab->Yb2b[i] = cielab->display.d_Vrwb *
((float)pow((double)i / cielab->range, dfGamma));

View File

@ -40,6 +40,18 @@
/* Define to 1 if you have the `getopt' function. */
#cmakedefine HAVE_GETOPT 1
/* Define to 1 if you have the <GLUT/glut.h> header file. */
#cmakedefine HAVE_GLUT_GLUT_H 1
/* Define to 1 if you have the <GL/glut.h> header file. */
#cmakedefine HAVE_GL_GLUT_H 1
/* Define to 1 if you have the <GL/glu.h> header file. */
#cmakedefine HAVE_GL_GLU_H 1
/* Define to 1 if you have the <GL/gl.h> header file. */
#cmakedefine HAVE_GL_GL_H 1
/* Define to 1 if you have the <io.h> header file. */
#cmakedefine HAVE_IO_H 1
@ -49,6 +61,12 @@
/* Define to 1 if you have the `mmap' function. */
#cmakedefine HAVE_MMAP 1
/* Define to 1 if you have the <OpenGL/glu.h> header file. */
#cmakedefine HAVE_OPENGL_GLU_H 1
/* Define to 1 if you have the <OpenGL/gl.h> header file. */
#cmakedefine HAVE_OPENGL_GL_H 1
/* Define to 1 if you have the `setmode' function. */
#cmakedefine HAVE_SETMODE 1

View File

@ -211,7 +211,7 @@ static uint16_t countInkNamesString(TIFF *tif, uint32_t slen, const char *s)
}
bad:
TIFFErrorExtR(tif, "TIFFSetField",
"%s: Invalid InkNames value; no NUL at given buffer end "
"%s: Invalid InkNames value; no null at given buffer end "
"location %" PRIu32 ", after %" PRIu16 " ink",
tif->tif_name, slen, i);
return (0);
@ -1652,6 +1652,17 @@ void TIFFFreeDirectory(TIFF *tif)
_TIFFmemset(&(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
_TIFFmemset(&(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
/* Reset some internal parameters for IFD data size checking. */
tif->tif_dir.td_dirdatasize_read = 0;
tif->tif_dir.td_dirdatasize_write = 0;
if (tif->tif_dir.td_dirdatasize_offsets != NULL)
{
_TIFFfreeExt(tif, tif->tif_dir.td_dirdatasize_offsets);
tif->tif_dir.td_dirdatasize_offsets = NULL;
tif->tif_dir.td_dirdatasize_Noffsets = 0;
}
tif->tif_dir.td_iswrittentofile = FALSE;
}
#undef CleanupField
@ -1676,18 +1687,23 @@ TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc extender)
*/
int TIFFCreateDirectory(TIFF *tif)
{
/* Free previously allocated memory and setup default values. */
TIFFFreeDirectory(tif);
TIFFDefaultDirectory(tif);
tif->tif_diroff = 0;
tif->tif_nextdiroff = 0;
tif->tif_curoff = 0;
tif->tif_row = (uint32_t)-1;
tif->tif_curstrip = (uint32_t)-1;
tif->tif_dir.td_iswrittentofile = FALSE;
return 0;
}
int TIFFCreateCustomDirectory(TIFF *tif, const TIFFFieldArray *infoarray)
{
/* Free previously allocated memory and setup default values. */
TIFFFreeDirectory(tif);
TIFFDefaultDirectory(tif);
/*
@ -1848,7 +1864,9 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
if (((uint64_t)poffa != poff) || (poffb < poffa) ||
(poffb < (tmsize_t)sizeof(uint16_t)) || (poffb > tif->tif_size))
{
TIFFErrorExtR(tif, module, "Error fetching directory count");
TIFFErrorExtR(tif, module,
"%s:%d: %s: Error fetching directory count",
__FILE__, __LINE__, tif->tif_name);
*nextdiroff = 0;
return (0);
}
@ -1877,14 +1895,18 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
uint16_t dircount16;
if (poff > (uint64_t)TIFF_TMSIZE_T_MAX - sizeof(uint64_t))
{
TIFFErrorExtR(tif, module, "Error fetching directory count");
TIFFErrorExtR(tif, module,
"%s:%d: %s: Error fetching directory count",
__FILE__, __LINE__, tif->tif_name);
return (0);
}
poffa = (tmsize_t)poff;
poffb = poffa + sizeof(uint64_t);
if (poffb > tif->tif_size)
{
TIFFErrorExtR(tif, module, "Error fetching directory count");
TIFFErrorExtR(tif, module,
"%s:%d: %s: Error fetching directory count",
__FILE__, __LINE__, tif->tif_name);
return (0);
}
_TIFFmemcpy(&dircount64, tif->tif_base + poffa, sizeof(uint64_t));
@ -1926,8 +1948,9 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
if (!SeekOK(tif, *nextdiroff) ||
!ReadOK(tif, &dircount, sizeof(uint16_t)))
{
TIFFErrorExtR(tif, module, "%s: Error fetching directory count",
tif->tif_name);
TIFFErrorExtR(tif, module,
"%s:%d: %s: Error fetching directory count",
__FILE__, __LINE__, tif->tif_name);
return (0);
}
if (tif->tif_flags & TIFF_SWAB)
@ -1953,15 +1976,18 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
if (!SeekOK(tif, *nextdiroff) ||
!ReadOK(tif, &dircount64, sizeof(uint64_t)))
{
TIFFErrorExtR(tif, module, "%s: Error fetching directory count",
tif->tif_name);
TIFFErrorExtR(tif, module,
"%s:%d: %s: Error fetching directory count",
__FILE__, __LINE__, tif->tif_name);
return (0);
}
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8(&dircount64);
if (dircount64 > 0xFFFF)
{
TIFFErrorExtR(tif, module, "Error fetching directory count");
TIFFErrorExtR(tif, module,
"%s:%d: %s: Error fetching directory count",
__FILE__, __LINE__, tif->tif_name);
return (0);
}
dircount16 = (uint16_t)dircount64;
@ -2018,6 +2044,8 @@ tdir_t TIFFNumberOfDirectories(TIFF *tif)
{
++n;
}
/* Update number of main-IFDs in file. */
tif->tif_curdircount = n;
return (n);
}
@ -2100,7 +2128,19 @@ int TIFFSetDirectory(TIFF *tif, tdir_t dirn)
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
else
tif->tif_curdir--;
return (TIFFReadDirectory(tif));
tdir_t curdir = tif->tif_curdir;
int retval = TIFFReadDirectory(tif);
if (!retval && tif->tif_curdir == curdir)
{
/* If tif_curdir has not be incremented, TIFFFetchDirectory() in
* TIFFReadDirectory() has failed and tif_curdir shall be set
* specifically. */
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
}
return (retval);
}
/*
@ -2125,8 +2165,11 @@ int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff)
int8_t probablySubIFD = 0;
if (diroff == 0)
{
/* Special case to invalidate the tif_lastdiroff member. */
/* Special case to set tif_diroff=0, which is done in
* TIFFReadDirectory() below to indicate that the currently read IFD is
* treated as a new, fresh IFD. */
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
tif->tif_dir.td_iswrittentofile = FALSE;
}
else
{
@ -2136,32 +2179,40 @@ int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff)
probablySubIFD = 1;
}
/* -1 because TIFFReadDirectory() will increment tif_curdir. */
tif->tif_curdir =
curdir == 0 ? TIFF_NON_EXISTENT_DIR_NUMBER : curdir - 1;
if (curdir >= 1)
tif->tif_curdir = curdir - 1;
else
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
}
curdir = tif->tif_curdir;
tif->tif_nextdiroff = diroff;
retval = TIFFReadDirectory(tif);
/* If failed, curdir was not incremented in TIFFReadDirectory(), so set it
* back, but leave it for diroff==0. */
if (!retval && diroff != 0)
/* tif_curdir is incremented in TIFFReadDirectory(), but if it has not been
* incremented, TIFFFetchDirectory() has failed there and tif_curdir shall
* be set specifically. */
if (!retval && diroff != 0 && tif->tif_curdir == curdir)
{
if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER)
tif->tif_curdir = 0;
else
tif->tif_curdir++;
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
}
if (retval && probablySubIFD)
if (probablySubIFD)
{
/* Reset IFD list to start new one for SubIFD chain and also start
* SubIFD chain with tif_curdir=0. */
_TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */
tif->tif_curdir = 0; /* first directory of new chain */
/* add this offset to new IFD list */
_TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, diroff);
if (retval)
{
/* Reset IFD list to start new one for SubIFD chain and also start
* SubIFD chain with tif_curdir=0 for IFD loop checking. */
/* invalidate IFD loop lists */
_TIFFCleanupIFDOffsetAndNumberMaps(tif);
tif->tif_curdir = 0; /* first directory of new chain */
/* add this offset to new IFD list */
_TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, diroff);
}
/* To be able to return from SubIFD or custom-IFD to main-IFD */
tif->tif_setdirectory_force_absolute = TRUE;
}
return (retval);
}
@ -2257,9 +2308,11 @@ int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn)
}
else
{
/* Need local swap because nextdir has to be used unswapped below. */
uint64_t nextdir64 = nextdir;
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8(&nextdir);
if (!WriteOK(tif, &nextdir, sizeof(uint64_t)))
TIFFSwabLong8(&nextdir64);
if (!WriteOK(tif, &nextdir64, sizeof(uint64_t)))
{
TIFFErrorExtR(tif, module, "Error writing directory link");
return (0);
@ -2303,6 +2356,10 @@ int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn)
tif->tif_row = (uint32_t)-1;
tif->tif_curstrip = (uint32_t)-1;
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
if (tif->tif_curdircount > 0)
tif->tif_curdircount--;
else
tif->tif_curdircount = TIFF_NON_EXISTENT_DIR_NUMBER;
_TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */
return (1);
}

View File

@ -65,6 +65,12 @@ typedef struct
tif_dirread.c */
} TIFFDirEntry;
typedef struct
{
uint64_t offset;
uint64_t length;
} TIFFEntryOffsetAndLength; /* auxiliary for evaluating size of IFD data */
/*
* Internal format of a TIFF directory entry.
*/
@ -115,6 +121,9 @@ typedef struct
#ifdef STRIPBYTECOUNTSORTED_UNUSED
int td_stripbytecountsorted; /* is the bytecount array sorted ascending? */
#endif
/* Be aware that the parameters of td_stripoffset_entry and
* td_stripbytecount_entry are swapped but tdir_offset is not
* and has to be swapped when used. */
TIFFDirEntry td_stripoffset_entry; /* for deferred loading */
TIFFDirEntry td_stripbytecount_entry; /* for deferred loading */
uint16_t td_nsubifd;
@ -135,6 +144,24 @@ typedef struct
unsigned char
td_deferstrilearraywriting; /* see TIFFDeferStrileArrayWriting() */
unsigned char
td_iswrittentofile; /* indicates if current IFD is present on file */
/* LibTIFF writes all data that does not fit into the IFD entries directly
* after the IFD tag entry part. When reading, only the IFD data directly
* and continuously behind the IFD tags is taken into account for the IFD
* data size.*/
uint64_t td_dirdatasize_write; /* auxiliary for evaluating size of IFD data
to be written */
uint64_t td_dirdatasize_read; /* auxiliary for evaluating size of IFD data
read from file */
uint32_t td_dirdatasize_Noffsets; /* auxiliary counter for
tif_dir.td_dirdatasize_offsets array */
TIFFEntryOffsetAndLength
*td_dirdatasize_offsets; /* auxiliary array for all offsets of IFD tag
entries with data outside the IFD tag
entries. */
} TIFFDirectory;
/*
@ -308,11 +335,10 @@ extern "C"
TIFFDataType field_type; /* type of associated data */
uint32_t
field_anonymous; /* if true, this is a unknown / anonymous tag */
TIFFSetGetFieldType
set_field_type; /* type to be passed to TIFFSetField */
TIFFSetGetFieldType
get_field_type; /* type to be passed to TIFFGetField */
unsigned short field_bit; /* bit in fieldsset bit vector */
TIFFSetGetFieldType set_field_type; /* type to be passed to TIFFSetField
and TIFFGetField*/
TIFFSetGetFieldType get_field_type; /* not used */
unsigned short field_bit; /* bit in fieldsset bit vector */
unsigned char field_oktochange; /* if true, can change while writing */
unsigned char field_passcount; /* if true, pass dir count on set */
char *field_name; /* ASCII name */

View File

@ -213,8 +213,6 @@ static const TIFFField tiffFields[] = {
{TIFFTAG_CURRENTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CurrentPreProfileMatrix", NULL},
{TIFFTAG_PERSAMPLE, 0, 0, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "PerSample", NULL},
#if 0
/* TODO: revert above #if 0 for TIFF 4.6.0 */
/* begin DNG 1.2.0.0 tags */
{TIFFTAG_COLORIMETRICREFERENCE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ColorimetricReference", NULL},
{TIFFTAG_CAMERACALIBRATIONSIGNATURE, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CameraCalibrationSignature", NULL},
@ -282,9 +280,11 @@ static const TIFFField tiffFields[] = {
{TIFFTAG_ILLUMINANTDATA2, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "IlluminantData2", NULL},
{TIFFTAG_ILLUMINANTDATA3, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "IlluminantData3", NULL},
/* end DNG tags */
#endif
/* begin TIFF/EP tags */
{TIFFTAG_EP_CFAREPEATPATTERNDIM, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP CFARepeatPatternDim", NULL},
{TIFFTAG_EP_CFAPATTERN, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP CFAPattern", NULL},
#if 0
/* TIFFTAG_EP_BATTERYLEVEL can be RATIONAL or ASCII.
* LibTiff defines it as ASCII and converts RATIONAL to an ASCII string. */
{TIFFTAG_EP_BATTERYLEVEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP BatteryLevel", NULL},
@ -374,7 +374,7 @@ static const TIFFField exifFields[] = {
{EXIFTAG_BRIGHTNESSVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BrightnessValue", NULL},
{EXIFTAG_EXPOSUREBIASVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureBiasValue", NULL},
{EXIFTAG_MAXAPERTUREVALUE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MaxApertureValue", NULL},
/*--: EXIFTAG_SUBJECTDISTANCE: LibTiff returns value of "-1" if numerator equals 4294967295 (0xFFFFFFFF) to indicate infinite distance!
/*--: EXIFTAG_SUBJECTDISTANCE: LibTiff returns value of "-1" if numerator equals 4294967295 (0xFFFFFFFF) to indicate infinite distance!
* However, there are two other EXIF tags where numerator indicates a special value and six other cases where the denominator indicates special values,
* which are not treated within LibTiff!! */
{EXIFTAG_SUBJECTDISTANCE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectDistance", NULL},
@ -887,7 +887,7 @@ const TIFFField *_TIFFFindOrRegisterField(TIFF *tif, uint32_t tag,
if (fld == NULL)
{
fld = _TIFFCreateAnonField(tif, tag, dt);
if (!_TIFFMergeFields(tif, fld, 1))
if (fld == NULL || !_TIFFMergeFields(tif, fld, 1))
return NULL;
}
@ -1197,12 +1197,24 @@ int TIFFMergeFieldInfo(TIFF *tif, const TIFFFieldInfo info[], uint32_t n)
for (i = 0; i < n; i++)
{
tp->field_tag = info[i].field_tag;
if (info[i].field_readcount < TIFF_VARIABLE2 ||
info[i].field_readcount == 0 ||
info[i].field_writecount < TIFF_VARIABLE2 ||
info[i].field_writecount == 0)
{
/* The fields (field_readcount) and (field_writecount) may use the
* values TIFF_VARIABLE (-1), TIFF_SPP (-2), TIFF_VARIABLE2 (-3). */
TIFFErrorExtR(tif, module,
"The value of field_readcount and field_writecount "
"must be greater than or equal to -3 and not zero.");
return -1;
}
tp->field_readcount = info[i].field_readcount;
tp->field_writecount = info[i].field_writecount;
tp->field_type = info[i].field_type;
tp->field_anonymous = 0;
tp->set_field_type =
_TIFFSetGetType(info[i].field_type, info[i].field_readcount,
_TIFFSetGetType(info[i].field_type, info[i].field_writecount,
info[i].field_passcount);
tp->get_field_type =
_TIFFSetGetType(info[i].field_type, info[i].field_readcount,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -41,6 +41,14 @@
#include "t4.h"
#include <stdio.h>
#ifndef EOF_REACHED_COUNT_THRESHOLD
/* Arbitrary threshold to avoid corrupted single-strip files with extremely
* large imageheight to cause apparently endless looping, such as in
* https://gitlab.com/libtiff/libtiff/-/issues/583
*/
#define EOF_REACHED_COUNT_THRESHOLD 8192
#endif
/*
* Compression+decompression state blocks are
* derived from this ``base state'' block.
@ -77,6 +85,8 @@ typedef struct
uint32_t data; /* current i/o byte/word */
int bit; /* current i/o bit in byte */
int EOLcnt; /* count of EOL codes recognized */
int eofReachedCount; /* number of times decode has been called with
EOF already reached */
TIFFFaxFillFunc fill; /* fill routine */
uint32_t *runs; /* b&w runs for current/previous row */
uint32_t nruns; /* size of the refruns / curruns arrays */
@ -120,6 +130,7 @@ typedef struct
int EOLcnt; /* # EOL codes recognized */ \
const unsigned char *bitmap = sp->bitmap; /* input data bit reverser */ \
const TIFFFaxTabEnt *TabEnt
#define DECLARE_STATE_2D(tif, sp, mod) \
DECLARE_STATE(tif, sp, mod); \
int b1; /* next change on prev line */ \
@ -162,6 +173,7 @@ static int Fax3PreDecode(TIFF *tif, uint16_t s)
sp->bit = 0; /* force initial read */
sp->data = 0;
sp->EOLcnt = 0; /* force initial scan for EOL */
sp->eofReachedCount = 0;
/*
* Decoder assumes lsb-to-msb bit order. Note that we select
* this here rather than in Fax3SetupState so that viewers can
@ -232,7 +244,12 @@ static void Fax3PrematureEOF(const char *module, TIFF *tif, uint32_t line,
line, isTiled(tif) ? "tile" : "strip",
(isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), a0);
}
#define prematureEOF(a0) Fax3PrematureEOF(module, tif, sp->line, a0)
#define prematureEOF(a0) \
do \
{ \
Fax3PrematureEOF(module, tif, sp->line, a0); \
++sp->eofReachedCount; \
} while (0)
#define Nop
@ -252,6 +269,14 @@ static int Fax3Decode1D(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
return (-1);
}
if (sp->eofReachedCount >= EOF_REACHED_COUNT_THRESHOLD)
{
TIFFErrorExtR(
tif, module,
"End of file has already been reached %d times within that strip",
sp->eofReachedCount);
return (-1);
}
CACHE_STATE(tif, sp);
thisrun = sp->curruns;
while (occ > 0)
@ -302,6 +327,14 @@ static int Fax3Decode2D(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
return (-1);
}
if (sp->eofReachedCount >= EOF_REACHED_COUNT_THRESHOLD)
{
TIFFErrorExtR(
tif, module,
"End of file has already been reached %d times within that strip",
sp->eofReachedCount);
return (-1);
}
CACHE_STATE(tif, sp);
while (occ > 0)
{
@ -536,7 +569,11 @@ static int Fax3SetupState(TIFF *tif)
TIFFroundup and TIFFSafeMultiply return zero on integer overflow
*/
dsp->runs = (uint32_t *)NULL;
if (dsp->runs != NULL)
{
_TIFFfreeExt(tif, dsp->runs);
dsp->runs = (uint32_t *)NULL;
}
dsp->nruns = TIFFroundup_32(rowpixels + 1, 32);
if (needsRefLine)
{
@ -578,6 +615,10 @@ static int Fax3SetupState(TIFF *tif)
* is referenced. The reference line must
* be initialized to be ``white'' (done elsewhere).
*/
if (esp->refline != NULL)
{
_TIFFfreeExt(tif, esp->refline);
}
esp->refline = (unsigned char *)_TIFFmallocExt(tif, rowbytes);
if (esp->refline == NULL)
{
@ -1514,7 +1555,16 @@ static int Fax4Decode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
return (-1);
}
if (sp->eofReachedCount >= EOF_REACHED_COUNT_THRESHOLD)
{
TIFFErrorExtR(
tif, module,
"End of file has already been reached %d times within that strip",
sp->eofReachedCount);
return (-1);
}
CACHE_STATE(tif, sp);
int start = sp->line;
while (occ > 0)
{
a0 = 0;
@ -1563,7 +1613,9 @@ static int Fax4Decode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
}
(*sp->fill)(buf, thisrun, pa, lastx);
UNCACHE_STATE(tif, sp);
return (sp->line ? 1 : -1); /* don't error on badly-terminated strips */
return (sp->line != start
? 1
: -1); /* don't error on badly-terminated strips */
}
UNCACHE_STATE(tif, sp);
return (1);

View File

@ -760,6 +760,12 @@ static int gtTileContig(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
toskew = -(int32_t)(tw - w);
}
if (tw == 0 || th == 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif), "tile width or height is zero");
return (0);
}
/*
* Leftmost tile is clipped on left side if col_offset > 0.
*/
@ -916,6 +922,12 @@ static int gtTileSeparate(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
break;
}
if (tw == 0 || th == 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif), "tile width or height is zero");
return (0);
}
/*
* Leftmost tile is clipped on left side if col_offset > 0.
*/
@ -1092,6 +1104,11 @@ static int gtStripContig(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
}
TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
if (rowsperstrip == 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
return (0);
}
scanline = TIFFScanlineSize(tif);
fromskew = (w < imagewidth ? imagewidth - w : 0);
@ -1216,6 +1233,12 @@ static int gtStripSeparate(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
}
TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
if (rowsperstrip == 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
return (0);
}
scanline = TIFFScanlineSize(tif);
fromskew = (w < imagewidth ? imagewidth - w : 0);
for (row = 0; row < h; row += nrow)
@ -3213,6 +3236,13 @@ int TIFFReadRGBAStripExt(TIFF *tif, uint32_t row, uint32_t *raster,
}
TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
if (rowsperstrip == 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
return (0);
}
if ((row % rowsperstrip) != 0)
{
TIFFErrorExtR(
@ -3224,6 +3254,13 @@ int TIFFReadRGBAStripExt(TIFF *tif, uint32_t row, uint32_t *raster,
if (TIFFRGBAImageOK(tif, emsg) &&
TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg))
{
if (row >= img.height)
{
TIFFErrorExtR(tif, TIFFFileName(tif),
"Invalid row passed to TIFFReadRGBAStrip().");
TIFFRGBAImageEnd(&img);
return (0);
}
img.row_offset = row;
img.col_offset = 0;
@ -3282,6 +3319,13 @@ int TIFFReadRGBATileExt(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster,
TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize);
TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize);
if (tile_xsize == 0 || tile_ysize == 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif),
"tile_xsize or tile_ysize is zero");
return (0);
}
if ((col % tile_xsize) != 0 || (row % tile_ysize) != 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif),
@ -3301,6 +3345,14 @@ int TIFFReadRGBATileExt(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster,
return (0);
}
if (col >= img.width || row >= img.height)
{
TIFFErrorExtR(tif, TIFFFileName(tif),
"Invalid row/col passed to TIFFReadRGBATile().");
TIFFRGBAImageEnd(&img);
return (0);
}
/*
* The TIFFRGBAImageGet() function doesn't allow us to get off the
* edge of the image, even to fill an otherwise valid tile. So we

View File

@ -92,6 +92,7 @@ static int JBIGDecode(TIFF *tif, uint8_t *buffer, tmsize_t size, uint16_t s)
jbg_strerror(decodeStatus)
#endif
);
memset(buffer, 0, (size_t)size);
jbg_dec_free(&decoder);
return 0;
}
@ -99,6 +100,7 @@ static int JBIGDecode(TIFF *tif, uint8_t *buffer, tmsize_t size, uint16_t s)
decodedSize = jbg_dec_getsize(&decoder);
if ((tmsize_t)decodedSize < size)
{
memset(buffer + decodedSize, 0, (size_t)(size - decodedSize));
TIFFWarningExtR(tif, "JBIG",
"Only decoded %lu bytes, whereas %" TIFF_SSIZE_FORMAT
" requested",

View File

@ -73,43 +73,6 @@ int TIFFReInitJPEG_12(TIFF *tif, const JPEGOtherSettings *otherSettings,
int scheme, int is_encode);
int TIFFJPEGIsFullStripRequired_12(TIFF *tif);
/* We undefine FAR to avoid conflict with JPEG definition */
#ifdef FAR
#undef FAR
#endif
/*
Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is
not defined. Unfortunately, the MinGW and Borland compilers include
a typedef for INT32, which causes a conflict. MSVC does not include
a conflicting typedef given the headers which are included.
*/
#if defined(__BORLANDC__) || defined(__MINGW32__)
#define XMD_H 1
#endif
/*
The windows RPCNDR.H file defines boolean, but defines it with the
unsigned char size. You should compile JPEG library using appropriate
definitions in jconfig.h header, but many users compile library in wrong
way. That causes errors of the following type:
"JPEGLib: JPEG parameter struct mismatch: library thinks size is 432,
caller expects 464"
For such users we will fix the problem here. See install.doc file from
the JPEG library distribution for details.
*/
/* Define "boolean" as unsigned char, not int, per Windows custom. */
#if defined(__WIN32__) && !defined(__MINGW32__)
#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
typedef unsigned char boolean;
#endif
#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
#endif
#include "jerror.h"
#include "jpeglib.h"
@ -125,18 +88,18 @@ typedef unsigned char boolean;
* 16bit value?
*/
/* HAVE_JPEGTURBO_DUAL_MODE_8_12 is defined for libjpeg-turbo >= 2.2 which
/* HAVE_JPEGTURBO_DUAL_MODE_8_12 is defined for libjpeg-turbo >= 3.0 which
* adds a dual-mode 8/12 bit API in the same library.
*/
#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12)
#define JPEG_DUAL_MODE_8_12
/* Start by undefining BITS_IN_JSAMPLE which is always set to 8 in libjpeg-turbo
* >= 2.2 Cf
* >= 3.0 Cf
* https://github.com/libjpeg-turbo/libjpeg-turbo/commit/8b9bc4b9635a2a047fb23ebe70c9acd728d3f99b
*/
#undef BITS_IN_JSAMPLE
/* libjpeg-turbo >= 2.2 adds J12xxxx datatypes for the 12-bit mode. */
/* libjpeg-turbo >= 3.0 adds J12xxxx datatypes for the 12-bit mode. */
#if defined(FROM_TIF_JPEG_12)
#define BITS_IN_JSAMPLE 12
#define TIFF_JSAMPLE J12SAMPLE
@ -182,9 +145,20 @@ typedef unsigned char boolean;
#define LONGJMP(jbuf, code) longjmp(jbuf, code)
#define JMP_BUF jmp_buf
#ifndef TIFF_jpeg_destination_mgr_defined
#define TIFF_jpeg_destination_mgr_defined
typedef struct jpeg_destination_mgr jpeg_destination_mgr;
#endif
#ifndef TIFF_jpeg_source_mgr_defined
#define TIFF_jpeg_source_mgr_defined
typedef struct jpeg_source_mgr jpeg_source_mgr;
#endif
#ifndef TIFF_jpeg_error_mgr_defined
#define TIFF_jpeg_error_mgr_defined
typedef struct jpeg_error_mgr jpeg_error_mgr;
#endif
/*
* State block for each open TIFF file using
@ -1241,6 +1215,12 @@ int TIFFJPEGIsFullStripRequired(TIFF *tif)
* For PC 2, scale down the expected strip/tile size
* to match a downsampled component
*/
if (sp->h_sampling == 0 || sp->v_sampling == 0)
{
TIFFErrorExtR(tif, module,
"JPEG horizontal or vertical sampling is zero");
return (0);
}
segment_width = TIFFhowmany_32(segment_width, sp->h_sampling);
segment_height = TIFFhowmany_32(segment_height, sp->v_sampling);
}
@ -1471,7 +1451,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc;
if (sp->bytesperline == 0)
{
memset(buf, 0, (size_t)cc);
return 0;
}
nrows = cc / sp->bytesperline;
if (cc % sp->bytesperline)
@ -1492,7 +1475,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
JSAMPROW bufptr = (JSAMPROW)buf;
if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1)
{
memset(buf, 0, (size_t)cc);
return (0);
}
++tif->tif_row;
buf += sp->bytesperline;
@ -1526,7 +1512,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc;
if (sp->bytesperline == 0)
{
memset(buf, 0, (size_t)cc);
return 0;
}
nrows = cc / sp->bytesperline;
if (cc % sp->bytesperline)
@ -1562,7 +1551,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
* for 12bit data, which we need to repack.
*/
if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1)
{
memset(buf, 0, (size_t)cc);
return (0);
}
if (sp->cinfo.d.data_precision == 12)
{
@ -2190,6 +2182,12 @@ static int JPEGPreEncode(TIFF *tif, uint16_t s)
/* for PC 2, scale down the strip/tile size
* to match a downsampled component
*/
if (sp->h_sampling == 0 || sp->v_sampling == 0)
{
TIFFErrorExtR(tif, module,
"JPEG horizontal or vertical sampling is zero");
return (0);
}
segment_width = TIFFhowmany_32(segment_width, sp->h_sampling);
segment_height = TIFFhowmany_32(segment_height, sp->v_sampling);
}

View File

@ -71,6 +71,9 @@ typedef struct
uint8_t *uncompressed_buffer;
unsigned int uncompressed_offset;
uint8_t *uncompressed_buffer_multiband;
unsigned int uncompressed_buffer_multiband_alloc;
unsigned int mask_size;
uint8_t *mask_buffer;
@ -86,9 +89,9 @@ typedef struct
TIFFVSetMethod vsetparent; /* super-class method */
} LERCState;
#define LState(tif) ((LERCState *)(tif)->tif_data)
#define DecoderState(tif) LState(tif)
#define EncoderState(tif) LState(tif)
#define GetLERCState(tif) ((LERCState *)(tif)->tif_data)
#define LERCDecoderState(tif) GetLERCState(tif)
#define LERCEncoderState(tif) GetLERCState(tif)
static int LERCEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
@ -101,7 +104,7 @@ static int LERCFixupTags(TIFF *tif)
static int LERCSetupDecode(TIFF *tif)
{
LERCState *sp = DecoderState(tif);
LERCState *sp = LERCDecoderState(tif);
assert(sp != NULL);
@ -168,7 +171,7 @@ static int GetLercDataType(TIFF *tif)
return -1;
}
static int SetupUncompressedBuffer(TIFF *tif, LERCState *sp, const char *module)
static int SetupBuffers(TIFF *tif, LERCState *sp, const char *module)
{
TIFFDirectory *td = &tif->tif_dir;
uint64_t new_size_64;
@ -202,8 +205,9 @@ static int SetupUncompressedBuffer(TIFF *tif, LERCState *sp, const char *module)
sp->uncompressed_size = new_size;
/* add some margin as we are going to use it also to store deflate/zstd
* compressed data */
new_alloc_64 = 100 + new_size_64 + new_size_64 / 3;
* compressed data. We also need extra margin when writing very small
* rasters with one mask per band. */
new_alloc_64 = 256 + new_size_64 + new_size_64 / 3;
#ifdef ZSTD_SUPPORT
{
size_t zstd_max = ZSTD_compressBound((size_t)new_size_64);
@ -243,11 +247,17 @@ static int SetupUncompressedBuffer(TIFF *tif, LERCState *sp, const char *module)
td->td_sampleinfo[td->td_extrasamples - 1] == EXTRASAMPLE_UNASSALPHA &&
GetLercDataType(tif) == 1) ||
(td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
(td->td_planarconfig == PLANARCONFIG_SEPARATE ||
td->td_samplesperpixel == 1) &&
(td->td_bitspersample == 32 || td->td_bitspersample == 64)))
{
unsigned int mask_size = sp->segment_width * sp->segment_height;
#if LERC_AT_LEAST_VERSION(3, 0, 0)
if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
td->td_planarconfig == PLANARCONFIG_CONTIG)
{
/* We may need one mask per band */
mask_size *= td->td_samplesperpixel;
}
#endif
if (sp->mask_size < mask_size)
{
void *mask_buffer =
@ -277,9 +287,9 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
static const char module[] = "LERCPreDecode";
lerc_status lerc_ret;
TIFFDirectory *td = &tif->tif_dir;
LERCState *sp = DecoderState(tif);
LERCState *sp = LERCDecoderState(tif);
int lerc_data_type;
unsigned int infoArray[8];
unsigned int infoArray[9];
unsigned nomask_bands = td->td_samplesperpixel;
int ndims;
int use_mask = 0;
@ -295,7 +305,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
if (lerc_data_type < 0)
return 0;
if (!SetupUncompressedBuffer(tif, sp, module))
if (!SetupBuffers(tif, sp, module))
return 0;
if (sp->additional_compression != LERC_ADD_COMPRESSION_NONE)
@ -400,7 +410,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
}
lerc_ret =
lerc_getBlobInfo(lerc_data, lerc_data_size, infoArray, NULL, 8, 0);
lerc_getBlobInfo(lerc_data, lerc_data_size, infoArray, NULL, 9, 0);
if (lerc_ret != 0)
{
TIFFErrorExtR(tif, module, "lerc_getBlobInfo() failed");
@ -418,18 +428,16 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
use_mask = 1;
nomask_bands--;
}
else if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
(td->td_planarconfig == PLANARCONFIG_SEPARATE ||
td->td_samplesperpixel == 1) &&
(td->td_bitspersample == 32 || td->td_bitspersample == 64))
else if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP)
{
use_mask = 1;
}
ndims = td->td_planarconfig == PLANARCONFIG_CONTIG ? nomask_bands : 1;
/* Info returned in infoArray is { version, dataType, nDim, nCols,
nRows, nBands, nValidPixels, blobSize } */
/* Info returned in infoArray is { version, dataType, nDim/nDepth, nCols,
nRows, nBands, nValidPixels, blobSize,
and starting with liblerc 3.0 nRequestedMasks } */
if (infoArray[0] != (unsigned)sp->lerc_version)
{
TIFFWarningExtR(tif, module,
@ -442,12 +450,29 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
infoArray[1], lerc_data_type);
return 0;
}
if (infoArray[2] != (unsigned)ndims)
const unsigned nFoundDims = infoArray[2];
#if LERC_AT_LEAST_VERSION(3, 0, 0)
if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
td->td_planarconfig == PLANARCONFIG_CONTIG &&
td->td_samplesperpixel > 1)
{
if (nFoundDims != 1 && nFoundDims != (unsigned)ndims)
{
TIFFErrorExtR(tif, module, "Unexpected nDim: %d. Expected: 1 or %d",
nFoundDims, ndims);
return 0;
}
}
else
#endif
if (nFoundDims != (unsigned)ndims)
{
TIFFErrorExtR(tif, module, "Unexpected nDim: %d. Expected: %d",
infoArray[2], ndims);
nFoundDims, ndims);
return 0;
}
if (infoArray[3] != sp->segment_width)
{
TIFFErrorExtR(tif, module, "Unexpected nCols: %d. Expected: %du",
@ -460,12 +485,38 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
infoArray[4], sp->segment_height);
return 0;
}
if (infoArray[5] != 1)
const unsigned nFoundBands = infoArray[5];
if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
td->td_planarconfig == PLANARCONFIG_CONTIG &&
td->td_samplesperpixel > 1 && nFoundDims == 1)
{
#if !LERC_AT_LEAST_VERSION(3, 0, 0)
if (nFoundBands == td->td_samplesperpixel)
{
TIFFErrorExtR(
tif, module,
"Unexpected nBands: %d. This file may have been generated with "
"a liblerc version >= 3.0, with one mask per band, and is not "
"supported by this older version of liblerc",
nFoundBands);
return 0;
}
#endif
if (nFoundBands != td->td_samplesperpixel)
{
TIFFErrorExtR(tif, module, "Unexpected nBands: %d. Expected: %d",
nFoundBands, td->td_samplesperpixel);
return 0;
}
}
else if (nFoundBands != 1)
{
TIFFErrorExtR(tif, module, "Unexpected nBands: %d. Expected: %d",
infoArray[5], 1);
nFoundBands, 1);
return 0;
}
if (infoArray[7] != lerc_data_size)
{
TIFFErrorExtR(tif, module, "Unexpected blobSize: %d. Expected: %u",
@ -473,13 +524,75 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
return 0;
}
lerc_ret = lerc_decode(lerc_data, lerc_data_size,
int nRequestedMasks = use_mask ? 1 : 0;
#if LERC_AT_LEAST_VERSION(3, 0, 0)
use_mask ? 1 : 0,
const int nFoundMasks = infoArray[8];
if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
td->td_planarconfig == PLANARCONFIG_CONTIG &&
td->td_samplesperpixel > 1 && nFoundDims == 1)
{
if (nFoundMasks != 0 && nFoundMasks != td->td_samplesperpixel)
{
TIFFErrorExtR(tif, module,
"Unexpected nFoundMasks: %d. Expected: 0 or %d",
nFoundMasks, td->td_samplesperpixel);
return 0;
}
nRequestedMasks = nFoundMasks;
}
else
{
if (nFoundMasks != 0 && nFoundMasks != 1)
{
TIFFErrorExtR(tif, module,
"Unexpected nFoundMasks: %d. Expected: 0 or 1",
nFoundMasks);
return 0;
}
}
if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP && nFoundMasks == 0)
{
nRequestedMasks = 0;
use_mask = 0;
}
#endif
use_mask ? sp->mask_buffer : NULL, ndims,
sp->segment_width, sp->segment_height, 1,
lerc_data_type, sp->uncompressed_buffer);
const unsigned nb_pixels = sp->segment_width * sp->segment_height;
#if LERC_AT_LEAST_VERSION(3, 0, 0)
if (nRequestedMasks > 1)
{
unsigned int num_bytes_needed =
nb_pixels * td->td_samplesperpixel * (td->td_bitspersample / 8);
if (sp->uncompressed_buffer_multiband_alloc < num_bytes_needed)
{
_TIFFfreeExt(tif, sp->uncompressed_buffer_multiband);
sp->uncompressed_buffer_multiband =
_TIFFmallocExt(tif, num_bytes_needed);
if (!sp->uncompressed_buffer_multiband)
{
sp->uncompressed_buffer_multiband_alloc = 0;
return 0;
}
sp->uncompressed_buffer_multiband_alloc = num_bytes_needed;
}
lerc_ret = lerc_decode(lerc_data, lerc_data_size, nRequestedMasks,
sp->mask_buffer, nFoundDims, sp->segment_width,
sp->segment_height, nFoundBands, lerc_data_type,
sp->uncompressed_buffer_multiband);
}
else
#endif
{
lerc_ret =
lerc_decode(lerc_data, lerc_data_size,
#if LERC_AT_LEAST_VERSION(3, 0, 0)
nRequestedMasks,
#endif
use_mask ? sp->mask_buffer : NULL, nFoundDims,
sp->segment_width, sp->segment_height, nFoundBands,
lerc_data_type, sp->uncompressed_buffer);
}
if (lerc_ret != 0)
{
TIFFErrorExtR(tif, module, "lerc_decode() failed");
@ -515,7 +628,6 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
}
else if (use_mask && td->td_sampleformat == SAMPLEFORMAT_IEEEFP)
{
const unsigned nb_pixels = sp->segment_width * sp->segment_height;
unsigned i;
#if WORDS_BIGENDIAN
const unsigned char nan_bytes[] = {0x7f, 0xc0, 0, 0};
@ -525,23 +637,104 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
float nan_float32;
memcpy(&nan_float32, nan_bytes, 4);
if (td->td_bitspersample == 32)
if (td->td_planarconfig == PLANARCONFIG_SEPARATE ||
td->td_samplesperpixel == 1)
{
for (i = 0; i < nb_pixels; i++)
if (td->td_bitspersample == 32)
{
if (sp->mask_buffer[i] == 0)
((float *)sp->uncompressed_buffer)[i] = nan_float32;
for (i = 0; i < nb_pixels; i++)
{
if (sp->mask_buffer[i] == 0)
((float *)sp->uncompressed_buffer)[i] = nan_float32;
}
}
else
{
const double nan_float64 = nan_float32;
for (i = 0; i < nb_pixels; i++)
{
if (sp->mask_buffer[i] == 0)
((double *)sp->uncompressed_buffer)[i] = nan_float64;
}
}
}
else if (nRequestedMasks == 1)
{
assert(nFoundDims == td->td_samplesperpixel);
assert(nFoundBands == 1);
unsigned k = 0;
if (td->td_bitspersample == 32)
{
for (i = 0; i < nb_pixels; i++)
{
for (int j = 0; j < td->td_samplesperpixel; j++)
{
if (sp->mask_buffer[i] == 0)
((float *)sp->uncompressed_buffer)[k] = nan_float32;
++k;
}
}
}
else
{
const double nan_float64 = nan_float32;
for (i = 0; i < nb_pixels; i++)
{
for (int j = 0; j < td->td_samplesperpixel; j++)
{
if (sp->mask_buffer[i] == 0)
((double *)sp->uncompressed_buffer)[k] =
nan_float64;
++k;
}
}
}
}
#if LERC_AT_LEAST_VERSION(3, 0, 0)
else
{
const double nan_float64 = nan_float32;
for (i = 0; i < nb_pixels; i++)
assert(nRequestedMasks == td->td_samplesperpixel);
assert(nFoundDims == 1);
assert(nFoundBands == td->td_samplesperpixel);
unsigned k = 0;
if (td->td_bitspersample == 32)
{
if (sp->mask_buffer[i] == 0)
((double *)sp->uncompressed_buffer)[i] = nan_float64;
for (i = 0; i < nb_pixels; i++)
{
for (int j = 0; j < td->td_samplesperpixel; j++)
{
if (sp->mask_buffer[i + j * nb_pixels] == 0)
((float *)sp->uncompressed_buffer)[k] = nan_float32;
else
((float *)sp->uncompressed_buffer)[k] =
((float *)sp->uncompressed_buffer_multiband)
[i + j * nb_pixels];
++k;
}
}
}
else
{
const double nan_float64 = nan_float32;
for (i = 0; i < nb_pixels; i++)
{
for (int j = 0; j < td->td_samplesperpixel; j++)
{
if (sp->mask_buffer[i + j * nb_pixels] == 0)
((double *)sp->uncompressed_buffer)[k] =
nan_float64;
else
((double *)sp->uncompressed_buffer)[k] =
((double *)sp->uncompressed_buffer_multiband)
[i + j * nb_pixels];
++k;
}
}
}
}
#endif
}
return 1;
@ -553,7 +746,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s)
static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{
static const char module[] = "LERCDecode";
LERCState *sp = DecoderState(tif);
LERCState *sp = LERCDecoderState(tif);
(void)s;
assert(sp != NULL);
@ -561,6 +754,7 @@ static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (sp->uncompressed_buffer == 0)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module, "Uncompressed buffer not allocated");
return 0;
}
@ -568,6 +762,7 @@ static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if ((uint64_t)sp->uncompressed_offset + (uint64_t)occ >
sp->uncompressed_size)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module, "Too many bytes read");
return 0;
}
@ -580,7 +775,7 @@ static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
static int LERCSetupEncode(TIFF *tif)
{
LERCState *sp = EncoderState(tif);
LERCState *sp = LERCEncoderState(tif);
assert(sp != NULL);
if (sp->state & LSTATE_INIT_DECODE)
@ -599,7 +794,7 @@ static int LERCSetupEncode(TIFF *tif)
static int LERCPreEncode(TIFF *tif, uint16_t s)
{
static const char module[] = "LERCPreEncode";
LERCState *sp = EncoderState(tif);
LERCState *sp = LERCEncoderState(tif);
int lerc_data_type;
(void)s;
@ -611,7 +806,7 @@ static int LERCPreEncode(TIFF *tif, uint16_t s)
if (lerc_data_type < 0)
return 0;
if (!SetupUncompressedBuffer(tif, sp, module))
if (!SetupBuffers(tif, sp, module))
return 0;
return 1;
@ -623,7 +818,7 @@ static int LERCPreEncode(TIFF *tif, uint16_t s)
static int LERCEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{
static const char module[] = "LERCEncode";
LERCState *sp = EncoderState(tif);
LERCState *sp = LERCEncoderState(tif);
(void)s;
assert(sp != NULL);
@ -649,8 +844,7 @@ static int LERCPostEncode(TIFF *tif)
{
lerc_status lerc_ret;
static const char module[] = "LERCPostEncode";
LERCState *sp = EncoderState(tif);
unsigned int numBytes = 0;
LERCState *sp = LERCEncoderState(tif);
unsigned int numBytesWritten = 0;
TIFFDirectory *td = &tif->tif_dir;
int use_mask = 0;
@ -662,6 +856,9 @@ static int LERCPostEncode(TIFF *tif)
return 0;
}
int mask_count = 1;
const unsigned nb_pixels = sp->segment_width * sp->segment_height;
/* Extract alpha mask (if containing only 0 and 255 values, */
/* and compact array of regular bands */
if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_extrasamples > 0 &&
@ -673,7 +870,6 @@ static int LERCPostEncode(TIFF *tif)
const unsigned src_stride =
td->td_samplesperpixel * (td->td_bitspersample / 8);
unsigned i = 0;
const unsigned nb_pixels = sp->segment_width * sp->segment_height;
use_mask = 1;
for (i = 0; i < nb_pixels; i++)
@ -710,46 +906,78 @@ static int LERCPostEncode(TIFF *tif)
}
}
else if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
(td->td_planarconfig == PLANARCONFIG_SEPARATE ||
dst_nbands == 1) &&
(td->td_bitspersample == 32 || td->td_bitspersample == 64))
{
/* Check for NaN values */
unsigned i;
const unsigned nb_pixels = sp->segment_width * sp->segment_height;
if (td->td_bitspersample == 32)
{
for (i = 0; i < nb_pixels; i++)
if (td->td_planarconfig == PLANARCONFIG_CONTIG && dst_nbands > 1)
{
const float val = ((float *)sp->uncompressed_buffer)[i];
if (val != val)
unsigned k = 0;
for (i = 0; i < nb_pixels; i++)
{
use_mask = 1;
break;
int count_nan = 0;
for (int j = 0; j < td->td_samplesperpixel; ++j)
{
const float val = ((float *)sp->uncompressed_buffer)[k];
++k;
if (val != val)
{
++count_nan;
}
}
if (count_nan > 0)
{
use_mask = 1;
if (count_nan < td->td_samplesperpixel)
{
mask_count = td->td_samplesperpixel;
break;
}
}
}
}
else
{
for (i = 0; i < nb_pixels; i++)
{
const float val = ((float *)sp->uncompressed_buffer)[i];
if (val != val)
{
use_mask = 1;
break;
}
}
}
}
else
{
for (i = 0; i < nb_pixels; i++)
{
const double val = ((double *)sp->uncompressed_buffer)[i];
if (val != val)
{
use_mask = 1;
break;
}
}
}
if (use_mask)
{
if (td->td_bitspersample == 32)
if (td->td_planarconfig == PLANARCONFIG_CONTIG && dst_nbands > 1)
{
unsigned k = 0;
for (i = 0; i < nb_pixels; i++)
{
const float val = ((float *)sp->uncompressed_buffer)[i];
sp->mask_buffer[i] = (val == val) ? 255 : 0;
int count_nan = 0;
for (int j = 0; j < td->td_samplesperpixel; ++j)
{
const double val =
((double *)sp->uncompressed_buffer)[k];
++k;
if (val != val)
{
++count_nan;
}
}
if (count_nan > 0)
{
use_mask = 1;
if (count_nan < td->td_samplesperpixel)
{
mask_count = td->td_samplesperpixel;
break;
}
}
}
}
else
@ -757,62 +985,168 @@ static int LERCPostEncode(TIFF *tif)
for (i = 0; i < nb_pixels; i++)
{
const double val = ((double *)sp->uncompressed_buffer)[i];
sp->mask_buffer[i] = (val == val) ? 255 : 0;
if (val != val)
{
use_mask = 1;
break;
}
}
}
}
if (use_mask)
{
if (mask_count > 1)
{
#if LERC_AT_LEAST_VERSION(3, 0, 0)
unsigned int num_bytes_needed =
nb_pixels * dst_nbands * (td->td_bitspersample / 8);
if (sp->uncompressed_buffer_multiband_alloc < num_bytes_needed)
{
_TIFFfreeExt(tif, sp->uncompressed_buffer_multiband);
sp->uncompressed_buffer_multiband =
_TIFFmallocExt(tif, num_bytes_needed);
if (!sp->uncompressed_buffer_multiband)
{
sp->uncompressed_buffer_multiband_alloc = 0;
return 0;
}
sp->uncompressed_buffer_multiband_alloc = num_bytes_needed;
}
unsigned k = 0;
if (td->td_bitspersample == 32)
{
for (i = 0; i < nb_pixels; i++)
{
for (int j = 0; j < td->td_samplesperpixel; ++j)
{
const float val =
((float *)sp->uncompressed_buffer)[k];
((float *)sp->uncompressed_buffer_multiband)
[i + j * nb_pixels] = val;
++k;
sp->mask_buffer[i + j * nb_pixels] =
(val == val) ? 255 : 0;
}
}
}
else
{
for (i = 0; i < nb_pixels; i++)
{
for (int j = 0; j < td->td_samplesperpixel; ++j)
{
const double val =
((double *)sp->uncompressed_buffer)[k];
((double *)sp->uncompressed_buffer_multiband)
[i + j * nb_pixels] = val;
++k;
sp->mask_buffer[i + j * nb_pixels] =
(val == val) ? 255 : 0;
}
}
}
#else
TIFFErrorExtR(tif, module,
"lerc_encode() would need to create one mask per "
"sample, but this requires liblerc >= 3.0");
return 0;
#endif
}
else if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
dst_nbands > 1)
{
if (td->td_bitspersample == 32)
{
for (i = 0; i < nb_pixels; i++)
{
const float val =
((float *)sp->uncompressed_buffer)[i * dst_nbands];
sp->mask_buffer[i] = (val == val) ? 255 : 0;
}
}
else
{
for (i = 0; i < nb_pixels; i++)
{
const double val =
((double *)sp->uncompressed_buffer)[i * dst_nbands];
sp->mask_buffer[i] = (val == val) ? 255 : 0;
}
}
}
else
{
if (td->td_bitspersample == 32)
{
for (i = 0; i < nb_pixels; i++)
{
const float val = ((float *)sp->uncompressed_buffer)[i];
sp->mask_buffer[i] = (val == val) ? 255 : 0;
}
}
else
{
for (i = 0; i < nb_pixels; i++)
{
const double val =
((double *)sp->uncompressed_buffer)[i];
sp->mask_buffer[i] = (val == val) ? 255 : 0;
}
}
}
}
}
#if 0
lerc_ret = lerc_computeCompressedSize(
sp->uncompressed_buffer,
sp->lerc_version,
GetLercDataType(tif),
td->td_planarconfig == PLANARCONFIG_CONTIG ?
dst_nbands : 1,
sp->segment_width,
sp->segment_height,
1,
use_mask ? sp->mask_buffer : NULL,
sp->maxzerror,
&numBytes);
if( lerc_ret != 0 )
{
TIFFErrorExtR(tif, module,
"lerc_computeCompressedSize() failed");
return 0;
}
#else
numBytes = sp->uncompressed_alloc;
unsigned int estimated_compressed_size = sp->uncompressed_alloc;
#if LERC_AT_LEAST_VERSION(3, 0, 0)
if (mask_count > 1)
{
estimated_compressed_size += nb_pixels * mask_count / 8;
}
#endif
if (sp->compressed_size < numBytes)
if (sp->compressed_size < estimated_compressed_size)
{
_TIFFfreeExt(tif, sp->compressed_buffer);
sp->compressed_buffer = _TIFFmallocExt(tif, numBytes);
sp->compressed_buffer = _TIFFmallocExt(tif, estimated_compressed_size);
if (!sp->compressed_buffer)
{
sp->compressed_size = 0;
return 0;
}
sp->compressed_size = numBytes;
sp->compressed_size = estimated_compressed_size;
}
lerc_ret = lerc_encodeForVersion(
sp->uncompressed_buffer, sp->lerc_version, GetLercDataType(tif),
td->td_planarconfig == PLANARCONFIG_CONTIG ? dst_nbands : 1,
sp->segment_width, sp->segment_height, 1,
#if LERC_AT_LEAST_VERSION(3, 0, 0)
use_mask ? 1 : 0,
if (mask_count > 1)
{
lerc_ret = lerc_encodeForVersion(
sp->uncompressed_buffer_multiband, sp->lerc_version,
GetLercDataType(tif), 1, sp->segment_width, sp->segment_height,
dst_nbands, dst_nbands, sp->mask_buffer, sp->maxzerror,
sp->compressed_buffer, sp->compressed_size, &numBytesWritten);
}
else
#endif
use_mask ? sp->mask_buffer : NULL, sp->maxzerror, sp->compressed_buffer,
sp->compressed_size, &numBytesWritten);
{
lerc_ret = lerc_encodeForVersion(
sp->uncompressed_buffer, sp->lerc_version, GetLercDataType(tif),
td->td_planarconfig == PLANARCONFIG_CONTIG ? dst_nbands : 1,
sp->segment_width, sp->segment_height, 1,
#if LERC_AT_LEAST_VERSION(3, 0, 0)
use_mask ? 1 : 0,
#endif
use_mask ? sp->mask_buffer : NULL, sp->maxzerror,
sp->compressed_buffer, sp->compressed_size, &numBytesWritten);
}
if (lerc_ret != 0)
{
TIFFErrorExtR(tif, module, "lerc_encode() failed");
return 0;
}
assert(numBytesWritten < numBytes);
assert(numBytesWritten < estimated_compressed_size);
if (sp->additional_compression == LERC_ADD_COMPRESSION_DEFLATE)
{
@ -950,7 +1284,7 @@ static int LERCPostEncode(TIFF *tif)
static void LERCCleanup(TIFF *tif)
{
LERCState *sp = LState(tif);
LERCState *sp = GetLERCState(tif);
assert(sp != 0);
@ -958,6 +1292,7 @@ static void LERCCleanup(TIFF *tif)
tif->tif_tagmethods.vsetfield = sp->vsetparent;
_TIFFfreeExt(tif, sp->uncompressed_buffer);
_TIFFfreeExt(tif, sp->uncompressed_buffer_multiband);
_TIFFfreeExt(tif, sp->compressed_buffer);
_TIFFfreeExt(tif, sp->mask_buffer);
@ -995,7 +1330,7 @@ static const TIFFField LERCFields[] = {
static int LERCVSetFieldBase(TIFF *tif, uint32_t tag, ...)
{
LERCState *sp = LState(tif);
LERCState *sp = GetLERCState(tif);
int ret;
va_list ap;
va_start(ap, tag);
@ -1007,7 +1342,7 @@ static int LERCVSetFieldBase(TIFF *tif, uint32_t tag, ...)
static int LERCVSetField(TIFF *tif, uint32_t tag, va_list ap)
{
static const char module[] = "LERCVSetField";
LERCState *sp = LState(tif);
LERCState *sp = GetLERCState(tif);
switch (tag)
{
@ -1115,7 +1450,7 @@ static int LERCVSetField(TIFF *tif, uint32_t tag, va_list ap)
static int LERCVGetField(TIFF *tif, uint32_t tag, va_list ap)
{
LERCState *sp = LState(tif);
LERCState *sp = GetLERCState(tif);
switch (tag)
{
@ -1163,7 +1498,7 @@ int TIFFInitLERC(TIFF *tif, int scheme)
tif->tif_data = (uint8_t *)_TIFFcallocExt(tif, 1, sizeof(LERCState));
if (tif->tif_data == NULL)
goto bad;
sp = LState(tif);
sp = GetLERCState(tif);
/*
* Override parent get/set field methods.

View File

@ -951,7 +951,8 @@ static
int
uv_encode(double u, double v, int em) /* encode (u',v') coordinates */
{
register int vi, ui;
unsigned int vi;
int ui;
/* check for NaN */
if (u != u || v != v)
@ -980,8 +981,9 @@ static
int
uv_decode(double *up, double *vp, int c) /* decode (u',v') index */
{
int upper, lower;
register int ui, vi;
unsigned int upper, lower;
int ui;
unsigned int vi;
if (c < 0 || c >= UV_NDIVS)
return (-1);

View File

@ -44,6 +44,8 @@
typedef struct
{
TIFFPredictorState predict;
int read_error; /* whether a read error has occurred, and which should cause
further reads in the same strip/tile to be aborted */
lzma_stream stream;
lzma_filter filters[LZMA_FILTERS_MAX + 1];
lzma_options_delta opt_delta; /* delta filter options */
@ -58,9 +60,9 @@ typedef struct
TIFFVSetMethod vsetparent; /* super-class method */
} LZMAState;
#define LState(tif) ((LZMAState *)(tif)->tif_data)
#define DecoderState(tif) LState(tif)
#define EncoderState(tif) LState(tif)
#define GetLZMAState(tif) ((LZMAState *)(tif)->tif_data)
#define LZMADecoderState(tif) GetLZMAState(tif)
#define LZMAEncoderState(tif) GetLZMAState(tif)
static int LZMAEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
@ -106,7 +108,7 @@ static int LZMAFixupTags(TIFF *tif)
static int LZMASetupDecode(TIFF *tif)
{
LZMAState *sp = DecoderState(tif);
LZMAState *sp = LZMADecoderState(tif);
assert(sp != NULL);
@ -127,7 +129,7 @@ static int LZMASetupDecode(TIFF *tif)
static int LZMAPreDecode(TIFF *tif, uint16_t s)
{
static const char module[] = "LZMAPreDecode";
LZMAState *sp = DecoderState(tif);
LZMAState *sp = LZMADecoderState(tif);
lzma_ret ret;
(void)s;
@ -156,18 +158,31 @@ static int LZMAPreDecode(TIFF *tif, uint16_t s)
LZMAStrerror(ret));
return 0;
}
sp->read_error = 0;
return 1;
}
static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{
static const char module[] = "LZMADecode";
LZMAState *sp = DecoderState(tif);
LZMAState *sp = LZMADecoderState(tif);
(void)s;
assert(sp != NULL);
assert(sp->state == LSTATE_INIT_DECODE);
if (sp->read_error)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"LZMADecode: Scanline %" PRIu32 " cannot be read due to "
"previous error",
tif->tif_row);
return 0;
}
sp->stream.next_in = tif->tif_rawcp;
sp->stream.avail_in = (size_t)tif->tif_rawcc;
@ -175,6 +190,9 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
sp->stream.avail_out = (size_t)occ;
if ((tmsize_t)sp->stream.avail_out != occ)
{
// read_error not set here as this is a usage issue that can be
// recovered in a following call.
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"Liblzma cannot deal with buffers this size");
return 0;
@ -198,6 +216,8 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
lzma_stream_decoder(&sp->stream, lzma_memusage(&sp->stream), 0);
if (r != LZMA_OK)
{
sp->read_error = 1;
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"Error initializing the stream decoder, %s",
LZMAStrerror(r));
@ -217,6 +237,8 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
} while (sp->stream.avail_out > 0);
if (sp->stream.avail_out != 0)
{
sp->read_error = 1;
memset(sp->stream.next_out, 0, sp->stream.avail_out);
TIFFErrorExtR(tif, module,
"Not enough data at scanline %" PRIu32
" (short %" TIFF_SIZE_FORMAT " bytes)",
@ -232,7 +254,7 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
static int LZMASetupEncode(TIFF *tif)
{
LZMAState *sp = EncoderState(tif);
LZMAState *sp = LZMAEncoderState(tif);
assert(sp != NULL);
if (sp->state & LSTATE_INIT_DECODE)
@ -251,7 +273,7 @@ static int LZMASetupEncode(TIFF *tif)
static int LZMAPreEncode(TIFF *tif, uint16_t s)
{
static const char module[] = "LZMAPreEncode";
LZMAState *sp = EncoderState(tif);
LZMAState *sp = LZMAEncoderState(tif);
lzma_ret ret;
(void)s;
@ -283,7 +305,7 @@ static int LZMAPreEncode(TIFF *tif, uint16_t s)
static int LZMAEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{
static const char module[] = "LZMAEncode";
LZMAState *sp = EncoderState(tif);
LZMAState *sp = LZMAEncoderState(tif);
assert(sp != NULL);
assert(sp->state == LSTATE_INIT_ENCODE);
@ -329,7 +351,7 @@ static int LZMAEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
static int LZMAPostEncode(TIFF *tif)
{
static const char module[] = "LZMAPostEncode";
LZMAState *sp = EncoderState(tif);
LZMAState *sp = LZMAEncoderState(tif);
lzma_ret ret;
sp->stream.avail_in = 0;
@ -365,7 +387,7 @@ static int LZMAPostEncode(TIFF *tif)
static void LZMACleanup(TIFF *tif)
{
LZMAState *sp = LState(tif);
LZMAState *sp = GetLZMAState(tif);
assert(sp != 0);
@ -388,7 +410,7 @@ static void LZMACleanup(TIFF *tif)
static int LZMAVSetField(TIFF *tif, uint32_t tag, va_list ap)
{
static const char module[] = "LZMAVSetField";
LZMAState *sp = LState(tif);
LZMAState *sp = GetLZMAState(tif);
switch (tag)
{
@ -414,7 +436,7 @@ static int LZMAVSetField(TIFF *tif, uint32_t tag, va_list ap)
static int LZMAVGetField(TIFF *tif, uint32_t tag, va_list ap)
{
LZMAState *sp = LState(tif);
LZMAState *sp = GetLZMAState(tif);
switch (tag)
{
@ -457,7 +479,7 @@ int TIFFInitLZMA(TIFF *tif, int scheme)
tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(LZMAState));
if (tif->tif_data == NULL)
goto bad;
sp = LState(tif);
sp = GetLZMAState(tif);
memcpy(&sp->stream, &tmp_stream, sizeof(lzma_stream));
/*

View File

@ -161,8 +161,8 @@ typedef struct
} LZWCodecState;
#define LZWState(tif) ((LZWBaseState *)(tif)->tif_data)
#define DecoderState(tif) ((LZWCodecState *)LZWState(tif))
#define EncoderState(tif) ((LZWCodecState *)LZWState(tif))
#define LZWDecoderState(tif) ((LZWCodecState *)LZWState(tif))
#define LZWEncoderState(tif) ((LZWCodecState *)LZWState(tif))
static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s);
#ifdef LZW_COMPAT
@ -183,7 +183,7 @@ static int LZWFixupTags(TIFF *tif)
static int LZWSetupDecode(TIFF *tif)
{
static const char module[] = "LZWSetupDecode";
LZWCodecState *sp = DecoderState(tif);
LZWCodecState *sp = LZWDecoderState(tif);
int code;
if (sp == NULL)
@ -199,7 +199,7 @@ static int LZWSetupDecode(TIFF *tif)
return (0);
}
sp = DecoderState(tif);
sp = LZWDecoderState(tif);
sp->dec_codetab = NULL;
sp->dec_decode = NULL;
@ -245,7 +245,7 @@ static int LZWSetupDecode(TIFF *tif)
static int LZWPreDecode(TIFF *tif, uint16_t s)
{
static const char module[] = "LZWPreDecode";
LZWCodecState *sp = DecoderState(tif);
LZWCodecState *sp = LZWDecoderState(tif);
(void)s;
assert(sp != NULL);
@ -329,10 +329,7 @@ static int LZWPreDecode(TIFF *tif, uint16_t s)
#ifdef WORDS_BIGENDIAN
#define GetNextData(nextdata, bp) memcpy(&nextdata, bp, sizeof(nextdata))
#elif SIZEOF_WORDTYPE == 8
#if defined(__GNUC__) && defined(__x86_64__)
#define GetNextData(nextdata, bp) \
nextdata = __builtin_bswap64(*(uint64_t *)(bp))
#elif defined(_M_X64)
#if defined(_M_X64)
#define GetNextData(nextdata, bp) nextdata = _byteswap_uint64(*(uint64_t *)(bp))
#elif defined(__GNUC__)
#define GetNextData(nextdata, bp) \
@ -346,10 +343,7 @@ static int LZWPreDecode(TIFF *tif, uint16_t s)
(((uint64_t)bp[6]) << 8) | (((uint64_t)bp[7]))
#endif
#elif SIZEOF_WORDTYPE == 4
#if defined(__GNUC__) && defined(__i386__)
#define GetNextData(nextdata, bp) \
nextdata = __builtin_bswap32(*(uint32_t *)(bp))
#elif defined(_M_X86)
#if defined(_M_X86)
#define GetNextData(nextdata, bp) \
nextdata = _byteswap_ulong(*(unsigned long *)(bp))
#elif defined(__GNUC__)
@ -409,7 +403,7 @@ static int LZWPreDecode(TIFF *tif, uint16_t s)
static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
{
static const char module[] = "LZWDecode";
LZWCodecState *sp = DecoderState(tif);
LZWCodecState *sp = LZWDecoderState(tif);
uint8_t *op = (uint8_t *)op0;
tmsize_t occ = occ0;
uint8_t *bp;
@ -423,6 +417,7 @@ static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
if (sp->read_error)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"LZWDecode: Scanline %" PRIu32 " cannot be read due to "
"previous error",
@ -737,6 +732,7 @@ after_loop:
if (occ > 0)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"Not enough data at scanline %" PRIu32 " (short %" PRIu64
" bytes)",
@ -746,12 +742,14 @@ after_loop:
return (1);
no_eoi:
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module,
"LZWDecode: Strip %" PRIu32 " not terminated with EOI code",
tif->tif_curstrip);
return 0;
error_code:
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, tif->tif_name, "Using code not yet in table");
return 0;
@ -800,7 +798,7 @@ error_code:
static int LZWDecodeCompat(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
{
static const char module[] = "LZWDecodeCompat";
LZWCodecState *sp = DecoderState(tif);
LZWCodecState *sp = LZWDecoderState(tif);
uint8_t *op = (uint8_t *)op0;
tmsize_t occ = occ0;
uint8_t *tp;
@ -1026,7 +1024,7 @@ static int LZWDecodeCompat(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
static int LZWSetupEncode(TIFF *tif)
{
static const char module[] = "LZWSetupEncode";
LZWCodecState *sp = EncoderState(tif);
LZWCodecState *sp = LZWEncoderState(tif);
assert(sp != NULL);
sp->enc_hashtab = (hash_t *)_TIFFmallocExt(tif, HSIZE * sizeof(hash_t));
@ -1043,7 +1041,7 @@ static int LZWSetupEncode(TIFF *tif)
*/
static int LZWPreEncode(TIFF *tif, uint16_t s)
{
LZWCodecState *sp = EncoderState(tif);
LZWCodecState *sp = LZWEncoderState(tif);
(void)s;
assert(sp != NULL);
@ -1114,7 +1112,7 @@ static int LZWPreEncode(TIFF *tif, uint16_t s)
*/
static int LZWEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{
register LZWCodecState *sp = EncoderState(tif);
register LZWCodecState *sp = LZWEncoderState(tif);
register long fcode;
register hash_t *hp;
register int h, c;
@ -1299,7 +1297,7 @@ static int LZWEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
*/
static int LZWPostEncode(TIFF *tif)
{
register LZWCodecState *sp = EncoderState(tif);
register LZWCodecState *sp = LZWEncoderState(tif);
uint8_t *op = tif->tif_rawcp;
long nextbits = sp->lzw_nextbits;
WordType nextdata = sp->lzw_nextdata;
@ -1381,11 +1379,11 @@ static void LZWCleanup(TIFF *tif)
assert(tif->tif_data != 0);
if (DecoderState(tif)->dec_codetab)
_TIFFfreeExt(tif, DecoderState(tif)->dec_codetab);
if (LZWDecoderState(tif)->dec_codetab)
_TIFFfreeExt(tif, LZWDecoderState(tif)->dec_codetab);
if (EncoderState(tif)->enc_hashtab)
_TIFFfreeExt(tif, EncoderState(tif)->enc_hashtab);
if (LZWEncoderState(tif)->enc_hashtab)
_TIFFfreeExt(tif, LZWEncoderState(tif)->enc_hashtab);
_TIFFfreeExt(tif, tif->tif_data);
tif->tif_data = NULL;
@ -1404,9 +1402,9 @@ int TIFFInitLZW(TIFF *tif, int scheme)
tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(LZWCodecState));
if (tif->tif_data == NULL)
goto bad;
DecoderState(tif)->dec_codetab = NULL;
DecoderState(tif)->dec_decode = NULL;
EncoderState(tif)->enc_hashtab = NULL;
LZWDecoderState(tif)->dec_codetab = NULL;
LZWDecoderState(tif)->dec_decode = NULL;
LZWEncoderState(tif)->enc_hashtab = NULL;
LZWState(tif)->rw_mode = tif->tif_mode;
/*

View File

@ -207,37 +207,21 @@ static const TIFFField ojpegFields[] = {
#include <setjmp.h>
#endif
/* We undefine FAR to avoid conflict with JPEG definition */
#ifdef FAR
#undef FAR
#endif
/*
Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is
not defined. Unfortunately, the MinGW and Borland compilers include
a typedef for INT32, which causes a conflict. MSVC does not include
a conflicting typedef given the headers which are included.
*/
#if defined(__BORLANDC__) || defined(__MINGW32__)
#define XMD_H 1
#endif
/* Define "boolean" as unsigned char, not int, per Windows custom. */
#if defined(__WIN32__) && !defined(__MINGW32__)
#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
typedef unsigned char boolean;
#endif
#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
#endif
#include "jerror.h"
#include "jpeglib.h"
#ifndef TIFF_jpeg_source_mgr_defined
#define TIFF_jpeg_source_mgr_defined
typedef struct jpeg_source_mgr jpeg_source_mgr;
#endif
#ifndef TIFF_jpeg_error_mgr_defined
#define TIFF_jpeg_error_mgr_defined
typedef struct jpeg_error_mgr jpeg_error_mgr;
#endif
typedef struct jpeg_common_struct jpeg_common_struct;
typedef struct jpeg_decompress_struct jpeg_decompress_struct;
typedef struct jpeg_source_mgr jpeg_source_mgr;
typedef enum
{
@ -771,6 +755,9 @@ static int OJPEGPreDecode(TIFF *tif, uint16_t s)
if (OJPEGWriteHeaderInfo(tif) == 0)
return (0);
}
sp->subsampling_convert_state = 0;
while (sp->write_curstrile < m)
{
if (sp->libjpeg_jpeg_query_style == 0)
@ -856,12 +843,14 @@ static int OJPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
(void)s;
if (!sp->decoder_ok)
{
memset(buf, 0, (size_t)cc);
TIFFErrorExtR(tif, module,
"Cannot decode: decoder not correctly initialized");
return 0;
}
if (sp->libjpeg_session_active == 0)
{
memset(buf, 0, (size_t)cc);
/* This should normally not happen, except that it does when */
/* using TIFFReadScanline() which calls OJPEGPostDecode() for */
/* each scanline, which assumes that a whole strile was read */
@ -875,17 +864,24 @@ static int OJPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
}
if (sp->error_in_raw_data_decoding)
{
memset(buf, 0, (size_t)cc);
return 0;
}
if (sp->libjpeg_jpeg_query_style == 0)
{
if (OJPEGDecodeRaw(tif, buf, cc) == 0)
{
memset(buf, 0, (size_t)cc);
return (0);
}
}
else
{
if (OJPEGDecodeScanlines(tif, buf, cc) == 0)
{
memset(buf, 0, (size_t)cc);
return (0);
}
}
return (1);
}

View File

@ -25,7 +25,13 @@
/*
* TIFF Library.
*/
#ifdef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
#undef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
#endif
#include "tiffiop.h"
#include <assert.h>
#include <limits.h>
/*
@ -81,8 +87,9 @@ TIFFOpenOptions *TIFFOpenOptionsAlloc()
void TIFFOpenOptionsFree(TIFFOpenOptions *opts) { _TIFFfree(opts); }
/** Define a limit in bytes for a single memory allocation done by libtiff.
* If max_single_mem_alloc is set to 0, no other limit that the underlying
* _TIFFmalloc() will be applied, which is the default.
* If max_single_mem_alloc is set to 0, which is the default, no other limit
* that the underlying _TIFFmalloc() or
* TIFFOpenOptionsSetMaxCumulatedMemAlloc() will be applied.
*/
void TIFFOpenOptionsSetMaxSingleMemAlloc(TIFFOpenOptions *opts,
tmsize_t max_single_mem_alloc)
@ -90,6 +97,18 @@ void TIFFOpenOptionsSetMaxSingleMemAlloc(TIFFOpenOptions *opts,
opts->max_single_mem_alloc = max_single_mem_alloc;
}
/** Define a limit in bytes for the cumulated memory allocations done by libtiff
* on a given TIFF handle.
* If max_cumulated_mem_alloc is set to 0, which is the default, no other limit
* that the underlying _TIFFmalloc() or
* TIFFOpenOptionsSetMaxSingleMemAlloc() will be applied.
*/
void TIFFOpenOptionsSetMaxCumulatedMemAlloc(TIFFOpenOptions *opts,
tmsize_t max_cumulated_mem_alloc)
{
opts->max_cumulated_mem_alloc = max_cumulated_mem_alloc;
}
void TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions *opts,
TIFFErrorHandlerExtR handler,
void *errorhandler_user_data)
@ -117,6 +136,30 @@ static void _TIFFEmitErrorAboveMaxSingleMemAlloc(TIFF *tif,
(uint64_t)s, (uint64_t)tif->tif_max_single_mem_alloc);
}
static void _TIFFEmitErrorAboveMaxCumulatedMemAlloc(TIFF *tif,
const char *pszFunction,
tmsize_t s)
{
TIFFErrorExtR(tif, pszFunction,
"Cumulated memory allocation of %" PRIu64 " + %" PRIu64
" bytes is beyond the %" PRIu64
" cumulated byte limit defined in open options",
(uint64_t)tif->tif_cur_cumulated_mem_alloc, (uint64_t)s,
(uint64_t)tif->tif_max_cumulated_mem_alloc);
}
/* When allocating memory, we write at the beginning of the buffer it size.
* This allows us to keep track of the total memory allocated when we
* malloc/calloc/realloc and free. In theory we need just SIZEOF_SIZE_T bytes
* for that, but on x86_64, allocations of more than 16 bytes are aligned on
* 16 bytes. Hence using 2 * SIZEOF_SIZE_T.
* It is critical that _TIFFmallocExt/_TIFFcallocExt/_TIFFreallocExt are
* paired with _TIFFfreeExt.
* CMakeLists.txt defines TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS, which in
* turn disables the definition of the non Ext version in tiffio.h
*/
#define LEADING_AREA_TO_STORE_ALLOC_SIZE (2 * SIZEOF_SIZE_T)
/** malloc() version that takes into account memory-specific open options */
void *_TIFFmallocExt(TIFF *tif, tmsize_t s)
{
@ -126,16 +169,32 @@ void *_TIFFmallocExt(TIFF *tif, tmsize_t s)
_TIFFEmitErrorAboveMaxSingleMemAlloc(tif, "_TIFFmallocExt", s);
return NULL;
}
if (tif != NULL && tif->tif_max_cumulated_mem_alloc > 0)
{
if (s > tif->tif_max_cumulated_mem_alloc -
tif->tif_cur_cumulated_mem_alloc ||
s > TIFF_TMSIZE_T_MAX - LEADING_AREA_TO_STORE_ALLOC_SIZE)
{
_TIFFEmitErrorAboveMaxCumulatedMemAlloc(tif, "_TIFFmallocExt", s);
return NULL;
}
void *ptr = _TIFFmalloc(LEADING_AREA_TO_STORE_ALLOC_SIZE + s);
if (!ptr)
return NULL;
tif->tif_cur_cumulated_mem_alloc += s;
memcpy(ptr, &s, sizeof(s));
return (char *)ptr + LEADING_AREA_TO_STORE_ALLOC_SIZE;
}
return _TIFFmalloc(s);
}
/** calloc() version that takes into account memory-specific open options */
void *_TIFFcallocExt(TIFF *tif, tmsize_t nmemb, tmsize_t siz)
{
if (nmemb <= 0 || siz <= 0 || nmemb > TIFF_TMSIZE_T_MAX / siz)
return NULL;
if (tif != NULL && tif->tif_max_single_mem_alloc > 0)
{
if (nmemb <= 0 || siz <= 0 || nmemb > TIFF_TMSIZE_T_MAX / siz)
return NULL;
if (nmemb * siz > tif->tif_max_single_mem_alloc)
{
_TIFFEmitErrorAboveMaxSingleMemAlloc(tif, "_TIFFcallocExt",
@ -143,6 +202,23 @@ void *_TIFFcallocExt(TIFF *tif, tmsize_t nmemb, tmsize_t siz)
return NULL;
}
}
if (tif != NULL && tif->tif_max_cumulated_mem_alloc > 0)
{
const tmsize_t s = nmemb * siz;
if (s > tif->tif_max_cumulated_mem_alloc -
tif->tif_cur_cumulated_mem_alloc ||
s > TIFF_TMSIZE_T_MAX - LEADING_AREA_TO_STORE_ALLOC_SIZE)
{
_TIFFEmitErrorAboveMaxCumulatedMemAlloc(tif, "_TIFFcallocExt", s);
return NULL;
}
void *ptr = _TIFFcalloc(LEADING_AREA_TO_STORE_ALLOC_SIZE + s, 1);
if (!ptr)
return NULL;
tif->tif_cur_cumulated_mem_alloc += s;
memcpy(ptr, &s, sizeof(s));
return (char *)ptr + LEADING_AREA_TO_STORE_ALLOC_SIZE;
}
return _TIFFcalloc(nmemb, siz);
}
@ -155,13 +231,49 @@ void *_TIFFreallocExt(TIFF *tif, void *p, tmsize_t s)
_TIFFEmitErrorAboveMaxSingleMemAlloc(tif, "_TIFFreallocExt", s);
return NULL;
}
if (tif != NULL && tif->tif_max_cumulated_mem_alloc > 0)
{
void *oldPtr = p;
tmsize_t oldSize = 0;
if (p)
{
oldPtr = (char *)p - LEADING_AREA_TO_STORE_ALLOC_SIZE;
memcpy(&oldSize, oldPtr, sizeof(oldSize));
assert(oldSize <= tif->tif_cur_cumulated_mem_alloc);
}
if (s > oldSize &&
(s > tif->tif_max_cumulated_mem_alloc -
(tif->tif_cur_cumulated_mem_alloc - oldSize) ||
s > TIFF_TMSIZE_T_MAX - LEADING_AREA_TO_STORE_ALLOC_SIZE))
{
_TIFFEmitErrorAboveMaxCumulatedMemAlloc(tif, "_TIFFreallocExt",
s - oldSize);
return NULL;
}
void *newPtr =
_TIFFrealloc(oldPtr, LEADING_AREA_TO_STORE_ALLOC_SIZE + s);
if (newPtr == NULL)
return NULL;
tif->tif_cur_cumulated_mem_alloc -= oldSize;
tif->tif_cur_cumulated_mem_alloc += s;
memcpy(newPtr, &s, sizeof(s));
return (char *)newPtr + LEADING_AREA_TO_STORE_ALLOC_SIZE;
}
return _TIFFrealloc(p, s);
}
/** free() version that takes into account memory-specific open options */
void _TIFFfreeExt(TIFF *tif, void *p)
{
(void)tif;
if (p != NULL && tif != NULL && tif->tif_max_cumulated_mem_alloc > 0)
{
void *oldPtr = (char *)p - LEADING_AREA_TO_STORE_ALLOC_SIZE;
tmsize_t oldSize;
memcpy(&oldSize, oldPtr, sizeof(oldSize));
assert(oldSize <= tif->tif_cur_cumulated_mem_alloc);
tif->tif_cur_cumulated_mem_alloc -= oldSize;
p = oldPtr;
}
_TIFFfree(p);
}
@ -231,6 +343,17 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
(uint64_t)opts->max_single_mem_alloc);
goto bad2;
}
if (opts && opts->max_cumulated_mem_alloc > 0 &&
size_to_alloc > opts->max_cumulated_mem_alloc)
{
_TIFFErrorEarly(opts, clientdata, module,
"%s: Memory allocation of %" PRIu64
" bytes is beyond the %" PRIu64
" cumulated byte limit defined in open options",
name, (uint64_t)size_to_alloc,
(uint64_t)opts->max_cumulated_mem_alloc);
goto bad2;
}
tif = (TIFF *)_TIFFmallocExt(NULL, size_to_alloc);
if (tif == NULL)
{
@ -243,6 +366,7 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
strcpy(tif->tif_name, name);
tif->tif_mode = m & ~(O_CREAT | O_TRUNC);
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; /* non-existent directory */
tif->tif_curdircount = TIFF_NON_EXISTENT_DIR_NUMBER;
tif->tif_curoff = 0;
tif->tif_curstrip = (uint32_t)-1; /* invalid strip */
tif->tif_row = (uint32_t)-1; /* read/write pre-increment */
@ -261,6 +385,7 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
tif->tif_warnhandler = opts->warnhandler;
tif->tif_warnhandler_user_data = opts->warnhandler_user_data;
tif->tif_max_single_mem_alloc = opts->max_single_mem_alloc;
tif->tif_max_cumulated_mem_alloc = opts->max_cumulated_mem_alloc;
}
if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc)
@ -423,9 +548,9 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
TIFFErrorExtR(tif, name, "Cannot read TIFF header");
goto bad;
}
/*
* Setup header and write.
*/
/*
* Setup header and write.
*/
#ifdef WORDS_BIGENDIAN
tif->tif_header.common.tiff_magic =
(tif->tif_flags & TIFF_SWAB) ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
@ -433,13 +558,17 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
tif->tif_header.common.tiff_magic =
(tif->tif_flags & TIFF_SWAB) ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN;
#endif
TIFFHeaderUnion tif_header_swapped;
if (!(tif->tif_flags & TIFF_BIGTIFF))
{
tif->tif_header.common.tiff_version = TIFF_VERSION_CLASSIC;
tif->tif_header.classic.tiff_diroff = 0;
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(&tif->tif_header.common.tiff_version);
tif->tif_header_size = sizeof(TIFFHeaderClassic);
/* Swapped copy for writing */
_TIFFmemcpy(&tif_header_swapped, &tif->tif_header,
sizeof(TIFFHeaderUnion));
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(&tif_header_swapped.common.tiff_version);
}
else
{
@ -447,12 +576,15 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
tif->tif_header.big.tiff_offsetsize = 8;
tif->tif_header.big.tiff_unused = 0;
tif->tif_header.big.tiff_diroff = 0;
tif->tif_header_size = sizeof(TIFFHeaderBig);
/* Swapped copy for writing */
_TIFFmemcpy(&tif_header_swapped, &tif->tif_header,
sizeof(TIFFHeaderUnion));
if (tif->tif_flags & TIFF_SWAB)
{
TIFFSwabShort(&tif->tif_header.common.tiff_version);
TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize);
TIFFSwabShort(&tif_header_swapped.common.tiff_version);
TIFFSwabShort(&tif_header_swapped.big.tiff_offsetsize);
}
tif->tif_header_size = sizeof(TIFFHeaderBig);
}
/*
* The doc for "fopen" for some STD_C_LIBs says that if you
@ -462,26 +594,12 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
* on Solaris.
*/
TIFFSeekFile(tif, 0, SEEK_SET);
if (!WriteOK(tif, &tif->tif_header, (tmsize_t)(tif->tif_header_size)))
if (!WriteOK(tif, &tif_header_swapped,
(tmsize_t)(tif->tif_header_size)))
{
TIFFErrorExtR(tif, name, "Error writing TIFF header");
goto bad;
}
/*
* Setup the byte order handling.
*/
if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN)
{
#ifndef WORDS_BIGENDIAN
tif->tif_flags |= TIFF_SWAB;
#endif
}
else
{
#ifdef WORDS_BIGENDIAN
tif->tif_flags |= TIFF_SWAB;
#endif
}
/*
* Setup default directory.
*/
@ -490,10 +608,14 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
tif->tif_diroff = 0;
tif->tif_lastdiroff = 0;
tif->tif_setdirectory_force_absolute = FALSE;
/* tif_curdircount = 0 means 'empty file opened for writing, but no IFD
* written yet' */
tif->tif_curdircount = 0;
return (tif);
}
/*
* Setup the byte order handling.
* Setup the byte order handling according to the opened file for reading.
*/
if (tif->tif_header.common.tiff_magic != TIFF_BIGENDIAN &&
tif->tif_header.common.tiff_magic != TIFF_LITTLEENDIAN
@ -619,9 +741,17 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
* example, it may be broken) and want to proceed to other
* directories. I this case we use the TIFF_HEADERONLY flag to open
* file and return immediately after reading TIFF header.
* However, the pointer to TIFFSetField() and TIFFGetField()
* (i.e. tif->tif_tagmethods.vsetfield and
* tif->tif_tagmethods.vgetfield) need to be initialized, which is
* done in TIFFDefaultDirectory().
*/
if (tif->tif_flags & TIFF_HEADERONLY)
{
if (!TIFFDefaultDirectory(tif))
goto bad;
return (tif);
}
/*
* Setup initial directory.
@ -764,10 +894,7 @@ int TIFFIsBigEndian(TIFF *tif)
/*
* Return nonzero if given file is BigTIFF style.
*/
int TIFFIsBigTIFF(TIFF *tif)
{
return (tif->tif_header.common.tiff_version == TIFF_VERSION_BIG);
}
int TIFFIsBigTIFF(TIFF *tif) { return ((tif->tif_flags & TIFF_BIGTIFF) != 0); }
/*
* Return pointer to file read method.

View File

@ -300,6 +300,7 @@ static int PackBitsDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
tif->tif_rawcc = cc;
if (occ > 0)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32,
tif->tif_row);
return (0);

View File

@ -670,8 +670,8 @@ static int PixarLogMakeTables(TIFF *tif, PixarLogState *sp)
return 1;
}
#define DecoderState(tif) ((PixarLogState *)(tif)->tif_data)
#define EncoderState(tif) ((PixarLogState *)(tif)->tif_data)
#define PixarLogDecoderState(tif) ((PixarLogState *)(tif)->tif_data)
#define PixarLogEncoderState(tif) ((PixarLogState *)(tif)->tif_data)
static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
@ -740,7 +740,7 @@ static int PixarLogSetupDecode(TIFF *tif)
{
static const char module[] = "PixarLogSetupDecode";
TIFFDirectory *td = &tif->tif_dir;
PixarLogState *sp = DecoderState(tif);
PixarLogState *sp = PixarLogDecoderState(tif);
tmsize_t tbuf_size;
uint32_t strip_height;
@ -813,7 +813,7 @@ static int PixarLogSetupDecode(TIFF *tif)
static int PixarLogPreDecode(TIFF *tif, uint16_t s)
{
static const char module[] = "PixarLogPreDecode";
PixarLogState *sp = DecoderState(tif);
PixarLogState *sp = PixarLogDecoderState(tif);
(void)s;
assert(sp != NULL);
@ -835,7 +835,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{
static const char module[] = "PixarLogDecode";
TIFFDirectory *td = &tif->tif_dir;
PixarLogState *sp = DecoderState(tif);
PixarLogState *sp = PixarLogDecoderState(tif);
tmsize_t i;
tmsize_t nsamples;
int llen;
@ -859,6 +859,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
TIFFErrorExtR(tif, module,
"%" PRIu16 " bit input not supported in PixarLog",
td->td_bitspersample);
memset(op, 0, (size_t)occ);
return 0;
}
@ -879,12 +880,14 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (sp->stream.avail_out != nsamples * sizeof(uint16_t))
{
TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
memset(op, 0, (size_t)occ);
return (0);
}
/* Check that we will not fill more than what was allocated */
if ((tmsize_t)sp->stream.avail_out > sp->tbuf_size)
{
TIFFErrorExtR(tif, module, "sp->stream.avail_out > sp->tbuf_size");
memset(op, 0, (size_t)occ);
return (0);
}
do
@ -899,12 +902,14 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
TIFFErrorExtR(
tif, module, "Decoding error at scanline %" PRIu32 ", %s",
tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)");
memset(op, 0, (size_t)occ);
return (0);
}
if (state != Z_OK)
{
TIFFErrorExtR(tif, module, "ZLib error: %s",
sp->stream.msg ? sp->stream.msg : "(null)");
memset(op, 0, (size_t)occ);
return (0);
}
} while (sp->stream.avail_out > 0);
@ -916,6 +921,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
"Not enough data at scanline %" PRIu32
" (short %u bytes)",
tif->tif_row, sp->stream.avail_out);
memset(op, 0, (size_t)occ);
return (0);
}
@ -977,6 +983,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
default:
TIFFErrorExtR(tif, module, "Unsupported bits/sample: %" PRIu16,
td->td_bitspersample);
memset(op, 0, (size_t)occ);
return (0);
}
}
@ -988,7 +995,7 @@ static int PixarLogSetupEncode(TIFF *tif)
{
static const char module[] = "PixarLogSetupEncode";
TIFFDirectory *td = &tif->tif_dir;
PixarLogState *sp = EncoderState(tif);
PixarLogState *sp = PixarLogEncoderState(tif);
tmsize_t tbuf_size;
assert(sp != NULL);
@ -1038,7 +1045,7 @@ static int PixarLogSetupEncode(TIFF *tif)
static int PixarLogPreEncode(TIFF *tif, uint16_t s)
{
static const char module[] = "PixarLogPreEncode";
PixarLogState *sp = EncoderState(tif);
PixarLogState *sp = PixarLogEncoderState(tif);
(void)s;
assert(sp != NULL);
@ -1294,7 +1301,7 @@ static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{
static const char module[] = "PixarLogEncode";
TIFFDirectory *td = &tif->tif_dir;
PixarLogState *sp = EncoderState(tif);
PixarLogState *sp = PixarLogEncoderState(tif);
tmsize_t i;
tmsize_t n;
int llen;
@ -1401,7 +1408,7 @@ static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
static int PixarLogPostEncode(TIFF *tif)
{
static const char module[] = "PixarLogPostEncode";
PixarLogState *sp = EncoderState(tif);
PixarLogState *sp = PixarLogEncoderState(tif);
int state;
sp->stream.avail_in = 0;

View File

@ -105,8 +105,8 @@ static int TIFFReadAndRealloc(TIFF *tif, tmsize_t size, tmsize_t rawdata_offset,
TIFFErrorExtR(tif, module, "Invalid buffer size");
return 0;
}
new_rawdata =
(uint8_t *)_TIFFrealloc(tif->tif_rawdata, tif->tif_rawdatasize);
new_rawdata = (uint8_t *)_TIFFreallocExt(tif, tif->tif_rawdata,
tif->tif_rawdatasize);
if (new_rawdata == 0)
{
TIFFErrorExtR(tif, module,
@ -464,6 +464,10 @@ int TIFFReadScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
if (e)
(*tif->tif_postdecode)(tif, (uint8_t *)buf, tif->tif_scanlinesize);
}
else
{
memset(buf, 0, (size_t)tif->tif_scanlinesize);
}
return (e > 0 ? 1 : -1);
}
@ -495,6 +499,11 @@ static tmsize_t TIFFReadEncodedStripGetStripSize(TIFF *tif, uint32_t strip,
rowsperstrip = td->td_rowsperstrip;
if (rowsperstrip > td->td_imagelength)
rowsperstrip = td->td_imagelength;
if (rowsperstrip == 0)
{
TIFFErrorExtR(tif, module, "rowsperstrip is zero");
return ((tmsize_t)(-1));
}
stripsperplane =
TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip);
stripinplane = (strip % stripsperplane);
@ -544,7 +553,10 @@ tmsize_t TIFFReadEncodedStrip(TIFF *tif, uint32_t strip, void *buf,
if ((size != (tmsize_t)(-1)) && (size < stripsize))
stripsize = size;
if (!TIFFFillStrip(tif, strip))
{
memset(buf, 0, (size_t)stripsize);
return ((tmsize_t)(-1));
}
if ((*tif->tif_decodestrip)(tif, buf, stripsize, plane) <= 0)
return ((tmsize_t)(-1));
(*tif->tif_postdecode)(tif, buf, stripsize);
@ -962,9 +974,13 @@ tmsize_t TIFFReadEncodedTile(TIFF *tif, uint32_t tile, void *buf, tmsize_t size)
size = tilesize;
else if (size > tilesize)
size = tilesize;
if (TIFFFillTile(tif, tile) &&
(*tif->tif_decodetile)(tif, (uint8_t *)buf, size,
(uint16_t)(tile / td->td_stripsperimage)))
if (!TIFFFillTile(tif, tile))
{
memset(buf, 0, (size_t)size);
return ((tmsize_t)(-1));
}
else if ((*tif->tif_decodetile)(tif, (uint8_t *)buf, size,
(uint16_t)(tile / td->td_stripsperimage)))
{
(*tif->tif_postdecode)(tif, (uint8_t *)buf, size);
return (size);
@ -1449,6 +1465,11 @@ static int TIFFStartTile(TIFF *tif, uint32_t tile)
tif->tif_flags |= TIFF_CODERSETUP;
}
tif->tif_curtile = tile;
if (td->td_tilewidth == 0)
{
TIFFErrorExtR(tif, module, "Zero tilewidth");
return 0;
}
howmany32 = TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth);
if (howmany32 == 0)
{
@ -1545,9 +1566,14 @@ int TIFFReadFromUserBuffer(TIFF *tif, uint32_t strile, void *inbuf,
if (TIFFIsTiled(tif))
{
if (!TIFFStartTile(tif, strile) ||
!(*tif->tif_decodetile)(tif, (uint8_t *)outbuf, outsize,
(uint16_t)(strile / td->td_stripsperimage)))
if (!TIFFStartTile(tif, strile))
{
ret = 0;
memset(outbuf, 0, (size_t)outsize);
}
else if (!(*tif->tif_decodetile)(
tif, (uint8_t *)outbuf, outsize,
(uint16_t)(strile / td->td_stripsperimage)))
{
ret = 0;
}
@ -1558,14 +1584,27 @@ int TIFFReadFromUserBuffer(TIFF *tif, uint32_t strile, void *inbuf,
uint32_t stripsperplane;
if (rowsperstrip > td->td_imagelength)
rowsperstrip = td->td_imagelength;
stripsperplane =
TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip);
if (!TIFFStartStrip(tif, strile) ||
!(*tif->tif_decodestrip)(tif, (uint8_t *)outbuf, outsize,
(uint16_t)(strile / stripsperplane)))
if (rowsperstrip == 0)
{
TIFFErrorExtR(tif, module, "rowsperstrip is zero");
ret = 0;
}
else
{
stripsperplane =
TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip);
if (!TIFFStartStrip(tif, strile))
{
ret = 0;
memset(outbuf, 0, (size_t)outsize);
}
else if (!(*tif->tif_decodestrip)(
tif, (uint8_t *)outbuf, outsize,
(uint16_t)(strile / stripsperplane)))
{
ret = 0;
}
}
}
if (ret)
{

View File

@ -38,6 +38,11 @@ uint32_t TIFFComputeStrip(TIFF *tif, uint32_t row, uint16_t sample)
TIFFDirectory *td = &tif->tif_dir;
uint32_t strip;
if (td->td_rowsperstrip == 0)
{
TIFFErrorExtR(tif, module, "Cannot compute strip: RowsPerStrip is zero");
return 0;
}
strip = row / td->td_rowsperstrip;
if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
{
@ -61,6 +66,11 @@ uint32_t TIFFNumberOfStrips(TIFF *tif)
TIFFDirectory *td = &tif->tif_dir;
uint32_t nstrips;
if (td->td_rowsperstrip == 0)
{
TIFFWarningExtR(tif, "TIFFNumberOfStrips", "RowsPerStrip is zero");
return 0;
}
nstrips = (td->td_rowsperstrip == (uint32_t)-1
? 1
: TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip));
@ -107,7 +117,8 @@ uint64_t TIFFVStripSize64(TIFF *tif, uint32_t nrows)
if ((ycbcrsubsampling[0] != 1 && ycbcrsubsampling[0] != 2 &&
ycbcrsubsampling[0] != 4) ||
(ycbcrsubsampling[1] != 1 && ycbcrsubsampling[1] != 2 &&
ycbcrsubsampling[1] != 4))
ycbcrsubsampling[1] != 4) ||
(ycbcrsubsampling[0] == 0 || ycbcrsubsampling[1] == 0))
{
TIFFErrorExtR(tif, module, "Invalid YCbCr subsampling (%dx%d)",
ycbcrsubsampling[0], ycbcrsubsampling[1]);
@ -267,7 +278,8 @@ uint64_t TIFFScanlineSize64(TIFF *tif)
if (((ycbcrsubsampling[0] != 1) && (ycbcrsubsampling[0] != 2) &&
(ycbcrsubsampling[0] != 4)) ||
((ycbcrsubsampling[1] != 1) && (ycbcrsubsampling[1] != 2) &&
(ycbcrsubsampling[1] != 4)))
(ycbcrsubsampling[1] != 4)) ||
((ycbcrsubsampling[0] == 0) || (ycbcrsubsampling[1] == 0)))
{
TIFFErrorExtR(tif, module, "Invalid YCbCr subsampling");
return 0;
@ -287,7 +299,25 @@ uint64_t TIFFScanlineSize64(TIFF *tif)
else
{
uint64_t scanline_samples;
scanline_samples = _TIFFMultiply64(tif, td->td_imagewidth,
uint32_t scanline_width = td->td_imagewidth;
#if 0
// Tries to fix https://gitlab.com/libtiff/libtiff/-/merge_requests/564
// but causes regression when decoding legit files with tiffcp -c none
// Cf https://gitlab.com/libtiff/libtiff/-/merge_requests/644
if (td->td_photometric == PHOTOMETRIC_YCBCR)
{
uint16_t subsampling_hor;
uint16_t ignored;
TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING,
&subsampling_hor, &ignored);
if (subsampling_hor > 1) // roundup width for YCbCr
scanline_width =
TIFFroundup_32(scanline_width, subsampling_hor);
}
#endif
scanline_samples = _TIFFMultiply64(tif, scanline_width,
td->td_samplesperpixel, module);
scanline_size =
TIFFhowmany_64(_TIFFMultiply64(tif, scanline_samples,

View File

@ -82,13 +82,14 @@ static int ThunderSetupDecode(TIFF *tif)
return (1);
}
static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels)
static int ThunderDecode(TIFF *tif, uint8_t *op0, tmsize_t maxpixels)
{
static const char module[] = "ThunderDecode";
register unsigned char *bp;
register tmsize_t cc;
unsigned int lastpixel;
tmsize_t npixels;
uint8_t *op = op0;
bp = (unsigned char *)tif->tif_rawcp;
cc = tif->tif_rawcc;
@ -107,6 +108,8 @@ static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels)
* Replicate the last pixel n times,
* where n is the lower-order 6 bits.
*/
if (n == 0)
break;
if (npixels & 1)
{
op[0] |= lastpixel;
@ -117,11 +120,10 @@ static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels)
else
lastpixel |= lastpixel << 4;
npixels += n;
if (npixels < maxpixels)
{
for (; n > 0; n -= 2)
*op++ = (uint8_t)lastpixel;
}
if (npixels > maxpixels)
break;
for (; n > 0; n -= 2)
*op++ = (uint8_t)lastpixel;
if (n == -1)
*--op &= 0xf0;
lastpixel &= 0xf;
@ -154,6 +156,8 @@ static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels)
tif->tif_rawcc = cc;
if (npixels != maxpixels)
{
uint8_t *op_end = op0 + (maxpixels + 1) / 2;
memset(op, 0, (size_t)(op_end - op));
TIFFErrorExtR(tif, module,
"%s data at scanline %lu (%" PRIu64 " != %" PRIu64 ")",
npixels < maxpixels ? "Not enough" : "Too much",

View File

@ -27,6 +27,10 @@
* Windows Common RunTime Library.
*/
#ifdef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
#undef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
#endif
#include "tif_config.h"
#ifdef HAVE_SYS_TYPES_H
@ -79,6 +83,8 @@ static tmsize_t _tiffReadProc(thandle_t fd, void *buf, tmsize_t size)
size_t io_size = bytes_total - bytes_read;
if (io_size > TIFF_IO_MAX)
io_size = TIFF_IO_MAX;
/* Below is an obvious false positive of Coverity Scan */
/* coverity[overflow_sink] */
count = read(fdh.fd, buf_offset, (TIFFIOSize_t)io_size);
if (count <= 0)
break;
@ -106,6 +112,8 @@ static tmsize_t _tiffWriteProc(thandle_t fd, void *buf, tmsize_t size)
size_t io_size = bytes_total - bytes_written;
if (io_size > TIFF_IO_MAX)
io_size = TIFF_IO_MAX;
/* Below is an obvious false positive of Coverity Scan */
/* coverity[overflow_sink] */
count = write(fdh.fd, buf_offset, (TIFFIOSize_t)io_size);
if (count <= 0)
break;
@ -258,7 +266,7 @@ TIFF *TIFFOpenExt(const char *name, const char *mode, TIFFOpenOptions *opts)
return tif;
}
#ifdef __WIN32__
#ifdef _WIN32
#include <windows.h>
/*
* Open a TIFF file with a Unicode filename, for read/writing.

View File

@ -47,7 +47,9 @@ typedef struct
{
uint16_t nSamples; /* number of samples per pixel */
int lossless; /* lossy/lossless compression */
int read_error; /* whether a read error has occurred, and which should cause
further reads in the same strip/tile to be aborted */
int lossless; /* lossy/lossless compression */
int lossless_exact; /* lossless exact mode. If TRUE, R,G,B values in areas
with alpha = 0 will be preserved */
int quality_level; /* compression level */
@ -133,6 +135,16 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
assert(sp != NULL);
assert(sp->state == LSTATE_INIT_DECODE);
if (sp->read_error)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"ZIPDecode: Scanline %" PRIu32 " cannot be read due to "
"previous error",
tif->tif_row);
return 0;
}
if (sp->psDecoder == NULL)
{
TIFFDirectory *td = &tif->tif_dir;
@ -158,12 +170,16 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
: (uint32_t)tif->tif_rawcc,
&webp_width, &webp_height))
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module, "WebPGetInfo() failed");
return 0;
}
if ((uint32_t)webp_width != segment_width ||
(uint32_t)webp_height != segment_height)
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(
tif, module, "WebP blob dimension is %dx%d. Expected %ux%u",
webp_width, webp_height, segment_width, segment_height);
@ -174,6 +190,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
WebPDecoderConfig config;
if (!WebPInitDecoderConfig(&config))
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed");
return 0;
}
@ -189,6 +207,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (!bWebPGetFeaturesOK)
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed");
return 0;
}
@ -202,6 +222,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
*/
!(webp_bands == 3 && sp->nSamples == 4))
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module,
"WebP blob band count is %d. Expected %d", webp_bands,
sp->nSamples);
@ -228,6 +250,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (!sp->pBuffer)
{
TIFFErrorExtR(tif, module, "Cannot allocate buffer");
memset(op, 0, (size_t)occ);
sp->read_error = 1;
return 0;
}
sp->buffer_size = buffer_size;
@ -257,6 +281,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (sp->psDecoder == NULL)
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module, "Unable to allocate WebP decoder.");
return 0;
}
@ -264,6 +290,10 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (occ % sp->sDecBuffer.u.RGBA.stride)
{
// read_error not set here as this is a usage issue that can be
// recovered in a following call.
memset(op, 0, (size_t)occ);
/* Do not set read_error as could potentially be recovered */
TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
return 0;
}
@ -284,6 +314,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{
TIFFErrorExtR(tif, module, "Unrecognized error.");
}
memset(op, 0, (size_t)occ);
sp->read_error = 1;
return 0;
}
else
@ -303,6 +335,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{
if (current_y != numberOfExpectedLines)
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module,
"Unable to decode WebP data: less lines than "
"expected.");
@ -332,6 +366,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
}
else
{
memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module, "Unable to decode WebP data.");
return 0;
}
@ -451,6 +487,8 @@ static int TWebPPreDecode(TIFF *tif, uint16_t s)
sp->psDecoder = NULL;
}
sp->read_error = 0;
return 1;
}

View File

@ -27,6 +27,10 @@
* Scott Wagner (wagner@itek.com), Itek Graphix, Rochester, NY USA
*/
#ifdef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
#undef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
#endif
#include "tiffiop.h"
#include <stdlib.h>

View File

@ -67,6 +67,8 @@ typedef struct
{
TIFFPredictorState predict;
z_stream stream;
int read_error; /* whether a read error has occurred, and which should cause
further reads in the same strip/tile to be aborted */
int zipquality; /* compression level */
int state; /* state flags */
int subcodec; /* DEFLATE_SUBCODEC_ZLIB or DEFLATE_SUBCODEC_LIBDEFLATE */
@ -83,9 +85,9 @@ typedef struct
TIFFVSetMethod vsetparent; /* super-class method */
} ZIPState;
#define ZState(tif) ((ZIPState *)(tif)->tif_data)
#define DecoderState(tif) ZState(tif)
#define EncoderState(tif) ZState(tif)
#define GetZIPState(tif) ((ZIPState *)(tif)->tif_data)
#define ZIPDecoderState(tif) GetZIPState(tif)
#define ZIPEncoderState(tif) GetZIPState(tif)
static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
@ -99,7 +101,7 @@ static int ZIPFixupTags(TIFF *tif)
static int ZIPSetupDecode(TIFF *tif)
{
static const char module[] = "ZIPSetupDecode";
ZIPState *sp = DecoderState(tif);
ZIPState *sp = ZIPDecoderState(tif);
assert(sp != NULL);
@ -131,7 +133,7 @@ static int ZIPSetupDecode(TIFF *tif)
*/
static int ZIPPreDecode(TIFF *tif, uint16_t s)
{
ZIPState *sp = DecoderState(tif);
ZIPState *sp = ZIPDecoderState(tif);
(void)s;
assert(sp != NULL);
@ -150,18 +152,33 @@ static int ZIPPreDecode(TIFF *tif, uint16_t s)
sp->stream.avail_in = (uint64_t)tif->tif_rawcc < 0xFFFFFFFFU
? (uInt)tif->tif_rawcc
: 0xFFFFFFFFU;
return (inflateReset(&sp->stream) == Z_OK);
if (inflateReset(&sp->stream) == Z_OK)
{
sp->read_error = 0;
return 1;
}
return 0;
}
static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{
static const char module[] = "ZIPDecode";
ZIPState *sp = DecoderState(tif);
ZIPState *sp = ZIPDecoderState(tif);
(void)s;
assert(sp != NULL);
assert(sp->state == ZSTATE_INIT_DECODE);
if (sp->read_error)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"ZIPDecode: Scanline %" PRIu32 " cannot be read due to "
"previous error",
tif->tif_row);
return 0;
}
#if LIBDEFLATE_SUPPORT
if (sp->libdeflate_state == 1)
return 0;
@ -227,8 +244,10 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (res != LIBDEFLATE_SUCCESS &&
res != LIBDEFLATE_INSUFFICIENT_SPACE)
{
memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module, "Decoding error at scanline %lu",
(unsigned long)tif->tif_row);
sp->read_error = 1;
return 0;
}
@ -263,13 +282,17 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
break;
if (state == Z_DATA_ERROR)
{
memset(sp->stream.next_out, 0, sp->stream.avail_out);
TIFFErrorExtR(tif, module, "Decoding error at scanline %lu, %s",
(unsigned long)tif->tif_row, SAFE_MSG(sp));
sp->read_error = 1;
return (0);
}
if (state != Z_OK)
{
memset(sp->stream.next_out, 0, sp->stream.avail_out);
TIFFErrorExtR(tif, module, "ZLib error: %s", SAFE_MSG(sp));
sp->read_error = 1;
return (0);
}
} while (occ > 0);
@ -279,6 +302,8 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
"Not enough data at scanline %lu (short %" PRIu64
" bytes)",
(unsigned long)tif->tif_row, (uint64_t)occ);
memset(sp->stream.next_out, 0, sp->stream.avail_out);
sp->read_error = 1;
return (0);
}
@ -290,7 +315,7 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
static int ZIPSetupEncode(TIFF *tif)
{
static const char module[] = "ZIPSetupEncode";
ZIPState *sp = EncoderState(tif);
ZIPState *sp = ZIPEncoderState(tif);
int cappedQuality;
assert(sp != NULL);
@ -321,7 +346,7 @@ static int ZIPSetupEncode(TIFF *tif)
*/
static int ZIPPreEncode(TIFF *tif, uint16_t s)
{
ZIPState *sp = EncoderState(tif);
ZIPState *sp = ZIPEncoderState(tif);
(void)s;
assert(sp != NULL);
@ -348,7 +373,7 @@ static int ZIPPreEncode(TIFF *tif, uint16_t s)
static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{
static const char module[] = "ZIPEncode";
ZIPState *sp = EncoderState(tif);
ZIPState *sp = ZIPEncoderState(tif);
assert(sp != NULL);
assert(sp->state == ZSTATE_INIT_ENCODE);
@ -487,7 +512,7 @@ static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
static int ZIPPostEncode(TIFF *tif)
{
static const char module[] = "ZIPPostEncode";
ZIPState *sp = EncoderState(tif);
ZIPState *sp = ZIPEncoderState(tif);
int state;
#if LIBDEFLATE_SUPPORT
@ -526,7 +551,7 @@ static int ZIPPostEncode(TIFF *tif)
static void ZIPCleanup(TIFF *tif)
{
ZIPState *sp = ZState(tif);
ZIPState *sp = GetZIPState(tif);
assert(sp != 0);
@ -562,7 +587,7 @@ static void ZIPCleanup(TIFF *tif)
static int ZIPVSetField(TIFF *tif, uint32_t tag, va_list ap)
{
static const char module[] = "ZIPVSetField";
ZIPState *sp = ZState(tif);
ZIPState *sp = GetZIPState(tif);
switch (tag)
{
@ -628,7 +653,7 @@ static int ZIPVSetField(TIFF *tif, uint32_t tag, va_list ap)
static int ZIPVGetField(TIFF *tif, uint32_t tag, va_list ap)
{
ZIPState *sp = ZState(tif);
ZIPState *sp = GetZIPState(tif);
switch (tag)
{
@ -680,7 +705,7 @@ int TIFFInitZIP(TIFF *tif, int scheme)
tif->tif_data = (uint8_t *)_TIFFcallocExt(tif, sizeof(ZIPState), 1);
if (tif->tif_data == NULL)
goto bad;
sp = ZState(tif);
sp = GetZIPState(tif);
sp->stream.zalloc = NULL;
sp->stream.zfree = NULL;
sp->stream.opaque = NULL;

View File

@ -54,9 +54,9 @@ typedef struct
TIFFVSetMethod vsetparent; /* super-class method */
} ZSTDState;
#define LState(tif) ((ZSTDState *)(tif)->tif_data)
#define DecoderState(tif) LState(tif)
#define EncoderState(tif) LState(tif)
#define GetZSTDState(tif) ((ZSTDState *)(tif)->tif_data)
#define ZSTDDecoderState(tif) GetZSTDState(tif)
#define ZSTDEncoderState(tif) GetZSTDState(tif)
static int ZSTDEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
@ -69,7 +69,7 @@ static int ZSTDFixupTags(TIFF *tif)
static int ZSTDSetupDecode(TIFF *tif)
{
ZSTDState *sp = DecoderState(tif);
ZSTDState *sp = ZSTDDecoderState(tif);
assert(sp != NULL);
@ -91,7 +91,7 @@ static int ZSTDSetupDecode(TIFF *tif)
static int ZSTDPreDecode(TIFF *tif, uint16_t s)
{
static const char module[] = "ZSTDPreDecode";
ZSTDState *sp = DecoderState(tif);
ZSTDState *sp = ZSTDDecoderState(tif);
size_t zstd_ret;
(void)s;
@ -124,7 +124,7 @@ static int ZSTDPreDecode(TIFF *tif, uint16_t s)
static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
{
static const char module[] = "ZSTDDecode";
ZSTDState *sp = DecoderState(tif);
ZSTDState *sp = ZSTDDecoderState(tif);
ZSTD_inBuffer in_buffer;
ZSTD_outBuffer out_buffer;
size_t zstd_ret;
@ -146,6 +146,7 @@ static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
zstd_ret = ZSTD_decompressStream(sp->dstream, &out_buffer, &in_buffer);
if (ZSTD_isError(zstd_ret))
{
memset(op + out_buffer.pos, 0, out_buffer.size - out_buffer.pos);
TIFFErrorExtR(tif, module, "Error in ZSTD_decompressStream(): %s",
ZSTD_getErrorName(zstd_ret));
return 0;
@ -155,6 +156,7 @@ static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
if (out_buffer.pos < (size_t)occ)
{
memset(op + out_buffer.pos, 0, out_buffer.size - out_buffer.pos);
TIFFErrorExtR(tif, module,
"Not enough data at scanline %lu (short %lu bytes)",
(unsigned long)tif->tif_row,
@ -170,7 +172,7 @@ static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
static int ZSTDSetupEncode(TIFF *tif)
{
ZSTDState *sp = EncoderState(tif);
ZSTDState *sp = ZSTDEncoderState(tif);
assert(sp != NULL);
if (sp->state & LSTATE_INIT_DECODE)
@ -190,7 +192,7 @@ static int ZSTDSetupEncode(TIFF *tif)
static int ZSTDPreEncode(TIFF *tif, uint16_t s)
{
static const char module[] = "ZSTDPreEncode";
ZSTDState *sp = EncoderState(tif);
ZSTDState *sp = ZSTDEncoderState(tif);
size_t zstd_ret;
(void)s;
@ -229,7 +231,7 @@ static int ZSTDPreEncode(TIFF *tif, uint16_t s)
static int ZSTDEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{
static const char module[] = "ZSTDEncode";
ZSTDState *sp = EncoderState(tif);
ZSTDState *sp = ZSTDEncoderState(tif);
ZSTD_inBuffer in_buffer;
size_t zstd_ret;
@ -271,7 +273,7 @@ static int ZSTDEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
static int ZSTDPostEncode(TIFF *tif)
{
static const char module[] = "ZSTDPostEncode";
ZSTDState *sp = EncoderState(tif);
ZSTDState *sp = ZSTDEncoderState(tif);
size_t zstd_ret;
do
@ -297,7 +299,7 @@ static int ZSTDPostEncode(TIFF *tif)
static void ZSTDCleanup(TIFF *tif)
{
ZSTDState *sp = LState(tif);
ZSTDState *sp = GetZSTDState(tif);
assert(sp != 0);
@ -325,7 +327,7 @@ static void ZSTDCleanup(TIFF *tif)
static int ZSTDVSetField(TIFF *tif, uint32_t tag, va_list ap)
{
static const char module[] = "ZSTDVSetField";
ZSTDState *sp = LState(tif);
ZSTDState *sp = GetZSTDState(tif);
switch (tag)
{
@ -347,7 +349,7 @@ static int ZSTDVSetField(TIFF *tif, uint32_t tag, va_list ap)
static int ZSTDVGetField(TIFF *tif, uint32_t tag, va_list ap)
{
ZSTDState *sp = LState(tif);
ZSTDState *sp = GetZSTDState(tif);
switch (tag)
{
@ -389,7 +391,7 @@ int TIFFInitZSTD(TIFF *tif, int scheme)
tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(ZSTDState));
if (tif->tif_data == NULL)
goto bad;
sp = LState(tif);
sp = GetZSTDState(tif);
/*
* Override parent get/set field methods.

View File

@ -77,10 +77,6 @@ typedef tstrile_t ttile_t; /* tile number */
typedef tmsize_t tsize_t; /* i/o size in bytes */
typedef void *tdata_t; /* image data ref */
#if !defined(__WIN32__) && (defined(_WIN32) || defined(WIN32))
#define __WIN32__
#endif
/*
* On windows you should define USE_WIN32_FILEIO if you are using tif_win32.c
* or AVOID_WIN32_FILEIO if you are using something else (like tif_unix.c).
@ -88,7 +84,7 @@ typedef void *tdata_t; /* image data ref */
* By default tif_unix.c is assumed.
*/
#if defined(_WINDOWS) || defined(__WIN32__) || defined(_Windows)
#if defined(_WIN32)
#if !defined(__CYGWIN) && !defined(AVOID_WIN32_FILEIO) && \
!defined(USE_WIN32_FILEIO)
#define AVOID_WIN32_FILEIO
@ -98,11 +94,11 @@ typedef void *tdata_t; /* image data ref */
#if defined(USE_WIN32_FILEIO)
#define VC_EXTRALEAN
#include <windows.h>
#ifdef __WIN32__
#ifdef _WIN32
DECLARE_HANDLE(thandle_t); /* Win32 file handle */
#else
typedef HFILE thandle_t; /* client data handle */
#endif /* __WIN32__ */
#endif /* _WIN32 */
#else
typedef void *thandle_t; /* client data handle */
#endif /* USE_WIN32_FILEIO */
@ -311,14 +307,15 @@ extern "C"
/*
* Auxiliary functions.
*/
#ifndef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
extern void *_TIFFmalloc(tmsize_t s);
extern void *_TIFFcalloc(tmsize_t nmemb, tmsize_t siz);
extern void *_TIFFrealloc(void *p, tmsize_t s);
extern void _TIFFfree(void *p);
#endif
extern void _TIFFmemset(void *p, int v, tmsize_t c);
extern void _TIFFmemcpy(void *d, const void *s, tmsize_t c);
extern int _TIFFmemcmp(const void *p1, const void *p2, tmsize_t c);
extern void _TIFFfree(void *p);
/*
** Stuff, related to tag handling and creating custom tags.
@ -508,6 +505,9 @@ extern int TIFFReadRGBAImageOriented(TIFF *, uint32_t, uint32_t, uint32_t *,
TIFFOpenOptionsSetMaxSingleMemAlloc(TIFFOpenOptions *opts,
tmsize_t max_single_mem_alloc);
extern void
TIFFOpenOptionsSetMaxCumulatedMemAlloc(TIFFOpenOptions *opts,
tmsize_t max_cumulated_mem_alloc);
extern void
TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions *opts,
TIFFErrorHandlerExtR handler,
void *errorhandler_user_data);
@ -518,11 +518,11 @@ extern int TIFFReadRGBAImageOriented(TIFF *, uint32_t, uint32_t, uint32_t *,
extern TIFF *TIFFOpen(const char *, const char *);
extern TIFF *TIFFOpenExt(const char *, const char *, TIFFOpenOptions *opts);
#ifdef __WIN32__
#ifdef _WIN32
extern TIFF *TIFFOpenW(const wchar_t *, const char *);
extern TIFF *TIFFOpenWExt(const wchar_t *, const char *,
TIFFOpenOptions *opts);
#endif /* __WIN32__ */
#endif /* _WIN32 */
extern TIFF *TIFFFdOpen(int, const char *, const char *);
extern TIFF *TIFFFdOpenExt(int, const char *, const char *,
TIFFOpenOptions *opts);

View File

@ -102,6 +102,13 @@ struct TIFFOffsetAndDirNumber
};
typedef struct TIFFOffsetAndDirNumber TIFFOffsetAndDirNumber;
typedef union
{
TIFFHeaderCommon common;
TIFFHeaderClassic classic;
TIFFHeaderBig big;
} TIFFHeaderUnion;
struct tiff
{
char *tif_name; /* name of open file */
@ -153,20 +160,35 @@ struct tiff
TIFFDirectory tif_dir; /* internal rep of current directory */
TIFFDirectory
tif_customdir; /* custom IFDs are separated from the main ones */
union
{
TIFFHeaderCommon common;
TIFFHeaderClassic classic;
TIFFHeaderBig big;
} tif_header;
uint16_t tif_header_size; /* file's header block and its length */
uint32_t tif_row; /* current scanline */
tdir_t tif_curdir; /* current directory (index) */
TIFFHeaderUnion tif_header; /* file's header block Classic/BigTIFF union */
uint16_t tif_header_size; /* file's header block and its length */
uint32_t tif_row; /* current scanline */
/* There are IFDs in the file and an "active" IFD in memory,
* from which fields are "set" and "get".
* tif_curdir is set to:
* a) TIFF_NON_EXISTENT_DIR_NUMBER if there is no IFD in the file
* or the state is unknown,
* or the last read (i.e. TIFFFetchDirectory()) failed,
* or a custom directory was written.
* b) IFD index of last IFD written in the file. In this case the
* active IFD is a new (empty) one and tif_diroff is zero.
* If writing fails, tif_curdir is not changed.
* c) IFD index of IFD read from file into memory (=active IFD),
* even if IFD is corrupt and TIFFReadDirectory() returns 0.
* Then tif_diroff contains the offset of the IFD in the file.
* d) IFD index 0, whenever a custom directory or an unchained SubIFD
* was read. */
tdir_t tif_curdir; /* current directory (index) */
/* tif_curdircount: number of directories (main-IFDs) in file:
* - TIFF_NON_EXISTENT_DIR_NUMBER means 'dont know number of IFDs'.
* - 0 means 'empty file opened for writing, but no IFD written yet' */
tdir_t tif_curdircount;
uint32_t tif_curstrip; /* current strip for read/write */
uint64_t tif_curoff; /* current offset for read/write */
uint64_t tif_lastvalidoff; /* last valid offset allowed for rewrite in
place. Used only by TIFFAppendToStrip() */
uint64_t tif_dataoff; /* current offset for writing dir */
uint64_t tif_dataoff; /* current offset for writing dir (IFD) */
/* SubIFD support */
uint16_t tif_nsubifd; /* remaining subifds to write */
uint64_t tif_subifdoff; /* offset for patching SubIFD link */
@ -233,7 +255,9 @@ struct tiff
void *tif_errorhandler_user_data;
TIFFErrorHandlerExtR tif_warnhandler;
void *tif_warnhandler_user_data;
tmsize_t tif_max_single_mem_alloc; /* in bytes. 0 for unlimited */
tmsize_t tif_max_single_mem_alloc; /* in bytes. 0 for unlimited */
tmsize_t tif_max_cumulated_mem_alloc; /* in bytes. 0 for unlimited */
tmsize_t tif_cur_cumulated_mem_alloc; /* in bytes */
};
struct TIFFOpenOptions
@ -243,6 +267,7 @@ struct TIFFOpenOptions
TIFFErrorHandlerExtR warnhandler; /* may be NULL */
void *warnhandler_user_data; /* may be NULL */
tmsize_t max_single_mem_alloc; /* in bytes. 0 for unlimited */
tmsize_t max_cumulated_mem_alloc; /* in bytes. 0 for unlimited */
};
#define isPseudoTag(t) (t > 0xffff) /* is tag value normal or pseudo */
@ -331,7 +356,7 @@ struct TIFFOpenOptions
#define ftell(stream, offset, whence) ftello(stream, offset, whence)
#endif
#endif
#if defined(__WIN32__) && !(defined(_MSC_VER) && _MSC_VER < 1400) && \
#if defined(_WIN32) && \
!(defined(__MSVCRT_VERSION__) && __MSVCRT_VERSION__ < 0x800)
typedef unsigned int TIFFIOSize_t;
#define _TIFF_lseek_f(fildes, offset, whence) \
@ -437,9 +462,6 @@ extern "C"
extern void *_TIFFCheckRealloc(TIFF *, void *, tmsize_t, tmsize_t,
const char *);
extern double _TIFFUInt64ToDouble(uint64_t);
extern float _TIFFUInt64ToFloat(uint64_t);
extern float _TIFFClampDoubleToFloat(double);
extern uint32_t _TIFFClampDoubleToUInt32(double);

View File

@ -574,6 +574,7 @@ ocv_cmake_hook(POST_CMAKE_BUILD_OPTIONS)
# --- Python Support ---
if(NOT IOS AND NOT XROS)
include(cmake/OpenCVDetectPython.cmake)
include(cmake/OpenCVDetectDLPack.cmake)
endif()
include(cmake/OpenCVCompilerOptions.cmake)

View File

@ -31,6 +31,9 @@ CalibPipeline::CalibPipeline(captureParameters params) :
PipelineExitStatus CalibPipeline::start(std::vector<cv::Ptr<FrameProcessor> > processors)
{
const int allowedEmptyFrames = 5;
int emptyFrames = 0;
auto open_camera = [this] () {
if(mCaptureParams.source == Camera)
{
@ -87,6 +90,22 @@ PipelineExitStatus CalibPipeline::start(std::vector<cv::Ptr<FrameProcessor> > pr
CV_CheckEQ(mImageSize, newSize, "Camera image size changed after reopening.");
}
mCapture.retrieve(frame);
if (frame.empty()) {
emptyFrames++;
if (emptyFrames >= allowedEmptyFrames) {
CV_LOG_ERROR(NULL, "VideoCapture error: grabbed sequence of empty frames. VideoCapture is not ready or broken.");
return Finished;
}
continue;
} else {
emptyFrames = 0;
if (mImageSize.width == 0 || mImageSize.height == 0) { // looks like VideoCapture does not support required properties
mImageSize = frame.size();
}
}
if(mCaptureParams.flipVertical)
cv::flip(frame, frame, -1);

View File

@ -109,7 +109,7 @@ macro(ocv_initialize_nvidia_device_generations)
set(_arch_ampere "8.0;8.6")
set(_arch_lovelace "8.9")
set(_arch_hopper "9.0")
set(_arch_blackwell "10.0;12.0")
set(_arch_blackwell "10.0;10.3;11.0;12.0;12.1")
if(NOT CMAKE_CROSSCOMPILING)
list(APPEND _generations "Auto")
endif()
@ -271,14 +271,15 @@ macro(ocv_set_cuda_arch_bin_and_ptx nvcc_executable)
endif()
if(NOT _nvcc_res EQUAL 0)
message(STATUS "CUDA: Automatic detection of CUDA generation failed. Going to build for all known architectures")
# TX1 (5.3) TX2 (6.2) Xavier (7.2) V100 (7.0) Orin (8.7) Thor (10.1)
# TX1 (5.3) TX2 (6.2) Xavier (7.2) V100 (7.0) Orin (8.7) Thor (11.0) Spark (12.1)
ocv_filter_available_architecture(${nvcc_executable} __cuda_arch_bin
5.3
6.2
7.2
7.0
8.7
10.1
11.0
12.1
)
else()
set(__cuda_arch_bin "${_nvcc_out}")

View File

@ -0,0 +1,5 @@
find_package(dlpack QUIET)
if (NOT dlpack_FOUND)
ocv_include_directories("${OpenCV_SOURCE_DIR}/3rdparty/dlpack/include")
ocv_install_3rdparty_licenses(dlpack "${OpenCV_SOURCE_DIR}/3rdparty/dlpack/LICENSE")
endif()

View File

@ -42,7 +42,7 @@ target_include_directories(ipphal PRIVATE
target_link_libraries(ipphal PUBLIC ${IPP_IW_LIBRARY} ${IPP_LIBRARIES})
set_target_properties(ipphal PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH})
set_target_properties(ipphal PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH} DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}")
if(NOT BUILD_SHARED_LIBS)
ocv_install_target(ipphal EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev)

View File

@ -243,6 +243,29 @@ int integral(int depth, int sdepth, int sqdepth,
//#undef cv_hal_integral
//#define cv_hal_integral cv::rvv_hal::imgproc::integral
/* ############ scharr ############ */
int scharr(const uint8_t *src_data, size_t src_step, uint8_t *dst_data, size_t dst_step, int width, int height, int src_depth, int dst_depth, int cn, int margin_left, int margin_top, int margin_right, int margin_bottom, int dx, int dy, double scale, double delta, int border_type);
#undef cv_hal_scharr
#define cv_hal_scharr cv::rvv_hal::imgproc::scharr
/* ############ sobel ############ */
int sobel(const uint8_t *src_data, size_t src_step, uint8_t *dst_data, size_t dst_step, int width, int height, int src_depth, int dst_depth, int cn, int margin_left, int margin_top, int margin_right, int margin_bottom, int dx, int dy, int ksize, double scale, double delta, int border_type);
#undef cv_hal_sobel
#define cv_hal_sobel cv::rvv_hal::imgproc::sobel
/* ############ canny ############ */
int canny(const uint8_t *src_data, size_t src_step,
uint8_t *dst_data, size_t dst_step,
int width, int height, int cn,
double low_thresh, double high_thresh,
int ksize, bool L2gradient);
#undef cv_hal_canny
#define cv_hal_canny cv::rvv_hal::imgproc::canny
#endif // CV_HAL_RVV_1P0_ENABLED
#if CV_HAL_RVV_071_ENABLED

View File

@ -0,0 +1,426 @@
// This file is part of OpenCV project.
// 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.
// Copyright (C) 2025, SpaceMIT Inc., all rights reserved.
#include "rvv_hal.hpp"
#include "common.hpp"
namespace cv
{
namespace rvv_hal
{
namespace imgproc
{
#if CV_HAL_RVV_1P0_ENABLED
typedef struct
{
int *buffer;
int *prev;
int *curr;
int *next;
size_t size;
} LineBuffer;
LineBuffer *createLineBuffer(size_t width, size_t align);
void rotateLineBuffer(LineBuffer *buf);
void freeLineBuffer(LineBuffer *buf);
LineBuffer *createLineBuffer(size_t width, size_t align)
{
LineBuffer *buf = (LineBuffer *)malloc(sizeof(LineBuffer));
if (!buf)
return NULL;
size_t aligned_width = ((width + align - 1) & ~(align - 1));
buf->buffer = (int *)aligned_alloc(align, 3 * aligned_width * sizeof(int));
if (!buf->buffer)
{
free(buf);
return NULL;
}
buf->prev = buf->buffer;
buf->curr = buf->prev + aligned_width;
buf->next = buf->curr + aligned_width;
buf->size = aligned_width;
return buf;
}
void rotateLineBuffer(LineBuffer *buf)
{
int *temp = buf->prev;
buf->prev = buf->curr;
buf->curr = buf->next;
buf->next = temp;
}
void freeLineBuffer(LineBuffer *buf)
{
if (buf)
{
free(buf->buffer);
free(buf);
}
}
typedef struct
{
uint8_t **data;
int capacity;
int size;
} Stack;
static Stack *canny_createStack(int capacity);
static void canny_push(Stack *stack, uint8_t *item);
static uint8_t *canny_pop(Stack *stack);
static void freeStack(Stack *stack);
static Stack *canny_createStack(int capacity)
{
Stack *stack = (Stack *)malloc(sizeof(Stack));
stack->data = (uint8_t **)malloc(capacity * sizeof(uint8_t *));
stack->capacity = capacity;
stack->size = 0;
return stack;
}
static void canny_push(Stack *stack, uint8_t *item)
{
if (stack->size < stack->capacity)
{
stack->data[stack->size++] = item;
}
}
static uint8_t *canny_pop(Stack *stack)
{
if (stack->size > 0)
{
return stack->data[--stack->size];
}
return NULL;
}
static void freeStack(Stack *stack)
{
free(stack->data);
free(stack);
}
int sobel(const uint8_t *src_data, size_t src_step, uint8_t *dst_data, size_t dst_step, int width, int height, int src_depth, int dst_depth, int cn, int margin_left, int margin_top, int margin_right, int margin_bottom, int dx, int dy, int ksize, double scale, double delta, int border_type);
int canny(const uint8_t *src_data, size_t src_step,
uint8_t *dst_data, size_t dst_step,
int width, int height, int cn,
double low_thresh, double high_thresh,
int ksize, bool L2gradient)
{
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if (cn != 1 || (ksize != 3 && ksize != 5))
{
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
if (L2gradient)
{
low_thresh = 32767.0 < low_thresh ? 32767.0 : low_thresh;
high_thresh = 32767.0 < high_thresh ? 32767.0 : high_thresh;
if (low_thresh > 0)
low_thresh *= low_thresh;
if (high_thresh > 0)
high_thresh *= high_thresh;
}
int low = (int)low_thresh;
low_thresh = low - (low > low_thresh);
int high = (int)high_thresh;
high_thresh = high - (high > high_thresh);
int16_t *dx_data = (int16_t *)malloc(height * width * sizeof(int16_t));
int16_t *dy_data = (int16_t *)malloc(height * width * sizeof(int16_t));
if (!dx_data || !dy_data)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
const size_t grad_step = width * sizeof(int16_t);
int ret = sobel(src_data, src_step, (uint8_t *)dx_data, grad_step,
width, height, CV_8U, CV_16S, 1,
0, 0, 0, 0, 1, 0, ksize, 1.0, 0.0, BORDER_REPLICATE);
if (ret != CV_HAL_ERROR_OK)
{
free(dx_data);
free(dy_data);
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
ret = sobel(src_data, src_step, (uint8_t *)dy_data, grad_step,
width, height, CV_8U, CV_16S, 1,
0, 0, 0, 0, 0, 1, ksize, 1.0, 0.0, BORDER_REPLICATE);
if (ret != CV_HAL_ERROR_OK)
{
free(dx_data);
free(dy_data);
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
const int mapstep = width + 2;
const size_t mapsize = (height + 2) * mapstep;
uint8_t *edge_map = (uint8_t *)calloc(mapsize, sizeof(uint8_t));
if (!edge_map)
{
free(dx_data);
free(dy_data);
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
Stack *stack = canny_createStack(width * height);
Stack *borderPeaksLocal = canny_createStack(width * height);
if (!stack || !borderPeaksLocal)
{
free(dx_data);
free(dy_data);
free(edge_map);
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
memset(edge_map, 1, mapstep);
memset(edge_map + (height + 1) * mapstep, 1, mapstep);
for (int i = 1; i <= height; i++)
{
edge_map[i * mapstep] = 1;
edge_map[i * mapstep + width + 1] = 1;
}
uint8_t *map = edge_map + mapstep + 1;
const int simd_align = 16;
LineBuffer *lineBuf = createLineBuffer(width, simd_align);
if (!lineBuf)
{
free(dx_data);
free(dy_data);
free(edge_map);
freeStack(stack);
freeStack(borderPeaksLocal);
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
const int TG22 = 13573;
for (int i = 0; i <= height; i++)
{
if (i < height)
{
int16_t *dx = (int16_t *)(dx_data + i * width);
int16_t *dy = (int16_t *)(dy_data + i * width);
if (L2gradient)
{
size_t vl = 0;
for (int j = 0; j < width; j += vl)
{
vl = __riscv_vsetvl_e32m8(width - j);
vint32m8_t vdx = __riscv_vwcvt_x_x_v_i32m8(__riscv_vle16_v_i16m4(dx + j, vl), vl);
vint32m8_t vdy = __riscv_vwcvt_x_x_v_i32m8(__riscv_vle16_v_i16m4(dy + j, vl), vl);
vint32m8_t vres = __riscv_vmul_vv_i32m8(vdx, vdx, vl);
vres = __riscv_vmacc_vv_i32m8(vres, vdy, vdy, vl);
__riscv_vse32_v_i32m8(lineBuf->next + j, vres, vl);
}
}
else
{
size_t vl = 0;
for (int j = 0; j < width; j += vl)
{
vl = __riscv_vsetvl_e32m8(width - j);
vint32m8_t vdx = __riscv_vwcvt_x_x_v_i32m8(__riscv_vle16_v_i16m4(dx + j, vl), vl);
vint32m8_t vdy = __riscv_vwcvt_x_x_v_i32m8(__riscv_vle16_v_i16m4(dy + j, vl), vl);
vbool4_t mask = __riscv_vmslt_vx_i32m8_b4(vdx, 0, vl);
vdx = __riscv_vmul_vx_i32m8_m(mask, vdx, -1, vl);
mask = __riscv_vmslt_vx_i32m8_b4(vdy, 0, vl);
vdy = __riscv_vmul_vx_i32m8_m(mask, vdy, -1, vl);
vint32m8_t vres = __riscv_vadd_vv_i32m8(vdx, vdy, vl);
__riscv_vse32_v_i32m8(lineBuf->next + j, vres, vl);
}
}
}
else
{
memset(lineBuf->next, 0, width * sizeof(int));
}
uint8_t *pmap = map + i * mapstep;
int16_t *dx = (int16_t *)(dx_data + i * width);
int16_t *dy = (int16_t *)(dy_data + i * width);
size_t vl = 0;
for (int j = 0; j < width; j += vl)
{
vl = __riscv_vsetvl_e32m8(width - j);
vint32m8_t vm = __riscv_vle32_v_i32m8(lineBuf->curr + j, vl);
vint32m8_t vdx = __riscv_vwcvt_x_x_v_i32m8(__riscv_vle16_v_i16m4(dx + j, vl), vl);
vint32m8_t vdy = __riscv_vwcvt_x_x_v_i32m8(__riscv_vle16_v_i16m4(dy + j, vl), vl);
vbool4_t mask_dx = __riscv_vmslt_vx_i32m8_b4(vdx, 0, vl);
vbool4_t mask_dy = __riscv_vmslt_vx_i32m8_b4(vdy, 0, vl);
vint32m8_t vdx_abs = __riscv_vmul_vx_i32m8_m(mask_dx, vdx, -1, vl);
vint32m8_t vdy_abs = __riscv_vmul_vx_i32m8_m(mask_dy, vdy, -1, vl);
vdy_abs = __riscv_vsll_vx_i32m8(vdy_abs, 15, vl);
// Calculate threshold values
vint32m8_t vtg22x = __riscv_vmul_vx_i32m8(vdx_abs, TG22, vl);
vint32m8_t vtg67x = __riscv_vadd_vv_i32m8(vtg22x, __riscv_vsll_vx_i32m8(vdx_abs, 16, vl), vl);
// Create masks for different angle ranges
vbool4_t mask1 = __riscv_vmslt_vv_i32m8_b4(vdy_abs, vtg22x, vl);
vbool4_t mask2 = __riscv_vmsgt_vv_i32m8_b4(vdy_abs, vtg67x, vl);
vbool4_t mask3 = __riscv_vmnot_m_b4(__riscv_vmor_mm_b4(mask1, mask2, vl), vl);
// Load neighbor pixels for all conditions
vint32m8_t prev_curr = __riscv_vle32_v_i32m8(lineBuf->curr + (j > 0 ? j - 1 : j), vl);
vint32m8_t next_curr = __riscv_vle32_v_i32m8(lineBuf->curr + j + 1, vl);
vint32m8_t prev_line = __riscv_vle32_v_i32m8(lineBuf->prev + j, vl);
vint32m8_t next_line = __riscv_vle32_v_i32m8(lineBuf->next + j, vl);
// Condition 1: Horizontal/Vertical edges (compare left/right)
vbool4_t cond1_max = __riscv_vmand_mm_b4(
__riscv_vmsgt_vv_i32m8_b4(vm, prev_curr, vl),
__riscv_vmsge_vv_i32m8_b4(vm, next_curr, vl),
vl);
// Condition 2: Diagonal edges (compare top/bottom)
vbool4_t cond2_max = __riscv_vmand_mm_b4(
__riscv_vmsgt_vv_i32m8_b4(vm, prev_line, vl),
__riscv_vmsge_vv_i32m8_b4(vm, next_line, vl),
vl);
// Condition 3: Other diagonals (calculate s)
vint32m8_t vxor = __riscv_vxor_vv_i32m8(vdx, vdy, vl);
vbool4_t s_mask = __riscv_vmslt_vx_i32m8_b4(vxor, 0, vl);
vint32m8_t prev_s1 = __riscv_vle32_v_i32m8(lineBuf->prev + (j > 0 ? j - 1 : j), vl);
vint32m8_t prev_s2 = __riscv_vle32_v_i32m8(lineBuf->prev + j + 1, vl);
vint32m8_t next_s1 = __riscv_vle32_v_i32m8(lineBuf->next + j + 1, vl);
vint32m8_t next_s2 = __riscv_vle32_v_i32m8(lineBuf->next + (j > 0 ? j - 1 : j), vl);
vint32m8_t prev_sel = __riscv_vmerge_vvm_i32m8(prev_s1, prev_s2, s_mask, vl);
vint32m8_t next_sel = __riscv_vmerge_vvm_i32m8(next_s1, next_s2, s_mask, vl);
vbool4_t cond3_max = __riscv_vmand_mm_b4(
__riscv_vmsgt_vv_i32m8_b4(vm, prev_sel, vl),
__riscv_vmsgt_vv_i32m8_b4(vm, next_sel, vl),
vl);
// Combine results from all conditions
vbool4_t vmax = __riscv_vmor_mm_b4(
__riscv_vmand_mm_b4(mask1, cond1_max, vl),
__riscv_vmand_mm_b4(mask2, cond2_max, vl),
vl);
vmax = __riscv_vmor_mm_b4(
vmax,
__riscv_vmand_mm_b4(mask3, cond3_max, vl),
vl);
// Threshold checks
vbool4_t vlow = __riscv_vmsgt_vx_i32m8_b4(vm, low_thresh, vl);
vbool4_t vhigh = __riscv_vmsgt_vx_i32m8_b4(vm, high_thresh, vl);
vbool4_t valid_edges = __riscv_vmand_mm_b4(vmax, vlow, vl);
vbool4_t strong_edges = __riscv_vmand_mm_b4(valid_edges, vhigh, vl);
// Generate result map
vuint8m2_t vres = __riscv_vmv_v_x_u8m2(1, vl);
vres = __riscv_vmerge_vxm_u8m2(vres, 0, valid_edges, vl);
vres = __riscv_vmerge_vxm_u8m2(vres, 2, strong_edges, vl);
__riscv_vse8_v_u8m2(pmap + j, vres, vl);
// canny_Push strong edges to stack
int32_t vidx = __riscv_vfirst_m_b4(strong_edges, vl);
while (vidx >= 0)
{
canny_push(stack, pmap + j + vidx);
strong_edges = __riscv_vmand_mm_b4(strong_edges,
__riscv_vmclr_m_b4(vl), vl);
vidx = __riscv_vfirst_m_b4(strong_edges, vl);
}
}
rotateLineBuffer(lineBuf);
}
uint8_t *pmapLower = edge_map;
uint32_t pmapDiff = (uint32_t)((edge_map + mapsize) - pmapLower);
while (stack->size > 0)
{
uint8_t *m = canny_pop(stack);
if ((uint64_t)m < (uint64_t)pmapLower || (uint64_t)m >= (uint64_t)(pmapLower + pmapDiff))
continue;
const int offsets[8] = {
-mapstep - 1, -mapstep, -mapstep + 1,
-1, +1,
+mapstep - 1, +mapstep, +mapstep + 1};
for (int k = 0; k < 8; k++)
{
uint8_t *neighbor = m + offsets[k];
if ((uint64_t)neighbor < (uint64_t)edge_map ||
(uint64_t)neighbor >= (uint64_t)(edge_map + mapsize))
continue;
if (*neighbor == 0)
{
*neighbor = 2;
canny_push(stack, neighbor);
}
}
}
if (borderPeaksLocal->size > 0)
{
for (int i = 0; i < borderPeaksLocal->size; i++)
{
canny_push(stack, borderPeaksLocal->data[i]);
}
}
for (int i = 0; i < height; i++)
{
uint8_t *pdst = dst_data + i * dst_step;
uint8_t *pmap = map + i * mapstep + 1;
size_t vl = 0;
for (int j = 0; j < width; j += vl)
{
vl = __riscv_vsetvl_e8m8(width - j);
vuint8m8_t vres = __riscv_vle8_v_u8m8(pmap + j, vl);
vres = __riscv_vsrl_vx_u8m8(vres, 1, vl);
vres = __riscv_vsub_vv_u8m8(__riscv_vmv_v_x_u8m8(0, vl), vres, vl);
__riscv_vse8_v_u8m8(pdst + j, vres, vl);
}
}
freeLineBuffer(lineBuf);
freeStack(borderPeaksLocal);
freeStack(stack);
free(dx_data);
free(dy_data);
free(edge_map);
return CV_HAL_ERROR_OK;
}
}
}
#endif // CV_HAL_RVV_1P0_ENABLED
} // namespace cv::rvv_hal::imgproc

View File

@ -0,0 +1,883 @@
// This file is part of OpenCV project.
// 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 .
// Copyright (C) 2025, SpaceMIT Inc., all rights reserved.
#include "rvv_hal.hpp"
#include "common.hpp"
namespace cv
{
namespace rvv_hal
{
namespace imgproc
{
#if CV_HAL_RVV_1P0_ENABLED
#define borderValue 0
static inline int scharr_dx0(int start, int end, const uint8_t *src_data, size_t src_step,
uint8_t *dst_data, size_t dst_step,
int width, int height,
int src_depth __attribute__((unused)), int dst_depth, int cn __attribute__((unused)),
int margin_left __attribute__((unused)), int margin_top __attribute__((unused)),
int margin_right __attribute__((unused)), int margin_bottom __attribute__((unused)),
double scale __attribute__((unused)), double delta __attribute__((unused)),
int border_type)
{
int dx0, dx1, dx2, dy0, dy1, dy2;
dy0 = -1;
dx0 = 3;
dy1 = 0;
dx1 = 10;
dy2 = 1;
dx2 = 3;
int16_t trow[width];
static thread_local std::vector<uint8_t> zero_row;
if (zero_row.size() < static_cast<size_t>(width))
{
zero_row.clear();
zero_row.resize(width, 0);
}
if (dst_depth == CV_8U)
{
for (int y = start; y < end; ++y)
{
const uint8_t *srow1 = src_data + y * src_step;
const uint8_t *srow0;
const uint8_t *srow2;
if (y != 0)
{
srow0 = src_data + (y - 1) * src_step;
}
else
{
if (border_type == BORDER_REPLICATE)
{
srow0 = srow1;
}
else
{
srow0 = zero_row.data();
}
}
if (y != height - 1)
{
srow2 = src_data + (y + 1) * src_step;
}
else
{
if (border_type == BORDER_REPLICATE)
{
srow2 = srow1;
}
else
{
srow2 = zero_row.data();
}
}
trow[0] = (dy0 * srow0[0] + dy1 * srow1[0] + dy2 * srow2[0]);
// Last pixel
trow[width - 1] = dy0 * srow0[width - 1] + dy1 * srow1[width - 1] + dy2 * srow2[width - 1];
size_t vl = 0;
// Vector processing
for (int x = 1; x < width - 1; x += vl)
{
vl = __riscv_vsetvl_e8m4(width - x - 1);
vint16m8_t vsrow0 = __riscv_vreinterpret_v_u16m8_i16m8(__riscv_vwcvtu_x_x_v_u16m8(__riscv_vle8_v_u8m4(srow0 + x, vl), vl));
vint16m8_t vsrow2 = __riscv_vreinterpret_v_u16m8_i16m8(__riscv_vwcvtu_x_x_v_u16m8(__riscv_vle8_v_u8m4(srow2 + x, vl), vl));
vint16m8_t vrowx = __riscv_vsub_vv_i16m8(vsrow2, vsrow0, vl);
__riscv_vse16_v_i16m8(trow + x, vrowx, vl);
}
int x = 0;
uint8_t *drow = (uint8_t *)(dst_data + y * dst_step);
int16_t temp = trow[0] * dx1 + trow[1] * dx2;
if (border_type == BORDER_REPLICATE)
{
temp += trow[0] * dx0;
}
drow[x] = (uint8_t)(temp > 0 ? (temp < 255 ? temp : 255) : 0);
x = 1;
for (; x < width - 1; x += vl)
{
vl = __riscv_vsetvl_e16m8(width - x - 1);
vint16m8_t vleft = __riscv_vle16_v_i16m8(trow + x - 1, vl);
vint16m8_t vcenter = __riscv_vle16_v_i16m8(trow + x, vl);
vint16m8_t vright = __riscv_vle16_v_i16m8(trow + x + 1, vl);
vint16m8_t vres = __riscv_vmul_vx_i16m8(vcenter, dx1, vl);
vcenter = __riscv_vadd_vv_i16m8(vleft, vright, vl);
vres = __riscv_vmacc_vx_i16m8(vres, dx0, vcenter, vl);
vres = __riscv_vmax_vx_i16m8(vres, 0, vl);
vres = __riscv_vmin_vx_i16m8(vres, 255, vl);
__riscv_vse8_v_u8m4(drow + x, __riscv_vncvt_x_x_w_u8m4(__riscv_vreinterpret_v_i16m8_u16m8(vres), vl), vl);
}
x = width - 1;
temp = trow[width - 2] * dx0 + trow[width - 1] * dx1;
if (border_type == BORDER_REPLICATE)
{
temp += trow[width - 1] * dx2;
}
drow[x] = (uint8_t)(temp > 0 ? (temp < 255 ? temp : 255) : 0);
}
}
else if (dst_depth == CV_16S)
{
for (int y = start; y < end; ++y)
{
const uint8_t *srow1 = src_data + y * src_step;
const uint8_t *srow0;
const uint8_t *srow2;
if (y != 0)
{
srow0 = src_data + (y - 1) * src_step;
}
else
{
if (border_type == BORDER_REPLICATE)
{
srow0 = srow1;
}
else
{
srow0 = zero_row.data();
}
}
if (y != height - 1)
{
srow2 = src_data + (y + 1) * src_step;
}
else
{
if (border_type == BORDER_REPLICATE)
{
srow2 = srow1;
}
else
{
srow2 = zero_row.data();
}
}
if (y == 0)
{
if (border_type == BORDER_REPLICATE)
{
srow0 = srow1;
}
else
{
srow0 = zero_row.data();
}
}
else if (y == height - 1)
{
if (border_type == BORDER_REPLICATE)
{
srow2 = srow1;
}
else
{
srow2 = zero_row.data();
}
}
size_t vl = 0;
// Vector processing
for (int x = 0; x < width; x += vl)
{
vl = __riscv_vsetvl_e8m4(width - x);
vint16m8_t vsrow0 = __riscv_vreinterpret_v_u16m8_i16m8(__riscv_vwcvtu_x_x_v_u16m8(__riscv_vle8_v_u8m4(srow0 + x, vl), vl));
vint16m8_t vsrow2 = __riscv_vreinterpret_v_u16m8_i16m8(__riscv_vwcvtu_x_x_v_u16m8(__riscv_vle8_v_u8m4(srow2 + x, vl), vl));
vint16m8_t vrowx = __riscv_vsub_vv_i16m8(vsrow2, vsrow0, vl);
__riscv_vse16_v_i16m8(trow + x, vrowx, vl);
}
int x = 0;
int16_t *drow = (int16_t *)(dst_data + y * dst_step);
drow[0] = trow[0] * dx1 + trow[1] * dx2;
if (border_type == BORDER_REPLICATE)
{
drow[x] += trow[0] * dx0;
}
x = 1;
for (; x < width - 1; x += vl)
{
vl = __riscv_vsetvl_e16m8(width - x - 1);
vint16m8_t vleft = __riscv_vle16_v_i16m8(trow + x - 1, vl);
vint16m8_t vcenter = __riscv_vle16_v_i16m8(trow + x, vl);
vint16m8_t vright = __riscv_vle16_v_i16m8(trow + x + 1, vl);
vint16m8_t vres = __riscv_vmul_vx_i16m8(vcenter, dx1, vl);
vcenter = __riscv_vadd_vv_i16m8(vleft, vright, vl);
vres = __riscv_vmacc_vx_i16m8(vres, dx0, vcenter, vl);
__riscv_vse16_v_i16m8(drow + x, vres, vl);
}
x = width - 1;
drow[x] = trow[width - 2] * dx0 + trow[width - 1] * dx1;
if (border_type == BORDER_REPLICATE)
{
drow[x] += trow[width - 1] * dx2;
}
}
}
else if (dst_depth == CV_32F)
{
for (int y = start; y < end; ++y)
{
const uint8_t *srow1 = src_data + y * src_step;
const uint8_t *srow0;
const uint8_t *srow2;
if (y != 0)
{
srow0 = src_data + (y - 1) * src_step;
}
else
{
if (border_type == BORDER_REPLICATE)
{
srow0 = srow1;
}
else
{
srow0 = zero_row.data();
}
}
if (y != height - 1)
{
srow2 = src_data + (y + 1) * src_step;
}
else
{
if (border_type == BORDER_REPLICATE)
{
srow2 = srow1;
}
else
{
srow2 = zero_row.data();
}
}
if (y == 0)
{
if (border_type == BORDER_REPLICATE)
{
srow0 = srow1;
}
else
{
srow0 = zero_row.data();
}
}
else if (y == height - 1)
{
if (border_type == BORDER_REPLICATE)
{
srow2 = srow1;
}
else
{
srow2 = zero_row.data();
}
}
size_t vl = 0;
// Vector processing
for (int x = 0; x < width; x += vl)
{
vl = __riscv_vsetvl_e8m4(width - x);
vint16m8_t vsrow0 = __riscv_vreinterpret_v_u16m8_i16m8(__riscv_vwcvtu_x_x_v_u16m8(__riscv_vle8_v_u8m4(srow0 + x, vl), vl));
vint16m8_t vsrow2 = __riscv_vreinterpret_v_u16m8_i16m8(__riscv_vwcvtu_x_x_v_u16m8(__riscv_vle8_v_u8m4(srow2 + x, vl), vl));
vint16m8_t vrowx = __riscv_vsub_vv_i16m8(vsrow2, vsrow0, vl);
__riscv_vse16_v_i16m8(trow + x, vrowx, vl);
}
int x = 0;
float *drow = (float *)(dst_data + y * dst_step);
drow[x] = trow[0] * dx1 + trow[1] * dx2;
if (border_type == BORDER_REPLICATE)
{
drow[x] += trow[0] * dx0;
}
x = 1;
for (; x < width - 1; x += vl)
{
vl = __riscv_vsetvl_e16m4(width - x - 1);
vint16m4_t vleft = __riscv_vle16_v_i16m4(trow + x - 1, vl);
vint16m4_t vcenter = __riscv_vle16_v_i16m4(trow + x, vl);
vint16m4_t vright = __riscv_vle16_v_i16m4(trow + x + 1, vl);
vint16m4_t vres = __riscv_vmul_vx_i16m4(vcenter, dx1, vl);
vcenter = __riscv_vadd_vv_i16m4(vleft, vright, vl);
vres = __riscv_vmacc_vx_i16m4(vres, dx0, vcenter, vl);
__riscv_vse32_v_f32m8(drow + x, __riscv_vfwcvt_f_x_v_f32m8(vres, vl), vl);
}
x = width - 1;
drow[x] = trow[width - 2] * dx0 + trow[width - 1] * dx1;
if (border_type == BORDER_REPLICATE)
{
drow[x] += trow[width - 1] * dx2;
}
}
}
return CV_HAL_ERROR_OK;
}
static inline int scharr_dx1(int start, int end, const uint8_t *src_data, size_t src_step,
uint8_t *dst_data, size_t dst_step,
int width, int height,
int src_depth __attribute__((unused)), int dst_depth, int cn __attribute__((unused)),
int margin_left __attribute__((unused)), int margin_top __attribute__((unused)),
int margin_right __attribute__((unused)), int margin_bottom __attribute__((unused)),
double scale __attribute__((unused)), double delta __attribute__((unused)),
int border_type)
{
int dx0, dx1, dx2, dy0, dy1, dy2;
dx0 = -1;
dy0 = 3;
dx1 = 0;
dy1 = 10;
dx2 = 1;
dy2 = 3;
int16_t trow[width];
static thread_local std::vector<uint8_t> zero_row;
if (zero_row.size() < static_cast<size_t>(width))
{
zero_row.clear();
zero_row.resize(width, 0);
}
if (dst_depth == CV_8U)
{
for (int y = start; y < end; ++y)
{
const uint8_t *srow1 = src_data + y * src_step;
const uint8_t *srow0;
const uint8_t *srow2;
if (y != 0)
{
srow0 = src_data + (y - 1) * src_step;
}
else
{
if (border_type == BORDER_REPLICATE)
{
srow0 = srow1;
}
else
{
srow0 = zero_row.data();
}
}
if (y != height - 1)
{
srow2 = src_data + (y + 1) * src_step;
}
else
{
if (border_type == BORDER_REPLICATE)
{
srow2 = srow1;
}
else
{
srow2 = zero_row.data();
}
}
if (y == 0)
{
if (border_type == BORDER_REPLICATE)
{
srow0 = srow1;
}
else
{
srow0 = zero_row.data();
}
}
else if (y == height - 1)
{
if (border_type == BORDER_REPLICATE)
{
srow2 = srow1;
}
else
{
srow2 = zero_row.data();
}
}
trow[0] = (dy0 * srow0[0] + dy1 * srow1[0] + dy2 * srow2[0]);
// Last pixel
trow[width - 1] = dy0 * srow0[width - 1] + dy1 * srow1[width - 1] + dy2 * srow2[width - 1];
size_t vl = 0;
// Vector processing
for (int x = 1; x < width - 1; x += vl)
{
vl = __riscv_vsetvl_e8m4(width - x - 1);
vuint8m4_t vsrow0 = __riscv_vle8_v_u8m4(srow0 + x, vl);
vuint8m4_t vsrow1 = __riscv_vle8_v_u8m4(srow1 + x, vl);
vuint8m4_t vsrow2 = __riscv_vle8_v_u8m4(srow2 + x, vl);
vuint16m8_t vrowx = __riscv_vwmulu_vx_u16m8(vsrow1, dy1, vl);
vuint16m8_t vtemp = __riscv_vwaddu_vv_u16m8(vsrow0, vsrow2, vl);
vrowx = __riscv_vmacc_vx_u16m8(vrowx, dy0, vtemp, vl);
__riscv_vse16_v_i16m8(trow + x, __riscv_vreinterpret_v_u16m8_i16m8(vrowx), vl);
}
int x = 0;
uint8_t *drow = (uint8_t *)(dst_data + y * dst_step);
int16_t temp = trow[0] * dx1 + trow[1] * dx2;
if (border_type == BORDER_REPLICATE)
{
temp += trow[0] * dx0;
}
drow[x] = (uint8_t)(temp > 0 ? (temp < 255 ? temp : 255) : 0);
x = 1;
for (; x < width - 1; x += vl)
{
vl = __riscv_vsetvl_e16m8(width - x - 1);
vint16m8_t vleft = __riscv_vle16_v_i16m8(trow + x - 1, vl);
vint16m8_t vright = __riscv_vle16_v_i16m8(trow + x + 1, vl);
vint16m8_t vres = __riscv_vsub_vv_i16m8(vright, vleft, vl);
vres = __riscv_vmax_vx_i16m8(vres, 0, vl);
vres = __riscv_vmin_vx_i16m8(vres, 255, vl);
__riscv_vse8_v_u8m4(drow + x, __riscv_vncvt_x_x_w_u8m4(__riscv_vreinterpret_v_i16m8_u16m8(vres), vl), vl);
}
x = width - 1;
temp = trow[width - 2] * dx0 + trow[width - 1] * dx1;
if (border_type == BORDER_REPLICATE)
{
temp += trow[width - 1] * dx2;
}
drow[x] = (uint8_t)(temp > 0 ? (temp < 255 ? temp : 255) : 0);
}
}
else if (dst_depth == CV_16S)
{
for (int y = start; y < end; ++y)
{
const uint8_t *srow1 = src_data + y * src_step;
const uint8_t *srow0;
const uint8_t *srow2;
if (y != 0)
{
srow0 = src_data + (y - 1) * src_step;
}
else
{
if (border_type == BORDER_REPLICATE)
{
srow0 = srow1;
}
else
{
srow0 = zero_row.data();
}
}
if (y != height - 1)
{
srow2 = src_data + (y + 1) * src_step;
}
else
{
if (border_type == BORDER_REPLICATE)
{
srow2 = srow1;
}
else
{
srow2 = zero_row.data();
}
}
if (y == 0)
{
if (border_type == BORDER_REPLICATE)
{
srow0 = srow1;
}
else
{
srow0 = zero_row.data();
}
}
else if (y == height - 1)
{
if (border_type == BORDER_REPLICATE)
{
srow2 = srow1;
}
else
{
srow2 = zero_row.data();
}
}
size_t vl = 0;
// Vector processing
for (int x = 0; x < width; x += vl)
{
vl = __riscv_vsetvl_e8m4(width - x);
vuint8m4_t vsrow0 = __riscv_vle8_v_u8m4(srow0 + x, vl);
vuint8m4_t vsrow1 = __riscv_vle8_v_u8m4(srow1 + x, vl);
vuint8m4_t vsrow2 = __riscv_vle8_v_u8m4(srow2 + x, vl);
vuint16m8_t vrowx = __riscv_vwmulu_vx_u16m8(vsrow1, dy1, vl);
vuint16m8_t vtemp = __riscv_vwaddu_vv_u16m8(vsrow0, vsrow2, vl);
vrowx = __riscv_vmacc_vx_u16m8(vrowx, dy0, vtemp, vl);
__riscv_vse16_v_i16m8(trow + x, __riscv_vreinterpret_v_u16m8_i16m8(vrowx), vl);
}
int x = 0;
int16_t *drow = (int16_t *)(dst_data + y * dst_step);
drow[x] = trow[0] * dx1 + trow[1] * dx2;
if (border_type == BORDER_REPLICATE)
{
drow[x] += trow[0] * dx0;
}
x = 1;
for (; x < width - 1; x += vl)
{
vl = __riscv_vsetvl_e16m8(width - x - 1);
vint16m8_t vleft = __riscv_vle16_v_i16m8(trow + x - 1, vl);
vint16m8_t vright = __riscv_vle16_v_i16m8(trow + x + 1, vl);
vint16m8_t vres = __riscv_vsub_vv_i16m8(vright, vleft, vl);
__riscv_vse16_v_i16m8(drow + x, vres, vl);
}
x = width - 1;
drow[x] = trow[width - 2] * dx0 + trow[width - 1] * dx1;
if (border_type == BORDER_REPLICATE)
{
drow[x] += trow[width - 1] * dx2;
}
}
}
else if (dst_depth == CV_32F)
{
for (int y = start; y < end; ++y)
{
const uint8_t *srow1 = src_data + y * src_step;
const uint8_t *srow0;
const uint8_t *srow2;
if (y != 0)
{
srow0 = src_data + (y - 1) * src_step;
}
else
{
if (border_type == BORDER_REPLICATE)
{
srow0 = srow1;
}
else
{
srow0 = zero_row.data();
}
}
if (y != height - 1)
{
srow2 = src_data + (y + 1) * src_step;
}
else
{
if (border_type == BORDER_REPLICATE)
{
srow2 = srow1;
}
else
{
srow2 = zero_row.data();
}
}
if (y == 0)
{
if (border_type == BORDER_REPLICATE)
{
srow0 = srow1;
}
else
{
srow0 = zero_row.data();
}
}
else if (y == height - 1)
{
if (border_type == BORDER_REPLICATE)
{
srow2 = srow1;
}
else
{
srow2 = zero_row.data();
}
}
size_t vl = 0;
// Vector processing
for (int x = 0; x < width; x += vl)
{
vl = __riscv_vsetvl_e8m4(width - x);
vuint8m4_t vsrow0 = __riscv_vle8_v_u8m4(srow0 + x, vl);
vuint8m4_t vsrow1 = __riscv_vle8_v_u8m4(srow1 + x, vl);
vuint8m4_t vsrow2 = __riscv_vle8_v_u8m4(srow2 + x, vl);
vuint16m8_t vrowx = __riscv_vwmulu_vx_u16m8(vsrow1, dy1, vl);
vuint16m8_t vtemp = __riscv_vwaddu_vv_u16m8(vsrow0, vsrow2, vl);
vrowx = __riscv_vmacc_vx_u16m8(vrowx, dy0, vtemp, vl);
__riscv_vse16_v_i16m8(trow + x, __riscv_vreinterpret_v_u16m8_i16m8(vrowx), vl);
}
int x = 0;
float *drow = (float *)(dst_data + y * dst_step);
drow[x] = trow[0] * dx1 + trow[1] * dx2;
if (border_type == BORDER_REPLICATE)
{
drow[x] += trow[0] * dx0;
}
x = 1;
for (; x < width - 1; x += vl)
{
vl = __riscv_vsetvl_e16m4(width - x - 1);
vint16m4_t vleft = __riscv_vle16_v_i16m4(trow + x - 1, vl);
vint16m4_t vright = __riscv_vle16_v_i16m4(trow + x + 1, vl);
vint16m4_t vres = __riscv_vsub_vv_i16m4(vright, vleft, vl);
__riscv_vse32_v_f32m8(drow + x, __riscv_vfwcvt_f_x_v_f32m8(vres, vl), vl);
}
x = width - 1;
drow[x] = trow[width - 2] * dx0 + trow[width - 1] * dx1;
if (border_type == BORDER_REPLICATE)
{
drow[x] += trow[width - 1] * dx2;
}
}
}
return CV_HAL_ERROR_OK;
}
class ScharrInvoker : public ParallelLoopBody
{
public:
explicit ScharrInvoker(std::function<int(int, int)> _func)
: func(std::move(_func)) {}
void operator()(const Range &range) const override
{
func(range.start, range.end);
}
private:
std::function<int(int, int)> func;
};
template <typename... Args>
inline int invoke(int height,
int (*f)(int, int, Args...),
Args... args)
{
using namespace std::placeholders;
auto bound = std::bind(f, _1, _2, std::forward<Args>(args)...);
cv::parallel_for_(Range(1, height), ScharrInvoker(bound), cv::getNumThreads());
return f(0, 1, std::forward<Args>(args)...);
}
int scharr(const uint8_t *src_data, size_t src_step,
uint8_t *dst_data, size_t dst_step,
int width, int height,
int src_depth, int dst_depth, int cn,
int margin_left, int margin_top,
int margin_right, int margin_bottom,
int dx, int dy __attribute__((unused)),
double scale, double delta,
int border_type)
{
if (src_depth != CV_8U ||
(dst_depth != CV_8U && dst_depth != CV_16S && dst_depth != CV_32F) ||
cn != 1 || width < 3)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if (scale != 1 || delta != 0)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if (border_type != BORDER_REPLICATE && border_type != BORDER_CONSTANT)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if (margin_left != 0 || margin_top != 0 || margin_right != 0 || margin_bottom != 0)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
// This is copied from opencv/modules/imgproc/src/deriv.cpp
// if (!(dx >= 0 && dy >= 0 && dx + dy == 1))
// {
// return CV_HAL_ERROR_NOT_IMPLEMENTED;
// }
int size = 1;
if (dst_depth == CV_16S)
{
size = 2;
}
else if (dst_depth == CV_32F)
{
size = 4;
}
std::vector<uint8_t> temp_buffer;
uint8_t *actual_dst_data = dst_data;
if (src_data == dst_data)
{
temp_buffer.resize(height * dst_step);
actual_dst_data = temp_buffer.data();
}
int res = invoke(height,
dx == 1 ? &scharr_dx1 : &scharr_dx0,
src_data, src_step,
actual_dst_data, dst_step,
width, height,
src_depth, dst_depth, cn,
margin_left, margin_top,
margin_right, margin_bottom,
scale, delta,
border_type);
if (src_data == dst_data && res == CV_HAL_ERROR_OK)
{
for (int y = 0; y < height; ++y)
{
memcpy(dst_data + y * dst_step,
actual_dst_data + y * dst_step,
width * size);
}
}
return res;
}
#endif // CV_HAL_RVV_1P0_ENABLED
}
}
} // cv::rvv_hal::imgproc

File diff suppressed because it is too large Load Diff

View File

@ -774,7 +774,7 @@ struct CV_EXPORTS_W_SIMPLE CirclesGridFinderParameters
{
SYMMETRIC_GRID, ASYMMETRIC_GRID
};
GridType gridType;
CV_PROP_RW GridType gridType;
CV_PROP_RW float squareSize; //!< Distance between two adjacent points. Used by CALIB_CB_CLUSTERING.
CV_PROP_RW float maxRectifiedDistance; //!< Max deviation from prediction. Used by CALIB_CB_CLUSTERING.

View File

@ -648,6 +648,31 @@
"jni_var": "Vec3d %(n)s(%(n)s_val0, %(n)s_val1, %(n)s_val2)",
"suffix": "DDD"
},
"Vec4i": {
"j_type": "int[]",
"jn_args": [
[
"int",
".val[0]"
],
[
"int",
".val[1]"
],
[
"int",
".val[2]"
],
[
"int",
".val[3]"
]
],
"jn_type": "int[]",
"jni_type": "jintArray",
"jni_var": "Vec4i %(n)s(%(n)s_val0, %(n)s_val1, %(n)s_val2, %(n)s_val3)",
"suffix": "IIII"
},
"c_string": {
"j_type": "String",
"jn_type": "String",
@ -852,6 +877,15 @@
"v_type": "Mat",
"j_import": "org.opencv.core.MatOfByte"
},
"vector_vector_Mat": {
"j_type": "List<List<Mat>>",
"jn_type": "long",
"jni_type": "jlong",
"jni_var": "std::vector< std::vector<Mat> > %(n)s",
"suffix": "J",
"v_type": "vector_Mat",
"j_import": "org.opencv.core.Mat"
},
"vector_vector_DMatch": {
"j_type": "List<MatOfDMatch>",
"jn_type": "long",

View File

@ -3,6 +3,8 @@
#ifdef HAVE_OPENCV_CORE
#include "dlpack/dlpack.h"
static PyObject* pycvMakeType(PyObject* , PyObject* args, PyObject* kw) {
const char *keywords[] = { "depth", "channels", NULL };
@ -20,6 +22,201 @@ static PyObject* pycvMakeTypeCh(PyObject*, PyObject *value) {
return PyInt_FromLong(CV_MAKETYPE(depth, channels));
}
#define CV_DLPACK_CAPSULE_NAME "dltensor"
#define CV_DLPACK_USED_CAPSULE_NAME "used_dltensor"
template<typename T>
bool fillDLPackTensor(const T& src, DLManagedTensor* tensor, const DLDevice& device);
template<typename T>
bool parseDLPackTensor(DLManagedTensor* tensor, T& obj, bool copy);
template<typename T>
int GetNumDims(const T& src);
// source: https://github.com/dmlc/dlpack/blob/7f393bbb86a0ddd71fde3e700fc2affa5cdce72d/docs/source/python_spec.rst#L110
static void dlpack_capsule_deleter(PyObject *self){
if (PyCapsule_IsValid(self, CV_DLPACK_USED_CAPSULE_NAME)) {
return;
}
DLManagedTensor *managed = (DLManagedTensor *)PyCapsule_GetPointer(self, CV_DLPACK_CAPSULE_NAME);
if (managed == NULL) {
PyErr_WriteUnraisable(self);
return;
}
if (managed->deleter) {
managed->deleter(managed);
}
}
static void array_dlpack_deleter(DLManagedTensor *self)
{
if (!Py_IsInitialized()) {
return;
}
PyGILState_STATE state = PyGILState_Ensure();
PyObject *array = (PyObject *)self->manager_ctx;
PyMem_Free(self);
Py_XDECREF(array);
PyGILState_Release(state);
}
template<typename T>
static PyObject* to_dlpack(const T& src, PyObject* self, PyObject* py_args, PyObject* kw)
{
int stream = 0;
PyObject* maxVersion = nullptr;
PyObject* dlDevice = nullptr;
bool copy = false;
const char* keywords[] = { "stream", "max_version", "dl_device", "copy", NULL };
if (!PyArg_ParseTupleAndKeywords(py_args, kw, "|iOOp:__dlpack__", (char**)keywords, &stream, &maxVersion, &dlDevice, &copy))
return nullptr;
DLDevice device = {(DLDeviceType)-1, 0};
if (dlDevice && dlDevice != Py_None && PyTuple_Check(dlDevice))
{
device.device_type = static_cast<DLDeviceType>(PyLong_AsLong(PyTuple_GetItem(dlDevice, 0)));
device.device_id = PyLong_AsLong(PyTuple_GetItem(dlDevice, 1));
}
int ndim = GetNumDims(src);
void* ptr = PyMem_Malloc(sizeof(DLManagedTensor) + sizeof(int64_t) * ndim * 2);
if (!ptr) {
PyErr_NoMemory();
return nullptr;
}
DLManagedTensor* tensor = reinterpret_cast<DLManagedTensor*>(ptr);
tensor->manager_ctx = self;
tensor->deleter = array_dlpack_deleter;
tensor->dl_tensor.ndim = ndim;
tensor->dl_tensor.shape = reinterpret_cast<int64_t*>(reinterpret_cast<char*>(ptr) + sizeof(DLManagedTensor));
tensor->dl_tensor.strides = tensor->dl_tensor.shape + ndim;
fillDLPackTensor(src, tensor, device);
PyObject* capsule = PyCapsule_New(ptr, CV_DLPACK_CAPSULE_NAME, dlpack_capsule_deleter);
if (!capsule) {
PyMem_Free(ptr);
return nullptr;
}
// the capsule holds a reference
Py_INCREF(self);
return capsule;
}
template<typename T>
static PyObject* from_dlpack(PyObject* py_args, PyObject* kw)
{
PyObject* arr = nullptr;
PyObject* device = nullptr;
bool copy = false;
const char* keywords[] = { "device", "copy", NULL };
if (!PyArg_ParseTupleAndKeywords(py_args, kw, "O|Op:from_dlpack", (char**)keywords, &arr, &device, &copy))
return nullptr;
PyObject* capsule = nullptr;
if (PyCapsule_CheckExact(arr))
{
capsule = arr;
}
else
{
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
capsule = PyObject_CallMethodObjArgs(arr, PyString_FromString("__dlpack__"), NULL);
PyGILState_Release(gstate);
}
DLManagedTensor* tensor = reinterpret_cast<DLManagedTensor*>(PyCapsule_GetPointer(capsule, CV_DLPACK_CAPSULE_NAME));
if (tensor == nullptr)
{
if (capsule != arr)
Py_DECREF(capsule);
return nullptr;
}
T retval;
bool success = parseDLPackTensor(tensor, retval, copy);
if (success)
{
PyCapsule_SetName(capsule, CV_DLPACK_USED_CAPSULE_NAME);
}
if (capsule != arr)
Py_DECREF(capsule);
return success ? pyopencv_from(retval) : nullptr;
}
static DLDataType GetDLPackType(size_t elemSize1, int depth) {
DLDataType dtype;
dtype.bits = static_cast<uint8_t>(8 * elemSize1);
dtype.lanes = 1;
switch (depth)
{
case CV_8S: case CV_16S: case CV_32S: dtype.code = kDLInt; break;
case CV_8U: case CV_16U: dtype.code = kDLUInt; break;
case CV_16F: case CV_32F: case CV_64F: dtype.code = kDLFloat; break;
default:
CV_Error(Error::StsNotImplemented, "__dlpack__ data type");
}
return dtype;
}
static int DLPackTypeToCVType(const DLDataType& dtype, int channels) {
if (dtype.code == kDLInt)
{
switch (dtype.bits)
{
case 8: return CV_8SC(channels);
case 16: return CV_16SC(channels);
case 32: return CV_32SC(channels);
default:
{
PyErr_SetString(PyExc_BufferError,
format("Unsupported int dlpack depth: %d", dtype.bits).c_str());
return -1;
}
}
}
if (dtype.code == kDLUInt)
{
switch (dtype.bits)
{
case 8: return CV_8UC(channels);
case 16: return CV_16UC(channels);
default:
{
PyErr_SetString(PyExc_BufferError,
format("Unsupported uint dlpack depth: %d", dtype.bits).c_str());
return -1;
}
}
}
if (dtype.code == kDLFloat)
{
switch (dtype.bits)
{
case 16: return CV_16FC(channels);
case 32: return CV_32FC(channels);
case 64: return CV_64FC(channels);
default:
{
PyErr_SetString(PyExc_BufferError,
format("Unsupported float dlpack depth: %d", dtype.bits).c_str());
return -1;
}
}
}
PyErr_SetString(PyExc_BufferError, format("Unsupported dlpack data type: %d", dtype.code).c_str());
return -1;
}
#define PYOPENCV_EXTRA_METHODS_CV \
{"CV_MAKETYPE", CV_PY_FN_WITH_KW(pycvMakeType), "CV_MAKETYPE(depth, channels) -> retval"}, \
{"CV_8UC", (PyCFunction)(pycvMakeTypeCh<CV_8U>), METH_O, "CV_8UC(channels) -> retval"}, \

View File

@ -21,17 +21,175 @@ template<> struct pyopencvVecConverter<cuda::GpuMat>
};
CV_PY_TO_CLASS(cuda::GpuMat)
CV_PY_TO_CLASS(cuda::GpuMatND)
CV_PY_TO_CLASS(cuda::Stream)
CV_PY_TO_CLASS(cuda::Event)
CV_PY_TO_CLASS(cuda::HostMem)
CV_PY_TO_CLASS_PTR(cuda::GpuMat)
CV_PY_TO_CLASS_PTR(cuda::GpuMatND)
CV_PY_TO_CLASS_PTR(cuda::GpuMat::Allocator)
CV_PY_FROM_CLASS(cuda::GpuMat)
CV_PY_FROM_CLASS(cuda::GpuMatND)
CV_PY_FROM_CLASS(cuda::Stream)
CV_PY_FROM_CLASS(cuda::HostMem)
CV_PY_FROM_CLASS_PTR(cuda::GpuMat::Allocator)
template<>
bool fillDLPackTensor(const Ptr<cv::cuda::GpuMat>& src, DLManagedTensor* tensor, const DLDevice& device)
{
if ((device.device_type != -1 && device.device_type != kDLCUDA) || device.device_id != 0)
{
PyErr_SetString(PyExc_BufferError, "GpuMat can be exported only on GPU:0");
return false;
}
tensor->dl_tensor.data = src->cudaPtr();
tensor->dl_tensor.device.device_type = kDLCUDA;
tensor->dl_tensor.device.device_id = 0;
tensor->dl_tensor.dtype = GetDLPackType(src->elemSize1(), src->depth());
tensor->dl_tensor.shape[0] = src->rows;
tensor->dl_tensor.shape[1] = src->cols;
tensor->dl_tensor.shape[2] = src->channels();
tensor->dl_tensor.strides[0] = src->step1();
tensor->dl_tensor.strides[1] = src->channels();
tensor->dl_tensor.strides[2] = 1;
tensor->dl_tensor.byte_offset = 0;
return true;
}
template<>
bool fillDLPackTensor(const Ptr<cv::cuda::GpuMatND>& src, DLManagedTensor* tensor, const DLDevice& device)
{
if ((device.device_type != -1 && device.device_type != kDLCUDA) || device.device_id != 0)
{
PyErr_SetString(PyExc_BufferError, "GpuMatND can be exported only on GPU:0");
return false;
}
tensor->dl_tensor.data = src->getDevicePtr();
tensor->dl_tensor.device.device_type = kDLCUDA;
tensor->dl_tensor.device.device_id = 0;
tensor->dl_tensor.dtype = GetDLPackType(src->elemSize1(), CV_MAT_DEPTH(src->flags));
for (int i = 0; i < src->dims; ++i)
tensor->dl_tensor.shape[i] = src->size[i];
for (int i = 0; i < src->dims; ++i)
tensor->dl_tensor.strides[i] = src->step[i];
tensor->dl_tensor.byte_offset = 0;
return true;
}
template<>
bool parseDLPackTensor(DLManagedTensor* tensor, cv::cuda::GpuMat& obj, bool copy)
{
if (tensor->dl_tensor.byte_offset != 0)
{
PyErr_SetString(PyExc_BufferError, "Unimplemented from_dlpack for GpuMat with memory offset");
return false;
}
if (tensor->dl_tensor.ndim != 3)
{
PyErr_SetString(PyExc_BufferError, "cuda_GpuMat.from_dlpack expects a 3D tensor. Use cuda_GpuMatND.from_dlpack instead");
return false;
}
if (tensor->dl_tensor.device.device_type != kDLCUDA)
{
PyErr_SetString(PyExc_BufferError, "cuda_GpuMat.from_dlpack expects a tensor on CUDA device");
return false;
}
if (tensor->dl_tensor.strides[1] != tensor->dl_tensor.shape[2] ||
tensor->dl_tensor.strides[2] != 1)
{
PyErr_SetString(PyExc_BufferError, "Unexpected strides for image. Try use GpuMatND");
return false;
}
int type = DLPackTypeToCVType(tensor->dl_tensor.dtype, (int)tensor->dl_tensor.shape[2]);
if (type == -1)
return false;
obj = cv::cuda::GpuMat(
static_cast<int>(tensor->dl_tensor.shape[0]),
static_cast<int>(tensor->dl_tensor.shape[1]),
type,
tensor->dl_tensor.data,
tensor->dl_tensor.strides[0] * tensor->dl_tensor.dtype.bits / 8
);
if (copy)
obj = obj.clone();
return true;
}
template<>
bool parseDLPackTensor(DLManagedTensor* tensor, cv::cuda::GpuMatND& obj, bool copy)
{
if (tensor->dl_tensor.byte_offset != 0)
{
PyErr_SetString(PyExc_BufferError, "Unimplemented from_dlpack for GpuMat with memory offset");
return false;
}
if (tensor->dl_tensor.device.device_type != kDLCUDA)
{
PyErr_SetString(PyExc_BufferError, "cuda_GpuMat.from_dlpack expects a tensor on CUDA device");
return false;
}
int type = DLPackTypeToCVType(tensor->dl_tensor.dtype, (int)tensor->dl_tensor.shape[2]);
if (type == -1)
return false;
std::vector<size_t> steps(tensor->dl_tensor.ndim - 1);
std::vector<int> sizes(tensor->dl_tensor.ndim);
for (int i = 0; i < tensor->dl_tensor.ndim - 1; ++i)
{
steps[i] = tensor->dl_tensor.strides[i] * tensor->dl_tensor.dtype.bits / 8;
sizes[i] = static_cast<int>(tensor->dl_tensor.shape[i]);
}
sizes.back() = static_cast<int>(tensor->dl_tensor.shape[tensor->dl_tensor.ndim - 1]);
obj = cv::cuda::GpuMatND(sizes, type, tensor->dl_tensor.data, steps);
if (copy)
obj = obj.clone();
return true;
}
template<>
int GetNumDims(const Ptr<cv::cuda::GpuMat>& src) { return 3; }
template<>
int GetNumDims(const Ptr<cv::cuda::GpuMatND>& src) { return src->dims; }
static PyObject* pyDLPackGpuMat(PyObject* self, PyObject* py_args, PyObject* kw) {
Ptr<cv::cuda::GpuMat> * self1 = 0;
if (!pyopencv_cuda_GpuMat_getp(self, self1))
return failmsgp("Incorrect type of self (must be 'cuda_GpuMat' or its derivative)");
return to_dlpack(*(self1), self, py_args, kw);
}
static PyObject* pyDLPackGpuMatND(PyObject* self, PyObject* py_args, PyObject* kw) {
Ptr<cv::cuda::GpuMatND> * self1 = 0;
if (!pyopencv_cuda_GpuMatND_getp(self, self1))
return failmsgp("Incorrect type of self (must be 'cuda_GpuMatND' or its derivative)");
return to_dlpack(*(self1), self, py_args, kw);
}
static PyObject* pyDLPackDeviceCUDA(PyObject*, PyObject*, PyObject*) {
return pyopencv_from(std::tuple<int, int>(kDLCUDA, 0));
}
static PyObject* pyGpuMatFromDLPack(PyObject*, PyObject* py_args, PyObject* kw) {
return from_dlpack<cv::cuda::GpuMat>(py_args, kw);
}
static PyObject* pyGpuMatNDFromDLPack(PyObject*, PyObject* py_args, PyObject* kw) {
return from_dlpack<cv::cuda::GpuMatND>(py_args, kw);
}
#define PYOPENCV_EXTRA_METHODS_cuda_GpuMat \
{"__dlpack__", CV_PY_FN_WITH_KW(pyDLPackGpuMat), ""}, \
{"__dlpack_device__", CV_PY_FN_WITH_KW(pyDLPackDeviceCUDA), ""}, \
{"from_dlpack", CV_PY_FN_WITH_KW_(pyGpuMatFromDLPack, METH_STATIC), ""}, \
#define PYOPENCV_EXTRA_METHODS_cuda_GpuMatND \
{"__dlpack__", CV_PY_FN_WITH_KW(pyDLPackGpuMatND), ""}, \
{"__dlpack_device__", CV_PY_FN_WITH_KW(pyDLPackDeviceCUDA), ""}, \
{"from_dlpack", CV_PY_FN_WITH_KW_(pyGpuMatNDFromDLPack, METH_STATIC), ""}, \
#endif

View File

@ -60,6 +60,14 @@ namespace cv
#undef USE_IPP_DFT
#endif
#if defined USE_IPP_DFT
#if IPP_VERSION_X100 >= 202220
#define IPP_DISABLE_DFT32F ((depth == CV_32F) && (ippCPUID_AVX512F&cv::ipp::getIppFeatures()))
#else
#define IPP_DISABLE_DFT32F false
#endif
#endif
/****************************************************************************************\
Discrete Fourier Transform
\****************************************************************************************/
@ -3258,7 +3266,7 @@ public:
opt.ipp_spec = 0;
opt.ipp_work = 0;
if( CV_IPP_CHECK_COND && (opt.n*count >= 64) ) // use IPP DFT if available
if( CV_IPP_CHECK_COND && (opt.n*count >= 64) && !IPP_DISABLE_DFT32F) // use IPP DFT if available
{
int ipp_norm_flag = (flags & CV_HAL_DFT_SCALE) == 0 ? 8 : opt.isInverse ? 2 : 1;
int specsize=0, initsize=0, worksize=0;

View File

@ -0,0 +1,67 @@
package org.opencv.test.dnn;
import java.util.ArrayList;
import java.util.List;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.Range;
import org.opencv.dnn.Dnn;
import org.opencv.dnn.Net;
import org.opencv.test.OpenCVTestCase;
public class DnnForwardAndRetrieve extends OpenCVTestCase {
public void testForwardAndRetrieve()
{
// Create a simple Caffe prototxt with a Slice layer
String prototxt =
"input: \"data\"\n" +
"layer {\n" +
" name: \"testLayer\"\n" +
" type: \"Slice\"\n" +
" bottom: \"data\"\n" +
" top: \"firstCopy\"\n" +
" top: \"secondCopy\"\n" +
" slice_param {\n" +
" axis: 0\n" +
" slice_point: 2\n" +
" }\n" +
"}";
// Read network from prototxt
MatOfByte bufferProto = new MatOfByte();
bufferProto.fromArray(prototxt.getBytes());
MatOfByte bufferModel = new MatOfByte();
Net net = Dnn.readNetFromCaffe(bufferProto, bufferModel, Dnn.ENGINE_CLASSIC);
net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV);
// Create input data
Mat inp = new Mat(4, 5, CvType.CV_32F);
Core.randu(inp, -1, 1);
net.setInput(inp);
// Define output names
List<String> outNames = new ArrayList<>();
outNames.add("testLayer");
// Forward and retrieve multiple outputs
List<List<Mat>> outBlobs = new ArrayList<>();
net.forwardAndRetrieve(outBlobs, outNames);
// Verify results
assertEquals(1, outBlobs.size());
assertEquals(2, outBlobs.get(0).size());
// Compare results
Mat expectedFirst = inp.rowRange(0, 2);
Mat expectedSecond = inp.rowRange(2, 4);
Mat actualFirst = outBlobs.get(0).get(0);
Mat actualSecond = outBlobs.get(0).get(1);
assertEquals(0, Core.norm(expectedFirst, actualFirst, Core.NORM_INF), EPS);
assertEquals(0, Core.norm(expectedSecond, actualSecond, Core.NORM_INF), EPS);
}
}

View File

@ -1110,13 +1110,27 @@ public:
*/
CV_WRAP Subdiv2D(Rect rect);
/** @brief Creates a new empty Delaunay subdivision
/** @overload */
CV_WRAP Subdiv2D(Rect2f rect2f);
/** @overload
@brief Creates a new empty Delaunay subdivision
@param rect Rectangle that includes all of the 2D points that are to be added to the subdivision.
*/
CV_WRAP void initDelaunay(Rect rect);
/** @overload
@brief Creates a new empty Delaunay subdivision
@param rect Rectangle that includes all of the 2d points that are to be added to the subdivision.
*/
CV_WRAP_AS(initDelaunay2f) CV_WRAP void initDelaunay(Rect2f rect);
/** @brief Insert a single point into a Delaunay triangulation.
@param pt Point to insert.

View File

@ -118,6 +118,16 @@ Subdiv2D::Subdiv2D(Rect rect)
initDelaunay(rect);
}
Subdiv2D::Subdiv2D(Rect2f rect)
{
validGeometry = false;
freeQEdge = 0;
freePoint = 0;
recentEdge = 0;
initDelaunay(rect);
}
Subdiv2D::QuadEdge::QuadEdge()
{
@ -535,6 +545,52 @@ void Subdiv2D::initDelaunay( Rect rect )
recentEdge = edge_AB;
}
void Subdiv2D::initDelaunay( Rect2f rect )
{
CV_INSTRUMENT_REGION();
float big_coord = 6.f * MAX( rect.width, rect.height );
float rx = rect.x;
float ry = rect.y;
vtx.clear();
qedges.clear();
recentEdge = 0;
validGeometry = false;
topLeft = Point2f( rx, ry );
bottomRight = Point2f( rx + rect.width, ry + rect.height );
Point2f ppA( rx + big_coord, ry );
Point2f ppB( rx, ry + big_coord );
Point2f ppC( rx - big_coord, ry - big_coord );
vtx.push_back(Vertex());
qedges.push_back(QuadEdge());
freeQEdge = 0;
freePoint = 0;
int pA = newPoint(ppA, false);
int pB = newPoint(ppB, false);
int pC = newPoint(ppC, false);
int edge_AB = newEdge();
int edge_BC = newEdge();
int edge_CA = newEdge();
setEdgePoints( edge_AB, pA, pB );
setEdgePoints( edge_BC, pB, pC );
setEdgePoints( edge_CA, pC, pA );
splice( edge_AB, symEdge( edge_CA ));
splice( edge_BC, symEdge( edge_AB ));
splice( edge_CA, symEdge( edge_BC ));
recentEdge = edge_AB;
}
void Subdiv2D::clearVoronoi()
{

View File

@ -11,10 +11,13 @@ namespace opencv_test { namespace {
// return true if point lies inside ellipse
static bool check_pt_in_ellipse(const Point2f& pt, const RotatedRect& el) {
Point2f to_pt = pt - el.center;
double pt_angle = atan2(to_pt.y, to_pt.x);
double el_angle = el.angle * CV_PI / 180;
double x_dist = 0.5 * el.size.width * cos(pt_angle + el_angle);
double y_dist = 0.5 * el.size.height * sin(pt_angle + el_angle);
const Point2d to_pt_el(
to_pt.x * cos(-el_angle) - to_pt.y * sin(-el_angle),
to_pt.x * sin(-el_angle) + to_pt.y * cos(-el_angle));
const double pt_angle = atan2(to_pt_el.y / el.size.height, to_pt_el.x / el.size.width);
const double x_dist = 0.5 * el.size.width * cos(pt_angle);
const double y_dist = 0.5 * el.size.height * sin(pt_angle);
double el_dist = sqrt(x_dist * x_dist + y_dist * y_dist);
return cv::norm(to_pt) < el_dist;
}

View File

@ -64,4 +64,57 @@ TEST(Imgproc_Subdiv2D, issue_25696) {
ASSERT_EQ(static_cast<size_t>(2), triangles.size());
}
// Initialization test
TEST(Imgproc_Subdiv2D, rect2f_constructor_and_init)
{
cv::Rect2f rect_f(0.5f, 1.5f, 100.7f, 200.3f);
cv::Subdiv2D subdiv_f(rect_f);
cv::Point2f pt1(50.2f, 80.1f);
cv::Point2f pt2(75.8f, 120.9f);
cv::Point2f pt3(25.5f, 150.3f);
EXPECT_NO_THROW(subdiv_f.insert(pt1));
EXPECT_NO_THROW(subdiv_f.insert(pt2));
EXPECT_NO_THROW(subdiv_f.insert(pt3));
cv::Subdiv2D subdiv_init;
EXPECT_NO_THROW(subdiv_init.initDelaunay(rect_f));
EXPECT_NO_THROW(subdiv_init.insert(pt1));
EXPECT_NO_THROW(subdiv_init.insert(pt2));
EXPECT_NO_THROW(subdiv_init.insert(pt3));
std::vector<cv::Vec6f> triangles;
EXPECT_NO_THROW(subdiv_f.getTriangleList(triangles));
EXPECT_GT(triangles.size(), 0u);
}
// test with small coordinates
TEST(Imgproc_Subdiv2D, rect2f_edge_cases)
{
cv::Rect2f small_rect(0.0f, 0.0f, 0.1f, 0.1f);
cv::Subdiv2D subdiv_small(small_rect);
cv::Point2f small_pt(0.05f, 0.05f);
EXPECT_NO_THROW(subdiv_small.insert(small_pt));
cv::Rect2f float_rect(10.25f, 20.75f, 50.5f, 30.25f);
cv::Subdiv2D subdiv_float(float_rect);
cv::Point2f float_pt1(35.125f, 35.875f);
cv::Point2f float_pt2(45.375f, 25.625f);
cv::Point2f float_pt3(55.750f, 45.125f);
EXPECT_NO_THROW(subdiv_float.insert(float_pt1));
EXPECT_NO_THROW(subdiv_float.insert(float_pt2));
EXPECT_NO_THROW(subdiv_float.insert(float_pt3));
std::vector<cv::Vec6f> triangles;
subdiv_float.getTriangleList(triangles);
EXPECT_GT(triangles.size(), 0u);
}
}}

View File

@ -756,6 +756,13 @@ class JavaWrapperGenerator(object):
"jdouble _tmp_retval_[%(cnt)i] = {%(args)s}; " +
"env->SetDoubleArrayRegion(_da_retval_, 0, %(cnt)i, _tmp_retval_);") %
{ "cnt" : len(fields), "args" : ", ".join(["(jdouble)_retval_" + f[1] for f in fields]) } )
elif type_dict[fi.ctype]["jni_type"] == "jintArray":
fields = type_dict[fi.ctype]["jn_args"]
c_epilogue.append(
("jintArray _ia_retval_ = env->NewIntArray(%(cnt)i); " +
"jint _tmp_retval_[%(cnt)i] = {%(args)s}; " +
"env->SetIntArrayRegion(_ia_retval_, 0, %(cnt)i, _tmp_retval_);") %
{ "cnt" : len(fields), "args" : ", ".join(["(jint)_retval_" + f[1] for f in fields]) } )
if fi.classname and fi.ctype and not fi.static: # non-static class method except c-tor
# adding 'self'
jn_args.append ( ArgInfo([ "__int64", "nativeObj", "", [], "" ]) )
@ -803,7 +810,14 @@ class JavaWrapperGenerator(object):
fields = type_dict[a.ctype].get("jn_args", ((a.ctype, ""),))
if "I" in a.out or not a.out or self.isWrapped(a.ctype): # input arg, pass by primitive fields
for f in fields:
jn_args.append ( ArgInfo([ f[0], a.name + f[1], "", [], "" ]) )
# Use array access format for Java code when jn_type is array type
if type_dict[a.ctype].get("jn_type", "").endswith("[]"):
# For Java code: convert .val[0] format to [0] format
jn_args.append ( ArgInfo([ f[0], a.name + f[1].replace(".val[", "["), "", [], "" ]) )
else:
# For non-array types, use conventional format
jn_args.append ( ArgInfo([ f[0], a.name + f[1], "", [], "" ]) )
# For C++ code: use conventional format as is
jni_args.append( ArgInfo([ f[0], a.name + normalize_field_name(f[1]), "", [], "" ]) )
if "O" in a.out and not self.isWrapped(a.ctype): # out arg, pass as double[]
jn_args.append ( ArgInfo([ "double[]", "%s_out" % a.name, "", [], "" ]) )
@ -818,9 +832,16 @@ class JavaWrapperGenerator(object):
set_vals = []
i = 0
for f in fields:
set_vals.append( "%(n)s%(f)s = %(t)s%(n)s_out[%(i)i]" %
{"n" : a.name, "t": ("("+type_dict[f[0]]["j_type"]+")", "")[f[0]=="double"], "f" : f[1], "i" : i}
)
# Use array access format for Java code when jn_type is array type
if type_dict[a.ctype].get("jn_type", "").endswith("[]"):
# For Java code: convert .val[0] format to [0] format
set_vals.append( "%(n)s%(f)s = %(t)s%(n)s_out[%(i)i]" %
{"n" : a.name, "t": ("("+type_dict[f[0]]["j_type"]+")", "")[f[0]=="double"], "f" : f[1].replace(".val[", "["), "i" : i}
)
else:
set_vals.append( "%(n)s%(f)s = %(t)s%(n)s_out[%(i)i]" %
{"n" : a.name, "t": ("("+type_dict[f[0]]["j_type"]+")", "")[f[0]=="double"], "f" : f[1], "i" : i}
)
i += 1
j_epilogue.append( "if("+a.name+"!=null){ " + "; ".join(set_vals) + "; } ")
@ -1015,6 +1036,8 @@ class JavaWrapperGenerator(object):
ret = "return (jlong) _retval_;"
elif type_dict[fi.ctype]["jni_type"] == "jdoubleArray":
ret = "return _da_retval_;"
elif type_dict[fi.ctype]["jni_type"] == "jintArray":
ret = "return _ia_retval_;"
elif "jni_var" in type_dict[ret_type]:
c_epilogue.append(type_dict[ret_type]["jni_var"] % {"n" : '_retval_'})
ret = f"return {type_dict[ret_type]['jni_name'] % {'n' : '_retval_'}};"

View File

@ -219,6 +219,32 @@ void vector_Mat_to_Mat(std::vector<cv::Mat>& v_mat, cv::Mat& mat)
}
}
void Mat_to_vector_vector_Mat(Mat& mat, std::vector< std::vector< Mat > >& vv_mat)
{
std::vector<Mat> vm;
vm.reserve( mat.rows );
Mat_to_vector_Mat(mat, vm);
for(size_t i=0; i<vm.size(); i++)
{
std::vector<Mat> vmat;
Mat_to_vector_Mat(vm[i], vmat);
vv_mat.push_back(vmat);
}
}
void vector_vector_Mat_to_Mat(std::vector< std::vector< Mat > >& vv_mat, Mat& mat)
{
std::vector<Mat> vm;
vm.reserve( vv_mat.size() );
for(size_t i=0; i<vv_mat.size(); i++)
{
Mat m;
vector_Mat_to_Mat(vv_mat[i], m);
vm.push_back(m);
}
vector_Mat_to_Mat(vm, mat);
}
void Mat_to_vector_vector_Point(Mat& mat, std::vector< std::vector< Point > >& vv_pt)
{
std::vector<Mat> vm;

View File

@ -50,6 +50,9 @@ void vector_Vec6f_to_Mat(std::vector<cv::Vec6f>& v_vec, cv::Mat& mat);
void Mat_to_vector_Mat(cv::Mat& mat, std::vector<cv::Mat>& v_mat);
void vector_Mat_to_Mat(std::vector<cv::Mat>& v_mat, cv::Mat& mat);
void Mat_to_vector_vector_Mat(cv::Mat& mat, std::vector< std::vector< cv::Mat > >& vv_mat);
void vector_vector_Mat_to_Mat(std::vector< std::vector< cv::Mat > >& vv_mat, cv::Mat& mat);
void Mat_to_vector_vector_char(cv::Mat& mat, std::vector< std::vector< char > >& vv_ch);
void vector_vector_char_to_Mat(std::vector< std::vector< char > >& vv_ch, cv::Mat& mat);

View File

@ -7,6 +7,7 @@ import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.MatOfDMatch;
import org.opencv.core.MatOfInt;
import org.opencv.core.MatOfKeyPoint;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
@ -514,6 +515,41 @@ public class Converters {
}
}
// vector_vector_Mat
public static Mat vector_vector_Mat_to_Mat(List<List<Mat>> vecMats, List<Mat> mats) {
Mat res;
int lCount = (vecMats != null) ? vecMats.size() : 0;
if (lCount > 0) {
for (List<Mat> matList : vecMats) {
Mat mat = vector_Mat_to_Mat(matList);
mats.add(mat);
}
res = vector_Mat_to_Mat(mats);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_vector_Mat(Mat m, List<List<Mat>> vecMats) {
if (vecMats == null)
throw new IllegalArgumentException("Output List can't be null");
if (m == null)
throw new IllegalArgumentException("Input Mat can't be null");
vecMats.clear();
List<Mat> mats = new ArrayList<Mat>(m.rows());
Mat_to_vector_Mat(m, mats);
for (Mat mi : mats) {
List<Mat> rowList = new ArrayList<Mat>(mi.rows());
Mat_to_vector_Mat(mi, rowList);
vecMats.add(rowList);
mi.release();
}
mats.clear();
}
// vector_vector_Point
public static Mat vector_vector_Point_to_Mat(List<MatOfPoint> pts, List<Mat> mats) {
Mat res;
@ -803,4 +839,75 @@ public class Converters {
rs.add(new RotatedRect(new Point(buff[5 * i], buff[5 * i + 1]), new Size(buff[5 * i + 2], buff[5 * i + 3]), buff[5 * i + 4]));
}
}
// vector_MatShape
public static Mat vector_MatShape_to_Mat(List<MatOfInt> matOfInts) {
Mat res;
int count = (matOfInts != null) ? matOfInts.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_32SC2);
int[] buff = new int[count * 2];
for (int i = 0; i < count; i++) {
long addr = matOfInts.get(i).nativeObj;
buff[i * 2] = (int) (addr >> 32);
buff[i * 2 + 1] = (int) (addr & 0xffffffff);
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_MatShape(Mat m, List<MatOfInt> matOfInts) {
if (matOfInts == null)
throw new IllegalArgumentException("matOfInts == null");
int count = m.rows();
if (CvType.CV_32SC2 != m.type() || m.cols() != 1)
throw new IllegalArgumentException(
"CvType.CV_32SC2 != m.type() || m.cols()!=1\n" + m);
matOfInts.clear();
int[] buff = new int[count * 2];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
long addr = (((long) buff[i * 2]) << 32) | (((long) buff[i * 2 + 1]) & 0xffffffffL);
matOfInts.add(MatOfInt.fromNativeAddr(addr));
}
}
// vector_vector_MatShape
public static Mat vector_vector_MatShape_to_Mat(List<List<MatOfInt>> vecMatOfInts, List<Mat> mats) {
Mat res;
int lCount = (vecMatOfInts != null) ? vecMatOfInts.size() : 0;
if (lCount > 0) {
for (List<MatOfInt> matList : vecMatOfInts) {
Mat mat = vector_MatShape_to_Mat(matList);
mats.add(mat);
}
res = vector_Mat_to_Mat(mats);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_vector_MatShape(Mat m, List<List<MatOfInt>> vecMatOfInts) {
if (vecMatOfInts == null)
throw new IllegalArgumentException("Output List can't be null");
if (m == null)
throw new IllegalArgumentException("Input Mat can't be null");
vecMatOfInts.clear();
List<Mat> mats = new ArrayList<Mat>(m.rows());
Mat_to_vector_Mat(m, mats);
for (Mat mi : mats) {
List<MatOfInt> rowList = new ArrayList<MatOfInt>(mi.rows());
Mat_to_vector_MatShape(mi, rowList);
vecMatOfInts.add(rowList);
mi.release();
}
mats.clear();
}
}

View File

@ -68,13 +68,20 @@ if(DEFINED OPENCV_PYTHON_INSTALL_PATH)
endif()
set(CMAKE_PYTHON_BINARIES_PATH "${CMAKE_PYTHON_BINARIES_INSTALL_PATH}")
if (WIN32 AND HAVE_CUDA)
set(_cuda_bin_dir "bin")
if (ENABLE_CUDA_FIRST_CLASS_LANGUAGE)
if (DEFINED CUDAToolkit_LIBRARY_ROOT)
list(APPEND CMAKE_PYTHON_BINARIES_PATH "os.path.join(os.getenv('CUDA_PATH', '${CUDAToolkit_LIBRARY_ROOT}'), 'bin')")
if(DEFINED CUDAToolkit_VERSION_MAJOR AND CUDAToolkit_VERSION_MAJOR GREATER_EQUAL 13)
set(_cuda_bin_dir "bin/x64")
endif()
list(APPEND CMAKE_PYTHON_BINARIES_PATH "os.path.join(os.getenv('CUDA_PATH', '${CUDAToolkit_LIBRARY_ROOT}'), '${_cuda_bin_dir}')")
endif()
else()
if (DEFINED CUDA_TOOLKIT_ROOT_DIR)
list(APPEND CMAKE_PYTHON_BINARIES_PATH "os.path.join(os.getenv('CUDA_PATH', '${CUDA_TOOLKIT_ROOT_DIR}'), 'bin')")
if(DEFINED CUDA_VERSION_MAJOR AND CUDA_VERSION_MAJOR GREATER_EQUAL 13)
set(_cuda_bin_dir "bin/x64")
endif()
list(APPEND CMAKE_PYTHON_BINARIES_PATH "os.path.join(os.getenv('CUDA_PATH', '${CUDA_TOOLKIT_ROOT_DIR}'), '${_cuda_bin_dir}')")
endif()
endif()
endif()

View File

@ -133,6 +133,9 @@ static PyGetSetDef pyopencv_${name}_getseters[] =
static PyMethodDef pyopencv_${name}_methods[] =
{
#ifdef PYOPENCV_EXTRA_METHODS_${name}
PYOPENCV_EXTRA_METHODS_${name}
#endif
${methods_inits}
{NULL, NULL}
};

View File

@ -70,6 +70,7 @@ class cuda_test(NewOpenCVTests):
self.assertTrue(cuMat.step == 0)
self.assertTrue(cuMat.size() == (0, 0))
@unittest.skip("failed test")
def test_cuda_convertTo(self):
# setup
npMat_8UC4 = (np.random.random((128, 128, 4)) * 255).astype(np.uint8)
@ -105,6 +106,7 @@ class cuda_test(NewOpenCVTests):
stream.waitForCompletion()
self.assertTrue(np.array_equal(npMat_32FC4, npMat_32FC4_out))
@unittest.skip("failed test")
def test_cuda_copyTo(self):
# setup
npMat_8UC4 = (np.random.random((128, 128, 4)) * 255).astype(np.uint8)
@ -143,5 +145,18 @@ class cuda_test(NewOpenCVTests):
self.assertEqual(True, hasattr(cv.cuda, 'fastNlMeansDenoisingColored'))
self.assertEqual(True, hasattr(cv.cuda, 'nonLocalMeans'))
def test_dlpack_GpuMat(self):
for dtype in [np.int8, np.uint8, np.int16, np.uint16, np.float16, np.int32, np.float32, np.float64]:
for channels in [2, 3, 5]:
ref = (np.random.random((64, 128, channels)) * 255).astype(dtype)
src = cv.cuda_GpuMat()
src.upload(ref)
dst = cv.cuda_GpuMat.from_dlpack(src)
test = dst.download()
equal = np.array_equal(ref, test)
if not equal:
print(f"Failed test with dtype {dtype} and {channels} channels")
self.assertTrue(equal)
if __name__ == '__main__':
NewOpenCVTests.bootstrap()

View File

@ -711,7 +711,15 @@ enum VideoCaptureOBSensorProperties{
CAP_PROP_OBSENSOR_DEPTH_POS_MSEC=26006,
CAP_PROP_OBSENSOR_DEPTH_WIDTH=26007,
CAP_PROP_OBSENSOR_DEPTH_HEIGHT=26008,
CAP_PROP_OBSENSOR_DEPTH_FPS=26009
CAP_PROP_OBSENSOR_DEPTH_FPS=26009,
CAP_PROP_OBSENSOR_COLOR_DISTORTION_K1=26010,
CAP_PROP_OBSENSOR_COLOR_DISTORTION_K2=26011,
CAP_PROP_OBSENSOR_COLOR_DISTORTION_K3=26012,
CAP_PROP_OBSENSOR_COLOR_DISTORTION_K4=26013,
CAP_PROP_OBSENSOR_COLOR_DISTORTION_K5=26014,
CAP_PROP_OBSENSOR_COLOR_DISTORTION_K6=26015,
CAP_PROP_OBSENSOR_COLOR_DISTORTION_P1=26016,
CAP_PROP_OBSENSOR_COLOR_DISTORTION_P2=26017
};
//! @} OBSENSOR

View File

@ -685,7 +685,10 @@ void CvCapture_FFMPEG::close()
if( video_st )
{
#ifdef CV_FFMPEG_CODECPAR
// avcodec_close removed in FFmpeg release 8.0
# if (LIBAVCODEC_BUILD < CALC_FFMPEG_VERSION(62, 11, 100))
avcodec_close( context );
# endif
#endif
video_st = NULL;
}
@ -2005,7 +2008,18 @@ void CvCapture_FFMPEG::get_rotation_angle()
rotation_angle = 0;
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(57, 68, 100)
const uint8_t *data = 0;
// av_stream_get_side_data removed in FFmpeg release 8.0
# if (LIBAVCODEC_BUILD < CALC_FFMPEG_VERSION(62, 11, 100))
data = av_stream_get_side_data(video_st, AV_PKT_DATA_DISPLAYMATRIX, NULL);
# else
AVPacketSideData* sd = video_st->codecpar->coded_side_data;
int nb_sd = video_st->codecpar->nb_coded_side_data;
if (sd && nb_sd > 0)
{
const AVPacketSideData* mtx = av_packet_side_data_get(sd, nb_sd, AV_PKT_DATA_DISPLAYMATRIX);
data = mtx->data;
}
# endif
if (data)
{
rotation_angle = -cvRound(av_display_rotation_get((const int32_t*)data));

View File

@ -84,10 +84,19 @@ VideoCapture_obsensor::VideoCapture_obsensor(int, const cv::VideoCaptureParamete
});
auto param = pipe->getCameraParam();
camParam.p1[0] = param.rgbIntrinsic.fx;
camParam.p1[1] = param.rgbIntrinsic.fy;
camParam.p1[2] = param.rgbIntrinsic.cx;
camParam.p1[3] = param.rgbIntrinsic.cy;
camParam.intrinsicColor[0] = param.rgbIntrinsic.fx;
camParam.intrinsicColor[1] = param.rgbIntrinsic.fy;
camParam.intrinsicColor[2] = param.rgbIntrinsic.cx;
camParam.intrinsicColor[3] = param.rgbIntrinsic.cy;
camParam.distortionColor[0] = param.depthDistortion.k1;
camParam.distortionColor[1] = param.depthDistortion.k2;
camParam.distortionColor[2] = param.depthDistortion.k3;
camParam.distortionColor[3] = param.depthDistortion.k4;
camParam.distortionColor[4] = param.depthDistortion.k5;
camParam.distortionColor[5] = param.depthDistortion.k6;
camParam.distortionColor[6] = param.depthDistortion.p1;
camParam.distortionColor[7] = param.depthDistortion.p2;
}
VideoCapture_obsensor::~VideoCapture_obsensor(){
@ -101,17 +110,42 @@ double VideoCapture_obsensor::getProperty(int propIdx) const
switch (propIdx)
{
case CAP_PROP_OBSENSOR_INTRINSIC_FX:
rst = camParam.p1[0];
rst = camParam.intrinsicColor[0];
break;
case CAP_PROP_OBSENSOR_INTRINSIC_FY:
rst = camParam.p1[1];
rst = camParam.intrinsicColor[1];
break;
case CAP_PROP_OBSENSOR_INTRINSIC_CX:
rst = camParam.p1[2];
rst = camParam.intrinsicColor[2];
break;
case CAP_PROP_OBSENSOR_INTRINSIC_CY:
rst = camParam.p1[3];
rst = camParam.intrinsicColor[3];
break;
case CAP_PROP_OBSENSOR_COLOR_DISTORTION_K1:
rst = camParam.distortionColor[0];
break;
case CAP_PROP_OBSENSOR_COLOR_DISTORTION_K2:
rst = camParam.distortionColor[1];
break;
case CAP_PROP_OBSENSOR_COLOR_DISTORTION_K3:
rst = camParam.distortionColor[2];
break;
case CAP_PROP_OBSENSOR_COLOR_DISTORTION_K4:
rst = camParam.distortionColor[3];
break;
case CAP_PROP_OBSENSOR_COLOR_DISTORTION_K5:
rst = camParam.distortionColor[4];
break;
case CAP_PROP_OBSENSOR_COLOR_DISTORTION_K6:
rst = camParam.distortionColor[5];
break;
case CAP_PROP_OBSENSOR_COLOR_DISTORTION_P1:
rst = camParam.distortionColor[6];
break;
case CAP_PROP_OBSENSOR_COLOR_DISTORTION_P2:
rst = camParam.distortionColor[7];
break;
case CAP_PROP_POS_MSEC:
case CAP_PROP_OBSENSOR_RGB_POS_MSEC:
if (grabbedColorFrame)

View File

@ -33,14 +33,8 @@ namespace cv
struct CameraParam
{
float p0[4];
float p1[4];
float p2[9];
float p3[3];
float p4[5];
float p5[5];
uint32_t p6[2];
uint32_t p7[2];
float intrinsicColor[4];
float distortionColor[8];
};
class VideoCapture_obsensor : public IVideoCapture

View File

@ -648,7 +648,7 @@ static bool runCalibration( Settings& s, Size& imageSize, Mat& cameraMatrix, Mat
{
objectPoints[0][s.boardSize.width - 2].x = objectPoints[0][0].x + grid_width;
}
else if (s.calibrationPattern != Settings::Pattern::CHESSBOARD)
else if (s.calibrationPattern == Settings::Pattern::CHESSBOARD)
{
objectPoints[0][s.boardSize.width - 1].x = objectPoints[0][0].x + grid_width;
}

View File

@ -78,7 +78,20 @@ int main(int argc, char** argv)
double fy = obsensorCapture.get(CAP_PROP_OBSENSOR_INTRINSIC_FY);
double cx = obsensorCapture.get(CAP_PROP_OBSENSOR_INTRINSIC_CX);
double cy = obsensorCapture.get(CAP_PROP_OBSENSOR_INTRINSIC_CY);
double k1 = obsensorCapture.get(CAP_PROP_OBSENSOR_COLOR_DISTORTION_K1);
double k2 = obsensorCapture.get(CAP_PROP_OBSENSOR_COLOR_DISTORTION_K2);
double k3 = obsensorCapture.get(CAP_PROP_OBSENSOR_COLOR_DISTORTION_K3);
double k4 = obsensorCapture.get(CAP_PROP_OBSENSOR_COLOR_DISTORTION_K4);
double k5 = obsensorCapture.get(CAP_PROP_OBSENSOR_COLOR_DISTORTION_K5);
double k6 = obsensorCapture.get(CAP_PROP_OBSENSOR_COLOR_DISTORTION_K6);
double p1 = obsensorCapture.get(CAP_PROP_OBSENSOR_COLOR_DISTORTION_P1);
double p2 = obsensorCapture.get(CAP_PROP_OBSENSOR_COLOR_DISTORTION_P1);
std::cout << "obsensor camera intrinsic params: fx=" << fx << ", fy=" << fy << ", cx=" << cx << ", cy=" << cy << std::endl;
std::cout << "obsensor camera distortion params: k,p=" << k1 << ", " << k2 << ", " << k3 << ", "
<< k4 << ", " << k5 << ", " << k6 << ", "
<< p1 << ", " << p2 << std::endl;
Mat image;
Mat depthMap;