From 0de26fd78e1fc0597c0ed840694ac8612cccfeeb Mon Sep 17 00:00:00 2001 From: Letu Ren Date: Wed, 27 Dec 2023 12:06:17 +0800 Subject: [PATCH 001/119] Add zlib-ng as an alternative zlib implementation Zlib-ng is zlib replacement with optimizations for "next generation" systems. Its optimization may benifits image library decode and encode speed such as libpng. In our tests, if using zlib-ng and libpng combination on a x86_64 machine with AVX2, the time of `imdecode` amd `imencode` will drop 20% approximately. This patch enables zlib-ng's optimization if `CV_DISABLE_OPTIMIZATION` is OFF. Since Zlib-ng can dispatch intrinsics on the fly, port work is much easier. Related discussion: https://github.com/opencv/opencv/issues/22573 --- 3rdparty/readme.txt | 8 + 3rdparty/zlib-ng/CMakeLists.txt | 796 ++ 3rdparty/zlib-ng/LICENSE.md | 19 + 3rdparty/zlib-ng/README.md | 229 + 3rdparty/zlib-ng/adler32.c | 115 + 3rdparty/zlib-ng/adler32_fold.c | 16 + 3rdparty/zlib-ng/adler32_fold.h | 11 + 3rdparty/zlib-ng/adler32_p.h | 70 + 3rdparty/zlib-ng/arch/.gitignore | 2 + 3rdparty/zlib-ng/arch/arm/Makefile.in | 85 + 3rdparty/zlib-ng/arch/arm/acle_intrins.h | 35 + 3rdparty/zlib-ng/arch/arm/adler32_neon.c | 215 + 3rdparty/zlib-ng/arch/arm/arm_features.c | 100 + 3rdparty/zlib-ng/arch/arm/arm_features.h | 16 + 3rdparty/zlib-ng/arch/arm/chunkset_neon.c | 99 + 3rdparty/zlib-ng/arch/arm/compare256_neon.c | 59 + 3rdparty/zlib-ng/arch/arm/crc32_acle.c | 78 + .../zlib-ng/arch/arm/insert_string_acle.c | 24 + 3rdparty/zlib-ng/arch/arm/neon_intrins.h | 58 + 3rdparty/zlib-ng/arch/arm/slide_hash_armv6.c | 47 + 3rdparty/zlib-ng/arch/arm/slide_hash_neon.c | 46 + 3rdparty/zlib-ng/arch/generic/Makefile.in | 24 + .../arch/generic/chunk_permute_table.h | 53 + 3rdparty/zlib-ng/arch/power/Makefile.in | 93 + 3rdparty/zlib-ng/arch/power/adler32_power8.c | 153 + 3rdparty/zlib-ng/arch/power/adler32_vmx.c | 186 + 3rdparty/zlib-ng/arch/power/chunkset_power8.c | 55 + .../zlib-ng/arch/power/compare256_power9.c | 64 + 3rdparty/zlib-ng/arch/power/crc32_constants.h | 1123 ++ 3rdparty/zlib-ng/arch/power/crc32_power8.c | 589 + .../zlib-ng/arch/power/fallback_builtins.h | 31 + 3rdparty/zlib-ng/arch/power/power_features.c | 46 + 3rdparty/zlib-ng/arch/power/power_features.h | 18 + .../zlib-ng/arch/power/slide_hash_power8.c | 12 + 3rdparty/zlib-ng/arch/power/slide_hash_vmx.c | 10 + 3rdparty/zlib-ng/arch/power/slide_ppc_tpl.h | 31 + 3rdparty/zlib-ng/arch/riscv/README.md | 45 + 3rdparty/zlib-ng/arch/riscv/adler32_rvv.c | 132 + 3rdparty/zlib-ng/arch/riscv/chunkset_rvv.c | 121 + 3rdparty/zlib-ng/arch/riscv/compare256_rvv.c | 47 + 3rdparty/zlib-ng/arch/riscv/riscv_features.c | 45 + 3rdparty/zlib-ng/arch/riscv/riscv_features.h | 18 + 3rdparty/zlib-ng/arch/riscv/slide_hash_rvv.c | 34 + 3rdparty/zlib-ng/arch/x86/Makefile.in | 147 + 3rdparty/zlib-ng/arch/x86/adler32_avx2.c | 154 + 3rdparty/zlib-ng/arch/x86/adler32_avx2_p.h | 32 + 3rdparty/zlib-ng/arch/x86/adler32_avx512.c | 115 + 3rdparty/zlib-ng/arch/x86/adler32_avx512_p.h | 46 + .../zlib-ng/arch/x86/adler32_avx512_vnni.c | 225 + 3rdparty/zlib-ng/arch/x86/adler32_sse42.c | 121 + 3rdparty/zlib-ng/arch/x86/adler32_ssse3.c | 156 + 3rdparty/zlib-ng/arch/x86/adler32_ssse3_p.h | 29 + 3rdparty/zlib-ng/arch/x86/chunkset_avx2.c | 133 + 3rdparty/zlib-ng/arch/x86/chunkset_sse2.c | 56 + 3rdparty/zlib-ng/arch/x86/chunkset_ssse3.c | 101 + 3rdparty/zlib-ng/arch/x86/compare256_avx2.c | 63 + 3rdparty/zlib-ng/arch/x86/compare256_sse2.c | 96 + .../arch/x86/crc32_fold_pclmulqdq_tpl.h | 186 + .../arch/x86/crc32_fold_vpclmulqdq_tpl.h | 107 + 3rdparty/zlib-ng/arch/x86/crc32_pclmulqdq.c | 30 + .../zlib-ng/arch/x86/crc32_pclmulqdq_tpl.h | 363 + 3rdparty/zlib-ng/arch/x86/crc32_vpclmulqdq.c | 17 + .../zlib-ng/arch/x86/insert_string_sse42.c | 24 + 3rdparty/zlib-ng/arch/x86/slide_hash_avx2.c | 39 + 3rdparty/zlib-ng/arch/x86/slide_hash_sse2.c | 62 + 3rdparty/zlib-ng/arch/x86/x86_features.c | 97 + 3rdparty/zlib-ng/arch/x86/x86_features.h | 24 + 3rdparty/zlib-ng/arch/x86/x86_intrins.h | 87 + 3rdparty/zlib-ng/chunkset.c | 42 + 3rdparty/zlib-ng/chunkset_tpl.h | 200 + .../zlib-ng/cmake/detect-intrinsics.cmake | 543 + 3rdparty/zlib-ng/cmake/fallback-macros.cmake | 19 + 3rdparty/zlib-ng/compare256.c | 180 + 3rdparty/zlib-ng/compare256_rle.h | 134 + 3rdparty/zlib-ng/compress.c | 98 + 3rdparty/zlib-ng/cpu_features.c | 23 + 3rdparty/zlib-ng/cpu_features.h | 303 + 3rdparty/zlib-ng/crc32_braid.c | 267 + 3rdparty/zlib-ng/crc32_braid_comb.c | 57 + 3rdparty/zlib-ng/crc32_braid_comb_p.h | 42 + 3rdparty/zlib-ng/crc32_braid_p.h | 50 + 3rdparty/zlib-ng/crc32_braid_tbl.h | 9446 +++++++++++++++++ 3rdparty/zlib-ng/crc32_fold.c | 33 + 3rdparty/zlib-ng/crc32_fold.h | 21 + 3rdparty/zlib-ng/deflate.c | 1410 +++ 3rdparty/zlib-ng/deflate.h | 408 + 3rdparty/zlib-ng/deflate_fast.c | 102 + 3rdparty/zlib-ng/deflate_huff.c | 45 + 3rdparty/zlib-ng/deflate_medium.c | 293 + 3rdparty/zlib-ng/deflate_p.h | 116 + 3rdparty/zlib-ng/deflate_quick.c | 129 + 3rdparty/zlib-ng/deflate_rle.c | 85 + 3rdparty/zlib-ng/deflate_slow.c | 143 + 3rdparty/zlib-ng/deflate_stored.c | 186 + 3rdparty/zlib-ng/fallback_builtins.h | 50 + 3rdparty/zlib-ng/functable.c | 403 + 3rdparty/zlib-ng/functable.h | 42 + 3rdparty/zlib-ng/gzguts.h | 144 + 3rdparty/zlib-ng/gzlib.c | 525 + 3rdparty/zlib-ng/gzread.c.in | 606 ++ 3rdparty/zlib-ng/gzwrite.c | 526 + 3rdparty/zlib-ng/infback.c | 511 + 3rdparty/zlib-ng/inffast_tpl.h | 326 + 3rdparty/zlib-ng/inffixed_tbl.h | 94 + 3rdparty/zlib-ng/inflate.c | 1413 +++ 3rdparty/zlib-ng/inflate.h | 140 + 3rdparty/zlib-ng/inflate_p.h | 230 + 3rdparty/zlib-ng/inftrees.c | 295 + 3rdparty/zlib-ng/inftrees.h | 66 + 3rdparty/zlib-ng/insert_string.c | 21 + 3rdparty/zlib-ng/insert_string_roll.c | 24 + 3rdparty/zlib-ng/insert_string_tpl.h | 108 + 3rdparty/zlib-ng/match_tpl.h | 289 + 3rdparty/zlib-ng/slide_hash.c | 52 + 3rdparty/zlib-ng/trees.c | 818 ++ 3rdparty/zlib-ng/trees.h | 40 + 3rdparty/zlib-ng/trees_emit.h | 227 + 3rdparty/zlib-ng/trees_tbl.h | 132 + 3rdparty/zlib-ng/uncompr.c | 80 + 3rdparty/zlib-ng/zbuild.h | 260 + 3rdparty/zlib-ng/zconf.h.in | 206 + 3rdparty/zlib-ng/zendian.h | 60 + 3rdparty/zlib-ng/zlib.h.in | 1859 ++++ 3rdparty/zlib-ng/zlib_name_mangling.h.empty | 8 + 3rdparty/zlib-ng/zutil.c | 159 + 3rdparty/zlib-ng/zutil.h | 148 + 3rdparty/zlib-ng/zutil_p.h | 71 + CMakeLists.txt | 9 +- cmake/OpenCVFindLibsGrfmt.cmake | 38 +- 129 files changed, 31910 insertions(+), 13 deletions(-) create mode 100644 3rdparty/zlib-ng/CMakeLists.txt create mode 100644 3rdparty/zlib-ng/LICENSE.md create mode 100644 3rdparty/zlib-ng/README.md create mode 100644 3rdparty/zlib-ng/adler32.c create mode 100644 3rdparty/zlib-ng/adler32_fold.c create mode 100644 3rdparty/zlib-ng/adler32_fold.h create mode 100644 3rdparty/zlib-ng/adler32_p.h create mode 100644 3rdparty/zlib-ng/arch/.gitignore create mode 100644 3rdparty/zlib-ng/arch/arm/Makefile.in create mode 100644 3rdparty/zlib-ng/arch/arm/acle_intrins.h create mode 100644 3rdparty/zlib-ng/arch/arm/adler32_neon.c create mode 100644 3rdparty/zlib-ng/arch/arm/arm_features.c create mode 100644 3rdparty/zlib-ng/arch/arm/arm_features.h create mode 100644 3rdparty/zlib-ng/arch/arm/chunkset_neon.c create mode 100644 3rdparty/zlib-ng/arch/arm/compare256_neon.c create mode 100644 3rdparty/zlib-ng/arch/arm/crc32_acle.c create mode 100644 3rdparty/zlib-ng/arch/arm/insert_string_acle.c create mode 100644 3rdparty/zlib-ng/arch/arm/neon_intrins.h create mode 100644 3rdparty/zlib-ng/arch/arm/slide_hash_armv6.c create mode 100644 3rdparty/zlib-ng/arch/arm/slide_hash_neon.c create mode 100644 3rdparty/zlib-ng/arch/generic/Makefile.in create mode 100644 3rdparty/zlib-ng/arch/generic/chunk_permute_table.h create mode 100644 3rdparty/zlib-ng/arch/power/Makefile.in create mode 100644 3rdparty/zlib-ng/arch/power/adler32_power8.c create mode 100644 3rdparty/zlib-ng/arch/power/adler32_vmx.c create mode 100644 3rdparty/zlib-ng/arch/power/chunkset_power8.c create mode 100644 3rdparty/zlib-ng/arch/power/compare256_power9.c create mode 100644 3rdparty/zlib-ng/arch/power/crc32_constants.h create mode 100644 3rdparty/zlib-ng/arch/power/crc32_power8.c create mode 100644 3rdparty/zlib-ng/arch/power/fallback_builtins.h create mode 100644 3rdparty/zlib-ng/arch/power/power_features.c create mode 100644 3rdparty/zlib-ng/arch/power/power_features.h create mode 100644 3rdparty/zlib-ng/arch/power/slide_hash_power8.c create mode 100644 3rdparty/zlib-ng/arch/power/slide_hash_vmx.c create mode 100644 3rdparty/zlib-ng/arch/power/slide_ppc_tpl.h create mode 100644 3rdparty/zlib-ng/arch/riscv/README.md create mode 100644 3rdparty/zlib-ng/arch/riscv/adler32_rvv.c create mode 100644 3rdparty/zlib-ng/arch/riscv/chunkset_rvv.c create mode 100644 3rdparty/zlib-ng/arch/riscv/compare256_rvv.c create mode 100644 3rdparty/zlib-ng/arch/riscv/riscv_features.c create mode 100644 3rdparty/zlib-ng/arch/riscv/riscv_features.h create mode 100644 3rdparty/zlib-ng/arch/riscv/slide_hash_rvv.c create mode 100644 3rdparty/zlib-ng/arch/x86/Makefile.in create mode 100644 3rdparty/zlib-ng/arch/x86/adler32_avx2.c create mode 100644 3rdparty/zlib-ng/arch/x86/adler32_avx2_p.h create mode 100644 3rdparty/zlib-ng/arch/x86/adler32_avx512.c create mode 100644 3rdparty/zlib-ng/arch/x86/adler32_avx512_p.h create mode 100644 3rdparty/zlib-ng/arch/x86/adler32_avx512_vnni.c create mode 100644 3rdparty/zlib-ng/arch/x86/adler32_sse42.c create mode 100644 3rdparty/zlib-ng/arch/x86/adler32_ssse3.c create mode 100644 3rdparty/zlib-ng/arch/x86/adler32_ssse3_p.h create mode 100644 3rdparty/zlib-ng/arch/x86/chunkset_avx2.c create mode 100644 3rdparty/zlib-ng/arch/x86/chunkset_sse2.c create mode 100644 3rdparty/zlib-ng/arch/x86/chunkset_ssse3.c create mode 100644 3rdparty/zlib-ng/arch/x86/compare256_avx2.c create mode 100644 3rdparty/zlib-ng/arch/x86/compare256_sse2.c create mode 100644 3rdparty/zlib-ng/arch/x86/crc32_fold_pclmulqdq_tpl.h create mode 100644 3rdparty/zlib-ng/arch/x86/crc32_fold_vpclmulqdq_tpl.h create mode 100644 3rdparty/zlib-ng/arch/x86/crc32_pclmulqdq.c create mode 100644 3rdparty/zlib-ng/arch/x86/crc32_pclmulqdq_tpl.h create mode 100644 3rdparty/zlib-ng/arch/x86/crc32_vpclmulqdq.c create mode 100644 3rdparty/zlib-ng/arch/x86/insert_string_sse42.c create mode 100644 3rdparty/zlib-ng/arch/x86/slide_hash_avx2.c create mode 100644 3rdparty/zlib-ng/arch/x86/slide_hash_sse2.c create mode 100644 3rdparty/zlib-ng/arch/x86/x86_features.c create mode 100644 3rdparty/zlib-ng/arch/x86/x86_features.h create mode 100644 3rdparty/zlib-ng/arch/x86/x86_intrins.h create mode 100644 3rdparty/zlib-ng/chunkset.c create mode 100644 3rdparty/zlib-ng/chunkset_tpl.h create mode 100644 3rdparty/zlib-ng/cmake/detect-intrinsics.cmake create mode 100644 3rdparty/zlib-ng/cmake/fallback-macros.cmake create mode 100644 3rdparty/zlib-ng/compare256.c create mode 100644 3rdparty/zlib-ng/compare256_rle.h create mode 100644 3rdparty/zlib-ng/compress.c create mode 100644 3rdparty/zlib-ng/cpu_features.c create mode 100644 3rdparty/zlib-ng/cpu_features.h create mode 100644 3rdparty/zlib-ng/crc32_braid.c create mode 100644 3rdparty/zlib-ng/crc32_braid_comb.c create mode 100644 3rdparty/zlib-ng/crc32_braid_comb_p.h create mode 100644 3rdparty/zlib-ng/crc32_braid_p.h create mode 100644 3rdparty/zlib-ng/crc32_braid_tbl.h create mode 100644 3rdparty/zlib-ng/crc32_fold.c create mode 100644 3rdparty/zlib-ng/crc32_fold.h create mode 100644 3rdparty/zlib-ng/deflate.c create mode 100644 3rdparty/zlib-ng/deflate.h create mode 100644 3rdparty/zlib-ng/deflate_fast.c create mode 100644 3rdparty/zlib-ng/deflate_huff.c create mode 100644 3rdparty/zlib-ng/deflate_medium.c create mode 100644 3rdparty/zlib-ng/deflate_p.h create mode 100644 3rdparty/zlib-ng/deflate_quick.c create mode 100644 3rdparty/zlib-ng/deflate_rle.c create mode 100644 3rdparty/zlib-ng/deflate_slow.c create mode 100644 3rdparty/zlib-ng/deflate_stored.c create mode 100644 3rdparty/zlib-ng/fallback_builtins.h create mode 100644 3rdparty/zlib-ng/functable.c create mode 100644 3rdparty/zlib-ng/functable.h create mode 100644 3rdparty/zlib-ng/gzguts.h create mode 100644 3rdparty/zlib-ng/gzlib.c create mode 100644 3rdparty/zlib-ng/gzread.c.in create mode 100644 3rdparty/zlib-ng/gzwrite.c create mode 100644 3rdparty/zlib-ng/infback.c create mode 100644 3rdparty/zlib-ng/inffast_tpl.h create mode 100644 3rdparty/zlib-ng/inffixed_tbl.h create mode 100644 3rdparty/zlib-ng/inflate.c create mode 100644 3rdparty/zlib-ng/inflate.h create mode 100644 3rdparty/zlib-ng/inflate_p.h create mode 100644 3rdparty/zlib-ng/inftrees.c create mode 100644 3rdparty/zlib-ng/inftrees.h create mode 100644 3rdparty/zlib-ng/insert_string.c create mode 100644 3rdparty/zlib-ng/insert_string_roll.c create mode 100644 3rdparty/zlib-ng/insert_string_tpl.h create mode 100644 3rdparty/zlib-ng/match_tpl.h create mode 100644 3rdparty/zlib-ng/slide_hash.c create mode 100644 3rdparty/zlib-ng/trees.c create mode 100644 3rdparty/zlib-ng/trees.h create mode 100644 3rdparty/zlib-ng/trees_emit.h create mode 100644 3rdparty/zlib-ng/trees_tbl.h create mode 100644 3rdparty/zlib-ng/uncompr.c create mode 100644 3rdparty/zlib-ng/zbuild.h create mode 100644 3rdparty/zlib-ng/zconf.h.in create mode 100644 3rdparty/zlib-ng/zendian.h create mode 100644 3rdparty/zlib-ng/zlib.h.in create mode 100644 3rdparty/zlib-ng/zlib_name_mangling.h.empty create mode 100644 3rdparty/zlib-ng/zutil.c create mode 100644 3rdparty/zlib-ng/zutil.h create mode 100644 3rdparty/zlib-ng/zutil_p.h diff --git a/3rdparty/readme.txt b/3rdparty/readme.txt index 02875ece2839..4ef1966f7a4c 100644 --- a/3rdparty/readme.txt +++ b/3rdparty/readme.txt @@ -49,6 +49,14 @@ zlib General purpose LZ77 compression library Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler. See zlib home page http://www.zlib.net for details and links to the source code + +zlib-ng zlib data compression library for the next generation systems + (C) 1995-2013 Jean-loup Gailly and Mark Adler + See zlib-ng official GitHub repository + https://github.com/zlib-ng/zlib-ng.git + for details and links to source code + + WITH_ZLIB_NG CMake option must be ON to use zlib-ng as the zlib implementation. ------------------------------------------------------------------------------------ jasper JasPer is a collection of software (i.e., a library and application programs) for the coding diff --git a/3rdparty/zlib-ng/CMakeLists.txt b/3rdparty/zlib-ng/CMakeLists.txt new file mode 100644 index 000000000000..c05511ca8718 --- /dev/null +++ b/3rdparty/zlib-ng/CMakeLists.txt @@ -0,0 +1,796 @@ +project(${ZLIB_LIBRARY} LANGUAGES C) + +if("c_std_11" IN_LIST CMAKE_C_COMPILE_FEATURES) + set(CMAKE_C_STANDARD 11) # The C standard whose features are requested to build this target +else() + set(CMAKE_C_STANDARD 99) +endif() +set(CMAKE_C_STANDARD_REQUIRED ON) # Boolean describing whether the value of C_STANDARD is a requirement +set(CMAKE_C_EXTENSIONS OFF) # Boolean specifying whether compiler specific extensions are requested + +include(CheckTypeSize) +include(CheckSymbolExists) +include(CheckFunctionExists) +include(CheckIncludeFile) +include(CheckCSourceCompiles) +include(CheckCSourceRuns) +include(CheckCCompilerFlag) +include(CMakeDependentOption) + +if(X86_64 OR X86) + set(BASEARCH_X86_FOUND TRUE) +endif() +if(AARCH64 OR ARM) + set(BASEARCH_ARM_FOUND TRUE) +endif() +if(PPC64LE OR PPC64) + set(BASEARCH_PPC_FOUND TRUE) +endif() +if(RISCV) + set(BASEARCH_RISCV_FOUND TRUE) +endif() + +include(cmake/detect-intrinsics.cmake) +include(cmake/fallback-macros.cmake) + +set(ZLIB_SYMBOL_PREFIX "") + +if(BASEARCH_X86_FOUND) + set(WITH_AVX2 ON) + set(WITH_AVX512 ON) + set(WITH_AVX512VNNI ON) + set(WITH_SSE2 ON) + set(WITH_SSSE3 ON) + set(WITH_SSE42 ON) + set(WITH_PCLMULQDQ ON) + set(WITH_VPCLMULQDQ ON) +endif() +if(BASEARCH_ARM_FOUND) + set(WITH_ACLE ON) + set(WITH_NEON ON) + if(ARM) + set(WITH_ARMV6 ON) + else() + set(WITH_ARMV6 OFF) + endif() +endif() +if(BASEARCH_PPC_FOUND) + set(WITH_ALTIVEC ON) + set(WITH_POWER8 ON) + set(WITH_POWER9 ON) +endif() +if(BASEARCH_RISCV_FOUND) + set(WITH_RVV ON) +endif() + + +add_definitions(-DZLIB_COMPAT) + +add_definitions(-DWITH_GZFILEOP) + +if(CMAKE_C_COMPILER_ID MATCHES "^Intel") + set(WARNFLAGS_DISABLE) +elseif(MSVC) + # Minimum supported MSVC version is 1800 = Visual Studio 12.0/2013 + # See also https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html + if(MSVC_VERSION VERSION_LESS 1800) + message(SEND_ERROR "Unsupported Visual Studio compiler version (requires 2013 or later).") + endif() + # TODO. ICC can be used through MSVC. I'm not sure if we'd ever see that combination + # (who'd use cmake from an IDE...) but checking for ICC before checking for MSVC should + # avoid mistakes. + # /Oi ? + set(WARNFLAGS_DISABLE) + if(BASEARCH_ARM_FOUND) + add_definitions(-D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE) + if(NOT "${ARCH}" MATCHES "aarch64") + set(NEONFLAG "/arch:VFPv4") + endif() + endif() +elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + set(WARNFLAGS_DISABLE) + # Check whether -fno-lto is available + set(CMAKE_REQUIRED_FLAGS "-fno-lto") + check_c_source_compiles( + "int main() { return 0; }" + FNO_LTO_AVAILABLE FAIL_REGEX "not supported") + set(CMAKE_REQUIRED_FLAGS) + if(FNO_LTO_AVAILABLE) + set(ZNOLTOFLAG "-fno-lto") + endif() + if(BASEARCH_ARM_FOUND) + if(ARM AND NOT CMAKE_C_FLAGS MATCHES "-mfloat-abi") + # Auto-detect support for ARM floating point ABI + check_include_file(features.h HAVE_FEATURES_H) + if(HAVE_FEATURES_H) + set(CMAKE_REQUIRED_FLAGS -mfloat-abi=softfp) + check_c_source_compiles( + "#include + int main() { return 0; }" + HAVE_FLOATABI_SOFTFP) + if(HAVE_FLOATABI_SOFTFP) + set(FLOATABI -mfloat-abi=softfp) + else() + set(CMAKE_REQUIRED_FLAGS -mfloat-abi=hard) + check_c_source_compiles( + "#include + int main() { return 0; }" + HAVE_FLOATABI_HARD) + if(HAVE_FLOATABI_HARD) + set(FLOATABI -mfloat-abi=hard) + endif() + endif() + set(CMAKE_REQUIRED_FLAGS) + endif() + if(FLOATABI) + message(STATUS "${ZLIB_LIBRARY} ARM floating point arch: ${FLOATABI}") + add_compile_options(${FLOATABI}) + else() + message(STATUS "${ZLIB_LIBRARY} ARM floating point arch not auto-detected") + endif() + endif() + endif() + if(FNO_LTO_AVAILABLE) + set(NOLTOFLAG ${ZNOLTOFLAG}) + endif() + if(MINGW) + # Add `-Wno-pedantic-ms-format` only if the toolchain supports it + check_c_compiler_flag(-Wno-pedantic-ms-format HAVE_NO_PEDANTIC_MS_FORMAT) + if(HAVE_NO_PEDANTIC_MS_FORMAT) + list(APPEND WARNFLAGS_DISABLE -Wno-pedantic-ms-format) + endif() + endif() +endif() + +# Force disable LTO +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF) + +# Apply warning compiler flags +add_compile_options(${WARNFLAGS_DISABLE}) + +# Replace optimization level 3 added by default with level 2 +if(NOT MSVC AND NOT CMAKE_C_FLAGS MATCHES "([\\/\\-]O)3") + string(REGEX REPLACE "([\\/\\-]O)3" "\\12" + CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") +endif() + +# +# Check for standard/system includes +# +check_include_file(arm_acle.h HAVE_ARM_ACLE_H) +if(HAVE_ARM_ACLE_H) + add_definitions(-DHAVE_ARM_ACLE_H) +endif() +check_include_file(sys/auxv.h HAVE_SYS_AUXV_H) +if(HAVE_SYS_AUXV_H) + add_definitions(-DHAVE_SYS_AUXV_H) +endif() +check_include_file(sys/sdt.h HAVE_SYS_SDT_H) +if(HAVE_SYS_SDT_H) + add_definitions(-DHAVE_SYS_SDT_H) +endif() +check_include_file(unistd.h HAVE_UNISTD_H) + +# +# Check to see if we have large file support +# +set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64) +check_type_size(off64_t OFF64_T) +if(HAVE_OFF64_T) + add_definitions(-D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64) +else() + check_type_size(_off64_t _OFF64_T) + if(HAVE__OFF64_T) + add_definitions(-D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64) + else() + check_type_size(__off64_t __OFF64_T) + endif() +endif() +set(CMAKE_REQUIRED_DEFINITIONS) # clear variable + +# +# Check for fseeko and other optional functions +# +check_function_exists(fseeko HAVE_FSEEKO) +if(NOT HAVE_FSEEKO) + add_definitions(-DNO_FSEEKO) +endif() + +check_function_exists(strerror HAVE_STRERROR) +if(NOT HAVE_STRERROR) + add_definitions(-DNO_STRERROR) +endif() + +set(CMAKE_REQUIRED_DEFINITIONS -D_POSIX_C_SOURCE=200112L) +check_symbol_exists(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN) +if(HAVE_POSIX_MEMALIGN) + add_definitions(-DHAVE_POSIX_MEMALIGN) +endif() +set(CMAKE_REQUIRED_DEFINITIONS) + +set(CMAKE_REQUIRED_DEFINITIONS -D_ISOC11_SOURCE=1) +check_symbol_exists(aligned_alloc stdlib.h HAVE_ALIGNED_ALLOC) +if(HAVE_ALIGNED_ALLOC) + add_definitions(-DHAVE_ALIGNED_ALLOC) +endif() +set(CMAKE_REQUIRED_DEFINITIONS) + +# +# Check if we can hide zlib internal symbols that are linked between separate source files using hidden +# +check_c_source_compiles( + "#define Z_INTERNAL __attribute__((visibility (\"hidden\"))) + int Z_INTERNAL foo; + int main() { + return 0; + }" + HAVE_ATTRIBUTE_VISIBILITY_HIDDEN FAIL_REGEX "visibility") +if(HAVE_ATTRIBUTE_VISIBILITY_HIDDEN) + add_definitions(-DHAVE_VISIBILITY_HIDDEN) +endif() + +# +# Check if we can hide zlib internal symbols that are linked between separate source files using internal +# +check_c_source_compiles( + "#define Z_INTERNAL __attribute__((visibility (\"internal\"))) + int Z_INTERNAL foo; + int main() { + return 0; + }" + HAVE_ATTRIBUTE_VISIBILITY_INTERNAL FAIL_REGEX "visibility") +if(HAVE_ATTRIBUTE_VISIBILITY_INTERNAL) + add_definitions(-DHAVE_VISIBILITY_INTERNAL) +endif() + +# +# Check for __attribute__((aligned(x))) support in the compiler +# +check_c_source_compiles( + "int main(void) { + __attribute__((aligned(8))) int test = 0; + (void)test; + return 0; + }" + HAVE_ATTRIBUTE_ALIGNED FAIL_REGEX "aligned") +if(HAVE_ATTRIBUTE_ALIGNED) + add_definitions(-DHAVE_ATTRIBUTE_ALIGNED) +endif() + +# +# check for __builtin_ctz() support in the compiler +# +check_c_source_compiles( + "int main(void) { + unsigned int zero = 0; + long test = __builtin_ctz(zero); + (void)test; + return 0; + }" + HAVE_BUILTIN_CTZ +) +if(HAVE_BUILTIN_CTZ) + add_definitions(-DHAVE_BUILTIN_CTZ) +endif() + +# +# check for __builtin_ctzll() support in the compiler +# +check_c_source_compiles( + "int main(void) { + unsigned int zero = 0; + long test = __builtin_ctzll(zero); + (void)test; + return 0; + }" + HAVE_BUILTIN_CTZLL +) +if(HAVE_BUILTIN_CTZLL) + add_definitions(-DHAVE_BUILTIN_CTZLL) +endif() + +# +# check for ptrdiff_t support +# +check_c_source_compiles( + "#include + int main() { + ptrdiff_t *a; + (void)a; + return 0; + }" + HAVE_PTRDIFF_T +) +if(NOT HAVE_PTRDIFF_T) + set(NEED_PTRDIFF_T 1) + + check_type_size("void *" SIZEOF_DATA_PTR) + message(STATUS "sizeof(void *) is ${SIZEOF_DATA_PTR} bytes") + + if(${SIZEOF_DATA_PTR} MATCHES "4") + set(PTRDIFF_TYPE "uint32_t") + elseif(${SIZEOF_DATA_PTR} MATCHES "8") + set(PTRDIFF_TYPE "uint64_t") + else() + message(FATAL_ERROR "sizeof(void *) is neither 32 nor 64 bit") + endif() +endif() + +if(MSVC) + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) +endif() + +set(ZLIB_ARCH_SRCS) +set(ZLIB_ARCH_HDRS) +set(ARCHDIR "arch/generic") +if(BASEARCH_X86_FOUND) + set(ARCHDIR "arch/x86") +endif() +if(BASEARCH_ARM_FOUND) + set(ARCHDIR "arch/arm") +endif() +if(BASEARCH_PPC_FOUND) + set(ARCHDIR "arch/power") +endif() +if(BASEARCH_RISCV_FOUND) + set(ARCHDIR "arch/riscv") +endif() + +if(NOT CV_DISABLE_OPTIMIZATION) + if(BASEARCH_ARM_FOUND) + add_definitions(-DARM_FEATURES) + if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + if("${ARCH}" MATCHES "aarch64") + check_c_source_compiles( + "#include + int main() { + return (getauxval(AT_HWCAP) & HWCAP_CRC32); + }" + ARM_AUXV_HAS_CRC32 + ) + if(ARM_AUXV_HAS_CRC32) + add_definitions(-DARM_AUXV_HAS_CRC32) + else() + message(STATUS "HWCAP_CRC32 not present in sys/auxv.h; cannot detect support at runtime.") + endif() + else() + check_c_source_compiles( + "#include + int main() { + return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); + }" + ARM_AUXV_HAS_CRC32 + ) + if(ARM_AUXV_HAS_CRC32) + add_definitions(-DARM_AUXV_HAS_CRC32) + else() + check_c_source_compiles( + "#include + #include + int main() { + return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); + }" + ARM_HWCAP_HAS_CRC32 + ) + if(ARM_HWCAP_HAS_CRC32) + add_definitions(-DARM_AUXV_HAS_CRC32 -DARM_ASM_HWCAP) + else() + message(STATUS "HWCAP2_CRC32 not present in sys/auxv.h; cannot detect support at runtime.") + endif() + endif() + check_c_source_compiles( + "#include + int main() { + return (getauxval(AT_HWCAP) & HWCAP_ARM_NEON); + }" + ARM_AUXV_HAS_NEON + ) + if(ARM_AUXV_HAS_NEON) + add_definitions(-DARM_AUXV_HAS_NEON) + else() + check_c_source_compiles( + "#include + int main() { + return (getauxval(AT_HWCAP) & HWCAP_NEON); + }" + ARM_AUXV_HAS_NEON + ) + if (ARM_AUXV_HAS_NEON) + add_definitions(-DARM_AUXV_HAS_NEON) + else() + message(STATUS "Neither HWCAP_ARM_NEON or HWCAP_NEON present in sys/auxv.h; cannot detect support at runtime.") + endif() + endif() + endif() + endif() + list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/arm_features.h) + list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/arm_features.c) + if(WITH_ACLE) + check_acle_compiler_flag() + if(HAVE_ACLE_FLAG) + add_definitions(-DARM_ACLE) + set(ACLE_SRCS ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c) + set_property(SOURCE ${ACLE_SRCS} PROPERTY COMPILE_FLAGS "${ACLEFLAG} ${NOLTOFLAG}") + list(APPEND ZLIB_ARCH_SRCS ${ACLE_SRCS}) + else() + set(WITH_ACLE OFF) + endif() + else() + set(WITH_ACLE OFF) + endif() + if(WITH_NEON) + check_neon_compiler_flag() + if(NEON_AVAILABLE) + add_definitions(-DARM_NEON) + set(NEON_SRCS ${ARCHDIR}/adler32_neon.c ${ARCHDIR}/chunkset_neon.c + ${ARCHDIR}/compare256_neon.c ${ARCHDIR}/slide_hash_neon.c) + list(APPEND ZLIB_ARCH_SRCS ${NEON_SRCS}) + set_property(SOURCE ${NEON_SRCS} PROPERTY COMPILE_FLAGS "${NEONFLAG} ${NOLTOFLAG}") + if(MSVC) + add_definitions(-D__ARM_NEON__) + endif() + check_neon_ld4_intrinsics() + if(NEON_HAS_LD4) + add_definitions(-DARM_NEON_HASLD4) + endif() + else() + set(WITH_NEON OFF) + endif() + endif() + if(WITH_ARMV6) + check_armv6_compiler_flag() + if(HAVE_ARMV6_INLINE_ASM OR HAVE_ARMV6_INTRIN) + add_definitions(-DARM_SIMD) + set(ARMV6_SRCS ${ARCHDIR}/slide_hash_armv6.c) + set_property(SOURCE ${ARMV6_SRCS} PROPERTY COMPILE_FLAGS "${ARMV6FLAG} ${NOLTOFLAG}") + list(APPEND ZLIB_ARCH_SRCS ${ARMV6_SRCS}) + if(HAVE_ARMV6_INTRIN) + add_definitions(-DARM_SIMD_INTRIN) + endif() + else() + set(WITH_ARMV6 OFF) + endif() + else() + set(WITH_ARMV6 OFF) + endif() + endif() + if(BASEARCH_PPC_FOUND) + # Common arch detection code + if(WITH_ALTIVEC) + check_ppc_intrinsics() + endif() + if(WITH_POWER8) + check_power8_intrinsics() + endif() + if(WITH_POWER9) + check_power9_intrinsics() + endif() + if(HAVE_VMX OR HAVE_POWER8_INTRIN OR HAVE_POWER9_INTRIN) + add_definitions(-DPOWER_FEATURES) + list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/power_features.h) + list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/power_features.c) + endif() + # VMX specific options and files + if(WITH_ALTIVEC) + if(HAVE_VMX) + add_definitions(-DPPC_FEATURES) + if(HAVE_ALTIVEC) + add_definitions(-DPPC_VMX) + set(PPC_SRCS ${ARCHDIR}/adler32_vmx.c ${ARCHDIR}/slide_hash_vmx.c) + list(APPEND ZLIB_ARCH_SRCS ${PPC_SRCS}) + set_property(SOURCE ${PPC_SRCS} PROPERTY COMPILE_FLAGS "${PPCFLAGS}") + else() + set(WITH_ALTIVEC OFF) + endif() + endif() + endif() + # Power8 specific options and files + if(WITH_POWER8) + if(HAVE_POWER8_INTRIN) + add_definitions(-DPOWER8_VSX) + set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/chunkset_power8.c ${ARCHDIR}/slide_hash_power8.c) + if("${ARCH}" MATCHES "powerpc64(le)?") + add_definitions(-DPOWER8_VSX_CRC32) + list(APPEND POWER8_SRCS ${ARCHDIR}/crc32_power8.c) + endif() + list(APPEND ZLIB_ARCH_SRCS ${POWER8_SRCS}) + set_property(SOURCE ${POWER8_SRCS} PROPERTY COMPILE_FLAGS "${POWER8FLAG} ${NOLTOFLAG}") + else() + set(WITH_POWER8 OFF) + endif() + endif() + # Power9 specific options and files + if(WITH_POWER9) + if(HAVE_POWER9_INTRIN) + add_definitions(-DPOWER9) + set(POWER9_SRCS ${ARCHDIR}/compare256_power9.c) + list(APPEND ZLIB_ARCH_SRCS ${POWER9_SRCS}) + set_property(SOURCE ${POWER9_SRCS} PROPERTY COMPILE_FLAGS "${POWER9FLAG} ${NOLTOFLAG}") + else() + set(WITH_POWER9 OFF) + endif() + endif() + endif() + if(BASEARCH_RISCV_FOUND) + if(WITH_RVV) + check_rvv_intrinsics() + if(HAVE_RVV_INTRIN) + add_definitions(-DRISCV_FEATURES) + add_definitions(-DRISCV_RVV) + list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/riscv_features.h) + list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/riscv_features.c) + # FIXME: we will not set compile flags for riscv_features.c when + # the kernels update hwcap or hwprobe for riscv + set(RVV_SRCS ${ARCHDIR}/riscv_features.c ${ARCHDIR}/adler32_rvv.c ${ARCHDIR}/chunkset_rvv.c ${ARCHDIR}/compare256_rvv.c ${ARCHDIR}/slide_hash_rvv.c) + list(APPEND ZLIB_ARCH_SRCS ${RVV_SRCS}) + set_property(SOURCE ${RVV_SRCS} PROPERTY COMPILE_FLAGS "${RISCVFLAG} ${NOLTOFLAG}") + else() + set(WITH_RVV OFF) + endif() + endif() + endif() + if(BASEARCH_X86_FOUND) + add_definitions(-DX86_FEATURES) + list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/x86_features.h) + list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/x86_features.c) + if(MSVC) + list(APPEND ZLIB_ARCH_HDRS fallback_builtins.h) + endif() + if(WITH_AVX2) + check_avx2_intrinsics() + if(HAVE_AVX2_INTRIN) + add_definitions(-DX86_AVX2) + set(AVX2_SRCS ${ARCHDIR}/slide_hash_avx2.c) + list(APPEND AVX2_SRCS ${ARCHDIR}/chunkset_avx2.c) + list(APPEND AVX2_SRCS ${ARCHDIR}/compare256_avx2.c) + list(APPEND AVX2_SRCS ${ARCHDIR}/adler32_avx2.c) + list(APPEND ZLIB_ARCH_SRCS ${AVX2_SRCS}) + set_property(SOURCE ${AVX2_SRCS} PROPERTY COMPILE_FLAGS "${AVX2FLAG} ${NOLTOFLAG}") + else() + set(WITH_AVX2 OFF) + endif() + endif() + if(WITH_AVX512) + check_avx512_intrinsics() + if(HAVE_AVX512_INTRIN) + add_definitions(-DX86_AVX512) + list(APPEND AVX512_SRCS ${ARCHDIR}/adler32_avx512.c) + list(APPEND ZLIB_ARCH_SRCS ${AVX512_SRCS}) + list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/adler32_avx512_p.h) + if(HAVE_MASK_INTRIN) + add_definitions(-DX86_MASK_INTRIN) + endif() + set_property(SOURCE ${AVX512_SRCS} PROPERTY COMPILE_FLAGS "${AVX512FLAG} ${NOLTOFLAG}") + else() + set(WITH_AVX512 OFF) + endif() + endif() + if(WITH_AVX512VNNI) + check_avx512vnni_intrinsics() + if(HAVE_AVX512VNNI_INTRIN) + add_definitions(-DX86_AVX512VNNI) + list(APPEND AVX512VNNI_SRCS ${ARCHDIR}/adler32_avx512_vnni.c) + list(APPEND ZLIB_ARCH_SRCS ${AVX512VNNI_SRCS}) + set_property(SOURCE ${AVX512VNNI_SRCS} PROPERTY COMPILE_FLAGS "${AVX512VNNIFLAG} ${NOLTOFLAG}") + else() + set(WITH_AVX512VNNI OFF) + endif() + endif() + if(WITH_SSE42) + check_sse42_intrinsics() + if(HAVE_SSE42_INTRIN) + add_definitions(-DX86_SSE42) + set(SSE42_SRCS ${ARCHDIR}/adler32_sse42.c ${ARCHDIR}/insert_string_sse42.c) + list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) + set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE42FLAG} ${NOLTOFLAG}") + else() + set(WITH_SSE42 OFF) + endif() + endif() + if(WITH_SSE2) + check_sse2_intrinsics() + if(HAVE_SSE2_INTRIN) + add_definitions(-DX86_SSE2) + set(SSE2_SRCS ${ARCHDIR}/chunkset_sse2.c ${ARCHDIR}/compare256_sse2.c ${ARCHDIR}/slide_hash_sse2.c) + list(APPEND ZLIB_ARCH_SRCS ${SSE2_SRCS}) + if(NOT ${ARCH} MATCHES "x86_64") + set_property(SOURCE ${SSE2_SRCS} PROPERTY COMPILE_FLAGS "${SSE2FLAG} ${NOLTOFLAG}") + add_definitions(-DX86_NOCHECK_SSE2) + endif() + else() + set(WITH_SSE2 OFF) + endif() + endif() + if(WITH_SSSE3) + check_ssse3_intrinsics() + if(HAVE_SSSE3_INTRIN) + add_definitions(-DX86_SSSE3) + set(SSSE3_SRCS ${ARCHDIR}/adler32_ssse3.c ${ARCHDIR}/chunkset_ssse3.c) + list(APPEND ZLIB_ARCH_SRCS ${SSSE3_SRCS}) + set_property(SOURCE ${SSSE3_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${NOLTOFLAG}") + else() + set(WITH_SSSE3 OFF) + endif() + endif() + if(WITH_PCLMULQDQ AND WITH_SSSE3 AND WITH_SSE42) + check_pclmulqdq_intrinsics() + if(HAVE_PCLMULQDQ_INTRIN AND HAVE_SSSE3_INTRIN) + add_definitions(-DX86_PCLMULQDQ_CRC) + set(PCLMULQDQ_SRCS ${ARCHDIR}/crc32_pclmulqdq.c) + list(APPEND ZLIB_ARCH_SRCS ${PCLMULQDQ_SRCS}) + set_property(SOURCE ${PCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${SSE42FLAG} ${PCLMULFLAG} ${NOLTOFLAG}") + + if(WITH_VPCLMULQDQ AND WITH_AVX512) + check_vpclmulqdq_intrinsics() + if(HAVE_VPCLMULQDQ_INTRIN AND HAVE_AVX512_INTRIN) + add_definitions(-DX86_VPCLMULQDQ_CRC) + set(VPCLMULQDQ_SRCS ${ARCHDIR}/crc32_vpclmulqdq.c) + list(APPEND ZLIB_ARCH_SRCS ${VPCLMULQDQ_SRCS}) + set_property(SOURCE ${VPCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${SSE42FLAG} ${PCLMULFLAG} ${VPCLMULFLAG} ${AVX512FLAG} ${NOLTOFLAG}") + else() + set(WITH_VPCLMULQDQ OFF) + endif() + else() + set(WITH_VPCLMULQDQ OFF) + endif() + else() + set(WITH_PCLMULQDQ OFF) + set(WITH_VPCLMULQDQ OFF) + endif() + else() + set(WITH_PCLMULQDQ OFF) + set(WITH_VPCLMULQDQ OFF) + endif() + check_xsave_intrinsics() + if(HAVE_XSAVE_INTRIN) + set_property(SOURCE ${ARCHDIR}/x86_features.c PROPERTY COMPILE_FLAGS "${XSAVEFLAG}") + endif() + endif() +endif() + +#============================================================================ +# zconf.h +#============================================================================ + +macro(generate_cmakein input output) + file(REMOVE ${output}) + file(STRINGS ${input} _lines) + foreach(_line IN LISTS _lines) + string(REGEX REPLACE "#ifdef HAVE_UNISTD_H.*" "@ZCONF_UNISTD_LINE@" _line "${_line}") + string(REGEX REPLACE "#ifdef NEED_PTRDIFF_T.*" "@ZCONF_PTRDIFF_LINE@" _line "${_line}") + if(NEED_PTRDIFF_T) + string(REGEX REPLACE "typedef PTRDIFF_TYPE" "typedef @PTRDIFF_TYPE@" _line "${_line}") + endif() + file(APPEND ${output} "${_line}\n") + endforeach() +endmacro(generate_cmakein) + +generate_cmakein( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.in ${CMAKE_CURRENT_BINARY_DIR}/zconf.h.cmakein ) + +#============================================================================ +# zlib +#============================================================================ + +set(ZLIB_PUBLIC_HDRS + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h + ${CMAKE_CURRENT_BINARY_DIR}/zlib_name_mangling.h + ${CMAKE_CURRENT_BINARY_DIR}/zlib.h +) +set(ZLIB_PRIVATE_HDRS + adler32_p.h + chunkset_tpl.h + compare256_rle.h + cpu_features.h + crc32_braid_p.h + crc32_braid_comb_p.h + crc32_braid_tbl.h + crc32_fold.h + deflate.h + deflate_p.h + functable.h + inffast_tpl.h + inffixed_tbl.h + inflate.h + inflate_p.h + inftrees.h + insert_string_tpl.h + match_tpl.h + trees.h + trees_emit.h + trees_tbl.h + zbuild.h + zendian.h + zutil.h +) +set(ZLIB_SRCS + adler32.c + adler32_fold.c + chunkset.c + compare256.c + compress.c + cpu_features.c + crc32_braid.c + crc32_braid_comb.c + crc32_fold.c + deflate.c + deflate_fast.c + deflate_huff.c + deflate_medium.c + deflate_quick.c + deflate_rle.c + deflate_slow.c + deflate_stored.c + functable.c + infback.c + inflate.c + inftrees.c + insert_string.c + insert_string_roll.c + slide_hash.c + trees.c + uncompr.c + zutil.c +) + +set(ZLIB_GZFILE_PRIVATE_HDRS + gzguts.h +) +set(ZLIB_GZFILE_SRCS + gzlib.c + ${CMAKE_CURRENT_BINARY_DIR}/gzread.c + gzwrite.c +) + +set(ZLIB_ALL_SRCS ${ZLIB_SRCS} ${ZLIB_ARCH_HDRS} ${ZLIB_ARCH_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +list(APPEND ZLIB_ALL_SRCS ${ZLIB_GZFILE_PRIVATE_HDRS} ${ZLIB_GZFILE_SRCS}) + +add_library(zlib STATIC ${ZLIB_ALL_SRCS}) + +target_include_directories(zlib PUBLIC + "$" + "$") + +if(HAVE_UNISTD_H) + SET(ZCONF_UNISTD_LINE "#if 1 /* was set to #if 1 by configure/cmake/etc */") +else() + SET(ZCONF_UNISTD_LINE "#if 0 /* was set to #if 0 by configure/cmake/etc */") +endif() +if(NEED_PTRDIFF_T) + SET(ZCONF_PTRDIFF_LINE "#if 1 /* was set to #if 1 by configure/cmake/etc */") +else() + SET(ZCONF_PTRDIFF_LINE "#ifdef NEED_PTRDIFF_T /* may be set to #if 1 by configure/cmake/etc */") +endif() + +configure_file(${CMAKE_CURRENT_BINARY_DIR}/zconf.h.cmakein + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zlib.h.in + ${CMAKE_CURRENT_BINARY_DIR}/zlib.h @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gzread.c.in + ${CMAKE_CURRENT_BINARY_DIR}/gzread.c @ONLY) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zlib_name_mangling.h.empty + ${CMAKE_CURRENT_BINARY_DIR}/zlib_name_mangling${SUFFIX}.h COPYONLY) + +ocv_warnings_disable(CMAKE_C_FLAGS -Wmissing-prototypes + -Wundef + -Wmissing-declarations +) + +set_target_properties(${ZLIB_LIBRARY} PROPERTIES + OUTPUT_NAME ${ZLIB_LIBRARY} + DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" + COMPILE_PDB_NAME ${ZLIB_LIBRARY} + COMPILE_PDB_NAME_DEBUG "${ZLIB_LIBRARY}${OPENCV_DEBUG_POSTFIX}" + ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH} +) + +if(ENABLE_SOLUTION_FOLDERS) + set_target_properties(${ZLIB_LIBRARY} PROPERTIES FOLDER "3rdparty") +endif() + +if(NOT BUILD_SHARED_LIBS) + ocv_install_target(${ZLIB_LIBRARY} EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) +endif() + +ocv_install_3rdparty_licenses(${ZLIB_LIBRARY} LICENSE.md) diff --git a/3rdparty/zlib-ng/LICENSE.md b/3rdparty/zlib-ng/LICENSE.md new file mode 100644 index 000000000000..adb48d47296b --- /dev/null +++ b/3rdparty/zlib-ng/LICENSE.md @@ -0,0 +1,19 @@ +(C) 1995-2013 Jean-loup Gailly and Mark Adler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution. diff --git a/3rdparty/zlib-ng/README.md b/3rdparty/zlib-ng/README.md new file mode 100644 index 000000000000..4f9fe09c6911 --- /dev/null +++ b/3rdparty/zlib-ng/README.md @@ -0,0 +1,229 @@ +| CI | Stable | Develop | +|:---|:-------|:--------| +| GitHub Actions | [![Stable CMake](https://github.com/zlib-ng/zlib-ng/actions/workflows/cmake.yml/badge.svg?branch=stable)](https://github.com/zlib-ng/zlib-ng/actions/workflows/cmake.yml?query=branch%3Astable)
[![Stable Configure](https://github.com/zlib-ng/zlib-ng/actions/workflows/configure.yml/badge.svg?branch=stable)](https://github.com/zlib-ng/zlib-ng/actions/workflows/configure.yml?query=branch%3Astable)
[![Stable NMake](https://github.com/zlib-ng/zlib-ng/actions/workflows/nmake.yml/badge.svg?branch=stable)](https://github.com/zlib-ng/zlib-ng/actions/workflows/nmake.yml?query=branch%3Astable) | [![Develop CMake](https://github.com/zlib-ng/zlib-ng/actions/workflows/cmake.yml/badge.svg?branch=develop)](https://github.com/zlib-ng/zlib-ng/actions/workflows/cmake.yml?query=branch%3Adevelop)
[![Develop Configure](https://github.com/zlib-ng/zlib-ng/actions/workflows/configure.yml/badge.svg?branch=develop)](https://github.com/zlib-ng/zlib-ng/actions/workflows/configure.yml?query=branch%3Adevelop)
[![Develop NMake](https://github.com/zlib-ng/zlib-ng/actions/workflows/nmake.yml/badge.svg?branch=develop)](https://github.com/zlib-ng/zlib-ng/actions/workflows/nmake.yml?query=branch%3Adevelop) | +| CodeFactor | [![CodeFactor](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng/badge/stable)](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng/overview/stable) | [![CodeFactor](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng/badge/develop)](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng/overview/develop) | +| OSS-Fuzz | [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/zlib-ng.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:zlib-ng) | [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/zlib-ng.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:zlib-ng) | +| Codecov | [![codecov](https://codecov.io/github/zlib-ng/zlib-ng/branch/stable/graph/badge.svg?token=uKsgK9LIuC)](https://codecov.io/github/zlib-ng/zlib-ng/tree/stable) | [![codecov](https://codecov.io/github/zlib-ng/zlib-ng/branch/develop/graph/badge.svg?token=uKsgK9LIuC)](https://codecov.io/github/zlib-ng/zlib-ng/tree/develop) | + +## zlib-ng +*zlib data compression library for the next generation systems* + +Maintained by Hans Kristian Rosbach + aka Dead2 (zlib-ng àt circlestorm dót org) + +Features +-------- + +* Zlib compatible API with support for dual-linking +* Modernized native API based on zlib API for ease of porting +* Modern C11 syntax and a clean code layout +* Deflate medium and quick algorithms based on Intel’s zlib fork +* Support for CPU intrinsics when available + * Adler32 implementation using SSSE3, AVX2, AVX512, AVX512-VNNI, Neon, VMX & VSX + * CRC32-B implementation using PCLMULQDQ, VPCLMULQDQ, ACLE, & IBM Z + * Hash table implementation using CRC32-C intrinsics on x86 and ARM + * Slide hash implementations using SSE2, AVX2, ARMv6, Neon, VMX & VSX + * Compare256 implementations using SSE2, AVX2, Neon, POWER9 & RVV + * Inflate chunk copying using SSE2, SSSE3, AVX, Neon & VSX + * Support for hardware-accelerated deflate using IBM Z DFLTCC +* Unaligned memory read/writes and large bit buffer improvements +* Includes improvements from Cloudflare and Intel forks +* Configure, CMake, and NMake build system support +* Comprehensive set of CMake unit tests +* Code sanitizers, fuzzing, and coverage +* GitHub Actions continuous integration on Windows, macOS, and Linux + * Emulated CI for ARM, AARCH64, PPC, PPC64, RISCV, SPARC64, S390x using qemu + + +History +------- + +The motivation for this fork was seeing several 3rd party contributions with new optimizations not getting +implemented into the official zlib repository. + +Mark Adler has been maintaining zlib for a very long time, and he has done a great job and hopefully he will continue +for a long time yet. The idea of zlib-ng is not to replace zlib, but to co-exist as a drop-in replacement with a +lower threshold for code change. + +zlib has a long history and is incredibly portable, even supporting many systems that predate the Internet.
+That is great, but it can complicate further development and maintainability. The zlib code contains many workarounds +for really old compilers or to accommodate systems with limitations such as operating in a 16-bit environment. + +Many of these workarounds are only maintenance burdens, some of them are pretty huge code-wise. With many workarounds +cluttered throughout the code, it makes it harder for new programmers with an idea/interest for zlib to contribute. + +I decided to make a fork, merge all the Intel optimizations, some of the Cloudflare optimizations, plus a couple other +smaller patches. Then started cleaning out workarounds, various dead code, all contrib and example code.
+The result is a better performing and easier to maintain zlib-ng. + +A lot of improvements have gone into zlib-ng since its start, and numerous people and companies have contributed both +small and big improvements, or valuable testing. + + +Build +----- +Please read LICENSE.md, it is very simple and very liberal. + +There are two ways to build zlib-ng: + +### Cmake + +To build zlib-ng using the cross-platform makefile generator cmake. + +``` +cmake . +cmake --build . --config Release +ctest --verbose -C Release +``` + +Alternatively, you can use the cmake configuration GUI tool ccmake: + +``` +ccmake . +``` + +### Configure + +To build zlib-ng using the bash configure script: + +``` +./configure +make +make test +``` + +Build Options +------------- + +| CMake | configure | Description | Default | +|:-------------------------|:-------------------------|:--------------------------------------------------------------------------------------|---------| +| ZLIB_COMPAT | --zlib-compat | Compile with zlib compatible API | OFF | +| ZLIB_ENABLE_TESTS | | Build test binaries | ON | +| WITH_GZFILEOP | --without-gzfileops | Compile with support for gzFile related functions | ON | +| WITH_OPTIM | --without-optimizations | Build with optimisations | ON | +| WITH_NEW_STRATEGIES | --without-new-strategies | Use new strategies | ON | +| WITH_NATIVE_INSTRUCTIONS | | Compiles with full instruction set supported on this host (gcc/clang -march=native) | OFF | +| WITH_SANITIZER | | Build with sanitizer (memory, address, undefined) | OFF | +| WITH_GTEST | | Build gtest_zlib | ON | +| WITH_FUZZERS | | Build test/fuzz | OFF | +| WITH_BENCHMARKS | | Build test/benchmarks | OFF | +| WITH_MAINTAINER_WARNINGS | | Build with project maintainer warnings | OFF | +| WITH_CODE_COVERAGE | | Enable code coverage reporting | OFF | + + +Install +------- + +WARNING: We do not recommend manually installing unless you really know what you are doing, because this can +potentially override the system default zlib library, and any incompatibility or wrong configuration of zlib-ng +can make the whole system unusable, requiring recovery or reinstall. +If you still want a manual install, we recommend using the /opt/ path prefix. + +For Linux distros, an alternative way to use zlib-ng (if compiled in zlib-compat mode) instead of zlib, is through +the use of the _LD_PRELOAD_ environment variable. If the program is dynamically linked with zlib, then the program +will temporarily attempt to use zlib-ng instead, without risking system-wide instability. + +``` +LD_PRELOAD=/opt/zlib-ng/libz.so.1.2.13.zlib-ng /usr/bin/program +``` + +### Cmake + +To install zlib-ng system-wide using cmake: + +```sh or powershell +cmake --build . --target install +``` + +### Configure + +To install zlib-ng system-wide using the configure script: + +```sh +make install +``` + +### CPack + +After building with cmake, an installation package can be created using cpack. By default a tgz package is created, +but you can append `-G ` to each command to generate alternative packages types (TGZ, ZIP, RPM, DEB). To easily +create a rpm or deb package, you would use `-G RPM` or `-G DEB` respectively. + +```sh or powershell +cd build +cpack --config CPackConfig.cmake +cpack --config CPackSourceConfig.cmake +``` + +### Vcpkg + +Alternatively, you can build and install zlib-ng using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager: + +```sh or powershell +git clone https://github.com/Microsoft/vcpkg.git +cd vcpkg +./bootstrap-vcpkg.sh # "./bootstrap-vcpkg.bat" for powershell +./vcpkg integrate install +./vcpkg install zlib-ng +``` + +The zlib-ng port in vcpkg is kept up to date by Microsoft team members and community contributors. +If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. + +Contributing +------------ + +Zlib-ng is aiming to be open to contributions, and we would be delighted to receive pull requests on github. +Help with testing and reviewing pull requests etc is also very much appreciated. + +Please check the Wiki for more info: [Contributing](https://github.com/zlib-ng/zlib-ng/wiki/Contributing) + +Acknowledgments +---------------- + +Thanks go out to all the people and companies who have taken the time to contribute +code reviews, testing and/or patches. Zlib-ng would not have been nearly as good without you. + +The deflate format used by zlib was defined by Phil Katz.
+The deflate and zlib specifications were written by L. Peter Deutsch. + +zlib was originally created by Jean-loup Gailly (compression) and Mark Adler (decompression). + + +Advanced Build Options +---------------------- + +| CMake | configure | Description | Default | +|:--------------------------------|:----------------------|:--------------------------------------------------------------------|------------------------| +| FORCE_SSE2 | --force-sse2 | Skip runtime check for SSE2 instructions (Always on for x86_64) | OFF (x86) | +| WITH_AVX2 | | Build with AVX2 intrinsics | ON | +| WITH_AVX512 | | Build with AVX512 intrinsics | ON | +| WITH_AVX512VNNI | | Build with AVX512VNNI intrinsics | ON | +| WITH_SSE2 | | Build with SSE2 intrinsics | ON | +| WITH_SSSE3 | | Build with SSSE3 intrinsics | ON | +| WITH_SSE42 | | Build with SSE42 intrinsics | ON | +| WITH_PCLMULQDQ | | Build with PCLMULQDQ intrinsics | ON | +| WITH_VPCLMULQDQ | --without-vpclmulqdq | Build with VPCLMULQDQ intrinsics | ON | +| WITH_ACLE | --without-acle | Build with ACLE intrinsics | ON | +| WITH_NEON | --without-neon | Build with NEON intrinsics | ON | +| WITH_ARMV6 | --without-armv6 | Build with ARMv6 intrinsics | ON | +| WITH_ALTIVEC | --without-altivec | Build with AltiVec (VMX) intrinsics | ON | +| WITH_POWER8 | --without-power8 | Build with POWER8 optimisations | ON | +| WITH_RVV | | Build with RVV intrinsics | ON | +| WITH_CRC32_VX | --without-crc32-vx | Build with vectorized CRC32 on IBM Z | ON | +| WITH_DFLTCC_DEFLATE | --with-dfltcc-deflate | Build with DFLTCC intrinsics for compression on IBM Z | OFF | +| WITH_DFLTCC_INFLATE | --with-dfltcc-inflate | Build with DFLTCC intrinsics for decompression on IBM Z | OFF | +| WITH_UNALIGNED | --without-unaligned | Allow optimizations that use unaligned reads if safe on current arch| ON | +| WITH_INFLATE_STRICT | | Build with strict inflate distance checking | OFF | +| WITH_INFLATE_ALLOW_INVALID_DIST | | Build with zero fill for inflate invalid distances | OFF | +| INSTALL_UTILS | | Copy minigzip and minideflate during install | OFF | +| ZLIBNG_ENABLE_TESTS | | Test zlib-ng specific API | ON | + + +Related Projects +---------------- + +* Fork of the popular minizip https://github.com/zlib-ng/minizip-ng +* Python tool to benchmark minigzip/minideflate https://github.com/zlib-ng/deflatebench +* Python tool to benchmark pigz https://github.com/zlib-ng/pigzbench +* 3rd party patches for zlib-ng compatibility https://github.com/zlib-ng/patches diff --git a/3rdparty/zlib-ng/adler32.c b/3rdparty/zlib-ng/adler32.c new file mode 100644 index 000000000000..95ac13c3046b --- /dev/null +++ b/3rdparty/zlib-ng/adler32.c @@ -0,0 +1,115 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "functable.h" +#include "adler32_p.h" + +/* ========================================================================= */ +Z_INTERNAL uint32_t adler32_c(uint32_t adler, const uint8_t *buf, size_t len) { + uint32_t sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (UNLIKELY(len == 1)) + return adler32_len_1(adler, buf, sum2); + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (UNLIKELY(buf == NULL)) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (UNLIKELY(len < 16)) + return adler32_len_16(adler, buf, len, sum2); + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; +#ifdef UNROLL_MORE + n = NMAX / 16; /* NMAX is divisible by 16 */ +#else + n = NMAX / 8; /* NMAX is divisible by 8 */ +#endif + do { +#ifdef UNROLL_MORE + DO16(adler, sum2, buf); /* 16 sums unrolled */ + buf += 16; +#else + DO8(adler, sum2, buf, 0); /* 8 sums unrolled */ + buf += 8; +#endif + } while (--n); + adler %= BASE; + sum2 %= BASE; + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + return adler32_len_64(adler, buf, len, sum2); +} + +#ifdef ZLIB_COMPAT +unsigned long Z_EXPORT PREFIX(adler32_z)(unsigned long adler, const unsigned char *buf, size_t len) { + return (unsigned long)functable.adler32((uint32_t)adler, buf, len); +} +#else +uint32_t Z_EXPORT PREFIX(adler32_z)(uint32_t adler, const unsigned char *buf, size_t len) { + return functable.adler32(adler, buf, len); +} +#endif + +/* ========================================================================= */ +#ifdef ZLIB_COMPAT +unsigned long Z_EXPORT PREFIX(adler32)(unsigned long adler, const unsigned char *buf, unsigned int len) { + return (unsigned long)functable.adler32((uint32_t)adler, buf, len); +} +#else +uint32_t Z_EXPORT PREFIX(adler32)(uint32_t adler, const unsigned char *buf, uint32_t len) { + return functable.adler32(adler, buf, len); +} +#endif + +/* ========================================================================= */ +static uint32_t adler32_combine_(uint32_t adler1, uint32_t adler2, z_off64_t len2) { + uint32_t sum1; + uint32_t sum2; + unsigned rem; + + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffff; + + /* the derivation of this formula is left as an exercise for the reader */ + len2 %= BASE; /* assumes len2 >= 0 */ + rem = (unsigned)len2; + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + sum2 %= BASE; + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +#ifdef ZLIB_COMPAT +unsigned long Z_EXPORT PREFIX(adler32_combine)(unsigned long adler1, unsigned long adler2, z_off_t len2) { + return (unsigned long)adler32_combine_((uint32_t)adler1, (uint32_t)adler2, len2); +} + +unsigned long Z_EXPORT PREFIX4(adler32_combine)(unsigned long adler1, unsigned long adler2, z_off64_t len2) { + return (unsigned long)adler32_combine_((uint32_t)adler1, (uint32_t)adler2, len2); +} +#else +uint32_t Z_EXPORT PREFIX4(adler32_combine)(uint32_t adler1, uint32_t adler2, z_off64_t len2) { + return adler32_combine_(adler1, adler2, len2); +} +#endif diff --git a/3rdparty/zlib-ng/adler32_fold.c b/3rdparty/zlib-ng/adler32_fold.c new file mode 100644 index 000000000000..e2f6f9ac7dd2 --- /dev/null +++ b/3rdparty/zlib-ng/adler32_fold.c @@ -0,0 +1,16 @@ +/* adler32_fold.c -- adler32 folding interface + * Copyright (C) 2022 Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "functable.h" +#include "adler32_fold.h" + +#include + +Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { + adler = functable.adler32(adler, src, len); + memcpy(dst, src, len); + return adler; +} diff --git a/3rdparty/zlib-ng/adler32_fold.h b/3rdparty/zlib-ng/adler32_fold.h new file mode 100644 index 000000000000..20aa1c7400b7 --- /dev/null +++ b/3rdparty/zlib-ng/adler32_fold.h @@ -0,0 +1,11 @@ +/* adler32_fold.h -- adler32 folding interface + * Copyright (C) 2022 Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ADLER32_FOLD_H_ +#define ADLER32_FOLD_H_ + +Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); + +#endif diff --git a/3rdparty/zlib-ng/adler32_p.h b/3rdparty/zlib-ng/adler32_p.h new file mode 100644 index 000000000000..38ba2ad72149 --- /dev/null +++ b/3rdparty/zlib-ng/adler32_p.h @@ -0,0 +1,70 @@ +/* adler32_p.h -- Private inline functions and macros shared with + * different computation of the Adler-32 checksum + * of a data stream. + * Copyright (C) 1995-2011, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ADLER32_P_H +#define ADLER32_P_H + +#define BASE 65521U /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(sum1, sum2, buf, i) {(sum1) += buf[(i)]; (sum2) += (sum1);} +#define DO2(sum1, sum2, buf, i) {DO1(sum1, sum2, buf, i); DO1(sum1, sum2, buf, i+1);} +#define DO4(sum1, sum2, buf, i) {DO2(sum1, sum2, buf, i); DO2(sum1, sum2, buf, i+2);} +#define DO8(sum1, sum2, buf, i) {DO4(sum1, sum2, buf, i); DO4(sum1, sum2, buf, i+4);} +#define DO16(sum1, sum2, buf) {DO8(sum1, sum2, buf, 0); DO8(sum1, sum2, buf, 8);} + +static inline uint32_t adler32_len_1(uint32_t adler, const uint8_t *buf, uint32_t sum2) { + adler += buf[0]; + adler %= BASE; + sum2 += adler; + sum2 %= BASE; + return adler | (sum2 << 16); +} + +static inline uint32_t adler32_len_16(uint32_t adler, const uint8_t *buf, size_t len, uint32_t sum2) { + while (len) { + --len; + adler += *buf++; + sum2 += adler; + } + adler %= BASE; + sum2 %= BASE; /* only added so many BASE's */ + /* return recombined sums */ + return adler | (sum2 << 16); +} + +static inline uint32_t adler32_copy_len_16(uint32_t adler, const uint8_t *buf, uint8_t *dst, size_t len, uint32_t sum2) { + while (len--) { + *dst = *buf++; + adler += *dst++; + sum2 += adler; + } + adler %= BASE; + sum2 %= BASE; /* only added so many BASE's */ + /* return recombined sums */ + return adler | (sum2 << 16); +} + +static inline uint32_t adler32_len_64(uint32_t adler, const uint8_t *buf, size_t len, uint32_t sum2) { +#ifdef UNROLL_MORE + while (len >= 16) { + len -= 16; + DO16(adler, sum2, buf); + buf += 16; +#else + while (len >= 8) { + len -= 8; + DO8(adler, sum2, buf, 0); + buf += 8; +#endif + } + /* Process tail (len < 16). */ + return adler32_len_16(adler, buf, len, sum2); +} + +#endif /* ADLER32_P_H */ diff --git a/3rdparty/zlib-ng/arch/.gitignore b/3rdparty/zlib-ng/arch/.gitignore new file mode 100644 index 000000000000..2c3af0a08cbd --- /dev/null +++ b/3rdparty/zlib-ng/arch/.gitignore @@ -0,0 +1,2 @@ +# ignore Makefiles; they're all automatically generated +Makefile diff --git a/3rdparty/zlib-ng/arch/arm/Makefile.in b/3rdparty/zlib-ng/arch/arm/Makefile.in new file mode 100644 index 000000000000..9d05b00b54ed --- /dev/null +++ b/3rdparty/zlib-ng/arch/arm/Makefile.in @@ -0,0 +1,85 @@ +# Makefile for zlib +# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler +# For conditions of distribution and use, see copyright notice in zlib.h + +CC= +CFLAGS= +SFLAGS= +INCLUDES= +SUFFIX= + +ACLEFLAG= +NEONFLAG= +ARMV6FLAG= +NOLTOFLAG= + +SRCDIR=. +SRCTOP=../.. +TOPDIR=$(SRCTOP) + +all: \ + adler32_neon.o adler32_neon.lo \ + arm_features.o arm_features.lo \ + chunkset_neon.o chunkset_neon.lo \ + compare256_neon.o compare256_neon.lo \ + crc32_acle.o crc32_acle.lo \ + slide_hash_neon.o slide_hash_neon.lo \ + slide_hash_armv6.o slide_hash_armv6.lo \ + insert_string_acle.o insert_string_acle.lo + +adler32_neon.o: + $(CC) $(CFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_neon.c + +adler32_neon.lo: + $(CC) $(SFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_neon.c + +arm_features.o: + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arm_features.c + +arm_features.lo: + $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arm_features.c + +chunkset_neon.o: + $(CC) $(CFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_neon.c + +chunkset_neon.lo: + $(CC) $(SFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_neon.c + +compare256_neon.o: + $(CC) $(CFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_neon.c + +compare256_neon.lo: + $(CC) $(SFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_neon.c + +crc32_acle.o: + $(CC) $(CFLAGS) $(ACLEFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_acle.c + +crc32_acle.lo: + $(CC) $(SFLAGS) $(ACLEFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_acle.c + +slide_hash_neon.o: + $(CC) $(CFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_neon.c + +slide_hash_neon.lo: + $(CC) $(SFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_neon.c + +slide_hash_armv6.o: + $(CC) $(CFLAGS) $(ARMV6FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_armv6.c + +slide_hash_armv6.lo: + $(CC) $(SFLAGS) $(ARMV6FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_armv6.c + +insert_string_acle.o: + $(CC) $(CFLAGS) $(ACLEFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_acle.c + +insert_string_acle.lo: + $(CC) $(SFLAGS) $(ACLEFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_acle.c + +mostlyclean: clean +clean: + rm -f *.o *.lo *~ + rm -rf objs + rm -f *.gcda *.gcno *.gcov + +distclean: clean + rm -f Makefile diff --git a/3rdparty/zlib-ng/arch/arm/acle_intrins.h b/3rdparty/zlib-ng/arch/arm/acle_intrins.h new file mode 100644 index 000000000000..a67cf3aabdf0 --- /dev/null +++ b/3rdparty/zlib-ng/arch/arm/acle_intrins.h @@ -0,0 +1,35 @@ +#ifndef ARM_ACLE_INTRINS_H +#define ARM_ACLE_INTRINS_H + +#include +#ifdef _MSC_VER +# include +#elif defined(HAVE_ARM_ACLE_H) +# include +#endif + +#ifdef ARM_ACLE +#if defined(__aarch64__) +# define Z_TARGET_CRC Z_TARGET("+crc") +#else +# define Z_TARGET_CRC +#endif +#endif + +#ifdef ARM_SIMD +#ifdef _MSC_VER +typedef uint32_t uint16x2_t; + +#define __uqsub16 _arm_uqsub16 +#elif !defined(ARM_SIMD_INTRIN) +typedef uint32_t uint16x2_t; + +static inline uint16x2_t __uqsub16(uint16x2_t __a, uint16x2_t __b) { + uint16x2_t __c; + __asm__ __volatile__("uqsub16 %0, %1, %2" : "=r" (__c) : "r"(__a), "r"(__b)); + return __c; +} +#endif +#endif + +#endif // include guard ARM_ACLE_INTRINS_H diff --git a/3rdparty/zlib-ng/arch/arm/adler32_neon.c b/3rdparty/zlib-ng/arch/arm/adler32_neon.c new file mode 100644 index 000000000000..f1c43ff04749 --- /dev/null +++ b/3rdparty/zlib-ng/arch/arm/adler32_neon.c @@ -0,0 +1,215 @@ +/* Copyright (C) 1995-2011, 2016 Mark Adler + * Copyright (C) 2017 ARM Holdings Inc. + * Authors: + * Adenilson Cavalcanti + * Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ +#ifdef ARM_NEON +#include "neon_intrins.h" +#include "../../zbuild.h" +#include "../../adler32_p.h" + +static void NEON_accum32(uint32_t *s, const uint8_t *buf, size_t len) { + static const uint16_t ALIGNED_(16) taps[64] = { + 64, 63, 62, 61, 60, 59, 58, 57, + 56, 55, 54, 53, 52, 51, 50, 49, + 48, 47, 46, 45, 44, 43, 42, 41, + 40, 39, 38, 37, 36, 35, 34, 33, + 32, 31, 30, 29, 28, 27, 26, 25, + 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, + 8, 7, 6, 5, 4, 3, 2, 1 }; + + uint32x4_t adacc = vdupq_n_u32(0); + uint32x4_t s2acc = vdupq_n_u32(0); + uint32x4_t s2acc_0 = vdupq_n_u32(0); + uint32x4_t s2acc_1 = vdupq_n_u32(0); + uint32x4_t s2acc_2 = vdupq_n_u32(0); + + adacc = vsetq_lane_u32(s[0], adacc, 0); + s2acc = vsetq_lane_u32(s[1], s2acc, 0); + + uint32x4_t s3acc = vdupq_n_u32(0); + uint32x4_t adacc_prev = adacc; + + uint16x8_t s2_0, s2_1, s2_2, s2_3; + s2_0 = s2_1 = s2_2 = s2_3 = vdupq_n_u16(0); + + uint16x8_t s2_4, s2_5, s2_6, s2_7; + s2_4 = s2_5 = s2_6 = s2_7 = vdupq_n_u16(0); + + size_t num_iter = len >> 2; + int rem = len & 3; + + for (size_t i = 0; i < num_iter; ++i) { + uint8x16x4_t d0_d3 = vld1q_u8_x4(buf); + + /* Unfortunately it doesn't look like there's a direct sum 8 bit to 32 + * bit instruction, we'll have to make due summing to 16 bits first */ + uint16x8x2_t hsum, hsum_fold; + hsum.val[0] = vpaddlq_u8(d0_d3.val[0]); + hsum.val[1] = vpaddlq_u8(d0_d3.val[1]); + + hsum_fold.val[0] = vpadalq_u8(hsum.val[0], d0_d3.val[2]); + hsum_fold.val[1] = vpadalq_u8(hsum.val[1], d0_d3.val[3]); + + adacc = vpadalq_u16(adacc, hsum_fold.val[0]); + s3acc = vaddq_u32(s3acc, adacc_prev); + adacc = vpadalq_u16(adacc, hsum_fold.val[1]); + + /* If we do straight widening additions to the 16 bit values, we don't incur + * the usual penalties of a pairwise add. We can defer the multiplications + * until the very end. These will not overflow because we are incurring at + * most 408 loop iterations (NMAX / 64), and a given lane is only going to be + * summed into once. This means for the maximum input size, the largest value + * we will see is 255 * 102 = 26010, safely under uint16 max */ + s2_0 = vaddw_u8(s2_0, vget_low_u8(d0_d3.val[0])); + s2_1 = vaddw_high_u8(s2_1, d0_d3.val[0]); + s2_2 = vaddw_u8(s2_2, vget_low_u8(d0_d3.val[1])); + s2_3 = vaddw_high_u8(s2_3, d0_d3.val[1]); + s2_4 = vaddw_u8(s2_4, vget_low_u8(d0_d3.val[2])); + s2_5 = vaddw_high_u8(s2_5, d0_d3.val[2]); + s2_6 = vaddw_u8(s2_6, vget_low_u8(d0_d3.val[3])); + s2_7 = vaddw_high_u8(s2_7, d0_d3.val[3]); + + adacc_prev = adacc; + buf += 64; + } + + s3acc = vshlq_n_u32(s3acc, 6); + + if (rem) { + uint32x4_t s3acc_0 = vdupq_n_u32(0); + while (rem--) { + uint8x16_t d0 = vld1q_u8(buf); + uint16x8_t adler; + adler = vpaddlq_u8(d0); + s2_6 = vaddw_u8(s2_6, vget_low_u8(d0)); + s2_7 = vaddw_high_u8(s2_7, d0); + adacc = vpadalq_u16(adacc, adler); + s3acc_0 = vaddq_u32(s3acc_0, adacc_prev); + adacc_prev = adacc; + buf += 16; + } + + s3acc_0 = vshlq_n_u32(s3acc_0, 4); + s3acc = vaddq_u32(s3acc_0, s3acc); + } + + uint16x8x4_t t0_t3 = vld1q_u16_x4(taps); + uint16x8x4_t t4_t7 = vld1q_u16_x4(taps + 32); + + s2acc = vmlal_high_u16(s2acc, t0_t3.val[0], s2_0); + s2acc_0 = vmlal_u16(s2acc_0, vget_low_u16(t0_t3.val[0]), vget_low_u16(s2_0)); + s2acc_1 = vmlal_high_u16(s2acc_1, t0_t3.val[1], s2_1); + s2acc_2 = vmlal_u16(s2acc_2, vget_low_u16(t0_t3.val[1]), vget_low_u16(s2_1)); + + s2acc = vmlal_high_u16(s2acc, t0_t3.val[2], s2_2); + s2acc_0 = vmlal_u16(s2acc_0, vget_low_u16(t0_t3.val[2]), vget_low_u16(s2_2)); + s2acc_1 = vmlal_high_u16(s2acc_1, t0_t3.val[3], s2_3); + s2acc_2 = vmlal_u16(s2acc_2, vget_low_u16(t0_t3.val[3]), vget_low_u16(s2_3)); + + s2acc = vmlal_high_u16(s2acc, t4_t7.val[0], s2_4); + s2acc_0 = vmlal_u16(s2acc_0, vget_low_u16(t4_t7.val[0]), vget_low_u16(s2_4)); + s2acc_1 = vmlal_high_u16(s2acc_1, t4_t7.val[1], s2_5); + s2acc_2 = vmlal_u16(s2acc_2, vget_low_u16(t4_t7.val[1]), vget_low_u16(s2_5)); + + s2acc = vmlal_high_u16(s2acc, t4_t7.val[2], s2_6); + s2acc_0 = vmlal_u16(s2acc_0, vget_low_u16(t4_t7.val[2]), vget_low_u16(s2_6)); + s2acc_1 = vmlal_high_u16(s2acc_1, t4_t7.val[3], s2_7); + s2acc_2 = vmlal_u16(s2acc_2, vget_low_u16(t4_t7.val[3]), vget_low_u16(s2_7)); + + s2acc = vaddq_u32(s2acc_0, s2acc); + s2acc_2 = vaddq_u32(s2acc_1, s2acc_2); + s2acc = vaddq_u32(s2acc, s2acc_2); + + uint32x2_t adacc2, s2acc2, as; + s2acc = vaddq_u32(s2acc, s3acc); + adacc2 = vpadd_u32(vget_low_u32(adacc), vget_high_u32(adacc)); + s2acc2 = vpadd_u32(vget_low_u32(s2acc), vget_high_u32(s2acc)); + as = vpadd_u32(adacc2, s2acc2); + s[0] = vget_lane_u32(as, 0); + s[1] = vget_lane_u32(as, 1); +} + +static void NEON_handle_tail(uint32_t *pair, const uint8_t *buf, size_t len) { + unsigned int i; + for (i = 0; i < len; ++i) { + pair[0] += buf[i]; + pair[1] += pair[0]; + } +} + +Z_INTERNAL uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, size_t len) { + /* split Adler-32 into component sums */ + uint32_t sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) + return adler32_len_1(adler, buf, sum2); + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) + return adler32_len_16(adler, buf, len, sum2); + + uint32_t pair[2]; + int n = NMAX; + unsigned int done = 0; + + /* Split Adler-32 into component sums, it can be supplied by + * the caller sites (e.g. in a PNG file). + */ + pair[0] = adler; + pair[1] = sum2; + + /* If memory is not SIMD aligned, do scalar sums to an aligned + * offset, provided that doing so doesn't completely eliminate + * SIMD operation. Aligned loads are still faster on ARM, even + * though there's no explicit aligned load instruction */ + unsigned int align_offset = ((uintptr_t)buf & 15); + unsigned int align_adj = (align_offset) ? 16 - align_offset : 0; + + if (align_offset && len >= (16 + align_adj)) { + NEON_handle_tail(pair, buf, align_adj); + n -= align_adj; + done += align_adj; + + } else { + /* If here, we failed the len criteria test, it wouldn't be + * worthwhile to do scalar aligning sums */ + align_adj = 0; + } + + while (done < len) { + int remaining = (int)(len - done); + n = MIN(remaining, (done == align_adj) ? n : NMAX); + + if (n < 16) + break; + + NEON_accum32(pair, buf + done, n >> 4); + pair[0] %= BASE; + pair[1] %= BASE; + + int actual_nsums = (n >> 4) << 4; + done += actual_nsums; + } + + /* Handle the tail elements. */ + if (done < len) { + NEON_handle_tail(pair, (buf + done), len - done); + pair[0] %= BASE; + pair[1] %= BASE; + } + + /* D = B * 65536 + A, see: https://en.wikipedia.org/wiki/Adler-32. */ + return (pair[1] << 16) | pair[0]; +} + +#endif diff --git a/3rdparty/zlib-ng/arch/arm/arm_features.c b/3rdparty/zlib-ng/arch/arm/arm_features.c new file mode 100644 index 000000000000..a0e070ba9561 --- /dev/null +++ b/3rdparty/zlib-ng/arch/arm/arm_features.c @@ -0,0 +1,100 @@ +#include "../../zbuild.h" +#include "arm_features.h" + +#if defined(__linux__) && defined(HAVE_SYS_AUXV_H) +# include +# ifdef ARM_ASM_HWCAP +# include +# endif +#elif defined(__FreeBSD__) && defined(__aarch64__) +# include +# ifndef ID_AA64ISAR0_CRC32_VAL +# define ID_AA64ISAR0_CRC32_VAL ID_AA64ISAR0_CRC32 +# endif +#elif defined(__APPLE__) +# if !defined(_DARWIN_C_SOURCE) +# define _DARWIN_C_SOURCE /* enable types aliases (eg u_int) */ +# endif +# include +#elif defined(_WIN32) +# include +#endif + +static int arm_has_crc32() { +#if defined(__linux__) && defined(ARM_AUXV_HAS_CRC32) +# ifdef HWCAP_CRC32 + return (getauxval(AT_HWCAP) & HWCAP_CRC32) != 0 ? 1 : 0; +# else + return (getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0 ? 1 : 0; +# endif +#elif defined(__FreeBSD__) && defined(__aarch64__) + return getenv("QEMU_EMULATING") == NULL + && ID_AA64ISAR0_CRC32_VAL(READ_SPECIALREG(id_aa64isar0_el1)) >= ID_AA64ISAR0_CRC32_BASE; +#elif defined(__APPLE__) + int hascrc32; + size_t size = sizeof(hascrc32); + return sysctlbyname("hw.optional.armv8_crc32", &hascrc32, &size, NULL, 0) == 0 + && hascrc32 == 1; +#elif defined(_WIN32) + return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE); +#elif defined(ARM_NOCHECK_ACLE) + return 1; +#else + return 0; +#endif +} + +/* AArch64 has neon. */ +#if !defined(__aarch64__) && !defined(_M_ARM64) && !defined(_M_ARM64EC) +static inline int arm_has_neon() { +#if defined(__linux__) && defined(ARM_AUXV_HAS_NEON) +# ifdef HWCAP_ARM_NEON + return (getauxval(AT_HWCAP) & HWCAP_ARM_NEON) != 0 ? 1 : 0; +# else + return (getauxval(AT_HWCAP) & HWCAP_NEON) != 0 ? 1 : 0; +# endif +#elif defined(__APPLE__) + int hasneon; + size_t size = sizeof(hasneon); + return sysctlbyname("hw.optional.neon", &hasneon, &size, NULL, 0) == 0 + && hasneon == 1; +#elif defined(_M_ARM) && defined(WINAPI_FAMILY_PARTITION) +# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) + return 1; /* Always supported */ +# endif +#endif + +#if defined(ARM_NOCHECK_NEON) + return 1; +#else + return 0; +#endif +} +#endif + +/* AArch64 does not have ARMv6 SIMD. */ +#if !defined(__aarch64__) && !defined(_M_ARM64) && !defined(_M_ARM64EC) +static inline int arm_has_simd() { +#if defined(__linux__) && defined(HAVE_SYS_AUXV_H) + const char *platform = (const char *)getauxval(AT_PLATFORM); + return strncmp(platform, "v6l", 3) == 0 + || strncmp(platform, "v7l", 3) == 0 + || strncmp(platform, "v8l", 3) == 0; +#elif defined(ARM_NOCHECK_SIMD) + return 1; +#else + return 0; +#endif +} +#endif + +void Z_INTERNAL arm_check_features(struct arm_cpu_features *features) { +#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) + features->has_simd = 0; /* never available */ + features->has_neon = 1; /* always available */ +#else + features->has_simd = arm_has_simd(); + features->has_neon = arm_has_neon(); +#endif + features->has_crc32 = arm_has_crc32(); +} diff --git a/3rdparty/zlib-ng/arch/arm/arm_features.h b/3rdparty/zlib-ng/arch/arm/arm_features.h new file mode 100644 index 000000000000..eca078e310ea --- /dev/null +++ b/3rdparty/zlib-ng/arch/arm/arm_features.h @@ -0,0 +1,16 @@ +/* arm_features.h -- check for ARM features. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ARM_H_ +#define ARM_H_ + +struct arm_cpu_features { + int has_simd; + int has_neon; + int has_crc32; +}; + +void Z_INTERNAL arm_check_features(struct arm_cpu_features *features); + +#endif /* ARM_H_ */ diff --git a/3rdparty/zlib-ng/arch/arm/chunkset_neon.c b/3rdparty/zlib-ng/arch/arm/chunkset_neon.c new file mode 100644 index 000000000000..f9a444b0681f --- /dev/null +++ b/3rdparty/zlib-ng/arch/arm/chunkset_neon.c @@ -0,0 +1,99 @@ +/* chunkset_neon.c -- NEON inline functions to copy small data chunks. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef ARM_NEON +#include "neon_intrins.h" +#include "../../zbuild.h" +#include "../generic/chunk_permute_table.h" + +typedef uint8x16_t chunk_t; + +#define CHUNK_SIZE 16 + +#define HAVE_CHUNKMEMSET_2 +#define HAVE_CHUNKMEMSET_4 +#define HAVE_CHUNKMEMSET_8 +#define HAVE_CHUNK_MAG + +static const lut_rem_pair perm_idx_lut[13] = { + {0, 1}, /* 3 */ + {0, 0}, /* don't care */ + {1 * 32, 1}, /* 5 */ + {2 * 32, 4}, /* 6 */ + {3 * 32, 2}, /* 7 */ + {0 * 32, 0}, /* don't care */ + {4 * 32, 7}, /* 9 */ + {5 * 32, 6}, /* 10 */ + {6 * 32, 5}, /* 11 */ + {7 * 32, 4}, /* 12 */ + {8 * 32, 3}, /* 13 */ + {9 * 32, 2}, /* 14 */ + {10 * 32, 1},/* 15 */ +}; + +static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { + uint16_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = vreinterpretq_u8_u16(vdupq_n_u16(tmp)); +} + +static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { + uint32_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = vreinterpretq_u8_u32(vdupq_n_u32(tmp)); +} + +static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { + uint64_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = vreinterpretq_u8_u64(vdupq_n_u64(tmp)); +} + +#define CHUNKSIZE chunksize_neon +#define CHUNKCOPY chunkcopy_neon +#define CHUNKUNROLL chunkunroll_neon +#define CHUNKMEMSET chunkmemset_neon +#define CHUNKMEMSET_SAFE chunkmemset_safe_neon + +static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { + *chunk = vld1q_u8(s); +} + +static inline void storechunk(uint8_t *out, chunk_t *chunk) { + vst1q_u8(out, *chunk); +} + +static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t dist) { + lut_rem_pair lut_rem = perm_idx_lut[dist - 3]; + *chunk_rem = lut_rem.remval; + + /* See note in chunkset_ssse3.c for why this is ok */ + __msan_unpoison(buf + dist, 16 - dist); + + /* This version of table is only available on aarch64 */ +#if defined(_M_ARM64) || defined(_M_ARM64EC) || defined(__aarch64__) + uint8x16_t ret_vec = vld1q_u8(buf); + + uint8x16_t perm_vec = vld1q_u8(permute_table + lut_rem.idx); + return vqtbl1q_u8(ret_vec, perm_vec); +#else + uint8x8_t ret0, ret1, a, b, perm_vec0, perm_vec1; + perm_vec0 = vld1_u8(permute_table + lut_rem.idx); + perm_vec1 = vld1_u8(permute_table + lut_rem.idx + 8); + a = vld1_u8(buf); + b = vld1_u8(buf + 8); + ret0 = vtbl1_u8(a, perm_vec0); + uint8x8x2_t ab = {{a, b}}; + ret1 = vtbl2_u8(ab, perm_vec1); + return vcombine_u8(ret0, ret1); +#endif +} + +#include "chunkset_tpl.h" + +#define INFLATE_FAST inflate_fast_neon + +#include "inffast_tpl.h" + +#endif diff --git a/3rdparty/zlib-ng/arch/arm/compare256_neon.c b/3rdparty/zlib-ng/arch/arm/compare256_neon.c new file mode 100644 index 000000000000..7daeba411ece --- /dev/null +++ b/3rdparty/zlib-ng/arch/arm/compare256_neon.c @@ -0,0 +1,59 @@ +/* compare256_neon.c - NEON version of compare256 + * Copyright (C) 2022 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "../../zbuild.h" + +#include "fallback_builtins.h" + +#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) +#include "neon_intrins.h" + +static inline uint32_t compare256_neon_static(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + + do { + uint8x16_t a, b, cmp; + uint64_t lane; + + a = vld1q_u8(src0); + b = vld1q_u8(src1); + + cmp = veorq_u8(a, b); + + lane = vgetq_lane_u64(vreinterpretq_u64_u8(cmp), 0); + if (lane) { + uint32_t match_byte = (uint32_t)__builtin_ctzll(lane) / 8; + return len + match_byte; + } + len += 8; + lane = vgetq_lane_u64(vreinterpretq_u64_u8(cmp), 1); + if (lane) { + uint32_t match_byte = (uint32_t)__builtin_ctzll(lane) / 8; + return len + match_byte; + } + len += 8; + + src0 += 16, src1 += 16; + } while (len < 256); + + return 256; +} + +Z_INTERNAL uint32_t compare256_neon(const uint8_t *src0, const uint8_t *src1) { + return compare256_neon_static(src0, src1); +} + +#define LONGEST_MATCH longest_match_neon +#define COMPARE256 compare256_neon_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_neon +#define COMPARE256 compare256_neon_static + +#include "match_tpl.h" + +#endif diff --git a/3rdparty/zlib-ng/arch/arm/crc32_acle.c b/3rdparty/zlib-ng/arch/arm/crc32_acle.c new file mode 100644 index 000000000000..ac7d6ff66b3e --- /dev/null +++ b/3rdparty/zlib-ng/arch/arm/crc32_acle.c @@ -0,0 +1,78 @@ +/* crc32_acle.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler + * Copyright (C) 2016 Yang Zhang + * For conditions of distribution and use, see copyright notice in zlib.h + * +*/ + +#ifdef ARM_ACLE +#include "acle_intrins.h" +#include "../../zbuild.h" + +Z_INTERNAL Z_TARGET_CRC uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, size_t len) { + Z_REGISTER uint32_t c; + Z_REGISTER const uint16_t *buf2; + Z_REGISTER const uint32_t *buf4; + Z_REGISTER const uint64_t *buf8; + + c = ~crc; + + if (UNLIKELY(len == 1)) { + c = __crc32b(c, *buf); + c = ~c; + return c; + } + + if ((ptrdiff_t)buf & (sizeof(uint64_t) - 1)) { + if (len && ((ptrdiff_t)buf & 1)) { + c = __crc32b(c, *buf++); + len--; + } + + if ((len >= sizeof(uint16_t)) && ((ptrdiff_t)buf & sizeof(uint16_t))) { + buf2 = (const uint16_t *) buf; + c = __crc32h(c, *buf2++); + len -= sizeof(uint16_t); + buf4 = (const uint32_t *) buf2; + } else { + buf4 = (const uint32_t *) buf; + } + + if ((len >= sizeof(uint32_t)) && ((ptrdiff_t)buf & sizeof(uint32_t))) { + c = __crc32w(c, *buf4++); + len -= sizeof(uint32_t); + } + + buf8 = (const uint64_t *) buf4; + } else { + buf8 = (const uint64_t *) buf; + } + + while (len >= sizeof(uint64_t)) { + c = __crc32d(c, *buf8++); + len -= sizeof(uint64_t); + } + + if (len >= sizeof(uint32_t)) { + buf4 = (const uint32_t *) buf8; + c = __crc32w(c, *buf4++); + len -= sizeof(uint32_t); + buf2 = (const uint16_t *) buf4; + } else { + buf2 = (const uint16_t *) buf8; + } + + if (len >= sizeof(uint16_t)) { + c = __crc32h(c, *buf2++); + len -= sizeof(uint16_t); + } + + buf = (const unsigned char *) buf2; + if (len) { + c = __crc32b(c, *buf); + } + + c = ~c; + return c; +} +#endif diff --git a/3rdparty/zlib-ng/arch/arm/insert_string_acle.c b/3rdparty/zlib-ng/arch/arm/insert_string_acle.c new file mode 100644 index 000000000000..aa8385c712e6 --- /dev/null +++ b/3rdparty/zlib-ng/arch/arm/insert_string_acle.c @@ -0,0 +1,24 @@ +/* insert_string_acle.c -- insert_string integer hash variant using ACLE's CRC instructions + * + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + */ + +#ifdef ARM_ACLE +#include "acle_intrins.h" +#include "../../zbuild.h" +#include "../../deflate.h" + +#define HASH_CALC(s, h, val) \ + h = __crc32w(0, val) + +#define HASH_CALC_VAR h +#define HASH_CALC_VAR_INIT uint32_t h = 0 + +#define UPDATE_HASH Z_TARGET_CRC update_hash_acle +#define INSERT_STRING Z_TARGET_CRC insert_string_acle +#define QUICK_INSERT_STRING Z_TARGET_CRC quick_insert_string_acle + +#include "../../insert_string_tpl.h" +#endif diff --git a/3rdparty/zlib-ng/arch/arm/neon_intrins.h b/3rdparty/zlib-ng/arch/arm/neon_intrins.h new file mode 100644 index 000000000000..51df77dbe685 --- /dev/null +++ b/3rdparty/zlib-ng/arch/arm/neon_intrins.h @@ -0,0 +1,58 @@ +#ifndef ARM_NEON_INTRINS_H +#define ARM_NEON_INTRINS_H + +#if defined(_MSC_VER) && (defined(_M_ARM64) || defined(_M_ARM64EC)) +/* arm64_neon.h is MSVC specific */ +# include +#else +# include +#endif + +#if defined(ARM_NEON) && !defined(__aarch64__) && !defined(_M_ARM64) && !defined(_M_ARM64EC) +/* Compatibility shim for the _high family of functions */ +#define vmull_high_u8(a, b) vmull_u8(vget_high_u8(a), vget_high_u8(b)) +#define vmlal_high_u8(a, b, c) vmlal_u8(a, vget_high_u8(b), vget_high_u8(c)) +#define vmlal_high_u16(a, b, c) vmlal_u16(a, vget_high_u16(b), vget_high_u16(c)) +#define vaddw_high_u8(a, b) vaddw_u8(a, vget_high_u8(b)) +#endif + +#ifdef ARM_NEON + +#define vqsubq_u16_x4_x1(out, a, b) do { \ + out.val[0] = vqsubq_u16(a.val[0], b); \ + out.val[1] = vqsubq_u16(a.val[1], b); \ + out.val[2] = vqsubq_u16(a.val[2], b); \ + out.val[3] = vqsubq_u16(a.val[3], b); \ +} while (0) + + +# ifndef ARM_NEON_HASLD4 + +static inline uint16x8x4_t vld1q_u16_x4(uint16_t const *a) { + uint16x8x4_t ret = (uint16x8x4_t) {{ + vld1q_u16(a), + vld1q_u16(a+8), + vld1q_u16(a+16), + vld1q_u16(a+24)}}; + return ret; +} + +static inline uint8x16x4_t vld1q_u8_x4(uint8_t const *a) { + uint8x16x4_t ret = (uint8x16x4_t) {{ + vld1q_u8(a), + vld1q_u8(a+16), + vld1q_u8(a+32), + vld1q_u8(a+48)}}; + return ret; +} + +static inline void vst1q_u16_x4(uint16_t *p, uint16x8x4_t a) { + vst1q_u16(p, a.val[0]); + vst1q_u16(p + 8, a.val[1]); + vst1q_u16(p + 16, a.val[2]); + vst1q_u16(p + 24, a.val[3]); +} +# endif // HASLD4 check +#endif + +#endif // include guard ARM_NEON_INTRINS_H diff --git a/3rdparty/zlib-ng/arch/arm/slide_hash_armv6.c b/3rdparty/zlib-ng/arch/arm/slide_hash_armv6.c new file mode 100644 index 000000000000..0a2eeccf9269 --- /dev/null +++ b/3rdparty/zlib-ng/arch/arm/slide_hash_armv6.c @@ -0,0 +1,47 @@ +/* slide_hash_armv6.c -- Optimized hash table shifting for ARMv6 with support for SIMD instructions + * Copyright (C) 2023 Cameron Cawley + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#if defined(ARM_SIMD) +#include "acle_intrins.h" +#include "../../zbuild.h" +#include "../../deflate.h" + +/* SIMD version of hash_chain rebase */ +static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) { + Z_REGISTER uint16x2_t v; + uint16x2_t p0, p1, p2, p3; + Z_REGISTER size_t n; + + size_t size = entries*sizeof(table[0]); + Assert((size % (sizeof(uint16x2_t) * 4) == 0), "hash table size err"); + + Assert(sizeof(Pos) == 2, "Wrong Pos size"); + v = wsize | (wsize << 16); + + n = size / (sizeof(uint16x2_t) * 4); + do { + p0 = *((const uint16x2_t *)(table)); + p1 = *((const uint16x2_t *)(table+2)); + p2 = *((const uint16x2_t *)(table+4)); + p3 = *((const uint16x2_t *)(table+6)); + p0 = __uqsub16(p0, v); + p1 = __uqsub16(p1, v); + p2 = __uqsub16(p2, v); + p3 = __uqsub16(p3, v); + *((uint16x2_t *)(table)) = p0; + *((uint16x2_t *)(table+2)) = p1; + *((uint16x2_t *)(table+4)) = p2; + *((uint16x2_t *)(table+6)) = p3; + table += 8; + } while (--n); +} + +Z_INTERNAL void slide_hash_armv6(deflate_state *s) { + unsigned int wsize = s->w_size; + + slide_hash_chain(s->head, HASH_SIZE, wsize); + slide_hash_chain(s->prev, wsize, wsize); +} +#endif diff --git a/3rdparty/zlib-ng/arch/arm/slide_hash_neon.c b/3rdparty/zlib-ng/arch/arm/slide_hash_neon.c new file mode 100644 index 000000000000..a96ca11799b5 --- /dev/null +++ b/3rdparty/zlib-ng/arch/arm/slide_hash_neon.c @@ -0,0 +1,46 @@ +/* slide_hash_neon.c -- Optimized hash table shifting for ARM with support for NEON instructions + * Copyright (C) 2017-2020 Mika T. Lindqvist + * + * Authors: + * Mika T. Lindqvist + * Jun He + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef ARM_NEON +#include "neon_intrins.h" +#include "../../zbuild.h" +#include "../../deflate.h" + +/* SIMD version of hash_chain rebase */ +static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) { + Z_REGISTER uint16x8_t v; + uint16x8x4_t p0, p1; + Z_REGISTER size_t n; + + size_t size = entries*sizeof(table[0]); + Assert((size % sizeof(uint16x8_t) * 8 == 0), "hash table size err"); + + Assert(sizeof(Pos) == 2, "Wrong Pos size"); + v = vdupq_n_u16(wsize); + + n = size / (sizeof(uint16x8_t) * 8); + do { + p0 = vld1q_u16_x4(table); + p1 = vld1q_u16_x4(table+32); + vqsubq_u16_x4_x1(p0, p0, v); + vqsubq_u16_x4_x1(p1, p1, v); + vst1q_u16_x4(table, p0); + vst1q_u16_x4(table+32, p1); + table += 64; + } while (--n); +} + +Z_INTERNAL void slide_hash_neon(deflate_state *s) { + unsigned int wsize = s->w_size; + + slide_hash_chain(s->head, HASH_SIZE, wsize); + slide_hash_chain(s->prev, wsize, wsize); +} +#endif diff --git a/3rdparty/zlib-ng/arch/generic/Makefile.in b/3rdparty/zlib-ng/arch/generic/Makefile.in new file mode 100644 index 000000000000..c717026f86e4 --- /dev/null +++ b/3rdparty/zlib-ng/arch/generic/Makefile.in @@ -0,0 +1,24 @@ +# Makefile for zlib +# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler +# For conditions of distribution and use, see copyright notice in zlib.h + +CC= +CFLAGS= +SFLAGS= +INCLUDES= + +SRCDIR=. +SRCTOP=../.. +TOPDIR=$(SRCTOP) + +all: + + +mostlyclean: clean +clean: + rm -f *.o *.lo *~ \ + rm -rf objs + rm -f *.gcda *.gcno *.gcov + +distclean: clean + rm -f Makefile diff --git a/3rdparty/zlib-ng/arch/generic/chunk_permute_table.h b/3rdparty/zlib-ng/arch/generic/chunk_permute_table.h new file mode 100644 index 000000000000..bad66ccc774b --- /dev/null +++ b/3rdparty/zlib-ng/arch/generic/chunk_permute_table.h @@ -0,0 +1,53 @@ +/* chunk_permute_table.h - shared AVX/SSSE3 permutation table for use with chunkmemset family of functions. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef CHUNK_PERMUTE_TABLE_H_ +#define CHUNK_PERMUTE_TABLE_H_ + +#include "zbuild.h" + +/* Need entries for all numbers not an even modulus for 1, 2, 4, 8, 16 & 32 */ +static const ALIGNED_(32) uint8_t permute_table[26*32] = { + 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, /* dist 3 */ + 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, /* dist 5 */ + 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, /* dist 6 */ + 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, /* dist 7 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, /* dist 9 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, /* dist 10 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* dist 11 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, /* dist 12 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 3, 4, 5, /* dist 13 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 1, 2, 3, /* dist 14 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, /* dist 15 */ + + /* Beyond dists of 15 means we have to permute from a vector > len(m128i). Because AVX couldn't permute + * beyond 128 bit lanes until AVX512 for sub 4-byte sequences, we have to do some math here for an eventual + * blend with a comparison. That means we need to wrap the indices with yet another derived table. For simplicity, + * we'll use absolute indexing here to derive a blend vector. This is actually a lot simpler with ARM's TBL, but, + * this is what we're dealt. + */ + + 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* dist 17 */ + 16, 17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, /* dist 18 */ + 16, 17, 18, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, /* dist 19 */ + 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, /* dist 20 */ + 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, /* dist 21 */ + 16, 17, 18, 19, 20, 21, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* dist 22 */ + 16, 17, 18, 19, 20, 21, 22, 0, 1, 2, 3, 4, 5, 6, 7, 8, /* dist 23 */ + 16, 17, 18, 19, 20, 21, 22, 23, 0, 1, 2, 3, 4, 5, 6, 7, /* dist 24 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 0, 1, 2, 3, 4, 5, 6, /* dist 25 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 1, 2, 3, 4, 5, /* dist 26 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 0, 1, 2, 3, 4, /* dist 27 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 1, 2, 3, /* dist 28 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 0, 1, 2, /* dist 29 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 1, /* dist 30 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 0, /* dist 31 */ +}; + +typedef struct lut_rem_pair_s { + uint16_t idx; + uint16_t remval; +} lut_rem_pair; + +#endif diff --git a/3rdparty/zlib-ng/arch/power/Makefile.in b/3rdparty/zlib-ng/arch/power/Makefile.in new file mode 100644 index 000000000000..e2bec5e510e7 --- /dev/null +++ b/3rdparty/zlib-ng/arch/power/Makefile.in @@ -0,0 +1,93 @@ +# Makefile for POWER-specific files +# Copyright (C) 2020 Matheus Castanho , IBM +# Copyright (C) 2021 Mika T. Lindqvist +# For conditions of distribution and use, see copyright notice in zlib.h + +CC= +CFLAGS= +SFLAGS= +INCLUDES= +SUFFIX= + +P8FLAGS=-mcpu=power8 +P9FLAGS=-mcpu=power9 +PPCFLAGS=-maltivec +NOLTOFLAG= + +SRCDIR=. +SRCTOP=../.. +TOPDIR=$(SRCTOP) + +all: power_features.o \ + power_features.lo \ + adler32_power8.o \ + adler32_power8.lo \ + adler32_vmx.o \ + adler32_vmx.lo \ + chunkset_power8.o \ + chunkset_power8.lo \ + compare256_power9.o \ + compare256_power9.lo \ + crc32_power8.o \ + crc32_power8.lo \ + slide_hash_power8.o \ + slide_hash_power8.lo \ + slide_hash_vmx.o \ + slide_hash_vmx.lo + +power_features.o: + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/power_features.c + +power_features.lo: + $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/power_features.c + +adler32_power8.o: + $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_power8.c + +adler32_power8.lo: + $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_power8.c + +adler32_vmx.o: + $(CC) $(CFLAGS) $(PPCFLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_vmx.c + +adler32_vmx.lo: + $(CC) $(SFLAGS) $(PPCFLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_vmx.c + +chunkset_power8.o: + $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_power8.c + +chunkset_power8.lo: + $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_power8.c + +compare256_power9.o: + $(CC) $(CFLAGS) $(P9FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_power9.c + +compare256_power9.lo: + $(CC) $(SFLAGS) $(P9FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_power9.c + +crc32_power8.o: + $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_power8.c + +crc32_power8.lo: + $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_power8.c + +slide_hash_power8.o: + $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_power8.c + +slide_hash_power8.lo: + $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_power8.c + +slide_hash_vmx.o: + $(CC) $(CFLAGS) ${PPCFLAGS} $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_vmx.c + +slide_hash_vmx.lo: + $(CC) $(SFLAGS) ${PPCFLAGS} $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_vmx.c + +mostlyclean: clean +clean: + rm -f *.o *.lo *~ + rm -rf objs + rm -f *.gcda *.gcno *.gcov + +distclean: clean + rm -f Makefile diff --git a/3rdparty/zlib-ng/arch/power/adler32_power8.c b/3rdparty/zlib-ng/arch/power/adler32_power8.c new file mode 100644 index 000000000000..4aaea9f50b3a --- /dev/null +++ b/3rdparty/zlib-ng/arch/power/adler32_power8.c @@ -0,0 +1,153 @@ +/* Adler32 for POWER8 using VSX instructions. + * Copyright (C) 2020 IBM Corporation + * Author: Rogerio Alves + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Calculate adler32 checksum for 16 bytes at once using POWER8+ VSX (vector) + * instructions. + * + * If adler32 do 1 byte at time on the first iteration s1 is s1_0 (_n means + * iteration n) is the initial value of adler - at start _0 is 1 unless + * adler initial value is different than 1. So s1_1 = s1_0 + c[0] after + * the first calculation. For the iteration s1_2 = s1_1 + c[1] and so on. + * Hence, for iteration N, s1_N = s1_(N-1) + c[N] is the value of s1 on + * after iteration N. + * + * Therefore, for s2 and iteration N, s2_N = s2_0 + N*s1_N + N*c[0] + + * N-1*c[1] + ... + c[N] + * + * In a more general way: + * + * s1_N = s1_0 + sum(i=1 to N)c[i] + * s2_N = s2_0 + N*s1 + sum (i=1 to N)(N-i+1)*c[i] + * + * Where s1_N, s2_N are the values for s1, s2 after N iterations. So if we + * can process N-bit at time we can do this at once. + * + * Since VSX can support 16-bit vector instructions, we can process + * 16-bit at time using N = 16 we have: + * + * s1 = s1_16 = s1_(16-1) + c[16] = s1_0 + sum(i=1 to 16)c[i] + * s2 = s2_16 = s2_0 + 16*s1 + sum(i=1 to 16)(16-i+1)*c[i] + * + * After the first iteration we calculate the adler32 checksum for 16 bytes. + * + * For more background about adler32 please check the RFC: + * https://www.ietf.org/rfc/rfc1950.txt + */ + +#ifdef POWER8_VSX + +#include +#include "zbuild.h" +#include "adler32_p.h" + +/* Vector across sum unsigned int (saturate). */ +static inline vector unsigned int vec_sumsu(vector unsigned int __a, vector unsigned int __b) { + __b = vec_sld(__a, __a, 8); + __b = vec_add(__b, __a); + __a = vec_sld(__b, __b, 4); + __a = vec_add(__a, __b); + + return __a; +} + +Z_INTERNAL uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, size_t len) { + uint32_t s1 = adler & 0xffff; + uint32_t s2 = (adler >> 16) & 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (UNLIKELY(len == 1)) + return adler32_len_1(s1, buf, s2); + + /* If buffer is empty or len=0 we need to return adler initial value. */ + if (UNLIKELY(buf == NULL)) + return 1; + + /* This is faster than VSX code for len < 64. */ + if (len < 64) + return adler32_len_64(s1, buf, len, s2); + + /* Use POWER VSX instructions for len >= 64. */ + const vector unsigned int v_zeros = { 0 }; + const vector unsigned char v_mul = {16, 15, 14, 13, 12, 11, 10, 9, 8, 7, + 6, 5, 4, 3, 2, 1}; + const vector unsigned char vsh = vec_splat_u8(4); + const vector unsigned int vmask = {0xffffffff, 0x0, 0x0, 0x0}; + vector unsigned int vs1 = { 0 }; + vector unsigned int vs2 = { 0 }; + vector unsigned int vs1_save = { 0 }; + vector unsigned int vsum1, vsum2; + vector unsigned char vbuf; + int n; + + vs1[0] = s1; + vs2[0] = s2; + + /* Do length bigger than NMAX in blocks of NMAX size. */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; + do { + vbuf = vec_xl(0, (unsigned char *) buf); + vsum1 = vec_sum4s(vbuf, v_zeros); /* sum(i=1 to 16) buf[i]. */ + /* sum(i=1 to 16) buf[i]*(16-i+1). */ + vsum2 = vec_msum(vbuf, v_mul, v_zeros); + /* Save vs1. */ + vs1_save = vec_add(vs1_save, vs1); + /* Accumulate the sums. */ + vs1 = vec_add(vsum1, vs1); + vs2 = vec_add(vsum2, vs2); + + buf += 16; + } while (--n); + /* Once each block of NMAX size. */ + vs1 = vec_sumsu(vs1, vsum1); + vs1_save = vec_sll(vs1_save, vsh); /* 16*vs1_save. */ + vs2 = vec_add(vs1_save, vs2); + vs2 = vec_sumsu(vs2, vsum2); + + /* vs1[0] = (s1_i + sum(i=1 to 16)buf[i]) mod 65521. */ + vs1[0] = vs1[0] % BASE; + /* vs2[0] = s2_i + 16*s1_save + + sum(i=1 to 16)(16-i+1)*buf[i] mod 65521. */ + vs2[0] = vs2[0] % BASE; + + vs1 = vec_and(vs1, vmask); + vs2 = vec_and(vs2, vmask); + vs1_save = v_zeros; + } + + /* len is less than NMAX one modulo is needed. */ + if (len >= 16) { + while (len >= 16) { + len -= 16; + + vbuf = vec_xl(0, (unsigned char *) buf); + + vsum1 = vec_sum4s(vbuf, v_zeros); /* sum(i=1 to 16) buf[i]. */ + /* sum(i=1 to 16) buf[i]*(16-i+1). */ + vsum2 = vec_msum(vbuf, v_mul, v_zeros); + /* Save vs1. */ + vs1_save = vec_add(vs1_save, vs1); + /* Accumulate the sums. */ + vs1 = vec_add(vsum1, vs1); + vs2 = vec_add(vsum2, vs2); + + buf += 16; + } + /* Since the size will be always less than NMAX we do this once. */ + vs1 = vec_sumsu(vs1, vsum1); + vs1_save = vec_sll(vs1_save, vsh); /* 16*vs1_save. */ + vs2 = vec_add(vs1_save, vs2); + vs2 = vec_sumsu(vs2, vsum2); + } + /* Copy result back to s1, s2 (mod 65521). */ + s1 = vs1[0] % BASE; + s2 = vs2[0] % BASE; + + /* Process tail (len < 16). */ + return adler32_len_16(s1, buf, len, s2); +} + +#endif /* POWER8_VSX */ diff --git a/3rdparty/zlib-ng/arch/power/adler32_vmx.c b/3rdparty/zlib-ng/arch/power/adler32_vmx.c new file mode 100644 index 000000000000..3470c28a12f7 --- /dev/null +++ b/3rdparty/zlib-ng/arch/power/adler32_vmx.c @@ -0,0 +1,186 @@ +/* adler32_vmx.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011 Mark Adler + * Copyright (C) 2017-2023 Mika T. Lindqvist + * Copyright (C) 2021 Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef PPC_VMX +#include +#include "zbuild.h" +#include "zendian.h" +#include "adler32_p.h" + +#define vmx_zero() (vec_splat_u32(0)) + +static inline void vmx_handle_head_or_tail(uint32_t *pair, const uint8_t *buf, size_t len) { + unsigned int i; + for (i = 0; i < len; ++i) { + pair[0] += buf[i]; + pair[1] += pair[0]; + } +} + +static void vmx_accum32(uint32_t *s, const uint8_t *buf, size_t len) { + /* Different taps for the separable components of sums */ + const vector unsigned char t0 = {64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49}; + const vector unsigned char t1 = {48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33}; + const vector unsigned char t2 = {32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17}; + const vector unsigned char t3 = {16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; + /* As silly and inefficient as it seems, creating 1 permutation vector to permute + * a 2 element vector from a single load + a subsequent shift is just barely faster + * than doing 2 indexed insertions into zero initialized vectors from unaligned memory. */ + const vector unsigned char s0_perm = {0, 1, 2, 3, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; + const vector unsigned char shift_vec = vec_sl(vec_splat_u8(8), vec_splat_u8(2)); + vector unsigned int adacc, s2acc; + vector unsigned int pair_vec = vec_ld(0, s); + adacc = vec_perm(pair_vec, pair_vec, s0_perm); +#if BYTE_ORDER == LITTLE_ENDIAN + s2acc = vec_sro(pair_vec, shift_vec); +#else + s2acc = vec_slo(pair_vec, shift_vec); +#endif + + vector unsigned int zero = vmx_zero(); + vector unsigned int s3acc = zero; + vector unsigned int s3acc_0 = zero; + vector unsigned int adacc_prev = adacc; + vector unsigned int adacc_prev_0 = zero; + + vector unsigned int s2acc_0 = zero; + vector unsigned int s2acc_1 = zero; + vector unsigned int s2acc_2 = zero; + + /* Maintain a running sum of a second half, this might help use break yet another + * data dependency bubble in the sum */ + vector unsigned int adacc_0 = zero; + + int num_iter = len / 4; + int rem = len & 3; + + for (int i = 0; i < num_iter; ++i) { + vector unsigned char d0 = vec_ld(0, buf); + vector unsigned char d1 = vec_ld(16, buf); + vector unsigned char d2 = vec_ld(32, buf); + vector unsigned char d3 = vec_ld(48, buf); + + /* The core operation of the loop, basically + * what is being unrolled below */ + adacc = vec_sum4s(d0, adacc); + s3acc = vec_add(s3acc, adacc_prev); + s3acc_0 = vec_add(s3acc_0, adacc_prev_0); + s2acc = vec_msum(t0, d0, s2acc); + + /* interleave dependent sums in here */ + adacc_0 = vec_sum4s(d1, adacc_0); + s2acc_0 = vec_msum(t1, d1, s2acc_0); + adacc = vec_sum4s(d2, adacc); + s2acc_1 = vec_msum(t2, d2, s2acc_1); + s2acc_2 = vec_msum(t3, d3, s2acc_2); + adacc_0 = vec_sum4s(d3, adacc_0); + + adacc_prev = adacc; + adacc_prev_0 = adacc_0; + buf += 64; + } + + adacc = vec_add(adacc, adacc_0); + s3acc = vec_add(s3acc, s3acc_0); + s3acc = vec_sl(s3acc, vec_splat_u32(6)); + + if (rem) { + adacc_prev = vec_add(adacc_prev_0, adacc_prev); + adacc_prev = vec_sl(adacc_prev, vec_splat_u32(4)); + while (rem--) { + vector unsigned char d0 = vec_ld(0, buf); + adacc = vec_sum4s(d0, adacc); + s3acc = vec_add(s3acc, adacc_prev); + s2acc = vec_msum(t3, d0, s2acc); + adacc_prev = vec_sl(adacc, vec_splat_u32(4)); + buf += 16; + } + } + + + /* Sum up independent second sums */ + s2acc = vec_add(s2acc, s2acc_0); + s2acc_2 = vec_add(s2acc_1, s2acc_2); + s2acc = vec_add(s2acc, s2acc_2); + + s2acc = vec_add(s2acc, s3acc); + + adacc = vec_add(adacc, vec_sld(adacc, adacc, 8)); + s2acc = vec_add(s2acc, vec_sld(s2acc, s2acc, 8)); + adacc = vec_add(adacc, vec_sld(adacc, adacc, 4)); + s2acc = vec_add(s2acc, vec_sld(s2acc, s2acc, 4)); + + vec_ste(adacc, 0, s); + vec_ste(s2acc, 0, s+1); +} + +Z_INTERNAL uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, size_t len) { + uint32_t sum2; + uint32_t pair[16] ALIGNED_(16); + memset(&pair[2], 0, 14); + int n = NMAX; + unsigned int done = 0, i; + + /* Split Adler-32 into component sums, it can be supplied by + * the caller sites (e.g. in a PNG file). + */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + pair[0] = adler; + pair[1] = sum2; + + /* in case user likes doing a byte at a time, keep it fast */ + if (UNLIKELY(len == 1)) + return adler32_len_1(adler, buf, sum2); + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (UNLIKELY(buf == NULL)) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (UNLIKELY(len < 16)) + return adler32_len_16(adler, buf, len, sum2); + + // Align buffer + unsigned int al = 0; + if ((uintptr_t)buf & 0xf) { + al = 16-((uintptr_t)buf & 0xf); + if (al > len) { + al=len; + } + vmx_handle_head_or_tail(pair, buf, al); + + done += al; + /* Rather than rebasing, we can reduce the max sums for the + * first round only */ + n -= al; + } + for (i = al; i < len; i += n) { + int remaining = (int)(len-i); + n = MIN(remaining, (i == al) ? n : NMAX); + + if (n < 16) + break; + + vmx_accum32(pair, buf + i, n / 16); + pair[0] %= BASE; + pair[1] %= BASE; + + done += (n / 16) * 16; + } + + /* Handle the tail elements. */ + if (done < len) { + vmx_handle_head_or_tail(pair, (buf + done), len - done); + pair[0] %= BASE; + pair[1] %= BASE; + } + + /* D = B * 65536 + A, see: https://en.wikipedia.org/wiki/Adler-32. */ + return (pair[1] << 16) | pair[0]; +} +#endif diff --git a/3rdparty/zlib-ng/arch/power/chunkset_power8.c b/3rdparty/zlib-ng/arch/power/chunkset_power8.c new file mode 100644 index 000000000000..7cbb8029b3b1 --- /dev/null +++ b/3rdparty/zlib-ng/arch/power/chunkset_power8.c @@ -0,0 +1,55 @@ +/* chunkset_power8.c -- VSX inline functions to copy small data chunks. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef POWER8_VSX +#include +#include "../../zbuild.h" + +typedef vector unsigned char chunk_t; + +#define CHUNK_SIZE 16 + +#define HAVE_CHUNKMEMSET_2 +#define HAVE_CHUNKMEMSET_4 +#define HAVE_CHUNKMEMSET_8 + +static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { + uint16_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = (vector unsigned char)vec_splats(tmp); +} + +static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { + uint32_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = (vector unsigned char)vec_splats(tmp); +} + +static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { + uint64_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = (vector unsigned char)vec_splats((unsigned long long)tmp); +} + +static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { + *chunk = vec_xl(0, s); +} + +static inline void storechunk(uint8_t *out, chunk_t *chunk) { + vec_xst(*chunk, 0, out); +} + +#define CHUNKSIZE chunksize_power8 +#define CHUNKCOPY chunkcopy_power8 +#define CHUNKUNROLL chunkunroll_power8 +#define CHUNKMEMSET chunkmemset_power8 +#define CHUNKMEMSET_SAFE chunkmemset_safe_power8 + +#include "chunkset_tpl.h" + +#define INFLATE_FAST inflate_fast_power8 + +#include "inffast_tpl.h" + +#endif diff --git a/3rdparty/zlib-ng/arch/power/compare256_power9.c b/3rdparty/zlib-ng/arch/power/compare256_power9.c new file mode 100644 index 000000000000..9b0ddaf80045 --- /dev/null +++ b/3rdparty/zlib-ng/arch/power/compare256_power9.c @@ -0,0 +1,64 @@ +/* compare256_power9.c - Power9 version of compare256 + * Copyright (C) 2019 Matheus Castanho , IBM + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef POWER9 +#include +#include "../../zbuild.h" +#include "../../zendian.h" + +/* Older versions of GCC misimplemented semantics for these bit counting builtins. + * https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=3f30f2d1dbb3228b8468b26239fe60c2974ce2ac */ +#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ < 12) +#if BYTE_ORDER == LITTLE_ENDIAN +# define zng_vec_vctzlsbb(vc, len) len = __builtin_vec_vctzlsbb(vc) +#else +# define zng_vec_vctzlsbb(vc, len) len = __builtin_vec_vclzlsbb(vc) +#endif +#else +# define zng_vec_vctzlsbb(vc, len) len = vec_cntlz_lsbb(vc) +#endif + +static inline uint32_t compare256_power9_static(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0, cmplen; + + do { + vector unsigned char vsrc0, vsrc1, vc; + + vsrc0 = *((vector unsigned char *)src0); + vsrc1 = *((vector unsigned char *)src1); + + /* Compare 16 bytes at a time. Each byte of vc will be either + * all ones or all zeroes, depending on the result of the comparison. */ + vc = (vector unsigned char)vec_cmpne(vsrc0, vsrc1); + + /* Since the index of matching bytes will contain only zeroes + * on vc (since we used cmpne), counting the number of consecutive + * bytes where LSB == 0 is the same as counting the length of the match. */ + zng_vec_vctzlsbb(vc, cmplen); + if (cmplen != 16) + return len + cmplen; + + src0 += 16, src1 += 16, len += 16; + } while (len < 256); + + return 256; +} + +Z_INTERNAL uint32_t compare256_power9(const uint8_t *src0, const uint8_t *src1) { + return compare256_power9_static(src0, src1); +} + +#define LONGEST_MATCH longest_match_power9 +#define COMPARE256 compare256_power9_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_power9 +#define COMPARE256 compare256_power9_static + +#include "match_tpl.h" + +#endif diff --git a/3rdparty/zlib-ng/arch/power/crc32_constants.h b/3rdparty/zlib-ng/arch/power/crc32_constants.h new file mode 100644 index 000000000000..8c8f2153b60e --- /dev/null +++ b/3rdparty/zlib-ng/arch/power/crc32_constants.h @@ -0,0 +1,1123 @@ +/* Constants table used by crc32_power8.c + * Copyright (C) 2021 IBM Corporation + * + * This file was automatically generated, DO NOT EDIT IT MANUALLY. + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zendian.h" +#include "zbuild.h" + +/* Reduce 262144 kbits to 1024 bits */ +static const __vector unsigned long long vcrc_const[255] ALIGNED_(16) = { +#if BYTE_ORDER == LITTLE_ENDIAN + /* x^261120 mod p(x)` << 1, x^261184 mod p(x)` << 1 */ + { 0x0000000099ea94a8, 0x00000001651797d2 }, + /* x^260096 mod p(x)` << 1, x^260160 mod p(x)` << 1 */ + { 0x00000000945a8420, 0x0000000021e0d56c }, + /* x^259072 mod p(x)` << 1, x^259136 mod p(x)` << 1 */ + { 0x0000000030762706, 0x000000000f95ecaa }, + /* x^258048 mod p(x)` << 1, x^258112 mod p(x)` << 1 */ + { 0x00000001a52fc582, 0x00000001ebd224ac }, + /* x^257024 mod p(x)` << 1, x^257088 mod p(x)` << 1 */ + { 0x00000001a4a7167a, 0x000000000ccb97ca }, + /* x^256000 mod p(x)` << 1, x^256064 mod p(x)` << 1 */ + { 0x000000000c18249a, 0x00000001006ec8a8 }, + /* x^254976 mod p(x)` << 1, x^255040 mod p(x)` << 1 */ + { 0x00000000a924ae7c, 0x000000014f58f196 }, + /* x^253952 mod p(x)` << 1, x^254016 mod p(x)` << 1 */ + { 0x00000001e12ccc12, 0x00000001a7192ca6 }, + /* x^252928 mod p(x)` << 1, x^252992 mod p(x)` << 1 */ + { 0x00000000a0b9d4ac, 0x000000019a64bab2 }, + /* x^251904 mod p(x)` << 1, x^251968 mod p(x)` << 1 */ + { 0x0000000095e8ddfe, 0x0000000014f4ed2e }, + /* x^250880 mod p(x)` << 1, x^250944 mod p(x)` << 1 */ + { 0x00000000233fddc4, 0x000000011092b6a2 }, + /* x^249856 mod p(x)` << 1, x^249920 mod p(x)` << 1 */ + { 0x00000001b4529b62, 0x00000000c8a1629c }, + /* x^248832 mod p(x)` << 1, x^248896 mod p(x)` << 1 */ + { 0x00000001a7fa0e64, 0x000000017bf32e8e }, + /* x^247808 mod p(x)` << 1, x^247872 mod p(x)` << 1 */ + { 0x00000001b5334592, 0x00000001f8cc6582 }, + /* x^246784 mod p(x)` << 1, x^246848 mod p(x)` << 1 */ + { 0x000000011f8ee1b4, 0x000000008631ddf0 }, + /* x^245760 mod p(x)` << 1, x^245824 mod p(x)` << 1 */ + { 0x000000006252e632, 0x000000007e5a76d0 }, + /* x^244736 mod p(x)` << 1, x^244800 mod p(x)` << 1 */ + { 0x00000000ab973e84, 0x000000002b09b31c }, + /* x^243712 mod p(x)` << 1, x^243776 mod p(x)` << 1 */ + { 0x000000007734f5ec, 0x00000001b2df1f84 }, + /* x^242688 mod p(x)` << 1, x^242752 mod p(x)` << 1 */ + { 0x000000007c547798, 0x00000001d6f56afc }, + /* x^241664 mod p(x)` << 1, x^241728 mod p(x)` << 1 */ + { 0x000000007ec40210, 0x00000001b9b5e70c }, + /* x^240640 mod p(x)` << 1, x^240704 mod p(x)` << 1 */ + { 0x00000001ab1695a8, 0x0000000034b626d2 }, + /* x^239616 mod p(x)` << 1, x^239680 mod p(x)` << 1 */ + { 0x0000000090494bba, 0x000000014c53479a }, + /* x^238592 mod p(x)` << 1, x^238656 mod p(x)` << 1 */ + { 0x00000001123fb816, 0x00000001a6d179a4 }, + /* x^237568 mod p(x)` << 1, x^237632 mod p(x)` << 1 */ + { 0x00000001e188c74c, 0x000000015abd16b4 }, + /* x^236544 mod p(x)` << 1, x^236608 mod p(x)` << 1 */ + { 0x00000001c2d3451c, 0x00000000018f9852 }, + /* x^235520 mod p(x)` << 1, x^235584 mod p(x)` << 1 */ + { 0x00000000f55cf1ca, 0x000000001fb3084a }, + /* x^234496 mod p(x)` << 1, x^234560 mod p(x)` << 1 */ + { 0x00000001a0531540, 0x00000000c53dfb04 }, + /* x^233472 mod p(x)` << 1, x^233536 mod p(x)` << 1 */ + { 0x0000000132cd7ebc, 0x00000000e10c9ad6 }, + /* x^232448 mod p(x)` << 1, x^232512 mod p(x)` << 1 */ + { 0x0000000073ab7f36, 0x0000000025aa994a }, + /* x^231424 mod p(x)` << 1, x^231488 mod p(x)` << 1 */ + { 0x0000000041aed1c2, 0x00000000fa3a74c4 }, + /* x^230400 mod p(x)` << 1, x^230464 mod p(x)` << 1 */ + { 0x0000000136c53800, 0x0000000033eb3f40 }, + /* x^229376 mod p(x)` << 1, x^229440 mod p(x)` << 1 */ + { 0x0000000126835a30, 0x000000017193f296 }, + /* x^228352 mod p(x)` << 1, x^228416 mod p(x)` << 1 */ + { 0x000000006241b502, 0x0000000043f6c86a }, + /* x^227328 mod p(x)` << 1, x^227392 mod p(x)` << 1 */ + { 0x00000000d5196ad4, 0x000000016b513ec6 }, + /* x^226304 mod p(x)` << 1, x^226368 mod p(x)` << 1 */ + { 0x000000009cfa769a, 0x00000000c8f25b4e }, + /* x^225280 mod p(x)` << 1, x^225344 mod p(x)` << 1 */ + { 0x00000000920e5df4, 0x00000001a45048ec }, + /* x^224256 mod p(x)` << 1, x^224320 mod p(x)` << 1 */ + { 0x0000000169dc310e, 0x000000000c441004 }, + /* x^223232 mod p(x)` << 1, x^223296 mod p(x)` << 1 */ + { 0x0000000009fc331c, 0x000000000e17cad6 }, + /* x^222208 mod p(x)` << 1, x^222272 mod p(x)` << 1 */ + { 0x000000010d94a81e, 0x00000001253ae964 }, + /* x^221184 mod p(x)` << 1, x^221248 mod p(x)` << 1 */ + { 0x0000000027a20ab2, 0x00000001d7c88ebc }, + /* x^220160 mod p(x)` << 1, x^220224 mod p(x)` << 1 */ + { 0x0000000114f87504, 0x00000001e7ca913a }, + /* x^219136 mod p(x)` << 1, x^219200 mod p(x)` << 1 */ + { 0x000000004b076d96, 0x0000000033ed078a }, + /* x^218112 mod p(x)` << 1, x^218176 mod p(x)` << 1 */ + { 0x00000000da4d1e74, 0x00000000e1839c78 }, + /* x^217088 mod p(x)` << 1, x^217152 mod p(x)` << 1 */ + { 0x000000001b81f672, 0x00000001322b267e }, + /* x^216064 mod p(x)` << 1, x^216128 mod p(x)` << 1 */ + { 0x000000009367c988, 0x00000000638231b6 }, + /* x^215040 mod p(x)` << 1, x^215104 mod p(x)` << 1 */ + { 0x00000001717214ca, 0x00000001ee7f16f4 }, + /* x^214016 mod p(x)` << 1, x^214080 mod p(x)` << 1 */ + { 0x000000009f47d820, 0x0000000117d9924a }, + /* x^212992 mod p(x)` << 1, x^213056 mod p(x)` << 1 */ + { 0x000000010d9a47d2, 0x00000000e1a9e0c4 }, + /* x^211968 mod p(x)` << 1, x^212032 mod p(x)` << 1 */ + { 0x00000000a696c58c, 0x00000001403731dc }, + /* x^210944 mod p(x)` << 1, x^211008 mod p(x)` << 1 */ + { 0x000000002aa28ec6, 0x00000001a5ea9682 }, + /* x^209920 mod p(x)` << 1, x^209984 mod p(x)` << 1 */ + { 0x00000001fe18fd9a, 0x0000000101c5c578 }, + /* x^208896 mod p(x)` << 1, x^208960 mod p(x)` << 1 */ + { 0x000000019d4fc1ae, 0x00000000dddf6494 }, + /* x^207872 mod p(x)` << 1, x^207936 mod p(x)` << 1 */ + { 0x00000001ba0e3dea, 0x00000000f1c3db28 }, + /* x^206848 mod p(x)` << 1, x^206912 mod p(x)` << 1 */ + { 0x0000000074b59a5e, 0x000000013112fb9c }, + /* x^205824 mod p(x)` << 1, x^205888 mod p(x)` << 1 */ + { 0x00000000f2b5ea98, 0x00000000b680b906 }, + /* x^204800 mod p(x)` << 1, x^204864 mod p(x)` << 1 */ + { 0x0000000187132676, 0x000000001a282932 }, + /* x^203776 mod p(x)` << 1, x^203840 mod p(x)` << 1 */ + { 0x000000010a8c6ad4, 0x0000000089406e7e }, + /* x^202752 mod p(x)` << 1, x^202816 mod p(x)` << 1 */ + { 0x00000001e21dfe70, 0x00000001def6be8c }, + /* x^201728 mod p(x)` << 1, x^201792 mod p(x)` << 1 */ + { 0x00000001da0050e4, 0x0000000075258728 }, + /* x^200704 mod p(x)` << 1, x^200768 mod p(x)` << 1 */ + { 0x00000000772172ae, 0x000000019536090a }, + /* x^199680 mod p(x)` << 1, x^199744 mod p(x)` << 1 */ + { 0x00000000e47724aa, 0x00000000f2455bfc }, + /* x^198656 mod p(x)` << 1, x^198720 mod p(x)` << 1 */ + { 0x000000003cd63ac4, 0x000000018c40baf4 }, + /* x^197632 mod p(x)` << 1, x^197696 mod p(x)` << 1 */ + { 0x00000001bf47d352, 0x000000004cd390d4 }, + /* x^196608 mod p(x)` << 1, x^196672 mod p(x)` << 1 */ + { 0x000000018dc1d708, 0x00000001e4ece95a }, + /* x^195584 mod p(x)` << 1, x^195648 mod p(x)` << 1 */ + { 0x000000002d4620a4, 0x000000001a3ee918 }, + /* x^194560 mod p(x)` << 1, x^194624 mod p(x)` << 1 */ + { 0x0000000058fd1740, 0x000000007c652fb8 }, + /* x^193536 mod p(x)` << 1, x^193600 mod p(x)` << 1 */ + { 0x00000000dadd9bfc, 0x000000011c67842c }, + /* x^192512 mod p(x)` << 1, x^192576 mod p(x)` << 1 */ + { 0x00000001ea2140be, 0x00000000254f759c }, + /* x^191488 mod p(x)` << 1, x^191552 mod p(x)` << 1 */ + { 0x000000009de128ba, 0x000000007ece94ca }, + /* x^190464 mod p(x)` << 1, x^190528 mod p(x)` << 1 */ + { 0x000000013ac3aa8e, 0x0000000038f258c2 }, + /* x^189440 mod p(x)` << 1, x^189504 mod p(x)` << 1 */ + { 0x0000000099980562, 0x00000001cdf17b00 }, + /* x^188416 mod p(x)` << 1, x^188480 mod p(x)` << 1 */ + { 0x00000001c1579c86, 0x000000011f882c16 }, + /* x^187392 mod p(x)` << 1, x^187456 mod p(x)` << 1 */ + { 0x0000000068dbbf94, 0x0000000100093fc8 }, + /* x^186368 mod p(x)` << 1, x^186432 mod p(x)` << 1 */ + { 0x000000004509fb04, 0x00000001cd684f16 }, + /* x^185344 mod p(x)` << 1, x^185408 mod p(x)` << 1 */ + { 0x00000001202f6398, 0x000000004bc6a70a }, + /* x^184320 mod p(x)` << 1, x^184384 mod p(x)` << 1 */ + { 0x000000013aea243e, 0x000000004fc7e8e4 }, + /* x^183296 mod p(x)` << 1, x^183360 mod p(x)` << 1 */ + { 0x00000001b4052ae6, 0x0000000130103f1c }, + /* x^182272 mod p(x)` << 1, x^182336 mod p(x)` << 1 */ + { 0x00000001cd2a0ae8, 0x0000000111b0024c }, + /* x^181248 mod p(x)` << 1, x^181312 mod p(x)` << 1 */ + { 0x00000001fe4aa8b4, 0x000000010b3079da }, + /* x^180224 mod p(x)` << 1, x^180288 mod p(x)` << 1 */ + { 0x00000001d1559a42, 0x000000010192bcc2 }, + /* x^179200 mod p(x)` << 1, x^179264 mod p(x)` << 1 */ + { 0x00000001f3e05ecc, 0x0000000074838d50 }, + /* x^178176 mod p(x)` << 1, x^178240 mod p(x)` << 1 */ + { 0x0000000104ddd2cc, 0x000000001b20f520 }, + /* x^177152 mod p(x)` << 1, x^177216 mod p(x)` << 1 */ + { 0x000000015393153c, 0x0000000050c3590a }, + /* x^176128 mod p(x)` << 1, x^176192 mod p(x)` << 1 */ + { 0x0000000057e942c6, 0x00000000b41cac8e }, + /* x^175104 mod p(x)` << 1, x^175168 mod p(x)` << 1 */ + { 0x000000012c633850, 0x000000000c72cc78 }, + /* x^174080 mod p(x)` << 1, x^174144 mod p(x)` << 1 */ + { 0x00000000ebcaae4c, 0x0000000030cdb032 }, + /* x^173056 mod p(x)` << 1, x^173120 mod p(x)` << 1 */ + { 0x000000013ee532a6, 0x000000013e09fc32 }, + /* x^172032 mod p(x)` << 1, x^172096 mod p(x)` << 1 */ + { 0x00000001bf0cbc7e, 0x000000001ed624d2 }, + /* x^171008 mod p(x)` << 1, x^171072 mod p(x)` << 1 */ + { 0x00000000d50b7a5a, 0x00000000781aee1a }, + /* x^169984 mod p(x)` << 1, x^170048 mod p(x)` << 1 */ + { 0x0000000002fca6e8, 0x00000001c4d8348c }, + /* x^168960 mod p(x)` << 1, x^169024 mod p(x)` << 1 */ + { 0x000000007af40044, 0x0000000057a40336 }, + /* x^167936 mod p(x)` << 1, x^168000 mod p(x)` << 1 */ + { 0x0000000016178744, 0x0000000085544940 }, + /* x^166912 mod p(x)` << 1, x^166976 mod p(x)` << 1 */ + { 0x000000014c177458, 0x000000019cd21e80 }, + /* x^165888 mod p(x)` << 1, x^165952 mod p(x)` << 1 */ + { 0x000000011b6ddf04, 0x000000013eb95bc0 }, + /* x^164864 mod p(x)` << 1, x^164928 mod p(x)` << 1 */ + { 0x00000001f3e29ccc, 0x00000001dfc9fdfc }, + /* x^163840 mod p(x)` << 1, x^163904 mod p(x)` << 1 */ + { 0x0000000135ae7562, 0x00000000cd028bc2 }, + /* x^162816 mod p(x)` << 1, x^162880 mod p(x)` << 1 */ + { 0x0000000190ef812c, 0x0000000090db8c44 }, + /* x^161792 mod p(x)` << 1, x^161856 mod p(x)` << 1 */ + { 0x0000000067a2c786, 0x000000010010a4ce }, + /* x^160768 mod p(x)` << 1, x^160832 mod p(x)` << 1 */ + { 0x0000000048b9496c, 0x00000001c8f4c72c }, + /* x^159744 mod p(x)` << 1, x^159808 mod p(x)` << 1 */ + { 0x000000015a422de6, 0x000000001c26170c }, + /* x^158720 mod p(x)` << 1, x^158784 mod p(x)` << 1 */ + { 0x00000001ef0e3640, 0x00000000e3fccf68 }, + /* x^157696 mod p(x)` << 1, x^157760 mod p(x)` << 1 */ + { 0x00000001006d2d26, 0x00000000d513ed24 }, + /* x^156672 mod p(x)` << 1, x^156736 mod p(x)` << 1 */ + { 0x00000001170d56d6, 0x00000000141beada }, + /* x^155648 mod p(x)` << 1, x^155712 mod p(x)` << 1 */ + { 0x00000000a5fb613c, 0x000000011071aea0 }, + /* x^154624 mod p(x)` << 1, x^154688 mod p(x)` << 1 */ + { 0x0000000040bbf7fc, 0x000000012e19080a }, + /* x^153600 mod p(x)` << 1, x^153664 mod p(x)` << 1 */ + { 0x000000016ac3a5b2, 0x0000000100ecf826 }, + /* x^152576 mod p(x)` << 1, x^152640 mod p(x)` << 1 */ + { 0x00000000abf16230, 0x0000000069b09412 }, + /* x^151552 mod p(x)` << 1, x^151616 mod p(x)` << 1 */ + { 0x00000001ebe23fac, 0x0000000122297bac }, + /* x^150528 mod p(x)` << 1, x^150592 mod p(x)` << 1 */ + { 0x000000008b6a0894, 0x00000000e9e4b068 }, + /* x^149504 mod p(x)` << 1, x^149568 mod p(x)` << 1 */ + { 0x00000001288ea478, 0x000000004b38651a }, + /* x^148480 mod p(x)` << 1, x^148544 mod p(x)` << 1 */ + { 0x000000016619c442, 0x00000001468360e2 }, + /* x^147456 mod p(x)` << 1, x^147520 mod p(x)` << 1 */ + { 0x0000000086230038, 0x00000000121c2408 }, + /* x^146432 mod p(x)` << 1, x^146496 mod p(x)` << 1 */ + { 0x000000017746a756, 0x00000000da7e7d08 }, + /* x^145408 mod p(x)` << 1, x^145472 mod p(x)` << 1 */ + { 0x0000000191b8f8f8, 0x00000001058d7652 }, + /* x^144384 mod p(x)` << 1, x^144448 mod p(x)` << 1 */ + { 0x000000008e167708, 0x000000014a098a90 }, + /* x^143360 mod p(x)` << 1, x^143424 mod p(x)` << 1 */ + { 0x0000000148b22d54, 0x0000000020dbe72e }, + /* x^142336 mod p(x)` << 1, x^142400 mod p(x)` << 1 */ + { 0x0000000044ba2c3c, 0x000000011e7323e8 }, + /* x^141312 mod p(x)` << 1, x^141376 mod p(x)` << 1 */ + { 0x00000000b54d2b52, 0x00000000d5d4bf94 }, + /* x^140288 mod p(x)` << 1, x^140352 mod p(x)` << 1 */ + { 0x0000000005a4fd8a, 0x0000000199d8746c }, + /* x^139264 mod p(x)` << 1, x^139328 mod p(x)` << 1 */ + { 0x0000000139f9fc46, 0x00000000ce9ca8a0 }, + /* x^138240 mod p(x)` << 1, x^138304 mod p(x)` << 1 */ + { 0x000000015a1fa824, 0x00000000136edece }, + /* x^137216 mod p(x)` << 1, x^137280 mod p(x)` << 1 */ + { 0x000000000a61ae4c, 0x000000019b92a068 }, + /* x^136192 mod p(x)` << 1, x^136256 mod p(x)` << 1 */ + { 0x0000000145e9113e, 0x0000000071d62206 }, + /* x^135168 mod p(x)` << 1, x^135232 mod p(x)` << 1 */ + { 0x000000006a348448, 0x00000000dfc50158 }, + /* x^134144 mod p(x)` << 1, x^134208 mod p(x)` << 1 */ + { 0x000000004d80a08c, 0x00000001517626bc }, + /* x^133120 mod p(x)` << 1, x^133184 mod p(x)` << 1 */ + { 0x000000014b6837a0, 0x0000000148d1e4fa }, + /* x^132096 mod p(x)` << 1, x^132160 mod p(x)` << 1 */ + { 0x000000016896a7fc, 0x0000000094d8266e }, + /* x^131072 mod p(x)` << 1, x^131136 mod p(x)` << 1 */ + { 0x000000014f187140, 0x00000000606c5e34 }, + /* x^130048 mod p(x)` << 1, x^130112 mod p(x)` << 1 */ + { 0x000000019581b9da, 0x000000019766beaa }, + /* x^129024 mod p(x)` << 1, x^129088 mod p(x)` << 1 */ + { 0x00000001091bc984, 0x00000001d80c506c }, + /* x^128000 mod p(x)` << 1, x^128064 mod p(x)` << 1 */ + { 0x000000001067223c, 0x000000001e73837c }, + /* x^126976 mod p(x)` << 1, x^127040 mod p(x)` << 1 */ + { 0x00000001ab16ea02, 0x0000000064d587de }, + /* x^125952 mod p(x)` << 1, x^126016 mod p(x)` << 1 */ + { 0x000000013c4598a8, 0x00000000f4a507b0 }, + /* x^124928 mod p(x)` << 1, x^124992 mod p(x)` << 1 */ + { 0x00000000b3735430, 0x0000000040e342fc }, + /* x^123904 mod p(x)` << 1, x^123968 mod p(x)` << 1 */ + { 0x00000001bb3fc0c0, 0x00000001d5ad9c3a }, + /* x^122880 mod p(x)` << 1, x^122944 mod p(x)` << 1 */ + { 0x00000001570ae19c, 0x0000000094a691a4 }, + /* x^121856 mod p(x)` << 1, x^121920 mod p(x)` << 1 */ + { 0x00000001ea910712, 0x00000001271ecdfa }, + /* x^120832 mod p(x)` << 1, x^120896 mod p(x)` << 1 */ + { 0x0000000167127128, 0x000000009e54475a }, + /* x^119808 mod p(x)` << 1, x^119872 mod p(x)` << 1 */ + { 0x0000000019e790a2, 0x00000000c9c099ee }, + /* x^118784 mod p(x)` << 1, x^118848 mod p(x)` << 1 */ + { 0x000000003788f710, 0x000000009a2f736c }, + /* x^117760 mod p(x)` << 1, x^117824 mod p(x)` << 1 */ + { 0x00000001682a160e, 0x00000000bb9f4996 }, + /* x^116736 mod p(x)` << 1, x^116800 mod p(x)` << 1 */ + { 0x000000007f0ebd2e, 0x00000001db688050 }, + /* x^115712 mod p(x)` << 1, x^115776 mod p(x)` << 1 */ + { 0x000000002b032080, 0x00000000e9b10af4 }, + /* x^114688 mod p(x)` << 1, x^114752 mod p(x)` << 1 */ + { 0x00000000cfd1664a, 0x000000012d4545e4 }, + /* x^113664 mod p(x)` << 1, x^113728 mod p(x)` << 1 */ + { 0x00000000aa1181c2, 0x000000000361139c }, + /* x^112640 mod p(x)` << 1, x^112704 mod p(x)` << 1 */ + { 0x00000000ddd08002, 0x00000001a5a1a3a8 }, + /* x^111616 mod p(x)` << 1, x^111680 mod p(x)` << 1 */ + { 0x00000000e8dd0446, 0x000000006844e0b0 }, + /* x^110592 mod p(x)` << 1, x^110656 mod p(x)` << 1 */ + { 0x00000001bbd94a00, 0x00000000c3762f28 }, + /* x^109568 mod p(x)` << 1, x^109632 mod p(x)` << 1 */ + { 0x00000000ab6cd180, 0x00000001d26287a2 }, + /* x^108544 mod p(x)` << 1, x^108608 mod p(x)` << 1 */ + { 0x0000000031803ce2, 0x00000001f6f0bba8 }, + /* x^107520 mod p(x)` << 1, x^107584 mod p(x)` << 1 */ + { 0x0000000024f40b0c, 0x000000002ffabd62 }, + /* x^106496 mod p(x)` << 1, x^106560 mod p(x)` << 1 */ + { 0x00000001ba1d9834, 0x00000000fb4516b8 }, + /* x^105472 mod p(x)` << 1, x^105536 mod p(x)` << 1 */ + { 0x0000000104de61aa, 0x000000018cfa961c }, + /* x^104448 mod p(x)` << 1, x^104512 mod p(x)` << 1 */ + { 0x0000000113e40d46, 0x000000019e588d52 }, + /* x^103424 mod p(x)` << 1, x^103488 mod p(x)` << 1 */ + { 0x00000001415598a0, 0x00000001180f0bbc }, + /* x^102400 mod p(x)` << 1, x^102464 mod p(x)` << 1 */ + { 0x00000000bf6c8c90, 0x00000000e1d9177a }, + /* x^101376 mod p(x)` << 1, x^101440 mod p(x)` << 1 */ + { 0x00000001788b0504, 0x0000000105abc27c }, + /* x^100352 mod p(x)` << 1, x^100416 mod p(x)` << 1 */ + { 0x0000000038385d02, 0x00000000972e4a58 }, + /* x^99328 mod p(x)` << 1, x^99392 mod p(x)` << 1 */ + { 0x00000001b6c83844, 0x0000000183499a5e }, + /* x^98304 mod p(x)` << 1, x^98368 mod p(x)` << 1 */ + { 0x0000000051061a8a, 0x00000001c96a8cca }, + /* x^97280 mod p(x)` << 1, x^97344 mod p(x)` << 1 */ + { 0x000000017351388a, 0x00000001a1a5b60c }, + /* x^96256 mod p(x)` << 1, x^96320 mod p(x)` << 1 */ + { 0x0000000132928f92, 0x00000000e4b6ac9c }, + /* x^95232 mod p(x)` << 1, x^95296 mod p(x)` << 1 */ + { 0x00000000e6b4f48a, 0x00000001807e7f5a }, + /* x^94208 mod p(x)` << 1, x^94272 mod p(x)` << 1 */ + { 0x0000000039d15e90, 0x000000017a7e3bc8 }, + /* x^93184 mod p(x)` << 1, x^93248 mod p(x)` << 1 */ + { 0x00000000312d6074, 0x00000000d73975da }, + /* x^92160 mod p(x)` << 1, x^92224 mod p(x)` << 1 */ + { 0x000000017bbb2cc4, 0x000000017375d038 }, + /* x^91136 mod p(x)` << 1, x^91200 mod p(x)` << 1 */ + { 0x000000016ded3e18, 0x00000000193680bc }, + /* x^90112 mod p(x)` << 1, x^90176 mod p(x)` << 1 */ + { 0x00000000f1638b16, 0x00000000999b06f6 }, + /* x^89088 mod p(x)` << 1, x^89152 mod p(x)` << 1 */ + { 0x00000001d38b9ecc, 0x00000001f685d2b8 }, + /* x^88064 mod p(x)` << 1, x^88128 mod p(x)` << 1 */ + { 0x000000018b8d09dc, 0x00000001f4ecbed2 }, + /* x^87040 mod p(x)` << 1, x^87104 mod p(x)` << 1 */ + { 0x00000000e7bc27d2, 0x00000000ba16f1a0 }, + /* x^86016 mod p(x)` << 1, x^86080 mod p(x)` << 1 */ + { 0x00000000275e1e96, 0x0000000115aceac4 }, + /* x^84992 mod p(x)` << 1, x^85056 mod p(x)` << 1 */ + { 0x00000000e2e3031e, 0x00000001aeff6292 }, + /* x^83968 mod p(x)` << 1, x^84032 mod p(x)` << 1 */ + { 0x00000001041c84d8, 0x000000009640124c }, + /* x^82944 mod p(x)` << 1, x^83008 mod p(x)` << 1 */ + { 0x00000000706ce672, 0x0000000114f41f02 }, + /* x^81920 mod p(x)` << 1, x^81984 mod p(x)` << 1 */ + { 0x000000015d5070da, 0x000000009c5f3586 }, + /* x^80896 mod p(x)` << 1, x^80960 mod p(x)` << 1 */ + { 0x0000000038f9493a, 0x00000001878275fa }, + /* x^79872 mod p(x)` << 1, x^79936 mod p(x)` << 1 */ + { 0x00000000a3348a76, 0x00000000ddc42ce8 }, + /* x^78848 mod p(x)` << 1, x^78912 mod p(x)` << 1 */ + { 0x00000001ad0aab92, 0x0000000181d2c73a }, + /* x^77824 mod p(x)` << 1, x^77888 mod p(x)` << 1 */ + { 0x000000019e85f712, 0x0000000141c9320a }, + /* x^76800 mod p(x)` << 1, x^76864 mod p(x)` << 1 */ + { 0x000000005a871e76, 0x000000015235719a }, + /* x^75776 mod p(x)` << 1, x^75840 mod p(x)` << 1 */ + { 0x000000017249c662, 0x00000000be27d804 }, + /* x^74752 mod p(x)` << 1, x^74816 mod p(x)` << 1 */ + { 0x000000003a084712, 0x000000006242d45a }, + /* x^73728 mod p(x)` << 1, x^73792 mod p(x)` << 1 */ + { 0x00000000ed438478, 0x000000009a53638e }, + /* x^72704 mod p(x)` << 1, x^72768 mod p(x)` << 1 */ + { 0x00000000abac34cc, 0x00000001001ecfb6 }, + /* x^71680 mod p(x)` << 1, x^71744 mod p(x)` << 1 */ + { 0x000000005f35ef3e, 0x000000016d7c2d64 }, + /* x^70656 mod p(x)` << 1, x^70720 mod p(x)` << 1 */ + { 0x0000000047d6608c, 0x00000001d0ce46c0 }, + /* x^69632 mod p(x)` << 1, x^69696 mod p(x)` << 1 */ + { 0x000000002d01470e, 0x0000000124c907b4 }, + /* x^68608 mod p(x)` << 1, x^68672 mod p(x)` << 1 */ + { 0x0000000158bbc7b0, 0x0000000018a555ca }, + /* x^67584 mod p(x)` << 1, x^67648 mod p(x)` << 1 */ + { 0x00000000c0a23e8e, 0x000000006b0980bc }, + /* x^66560 mod p(x)` << 1, x^66624 mod p(x)` << 1 */ + { 0x00000001ebd85c88, 0x000000008bbba964 }, + /* x^65536 mod p(x)` << 1, x^65600 mod p(x)` << 1 */ + { 0x000000019ee20bb2, 0x00000001070a5a1e }, + /* x^64512 mod p(x)` << 1, x^64576 mod p(x)` << 1 */ + { 0x00000001acabf2d6, 0x000000002204322a }, + /* x^63488 mod p(x)` << 1, x^63552 mod p(x)` << 1 */ + { 0x00000001b7963d56, 0x00000000a27524d0 }, + /* x^62464 mod p(x)` << 1, x^62528 mod p(x)` << 1 */ + { 0x000000017bffa1fe, 0x0000000020b1e4ba }, + /* x^61440 mod p(x)` << 1, x^61504 mod p(x)` << 1 */ + { 0x000000001f15333e, 0x0000000032cc27fc }, + /* x^60416 mod p(x)` << 1, x^60480 mod p(x)` << 1 */ + { 0x000000018593129e, 0x0000000044dd22b8 }, + /* x^59392 mod p(x)` << 1, x^59456 mod p(x)` << 1 */ + { 0x000000019cb32602, 0x00000000dffc9e0a }, + /* x^58368 mod p(x)` << 1, x^58432 mod p(x)` << 1 */ + { 0x0000000142b05cc8, 0x00000001b7a0ed14 }, + /* x^57344 mod p(x)` << 1, x^57408 mod p(x)` << 1 */ + { 0x00000001be49e7a4, 0x00000000c7842488 }, + /* x^56320 mod p(x)` << 1, x^56384 mod p(x)` << 1 */ + { 0x0000000108f69d6c, 0x00000001c02a4fee }, + /* x^55296 mod p(x)` << 1, x^55360 mod p(x)` << 1 */ + { 0x000000006c0971f0, 0x000000003c273778 }, + /* x^54272 mod p(x)` << 1, x^54336 mod p(x)` << 1 */ + { 0x000000005b16467a, 0x00000001d63f8894 }, + /* x^53248 mod p(x)` << 1, x^53312 mod p(x)` << 1 */ + { 0x00000001551a628e, 0x000000006be557d6 }, + /* x^52224 mod p(x)` << 1, x^52288 mod p(x)` << 1 */ + { 0x000000019e42ea92, 0x000000006a7806ea }, + /* x^51200 mod p(x)` << 1, x^51264 mod p(x)` << 1 */ + { 0x000000012fa83ff2, 0x000000016155aa0c }, + /* x^50176 mod p(x)` << 1, x^50240 mod p(x)` << 1 */ + { 0x000000011ca9cde0, 0x00000000908650ac }, + /* x^49152 mod p(x)` << 1, x^49216 mod p(x)` << 1 */ + { 0x00000000c8e5cd74, 0x00000000aa5a8084 }, + /* x^48128 mod p(x)` << 1, x^48192 mod p(x)` << 1 */ + { 0x0000000096c27f0c, 0x0000000191bb500a }, + /* x^47104 mod p(x)` << 1, x^47168 mod p(x)` << 1 */ + { 0x000000002baed926, 0x0000000064e9bed0 }, + /* x^46080 mod p(x)` << 1, x^46144 mod p(x)` << 1 */ + { 0x000000017c8de8d2, 0x000000009444f302 }, + /* x^45056 mod p(x)` << 1, x^45120 mod p(x)` << 1 */ + { 0x00000000d43d6068, 0x000000019db07d3c }, + /* x^44032 mod p(x)` << 1, x^44096 mod p(x)` << 1 */ + { 0x00000000cb2c4b26, 0x00000001359e3e6e }, + /* x^43008 mod p(x)` << 1, x^43072 mod p(x)` << 1 */ + { 0x0000000145b8da26, 0x00000001e4f10dd2 }, + /* x^41984 mod p(x)` << 1, x^42048 mod p(x)` << 1 */ + { 0x000000018fff4b08, 0x0000000124f5735e }, + /* x^40960 mod p(x)` << 1, x^41024 mod p(x)` << 1 */ + { 0x0000000150b58ed0, 0x0000000124760a4c }, + /* x^39936 mod p(x)` << 1, x^40000 mod p(x)` << 1 */ + { 0x00000001549f39bc, 0x000000000f1fc186 }, + /* x^38912 mod p(x)` << 1, x^38976 mod p(x)` << 1 */ + { 0x00000000ef4d2f42, 0x00000000150e4cc4 }, + /* x^37888 mod p(x)` << 1, x^37952 mod p(x)` << 1 */ + { 0x00000001b1468572, 0x000000002a6204e8 }, + /* x^36864 mod p(x)` << 1, x^36928 mod p(x)` << 1 */ + { 0x000000013d7403b2, 0x00000000beb1d432 }, + /* x^35840 mod p(x)` << 1, x^35904 mod p(x)` << 1 */ + { 0x00000001a4681842, 0x0000000135f3f1f0 }, + /* x^34816 mod p(x)` << 1, x^34880 mod p(x)` << 1 */ + { 0x0000000167714492, 0x0000000074fe2232 }, + /* x^33792 mod p(x)` << 1, x^33856 mod p(x)` << 1 */ + { 0x00000001e599099a, 0x000000001ac6e2ba }, + /* x^32768 mod p(x)` << 1, x^32832 mod p(x)` << 1 */ + { 0x00000000fe128194, 0x0000000013fca91e }, + /* x^31744 mod p(x)` << 1, x^31808 mod p(x)` << 1 */ + { 0x0000000077e8b990, 0x0000000183f4931e }, + /* x^30720 mod p(x)` << 1, x^30784 mod p(x)` << 1 */ + { 0x00000001a267f63a, 0x00000000b6d9b4e4 }, + /* x^29696 mod p(x)` << 1, x^29760 mod p(x)` << 1 */ + { 0x00000001945c245a, 0x00000000b5188656 }, + /* x^28672 mod p(x)` << 1, x^28736 mod p(x)` << 1 */ + { 0x0000000149002e76, 0x0000000027a81a84 }, + /* x^27648 mod p(x)` << 1, x^27712 mod p(x)` << 1 */ + { 0x00000001bb8310a4, 0x0000000125699258 }, + /* x^26624 mod p(x)` << 1, x^26688 mod p(x)` << 1 */ + { 0x000000019ec60bcc, 0x00000001b23de796 }, + /* x^25600 mod p(x)` << 1, x^25664 mod p(x)` << 1 */ + { 0x000000012d8590ae, 0x00000000fe4365dc }, + /* x^24576 mod p(x)` << 1, x^24640 mod p(x)` << 1 */ + { 0x0000000065b00684, 0x00000000c68f497a }, + /* x^23552 mod p(x)` << 1, x^23616 mod p(x)` << 1 */ + { 0x000000015e5aeadc, 0x00000000fbf521ee }, + /* x^22528 mod p(x)` << 1, x^22592 mod p(x)` << 1 */ + { 0x00000000b77ff2b0, 0x000000015eac3378 }, + /* x^21504 mod p(x)` << 1, x^21568 mod p(x)` << 1 */ + { 0x0000000188da2ff6, 0x0000000134914b90 }, + /* x^20480 mod p(x)` << 1, x^20544 mod p(x)` << 1 */ + { 0x0000000063da929a, 0x0000000016335cfe }, + /* x^19456 mod p(x)` << 1, x^19520 mod p(x)` << 1 */ + { 0x00000001389caa80, 0x000000010372d10c }, + /* x^18432 mod p(x)` << 1, x^18496 mod p(x)` << 1 */ + { 0x000000013db599d2, 0x000000015097b908 }, + /* x^17408 mod p(x)` << 1, x^17472 mod p(x)` << 1 */ + { 0x0000000122505a86, 0x00000001227a7572 }, + /* x^16384 mod p(x)` << 1, x^16448 mod p(x)` << 1 */ + { 0x000000016bd72746, 0x000000009a8f75c0 }, + /* x^15360 mod p(x)` << 1, x^15424 mod p(x)` << 1 */ + { 0x00000001c3faf1d4, 0x00000000682c77a2 }, + /* x^14336 mod p(x)` << 1, x^14400 mod p(x)` << 1 */ + { 0x00000001111c826c, 0x00000000231f091c }, + /* x^13312 mod p(x)` << 1, x^13376 mod p(x)` << 1 */ + { 0x00000000153e9fb2, 0x000000007d4439f2 }, + /* x^12288 mod p(x)` << 1, x^12352 mod p(x)` << 1 */ + { 0x000000002b1f7b60, 0x000000017e221efc }, + /* x^11264 mod p(x)` << 1, x^11328 mod p(x)` << 1 */ + { 0x00000000b1dba570, 0x0000000167457c38 }, + /* x^10240 mod p(x)` << 1, x^10304 mod p(x)` << 1 */ + { 0x00000001f6397b76, 0x00000000bdf081c4 }, + /* x^9216 mod p(x)` << 1, x^9280 mod p(x)` << 1 */ + { 0x0000000156335214, 0x000000016286d6b0 }, + /* x^8192 mod p(x)` << 1, x^8256 mod p(x)` << 1 */ + { 0x00000001d70e3986, 0x00000000c84f001c }, + /* x^7168 mod p(x)` << 1, x^7232 mod p(x)` << 1 */ + { 0x000000003701a774, 0x0000000064efe7c0 }, + /* x^6144 mod p(x)` << 1, x^6208 mod p(x)` << 1 */ + { 0x00000000ac81ef72, 0x000000000ac2d904 }, + /* x^5120 mod p(x)` << 1, x^5184 mod p(x)` << 1 */ + { 0x0000000133212464, 0x00000000fd226d14 }, + /* x^4096 mod p(x)` << 1, x^4160 mod p(x)` << 1 */ + { 0x00000000e4e45610, 0x000000011cfd42e0 }, + /* x^3072 mod p(x)` << 1, x^3136 mod p(x)` << 1 */ + { 0x000000000c1bd370, 0x000000016e5a5678 }, + /* x^2048 mod p(x)` << 1, x^2112 mod p(x)` << 1 */ + { 0x00000001a7b9e7a6, 0x00000001d888fe22 }, + /* x^1024 mod p(x)` << 1, x^1088 mod p(x)` << 1 */ + { 0x000000007d657a10, 0x00000001af77fcd4 } +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + /* x^261120 mod p(x)` << 1, x^261184 mod p(x)` << 1 */ + { 0x00000001651797d2, 0x0000000099ea94a8 }, + /* x^260096 mod p(x)` << 1, x^260160 mod p(x)` << 1 */ + { 0x0000000021e0d56c, 0x00000000945a8420 }, + /* x^259072 mod p(x)` << 1, x^259136 mod p(x)` << 1 */ + { 0x000000000f95ecaa, 0x0000000030762706 }, + /* x^258048 mod p(x)` << 1, x^258112 mod p(x)` << 1 */ + { 0x00000001ebd224ac, 0x00000001a52fc582 }, + /* x^257024 mod p(x)` << 1, x^257088 mod p(x)` << 1 */ + { 0x000000000ccb97ca, 0x00000001a4a7167a }, + /* x^256000 mod p(x)` << 1, x^256064 mod p(x)` << 1 */ + { 0x00000001006ec8a8, 0x000000000c18249a }, + /* x^254976 mod p(x)` << 1, x^255040 mod p(x)` << 1 */ + { 0x000000014f58f196, 0x00000000a924ae7c }, + /* x^253952 mod p(x)` << 1, x^254016 mod p(x)` << 1 */ + { 0x00000001a7192ca6, 0x00000001e12ccc12 }, + /* x^252928 mod p(x)` << 1, x^252992 mod p(x)` << 1 */ + { 0x000000019a64bab2, 0x00000000a0b9d4ac }, + /* x^251904 mod p(x)` << 1, x^251968 mod p(x)` << 1 */ + { 0x0000000014f4ed2e, 0x0000000095e8ddfe }, + /* x^250880 mod p(x)` << 1, x^250944 mod p(x)` << 1 */ + { 0x000000011092b6a2, 0x00000000233fddc4 }, + /* x^249856 mod p(x)` << 1, x^249920 mod p(x)` << 1 */ + { 0x00000000c8a1629c, 0x00000001b4529b62 }, + /* x^248832 mod p(x)` << 1, x^248896 mod p(x)` << 1 */ + { 0x000000017bf32e8e, 0x00000001a7fa0e64 }, + /* x^247808 mod p(x)` << 1, x^247872 mod p(x)` << 1 */ + { 0x00000001f8cc6582, 0x00000001b5334592 }, + /* x^246784 mod p(x)` << 1, x^246848 mod p(x)` << 1 */ + { 0x000000008631ddf0, 0x000000011f8ee1b4 }, + /* x^245760 mod p(x)` << 1, x^245824 mod p(x)` << 1 */ + { 0x000000007e5a76d0, 0x000000006252e632 }, + /* x^244736 mod p(x)` << 1, x^244800 mod p(x)` << 1 */ + { 0x000000002b09b31c, 0x00000000ab973e84 }, + /* x^243712 mod p(x)` << 1, x^243776 mod p(x)` << 1 */ + { 0x00000001b2df1f84, 0x000000007734f5ec }, + /* x^242688 mod p(x)` << 1, x^242752 mod p(x)` << 1 */ + { 0x00000001d6f56afc, 0x000000007c547798 }, + /* x^241664 mod p(x)` << 1, x^241728 mod p(x)` << 1 */ + { 0x00000001b9b5e70c, 0x000000007ec40210 }, + /* x^240640 mod p(x)` << 1, x^240704 mod p(x)` << 1 */ + { 0x0000000034b626d2, 0x00000001ab1695a8 }, + /* x^239616 mod p(x)` << 1, x^239680 mod p(x)` << 1 */ + { 0x000000014c53479a, 0x0000000090494bba }, + /* x^238592 mod p(x)` << 1, x^238656 mod p(x)` << 1 */ + { 0x00000001a6d179a4, 0x00000001123fb816 }, + /* x^237568 mod p(x)` << 1, x^237632 mod p(x)` << 1 */ + { 0x000000015abd16b4, 0x00000001e188c74c }, + /* x^236544 mod p(x)` << 1, x^236608 mod p(x)` << 1 */ + { 0x00000000018f9852, 0x00000001c2d3451c }, + /* x^235520 mod p(x)` << 1, x^235584 mod p(x)` << 1 */ + { 0x000000001fb3084a, 0x00000000f55cf1ca }, + /* x^234496 mod p(x)` << 1, x^234560 mod p(x)` << 1 */ + { 0x00000000c53dfb04, 0x00000001a0531540 }, + /* x^233472 mod p(x)` << 1, x^233536 mod p(x)` << 1 */ + { 0x00000000e10c9ad6, 0x0000000132cd7ebc }, + /* x^232448 mod p(x)` << 1, x^232512 mod p(x)` << 1 */ + { 0x0000000025aa994a, 0x0000000073ab7f36 }, + /* x^231424 mod p(x)` << 1, x^231488 mod p(x)` << 1 */ + { 0x00000000fa3a74c4, 0x0000000041aed1c2 }, + /* x^230400 mod p(x)` << 1, x^230464 mod p(x)` << 1 */ + { 0x0000000033eb3f40, 0x0000000136c53800 }, + /* x^229376 mod p(x)` << 1, x^229440 mod p(x)` << 1 */ + { 0x000000017193f296, 0x0000000126835a30 }, + /* x^228352 mod p(x)` << 1, x^228416 mod p(x)` << 1 */ + { 0x0000000043f6c86a, 0x000000006241b502 }, + /* x^227328 mod p(x)` << 1, x^227392 mod p(x)` << 1 */ + { 0x000000016b513ec6, 0x00000000d5196ad4 }, + /* x^226304 mod p(x)` << 1, x^226368 mod p(x)` << 1 */ + { 0x00000000c8f25b4e, 0x000000009cfa769a }, + /* x^225280 mod p(x)` << 1, x^225344 mod p(x)` << 1 */ + { 0x00000001a45048ec, 0x00000000920e5df4 }, + /* x^224256 mod p(x)` << 1, x^224320 mod p(x)` << 1 */ + { 0x000000000c441004, 0x0000000169dc310e }, + /* x^223232 mod p(x)` << 1, x^223296 mod p(x)` << 1 */ + { 0x000000000e17cad6, 0x0000000009fc331c }, + /* x^222208 mod p(x)` << 1, x^222272 mod p(x)` << 1 */ + { 0x00000001253ae964, 0x000000010d94a81e }, + /* x^221184 mod p(x)` << 1, x^221248 mod p(x)` << 1 */ + { 0x00000001d7c88ebc, 0x0000000027a20ab2 }, + /* x^220160 mod p(x)` << 1, x^220224 mod p(x)` << 1 */ + { 0x00000001e7ca913a, 0x0000000114f87504 }, + /* x^219136 mod p(x)` << 1, x^219200 mod p(x)` << 1 */ + { 0x0000000033ed078a, 0x000000004b076d96 }, + /* x^218112 mod p(x)` << 1, x^218176 mod p(x)` << 1 */ + { 0x00000000e1839c78, 0x00000000da4d1e74 }, + /* x^217088 mod p(x)` << 1, x^217152 mod p(x)` << 1 */ + { 0x00000001322b267e, 0x000000001b81f672 }, + /* x^216064 mod p(x)` << 1, x^216128 mod p(x)` << 1 */ + { 0x00000000638231b6, 0x000000009367c988 }, + /* x^215040 mod p(x)` << 1, x^215104 mod p(x)` << 1 */ + { 0x00000001ee7f16f4, 0x00000001717214ca }, + /* x^214016 mod p(x)` << 1, x^214080 mod p(x)` << 1 */ + { 0x0000000117d9924a, 0x000000009f47d820 }, + /* x^212992 mod p(x)` << 1, x^213056 mod p(x)` << 1 */ + { 0x00000000e1a9e0c4, 0x000000010d9a47d2 }, + /* x^211968 mod p(x)` << 1, x^212032 mod p(x)` << 1 */ + { 0x00000001403731dc, 0x00000000a696c58c }, + /* x^210944 mod p(x)` << 1, x^211008 mod p(x)` << 1 */ + { 0x00000001a5ea9682, 0x000000002aa28ec6 }, + /* x^209920 mod p(x)` << 1, x^209984 mod p(x)` << 1 */ + { 0x0000000101c5c578, 0x00000001fe18fd9a }, + /* x^208896 mod p(x)` << 1, x^208960 mod p(x)` << 1 */ + { 0x00000000dddf6494, 0x000000019d4fc1ae }, + /* x^207872 mod p(x)` << 1, x^207936 mod p(x)` << 1 */ + { 0x00000000f1c3db28, 0x00000001ba0e3dea }, + /* x^206848 mod p(x)` << 1, x^206912 mod p(x)` << 1 */ + { 0x000000013112fb9c, 0x0000000074b59a5e }, + /* x^205824 mod p(x)` << 1, x^205888 mod p(x)` << 1 */ + { 0x00000000b680b906, 0x00000000f2b5ea98 }, + /* x^204800 mod p(x)` << 1, x^204864 mod p(x)` << 1 */ + { 0x000000001a282932, 0x0000000187132676 }, + /* x^203776 mod p(x)` << 1, x^203840 mod p(x)` << 1 */ + { 0x0000000089406e7e, 0x000000010a8c6ad4 }, + /* x^202752 mod p(x)` << 1, x^202816 mod p(x)` << 1 */ + { 0x00000001def6be8c, 0x00000001e21dfe70 }, + /* x^201728 mod p(x)` << 1, x^201792 mod p(x)` << 1 */ + { 0x0000000075258728, 0x00000001da0050e4 }, + /* x^200704 mod p(x)` << 1, x^200768 mod p(x)` << 1 */ + { 0x000000019536090a, 0x00000000772172ae }, + /* x^199680 mod p(x)` << 1, x^199744 mod p(x)` << 1 */ + { 0x00000000f2455bfc, 0x00000000e47724aa }, + /* x^198656 mod p(x)` << 1, x^198720 mod p(x)` << 1 */ + { 0x000000018c40baf4, 0x000000003cd63ac4 }, + /* x^197632 mod p(x)` << 1, x^197696 mod p(x)` << 1 */ + { 0x000000004cd390d4, 0x00000001bf47d352 }, + /* x^196608 mod p(x)` << 1, x^196672 mod p(x)` << 1 */ + { 0x00000001e4ece95a, 0x000000018dc1d708 }, + /* x^195584 mod p(x)` << 1, x^195648 mod p(x)` << 1 */ + { 0x000000001a3ee918, 0x000000002d4620a4 }, + /* x^194560 mod p(x)` << 1, x^194624 mod p(x)` << 1 */ + { 0x000000007c652fb8, 0x0000000058fd1740 }, + /* x^193536 mod p(x)` << 1, x^193600 mod p(x)` << 1 */ + { 0x000000011c67842c, 0x00000000dadd9bfc }, + /* x^192512 mod p(x)` << 1, x^192576 mod p(x)` << 1 */ + { 0x00000000254f759c, 0x00000001ea2140be }, + /* x^191488 mod p(x)` << 1, x^191552 mod p(x)` << 1 */ + { 0x000000007ece94ca, 0x000000009de128ba }, + /* x^190464 mod p(x)` << 1, x^190528 mod p(x)` << 1 */ + { 0x0000000038f258c2, 0x000000013ac3aa8e }, + /* x^189440 mod p(x)` << 1, x^189504 mod p(x)` << 1 */ + { 0x00000001cdf17b00, 0x0000000099980562 }, + /* x^188416 mod p(x)` << 1, x^188480 mod p(x)` << 1 */ + { 0x000000011f882c16, 0x00000001c1579c86 }, + /* x^187392 mod p(x)` << 1, x^187456 mod p(x)` << 1 */ + { 0x0000000100093fc8, 0x0000000068dbbf94 }, + /* x^186368 mod p(x)` << 1, x^186432 mod p(x)` << 1 */ + { 0x00000001cd684f16, 0x000000004509fb04 }, + /* x^185344 mod p(x)` << 1, x^185408 mod p(x)` << 1 */ + { 0x000000004bc6a70a, 0x00000001202f6398 }, + /* x^184320 mod p(x)` << 1, x^184384 mod p(x)` << 1 */ + { 0x000000004fc7e8e4, 0x000000013aea243e }, + /* x^183296 mod p(x)` << 1, x^183360 mod p(x)` << 1 */ + { 0x0000000130103f1c, 0x00000001b4052ae6 }, + /* x^182272 mod p(x)` << 1, x^182336 mod p(x)` << 1 */ + { 0x0000000111b0024c, 0x00000001cd2a0ae8 }, + /* x^181248 mod p(x)` << 1, x^181312 mod p(x)` << 1 */ + { 0x000000010b3079da, 0x00000001fe4aa8b4 }, + /* x^180224 mod p(x)` << 1, x^180288 mod p(x)` << 1 */ + { 0x000000010192bcc2, 0x00000001d1559a42 }, + /* x^179200 mod p(x)` << 1, x^179264 mod p(x)` << 1 */ + { 0x0000000074838d50, 0x00000001f3e05ecc }, + /* x^178176 mod p(x)` << 1, x^178240 mod p(x)` << 1 */ + { 0x000000001b20f520, 0x0000000104ddd2cc }, + /* x^177152 mod p(x)` << 1, x^177216 mod p(x)` << 1 */ + { 0x0000000050c3590a, 0x000000015393153c }, + /* x^176128 mod p(x)` << 1, x^176192 mod p(x)` << 1 */ + { 0x00000000b41cac8e, 0x0000000057e942c6 }, + /* x^175104 mod p(x)` << 1, x^175168 mod p(x)` << 1 */ + { 0x000000000c72cc78, 0x000000012c633850 }, + /* x^174080 mod p(x)` << 1, x^174144 mod p(x)` << 1 */ + { 0x0000000030cdb032, 0x00000000ebcaae4c }, + /* x^173056 mod p(x)` << 1, x^173120 mod p(x)` << 1 */ + { 0x000000013e09fc32, 0x000000013ee532a6 }, + /* x^172032 mod p(x)` << 1, x^172096 mod p(x)` << 1 */ + { 0x000000001ed624d2, 0x00000001bf0cbc7e }, + /* x^171008 mod p(x)` << 1, x^171072 mod p(x)` << 1 */ + { 0x00000000781aee1a, 0x00000000d50b7a5a }, + /* x^169984 mod p(x)` << 1, x^170048 mod p(x)` << 1 */ + { 0x00000001c4d8348c, 0x0000000002fca6e8 }, + /* x^168960 mod p(x)` << 1, x^169024 mod p(x)` << 1 */ + { 0x0000000057a40336, 0x000000007af40044 }, + /* x^167936 mod p(x)` << 1, x^168000 mod p(x)` << 1 */ + { 0x0000000085544940, 0x0000000016178744 }, + /* x^166912 mod p(x)` << 1, x^166976 mod p(x)` << 1 */ + { 0x000000019cd21e80, 0x000000014c177458 }, + /* x^165888 mod p(x)` << 1, x^165952 mod p(x)` << 1 */ + { 0x000000013eb95bc0, 0x000000011b6ddf04 }, + /* x^164864 mod p(x)` << 1, x^164928 mod p(x)` << 1 */ + { 0x00000001dfc9fdfc, 0x00000001f3e29ccc }, + /* x^163840 mod p(x)` << 1, x^163904 mod p(x)` << 1 */ + { 0x00000000cd028bc2, 0x0000000135ae7562 }, + /* x^162816 mod p(x)` << 1, x^162880 mod p(x)` << 1 */ + { 0x0000000090db8c44, 0x0000000190ef812c }, + /* x^161792 mod p(x)` << 1, x^161856 mod p(x)` << 1 */ + { 0x000000010010a4ce, 0x0000000067a2c786 }, + /* x^160768 mod p(x)` << 1, x^160832 mod p(x)` << 1 */ + { 0x00000001c8f4c72c, 0x0000000048b9496c }, + /* x^159744 mod p(x)` << 1, x^159808 mod p(x)` << 1 */ + { 0x000000001c26170c, 0x000000015a422de6 }, + /* x^158720 mod p(x)` << 1, x^158784 mod p(x)` << 1 */ + { 0x00000000e3fccf68, 0x00000001ef0e3640 }, + /* x^157696 mod p(x)` << 1, x^157760 mod p(x)` << 1 */ + { 0x00000000d513ed24, 0x00000001006d2d26 }, + /* x^156672 mod p(x)` << 1, x^156736 mod p(x)` << 1 */ + { 0x00000000141beada, 0x00000001170d56d6 }, + /* x^155648 mod p(x)` << 1, x^155712 mod p(x)` << 1 */ + { 0x000000011071aea0, 0x00000000a5fb613c }, + /* x^154624 mod p(x)` << 1, x^154688 mod p(x)` << 1 */ + { 0x000000012e19080a, 0x0000000040bbf7fc }, + /* x^153600 mod p(x)` << 1, x^153664 mod p(x)` << 1 */ + { 0x0000000100ecf826, 0x000000016ac3a5b2 }, + /* x^152576 mod p(x)` << 1, x^152640 mod p(x)` << 1 */ + { 0x0000000069b09412, 0x00000000abf16230 }, + /* x^151552 mod p(x)` << 1, x^151616 mod p(x)` << 1 */ + { 0x0000000122297bac, 0x00000001ebe23fac }, + /* x^150528 mod p(x)` << 1, x^150592 mod p(x)` << 1 */ + { 0x00000000e9e4b068, 0x000000008b6a0894 }, + /* x^149504 mod p(x)` << 1, x^149568 mod p(x)` << 1 */ + { 0x000000004b38651a, 0x00000001288ea478 }, + /* x^148480 mod p(x)` << 1, x^148544 mod p(x)` << 1 */ + { 0x00000001468360e2, 0x000000016619c442 }, + /* x^147456 mod p(x)` << 1, x^147520 mod p(x)` << 1 */ + { 0x00000000121c2408, 0x0000000086230038 }, + /* x^146432 mod p(x)` << 1, x^146496 mod p(x)` << 1 */ + { 0x00000000da7e7d08, 0x000000017746a756 }, + /* x^145408 mod p(x)` << 1, x^145472 mod p(x)` << 1 */ + { 0x00000001058d7652, 0x0000000191b8f8f8 }, + /* x^144384 mod p(x)` << 1, x^144448 mod p(x)` << 1 */ + { 0x000000014a098a90, 0x000000008e167708 }, + /* x^143360 mod p(x)` << 1, x^143424 mod p(x)` << 1 */ + { 0x0000000020dbe72e, 0x0000000148b22d54 }, + /* x^142336 mod p(x)` << 1, x^142400 mod p(x)` << 1 */ + { 0x000000011e7323e8, 0x0000000044ba2c3c }, + /* x^141312 mod p(x)` << 1, x^141376 mod p(x)` << 1 */ + { 0x00000000d5d4bf94, 0x00000000b54d2b52 }, + /* x^140288 mod p(x)` << 1, x^140352 mod p(x)` << 1 */ + { 0x0000000199d8746c, 0x0000000005a4fd8a }, + /* x^139264 mod p(x)` << 1, x^139328 mod p(x)` << 1 */ + { 0x00000000ce9ca8a0, 0x0000000139f9fc46 }, + /* x^138240 mod p(x)` << 1, x^138304 mod p(x)` << 1 */ + { 0x00000000136edece, 0x000000015a1fa824 }, + /* x^137216 mod p(x)` << 1, x^137280 mod p(x)` << 1 */ + { 0x000000019b92a068, 0x000000000a61ae4c }, + /* x^136192 mod p(x)` << 1, x^136256 mod p(x)` << 1 */ + { 0x0000000071d62206, 0x0000000145e9113e }, + /* x^135168 mod p(x)` << 1, x^135232 mod p(x)` << 1 */ + { 0x00000000dfc50158, 0x000000006a348448 }, + /* x^134144 mod p(x)` << 1, x^134208 mod p(x)` << 1 */ + { 0x00000001517626bc, 0x000000004d80a08c }, + /* x^133120 mod p(x)` << 1, x^133184 mod p(x)` << 1 */ + { 0x0000000148d1e4fa, 0x000000014b6837a0 }, + /* x^132096 mod p(x)` << 1, x^132160 mod p(x)` << 1 */ + { 0x0000000094d8266e, 0x000000016896a7fc }, + /* x^131072 mod p(x)` << 1, x^131136 mod p(x)` << 1 */ + { 0x00000000606c5e34, 0x000000014f187140 }, + /* x^130048 mod p(x)` << 1, x^130112 mod p(x)` << 1 */ + { 0x000000019766beaa, 0x000000019581b9da }, + /* x^129024 mod p(x)` << 1, x^129088 mod p(x)` << 1 */ + { 0x00000001d80c506c, 0x00000001091bc984 }, + /* x^128000 mod p(x)` << 1, x^128064 mod p(x)` << 1 */ + { 0x000000001e73837c, 0x000000001067223c }, + /* x^126976 mod p(x)` << 1, x^127040 mod p(x)` << 1 */ + { 0x0000000064d587de, 0x00000001ab16ea02 }, + /* x^125952 mod p(x)` << 1, x^126016 mod p(x)` << 1 */ + { 0x00000000f4a507b0, 0x000000013c4598a8 }, + /* x^124928 mod p(x)` << 1, x^124992 mod p(x)` << 1 */ + { 0x0000000040e342fc, 0x00000000b3735430 }, + /* x^123904 mod p(x)` << 1, x^123968 mod p(x)` << 1 */ + { 0x00000001d5ad9c3a, 0x00000001bb3fc0c0 }, + /* x^122880 mod p(x)` << 1, x^122944 mod p(x)` << 1 */ + { 0x0000000094a691a4, 0x00000001570ae19c }, + /* x^121856 mod p(x)` << 1, x^121920 mod p(x)` << 1 */ + { 0x00000001271ecdfa, 0x00000001ea910712 }, + /* x^120832 mod p(x)` << 1, x^120896 mod p(x)` << 1 */ + { 0x000000009e54475a, 0x0000000167127128 }, + /* x^119808 mod p(x)` << 1, x^119872 mod p(x)` << 1 */ + { 0x00000000c9c099ee, 0x0000000019e790a2 }, + /* x^118784 mod p(x)` << 1, x^118848 mod p(x)` << 1 */ + { 0x000000009a2f736c, 0x000000003788f710 }, + /* x^117760 mod p(x)` << 1, x^117824 mod p(x)` << 1 */ + { 0x00000000bb9f4996, 0x00000001682a160e }, + /* x^116736 mod p(x)` << 1, x^116800 mod p(x)` << 1 */ + { 0x00000001db688050, 0x000000007f0ebd2e }, + /* x^115712 mod p(x)` << 1, x^115776 mod p(x)` << 1 */ + { 0x00000000e9b10af4, 0x000000002b032080 }, + /* x^114688 mod p(x)` << 1, x^114752 mod p(x)` << 1 */ + { 0x000000012d4545e4, 0x00000000cfd1664a }, + /* x^113664 mod p(x)` << 1, x^113728 mod p(x)` << 1 */ + { 0x000000000361139c, 0x00000000aa1181c2 }, + /* x^112640 mod p(x)` << 1, x^112704 mod p(x)` << 1 */ + { 0x00000001a5a1a3a8, 0x00000000ddd08002 }, + /* x^111616 mod p(x)` << 1, x^111680 mod p(x)` << 1 */ + { 0x000000006844e0b0, 0x00000000e8dd0446 }, + /* x^110592 mod p(x)` << 1, x^110656 mod p(x)` << 1 */ + { 0x00000000c3762f28, 0x00000001bbd94a00 }, + /* x^109568 mod p(x)` << 1, x^109632 mod p(x)` << 1 */ + { 0x00000001d26287a2, 0x00000000ab6cd180 }, + /* x^108544 mod p(x)` << 1, x^108608 mod p(x)` << 1 */ + { 0x00000001f6f0bba8, 0x0000000031803ce2 }, + /* x^107520 mod p(x)` << 1, x^107584 mod p(x)` << 1 */ + { 0x000000002ffabd62, 0x0000000024f40b0c }, + /* x^106496 mod p(x)` << 1, x^106560 mod p(x)` << 1 */ + { 0x00000000fb4516b8, 0x00000001ba1d9834 }, + /* x^105472 mod p(x)` << 1, x^105536 mod p(x)` << 1 */ + { 0x000000018cfa961c, 0x0000000104de61aa }, + /* x^104448 mod p(x)` << 1, x^104512 mod p(x)` << 1 */ + { 0x000000019e588d52, 0x0000000113e40d46 }, + /* x^103424 mod p(x)` << 1, x^103488 mod p(x)` << 1 */ + { 0x00000001180f0bbc, 0x00000001415598a0 }, + /* x^102400 mod p(x)` << 1, x^102464 mod p(x)` << 1 */ + { 0x00000000e1d9177a, 0x00000000bf6c8c90 }, + /* x^101376 mod p(x)` << 1, x^101440 mod p(x)` << 1 */ + { 0x0000000105abc27c, 0x00000001788b0504 }, + /* x^100352 mod p(x)` << 1, x^100416 mod p(x)` << 1 */ + { 0x00000000972e4a58, 0x0000000038385d02 }, + /* x^99328 mod p(x)` << 1, x^99392 mod p(x)` << 1 */ + { 0x0000000183499a5e, 0x00000001b6c83844 }, + /* x^98304 mod p(x)` << 1, x^98368 mod p(x)` << 1 */ + { 0x00000001c96a8cca, 0x0000000051061a8a }, + /* x^97280 mod p(x)` << 1, x^97344 mod p(x)` << 1 */ + { 0x00000001a1a5b60c, 0x000000017351388a }, + /* x^96256 mod p(x)` << 1, x^96320 mod p(x)` << 1 */ + { 0x00000000e4b6ac9c, 0x0000000132928f92 }, + /* x^95232 mod p(x)` << 1, x^95296 mod p(x)` << 1 */ + { 0x00000001807e7f5a, 0x00000000e6b4f48a }, + /* x^94208 mod p(x)` << 1, x^94272 mod p(x)` << 1 */ + { 0x000000017a7e3bc8, 0x0000000039d15e90 }, + /* x^93184 mod p(x)` << 1, x^93248 mod p(x)` << 1 */ + { 0x00000000d73975da, 0x00000000312d6074 }, + /* x^92160 mod p(x)` << 1, x^92224 mod p(x)` << 1 */ + { 0x000000017375d038, 0x000000017bbb2cc4 }, + /* x^91136 mod p(x)` << 1, x^91200 mod p(x)` << 1 */ + { 0x00000000193680bc, 0x000000016ded3e18 }, + /* x^90112 mod p(x)` << 1, x^90176 mod p(x)` << 1 */ + { 0x00000000999b06f6, 0x00000000f1638b16 }, + /* x^89088 mod p(x)` << 1, x^89152 mod p(x)` << 1 */ + { 0x00000001f685d2b8, 0x00000001d38b9ecc }, + /* x^88064 mod p(x)` << 1, x^88128 mod p(x)` << 1 */ + { 0x00000001f4ecbed2, 0x000000018b8d09dc }, + /* x^87040 mod p(x)` << 1, x^87104 mod p(x)` << 1 */ + { 0x00000000ba16f1a0, 0x00000000e7bc27d2 }, + /* x^86016 mod p(x)` << 1, x^86080 mod p(x)` << 1 */ + { 0x0000000115aceac4, 0x00000000275e1e96 }, + /* x^84992 mod p(x)` << 1, x^85056 mod p(x)` << 1 */ + { 0x00000001aeff6292, 0x00000000e2e3031e }, + /* x^83968 mod p(x)` << 1, x^84032 mod p(x)` << 1 */ + { 0x000000009640124c, 0x00000001041c84d8 }, + /* x^82944 mod p(x)` << 1, x^83008 mod p(x)` << 1 */ + { 0x0000000114f41f02, 0x00000000706ce672 }, + /* x^81920 mod p(x)` << 1, x^81984 mod p(x)` << 1 */ + { 0x000000009c5f3586, 0x000000015d5070da }, + /* x^80896 mod p(x)` << 1, x^80960 mod p(x)` << 1 */ + { 0x00000001878275fa, 0x0000000038f9493a }, + /* x^79872 mod p(x)` << 1, x^79936 mod p(x)` << 1 */ + { 0x00000000ddc42ce8, 0x00000000a3348a76 }, + /* x^78848 mod p(x)` << 1, x^78912 mod p(x)` << 1 */ + { 0x0000000181d2c73a, 0x00000001ad0aab92 }, + /* x^77824 mod p(x)` << 1, x^77888 mod p(x)` << 1 */ + { 0x0000000141c9320a, 0x000000019e85f712 }, + /* x^76800 mod p(x)` << 1, x^76864 mod p(x)` << 1 */ + { 0x000000015235719a, 0x000000005a871e76 }, + /* x^75776 mod p(x)` << 1, x^75840 mod p(x)` << 1 */ + { 0x00000000be27d804, 0x000000017249c662 }, + /* x^74752 mod p(x)` << 1, x^74816 mod p(x)` << 1 */ + { 0x000000006242d45a, 0x000000003a084712 }, + /* x^73728 mod p(x)` << 1, x^73792 mod p(x)` << 1 */ + { 0x000000009a53638e, 0x00000000ed438478 }, + /* x^72704 mod p(x)` << 1, x^72768 mod p(x)` << 1 */ + { 0x00000001001ecfb6, 0x00000000abac34cc }, + /* x^71680 mod p(x)` << 1, x^71744 mod p(x)` << 1 */ + { 0x000000016d7c2d64, 0x000000005f35ef3e }, + /* x^70656 mod p(x)` << 1, x^70720 mod p(x)` << 1 */ + { 0x00000001d0ce46c0, 0x0000000047d6608c }, + /* x^69632 mod p(x)` << 1, x^69696 mod p(x)` << 1 */ + { 0x0000000124c907b4, 0x000000002d01470e }, + /* x^68608 mod p(x)` << 1, x^68672 mod p(x)` << 1 */ + { 0x0000000018a555ca, 0x0000000158bbc7b0 }, + /* x^67584 mod p(x)` << 1, x^67648 mod p(x)` << 1 */ + { 0x000000006b0980bc, 0x00000000c0a23e8e }, + /* x^66560 mod p(x)` << 1, x^66624 mod p(x)` << 1 */ + { 0x000000008bbba964, 0x00000001ebd85c88 }, + /* x^65536 mod p(x)` << 1, x^65600 mod p(x)` << 1 */ + { 0x00000001070a5a1e, 0x000000019ee20bb2 }, + /* x^64512 mod p(x)` << 1, x^64576 mod p(x)` << 1 */ + { 0x000000002204322a, 0x00000001acabf2d6 }, + /* x^63488 mod p(x)` << 1, x^63552 mod p(x)` << 1 */ + { 0x00000000a27524d0, 0x00000001b7963d56 }, + /* x^62464 mod p(x)` << 1, x^62528 mod p(x)` << 1 */ + { 0x0000000020b1e4ba, 0x000000017bffa1fe }, + /* x^61440 mod p(x)` << 1, x^61504 mod p(x)` << 1 */ + { 0x0000000032cc27fc, 0x000000001f15333e }, + /* x^60416 mod p(x)` << 1, x^60480 mod p(x)` << 1 */ + { 0x0000000044dd22b8, 0x000000018593129e }, + /* x^59392 mod p(x)` << 1, x^59456 mod p(x)` << 1 */ + { 0x00000000dffc9e0a, 0x000000019cb32602 }, + /* x^58368 mod p(x)` << 1, x^58432 mod p(x)` << 1 */ + { 0x00000001b7a0ed14, 0x0000000142b05cc8 }, + /* x^57344 mod p(x)` << 1, x^57408 mod p(x)` << 1 */ + { 0x00000000c7842488, 0x00000001be49e7a4 }, + /* x^56320 mod p(x)` << 1, x^56384 mod p(x)` << 1 */ + { 0x00000001c02a4fee, 0x0000000108f69d6c }, + /* x^55296 mod p(x)` << 1, x^55360 mod p(x)` << 1 */ + { 0x000000003c273778, 0x000000006c0971f0 }, + /* x^54272 mod p(x)` << 1, x^54336 mod p(x)` << 1 */ + { 0x00000001d63f8894, 0x000000005b16467a }, + /* x^53248 mod p(x)` << 1, x^53312 mod p(x)` << 1 */ + { 0x000000006be557d6, 0x00000001551a628e }, + /* x^52224 mod p(x)` << 1, x^52288 mod p(x)` << 1 */ + { 0x000000006a7806ea, 0x000000019e42ea92 }, + /* x^51200 mod p(x)` << 1, x^51264 mod p(x)` << 1 */ + { 0x000000016155aa0c, 0x000000012fa83ff2 }, + /* x^50176 mod p(x)` << 1, x^50240 mod p(x)` << 1 */ + { 0x00000000908650ac, 0x000000011ca9cde0 }, + /* x^49152 mod p(x)` << 1, x^49216 mod p(x)` << 1 */ + { 0x00000000aa5a8084, 0x00000000c8e5cd74 }, + /* x^48128 mod p(x)` << 1, x^48192 mod p(x)` << 1 */ + { 0x0000000191bb500a, 0x0000000096c27f0c }, + /* x^47104 mod p(x)` << 1, x^47168 mod p(x)` << 1 */ + { 0x0000000064e9bed0, 0x000000002baed926 }, + /* x^46080 mod p(x)` << 1, x^46144 mod p(x)` << 1 */ + { 0x000000009444f302, 0x000000017c8de8d2 }, + /* x^45056 mod p(x)` << 1, x^45120 mod p(x)` << 1 */ + { 0x000000019db07d3c, 0x00000000d43d6068 }, + /* x^44032 mod p(x)` << 1, x^44096 mod p(x)` << 1 */ + { 0x00000001359e3e6e, 0x00000000cb2c4b26 }, + /* x^43008 mod p(x)` << 1, x^43072 mod p(x)` << 1 */ + { 0x00000001e4f10dd2, 0x0000000145b8da26 }, + /* x^41984 mod p(x)` << 1, x^42048 mod p(x)` << 1 */ + { 0x0000000124f5735e, 0x000000018fff4b08 }, + /* x^40960 mod p(x)` << 1, x^41024 mod p(x)` << 1 */ + { 0x0000000124760a4c, 0x0000000150b58ed0 }, + /* x^39936 mod p(x)` << 1, x^40000 mod p(x)` << 1 */ + { 0x000000000f1fc186, 0x00000001549f39bc }, + /* x^38912 mod p(x)` << 1, x^38976 mod p(x)` << 1 */ + { 0x00000000150e4cc4, 0x00000000ef4d2f42 }, + /* x^37888 mod p(x)` << 1, x^37952 mod p(x)` << 1 */ + { 0x000000002a6204e8, 0x00000001b1468572 }, + /* x^36864 mod p(x)` << 1, x^36928 mod p(x)` << 1 */ + { 0x00000000beb1d432, 0x000000013d7403b2 }, + /* x^35840 mod p(x)` << 1, x^35904 mod p(x)` << 1 */ + { 0x0000000135f3f1f0, 0x00000001a4681842 }, + /* x^34816 mod p(x)` << 1, x^34880 mod p(x)` << 1 */ + { 0x0000000074fe2232, 0x0000000167714492 }, + /* x^33792 mod p(x)` << 1, x^33856 mod p(x)` << 1 */ + { 0x000000001ac6e2ba, 0x00000001e599099a }, + /* x^32768 mod p(x)` << 1, x^32832 mod p(x)` << 1 */ + { 0x0000000013fca91e, 0x00000000fe128194 }, + /* x^31744 mod p(x)` << 1, x^31808 mod p(x)` << 1 */ + { 0x0000000183f4931e, 0x0000000077e8b990 }, + /* x^30720 mod p(x)` << 1, x^30784 mod p(x)` << 1 */ + { 0x00000000b6d9b4e4, 0x00000001a267f63a }, + /* x^29696 mod p(x)` << 1, x^29760 mod p(x)` << 1 */ + { 0x00000000b5188656, 0x00000001945c245a }, + /* x^28672 mod p(x)` << 1, x^28736 mod p(x)` << 1 */ + { 0x0000000027a81a84, 0x0000000149002e76 }, + /* x^27648 mod p(x)` << 1, x^27712 mod p(x)` << 1 */ + { 0x0000000125699258, 0x00000001bb8310a4 }, + /* x^26624 mod p(x)` << 1, x^26688 mod p(x)` << 1 */ + { 0x00000001b23de796, 0x000000019ec60bcc }, + /* x^25600 mod p(x)` << 1, x^25664 mod p(x)` << 1 */ + { 0x00000000fe4365dc, 0x000000012d8590ae }, + /* x^24576 mod p(x)` << 1, x^24640 mod p(x)` << 1 */ + { 0x00000000c68f497a, 0x0000000065b00684 }, + /* x^23552 mod p(x)` << 1, x^23616 mod p(x)` << 1 */ + { 0x00000000fbf521ee, 0x000000015e5aeadc }, + /* x^22528 mod p(x)` << 1, x^22592 mod p(x)` << 1 */ + { 0x000000015eac3378, 0x00000000b77ff2b0 }, + /* x^21504 mod p(x)` << 1, x^21568 mod p(x)` << 1 */ + { 0x0000000134914b90, 0x0000000188da2ff6 }, + /* x^20480 mod p(x)` << 1, x^20544 mod p(x)` << 1 */ + { 0x0000000016335cfe, 0x0000000063da929a }, + /* x^19456 mod p(x)` << 1, x^19520 mod p(x)` << 1 */ + { 0x000000010372d10c, 0x00000001389caa80 }, + /* x^18432 mod p(x)` << 1, x^18496 mod p(x)` << 1 */ + { 0x000000015097b908, 0x000000013db599d2 }, + /* x^17408 mod p(x)` << 1, x^17472 mod p(x)` << 1 */ + { 0x00000001227a7572, 0x0000000122505a86 }, + /* x^16384 mod p(x)` << 1, x^16448 mod p(x)` << 1 */ + { 0x000000009a8f75c0, 0x000000016bd72746 }, + /* x^15360 mod p(x)` << 1, x^15424 mod p(x)` << 1 */ + { 0x00000000682c77a2, 0x00000001c3faf1d4 }, + /* x^14336 mod p(x)` << 1, x^14400 mod p(x)` << 1 */ + { 0x00000000231f091c, 0x00000001111c826c }, + /* x^13312 mod p(x)` << 1, x^13376 mod p(x)` << 1 */ + { 0x000000007d4439f2, 0x00000000153e9fb2 }, + /* x^12288 mod p(x)` << 1, x^12352 mod p(x)` << 1 */ + { 0x000000017e221efc, 0x000000002b1f7b60 }, + /* x^11264 mod p(x)` << 1, x^11328 mod p(x)` << 1 */ + { 0x0000000167457c38, 0x00000000b1dba570 }, + /* x^10240 mod p(x)` << 1, x^10304 mod p(x)` << 1 */ + { 0x00000000bdf081c4, 0x00000001f6397b76 }, + /* x^9216 mod p(x)` << 1, x^9280 mod p(x)` << 1 */ + { 0x000000016286d6b0, 0x0000000156335214 }, + /* x^8192 mod p(x)` << 1, x^8256 mod p(x)` << 1 */ + { 0x00000000c84f001c, 0x00000001d70e3986 }, + /* x^7168 mod p(x)` << 1, x^7232 mod p(x)` << 1 */ + { 0x0000000064efe7c0, 0x000000003701a774 }, + /* x^6144 mod p(x)` << 1, x^6208 mod p(x)` << 1 */ + { 0x000000000ac2d904, 0x00000000ac81ef72 }, + /* x^5120 mod p(x)` << 1, x^5184 mod p(x)` << 1 */ + { 0x00000000fd226d14, 0x0000000133212464 }, + /* x^4096 mod p(x)` << 1, x^4160 mod p(x)` << 1 */ + { 0x000000011cfd42e0, 0x00000000e4e45610 }, + /* x^3072 mod p(x)` << 1, x^3136 mod p(x)` << 1 */ + { 0x000000016e5a5678, 0x000000000c1bd370 }, + /* x^2048 mod p(x)` << 1, x^2112 mod p(x)` << 1 */ + { 0x00000001d888fe22, 0x00000001a7b9e7a6 }, + /* x^1024 mod p(x)` << 1, x^1088 mod p(x)` << 1 */ + { 0x00000001af77fcd4, 0x000000007d657a10 } +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ +}; + +/* Reduce final 1024-2048 bits to 64 bits, shifting 32 bits to include the trailing 32 bits of zeros */ + +static const __vector unsigned long long vcrc_short_const[16] ALIGNED_(16) = { +#if BYTE_ORDER == LITTLE_ENDIAN + /* x^1952 mod p(x) , x^1984 mod p(x) , x^2016 mod p(x) , x^2048 mod p(x) */ + { 0x99168a18ec447f11, 0xed837b2613e8221e }, + /* x^1824 mod p(x) , x^1856 mod p(x) , x^1888 mod p(x) , x^1920 mod p(x) */ + { 0xe23e954e8fd2cd3c, 0xc8acdd8147b9ce5a }, + /* x^1696 mod p(x) , x^1728 mod p(x) , x^1760 mod p(x) , x^1792 mod p(x) */ + { 0x92f8befe6b1d2b53, 0xd9ad6d87d4277e25 }, + /* x^1568 mod p(x) , x^1600 mod p(x) , x^1632 mod p(x) , x^1664 mod p(x) */ + { 0xf38a3556291ea462, 0xc10ec5e033fbca3b }, + /* x^1440 mod p(x) , x^1472 mod p(x) , x^1504 mod p(x) , x^1536 mod p(x) */ + { 0x974ac56262b6ca4b, 0xc0b55b0e82e02e2f }, + /* x^1312 mod p(x) , x^1344 mod p(x) , x^1376 mod p(x) , x^1408 mod p(x) */ + { 0x855712b3784d2a56, 0x71aa1df0e172334d }, + /* x^1184 mod p(x) , x^1216 mod p(x) , x^1248 mod p(x) , x^1280 mod p(x) */ + { 0xa5abe9f80eaee722, 0xfee3053e3969324d }, + /* x^1056 mod p(x) , x^1088 mod p(x) , x^1120 mod p(x) , x^1152 mod p(x) */ + { 0x1fa0943ddb54814c, 0xf44779b93eb2bd08 }, + /* x^928 mod p(x) , x^960 mod p(x) , x^992 mod p(x) , x^1024 mod p(x) */ + { 0xa53ff440d7bbfe6a, 0xf5449b3f00cc3374 }, + /* x^800 mod p(x) , x^832 mod p(x) , x^864 mod p(x) , x^896 mod p(x) */ + { 0xebe7e3566325605c, 0x6f8346e1d777606e }, + /* x^672 mod p(x) , x^704 mod p(x) , x^736 mod p(x) , x^768 mod p(x) */ + { 0xc65a272ce5b592b8, 0xe3ab4f2ac0b95347 }, + /* x^544 mod p(x) , x^576 mod p(x) , x^608 mod p(x) , x^640 mod p(x) */ + { 0x5705a9ca4721589f, 0xaa2215ea329ecc11 }, + /* x^416 mod p(x) , x^448 mod p(x) , x^480 mod p(x) , x^512 mod p(x) */ + { 0xe3720acb88d14467, 0x1ed8f66ed95efd26 }, + /* x^288 mod p(x) , x^320 mod p(x) , x^352 mod p(x) , x^384 mod p(x) */ + { 0xba1aca0315141c31, 0x78ed02d5a700e96a }, + /* x^160 mod p(x) , x^192 mod p(x) , x^224 mod p(x) , x^256 mod p(x) */ + { 0xad2a31b3ed627dae, 0xba8ccbe832b39da3 }, + /* x^32 mod p(x) , x^64 mod p(x) , x^96 mod p(x) , x^128 mod p(x) */ + { 0x6655004fa06a2517, 0xedb88320b1e6b092 } +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + /* x^1952 mod p(x) , x^1984 mod p(x) , x^2016 mod p(x) , x^2048 mod p(x) */ + { 0xed837b2613e8221e, 0x99168a18ec447f11 }, + /* x^1824 mod p(x) , x^1856 mod p(x) , x^1888 mod p(x) , x^1920 mod p(x) */ + { 0xc8acdd8147b9ce5a, 0xe23e954e8fd2cd3c }, + /* x^1696 mod p(x) , x^1728 mod p(x) , x^1760 mod p(x) , x^1792 mod p(x) */ + { 0xd9ad6d87d4277e25, 0x92f8befe6b1d2b53 }, + /* x^1568 mod p(x) , x^1600 mod p(x) , x^1632 mod p(x) , x^1664 mod p(x) */ + { 0xc10ec5e033fbca3b, 0xf38a3556291ea462 }, + /* x^1440 mod p(x) , x^1472 mod p(x) , x^1504 mod p(x) , x^1536 mod p(x) */ + { 0xc0b55b0e82e02e2f, 0x974ac56262b6ca4b }, + /* x^1312 mod p(x) , x^1344 mod p(x) , x^1376 mod p(x) , x^1408 mod p(x) */ + { 0x71aa1df0e172334d, 0x855712b3784d2a56 }, + /* x^1184 mod p(x) , x^1216 mod p(x) , x^1248 mod p(x) , x^1280 mod p(x) */ + { 0xfee3053e3969324d, 0xa5abe9f80eaee722 }, + /* x^1056 mod p(x) , x^1088 mod p(x) , x^1120 mod p(x) , x^1152 mod p(x) */ + { 0xf44779b93eb2bd08, 0x1fa0943ddb54814c }, + /* x^928 mod p(x) , x^960 mod p(x) , x^992 mod p(x) , x^1024 mod p(x) */ + { 0xf5449b3f00cc3374, 0xa53ff440d7bbfe6a }, + /* x^800 mod p(x) , x^832 mod p(x) , x^864 mod p(x) , x^896 mod p(x) */ + { 0x6f8346e1d777606e, 0xebe7e3566325605c }, + /* x^672 mod p(x) , x^704 mod p(x) , x^736 mod p(x) , x^768 mod p(x) */ + { 0xe3ab4f2ac0b95347, 0xc65a272ce5b592b8 }, + /* x^544 mod p(x) , x^576 mod p(x) , x^608 mod p(x) , x^640 mod p(x) */ + { 0xaa2215ea329ecc11, 0x5705a9ca4721589f }, + /* x^416 mod p(x) , x^448 mod p(x) , x^480 mod p(x) , x^512 mod p(x) */ + { 0x1ed8f66ed95efd26, 0xe3720acb88d14467 }, + /* x^288 mod p(x) , x^320 mod p(x) , x^352 mod p(x) , x^384 mod p(x) */ + { 0x78ed02d5a700e96a, 0xba1aca0315141c31 }, + /* x^160 mod p(x) , x^192 mod p(x) , x^224 mod p(x) , x^256 mod p(x) */ + { 0xba8ccbe832b39da3, 0xad2a31b3ed627dae }, + /* x^32 mod p(x) , x^64 mod p(x) , x^96 mod p(x) , x^128 mod p(x) */ + { 0xedb88320b1e6b092, 0x6655004fa06a2517 } +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ +}; + +/* Barrett constants */ +/* 33 bit reflected Barrett constant m - (4^32)/n */ + +static const __vector unsigned long long v_Barrett_const[2] ALIGNED_(16) = { + /* x^64 div p(x) */ +#if BYTE_ORDER == LITTLE_ENDIAN + { 0x00000001f7011641, 0x0000000000000000 }, + { 0x00000001db710641, 0x0000000000000000 } +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + { 0x0000000000000000, 0x00000001f7011641 }, + { 0x0000000000000000, 0x00000001db710641 } +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ +}; diff --git a/3rdparty/zlib-ng/arch/power/crc32_power8.c b/3rdparty/zlib-ng/arch/power/crc32_power8.c new file mode 100644 index 000000000000..1cb5f299f3d9 --- /dev/null +++ b/3rdparty/zlib-ng/arch/power/crc32_power8.c @@ -0,0 +1,589 @@ +/* crc32 for POWER8 using VSX instructions + * Copyright (C) 2021 IBM Corporation + * + * Author: Rogerio Alves + * + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Calculate the checksum of data that is 16 byte aligned and a multiple of + * 16 bytes. + * + * The first step is to reduce it to 1024 bits. We do this in 8 parallel + * chunks in order to mask the latency of the vpmsum instructions. If we + * have more than 32 kB of data to checksum we repeat this step multiple + * times, passing in the previous 1024 bits. + * + * The next step is to reduce the 1024 bits to 64 bits. This step adds + * 32 bits of 0s to the end - this matches what a CRC does. We just + * calculate constants that land the data in this 32 bits. + * + * We then use fixed point Barrett reduction to compute a mod n over GF(2) + * for n = CRC using POWER8 instructions. We use x = 32. + * + * http://en.wikipedia.org/wiki/Barrett_reduction + * + * This code uses gcc vector builtins instead using assembly directly. + */ + +#include +#include "zendian.h" +#include "zbuild.h" + +#include "crc32_constants.h" +#include "crc32_braid_tbl.h" + +#if defined (__clang__) +#include "fallback_builtins.h" +#endif + +#define MAX_SIZE 32768 +#define VMX_ALIGN 16 +#define VMX_ALIGN_MASK (VMX_ALIGN-1) + +static unsigned int crc32_align(unsigned int crc, const unsigned char *p, unsigned long len) { + while (len--) + crc = crc_table[(crc ^ *p++) & 0xff] ^ (crc >> 8); + return crc; +} + +static unsigned int ALIGNED_(32) __crc32_vpmsum(unsigned int crc, const void* p, unsigned long len); + +Z_INTERNAL uint32_t crc32_power8(uint32_t crc, const unsigned char *p, size_t _len) { + unsigned int prealign; + unsigned int tail; + + unsigned long len = (unsigned long) _len; + + if (p == (const unsigned char *) 0x0) + return 0; + + crc ^= 0xffffffff; + + if (len < VMX_ALIGN + VMX_ALIGN_MASK) { + crc = crc32_align(crc, p, len); + goto out; + } + + if ((unsigned long)p & VMX_ALIGN_MASK) { + prealign = VMX_ALIGN - ((unsigned long)p & VMX_ALIGN_MASK); + crc = crc32_align(crc, p, prealign); + len -= prealign; + p += prealign; + } + + crc = __crc32_vpmsum(crc, p, len & ~VMX_ALIGN_MASK); + + tail = len & VMX_ALIGN_MASK; + if (tail) { + p += len & ~VMX_ALIGN_MASK; + crc = crc32_align(crc, p, tail); + } + +out: + crc ^= 0xffffffff; + + return crc; +} + +/* When we have a load-store in a single-dispatch group and address overlap + * such that forward is not allowed (load-hit-store) the group must be flushed. + * A group ending NOP prevents the flush. + */ +#define GROUP_ENDING_NOP __asm__("ori 2,2,0" ::: "memory") + +#if BYTE_ORDER == BIG_ENDIAN +#define BYTESWAP_DATA +#endif + +#ifdef BYTESWAP_DATA +#define VEC_PERM(vr, va, vb, vc) vr = vec_perm(va, vb, (__vector unsigned char) vc) +#if BYTE_ORDER == LITTLE_ENDIAN +/* Byte reverse permute constant LE. */ +static const __vector unsigned long long vperm_const ALIGNED_(16) = { 0x08090A0B0C0D0E0FUL, 0x0001020304050607UL }; +#else +static const __vector unsigned long long vperm_const ALIGNED_(16) = { 0x0F0E0D0C0B0A0908UL, 0X0706050403020100UL }; +#endif +#else +#define VEC_PERM(vr, va, vb, vc) +#endif + +static unsigned int ALIGNED_(32) __crc32_vpmsum(unsigned int crc, const void* p, unsigned long len) { + + const __vector unsigned long long vzero = {0,0}; + const __vector unsigned long long vones = {0xffffffffffffffffUL, 0xffffffffffffffffUL}; + + const __vector unsigned long long vmask_32bit = + (__vector unsigned long long)vec_sld((__vector unsigned char)vzero, (__vector unsigned char)vones, 4); + + const __vector unsigned long long vmask_64bit = + (__vector unsigned long long)vec_sld((__vector unsigned char)vzero, (__vector unsigned char)vones, 8); + + __vector unsigned long long vcrc; + + __vector unsigned long long vconst1, vconst2; + + /* vdata0-vdata7 will contain our data (p). */ + __vector unsigned long long vdata0, vdata1, vdata2, vdata3, vdata4, vdata5, vdata6, vdata7; + + /* v0-v7 will contain our checksums */ + __vector unsigned long long v0 = {0,0}; + __vector unsigned long long v1 = {0,0}; + __vector unsigned long long v2 = {0,0}; + __vector unsigned long long v3 = {0,0}; + __vector unsigned long long v4 = {0,0}; + __vector unsigned long long v5 = {0,0}; + __vector unsigned long long v6 = {0,0}; + __vector unsigned long long v7 = {0,0}; + + + /* Vector auxiliary variables. */ + __vector unsigned long long va0, va1, va2, va3, va4, va5, va6, va7; + + unsigned int offset; /* Constant table offset. */ + + unsigned long i; /* Counter. */ + unsigned long chunks; + + unsigned long block_size; + int next_block = 0; + + /* Align by 128 bits. The last 128 bit block will be processed at end. */ + unsigned long length = len & 0xFFFFFFFFFFFFFF80UL; + + vcrc = (__vector unsigned long long)__builtin_pack_vector_int128(0UL, crc); + + /* Short version. */ + if (len < 256) { + /* Calculate where in the constant table we need to start. */ + offset = 256 - len; + + vconst1 = vec_ld(offset, vcrc_short_const); + vdata0 = vec_ld(0, (__vector unsigned long long*) p); + VEC_PERM(vdata0, vdata0, vconst1, vperm_const); + + /* xor initial value */ + vdata0 = vec_xor(vdata0, vcrc); + + vdata0 = (__vector unsigned long long) __builtin_crypto_vpmsumw( + (__vector unsigned int)vdata0, (__vector unsigned int)vconst1); + v0 = vec_xor(v0, vdata0); + + for (i = 16; i < len; i += 16) { + vconst1 = vec_ld(offset + i, vcrc_short_const); + vdata0 = vec_ld(i, (__vector unsigned long long*) p); + VEC_PERM(vdata0, vdata0, vconst1, vperm_const); + vdata0 = (__vector unsigned long long) __builtin_crypto_vpmsumw( + (__vector unsigned int)vdata0, (__vector unsigned int)vconst1); + v0 = vec_xor(v0, vdata0); + } + } else { + + /* Load initial values. */ + vdata0 = vec_ld(0, (__vector unsigned long long*) p); + vdata1 = vec_ld(16, (__vector unsigned long long*) p); + + VEC_PERM(vdata0, vdata0, vdata0, vperm_const); + VEC_PERM(vdata1, vdata1, vdata1, vperm_const); + + vdata2 = vec_ld(32, (__vector unsigned long long*) p); + vdata3 = vec_ld(48, (__vector unsigned long long*) p); + + VEC_PERM(vdata2, vdata2, vdata2, vperm_const); + VEC_PERM(vdata3, vdata3, vdata3, vperm_const); + + vdata4 = vec_ld(64, (__vector unsigned long long*) p); + vdata5 = vec_ld(80, (__vector unsigned long long*) p); + + VEC_PERM(vdata4, vdata4, vdata4, vperm_const); + VEC_PERM(vdata5, vdata5, vdata5, vperm_const); + + vdata6 = vec_ld(96, (__vector unsigned long long*) p); + vdata7 = vec_ld(112, (__vector unsigned long long*) p); + + VEC_PERM(vdata6, vdata6, vdata6, vperm_const); + VEC_PERM(vdata7, vdata7, vdata7, vperm_const); + + /* xor in initial value */ + vdata0 = vec_xor(vdata0, vcrc); + + p = (char *)p + 128; + + do { + /* Checksum in blocks of MAX_SIZE. */ + block_size = length; + if (block_size > MAX_SIZE) { + block_size = MAX_SIZE; + } + + length = length - block_size; + + /* + * Work out the offset into the constants table to start at. Each + * constant is 16 bytes, and it is used against 128 bytes of input + * data - 128 / 16 = 8 + */ + offset = (MAX_SIZE/8) - (block_size/8); + /* We reduce our final 128 bytes in a separate step */ + chunks = (block_size/128)-1; + + vconst1 = vec_ld(offset, vcrc_const); + + va0 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata0, + (__vector unsigned long long)vconst1); + va1 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata1, + (__vector unsigned long long)vconst1); + va2 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata2, + (__vector unsigned long long)vconst1); + va3 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata3, + (__vector unsigned long long)vconst1); + va4 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata4, + (__vector unsigned long long)vconst1); + va5 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata5, + (__vector unsigned long long)vconst1); + va6 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata6, + (__vector unsigned long long)vconst1); + va7 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata7, + (__vector unsigned long long)vconst1); + + if (chunks > 1) { + offset += 16; + vconst2 = vec_ld(offset, vcrc_const); + GROUP_ENDING_NOP; + + vdata0 = vec_ld(0, (__vector unsigned long long*) p); + VEC_PERM(vdata0, vdata0, vdata0, vperm_const); + + vdata1 = vec_ld(16, (__vector unsigned long long*) p); + VEC_PERM(vdata1, vdata1, vdata1, vperm_const); + + vdata2 = vec_ld(32, (__vector unsigned long long*) p); + VEC_PERM(vdata2, vdata2, vdata2, vperm_const); + + vdata3 = vec_ld(48, (__vector unsigned long long*) p); + VEC_PERM(vdata3, vdata3, vdata3, vperm_const); + + vdata4 = vec_ld(64, (__vector unsigned long long*) p); + VEC_PERM(vdata4, vdata4, vdata4, vperm_const); + + vdata5 = vec_ld(80, (__vector unsigned long long*) p); + VEC_PERM(vdata5, vdata5, vdata5, vperm_const); + + vdata6 = vec_ld(96, (__vector unsigned long long*) p); + VEC_PERM(vdata6, vdata6, vdata6, vperm_const); + + vdata7 = vec_ld(112, (__vector unsigned long long*) p); + VEC_PERM(vdata7, vdata7, vdata7, vperm_const); + + p = (char *)p + 128; + + /* + * main loop. Each iteration calculates the CRC for a 128-byte + * block. + */ + for (i = 0; i < chunks-2; i++) { + vconst1 = vec_ld(offset, vcrc_const); + offset += 16; + GROUP_ENDING_NOP; + + v0 = vec_xor(v0, va0); + va0 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata0, + (__vector unsigned long long)vconst2); + vdata0 = vec_ld(0, (__vector unsigned long long*) p); + VEC_PERM(vdata0, vdata0, vdata0, vperm_const); + GROUP_ENDING_NOP; + + v1 = vec_xor(v1, va1); + va1 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata1, + (__vector unsigned long long)vconst2); + vdata1 = vec_ld(16, (__vector unsigned long long*) p); + VEC_PERM(vdata1, vdata1, vdata1, vperm_const); + GROUP_ENDING_NOP; + + v2 = vec_xor(v2, va2); + va2 = __builtin_crypto_vpmsumd((__vector unsigned long long) + vdata2, (__vector unsigned long long)vconst2); + vdata2 = vec_ld(32, (__vector unsigned long long*) p); + VEC_PERM(vdata2, vdata2, vdata2, vperm_const); + GROUP_ENDING_NOP; + + v3 = vec_xor(v3, va3); + va3 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata3, + (__vector unsigned long long)vconst2); + vdata3 = vec_ld(48, (__vector unsigned long long*) p); + VEC_PERM(vdata3, vdata3, vdata3, vperm_const); + + vconst2 = vec_ld(offset, vcrc_const); + GROUP_ENDING_NOP; + + v4 = vec_xor(v4, va4); + va4 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata4, + (__vector unsigned long long)vconst1); + vdata4 = vec_ld(64, (__vector unsigned long long*) p); + VEC_PERM(vdata4, vdata4, vdata4, vperm_const); + GROUP_ENDING_NOP; + + v5 = vec_xor(v5, va5); + va5 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata5, + (__vector unsigned long long)vconst1); + vdata5 = vec_ld(80, (__vector unsigned long long*) p); + VEC_PERM(vdata5, vdata5, vdata5, vperm_const); + GROUP_ENDING_NOP; + + v6 = vec_xor(v6, va6); + va6 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata6, + (__vector unsigned long long)vconst1); + vdata6 = vec_ld(96, (__vector unsigned long long*) p); + VEC_PERM(vdata6, vdata6, vdata6, vperm_const); + GROUP_ENDING_NOP; + + v7 = vec_xor(v7, va7); + va7 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata7, + (__vector unsigned long long)vconst1); + vdata7 = vec_ld(112, (__vector unsigned long long*) p); + VEC_PERM(vdata7, vdata7, vdata7, vperm_const); + + p = (char *)p + 128; + } + + /* First cool down */ + vconst1 = vec_ld(offset, vcrc_const); + offset += 16; + + v0 = vec_xor(v0, va0); + va0 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata0, + (__vector unsigned long long)vconst1); + GROUP_ENDING_NOP; + + v1 = vec_xor(v1, va1); + va1 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata1, + (__vector unsigned long long)vconst1); + GROUP_ENDING_NOP; + + v2 = vec_xor(v2, va2); + va2 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata2, + (__vector unsigned long long)vconst1); + GROUP_ENDING_NOP; + + v3 = vec_xor(v3, va3); + va3 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata3, + (__vector unsigned long long)vconst1); + GROUP_ENDING_NOP; + + v4 = vec_xor(v4, va4); + va4 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata4, + (__vector unsigned long long)vconst1); + GROUP_ENDING_NOP; + + v5 = vec_xor(v5, va5); + va5 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata5, + (__vector unsigned long long)vconst1); + GROUP_ENDING_NOP; + + v6 = vec_xor(v6, va6); + va6 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata6, + (__vector unsigned long long)vconst1); + GROUP_ENDING_NOP; + + v7 = vec_xor(v7, va7); + va7 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata7, + (__vector unsigned long long)vconst1); + }/* else */ + + /* Second cool down. */ + v0 = vec_xor(v0, va0); + v1 = vec_xor(v1, va1); + v2 = vec_xor(v2, va2); + v3 = vec_xor(v3, va3); + v4 = vec_xor(v4, va4); + v5 = vec_xor(v5, va5); + v6 = vec_xor(v6, va6); + v7 = vec_xor(v7, va7); + + /* + * vpmsumd produces a 96 bit result in the least significant bits + * of the register. Since we are bit reflected we have to shift it + * left 32 bits so it occupies the least significant bits in the + * bit reflected domain. + */ + v0 = (__vector unsigned long long)vec_sld((__vector unsigned char)v0, + (__vector unsigned char)vzero, 4); + v1 = (__vector unsigned long long)vec_sld((__vector unsigned char)v1, + (__vector unsigned char)vzero, 4); + v2 = (__vector unsigned long long)vec_sld((__vector unsigned char)v2, + (__vector unsigned char)vzero, 4); + v3 = (__vector unsigned long long)vec_sld((__vector unsigned char)v3, + (__vector unsigned char)vzero, 4); + v4 = (__vector unsigned long long)vec_sld((__vector unsigned char)v4, + (__vector unsigned char)vzero, 4); + v5 = (__vector unsigned long long)vec_sld((__vector unsigned char)v5, + (__vector unsigned char)vzero, 4); + v6 = (__vector unsigned long long)vec_sld((__vector unsigned char)v6, + (__vector unsigned char)vzero, 4); + v7 = (__vector unsigned long long)vec_sld((__vector unsigned char)v7, + (__vector unsigned char)vzero, 4); + + /* xor with the last 1024 bits. */ + va0 = vec_ld(0, (__vector unsigned long long*) p); + VEC_PERM(va0, va0, va0, vperm_const); + + va1 = vec_ld(16, (__vector unsigned long long*) p); + VEC_PERM(va1, va1, va1, vperm_const); + + va2 = vec_ld(32, (__vector unsigned long long*) p); + VEC_PERM(va2, va2, va2, vperm_const); + + va3 = vec_ld(48, (__vector unsigned long long*) p); + VEC_PERM(va3, va3, va3, vperm_const); + + va4 = vec_ld(64, (__vector unsigned long long*) p); + VEC_PERM(va4, va4, va4, vperm_const); + + va5 = vec_ld(80, (__vector unsigned long long*) p); + VEC_PERM(va5, va5, va5, vperm_const); + + va6 = vec_ld(96, (__vector unsigned long long*) p); + VEC_PERM(va6, va6, va6, vperm_const); + + va7 = vec_ld(112, (__vector unsigned long long*) p); + VEC_PERM(va7, va7, va7, vperm_const); + + p = (char *)p + 128; + + vdata0 = vec_xor(v0, va0); + vdata1 = vec_xor(v1, va1); + vdata2 = vec_xor(v2, va2); + vdata3 = vec_xor(v3, va3); + vdata4 = vec_xor(v4, va4); + vdata5 = vec_xor(v5, va5); + vdata6 = vec_xor(v6, va6); + vdata7 = vec_xor(v7, va7); + + /* Check if we have more blocks to process */ + next_block = 0; + if (length != 0) { + next_block = 1; + + /* zero v0-v7 */ + v0 = vec_xor(v0, v0); + v1 = vec_xor(v1, v1); + v2 = vec_xor(v2, v2); + v3 = vec_xor(v3, v3); + v4 = vec_xor(v4, v4); + v5 = vec_xor(v5, v5); + v6 = vec_xor(v6, v6); + v7 = vec_xor(v7, v7); + } + length = length + 128; + + } while (next_block); + + /* Calculate how many bytes we have left. */ + length = (len & 127); + + /* Calculate where in (short) constant table we need to start. */ + offset = 128 - length; + + v0 = vec_ld(offset, vcrc_short_const); + v1 = vec_ld(offset + 16, vcrc_short_const); + v2 = vec_ld(offset + 32, vcrc_short_const); + v3 = vec_ld(offset + 48, vcrc_short_const); + v4 = vec_ld(offset + 64, vcrc_short_const); + v5 = vec_ld(offset + 80, vcrc_short_const); + v6 = vec_ld(offset + 96, vcrc_short_const); + v7 = vec_ld(offset + 112, vcrc_short_const); + + offset += 128; + + v0 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata0, (__vector unsigned int)v0); + v1 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata1, (__vector unsigned int)v1); + v2 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata2, (__vector unsigned int)v2); + v3 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata3, (__vector unsigned int)v3); + v4 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata4, (__vector unsigned int)v4); + v5 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata5, (__vector unsigned int)v5); + v6 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata6, (__vector unsigned int)v6); + v7 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata7, (__vector unsigned int)v7); + + /* Now reduce the tail (0-112 bytes). */ + for (i = 0; i < length; i+=16) { + vdata0 = vec_ld(i,(__vector unsigned long long*)p); + VEC_PERM(vdata0, vdata0, vdata0, vperm_const); + va0 = vec_ld(offset + i,vcrc_short_const); + va0 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata0, (__vector unsigned int)va0); + v0 = vec_xor(v0, va0); + } + + /* xor all parallel chunks together. */ + v0 = vec_xor(v0, v1); + v2 = vec_xor(v2, v3); + v4 = vec_xor(v4, v5); + v6 = vec_xor(v6, v7); + + v0 = vec_xor(v0, v2); + v4 = vec_xor(v4, v6); + + v0 = vec_xor(v0, v4); + } + + /* Barrett Reduction */ + vconst1 = vec_ld(0, v_Barrett_const); + vconst2 = vec_ld(16, v_Barrett_const); + + v1 = (__vector unsigned long long)vec_sld((__vector unsigned char)v0, + (__vector unsigned char)v0, 8); + v0 = vec_xor(v1,v0); + + /* shift left one bit */ + __vector unsigned char vsht_splat = vec_splat_u8 (1); + v0 = (__vector unsigned long long)vec_sll((__vector unsigned char)v0, vsht_splat); + + v0 = vec_and(v0, vmask_64bit); + + /* + * The reflected version of Barrett reduction. Instead of bit + * reflecting our data (which is expensive to do), we bit reflect our + * constants and our algorithm, which means the intermediate data in + * our vector registers goes from 0-63 instead of 63-0. We can reflect + * the algorithm because we don't carry in mod 2 arithmetic. + */ + + /* bottom 32 bits of a */ + v1 = vec_and(v0, vmask_32bit); + + /* ma */ + v1 = __builtin_crypto_vpmsumd((__vector unsigned long long)v1, + (__vector unsigned long long)vconst1); + + /* bottom 32bits of ma */ + v1 = vec_and(v1, vmask_32bit); + /* qn */ + v1 = __builtin_crypto_vpmsumd((__vector unsigned long long)v1, + (__vector unsigned long long)vconst2); + /* a - qn, subtraction is xor in GF(2) */ + v0 = vec_xor (v0, v1); + + /* + * Since we are bit reflected, the result (ie the low 32 bits) is in + * the high 32 bits. We just need to shift it left 4 bytes + * V0 [ 0 1 X 3 ] + * V0 [ 0 X 2 3 ] + */ + + /* shift result into top 64 bits of */ + v0 = (__vector unsigned long long)vec_sld((__vector unsigned char)v0, + (__vector unsigned char)vzero, 4); + +#if BYTE_ORDER == BIG_ENDIAN + return v0[0]; +#else + return v0[1]; +#endif +} diff --git a/3rdparty/zlib-ng/arch/power/fallback_builtins.h b/3rdparty/zlib-ng/arch/power/fallback_builtins.h new file mode 100644 index 000000000000..ed9584617b15 --- /dev/null +++ b/3rdparty/zlib-ng/arch/power/fallback_builtins.h @@ -0,0 +1,31 @@ +/* Helper functions to work around issues with clang builtins + * Copyright (C) 2021 IBM Corporation + * + * Authors: + * Daniel Black + * Rogerio Alves + * Tulio Magno Quites Machado Filho + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef POWER_BUILTINS_H +#define POWER_BUILTINS_H + +/* + * These stubs fix clang incompatibilities with GCC builtins. + */ + +#ifndef __builtin_crypto_vpmsumw +#define __builtin_crypto_vpmsumw __builtin_crypto_vpmsumb +#endif +#ifndef __builtin_crypto_vpmsumd +#define __builtin_crypto_vpmsumd __builtin_crypto_vpmsumb +#endif + +static inline __vector unsigned long long __attribute__((overloadable)) +vec_ld(int __a, const __vector unsigned long long* __b) { + return (__vector unsigned long long)__builtin_altivec_lvx(__a, __b); +} + +#endif diff --git a/3rdparty/zlib-ng/arch/power/power_features.c b/3rdparty/zlib-ng/arch/power/power_features.c new file mode 100644 index 000000000000..f73503734b13 --- /dev/null +++ b/3rdparty/zlib-ng/arch/power/power_features.c @@ -0,0 +1,46 @@ +/* power_features.c - POWER feature check + * Copyright (C) 2020 Matheus Castanho , IBM + * Copyright (C) 2021-2022 Mika T. Lindqvist + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef HAVE_SYS_AUXV_H +# include +#endif +#ifdef __FreeBSD__ +# include +#endif +#include "../../zbuild.h" +#include "power_features.h" + +void Z_INTERNAL power_check_features(struct power_cpu_features *features) { +#ifdef PPC_FEATURES + unsigned long hwcap; +#ifdef __FreeBSD__ + elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)); +#else + hwcap = getauxval(AT_HWCAP); +#endif + + if (hwcap & PPC_FEATURE_HAS_ALTIVEC) + features->has_altivec = 1; +#endif + +#ifdef POWER_FEATURES + unsigned long hwcap2; +#ifdef __FreeBSD__ + elf_aux_info(AT_HWCAP2, &hwcap2, sizeof(hwcap2)); +#else + hwcap2 = getauxval(AT_HWCAP2); +#endif + +#ifdef POWER8_VSX + if (hwcap2 & PPC_FEATURE2_ARCH_2_07) + features->has_arch_2_07 = 1; +#endif +#ifdef POWER9 + if (hwcap2 & PPC_FEATURE2_ARCH_3_00) + features->has_arch_3_00 = 1; +#endif +#endif +} diff --git a/3rdparty/zlib-ng/arch/power/power_features.h b/3rdparty/zlib-ng/arch/power/power_features.h new file mode 100644 index 000000000000..9252364cc48d --- /dev/null +++ b/3rdparty/zlib-ng/arch/power/power_features.h @@ -0,0 +1,18 @@ +/* power_features.h -- check for POWER CPU features + * Copyright (C) 2020 Matheus Castanho , IBM + * Copyright (C) 2021 Mika T. Lindqvist + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef POWER_H_ +#define POWER_H_ + +struct power_cpu_features { + int has_altivec; + int has_arch_2_07; + int has_arch_3_00; +}; + +void Z_INTERNAL power_check_features(struct power_cpu_features *features); + +#endif /* POWER_H_ */ diff --git a/3rdparty/zlib-ng/arch/power/slide_hash_power8.c b/3rdparty/zlib-ng/arch/power/slide_hash_power8.c new file mode 100644 index 000000000000..d01e0acd5661 --- /dev/null +++ b/3rdparty/zlib-ng/arch/power/slide_hash_power8.c @@ -0,0 +1,12 @@ +/* Optimized slide_hash for POWER processors + * Copyright (C) 2019-2020 IBM Corporation + * Author: Matheus Castanho + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef POWER8_VSX + +#define SLIDE_PPC slide_hash_power8 +#include "slide_ppc_tpl.h" + +#endif /* POWER8_VSX */ diff --git a/3rdparty/zlib-ng/arch/power/slide_hash_vmx.c b/3rdparty/zlib-ng/arch/power/slide_hash_vmx.c new file mode 100644 index 000000000000..5a87ef7d9aa0 --- /dev/null +++ b/3rdparty/zlib-ng/arch/power/slide_hash_vmx.c @@ -0,0 +1,10 @@ +/* Optimized slide_hash for PowerPC processors with VMX instructions + * Copyright (C) 2017-2021 Mika T. Lindqvist + * For conditions of distribution and use, see copyright notice in zlib.h + */ +#ifdef PPC_VMX + +#define SLIDE_PPC slide_hash_vmx +#include "slide_ppc_tpl.h" + +#endif /* PPC_VMX */ diff --git a/3rdparty/zlib-ng/arch/power/slide_ppc_tpl.h b/3rdparty/zlib-ng/arch/power/slide_ppc_tpl.h new file mode 100644 index 000000000000..5c17e38fb310 --- /dev/null +++ b/3rdparty/zlib-ng/arch/power/slide_ppc_tpl.h @@ -0,0 +1,31 @@ +/* Optimized slide_hash for PowerPC processors + * Copyright (C) 2017-2021 Mika T. Lindqvist + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include "zbuild.h" +#include "deflate.h" + +static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) { + const vector unsigned short vmx_wsize = vec_splats(wsize); + Pos *p = table; + + do { + vector unsigned short value, result; + + value = vec_ld(0, p); + result = vec_subs(value, vmx_wsize); + vec_st(result, 0, p); + + p += 8; + entries -= 8; + } while (entries > 0); +} + +void Z_INTERNAL SLIDE_PPC(deflate_state *s) { + uint16_t wsize = s->w_size; + + slide_hash_chain(s->head, HASH_SIZE, wsize); + slide_hash_chain(s->prev, wsize, wsize); +} diff --git a/3rdparty/zlib-ng/arch/riscv/README.md b/3rdparty/zlib-ng/arch/riscv/README.md new file mode 100644 index 000000000000..013095c3732f --- /dev/null +++ b/3rdparty/zlib-ng/arch/riscv/README.md @@ -0,0 +1,45 @@ +# Building RISC-V Target with Cmake # + +> **Warning** +> Runtime rvv detection (using `hwcap`) requires linux kernel 6.5 or newer. +> +> When running on older kernels, we fall back to compile-time detection, potentially this can cause crashes if rvv is enabled at compile but not supported by the target cpu. +> Therefore if older kernel support is needed, rvv should be disabled if the target cpu does not support it. +## Prerequisite: Build RISC-V Clang Toolchain and QEMU ## + +If you don't have prebuilt clang and riscv64 qemu, you can refer to the [script](https://github.com/sifive/prepare-riscv-toolchain-qemu/blob/main/prepare_riscv_toolchain_qemu.sh) to get the source. Copy the script to the zlib-ng root directory, and run it to download the source and build them. Modify the content according to your conditions (e.g., toolchain version). + +```bash +./prepare_riscv_toolchain_qemu.sh +``` + +After running script, clang & qemu are built in `build-toolchain-qemu/riscv-clang/` & `build-toolchain-qemu/riscv-qemu/`. + +`build-toolchain-qemu/riscv-clang/` is your `TOOLCHAIN_PATH`. +`build-toolchain-qemu/riscv-qemu/bin/qemu-riscv64` is your `QEMU_PATH`. + +You can also download the prebuilt toolchain & qemu from [the release page](https://github.com/sifive/prepare-riscv-toolchain-qemu/releases), and enjoy using them. + +## Cross-Compile for RISC-V Target ## + +```bash +cmake -G Ninja -B ./build-riscv \ + -D CMAKE_TOOLCHAIN_FILE=./cmake/toolchain-riscv.cmake \ + -D CMAKE_INSTALL_PREFIX=./build-riscv/install \ + -D TOOLCHAIN_PATH={TOOLCHAIN_PATH} \ + -D QEMU_PATH={QEMU_PATH} \ + . + +cmake --build ./build-riscv +``` + +Disable the option if there is no RVV support: +``` +-D WITH_RVV=OFF +``` + +## Run Unittests on User Mode QEMU ## + +```bash +cd ./build-riscv && ctest --verbose +``` diff --git a/3rdparty/zlib-ng/arch/riscv/adler32_rvv.c b/3rdparty/zlib-ng/arch/riscv/adler32_rvv.c new file mode 100644 index 000000000000..da46f37e73c1 --- /dev/null +++ b/3rdparty/zlib-ng/arch/riscv/adler32_rvv.c @@ -0,0 +1,132 @@ +/* adler32_rvv.c - RVV version of adler32 + * Copyright (C) 2023 SiFive, Inc. All rights reserved. + * Contributed by Alex Chiang + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef RISCV_RVV + +#include +#include + +#include "../../zbuild.h" +#include "../../adler32_p.h" + +static inline uint32_t adler32_rvv_impl(uint32_t adler, uint8_t* restrict dst, const uint8_t *src, size_t len, int COPY) { + /* split Adler-32 into component sums */ + uint32_t sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + if (COPY) memcpy(dst, src, 1); + return adler32_len_1(adler, src, sum2); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (src == NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + if (COPY) memcpy(dst, src, len); + return adler32_len_16(adler, src, len, sum2); + } + + size_t left = len; + size_t vl = __riscv_vsetvlmax_e8m1(); + vl = vl > 256 ? 256 : vl; + vuint32m4_t v_buf32_accu = __riscv_vmv_v_x_u32m4(0, vl); + vuint32m4_t v_adler32_prev_accu = __riscv_vmv_v_x_u32m4(0, vl); + vuint16m2_t v_buf16_accu; + + /* + * We accumulate 8-bit data, and to prevent overflow, we have to use a 32-bit accumulator. + * However, adding 8-bit data into a 32-bit accumulator isn't efficient. We use 16-bit & 32-bit + * accumulators to boost performance. + * + * The block_size is the largest multiple of vl that <= 256, because overflow would occur when + * vl > 256 (255 * 256 <= UINT16_MAX). + * + * We accumulate 8-bit data into a 16-bit accumulator and then + * move the data into the 32-bit accumulator at the last iteration. + */ + size_t block_size = (256 / vl) * vl; + size_t nmax_limit = (NMAX / block_size); + size_t cnt = 0; + while (left >= block_size) { + v_buf16_accu = __riscv_vmv_v_x_u16m2(0, vl); + size_t subprob = block_size; + while (subprob > 0) { + vuint8m1_t v_buf8 = __riscv_vle8_v_u8m1(src, vl); + if (COPY) __riscv_vse8_v_u8m1(dst, v_buf8, vl); + v_adler32_prev_accu = __riscv_vwaddu_wv_u32m4(v_adler32_prev_accu, v_buf16_accu, vl); + v_buf16_accu = __riscv_vwaddu_wv_u16m2(v_buf16_accu, v_buf8, vl); + src += vl; + if (COPY) dst += vl; + subprob -= vl; + } + v_adler32_prev_accu = __riscv_vmacc_vx_u32m4(v_adler32_prev_accu, block_size / vl, v_buf32_accu, vl); + v_buf32_accu = __riscv_vwaddu_wv_u32m4(v_buf32_accu, v_buf16_accu, vl); + left -= block_size; + /* do modulo once each block of NMAX size */ + if (++cnt >= nmax_limit) { + v_adler32_prev_accu = __riscv_vremu_vx_u32m4(v_adler32_prev_accu, BASE, vl); + cnt = 0; + } + } + /* the left len <= 256 now, we can use 16-bit accum safely */ + v_buf16_accu = __riscv_vmv_v_x_u16m2(0, vl); + size_t res = left; + while (left >= vl) { + vuint8m1_t v_buf8 = __riscv_vle8_v_u8m1(src, vl); + if (COPY) __riscv_vse8_v_u8m1(dst, v_buf8, vl); + v_adler32_prev_accu = __riscv_vwaddu_wv_u32m4(v_adler32_prev_accu, v_buf16_accu, vl); + v_buf16_accu = __riscv_vwaddu_wv_u16m2(v_buf16_accu, v_buf8, vl); + src += vl; + if (COPY) dst += vl; + left -= vl; + } + v_adler32_prev_accu = __riscv_vmacc_vx_u32m4(v_adler32_prev_accu, res / vl, v_buf32_accu, vl); + v_adler32_prev_accu = __riscv_vremu_vx_u32m4(v_adler32_prev_accu, BASE, vl); + v_buf32_accu = __riscv_vwaddu_wv_u32m4(v_buf32_accu, v_buf16_accu, vl); + + vuint32m4_t v_seq = __riscv_vid_v_u32m4(vl); + vuint32m4_t v_rev_seq = __riscv_vrsub_vx_u32m4(v_seq, vl, vl); + vuint32m4_t v_sum32_accu = __riscv_vmul_vv_u32m4(v_buf32_accu, v_rev_seq, vl); + + v_sum32_accu = __riscv_vadd_vv_u32m4(v_sum32_accu, __riscv_vmul_vx_u32m4(v_adler32_prev_accu, vl, vl), vl); + + vuint32m1_t v_sum2_sum = __riscv_vmv_s_x_u32m1(0, vl); + v_sum2_sum = __riscv_vredsum_vs_u32m4_u32m1(v_sum32_accu, v_sum2_sum, vl); + uint32_t sum2_sum = __riscv_vmv_x_s_u32m1_u32(v_sum2_sum); + + sum2 += (sum2_sum + adler * (len - left)); + + vuint32m1_t v_adler_sum = __riscv_vmv_s_x_u32m1(0, vl); + v_adler_sum = __riscv_vredsum_vs_u32m4_u32m1(v_buf32_accu, v_adler_sum, vl); + uint32_t adler_sum = __riscv_vmv_x_s_u32m1_u32(v_adler_sum); + + adler += adler_sum; + + while (left--) { + if (COPY) *dst++ = *src; + adler += *src++; + sum2 += adler; + } + + sum2 %= BASE; + adler %= BASE; + + return adler | (sum2 << 16); +} + +Z_INTERNAL uint32_t adler32_fold_copy_rvv(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { + return adler32_rvv_impl(adler, dst, src, len, 1); +} + +Z_INTERNAL uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len) { + return adler32_rvv_impl(adler, NULL, buf, len, 0); +} + +#endif // RISCV_RVV diff --git a/3rdparty/zlib-ng/arch/riscv/chunkset_rvv.c b/3rdparty/zlib-ng/arch/riscv/chunkset_rvv.c new file mode 100644 index 000000000000..ee43bde2f71d --- /dev/null +++ b/3rdparty/zlib-ng/arch/riscv/chunkset_rvv.c @@ -0,0 +1,121 @@ +/* chunkset_rvv.c - RVV version of chunkset + * Copyright (C) 2023 SiFive, Inc. All rights reserved. + * Contributed by Alex Chiang + * For conditions of distribution and use, see copyright notice in zlib.h + */ +#include +#include "zbuild.h" + +/* + * RISC-V glibc would enable RVV optimized memcpy at runtime by IFUNC, + * so we prefer using large size chunk and copy memory as much as possible. + */ +#define CHUNK_SIZE 32 + +#define HAVE_CHUNKMEMSET_2 +#define HAVE_CHUNKMEMSET_4 +#define HAVE_CHUNKMEMSET_8 + +#define CHUNK_MEMSET_RVV_IMPL(elen) \ +do { \ + size_t vl, len = CHUNK_SIZE / sizeof(uint##elen##_t); \ + uint##elen##_t val = *(uint##elen##_t*)from; \ + uint##elen##_t* chunk_p = (uint##elen##_t*)chunk; \ + do { \ + vl = __riscv_vsetvl_e##elen##m4(len); \ + vuint##elen##m4_t v_val = __riscv_vmv_v_x_u##elen##m4(val, vl); \ + __riscv_vse##elen##_v_u##elen##m4(chunk_p, v_val, vl); \ + len -= vl; chunk_p += vl; \ + } while (len > 0); \ +} while (0) + +/* We don't have a 32-byte datatype for RISC-V arch. */ +typedef struct chunk_s { + uint64_t data[4]; +} chunk_t; + +static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { + CHUNK_MEMSET_RVV_IMPL(16); +} + +static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { + CHUNK_MEMSET_RVV_IMPL(32); +} + +static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { + CHUNK_MEMSET_RVV_IMPL(64); +} + +static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { + memcpy(chunk->data, (uint8_t *)s, CHUNK_SIZE); +} + +static inline void storechunk(uint8_t *out, chunk_t *chunk) { + memcpy(out, chunk->data, CHUNK_SIZE); +} + +#define CHUNKSIZE chunksize_rvv +#define CHUNKCOPY chunkcopy_rvv +#define CHUNKUNROLL chunkunroll_rvv +#define CHUNKMEMSET chunkmemset_rvv +#define CHUNKMEMSET_SAFE chunkmemset_safe_rvv + +#define HAVE_CHUNKCOPY + +/* + * Assuming that the length is non-zero, and that `from` lags `out` by at least + * sizeof chunk_t bytes, please see the comments in chunkset_tpl.h. + * + * We load/store a single chunk once in the `CHUNKCOPY`. + * However, RISC-V glibc would enable RVV optimized memcpy at runtime by IFUNC, + * such that, we prefer copy large memory size once to make good use of the the RVV advance. + * + * To be aligned to the other platforms, we didn't modify `CHUNKCOPY` method a lot, + * but we still copy as much memory as possible for some conditions. + * + * case 1: out - from >= len (no overlap) + * We can use memcpy to copy `len` size once + * because the memory layout would be the same. + * + * case 2: overlap + * We copy N chunks using memcpy at once, aiming to achieve our goal: + * to copy as much memory as possible. + * + * After using a single memcpy to copy N chunks, we have to use series of + * loadchunk and storechunk to ensure the result is correct. + */ +static inline uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { + Assert(len > 0, "chunkcopy should never have a length 0"); + int32_t align = ((len - 1) % sizeof(chunk_t)) + 1; + memcpy(out, from, sizeof(chunk_t)); + out += align; + from += align; + len -= align; + ptrdiff_t dist = out - from; + if (dist >= len) { + memcpy(out, from, len); + out += len; + from += len; + return out; + } + if (dist >= sizeof(chunk_t)) { + dist = (dist / sizeof(chunk_t)) * sizeof(chunk_t); + memcpy(out, from, dist); + out += dist; + from += dist; + len -= dist; + } + while (len > 0) { + memcpy(out, from, sizeof(chunk_t)); + out += sizeof(chunk_t); + from += sizeof(chunk_t); + len -= sizeof(chunk_t); + } + return out; +} + +#include "chunkset_tpl.h" + +#define INFLATE_FAST inflate_fast_rvv + +#include "inffast_tpl.h" diff --git a/3rdparty/zlib-ng/arch/riscv/compare256_rvv.c b/3rdparty/zlib-ng/arch/riscv/compare256_rvv.c new file mode 100644 index 000000000000..0fd6082c44d0 --- /dev/null +++ b/3rdparty/zlib-ng/arch/riscv/compare256_rvv.c @@ -0,0 +1,47 @@ +/* compare256_rvv.c - RVV version of compare256 + * Copyright (C) 2023 SiFive, Inc. All rights reserved. + * Contributed by Alex Chiang + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef RISCV_RVV + +#include "../../zbuild.h" +#include "fallback_builtins.h" + +#include + +static inline uint32_t compare256_rvv_static(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + size_t vl; + long found_diff; + do { + vl = __riscv_vsetvl_e8m4(256 - len); + vuint8m4_t v_src0 = __riscv_vle8_v_u8m4(src0, vl); + vuint8m4_t v_src1 = __riscv_vle8_v_u8m4(src1, vl); + vbool2_t v_mask = __riscv_vmsne_vv_u8m4_b2(v_src0, v_src1, vl); + found_diff = __riscv_vfirst_m_b2(v_mask, vl); + if (found_diff >= 0) + return len + (uint32_t)found_diff; + src0 += vl, src1 += vl, len += vl; + } while (len < 256); + + return 256; +} + +Z_INTERNAL uint32_t compare256_rvv(const uint8_t *src0, const uint8_t *src1) { + return compare256_rvv_static(src0, src1); +} + +#define LONGEST_MATCH longest_match_rvv +#define COMPARE256 compare256_rvv_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_rvv +#define COMPARE256 compare256_rvv_static + +#include "match_tpl.h" + +#endif // RISCV_RVV diff --git a/3rdparty/zlib-ng/arch/riscv/riscv_features.c b/3rdparty/zlib-ng/arch/riscv/riscv_features.c new file mode 100644 index 000000000000..b066f427e0fc --- /dev/null +++ b/3rdparty/zlib-ng/arch/riscv/riscv_features.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include + +#include "../../zbuild.h" +#include "riscv_features.h" + +#define ISA_V_HWCAP (1 << ('v' - 'a')) + +int Z_INTERNAL is_kernel_version_greater_or_equal_to_6_5() { + struct utsname buffer; + uname(&buffer); + + int major, minor; + if (sscanf(buffer.release, "%d.%d", &major, &minor) != 2) { + // Something bad with uname() + return 0; + } + + if (major > 6 || major == 6 && minor >= 5) + return 1; + return 0; +} + +void Z_INTERNAL riscv_check_features_compile_time(struct riscv_cpu_features *features) { +#if defined(__riscv_v) && defined(__linux__) + features->has_rvv = 1; +#else + features->has_rvv = 0; +#endif +} + +void Z_INTERNAL riscv_check_features_runtime(struct riscv_cpu_features *features) { + unsigned long hw_cap = getauxval(AT_HWCAP); + features->has_rvv = hw_cap & ISA_V_HWCAP; +} + +void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features) { + if (is_kernel_version_greater_or_equal_to_6_5()) + riscv_check_features_runtime(features); + else + riscv_check_features_compile_time(features); +} diff --git a/3rdparty/zlib-ng/arch/riscv/riscv_features.h b/3rdparty/zlib-ng/arch/riscv/riscv_features.h new file mode 100644 index 000000000000..c76e967c36ce --- /dev/null +++ b/3rdparty/zlib-ng/arch/riscv/riscv_features.h @@ -0,0 +1,18 @@ +/* riscv_features.h -- check for riscv features. + * + * Copyright (C) 2023 SiFive, Inc. All rights reserved. + * Contributed by Alex Chiang + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef RISCV_H_ +#define RISCV_H_ + +struct riscv_cpu_features { + int has_rvv; +}; + +void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features); + +#endif /* RISCV_H_ */ diff --git a/3rdparty/zlib-ng/arch/riscv/slide_hash_rvv.c b/3rdparty/zlib-ng/arch/riscv/slide_hash_rvv.c new file mode 100644 index 000000000000..1164e89ba250 --- /dev/null +++ b/3rdparty/zlib-ng/arch/riscv/slide_hash_rvv.c @@ -0,0 +1,34 @@ +/* slide_hash_rvv.c - RVV version of slide_hash + * Copyright (C) 2023 SiFive, Inc. All rights reserved. + * Contributed by Alex Chiang + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef RISCV_RVV + +#include + +#include "../../zbuild.h" +#include "../../deflate.h" + +static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) { + size_t vl; + while (entries > 0) { + vl = __riscv_vsetvl_e16m4(entries); + vuint16m4_t v_tab = __riscv_vle16_v_u16m4(table, vl); + vuint16m4_t v_diff = __riscv_vsub_vx_u16m4(v_tab, wsize, vl); + vbool4_t mask = __riscv_vmsltu_vx_u16m4_b4(v_tab, wsize, vl); + v_tab = __riscv_vmerge_vxm_u16m4(v_diff, 0, mask, vl); + __riscv_vse16_v_u16m4(table, v_tab, vl); + table += vl, entries -= vl; + } +} + +Z_INTERNAL void slide_hash_rvv(deflate_state *s) { + uint16_t wsize = (uint16_t)s->w_size; + + slide_hash_chain(s->head, HASH_SIZE, wsize); + slide_hash_chain(s->prev, wsize, wsize); +} + +#endif // RISCV_RVV diff --git a/3rdparty/zlib-ng/arch/x86/Makefile.in b/3rdparty/zlib-ng/arch/x86/Makefile.in new file mode 100644 index 000000000000..7c052469b298 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/Makefile.in @@ -0,0 +1,147 @@ +# Makefile for zlib +# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler +# For conditions of distribution and use, see copyright notice in zlib.h + +CC= +CFLAGS= +SFLAGS= +INCLUDES= +SUFFIX= + +AVX512FLAG=-mavx512f -mavx512dq -mavx512vl -mavx512bw +AVX512VNNIFLAG=-mavx512vnni +AVX2FLAG=-mavx2 +SSE2FLAG=-msse2 +SSSE3FLAG=-mssse3 +SSE42FLAG=-msse4.2 +PCLMULFLAG=-mpclmul +VPCLMULFLAG=-mvpclmulqdq +XSAVEFLAG=-mxsave +NOLTOFLAG= + +SRCDIR=. +SRCTOP=../.. +TOPDIR=$(SRCTOP) + +all: \ + x86_features.o x86_features.lo \ + adler32_avx2.o adler32_avx2.lo \ + adler32_avx512.o adler32_avx512.lo \ + adler32_avx512_vnni.o adler32_avx512_vnni.lo \ + adler32_sse42.o adler32_sse42.lo \ + adler32_ssse3.o adler32_ssse3.lo \ + chunkset_avx2.o chunkset_avx2.lo \ + chunkset_sse2.o chunkset_sse2.lo \ + chunkset_ssse3.o chunkset_ssse3.lo \ + compare256_avx2.o compare256_avx2.lo \ + compare256_sse2.o compare256_sse2.lo \ + insert_string_sse42.o insert_string_sse42.lo \ + crc32_pclmulqdq.o crc32_pclmulqdq.lo \ + crc32_vpclmulqdq.o crc32_vpclmulqdq.lo \ + slide_hash_avx2.o slide_hash_avx2.lo \ + slide_hash_sse2.o slide_hash_sse2.lo + +x86_features.o: + $(CC) $(CFLAGS) $(XSAVEFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/x86_features.c + +x86_features.lo: + $(CC) $(SFLAGS) $(XSAVEFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/x86_features.c + +chunkset_avx2.o: + $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx2.c + +chunkset_avx2.lo: + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx2.c + +chunkset_sse2.o: + $(CC) $(CFLAGS) $(SSE2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse2.c + +chunkset_sse2.lo: + $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse2.c + +chunkset_ssse3.o: + $(CC) $(CFLAGS) $(SSSE3FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_ssse3.c + +chunkset_ssse3.lo: + $(CC) $(SFLAGS) $(SSSE3FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_ssse3.c + +compare256_avx2.o: + $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_avx2.c + +compare256_avx2.lo: + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_avx2.c + +compare256_sse2.o: + $(CC) $(CFLAGS) $(SSE2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_sse2.c + +compare256_sse2.lo: + $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_sse2.c + +insert_string_sse42.o: + $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse42.c + +insert_string_sse42.lo: + $(CC) $(SFLAGS) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse42.c + +crc32_pclmulqdq.o: + $(CC) $(CFLAGS) $(PCLMULFLAG) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_pclmulqdq.c + +crc32_pclmulqdq.lo: + $(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_pclmulqdq.c + +crc32_vpclmulqdq.o: + $(CC) $(CFLAGS) $(PCLMULFLAG) $(SSE42FLAG) $(VPCLMULFLAG) $(AVX512FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_vpclmulqdq.c + +crc32_vpclmulqdq.lo: + $(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE42FLAG) $(VPCLMULFLAG) $(AVX512FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_vpclmulqdq.c + +slide_hash_avx2.o: + $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_avx2.c + +slide_hash_avx2.lo: + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_avx2.c + +slide_hash_sse2.o: + $(CC) $(CFLAGS) $(SSE2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_sse2.c + +slide_hash_sse2.lo: + $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_sse2.c + +adler32_avx2.o: $(SRCDIR)/adler32_avx2.c + $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx2.c + +adler32_avx2.lo: $(SRCDIR)/adler32_avx2.c + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx2.c + +adler32_avx512.o: $(SRCDIR)/adler32_avx512.c + $(CC) $(CFLAGS) $(AVX512FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512.c + +adler32_avx512.lo: $(SRCDIR)/adler32_avx512.c + $(CC) $(SFLAGS) $(AVX512FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512.c + +adler32_avx512_vnni.o: $(SRCDIR)/adler32_avx512_vnni.c + $(CC) $(CFLAGS) $(AVX512VNNIFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512_vnni.c + +adler32_avx512_vnni.lo: $(SRCDIR)/adler32_avx512_vnni.c + $(CC) $(SFLAGS) $(AVX512VNNIFLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512_vnni.c + +adler32_ssse3.o: $(SRCDIR)/adler32_ssse3.c + $(CC) $(CFLAGS) $(SSSE3FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_ssse3.c + +adler32_ssse3.lo: $(SRCDIR)/adler32_ssse3.c + $(CC) $(SFLAGS) $(SSSE3FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_ssse3.c + +adler32_sse42.o: $(SRCDIR)/adler32_sse42.c + $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_sse42.c + +adler32_sse42.lo: $(SRCDIR)/adler32_sse42.c + $(CC) $(SFLAGS) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_sse42.c + +mostlyclean: clean +clean: + rm -f *.o *.lo *~ + rm -rf objs + rm -f *.gcda *.gcno *.gcov + +distclean: clean + rm -f Makefile diff --git a/3rdparty/zlib-ng/arch/x86/adler32_avx2.c b/3rdparty/zlib-ng/arch/x86/adler32_avx2.c new file mode 100644 index 000000000000..e3ac6705cef3 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/adler32_avx2.c @@ -0,0 +1,154 @@ +/* adler32_avx2.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011 Mark Adler + * Copyright (C) 2022 Adam Stylinski + * Authors: + * Brian Bockelman + * Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef X86_AVX2 + +#include "../../zbuild.h" +#include +#include "../../adler32_fold.h" +#include "../../adler32_p.h" +#include "adler32_avx2_p.h" +#include "x86_intrins.h" + +#ifdef X86_SSE42 +extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *src, size_t len); + +#define copy_sub32(a, b, c, d) adler32_fold_copy_sse42(a, b, c, d) +#define sub32(a, b, c) adler32_ssse3(a, b, c) +#else +#define copy_sub32(a, b, c, d) adler32_copy_len_16(adler0, c, b, d, adler1) +#define sub32(a, b, c) adler32_len_16(adler0, b, c, adler1) +#endif + +static inline uint32_t adler32_fold_copy_impl(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len, const int COPY) { + if (src == NULL) return 1L; + if (len == 0) return adler; + + uint32_t adler0, adler1; + adler1 = (adler >> 16) & 0xffff; + adler0 = adler & 0xffff; + +rem_peel: + if (len < 16) { + if (COPY) { + return adler32_copy_len_16(adler0, src, dst, len, adler1); + } else { + return adler32_len_16(adler0, src, len, adler1); + } + } else if (len < 32) { + if (COPY) { + return copy_sub32(adler, dst, src, len); + } else { + return sub32(adler, src, len); + } + } + + __m256i vs1, vs2; + + const __m256i dot2v = _mm256_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m256i dot3v = _mm256_set1_epi16(1); + const __m256i zero = _mm256_setzero_si256(); + + while (len >= 32) { + vs1 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler0)); + vs2 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler1)); + __m256i vs1_0 = vs1; + __m256i vs3 = _mm256_setzero_si256(); + + size_t k = MIN(len, NMAX); + k -= k % 32; + len -= k; + + while (k >= 32) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 32 vs1 + sum( (32-i+1) c[i] ) + */ + __m256i vbuf = _mm256_loadu_si256((__m256i*)src); + src += 32; + k -= 32; + + __m256i vs1_sad = _mm256_sad_epu8(vbuf, zero); // Sum of abs diff, resulting in 2 x int32's + + if (COPY) { + _mm256_storeu_si256((__m256i*)dst, vbuf); + dst += 32; + } + + vs1 = _mm256_add_epi32(vs1, vs1_sad); + vs3 = _mm256_add_epi32(vs3, vs1_0); + __m256i v_short_sum2 = _mm256_maddubs_epi16(vbuf, dot2v); // sum 32 uint8s to 16 shorts + __m256i vsum2 = _mm256_madd_epi16(v_short_sum2, dot3v); // sum 16 shorts to 8 uint32s + vs2 = _mm256_add_epi32(vsum2, vs2); + vs1_0 = vs1; + } + + /* Defer the multiplication with 32 to outside of the loop */ + vs3 = _mm256_slli_epi32(vs3, 5); + vs2 = _mm256_add_epi32(vs2, vs3); + + /* The compiler is generating the following sequence for this integer modulus + * when done the scalar way, in GPRs: + + adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE) + + (s1_unpack[4] % BASE) + (s1_unpack[5] % BASE) + (s1_unpack[6] % BASE) + (s1_unpack[7] % BASE); + + mov $0x80078071,%edi // move magic constant into 32 bit register %edi + ... + vmovd %xmm1,%esi // move vector lane 0 to 32 bit register %esi + mov %rsi,%rax // zero-extend this value to 64 bit precision in %rax + imul %rdi,%rsi // do a signed multiplication with magic constant and vector element + shr $0x2f,%rsi // shift right by 47 + imul $0xfff1,%esi,%esi // do a signed multiplication with value truncated to 32 bits with 0xfff1 + sub %esi,%eax // subtract lower 32 bits of original vector value from modified one above + ... + // repeats for each element with vpextract instructions + + This is tricky with AVX2 for a number of reasons: + 1.) There's no 64 bit multiplication instruction, but there is a sequence to get there + 2.) There's ways to extend vectors to 64 bit precision, but no simple way to truncate + back down to 32 bit precision later (there is in AVX512) + 3.) Full width integer multiplications aren't cheap + + We can, however, do a relatively cheap sequence for horizontal sums. + Then, we simply do the integer modulus on the resulting 64 bit GPR, on a scalar value. It was + previously thought that casting to 64 bit precision was needed prior to the horizontal sum, but + that is simply not the case, as NMAX is defined as the maximum number of scalar sums that can be + performed on the maximum possible inputs before overflow + */ + + + /* In AVX2-land, this trip through GPRs will probably be unavoidable, as there's no cheap and easy + * conversion from 64 bit integer to 32 bit (needed for the inexpensive modulus with a constant). + * This casting to 32 bit is cheap through GPRs (just register aliasing). See above for exactly + * what the compiler is doing to avoid integer divisions. */ + adler0 = partial_hsum256(vs1) % BASE; + adler1 = hsum256(vs2) % BASE; + } + + adler = adler0 | (adler1 << 16); + + if (len) { + goto rem_peel; + } + + return adler; +} + +Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, size_t len) { + return adler32_fold_copy_impl(adler, NULL, src, len, 0); +} + +Z_INTERNAL uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { + return adler32_fold_copy_impl(adler, dst, src, len, 1); +} + +#endif diff --git a/3rdparty/zlib-ng/arch/x86/adler32_avx2_p.h b/3rdparty/zlib-ng/arch/x86/adler32_avx2_p.h new file mode 100644 index 000000000000..f0f8a4a887b1 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/adler32_avx2_p.h @@ -0,0 +1,32 @@ +/* adler32_avx2_p.h -- adler32 avx2 utility functions + * Copyright (C) 2022 Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ADLER32_AVX2_P_H_ +#define ADLER32_AVX2_P_H_ + +#if defined(X86_AVX2) || defined(X86_AVX512VNNI) + +/* 32 bit horizontal sum, adapted from Agner Fog's vector library. */ +static inline uint32_t hsum256(__m256i x) { + __m128i sum1 = _mm_add_epi32(_mm256_extracti128_si256(x, 1), + _mm256_castsi256_si128(x)); + __m128i sum2 = _mm_add_epi32(sum1, _mm_unpackhi_epi64(sum1, sum1)); + __m128i sum3 = _mm_add_epi32(sum2, _mm_shuffle_epi32(sum2, 1)); + return (uint32_t)_mm_cvtsi128_si32(sum3); +} + +static inline uint32_t partial_hsum256(__m256i x) { + /* We need a permutation vector to extract every other integer. The + * rest are going to be zeros */ + const __m256i perm_vec = _mm256_setr_epi32(0, 2, 4, 6, 1, 1, 1, 1); + __m256i non_zero = _mm256_permutevar8x32_epi32(x, perm_vec); + __m128i non_zero_sse = _mm256_castsi256_si128(non_zero); + __m128i sum2 = _mm_add_epi32(non_zero_sse,_mm_unpackhi_epi64(non_zero_sse, non_zero_sse)); + __m128i sum3 = _mm_add_epi32(sum2, _mm_shuffle_epi32(sum2, 1)); + return (uint32_t)_mm_cvtsi128_si32(sum3); +} +#endif + +#endif diff --git a/3rdparty/zlib-ng/arch/x86/adler32_avx512.c b/3rdparty/zlib-ng/arch/x86/adler32_avx512.c new file mode 100644 index 000000000000..aa6cc170185b --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/adler32_avx512.c @@ -0,0 +1,115 @@ +/* adler32_avx512.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011 Mark Adler + * Authors: + * Adam Stylinski + * Brian Bockelman + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef X86_AVX512 + +#include "../../zbuild.h" +#include "../../adler32_p.h" +#include "../../adler32_fold.h" +#include "../../cpu_features.h" +#include +#include "x86_intrins.h" +#include "adler32_avx512_p.h" + +static inline uint32_t adler32_fold_copy_impl(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len, const int COPY) { + if (src == NULL) return 1L; + if (len == 0) return adler; + + uint32_t adler0, adler1; + adler1 = (adler >> 16) & 0xffff; + adler0 = adler & 0xffff; + +rem_peel: + if (len < 64) { + /* This handles the remaining copies, just call normal adler checksum after this */ + if (COPY) { + __mmask64 storemask = (0xFFFFFFFFFFFFFFFFUL >> (64 - len)); + __m512i copy_vec = _mm512_maskz_loadu_epi8(storemask, src); + _mm512_mask_storeu_epi8(dst, storemask, copy_vec); + } + +#ifdef X86_AVX2 + return adler32_avx2(adler, src, len); +#elif defined(X86_SSSE3) + return adler32_ssse3(adler, src, len); +#else + return adler32_len_16(adler0, src, len, adler1); +#endif + } + + __m512i vbuf, vs1_0, vs3; + + const __m512i dot2v = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64); + const __m512i dot3v = _mm512_set1_epi16(1); + const __m512i zero = _mm512_setzero_si512(); + size_t k; + + while (len >= 64) { + __m512i vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler0)); + __m512i vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler1)); + vs1_0 = vs1; + vs3 = _mm512_setzero_si512(); + + k = MIN(len, NMAX); + k -= k % 64; + len -= k; + + while (k >= 64) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 64 vs1 + sum( (64-i+1) c[i] ) + */ + vbuf = _mm512_loadu_si512(src); + + if (COPY) { + _mm512_storeu_si512(dst, vbuf); + dst += 64; + } + + src += 64; + k -= 64; + + __m512i vs1_sad = _mm512_sad_epu8(vbuf, zero); + __m512i v_short_sum2 = _mm512_maddubs_epi16(vbuf, dot2v); + vs1 = _mm512_add_epi32(vs1_sad, vs1); + vs3 = _mm512_add_epi32(vs3, vs1_0); + __m512i vsum2 = _mm512_madd_epi16(v_short_sum2, dot3v); + vs2 = _mm512_add_epi32(vsum2, vs2); + vs1_0 = vs1; + } + + vs3 = _mm512_slli_epi32(vs3, 6); + vs2 = _mm512_add_epi32(vs2, vs3); + + adler0 = partial_hsum(vs1) % BASE; + adler1 = _mm512_reduce_add_epu32(vs2) % BASE; + } + + adler = adler0 | (adler1 << 16); + + /* Process tail (len < 64). */ + if (len) { + goto rem_peel; + } + + return adler; +} + +Z_INTERNAL uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { + return adler32_fold_copy_impl(adler, dst, src, len, 1); +} + +Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, size_t len) { + return adler32_fold_copy_impl(adler, NULL, src, len, 0); +} + +#endif + diff --git a/3rdparty/zlib-ng/arch/x86/adler32_avx512_p.h b/3rdparty/zlib-ng/arch/x86/adler32_avx512_p.h new file mode 100644 index 000000000000..5b79d2ab6ee7 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/adler32_avx512_p.h @@ -0,0 +1,46 @@ +#ifndef AVX512_FUNCS_H +#define AVX512_FUNCS_H + +#include +#include +/* Written because *_add_epi32(a) sets off ubsan */ +static inline uint32_t _mm512_reduce_add_epu32(__m512i x) { + __m256i a = _mm512_extracti64x4_epi64(x, 1); + __m256i b = _mm512_extracti64x4_epi64(x, 0); + + __m256i a_plus_b = _mm256_add_epi32(a, b); + __m128i c = _mm256_extracti128_si256(a_plus_b, 1); + __m128i d = _mm256_extracti128_si256(a_plus_b, 0); + __m128i c_plus_d = _mm_add_epi32(c, d); + + __m128i sum1 = _mm_unpackhi_epi64(c_plus_d, c_plus_d); + __m128i sum2 = _mm_add_epi32(sum1, c_plus_d); + __m128i sum3 = _mm_shuffle_epi32(sum2, 0x01); + __m128i sum4 = _mm_add_epi32(sum2, sum3); + + return _mm_cvtsi128_si32(sum4); +} + +static inline uint32_t partial_hsum(__m512i x) { + /* We need a permutation vector to extract every other integer. The + * rest are going to be zeros. Marking this const so the compiler stands + * a better chance of keeping this resident in a register through entire + * loop execution. We certainly have enough zmm registers (32) */ + const __m512i perm_vec = _mm512_setr_epi32(0, 2, 4, 6, 8, 10, 12, 14, + 1, 1, 1, 1, 1, 1, 1, 1); + + __m512i non_zero = _mm512_permutexvar_epi32(perm_vec, x); + + /* From here, it's a simple 256 bit wide reduction sum */ + __m256i non_zero_avx = _mm512_castsi512_si256(non_zero); + + /* See Agner Fog's vectorclass for a decent reference. Essentially, phadd is + * pretty slow, much slower than the longer instruction sequence below */ + __m128i sum1 = _mm_add_epi32(_mm256_extracti128_si256(non_zero_avx, 1), + _mm256_castsi256_si128(non_zero_avx)); + __m128i sum2 = _mm_add_epi32(sum1,_mm_unpackhi_epi64(sum1, sum1)); + __m128i sum3 = _mm_add_epi32(sum2,_mm_shuffle_epi32(sum2, 1)); + return (uint32_t)_mm_cvtsi128_si32(sum3); +} + +#endif diff --git a/3rdparty/zlib-ng/arch/x86/adler32_avx512_vnni.c b/3rdparty/zlib-ng/arch/x86/adler32_avx512_vnni.c new file mode 100644 index 000000000000..771f7ebe043f --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/adler32_avx512_vnni.c @@ -0,0 +1,225 @@ +/* adler32_avx512_vnni.c -- compute the Adler-32 checksum of a data stream + * Based on Brian Bockelman's AVX2 version + * Copyright (C) 1995-2011 Mark Adler + * Authors: + * Adam Stylinski + * Brian Bockelman + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef X86_AVX512VNNI + +#include "../../zbuild.h" +#include "../../adler32_p.h" +#include "../../cpu_features.h" +#include +#include "../../adler32_fold.h" +#include "x86_intrins.h" +#include "adler32_avx512_p.h" +#include "adler32_avx2_p.h" + +Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *src, size_t len) { + if (src == NULL) return 1L; + if (len == 0) return adler; + + uint32_t adler0, adler1; + adler1 = (adler >> 16) & 0xffff; + adler0 = adler & 0xffff; + +rem_peel: + if (len < 32) +#if defined(X86_SSSE3) + return adler32_ssse3(adler, src, len); +#else + return adler32_len_16(adler0, src, len, adler1); +#endif + + if (len < 64) +#ifdef X86_AVX2 + return adler32_avx2(adler, src, len); +#elif defined(X86_SSE3) + return adler32_ssse3(adler, src, len); +#else + return adler32_len_16(adler0, src, len, adler1); +#endif + + const __m512i dot2v = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64); + + const __m512i zero = _mm512_setzero_si512(); + __m512i vs1, vs2; + + while (len >= 64) { + vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler0)); + vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler1)); + size_t k = MIN(len, NMAX); + k -= k % 64; + len -= k; + __m512i vs1_0 = vs1; + __m512i vs3 = _mm512_setzero_si512(); + /* We might get a tad bit more ILP here if we sum to a second register in the loop */ + __m512i vs2_1 = _mm512_setzero_si512(); + __m512i vbuf0, vbuf1; + + /* Remainder peeling */ + if (k % 128) { + vbuf1 = _mm512_loadu_si512((__m512i*)src); + + src += 64; + k -= 64; + + __m512i vs1_sad = _mm512_sad_epu8(vbuf1, zero); + vs1 = _mm512_add_epi32(vs1, vs1_sad); + vs3 = _mm512_add_epi32(vs3, vs1_0); + vs2 = _mm512_dpbusd_epi32(vs2, vbuf1, dot2v); + vs1_0 = vs1; + } + + /* Manually unrolled this loop by 2 for an decent amount of ILP */ + while (k >= 128) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 64 vs1 + sum( (64-i+1) c[i] ) + */ + vbuf0 = _mm512_loadu_si512((__m512i*)src); + vbuf1 = _mm512_loadu_si512((__m512i*)(src + 64)); + src += 128; + k -= 128; + + __m512i vs1_sad = _mm512_sad_epu8(vbuf0, zero); + vs1 = _mm512_add_epi32(vs1, vs1_sad); + vs3 = _mm512_add_epi32(vs3, vs1_0); + /* multiply-add, resulting in 16 ints. Fuse with sum stage from prior versions, as we now have the dp + * instructions to eliminate them */ + vs2 = _mm512_dpbusd_epi32(vs2, vbuf0, dot2v); + + vs3 = _mm512_add_epi32(vs3, vs1); + vs1_sad = _mm512_sad_epu8(vbuf1, zero); + vs1 = _mm512_add_epi32(vs1, vs1_sad); + vs2_1 = _mm512_dpbusd_epi32(vs2_1, vbuf1, dot2v); + vs1_0 = vs1; + } + + vs3 = _mm512_slli_epi32(vs3, 6); + vs2 = _mm512_add_epi32(vs2, vs3); + vs2 = _mm512_add_epi32(vs2, vs2_1); + + adler0 = partial_hsum(vs1) % BASE; + adler1 = _mm512_reduce_add_epu32(vs2) % BASE; + } + + adler = adler0 | (adler1 << 16); + + /* Process tail (len < 64). */ + if (len) { + goto rem_peel; + } + + return adler; +} + +Z_INTERNAL uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { + if (src == NULL) return 1L; + if (len == 0) return adler; + + uint32_t adler0, adler1; + adler1 = (adler >> 16) & 0xffff; + adler0 = adler & 0xffff; + +rem_peel_copy: + if (len < 32) { + /* This handles the remaining copies, just call normal adler checksum after this */ + __mmask32 storemask = (0xFFFFFFFFUL >> (32 - len)); + __m256i copy_vec = _mm256_maskz_loadu_epi8(storemask, src); + _mm256_mask_storeu_epi8(dst, storemask, copy_vec); + +#if defined(X86_SSSE3) + return adler32_ssse3(adler, src, len); +#else + return adler32_len_16(adler0, src, len, adler1); +#endif + } + + const __m256i dot2v = _mm256_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + + const __m256i zero = _mm256_setzero_si256(); + __m256i vs1, vs2; + + while (len >= 32) { + vs1 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler0)); + vs2 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler1)); + size_t k = MIN(len, NMAX); + k -= k % 32; + len -= k; + __m256i vs1_0 = vs1; + __m256i vs3 = _mm256_setzero_si256(); + /* We might get a tad bit more ILP here if we sum to a second register in the loop */ + __m256i vs2_1 = _mm256_setzero_si256(); + __m256i vbuf0, vbuf1; + + /* Remainder peeling */ + if (k % 64) { + vbuf1 = _mm256_loadu_si256((__m256i*)src); + _mm256_storeu_si256((__m256i*)dst, vbuf1); + dst += 32; + + src += 32; + k -= 32; + + __m256i vs1_sad = _mm256_sad_epu8(vbuf1, zero); + vs1 = _mm256_add_epi32(vs1, vs1_sad); + vs3 = _mm256_add_epi32(vs3, vs1_0); + vs2 = _mm256_dpbusd_epi32(vs2, vbuf1, dot2v); + vs1_0 = vs1; + } + + /* Manually unrolled this loop by 2 for an decent amount of ILP */ + while (k >= 64) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 64 vs1 + sum( (64-i+1) c[i] ) + */ + vbuf0 = _mm256_loadu_si256((__m256i*)src); + vbuf1 = _mm256_loadu_si256((__m256i*)(src + 32)); + _mm256_storeu_si256((__m256i*)dst, vbuf0); + _mm256_storeu_si256((__m256i*)(dst + 32), vbuf1); + dst += 64; + src += 64; + k -= 64; + + __m256i vs1_sad = _mm256_sad_epu8(vbuf0, zero); + vs1 = _mm256_add_epi32(vs1, vs1_sad); + vs3 = _mm256_add_epi32(vs3, vs1_0); + /* multiply-add, resulting in 16 ints. Fuse with sum stage from prior versions, as we now have the dp + * instructions to eliminate them */ + vs2 = _mm256_dpbusd_epi32(vs2, vbuf0, dot2v); + + vs3 = _mm256_add_epi32(vs3, vs1); + vs1_sad = _mm256_sad_epu8(vbuf1, zero); + vs1 = _mm256_add_epi32(vs1, vs1_sad); + vs2_1 = _mm256_dpbusd_epi32(vs2_1, vbuf1, dot2v); + vs1_0 = vs1; + } + + vs3 = _mm256_slli_epi32(vs3, 5); + vs2 = _mm256_add_epi32(vs2, vs3); + vs2 = _mm256_add_epi32(vs2, vs2_1); + + adler0 = partial_hsum256(vs1) % BASE; + adler1 = hsum256(vs2) % BASE; + } + + adler = adler0 | (adler1 << 16); + + /* Process tail (len < 64). */ + if (len) { + goto rem_peel_copy; + } + + return adler; +} + +#endif diff --git a/3rdparty/zlib-ng/arch/x86/adler32_sse42.c b/3rdparty/zlib-ng/arch/x86/adler32_sse42.c new file mode 100644 index 000000000000..257a360982ed --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/adler32_sse42.c @@ -0,0 +1,121 @@ +/* adler32_sse42.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011 Mark Adler + * Authors: + * Adam Stylinski + * Brian Bockelman + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "../../zbuild.h" +#include "../../adler32_p.h" +#include "../../adler32_fold.h" +#include "adler32_ssse3_p.h" +#include + +#ifdef X86_SSE42 + +Z_INTERNAL uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { + uint32_t adler0, adler1; + adler1 = (adler >> 16) & 0xffff; + adler0 = adler & 0xffff; + +rem_peel: + if (len < 16) { + return adler32_copy_len_16(adler0, src, dst, len, adler1); + } + + __m128i vbuf, vbuf_0; + __m128i vs1_0, vs3, vs1, vs2, vs2_0, v_sad_sum1, v_short_sum2, v_short_sum2_0, + v_sad_sum2, vsum2, vsum2_0; + __m128i zero = _mm_setzero_si128(); + const __m128i dot2v = _mm_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17); + const __m128i dot2v_0 = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m128i dot3v = _mm_set1_epi16(1); + size_t k; + + while (len >= 16) { + + k = MIN(len, NMAX); + k -= k % 16; + len -= k; + + vs1 = _mm_cvtsi32_si128(adler0); + vs2 = _mm_cvtsi32_si128(adler1); + + vs3 = _mm_setzero_si128(); + vs2_0 = _mm_setzero_si128(); + vs1_0 = vs1; + + while (k >= 32) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + vbuf = _mm_loadu_si128((__m128i*)src); + vbuf_0 = _mm_loadu_si128((__m128i*)(src + 16)); + src += 32; + k -= 32; + + v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + v_sad_sum2 = _mm_sad_epu8(vbuf_0, zero); + _mm_storeu_si128((__m128i*)dst, vbuf); + _mm_storeu_si128((__m128i*)(dst + 16), vbuf_0); + dst += 32; + + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); + v_short_sum2_0 = _mm_maddubs_epi16(vbuf_0, dot2v_0); + + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + + vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + vsum2_0 = _mm_madd_epi16(v_short_sum2_0, dot3v); + vs1 = _mm_add_epi32(v_sad_sum2, vs1); + vs2 = _mm_add_epi32(vsum2, vs2); + vs2_0 = _mm_add_epi32(vsum2_0, vs2_0); + vs1_0 = vs1; + } + + vs2 = _mm_add_epi32(vs2_0, vs2); + vs3 = _mm_slli_epi32(vs3, 5); + vs2 = _mm_add_epi32(vs3, vs2); + vs3 = _mm_setzero_si128(); + + while (k >= 16) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + vbuf = _mm_loadu_si128((__m128i*)src); + src += 16; + k -= 16; + + v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v_0); + + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + vs2 = _mm_add_epi32(vsum2, vs2); + vs1_0 = vs1; + + _mm_storeu_si128((__m128i*)dst, vbuf); + dst += 16; + } + + vs3 = _mm_slli_epi32(vs3, 4); + vs2 = _mm_add_epi32(vs2, vs3); + + adler0 = partial_hsum(vs1) % BASE; + adler1 = hsum(vs2) % BASE; + } + + /* If this is true, there's fewer than 16 elements remaining */ + if (len) { + goto rem_peel; + } + + return adler0 | (adler1 << 16); +} + +#endif diff --git a/3rdparty/zlib-ng/arch/x86/adler32_ssse3.c b/3rdparty/zlib-ng/arch/x86/adler32_ssse3.c new file mode 100644 index 000000000000..ae819d632e53 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/adler32_ssse3.c @@ -0,0 +1,156 @@ +/* adler32_ssse3.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011 Mark Adler + * Authors: + * Adam Stylinski + * Brian Bockelman + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "../../zbuild.h" +#include "../../adler32_p.h" +#include "adler32_ssse3_p.h" + +#ifdef X86_SSSE3 + +#include + +Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, size_t len) { + uint32_t sum2; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (UNLIKELY(len == 1)) + return adler32_len_1(adler, buf, sum2); + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (UNLIKELY(buf == NULL)) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (UNLIKELY(len < 16)) + return adler32_len_16(adler, buf, len, sum2); + + const __m128i dot2v = _mm_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17); + const __m128i dot2v_0 = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m128i dot3v = _mm_set1_epi16(1); + const __m128i zero = _mm_setzero_si128(); + + __m128i vbuf, vs1_0, vs3, vs1, vs2, vs2_0, v_sad_sum1, v_short_sum2, v_short_sum2_0, + vbuf_0, v_sad_sum2, vsum2, vsum2_0; + + /* If our buffer is unaligned (likely), make the determination whether + * or not there's enough of a buffer to consume to make the scalar, aligning + * additions worthwhile or if it's worth it to just eat the cost of an unaligned + * load. This is a pretty simple test, just test if 16 - the remainder + len is + * < 16 */ + size_t max_iters = NMAX; + size_t rem = (uintptr_t)buf & 15; + size_t align_offset = 16 - rem; + size_t k = 0; + if (rem) { + if (len < 16 + align_offset) { + /* Let's eat the cost of this one unaligned load so that + * we don't completely skip over the vectorization. Doing + * 16 bytes at a time unaligned is better than 16 + <= 15 + * sums */ + vbuf = _mm_loadu_si128((__m128i*)buf); + len -= 16; + buf += 16; + vs1 = _mm_cvtsi32_si128(adler); + vs2 = _mm_cvtsi32_si128(sum2); + vs3 = _mm_setzero_si128(); + vs1_0 = vs1; + goto unaligned_jmp; + } + + for (size_t i = 0; i < align_offset; ++i) { + adler += *(buf++); + sum2 += adler; + } + + /* lop off the max number of sums based on the scalar sums done + * above */ + len -= align_offset; + max_iters -= align_offset; + } + + + while (len >= 16) { + vs1 = _mm_cvtsi32_si128(adler); + vs2 = _mm_cvtsi32_si128(sum2); + vs3 = _mm_setzero_si128(); + vs2_0 = _mm_setzero_si128(); + vs1_0 = vs1; + + k = (len < max_iters ? len : max_iters); + k -= k % 16; + len -= k; + + while (k >= 32) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + vbuf = _mm_load_si128((__m128i*)buf); + vbuf_0 = _mm_load_si128((__m128i*)(buf + 16)); + buf += 32; + k -= 32; + + v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + v_sad_sum2 = _mm_sad_epu8(vbuf_0, zero); + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + + vs1 = _mm_add_epi32(v_sad_sum2, vs1); + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); + vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + v_short_sum2_0 = _mm_maddubs_epi16(vbuf_0, dot2v_0); + vs2 = _mm_add_epi32(vsum2, vs2); + vsum2_0 = _mm_madd_epi16(v_short_sum2_0, dot3v); + vs2_0 = _mm_add_epi32(vsum2_0, vs2_0); + vs1_0 = vs1; + } + + vs2 = _mm_add_epi32(vs2_0, vs2); + vs3 = _mm_slli_epi32(vs3, 5); + vs2 = _mm_add_epi32(vs3, vs2); + vs3 = _mm_setzero_si128(); + + while (k >= 16) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + vbuf = _mm_load_si128((__m128i*)buf); + buf += 16; + k -= 16; + +unaligned_jmp: + v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v_0); + vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + vs2 = _mm_add_epi32(vsum2, vs2); + vs1_0 = vs1; + } + + vs3 = _mm_slli_epi32(vs3, 4); + vs2 = _mm_add_epi32(vs2, vs3); + + /* We don't actually need to do a full horizontal sum, since psadbw is actually doing + * a partial reduction sum implicitly and only summing to integers in vector positions + * 0 and 2. This saves us some contention on the shuffle port(s) */ + adler = partial_hsum(vs1) % BASE; + sum2 = hsum(vs2) % BASE; + max_iters = NMAX; + } + + /* Process tail (len < 16). */ + return adler32_len_16(adler, buf, len, sum2); +} + +#endif diff --git a/3rdparty/zlib-ng/arch/x86/adler32_ssse3_p.h b/3rdparty/zlib-ng/arch/x86/adler32_ssse3_p.h new file mode 100644 index 000000000000..d7ec3fe0d5a3 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/adler32_ssse3_p.h @@ -0,0 +1,29 @@ +/* adler32_ssse3_p.h -- adler32 ssse3 utility functions + * Copyright (C) 2022 Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ADLER32_SSSE3_P_H_ +#define ADLER32_SSSE3_P_H_ + +#ifdef X86_SSSE3 + +#include +#include + +static inline uint32_t partial_hsum(__m128i x) { + __m128i second_int = _mm_srli_si128(x, 8); + __m128i sum = _mm_add_epi32(x, second_int); + return _mm_cvtsi128_si32(sum); +} + +static inline uint32_t hsum(__m128i x) { + __m128i sum1 = _mm_unpackhi_epi64(x, x); + __m128i sum2 = _mm_add_epi32(x, sum1); + __m128i sum3 = _mm_shuffle_epi32(sum2, 0x01); + __m128i sum4 = _mm_add_epi32(sum2, sum3); + return _mm_cvtsi128_si32(sum4); +} +#endif + +#endif diff --git a/3rdparty/zlib-ng/arch/x86/chunkset_avx2.c b/3rdparty/zlib-ng/arch/x86/chunkset_avx2.c new file mode 100644 index 000000000000..70620b91542e --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/chunkset_avx2.c @@ -0,0 +1,133 @@ +/* chunkset_avx2.c -- AVX2 inline functions to copy small data chunks. + * For conditions of distribution and use, see copyright notice in zlib.h + */ +#include "zbuild.h" + +#ifdef X86_AVX2 +#include +#include "../generic/chunk_permute_table.h" + +typedef __m256i chunk_t; + +#define CHUNK_SIZE 32 + +#define HAVE_CHUNKMEMSET_2 +#define HAVE_CHUNKMEMSET_4 +#define HAVE_CHUNKMEMSET_8 +#define HAVE_CHUNK_MAG + +/* Populate don't cares so that this is a direct lookup (with some indirection into the permute table), because dist can + * never be 0 - 2, we'll start with an offset, subtracting 3 from the input */ +static const lut_rem_pair perm_idx_lut[29] = { + { 0, 2}, /* 3 */ + { 0, 0}, /* don't care */ + { 1 * 32, 2}, /* 5 */ + { 2 * 32, 2}, /* 6 */ + { 3 * 32, 4}, /* 7 */ + { 0 * 32, 0}, /* don't care */ + { 4 * 32, 5}, /* 9 */ + { 5 * 32, 22}, /* 10 */ + { 6 * 32, 21}, /* 11 */ + { 7 * 32, 20}, /* 12 */ + { 8 * 32, 6}, /* 13 */ + { 9 * 32, 4}, /* 14 */ + {10 * 32, 2}, /* 15 */ + { 0 * 32, 0}, /* don't care */ + {11 * 32, 15}, /* 17 */ + {11 * 32 + 16, 14}, /* 18 */ + {11 * 32 + 16 * 2, 13}, /* 19 */ + {11 * 32 + 16 * 3, 12}, /* 20 */ + {11 * 32 + 16 * 4, 11}, /* 21 */ + {11 * 32 + 16 * 5, 10}, /* 22 */ + {11 * 32 + 16 * 6, 9}, /* 23 */ + {11 * 32 + 16 * 7, 8}, /* 24 */ + {11 * 32 + 16 * 8, 7}, /* 25 */ + {11 * 32 + 16 * 9, 6}, /* 26 */ + {11 * 32 + 16 * 10, 5}, /* 27 */ + {11 * 32 + 16 * 11, 4}, /* 28 */ + {11 * 32 + 16 * 12, 3}, /* 29 */ + {11 * 32 + 16 * 13, 2}, /* 30 */ + {11 * 32 + 16 * 14, 1} /* 31 */ +}; + +static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { + int16_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = _mm256_set1_epi16(tmp); +} + +static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { + int32_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = _mm256_set1_epi32(tmp); +} + +static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { + int64_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = _mm256_set1_epi64x(tmp); +} + +static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { + *chunk = _mm256_loadu_si256((__m256i *)s); +} + +static inline void storechunk(uint8_t *out, chunk_t *chunk) { + _mm256_storeu_si256((__m256i *)out, *chunk); +} + +static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t dist) { + lut_rem_pair lut_rem = perm_idx_lut[dist - 3]; + __m256i ret_vec; + /* While technically we only need to read 4 or 8 bytes into this vector register for a lot of cases, GCC is + * compiling this to a shared load for all branches, preferring the simpler code. Given that the buf value isn't in + * GPRs to begin with the 256 bit load is _probably_ just as inexpensive */ + *chunk_rem = lut_rem.remval; + + /* See note in chunkset_ssse3.c for why this is ok */ + __msan_unpoison(buf + dist, 32 - dist); + + if (dist < 16) { + /* This simpler case still requires us to shuffle in 128 bit lanes, so we must apply a static offset after + * broadcasting the first vector register to both halves. This is _marginally_ faster than doing two separate + * shuffles and combining the halves later */ + const __m256i permute_xform = + _mm256_setr_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16); + __m256i perm_vec = _mm256_load_si256((__m256i*)(permute_table+lut_rem.idx)); + __m128i ret_vec0 = _mm_loadu_si128((__m128i*)buf); + perm_vec = _mm256_add_epi8(perm_vec, permute_xform); + ret_vec = _mm256_inserti128_si256(_mm256_castsi128_si256(ret_vec0), ret_vec0, 1); + ret_vec = _mm256_shuffle_epi8(ret_vec, perm_vec); + } else if (dist == 16) { + __m128i ret_vec0 = _mm_loadu_si128((__m128i*)buf); + return _mm256_inserti128_si256(_mm256_castsi128_si256(ret_vec0), ret_vec0, 1); + } else { + __m128i ret_vec0 = _mm_loadu_si128((__m128i*)buf); + __m128i ret_vec1 = _mm_loadu_si128((__m128i*)(buf + 16)); + /* Take advantage of the fact that only the latter half of the 256 bit vector will actually differ */ + __m128i perm_vec1 = _mm_load_si128((__m128i*)(permute_table + lut_rem.idx)); + __m128i xlane_permutes = _mm_cmpgt_epi8(_mm_set1_epi8(16), perm_vec1); + __m128i xlane_res = _mm_shuffle_epi8(ret_vec0, perm_vec1); + /* Since we can't wrap twice, we can simply keep the later half exactly how it is instead of having to _also_ + * shuffle those values */ + __m128i latter_half = _mm_blendv_epi8(ret_vec1, xlane_res, xlane_permutes); + ret_vec = _mm256_inserti128_si256(_mm256_castsi128_si256(ret_vec0), latter_half, 1); + } + + return ret_vec; +} + +#define CHUNKSIZE chunksize_avx2 +#define CHUNKCOPY chunkcopy_avx2 +#define CHUNKUNROLL chunkunroll_avx2 +#define CHUNKMEMSET chunkmemset_avx2 +#define CHUNKMEMSET_SAFE chunkmemset_safe_avx2 + +#include "chunkset_tpl.h" + +#define INFLATE_FAST inflate_fast_avx2 + +#include "inffast_tpl.h" + +#endif diff --git a/3rdparty/zlib-ng/arch/x86/chunkset_sse2.c b/3rdparty/zlib-ng/arch/x86/chunkset_sse2.c new file mode 100644 index 000000000000..c402c0ee18f6 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/chunkset_sse2.c @@ -0,0 +1,56 @@ +/* chunkset_sse2.c -- SSE2 inline functions to copy small data chunks. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" + +#ifdef X86_SSE2 +#include + +typedef __m128i chunk_t; + +#define CHUNK_SIZE 16 + +#define HAVE_CHUNKMEMSET_2 +#define HAVE_CHUNKMEMSET_4 +#define HAVE_CHUNKMEMSET_8 + +static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { + int16_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = _mm_set1_epi16(tmp); +} + +static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { + int32_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = _mm_set1_epi32(tmp); +} + +static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { + int64_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = _mm_set1_epi64x(tmp); +} + +static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { + *chunk = _mm_loadu_si128((__m128i *)s); +} + +static inline void storechunk(uint8_t *out, chunk_t *chunk) { + _mm_storeu_si128((__m128i *)out, *chunk); +} + +#define CHUNKSIZE chunksize_sse2 +#define CHUNKCOPY chunkcopy_sse2 +#define CHUNKUNROLL chunkunroll_sse2 +#define CHUNKMEMSET chunkmemset_sse2 +#define CHUNKMEMSET_SAFE chunkmemset_safe_sse2 + +#include "chunkset_tpl.h" + +#define INFLATE_FAST inflate_fast_sse2 + +#include "inffast_tpl.h" + +#endif diff --git a/3rdparty/zlib-ng/arch/x86/chunkset_ssse3.c b/3rdparty/zlib-ng/arch/x86/chunkset_ssse3.c new file mode 100644 index 000000000000..c06d1b37bd7e --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/chunkset_ssse3.c @@ -0,0 +1,101 @@ +/* chunkset_ssse3.c -- SSSE3 inline functions to copy small data chunks. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" + +/* This requires SSE2 support. While it's implicit with SSSE3, we can minimize + * code size by sharing the chunkcopy functions, which will certainly compile + * to identical machine code */ +#if defined(X86_SSSE3) && defined(X86_SSE2) +#include +#include "../generic/chunk_permute_table.h" + +typedef __m128i chunk_t; + +#define CHUNK_SIZE 16 + +#define HAVE_CHUNKMEMSET_2 +#define HAVE_CHUNKMEMSET_4 +#define HAVE_CHUNKMEMSET_8 +#define HAVE_CHUNK_MAG +#define HAVE_CHUNKCOPY +#define HAVE_CHUNKUNROLL + +static const lut_rem_pair perm_idx_lut[13] = { + {0, 1}, /* 3 */ + {0, 0}, /* don't care */ + {1 * 32, 1}, /* 5 */ + {2 * 32, 4}, /* 6 */ + {3 * 32, 2}, /* 7 */ + {0 * 32, 0}, /* don't care */ + {4 * 32, 7}, /* 9 */ + {5 * 32, 6}, /* 10 */ + {6 * 32, 5}, /* 11 */ + {7 * 32, 4}, /* 12 */ + {8 * 32, 3}, /* 13 */ + {9 * 32, 2}, /* 14 */ + {10 * 32, 1},/* 15 */ +}; + + +static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { + int16_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = _mm_set1_epi16(tmp); +} + +static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { + int32_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = _mm_set1_epi32(tmp); +} + +static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { + int64_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + *chunk = _mm_set1_epi64x(tmp); +} + +static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { + *chunk = _mm_loadu_si128((__m128i *)s); +} + +static inline void storechunk(uint8_t *out, chunk_t *chunk) { + _mm_storeu_si128((__m128i *)out, *chunk); +} + +static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t dist) { + lut_rem_pair lut_rem = perm_idx_lut[dist - 3]; + __m128i perm_vec, ret_vec; + /* Important to note: + * This is _not_ to subvert the memory sanitizer but to instead unpoison some + * bytes we willingly and purposefully load uninitialized that we swizzle over + * in a vector register, anyway. If what we assume is wrong about what is used, + * the memory sanitizer will still usefully flag it */ + __msan_unpoison(buf + dist, 16 - dist); + ret_vec = _mm_loadu_si128((__m128i*)buf); + *chunk_rem = lut_rem.remval; + + perm_vec = _mm_load_si128((__m128i*)(permute_table + lut_rem.idx)); + ret_vec = _mm_shuffle_epi8(ret_vec, perm_vec); + + return ret_vec; +} + +extern uint8_t* chunkcopy_sse2(uint8_t *out, uint8_t const *from, unsigned len); +extern uint8_t* chunkunroll_sse2(uint8_t *out, unsigned *dist, unsigned *len); + +#define CHUNKSIZE chunksize_ssse3 +#define CHUNKMEMSET chunkmemset_ssse3 +#define CHUNKMEMSET_SAFE chunkmemset_safe_ssse3 +#define CHUNKCOPY chunkcopy_sse2 +#define CHUNKUNROLL chunkunroll_sse2 + +#include "chunkset_tpl.h" + +#define INFLATE_FAST inflate_fast_ssse3 + +#include "inffast_tpl.h" + +#endif diff --git a/3rdparty/zlib-ng/arch/x86/compare256_avx2.c b/3rdparty/zlib-ng/arch/x86/compare256_avx2.c new file mode 100644 index 000000000000..1318a0e333a4 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/compare256_avx2.c @@ -0,0 +1,63 @@ +/* compare256_avx2.c -- AVX2 version of compare256 + * Copyright Mika T. Lindqvist + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "../../zbuild.h" + +#include "fallback_builtins.h" + +#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) + +#include +#ifdef _MSC_VER +# include +#endif + +static inline uint32_t compare256_avx2_static(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + + do { + __m256i ymm_src0, ymm_src1, ymm_cmp; + ymm_src0 = _mm256_loadu_si256((__m256i*)src0); + ymm_src1 = _mm256_loadu_si256((__m256i*)src1); + ymm_cmp = _mm256_cmpeq_epi8(ymm_src0, ymm_src1); /* non-identical bytes = 00, identical bytes = FF */ + unsigned mask = (unsigned)_mm256_movemask_epi8(ymm_cmp); + if (mask != 0xFFFFFFFF) { + uint32_t match_byte = (uint32_t)__builtin_ctz(~mask); /* Invert bits so identical = 0 */ + return len + match_byte; + } + + src0 += 32, src1 += 32, len += 32; + + ymm_src0 = _mm256_loadu_si256((__m256i*)src0); + ymm_src1 = _mm256_loadu_si256((__m256i*)src1); + ymm_cmp = _mm256_cmpeq_epi8(ymm_src0, ymm_src1); + mask = (unsigned)_mm256_movemask_epi8(ymm_cmp); + if (mask != 0xFFFFFFFF) { + uint32_t match_byte = (uint32_t)__builtin_ctz(~mask); + return len + match_byte; + } + + src0 += 32, src1 += 32, len += 32; + } while (len < 256); + + return 256; +} + +Z_INTERNAL uint32_t compare256_avx2(const uint8_t *src0, const uint8_t *src1) { + return compare256_avx2_static(src0, src1); +} + +#define LONGEST_MATCH longest_match_avx2 +#define COMPARE256 compare256_avx2_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_avx2 +#define COMPARE256 compare256_avx2_static + +#include "match_tpl.h" + +#endif diff --git a/3rdparty/zlib-ng/arch/x86/compare256_sse2.c b/3rdparty/zlib-ng/arch/x86/compare256_sse2.c new file mode 100644 index 000000000000..aad4bd240d20 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/compare256_sse2.c @@ -0,0 +1,96 @@ +/* compare256_sse2.c -- SSE2 version of compare256 + * Copyright Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "../../zbuild.h" + +#include "fallback_builtins.h" + +#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) + +#include + +static inline uint32_t compare256_sse2_static(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + int align_offset = ((uintptr_t)src0) & 15; + const uint8_t *end0 = src0 + 256; + const uint8_t *end1 = src1 + 256; + __m128i xmm_src0, xmm_src1, xmm_cmp; + + /* Do the first load unaligned, than all subsequent ones we have at least + * one aligned load. Sadly aligning both loads is probably unrealistic */ + xmm_src0 = _mm_loadu_si128((__m128i*)src0); + xmm_src1 = _mm_loadu_si128((__m128i*)src1); + xmm_cmp = _mm_cmpeq_epi8(xmm_src0, xmm_src1); + + unsigned mask = (unsigned)_mm_movemask_epi8(xmm_cmp); + + /* Compiler _may_ turn this branch into a ptest + movemask, + * since a lot of those uops are shared and fused */ + if (mask != 0xFFFF) { + uint32_t match_byte = (uint32_t)__builtin_ctz(~mask); + return len + match_byte; + } + + int align_adv = 16 - align_offset; + len += align_adv; + src0 += align_adv; + src1 += align_adv; + + /* Do a flooring division (should just be a shift right) */ + int num_iter = (256 - len) / 16; + + for (int i = 0; i < num_iter; ++i) { + xmm_src0 = _mm_load_si128((__m128i*)src0); + xmm_src1 = _mm_loadu_si128((__m128i*)src1); + xmm_cmp = _mm_cmpeq_epi8(xmm_src0, xmm_src1); + + mask = (unsigned)_mm_movemask_epi8(xmm_cmp); + + /* Compiler _may_ turn this branch into a ptest + movemask, + * since a lot of those uops are shared and fused */ + if (mask != 0xFFFF) { + uint32_t match_byte = (uint32_t)__builtin_ctz(~mask); + return len + match_byte; + } + + len += 16, src0 += 16, src1 += 16; + } + + if (align_offset) { + src0 = end0 - 16; + src1 = end1 - 16; + len = 256 - 16; + + xmm_src0 = _mm_loadu_si128((__m128i*)src0); + xmm_src1 = _mm_loadu_si128((__m128i*)src1); + xmm_cmp = _mm_cmpeq_epi8(xmm_src0, xmm_src1); + + mask = (unsigned)_mm_movemask_epi8(xmm_cmp); + + if (mask != 0xFFFF) { + uint32_t match_byte = (uint32_t)__builtin_ctz(~mask); + return len + match_byte; + } + } + + return 256; +} + +Z_INTERNAL uint32_t compare256_sse2(const uint8_t *src0, const uint8_t *src1) { + return compare256_sse2_static(src0, src1); +} + +#define LONGEST_MATCH longest_match_sse2 +#define COMPARE256 compare256_sse2_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_sse2 +#define COMPARE256 compare256_sse2_static + +#include "match_tpl.h" + +#endif diff --git a/3rdparty/zlib-ng/arch/x86/crc32_fold_pclmulqdq_tpl.h b/3rdparty/zlib-ng/arch/x86/crc32_fold_pclmulqdq_tpl.h new file mode 100644 index 000000000000..3e799283173c --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/crc32_fold_pclmulqdq_tpl.h @@ -0,0 +1,186 @@ +/* + * Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ + * instruction. + * + * A white paper describing this algorithm can be found at: + * doc/crc-pclmulqdq.pdf + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * Copyright (C) 2016 Marian Beermann (support for initial value) + * Authors: + * Wajdi Feghali + * Jim Guilford + * Vinodh Gopal + * Erdinc Ozturk + * Jim Kukunas + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef COPY +Z_INTERNAL void CRC32_FOLD_COPY(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { +#else +Z_INTERNAL void CRC32_FOLD(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { +#endif + unsigned long algn_diff; + __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; + __m128i xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3; + __m128i xmm_crc_part = _mm_setzero_si128(); +#ifdef COPY + char ALIGNED_(16) partial_buf[16] = { 0 }; +#else + __m128i xmm_initial = _mm_cvtsi32_si128(init_crc); + int32_t first = init_crc != 0; + + /* Technically the CRC functions don't even call this for input < 64, but a bare minimum of 31 + * bytes of input is needed for the aligning load that occurs. If there's an initial CRC, to + * carry it forward through the folded CRC there must be 16 - src % 16 + 16 bytes available, which + * by definition can be up to 15 bytes + one full vector load. */ + assert(len >= 31 || first == 0); +#endif + crc32_fold_load((__m128i *)crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + if (len < 16) { +#ifdef COPY + if (len == 0) + return; + + memcpy(partial_buf, src, len); + xmm_crc_part = _mm_load_si128((const __m128i *)partial_buf); + memcpy(dst, partial_buf, len); +#endif + goto partial; + } + + algn_diff = ((uintptr_t)16 - ((uintptr_t)src & 0xF)) & 0xF; + if (algn_diff) { + xmm_crc_part = _mm_loadu_si128((__m128i *)src); +#ifdef COPY + _mm_storeu_si128((__m128i *)dst, xmm_crc_part); + dst += algn_diff; +#else + XOR_INITIAL128(xmm_crc_part); + + if (algn_diff < 4 && init_crc != 0) { + xmm_t0 = xmm_crc_part; + xmm_crc_part = _mm_loadu_si128((__m128i*)src + 1); + fold_1(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0); + src += 16; + len -= 16; + } +#endif + + partial_fold(algn_diff, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); + + src += algn_diff; + len -= algn_diff; + } + +#ifdef X86_VPCLMULQDQ + if (len >= 256) { +#ifdef COPY + size_t n = fold_16_vpclmulqdq_copy(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, dst, src, len); + dst += n; +#else + size_t n = fold_16_vpclmulqdq(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, src, len, + xmm_initial, first); + first = 0; +#endif + len -= n; + src += n; + } +#endif + + while (len >= 64) { + len -= 64; + xmm_t0 = _mm_load_si128((__m128i *)src); + xmm_t1 = _mm_load_si128((__m128i *)src + 1); + xmm_t2 = _mm_load_si128((__m128i *)src + 2); + xmm_t3 = _mm_load_si128((__m128i *)src + 3); + src += 64; + + fold_4(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); +#ifdef COPY + _mm_storeu_si128((__m128i *)dst, xmm_t0); + _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); + _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); + _mm_storeu_si128((__m128i *)dst + 3, xmm_t3); + dst += 64; +#else + XOR_INITIAL128(xmm_t0); +#endif + + xmm_crc0 = _mm_xor_si128(xmm_crc0, xmm_t0); + xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t1); + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t2); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t3); + } + + /* + * len = num bytes left - 64 + */ + if (len >= 48) { + len -= 48; + + xmm_t0 = _mm_load_si128((__m128i *)src); + xmm_t1 = _mm_load_si128((__m128i *)src + 1); + xmm_t2 = _mm_load_si128((__m128i *)src + 2); + src += 48; +#ifdef COPY + _mm_storeu_si128((__m128i *)dst, xmm_t0); + _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); + _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); + dst += 48; +#else + XOR_INITIAL128(xmm_t0); +#endif + fold_3(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t0); + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t1); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t2); + } else if (len >= 32) { + len -= 32; + + xmm_t0 = _mm_load_si128((__m128i *)src); + xmm_t1 = _mm_load_si128((__m128i *)src + 1); + src += 32; +#ifdef COPY + _mm_storeu_si128((__m128i *)dst, xmm_t0); + _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); + dst += 32; +#else + XOR_INITIAL128(xmm_t0); +#endif + fold_2(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t0); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t1); + } else if (len >= 16) { + len -= 16; + xmm_t0 = _mm_load_si128((__m128i *)src); + src += 16; +#ifdef COPY + _mm_storeu_si128((__m128i *)dst, xmm_t0); + dst += 16; +#else + XOR_INITIAL128(xmm_t0); +#endif + fold_1(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0); + } + +partial: + if (len) { + memcpy(&xmm_crc_part, src, len); +#ifdef COPY + _mm_storeu_si128((__m128i *)partial_buf, xmm_crc_part); + memcpy(dst, partial_buf, len); +#endif + partial_fold(len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); + } + + crc32_fold_save((__m128i *)crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); +} diff --git a/3rdparty/zlib-ng/arch/x86/crc32_fold_vpclmulqdq_tpl.h b/3rdparty/zlib-ng/arch/x86/crc32_fold_vpclmulqdq_tpl.h new file mode 100644 index 000000000000..3ea5c33055b0 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/crc32_fold_vpclmulqdq_tpl.h @@ -0,0 +1,107 @@ +/* crc32_fold_vpclmulqdq_tpl.h -- VPCMULQDQ-based CRC32 folding template. + * Copyright Wangyang Guo (wangyang.guo@intel.com) + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef COPY +static size_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len) { +#else +static size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, size_t len, + __m128i init_crc, int32_t first) { + __m512i zmm_initial = _mm512_zextsi128_si512(init_crc); +#endif + __m512i zmm_t0, zmm_t1, zmm_t2, zmm_t3; + __m512i zmm_crc0, zmm_crc1, zmm_crc2, zmm_crc3; + __m512i z0, z1, z2, z3; + size_t len_tmp = len; + const __m512i zmm_fold4 = _mm512_set4_epi32( + 0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596); + const __m512i zmm_fold16 = _mm512_set4_epi32( + 0x00000001, 0x1542778a, 0x00000001, 0x322d1430); + + // zmm register init + zmm_crc0 = _mm512_setzero_si512(); + zmm_t0 = _mm512_loadu_si512((__m512i *)src); +#ifndef COPY + XOR_INITIAL512(zmm_t0); +#endif + zmm_crc1 = _mm512_loadu_si512((__m512i *)src + 1); + zmm_crc2 = _mm512_loadu_si512((__m512i *)src + 2); + zmm_crc3 = _mm512_loadu_si512((__m512i *)src + 3); + + /* already have intermediate CRC in xmm registers + * fold4 with 4 xmm_crc to get zmm_crc0 + */ + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc0, 0); + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc1, 1); + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc2, 2); + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc3, 3); + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_ternarylogic_epi32(zmm_crc0, z0, zmm_t0, 0x96); + +#ifdef COPY + _mm512_storeu_si512((__m512i *)dst, zmm_t0); + _mm512_storeu_si512((__m512i *)dst + 1, zmm_crc1); + _mm512_storeu_si512((__m512i *)dst + 2, zmm_crc2); + _mm512_storeu_si512((__m512i *)dst + 3, zmm_crc3); + dst += 256; +#endif + len -= 256; + src += 256; + + // fold-16 loops + while (len >= 256) { + zmm_t0 = _mm512_loadu_si512((__m512i *)src); + zmm_t1 = _mm512_loadu_si512((__m512i *)src + 1); + zmm_t2 = _mm512_loadu_si512((__m512i *)src + 2); + zmm_t3 = _mm512_loadu_si512((__m512i *)src + 3); + + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold16, 0x01); + z1 = _mm512_clmulepi64_epi128(zmm_crc1, zmm_fold16, 0x01); + z2 = _mm512_clmulepi64_epi128(zmm_crc2, zmm_fold16, 0x01); + z3 = _mm512_clmulepi64_epi128(zmm_crc3, zmm_fold16, 0x01); + + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold16, 0x10); + zmm_crc1 = _mm512_clmulepi64_epi128(zmm_crc1, zmm_fold16, 0x10); + zmm_crc2 = _mm512_clmulepi64_epi128(zmm_crc2, zmm_fold16, 0x10); + zmm_crc3 = _mm512_clmulepi64_epi128(zmm_crc3, zmm_fold16, 0x10); + + zmm_crc0 = _mm512_ternarylogic_epi32(zmm_crc0, z0, zmm_t0, 0x96); + zmm_crc1 = _mm512_ternarylogic_epi32(zmm_crc1, z1, zmm_t1, 0x96); + zmm_crc2 = _mm512_ternarylogic_epi32(zmm_crc2, z2, zmm_t2, 0x96); + zmm_crc3 = _mm512_ternarylogic_epi32(zmm_crc3, z3, zmm_t3, 0x96); + +#ifdef COPY + _mm512_storeu_si512((__m512i *)dst, zmm_t0); + _mm512_storeu_si512((__m512i *)dst + 1, zmm_t1); + _mm512_storeu_si512((__m512i *)dst + 2, zmm_t2); + _mm512_storeu_si512((__m512i *)dst + 3, zmm_t3); + dst += 256; +#endif + len -= 256; + src += 256; + } + // zmm_crc[0,1,2,3] -> zmm_crc0 + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_ternarylogic_epi32(zmm_crc0, z0, zmm_crc1, 0x96); + + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_ternarylogic_epi32(zmm_crc0, z0, zmm_crc2, 0x96); + + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_ternarylogic_epi32(zmm_crc0, z0, zmm_crc3, 0x96); + + // zmm_crc0 -> xmm_crc[0, 1, 2, 3] + *xmm_crc0 = _mm512_extracti32x4_epi32(zmm_crc0, 0); + *xmm_crc1 = _mm512_extracti32x4_epi32(zmm_crc0, 1); + *xmm_crc2 = _mm512_extracti32x4_epi32(zmm_crc0, 2); + *xmm_crc3 = _mm512_extracti32x4_epi32(zmm_crc0, 3); + + return (len_tmp - len); // return n bytes processed +} diff --git a/3rdparty/zlib-ng/arch/x86/crc32_pclmulqdq.c b/3rdparty/zlib-ng/arch/x86/crc32_pclmulqdq.c new file mode 100644 index 000000000000..9383b7a2ba00 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/crc32_pclmulqdq.c @@ -0,0 +1,30 @@ +/* + * Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ + * instruction. + * + * A white paper describing this algorithm can be found at: + * doc/crc-pclmulqdq.pdf + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * Copyright (C) 2016 Marian Beermann (support for initial value) + * Authors: + * Wajdi Feghali + * Jim Guilford + * Vinodh Gopal + * Erdinc Ozturk + * Jim Kukunas + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef X86_PCLMULQDQ_CRC + +#define CRC32_FOLD_COPY crc32_fold_pclmulqdq_copy +#define CRC32_FOLD crc32_fold_pclmulqdq +#define CRC32_FOLD_RESET crc32_fold_pclmulqdq_reset +#define CRC32_FOLD_FINAL crc32_fold_pclmulqdq_final +#define CRC32 crc32_pclmulqdq + +#include "crc32_pclmulqdq_tpl.h" + +#endif diff --git a/3rdparty/zlib-ng/arch/x86/crc32_pclmulqdq_tpl.h b/3rdparty/zlib-ng/arch/x86/crc32_pclmulqdq_tpl.h new file mode 100644 index 000000000000..05d3b15257f7 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/crc32_pclmulqdq_tpl.h @@ -0,0 +1,363 @@ +/* + * Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ + * instruction. + * + * A white paper describing this algorithm can be found at: + * doc/crc-pclmulqdq.pdf + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * Copyright (C) 2016 Marian Beermann (support for initial value) + * Authors: + * Wajdi Feghali + * Jim Guilford + * Vinodh Gopal + * Erdinc Ozturk + * Jim Kukunas + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "../../zbuild.h" + +#include +#include +#include // _mm_extract_epi32 +#ifdef X86_VPCLMULQDQ +# include +#endif + +#include "../../crc32_fold.h" +#include "../../crc32_braid_p.h" +#include "x86_intrins.h" +#include + +#ifdef X86_VPCLMULQDQ +static size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, size_t len, __m128i init_crc, + int32_t first); +static size_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len); +#endif + +static void fold_1(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { + const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + __m128i x_tmp3; + __m128 ps_crc0, ps_crc3, ps_res; + + x_tmp3 = *xmm_crc3; + + *xmm_crc3 = *xmm_crc0; + *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); + *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); + ps_crc0 = _mm_castsi128_ps(*xmm_crc0); + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + ps_res = _mm_xor_ps(ps_crc0, ps_crc3); + + *xmm_crc0 = *xmm_crc1; + *xmm_crc1 = *xmm_crc2; + *xmm_crc2 = x_tmp3; + *xmm_crc3 = _mm_castps_si128(ps_res); +} + +static void fold_2(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { + const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + __m128i x_tmp3, x_tmp2; + __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res31, ps_res20; + + x_tmp3 = *xmm_crc3; + x_tmp2 = *xmm_crc2; + + *xmm_crc3 = *xmm_crc1; + *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); + *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + ps_crc1 = _mm_castsi128_ps(*xmm_crc1); + ps_res31 = _mm_xor_ps(ps_crc3, ps_crc1); + + *xmm_crc2 = *xmm_crc0; + *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); + *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10); + ps_crc0 = _mm_castsi128_ps(*xmm_crc0); + ps_crc2 = _mm_castsi128_ps(*xmm_crc2); + ps_res20 = _mm_xor_ps(ps_crc0, ps_crc2); + + *xmm_crc0 = x_tmp2; + *xmm_crc1 = x_tmp3; + *xmm_crc2 = _mm_castps_si128(ps_res20); + *xmm_crc3 = _mm_castps_si128(ps_res31); +} + +static void fold_3(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { + const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + __m128i x_tmp3; + __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res32, ps_res21, ps_res10; + + x_tmp3 = *xmm_crc3; + + *xmm_crc3 = *xmm_crc2; + *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01); + *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); + ps_crc2 = _mm_castsi128_ps(*xmm_crc2); + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + ps_res32 = _mm_xor_ps(ps_crc2, ps_crc3); + + *xmm_crc2 = *xmm_crc1; + *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); + *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10); + ps_crc1 = _mm_castsi128_ps(*xmm_crc1); + ps_crc2 = _mm_castsi128_ps(*xmm_crc2); + ps_res21 = _mm_xor_ps(ps_crc1, ps_crc2); + + *xmm_crc1 = *xmm_crc0; + *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); + *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x10); + ps_crc0 = _mm_castsi128_ps(*xmm_crc0); + ps_crc1 = _mm_castsi128_ps(*xmm_crc1); + ps_res10 = _mm_xor_ps(ps_crc0, ps_crc1); + + *xmm_crc0 = x_tmp3; + *xmm_crc1 = _mm_castps_si128(ps_res10); + *xmm_crc2 = _mm_castps_si128(ps_res21); + *xmm_crc3 = _mm_castps_si128(ps_res32); +} + +static void fold_4(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { + const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + __m128i x_tmp0, x_tmp1, x_tmp2, x_tmp3; + __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3; + __m128 ps_t0, ps_t1, ps_t2, ps_t3; + __m128 ps_res0, ps_res1, ps_res2, ps_res3; + + x_tmp0 = *xmm_crc0; + x_tmp1 = *xmm_crc1; + x_tmp2 = *xmm_crc2; + x_tmp3 = *xmm_crc3; + + *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); + x_tmp0 = _mm_clmulepi64_si128(x_tmp0, xmm_fold4, 0x10); + ps_crc0 = _mm_castsi128_ps(*xmm_crc0); + ps_t0 = _mm_castsi128_ps(x_tmp0); + ps_res0 = _mm_xor_ps(ps_crc0, ps_t0); + + *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); + x_tmp1 = _mm_clmulepi64_si128(x_tmp1, xmm_fold4, 0x10); + ps_crc1 = _mm_castsi128_ps(*xmm_crc1); + ps_t1 = _mm_castsi128_ps(x_tmp1); + ps_res1 = _mm_xor_ps(ps_crc1, ps_t1); + + *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01); + x_tmp2 = _mm_clmulepi64_si128(x_tmp2, xmm_fold4, 0x10); + ps_crc2 = _mm_castsi128_ps(*xmm_crc2); + ps_t2 = _mm_castsi128_ps(x_tmp2); + ps_res2 = _mm_xor_ps(ps_crc2, ps_t2); + + *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x01); + x_tmp3 = _mm_clmulepi64_si128(x_tmp3, xmm_fold4, 0x10); + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + ps_t3 = _mm_castsi128_ps(x_tmp3); + ps_res3 = _mm_xor_ps(ps_crc3, ps_t3); + + *xmm_crc0 = _mm_castps_si128(ps_res0); + *xmm_crc1 = _mm_castps_si128(ps_res1); + *xmm_crc2 = _mm_castps_si128(ps_res2); + *xmm_crc3 = _mm_castps_si128(ps_res3); +} + +static const unsigned ALIGNED_(32) pshufb_shf_table[60] = { + 0x84838281, 0x88878685, 0x8c8b8a89, 0x008f8e8d, /* shl 15 (16 - 1)/shr1 */ + 0x85848382, 0x89888786, 0x8d8c8b8a, 0x01008f8e, /* shl 14 (16 - 3)/shr2 */ + 0x86858483, 0x8a898887, 0x8e8d8c8b, 0x0201008f, /* shl 13 (16 - 4)/shr3 */ + 0x87868584, 0x8b8a8988, 0x8f8e8d8c, 0x03020100, /* shl 12 (16 - 4)/shr4 */ + 0x88878685, 0x8c8b8a89, 0x008f8e8d, 0x04030201, /* shl 11 (16 - 5)/shr5 */ + 0x89888786, 0x8d8c8b8a, 0x01008f8e, 0x05040302, /* shl 10 (16 - 6)/shr6 */ + 0x8a898887, 0x8e8d8c8b, 0x0201008f, 0x06050403, /* shl 9 (16 - 7)/shr7 */ + 0x8b8a8988, 0x8f8e8d8c, 0x03020100, 0x07060504, /* shl 8 (16 - 8)/shr8 */ + 0x8c8b8a89, 0x008f8e8d, 0x04030201, 0x08070605, /* shl 7 (16 - 9)/shr9 */ + 0x8d8c8b8a, 0x01008f8e, 0x05040302, 0x09080706, /* shl 6 (16 -10)/shr10*/ + 0x8e8d8c8b, 0x0201008f, 0x06050403, 0x0a090807, /* shl 5 (16 -11)/shr11*/ + 0x8f8e8d8c, 0x03020100, 0x07060504, 0x0b0a0908, /* shl 4 (16 -12)/shr12*/ + 0x008f8e8d, 0x04030201, 0x08070605, 0x0c0b0a09, /* shl 3 (16 -13)/shr13*/ + 0x01008f8e, 0x05040302, 0x09080706, 0x0d0c0b0a, /* shl 2 (16 -14)/shr14*/ + 0x0201008f, 0x06050403, 0x0a090807, 0x0e0d0c0b /* shl 1 (16 -15)/shr15*/ +}; + +static void partial_fold(const size_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, + __m128i *xmm_crc3, __m128i *xmm_crc_part) { + const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + const __m128i xmm_mask3 = _mm_set1_epi32((int32_t)0x80808080); + + __m128i xmm_shl, xmm_shr, xmm_tmp1, xmm_tmp2, xmm_tmp3; + __m128i xmm_a0_0, xmm_a0_1; + __m128 ps_crc3, psa0_0, psa0_1, ps_res; + + xmm_shl = _mm_load_si128((__m128i *)(pshufb_shf_table + (4 * (len - 1)))); + xmm_shr = xmm_shl; + xmm_shr = _mm_xor_si128(xmm_shr, xmm_mask3); + + xmm_a0_0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shl); + + *xmm_crc0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shr); + xmm_tmp1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shl); + *xmm_crc0 = _mm_or_si128(*xmm_crc0, xmm_tmp1); + + *xmm_crc1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shr); + xmm_tmp2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shl); + *xmm_crc1 = _mm_or_si128(*xmm_crc1, xmm_tmp2); + + *xmm_crc2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shr); + xmm_tmp3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shl); + *xmm_crc2 = _mm_or_si128(*xmm_crc2, xmm_tmp3); + + *xmm_crc3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shr); + *xmm_crc_part = _mm_shuffle_epi8(*xmm_crc_part, xmm_shl); + *xmm_crc3 = _mm_or_si128(*xmm_crc3, *xmm_crc_part); + + xmm_a0_1 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x10); + xmm_a0_0 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x01); + + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + psa0_0 = _mm_castsi128_ps(xmm_a0_0); + psa0_1 = _mm_castsi128_ps(xmm_a0_1); + + ps_res = _mm_xor_ps(ps_crc3, psa0_0); + ps_res = _mm_xor_ps(ps_res, psa0_1); + + *xmm_crc3 = _mm_castps_si128(ps_res); +} + +static inline void crc32_fold_load(__m128i *fold, __m128i *fold0, __m128i *fold1, __m128i *fold2, __m128i *fold3) { + *fold0 = _mm_load_si128(fold + 0); + *fold1 = _mm_load_si128(fold + 1); + *fold2 = _mm_load_si128(fold + 2); + *fold3 = _mm_load_si128(fold + 3); +} + +static inline void crc32_fold_save(__m128i *fold, const __m128i *fold0, const __m128i *fold1, + const __m128i *fold2, const __m128i *fold3) { + _mm_storeu_si128(fold + 0, *fold0); + _mm_storeu_si128(fold + 1, *fold1); + _mm_storeu_si128(fold + 2, *fold2); + _mm_storeu_si128(fold + 3, *fold3); +} + +Z_INTERNAL uint32_t CRC32_FOLD_RESET(crc32_fold *crc) { + __m128i xmm_crc0 = _mm_cvtsi32_si128(0x9db42487); + __m128i xmm_zero = _mm_setzero_si128(); + crc32_fold_save((__m128i *)crc->fold, &xmm_crc0, &xmm_zero, &xmm_zero, &xmm_zero); + return 0; +} + +#define ONCE(op) if (first) { first = 0; op; } +#define XOR_INITIAL128(where) ONCE(where = _mm_xor_si128(where, xmm_initial)) +#ifdef X86_VPCLMULQDQ +# define XOR_INITIAL512(where) ONCE(where = _mm512_xor_si512(where, zmm_initial)) +#endif + +#ifdef X86_VPCLMULQDQ +# include "crc32_fold_vpclmulqdq_tpl.h" +#endif +#include "crc32_fold_pclmulqdq_tpl.h" +#define COPY +#ifdef X86_VPCLMULQDQ +# include "crc32_fold_vpclmulqdq_tpl.h" +#endif +#include "crc32_fold_pclmulqdq_tpl.h" + +static const unsigned ALIGNED_(16) crc_k[] = { + 0xccaa009e, 0x00000000, /* rk1 */ + 0x751997d0, 0x00000001, /* rk2 */ + 0xccaa009e, 0x00000000, /* rk5 */ + 0x63cd6124, 0x00000001, /* rk6 */ + 0xf7011640, 0x00000001, /* rk7 */ + 0xdb710640, 0x00000001 /* rk8 */ +}; + +static const unsigned ALIGNED_(16) crc_mask[4] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000 +}; + +static const unsigned ALIGNED_(16) crc_mask2[4] = { + 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF +}; + +Z_INTERNAL uint32_t CRC32_FOLD_FINAL(crc32_fold *crc) { + const __m128i xmm_mask = _mm_load_si128((__m128i *)crc_mask); + const __m128i xmm_mask2 = _mm_load_si128((__m128i *)crc_mask2); + __m128i xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3; + __m128i x_tmp0, x_tmp1, x_tmp2, crc_fold; + + crc32_fold_load((__m128i *)crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + /* + * k1 + */ + crc_fold = _mm_load_si128((__m128i *)crc_k); + + x_tmp0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x10); + xmm_crc0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x01); + xmm_crc1 = _mm_xor_si128(xmm_crc1, x_tmp0); + xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_crc0); + + x_tmp1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x10); + xmm_crc1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x01); + xmm_crc2 = _mm_xor_si128(xmm_crc2, x_tmp1); + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_crc1); + + x_tmp2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x10); + xmm_crc2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x01); + xmm_crc3 = _mm_xor_si128(xmm_crc3, x_tmp2); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); + + /* + * k5 + */ + crc_fold = _mm_load_si128((__m128i *)(crc_k + 4)); + + xmm_crc0 = xmm_crc3; + xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0); + xmm_crc0 = _mm_srli_si128(xmm_crc0, 8); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0); + + xmm_crc0 = xmm_crc3; + xmm_crc3 = _mm_slli_si128(xmm_crc3, 4); + xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0); + xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask2); + + /* + * k7 + */ + xmm_crc1 = xmm_crc3; + xmm_crc2 = xmm_crc3; + crc_fold = _mm_load_si128((__m128i *)(crc_k + 8)); + + xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); + xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask); + + xmm_crc2 = xmm_crc3; + xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc1); + + crc->value = ~((uint32_t)_mm_extract_epi32(xmm_crc3, 2)); + + return crc->value; +} + +Z_INTERNAL uint32_t CRC32(uint32_t crc32, const uint8_t *buf, size_t len) { + /* For lens < 64, crc32_braid method is faster. The CRC32 instruction for + * these short lengths might also prove to be effective */ + if (len < 64) + return PREFIX(crc32_braid)(crc32, buf, len); + + crc32_fold ALIGNED_(16) crc_state; + CRC32_FOLD_RESET(&crc_state); + CRC32_FOLD(&crc_state, buf, len, crc32); + return CRC32_FOLD_FINAL(&crc_state); +} diff --git a/3rdparty/zlib-ng/arch/x86/crc32_vpclmulqdq.c b/3rdparty/zlib-ng/arch/x86/crc32_vpclmulqdq.c new file mode 100644 index 000000000000..ec641b43263b --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/crc32_vpclmulqdq.c @@ -0,0 +1,17 @@ +/* crc32_vpclmulqdq.c -- VPCMULQDQ-based CRC32 folding implementation. + * Copyright Wangyang Guo (wangyang.guo@intel.com) + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#if defined(X86_PCLMULQDQ_CRC) && defined(X86_VPCLMULQDQ_CRC) + +#define X86_VPCLMULQDQ +#define CRC32_FOLD_COPY crc32_fold_vpclmulqdq_copy +#define CRC32_FOLD crc32_fold_vpclmulqdq +#define CRC32_FOLD_RESET crc32_fold_vpclmulqdq_reset +#define CRC32_FOLD_FINAL crc32_fold_vpclmulqdq_final +#define CRC32 crc32_vpclmulqdq + +#include "crc32_pclmulqdq_tpl.h" + +#endif diff --git a/3rdparty/zlib-ng/arch/x86/insert_string_sse42.c b/3rdparty/zlib-ng/arch/x86/insert_string_sse42.c new file mode 100644 index 000000000000..ae092a7e477f --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/insert_string_sse42.c @@ -0,0 +1,24 @@ +/* insert_string_sse42.c -- insert_string integer hash variant using SSE4.2's CRC instructions + * + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + */ + +#ifdef X86_SSE42 +#include "../../zbuild.h" +#include +#include "../../deflate.h" + +#define HASH_CALC(s, h, val)\ + h = _mm_crc32_u32(h, val) + +#define HASH_CALC_VAR h +#define HASH_CALC_VAR_INIT uint32_t h = 0 + +#define UPDATE_HASH update_hash_sse42 +#define INSERT_STRING insert_string_sse42 +#define QUICK_INSERT_STRING quick_insert_string_sse42 + +#include "../../insert_string_tpl.h" +#endif diff --git a/3rdparty/zlib-ng/arch/x86/slide_hash_avx2.c b/3rdparty/zlib-ng/arch/x86/slide_hash_avx2.c new file mode 100644 index 000000000000..94fe10c7bf4a --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/slide_hash_avx2.c @@ -0,0 +1,39 @@ +/* + * AVX2 optimized hash slide, based on Intel's slide_sse implementation + * + * Copyright (C) 2017 Intel Corporation + * Authors: + * Arjan van de Ven + * Jim Kukunas + * Mika T. Lindqvist + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ +#include "../../zbuild.h" +#include "../../deflate.h" + +#include + +static inline void slide_hash_chain(Pos *table, uint32_t entries, const __m256i wsize) { + table += entries; + table -= 16; + + do { + __m256i value, result; + + value = _mm256_loadu_si256((__m256i *)table); + result = _mm256_subs_epu16(value, wsize); + _mm256_storeu_si256((__m256i *)table, result); + + table -= 16; + entries -= 16; + } while (entries > 0); +} + +Z_INTERNAL void slide_hash_avx2(deflate_state *s) { + uint16_t wsize = (uint16_t)s->w_size; + const __m256i ymm_wsize = _mm256_set1_epi16((short)wsize); + + slide_hash_chain(s->head, HASH_SIZE, ymm_wsize); + slide_hash_chain(s->prev, wsize, ymm_wsize); +} diff --git a/3rdparty/zlib-ng/arch/x86/slide_hash_sse2.c b/3rdparty/zlib-ng/arch/x86/slide_hash_sse2.c new file mode 100644 index 000000000000..5daac4a73981 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/slide_hash_sse2.c @@ -0,0 +1,62 @@ +/* + * SSE optimized hash slide + * + * Copyright (C) 2017 Intel Corporation + * Authors: + * Arjan van de Ven + * Jim Kukunas + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ +#include "../../zbuild.h" +#include "../../deflate.h" + +#include +#include + +static inline void slide_hash_chain(Pos *table0, Pos *table1, uint32_t entries0, + uint32_t entries1, const __m128i wsize) { + uint32_t entries; + Pos *table; + __m128i value0, value1, result0, result1; + + int on_chain = 0; + +next_chain: + table = (on_chain) ? table1 : table0; + entries = (on_chain) ? entries1 : entries0; + + table += entries; + table -= 16; + + /* ZALLOC allocates this pointer unless the user chose a custom allocator. + * Our alloc function is aligned to 64 byte boundaries */ + do { + value0 = _mm_load_si128((__m128i *)table); + value1 = _mm_load_si128((__m128i *)(table + 8)); + result0 = _mm_subs_epu16(value0, wsize); + result1 = _mm_subs_epu16(value1, wsize); + _mm_store_si128((__m128i *)table, result0); + _mm_store_si128((__m128i *)(table + 8), result1); + + table -= 16; + entries -= 16; + } while (entries > 0); + + ++on_chain; + if (on_chain > 1) { + return; + } else { + goto next_chain; + } +} + +Z_INTERNAL void slide_hash_sse2(deflate_state *s) { + uint16_t wsize = (uint16_t)s->w_size; + const __m128i xmm_wsize = _mm_set1_epi16((short)wsize); + + assert(((uintptr_t)s->head & 15) == 0); + assert(((uintptr_t)s->prev & 15) == 0); + + slide_hash_chain(s->head, s->prev, HASH_SIZE, wsize, xmm_wsize); +} diff --git a/3rdparty/zlib-ng/arch/x86/x86_features.c b/3rdparty/zlib-ng/arch/x86/x86_features.c new file mode 100644 index 000000000000..8d11564c24f9 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/x86_features.c @@ -0,0 +1,97 @@ +/* x86_features.c - x86 feature check + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * Author: + * Jim Kukunas + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "../../zbuild.h" +#include "x86_features.h" + +#ifdef _MSC_VER +# include +#else +// Newer versions of GCC and clang come with cpuid.h +# include +#endif + +#include + +static inline void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { +#ifdef _MSC_VER + unsigned int registers[4]; + __cpuid((int *)registers, info); + + *eax = registers[0]; + *ebx = registers[1]; + *ecx = registers[2]; + *edx = registers[3]; +#else + __cpuid(info, *eax, *ebx, *ecx, *edx); +#endif +} + +static inline void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { +#ifdef _MSC_VER + unsigned int registers[4]; + __cpuidex((int *)registers, info, subinfo); + + *eax = registers[0]; + *ebx = registers[1]; + *ecx = registers[2]; + *edx = registers[3]; +#else + __cpuid_count(info, subinfo, *eax, *ebx, *ecx, *edx); +#endif +} + +static inline uint64_t xgetbv(unsigned int xcr) { +#ifdef _MSC_VER + return _xgetbv(xcr); +#else + uint32_t eax, edx; + __asm__ ( ".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(xcr)); + return (uint64_t)(edx) << 32 | eax; +#endif +} + +void Z_INTERNAL x86_check_features(struct x86_cpu_features *features) { + unsigned eax, ebx, ecx, edx; + unsigned maxbasic; + + cpuid(0, &maxbasic, &ebx, &ecx, &edx); + cpuid(1 /*CPU_PROCINFO_AND_FEATUREBITS*/, &eax, &ebx, &ecx, &edx); + + features->has_sse2 = edx & 0x4000000; + features->has_ssse3 = ecx & 0x200; + features->has_sse42 = ecx & 0x100000; + features->has_pclmulqdq = ecx & 0x2; + + if (ecx & 0x08000000) { + uint64_t xfeature = xgetbv(0); + + features->has_os_save_ymm = ((xfeature & 0x06) == 0x06); + features->has_os_save_zmm = ((xfeature & 0xe6) == 0xe6); + } + + if (maxbasic >= 7) { + cpuidex(7, 0, &eax, &ebx, &ecx, &edx); + + // check BMI1 bit + // Reference: https://software.intel.com/sites/default/files/article/405250/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family.pdf + features->has_vpclmulqdq = ecx & 0x400; + + // check AVX2 bit if the OS supports saving YMM registers + if (features->has_os_save_ymm) { + features->has_avx2 = ebx & 0x20; + } + + // check AVX512 bits if the OS supports saving ZMM registers + if (features->has_os_save_zmm) { + features->has_avx512 = ebx & 0x00010000; + features->has_avx512vnni = ecx & 0x800; + } + } +} diff --git a/3rdparty/zlib-ng/arch/x86/x86_features.h b/3rdparty/zlib-ng/arch/x86/x86_features.h new file mode 100644 index 000000000000..4a36bde835d3 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/x86_features.h @@ -0,0 +1,24 @@ +/* x86_features.h -- check for CPU features +* Copyright (C) 2013 Intel Corporation Jim Kukunas +* For conditions of distribution and use, see copyright notice in zlib.h +*/ + +#ifndef X86_FEATURES_H_ +#define X86_FEATURES_H_ + +struct x86_cpu_features { + int has_avx2; + int has_avx512; + int has_avx512vnni; + int has_sse2; + int has_ssse3; + int has_sse42; + int has_pclmulqdq; + int has_vpclmulqdq; + int has_os_save_ymm; + int has_os_save_zmm; +}; + +void Z_INTERNAL x86_check_features(struct x86_cpu_features *features); + +#endif /* CPU_H_ */ diff --git a/3rdparty/zlib-ng/arch/x86/x86_intrins.h b/3rdparty/zlib-ng/arch/x86/x86_intrins.h new file mode 100644 index 000000000000..52e1085d66f9 --- /dev/null +++ b/3rdparty/zlib-ng/arch/x86/x86_intrins.h @@ -0,0 +1,87 @@ +#ifndef X86_INTRINS_H +#define X86_INTRINS_H + +/* Unfortunately GCC didn't support these things until version 10. + * Similarly, AppleClang didn't support them in Xcode 9.2 but did in 9.3. + */ +#ifdef __AVX2__ +#include + +#if (!defined(__clang__) && defined(__GNUC__) && __GNUC__ < 10) \ + || (defined(__apple_build_version__) && __apple_build_version__ < 9020039) +static inline __m256i _mm256_zextsi128_si256(__m128i a) { + __m128i r; + __asm__ volatile ("vmovdqa %1,%0" : "=x" (r) : "x" (a)); + return _mm256_castsi128_si256(r); +} + +#ifdef __AVX512F__ +static inline __m512i _mm512_zextsi128_si512(__m128i a) { + __m128i r; + __asm__ volatile ("vmovdqa %1,%0" : "=x" (r) : "x" (a)); + return _mm512_castsi128_si512(r); +} +#endif // __AVX512F__ +#endif // gcc/AppleClang version test + +#endif // __AVX2__ + +/* GCC <9 is missing some AVX512 intrinsics. + */ +#ifdef __AVX512F__ +#if (!defined(__clang__) && defined(__GNUC__) && __GNUC__ < 9) +#include + +#define PACK(c0, c1, c2, c3) (((int)(unsigned char)(c0) << 24) | ((int)(unsigned char)(c1) << 16) | \ + ((int)(unsigned char)(c2) << 8) | ((int)(unsigned char)(c3))) + +static inline __m512i _mm512_set_epi8(char __q63, char __q62, char __q61, char __q60, + char __q59, char __q58, char __q57, char __q56, + char __q55, char __q54, char __q53, char __q52, + char __q51, char __q50, char __q49, char __q48, + char __q47, char __q46, char __q45, char __q44, + char __q43, char __q42, char __q41, char __q40, + char __q39, char __q38, char __q37, char __q36, + char __q35, char __q34, char __q33, char __q32, + char __q31, char __q30, char __q29, char __q28, + char __q27, char __q26, char __q25, char __q24, + char __q23, char __q22, char __q21, char __q20, + char __q19, char __q18, char __q17, char __q16, + char __q15, char __q14, char __q13, char __q12, + char __q11, char __q10, char __q09, char __q08, + char __q07, char __q06, char __q05, char __q04, + char __q03, char __q02, char __q01, char __q00) { + return _mm512_set_epi32(PACK(__q63, __q62, __q61, __q60), PACK(__q59, __q58, __q57, __q56), + PACK(__q55, __q54, __q53, __q52), PACK(__q51, __q50, __q49, __q48), + PACK(__q47, __q46, __q45, __q44), PACK(__q43, __q42, __q41, __q40), + PACK(__q39, __q38, __q37, __q36), PACK(__q35, __q34, __q33, __q32), + PACK(__q31, __q30, __q29, __q28), PACK(__q27, __q26, __q25, __q24), + PACK(__q23, __q22, __q21, __q20), PACK(__q19, __q18, __q17, __q16), + PACK(__q15, __q14, __q13, __q12), PACK(__q11, __q10, __q09, __q08), + PACK(__q07, __q06, __q05, __q04), PACK(__q03, __q02, __q01, __q00)); +} + +#undef PACK + +#endif // gcc version test +#endif // __AVX512F__ + +/* Missing zero-extension AVX and AVX512 intrinsics. + * Fixed in Microsoft Visual Studio 2017 version 15.7 + * https://developercommunity.visualstudio.com/t/missing-zero-extension-avx-and-avx512-intrinsics/175737 + */ +#if defined(_MSC_VER) && _MSC_VER < 1914 +#ifdef __AVX2__ +static inline __m256i _mm256_zextsi128_si256(__m128i a) { + return _mm256_inserti128_si256(_mm256_setzero_si256(), a, 0); +} +#endif // __AVX2__ + +#ifdef __AVX512F__ +static inline __m512i _mm512_zextsi128_si512(__m128i a) { + return _mm512_inserti32x4(_mm512_setzero_si512(), a, 0); +} +#endif // __AVX512F__ +#endif // defined(_MSC_VER) && _MSC_VER < 1914 + +#endif // include guard X86_INTRINS_H diff --git a/3rdparty/zlib-ng/chunkset.c b/3rdparty/zlib-ng/chunkset.c new file mode 100644 index 000000000000..7b2bb7ba3676 --- /dev/null +++ b/3rdparty/zlib-ng/chunkset.c @@ -0,0 +1,42 @@ +/* chunkset.c -- inline functions to copy small data chunks. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" + +typedef uint64_t chunk_t; + +#define CHUNK_SIZE 8 + +#define HAVE_CHUNKMEMSET_4 +#define HAVE_CHUNKMEMSET_8 + +static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { + uint8_t *dest = (uint8_t *)chunk; + memcpy(dest, from, sizeof(uint32_t)); + memcpy(dest+4, from, sizeof(uint32_t)); +} + +static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { + memcpy(chunk, from, sizeof(uint64_t)); +} + +static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { + memcpy(chunk, (uint8_t *)s, sizeof(uint64_t)); +} + +static inline void storechunk(uint8_t *out, chunk_t *chunk) { + memcpy(out, chunk, sizeof(uint64_t)); +} + +#define CHUNKSIZE chunksize_c +#define CHUNKCOPY chunkcopy_c +#define CHUNKUNROLL chunkunroll_c +#define CHUNKMEMSET chunkmemset_c +#define CHUNKMEMSET_SAFE chunkmemset_safe_c + +#include "chunkset_tpl.h" + +#define INFLATE_FAST inflate_fast_c + +#include "inffast_tpl.h" diff --git a/3rdparty/zlib-ng/chunkset_tpl.h b/3rdparty/zlib-ng/chunkset_tpl.h new file mode 100644 index 000000000000..f909a12557f0 --- /dev/null +++ b/3rdparty/zlib-ng/chunkset_tpl.h @@ -0,0 +1,200 @@ +/* chunkset_tpl.h -- inline functions to copy small data chunks. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include + +#if CHUNK_SIZE == 32 && defined(X86_SSSE3) && defined(X86_SSE2) +extern uint8_t* chunkmemset_ssse3(uint8_t *out, unsigned dist, unsigned len); +#endif + +/* Returns the chunk size */ +Z_INTERNAL uint32_t CHUNKSIZE(void) { + return sizeof(chunk_t); +} + +/* Behave like memcpy, but assume that it's OK to overwrite at least + chunk_t bytes of output even if the length is shorter than this, + that the length is non-zero, and that `from` lags `out` by at least + sizeof chunk_t bytes (or that they don't overlap at all or simply that + the distance is less than the length of the copy). + + Aside from better memory bus utilisation, this means that short copies + (chunk_t bytes or fewer) will fall straight through the loop + without iteration, which will hopefully make the branch prediction more + reliable. */ +#ifndef HAVE_CHUNKCOPY +Z_INTERNAL uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { + Assert(len > 0, "chunkcopy should never have a length 0"); + chunk_t chunk; + int32_t align = ((len - 1) % sizeof(chunk_t)) + 1; + loadchunk(from, &chunk); + storechunk(out, &chunk); + out += align; + from += align; + len -= align; + while (len > 0) { + loadchunk(from, &chunk); + storechunk(out, &chunk); + out += sizeof(chunk_t); + from += sizeof(chunk_t); + len -= sizeof(chunk_t); + } + return out; +} +#endif + +/* Perform short copies until distance can be rewritten as being at least + sizeof chunk_t. + + This assumes that it's OK to overwrite at least the first + 2*sizeof(chunk_t) bytes of output even if the copy is shorter than this. + This assumption holds because inflate_fast() starts every iteration with at + least 258 bytes of output space available (258 being the maximum length + output from a single token; see inflate_fast()'s assumptions below). */ +#ifndef HAVE_CHUNKUNROLL +Z_INTERNAL uint8_t* CHUNKUNROLL(uint8_t *out, unsigned *dist, unsigned *len) { + unsigned char const *from = out - *dist; + chunk_t chunk; + while (*dist < *len && *dist < sizeof(chunk_t)) { + loadchunk(from, &chunk); + storechunk(out, &chunk); + out += *dist; + *len -= *dist; + *dist += *dist; + } + return out; +} +#endif + +#ifndef HAVE_CHUNK_MAG +/* Loads a magazine to feed into memory of the pattern */ +static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t dist) { + /* This code takes string of length dist from "from" and repeats + * it for as many times as can fit in a chunk_t (vector register) */ + uint32_t cpy_dist; + uint32_t bytes_remaining = sizeof(chunk_t); + chunk_t chunk_load; + uint8_t *cur_chunk = (uint8_t *)&chunk_load; + while (bytes_remaining) { + cpy_dist = MIN(dist, bytes_remaining); + memcpy(cur_chunk, buf, cpy_dist); + bytes_remaining -= cpy_dist; + cur_chunk += cpy_dist; + /* This allows us to bypass an expensive integer division since we're effectively + * counting in this loop, anyway */ + *chunk_rem = cpy_dist; + } + + return chunk_load; +} +#endif + +/* Copy DIST bytes from OUT - DIST into OUT + DIST * k, for 0 <= k < LEN/DIST. + Return OUT + LEN. */ +Z_INTERNAL uint8_t* CHUNKMEMSET(uint8_t *out, unsigned dist, unsigned len) { + /* Debug performance related issues when len < sizeof(uint64_t): + Assert(len >= sizeof(uint64_t), "chunkmemset should be called on larger chunks"); */ + Assert(dist > 0, "chunkmemset cannot have a distance 0"); + /* Only AVX2 */ +#if CHUNK_SIZE == 32 && defined(X86_SSSE3) && defined(X86_SSE2) + if (len <= 16) { + return chunkmemset_ssse3(out, dist, len); + } +#endif + + uint8_t *from = out - dist; + + if (dist == 1) { + memset(out, *from, len); + return out + len; + } else if (dist > sizeof(chunk_t)) { + return CHUNKCOPY(out, out - dist, len); + } + + chunk_t chunk_load; + uint32_t chunk_mod = 0; + + /* TODO: possibly build up a permutation table for this if not an even modulus */ +#ifdef HAVE_CHUNKMEMSET_2 + if (dist == 2) { + chunkmemset_2(from, &chunk_load); + } else +#endif +#ifdef HAVE_CHUNKMEMSET_4 + if (dist == 4) { + chunkmemset_4(from, &chunk_load); + } else +#endif +#ifdef HAVE_CHUNKMEMSET_8 + if (dist == 8) { + chunkmemset_8(from, &chunk_load); + } else if (dist == sizeof(chunk_t)) { + loadchunk(from, &chunk_load); + } else +#endif + { + chunk_load = GET_CHUNK_MAG(from, &chunk_mod, dist); + } + + /* If we're lucky enough and dist happens to be an even modulus of our vector length, + * we can do two stores per loop iteration, which for most ISAs, especially x86, is beneficial */ + if (chunk_mod == 0) { + while (len >= (2 * sizeof(chunk_t))) { + storechunk(out, &chunk_load); + storechunk(out + sizeof(chunk_t), &chunk_load); + out += 2 * sizeof(chunk_t); + len -= 2 * sizeof(chunk_t); + } + } + + /* If we don't have a "dist" length that divides evenly into a vector + * register, we can write the whole vector register but we need only + * advance by the amount of the whole string that fits in our chunk_t. + * If we do divide evenly into the vector length, adv_amount = chunk_t size*/ + uint32_t adv_amount = sizeof(chunk_t) - chunk_mod; + while (len >= sizeof(chunk_t)) { + storechunk(out, &chunk_load); + len -= adv_amount; + out += adv_amount; + } + + if (len) { + memcpy(out, &chunk_load, len); + out += len; + } + + return out; +} + +Z_INTERNAL uint8_t* CHUNKMEMSET_SAFE(uint8_t *out, unsigned dist, unsigned len, unsigned left) { +#if !defined(UNALIGNED64_OK) +# if !defined(UNALIGNED_OK) + static const uint32_t align_mask = 7; +# else + static const uint32_t align_mask = 3; +# endif +#endif + + len = MIN(len, left); + uint8_t *from = out - dist; +#if !defined(UNALIGNED64_OK) + while (((uintptr_t)out & align_mask) && (len > 0)) { + *out++ = *from++; + --len; + --left; + } +#endif + if (left < (unsigned)(3 * sizeof(chunk_t))) { + while (len > 0) { + *out++ = *from++; + --len; + } + return out; + } + if (len) + return CHUNKMEMSET(out, dist, len); + + return out; +} diff --git a/3rdparty/zlib-ng/cmake/detect-intrinsics.cmake b/3rdparty/zlib-ng/cmake/detect-intrinsics.cmake new file mode 100644 index 000000000000..74ac3910b8f4 --- /dev/null +++ b/3rdparty/zlib-ng/cmake/detect-intrinsics.cmake @@ -0,0 +1,543 @@ +# detect-intrinsics.cmake -- Detect compiler intrinsics support +# Licensed under the Zlib license, see LICENSE.md for details + +macro(check_acle_compiler_flag) + if(MSVC) + # Both ARM and ARM64-targeting msvc support intrinsics, but + # ARM msvc is missing some intrinsics introduced with ARMv8, e.g. crc32 + if(MSVC_C_ARCHITECTURE_ID STREQUAL "ARM64") + set(HAVE_ACLE_FLAG TRUE) + endif() + else() + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(ACLEFLAG "-march=armv8-a+crc" CACHE INTERNAL "Compiler option to enable ACLE support") + endif() + endif() + # Check whether compiler supports ACLE flag + set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "int main() { return 0; }" + HAVE_ACLE_FLAG FAIL_REGEX "not supported") + if(NOT NATIVEFLAG AND NOT HAVE_ACLE_FLAG) + set(ACLEFLAG "-march=armv8-a+crc+simd" CACHE INTERNAL "Compiler option to enable ACLE support" FORCE) + # Check whether compiler supports ACLE flag + set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG}") + check_c_source_compiles( + "int main() { return 0; }" + HAVE_ACLE_FLAG2 FAIL_REGEX "not supported") + set(HAVE_ACLE_FLAG ${HAVE_ACLE_FLAG2} CACHE INTERNAL "Have compiler option to enable ACLE intrinsics" FORCE) + unset(HAVE_ACLE_FLAG2 CACHE) # Don't cache this internal variable + endif() + set(CMAKE_REQUIRED_FLAGS) + endif() +endmacro() + +macro(check_armv6_compiler_flag) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + check_c_compiler_flag("-march=armv6" HAVE_MARCH_ARMV6) + if(HAVE_MARCH_ARMV6) + set(ARMV6FLAG "-march=armv6" CACHE INTERNAL "Compiler option to enable ARMv6 support") + endif() + endif() + endif() + # Check whether compiler supports ARMv6 inline asm + set(CMAKE_REQUIRED_FLAGS "${ARMV6FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "unsigned int f(unsigned int a, unsigned int b) { + unsigned int c; + __asm__ __volatile__ ( \"uqsub16 %0, %1, %2\" : \"=r\" (c) : \"r\" (a), \"r\" (b) ); + return (int)c; + } + int main(void) { return f(1,2); }" + HAVE_ARMV6_INLINE_ASM + ) + # Check whether compiler supports ARMv6 intrinsics + check_c_source_compiles( + "#if defined(_MSC_VER) + #include + #else + #include + #endif + unsigned int f(unsigned int a, unsigned int b) { + #if defined(_MSC_VER) + return _arm_uqsub16(a, b); + #else + return __uqsub16(a, b); + #endif + } + int main(void) { return 0; }" + HAVE_ARMV6_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_avx512_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "Intel") + if(CMAKE_HOST_UNIX OR APPLE) + set(AVX512FLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl") + else() + set(AVX512FLAG "/arch:AVX512") + endif() + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + # For CPUs that can benefit from AVX512, it seems GCC generates suboptimal + # instruction scheduling unless you specify a reasonable -mtune= target + set(AVX512FLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl") + if(NOT MSVC) + check_c_compiler_flag("-mtune=cascadelake" HAVE_CASCADE_LAKE) + if(HAVE_CASCADE_LAKE) + set(AVX512FLAG "${AVX512FLAG} -mtune=cascadelake") + else() + set(AVX512FLAG "${AVX512FLAG} -mtune=skylake-avx512") + endif() + unset(HAVE_CASCADE_LAKE) + endif() + endif() + elseif(MSVC) + set(AVX512FLAG "/arch:AVX512") + endif() + # Check whether compiler supports AVX512 intrinsics + set(CMAKE_REQUIRED_FLAGS "${AVX512FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + __m512i f(__m512i y) { + __m512i x = _mm512_set1_epi8(2); + return _mm512_sub_epi8(x, y); + } + int main(void) { return 0; }" + HAVE_AVX512_INTRIN + ) + + # Evidently both GCC and clang were late to implementing these + check_c_source_compiles( + "#include + __mmask16 f(__mmask16 x) { return _knot_mask16(x); } + int main(void) { return 0; }" + HAVE_MASK_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_avx512vnni_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "Intel") + if(CMAKE_HOST_UNIX OR APPLE) + set(AVX512VNNIFLAG "-mavx512f -mavx512bw -mavx512dq -mavx512vl -mavx512vnni") + else() + set(AVX512VNNIFLAG "/arch:AVX512") + endif() + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(AVX512VNNIFLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl -mavx512vnni") + if(NOT MSVC) + check_c_compiler_flag("-mtune=cascadelake" HAVE_CASCADE_LAKE) + if(HAVE_CASCADE_LAKE) + set(AVX512VNNIFLAG "${AVX512VNNIFLAG} -mtune=cascadelake") + else() + set(AVX512VNNIFLAG "${AVX512VNNIFLAG} -mtune=skylake-avx512") + endif() + unset(HAVE_CASCADE_LAKE) + endif() + endif() + elseif(MSVC) + set(AVX512VNNIFLAG "/arch:AVX512") + endif() + + # Check whether compiler supports AVX512vnni intrinsics + set(CMAKE_REQUIRED_FLAGS "${AVX512VNNIFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + __m512i f(__m512i x, __m512i y) { + __m512i z = _mm512_setzero_epi32(); + return _mm512_dpbusd_epi32(z, x, y); + } + int main(void) { return 0; }" + HAVE_AVX512VNNI_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_avx2_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "Intel") + if(CMAKE_HOST_UNIX OR APPLE) + set(AVX2FLAG "-mavx2") + else() + set(AVX2FLAG "/arch:AVX2") + endif() + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(AVX2FLAG "-mavx2") + endif() + elseif(MSVC) + set(AVX2FLAG "/arch:AVX2") + endif() + # Check whether compiler supports AVX2 intrinics + set(CMAKE_REQUIRED_FLAGS "${AVX2FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + __m256i f(__m256i x) { + const __m256i y = _mm256_set1_epi16(1); + return _mm256_subs_epu16(x, y); + } + int main(void) { return 0; }" + HAVE_AVX2_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_neon_compiler_flag) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + if("${ARCH}" MATCHES "aarch64") + set(NEONFLAG "-march=armv8-a+simd") + else() + set(NEONFLAG "-mfpu=neon") + endif() + endif() + endif() + # Check whether compiler supports NEON flag + set(CMAKE_REQUIRED_FLAGS "${NEONFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#if defined(_M_ARM64) || defined(_M_ARM64EC) + # include + #else + # include + #endif + int main() { return 0; }" + NEON_AVAILABLE FAIL_REGEX "not supported") + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_neon_ld4_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + if("${ARCH}" MATCHES "aarch64") + set(NEONFLAG "-march=armv8-a+simd") + else() + set(NEONFLAG "-mfpu=neon") + endif() + endif() + endif() + # Check whether compiler supports loading 4 neon vecs into a register range + set(CMAKE_REQUIRED_FLAGS "${NEONFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#if defined(_MSC_VER) && (defined(_M_ARM64) || defined(_M_ARM64EC)) + # include + #else + # include + #endif + int32x4x4_t f(int var[16]) { return vld1q_s32_x4(var); } + int main(void) { return 0; }" + NEON_HAS_LD4) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_pclmulqdq_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(PCLMULFLAG "-mpclmul") + endif() + endif() + # Check whether compiler supports PCLMULQDQ intrinsics + if(NOT (APPLE AND "${ARCH}" MATCHES "i386")) + # The pclmul code currently crashes on Mac in 32bit mode. Avoid for now. + set(CMAKE_REQUIRED_FLAGS "${PCLMULFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + #include + __m128i f(__m128i a, __m128i b) { return _mm_clmulepi64_si128(a, b, 0x10); } + int main(void) { return 0; }" + HAVE_PCLMULQDQ_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) + else() + set(HAVE_PCLMULQDQ_INTRIN OFF) + endif() +endmacro() + +macro(check_vpclmulqdq_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(VPCLMULFLAG "-mvpclmulqdq -mavx512f") + endif() + endif() + # Check whether compiler supports VPCLMULQDQ intrinsics + if(NOT (APPLE AND "${ARCH}" MATCHES "i386")) + set(CMAKE_REQUIRED_FLAGS "${VPCLMULFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + #include + __m512i f(__m512i a) { + __m512i b = _mm512_setzero_si512(); + return _mm512_clmulepi64_epi128(a, b, 0x10); + } + int main(void) { return 0; }" + HAVE_VPCLMULQDQ_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) + else() + set(HAVE_VPCLMULQDQ_INTRIN OFF) + endif() +endmacro() + +macro(check_ppc_intrinsics) + # Check if compiler supports AltiVec + set(CMAKE_REQUIRED_FLAGS "-maltivec ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + int main(void) + { + vector int a = vec_splats(0); + vector int b = vec_splats(0); + a = vec_add(a, b); + return 0; + }" + HAVE_ALTIVEC + ) + set(CMAKE_REQUIRED_FLAGS) + + if(HAVE_ALTIVEC) + set(PPCFLAGS "-maltivec") + endif() + + set(CMAKE_REQUIRED_FLAGS "-maltivec -mno-vsx ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + int main(void) + { + vector int a = vec_splats(0); + vector int b = vec_splats(0); + a = vec_add(a, b); + return 0; + }" + HAVE_NOVSX + ) + set(CMAKE_REQUIRED_FLAGS) + + if(HAVE_NOVSX) + set(PPCFLAGS "${PPCFLAGS} -mno-vsx") + endif() + + # Check if we have what we need for AltiVec optimizations + set(CMAKE_REQUIRED_FLAGS "${PPCFLAGS} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + #ifdef __FreeBSD__ + #include + #endif + int main() { + #ifdef __FreeBSD__ + unsigned long hwcap; + elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)); + return (hwcap & PPC_FEATURE_HAS_ALTIVEC); + #else + return (getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC); + #endif + }" + HAVE_VMX + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_power8_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(POWER8FLAG "-mcpu=power8") + endif() + endif() + # Check if we have what we need for POWER8 optimizations + set(CMAKE_REQUIRED_FLAGS "${POWER8FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + #ifdef __FreeBSD__ + #include + #endif + int main() { + #ifdef __FreeBSD__ + unsigned long hwcap; + elf_aux_info(AT_HWCAP2, &hwcap, sizeof(hwcap)); + return (hwcap & PPC_FEATURE2_ARCH_2_07); + #else + return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07); + #endif + }" + HAVE_POWER8_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_rvv_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(RISCVFLAG "-march=rv64gcv") + endif() + endif() + # Check whether compiler supports RVV + set(CMAKE_REQUIRED_FLAGS "${RISCVFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + int main() { + return 0; + }" + HAVE_RVV_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_s390_intrinsics) + check_c_source_compiles( + "#include + #ifndef HWCAP_S390_VXRS + #define HWCAP_S390_VXRS HWCAP_S390_VX + #endif + int main() { + return (getauxval(AT_HWCAP) & HWCAP_S390_VXRS); + }" + HAVE_S390_INTRIN + ) +endmacro() + +macro(check_power9_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(POWER9FLAG "-mcpu=power9") + endif() + endif() + # Check if we have what we need for POWER9 optimizations + set(CMAKE_REQUIRED_FLAGS "${POWER9FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + #ifdef __FreeBSD__ + #include + #endif + int main() { + #ifdef __FreeBSD__ + unsigned long hwcap; + elf_aux_info(AT_HWCAP2, &hwcap, sizeof(hwcap)); + return (hwcap & PPC_FEATURE2_ARCH_3_00); + #else + return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00); + #endif + }" + HAVE_POWER9_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_sse2_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "Intel") + if(CMAKE_HOST_UNIX OR APPLE) + set(SSE2FLAG "-msse2") + else() + set(SSE2FLAG "/arch:SSE2") + endif() + elseif(MSVC) + if(NOT "${ARCH}" MATCHES "x86_64") + set(SSE2FLAG "/arch:SSE2") + endif() + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(SSE2FLAG "-msse2") + endif() + endif() + # Check whether compiler supports SSE2 intrinsics + set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + __m128i f(__m128i x, __m128i y) { return _mm_sad_epu8(x, y); } + int main(void) { return 0; }" + HAVE_SSE2_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_ssse3_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "Intel") + if(CMAKE_HOST_UNIX OR APPLE) + set(SSSE3FLAG "-mssse3") + else() + set(SSSE3FLAG "/arch:SSSE3") + endif() + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(SSSE3FLAG "-mssse3") + endif() + endif() + # Check whether compiler supports SSSE3 intrinsics + set(CMAKE_REQUIRED_FLAGS "${SSSE3FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + __m128i f(__m128i u) { + __m128i v = _mm_set1_epi32(1); + return _mm_hadd_epi32(u, v); + } + int main(void) { return 0; }" + HAVE_SSSE3_INTRIN + ) +endmacro() + +macro(check_sse42_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "Intel") + if(CMAKE_HOST_UNIX OR APPLE) + set(SSE42FLAG "-msse4.2") + else() + set(SSE42FLAG "/arch:SSE4.2") + endif() + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(SSE42FLAG "-msse4.2") + endif() + endif() + # Check whether compiler supports SSE4.2 intrinsics + set(CMAKE_REQUIRED_FLAGS "${SSE42FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + unsigned int f(unsigned int a, unsigned int b) { return _mm_crc32_u32(a, b); } + int main(void) { return 0; }" + HAVE_SSE42_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_vgfma_intrinsics) + if(NOT NATIVEFLAG) + set(VGFMAFLAG "-march=z13") + if(CMAKE_C_COMPILER_ID MATCHES "GNU") + set(VGFMAFLAG "${VGFMAFLAG} -mzarch") + endif() + if(CMAKE_C_COMPILER_ID MATCHES "Clang") + set(VGFMAFLAG "${VGFMAFLAG} -fzvector") + endif() + endif() + # Check whether compiler supports "VECTOR GALOIS FIELD MULTIPLY SUM AND ACCUMULATE" intrinsic + set(CMAKE_REQUIRED_FLAGS "${VGFMAFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#include + int main(void) { + unsigned long long a __attribute__((vector_size(16))) = { 0 }; + unsigned long long b __attribute__((vector_size(16))) = { 0 }; + unsigned char c __attribute__((vector_size(16))) = { 0 }; + c = vec_gfmsum_accum_128(a, b, c); + return c[0]; + }" + HAVE_VGFMA_INTRIN FAIL_REGEX "not supported") + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_xsave_intrinsics) + if(NOT NATIVEFLAG AND NOT MSVC) + set(XSAVEFLAG "-mxsave") + endif() + set(CMAKE_REQUIRED_FLAGS "${XSAVEFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") + check_c_source_compiles( + "#ifdef _MSC_VER + # include + #else + # include + #endif + unsigned int f(unsigned int a) { return (int) _xgetbv(a); } + int main(void) { return 0; }" + HAVE_XSAVE_INTRIN FAIL_REGEX "not supported") + set(CMAKE_REQUIRED_FLAGS) +endmacro() diff --git a/3rdparty/zlib-ng/cmake/fallback-macros.cmake b/3rdparty/zlib-ng/cmake/fallback-macros.cmake new file mode 100644 index 000000000000..8bc6cf25be92 --- /dev/null +++ b/3rdparty/zlib-ng/cmake/fallback-macros.cmake @@ -0,0 +1,19 @@ +# fallback-macros.cmake -- CMake fallback macros +# Copyright (C) 2022 Nathan Moinvaziri +# Licensed under the Zlib license, see LICENSE.md for details + +# CMake less than version 3.5.2 +if(NOT COMMAND add_compile_options) + macro(add_compile_options options) + string(APPEND CMAKE_C_FLAGS ${options}) + string(APPEND CMAKE_CXX_FLAGS ${options}) + endmacro() +endif() + +# CMake less than version 3.14 +if(NOT COMMAND add_link_options) + macro(add_link_options options) + string(APPEND CMAKE_EXE_LINKER_FLAGS ${options}) + string(APPEND CMAKE_SHARED_LINKER_FLAGS ${options}) + endmacro() +endif() diff --git a/3rdparty/zlib-ng/compare256.c b/3rdparty/zlib-ng/compare256.c new file mode 100644 index 000000000000..82551cdd579e --- /dev/null +++ b/3rdparty/zlib-ng/compare256.c @@ -0,0 +1,180 @@ +/* compare256.c -- 256 byte memory comparison with match length return + * Copyright (C) 2020 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "zutil_p.h" +#include "fallback_builtins.h" + +/* ALIGNED, byte comparison */ +static inline uint32_t compare256_c_static(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + + do { + if (*src0 != *src1) + return len; + src0 += 1, src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src0 += 1, src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src0 += 1, src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src0 += 1, src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src0 += 1, src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src0 += 1, src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src0 += 1, src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src0 += 1, src1 += 1, len += 1; + } while (len < 256); + + return 256; +} + +Z_INTERNAL uint32_t compare256_c(const uint8_t *src0, const uint8_t *src1) { + return compare256_c_static(src0, src1); +} + +#define LONGEST_MATCH longest_match_c +#define COMPARE256 compare256_c_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_c +#define COMPARE256 compare256_c_static + +#include "match_tpl.h" + +#if defined(UNALIGNED_OK) && BYTE_ORDER == LITTLE_ENDIAN +/* 16-bit unaligned integer comparison */ +static inline uint32_t compare256_unaligned_16_static(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + + do { + if (zng_memcmp_2(src0, src1) != 0) + return len + (*src0 == *src1); + src0 += 2, src1 += 2, len += 2; + + if (zng_memcmp_2(src0, src1) != 0) + return len + (*src0 == *src1); + src0 += 2, src1 += 2, len += 2; + + if (zng_memcmp_2(src0, src1) != 0) + return len + (*src0 == *src1); + src0 += 2, src1 += 2, len += 2; + + if (zng_memcmp_2(src0, src1) != 0) + return len + (*src0 == *src1); + src0 += 2, src1 += 2, len += 2; + } while (len < 256); + + return 256; +} + +Z_INTERNAL uint32_t compare256_unaligned_16(const uint8_t *src0, const uint8_t *src1) { + return compare256_unaligned_16_static(src0, src1); +} + +#define LONGEST_MATCH longest_match_unaligned_16 +#define COMPARE256 compare256_unaligned_16_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_unaligned_16 +#define COMPARE256 compare256_unaligned_16_static + +#include "match_tpl.h" + +#ifdef HAVE_BUILTIN_CTZ +/* 32-bit unaligned integer comparison */ +static inline uint32_t compare256_unaligned_32_static(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + + do { + uint32_t sv, mv, diff; + + memcpy(&sv, src0, sizeof(sv)); + memcpy(&mv, src1, sizeof(mv)); + + diff = sv ^ mv; + if (diff) { + uint32_t match_byte = __builtin_ctz(diff) / 8; + return len + match_byte; + } + + src0 += 4, src1 += 4, len += 4; + } while (len < 256); + + return 256; +} + +Z_INTERNAL uint32_t compare256_unaligned_32(const uint8_t *src0, const uint8_t *src1) { + return compare256_unaligned_32_static(src0, src1); +} + +#define LONGEST_MATCH longest_match_unaligned_32 +#define COMPARE256 compare256_unaligned_32_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_unaligned_32 +#define COMPARE256 compare256_unaligned_32_static + +#include "match_tpl.h" + +#endif + +#if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) +/* UNALIGNED64_OK, 64-bit integer comparison */ +static inline uint32_t compare256_unaligned_64_static(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + + do { + uint64_t sv, mv, diff; + + memcpy(&sv, src0, sizeof(sv)); + memcpy(&mv, src1, sizeof(mv)); + + diff = sv ^ mv; + if (diff) { + uint64_t match_byte = __builtin_ctzll(diff) / 8; + return len + (uint32_t)match_byte; + } + + src0 += 8, src1 += 8, len += 8; + } while (len < 256); + + return 256; +} + +Z_INTERNAL uint32_t compare256_unaligned_64(const uint8_t *src0, const uint8_t *src1) { + return compare256_unaligned_64_static(src0, src1); +} + +#define LONGEST_MATCH longest_match_unaligned_64 +#define COMPARE256 compare256_unaligned_64_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_unaligned_64 +#define COMPARE256 compare256_unaligned_64_static + +#include "match_tpl.h" + +#endif + +#endif diff --git a/3rdparty/zlib-ng/compare256_rle.h b/3rdparty/zlib-ng/compare256_rle.h new file mode 100644 index 000000000000..0f3998d4a3f3 --- /dev/null +++ b/3rdparty/zlib-ng/compare256_rle.h @@ -0,0 +1,134 @@ +/* compare256_rle.h -- 256 byte run-length encoding comparison + * Copyright (C) 2022 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "fallback_builtins.h" + +typedef uint32_t (*compare256_rle_func)(const uint8_t* src0, const uint8_t* src1); + +/* ALIGNED, byte comparison */ +static inline uint32_t compare256_rle_c(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + + do { + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + } while (len < 256); + + return 256; +} + +#ifdef UNALIGNED_OK +/* 16-bit unaligned integer comparison */ +static inline uint32_t compare256_rle_unaligned_16(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + uint16_t src0_cmp, src1_cmp; + + memcpy(&src0_cmp, src0, sizeof(src0_cmp)); + + do { + memcpy(&src1_cmp, src1, sizeof(src1_cmp)); + if (src0_cmp != src1_cmp) + return len + (*src0 == *src1); + src1 += 2, len += 2; + memcpy(&src1_cmp, src1, sizeof(src1_cmp)); + if (src0_cmp != src1_cmp) + return len + (*src0 == *src1); + src1 += 2, len += 2; + memcpy(&src1_cmp, src1, sizeof(src1_cmp)); + if (src0_cmp != src1_cmp) + return len + (*src0 == *src1); + src1 += 2, len += 2; + memcpy(&src1_cmp, src1, sizeof(src1_cmp)); + if (src0_cmp != src1_cmp) + return len + (*src0 == *src1); + src1 += 2, len += 2; + } while (len < 256); + + return 256; +} + +#ifdef HAVE_BUILTIN_CTZ +/* 32-bit unaligned integer comparison */ +static inline uint32_t compare256_rle_unaligned_32(const uint8_t *src0, const uint8_t *src1) { + uint32_t sv, len = 0; + uint16_t src0_cmp; + + memcpy(&src0_cmp, src0, sizeof(src0_cmp)); + sv = ((uint32_t)src0_cmp << 16) | src0_cmp; + + do { + uint32_t mv, diff; + + memcpy(&mv, src1, sizeof(mv)); + + diff = sv ^ mv; + if (diff) { + uint32_t match_byte = __builtin_ctz(diff) / 8; + return len + match_byte; + } + + src1 += 4, len += 4; + } while (len < 256); + + return 256; +} + +#endif + +#if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) +/* 64-bit unaligned integer comparison */ +static inline uint32_t compare256_rle_unaligned_64(const uint8_t *src0, const uint8_t *src1) { + uint32_t src0_cmp32, len = 0; + uint16_t src0_cmp; + uint64_t sv; + + memcpy(&src0_cmp, src0, sizeof(src0_cmp)); + src0_cmp32 = ((uint32_t)src0_cmp << 16) | src0_cmp; + sv = ((uint64_t)src0_cmp32 << 32) | src0_cmp32; + + do { + uint64_t mv, diff; + + memcpy(&mv, src1, sizeof(mv)); + + diff = sv ^ mv; + if (diff) { + uint64_t match_byte = __builtin_ctzll(diff) / 8; + return len + (uint32_t)match_byte; + } + + src1 += 8, len += 8; + } while (len < 256); + + return 256; +} + +#endif + +#endif + diff --git a/3rdparty/zlib-ng/compress.c b/3rdparty/zlib-ng/compress.c new file mode 100644 index 000000000000..66118e4f4b71 --- /dev/null +++ b/3rdparty/zlib-ng/compress.c @@ -0,0 +1,98 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "zutil.h" + +/* =========================================================================== + * Architecture-specific hooks. + */ +#ifdef S390_DFLTCC_DEFLATE +# include "arch/s390/dfltcc_common.h" +#else +/* Returns the upper bound on compressed data length based on uncompressed data length, assuming default settings. + * Zero means that arch-specific deflation code behaves identically to the regular zlib-ng algorithms. */ +# define DEFLATE_BOUND_COMPLEN(source_len) 0 +#endif + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int Z_EXPORT PREFIX(compress2)(unsigned char *dest, z_uintmax_t *destLen, const unsigned char *source, + z_uintmax_t sourceLen, int level) { + PREFIX3(stream) stream; + int err; + const unsigned int max = (unsigned int)-1; + z_size_t left; + + left = *destLen; + *destLen = 0; + + stream.zalloc = NULL; + stream.zfree = NULL; + stream.opaque = NULL; + + err = PREFIX(deflateInit)(&stream, level); + if (err != Z_OK) + return err; + + stream.next_out = dest; + stream.avail_out = 0; + stream.next_in = (z_const unsigned char *)source; + stream.avail_in = 0; + + do { + if (stream.avail_out == 0) { + stream.avail_out = left > (unsigned long)max ? max : (unsigned int)left; + left -= stream.avail_out; + } + if (stream.avail_in == 0) { + stream.avail_in = sourceLen > (unsigned long)max ? max : (unsigned int)sourceLen; + sourceLen -= stream.avail_in; + } + err = PREFIX(deflate)(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH); + } while (err == Z_OK); + + *destLen = stream.total_out; + PREFIX(deflateEnd)(&stream); + return err == Z_STREAM_END ? Z_OK : err; +} + +/* =========================================================================== + */ +int Z_EXPORT PREFIX(compress)(unsigned char *dest, z_uintmax_t *destLen, const unsigned char *source, z_uintmax_t sourceLen) { + return PREFIX(compress2)(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +z_uintmax_t Z_EXPORT PREFIX(compressBound)(z_uintmax_t sourceLen) { + z_uintmax_t complen = DEFLATE_BOUND_COMPLEN(sourceLen); + + if (complen > 0) + /* Architecture-specific code provided an upper bound. */ + return complen + ZLIB_WRAPLEN; + +#ifndef NO_QUICK_STRATEGY + return sourceLen /* The source size itself */ + + (sourceLen == 0 ? 1 : 0) /* Always at least one byte for any input */ + + (sourceLen < 9 ? 1 : 0) /* One extra byte for lengths less than 9 */ + + DEFLATE_QUICK_OVERHEAD(sourceLen) /* Source encoding overhead, padded to next full byte */ + + DEFLATE_BLOCK_OVERHEAD /* Deflate block overhead bytes */ + + ZLIB_WRAPLEN; /* zlib wrapper */ +#else + return sourceLen + (sourceLen >> 4) + 7 + ZLIB_WRAPLEN; +#endif +} diff --git a/3rdparty/zlib-ng/cpu_features.c b/3rdparty/zlib-ng/cpu_features.c new file mode 100644 index 000000000000..3585172e5d20 --- /dev/null +++ b/3rdparty/zlib-ng/cpu_features.c @@ -0,0 +1,23 @@ +/* cpu_features.c -- CPU architecture feature check + * Copyright (C) 2017 Hans Kristian Rosbach + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "cpu_features.h" +#include + +Z_INTERNAL void cpu_check_features(struct cpu_features *features) { + memset(features, 0, sizeof(struct cpu_features)); +#if defined(X86_FEATURES) + x86_check_features(&features->x86); +#elif defined(ARM_FEATURES) + arm_check_features(&features->arm); +#elif defined(PPC_FEATURES) || defined(POWER_FEATURES) + power_check_features(&features->power); +#elif defined(S390_FEATURES) + s390_check_features(&features->s390); +#elif defined(RISCV_FEATURES) + riscv_check_features(&features->riscv); +#endif +} diff --git a/3rdparty/zlib-ng/cpu_features.h b/3rdparty/zlib-ng/cpu_features.h new file mode 100644 index 000000000000..00fa6c747c5f --- /dev/null +++ b/3rdparty/zlib-ng/cpu_features.h @@ -0,0 +1,303 @@ +/* cpu_features.h -- CPU architecture feature check + * Copyright (C) 2017 Hans Kristian Rosbach + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef CPU_FEATURES_H_ +#define CPU_FEATURES_H_ + +#include "adler32_fold.h" +#include "crc32_fold.h" + +#if defined(X86_FEATURES) +# include "arch/x86/x86_features.h" +# include "fallback_builtins.h" +#elif defined(ARM_FEATURES) +# include "arch/arm/arm_features.h" +#elif defined(PPC_FEATURES) || defined(POWER_FEATURES) +# include "arch/power/power_features.h" +#elif defined(S390_FEATURES) +# include "arch/s390/s390_features.h" +#elif defined(RISCV_FEATURES) +# include "arch/riscv/riscv_features.h" +#endif + +struct cpu_features { +#if defined(X86_FEATURES) + struct x86_cpu_features x86; +#elif defined(ARM_FEATURES) + struct arm_cpu_features arm; +#elif defined(PPC_FEATURES) || defined(POWER_FEATURES) + struct power_cpu_features power; +#elif defined(S390_FEATURES) + struct s390_cpu_features s390; +#elif defined(RISCV_FEATURES) + struct riscv_cpu_features riscv; +#else + char empty; +#endif +}; + +extern void cpu_check_features(struct cpu_features *features); + +/* adler32 */ +typedef uint32_t (*adler32_func)(uint32_t adler, const uint8_t *buf, size_t len); + +extern uint32_t adler32_c(uint32_t adler, const uint8_t *buf, size_t len); +#ifdef ARM_NEON +extern uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, size_t len); +#endif +#ifdef PPC_VMX +extern uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, size_t len); +#endif +#ifdef RISCV_RVV +extern uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len); +#endif +#ifdef X86_SSSE3 +extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, size_t len); +#endif +#ifdef X86_AVX2 +extern uint32_t adler32_avx2(uint32_t adler, const uint8_t *buf, size_t len); +#endif +#ifdef X86_AVX512 +extern uint32_t adler32_avx512(uint32_t adler, const uint8_t *buf, size_t len); +#endif +#ifdef X86_AVX512VNNI +extern uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *buf, size_t len); +#endif +#ifdef POWER8_VSX +extern uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, size_t len); +#endif + +/* adler32 folding */ +#ifdef RISCV_RVV +extern uint32_t adler32_fold_copy_rvv(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +#endif +#ifdef X86_SSE42 +extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +#endif +#ifdef X86_AVX2 +extern uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +#endif +#ifdef X86_AVX512 +extern uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +#endif +#ifdef X86_AVX512VNNI +extern uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +#endif + +/* CRC32 folding */ +#ifdef X86_PCLMULQDQ_CRC +extern uint32_t crc32_fold_pclmulqdq_reset(crc32_fold *crc); +extern void crc32_fold_pclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); +extern void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc); +extern uint32_t crc32_fold_pclmulqdq_final(crc32_fold *crc); +extern uint32_t crc32_pclmulqdq(uint32_t crc32, const uint8_t *buf, size_t len); +#endif +#if defined(X86_PCLMULQDQ_CRC) && defined(X86_VPCLMULQDQ_CRC) +extern uint32_t crc32_fold_vpclmulqdq_reset(crc32_fold *crc); +extern void crc32_fold_vpclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); +extern void crc32_fold_vpclmulqdq(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc); +extern uint32_t crc32_fold_vpclmulqdq_final(crc32_fold *crc); +extern uint32_t crc32_vpclmulqdq(uint32_t crc32, const uint8_t *buf, size_t len); +#endif + +/* memory chunking */ +extern uint32_t chunksize_c(void); +extern uint8_t* chunkmemset_safe_c(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#ifdef X86_SSE2 +extern uint32_t chunksize_sse2(void); +extern uint8_t* chunkmemset_safe_sse2(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#endif +#ifdef X86_SSSE3 +extern uint8_t* chunkmemset_safe_ssse3(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#endif +#ifdef X86_AVX2 +extern uint32_t chunksize_avx2(void); +extern uint8_t* chunkmemset_safe_avx2(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#endif +#ifdef ARM_NEON +extern uint32_t chunksize_neon(void); +extern uint8_t* chunkmemset_safe_neon(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#endif +#ifdef POWER8_VSX +extern uint32_t chunksize_power8(void); +extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#endif +#ifdef RISCV_RVV +extern uint32_t chunksize_rvv(void); +extern uint8_t* chunkmemset_safe_rvv(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#endif + +#ifdef ZLIB_COMPAT +typedef struct z_stream_s z_stream; +#else +typedef struct zng_stream_s zng_stream; +#endif + +/* inflate fast loop */ +extern void inflate_fast_c(PREFIX3(stream) *strm, uint32_t start); +#ifdef X86_SSE2 +extern void inflate_fast_sse2(PREFIX3(stream) *strm, uint32_t start); +#endif +#ifdef X86_SSSE3 +extern void inflate_fast_ssse3(PREFIX3(stream) *strm, uint32_t start); +#endif +#ifdef X86_AVX2 +extern void inflate_fast_avx2(PREFIX3(stream) *strm, uint32_t start); +#endif +#ifdef ARM_NEON +extern void inflate_fast_neon(PREFIX3(stream) *strm, uint32_t start); +#endif +#ifdef POWER8_VSX +extern void inflate_fast_power8(PREFIX3(stream) *strm, uint32_t start); +#endif +#ifdef RISCV_RVV +extern void inflate_fast_rvv(PREFIX3(stream) *strm, uint32_t start); +#endif + +/* CRC32 */ +typedef uint32_t (*crc32_func)(uint32_t crc32, const uint8_t *buf, size_t len); + +extern uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, size_t len); +#ifdef ARM_ACLE +extern uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, size_t len); +#elif defined(POWER8_VSX) +extern uint32_t crc32_power8(uint32_t crc, const uint8_t *buf, size_t len); +#elif defined(S390_CRC32_VX) +extern uint32_t crc32_s390_vx(uint32_t crc, const uint8_t *buf, size_t len); +#endif + +/* compare256 */ +typedef uint32_t (*compare256_func)(const uint8_t *src0, const uint8_t *src1); + +extern uint32_t compare256_c(const uint8_t *src0, const uint8_t *src1); +#if defined(UNALIGNED_OK) && BYTE_ORDER == LITTLE_ENDIAN +extern uint32_t compare256_unaligned_16(const uint8_t *src0, const uint8_t *src1); +#ifdef HAVE_BUILTIN_CTZ +extern uint32_t compare256_unaligned_32(const uint8_t *src0, const uint8_t *src1); +#endif +#if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) +extern uint32_t compare256_unaligned_64(const uint8_t *src0, const uint8_t *src1); +#endif +#endif +#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) +extern uint32_t compare256_sse2(const uint8_t *src0, const uint8_t *src1); +#endif +#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) +extern uint32_t compare256_avx2(const uint8_t *src0, const uint8_t *src1); +#endif +#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) +extern uint32_t compare256_neon(const uint8_t *src0, const uint8_t *src1); +#endif +#ifdef POWER9 +extern uint32_t compare256_power9(const uint8_t *src0, const uint8_t *src1); +#endif +#ifdef RISCV_RVV +extern uint32_t compare256_rvv(const uint8_t *src0, const uint8_t *src1); +#endif + +#ifdef DEFLATE_H_ +/* insert_string */ +extern void insert_string_c(deflate_state *const s, const uint32_t str, uint32_t count); +#ifdef X86_SSE42 +extern void insert_string_sse42(deflate_state *const s, const uint32_t str, uint32_t count); +#elif defined(ARM_ACLE) +extern void insert_string_acle(deflate_state *const s, const uint32_t str, uint32_t count); +#endif + +/* longest_match */ +extern uint32_t longest_match_c(deflate_state *const s, Pos cur_match); +#if defined(UNALIGNED_OK) && BYTE_ORDER == LITTLE_ENDIAN +extern uint32_t longest_match_unaligned_16(deflate_state *const s, Pos cur_match); +#ifdef HAVE_BUILTIN_CTZ +extern uint32_t longest_match_unaligned_32(deflate_state *const s, Pos cur_match); +#endif +#if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) +extern uint32_t longest_match_unaligned_64(deflate_state *const s, Pos cur_match); +#endif +#endif +#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) +extern uint32_t longest_match_sse2(deflate_state *const s, Pos cur_match); +#endif +#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) +extern uint32_t longest_match_avx2(deflate_state *const s, Pos cur_match); +#endif +#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) +extern uint32_t longest_match_neon(deflate_state *const s, Pos cur_match); +#endif +#ifdef POWER9 +extern uint32_t longest_match_power9(deflate_state *const s, Pos cur_match); +#endif +#ifdef RISCV_RVV +extern uint32_t longest_match_rvv(deflate_state *const s, Pos cur_match); +#endif + +/* longest_match_slow */ +extern uint32_t longest_match_slow_c(deflate_state *const s, Pos cur_match); +#if defined(UNALIGNED_OK) && BYTE_ORDER == LITTLE_ENDIAN +extern uint32_t longest_match_slow_unaligned_16(deflate_state *const s, Pos cur_match); +extern uint32_t longest_match_slow_unaligned_32(deflate_state *const s, Pos cur_match); +#ifdef UNALIGNED64_OK +extern uint32_t longest_match_slow_unaligned_64(deflate_state *const s, Pos cur_match); +#endif +#endif +#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) +extern uint32_t longest_match_slow_sse2(deflate_state *const s, Pos cur_match); +#endif +#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) +extern uint32_t longest_match_slow_avx2(deflate_state *const s, Pos cur_match); +#endif +#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) +extern uint32_t longest_match_slow_neon(deflate_state *const s, Pos cur_match); +#endif +#ifdef POWER9 +extern uint32_t longest_match_slow_power9(deflate_state *const s, Pos cur_match); +#endif +#ifdef RISCV_RVV +extern uint32_t longest_match_slow_rvv(deflate_state *const s, Pos cur_match); +#endif + +/* quick_insert_string */ +extern Pos quick_insert_string_c(deflate_state *const s, const uint32_t str); +#ifdef X86_SSE42 +extern Pos quick_insert_string_sse42(deflate_state *const s, const uint32_t str); +#elif defined(ARM_ACLE) +extern Pos quick_insert_string_acle(deflate_state *const s, const uint32_t str); +#endif + +/* slide_hash */ +typedef void (*slide_hash_func)(deflate_state *s); + +#ifdef X86_SSE2 +extern void slide_hash_sse2(deflate_state *s); +#endif +#if defined(ARM_SIMD) +extern void slide_hash_armv6(deflate_state *s); +#endif +#if defined(ARM_NEON) +extern void slide_hash_neon(deflate_state *s); +#endif +#if defined(PPC_VMX) +extern void slide_hash_vmx(deflate_state *s); +#endif +#if defined(POWER8_VSX) +extern void slide_hash_power8(deflate_state *s); +#endif +#if defined(RISCV_RVV) +extern void slide_hash_rvv(deflate_state *s); +#endif +#ifdef X86_AVX2 +extern void slide_hash_avx2(deflate_state *s); +#endif + +/* update_hash */ +extern uint32_t update_hash_c(deflate_state *const s, uint32_t h, uint32_t val); +#ifdef X86_SSE42 +extern uint32_t update_hash_sse42(deflate_state *const s, uint32_t h, uint32_t val); +#elif defined(ARM_ACLE) +extern uint32_t update_hash_acle(deflate_state *const s, uint32_t h, uint32_t val); +#endif +#endif + +#endif diff --git a/3rdparty/zlib-ng/crc32_braid.c b/3rdparty/zlib-ng/crc32_braid.c new file mode 100644 index 000000000000..96754b53dff9 --- /dev/null +++ b/3rdparty/zlib-ng/crc32_braid.c @@ -0,0 +1,267 @@ +/* crc32_braid.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2022 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * This interleaved implementation of a CRC makes use of pipelined multiple + * arithmetic-logic units, commonly found in modern CPU cores. It is due to + * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution. + */ + +#include "zbuild.h" +#include "zutil.h" +#include "functable.h" +#include "crc32_braid_p.h" +#include "crc32_braid_tbl.h" + +/* ========================================================================= */ + +const uint32_t * Z_EXPORT PREFIX(get_crc_table)(void) { + return (const uint32_t *)crc_table; +} + +#ifdef ZLIB_COMPAT +unsigned long Z_EXPORT PREFIX(crc32_z)(unsigned long crc, const unsigned char *buf, size_t len) { + if (buf == NULL) return 0; + + return (unsigned long)functable.crc32((uint32_t)crc, buf, len); +} +#else +uint32_t Z_EXPORT PREFIX(crc32_z)(uint32_t crc, const unsigned char *buf, size_t len) { + if (buf == NULL) return 0; + + return functable.crc32(crc, buf, len); +} +#endif + +#ifdef ZLIB_COMPAT +unsigned long Z_EXPORT PREFIX(crc32)(unsigned long crc, const unsigned char *buf, unsigned int len) { + return (unsigned long)PREFIX(crc32_z)((uint32_t)crc, buf, len); +} +#else +uint32_t Z_EXPORT PREFIX(crc32)(uint32_t crc, const unsigned char *buf, uint32_t len) { + return PREFIX(crc32_z)(crc, buf, len); +} +#endif + +/* ========================================================================= */ + +/* + A CRC of a message is computed on N braids of words in the message, where + each word consists of W bytes (4 or 8). If N is 3, for example, then three + running sparse CRCs are calculated respectively on each braid, at these + indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ... + This is done starting at a word boundary, and continues until as many blocks + of N * W bytes as are available have been processed. The results are combined + into a single CRC at the end. For this code, N must be in the range 1..6 and + W must be 4 or 8. The upper limit on N can be increased if desired by adding + more #if blocks, extending the patterns apparent in the code. In addition, + crc32 tables would need to be regenerated, if the maximum N value is increased. + + N and W are chosen empirically by benchmarking the execution time on a given + processor. The choices for N and W below were based on testing on Intel Kaby + Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64 + Octeon II processors. The Intel, AMD, and ARM processors were all fastest + with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4. + They were all tested with either gcc or clang, all using the -O3 optimization + level. Your mileage may vary. +*/ + +/* ========================================================================= */ + +#if BYTE_ORDER == LITTLE_ENDIAN +# define ZSWAPWORD(word) (word) +# define BRAID_TABLE crc_braid_table +#elif BYTE_ORDER == BIG_ENDIAN +# if W == 8 +# define ZSWAPWORD(word) ZSWAP64(word) +# elif W == 4 +# define ZSWAPWORD(word) ZSWAP32(word) +# endif +# define BRAID_TABLE crc_braid_big_table +#else +# error "No endian defined" +#endif +#define DO1 c = crc_table[(c ^ *buf++) & 0xff] ^ (c >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +#ifdef W +/* + Return the CRC of the W bytes in the word_t data, taking the + least-significant byte of the word as the first byte of data, without any pre + or post conditioning. This is used to combine the CRCs of each braid. + */ +#if BYTE_ORDER == LITTLE_ENDIAN +static uint32_t crc_word(z_word_t data) { + int k; + for (k = 0; k < W; k++) + data = (data >> 8) ^ crc_table[data & 0xff]; + return (uint32_t)data; +} +#elif BYTE_ORDER == BIG_ENDIAN +static z_word_t crc_word(z_word_t data) { + int k; + for (k = 0; k < W; k++) + data = (data << 8) ^ + crc_big_table[(data >> ((W - 1) << 3)) & 0xff]; + return data; +} +#endif /* BYTE_ORDER */ + +#endif /* W */ + +/* ========================================================================= */ +Z_INTERNAL uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, size_t len) { + Z_REGISTER uint32_t c; + + /* Pre-condition the CRC */ + c = (~crc) & 0xffffffff; + +#ifdef W + /* If provided enough bytes, do a braided CRC calculation. */ + if (len >= N * W + W - 1) { + size_t blks; + z_word_t const *words; + int k; + + /* Compute the CRC up to a z_word_t boundary. */ + while (len && ((uintptr_t)buf & (W - 1)) != 0) { + len--; + DO1; + } + + /* Compute the CRC on as many N z_word_t blocks as are available. */ + blks = len / (N * W); + len -= blks * N * W; + words = (z_word_t const *)buf; + + z_word_t crc0, word0, comb; +#if N > 1 + z_word_t crc1, word1; +#if N > 2 + z_word_t crc2, word2; +#if N > 3 + z_word_t crc3, word3; +#if N > 4 + z_word_t crc4, word4; +#if N > 5 + z_word_t crc5, word5; +#endif +#endif +#endif +#endif +#endif + /* Initialize the CRC for each braid. */ + crc0 = ZSWAPWORD(c); +#if N > 1 + crc1 = 0; +#if N > 2 + crc2 = 0; +#if N > 3 + crc3 = 0; +#if N > 4 + crc4 = 0; +#if N > 5 + crc5 = 0; +#endif +#endif +#endif +#endif +#endif + /* Process the first blks-1 blocks, computing the CRCs on each braid independently. */ + while (--blks) { + /* Load the word for each braid into registers. */ + word0 = crc0 ^ words[0]; +#if N > 1 + word1 = crc1 ^ words[1]; +#if N > 2 + word2 = crc2 ^ words[2]; +#if N > 3 + word3 = crc3 ^ words[3]; +#if N > 4 + word4 = crc4 ^ words[4]; +#if N > 5 + word5 = crc5 ^ words[5]; +#endif +#endif +#endif +#endif +#endif + words += N; + + /* Compute and update the CRC for each word. The loop should get unrolled. */ + crc0 = BRAID_TABLE[0][word0 & 0xff]; +#if N > 1 + crc1 = BRAID_TABLE[0][word1 & 0xff]; +#if N > 2 + crc2 = BRAID_TABLE[0][word2 & 0xff]; +#if N > 3 + crc3 = BRAID_TABLE[0][word3 & 0xff]; +#if N > 4 + crc4 = BRAID_TABLE[0][word4 & 0xff]; +#if N > 5 + crc5 = BRAID_TABLE[0][word5 & 0xff]; +#endif +#endif +#endif +#endif +#endif + for (k = 1; k < W; k++) { + crc0 ^= BRAID_TABLE[k][(word0 >> (k << 3)) & 0xff]; +#if N > 1 + crc1 ^= BRAID_TABLE[k][(word1 >> (k << 3)) & 0xff]; +#if N > 2 + crc2 ^= BRAID_TABLE[k][(word2 >> (k << 3)) & 0xff]; +#if N > 3 + crc3 ^= BRAID_TABLE[k][(word3 >> (k << 3)) & 0xff]; +#if N > 4 + crc4 ^= BRAID_TABLE[k][(word4 >> (k << 3)) & 0xff]; +#if N > 5 + crc5 ^= BRAID_TABLE[k][(word5 >> (k << 3)) & 0xff]; +#endif +#endif +#endif +#endif +#endif + } + } + + /* Process the last block, combining the CRCs of the N braids at the same time. */ + comb = crc_word(crc0 ^ words[0]); +#if N > 1 + comb = crc_word(crc1 ^ words[1] ^ comb); +#if N > 2 + comb = crc_word(crc2 ^ words[2] ^ comb); +#if N > 3 + comb = crc_word(crc3 ^ words[3] ^ comb); +#if N > 4 + comb = crc_word(crc4 ^ words[4] ^ comb); +#if N > 5 + comb = crc_word(crc5 ^ words[5] ^ comb); +#endif +#endif +#endif +#endif +#endif + words += N; + c = ZSWAPWORD(comb); + + /* Update the pointer to the remaining bytes to process. */ + buf = (const unsigned char *)words; + } + +#endif /* W */ + + /* Complete the computation of the CRC on any remaining bytes. */ + while (len >= 8) { + len -= 8; + DO8; + } + while (len) { + len--; + DO1; + } + + /* Return the CRC, post-conditioned. */ + return c ^ 0xffffffff; +} diff --git a/3rdparty/zlib-ng/crc32_braid_comb.c b/3rdparty/zlib-ng/crc32_braid_comb.c new file mode 100644 index 000000000000..75fb47425873 --- /dev/null +++ b/3rdparty/zlib-ng/crc32_braid_comb.c @@ -0,0 +1,57 @@ +/* crc32_braid_comb.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2022 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * This interleaved implementation of a CRC makes use of pipelined multiple + * arithmetic-logic units, commonly found in modern CPU cores. It is due to + * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution. + */ + +#include "zbuild.h" +#include "zutil.h" +#include "crc32_braid_p.h" +#include "crc32_braid_tbl.h" +#include "crc32_braid_comb_p.h" + +/* ========================================================================= */ +static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2) { + return multmodp(x2nmodp(len2, 3), crc1) ^ crc2; +} +static uint32_t crc32_combine_gen_(z_off64_t len2) { + return x2nmodp(len2, 3); +} +static uint32_t crc32_combine_op_(uint32_t crc1, uint32_t crc2, const uint32_t op) { + return multmodp(op, crc1) ^ crc2; +} + +/* ========================================================================= */ + +#ifdef ZLIB_COMPAT +unsigned long Z_EXPORT PREFIX(crc32_combine)(unsigned long crc1, unsigned long crc2, z_off_t len2) { + return (unsigned long)crc32_combine_((uint32_t)crc1, (uint32_t)crc2, len2); +} +unsigned long Z_EXPORT PREFIX4(crc32_combine)(unsigned long crc1, unsigned long crc2, z_off64_t len2) { + return (unsigned long)crc32_combine_((uint32_t)crc1, (uint32_t)crc2, len2); +} +unsigned long Z_EXPORT PREFIX(crc32_combine_gen)(z_off_t len2) { + return crc32_combine_gen_(len2); +} +unsigned long Z_EXPORT PREFIX4(crc32_combine_gen)(z_off64_t len2) { + return crc32_combine_gen_(len2); +} +unsigned long Z_EXPORT PREFIX(crc32_combine_op)(unsigned long crc1, unsigned long crc2, const unsigned long op) { + return (unsigned long)crc32_combine_op_((uint32_t)crc1, (uint32_t)crc2, (uint32_t)op); +} +#else +uint32_t Z_EXPORT PREFIX4(crc32_combine)(uint32_t crc1, uint32_t crc2, z_off64_t len2) { + return crc32_combine_(crc1, crc2, len2); +} +uint32_t Z_EXPORT PREFIX(crc32_combine_gen)(z_off64_t len2) { + return crc32_combine_gen_(len2); +} +uint32_t Z_EXPORT PREFIX(crc32_combine_op)(uint32_t crc1, uint32_t crc2, const uint32_t op) { + return crc32_combine_op_(crc1, crc2, op); +} +#endif + +/* ========================================================================= */ diff --git a/3rdparty/zlib-ng/crc32_braid_comb_p.h b/3rdparty/zlib-ng/crc32_braid_comb_p.h new file mode 100644 index 000000000000..a269e7f5b79f --- /dev/null +++ b/3rdparty/zlib-ng/crc32_braid_comb_p.h @@ -0,0 +1,42 @@ +#ifndef CRC32_BRAID_COMB_P_H_ +#define CRC32_BRAID_COMB_P_H_ + +/* + Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial, + reflected. For speed, this requires that a not be zero. + */ +static uint32_t multmodp(uint32_t a, uint32_t b) { + uint32_t m, p; + + m = (uint32_t)1 << 31; + p = 0; + for (;;) { + if (a & m) { + p ^= b; + if ((a & (m - 1)) == 0) + break; + } + m >>= 1; + b = b & 1 ? (b >> 1) ^ POLY : b >> 1; + } + return p; +} + +/* + Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been + initialized. + */ +static uint32_t x2nmodp(z_off64_t n, unsigned k) { + uint32_t p; + + p = (uint32_t)1 << 31; /* x^0 == 1 */ + while (n) { + if (n & 1) + p = multmodp(x2n_table[k & 31], p); + n >>= 1; + k++; + } + return p; +} + +#endif /* CRC32_BRAID_COMB_P_H_ */ diff --git a/3rdparty/zlib-ng/crc32_braid_p.h b/3rdparty/zlib-ng/crc32_braid_p.h new file mode 100644 index 000000000000..1d8a07068a4c --- /dev/null +++ b/3rdparty/zlib-ng/crc32_braid_p.h @@ -0,0 +1,50 @@ +#ifndef CRC32_BRAID_P_H_ +#define CRC32_BRAID_P_H_ + +#include "zbuild.h" +#include "zendian.h" + +/* Define N */ +#ifdef Z_TESTN +# define N Z_TESTN +#else +# define N 5 +#endif +#if N < 1 || N > 6 +# error N must be in 1..6 +#endif + +/* + Define W and the associated z_word_t type. If W is not defined, then a + braided calculation is not used, and the associated tables and code are not + compiled. + */ +#ifdef Z_TESTW +# if Z_TESTW-1 != -1 +# define W Z_TESTW +# endif +#else +# ifndef W +# if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) +# define W 8 +# else +# define W 4 +# endif +# endif +#endif +#ifdef W +# if W == 8 + typedef uint64_t z_word_t; +# else +# undef W +# define W 4 + typedef uint32_t z_word_t; +# endif +#endif + +/* CRC polynomial. */ +#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ + +extern uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, size_t len); + +#endif /* CRC32_BRAID_P_H_ */ diff --git a/3rdparty/zlib-ng/crc32_braid_tbl.h b/3rdparty/zlib-ng/crc32_braid_tbl.h new file mode 100644 index 000000000000..84d79a69e7dc --- /dev/null +++ b/3rdparty/zlib-ng/crc32_braid_tbl.h @@ -0,0 +1,9446 @@ +#ifndef CRC32_BRAID_TBL_H_ +#define CRC32_BRAID_TBL_H_ + +/* crc32_braid_tbl.h -- tables for braided CRC calculation + * Generated automatically by makecrct.c + */ + +static const uint32_t crc_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}; + +#ifdef W + +#if W == 8 + +static const z_word_t crc_big_table[] = { + 0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, + 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000, + 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000, + 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000, + 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000, + 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000, + 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000, + 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000, + 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000, + 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000, + 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000, + 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000, + 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000, + 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000, + 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000, + 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000, + 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000, + 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000, + 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000, + 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000, + 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000, + 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000, + 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000, + 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000, + 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000, + 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000, + 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000, + 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000, + 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000, + 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000, + 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000, + 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000, + 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000, + 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000, + 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000, + 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000, + 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000, + 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000, + 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000, + 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000, + 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000, + 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000, + 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000, + 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000, + 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000, + 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000, + 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000, + 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000, + 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000, + 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000, + 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000, + 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000, + 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000, + 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000, + 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000, + 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000, + 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000, + 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000, + 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000, + 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000, + 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000, + 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000, + 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000, + 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000, + 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000, + 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000, + 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000, + 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000, + 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000, + 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000, + 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000, + 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000, + 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000, + 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000, + 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000, + 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000, + 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000, + 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000, + 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000, + 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000, + 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000, + 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000, + 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000, + 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000, + 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000, + 0x8def022d00000000}; + +#else /* W == 4 */ + +static const z_word_t crc_big_table[] = { + 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, + 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, + 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, + 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, + 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, + 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, + 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, + 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, + 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, + 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, + 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, + 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, + 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, + 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, + 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, + 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, + 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, + 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, + 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, + 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, + 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, + 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, + 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, + 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, + 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, + 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, + 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, + 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, + 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, + 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, + 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, + 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, + 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, + 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, + 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, + 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, + 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, + 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, + 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, + 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, + 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, + 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, + 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, + 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, + 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, + 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, + 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, + 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, + 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, + 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, + 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, + 0x8def022d}; + +#endif + +#endif /* W */ + +#if N == 1 + +#if W == 8 + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, + 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, + 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, + 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, + 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e, + 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, + 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, + 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, + 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, + 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, + 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, + 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, + 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, + 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, + 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, + 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, + 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, + 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, + 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, + 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, + 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e, + 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, + 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed, + 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, + 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, + 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544, + 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, + 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, + 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, + 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, + 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, + 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, + 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, + 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7, + 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, + 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, + 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, + 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, + 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, + 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, + 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, + 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, + 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, + 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, + 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, + 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, + 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9, + 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, + 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, + 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, + 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, + 0x264b06e6}, + {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, + 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3, + 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, + 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, + 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9, + 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, + 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, + 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, + 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, + 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6, + 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, + 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, + 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, + 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, + 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, + 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, + 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, + 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, + 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, + 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, + 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, + 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, + 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, + 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, + 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, + 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, + 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, + 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, + 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, + 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, + 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, + 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, + 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, + 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd, + 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, + 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, + 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, + 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, + 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, + 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, + 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, + 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, + 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, + 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, + 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617, + 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, + 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959, + 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, + 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, + 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, + 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, + 0x92364a30}, + {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, + 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8, + 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, + 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, + 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6, + 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, + 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, + 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, + 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, + 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408, + 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, + 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, + 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, + 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, + 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, + 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, + 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, + 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, + 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, + 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, + 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, + 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, + 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca, + 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, + 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, + 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, + 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, + 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, + 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, + 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, + 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, + 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, + 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, + 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026, + 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, + 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, + 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, + 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, + 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, + 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, + 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, + 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, + 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, + 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, + 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, + 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, + 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, + 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, + 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, + 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1, + 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, + 0xe4c4abcc}, + {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, + 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271, + 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, + 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, + 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43, + 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, + 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, + 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, + 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, + 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, + 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, + 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, + 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, + 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, + 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, + 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, + 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, + 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, + 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, + 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, + 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, + 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, + 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, + 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, + 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, + 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922, + 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, + 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, + 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710, + 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, + 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, + 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, + 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, + 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7, + 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, + 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, + 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, + 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, + 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, + 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, + 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, + 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, + 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, + 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, + 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df, + 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, + 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, + 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, + 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, + 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, + 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, + 0xca64c78c}, + {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, + 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, + 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, + 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, + 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, + 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, + 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, + 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, + 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, + 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, + 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, + 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, + 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, + 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, + 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, + 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, + 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, + 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, + 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, + 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, + 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, + 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, + 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, + 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, + 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, + 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, + 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, + 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, + 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, + 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, + 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, + 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, + 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, + 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, + 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, + 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, + 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, + 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, + 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, + 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, + 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, + 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, + 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, + 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, + 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, + 0xde0506f1}, + {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, + 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, + 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, + 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, + 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, + 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, + 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, + 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, + 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, + 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, + 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, + 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, + 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, + 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, + 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, + 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, + 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, + 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, + 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, + 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, + 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, + 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, + 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, + 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, + 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, + 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, + 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, + 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, + 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, + 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, + 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, + 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, + 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, + 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, + 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, + 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, + 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, + 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, + 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, + 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, + 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, + 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, + 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, + 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, + 0xbe9834ed}, + {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, + 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, + 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, + 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, + 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, + 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, + 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, + 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, + 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, + 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, + 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, + 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, + 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, + 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, + 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, + 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, + 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, + 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, + 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, + 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, + 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, + 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, + 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, + 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, + 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, + 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, + 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, + 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, + 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, + 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, + 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, + 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, + 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, + 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, + 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, + 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, + 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, + 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, + 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, + 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, + 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, + 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, + 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, + 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, + 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, + 0x9324fd72}, + {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, + 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000, + 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000, + 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000, + 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000, + 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000, + 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000, + 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000, + 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000, + 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000, + 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000, + 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000, + 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000, + 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000, + 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000, + 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000, + 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000, + 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000, + 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000, + 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000, + 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000, + 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000, + 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000, + 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000, + 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000, + 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000, + 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000, + 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000, + 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000, + 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000, + 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000, + 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000, + 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000, + 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000, + 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000, + 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000, + 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000, + 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000, + 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000, + 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000, + 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000, + 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000, + 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000, + 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000, + 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000, + 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000, + 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000, + 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000, + 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000, + 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000, + 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000, + 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000, + 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000, + 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000, + 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000, + 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000, + 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000, + 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000, + 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000, + 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000, + 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000, + 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000, + 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000, + 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000, + 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000, + 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000, + 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000, + 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000, + 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000, + 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000, + 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000, + 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000, + 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000, + 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000, + 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000, + 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000, + 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000, + 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000, + 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000, + 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000, + 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000, + 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000, + 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000, + 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000, + 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000, + 0x8def022d00000000}, + {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000, + 0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000, + 0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000, + 0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000, + 0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000, + 0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000, + 0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000, + 0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000, + 0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000, + 0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000, + 0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000, + 0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000, + 0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000, + 0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000, + 0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000, + 0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000, + 0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000, + 0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000, + 0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000, + 0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000, + 0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000, + 0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000, + 0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000, + 0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000, + 0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000, + 0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000, + 0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000, + 0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000, + 0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000, + 0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000, + 0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000, + 0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000, + 0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000, + 0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000, + 0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000, + 0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000, + 0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000, + 0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000, + 0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000, + 0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000, + 0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000, + 0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000, + 0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000, + 0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000, + 0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000, + 0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000, + 0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000, + 0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000, + 0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000, + 0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000, + 0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000, + 0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000, + 0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000, + 0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000, + 0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000, + 0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000, + 0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000, + 0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000, + 0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000, + 0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000, + 0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000, + 0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000, + 0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000, + 0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000, + 0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000, + 0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000, + 0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000, + 0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000, + 0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000, + 0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000, + 0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000, + 0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000, + 0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000, + 0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000, + 0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000, + 0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000, + 0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000, + 0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000, + 0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000, + 0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000, + 0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000, + 0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000, + 0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000, + 0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000, + 0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000, + 0x72fd249300000000}, + {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000, + 0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000, + 0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000, + 0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000, + 0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000, + 0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000, + 0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000, + 0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000, + 0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000, + 0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000, + 0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000, + 0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000, + 0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000, + 0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000, + 0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000, + 0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000, + 0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000, + 0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000, + 0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000, + 0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000, + 0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000, + 0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000, + 0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000, + 0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000, + 0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000, + 0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000, + 0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000, + 0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000, + 0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000, + 0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000, + 0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000, + 0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000, + 0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000, + 0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000, + 0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000, + 0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000, + 0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000, + 0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000, + 0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000, + 0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000, + 0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000, + 0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000, + 0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000, + 0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000, + 0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000, + 0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000, + 0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000, + 0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000, + 0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000, + 0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000, + 0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000, + 0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000, + 0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000, + 0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000, + 0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000, + 0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000, + 0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000, + 0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000, + 0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000, + 0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000, + 0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000, + 0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000, + 0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000, + 0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000, + 0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000, + 0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000, + 0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000, + 0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000, + 0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000, + 0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000, + 0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000, + 0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000, + 0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000, + 0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000, + 0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000, + 0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000, + 0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000, + 0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000, + 0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000, + 0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000, + 0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000, + 0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000, + 0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000, + 0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000, + 0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000, + 0xed3498be00000000}, + {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000, + 0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000, + 0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000, + 0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000, + 0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000, + 0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000, + 0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000, + 0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000, + 0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000, + 0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000, + 0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000, + 0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000, + 0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000, + 0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000, + 0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000, + 0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000, + 0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000, + 0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000, + 0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000, + 0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000, + 0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000, + 0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000, + 0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000, + 0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000, + 0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000, + 0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000, + 0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000, + 0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000, + 0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000, + 0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000, + 0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000, + 0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000, + 0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000, + 0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000, + 0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000, + 0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000, + 0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000, + 0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000, + 0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000, + 0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000, + 0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000, + 0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000, + 0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000, + 0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000, + 0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000, + 0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000, + 0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000, + 0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000, + 0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000, + 0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000, + 0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000, + 0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000, + 0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000, + 0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000, + 0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000, + 0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000, + 0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000, + 0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000, + 0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000, + 0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000, + 0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000, + 0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000, + 0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000, + 0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000, + 0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000, + 0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000, + 0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000, + 0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000, + 0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000, + 0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000, + 0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000, + 0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000, + 0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000, + 0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000, + 0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000, + 0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000, + 0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000, + 0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000, + 0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000, + 0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000, + 0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000, + 0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000, + 0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000, + 0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000, + 0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000, + 0xf10605de00000000}, + {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000, + 0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000, + 0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000, + 0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000, + 0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000, + 0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000, + 0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000, + 0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000, + 0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000, + 0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000, + 0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000, + 0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000, + 0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000, + 0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000, + 0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000, + 0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000, + 0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000, + 0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000, + 0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000, + 0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000, + 0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000, + 0x572f712300000000, 0x4958f35800000000, 0xf971936500000000, + 0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000, + 0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000, + 0x8813836800000000, 0x383ae35500000000, 0xe840431200000000, + 0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000, + 0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000, + 0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000, + 0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000, + 0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000, + 0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000, + 0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000, + 0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000, + 0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000, + 0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000, + 0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000, + 0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000, + 0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000, + 0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000, + 0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000, + 0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000, + 0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000, + 0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000, + 0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000, + 0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000, + 0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000, + 0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000, + 0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000, + 0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000, + 0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000, + 0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000, + 0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000, + 0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000, + 0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000, + 0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000, + 0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000, + 0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000, + 0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000, + 0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000, + 0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000, + 0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000, + 0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000, + 0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000, + 0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000, + 0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000, + 0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000, + 0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000, + 0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000, + 0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000, + 0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000, + 0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000, + 0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000, + 0x983485b900000000, 0x281de58400000000, 0xf86745c300000000, + 0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000, + 0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000, + 0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000, + 0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000, + 0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000, + 0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000, + 0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000, + 0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000, + 0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000, + 0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000, + 0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000, + 0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000, + 0x8cc764ca00000000}, + {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000, + 0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000, + 0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000, + 0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000, + 0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000, + 0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000, + 0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000, + 0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000, + 0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000, + 0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000, + 0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000, + 0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000, + 0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000, + 0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000, + 0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000, + 0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000, + 0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000, + 0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000, + 0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000, + 0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000, + 0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000, + 0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000, + 0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000, + 0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000, + 0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000, + 0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000, + 0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000, + 0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000, + 0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000, + 0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000, + 0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000, + 0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000, + 0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000, + 0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000, + 0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000, + 0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000, + 0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000, + 0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000, + 0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000, + 0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000, + 0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000, + 0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000, + 0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000, + 0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000, + 0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000, + 0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000, + 0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000, + 0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000, + 0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000, + 0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000, + 0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000, + 0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000, + 0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000, + 0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000, + 0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000, + 0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000, + 0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000, + 0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000, + 0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000, + 0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000, + 0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000, + 0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000, + 0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000, + 0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000, + 0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000, + 0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000, + 0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000, + 0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000, + 0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000, + 0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000, + 0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000, + 0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000, + 0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000, + 0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000, + 0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000, + 0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000, + 0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000, + 0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000, + 0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000, + 0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000, + 0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000, + 0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000, + 0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000, + 0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000, + 0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000, + 0xccabc4e400000000}, + {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000, + 0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000, + 0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000, + 0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000, + 0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000, + 0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000, + 0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000, + 0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000, + 0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000, + 0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000, + 0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000, + 0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000, + 0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000, + 0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000, + 0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000, + 0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000, + 0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000, + 0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000, + 0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000, + 0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000, + 0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000, + 0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000, + 0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000, + 0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000, + 0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000, + 0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000, + 0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000, + 0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000, + 0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000, + 0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000, + 0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000, + 0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000, + 0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000, + 0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000, + 0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000, + 0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000, + 0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000, + 0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000, + 0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000, + 0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000, + 0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000, + 0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000, + 0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000, + 0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000, + 0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000, + 0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000, + 0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000, + 0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000, + 0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000, + 0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000, + 0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000, + 0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000, + 0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000, + 0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000, + 0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000, + 0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000, + 0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000, + 0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000, + 0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000, + 0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000, + 0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000, + 0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000, + 0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000, + 0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000, + 0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000, + 0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000, + 0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000, + 0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000, + 0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000, + 0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000, + 0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000, + 0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000, + 0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000, + 0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000, + 0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000, + 0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000, + 0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000, + 0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000, + 0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000, + 0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000, + 0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000, + 0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000, + 0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000, + 0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000, + 0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000, + 0x304a369200000000}, + {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000, + 0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000, + 0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000, + 0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000, + 0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000, + 0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000, + 0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000, + 0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000, + 0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000, + 0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000, + 0x1923316900000000, 0x87239ba500000000, 0x566276f900000000, + 0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000, + 0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000, + 0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000, + 0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000, + 0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000, + 0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000, + 0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000, + 0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000, + 0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000, + 0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000, + 0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000, + 0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000, + 0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000, + 0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000, + 0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000, + 0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000, + 0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000, + 0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000, + 0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000, + 0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000, + 0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000, + 0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000, + 0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000, + 0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000, + 0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000, + 0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000, + 0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000, + 0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000, + 0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000, + 0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000, + 0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000, + 0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000, + 0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000, + 0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000, + 0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000, + 0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000, + 0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000, + 0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000, + 0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000, + 0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000, + 0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000, + 0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000, + 0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000, + 0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000, + 0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000, + 0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000, + 0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000, + 0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000, + 0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000, + 0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000, + 0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000, + 0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000, + 0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000, + 0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000, + 0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000, + 0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000, + 0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000, + 0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000, + 0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000, + 0x6171384400000000, 0xff71928800000000, 0xe678578200000000, + 0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000, + 0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000, + 0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000, + 0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000, + 0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000, + 0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000, + 0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000, + 0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000, + 0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000, + 0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000, + 0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000, + 0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000, + 0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000, + 0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000, + 0xe6064b2600000000}}; + +#else /* W == 4 */ + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, + 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, + 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, + 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, + 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, + 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, + 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, + 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, + 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, + 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, + 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, + 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, + 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, + 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, + 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, + 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, + 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, + 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, + 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, + 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, + 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, + 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, + 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, + 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, + 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, + 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, + 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, + 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, + 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, + 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, + 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, + 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, + 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, + 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, + 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, + 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, + 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, + 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, + 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, + 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, + 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, + 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, + 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, + 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, + 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, + 0xde0506f1}, + {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, + 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, + 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, + 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, + 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, + 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, + 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, + 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, + 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, + 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, + 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, + 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, + 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, + 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, + 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, + 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, + 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, + 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, + 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, + 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, + 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, + 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, + 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, + 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, + 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, + 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, + 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, + 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, + 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, + 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, + 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, + 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, + 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, + 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, + 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, + 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, + 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, + 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, + 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, + 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, + 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, + 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, + 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, + 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, + 0xbe9834ed}, + {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, + 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, + 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, + 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, + 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, + 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, + 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, + 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, + 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, + 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, + 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, + 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, + 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, + 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, + 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, + 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, + 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, + 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, + 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, + 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, + 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, + 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, + 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, + 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, + 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, + 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, + 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, + 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, + 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, + 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, + 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, + 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, + 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, + 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, + 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, + 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, + 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, + 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, + 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, + 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, + 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, + 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, + 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, + 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, + 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, + 0x9324fd72}, + {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, + 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, + 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, + 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, + 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, + 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, + 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, + 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, + 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, + 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, + 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, + 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, + 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, + 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, + 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, + 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, + 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, + 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, + 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, + 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, + 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, + 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, + 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, + 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, + 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, + 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, + 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, + 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, + 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, + 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, + 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, + 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, + 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, + 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, + 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, + 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, + 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, + 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, + 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, + 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, + 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, + 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, + 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, + 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, + 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, + 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, + 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, + 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, + 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, + 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, + 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, + 0x8def022d}, + {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64, + 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1, + 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e, + 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61, + 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82, + 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff, + 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7, + 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da, + 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139, + 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6, + 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89, + 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c, + 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0, + 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d, + 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a, + 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177, + 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de, + 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b, + 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824, + 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e, + 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad, + 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0, + 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d, + 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60, + 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83, + 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822, + 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d, + 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8, + 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171, + 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c, + 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b, + 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6, + 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca, + 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f, + 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430, + 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf, + 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c, + 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51, + 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9, + 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84, + 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67, + 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398, + 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7, + 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62, + 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e, + 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923, + 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4, + 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9, + 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070, + 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5, + 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a, + 0x72fd2493}, + {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907, + 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f, + 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a, + 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e, + 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512, + 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14, + 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b, + 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d, + 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731, + 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925, + 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620, + 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28, + 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70, + 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176, + 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d, + 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b, + 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b, + 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63, + 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266, + 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a, + 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446, + 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40, + 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557, + 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51, + 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d, + 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0, + 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5, + 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed, + 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd, + 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb, + 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0, + 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6, + 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de, + 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6, + 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3, + 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7, + 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb, + 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd, + 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92, + 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094, + 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598, + 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c, + 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489, + 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81, + 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9, + 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af, + 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4, + 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2, + 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2, + 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba, + 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf, + 0xed3498be}, + {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f, + 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d, + 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0, + 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42, + 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95, + 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2, + 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a, + 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d, + 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea, + 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748, + 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5, + 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27, + 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b, + 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac, + 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4, + 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3, + 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44, + 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6, + 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b, + 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329, + 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe, + 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9, + 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1, + 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6, + 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921, + 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555, + 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8, + 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a, + 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd, + 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a, + 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2, + 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5, + 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2, + 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330, + 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad, + 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f, + 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8, + 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef, + 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc, + 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb, + 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c, + 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e, + 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03, + 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1, + 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6, + 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1, + 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9, + 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e, + 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409, + 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb, + 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966, + 0xf10605de}}; + +#endif /* W */ + +#endif /* N == 1 */ +#if N == 2 + +#if W == 8 + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87, + 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede, + 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab, + 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c, + 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1, + 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7, + 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e, + 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308, + 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5, + 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472, + 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07, + 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e, + 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa, + 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec, + 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6, + 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0, + 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3, + 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba, + 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf, + 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975, + 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8, + 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde, + 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a, + 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c, + 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1, + 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65, + 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410, + 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649, + 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a, + 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c, + 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946, + 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450, + 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e, + 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857, + 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022, + 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5, + 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758, + 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e, + 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d, + 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b, + 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6, + 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401, + 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74, + 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d, + 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073, + 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65, + 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f, + 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749, + 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a, + 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033, + 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846, + 0x0d7139d7}, + {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563, + 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f, + 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875, + 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536, + 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8, + 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43, + 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f, + 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184, + 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a, + 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39, + 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523, + 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f, + 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d, + 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6, + 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b, + 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0, + 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151, + 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d, + 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47, + 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a, + 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964, + 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef, + 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d, + 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6, + 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348, + 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53, + 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449, + 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645, + 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4, + 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f, + 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2, + 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69, + 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46, + 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a, + 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650, + 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13, + 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded, + 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366, + 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57, + 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc, + 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222, + 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61, + 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b, + 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277, + 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558, + 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3, + 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e, + 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5, + 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74, + 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78, + 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262, + 0x1c53e98a}, + {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b, + 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40, + 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580, + 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7, + 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a, + 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37, + 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75, + 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218, + 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5, + 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2, + 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02, + 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59, + 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1, + 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c, + 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a, + 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307, + 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486, + 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd, + 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d, + 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2, + 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f, + 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72, + 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8, + 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985, + 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268, + 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94, + 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454, + 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f, + 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e, + 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3, + 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915, + 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778, + 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821, + 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a, + 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba, + 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d, + 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560, + 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d, + 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe, + 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3, + 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e, + 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509, + 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9, + 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92, + 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb, + 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6, + 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50, + 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d, + 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc, + 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7, + 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927, + 0x3f88e851}, + {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96, + 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8, + 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0, + 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14, + 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7, + 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4, + 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe, + 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad, + 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e, + 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa, + 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2, + 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c, + 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab, + 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8, + 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d, + 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e, + 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7, + 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99, + 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1, + 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690, + 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933, + 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20, + 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf, + 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc, + 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f, + 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92, + 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca, + 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4, + 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd, + 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de, + 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb, + 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8, + 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474, + 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a, + 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252, + 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6, + 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55, + 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846, + 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7, + 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4, + 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47, + 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3, + 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb, + 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5, + 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49, + 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a, + 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f, + 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c, + 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305, + 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b, + 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523, + 0x3dee8ca6}, + {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f, + 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91, + 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e, + 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c, + 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02, + 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12, + 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567, + 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277, + 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679, + 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b, + 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4, + 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a, + 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0, + 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0, + 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91, + 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881, + 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173, + 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d, + 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912, + 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8, + 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6, + 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6, + 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b, + 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b, + 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75, + 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f, + 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00, + 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee, + 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c, + 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c, + 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d, + 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d, + 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67, + 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89, + 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706, + 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14, + 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a, + 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a, + 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f, + 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f, + 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591, + 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983, + 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c, + 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2, + 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8, + 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8, + 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89, + 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99, + 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b, + 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485, + 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a, + 0x36197165}, + {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382, + 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85, + 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06, + 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca, + 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e, + 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc, + 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616, + 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54, + 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10, + 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc, + 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f, + 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58, + 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef, + 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad, + 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b, + 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29, + 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6, + 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1, + 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622, + 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039, + 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d, + 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f, + 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32, + 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770, + 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034, + 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f, + 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc, + 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db, + 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154, + 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16, + 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0, + 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592, + 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca, + 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd, + 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e, + 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882, + 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6, + 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384, + 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1, + 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3, + 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7, + 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b, + 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8, + 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff, + 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7, + 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5, + 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23, + 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761, + 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee, + 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9, + 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a, + 0x1a3b93aa}, + {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a, + 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca, + 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3, + 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb, + 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c, + 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58, + 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed, + 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9, + 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e, + 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906, + 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f, + 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf, + 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0, + 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4, + 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769, + 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d, + 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632, + 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82, + 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb, + 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73, + 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484, + 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0, + 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5, + 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1, + 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516, + 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f, + 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946, + 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6, + 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9, + 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad, + 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820, + 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364, + 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab, + 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b, + 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62, + 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a, + 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd, + 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089, + 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c, + 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8, + 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f, + 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477, + 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e, + 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be, + 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71, + 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635, + 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8, + 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc, + 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3, + 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753, + 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a, + 0xe147d714}, + {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c, + 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b, + 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92, + 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4, + 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069, + 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526, + 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25, + 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a, + 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7, + 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491, + 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958, + 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f, + 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307, + 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648, + 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999, + 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6, + 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a, + 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d, + 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4, + 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61, + 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc, + 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3, + 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53, + 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c, + 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1, + 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c, + 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5, + 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92, + 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e, + 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771, + 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0, + 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def, + 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0, + 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7, + 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e, + 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58, + 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285, + 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca, + 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce, + 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81, + 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c, + 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a, + 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3, + 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4, + 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb, + 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4, + 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75, + 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a, + 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296, + 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1, + 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808, + 0x494f0c4b}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000, + 0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000, + 0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000, + 0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000, + 0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000, + 0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000, + 0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000, + 0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000, + 0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000, + 0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000, + 0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000, + 0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000, + 0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000, + 0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000, + 0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000, + 0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000, + 0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000, + 0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000, + 0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000, + 0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000, + 0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000, + 0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000, + 0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000, + 0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000, + 0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000, + 0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000, + 0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000, + 0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000, + 0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000, + 0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000, + 0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000, + 0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000, + 0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000, + 0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000, + 0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000, + 0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000, + 0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000, + 0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000, + 0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000, + 0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000, + 0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000, + 0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000, + 0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000, + 0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000, + 0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000, + 0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000, + 0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000, + 0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000, + 0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000, + 0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000, + 0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000, + 0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000, + 0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000, + 0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000, + 0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000, + 0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000, + 0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000, + 0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000, + 0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000, + 0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000, + 0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000, + 0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000, + 0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000, + 0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000, + 0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000, + 0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000, + 0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000, + 0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000, + 0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000, + 0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000, + 0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000, + 0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000, + 0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000, + 0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000, + 0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000, + 0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000, + 0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000, + 0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000, + 0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000, + 0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000, + 0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000, + 0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000, + 0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000, + 0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000, + 0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000, + 0x4b0c4f4900000000}, + {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000, + 0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000, + 0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000, + 0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000, + 0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000, + 0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000, + 0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000, + 0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000, + 0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000, + 0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000, + 0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000, + 0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000, + 0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000, + 0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000, + 0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000, + 0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000, + 0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000, + 0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000, + 0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000, + 0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000, + 0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000, + 0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000, + 0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000, + 0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000, + 0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000, + 0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000, + 0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000, + 0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000, + 0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000, + 0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000, + 0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000, + 0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000, + 0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000, + 0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000, + 0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000, + 0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000, + 0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000, + 0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000, + 0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000, + 0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000, + 0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000, + 0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000, + 0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000, + 0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000, + 0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000, + 0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000, + 0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000, + 0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000, + 0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000, + 0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000, + 0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000, + 0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000, + 0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000, + 0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000, + 0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000, + 0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000, + 0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000, + 0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000, + 0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000, + 0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000, + 0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000, + 0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000, + 0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000, + 0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000, + 0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000, + 0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000, + 0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000, + 0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000, + 0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000, + 0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000, + 0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000, + 0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000, + 0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000, + 0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000, + 0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000, + 0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000, + 0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000, + 0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000, + 0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000, + 0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000, + 0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000, + 0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000, + 0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000, + 0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000, + 0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000, + 0x14d747e100000000}, + {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000, + 0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000, + 0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000, + 0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000, + 0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000, + 0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000, + 0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000, + 0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000, + 0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000, + 0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000, + 0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000, + 0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000, + 0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000, + 0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000, + 0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000, + 0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000, + 0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000, + 0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000, + 0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000, + 0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000, + 0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000, + 0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000, + 0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000, + 0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000, + 0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000, + 0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000, + 0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000, + 0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000, + 0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000, + 0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000, + 0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000, + 0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000, + 0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000, + 0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000, + 0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000, + 0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000, + 0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000, + 0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000, + 0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000, + 0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000, + 0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000, + 0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000, + 0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000, + 0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000, + 0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000, + 0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000, + 0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000, + 0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000, + 0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000, + 0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000, + 0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000, + 0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000, + 0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000, + 0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000, + 0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000, + 0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000, + 0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000, + 0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000, + 0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000, + 0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000, + 0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000, + 0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000, + 0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000, + 0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000, + 0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000, + 0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000, + 0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000, + 0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000, + 0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000, + 0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000, + 0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000, + 0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000, + 0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000, + 0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000, + 0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000, + 0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000, + 0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000, + 0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000, + 0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000, + 0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000, + 0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000, + 0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000, + 0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000, + 0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000, + 0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000, + 0xaa933b1a00000000}, + {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000, + 0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000, + 0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000, + 0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000, + 0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000, + 0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000, + 0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000, + 0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000, + 0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000, + 0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000, + 0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000, + 0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000, + 0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000, + 0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000, + 0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000, + 0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000, + 0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000, + 0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000, + 0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000, + 0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000, + 0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000, + 0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000, + 0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000, + 0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000, + 0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000, + 0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000, + 0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000, + 0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000, + 0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000, + 0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000, + 0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000, + 0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000, + 0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000, + 0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000, + 0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000, + 0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000, + 0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000, + 0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000, + 0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000, + 0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000, + 0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000, + 0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000, + 0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000, + 0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000, + 0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000, + 0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000, + 0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000, + 0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000, + 0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000, + 0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000, + 0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000, + 0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000, + 0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000, + 0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000, + 0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000, + 0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000, + 0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000, + 0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000, + 0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000, + 0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000, + 0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000, + 0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000, + 0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000, + 0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000, + 0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000, + 0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000, + 0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000, + 0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000, + 0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000, + 0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000, + 0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000, + 0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000, + 0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000, + 0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000, + 0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000, + 0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000, + 0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000, + 0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000, + 0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000, + 0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000, + 0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000, + 0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000, + 0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000, + 0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000, + 0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000, + 0x6571193600000000}, + {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000, + 0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000, + 0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000, + 0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000, + 0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000, + 0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000, + 0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000, + 0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000, + 0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000, + 0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000, + 0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000, + 0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000, + 0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000, + 0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000, + 0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000, + 0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000, + 0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000, + 0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000, + 0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000, + 0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000, + 0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000, + 0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000, + 0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000, + 0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000, + 0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000, + 0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000, + 0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000, + 0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000, + 0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000, + 0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000, + 0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000, + 0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000, + 0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000, + 0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000, + 0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000, + 0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000, + 0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000, + 0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000, + 0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000, + 0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000, + 0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000, + 0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000, + 0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000, + 0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000, + 0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000, + 0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000, + 0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000, + 0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000, + 0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000, + 0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000, + 0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000, + 0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000, + 0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000, + 0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000, + 0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000, + 0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000, + 0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000, + 0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000, + 0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000, + 0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000, + 0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000, + 0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000, + 0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000, + 0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000, + 0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000, + 0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000, + 0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000, + 0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000, + 0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000, + 0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000, + 0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000, + 0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000, + 0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000, + 0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000, + 0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000, + 0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000, + 0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000, + 0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000, + 0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000, + 0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000, + 0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000, + 0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000, + 0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000, + 0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000, + 0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000, + 0xa68cee3d00000000}, + {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000, + 0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000, + 0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000, + 0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000, + 0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000, + 0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000, + 0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000, + 0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000, + 0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000, + 0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000, + 0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000, + 0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000, + 0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000, + 0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000, + 0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000, + 0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000, + 0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000, + 0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000, + 0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000, + 0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000, + 0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000, + 0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000, + 0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000, + 0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000, + 0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000, + 0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000, + 0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000, + 0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000, + 0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000, + 0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000, + 0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000, + 0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000, + 0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000, + 0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000, + 0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000, + 0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000, + 0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000, + 0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000, + 0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000, + 0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000, + 0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000, + 0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000, + 0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000, + 0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000, + 0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000, + 0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000, + 0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000, + 0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000, + 0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000, + 0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000, + 0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000, + 0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000, + 0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000, + 0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000, + 0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000, + 0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000, + 0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000, + 0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000, + 0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000, + 0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000, + 0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000, + 0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000, + 0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000, + 0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000, + 0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000, + 0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000, + 0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000, + 0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000, + 0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000, + 0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000, + 0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000, + 0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000, + 0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000, + 0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000, + 0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000, + 0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000, + 0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000, + 0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000, + 0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000, + 0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000, + 0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000, + 0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000, + 0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000, + 0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000, + 0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000, + 0x51e8883f00000000}, + {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000, + 0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000, + 0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000, + 0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000, + 0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000, + 0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000, + 0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000, + 0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000, + 0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000, + 0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000, + 0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000, + 0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000, + 0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000, + 0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000, + 0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000, + 0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000, + 0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000, + 0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000, + 0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000, + 0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000, + 0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000, + 0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000, + 0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000, + 0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000, + 0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000, + 0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000, + 0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000, + 0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000, + 0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000, + 0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000, + 0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000, + 0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000, + 0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000, + 0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000, + 0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000, + 0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000, + 0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000, + 0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000, + 0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000, + 0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000, + 0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000, + 0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000, + 0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000, + 0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000, + 0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000, + 0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000, + 0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000, + 0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000, + 0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000, + 0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000, + 0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000, + 0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000, + 0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000, + 0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000, + 0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000, + 0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000, + 0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000, + 0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000, + 0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000, + 0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000, + 0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000, + 0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000, + 0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000, + 0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000, + 0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000, + 0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000, + 0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000, + 0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000, + 0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000, + 0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000, + 0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000, + 0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000, + 0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000, + 0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000, + 0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000, + 0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000, + 0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000, + 0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000, + 0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000, + 0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000, + 0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000, + 0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000, + 0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000, + 0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000, + 0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000, + 0x8ae9531c00000000}, + {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000, + 0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000, + 0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000, + 0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000, + 0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000, + 0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000, + 0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000, + 0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000, + 0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000, + 0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000, + 0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000, + 0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000, + 0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000, + 0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000, + 0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000, + 0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000, + 0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000, + 0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000, + 0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000, + 0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000, + 0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000, + 0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000, + 0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000, + 0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000, + 0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000, + 0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000, + 0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000, + 0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000, + 0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000, + 0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000, + 0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000, + 0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000, + 0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000, + 0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000, + 0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000, + 0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000, + 0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000, + 0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000, + 0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000, + 0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000, + 0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000, + 0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000, + 0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000, + 0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000, + 0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000, + 0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000, + 0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000, + 0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000, + 0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000, + 0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000, + 0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000, + 0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000, + 0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000, + 0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000, + 0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000, + 0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000, + 0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000, + 0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000, + 0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000, + 0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000, + 0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000, + 0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000, + 0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000, + 0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000, + 0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000, + 0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000, + 0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000, + 0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000, + 0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000, + 0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000, + 0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000, + 0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000, + 0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000, + 0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000, + 0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000, + 0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000, + 0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000, + 0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000, + 0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000, + 0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000, + 0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000, + 0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000, + 0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000, + 0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000, + 0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000, + 0xd739710d00000000}}; + +#else /* W == 4 */ + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, + 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, + 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, + 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, + 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e, + 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, + 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, + 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, + 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, + 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, + 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, + 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, + 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, + 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, + 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, + 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, + 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, + 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, + 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, + 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, + 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e, + 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, + 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed, + 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, + 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, + 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544, + 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, + 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, + 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, + 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, + 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, + 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, + 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, + 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7, + 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, + 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, + 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, + 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, + 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, + 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, + 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, + 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, + 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, + 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, + 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, + 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, + 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9, + 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, + 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, + 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, + 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, + 0x264b06e6}, + {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, + 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3, + 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, + 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, + 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9, + 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, + 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, + 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, + 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, + 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6, + 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, + 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, + 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, + 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, + 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, + 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, + 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, + 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, + 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, + 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, + 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, + 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, + 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, + 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, + 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, + 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, + 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, + 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, + 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, + 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, + 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, + 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, + 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, + 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd, + 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, + 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, + 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, + 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, + 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, + 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, + 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, + 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, + 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, + 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, + 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617, + 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, + 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959, + 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, + 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, + 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, + 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, + 0x92364a30}, + {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, + 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8, + 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, + 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, + 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6, + 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, + 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, + 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, + 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, + 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408, + 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, + 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, + 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, + 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, + 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, + 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, + 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, + 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, + 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, + 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, + 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, + 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, + 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca, + 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, + 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, + 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, + 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, + 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, + 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, + 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, + 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, + 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, + 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, + 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026, + 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, + 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, + 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, + 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, + 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, + 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, + 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, + 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, + 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, + 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, + 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, + 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, + 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, + 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, + 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, + 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1, + 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, + 0xe4c4abcc}, + {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, + 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271, + 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, + 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, + 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43, + 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, + 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, + 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, + 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, + 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, + 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, + 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, + 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, + 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, + 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, + 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, + 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, + 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, + 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, + 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, + 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, + 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, + 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, + 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, + 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, + 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922, + 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, + 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, + 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710, + 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, + 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, + 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, + 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, + 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7, + 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, + 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, + 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, + 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, + 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, + 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, + 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, + 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, + 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, + 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, + 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df, + 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, + 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, + 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, + 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, + 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, + 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, + 0xca64c78c}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5, + 0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d, + 0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf, + 0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027, + 0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050, + 0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098, + 0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb, + 0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173, + 0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104, + 0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c, + 0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e, + 0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6, + 0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358, + 0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390, + 0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312, + 0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da, + 0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd, + 0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335, + 0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387, + 0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de, + 0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9, + 0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261, + 0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283, + 0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b, + 0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c, + 0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c, + 0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e, + 0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6, + 0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1, + 0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619, + 0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b, + 0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653, + 0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785, + 0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d, + 0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf, + 0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757, + 0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720, + 0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8, + 0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593, + 0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b, + 0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c, + 0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4, + 0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506, + 0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe, + 0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428, + 0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0, + 0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462, + 0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa, + 0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd, + 0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445, + 0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7, + 0x8cc764ca}, + {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b, + 0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27, + 0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a, + 0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285, + 0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef, + 0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf, + 0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a, + 0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a, + 0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70, + 0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf, + 0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2, + 0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e, + 0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f, + 0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f, + 0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae, + 0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe, + 0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97, + 0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b, + 0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436, + 0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e, + 0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4, + 0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4, + 0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46, + 0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716, + 0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c, + 0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5, + 0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8, + 0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774, + 0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d, + 0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d, + 0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc, + 0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec, + 0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82, + 0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e, + 0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623, + 0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c, + 0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6, + 0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6, + 0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c, + 0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c, + 0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66, + 0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9, + 0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4, + 0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978, + 0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416, + 0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946, + 0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7, + 0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7, + 0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e, + 0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32, + 0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f, + 0xccabc4e4}, + {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4, + 0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895, + 0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50, + 0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656, + 0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154, + 0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906, + 0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258, + 0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a, + 0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08, + 0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e, + 0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb, + 0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa, + 0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44, + 0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316, + 0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0, + 0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2, + 0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7, + 0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6, + 0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73, + 0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba, + 0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8, + 0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea, + 0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b, + 0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29, + 0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b, + 0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e, + 0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb, + 0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a, + 0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef, + 0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd, + 0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b, + 0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019, + 0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3, + 0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2, + 0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417, + 0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11, + 0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13, + 0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241, + 0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b, + 0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09, + 0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b, + 0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d, + 0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8, + 0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9, + 0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003, + 0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851, + 0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7, + 0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5, + 0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190, + 0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1, + 0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134, + 0x304a3692}, + {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84, + 0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f, + 0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15, + 0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2, + 0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf, + 0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7, + 0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb, + 0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3, + 0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae, + 0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749, + 0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243, + 0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8, + 0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29, + 0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61, + 0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8, + 0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0, + 0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1, + 0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a, + 0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40, + 0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e, + 0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03, + 0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b, + 0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee, + 0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6, + 0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb, + 0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f, + 0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495, + 0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e, + 0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f, + 0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067, + 0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be, + 0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6, + 0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e, + 0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5, + 0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf, + 0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958, + 0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305, + 0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d, + 0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338, + 0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370, + 0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d, + 0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca, + 0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0, + 0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b, + 0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083, + 0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb, + 0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012, + 0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a, + 0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b, + 0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0, + 0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea, + 0xe6064b26}}; + +#endif /* W */ + +#endif /* N == 2 */ +#if N == 3 + +#if W == 8 + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f, + 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999, + 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee, + 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615, + 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383, + 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb, + 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275, + 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d, + 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b, + 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460, + 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317, + 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1, + 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5, + 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd, + 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04, + 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c, + 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7, + 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11, + 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66, + 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7, + 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871, + 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309, + 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd, + 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85, + 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913, + 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d, + 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a, + 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc, + 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57, + 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f, + 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6, + 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e, + 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f, + 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289, + 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe, + 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05, + 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893, + 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb, + 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0, + 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8, + 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e, + 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5, + 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2, + 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574, + 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5, + 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add, + 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114, + 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c, + 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7, + 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701, + 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076, + 0x09cd8551}, + {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193, + 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2, + 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c, + 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71, + 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a, + 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d, + 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71, + 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436, + 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d, + 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000, + 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae, + 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf, + 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930, + 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277, + 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff, + 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8, + 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef, + 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e, + 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20, + 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95, + 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e, + 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9, + 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d, + 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a, + 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151, + 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4, + 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a, + 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b, + 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c, + 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b, + 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3, + 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4, + 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b, + 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a, + 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4, + 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189, + 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92, + 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5, + 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9, + 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe, + 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5, + 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8, + 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66, + 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707, + 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8, + 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f, + 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707, + 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40, + 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017, + 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876, + 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8, + 0x7bc97a0c}, + {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300, + 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0, + 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80, + 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701, + 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41, + 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81, + 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43, + 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83, + 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3, + 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42, + 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202, + 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2, + 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7, + 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407, + 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47, + 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87, + 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86, + 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46, + 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506, + 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44, + 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704, + 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4, + 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5, + 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505, + 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45, + 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f, + 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f, + 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f, + 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e, + 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e, + 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e, + 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce, + 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c, + 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc, + 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c, + 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d, + 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d, + 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d, + 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88, + 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48, + 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708, + 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89, + 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9, + 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309, + 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb, + 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b, + 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b, + 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b, + 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a, + 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a, + 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a, + 0x7851a2ca}, + {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb, + 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8, + 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0, + 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f, + 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a, + 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf, + 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5, + 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380, + 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815, + 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa, + 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2, + 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1, + 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1, + 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4, + 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa, + 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df, + 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6, + 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5, + 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad, + 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca, + 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f, + 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a, + 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8, + 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d, + 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708, + 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d, + 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865, + 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636, + 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f, + 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a, + 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744, + 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061, + 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0, + 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293, + 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb, + 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874, + 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1, + 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4, + 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f, + 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a, + 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f, + 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120, + 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778, + 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b, + 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a, + 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af, + 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81, + 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4, + 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd, + 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e, + 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6, + 0x566b6848}, + {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59, + 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4, + 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67, + 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef, + 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97, + 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88, + 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687, + 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698, + 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0, + 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068, + 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb, + 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056, + 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016, + 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009, + 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028, + 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037, + 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a, + 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7, + 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054, + 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7, + 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af, + 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0, + 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4, + 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab, + 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3, + 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a, + 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9, + 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54, + 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09, + 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16, + 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37, + 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28, + 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e, + 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3, + 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40, + 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8, + 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0, + 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf, + 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6, + 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9, + 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1, + 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059, + 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca, + 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067, + 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031, + 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e, + 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f, + 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010, + 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d, + 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0, + 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073, + 0xd8ac6b35}, + {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2, + 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd, + 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696, + 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3, + 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f, + 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35, + 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5, + 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f, + 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673, + 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46, + 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d, + 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632, + 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28, + 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192, + 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c, + 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6, + 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0, + 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff, + 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4, + 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95, + 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9, + 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03, + 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7, + 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d, + 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151, + 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808, + 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343, + 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c, + 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a, + 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0, + 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e, + 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594, + 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6, + 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399, + 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2, + 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7, + 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb, + 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571, + 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289, + 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33, + 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f, + 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a, + 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461, + 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e, + 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c, + 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6, + 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918, + 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2, + 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484, + 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb, + 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0, + 0xa140efa8}, + {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706, + 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed, + 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289, + 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a, + 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214, + 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3, + 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3, + 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254, + 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a, + 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9, + 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad, + 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746, + 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060, + 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187, + 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef, + 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408, + 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e, + 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495, + 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1, + 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532, + 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c, + 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb, + 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb, + 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c, + 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42, + 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060, + 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04, + 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef, + 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99, + 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e, + 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16, + 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1, + 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7, + 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c, + 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38, + 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb, + 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5, + 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42, + 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62, + 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85, + 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb, + 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18, + 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c, + 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997, + 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1, + 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36, + 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e, + 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9, + 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf, + 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24, + 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040, + 0x917cd6a1}, + {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf, + 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd, + 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896, + 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9, + 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3, + 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f, + 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d, + 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1, + 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab, + 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4, + 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f, + 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d, + 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4, + 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978, + 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad, + 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621, + 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46, + 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854, + 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f, + 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a, + 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890, + 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c, + 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4, + 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238, + 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622, + 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab, + 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0, + 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2, + 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295, + 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19, + 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc, + 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140, + 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd, + 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf, + 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184, + 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb, + 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1, + 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d, + 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb, + 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257, + 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d, + 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22, + 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069, + 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b, + 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6, + 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a, + 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf, + 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33, + 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254, + 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146, + 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d, + 0x18ba364e}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000, + 0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000, + 0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000, + 0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000, + 0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000, + 0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000, + 0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000, + 0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000, + 0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000, + 0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000, + 0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000, + 0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000, + 0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000, + 0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000, + 0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000, + 0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000, + 0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000, + 0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000, + 0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000, + 0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000, + 0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000, + 0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000, + 0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000, + 0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000, + 0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000, + 0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000, + 0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000, + 0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000, + 0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000, + 0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000, + 0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000, + 0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000, + 0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000, + 0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000, + 0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000, + 0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000, + 0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000, + 0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000, + 0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000, + 0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000, + 0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000, + 0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000, + 0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000, + 0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000, + 0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000, + 0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000, + 0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000, + 0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000, + 0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000, + 0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000, + 0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000, + 0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000, + 0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000, + 0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000, + 0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000, + 0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000, + 0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000, + 0x08eda52100000000, 0x4391370100000000, 0x005a918600000000, + 0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000, + 0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000, + 0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000, + 0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000, + 0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000, + 0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000, + 0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000, + 0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000, + 0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000, + 0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000, + 0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000, + 0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000, + 0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000, + 0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000, + 0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000, + 0x7b23114500000000, 0x305f836500000000, 0x739425e200000000, + 0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000, + 0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000, + 0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000, + 0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000, + 0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000, + 0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000, + 0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000, + 0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000, + 0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000, + 0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000, + 0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000, + 0x4e36ba1800000000}, + {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000, + 0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000, + 0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000, + 0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000, + 0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000, + 0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000, + 0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000, + 0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000, + 0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000, + 0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000, + 0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000, + 0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000, + 0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000, + 0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000, + 0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000, + 0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000, + 0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000, + 0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000, + 0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000, + 0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000, + 0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000, + 0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000, + 0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000, + 0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000, + 0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000, + 0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000, + 0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000, + 0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000, + 0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000, + 0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000, + 0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000, + 0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000, + 0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000, + 0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000, + 0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000, + 0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000, + 0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000, + 0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000, + 0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000, + 0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000, + 0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000, + 0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000, + 0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000, + 0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000, + 0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000, + 0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000, + 0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000, + 0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000, + 0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000, + 0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000, + 0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000, + 0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000, + 0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000, + 0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000, + 0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000, + 0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000, + 0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000, + 0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000, + 0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000, + 0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000, + 0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000, + 0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000, + 0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000, + 0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000, + 0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000, + 0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000, + 0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000, + 0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000, + 0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000, + 0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000, + 0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000, + 0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000, + 0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000, + 0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000, + 0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000, + 0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000, + 0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000, + 0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000, + 0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000, + 0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000, + 0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000, + 0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000, + 0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000, + 0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000, + 0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000, + 0xa1d67c9100000000}, + {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000, + 0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000, + 0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000, + 0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000, + 0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000, + 0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000, + 0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000, + 0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000, + 0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000, + 0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000, + 0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000, + 0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000, + 0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000, + 0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000, + 0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000, + 0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000, + 0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000, + 0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000, + 0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000, + 0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000, + 0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000, + 0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000, + 0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000, + 0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000, + 0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000, + 0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000, + 0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000, + 0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000, + 0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000, + 0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000, + 0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000, + 0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000, + 0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000, + 0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000, + 0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000, + 0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000, + 0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000, + 0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000, + 0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000, + 0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000, + 0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000, + 0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000, + 0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000, + 0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000, + 0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000, + 0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000, + 0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000, + 0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000, + 0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000, + 0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000, + 0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000, + 0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000, + 0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000, + 0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000, + 0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000, + 0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000, + 0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000, + 0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000, + 0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000, + 0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000, + 0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000, + 0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000, + 0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000, + 0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000, + 0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000, + 0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000, + 0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000, + 0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000, + 0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000, + 0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000, + 0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000, + 0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000, + 0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000, + 0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000, + 0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000, + 0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000, + 0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000, + 0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000, + 0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000, + 0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000, + 0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000, + 0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000, + 0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000, + 0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000, + 0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000, + 0xa8ef40a100000000}, + {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000, + 0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000, + 0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000, + 0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000, + 0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000, + 0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000, + 0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000, + 0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000, + 0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000, + 0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000, + 0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000, + 0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000, + 0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000, + 0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000, + 0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000, + 0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000, + 0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000, + 0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000, + 0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000, + 0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000, + 0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000, + 0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000, + 0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000, + 0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000, + 0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000, + 0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000, + 0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000, + 0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000, + 0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000, + 0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000, + 0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000, + 0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000, + 0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000, + 0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000, + 0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000, + 0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000, + 0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000, + 0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000, + 0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000, + 0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000, + 0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000, + 0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000, + 0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000, + 0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000, + 0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000, + 0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000, + 0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000, + 0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000, + 0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000, + 0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000, + 0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000, + 0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000, + 0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000, + 0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000, + 0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000, + 0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000, + 0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000, + 0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000, + 0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000, + 0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000, + 0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000, + 0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000, + 0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000, + 0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000, + 0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000, + 0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000, + 0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000, + 0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000, + 0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000, + 0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000, + 0x933d017400000000, 0xd506661100000000, 0x46a022f000000000, + 0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000, + 0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000, + 0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000, + 0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000, + 0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000, + 0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000, + 0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000, + 0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000, + 0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000, + 0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000, + 0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000, + 0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000, + 0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000, + 0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000, + 0x356bacd800000000}, + {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000, + 0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000, + 0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000, + 0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000, + 0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000, + 0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000, + 0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000, + 0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000, + 0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000, + 0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000, + 0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000, + 0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000, + 0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000, + 0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000, + 0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000, + 0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000, + 0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000, + 0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000, + 0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000, + 0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000, + 0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000, + 0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000, + 0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000, + 0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000, + 0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000, + 0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000, + 0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000, + 0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000, + 0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000, + 0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000, + 0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000, + 0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000, + 0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000, + 0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000, + 0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000, + 0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000, + 0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000, + 0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000, + 0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000, + 0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000, + 0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000, + 0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000, + 0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000, + 0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000, + 0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000, + 0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000, + 0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000, + 0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000, + 0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000, + 0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000, + 0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000, + 0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000, + 0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000, + 0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000, + 0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000, + 0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000, + 0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000, + 0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000, + 0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000, + 0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000, + 0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000, + 0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000, + 0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000, + 0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000, + 0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000, + 0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000, + 0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000, + 0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000, + 0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000, + 0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000, + 0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000, + 0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000, + 0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000, + 0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000, + 0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000, + 0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000, + 0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000, + 0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000, + 0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000, + 0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000, + 0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000, + 0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000, + 0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000, + 0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000, + 0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000, + 0x48686b5600000000}, + {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000, + 0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000, + 0x805af17200000000, 0x403ed96500000000, 0x002643b900000000, + 0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000, + 0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000, + 0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000, + 0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000, + 0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000, + 0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000, + 0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000, + 0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000, + 0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000, + 0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000, + 0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000, + 0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000, + 0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000, + 0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000, + 0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000, + 0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000, + 0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000, + 0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000, + 0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000, + 0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000, + 0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000, + 0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000, + 0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000, + 0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000, + 0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000, + 0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000, + 0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000, + 0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000, + 0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000, + 0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000, + 0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000, + 0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000, + 0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000, + 0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000, + 0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000, + 0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000, + 0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000, + 0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000, + 0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000, + 0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000, + 0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000, + 0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000, + 0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000, + 0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000, + 0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000, + 0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000, + 0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000, + 0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000, + 0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000, + 0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000, + 0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000, + 0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000, + 0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000, + 0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000, + 0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000, + 0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000, + 0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000, + 0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000, + 0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000, + 0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000, + 0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000, + 0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000, + 0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000, + 0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000, + 0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000, + 0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000, + 0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000, + 0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000, + 0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000, + 0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000, + 0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000, + 0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000, + 0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000, + 0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000, + 0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000, + 0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000, + 0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000, + 0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000, + 0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000, + 0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000, + 0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000, + 0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000, + 0xcaa2517800000000}, + {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000, + 0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000, + 0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000, + 0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000, + 0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000, + 0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000, + 0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000, + 0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000, + 0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000, + 0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000, + 0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000, + 0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000, + 0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000, + 0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000, + 0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000, + 0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000, + 0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000, + 0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000, + 0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000, + 0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000, + 0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000, + 0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000, + 0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000, + 0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000, + 0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000, + 0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000, + 0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000, + 0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000, + 0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000, + 0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000, + 0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000, + 0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000, + 0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000, + 0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000, + 0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000, + 0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000, + 0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000, + 0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000, + 0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000, + 0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000, + 0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000, + 0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000, + 0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000, + 0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000, + 0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000, + 0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000, + 0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000, + 0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000, + 0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000, + 0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000, + 0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000, + 0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000, + 0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000, + 0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000, + 0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000, + 0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000, + 0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000, + 0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000, + 0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000, + 0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000, + 0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000, + 0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000, + 0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000, + 0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000, + 0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000, + 0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000, + 0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000, + 0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000, + 0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000, + 0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000, + 0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000, + 0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000, + 0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000, + 0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000, + 0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000, + 0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000, + 0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000, + 0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000, + 0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000, + 0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000, + 0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000, + 0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000, + 0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000, + 0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000, + 0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000, + 0x0c7ac97b00000000}, + {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000, + 0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000, + 0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000, + 0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000, + 0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000, + 0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000, + 0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000, + 0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000, + 0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000, + 0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000, + 0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000, + 0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000, + 0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000, + 0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000, + 0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000, + 0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000, + 0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000, + 0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000, + 0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000, + 0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000, + 0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000, + 0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000, + 0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000, + 0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000, + 0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000, + 0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000, + 0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000, + 0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000, + 0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000, + 0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000, + 0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000, + 0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000, + 0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000, + 0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000, + 0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000, + 0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000, + 0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000, + 0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000, + 0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000, + 0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000, + 0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000, + 0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000, + 0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000, + 0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000, + 0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000, + 0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000, + 0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000, + 0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000, + 0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000, + 0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000, + 0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000, + 0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000, + 0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000, + 0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000, + 0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000, + 0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000, + 0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000, + 0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000, + 0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000, + 0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000, + 0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000, + 0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000, + 0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000, + 0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000, + 0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000, + 0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000, + 0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000, + 0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000, + 0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000, + 0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000, + 0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000, + 0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000, + 0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000, + 0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000, + 0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000, + 0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000, + 0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000, + 0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000, + 0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000, + 0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000, + 0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000, + 0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000, + 0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000, + 0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000, + 0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000, + 0x5185cd0900000000}}; + +#else /* W == 4 */ + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f, + 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91, + 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e, + 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c, + 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02, + 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12, + 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567, + 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277, + 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679, + 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b, + 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4, + 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a, + 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0, + 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0, + 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91, + 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881, + 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173, + 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d, + 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912, + 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8, + 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6, + 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6, + 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b, + 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b, + 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75, + 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f, + 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00, + 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee, + 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c, + 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c, + 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d, + 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d, + 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67, + 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89, + 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706, + 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14, + 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a, + 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a, + 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f, + 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f, + 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591, + 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983, + 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c, + 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2, + 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8, + 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8, + 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89, + 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99, + 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b, + 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485, + 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a, + 0x36197165}, + {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382, + 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85, + 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06, + 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca, + 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e, + 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc, + 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616, + 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54, + 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10, + 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc, + 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f, + 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58, + 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef, + 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad, + 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b, + 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29, + 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6, + 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1, + 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622, + 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039, + 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d, + 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f, + 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32, + 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770, + 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034, + 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f, + 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc, + 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db, + 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154, + 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16, + 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0, + 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592, + 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca, + 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd, + 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e, + 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882, + 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6, + 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384, + 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1, + 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3, + 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7, + 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b, + 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8, + 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff, + 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7, + 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5, + 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23, + 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761, + 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee, + 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9, + 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a, + 0x1a3b93aa}, + {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a, + 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca, + 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3, + 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb, + 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c, + 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58, + 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed, + 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9, + 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e, + 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906, + 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f, + 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf, + 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0, + 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4, + 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769, + 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d, + 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632, + 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82, + 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb, + 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73, + 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484, + 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0, + 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5, + 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1, + 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516, + 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f, + 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946, + 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6, + 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9, + 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad, + 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820, + 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364, + 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab, + 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b, + 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62, + 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a, + 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd, + 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089, + 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c, + 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8, + 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f, + 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477, + 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e, + 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be, + 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71, + 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635, + 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8, + 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc, + 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3, + 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753, + 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a, + 0xe147d714}, + {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c, + 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b, + 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92, + 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4, + 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069, + 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526, + 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25, + 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a, + 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7, + 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491, + 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958, + 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f, + 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307, + 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648, + 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999, + 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6, + 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a, + 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d, + 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4, + 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61, + 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc, + 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3, + 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53, + 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c, + 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1, + 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c, + 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5, + 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92, + 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e, + 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771, + 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0, + 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def, + 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0, + 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7, + 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e, + 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58, + 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285, + 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca, + 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce, + 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81, + 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c, + 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a, + 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3, + 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4, + 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb, + 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4, + 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75, + 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a, + 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296, + 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1, + 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808, + 0x494f0c4b}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d, + 0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac, + 0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8, + 0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95, + 0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817, + 0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d, + 0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac, + 0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6, + 0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564, + 0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39, + 0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d, + 0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac, + 0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de, + 0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594, + 0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b, + 0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01, + 0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f, + 0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de, + 0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba, + 0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65, + 0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7, + 0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad, + 0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de, + 0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294, + 0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716, + 0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71, + 0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15, + 0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4, + 0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca, + 0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280, + 0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f, + 0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15, + 0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9, + 0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748, + 0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c, + 0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971, + 0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3, + 0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9, + 0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196, + 0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc, + 0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e, + 0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03, + 0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67, + 0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296, + 0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a, + 0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170, + 0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af, + 0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5, + 0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb, + 0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a, + 0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e, + 0x4b0c4f49}, + {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09, + 0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc, + 0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e, + 0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc, + 0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934, + 0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2, + 0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b, + 0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad, + 0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155, + 0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187, + 0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65, + 0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390, + 0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e, + 0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378, + 0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889, + 0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f, + 0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0, + 0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145, + 0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7, + 0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a, + 0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2, + 0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924, + 0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2, + 0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514, + 0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec, + 0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709, + 0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb, + 0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e, + 0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1, + 0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227, + 0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6, + 0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030, + 0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0, + 0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55, + 0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7, + 0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165, + 0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d, + 0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b, + 0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c, + 0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a, + 0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362, + 0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0, + 0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52, + 0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7, + 0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237, + 0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1, + 0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020, + 0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6, + 0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719, + 0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec, + 0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e, + 0x14d747e1}, + {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0, + 0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b, + 0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652, + 0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437, + 0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514, + 0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265, + 0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de, + 0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af, + 0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c, + 0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9, + 0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0, + 0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b, + 0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6, + 0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7, + 0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734, + 0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045, + 0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8, + 0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303, + 0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a, + 0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9, + 0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea, + 0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b, + 0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6, + 0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7, + 0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4, + 0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6, + 0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f, + 0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054, + 0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9, + 0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8, + 0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b, + 0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a, + 0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441, + 0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a, + 0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3, + 0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6, + 0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5, + 0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94, + 0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9, + 0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288, + 0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab, + 0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce, + 0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7, + 0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c, + 0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527, + 0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256, + 0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5, + 0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4, + 0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39, + 0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2, + 0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db, + 0xaa933b1a}, + {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603, + 0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d, + 0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9, + 0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b, + 0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a, + 0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792, + 0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4, + 0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c, + 0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d, + 0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f, + 0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb, + 0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65, + 0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330, + 0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8, + 0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da, + 0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742, + 0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f, + 0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1, + 0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5, + 0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f, + 0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e, + 0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6, + 0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8, + 0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250, + 0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021, + 0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb, + 0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f, + 0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511, + 0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c, + 0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4, + 0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886, + 0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e, + 0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b, + 0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5, + 0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791, + 0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003, + 0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272, + 0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea, + 0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc, + 0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24, + 0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55, + 0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7, + 0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3, + 0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d, + 0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548, + 0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0, + 0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2, + 0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a, + 0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47, + 0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9, + 0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad, + 0x65711936}}; + +#endif /* W */ + +#endif /* N == 3 */ +#if N == 4 + +#if W == 8 + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a, + 0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe, + 0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b, + 0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656, + 0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd, + 0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d, + 0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7, + 0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47, + 0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac, + 0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691, + 0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404, + 0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0, + 0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4, + 0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424, + 0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5, + 0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65, + 0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67, + 0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3, + 0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626, + 0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9, + 0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222, + 0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2, + 0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a, + 0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a, + 0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1, + 0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2, + 0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077, + 0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3, + 0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1, + 0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621, + 0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0, + 0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60, + 0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0, + 0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64, + 0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1, + 0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc, + 0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027, + 0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7, + 0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9, + 0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79, + 0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292, + 0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af, + 0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a, + 0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee, + 0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e, + 0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe, + 0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f, + 0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff, + 0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd, + 0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29, + 0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc, + 0xe3c45916}, + {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344, + 0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59, + 0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e, + 0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463, + 0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98, + 0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d, + 0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3, + 0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656, + 0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad, + 0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0, + 0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397, + 0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a, + 0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2, + 0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357, + 0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8, + 0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d, + 0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696, + 0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b, + 0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc, + 0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0, + 0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b, + 0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be, + 0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811, + 0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384, + 0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f, + 0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955, + 0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362, + 0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f, + 0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94, + 0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701, + 0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe, + 0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b, + 0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1, + 0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc, + 0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b, + 0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986, + 0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d, + 0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8, + 0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4, + 0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371, + 0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a, + 0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87, + 0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0, + 0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad, + 0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527, + 0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2, + 0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d, + 0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998, + 0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73, + 0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e, + 0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59, + 0xa7520488}, + {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20, + 0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09, + 0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431, + 0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a, + 0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203, + 0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b, + 0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14, + 0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c, + 0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25, + 0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e, + 0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36, + 0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f, + 0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649, + 0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961, + 0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58, + 0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170, + 0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b, + 0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742, + 0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a, + 0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55, + 0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c, + 0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64, + 0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f, + 0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77, + 0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e, + 0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a, + 0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2, + 0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b, + 0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090, + 0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8, + 0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881, + 0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9, + 0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6, + 0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f, + 0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7, + 0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c, + 0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695, + 0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd, + 0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb, + 0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3, + 0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa, + 0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1, + 0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9, + 0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0, + 0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df, + 0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7, + 0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace, + 0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6, + 0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd, + 0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4, + 0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec, + 0x3522e9e4}, + {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1, + 0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86, + 0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b, + 0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669, + 0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7, + 0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352, + 0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03, + 0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6, + 0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38, + 0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a, + 0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7, + 0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80, + 0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7, + 0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522, + 0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d, + 0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8, + 0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103, + 0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54, + 0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9, + 0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0, + 0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e, + 0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb, + 0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1, + 0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624, + 0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea, + 0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a, + 0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37, + 0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360, + 0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab, + 0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e, + 0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741, + 0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4, + 0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334, + 0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63, + 0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de, + 0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c, + 0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942, + 0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7, + 0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131, + 0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4, + 0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a, + 0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758, + 0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5, + 0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2, + 0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32, + 0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7, + 0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8, + 0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d, + 0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6, + 0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1, + 0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c, + 0x97411e28}, + {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474, + 0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5, + 0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6, + 0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7, + 0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938, + 0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051, + 0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a, + 0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3, + 0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c, + 0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d, + 0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e, + 0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf, + 0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740, + 0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29, + 0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592, + 0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb, + 0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4, + 0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365, + 0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036, + 0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7, + 0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08, + 0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561, + 0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a, + 0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663, + 0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac, + 0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d, + 0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce, + 0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f, + 0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50, + 0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639, + 0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82, + 0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb, + 0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954, + 0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5, + 0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86, + 0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7, + 0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418, + 0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71, + 0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa, + 0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93, + 0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c, + 0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d, + 0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e, + 0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df, + 0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60, + 0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309, + 0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2, + 0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db, + 0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4, + 0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45, + 0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16, + 0x93c7a00b}, + {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45, + 0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb, + 0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d, + 0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696, + 0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf, + 0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb, + 0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028, + 0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c, + 0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65, + 0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be, + 0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038, + 0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6, + 0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15, + 0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11, + 0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d, + 0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19, + 0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05, + 0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b, + 0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d, + 0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c, + 0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35, + 0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31, + 0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068, + 0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c, + 0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25, + 0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a, + 0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac, + 0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22, + 0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e, + 0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a, + 0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36, + 0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32, + 0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84, + 0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a, + 0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c, + 0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057, + 0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e, + 0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a, + 0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc, + 0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8, + 0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1, + 0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a, + 0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec, + 0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62, + 0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4, + 0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0, + 0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc, + 0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8, + 0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4, + 0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a, + 0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc, + 0xce5f968d}, + {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de, + 0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b, + 0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d, + 0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680, + 0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4, + 0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d, + 0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde, + 0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97, + 0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3, + 0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e, + 0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678, + 0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d, + 0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723, + 0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a, + 0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0, + 0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9, + 0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85, + 0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770, + 0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56, + 0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a, + 0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e, + 0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67, + 0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785, + 0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc, + 0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788, + 0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90, + 0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6, + 0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843, + 0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f, + 0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336, + 0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac, + 0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5, + 0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68, + 0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d, + 0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb, + 0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36, + 0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72, + 0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b, + 0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b, + 0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402, + 0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446, + 0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb, + 0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed, + 0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418, + 0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95, + 0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc, + 0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946, + 0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f, + 0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233, + 0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6, + 0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0, + 0x3e721277}, + {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb, + 0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9, + 0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11, + 0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d, + 0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9, + 0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c, + 0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881, + 0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274, + 0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790, + 0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc, + 0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514, + 0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56, + 0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9, + 0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c, + 0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13, + 0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6, + 0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c, + 0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e, + 0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386, + 0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376, + 0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692, + 0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67, + 0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416, + 0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3, + 0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07, + 0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd, + 0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15, + 0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457, + 0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd, + 0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28, + 0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337, + 0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2, + 0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594, + 0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6, + 0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e, + 0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52, + 0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6, + 0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143, + 0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17, + 0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2, + 0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306, + 0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a, + 0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182, + 0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0, + 0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496, + 0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63, + 0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c, + 0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89, + 0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903, + 0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041, + 0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9, + 0x1c65ace7}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000, + 0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000, + 0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000, + 0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000, + 0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000, + 0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000, + 0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000, + 0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000, + 0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000, + 0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000, + 0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000, + 0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000, + 0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000, + 0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000, + 0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000, + 0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000, + 0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000, + 0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000, + 0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000, + 0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000, + 0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000, + 0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000, + 0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000, + 0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000, + 0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000, + 0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000, + 0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000, + 0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000, + 0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000, + 0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000, + 0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000, + 0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000, + 0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000, + 0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000, + 0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000, + 0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000, + 0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000, + 0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000, + 0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000, + 0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000, + 0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000, + 0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000, + 0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000, + 0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000, + 0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000, + 0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000, + 0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000, + 0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000, + 0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000, + 0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000, + 0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000, + 0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000, + 0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000, + 0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000, + 0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000, + 0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000, + 0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000, + 0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000, + 0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000, + 0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000, + 0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000, + 0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000, + 0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000, + 0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000, + 0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000, + 0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000, + 0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000, + 0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000, + 0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000, + 0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000, + 0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000, + 0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000, + 0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000, + 0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000, + 0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000, + 0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000, + 0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000, + 0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000, + 0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000, + 0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000, + 0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000, + 0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000, + 0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000, + 0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000, + 0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000, + 0xe7ac651c00000000}, + {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000, + 0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000, + 0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000, + 0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000, + 0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000, + 0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000, + 0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000, + 0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000, + 0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000, + 0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000, + 0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000, + 0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000, + 0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000, + 0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000, + 0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000, + 0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000, + 0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000, + 0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000, + 0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000, + 0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000, + 0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000, + 0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000, + 0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000, + 0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000, + 0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000, + 0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000, + 0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000, + 0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000, + 0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000, + 0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000, + 0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000, + 0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000, + 0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000, + 0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000, + 0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000, + 0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000, + 0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000, + 0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000, + 0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000, + 0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000, + 0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000, + 0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000, + 0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000, + 0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000, + 0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000, + 0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000, + 0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000, + 0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000, + 0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000, + 0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000, + 0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000, + 0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000, + 0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000, + 0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000, + 0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000, + 0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000, + 0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000, + 0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000, + 0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000, + 0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000, + 0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000, + 0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000, + 0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000, + 0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000, + 0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000, + 0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000, + 0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000, + 0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000, + 0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000, + 0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000, + 0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000, + 0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000, + 0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000, + 0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000, + 0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000, + 0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000, + 0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000, + 0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000, + 0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000, + 0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000, + 0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000, + 0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000, + 0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000, + 0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000, + 0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000, + 0x7712723e00000000}, + {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000, + 0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000, + 0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000, + 0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000, + 0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000, + 0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000, + 0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000, + 0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000, + 0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000, + 0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000, + 0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000, + 0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000, + 0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000, + 0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000, + 0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000, + 0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000, + 0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000, + 0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000, + 0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000, + 0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000, + 0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000, + 0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000, + 0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000, + 0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000, + 0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000, + 0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000, + 0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000, + 0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000, + 0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000, + 0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000, + 0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000, + 0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000, + 0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000, + 0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000, + 0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000, + 0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000, + 0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000, + 0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000, + 0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000, + 0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000, + 0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000, + 0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000, + 0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000, + 0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000, + 0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000, + 0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000, + 0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000, + 0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000, + 0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000, + 0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000, + 0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000, + 0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000, + 0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000, + 0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000, + 0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000, + 0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000, + 0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000, + 0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000, + 0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000, + 0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000, + 0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000, + 0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000, + 0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000, + 0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000, + 0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000, + 0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000, + 0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000, + 0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000, + 0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000, + 0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000, + 0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000, + 0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000, + 0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000, + 0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000, + 0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000, + 0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000, + 0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000, + 0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000, + 0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000, + 0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000, + 0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000, + 0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000, + 0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000, + 0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000, + 0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000, + 0x8d965fce00000000}, + {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000, + 0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000, + 0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000, + 0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000, + 0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000, + 0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000, + 0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000, + 0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000, + 0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000, + 0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000, + 0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000, + 0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000, + 0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000, + 0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000, + 0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000, + 0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000, + 0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000, + 0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000, + 0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000, + 0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000, + 0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000, + 0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000, + 0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000, + 0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000, + 0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000, + 0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000, + 0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000, + 0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000, + 0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000, + 0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000, + 0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000, + 0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000, + 0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000, + 0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000, + 0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000, + 0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000, + 0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000, + 0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000, + 0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000, + 0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000, + 0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000, + 0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000, + 0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000, + 0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000, + 0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000, + 0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000, + 0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000, + 0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000, + 0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000, + 0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000, + 0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000, + 0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000, + 0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000, + 0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000, + 0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000, + 0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000, + 0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000, + 0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000, + 0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000, + 0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000, + 0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000, + 0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000, + 0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000, + 0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000, + 0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000, + 0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000, + 0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000, + 0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000, + 0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000, + 0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000, + 0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000, + 0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000, + 0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000, + 0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000, + 0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000, + 0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000, + 0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000, + 0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000, + 0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000, + 0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000, + 0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000, + 0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000, + 0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000, + 0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000, + 0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000, + 0x0ba0c79300000000}, + {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000, + 0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000, + 0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000, + 0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000, + 0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000, + 0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000, + 0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000, + 0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000, + 0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000, + 0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000, + 0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000, + 0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000, + 0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000, + 0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000, + 0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000, + 0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000, + 0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000, + 0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000, + 0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000, + 0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000, + 0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000, + 0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000, + 0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000, + 0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000, + 0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000, + 0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000, + 0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000, + 0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000, + 0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000, + 0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000, + 0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000, + 0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000, + 0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000, + 0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000, + 0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000, + 0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000, + 0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000, + 0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000, + 0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000, + 0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000, + 0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000, + 0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000, + 0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000, + 0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000, + 0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000, + 0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000, + 0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000, + 0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000, + 0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000, + 0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000, + 0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000, + 0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000, + 0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000, + 0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000, + 0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000, + 0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000, + 0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000, + 0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000, + 0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000, + 0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000, + 0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000, + 0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000, + 0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000, + 0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000, + 0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000, + 0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000, + 0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000, + 0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000, + 0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000, + 0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000, + 0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000, + 0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000, + 0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000, + 0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000, + 0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000, + 0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000, + 0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000, + 0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000, + 0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000, + 0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000, + 0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000, + 0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000, + 0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000, + 0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000, + 0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000, + 0x281e419700000000}, + {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000, + 0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000, + 0x304a428900000000, 0x38a922b500000000, 0x011e763800000000, + 0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000, + 0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000, + 0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000, + 0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000, + 0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000, + 0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000, + 0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000, + 0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000, + 0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000, + 0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000, + 0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000, + 0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000, + 0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000, + 0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000, + 0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000, + 0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000, + 0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000, + 0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000, + 0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000, + 0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000, + 0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000, + 0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000, + 0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000, + 0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000, + 0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000, + 0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000, + 0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000, + 0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000, + 0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000, + 0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000, + 0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000, + 0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000, + 0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000, + 0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000, + 0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000, + 0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000, + 0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000, + 0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000, + 0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000, + 0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000, + 0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000, + 0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000, + 0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000, + 0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000, + 0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000, + 0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000, + 0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000, + 0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000, + 0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000, + 0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000, + 0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000, + 0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000, + 0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000, + 0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000, + 0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000, + 0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000, + 0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000, + 0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000, + 0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000, + 0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000, + 0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000, + 0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000, + 0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000, + 0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000, + 0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000, + 0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000, + 0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000, + 0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000, + 0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000, + 0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000, + 0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000, + 0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000, + 0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000, + 0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000, + 0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000, + 0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000, + 0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000, + 0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000, + 0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000, + 0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000, + 0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000, + 0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000, + 0xe4e9223500000000}, + {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000, + 0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000, + 0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000, + 0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000, + 0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000, + 0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000, + 0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000, + 0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000, + 0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000, + 0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000, + 0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000, + 0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000, + 0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000, + 0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000, + 0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000, + 0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000, + 0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000, + 0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000, + 0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000, + 0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000, + 0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000, + 0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000, + 0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000, + 0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000, + 0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000, + 0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000, + 0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000, + 0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000, + 0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000, + 0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000, + 0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000, + 0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000, + 0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000, + 0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000, + 0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000, + 0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000, + 0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000, + 0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000, + 0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000, + 0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000, + 0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000, + 0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000, + 0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000, + 0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000, + 0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000, + 0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000, + 0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000, + 0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000, + 0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000, + 0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000, + 0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000, + 0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000, + 0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000, + 0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000, + 0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000, + 0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000, + 0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000, + 0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000, + 0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000, + 0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000, + 0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000, + 0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000, + 0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000, + 0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000, + 0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000, + 0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000, + 0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000, + 0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000, + 0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000, + 0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000, + 0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000, + 0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000, + 0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000, + 0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000, + 0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000, + 0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000, + 0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000, + 0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000, + 0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000, + 0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000, + 0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000, + 0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000, + 0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000, + 0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000, + 0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000, + 0x880452a700000000}, + {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000, + 0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000, + 0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000, + 0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000, + 0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000, + 0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000, + 0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000, + 0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000, + 0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000, + 0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000, + 0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000, + 0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000, + 0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000, + 0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000, + 0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000, + 0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000, + 0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000, + 0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000, + 0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000, + 0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000, + 0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000, + 0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000, + 0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000, + 0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000, + 0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000, + 0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000, + 0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000, + 0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000, + 0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000, + 0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000, + 0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000, + 0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000, + 0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000, + 0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000, + 0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000, + 0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000, + 0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000, + 0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000, + 0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000, + 0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000, + 0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000, + 0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000, + 0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000, + 0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000, + 0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000, + 0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000, + 0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000, + 0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000, + 0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000, + 0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000, + 0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000, + 0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000, + 0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000, + 0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000, + 0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000, + 0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000, + 0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000, + 0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000, + 0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000, + 0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000, + 0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000, + 0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000, + 0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000, + 0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000, + 0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000, + 0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000, + 0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000, + 0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000, + 0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000, + 0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000, + 0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000, + 0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000, + 0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000, + 0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000, + 0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000, + 0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000, + 0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000, + 0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000, + 0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000, + 0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000, + 0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000, + 0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000, + 0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000, + 0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000, + 0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000, + 0x1659c4e300000000}}; + +#else /* W == 4 */ + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87, + 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede, + 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab, + 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c, + 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1, + 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7, + 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e, + 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308, + 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5, + 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472, + 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07, + 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e, + 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa, + 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec, + 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6, + 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0, + 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3, + 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba, + 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf, + 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975, + 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8, + 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde, + 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a, + 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c, + 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1, + 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65, + 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410, + 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649, + 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a, + 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c, + 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946, + 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450, + 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e, + 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857, + 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022, + 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5, + 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758, + 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e, + 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d, + 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b, + 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6, + 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401, + 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74, + 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d, + 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073, + 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65, + 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f, + 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749, + 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a, + 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033, + 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846, + 0x0d7139d7}, + {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563, + 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f, + 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875, + 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536, + 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8, + 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43, + 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f, + 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184, + 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a, + 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39, + 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523, + 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f, + 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d, + 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6, + 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b, + 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0, + 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151, + 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d, + 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47, + 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a, + 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964, + 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef, + 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d, + 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6, + 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348, + 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53, + 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449, + 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645, + 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4, + 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f, + 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2, + 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69, + 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46, + 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a, + 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650, + 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13, + 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded, + 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366, + 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57, + 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc, + 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222, + 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61, + 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b, + 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277, + 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558, + 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3, + 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e, + 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5, + 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74, + 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78, + 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262, + 0x1c53e98a}, + {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b, + 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40, + 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580, + 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7, + 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a, + 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37, + 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75, + 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218, + 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5, + 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2, + 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02, + 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59, + 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1, + 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c, + 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a, + 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307, + 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486, + 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd, + 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d, + 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2, + 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f, + 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72, + 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8, + 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985, + 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268, + 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94, + 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454, + 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f, + 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e, + 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3, + 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915, + 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778, + 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821, + 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a, + 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba, + 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d, + 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560, + 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d, + 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe, + 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3, + 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e, + 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509, + 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9, + 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92, + 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb, + 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6, + 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50, + 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d, + 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc, + 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7, + 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927, + 0x3f88e851}, + {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96, + 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8, + 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0, + 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14, + 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7, + 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4, + 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe, + 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad, + 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e, + 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa, + 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2, + 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c, + 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab, + 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8, + 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d, + 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e, + 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7, + 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99, + 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1, + 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690, + 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933, + 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20, + 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf, + 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc, + 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f, + 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92, + 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca, + 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4, + 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd, + 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de, + 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb, + 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8, + 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474, + 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a, + 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252, + 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6, + 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55, + 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846, + 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7, + 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4, + 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47, + 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3, + 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb, + 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5, + 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49, + 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a, + 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f, + 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c, + 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305, + 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b, + 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523, + 0x3dee8ca6}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0, + 0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587, + 0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa, + 0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09, + 0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee, + 0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3, + 0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3, + 0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce, + 0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429, + 0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda, + 0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7, + 0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0, + 0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd, + 0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0, + 0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287, + 0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a, + 0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9, + 0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e, + 0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3, + 0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3, + 0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054, + 0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49, + 0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da, + 0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7, + 0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20, + 0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d, + 0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00, + 0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347, + 0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14, + 0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209, + 0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e, + 0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33, + 0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3, + 0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194, + 0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9, + 0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a, + 0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd, + 0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0, + 0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d, + 0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460, + 0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87, + 0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674, + 0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509, + 0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e, + 0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae, + 0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3, + 0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694, + 0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989, + 0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da, + 0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d, + 0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0, + 0xa68cee3d}, + {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19, + 0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae, + 0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb, + 0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a, + 0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55, + 0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1, + 0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c, + 0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8, + 0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7, + 0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936, + 0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453, + 0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4, + 0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941, + 0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5, + 0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93, + 0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17, + 0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e, + 0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89, + 0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec, + 0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0, + 0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf, + 0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b, + 0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b, + 0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f, + 0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0, + 0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e, + 0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b, + 0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc, + 0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5, + 0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261, + 0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637, + 0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3, + 0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57, + 0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0, + 0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85, + 0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454, + 0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b, + 0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f, + 0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423, + 0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7, + 0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8, + 0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739, + 0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c, + 0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb, + 0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f, + 0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b, + 0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd, + 0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59, + 0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070, + 0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7, + 0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2, + 0x51e8883f}, + {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a, + 0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276, + 0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed, + 0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55, + 0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b, + 0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8, + 0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320, + 0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413, + 0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd, + 0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75, + 0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee, + 0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312, + 0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca, + 0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9, + 0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad, + 0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e, + 0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504, + 0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8, + 0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63, + 0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353, + 0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d, + 0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be, + 0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae, + 0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d, + 0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943, + 0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7, + 0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c, + 0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390, + 0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a, + 0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239, + 0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d, + 0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e, + 0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c, + 0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0, + 0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b, + 0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93, + 0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d, + 0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e, + 0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c, + 0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f, + 0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1, + 0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579, + 0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2, + 0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e, + 0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c, + 0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f, + 0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b, + 0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158, + 0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2, + 0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e, + 0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5, + 0x8ae9531c}, + {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4, + 0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd, + 0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220, + 0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf, + 0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495, + 0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def, + 0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90, + 0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea, + 0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0, + 0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f, + 0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2, + 0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab, + 0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e, + 0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754, + 0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda, + 0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0, + 0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c, + 0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215, + 0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8, + 0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910, + 0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a, + 0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30, + 0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658, + 0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22, + 0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478, + 0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2, + 0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f, + 0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606, + 0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba, + 0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0, + 0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e, + 0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034, + 0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f, + 0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996, + 0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b, + 0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84, + 0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de, + 0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4, + 0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5, + 0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f, + 0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5, + 0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a, + 0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7, + 0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce, + 0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65, + 0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f, + 0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91, + 0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb, + 0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57, + 0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e, + 0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3, + 0xd739710d}}; + +#endif /* W */ + +#endif /* N == 4 */ +#if N == 5 + +#if W == 8 + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df, + 0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8, + 0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef, + 0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376, + 0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201, + 0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399, + 0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372, + 0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea, + 0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d, + 0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004, + 0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353, + 0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334, + 0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a, + 0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2, + 0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a, + 0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2, + 0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b, + 0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c, + 0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b, + 0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f, + 0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338, + 0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0, + 0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6, + 0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e, + 0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319, + 0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3, + 0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4, + 0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783, + 0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a, + 0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492, + 0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a, + 0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2, + 0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496, + 0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1, + 0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6, + 0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f, + 0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548, + 0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0, + 0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741, + 0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9, + 0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae, + 0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437, + 0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760, + 0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707, + 0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433, + 0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab, + 0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703, + 0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b, + 0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412, + 0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475, + 0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722, + 0xe9947565}, + {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5, + 0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22, + 0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c, + 0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed, + 0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d, + 0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1, + 0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e, + 0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32, + 0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142, + 0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93, + 0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d, + 0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a, + 0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58, + 0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14, + 0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81, + 0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd, + 0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab, + 0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c, + 0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72, + 0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f, + 0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff, + 0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3, + 0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30, + 0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c, + 0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c, + 0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558, + 0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146, + 0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581, + 0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7, + 0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab, + 0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e, + 0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272, + 0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838, + 0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff, + 0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1, + 0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330, + 0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840, + 0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c, + 0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb, + 0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7, + 0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7, + 0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616, + 0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208, + 0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf, + 0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85, + 0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9, + 0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c, + 0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10, + 0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76, + 0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1, + 0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf, + 0xf7d05006}, + {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b, + 0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774, + 0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58, + 0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a, + 0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb, + 0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952, + 0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e, + 0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7, + 0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746, + 0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14, + 0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338, + 0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907, + 0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777, + 0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de, + 0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064, + 0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd, + 0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951, + 0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e, + 0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42, + 0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b, + 0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a, + 0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3, + 0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904, + 0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad, + 0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c, + 0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d, + 0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861, + 0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e, + 0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2, + 0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b, + 0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1, + 0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78, + 0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f, + 0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40, + 0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c, + 0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e, + 0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf, + 0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166, + 0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d, + 0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4, + 0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805, + 0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157, + 0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b, + 0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644, + 0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43, + 0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea, + 0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850, + 0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9, + 0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165, + 0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a, + 0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676, + 0xb2075b94}, + {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf, + 0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61, + 0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be, + 0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd, + 0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3, + 0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063, + 0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105, + 0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5, + 0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb, + 0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8, + 0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07, + 0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9, + 0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5, + 0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515, + 0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4, + 0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014, + 0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7, + 0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269, + 0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6, + 0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af, + 0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1, + 0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111, + 0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d, + 0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad, + 0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3, + 0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75, + 0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa, + 0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74, + 0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7, + 0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477, + 0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6, + 0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176, + 0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af, + 0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71, + 0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae, + 0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd, + 0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3, + 0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073, + 0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0, + 0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400, + 0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e, + 0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d, + 0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2, + 0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c, + 0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5, + 0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505, + 0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4, + 0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004, + 0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7, + 0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279, + 0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6, + 0xba50bcb9}, + {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897, + 0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb, + 0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2, + 0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2, + 0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372, + 0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70, + 0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92, + 0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190, + 0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40, + 0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430, + 0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759, + 0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75, + 0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2, + 0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0, + 0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7, + 0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5, + 0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39, + 0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215, + 0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c, + 0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5, + 0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625, + 0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27, + 0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c, + 0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e, + 0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee, + 0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71, + 0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18, + 0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134, + 0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8, + 0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba, + 0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd, + 0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff, + 0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a, + 0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6, + 0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf, + 0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf, + 0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f, + 0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d, + 0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d, + 0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f, + 0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af, + 0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df, + 0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6, + 0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a, + 0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef, + 0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed, + 0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa, + 0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8, + 0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624, + 0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08, + 0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861, + 0x808abcf4}, + {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2, + 0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd, + 0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76, + 0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52, + 0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e, + 0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124, + 0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147, + 0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d, + 0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31, + 0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15, + 0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae, + 0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1, + 0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d, + 0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307, + 0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9, + 0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3, + 0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084, + 0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb, + 0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850, + 0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2, + 0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe, + 0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94, + 0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261, + 0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b, + 0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917, + 0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53, + 0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8, + 0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787, + 0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0, + 0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba, + 0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404, + 0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e, + 0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af, + 0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0, + 0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b, + 0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f, + 0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543, + 0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129, + 0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627, + 0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d, + 0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51, + 0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75, + 0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce, + 0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1, + 0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760, + 0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a, + 0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4, + 0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde, + 0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089, + 0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6, + 0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d, + 0xefdb3f95}, + {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8, + 0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7, + 0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945, + 0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9, + 0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652, + 0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc, + 0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a, + 0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4, + 0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f, + 0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3, + 0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51, + 0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e, + 0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c, + 0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362, + 0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11, + 0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff, + 0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7, + 0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8, + 0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a, + 0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690, + 0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b, + 0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5, + 0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05, + 0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb, + 0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740, + 0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f, + 0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded, + 0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2, + 0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa, + 0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714, + 0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67, + 0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89, + 0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7, + 0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8, + 0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a, + 0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6, + 0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d, + 0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3, + 0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9, + 0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57, + 0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc, + 0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540, + 0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2, + 0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd, + 0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93, + 0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d, + 0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e, + 0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0, + 0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8, + 0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7, + 0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75, + 0x0e2fbf43}, + {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc, + 0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a, + 0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3, + 0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7, + 0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b, + 0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154, + 0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3, + 0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc, + 0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330, + 0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264, + 0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd, + 0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b, + 0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a, + 0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175, + 0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275, + 0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a, + 0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234, + 0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2, + 0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b, + 0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a, + 0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6, + 0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189, + 0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b, + 0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204, + 0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8, + 0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226, + 0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff, + 0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219, + 0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167, + 0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258, + 0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158, + 0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267, + 0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c, + 0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da, + 0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003, + 0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157, + 0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b, + 0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4, + 0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179, + 0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246, + 0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a, + 0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de, + 0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107, + 0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1, + 0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba, + 0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285, + 0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185, + 0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba, + 0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4, + 0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322, + 0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb, + 0xf4377108}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000, + 0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000, + 0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000, + 0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000, + 0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000, + 0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000, + 0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000, + 0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000, + 0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000, + 0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000, + 0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000, + 0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000, + 0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000, + 0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000, + 0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000, + 0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000, + 0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000, + 0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000, + 0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000, + 0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000, + 0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000, + 0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000, + 0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000, + 0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000, + 0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000, + 0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000, + 0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000, + 0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000, + 0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000, + 0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000, + 0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000, + 0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000, + 0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000, + 0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000, + 0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000, + 0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000, + 0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000, + 0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000, + 0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000, + 0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000, + 0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000, + 0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000, + 0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000, + 0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000, + 0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000, + 0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000, + 0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000, + 0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000, + 0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000, + 0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000, + 0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000, + 0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000, + 0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000, + 0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000, + 0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000, + 0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000, + 0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000, + 0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000, + 0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000, + 0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000, + 0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000, + 0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000, + 0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000, + 0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000, + 0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000, + 0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000, + 0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000, + 0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000, + 0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000, + 0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000, + 0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000, + 0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000, + 0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000, + 0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000, + 0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000, + 0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000, + 0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000, + 0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000, + 0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000, + 0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000, + 0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000, + 0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000, + 0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000, + 0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000, + 0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000, + 0x087137f400000000}, + {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000, + 0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000, + 0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000, + 0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000, + 0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000, + 0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000, + 0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000, + 0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000, + 0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000, + 0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000, + 0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000, + 0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000, + 0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000, + 0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000, + 0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000, + 0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000, + 0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000, + 0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000, + 0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000, + 0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000, + 0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000, + 0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000, + 0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000, + 0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000, + 0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000, + 0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000, + 0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000, + 0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000, + 0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000, + 0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000, + 0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000, + 0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000, + 0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000, + 0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000, + 0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000, + 0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000, + 0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000, + 0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000, + 0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000, + 0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000, + 0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000, + 0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000, + 0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000, + 0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000, + 0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000, + 0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000, + 0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000, + 0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000, + 0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000, + 0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000, + 0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000, + 0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000, + 0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000, + 0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000, + 0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000, + 0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000, + 0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000, + 0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000, + 0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000, + 0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000, + 0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000, + 0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000, + 0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000, + 0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000, + 0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000, + 0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000, + 0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000, + 0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000, + 0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000, + 0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000, + 0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000, + 0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000, + 0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000, + 0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000, + 0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000, + 0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000, + 0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000, + 0x1129fad400000000, 0x621116d400000000, 0x544094f000000000, + 0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000, + 0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000, + 0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000, + 0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000, + 0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000, + 0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000, + 0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000, + 0x43bf2f0e00000000}, + {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000, + 0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000, + 0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000, + 0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000, + 0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000, + 0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000, + 0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000, + 0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000, + 0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000, + 0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000, + 0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000, + 0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000, + 0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000, + 0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000, + 0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000, + 0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000, + 0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000, + 0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000, + 0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000, + 0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000, + 0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000, + 0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000, + 0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000, + 0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000, + 0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000, + 0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000, + 0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000, + 0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000, + 0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000, + 0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000, + 0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000, + 0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000, + 0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000, + 0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000, + 0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000, + 0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000, + 0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000, + 0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000, + 0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000, + 0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000, + 0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000, + 0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000, + 0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000, + 0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000, + 0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000, + 0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000, + 0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000, + 0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000, + 0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000, + 0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000, + 0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000, + 0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000, + 0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000, + 0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000, + 0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000, + 0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000, + 0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000, + 0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000, + 0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000, + 0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000, + 0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000, + 0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000, + 0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000, + 0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000, + 0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000, + 0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000, + 0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000, + 0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000, + 0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000, + 0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000, + 0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000, + 0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000, + 0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000, + 0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000, + 0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000, + 0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000, + 0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000, + 0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000, + 0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000, + 0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000, + 0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000, + 0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000, + 0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000, + 0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000, + 0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000, + 0x953fdbef00000000}, + {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000, + 0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000, + 0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000, + 0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000, + 0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000, + 0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000, + 0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000, + 0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000, + 0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000, + 0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000, + 0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000, + 0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000, + 0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000, + 0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000, + 0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000, + 0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000, + 0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000, + 0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000, + 0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000, + 0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000, + 0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000, + 0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000, + 0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000, + 0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000, + 0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000, + 0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000, + 0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000, + 0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000, + 0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000, + 0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000, + 0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000, + 0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000, + 0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000, + 0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000, + 0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000, + 0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000, + 0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000, + 0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000, + 0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000, + 0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000, + 0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000, + 0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000, + 0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000, + 0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000, + 0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000, + 0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000, + 0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000, + 0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000, + 0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000, + 0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000, + 0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000, + 0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000, + 0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000, + 0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000, + 0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000, + 0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000, + 0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000, + 0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000, + 0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000, + 0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000, + 0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000, + 0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000, + 0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000, + 0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000, + 0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000, + 0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000, + 0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000, + 0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000, + 0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000, + 0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000, + 0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000, + 0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000, + 0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000, + 0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000, + 0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000, + 0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000, + 0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000, + 0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000, + 0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000, + 0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000, + 0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000, + 0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000, + 0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000, + 0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000, + 0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000, + 0xf4bc8a8000000000}, + {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000, + 0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000, + 0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000, + 0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000, + 0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000, + 0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000, + 0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000, + 0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000, + 0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000, + 0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000, + 0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000, + 0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000, + 0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000, + 0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000, + 0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000, + 0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000, + 0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000, + 0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000, + 0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000, + 0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000, + 0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000, + 0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000, + 0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000, + 0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000, + 0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000, + 0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000, + 0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000, + 0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000, + 0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000, + 0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000, + 0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000, + 0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000, + 0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000, + 0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000, + 0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000, + 0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000, + 0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000, + 0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000, + 0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000, + 0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000, + 0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000, + 0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000, + 0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000, + 0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000, + 0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000, + 0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000, + 0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000, + 0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000, + 0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000, + 0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000, + 0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000, + 0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000, + 0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000, + 0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000, + 0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000, + 0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000, + 0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000, + 0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000, + 0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000, + 0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000, + 0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000, + 0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000, + 0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000, + 0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000, + 0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000, + 0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000, + 0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000, + 0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000, + 0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000, + 0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000, + 0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000, + 0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000, + 0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000, + 0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000, + 0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000, + 0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000, + 0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000, + 0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000, + 0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000, + 0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000, + 0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000, + 0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000, + 0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000, + 0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000, + 0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000, + 0xb9bc50ba00000000}, + {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000, + 0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000, + 0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000, + 0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000, + 0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000, + 0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000, + 0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000, + 0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000, + 0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000, + 0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000, + 0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000, + 0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000, + 0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000, + 0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000, + 0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000, + 0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000, + 0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000, + 0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000, + 0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000, + 0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000, + 0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000, + 0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000, + 0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000, + 0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000, + 0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000, + 0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000, + 0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000, + 0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000, + 0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000, + 0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000, + 0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000, + 0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000, + 0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000, + 0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000, + 0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000, + 0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000, + 0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000, + 0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000, + 0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000, + 0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000, + 0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000, + 0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000, + 0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000, + 0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000, + 0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000, + 0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000, + 0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000, + 0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000, + 0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000, + 0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000, + 0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000, + 0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000, + 0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000, + 0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000, + 0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000, + 0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000, + 0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000, + 0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000, + 0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000, + 0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000, + 0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000, + 0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000, + 0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000, + 0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000, + 0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000, + 0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000, + 0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000, + 0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000, + 0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000, + 0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000, + 0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000, + 0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000, + 0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000, + 0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000, + 0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000, + 0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000, + 0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000, + 0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000, + 0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000, + 0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000, + 0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000, + 0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000, + 0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000, + 0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000, + 0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000, + 0x945b07b200000000}, + {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000, + 0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000, + 0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000, + 0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000, + 0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000, + 0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000, + 0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000, + 0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000, + 0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000, + 0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000, + 0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000, + 0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000, + 0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000, + 0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000, + 0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000, + 0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000, + 0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000, + 0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000, + 0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000, + 0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000, + 0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000, + 0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000, + 0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000, + 0x149f066100000000, 0xef839db200000000, 0x468814fc00000000, + 0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000, + 0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000, + 0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000, + 0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000, + 0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000, + 0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000, + 0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000, + 0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000, + 0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000, + 0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000, + 0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000, + 0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000, + 0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000, + 0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000, + 0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000, + 0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000, + 0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000, + 0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000, + 0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000, + 0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000, + 0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000, + 0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000, + 0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000, + 0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000, + 0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000, + 0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000, + 0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000, + 0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000, + 0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000, + 0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000, + 0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000, + 0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000, + 0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000, + 0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000, + 0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000, + 0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000, + 0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000, + 0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000, + 0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000, + 0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000, + 0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000, + 0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000, + 0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000, + 0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000, + 0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000, + 0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000, + 0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000, + 0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000, + 0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000, + 0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000, + 0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000, + 0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000, + 0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000, + 0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000, + 0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000, + 0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000, + 0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000, + 0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000, + 0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000, + 0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000, + 0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000, + 0x0650d0f700000000}, + {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000, + 0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000, + 0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000, + 0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000, + 0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000, + 0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000, + 0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000, + 0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000, + 0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000, + 0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000, + 0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000, + 0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000, + 0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000, + 0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000, + 0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000, + 0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000, + 0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000, + 0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000, + 0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000, + 0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000, + 0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000, + 0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000, + 0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000, + 0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000, + 0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000, + 0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000, + 0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000, + 0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000, + 0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000, + 0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000, + 0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000, + 0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000, + 0xc702c15700000000, 0x809085f800000000, 0x082039d200000000, + 0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000, + 0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000, + 0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000, + 0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000, + 0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000, + 0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000, + 0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000, + 0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000, + 0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000, + 0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000, + 0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000, + 0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000, + 0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000, + 0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000, + 0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000, + 0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000, + 0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000, + 0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000, + 0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000, + 0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000, + 0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000, + 0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000, + 0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000, + 0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000, + 0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000, + 0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000, + 0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000, + 0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000, + 0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000, + 0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000, + 0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000, + 0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000, + 0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000, + 0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000, + 0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000, + 0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000, + 0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000, + 0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000, + 0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000, + 0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000, + 0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000, + 0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000, + 0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000, + 0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000, + 0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000, + 0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000, + 0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000, + 0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000, + 0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000, + 0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000, + 0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000, + 0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000, + 0x657594e900000000}}; + +#else /* W == 4 */ + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59, + 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4, + 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67, + 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef, + 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97, + 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88, + 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687, + 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698, + 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0, + 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068, + 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb, + 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056, + 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016, + 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009, + 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028, + 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037, + 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a, + 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7, + 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054, + 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7, + 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af, + 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0, + 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4, + 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab, + 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3, + 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a, + 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9, + 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54, + 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09, + 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16, + 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37, + 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28, + 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e, + 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3, + 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40, + 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8, + 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0, + 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf, + 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6, + 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9, + 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1, + 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059, + 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca, + 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067, + 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031, + 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e, + 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f, + 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010, + 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d, + 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0, + 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073, + 0xd8ac6b35}, + {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2, + 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd, + 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696, + 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3, + 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f, + 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35, + 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5, + 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f, + 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673, + 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46, + 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d, + 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632, + 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28, + 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192, + 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c, + 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6, + 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0, + 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff, + 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4, + 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95, + 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9, + 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03, + 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7, + 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d, + 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151, + 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808, + 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343, + 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c, + 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a, + 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0, + 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e, + 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594, + 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6, + 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399, + 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2, + 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7, + 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb, + 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571, + 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289, + 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33, + 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f, + 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a, + 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461, + 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e, + 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c, + 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6, + 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918, + 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2, + 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484, + 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb, + 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0, + 0xa140efa8}, + {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706, + 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed, + 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289, + 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a, + 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214, + 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3, + 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3, + 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254, + 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a, + 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9, + 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad, + 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746, + 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060, + 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187, + 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef, + 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408, + 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e, + 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495, + 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1, + 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532, + 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c, + 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb, + 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb, + 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c, + 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42, + 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060, + 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04, + 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef, + 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99, + 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e, + 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16, + 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1, + 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7, + 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c, + 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38, + 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb, + 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5, + 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42, + 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62, + 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85, + 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb, + 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18, + 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c, + 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997, + 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1, + 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36, + 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e, + 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9, + 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf, + 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24, + 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040, + 0x917cd6a1}, + {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf, + 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd, + 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896, + 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9, + 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3, + 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f, + 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d, + 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1, + 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab, + 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4, + 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f, + 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d, + 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4, + 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978, + 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad, + 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621, + 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46, + 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854, + 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f, + 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a, + 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890, + 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c, + 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4, + 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238, + 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622, + 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab, + 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0, + 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2, + 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295, + 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19, + 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc, + 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140, + 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd, + 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf, + 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184, + 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb, + 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1, + 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d, + 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb, + 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257, + 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d, + 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22, + 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069, + 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b, + 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6, + 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a, + 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf, + 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33, + 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254, + 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146, + 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d, + 0x18ba364e}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873, + 0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661, + 0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441, + 0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44, + 0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1, + 0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05, + 0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa, + 0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e, + 0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb, + 0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be, + 0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e, + 0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c, + 0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d, + 0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9, + 0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f, + 0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b, + 0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39, + 0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b, + 0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b, + 0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20, + 0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595, + 0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61, + 0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0, + 0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644, + 0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1, + 0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d, + 0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d, + 0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f, + 0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad, + 0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359, + 0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f, + 0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b, + 0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7, + 0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5, + 0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5, + 0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0, + 0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65, + 0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091, + 0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633, + 0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7, + 0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272, + 0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77, + 0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57, + 0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145, + 0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9, + 0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d, + 0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb, + 0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f, + 0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad, + 0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf, + 0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f, + 0x4e36ba18}, + {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b, + 0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8, + 0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19, + 0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4, + 0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239, + 0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd, + 0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258, + 0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc, + 0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41, + 0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c, + 0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d, + 0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e, + 0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba, + 0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e, + 0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8, + 0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c, + 0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f, + 0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c, + 0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d, + 0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d, + 0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0, + 0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014, + 0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc, + 0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628, + 0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5, + 0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941, + 0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0, + 0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53, + 0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880, + 0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264, + 0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92, + 0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776, + 0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8, + 0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b, + 0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea, + 0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837, + 0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca, + 0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e, + 0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211, + 0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5, + 0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08, + 0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5, + 0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934, + 0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7, + 0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049, + 0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad, + 0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b, + 0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf, + 0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c, + 0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f, + 0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e, + 0xa1d67c91}, + {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9, + 0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de, + 0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94, + 0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0, + 0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a, + 0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924, + 0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052, + 0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c, + 0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6, + 0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2, + 0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8, + 0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f, + 0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d, + 0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273, + 0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30, + 0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e, + 0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7, + 0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980, + 0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca, + 0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8, + 0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62, + 0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c, + 0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c, + 0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032, + 0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798, + 0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d, + 0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07, + 0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630, + 0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389, + 0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7, + 0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4, + 0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca, + 0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55, + 0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662, + 0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828, + 0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c, + 0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6, + 0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98, + 0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3, + 0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d, + 0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037, + 0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913, + 0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759, + 0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e, + 0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1, + 0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf, + 0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c, + 0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2, + 0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b, + 0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c, + 0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276, + 0xa8ef40a1}, + {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e, + 0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8, + 0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819, + 0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f, + 0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d, + 0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756, + 0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0, + 0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb, + 0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9, + 0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f, + 0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e, + 0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8, + 0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835, + 0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e, + 0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62, + 0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749, + 0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b, + 0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d, + 0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc, + 0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80, + 0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2, + 0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599, + 0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05, + 0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e, + 0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c, + 0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e, + 0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef, + 0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359, + 0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b, + 0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0, + 0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc, + 0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7, + 0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f, + 0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189, + 0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568, + 0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e, + 0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c, + 0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27, + 0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794, + 0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf, + 0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d, + 0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db, + 0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a, + 0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c, + 0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544, + 0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f, + 0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013, + 0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38, + 0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea, + 0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c, + 0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd, + 0x356bacd8}}; + +#endif /* W */ + +#endif /* N == 5 */ +#if N == 6 + +#if W == 8 + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370, + 0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d, + 0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69, + 0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426, + 0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3, + 0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f, + 0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c, + 0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490, + 0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155, + 0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a, + 0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e, + 0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603, + 0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349, + 0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5, + 0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50, + 0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc, + 0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b, + 0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76, + 0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862, + 0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9, + 0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c, + 0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0, + 0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937, + 0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b, + 0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e, + 0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e, + 0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a, + 0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357, + 0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0, + 0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c, + 0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9, + 0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165, + 0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766, + 0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b, + 0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f, + 0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030, + 0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5, + 0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59, + 0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63, + 0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf, + 0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a, + 0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845, + 0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51, + 0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c, + 0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f, + 0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3, + 0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46, + 0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea, + 0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d, + 0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60, + 0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74, + 0x8568a0a8}, + {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5, + 0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf, + 0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5, + 0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba, + 0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf, + 0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f, + 0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0, + 0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450, + 0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55, + 0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a, + 0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620, + 0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a, + 0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454, + 0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4, + 0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534, + 0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584, + 0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694, + 0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e, + 0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4, + 0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1, + 0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4, + 0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164, + 0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1, + 0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911, + 0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314, + 0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c, + 0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6, + 0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec, + 0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc, + 0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c, + 0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c, + 0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c, + 0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716, + 0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c, + 0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676, + 0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879, + 0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c, + 0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc, + 0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77, + 0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7, + 0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2, + 0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd, + 0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7, + 0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad, + 0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897, + 0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827, + 0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7, + 0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947, + 0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57, + 0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d, + 0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37, + 0x0d907052}, + {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d, + 0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89, + 0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31, + 0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81, + 0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e, + 0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0, + 0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f, + 0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291, + 0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e, + 0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e, + 0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936, + 0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2, + 0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13, + 0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d, + 0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f, + 0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1, + 0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a, + 0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae, + 0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516, + 0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f, + 0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20, + 0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe, + 0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28, + 0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6, + 0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419, + 0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5, + 0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d, + 0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889, + 0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412, + 0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c, + 0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e, + 0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0, + 0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02, + 0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986, + 0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e, + 0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e, + 0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221, + 0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf, + 0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913, + 0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d, + 0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622, + 0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592, + 0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a, + 0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae, + 0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c, + 0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82, + 0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20, + 0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe, + 0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025, + 0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1, + 0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719, + 0xfd1a6c8a}, + {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3, + 0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb, + 0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d, + 0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb, + 0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9, + 0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156, + 0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045, + 0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa, + 0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8, + 0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e, + 0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8, + 0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0, + 0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38, + 0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87, + 0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46, + 0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9, + 0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585, + 0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d, + 0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb, + 0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531, + 0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03, + 0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc, + 0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33, + 0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c, + 0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be, + 0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d, + 0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b, + 0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303, + 0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f, + 0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0, + 0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801, + 0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe, + 0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e, + 0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346, + 0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620, + 0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776, + 0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844, + 0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb, + 0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0, + 0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f, + 0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d, + 0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b, + 0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d, + 0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75, + 0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795, + 0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a, + 0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb, + 0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354, + 0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28, + 0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30, + 0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856, + 0x7895f01a}, + {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188, + 0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33, + 0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d, + 0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445, + 0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2, + 0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058, + 0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43, + 0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9, + 0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e, + 0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06, + 0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228, + 0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93, + 0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e, + 0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4, + 0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b, + 0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371, + 0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265, + 0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede, + 0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0, + 0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f, + 0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8, + 0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32, + 0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae, + 0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544, + 0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3, + 0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f, + 0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911, + 0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa, + 0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be, + 0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54, + 0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b, + 0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1, + 0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652, + 0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9, + 0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7, + 0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f, + 0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68, + 0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782, + 0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797, + 0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d, + 0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a, + 0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2, + 0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc, + 0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647, + 0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4, + 0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e, + 0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41, + 0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab, + 0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf, + 0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904, + 0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a, + 0x9239b848}, + {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad, + 0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0, + 0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40, + 0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b, + 0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d, + 0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b, + 0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb, + 0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d, + 0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b, + 0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0, + 0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840, + 0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d, + 0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b, + 0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d, + 0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6, + 0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0, + 0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580, + 0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd, + 0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d, + 0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b, + 0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d, + 0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b, + 0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6, + 0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0, + 0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6, + 0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c, + 0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c, + 0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461, + 0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841, + 0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317, + 0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac, + 0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa, + 0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7, + 0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba, + 0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a, + 0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161, + 0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777, + 0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21, + 0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a, + 0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc, + 0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da, + 0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1, + 0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01, + 0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c, + 0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241, + 0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917, + 0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac, + 0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa, + 0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da, + 0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397, + 0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537, + 0xeb36d3cc}, + {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b, + 0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059, + 0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251, + 0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d, + 0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9, + 0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c, + 0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41, + 0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4, + 0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10, + 0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c, + 0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54, + 0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476, + 0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8, + 0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d, + 0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92, + 0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307, + 0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad, + 0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f, + 0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87, + 0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17, + 0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3, + 0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46, + 0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197, + 0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02, + 0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6, + 0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e, + 0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96, + 0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4, + 0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e, + 0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b, + 0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934, + 0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1, + 0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7, + 0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5, + 0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd, + 0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1, + 0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475, + 0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0, + 0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155, + 0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0, + 0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304, + 0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348, + 0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140, + 0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862, + 0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14, + 0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181, + 0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e, + 0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab, + 0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01, + 0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523, + 0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b, + 0x38e5f3c5}, + {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06, + 0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad, + 0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509, + 0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba, + 0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414, + 0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3, + 0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733, + 0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994, + 0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a, + 0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889, + 0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d, + 0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386, + 0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621, + 0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886, + 0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e, + 0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389, + 0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f, + 0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294, + 0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30, + 0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3, + 0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d, + 0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba, + 0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a, + 0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad, + 0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03, + 0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2, + 0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306, + 0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad, + 0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b, + 0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc, + 0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914, + 0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3, + 0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435, + 0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e, + 0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a, + 0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589, + 0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27, + 0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080, + 0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21, + 0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586, + 0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28, + 0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b, + 0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f, + 0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94, + 0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12, + 0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5, + 0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d, + 0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba, + 0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c, + 0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7, + 0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103, + 0x3d3101a2}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000, + 0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000, + 0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000, + 0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000, + 0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000, + 0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000, + 0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000, + 0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000, + 0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000, + 0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000, + 0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000, + 0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000, + 0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000, + 0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000, + 0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000, + 0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000, + 0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000, + 0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000, + 0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000, + 0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000, + 0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000, + 0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000, + 0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000, + 0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000, + 0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000, + 0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000, + 0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000, + 0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000, + 0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000, + 0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000, + 0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000, + 0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000, + 0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000, + 0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000, + 0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000, + 0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000, + 0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000, + 0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000, + 0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000, + 0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000, + 0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000, + 0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000, + 0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000, + 0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000, + 0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000, + 0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000, + 0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000, + 0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000, + 0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000, + 0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000, + 0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000, + 0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000, + 0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000, + 0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000, + 0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000, + 0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000, + 0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000, + 0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000, + 0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000, + 0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000, + 0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000, + 0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000, + 0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000, + 0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000, + 0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000, + 0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000, + 0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000, + 0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000, + 0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000, + 0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000, + 0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000, + 0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000, + 0x3688267d00000000, 0x9718319500000000, 0x35af787600000000, + 0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000, + 0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000, + 0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000, + 0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000, + 0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000, + 0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000, + 0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000, + 0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000, + 0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000, + 0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000, + 0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000, + 0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000, + 0xa201313d00000000}, + {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000, + 0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000, + 0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000, + 0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000, + 0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000, + 0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000, + 0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000, + 0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000, + 0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000, + 0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000, + 0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000, + 0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000, + 0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000, + 0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000, + 0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000, + 0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000, + 0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000, + 0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000, + 0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000, + 0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000, + 0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000, + 0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000, + 0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000, + 0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000, + 0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000, + 0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000, + 0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000, + 0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000, + 0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000, + 0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000, + 0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000, + 0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000, + 0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000, + 0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000, + 0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000, + 0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000, + 0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000, + 0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000, + 0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000, + 0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000, + 0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000, + 0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000, + 0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000, + 0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000, + 0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000, + 0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000, + 0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000, + 0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000, + 0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000, + 0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000, + 0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000, + 0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000, + 0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000, + 0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000, + 0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000, + 0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000, + 0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000, + 0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000, + 0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000, + 0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000, + 0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000, + 0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000, + 0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000, + 0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000, + 0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000, + 0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000, + 0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000, + 0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000, + 0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000, + 0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000, + 0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000, + 0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000, + 0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000, + 0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000, + 0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000, + 0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000, + 0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000, + 0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000, + 0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000, + 0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000, + 0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000, + 0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000, + 0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000, + 0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000, + 0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000, + 0xc5f3e53800000000}, + {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000, + 0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000, + 0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000, + 0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000, + 0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000, + 0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000, + 0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000, + 0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000, + 0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000, + 0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000, + 0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000, + 0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000, + 0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000, + 0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000, + 0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000, + 0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000, + 0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000, + 0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000, + 0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000, + 0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000, + 0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000, + 0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000, + 0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000, + 0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000, + 0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000, + 0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000, + 0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000, + 0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000, + 0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000, + 0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000, + 0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000, + 0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000, + 0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000, + 0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000, + 0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000, + 0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000, + 0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000, + 0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000, + 0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000, + 0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000, + 0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000, + 0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000, + 0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000, + 0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000, + 0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000, + 0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000, + 0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000, + 0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000, + 0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000, + 0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000, + 0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000, + 0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000, + 0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000, + 0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000, + 0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000, + 0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000, + 0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000, + 0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000, + 0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000, + 0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000, + 0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000, + 0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000, + 0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000, + 0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000, + 0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000, + 0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000, + 0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000, + 0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000, + 0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000, + 0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000, + 0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000, + 0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000, + 0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000, + 0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000, + 0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000, + 0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000, + 0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000, + 0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000, + 0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000, + 0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000, + 0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000, + 0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000, + 0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000, + 0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000, + 0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000, + 0xccd336eb00000000}, + {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000, + 0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000, + 0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000, + 0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000, + 0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000, + 0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000, + 0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000, + 0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000, + 0xb249204500000000, 0xd071086f00000000, 0x7639701100000000, + 0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000, + 0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000, + 0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000, + 0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000, + 0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000, + 0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000, + 0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000, + 0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000, + 0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000, + 0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000, + 0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000, + 0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000, + 0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000, + 0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000, + 0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000, + 0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000, + 0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000, + 0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000, + 0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000, + 0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000, + 0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000, + 0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000, + 0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000, + 0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000, + 0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000, + 0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000, + 0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000, + 0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000, + 0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000, + 0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000, + 0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000, + 0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000, + 0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000, + 0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000, + 0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000, + 0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000, + 0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000, + 0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000, + 0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000, + 0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000, + 0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000, + 0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000, + 0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000, + 0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000, + 0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000, + 0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000, + 0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000, + 0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000, + 0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000, + 0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000, + 0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000, + 0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000, + 0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000, + 0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000, + 0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000, + 0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000, + 0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000, + 0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000, + 0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000, + 0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000, + 0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000, + 0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000, + 0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000, + 0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000, + 0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000, + 0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000, + 0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000, + 0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000, + 0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000, + 0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000, + 0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000, + 0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000, + 0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000, + 0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000, + 0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000, + 0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000, + 0x48b8399200000000}, + {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000, + 0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000, + 0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000, + 0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000, + 0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000, + 0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000, + 0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000, + 0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000, + 0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000, + 0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000, + 0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000, + 0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000, + 0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000, + 0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000, + 0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000, + 0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000, + 0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000, + 0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000, + 0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000, + 0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000, + 0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000, + 0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000, + 0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000, + 0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000, + 0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000, + 0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000, + 0xb521428400000000, 0xf909d42700000000, 0x762efede00000000, + 0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000, + 0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000, + 0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000, + 0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000, + 0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000, + 0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000, + 0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000, + 0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000, + 0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000, + 0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000, + 0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000, + 0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000, + 0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000, + 0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000, + 0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000, + 0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000, + 0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000, + 0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000, + 0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000, + 0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000, + 0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000, + 0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000, + 0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000, + 0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000, + 0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000, + 0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000, + 0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000, + 0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000, + 0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000, + 0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000, + 0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000, + 0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000, + 0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000, + 0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000, + 0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000, + 0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000, + 0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000, + 0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000, + 0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000, + 0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000, + 0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000, + 0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000, + 0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000, + 0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000, + 0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000, + 0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000, + 0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000, + 0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000, + 0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000, + 0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000, + 0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000, + 0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000, + 0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000, + 0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000, + 0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000, + 0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000, + 0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000, + 0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000, + 0x1af0957800000000}, + {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000, + 0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000, + 0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000, + 0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000, + 0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000, + 0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000, + 0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000, + 0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000, + 0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000, + 0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000, + 0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000, + 0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000, + 0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000, + 0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000, + 0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000, + 0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000, + 0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000, + 0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000, + 0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000, + 0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000, + 0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000, + 0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000, + 0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000, + 0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000, + 0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000, + 0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000, + 0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000, + 0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000, + 0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000, + 0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000, + 0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000, + 0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000, + 0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000, + 0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000, + 0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000, + 0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000, + 0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000, + 0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000, + 0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000, + 0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000, + 0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000, + 0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000, + 0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000, + 0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000, + 0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000, + 0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000, + 0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000, + 0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000, + 0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000, + 0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000, + 0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000, + 0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000, + 0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000, + 0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000, + 0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000, + 0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000, + 0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000, + 0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000, + 0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000, + 0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000, + 0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000, + 0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000, + 0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000, + 0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000, + 0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000, + 0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000, + 0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000, + 0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000, + 0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000, + 0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000, + 0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000, + 0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000, + 0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000, + 0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000, + 0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000, + 0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000, + 0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000, + 0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000, + 0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000, + 0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000, + 0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000, + 0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000, + 0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000, + 0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000, + 0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000, + 0x8a6c1afd00000000}, + {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000, + 0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000, + 0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000, + 0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000, + 0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000, + 0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000, + 0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000, + 0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000, + 0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000, + 0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000, + 0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000, + 0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000, + 0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000, + 0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000, + 0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000, + 0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000, + 0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000, + 0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000, + 0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000, + 0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000, + 0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000, + 0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000, + 0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000, + 0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000, + 0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000, + 0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000, + 0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000, + 0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000, + 0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000, + 0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000, + 0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000, + 0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000, + 0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000, + 0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000, + 0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000, + 0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000, + 0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000, + 0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000, + 0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000, + 0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000, + 0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000, + 0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000, + 0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000, + 0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000, + 0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000, + 0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000, + 0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000, + 0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000, + 0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000, + 0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000, + 0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000, + 0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000, + 0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000, + 0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000, + 0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000, + 0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000, + 0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000, + 0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000, + 0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000, + 0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000, + 0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000, + 0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000, + 0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000, + 0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000, + 0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000, + 0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000, + 0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000, + 0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000, + 0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000, + 0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000, + 0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000, + 0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000, + 0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000, + 0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000, + 0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000, + 0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000, + 0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000, + 0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000, + 0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000, + 0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000, + 0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000, + 0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000, + 0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000, + 0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000, + 0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000, + 0x5270900d00000000}, + {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000, + 0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000, + 0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000, + 0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000, + 0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000, + 0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000, + 0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000, + 0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000, + 0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000, + 0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000, + 0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000, + 0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000, + 0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000, + 0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000, + 0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000, + 0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000, + 0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000, + 0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000, + 0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000, + 0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000, + 0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000, + 0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000, + 0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000, + 0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000, + 0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000, + 0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000, + 0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000, + 0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000, + 0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000, + 0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000, + 0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000, + 0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000, + 0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000, + 0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000, + 0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000, + 0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000, + 0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000, + 0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000, + 0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000, + 0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000, + 0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000, + 0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000, + 0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000, + 0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000, + 0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000, + 0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000, + 0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000, + 0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000, + 0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000, + 0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000, + 0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000, + 0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000, + 0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000, + 0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000, + 0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000, + 0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000, + 0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000, + 0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000, + 0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000, + 0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000, + 0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000, + 0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000, + 0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000, + 0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000, + 0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000, + 0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000, + 0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000, + 0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000, + 0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000, + 0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000, + 0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000, + 0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000, + 0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000, + 0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000, + 0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000, + 0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000, + 0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000, + 0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000, + 0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000, + 0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000, + 0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000, + 0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000, + 0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000, + 0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000, + 0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000, + 0xa8a0688500000000}}; + +#else /* W == 4 */ + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f, + 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999, + 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee, + 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615, + 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383, + 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb, + 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275, + 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d, + 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b, + 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460, + 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317, + 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1, + 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5, + 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd, + 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04, + 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c, + 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7, + 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11, + 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66, + 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7, + 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871, + 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309, + 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd, + 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85, + 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913, + 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d, + 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a, + 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc, + 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57, + 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f, + 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6, + 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e, + 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f, + 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289, + 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe, + 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05, + 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893, + 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb, + 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0, + 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8, + 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e, + 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5, + 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2, + 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574, + 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5, + 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add, + 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114, + 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c, + 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7, + 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701, + 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076, + 0x09cd8551}, + {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193, + 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2, + 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c, + 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71, + 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a, + 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d, + 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71, + 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436, + 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d, + 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000, + 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae, + 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf, + 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930, + 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277, + 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff, + 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8, + 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef, + 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e, + 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20, + 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95, + 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e, + 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9, + 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d, + 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a, + 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151, + 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4, + 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a, + 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b, + 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c, + 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b, + 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3, + 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4, + 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b, + 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a, + 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4, + 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189, + 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92, + 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5, + 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9, + 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe, + 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5, + 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8, + 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66, + 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707, + 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8, + 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f, + 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707, + 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40, + 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017, + 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876, + 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8, + 0x7bc97a0c}, + {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300, + 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0, + 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80, + 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701, + 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41, + 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81, + 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43, + 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83, + 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3, + 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42, + 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202, + 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2, + 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7, + 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407, + 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47, + 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87, + 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86, + 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46, + 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506, + 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44, + 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704, + 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4, + 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5, + 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505, + 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45, + 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f, + 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f, + 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f, + 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e, + 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e, + 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e, + 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce, + 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c, + 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc, + 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c, + 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d, + 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d, + 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d, + 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88, + 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48, + 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708, + 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89, + 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9, + 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309, + 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb, + 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b, + 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b, + 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b, + 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a, + 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a, + 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a, + 0x7851a2ca}, + {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb, + 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8, + 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0, + 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f, + 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a, + 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf, + 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5, + 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380, + 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815, + 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa, + 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2, + 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1, + 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1, + 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4, + 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa, + 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df, + 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6, + 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5, + 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad, + 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca, + 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f, + 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a, + 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8, + 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d, + 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708, + 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d, + 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865, + 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636, + 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f, + 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a, + 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744, + 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061, + 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0, + 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293, + 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb, + 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874, + 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1, + 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4, + 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f, + 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a, + 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f, + 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120, + 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778, + 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b, + 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a, + 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af, + 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81, + 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4, + 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd, + 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e, + 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6, + 0x566b6848}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912, + 0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba, + 0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3, + 0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30, + 0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e, + 0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3, + 0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73, + 0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe, + 0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0, + 0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643, + 0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a, + 0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082, + 0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4, + 0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279, + 0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735, + 0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8, + 0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad, + 0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05, + 0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c, + 0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718, + 0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46, + 0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb, + 0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc, + 0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41, + 0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f, + 0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad, + 0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4, + 0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c, + 0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779, + 0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4, + 0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8, + 0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235, + 0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7, + 0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f, + 0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476, + 0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195, + 0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb, + 0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46, + 0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622, + 0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af, + 0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1, + 0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12, + 0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b, + 0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3, + 0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51, + 0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc, + 0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90, + 0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d, + 0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708, + 0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0, + 0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9, + 0x48686b56}, + {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c, + 0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae, + 0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb, + 0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90, + 0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410, + 0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b, + 0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6, + 0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed, + 0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d, + 0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036, + 0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953, + 0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1, + 0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca, + 0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781, + 0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d, + 0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416, + 0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f, + 0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd, + 0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8, + 0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b, + 0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb, + 0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0, + 0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5, + 0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e, + 0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e, + 0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558, + 0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d, + 0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf, + 0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6, + 0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad, + 0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971, + 0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a, + 0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b, + 0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969, + 0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c, + 0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57, + 0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7, + 0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c, + 0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab, + 0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0, + 0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160, + 0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b, + 0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e, + 0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac, + 0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d, + 0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546, + 0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a, + 0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1, + 0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8, + 0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a, + 0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f, + 0xcaa25178}, + {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00, + 0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b, + 0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed, + 0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777, + 0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01, + 0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a, + 0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef, + 0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74, + 0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002, + 0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498, + 0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee, + 0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75, + 0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05, + 0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e, + 0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8, + 0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73, + 0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404, + 0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f, + 0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9, + 0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71, + 0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607, + 0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c, + 0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb, + 0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470, + 0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806, + 0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790, + 0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6, + 0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d, + 0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a, + 0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991, + 0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7, + 0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c, + 0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09, + 0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92, + 0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4, + 0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e, + 0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08, + 0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593, + 0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3, + 0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778, + 0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e, + 0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94, + 0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2, + 0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079, + 0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c, + 0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497, + 0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1, + 0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a, + 0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d, + 0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396, + 0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0, + 0x0c7ac97b}, + {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669, + 0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853, + 0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062, + 0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527, + 0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad, + 0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545, + 0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27, + 0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf, + 0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45, + 0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800, + 0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031, + 0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b, + 0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26, + 0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce, + 0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d, + 0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5, + 0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130, + 0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a, + 0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b, + 0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480, + 0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a, + 0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2, + 0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e, + 0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996, + 0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c, + 0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc, + 0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd, + 0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7, + 0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232, + 0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da, + 0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439, + 0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1, + 0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da, + 0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0, + 0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1, + 0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94, + 0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e, + 0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6, + 0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2, + 0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a, + 0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0, + 0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95, + 0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4, + 0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e, + 0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395, + 0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d, + 0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e, + 0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676, + 0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83, + 0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9, + 0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888, + 0x5185cd09}}; + +#endif /* W */ + +#endif /* N == 6 */ + +static const uint32_t x2n_table[] = { + 0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000, + 0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467, + 0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0, + 0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169, + 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37, + 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a, + 0xc40ba6d0, 0xc4e22c3c}; + +#endif /* CRC32_BRAID_TBL_H_ */ diff --git a/3rdparty/zlib-ng/crc32_fold.c b/3rdparty/zlib-ng/crc32_fold.c new file mode 100644 index 000000000000..5b3c7c459fd3 --- /dev/null +++ b/3rdparty/zlib-ng/crc32_fold.c @@ -0,0 +1,33 @@ +/* crc32_fold.c -- crc32 folding interface + * Copyright (C) 2021 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ +#include "zbuild.h" +#include "functable.h" + +#include "crc32_fold.h" + +#include + +Z_INTERNAL uint32_t crc32_fold_reset_c(crc32_fold *crc) { + crc->value = CRC32_INITIAL_VALUE; + return crc->value; +} + +Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { + crc->value = functable.crc32(crc->value, src, len); + memcpy(dst, src, len); +} + +Z_INTERNAL void crc32_fold_c(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { + /* Note: while this is basically the same thing as the vanilla CRC function, we still need + * a functable entry for it so that we can generically dispatch to this function with the + * same arguments for the versions that _do_ do a folding CRC but we don't want a copy. The + * init_crc is an unused argument in this context */ + Z_UNUSED(init_crc); + crc->value = functable.crc32(crc->value, src, len); +} + +Z_INTERNAL uint32_t crc32_fold_final_c(crc32_fold *crc) { + return crc->value; +} diff --git a/3rdparty/zlib-ng/crc32_fold.h b/3rdparty/zlib-ng/crc32_fold.h new file mode 100644 index 000000000000..0d2ff66967de --- /dev/null +++ b/3rdparty/zlib-ng/crc32_fold.h @@ -0,0 +1,21 @@ +/* crc32_fold.h -- crc32 folding interface + * Copyright (C) 2021 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ +#ifndef CRC32_FOLD_H_ +#define CRC32_FOLD_H_ + +#define CRC32_FOLD_BUFFER_SIZE (16 * 4) +/* sizeof(__m128i) * (4 folds) */ + +typedef struct crc32_fold_s { + uint8_t fold[CRC32_FOLD_BUFFER_SIZE]; + uint32_t value; +} crc32_fold; + +Z_INTERNAL uint32_t crc32_fold_reset_c(crc32_fold *crc); +Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); +Z_INTERNAL void crc32_fold_c(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc); +Z_INTERNAL uint32_t crc32_fold_final_c(crc32_fold *crc); + +#endif diff --git a/3rdparty/zlib-ng/deflate.c b/3rdparty/zlib-ng/deflate.c new file mode 100644 index 000000000000..2a0a20e5d29a --- /dev/null +++ b/3rdparty/zlib-ng/deflate.c @@ -0,0 +1,1410 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in https://tools.ietf.org/html/rfc1951 + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +#include "zbuild.h" +#include "deflate.h" +#include "deflate_p.h" +#include "functable.h" + +/* Avoid conflicts with zlib.h macros */ +#ifdef ZLIB_COMPAT +# undef deflateInit +# undef deflateInit2 +#endif + +const char PREFIX(deflate_copyright)[] = " deflate 1.3.0 Copyright 1995-2023 Jean-loup Gailly and Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Architecture-specific hooks. + */ +#ifdef S390_DFLTCC_DEFLATE +# include "arch/s390/dfltcc_deflate.h" +#else +/* Memory management for the deflate state. Useful for allocating arch-specific extension blocks. */ +# define ZALLOC_DEFLATE_STATE(strm) ((deflate_state *)ZALLOC(strm, 1, sizeof(deflate_state))) +# define ZFREE_STATE(strm, addr) ZFREE(strm, addr) +# define ZCOPY_DEFLATE_STATE(dst, src) memcpy(dst, src, sizeof(deflate_state)) +/* Memory management for the window. Useful for allocation the aligned window. */ +# define ZALLOC_WINDOW(strm, items, size) ZALLOC(strm, items, size) +# define TRY_FREE_WINDOW(strm, addr) TRY_FREE(strm, addr) +/* Invoked at the beginning of deflateSetDictionary(). Useful for checking arch-specific window data. */ +# define DEFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) +/* Invoked at the beginning of deflateGetDictionary(). Useful for adjusting arch-specific window data. */ +# define DEFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) +/* Invoked at the end of deflateResetKeep(). Useful for initializing arch-specific extension blocks. */ +# define DEFLATE_RESET_KEEP_HOOK(strm) do {} while (0) +/* Invoked at the beginning of deflateParams(). Useful for updating arch-specific compression parameters. */ +# define DEFLATE_PARAMS_HOOK(strm, level, strategy, hook_flush) do {} while (0) +/* Returns whether the last deflate(flush) operation did everything it's supposed to do. */ +# define DEFLATE_DONE(strm, flush) 1 +/* Adjusts the upper bound on compressed data length based on compression parameters and uncompressed data length. + * Useful when arch-specific deflation code behaves differently than regular zlib-ng algorithms. */ +# define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, sourceLen) do {} while (0) +/* Returns whether an optimistic upper bound on compressed data length should *not* be used. + * Useful when arch-specific deflation code behaves differently than regular zlib-ng algorithms. */ +# define DEFLATE_NEED_CONSERVATIVE_BOUND(strm) 0 +/* Invoked for each deflate() call. Useful for plugging arch-specific deflation code. */ +# define DEFLATE_HOOK(strm, flush, bstate) 0 +/* Returns whether zlib-ng should compute a checksum. Set to 0 if arch-specific deflation code already does that. */ +# define DEFLATE_NEED_CHECKSUM(strm) 1 +/* Returns whether reproducibility parameter can be set to a given value. */ +# define DEFLATE_CAN_SET_REPRODUCIBLE(strm, reproducible) 1 +#endif + +/* =========================================================================== + * Function prototypes. + */ +static int deflateStateCheck (PREFIX3(stream) *strm); +Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush); +Z_INTERNAL block_state deflate_fast (deflate_state *s, int flush); +Z_INTERNAL block_state deflate_quick (deflate_state *s, int flush); +#ifndef NO_MEDIUM_STRATEGY +Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush); +#endif +Z_INTERNAL block_state deflate_slow (deflate_state *s, int flush); +Z_INTERNAL block_state deflate_rle (deflate_state *s, int flush); +Z_INTERNAL block_state deflate_huff (deflate_state *s, int flush); +static void lm_set_level (deflate_state *s, int level); +static void lm_init (deflate_state *s); +Z_INTERNAL unsigned read_buf (PREFIX3(stream) *strm, unsigned char *buf, unsigned size); + +extern uint32_t update_hash_roll (deflate_state *const s, uint32_t h, uint32_t val); +extern void insert_string_roll (deflate_state *const s, uint32_t str, uint32_t count); +extern Pos quick_insert_string_roll(deflate_state *const s, uint32_t str); + +/* =========================================================================== + * Local data + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + uint16_t good_length; /* reduce lazy search above this match length */ + uint16_t max_lazy; /* do not perform lazy search above this match length */ + uint16_t nice_length; /* quit search above this match length */ + uint16_t max_chain; + compress_func func; +} config; + +static const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ + +#ifdef NO_QUICK_STRATEGY +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +#else +/* 1 */ {0, 0, 0, 0, deflate_quick}, +/* 2 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +#endif + +#ifdef NO_MEDIUM_STRATEGY +/* 3 */ {4, 6, 32, 32, deflate_fast}, +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +#else +/* 3 */ {4, 6, 16, 6, deflate_medium}, +/* 4 */ {4, 12, 32, 24, deflate_medium}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_medium}, +/* 6 */ {8, 16, 128, 128, deflate_medium}, +#endif + +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ + +/* Note: the deflate() code requires max_lazy >= STD_MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ +#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) + + +/* =========================================================================== + * Initialize the hash table. prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) do { \ + memset((unsigned char *)s->head, 0, HASH_SIZE * sizeof(*s->head)); \ + } while (0) + +/* ========================================================================= */ +/* This function is hidden in ZLIB_COMPAT builds. */ +int32_t ZNG_CONDEXPORT PREFIX(deflateInit2)(PREFIX3(stream) *strm, int32_t level, int32_t method, int32_t windowBits, + int32_t memLevel, int32_t strategy) { + /* Todo: ignore strm->next_in if we use it as window */ + uint32_t window_padding = 0; + deflate_state *s; + int wrap = 1; + + /* Force initialization functable, because deflate captures function pointers from functable. */ + functable.force_init(); + + if (strm == NULL) + return Z_STREAM_ERROR; + + strm->msg = NULL; + if (strm->zalloc == NULL) { + strm->zalloc = PREFIX(zcalloc); + strm->opaque = NULL; + } + if (strm->zfree == NULL) + strm->zfree = PREFIX(zcfree); + + if (level == Z_DEFAULT_COMPRESSION) + level = 6; + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + if (windowBits < -MAX_WBITS) + return Z_STREAM_ERROR; + windowBits = -windowBits; +#ifdef GZIP + } else if (windowBits > MAX_WBITS) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; +#endif + } + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < MIN_WBITS || + windowBits > MAX_WBITS || level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED || + (windowBits == 8 && wrap != 1)) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) + windowBits = 9; /* until 256-byte window bug fixed */ + + s = ZALLOC_DEFLATE_STATE(strm); + if (s == NULL) + return Z_MEM_ERROR; + strm->state = (struct internal_state *)s; + s->strm = strm; + s->status = INIT_STATE; /* to pass state test in deflateReset() */ + + s->wrap = wrap; + s->gzhead = NULL; + s->w_bits = (unsigned int)windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + +#ifdef X86_PCLMULQDQ_CRC + window_padding = 8; +#endif + + s->window = (unsigned char *) ZALLOC_WINDOW(strm, s->w_size + window_padding, 2*sizeof(unsigned char)); + s->prev = (Pos *) ZALLOC(strm, s->w_size, sizeof(Pos)); + memset(s->prev, 0, s->w_size * sizeof(Pos)); + s->head = (Pos *) ZALLOC(strm, HASH_SIZE, sizeof(Pos)); + + s->high_water = 0; /* nothing written to s->window yet */ + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + /* We overlay pending_buf and sym_buf. This works since the average size + * for length/distance pairs over any compressed block is assured to be 31 + * bits or less. + * + * Analysis: The longest fixed codes are a length code of 8 bits plus 5 + * extra bits, for lengths 131 to 257. The longest fixed distance codes are + * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest + * possible fixed-codes length/distance pair is then 31 bits total. + * + * sym_buf starts one-fourth of the way into pending_buf. So there are + * three bytes in sym_buf for every four bytes in pending_buf. Each symbol + * in sym_buf is three bytes -- two for the distance and one for the + * literal/length. As each symbol is consumed, the pointer to the next + * sym_buf value to read moves forward three bytes. From that symbol, up to + * 31 bits are written to pending_buf. The closest the written pending_buf + * bits gets to the next sym_buf symbol to read is just before the last + * code is written. At that time, 31*(n-2) bits have been written, just + * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at + * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1 + * symbols are written.) The closest the writing gets to what is unread is + * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and + * can range from 128 to 32768. + * + * Therefore, at a minimum, there are 142 bits of space between what is + * written and what is read in the overlain buffers, so the symbols cannot + * be overwritten by the compressed data. That space is actually 139 bits, + * due to the three-bit fixed-code block header. + * + * That covers the case where either Z_FIXED is specified, forcing fixed + * codes, or when the use of fixed codes is chosen, because that choice + * results in a smaller compressed block than dynamic codes. That latter + * condition then assures that the above analysis also covers all dynamic + * blocks. A dynamic-code block will only be chosen to be emitted if it has + * fewer bits than a fixed-code block would for the same set of symbols. + * Therefore its average symbol length is assured to be less than 31. So + * the compressed data for a dynamic block also cannot overwrite the + * symbols from which it is being constructed. + */ + + s->pending_buf = (unsigned char *) ZALLOC(strm, s->lit_bufsize, 4); + s->pending_buf_size = s->lit_bufsize * 4; + + if (s->window == NULL || s->prev == NULL || s->head == NULL || s->pending_buf == NULL) { + s->status = FINISH_STATE; + strm->msg = ERR_MSG(Z_MEM_ERROR); + PREFIX(deflateEnd)(strm); + return Z_MEM_ERROR; + } + s->sym_buf = s->pending_buf + s->lit_bufsize; + s->sym_end = (s->lit_bufsize - 1) * 3; + /* We avoid equality with lit_bufsize*3 because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ + + s->level = level; + s->strategy = strategy; + s->block_open = 0; + s->reproducible = 0; + + return PREFIX(deflateReset)(strm); +} + +#ifndef ZLIB_COMPAT +int32_t Z_EXPORT PREFIX(deflateInit)(PREFIX3(stream) *strm, int32_t level) { + return PREFIX(deflateInit2)(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); +} +#endif + +/* Function used by zlib.h and zlib-ng version 2.0 macros */ +int32_t Z_EXPORT PREFIX(deflateInit_)(PREFIX3(stream) *strm, int32_t level, const char *version, int32_t stream_size) { + if (CHECK_VER_STSIZE(version, stream_size)) + return Z_VERSION_ERROR; + return PREFIX(deflateInit2)(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); +} + +/* Function used by zlib.h and zlib-ng version 2.0 macros */ +int32_t Z_EXPORT PREFIX(deflateInit2_)(PREFIX3(stream) *strm, int32_t level, int32_t method, int32_t windowBits, + int32_t memLevel, int32_t strategy, const char *version, int32_t stream_size) { + if (CHECK_VER_STSIZE(version, stream_size)) + return Z_VERSION_ERROR; + return PREFIX(deflateInit2)(strm, level, method, windowBits, memLevel, strategy); +} + +/* ========================================================================= + * Check for a valid deflate stream state. Return 0 if ok, 1 if not. + */ +static int deflateStateCheck(PREFIX3(stream) *strm) { + deflate_state *s; + if (strm == NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + s = strm->state; + if (s == NULL || s->strm != strm || (s->status < INIT_STATE || s->status > MAX_STATE)) + return 1; + return 0; +} + +/* ========================================================================= */ +int32_t Z_EXPORT PREFIX(deflateSetDictionary)(PREFIX3(stream) *strm, const uint8_t *dictionary, uint32_t dictLength) { + deflate_state *s; + unsigned int str, n; + int wrap; + uint32_t avail; + const unsigned char *next; + + if (deflateStateCheck(strm) || dictionary == NULL) + return Z_STREAM_ERROR; + s = strm->state; + wrap = s->wrap; + if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) + return Z_STREAM_ERROR; + + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap == 1) + strm->adler = functable.adler32(strm->adler, dictionary, dictLength); + DEFLATE_SET_DICTIONARY_HOOK(strm, dictionary, dictLength); /* hook for IBM Z DFLTCC */ + s->wrap = 0; /* avoid computing Adler-32 in read_buf */ + + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s->w_size) { + if (wrap == 0) { /* already empty otherwise */ + CLEAR_HASH(s); + s->strstart = 0; + s->block_start = 0; + s->insert = 0; + } + dictionary += dictLength - s->w_size; /* use the tail */ + dictLength = s->w_size; + } + + /* insert dictionary into window and hash */ + avail = strm->avail_in; + next = strm->next_in; + strm->avail_in = dictLength; + strm->next_in = (z_const unsigned char *)dictionary; + PREFIX(fill_window)(s); + while (s->lookahead >= STD_MIN_MATCH) { + str = s->strstart; + n = s->lookahead - (STD_MIN_MATCH - 1); + s->insert_string(s, str, n); + s->strstart = str + n; + s->lookahead = STD_MIN_MATCH - 1; + PREFIX(fill_window)(s); + } + s->strstart += s->lookahead; + s->block_start = (int)s->strstart; + s->insert = s->lookahead; + s->lookahead = 0; + s->prev_length = 0; + s->match_available = 0; + strm->next_in = (z_const unsigned char *)next; + strm->avail_in = avail; + s->wrap = wrap; + return Z_OK; +} + +/* ========================================================================= */ +int32_t Z_EXPORT PREFIX(deflateGetDictionary)(PREFIX3(stream) *strm, uint8_t *dictionary, uint32_t *dictLength) { + deflate_state *s; + unsigned int len; + + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + DEFLATE_GET_DICTIONARY_HOOK(strm, dictionary, dictLength); /* hook for IBM Z DFLTCC */ + s = strm->state; + len = s->strstart + s->lookahead; + if (len > s->w_size) + len = s->w_size; + if (dictionary != NULL && len) + memcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); + if (dictLength != NULL) + *dictLength = len; + return Z_OK; +} + +/* ========================================================================= */ +int32_t Z_EXPORT PREFIX(deflateResetKeep)(PREFIX3(stream) *strm) { + deflate_state *s; + + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + + strm->total_in = strm->total_out = 0; + strm->msg = NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + + s->status = +#ifdef GZIP + s->wrap == 2 ? GZIP_STATE : +#endif + INIT_STATE; + +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = functable.crc32_fold_reset(&s->crc_fold); + } else +#endif + strm->adler = ADLER32_INITIAL_VALUE; + s->last_flush = -2; + + zng_tr_init(s); + + DEFLATE_RESET_KEEP_HOOK(strm); /* hook for IBM Z DFLTCC */ + + return Z_OK; +} + +/* ========================================================================= */ +int32_t Z_EXPORT PREFIX(deflateReset)(PREFIX3(stream) *strm) { + int ret = PREFIX(deflateResetKeep)(strm); + if (ret == Z_OK) + lm_init(strm->state); + return ret; +} + +/* ========================================================================= */ +int32_t Z_EXPORT PREFIX(deflateSetHeader)(PREFIX3(stream) *strm, PREFIX(gz_headerp) head) { + if (deflateStateCheck(strm) || strm->state->wrap != 2) + return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int32_t Z_EXPORT PREFIX(deflatePending)(PREFIX3(stream) *strm, uint32_t *pending, int32_t *bits) { + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + if (pending != NULL) + *pending = strm->state->pending; + if (bits != NULL) + *bits = strm->state->bi_valid; + return Z_OK; +} + +/* ========================================================================= */ +int32_t Z_EXPORT PREFIX(deflatePrime)(PREFIX3(stream) *strm, int32_t bits, int32_t value) { + deflate_state *s; + uint64_t value64 = (uint64_t)value; + int32_t put; + + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + s = strm->state; + if (bits < 0 || bits > BIT_BUF_SIZE || bits > (int32_t)(sizeof(value) << 3) || + s->sym_buf < s->pending_out + ((BIT_BUF_SIZE + 7) >> 3)) + return Z_BUF_ERROR; + do { + put = BIT_BUF_SIZE - s->bi_valid; + put = MIN(put, bits); + + if (s->bi_valid == 0) + s->bi_buf = value64; + else + s->bi_buf |= (value64 & ((UINT64_C(1) << put) - 1)) << s->bi_valid; + s->bi_valid += put; + zng_tr_flush_bits(s); + value64 >>= put; + bits -= put; + } while (bits); + return Z_OK; +} + +/* ========================================================================= */ +int32_t Z_EXPORT PREFIX(deflateParams)(PREFIX3(stream) *strm, int32_t level, int32_t strategy) { + deflate_state *s; + compress_func func; + int hook_flush = Z_NO_FLUSH; + + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + s = strm->state; + + if (level == Z_DEFAULT_COMPRESSION) + level = 6; + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) + return Z_STREAM_ERROR; + DEFLATE_PARAMS_HOOK(strm, level, strategy, &hook_flush); /* hook for IBM Z DFLTCC */ + func = configuration_table[s->level].func; + + if (((strategy != s->strategy || func != configuration_table[level].func) && s->last_flush != -2) + || hook_flush != Z_NO_FLUSH) { + /* Flush the last buffer. Use Z_BLOCK mode, unless the hook requests a "stronger" one. */ + int flush = RANK(hook_flush) > RANK(Z_BLOCK) ? hook_flush : Z_BLOCK; + int err = PREFIX(deflate)(strm, flush); + if (err == Z_STREAM_ERROR) + return err; + if (strm->avail_in || ((int)s->strstart - s->block_start) + s->lookahead || !DEFLATE_DONE(strm, flush)) + return Z_BUF_ERROR; + } + if (s->level != level) { + if (s->level == 0 && s->matches != 0) { + if (s->matches == 1) { + functable.slide_hash(s); + } else { + CLEAR_HASH(s); + } + s->matches = 0; + } + + lm_set_level(s, level); + } + s->strategy = strategy; + return Z_OK; +} + +/* ========================================================================= */ +int32_t Z_EXPORT PREFIX(deflateTune)(PREFIX3(stream) *strm, int32_t good_length, int32_t max_lazy, int32_t nice_length, int32_t max_chain) { + deflate_state *s; + + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + s = strm->state; + s->good_match = (unsigned int)good_length; + s->max_lazy_match = (unsigned int)max_lazy; + s->nice_match = nice_length; + s->max_chain_length = (unsigned int)max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds for + * every combination of windowBits and memLevel. But even the conservative + * upper bound of about 14% expansion does not seem onerous for output buffer + * allocation. + */ +unsigned long Z_EXPORT PREFIX(deflateBound)(PREFIX3(stream) *strm, unsigned long sourceLen) { + deflate_state *s; + unsigned long complen, wraplen; + + /* conservative upper bound for compressed data */ + complen = sourceLen + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, sourceLen); /* hook for IBM Z DFLTCC */ + + /* if can't get parameters, return conservative bound plus zlib wrapper */ + if (deflateStateCheck(strm)) + return complen + 6; + + /* compute wrapper length */ + s = strm->state; + switch (s->wrap) { + case 0: /* raw deflate */ + wraplen = 0; + break; + case 1: /* zlib wrapper */ + wraplen = ZLIB_WRAPLEN + (s->strstart ? 4 : 0); + break; +#ifdef GZIP + case 2: /* gzip wrapper */ + wraplen = GZIP_WRAPLEN; + if (s->gzhead != NULL) { /* user-supplied gzip header */ + unsigned char *str; + if (s->gzhead->extra != NULL) { + wraplen += 2 + s->gzhead->extra_len; + } + str = s->gzhead->name; + if (str != NULL) { + do { + wraplen++; + } while (*str++); + } + str = s->gzhead->comment; + if (str != NULL) { + do { + wraplen++; + } while (*str++); + } + if (s->gzhead->hcrc) + wraplen += 2; + } + break; +#endif + default: /* for compiler happiness */ + wraplen = ZLIB_WRAPLEN; + } + + /* if not default parameters, return conservative bound */ + if (DEFLATE_NEED_CONSERVATIVE_BOUND(strm) || /* hook for IBM Z DFLTCC */ + s->w_bits != MAX_WBITS || HASH_BITS < 15) { + if (s->level == 0) { + /* upper bound for stored blocks with length 127 (memLevel == 1) -- + ~4% overhead plus a small constant */ + complen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) + (sourceLen >> 11) + 7; + } + + return complen + wraplen; + } + +#ifndef NO_QUICK_STRATEGY + return sourceLen /* The source size itself */ + + (sourceLen == 0 ? 1 : 0) /* Always at least one byte for any input */ + + (sourceLen < 9 ? 1 : 0) /* One extra byte for lengths less than 9 */ + + DEFLATE_QUICK_OVERHEAD(sourceLen) /* Source encoding overhead, padded to next full byte */ + + DEFLATE_BLOCK_OVERHEAD /* Deflate block overhead bytes */ + + wraplen; /* none, zlib or gzip wrapper */ +#else + return sourceLen + (sourceLen >> 4) + 7 + wraplen; +#endif +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output, except for + * some deflate_stored() output, goes through this function so some + * applications may wish to modify it to avoid allocating a large + * strm->next_out buffer and copying into it. (See also read_buf()). + */ +Z_INTERNAL void PREFIX(flush_pending)(PREFIX3(stream) *strm) { + uint32_t len; + deflate_state *s = strm->state; + + zng_tr_flush_bits(s); + len = MIN(s->pending, strm->avail_out); + if (len == 0) + return; + + Tracev((stderr, "[FLUSH]")); + memcpy(strm->next_out, s->pending_out, len); + strm->next_out += len; + s->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + s->pending -= len; + if (s->pending == 0) + s->pending_out = s->pending_buf; +} + +/* =========================================================================== + * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. + */ +#define HCRC_UPDATE(beg) \ + do { \ + if (s->gzhead->hcrc && s->pending > (beg)) \ + strm->adler = PREFIX(crc32)(strm->adler, s->pending_buf + (beg), s->pending - (beg)); \ + } while (0) + +/* ========================================================================= */ +int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { + int32_t old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) + return Z_STREAM_ERROR; + s = strm->state; + + if (strm->next_out == NULL || (strm->avail_in != 0 && strm->next_in == NULL) + || (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + old_flush = s->last_flush; + s->last_flush = flush; + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + PREFIX(flush_pending)(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Write the header */ + if (s->status == INIT_STATE && s->wrap == 0) + s->status = BUSY_STATE; + if (s->status == INIT_STATE) { + /* zlib header */ + unsigned int header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + unsigned int level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) + header |= PRESET_DICT; + header += 31 - (header % 31); + + put_short_msb(s, (uint16_t)header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) + put_uint32_msb(s, strm->adler); + strm->adler = ADLER32_INITIAL_VALUE; + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + PREFIX(flush_pending)(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#ifdef GZIP + if (s->status == GZIP_STATE) { + /* gzip header */ + functable.crc32_fold_reset(&s->crc_fold); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == NULL) { + put_uint32(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + PREFIX(flush_pending)(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == NULL ? 0 : 4) + + (s->gzhead->name == NULL ? 0 : 8) + + (s->gzhead->comment == NULL ? 0 : 16) + ); + put_uint32(s, s->gzhead->time); + put_byte(s, s->level == 9 ? 2 : (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != NULL) + put_short(s, (uint16_t)s->gzhead->extra_len); + if (s->gzhead->hcrc) + strm->adler = PREFIX(crc32)(strm->adler, s->pending_buf, s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != NULL) { + uint32_t beg = s->pending; /* start of bytes to update crc */ + uint32_t left = (s->gzhead->extra_len & 0xffff) - s->gzindex; + + while (s->pending + left > s->pending_buf_size) { + uint32_t copy = s->pending_buf_size - s->pending; + memcpy(s->pending_buf + s->pending, s->gzhead->extra + s->gzindex, copy); + s->pending = s->pending_buf_size; + HCRC_UPDATE(beg); + s->gzindex += copy; + PREFIX(flush_pending)(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + left -= copy; + } + memcpy(s->pending_buf + s->pending, s->gzhead->extra + s->gzindex, left); + s->pending += left; + HCRC_UPDATE(beg); + s->gzindex = 0; + } + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != NULL) { + uint32_t beg = s->pending; /* start of bytes to update crc */ + unsigned char val; + + do { + if (s->pending == s->pending_buf_size) { + HCRC_UPDATE(beg); + PREFIX(flush_pending)(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + HCRC_UPDATE(beg); + s->gzindex = 0; + } + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != NULL) { + uint32_t beg = s->pending; /* start of bytes to update crc */ + unsigned char val; + + do { + if (s->pending == s->pending_buf_size) { + HCRC_UPDATE(beg); + PREFIX(flush_pending)(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + HCRC_UPDATE(beg); + } + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) { + PREFIX(flush_pending)(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } + put_short(s, (uint16_t)strm->adler); + functable.crc32_fold_reset(&s->crc_fold); + } + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + PREFIX(flush_pending)(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#endif + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = DEFLATE_HOOK(strm, flush, &bstate) ? bstate : /* hook for IBM Z DFLTCC */ + s->level == 0 ? deflate_stored(s, flush) : + s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + zng_tr_align(s); + } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + zng_tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + if (s->lookahead == 0) { + s->strstart = 0; + s->block_start = 0; + s->insert = 0; + } + } + } + PREFIX(flush_pending)(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + + if (flush != Z_FINISH) + return Z_OK; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = functable.crc32_fold_final(&s->crc_fold); + + put_uint32(s, strm->adler); + put_uint32(s, (uint32_t)strm->total_in); + } else +#endif + { + if (s->wrap == 1) + put_uint32_msb(s, strm->adler); + } + PREFIX(flush_pending)(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) + s->wrap = -s->wrap; /* write the trailer only once! */ + if (s->pending == 0) { + Assert(s->bi_valid == 0, "bi_buf not flushed"); + return Z_STREAM_END; + } + return Z_OK; +} + +/* ========================================================================= */ +int32_t Z_EXPORT PREFIX(deflateEnd)(PREFIX3(stream) *strm) { + int32_t status; + + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + + status = strm->state->status; + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE_WINDOW(strm, strm->state->window); + + ZFREE_STATE(strm, strm->state); + strm->state = NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + */ +int32_t Z_EXPORT PREFIX(deflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *source) { + deflate_state *ds; + deflate_state *ss; + uint32_t window_padding = 0; + + if (deflateStateCheck(source) || dest == NULL) + return Z_STREAM_ERROR; + + ss = source->state; + + memcpy((void *)dest, (void *)source, sizeof(PREFIX3(stream))); + + ds = ZALLOC_DEFLATE_STATE(dest); + if (ds == NULL) + return Z_MEM_ERROR; + dest->state = (struct internal_state *) ds; + ZCOPY_DEFLATE_STATE(ds, ss); + ds->strm = dest; + +#ifdef X86_PCLMULQDQ_CRC + window_padding = 8; +#endif + + ds->window = (unsigned char *) ZALLOC_WINDOW(dest, ds->w_size + window_padding, 2*sizeof(unsigned char)); + ds->prev = (Pos *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Pos *) ZALLOC(dest, HASH_SIZE, sizeof(Pos)); + ds->pending_buf = (unsigned char *) ZALLOC(dest, ds->lit_bufsize, 4); + + if (ds->window == NULL || ds->prev == NULL || ds->head == NULL || ds->pending_buf == NULL) { + PREFIX(deflateEnd)(dest); + return Z_MEM_ERROR; + } + + memcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(unsigned char)); + memcpy((void *)ds->prev, (void *)ss->prev, ds->w_size * sizeof(Pos)); + memcpy((void *)ds->head, (void *)ss->head, HASH_SIZE * sizeof(Pos)); + memcpy(ds->pending_buf, ss->pending_buf, ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->sym_buf = ds->pending_buf + ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +Z_INTERNAL unsigned PREFIX(read_buf)(PREFIX3(stream) *strm, unsigned char *buf, unsigned size) { + uint32_t len = MIN(strm->avail_in, size); + if (len == 0) + return 0; + + strm->avail_in -= len; + + if (!DEFLATE_NEED_CHECKSUM(strm)) { + memcpy(buf, strm->next_in, len); +#ifdef GZIP + } else if (strm->state->wrap == 2) { + functable.crc32_fold_copy(&strm->state->crc_fold, buf, strm->next_in, len); +#endif + } else if (strm->state->wrap == 1) { + strm->adler = functable.adler32_fold_copy(strm->adler, buf, strm->next_in, len); + } else { + memcpy(buf, strm->next_in, len); + } + strm->next_in += len; + strm->total_in += len; + + return len; +} + +/* =========================================================================== + * Set longest match variables based on level configuration + */ +static void lm_set_level(deflate_state *s, int level) { + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + + /* Use rolling hash for deflate_slow algorithm with level 9. It allows us to + * properly lookup different hash chains to speed up longest_match search. Since hashing + * method changes depending on the level we cannot put this into functable. */ + if (s->max_chain_length > 1024) { + s->update_hash = &update_hash_roll; + s->insert_string = &insert_string_roll; + s->quick_insert_string = &quick_insert_string_roll; + } else { + s->update_hash = functable.update_hash; + s->insert_string = functable.insert_string; + s->quick_insert_string = functable.quick_insert_string; + } + + s->level = level; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +static void lm_init(deflate_state *s) { + s->window_size = 2 * s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + lm_set_level(s, s->level); + + s->strstart = 0; + s->block_start = 0; + s->lookahead = 0; + s->insert = 0; + s->prev_length = 0; + s->match_available = 0; + s->match_start = 0; + s->ins_h = 0; +} + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ + +void Z_INTERNAL PREFIX(fill_window)(deflate_state *s) { + unsigned n; + unsigned int more; /* Amount of free space at the end of the window. */ + unsigned int wsize = s->w_size; + + Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = s->window_size - s->lookahead - s->strstart; + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + memcpy(s->window, s->window+wsize, (unsigned)wsize); + if (s->match_start >= wsize) { + s->match_start -= wsize; + } else { + s->match_start = 0; + s->prev_length = 0; + } + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (int)wsize; + if (s->insert > s->strstart) + s->insert = s->strstart; + functable.slide_hash(s); + more += wsize; + } + if (s->strm->avail_in == 0) + break; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = PREFIX(read_buf)(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead + s->insert >= STD_MIN_MATCH) { + unsigned int str = s->strstart - s->insert; + if (UNLIKELY(s->max_chain_length > 1024)) { + s->ins_h = s->update_hash(s, s->window[str], s->window[str+1]); + } else if (str >= 1) { + s->quick_insert_string(s, str + 2 - STD_MIN_MATCH); + } + unsigned int count = s->insert; + if (UNLIKELY(s->lookahead == 1)) { + count -= 1; + } + if (count > 0) { + s->insert_string(s, str, count); + s->insert -= count; + } + } + /* If the whole input has less than STD_MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to STD_MAX_MATCH since the longest match + * routines allow scanning to strstart + STD_MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + unsigned int curr = s->strstart + s->lookahead; + unsigned int init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + memset(s->window + curr, 0, init); + s->high_water = curr + init; + } else if (s->high_water < curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + memset(s->window + s->high_water, 0, init); + s->high_water += init; + } + } + + Assert((unsigned long)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "not enough room for search"); +} + +#ifndef ZLIB_COMPAT +/* ========================================================================= + * Checks whether buffer size is sufficient and whether this parameter is a duplicate. + */ +static int32_t deflateSetParamPre(zng_deflate_param_value **out, size_t min_size, zng_deflate_param_value *param) { + int32_t buf_error = param->size < min_size; + + if (*out != NULL) { + (*out)->status = Z_BUF_ERROR; + buf_error = 1; + } + *out = param; + return buf_error; +} + +/* ========================================================================= */ +int32_t Z_EXPORT zng_deflateSetParams(zng_stream *strm, zng_deflate_param_value *params, size_t count) { + size_t i; + deflate_state *s; + zng_deflate_param_value *new_level = NULL; + zng_deflate_param_value *new_strategy = NULL; + zng_deflate_param_value *new_reproducible = NULL; + int param_buf_error; + int version_error = 0; + int buf_error = 0; + int stream_error = 0; + + /* Initialize the statuses. */ + for (i = 0; i < count; i++) + params[i].status = Z_OK; + + /* Check whether the stream state is consistent. */ + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + s = strm->state; + + /* Check buffer sizes and detect duplicates. */ + for (i = 0; i < count; i++) { + switch (params[i].param) { + case Z_DEFLATE_LEVEL: + param_buf_error = deflateSetParamPre(&new_level, sizeof(int), ¶ms[i]); + break; + case Z_DEFLATE_STRATEGY: + param_buf_error = deflateSetParamPre(&new_strategy, sizeof(int), ¶ms[i]); + break; + case Z_DEFLATE_REPRODUCIBLE: + param_buf_error = deflateSetParamPre(&new_reproducible, sizeof(int), ¶ms[i]); + break; + default: + params[i].status = Z_VERSION_ERROR; + version_error = 1; + param_buf_error = 0; + break; + } + if (param_buf_error) { + params[i].status = Z_BUF_ERROR; + buf_error = 1; + } + } + /* Exit early if small buffers or duplicates are detected. */ + if (buf_error) + return Z_BUF_ERROR; + + /* Apply changes, remember if there were errors. */ + if (new_level != NULL || new_strategy != NULL) { + int ret = PREFIX(deflateParams)(strm, new_level == NULL ? s->level : *(int *)new_level->buf, + new_strategy == NULL ? s->strategy : *(int *)new_strategy->buf); + if (ret != Z_OK) { + if (new_level != NULL) + new_level->status = Z_STREAM_ERROR; + if (new_strategy != NULL) + new_strategy->status = Z_STREAM_ERROR; + stream_error = 1; + } + } + if (new_reproducible != NULL) { + int val = *(int *)new_reproducible->buf; + if (DEFLATE_CAN_SET_REPRODUCIBLE(strm, val)) { + s->reproducible = val; + } else { + new_reproducible->status = Z_STREAM_ERROR; + stream_error = 1; + } + } + + /* Report version errors only if there are no real errors. */ + return stream_error ? Z_STREAM_ERROR : (version_error ? Z_VERSION_ERROR : Z_OK); +} + +/* ========================================================================= */ +int32_t Z_EXPORT zng_deflateGetParams(zng_stream *strm, zng_deflate_param_value *params, size_t count) { + deflate_state *s; + size_t i; + int32_t buf_error = 0; + int32_t version_error = 0; + + /* Initialize the statuses. */ + for (i = 0; i < count; i++) + params[i].status = Z_OK; + + /* Check whether the stream state is consistent. */ + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + s = strm->state; + + for (i = 0; i < count; i++) { + switch (params[i].param) { + case Z_DEFLATE_LEVEL: + if (params[i].size < sizeof(int)) + params[i].status = Z_BUF_ERROR; + else + *(int *)params[i].buf = s->level; + break; + case Z_DEFLATE_STRATEGY: + if (params[i].size < sizeof(int)) + params[i].status = Z_BUF_ERROR; + else + *(int *)params[i].buf = s->strategy; + break; + case Z_DEFLATE_REPRODUCIBLE: + if (params[i].size < sizeof(int)) + params[i].status = Z_BUF_ERROR; + else + *(int *)params[i].buf = s->reproducible; + break; + default: + params[i].status = Z_VERSION_ERROR; + version_error = 1; + break; + } + if (params[i].status == Z_BUF_ERROR) + buf_error = 1; + } + return buf_error ? Z_BUF_ERROR : (version_error ? Z_VERSION_ERROR : Z_OK); +} +#endif diff --git a/3rdparty/zlib-ng/deflate.h b/3rdparty/zlib-ng/deflate.h new file mode 100644 index 000000000000..8001b47c999d --- /dev/null +++ b/3rdparty/zlib-ng/deflate.h @@ -0,0 +1,408 @@ +#ifndef DEFLATE_H_ +#define DEFLATE_H_ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2016 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +#include "zutil.h" +#include "zendian.h" +#include "adler32_fold.h" +#include "crc32_fold.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define BIT_BUF_SIZE 64 +/* size of bit buffer in bi_buf */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define INIT_STATE 1 /* zlib header -> BUSY_STATE */ +#ifdef GZIP +# define GZIP_STATE 4 /* gzip header -> BUSY_STATE | EXTRA_STATE */ +# define EXTRA_STATE 5 /* gzip extra block -> NAME_STATE */ +# define NAME_STATE 6 /* gzip file name -> COMMENT_STATE */ +# define COMMENT_STATE 7 /* gzip comment -> HCRC_STATE */ +# define HCRC_STATE 8 /* gzip header CRC -> BUSY_STATE */ +#endif +#define BUSY_STATE 2 /* deflate -> FINISH_STATE */ +#define FINISH_STATE 3 /* stream complete */ +#ifdef GZIP +# define MAX_STATE HCRC_STATE +#else +# define MAX_STATE FINISH_STATE +#endif +/* Stream status */ + +#define HASH_BITS 16u /* log2(HASH_SIZE) */ +#ifndef HASH_SIZE +# define HASH_SIZE 65536u /* number of elements in hash table */ +#endif +#define HASH_MASK (HASH_SIZE - 1u) /* HASH_SIZE-1 */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + uint16_t freq; /* frequency count */ + uint16_t code; /* bit string */ + } fc; + union { + uint16_t dad; /* father node in Huffman tree */ + uint16_t len; /* length of bit string */ + } dl; +} ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + const static_tree_desc *stat_desc; /* the corresponding static tree */ +} tree_desc; + +typedef uint16_t Pos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. + */ +/* Type definitions for hash callbacks */ +typedef struct internal_state deflate_state; + +typedef uint32_t (* update_hash_cb) (deflate_state *const s, uint32_t h, uint32_t val); +typedef void (* insert_string_cb) (deflate_state *const s, uint32_t str, uint32_t count); +typedef Pos (* quick_insert_string_cb)(deflate_state *const s, uint32_t str); + +struct internal_state { + PREFIX3(stream) *strm; /* pointer back to this zlib stream */ + unsigned char *pending_buf; /* output still pending */ + unsigned char *pending_out; /* next pending byte to output to the stream */ + uint32_t pending_buf_size; /* size of pending_buf */ + uint32_t pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + uint32_t gzindex; /* where in extra, name, or comment */ + PREFIX(gz_headerp) gzhead; /* gzip header information to write */ + int status; /* as the name implies */ + int last_flush; /* value of flush param for previous deflate call */ + int reproducible; /* Whether reproducible compression results are required. */ + + int block_open; + /* Whether or not a block is currently open for the QUICK deflation scheme. + * This is set to 1 if there is an active block, or 0 if the block was just closed. + */ + + /* used by deflate.c: */ + + unsigned int w_size; /* LZ77 window size (32K by default) */ + unsigned int w_bits; /* log2(w_size) (8..16) */ + unsigned int w_mask; /* w_size - 1 */ + unsigned int lookahead; /* number of valid bytes ahead in window */ + + unsigned int high_water; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + + unsigned int window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + unsigned char *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-STD_MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + Pos *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Pos *head; /* Heads of the hash chains or 0. */ + + uint32_t ins_h; /* hash index of string to be inserted */ + + int block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + unsigned int match_length; /* length of best match */ + Pos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + unsigned int strstart; /* start of string to insert */ + unsigned int match_start; /* start of matching string */ + + unsigned int prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + unsigned int max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this length. + * A higher limit improves compression ratio but degrades the speed. + */ + + unsigned int max_lazy_match; + /* Attempt to find a better match only when the current match is strictly smaller + * than this value. This mechanism is used only for compression levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + update_hash_cb update_hash; + insert_string_cb insert_string; + quick_insert_string_cb quick_insert_string; + /* Hash function callbacks that can be configured depending on the deflate + * algorithm being used */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + unsigned int good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + struct crc32_fold_s ALIGNED_(16) crc_fold; + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to suppress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + uint16_t bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + unsigned char depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + unsigned int lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + unsigned char *sym_buf; /* buffer for distances and literals/lengths */ + unsigned int sym_next; /* running index in sym_buf */ + unsigned int sym_end; /* symbol table full when sym_next reaches this */ + + unsigned long opt_len; /* bit length of current block with optimal trees */ + unsigned long static_len; /* bit length of current block with static trees */ + unsigned int matches; /* number of string matches in current block */ + unsigned int insert; /* bytes at end of window left to insert */ + + /* compressed_len and bits_sent are only used if ZLIB_DEBUG is defined */ + unsigned long compressed_len; /* total bit length of compressed file mod 2^32 */ + unsigned long bits_sent; /* bit length of compressed data sent mod 2^32 */ + + /* Reserved for future use and alignment purposes */ + char *reserved_p; + + uint64_t bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least significant bits). */ + + int32_t bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit are always zero. */ + + /* Reserved for future use and alignment purposes */ + int32_t reserved[11]; +} ALIGNED_(8); + +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) { \ + s->pending_buf[s->pending++] = (unsigned char)(c); \ +} + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pending_buf. + */ +static inline void put_short(deflate_state *s, uint16_t w) { +#if BYTE_ORDER == BIG_ENDIAN + w = ZSWAP16(w); +#endif + memcpy(&s->pending_buf[s->pending], &w, sizeof(w)); + s->pending += 2; +} + +/* =========================================================================== + * Output a short MSB first on the stream. + * IN assertion: there is enough room in pending_buf. + */ +static inline void put_short_msb(deflate_state *s, uint16_t w) { +#if BYTE_ORDER == LITTLE_ENDIAN + w = ZSWAP16(w); +#endif + memcpy(&s->pending_buf[s->pending], &w, sizeof(w)); + s->pending += 2; +} + +/* =========================================================================== + * Output a 32-bit unsigned int LSB first on the stream. + * IN assertion: there is enough room in pending_buf. + */ +static inline void put_uint32(deflate_state *s, uint32_t dw) { +#if BYTE_ORDER == BIG_ENDIAN + dw = ZSWAP32(dw); +#endif + memcpy(&s->pending_buf[s->pending], &dw, sizeof(dw)); + s->pending += 4; +} + +/* =========================================================================== + * Output a 32-bit unsigned int MSB first on the stream. + * IN assertion: there is enough room in pending_buf. + */ +static inline void put_uint32_msb(deflate_state *s, uint32_t dw) { +#if BYTE_ORDER == LITTLE_ENDIAN + dw = ZSWAP32(dw); +#endif + memcpy(&s->pending_buf[s->pending], &dw, sizeof(dw)); + s->pending += 4; +} + +/* =========================================================================== + * Output a 64-bit unsigned int LSB first on the stream. + * IN assertion: there is enough room in pending_buf. + */ +static inline void put_uint64(deflate_state *s, uint64_t lld) { +#if BYTE_ORDER == BIG_ENDIAN + lld = ZSWAP64(lld); +#endif + memcpy(&s->pending_buf[s->pending], &lld, sizeof(lld)); + s->pending += 8; +} + +#define MIN_LOOKAHEAD (STD_MAX_MATCH + STD_MIN_MATCH + 1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the STD_MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size - MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define WIN_INIT STD_MAX_MATCH +/* Number of bytes after end of data in window to initialize in order to avoid + memory checker errors from longest match routines */ + + +void Z_INTERNAL PREFIX(fill_window)(deflate_state *s); +void Z_INTERNAL slide_hash_c(deflate_state *s); + + /* in trees.c */ +void Z_INTERNAL zng_tr_init(deflate_state *s); +void Z_INTERNAL zng_tr_flush_block(deflate_state *s, char *buf, uint32_t stored_len, int last); +void Z_INTERNAL zng_tr_flush_bits(deflate_state *s); +void Z_INTERNAL zng_tr_align(deflate_state *s); +void Z_INTERNAL zng_tr_stored_block(deflate_state *s, char *buf, uint32_t stored_len, int last); +uint16_t Z_INTERNAL PREFIX(bi_reverse)(unsigned code, int len); +void Z_INTERNAL PREFIX(flush_pending)(PREFIX3(streamp) strm); +#define d_code(dist) ((dist) < 256 ? zng_dist_code[dist] : zng_dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. zng_dist_code[256] and zng_dist_code[257] are never + * used. + */ + +/* Bit buffer and compress bits calculation debugging */ +#ifdef ZLIB_DEBUG +# define cmpr_bits_add(s, len) s->compressed_len += (len) +# define cmpr_bits_align(s) s->compressed_len = (s->compressed_len + 7) & ~7L +# define sent_bits_add(s, bits) s->bits_sent += (bits) +# define sent_bits_align(s) s->bits_sent = (s->bits_sent + 7) & ~7L +#else +# define cmpr_bits_add(s, len) Z_UNUSED(len) +# define cmpr_bits_align(s) +# define sent_bits_add(s, bits) Z_UNUSED(bits) +# define sent_bits_align(s) +#endif + +#endif /* DEFLATE_H_ */ diff --git a/3rdparty/zlib-ng/deflate_fast.c b/3rdparty/zlib-ng/deflate_fast.c new file mode 100644 index 000000000000..3184aa718c7e --- /dev/null +++ b/3rdparty/zlib-ng/deflate_fast.c @@ -0,0 +1,102 @@ +/* deflate_fast.c -- compress data using the fast strategy of deflation algorithm + * + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "deflate.h" +#include "deflate_p.h" +#include "functable.h" + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +Z_INTERNAL block_state deflate_fast(deflate_state *s, int flush) { + Pos hash_head; /* head of the hash chain */ + int bflush = 0; /* set if current block must be flushed */ + int64_t dist; + uint32_t match_len = 0; + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need STD_MAX_MATCH bytes + * for the next match, plus WANT_MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + PREFIX(fill_window)(s); + if (UNLIKELY(s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH)) { + return need_more; + } + if (UNLIKELY(s->lookahead == 0)) + break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= WANT_MIN_MATCH) { + hash_head = functable.quick_insert_string(s, s->strstart); + dist = (int64_t)s->strstart - hash_head; + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match length < WANT_MIN_MATCH + */ + if (dist <= MAX_DIST(s) && dist > 0 && hash_head != 0) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + match_len = functable.longest_match(s, hash_head); + /* longest_match() sets match_start */ + } + } + + if (match_len >= WANT_MIN_MATCH) { + check_match(s, s->strstart, s->match_start, match_len); + + bflush = zng_tr_tally_dist(s, s->strstart - s->match_start, match_len - STD_MIN_MATCH); + + s->lookahead -= match_len; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (match_len <= s->max_insert_length && s->lookahead >= WANT_MIN_MATCH) { + match_len--; /* string at strstart already in table */ + s->strstart++; + + functable.insert_string(s, s->strstart, match_len); + s->strstart += match_len; + } else { + s->strstart += match_len; + functable.quick_insert_string(s, s->strstart + 2 - STD_MIN_MATCH); + + /* If lookahead < STD_MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + match_len = 0; + } else { + /* No match, output a literal byte */ + bflush = zng_tr_tally_lit(s, s->window[s->strstart]); + s->lookahead--; + s->strstart++; + } + if (UNLIKELY(bflush)) + FLUSH_BLOCK(s, 0); + } + s->insert = s->strstart < (STD_MIN_MATCH - 1) ? s->strstart : (STD_MIN_MATCH - 1); + if (UNLIKELY(flush == Z_FINISH)) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (UNLIKELY(s->sym_next)) + FLUSH_BLOCK(s, 0); + return block_done; +} diff --git a/3rdparty/zlib-ng/deflate_huff.c b/3rdparty/zlib-ng/deflate_huff.c new file mode 100644 index 000000000000..b197e24d7c38 --- /dev/null +++ b/3rdparty/zlib-ng/deflate_huff.c @@ -0,0 +1,45 @@ +/* deflate_huff.c -- compress data using huffman encoding only strategy + * + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "deflate.h" +#include "deflate_p.h" +#include "functable.h" + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +Z_INTERNAL block_state deflate_huff(deflate_state *s, int flush) { + int bflush = 0; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s->lookahead == 0) { + PREFIX(fill_window)(s); + if (s->lookahead == 0) { + if (flush == Z_NO_FLUSH) + return need_more; + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + bflush = zng_tr_tally_lit(s, s->window[s->strstart]); + s->lookahead--; + s->strstart++; + if (bflush) + FLUSH_BLOCK(s, 0); + } + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->sym_next) + FLUSH_BLOCK(s, 0); + return block_done; +} diff --git a/3rdparty/zlib-ng/deflate_medium.c b/3rdparty/zlib-ng/deflate_medium.c new file mode 100644 index 000000000000..47796e32217a --- /dev/null +++ b/3rdparty/zlib-ng/deflate_medium.c @@ -0,0 +1,293 @@ +/* deflate_medium.c -- The deflate_medium deflate strategy + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * Authors: + * Arjan van de Ven + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ +#ifndef NO_MEDIUM_STRATEGY +#include "zbuild.h" +#include "deflate.h" +#include "deflate_p.h" +#include "functable.h" + +struct match { + uint16_t match_start; + uint16_t match_length; + uint16_t strstart; + uint16_t orgstart; +}; + +static int emit_match(deflate_state *s, struct match match) { + int bflush = 0; + + /* matches that are not long enough we need to emit as literals */ + if (match.match_length < WANT_MIN_MATCH) { + while (match.match_length) { + bflush += zng_tr_tally_lit(s, s->window[match.strstart]); + s->lookahead--; + match.strstart++; + match.match_length--; + } + return bflush; + } + + check_match(s, match.strstart, match.match_start, match.match_length); + + bflush += zng_tr_tally_dist(s, match.strstart - match.match_start, match.match_length - STD_MIN_MATCH); + + s->lookahead -= match.match_length; + return bflush; +} + +static void insert_match(deflate_state *s, struct match match) { + if (UNLIKELY(s->lookahead <= (unsigned int)(match.match_length + WANT_MIN_MATCH))) + return; + + /* matches that are not long enough we need to emit as literals */ + if (LIKELY(match.match_length < WANT_MIN_MATCH)) { + match.strstart++; + match.match_length--; + if (UNLIKELY(match.match_length > 0)) { + if (match.strstart >= match.orgstart) { + if (match.strstart + match.match_length - 1 >= match.orgstart) { + functable.insert_string(s, match.strstart, match.match_length); + } else { + functable.insert_string(s, match.strstart, match.orgstart - match.strstart + 1); + } + match.strstart += match.match_length; + match.match_length = 0; + } + } + return; + } + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (match.match_length <= 16 * s->max_insert_length && s->lookahead >= WANT_MIN_MATCH) { + match.match_length--; /* string at strstart already in table */ + match.strstart++; + + if (LIKELY(match.strstart >= match.orgstart)) { + if (LIKELY(match.strstart + match.match_length - 1 >= match.orgstart)) { + functable.insert_string(s, match.strstart, match.match_length); + } else { + functable.insert_string(s, match.strstart, match.orgstart - match.strstart + 1); + } + } else if (match.orgstart < match.strstart + match.match_length) { + functable.insert_string(s, match.orgstart, match.strstart + match.match_length - match.orgstart); + } + match.strstart += match.match_length; + match.match_length = 0; + } else { + match.strstart += match.match_length; + match.match_length = 0; + + if (match.strstart >= (STD_MIN_MATCH - 2)) + functable.quick_insert_string(s, match.strstart + 2 - STD_MIN_MATCH); + + /* If lookahead < WANT_MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } +} + +static void fizzle_matches(deflate_state *s, struct match *current, struct match *next) { + Pos limit; + unsigned char *match, *orig; + int changed = 0; + struct match c, n; + /* step zero: sanity checks */ + + if (current->match_length <= 1) + return; + + if (UNLIKELY(current->match_length > 1 + next->match_start)) + return; + + if (UNLIKELY(current->match_length > 1 + next->strstart)) + return; + + match = s->window - current->match_length + 1 + next->match_start; + orig = s->window - current->match_length + 1 + next->strstart; + + /* quick exit check.. if this fails then don't bother with anything else */ + if (LIKELY(*match != *orig)) + return; + + c = *current; + n = *next; + + /* step one: try to move the "next" match to the left as much as possible */ + limit = next->strstart > MAX_DIST(s) ? next->strstart - (Pos)MAX_DIST(s) : 0; + + match = s->window + n.match_start - 1; + orig = s->window + n.strstart - 1; + + while (*match == *orig) { + if (UNLIKELY(c.match_length < 1)) + break; + if (UNLIKELY(n.strstart <= limit)) + break; + if (UNLIKELY(n.match_length >= 256)) + break; + if (UNLIKELY(n.match_start <= 1)) + break; + + n.strstart--; + n.match_start--; + n.match_length++; + c.match_length--; + match--; + orig--; + changed++; + } + + if (!changed) + return; + + if (c.match_length <= 1 && n.match_length != 2) { + n.orgstart++; + *current = c; + *next = n; + } else { + return; + } +} + +Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { + /* Align the first struct to start on a new cacheline, this allows us to fit both structs in one cacheline */ + ALIGNED_(16) struct match current_match; + struct match next_match; + + /* For levels below 5, don't check the next position for a better match */ + int early_exit = s->level < 5; + + memset(¤t_match, 0, sizeof(struct match)); + memset(&next_match, 0, sizeof(struct match)); + + for (;;) { + Pos hash_head = 0; /* head of the hash chain */ + int bflush = 0; /* set if current block must be flushed */ + int64_t dist; + + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need STD_MAX_MATCH bytes + * for the next match, plus WANT_MIN_MATCH bytes to insert the + * string following the next current_match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + PREFIX(fill_window)(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (UNLIKELY(s->lookahead == 0)) + break; /* flush the current block */ + next_match.match_length = 0; + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + + /* If we already have a future match from a previous round, just use that */ + if (!early_exit && next_match.match_length > 0) { + current_match = next_match; + next_match.match_length = 0; + } else { + hash_head = 0; + if (s->lookahead >= WANT_MIN_MATCH) { + hash_head = functable.quick_insert_string(s, s->strstart); + } + + current_match.strstart = (uint16_t)s->strstart; + current_match.orgstart = current_match.strstart; + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < WANT_MIN_MATCH + */ + + dist = (int64_t)s->strstart - hash_head; + if (dist <= MAX_DIST(s) && dist > 0 && hash_head != 0) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + current_match.match_length = (uint16_t)functable.longest_match(s, hash_head); + current_match.match_start = (uint16_t)s->match_start; + if (UNLIKELY(current_match.match_length < WANT_MIN_MATCH)) + current_match.match_length = 1; + if (UNLIKELY(current_match.match_start >= current_match.strstart)) { + /* this can happen due to some restarts */ + current_match.match_length = 1; + } + } else { + /* Set up the match to be a 1 byte literal */ + current_match.match_start = 0; + current_match.match_length = 1; + } + } + + insert_match(s, current_match); + + /* now, look ahead one */ + if (LIKELY(!early_exit && s->lookahead > MIN_LOOKAHEAD && (uint32_t)(current_match.strstart + current_match.match_length) < (s->window_size - MIN_LOOKAHEAD))) { + s->strstart = current_match.strstart + current_match.match_length; + hash_head = functable.quick_insert_string(s, s->strstart); + + next_match.strstart = (uint16_t)s->strstart; + next_match.orgstart = next_match.strstart; + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < WANT_MIN_MATCH + */ + + dist = (int64_t)s->strstart - hash_head; + if (dist <= MAX_DIST(s) && dist > 0 && hash_head != 0) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + next_match.match_length = (uint16_t)functable.longest_match(s, hash_head); + next_match.match_start = (uint16_t)s->match_start; + if (UNLIKELY(next_match.match_start >= next_match.strstart)) { + /* this can happen due to some restarts */ + next_match.match_length = 1; + } + if (next_match.match_length < WANT_MIN_MATCH) + next_match.match_length = 1; + else + fizzle_matches(s, ¤t_match, &next_match); + } else { + /* Set up the match to be a 1 byte literal */ + next_match.match_start = 0; + next_match.match_length = 1; + } + + s->strstart = current_match.strstart; + } else { + next_match.match_length = 0; + } + + /* now emit the current match */ + bflush = emit_match(s, current_match); + + /* move the "cursor" forward */ + s->strstart += current_match.match_length; + + if (UNLIKELY(bflush)) + FLUSH_BLOCK(s, 0); + } + s->insert = s->strstart < (STD_MIN_MATCH - 1) ? s->strstart : (STD_MIN_MATCH - 1); + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (UNLIKELY(s->sym_next)) + FLUSH_BLOCK(s, 0); + + return block_done; +} +#endif diff --git a/3rdparty/zlib-ng/deflate_p.h b/3rdparty/zlib-ng/deflate_p.h new file mode 100644 index 000000000000..dd2021a0f59a --- /dev/null +++ b/3rdparty/zlib-ng/deflate_p.h @@ -0,0 +1,116 @@ +/* deflate_p.h -- Private inline functions and macros shared with more than + * one deflate method + * + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + */ + +#ifndef DEFLATE_P_H +#define DEFLATE_P_H + +/* Forward declare common non-inlined functions declared in deflate.c */ + +#ifdef ZLIB_DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +static inline void check_match(deflate_state *s, Pos start, Pos match, int length) { + /* check that the match length is valid*/ + if (length < STD_MIN_MATCH || length > STD_MAX_MATCH) { + fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); + z_error("invalid match length"); + } + /* check that the match isn't at the same position as the start string */ + if (match == start) { + fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); + z_error("invalid match position"); + } + /* check that the match is indeed a match */ + if (memcmp(s->window + match, s->window + start, length) != 0) { + int32_t i = 0; + fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); + do { + fprintf(stderr, " %03d: match [%02x] start [%02x]\n", i++, + s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr, "\\[%u,%d]", start-match, length); + do { + putc(s->window[start++], stderr); + } while (--length != 0); + } +} +#else +#define check_match(s, start, match, length) +#endif + +Z_INTERNAL void PREFIX(flush_pending)(PREFIX3(stream) *strm); +Z_INTERNAL unsigned PREFIX(read_buf)(PREFIX3(stream) *strm, unsigned char *buf, unsigned size); + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ + +extern const unsigned char Z_INTERNAL zng_length_code[]; +extern const unsigned char Z_INTERNAL zng_dist_code[]; + +static inline int zng_tr_tally_lit(deflate_state *s, unsigned char c) { + /* c is the unmatched char */ + s->sym_buf[s->sym_next++] = 0; + s->sym_buf[s->sym_next++] = 0; + s->sym_buf[s->sym_next++] = c; + s->dyn_ltree[c].Freq++; + Tracevv((stderr, "%c", c)); + Assert(c <= (STD_MAX_MATCH-STD_MIN_MATCH), "zng_tr_tally: bad literal"); + return (s->sym_next == s->sym_end); +} + +static inline int zng_tr_tally_dist(deflate_state *s, uint32_t dist, uint32_t len) { + /* dist: distance of matched string */ + /* len: match length-STD_MIN_MATCH */ + s->sym_buf[s->sym_next++] = (uint8_t)(dist); + s->sym_buf[s->sym_next++] = (uint8_t)(dist >> 8); + s->sym_buf[s->sym_next++] = (uint8_t)len; + s->matches++; + dist--; + Assert(dist < MAX_DIST(s) && (uint16_t)d_code(dist) < (uint16_t)D_CODES, + "zng_tr_tally: bad match"); + + s->dyn_ltree[zng_length_code[len]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + return (s->sym_next == s->sym_end); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, last) { \ + zng_tr_flush_block(s, (s->block_start >= 0 ? \ + (char *)&s->window[(unsigned)s->block_start] : \ + NULL), \ + (uint32_t)((int)s->strstart - s->block_start), \ + (last)); \ + s->block_start = (int)s->strstart; \ + PREFIX(flush_pending)(s->strm); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, last) { \ + FLUSH_BLOCK_ONLY(s, last); \ + if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ +} + +/* Maximum stored block length in deflate format (not including header). */ +#define MAX_STORED 65535 + +/* Compression function. Returns the block state after the call. */ +typedef block_state (*compress_func) (deflate_state *s, int flush); +/* Match function. Returns the longest match. */ +typedef uint32_t (*match_func) (deflate_state *const s, Pos cur_match); + +#endif diff --git a/3rdparty/zlib-ng/deflate_quick.c b/3rdparty/zlib-ng/deflate_quick.c new file mode 100644 index 000000000000..df5a17b9e662 --- /dev/null +++ b/3rdparty/zlib-ng/deflate_quick.c @@ -0,0 +1,129 @@ +/* + * The deflate_quick deflate strategy, designed to be used when cycles are + * at a premium. + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * Authors: + * Wajdi Feghali + * Jim Guilford + * Vinodh Gopal + * Erdinc Ozturk + * Jim Kukunas + * + * Portions are Copyright (C) 2016 12Sided Technology, LLC. + * Author: + * Phil Vachon + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "zutil_p.h" +#include "deflate.h" +#include "deflate_p.h" +#include "functable.h" +#include "trees_emit.h" + +extern const ct_data static_ltree[L_CODES+2]; +extern const ct_data static_dtree[D_CODES]; + +#define QUICK_START_BLOCK(s, last) { \ + zng_tr_emit_tree(s, STATIC_TREES, last); \ + s->block_open = 1 + (int)last; \ + s->block_start = (int)s->strstart; \ +} + +#define QUICK_END_BLOCK(s, last) { \ + if (s->block_open) { \ + zng_tr_emit_end_block(s, static_ltree, last); \ + s->block_open = 0; \ + s->block_start = (int)s->strstart; \ + PREFIX(flush_pending)(s->strm); \ + if (s->strm->avail_out == 0) \ + return (last) ? finish_started : need_more; \ + } \ +} + +Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { + Pos hash_head; + int64_t dist; + unsigned match_len, last; + + + last = (flush == Z_FINISH) ? 1 : 0; + if (UNLIKELY(last && s->block_open != 2)) { + /* Emit end of previous block */ + QUICK_END_BLOCK(s, 0); + /* Emit start of last block */ + QUICK_START_BLOCK(s, last); + } else if (UNLIKELY(s->block_open == 0 && s->lookahead > 0)) { + /* Start new block only when we have lookahead data, so that if no + input data is given an empty block will not be written */ + QUICK_START_BLOCK(s, last); + } + + for (;;) { + if (UNLIKELY(s->pending + ((BIT_BUF_SIZE + 7) >> 3) >= s->pending_buf_size)) { + PREFIX(flush_pending)(s->strm); + if (s->strm->avail_out == 0) { + return (last && s->strm->avail_in == 0 && s->bi_valid == 0 && s->block_open == 0) ? finish_started : need_more; + } + } + + if (UNLIKELY(s->lookahead < MIN_LOOKAHEAD)) { + PREFIX(fill_window)(s); + if (UNLIKELY(s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH)) { + return need_more; + } + if (UNLIKELY(s->lookahead == 0)) + break; + + if (UNLIKELY(s->block_open == 0)) { + /* Start new block when we have lookahead data, so that if no + input data is given an empty block will not be written */ + QUICK_START_BLOCK(s, last); + } + } + + if (LIKELY(s->lookahead >= WANT_MIN_MATCH)) { + hash_head = functable.quick_insert_string(s, s->strstart); + dist = (int64_t)s->strstart - hash_head; + + if (dist <= MAX_DIST(s) && dist > 0) { + const uint8_t *str_start = s->window + s->strstart; + const uint8_t *match_start = s->window + hash_head; + + if (zng_memcmp_2(str_start, match_start) == 0) { + match_len = functable.compare256(str_start+2, match_start+2) + 2; + + if (match_len >= WANT_MIN_MATCH) { + if (UNLIKELY(match_len > s->lookahead)) + match_len = s->lookahead; + if (UNLIKELY(match_len > STD_MAX_MATCH)) + match_len = STD_MAX_MATCH; + + check_match(s, s->strstart, hash_head, match_len); + + zng_tr_emit_dist(s, static_ltree, static_dtree, match_len - STD_MIN_MATCH, (uint32_t)dist); + s->lookahead -= match_len; + s->strstart += match_len; + continue; + } + } + } + } + + zng_tr_emit_lit(s, static_ltree, s->window[s->strstart]); + s->strstart++; + s->lookahead--; + } + + s->insert = s->strstart < (STD_MIN_MATCH - 1) ? s->strstart : (STD_MIN_MATCH - 1); + if (UNLIKELY(last)) { + QUICK_END_BLOCK(s, 1); + return finish_done; + } + + QUICK_END_BLOCK(s, 0); + return block_done; +} diff --git a/3rdparty/zlib-ng/deflate_rle.c b/3rdparty/zlib-ng/deflate_rle.c new file mode 100644 index 000000000000..cd0850994606 --- /dev/null +++ b/3rdparty/zlib-ng/deflate_rle.c @@ -0,0 +1,85 @@ +/* deflate_rle.c -- compress data using RLE strategy of deflation algorithm + * + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "compare256_rle.h" +#include "deflate.h" +#include "deflate_p.h" +#include "functable.h" + +#ifdef UNALIGNED_OK +# if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) +# define compare256_rle compare256_rle_unaligned_64 +# elif defined(HAVE_BUILTIN_CTZ) +# define compare256_rle compare256_rle_unaligned_32 +# else +# define compare256_rle compare256_rle_unaligned_16 +# endif +#else +# define compare256_rle compare256_rle_c +#endif + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +Z_INTERNAL block_state deflate_rle(deflate_state *s, int flush) { + int bflush = 0; /* set if current block must be flushed */ + unsigned char *scan; /* scan goes up to strend for length of run */ + uint32_t match_len = 0; + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need STD_MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. + */ + if (s->lookahead <= STD_MAX_MATCH) { + PREFIX(fill_window)(s); + if (s->lookahead <= STD_MAX_MATCH && flush == Z_NO_FLUSH) + return need_more; + if (s->lookahead == 0) + break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + if (s->lookahead >= STD_MIN_MATCH && s->strstart > 0) { + scan = s->window + s->strstart - 1; + if (scan[0] == scan[1] && scan[1] == scan[2]) { + match_len = compare256_rle(scan, scan+3)+2; + match_len = MIN(match_len, s->lookahead); + match_len = MIN(match_len, STD_MAX_MATCH); + } + Assert(scan+match_len <= s->window + s->window_size - 1, "wild scan"); + } + + /* Emit match if have run of STD_MIN_MATCH or longer, else emit literal */ + if (match_len >= STD_MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, match_len); + + bflush = zng_tr_tally_dist(s, 1, match_len - STD_MIN_MATCH); + + s->lookahead -= match_len; + s->strstart += match_len; + match_len = 0; + } else { + /* No match, output a literal byte */ + bflush = zng_tr_tally_lit(s, s->window[s->strstart]); + s->lookahead--; + s->strstart++; + } + if (bflush) + FLUSH_BLOCK(s, 0); + } + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->sym_next) + FLUSH_BLOCK(s, 0); + return block_done; +} diff --git a/3rdparty/zlib-ng/deflate_slow.c b/3rdparty/zlib-ng/deflate_slow.c new file mode 100644 index 000000000000..9f1c913467b7 --- /dev/null +++ b/3rdparty/zlib-ng/deflate_slow.c @@ -0,0 +1,143 @@ +/* deflate_slow.c -- compress data using the slow strategy of deflation algorithm + * + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "deflate.h" +#include "deflate_p.h" +#include "functable.h" + +/* =========================================================================== + * Same as deflate_medium, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { + Pos hash_head; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + int64_t dist; + uint32_t match_len; + match_func *longest_match; + + if (s->max_chain_length <= 1024) + longest_match = &functable.longest_match; + else + longest_match = &functable.longest_match_slow; + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need STD_MAX_MATCH bytes + * for the next match, plus WANT_MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + PREFIX(fill_window)(s); + if (UNLIKELY(s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH)) { + return need_more; + } + if (UNLIKELY(s->lookahead == 0)) + break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0; + if (LIKELY(s->lookahead >= WANT_MIN_MATCH)) { + hash_head = s->quick_insert_string(s, s->strstart); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_match = (Pos)s->match_start; + match_len = STD_MIN_MATCH - 1; + dist = (int64_t)s->strstart - hash_head; + + if (dist <= MAX_DIST(s) && dist > 0 && s->prev_length < s->max_lazy_match && hash_head != 0) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + match_len = (*longest_match)(s, hash_head); + /* longest_match() sets match_start */ + + if (match_len <= 5 && (s->strategy == Z_FILTERED)) { + /* If prev_match is also WANT_MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + match_len = STD_MIN_MATCH - 1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= STD_MIN_MATCH && match_len <= s->prev_length) { + unsigned int max_insert = s->strstart + s->lookahead - STD_MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + bflush = zng_tr_tally_dist(s, s->strstart -1 - s->prev_match, s->prev_length - STD_MIN_MATCH); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->prev_length -= 1; + s->lookahead -= s->prev_length; + + unsigned int mov_fwd = s->prev_length - 1; + if (max_insert > s->strstart) { + unsigned int insert_cnt = mov_fwd; + if (UNLIKELY(insert_cnt > max_insert - s->strstart)) + insert_cnt = max_insert - s->strstart; + s->insert_string(s, s->strstart + 1, insert_cnt); + } + s->prev_length = 0; + s->match_available = 0; + s->strstart += mov_fwd + 1; + + if (UNLIKELY(bflush)) + FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + bflush = zng_tr_tally_lit(s, s->window[s->strstart-1]); + if (UNLIKELY(bflush)) + FLUSH_BLOCK_ONLY(s, 0); + s->prev_length = match_len; + s->strstart++; + s->lookahead--; + if (UNLIKELY(s->strm->avail_out == 0)) + return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->prev_length = match_len; + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert(flush != Z_NO_FLUSH, "no flush?"); + if (UNLIKELY(s->match_available)) { + (void) zng_tr_tally_lit(s, s->window[s->strstart-1]); + s->match_available = 0; + } + s->insert = s->strstart < (STD_MIN_MATCH - 1) ? s->strstart : (STD_MIN_MATCH - 1); + if (UNLIKELY(flush == Z_FINISH)) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (UNLIKELY(s->sym_next)) + FLUSH_BLOCK(s, 0); + return block_done; +} diff --git a/3rdparty/zlib-ng/deflate_stored.c b/3rdparty/zlib-ng/deflate_stored.c new file mode 100644 index 000000000000..6160896b3fed --- /dev/null +++ b/3rdparty/zlib-ng/deflate_stored.c @@ -0,0 +1,186 @@ +/* deflate_stored.c -- store data without compression using deflation algorithm + * + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "deflate.h" +#include "deflate_p.h" +#include "functable.h" + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * + * In case deflateParams() is used to later switch to a non-zero compression + * level, s->matches (otherwise unused when storing) keeps track of the number + * of hash table slides to perform. If s->matches is 1, then one hash table + * slide will be done when switching. If s->matches is 2, the maximum value + * allowed here, then the hash table will be cleared, since two or more slides + * is the same as a clear. + * + * deflate_stored() is written to minimize the number of times an input byte is + * copied. It is most efficient with large input and output buffers, which + * maximizes the opportunites to have a single copy from next_in to next_out. + */ +Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush) { + /* Smallest worthy block size when not flushing or finishing. By default + * this is 32K. This can be as small as 507 bytes for memLevel == 1. For + * large input and output buffers, the stored block size will be larger. + */ + unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); + + /* Copy as many min_block or larger stored blocks directly to next_out as + * possible. If flushing, copy the remaining available input to next_out as + * stored blocks, if there is enough space. + */ + unsigned len, left, have, last = 0; + unsigned used = s->strm->avail_in; + do { + /* Set len to the maximum size block that we can copy directly with the + * available input data and output space. Set left to how much of that + * would be copied from what's left in the window. + */ + len = MAX_STORED; /* maximum deflate stored block length */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + if (s->strm->avail_out < have) /* need room for header */ + break; + /* maximum stored block length that will fit in avail_out: */ + have = s->strm->avail_out - have; + left = (int)s->strstart - s->block_start; /* bytes left in window */ + if (len > (unsigned long)left + s->strm->avail_in) + len = left + s->strm->avail_in; /* limit len to the input */ + len = MIN(len, have); /* limit len to the output */ + + /* If the stored block would be less than min_block in length, or if + * unable to copy all of the available input when flushing, then try + * copying to the window and the pending buffer instead. Also don't + * write an empty block when flushing -- deflate() does that. + */ + if (len < min_block && ((len == 0 && flush != Z_FINISH) || flush == Z_NO_FLUSH || len != left + s->strm->avail_in)) + break; + + /* Make a dummy stored block in pending to get the header bytes, + * including any pending bits. This also updates the debugging counts. + */ + last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; + zng_tr_stored_block(s, (char *)0, 0L, last); + + /* Replace the lengths in the dummy stored block with len. */ + s->pending -= 4; + put_short(s, (uint16_t)len); + put_short(s, (uint16_t)~len); + + /* Write the stored block header bytes. */ + PREFIX(flush_pending)(s->strm); + + /* Update debugging counts for the data about to be copied. */ + cmpr_bits_add(s, len << 3); + sent_bits_add(s, len << 3); + + /* Copy uncompressed bytes from the window to next_out. */ + if (left) { + left = MIN(left, len); + memcpy(s->strm->next_out, s->window + s->block_start, left); + s->strm->next_out += left; + s->strm->avail_out -= left; + s->strm->total_out += left; + s->block_start += (int)left; + len -= left; + } + + /* Copy uncompressed bytes directly from next_in to next_out, updating + * the check value. + */ + if (len) { + PREFIX(read_buf)(s->strm, s->strm->next_out, len); + s->strm->next_out += len; + s->strm->avail_out -= len; + s->strm->total_out += len; + } + } while (last == 0); + + /* Update the sliding window with the last s->w_size bytes of the copied + * data, or append all of the copied data to the existing window if less + * than s->w_size bytes were copied. Also update the number of bytes to + * insert in the hash tables, in the event that deflateParams() switches to + * a non-zero compression level. + */ + used -= s->strm->avail_in; /* number of input bytes directly copied */ + if (used) { + /* If any input was used, then no unused input remains in the window, + * therefore s->block_start == s->strstart. + */ + if (used >= s->w_size) { /* supplant the previous history */ + s->matches = 2; /* clear hash */ + memcpy(s->window, s->strm->next_in - s->w_size, s->w_size); + s->strstart = s->w_size; + s->insert = s->strstart; + } else { + if (s->window_size - s->strstart <= used) { + /* Slide the window down. */ + s->strstart -= s->w_size; + memcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + s->insert = MIN(s->insert, s->strstart); + } + memcpy(s->window + s->strstart, s->strm->next_in - used, used); + s->strstart += used; + s->insert += MIN(used, s->w_size - s->insert); + } + s->block_start = (int)s->strstart; + } + s->high_water = MAX(s->high_water, s->strstart); + + /* If the last block was written to next_out, then done. */ + if (last) + return finish_done; + + /* If flushing and all input has been consumed, then done. */ + if (flush != Z_NO_FLUSH && flush != Z_FINISH && s->strm->avail_in == 0 && (int)s->strstart == s->block_start) + return block_done; + + /* Fill the window with any remaining input. */ + have = s->window_size - s->strstart; + if (s->strm->avail_in > have && s->block_start >= (int)s->w_size) { + /* Slide the window down. */ + s->block_start -= (int)s->w_size; + s->strstart -= s->w_size; + memcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + have += s->w_size; /* more space now */ + s->insert = MIN(s->insert, s->strstart); + } + + have = MIN(have, s->strm->avail_in); + if (have) { + PREFIX(read_buf)(s->strm, s->window + s->strstart, have); + s->strstart += have; + s->insert += MIN(have, s->w_size - s->insert); + } + s->high_water = MAX(s->high_water, s->strstart); + + /* There was not enough avail_out to write a complete worthy or flushed + * stored block to next_out. Write a stored block to pending instead, if we + * have enough input for a worthy block, or if flushing and there is enough + * room for the remaining input as a stored block in the pending buffer. + */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + /* maximum stored block length that will fit in pending: */ + have = MIN(s->pending_buf_size - have, MAX_STORED); + min_block = MIN(have, s->w_size); + left = (int)s->strstart - s->block_start; + if (left >= min_block || ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && s->strm->avail_in == 0 && left <= have)) { + len = MIN(left, have); + last = flush == Z_FINISH && s->strm->avail_in == 0 && len == left ? 1 : 0; + zng_tr_stored_block(s, (char *)s->window + s->block_start, len, last); + s->block_start += (int)len; + PREFIX(flush_pending)(s->strm); + } + + /* We've done all we can with the available input and output. */ + return last ? finish_started : need_more; +} diff --git a/3rdparty/zlib-ng/fallback_builtins.h b/3rdparty/zlib-ng/fallback_builtins.h new file mode 100644 index 000000000000..79072a1028ec --- /dev/null +++ b/3rdparty/zlib-ng/fallback_builtins.h @@ -0,0 +1,50 @@ +#ifndef FALLBACK_BUILTINS_H +#define FALLBACK_BUILTINS_H + +#if defined(_MSC_VER) && !defined(__clang__) +#if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) + +#include +#ifdef X86_FEATURES +# include "arch/x86/x86_features.h" +#endif + +/* This is not a general purpose replacement for __builtin_ctz. The function expects that value is != 0. + * Because of that assumption trailing_zero is not initialized and the return value is not checked. + * Tzcnt and bsf give identical results except when input value is 0, therefore this can not be allowed. + * If tzcnt instruction is not supported, the cpu will itself execute bsf instead. + * Performance tzcnt/bsf is identical on Intel cpu, tzcnt is faster than bsf on AMD cpu. + */ +static __forceinline int __builtin_ctz(unsigned int value) { + Assert(value != 0, "Invalid input value: 0"); +# if defined(X86_FEATURES) && !(_MSC_VER < 1700) + return (int)_tzcnt_u32(value); +# else + unsigned long trailing_zero; + _BitScanForward(&trailing_zero, value); + return (int)trailing_zero; +# endif +} +#define HAVE_BUILTIN_CTZ + +#ifdef _M_AMD64 +/* This is not a general purpose replacement for __builtin_ctzll. The function expects that value is != 0. + * Because of that assumption trailing_zero is not initialized and the return value is not checked. + */ +static __forceinline int __builtin_ctzll(unsigned long long value) { + Assert(value != 0, "Invalid input value: 0"); +# if defined(X86_FEATURES) && !(_MSC_VER < 1700) + return (int)_tzcnt_u64(value); +# else + unsigned long trailing_zero; + _BitScanForward64(&trailing_zero, value); + return (int)trailing_zero; +# endif +} +#define HAVE_BUILTIN_CTZLL +#endif // Microsoft AMD64 + +#endif // Microsoft AMD64/IA64/x86/ARM/ARM64 test +#endif // _MSC_VER & !clang + +#endif // include guard FALLBACK_BUILTINS_H diff --git a/3rdparty/zlib-ng/functable.c b/3rdparty/zlib-ng/functable.c new file mode 100644 index 000000000000..37c4aeef7d0e --- /dev/null +++ b/3rdparty/zlib-ng/functable.c @@ -0,0 +1,403 @@ +/* functable.c -- Choose relevant optimized functions at runtime + * Copyright (C) 2017 Hans Kristian Rosbach + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "zendian.h" +#include "crc32_braid_p.h" +#include "deflate.h" +#include "deflate_p.h" +#include "functable.h" +#include "cpu_features.h" + +#if defined(_MSC_VER) +# include +#endif + +/* Platform has pointer size atomic store */ +#if defined(__GNUC__) || defined(__clang__) +# define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \ + __atomic_store(&(functable.FUNC_NAME), &(VAR.FUNC_NAME), __ATOMIC_SEQ_CST) +# define FUNCTABLE_BARRIER() __atomic_thread_fence(__ATOMIC_SEQ_CST) +#elif defined(_MSC_VER) +# define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \ + _InterlockedExchangePointer((void * volatile *)&(functable.FUNC_NAME), (void *)(VAR.FUNC_NAME)) +# if defined(_M_ARM) || defined(_M_ARM64) +# define FUNCTABLE_BARRIER() do { \ + _ReadWriteBarrier(); \ + __dmb(0xB); /* _ARM_BARRIER_ISH */ \ + _ReadWriteBarrier(); \ +} while (0) +# else +# define FUNCTABLE_BARRIER() _ReadWriteBarrier() +# endif +#else +# warning Unable to detect atomic intrinsic support. +# define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \ + *((void * volatile *)&(functable.FUNC_NAME)) = (void *)(VAR.FUNC_NAME) +# define FUNCTABLE_BARRIER() do { /* Empty */ } while (0) +#endif + +static void force_init_empty(void) { + // empty +} + +static void init_functable(void) { + struct functable_s ft; + struct cpu_features cf; + + cpu_check_features(&cf); + + // Generic code + ft.force_init = &force_init_empty; + ft.adler32 = &adler32_c; + ft.adler32_fold_copy = &adler32_fold_copy_c; + ft.chunkmemset_safe = &chunkmemset_safe_c; + ft.chunksize = &chunksize_c; + ft.crc32 = &PREFIX(crc32_braid); + ft.crc32_fold = &crc32_fold_c; + ft.crc32_fold_copy = &crc32_fold_copy_c; + ft.crc32_fold_final = &crc32_fold_final_c; + ft.crc32_fold_reset = &crc32_fold_reset_c; + ft.inflate_fast = &inflate_fast_c; + ft.insert_string = &insert_string_c; + ft.quick_insert_string = &quick_insert_string_c; + ft.slide_hash = &slide_hash_c; + ft.update_hash = &update_hash_c; + +#if defined(UNALIGNED_OK) && BYTE_ORDER == LITTLE_ENDIAN +# if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) + ft.longest_match = &longest_match_unaligned_64; + ft.longest_match_slow = &longest_match_slow_unaligned_64; + ft.compare256 = &compare256_unaligned_64; +# elif defined(HAVE_BUILTIN_CTZ) + ft.longest_match = &longest_match_unaligned_32; + ft.longest_match_slow = &longest_match_slow_unaligned_32; + ft.compare256 = &compare256_unaligned_32; +# else + ft.longest_match = &longest_match_unaligned_16; + ft.longest_match_slow = &longest_match_slow_unaligned_16; + ft.compare256 = &compare256_unaligned_16; +# endif +#else + ft.longest_match = &longest_match_c; + ft.longest_match_slow = &longest_match_slow_c; + ft.compare256 = &compare256_c; +#endif + + + // Select arch-optimized functions + + // X86 - SSE2 +#ifdef X86_SSE2 +# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) + if (cf.x86.has_sse2) +# endif + { + ft.chunkmemset_safe = &chunkmemset_safe_sse2; + ft.chunksize = &chunksize_sse2; + ft.inflate_fast = &inflate_fast_sse2; + ft.slide_hash = &slide_hash_sse2; +# ifdef HAVE_BUILTIN_CTZ + ft.compare256 = &compare256_sse2; + ft.longest_match = &longest_match_sse2; + ft.longest_match_slow = &longest_match_slow_sse2; +# endif + } +#endif + // X86 - SSSE3 +#ifdef X86_SSSE3 + if (cf.x86.has_ssse3) { + ft.adler32 = &adler32_ssse3; +# ifdef X86_SSE2 + ft.chunkmemset_safe = &chunkmemset_safe_ssse3; + ft.inflate_fast = &inflate_fast_ssse3; +# endif + } +#endif + // X86 - SSE4.2 +#ifdef X86_SSE42 + if (cf.x86.has_sse42) { + ft.adler32_fold_copy = &adler32_fold_copy_sse42; + ft.insert_string = &insert_string_sse42; + ft.quick_insert_string = &quick_insert_string_sse42; + ft.update_hash = &update_hash_sse42; + } +#endif + // X86 - PCLMUL +#ifdef X86_PCLMULQDQ_CRC + if (cf.x86.has_pclmulqdq) { + ft.crc32 = &crc32_pclmulqdq; + ft.crc32_fold = &crc32_fold_pclmulqdq; + ft.crc32_fold_copy = &crc32_fold_pclmulqdq_copy; + ft.crc32_fold_final = &crc32_fold_pclmulqdq_final; + ft.crc32_fold_reset = &crc32_fold_pclmulqdq_reset; + } +#endif + // X86 - AVX +#ifdef X86_AVX2 + if (cf.x86.has_avx2) { + ft.adler32 = &adler32_avx2; + ft.adler32_fold_copy = &adler32_fold_copy_avx2; + ft.chunkmemset_safe = &chunkmemset_safe_avx2; + ft.chunksize = &chunksize_avx2; + ft.inflate_fast = &inflate_fast_avx2; + ft.slide_hash = &slide_hash_avx2; +# ifdef HAVE_BUILTIN_CTZ + ft.compare256 = &compare256_avx2; + ft.longest_match = &longest_match_avx2; + ft.longest_match_slow = &longest_match_slow_avx2; +# endif + } +#endif +#ifdef X86_AVX512 + if (cf.x86.has_avx512) { + ft.adler32 = &adler32_avx512; + ft.adler32_fold_copy = &adler32_fold_copy_avx512; + } +#endif +#ifdef X86_AVX512VNNI + if (cf.x86.has_avx512vnni) { + ft.adler32 = &adler32_avx512_vnni; + ft.adler32_fold_copy = &adler32_fold_copy_avx512_vnni; + } +#endif + // X86 - VPCLMULQDQ +#if defined(X86_PCLMULQDQ_CRC) && defined(X86_VPCLMULQDQ_CRC) + if (cf.x86.has_pclmulqdq && cf.x86.has_avx512 && cf.x86.has_vpclmulqdq) { + ft.crc32 = &crc32_vpclmulqdq; + ft.crc32_fold = &crc32_fold_vpclmulqdq; + ft.crc32_fold_copy = &crc32_fold_vpclmulqdq_copy; + ft.crc32_fold_final = &crc32_fold_vpclmulqdq_final; + ft.crc32_fold_reset = &crc32_fold_vpclmulqdq_reset; + } +#endif + + + // ARM - SIMD +#ifdef ARM_SIMD +# ifndef ARM_NOCHECK_SIMD + if (cf.arm.has_simd) +# endif + { + ft.slide_hash = &slide_hash_armv6; + } +#endif + // ARM - NEON +#ifdef ARM_NEON +# ifndef ARM_NOCHECK_NEON + if (cf.arm.has_neon) +# endif + { + ft.adler32 = &adler32_neon; + ft.chunkmemset_safe = &chunkmemset_safe_neon; + ft.chunksize = &chunksize_neon; + ft.inflate_fast = &inflate_fast_neon; + ft.slide_hash = &slide_hash_neon; +# ifdef HAVE_BUILTIN_CTZLL + ft.compare256 = &compare256_neon; + ft.longest_match = &longest_match_neon; + ft.longest_match_slow = &longest_match_slow_neon; +# endif + } +#endif + // ARM - ACLE +#ifdef ARM_ACLE + if (cf.arm.has_crc32) { + ft.crc32 = &crc32_acle; + ft.insert_string = &insert_string_acle; + ft.quick_insert_string = &quick_insert_string_acle; + ft.update_hash = &update_hash_acle; + } +#endif + + + // Power - VMX +#ifdef PPC_VMX + if (cf.power.has_altivec) { + ft.adler32 = &adler32_vmx; + ft.slide_hash = &slide_hash_vmx; + } +#endif + // Power8 - VSX +#ifdef POWER8_VSX + if (cf.power.has_arch_2_07) { + ft.adler32 = &adler32_power8; + ft.chunkmemset_safe = &chunkmemset_safe_power8; + ft.chunksize = &chunksize_power8; + ft.inflate_fast = &inflate_fast_power8; + ft.slide_hash = &slide_hash_power8; + } +#endif +#ifdef POWER8_VSX_CRC32 + if (cf.power.has_arch_2_07) + ft.crc32 = &crc32_power8; +#endif + // Power9 +#ifdef POWER9 + if (cf.power.has_arch_3_00) { + ft.compare256 = &compare256_power9; + ft.longest_match = &longest_match_power9; + ft.longest_match_slow = &longest_match_slow_power9; + } +#endif + + + // RISCV - RVV +#ifdef RISCV_RVV + if (cf.riscv.has_rvv) { + ft.adler32 = &adler32_rvv; + ft.adler32_fold_copy = &adler32_fold_copy_rvv; + ft.chunkmemset_safe = &chunkmemset_safe_rvv; + ft.chunksize = &chunksize_rvv; + ft.compare256 = &compare256_rvv; + ft.inflate_fast = &inflate_fast_rvv; + ft.longest_match = &longest_match_rvv; + ft.longest_match_slow = &longest_match_slow_rvv; + ft.slide_hash = &slide_hash_rvv; + } +#endif + + + // S390 +#ifdef S390_CRC32_VX + if (cf.s390.has_vx) + ft.crc32 = crc32_s390_vx; +#endif + + // Assign function pointers individually for atomic operation + FUNCTABLE_ASSIGN(ft, force_init); + FUNCTABLE_ASSIGN(ft, adler32); + FUNCTABLE_ASSIGN(ft, adler32_fold_copy); + FUNCTABLE_ASSIGN(ft, chunkmemset_safe); + FUNCTABLE_ASSIGN(ft, chunksize); + FUNCTABLE_ASSIGN(ft, compare256); + FUNCTABLE_ASSIGN(ft, crc32); + FUNCTABLE_ASSIGN(ft, crc32_fold); + FUNCTABLE_ASSIGN(ft, crc32_fold_copy); + FUNCTABLE_ASSIGN(ft, crc32_fold_final); + FUNCTABLE_ASSIGN(ft, crc32_fold_reset); + FUNCTABLE_ASSIGN(ft, inflate_fast); + FUNCTABLE_ASSIGN(ft, insert_string); + FUNCTABLE_ASSIGN(ft, longest_match); + FUNCTABLE_ASSIGN(ft, longest_match_slow); + FUNCTABLE_ASSIGN(ft, quick_insert_string); + FUNCTABLE_ASSIGN(ft, slide_hash); + FUNCTABLE_ASSIGN(ft, update_hash); + + // Memory barrier for weak memory order CPUs + FUNCTABLE_BARRIER(); +} + +/* stub functions */ +static void force_init_stub(void) { + init_functable(); +} + +static uint32_t adler32_stub(uint32_t adler, const uint8_t* buf, size_t len) { + init_functable(); + return functable.adler32(adler, buf, len); +} + +static uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t* dst, const uint8_t* src, size_t len) { + init_functable(); + return functable.adler32_fold_copy(adler, dst, src, len); +} + +static uint8_t* chunkmemset_safe_stub(uint8_t* out, unsigned dist, unsigned len, unsigned left) { + init_functable(); + return functable.chunkmemset_safe(out, dist, len, left); +} + +static uint32_t chunksize_stub(void) { + init_functable(); + return functable.chunksize(); +} + +static uint32_t compare256_stub(const uint8_t* src0, const uint8_t* src1) { + init_functable(); + return functable.compare256(src0, src1); +} + +static uint32_t crc32_stub(uint32_t crc, const uint8_t* buf, size_t len) { + init_functable(); + return functable.crc32(crc, buf, len); +} + +static void crc32_fold_stub(crc32_fold* crc, const uint8_t* src, size_t len, uint32_t init_crc) { + init_functable(); + functable.crc32_fold(crc, src, len, init_crc); +} + +static void crc32_fold_copy_stub(crc32_fold* crc, uint8_t* dst, const uint8_t* src, size_t len) { + init_functable(); + functable.crc32_fold_copy(crc, dst, src, len); +} + +static uint32_t crc32_fold_final_stub(crc32_fold* crc) { + init_functable(); + return functable.crc32_fold_final(crc); +} + +static uint32_t crc32_fold_reset_stub(crc32_fold* crc) { + init_functable(); + return functable.crc32_fold_reset(crc); +} + +static void inflate_fast_stub(PREFIX3(stream) *strm, uint32_t start) { + init_functable(); + functable.inflate_fast(strm, start); +} + +static void insert_string_stub(deflate_state* const s, uint32_t str, uint32_t count) { + init_functable(); + functable.insert_string(s, str, count); +} + +static uint32_t longest_match_stub(deflate_state* const s, Pos cur_match) { + init_functable(); + return functable.longest_match(s, cur_match); +} + +static uint32_t longest_match_slow_stub(deflate_state* const s, Pos cur_match) { + init_functable(); + return functable.longest_match_slow(s, cur_match); +} + +static Pos quick_insert_string_stub(deflate_state* const s, const uint32_t str) { + init_functable(); + return functable.quick_insert_string(s, str); +} + +static void slide_hash_stub(deflate_state* s) { + init_functable(); + functable.slide_hash(s); +} + +static uint32_t update_hash_stub(deflate_state* const s, uint32_t h, uint32_t val) { + init_functable(); + return functable.update_hash(s, h, val); +} + +/* functable init */ +Z_INTERNAL struct functable_s functable = { + force_init_stub, + adler32_stub, + adler32_fold_copy_stub, + chunkmemset_safe_stub, + chunksize_stub, + compare256_stub, + crc32_stub, + crc32_fold_stub, + crc32_fold_copy_stub, + crc32_fold_final_stub, + crc32_fold_reset_stub, + inflate_fast_stub, + insert_string_stub, + longest_match_stub, + longest_match_slow_stub, + quick_insert_string_stub, + slide_hash_stub, + update_hash_stub +}; diff --git a/3rdparty/zlib-ng/functable.h b/3rdparty/zlib-ng/functable.h new file mode 100644 index 000000000000..9f78188e1054 --- /dev/null +++ b/3rdparty/zlib-ng/functable.h @@ -0,0 +1,42 @@ +/* functable.h -- Struct containing function pointers to optimized functions + * Copyright (C) 2017 Hans Kristian Rosbach + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef FUNCTABLE_H_ +#define FUNCTABLE_H_ + +#include "deflate.h" +#include "crc32_fold.h" +#include "adler32_fold.h" + +#ifdef ZLIB_COMPAT +typedef struct z_stream_s z_stream; +#else +typedef struct zng_stream_s zng_stream; +#endif + +struct functable_s { + void (* force_init) (void); + uint32_t (* adler32) (uint32_t adler, const uint8_t *buf, size_t len); + uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); + uint8_t* (* chunkmemset_safe) (uint8_t *out, unsigned dist, unsigned len, unsigned left); + uint32_t (* chunksize) (void); + uint32_t (* compare256) (const uint8_t *src0, const uint8_t *src1); + uint32_t (* crc32) (uint32_t crc, const uint8_t *buf, size_t len); + void (* crc32_fold) (struct crc32_fold_s *crc, const uint8_t *src, size_t len, uint32_t init_crc); + void (* crc32_fold_copy) (struct crc32_fold_s *crc, uint8_t *dst, const uint8_t *src, size_t len); + uint32_t (* crc32_fold_final) (struct crc32_fold_s *crc); + uint32_t (* crc32_fold_reset) (struct crc32_fold_s *crc); + void (* inflate_fast) (PREFIX3(stream) *strm, uint32_t start); + void (* insert_string) (deflate_state *const s, uint32_t str, uint32_t count); + uint32_t (* longest_match) (deflate_state *const s, Pos cur_match); + uint32_t (* longest_match_slow) (deflate_state *const s, Pos cur_match); + Pos (* quick_insert_string)(deflate_state *const s, uint32_t str); + void (* slide_hash) (deflate_state *s); + uint32_t (* update_hash) (deflate_state *const s, uint32_t h, uint32_t val); +}; + +Z_INTERNAL extern struct functable_s functable; + +#endif diff --git a/3rdparty/zlib-ng/gzguts.h b/3rdparty/zlib-ng/gzguts.h new file mode 100644 index 000000000000..a663844b693e --- /dev/null +++ b/3rdparty/zlib-ng/gzguts.h @@ -0,0 +1,144 @@ +#ifndef GZGUTS_H_ +#define GZGUTS_H_ +/* gzguts.h -- zlib internal header definitions for gz* operations + * Copyright (C) 2004-2019 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef _LARGEFILE64_SOURCE +# ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 +# endif +# undef _FILE_OFFSET_BITS +# undef _TIME_BITS +#endif + +#if defined(HAVE_VISIBILITY_INTERNAL) +# define Z_INTERNAL __attribute__((visibility ("internal"))) +#elif defined(HAVE_VISIBILITY_HIDDEN) +# define Z_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define Z_INTERNAL +#endif + +#include +#include +#include +#include +#include + +#if defined(ZLIB_COMPAT) +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#ifdef _WIN32 +# include +#endif + +#if defined(_WIN32) +# include +# define WIDECHAR +#endif + +#ifdef WINAPI_FAMILY +# define open _open +# define read _read +# define write _write +# define close _close +#endif + +/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +#if !defined(STDC99) && !defined(__CYGWIN__) && !defined(__MINGW__) && defined(_WIN32) +# if !defined(vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +#endif + +/* unlike snprintf (which is required in C99), _snprintf does not guarantee + null termination of the result -- however this is only used in gzlib.c + where the result is assured to fit in the space provided */ +#if defined(_MSC_VER) && _MSC_VER < 1900 +# define snprintf _snprintf +#endif + +/* get errno and strerror definition */ +#ifndef NO_STRERROR +# include +# define zstrerror() strerror(errno) +#else +# define zstrerror() "stdio error (consult errno)" +#endif + +/* default memLevel */ +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif + +/* default i/o buffer size -- double this for output when reading (this and + twice this must be able to fit in an unsigned type) */ +#ifndef GZBUFSIZE +# define GZBUFSIZE 131072 +#endif + +/* gzip modes, also provide a little integrity check on the passed structure */ +#define GZ_NONE 0 +#define GZ_READ 7247 +#define GZ_WRITE 31153 +#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ + +/* values for gz_state how */ +#define LOOK 0 /* look for a gzip header */ +#define COPY 1 /* copy input directly */ +#define GZIP 2 /* decompress a gzip stream */ + +/* internal gzip file state data structure */ +typedef struct { + /* exposed contents for gzgetc() macro */ + struct gzFile_s x; /* "x" for exposed */ + /* x.have: number of bytes available at x.next */ + /* x.next: next output data to deliver or write */ + /* x.pos: current position in uncompressed data */ + /* used for both reading and writing */ + int mode; /* see gzip modes above */ + int fd; /* file descriptor */ + char *path; /* path or fd for error messages */ + unsigned size; /* buffer size, zero if not allocated yet */ + unsigned want; /* requested buffer size, default is GZBUFSIZE */ + unsigned char *in; /* input buffer (double-sized when writing) */ + unsigned char *out; /* output buffer (double-sized when reading) */ + int direct; /* 0 if processing gzip, 1 if transparent */ + /* just for reading */ + int how; /* 0: get header, 1: copy, 2: decompress */ + z_off64_t start; /* where the gzip data started, for rewinding */ + int eof; /* true if end of input file reached */ + int past; /* true if read requested past end */ + /* just for writing */ + int level; /* compression level */ + int strategy; /* compression strategy */ + int reset; /* true if a reset is pending after a Z_FINISH */ + /* seek request */ + z_off64_t skip; /* amount to skip (already rewound if backwards) */ + int seek; /* true if seek request pending */ + /* error information */ + int err; /* error code */ + char *msg; /* error message */ + /* zlib inflate or deflate stream */ + PREFIX3(stream) strm; /* stream structure in-place (not a pointer) */ +} gz_state; +typedef gz_state *gz_statep; + +/* shared functions */ +void Z_INTERNAL gz_error(gz_state *, int, const char *); + +/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t + value -- needed when comparing unsigned to z_off64_t, which is signed + (possible z_off64_t types off_t, off64_t, and long are all signed) */ +#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) + +#endif /* GZGUTS_H_ */ diff --git a/3rdparty/zlib-ng/gzlib.c b/3rdparty/zlib-ng/gzlib.c new file mode 100644 index 000000000000..e613837efb52 --- /dev/null +++ b/3rdparty/zlib-ng/gzlib.c @@ -0,0 +1,525 @@ +/* gzlib.c -- zlib functions common to reading and writing gzip files + * Copyright (C) 2004-2019 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "zutil_p.h" +#include "gzguts.h" + +#if defined(_WIN32) +# define LSEEK _lseeki64 +#else +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define LSEEK lseek64 +#else +# define LSEEK lseek +#endif +#endif + +/* Local functions */ +static void gz_reset(gz_state *); +static gzFile gz_open(const void *, int, const char *); + +/* Reset gzip file state */ +static void gz_reset(gz_state *state) { + state->x.have = 0; /* no output data available */ + if (state->mode == GZ_READ) { /* for reading ... */ + state->eof = 0; /* not at end of file */ + state->past = 0; /* have not read past end yet */ + state->how = LOOK; /* look for gzip header */ + } + else /* for writing ... */ + state->reset = 0; /* no deflateReset pending */ + state->seek = 0; /* no seek request pending */ + gz_error(state, Z_OK, NULL); /* clear error */ + state->x.pos = 0; /* no uncompressed data yet */ + state->strm.avail_in = 0; /* no input data yet */ +} + +/* Open a gzip file either by name or file descriptor. */ +static gzFile gz_open(const void *path, int fd, const char *mode) { + gz_state *state; + size_t len; + int oflag; +#ifdef O_CLOEXEC + int cloexec = 0; +#endif +#ifdef O_EXCL + int exclusive = 0; +#endif + + /* check input */ + if (path == NULL) + return NULL; + + /* allocate gzFile structure to return */ + state = (gz_state *)zng_alloc(sizeof(gz_state)); + if (state == NULL) + return NULL; + state->size = 0; /* no buffers allocated yet */ + state->want = GZBUFSIZE; /* requested buffer size */ + state->msg = NULL; /* no error message yet */ + + /* interpret mode */ + state->mode = GZ_NONE; + state->level = Z_DEFAULT_COMPRESSION; + state->strategy = Z_DEFAULT_STRATEGY; + state->direct = 0; + while (*mode) { + if (*mode >= '0' && *mode <= '9') { + state->level = *mode - '0'; + } else { + switch (*mode) { + case 'r': + state->mode = GZ_READ; + break; +#ifndef NO_GZCOMPRESS + case 'w': + state->mode = GZ_WRITE; + break; + case 'a': + state->mode = GZ_APPEND; + break; +#endif + case '+': /* can't read and write at the same time */ + zng_free(state); + return NULL; + case 'b': /* ignore -- will request binary anyway */ + break; +#ifdef O_CLOEXEC + case 'e': + cloexec = 1; + break; +#endif +#ifdef O_EXCL + case 'x': + exclusive = 1; + break; +#endif + case 'f': + state->strategy = Z_FILTERED; + break; + case 'h': + state->strategy = Z_HUFFMAN_ONLY; + break; + case 'R': + state->strategy = Z_RLE; + break; + case 'F': + state->strategy = Z_FIXED; + break; + case 'T': + state->direct = 1; + break; + default: /* could consider as an error, but just ignore */ + {} + } + } + mode++; + } + + /* must provide an "r", "w", or "a" */ + if (state->mode == GZ_NONE) { + zng_free(state); + return NULL; + } + + /* can't force transparent read */ + if (state->mode == GZ_READ) { + if (state->direct) { + zng_free(state); + return NULL; + } + state->direct = 1; /* for empty file */ + } + + /* save the path name for error messages */ +#ifdef WIDECHAR + if (fd == -2) { + len = wcstombs(NULL, (const wchar_t *)path, 0); + if (len == (size_t)-1) + len = 0; + } else +#endif + len = strlen((const char *)path); + state->path = (char *)malloc(len + 1); + if (state->path == NULL) { + zng_free(state); + return NULL; + } +#ifdef WIDECHAR + if (fd == -2) + if (len) { + wcstombs(state->path, (const wchar_t *)path, len + 1); + } else { + *(state->path) = 0; + } + else +#endif + (void)snprintf(state->path, len + 1, "%s", (const char *)path); + + /* compute the flags for open() */ + oflag = +#ifdef O_LARGEFILE + O_LARGEFILE | +#endif +#ifdef O_BINARY + O_BINARY | +#endif +#ifdef O_CLOEXEC + (cloexec ? O_CLOEXEC : 0) | +#endif + (state->mode == GZ_READ ? + O_RDONLY : + (O_WRONLY | O_CREAT | +#ifdef O_EXCL + (exclusive ? O_EXCL : 0) | +#endif + (state->mode == GZ_WRITE ? + O_TRUNC : + O_APPEND))); + + /* open the file with the appropriate flags (or just use fd) */ + state->fd = fd > -1 ? fd : ( +#if defined(_WIN32) + fd == -2 ? _wopen((const wchar_t *)path, oflag, 0666) : +#elif __CYGWIN__ + fd == -2 ? open(state->path, oflag, 0666) : +#endif + open((const char *)path, oflag, 0666)); + if (state->fd == -1) { + free(state->path); + zng_free(state); + return NULL; + } + if (state->mode == GZ_APPEND) { + LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ + state->mode = GZ_WRITE; /* simplify later checks */ + } + + /* save the current position for rewinding (only if reading) */ + if (state->mode == GZ_READ) { + state->start = LSEEK(state->fd, 0, SEEK_CUR); + if (state->start == -1) state->start = 0; + } + + /* initialize stream */ + gz_reset(state); + + /* return stream */ + return (gzFile)state; +} + +/* -- see zlib.h -- */ +gzFile Z_EXPORT PREFIX(gzopen)(const char *path, const char *mode) { + return gz_open(path, -1, mode); +} + +#ifdef ZLIB_COMPAT +gzFile Z_EXPORT PREFIX4(gzopen)(const char *path, const char *mode) { + return gz_open(path, -1, mode); +} +#endif + +/* -- see zlib.h -- */ +gzFile Z_EXPORT PREFIX(gzdopen)(int fd, const char *mode) { + char *path; /* identifier for error messages */ + gzFile gz; + + if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) + return NULL; + (void)snprintf(path, 7 + 3 * sizeof(int), "", fd); /* for debugging */ + gz = gz_open(path, fd, mode); + free(path); + return gz; +} + +/* -- see zlib.h -- */ +#ifdef WIDECHAR +gzFile Z_EXPORT PREFIX(gzopen_w)(const wchar_t *path, const char *mode) { + return gz_open(path, -2, mode); +} +#endif + +int Z_EXPORT PREFIX(gzclose)(gzFile file) { +#ifndef NO_GZCOMPRESS + gz_state *state; + + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_state *)file; + + return state->mode == GZ_READ ? PREFIX(gzclose_r)(file) : PREFIX(gzclose_w)(file); +#else + return PREFIX(gzclose_r)(file); +#endif +} + +/* -- see zlib.h -- */ +int Z_EXPORT PREFIX(gzbuffer)(gzFile file, unsigned size) { + gz_state *state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_state *)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* make sure we haven't already allocated memory */ + if (state->size != 0) + return -1; + + /* check and set requested size */ + if ((size << 1) < size) + return -1; /* need to be able to double it */ + if (size < 8) + size = 8; /* needed to behave well with flushing */ + state->want = size; + return 0; +} + +/* -- see zlib.h -- */ +int Z_EXPORT PREFIX(gzrewind)(gzFile file) { + gz_state *state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_state *)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* back up and start over */ + if (LSEEK(state->fd, state->start, SEEK_SET) == -1) + return -1; + gz_reset(state); + return 0; +} + +/* -- see zlib.h -- */ +z_off64_t Z_EXPORT PREFIX4(gzseek)(gzFile file, z_off64_t offset, int whence) { + unsigned n; + z_off64_t ret; + gz_state *state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_state *)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* check that there's no error */ + if (state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + + /* can only seek from start or relative to current position */ + if (whence != SEEK_SET && whence != SEEK_CUR) + return -1; + + /* normalize offset to a SEEK_CUR specification */ + if (whence == SEEK_SET) + offset -= state->x.pos; + else if (state->seek) + offset += state->skip; + state->seek = 0; + + /* if within raw area while reading, just go there */ + if (state->mode == GZ_READ && state->how == COPY && state->x.pos + offset >= 0) { + ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR); + if (ret == -1) + return -1; + state->x.have = 0; + state->eof = 0; + state->past = 0; + state->seek = 0; + gz_error(state, Z_OK, NULL); + state->strm.avail_in = 0; + state->x.pos += offset; + return state->x.pos; + } + + /* calculate skip amount, rewinding if needed for back seek when reading */ + if (offset < 0) { + if (state->mode != GZ_READ) /* writing -- can't go backwards */ + return -1; + offset += state->x.pos; + if (offset < 0) /* before start of file! */ + return -1; + if (PREFIX(gzrewind)(file) == -1) /* rewind, then skip to offset */ + return -1; + } + + /* if reading, skip what's in output buffer (one less gzgetc() check) */ + if (state->mode == GZ_READ) { + n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? (unsigned)offset : state->x.have; + state->x.have -= n; + state->x.next += n; + state->x.pos += n; + offset -= n; + } + + /* request skip (if not zero) */ + if (offset) { + state->seek = 1; + state->skip = offset; + } + return state->x.pos + offset; +} + +/* -- see zlib.h -- */ +#ifdef ZLIB_COMPAT +z_off_t Z_EXPORT PREFIX(gzseek)(gzFile file, z_off_t offset, int whence) { + z_off64_t ret; + + ret = PREFIX4(gzseek)(file, (z_off64_t)offset, whence); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} +#endif + +/* -- see zlib.h -- */ +z_off64_t Z_EXPORT PREFIX4(gztell)(gzFile file) { + gz_state *state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_state *)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* return position */ + return state->x.pos + (state->seek ? state->skip : 0); +} + +/* -- see zlib.h -- */ +#ifdef ZLIB_COMPAT +z_off_t Z_EXPORT PREFIX(gztell)(gzFile file) { + + z_off64_t ret; + + ret = PREFIX4(gztell)(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} +#endif + +/* -- see zlib.h -- */ +z_off64_t Z_EXPORT PREFIX4(gzoffset)(gzFile file) { + z_off64_t offset; + gz_state *state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_state *)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* compute and return effective offset in file */ + offset = LSEEK(state->fd, 0, SEEK_CUR); + if (offset == -1) + return -1; + if (state->mode == GZ_READ) /* reading */ + offset -= state->strm.avail_in; /* don't count buffered input */ + return offset; +} + +/* -- see zlib.h -- */ +#ifdef ZLIB_COMPAT +z_off_t Z_EXPORT PREFIX(gzoffset)(gzFile file) { + z_off64_t ret; + + ret = PREFIX4(gzoffset)(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} +#endif + +/* -- see zlib.h -- */ +int Z_EXPORT PREFIX(gzeof)(gzFile file) { + gz_state *state; + + /* get internal structure and check integrity */ + if (file == NULL) + return 0; + state = (gz_state *)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return 0; + + /* return end-of-file state */ + return state->mode == GZ_READ ? state->past : 0; +} + +/* -- see zlib.h -- */ +const char * Z_EXPORT PREFIX(gzerror)(gzFile file, int *errnum) { + gz_state *state; + + /* get internal structure and check integrity */ + if (file == NULL) + return NULL; + state = (gz_state *)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return NULL; + + /* return error information */ + if (errnum != NULL) + *errnum = state->err; + return state->err == Z_MEM_ERROR ? "out of memory" : (state->msg == NULL ? "" : state->msg); +} + +/* -- see zlib.h -- */ +void Z_EXPORT PREFIX(gzclearerr)(gzFile file) { + gz_state *state; + + /* get internal structure and check integrity */ + if (file == NULL) + return; + state = (gz_state *)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return; + + /* clear error and end-of-file */ + if (state->mode == GZ_READ) { + state->eof = 0; + state->past = 0; + } + gz_error(state, Z_OK, NULL); +} + +/* Create an error message in allocated memory and set state->err and + state->msg accordingly. Free any previous error message already there. Do + not try to free or allocate space if the error is Z_MEM_ERROR (out of + memory). Simply save the error message as a static string. If there is an + allocation failure constructing the error message, then convert the error to + out of memory. */ +void Z_INTERNAL gz_error(gz_state *state, int err, const char *msg) { + /* free previously allocated message and clear */ + if (state->msg != NULL) { + if (state->err != Z_MEM_ERROR) + free(state->msg); + state->msg = NULL; + } + + /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ + if (err != Z_OK && err != Z_BUF_ERROR) + state->x.have = 0; + + /* set error code, and if no message, then done */ + state->err = err; + if (msg == NULL) + return; + + /* for an out of memory error, return literal string when requested */ + if (err == Z_MEM_ERROR) + return; + + /* construct error message with path */ + if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { + state->err = Z_MEM_ERROR; + return; + } + (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, "%s%s%s", state->path, ": ", msg); +} diff --git a/3rdparty/zlib-ng/gzread.c.in b/3rdparty/zlib-ng/gzread.c.in new file mode 100644 index 000000000000..1fc7b370fde3 --- /dev/null +++ b/3rdparty/zlib-ng/gzread.c.in @@ -0,0 +1,606 @@ +/* gzread.c -- zlib functions for reading gzip files + * Copyright (C) 2004-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "zutil_p.h" +#include "gzguts.h" + +/* Local functions */ +static int gz_load(gz_state *, unsigned char *, unsigned, unsigned *); +static int gz_avail(gz_state *); +static int gz_look(gz_state *); +static int gz_decomp(gz_state *); +static int gz_fetch(gz_state *); +static int gz_skip(gz_state *, z_off64_t); +static size_t gz_read(gz_state *, void *, size_t); + +/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from + state->fd, and update state->eof, state->err, and state->msg as appropriate. + This function needs to loop on read(), since read() is not guaranteed to + read the number of bytes requested, depending on the type of descriptor. */ +static int gz_load(gz_state *state, unsigned char *buf, unsigned len, unsigned *have) { + ssize_t ret; + + *have = 0; + do { + ret = read(state->fd, buf + *have, len - *have); + if (ret <= 0) + break; + *have += (unsigned)ret; + } while (*have < len); + if (ret < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + if (ret == 0) + state->eof = 1; + return 0; +} + +/* Load up input buffer and set eof flag if last data loaded -- return -1 on + error, 0 otherwise. Note that the eof flag is set when the end of the input + file is reached, even though there may be unused data in the buffer. Once + that data has been used, no more attempts will be made to read the file. + If strm->avail_in != 0, then the current data is moved to the beginning of + the input buffer, and then the remainder of the buffer is loaded with the + available data from the input file. */ +static int gz_avail(gz_state *state) { + unsigned got; + PREFIX3(stream) *strm = &(state->strm); + + if (state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + if (state->eof == 0) { + if (strm->avail_in) { /* copy what's there to the start */ + unsigned char *p = state->in; + unsigned const char *q = strm->next_in; + unsigned n = strm->avail_in; + do { + *p++ = *q++; + } while (--n); + } + if (gz_load(state, state->in + strm->avail_in, state->size - strm->avail_in, &got) == -1) + return -1; + strm->avail_in += got; + strm->next_in = state->in; + } + return 0; +} + +/* Look for gzip header, set up for inflate or copy. state->x.have must be 0. + If this is the first time in, allocate required memory. state->how will be + left unchanged if there is no more input data available, will be set to COPY + if there is no gzip header and direct copying will be performed, or it will + be set to GZIP for decompression. If direct copying, then leftover input + data from the input buffer will be copied to the output buffer. In that + case, all further file reads will be directly to either the output buffer or + a user buffer. If decompressing, the inflate state will be initialized. + gz_look() will return 0 on success or -1 on failure. */ +static int gz_look(gz_state *state) { + PREFIX3(stream) *strm = &(state->strm); + + /* allocate read buffers and inflate memory */ + if (state->size == 0) { + /* allocate buffers */ + state->in = (unsigned char *)zng_alloc(state->want); + state->out = (unsigned char *)zng_alloc(state->want << 1); + if (state->in == NULL || state->out == NULL) { + zng_free(state->out); + zng_free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + state->size = state->want; + + /* allocate inflate memory */ + state->strm.zalloc = NULL; + state->strm.zfree = NULL; + state->strm.opaque = NULL; + state->strm.avail_in = 0; + state->strm.next_in = NULL; + if (PREFIX(inflateInit2)(&(state->strm), MAX_WBITS + 16) != Z_OK) { /* gunzip */ + zng_free(state->out); + zng_free(state->in); + state->size = 0; + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + } + + /* get at least the magic bytes in the input buffer */ + if (strm->avail_in < 2) { + if (gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) + return 0; + } + + /* look for gzip magic bytes -- if there, do gzip decoding (note: there is + a logical dilemma here when considering the case of a partially written + gzip file, to wit, if a single 31 byte is written, then we cannot tell + whether this is a single-byte file, or just a partially written gzip + file -- for here we assume that if a gzip file is being written, then + the header will be written in a single operation, so that reading a + single byte is sufficient indication that it is not a gzip file) */ + if (strm->avail_in > 1 && + strm->next_in[0] == 31 && strm->next_in[1] == 139) { + PREFIX(inflateReset)(strm); + state->how = GZIP; + state->direct = 0; + return 0; + } + + /* no gzip header -- if we were decoding gzip before, then this is trailing + garbage. Ignore the trailing garbage and finish. */ + if (state->direct == 0) { + strm->avail_in = 0; + state->eof = 1; + state->x.have = 0; + return 0; + } + + /* doing raw i/o, copy any leftover input to output -- this assumes that + the output buffer is larger than the input buffer, which also assures + space for gzungetc() */ + state->x.next = state->out; + memcpy(state->x.next, strm->next_in, strm->avail_in); + state->x.have = strm->avail_in; + strm->avail_in = 0; + state->how = COPY; + state->direct = 1; + return 0; +} + +/* Decompress from input to the provided next_out and avail_out in the state. + On return, state->x.have and state->x.next point to the just decompressed + data. If the gzip stream completes, state->how is reset to LOOK to look for + the next gzip stream or raw data, once state->x.have is depleted. Returns 0 + on success, -1 on failure. */ +static int gz_decomp(gz_state *state) { + int ret = Z_OK; + unsigned had; + PREFIX3(stream) *strm = &(state->strm); + + /* fill output buffer up to end of deflate stream */ + had = strm->avail_out; + do { + /* get more input for inflate() */ + if (strm->avail_in == 0 && gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) { + gz_error(state, Z_BUF_ERROR, "unexpected end of file"); + break; + } + + /* decompress and handle errors */ + ret = PREFIX(inflate)(strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { + gz_error(state, Z_STREAM_ERROR, "internal error: inflate stream corrupt"); + return -1; + } + if (ret == Z_MEM_ERROR) { + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ + gz_error(state, Z_DATA_ERROR, strm->msg == NULL ? "compressed data error" : strm->msg); + return -1; + } + } while (strm->avail_out && ret != Z_STREAM_END); + + /* update available output */ + state->x.have = had - strm->avail_out; + state->x.next = strm->next_out - state->x.have; + + /* if the gzip stream completed successfully, look for another */ + if (ret == Z_STREAM_END) + state->how = LOOK; + + /* good decompression */ + return 0; +} + +/* Fetch data and put it in the output buffer. Assumes state->x.have is 0. + Data is either copied from the input file or decompressed from the input + file depending on state->how. If state->how is LOOK, then a gzip header is + looked for to determine whether to copy or decompress. Returns -1 on error, + otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the + end of the input file has been reached and all data has been processed. */ +static int gz_fetch(gz_state *state) { + PREFIX3(stream) *strm = &(state->strm); + + do { + switch (state->how) { + case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ + if (gz_look(state) == -1) + return -1; + if (state->how == LOOK) + return 0; + break; + case COPY: /* -> COPY */ + if (gz_load(state, state->out, state->size << 1, &(state->x.have)) + == -1) + return -1; + state->x.next = state->out; + return 0; + case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ + strm->avail_out = state->size << 1; + strm->next_out = state->out; + if (gz_decomp(state) == -1) + return -1; + } + } while (state->x.have == 0 && (!state->eof || strm->avail_in)); + return 0; +} + +/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ +static int gz_skip(gz_state *state, z_off64_t len) { + unsigned n; + + /* skip over len bytes or reach end-of-file, whichever comes first */ + while (len) + /* skip over whatever is in output buffer */ + if (state->x.have) { + n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? + (unsigned)len : state->x.have; + state->x.have -= n; + state->x.next += n; + state->x.pos += n; + len -= n; + } else if (state->eof && state->strm.avail_in == 0) { + /* output buffer empty -- return if we're at the end of the input */ + break; + } else { + /* need more data to skip -- load up output buffer */ + /* get more output, looking for header if required */ + if (gz_fetch(state) == -1) + return -1; + } + return 0; +} + +/* Read len bytes into buf from file, or less than len up to the end of the + input. Return the number of bytes read. If zero is returned, either the + end of file was reached, or there was an error. state->err must be + consulted in that case to determine which. */ +static size_t gz_read(gz_state *state, void *buf, size_t len) { + size_t got; + unsigned n; + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return 0; + } + + /* get len bytes to buf, or less than len if at the end */ + got = 0; + do { + /* set n to the maximum amount of len that fits in an unsigned int */ + n = (unsigned)-1; + if (n > len) + n = (unsigned)len; + + /* first just try copying data from the output buffer */ + if (state->x.have) { + if (state->x.have < n) + n = state->x.have; + memcpy(buf, state->x.next, n); + state->x.next += n; + state->x.have -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && state->strm.avail_in == 0) { + state->past = 1; /* tried to read past end */ + break; + } + + /* need output data -- for small len or new stream load up our output + buffer */ + else if (state->how == LOOK || n < (state->size << 1)) { + /* get more output, looking for header if required */ + if (gz_fetch(state) == -1) + return 0; + continue; /* no progress yet -- go back to copy above */ + /* the copy above assures that we will leave with space in the + output buffer, allowing at least one gzungetc() to succeed */ + } + + /* large len -- read directly into user buffer */ + else if (state->how == COPY) { /* read directly */ + if (gz_load(state, (unsigned char *)buf, n, &n) == -1) + return 0; + } + + /* large len -- decompress directly into user buffer */ + else { /* state->how == GZIP */ + state->strm.avail_out = n; + state->strm.next_out = (unsigned char *)buf; + if (gz_decomp(state) == -1) + return 0; + n = state->x.have; + state->x.have = 0; + } + + /* update progress */ + len -= n; + buf = (char *)buf + n; + got += n; + state->x.pos += n; + } while (len); + + /* return number of bytes read into user buffer */ + return got; +} + +/* -- see zlib.h -- */ +int Z_EXPORT PREFIX(gzread)(gzFile file, void *buf, unsigned len) { + gz_state *state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_state *)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids a flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); + return -1; + } + + /* read len or fewer bytes to buf */ + len = (unsigned)gz_read(state, buf, len); + + /* check for an error */ + if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + + /* return the number of bytes read (this is assured to fit in an int) */ + return (int)len; +} + +/* -- see zlib.h -- */ +size_t Z_EXPORT PREFIX(gzfread)(void *buf, size_t size, size_t nitems, gzFile file) { + size_t len; + gz_state *state; + + /* Exit early if size is zero, also prevents potential division by zero */ + if (size == 0) + return 0; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_state *)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return 0; + + /* compute bytes to read -- error on overflow */ + if (size && SIZE_MAX / size < nitems) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); + return 0; + } + len = nitems * size; + + /* read len or fewer bytes to buf, return the number of full items read */ + return len ? gz_read(state, buf, len) / size : 0; +} + +/* -- see zlib.h -- */ +#undef @ZLIB_SYMBOL_PREFIX@gzgetc +#undef @ZLIB_SYMBOL_PREFIX@zng_gzgetc +int Z_EXPORT PREFIX(gzgetc)(gzFile file) { + unsigned char buf[1]; + gz_state *state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_state *)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* try output buffer (no need to check for skip request) */ + if (state->x.have) { + state->x.have--; + state->x.pos++; + return *(state->x.next)++; + } + + /* nothing there -- try gz_read() */ + return gz_read(state, buf, 1) < 1 ? -1 : buf[0]; +} + +#ifdef ZLIB_COMPAT +int Z_EXPORT PREFIX(gzgetc_)(gzFile file) { + return PREFIX(gzgetc)(file); +} +#endif + +/* -- see zlib.h -- */ +int Z_EXPORT PREFIX(gzungetc)(int c, gzFile file) { + gz_state *state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_state *)file; + + /* in case this was just opened, set up the input buffer */ + if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) + (void)gz_look(state); + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* can't push EOF */ + if (c < 0) + return -1; + + /* if output buffer empty, put byte at end (allows more pushing) */ + if (state->x.have == 0) { + state->x.have = 1; + state->x.next = state->out + (state->size << 1) - 1; + state->x.next[0] = (unsigned char)c; + state->x.pos--; + state->past = 0; + return c; + } + + /* if no room, give up (must have already done a gzungetc()) */ + if (state->x.have == (state->size << 1)) { + gz_error(state, Z_DATA_ERROR, "out of room to push characters"); + return -1; + } + + /* slide output data if needed and insert byte before existing data */ + if (state->x.next == state->out) { + unsigned char *src = state->out + state->x.have; + unsigned char *dest = state->out + (state->size << 1); + while (src > state->out) + *--dest = *--src; + state->x.next = dest; + } + state->x.have++; + state->x.next--; + state->x.next[0] = (unsigned char)c; + state->x.pos--; + state->past = 0; + return c; +} + +/* -- see zlib.h -- */ +char * Z_EXPORT PREFIX(gzgets)(gzFile file, char *buf, int len) { + unsigned left, n; + char *str; + unsigned char *eol; + gz_state *state; + + /* check parameters and get internal structure */ + if (file == NULL || buf == NULL || len < 1) + return NULL; + state = (gz_state *)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return NULL; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return NULL; + } + + /* copy output bytes up to new line or len - 1, whichever comes first -- + append a terminating zero to the string (we don't check for a zero in + the contents, let the user worry about that) */ + str = buf; + left = (unsigned)len - 1; + if (left) { + do { + /* assure that something is in the output buffer */ + if (state->x.have == 0 && gz_fetch(state) == -1) + return NULL; /* error */ + if (state->x.have == 0) { /* end of file */ + state->past = 1; /* read past end */ + break; /* return what we have */ + } + + /* look for end-of-line in current output buffer */ + n = state->x.have > left ? left : state->x.have; + eol = (unsigned char *)memchr(state->x.next, '\n', n); + if (eol != NULL) + n = (unsigned)(eol - state->x.next) + 1; + + /* copy through end-of-line, or remainder if not found */ + memcpy(buf, state->x.next, n); + state->x.have -= n; + state->x.next += n; + state->x.pos += n; + left -= n; + buf += n; + } while (left && eol == NULL); + } + + /* return terminated string, or if nothing, end of file */ + if (buf == str) + return NULL; + buf[0] = 0; + return str; +} + +/* -- see zlib.h -- */ +int Z_EXPORT PREFIX(gzdirect)(gzFile file) { + gz_state *state; + + /* get internal structure */ + if (file == NULL) + return 0; + + state = (gz_state *)file; + + /* if the state is not known, but we can find out, then do so (this is + mainly for right after a gzopen() or gzdopen()) */ + if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) + (void)gz_look(state); + + /* return 1 if transparent, 0 if processing a gzip stream */ + return state->direct; +} + +/* -- see zlib.h -- */ +int Z_EXPORT PREFIX(gzclose_r)(gzFile file) { + int ret, err; + gz_state *state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + + state = (gz_state *)file; + + /* check that we're reading */ + if (state->mode != GZ_READ) + return Z_STREAM_ERROR; + + /* free memory and close file */ + if (state->size) { + PREFIX(inflateEnd)(&(state->strm)); + zng_free(state->out); + zng_free(state->in); + } + err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; + gz_error(state, Z_OK, NULL); + free(state->path); + ret = close(state->fd); + zng_free(state); + return ret ? Z_ERRNO : err; +} diff --git a/3rdparty/zlib-ng/gzwrite.c b/3rdparty/zlib-ng/gzwrite.c new file mode 100644 index 000000000000..08e0ce9aab2a --- /dev/null +++ b/3rdparty/zlib-ng/gzwrite.c @@ -0,0 +1,526 @@ +/* gzwrite.c -- zlib functions for writing gzip files + * Copyright (C) 2004-2019 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "zutil_p.h" +#include +#include "gzguts.h" + +/* Local functions */ +static int gz_init(gz_state *); +static int gz_comp(gz_state *, int); +static int gz_zero(gz_state *, z_off64_t); +static size_t gz_write(gz_state *, void const *, size_t); + +/* Initialize state for writing a gzip file. Mark initialization by setting + state->size to non-zero. Return -1 on a memory allocation failure, or 0 on + success. */ +static int gz_init(gz_state *state) { + int ret; + PREFIX3(stream) *strm = &(state->strm); + + /* allocate input buffer (double size for gzprintf) */ + state->in = (unsigned char *)zng_alloc(state->want << 1); + if (state->in == NULL) { + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + memset(state->in, 0, state->want << 1); + + /* only need output buffer and deflate state if compressing */ + if (!state->direct) { + /* allocate output buffer */ + state->out = (unsigned char *)zng_alloc(state->want); + if (state->out == NULL) { + zng_free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* allocate deflate memory, set up for gzip compression */ + strm->zalloc = NULL; + strm->zfree = NULL; + strm->opaque = NULL; + ret = PREFIX(deflateInit2)(strm, state->level, Z_DEFLATED, MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); + if (ret != Z_OK) { + zng_free(state->out); + zng_free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + strm->next_in = NULL; + } + + /* mark state as initialized */ + state->size = state->want; + + /* initialize write buffer if compressing */ + if (!state->direct) { + strm->avail_out = state->size; + strm->next_out = state->out; + state->x.next = strm->next_out; + } + return 0; +} + +/* Compress whatever is at avail_in and next_in and write to the output file. + Return -1 if there is an error writing to the output file or if gz_init() + fails to allocate memory, otherwise 0. flush is assumed to be a valid + deflate() flush value. If flush is Z_FINISH, then the deflate() state is + reset to start a new gzip stream. If gz->direct is true, then simply write + to the output file without compressing, and ignore flush. */ +static int gz_comp(gz_state *state, int flush) { + int ret; + ssize_t got; + unsigned have; + PREFIX3(stream) *strm = &(state->strm); + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return -1; + + /* write directly if requested */ + if (state->direct) { + got = write(state->fd, strm->next_in, strm->avail_in); + if (got < 0 || (unsigned)got != strm->avail_in) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + strm->avail_in = 0; + return 0; + } + + /* check for a pending reset */ + if (state->reset) { + /* don't start a new gzip member unless there is data to write */ + if (strm->avail_in == 0) + return 0; + PREFIX(deflateReset)(strm); + state->reset = 0; + } + + /* run deflate() on provided input until it produces no more output */ + ret = Z_OK; + do { + /* write out current buffer contents if full, or if flushing, but if + doing Z_FINISH then don't write until we get to Z_STREAM_END */ + if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) { + have = (unsigned)(strm->next_out - state->x.next); + if (have && ((got = write(state->fd, state->x.next, (unsigned long)have)) < 0 || (unsigned)got != have)) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + if (strm->avail_out == 0) { + strm->avail_out = state->size; + strm->next_out = state->out; + state->x.next = state->out; + } + state->x.next = strm->next_out; + } + + /* compress */ + have = strm->avail_out; + ret = PREFIX(deflate)(strm, flush); + if (ret == Z_STREAM_ERROR) { + gz_error(state, Z_STREAM_ERROR, "internal error: deflate stream corrupt"); + return -1; + } + have -= strm->avail_out; + } while (have); + + /* if that completed a deflate stream, allow another to start */ + if (flush == Z_FINISH) + state->reset = 1; + /* all done, no errors */ + return 0; +} + +/* Compress len zeros to output. Return -1 on a write error or memory + allocation failure by gz_comp(), or 0 on success. */ +static int gz_zero(gz_state *state, z_off64_t len) { + int first; + unsigned n; + PREFIX3(stream) *strm = &(state->strm); + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + + /* compress len zeros (len guaranteed > 0) */ + first = 1; + while (len) { + n = GT_OFF(state->size) || (z_off64_t)state->size > len ? (unsigned)len : state->size; + if (first) { + memset(state->in, 0, n); + first = 0; + } + strm->avail_in = n; + strm->next_in = state->in; + state->x.pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + len -= n; + } + return 0; +} + +/* Write len bytes from buf to file. Return the number of bytes written. If + the returned value is less than len, then there was an error. */ +static size_t gz_write(gz_state *state, void const *buf, size_t len) { + size_t put = len; + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* for small len, copy to input buffer, otherwise compress directly */ + if (len < state->size) { + /* copy to input buffer, compress when full */ + do { + unsigned have, copy; + + if (state->strm.avail_in == 0) + state->strm.next_in = state->in; + have = (unsigned)((state->strm.next_in + state->strm.avail_in) - + state->in); + copy = state->size - have; + if (copy > len) + copy = (unsigned)len; + memcpy(state->in + have, buf, copy); + state->strm.avail_in += copy; + state->x.pos += copy; + buf = (const char *)buf + copy; + len -= copy; + if (len && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } while (len); + } else { + /* consume whatever's left in the input buffer */ + if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* directly compress user buffer to file */ + state->strm.next_in = (z_const unsigned char *) buf; + do { + unsigned n = (unsigned)-1; + if (n > len) + n = (unsigned)len; + state->strm.avail_in = n; + state->x.pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + len -= n; + } while (len); + } + + /* input was all buffered or compressed */ + return put; +} + +/* -- see zlib.h -- */ +int Z_EXPORT PREFIX(gzwrite)(gzFile file, void const *buf, unsigned len) { + gz_state *state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_state *)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids a flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); + return 0; + } + + /* write len bytes from buf (the return value will fit in an int) */ + return (int)gz_write(state, buf, len); +} + +/* -- see zlib.h -- */ +size_t Z_EXPORT PREFIX(gzfwrite)(void const *buf, size_t size, size_t nitems, gzFile file) { + size_t len; + gz_state *state; + + /* Exit early if size is zero, also prevents potential division by zero */ + if (size == 0) + return 0; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_state *)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* compute bytes to read -- error on overflow */ + len = nitems * size; + if (len / size != nitems) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); + return 0; + } + + /* write len bytes to buf, return the number of full items written */ + return len ? gz_write(state, buf, len) / size : 0; +} + +/* -- see zlib.h -- */ +int Z_EXPORT PREFIX(gzputc)(gzFile file, int c) { + unsigned have; + unsigned char buf[1]; + gz_state *state; + PREFIX3(stream) *strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_state *)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* try writing to input buffer for speed (state->size == 0 if buffer not + initialized) */ + if (state->size) { + if (strm->avail_in == 0) + strm->next_in = state->in; + have = (unsigned)((strm->next_in + strm->avail_in) - state->in); + if (have < state->size) { + state->in[have] = (unsigned char)c; + strm->avail_in++; + state->x.pos++; + return c & 0xff; + } + } + + /* no room in buffer or not initialized, use gz_write() */ + buf[0] = (unsigned char)c; + if (gz_write(state, buf, 1) != 1) + return -1; + return c & 0xff; +} + +/* -- see zlib.h -- */ +int Z_EXPORT PREFIX(gzputs)(gzFile file, const char *s) { + size_t len, put; + gz_state *state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_state *)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; + + /* write string */ + len = strlen(s); + if ((int)len < 0 || (unsigned)len != len) { + gz_error(state, Z_STREAM_ERROR, "string length does not fit in int"); + return -1; + } + put = gz_write(state, s, len); + return put < len ? -1 : (int)len; +} + +/* -- see zlib.h -- */ +int Z_EXPORTVA PREFIX(gzvprintf)(gzFile file, const char *format, va_list va) { + int len; + unsigned left; + char *next; + gz_state *state; + PREFIX3(stream) *strm; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_state *)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return state->err; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return state->err; + } + + /* do the printf() into the input buffer, put length in len -- the input + buffer is double-sized just for this function, so there is guaranteed to + be state->size bytes available after the current contents */ + if (strm->avail_in == 0) + strm->next_in = state->in; + next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in); + next[state->size - 1] = 0; + len = vsnprintf(next, state->size, format, va); + + /* check that printf() results fit in buffer */ + if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0) + return 0; + + /* update buffer and position, compress first half if past that */ + strm->avail_in += (unsigned)len; + state->x.pos += len; + if (strm->avail_in >= state->size) { + left = strm->avail_in - state->size; + strm->avail_in = state->size; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return state->err; + memmove(state->in, state->in + state->size, left); + strm->next_in = state->in; + strm->avail_in = left; + } + return len; +} + +int Z_EXPORTVA PREFIX(gzprintf)(gzFile file, const char *format, ...) { + va_list va; + int ret; + + va_start(va, format); + ret = PREFIX(gzvprintf)(file, format, va); + va_end(va); + return ret; +} + +/* -- see zlib.h -- */ +int Z_EXPORT PREFIX(gzflush)(gzFile file, int flush) { + gz_state *state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_state *)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* check flush parameter */ + if (flush < 0 || flush > Z_FINISH) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return state->err; + } + + /* compress remaining data with requested flush */ + (void)gz_comp(state, flush); + return state->err; +} + +/* -- see zlib.h -- */ +int Z_EXPORT PREFIX(gzsetparams)(gzFile file, int level, int strategy) { + gz_state *state; + PREFIX3(stream) *strm; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_state *)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct) + return Z_STREAM_ERROR; + + /* if no change is requested, then do nothing */ + if (level == state->level && strategy == state->strategy) + return Z_OK; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return state->err; + } + + /* change compression parameters for subsequent input */ + if (state->size) { + /* flush previous input with previous parameters before changing */ + if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1) + return state->err; + PREFIX(deflateParams)(strm, level, strategy); + } + state->level = level; + state->strategy = strategy; + return Z_OK; +} + +/* -- see zlib.h -- */ +int Z_EXPORT PREFIX(gzclose_w)(gzFile file) { + int ret = Z_OK; + gz_state *state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_state *)file; + + /* check that we're writing */ + if (state->mode != GZ_WRITE) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + ret = state->err; + } + + /* flush, free memory, and close file */ + if (gz_comp(state, Z_FINISH) == -1) + ret = state->err; + if (state->size) { + if (!state->direct) { + (void)PREFIX(deflateEnd)(&(state->strm)); + zng_free(state->out); + } + zng_free(state->in); + } + gz_error(state, Z_OK, NULL); + free(state->path); + if (close(state->fd) == -1) + ret = Z_ERRNO; + zng_free(state); + return ret; +} diff --git a/3rdparty/zlib-ng/infback.c b/3rdparty/zlib-ng/infback.c new file mode 100644 index 000000000000..9f5042b4d3dc --- /dev/null +++ b/3rdparty/zlib-ng/infback.c @@ -0,0 +1,511 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2022 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zbuild.h" +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inflate_p.h" +#include "functable.h" + +/* Avoid conflicts with zlib.h macros */ +#ifdef ZLIB_COMPAT +# undef inflateBackInit +#endif + +/* + strm provides memory allocation functions in zalloc and zfree, or + NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + + This function is hidden in ZLIB_COMPAT builds. + */ +int32_t ZNG_CONDEXPORT PREFIX(inflateBackInit)(PREFIX3(stream) *strm, int32_t windowBits, uint8_t *window) { + struct inflate_state *state; + + if (strm == NULL || window == NULL || windowBits < MIN_WBITS || windowBits > MAX_WBITS) + return Z_STREAM_ERROR; + strm->msg = NULL; /* in case we return an error */ + if (strm->zalloc == NULL) { + strm->zalloc = PREFIX(zcalloc); + strm->opaque = NULL; + } + if (strm->zfree == NULL) + strm->zfree = PREFIX(zcfree); + state = ZALLOC_INFLATE_STATE(strm); + if (state == NULL) + return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state *)state; + state->dmax = 32768U; + state->wbits = (unsigned int)windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->wnext = 0; + state->whave = 0; + state->sane = 1; + state->chunksize = functable.chunksize(); + return Z_OK; +} + +/* Function used by zlib.h and zlib-ng version 2.0 macros */ +int32_t Z_EXPORT PREFIX(inflateBackInit_)(PREFIX3(stream) *strm, int32_t windowBits, uint8_t *window, + const char *version, int32_t stream_size) { + if (CHECK_VER_STSIZE(version, stream_size)) + return Z_VERSION_ERROR; + return PREFIX(inflateBackInit)(strm, windowBits, window); +} + +/* + Private macros for inflateBack() + Look in inflate_p.h for macros shared with inflate() +*/ + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += ((unsigned)(*next++) << bits); \ + bits += 8; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is NULL or the state was not initialized. + */ +int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in_desc, out_func out, void *out_desc) { + struct inflate_state *state; + z_const unsigned char *next; /* next input */ + unsigned char *put; /* next output */ + unsigned have, left; /* available input and output */ + uint32_t hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int32_t ret; /* return code */ + static const uint16_t order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == NULL || strm->state == NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + + /* Reset the state */ + strm->msg = NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + PREFIX(fixedtables)(state); + Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + SET_BAD("invalid block type"); + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + SET_BAD("invalid stored block lengths"); + break; + } + state->length = (uint16_t)hold; + Tracev((stderr, "inflate: stored length %u\n", state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + copy = MIN(copy, have); + copy = MIN(copy, left); + memcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + SET_BAD("too many length or distance symbols"); + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + + /* get code length code lengths (not a typo) */ + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (uint16_t)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (const code *)(state->next); + state->lenbits = 7; + ret = zng_inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); + if (ret) { + SET_BAD("invalid code lengths set"); + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + + /* get length and distance code code lengths */ + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if (here.bits <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + SET_BAD("invalid bit length repeat"); + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + SET_BAD("invalid bit length repeat"); + break; + } + while (copy) { + --copy; + state->lens[state->have++] = (uint16_t)len; + } + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) + break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + SET_BAD("invalid code -- missing end-of-block"); + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (10 and 9) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (const code *)(state->next); + state->lenbits = 10; + ret = zng_inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); + if (ret) { + SET_BAD("invalid literal/lengths set"); + break; + } + state->distcode = (const code *)(state->next); + state->distbits = 9; + ret = zng_inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + SET_BAD("invalid distances set"); + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + Z_FALLTHROUGH; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= INFLATE_FAST_MIN_HAVE && + left >= INFLATE_FAST_MIN_LEFT) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + functable.inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if (here.bits <= bits) + break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)last.bits + (unsigned)here.bits <= bits) + break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + state->length = here.val; + + /* process literal */ + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (here.op & 64) { + SET_BAD("invalid literal/length code"); + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (here.op & MAX_BITS); + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if (here.bits <= bits) + break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)last.bits + (unsigned)here.bits <= bits) + break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + if (here.op & 64) { + SET_BAD("invalid distance code"); + break; + } + state->offset = here.val; + state->extra = (here.op & MAX_BITS); + + /* get distance extra bits, if any */ + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } +#ifdef INFLATE_STRICT + if (state->offset > state->wsize - (state->whave < state->wsize ? left : 0)) { + SET_BAD("invalid distance too far back"); + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } else { + from = put - state->offset; + copy = left; + } + copy = MIN(copy, state->length); + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly */ + ret = Z_STREAM_END; + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Write leftover output and return unused input */ + inf_leave: + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left) && (ret == Z_STREAM_END)) { + ret = Z_BUF_ERROR; + } + } + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int32_t Z_EXPORT PREFIX(inflateBackEnd)(PREFIX3(stream) *strm) { + if (strm == NULL || strm->state == NULL || strm->zfree == NULL) + return Z_STREAM_ERROR; + ZFREE_STATE(strm, strm->state); + strm->state = NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/3rdparty/zlib-ng/inffast_tpl.h b/3rdparty/zlib-ng/inffast_tpl.h new file mode 100644 index 000000000000..9ddd187d8473 --- /dev/null +++ b/3rdparty/zlib-ng/inffast_tpl.h @@ -0,0 +1,326 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "zendian.h" +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inflate_p.h" +#include "functable.h" + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= INFLATE_FAST_MIN_HAVE + strm->avail_out >= INFLATE_FAST_MIN_LEFT + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - On some architectures, it can be significantly faster (e.g. up to 1.2x + faster on x86_64) to load from strm->next_in 64 bits, or 8 bytes, at a + time, so INFLATE_FAST_MIN_HAVE == 8. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { + /* start: inflate()'s starting value for strm->avail_out */ + struct inflate_state *state; + z_const unsigned char *in; /* local strm->next_in */ + const unsigned char *last; /* have enough input while in < last */ + unsigned char *out; /* local strm->next_out */ + unsigned char *beg; /* inflate()'s initial strm->next_out */ + unsigned char *end; /* while out < end, enough space available */ + unsigned char *safe; /* can use chunkcopy provided out < safe */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char *window; /* allocated sliding window, if wsize != 0 */ + + /* hold is a local copy of strm->hold. By default, hold satisfies the same + invariants that strm->hold does, namely that (hold >> bits) == 0. This + invariant is kept by loading bits into hold one byte at a time, like: + + hold |= next_byte_of_input << bits; in++; bits += 8; + + If we need to ensure that bits >= 15 then this code snippet is simply + repeated. Over one iteration of the outermost do/while loop, this + happens up to six times (48 bits of input), as described in the NOTES + above. + + However, on some little endian architectures, it can be significantly + faster to load 64 bits once instead of 8 bits six times: + + if (bits <= 16) { + hold |= next_8_bytes_of_input << bits; in += 6; bits += 48; + } + + Unlike the simpler one byte load, shifting the next_8_bytes_of_input + by bits will overflow and lose those high bits, up to 2 bytes' worth. + The conservative estimate is therefore that we have read only 6 bytes + (48 bits). Again, as per the NOTES above, 48 bits is sufficient for the + rest of the iteration, and we will not need to load another 8 bytes. + + Inside this function, we no longer satisfy (hold >> bits) == 0, but + this is not problematic, even if that overflow does not land on an 8 bit + byte boundary. Those excess bits will eventually shift down lower as the + Huffman decoder consumes input, and when new input bits need to be loaded + into the bits variable, the same input bits will be or'ed over those + existing bits. A bitwise or is idempotent: (a | b | b) equals (a | b). + Note that we therefore write that load operation as "hold |= etc" and not + "hold += etc". + + Outside that loop, at the end of the function, hold is bitwise and'ed + with (1<hold >> state->bits) == 0. + */ + uint64_t hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const *lcode; /* local strm->lencode */ + code const *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + const code *here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char *from; /* where to copy match from */ + unsigned extra_safe; /* copy chunks safely in all cases */ + + /* copy state to local variables */ + state = (struct inflate_state *)strm->state; + in = strm->next_in; + last = in + (strm->avail_in - (INFLATE_FAST_MIN_HAVE - 1)); + out = strm->next_out; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - (INFLATE_FAST_MIN_LEFT - 1)); + safe = out + strm->avail_out; +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* Detect if out and window point to the same memory allocation. In this instance it is + necessary to use safe chunk copy functions to prevent overwriting the window. If the + window is overwritten then future matches with far distances will fail to copy correctly. */ + extra_safe = (wsize != 0 && out >= window && out + INFLATE_FAST_MIN_LEFT <= window + wsize); + +#define REFILL() do { \ + hold |= load_64_bits(in, bits); \ + in += 7; \ + in -= ((bits >> 3) & 7); \ + bits |= 56; \ + } while (0) + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + REFILL(); + here = lcode + (hold & lmask); + if (here->op == 0) { + *out++ = (unsigned char)(here->val); + DROPBITS(here->bits); + here = lcode + (hold & lmask); + if (here->op == 0) { + *out++ = (unsigned char)(here->val); + DROPBITS(here->bits); + here = lcode + (hold & lmask); + } + } + dolen: + DROPBITS(here->bits); + op = here->op; + if (op == 0) { /* literal */ + Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here->val)); + *out++ = (unsigned char)(here->val); + } else if (op & 16) { /* length base */ + len = here->val; + op &= MAX_BITS; /* number of extra bits */ + len += BITS(op); + DROPBITS(op); + Tracevv((stderr, "inflate: length %u\n", len)); + here = dcode + (hold & dmask); + if (bits < MAX_BITS + MAX_DIST_EXTRA_BITS) { + REFILL(); + } + dodist: + DROPBITS(here->bits); + op = here->op; + if (op & 16) { /* distance base */ + dist = here->val; + op &= MAX_BITS; /* number of extra bits */ + dist += BITS(op); +#ifdef INFLATE_STRICT + if (dist > dmax) { + SET_BAD("invalid distance too far back"); + break; + } +#endif + DROPBITS(op); + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + SET_BAD("invalid distance too far back"); + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + *out++ = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + *out++ = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + *out++ = *from++; + } while (--len); + continue; + } +#endif + } + from = window; + if (wnext == 0) { /* very common case */ + from += wsize - op; + } else if (wnext >= op) { /* contiguous in window */ + from += wnext - op; + } else { /* wrap around window */ + op -= wnext; + from += wsize - op; + if (op < len) { /* some from end of window */ + len -= op; + out = chunkcopy_safe(out, from, op, safe); + from = window; /* more from start of window */ + op = wnext; + /* This (rare) case can create a situation where + the first chunkcopy below must be checked. + */ + } + } + if (op < len) { /* still need some from output */ + len -= op; + out = chunkcopy_safe(out, from, op, safe); + out = CHUNKUNROLL(out, &dist, &len); + out = chunkcopy_safe(out, out - dist, len, safe); + } else { + out = chunkcopy_safe(out, from, len, safe); + } + } else if (extra_safe) { + /* Whole reference is in range of current output. */ + if (dist >= len || dist >= state->chunksize) + out = chunkcopy_safe(out, out - dist, len, safe); + else + out = CHUNKMEMSET_SAFE(out, dist, len, (unsigned)((safe - out) + 1)); + } else { + /* Whole reference is in range of current output. No range checks are + necessary because we start with room for at least 258 bytes of output, + so unroll and roundoff operations can write beyond `out+len` so long + as they stay within 258 bytes of `out`. + */ + if (dist >= len || dist >= state->chunksize) + out = CHUNKCOPY(out, out - dist, len); + else + out = CHUNKMEMSET(out, dist, len); + } + } else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode + here->val + BITS(op); + goto dodist; + } else { + SET_BAD("invalid distance code"); + break; + } + } else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode + here->val + BITS(op); + goto dolen; + } else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } else { + SET_BAD("invalid literal/length code"); + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (UINT64_C(1) << bits) - 1; + + /* update state and return */ + strm->next_in = in; + strm->next_out = out; + strm->avail_in = (unsigned)(in < last ? (INFLATE_FAST_MIN_HAVE - 1) + (last - in) + : (INFLATE_FAST_MIN_HAVE - 1) - (in - last)); + strm->avail_out = (unsigned)(out < end ? (INFLATE_FAST_MIN_LEFT - 1) + (end - out) + : (INFLATE_FAST_MIN_LEFT - 1) - (out - end)); + + Assert(bits <= 32, "Remaining bits greater than 32"); + state->hold = (uint32_t)hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ diff --git a/3rdparty/zlib-ng/inffixed_tbl.h b/3rdparty/zlib-ng/inffixed_tbl.h new file mode 100644 index 000000000000..7292fa06eccd --- /dev/null +++ b/3rdparty/zlib-ng/inffixed_tbl.h @@ -0,0 +1,94 @@ +/* inffixed_tbl.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + +/* WARNING: this file should *not* be used by applications. + * It is part of the implementation of this library and is + * subject to change. Applications should only use zlib.h. + */ + +static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} +}; + +static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} +}; diff --git a/3rdparty/zlib-ng/inflate.c b/3rdparty/zlib-ng/inflate.c new file mode 100644 index 000000000000..fe55c498e312 --- /dev/null +++ b/3rdparty/zlib-ng/inflate.c @@ -0,0 +1,1413 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2022 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inflate_p.h" +#include "inffixed_tbl.h" +#include "functable.h" + +/* Avoid conflicts with zlib.h macros */ +#ifdef ZLIB_COMPAT +# undef inflateInit +# undef inflateInit2 +#endif + +/* function prototypes */ +static int inflateStateCheck(PREFIX3(stream) *strm); +static int updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t len, int32_t cksum); +static uint32_t syncsearch(uint32_t *have, const unsigned char *buf, uint32_t len); + +static inline void inf_chksum_cpy(PREFIX3(stream) *strm, uint8_t *dst, + const uint8_t *src, uint32_t copy) { + if (!copy) return; + struct inflate_state *state = (struct inflate_state*)strm->state; +#ifdef GUNZIP + if (state->flags) { + functable.crc32_fold_copy(&state->crc_fold, dst, src, copy); + } else +#endif + { + strm->adler = state->check = functable.adler32_fold_copy(state->check, dst, src, copy); + } +} + +static inline void inf_chksum(PREFIX3(stream) *strm, const uint8_t *src, uint32_t len) { + struct inflate_state *state = (struct inflate_state*)strm->state; +#ifdef GUNZIP + if (state->flags) { + functable.crc32_fold(&state->crc_fold, src, len, 0); + } else +#endif + { + strm->adler = state->check = functable.adler32(state->check, src, len); + } +} + +static int inflateStateCheck(PREFIX3(stream) *strm) { + struct inflate_state *state; + if (strm == NULL || strm->zalloc == NULL || strm->zfree == NULL) + return 1; + state = (struct inflate_state *)strm->state; + if (state == NULL || state->strm != strm || state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; +} + +int32_t Z_EXPORT PREFIX(inflateResetKeep)(PREFIX3(stream) *strm) { + struct inflate_state *state; + + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = NULL; + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; + state->mode = HEAD; + state->check = ADLER32_INITIAL_VALUE; + state->last = 0; + state->havedict = 0; + state->flags = -1; + state->dmax = 32768U; + state->head = NULL; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + INFLATE_RESET_KEEP_HOOK(strm); /* hook for IBM Z DFLTCC */ + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int32_t Z_EXPORT PREFIX(inflateReset)(PREFIX3(stream) *strm) { + struct inflate_state *state; + + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return PREFIX(inflateResetKeep)(strm); +} + +int32_t Z_EXPORT PREFIX(inflateReset2)(PREFIX3(stream) *strm, int32_t windowBits) { + int wrap; + struct inflate_state *state; + + /* get the state */ + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + if (windowBits < -MAX_WBITS) + return Z_STREAM_ERROR; + windowBits = -windowBits; + } else { + wrap = (windowBits >> 4) + 5; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= MAX_WBITS; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < MIN_WBITS || windowBits > MAX_WBITS)) + return Z_STREAM_ERROR; + if (state->window != NULL && state->wbits != (unsigned)windowBits) { + ZFREE_WINDOW(strm, state->window); + state->window = NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return PREFIX(inflateReset)(strm); +} + +/* This function is hidden in ZLIB_COMPAT builds. */ +int32_t ZNG_CONDEXPORT PREFIX(inflateInit2)(PREFIX3(stream) *strm, int32_t windowBits) { + int32_t ret; + struct inflate_state *state; + + /* Initialize functable earlier. */ + functable.force_init(); + + if (strm == NULL) + return Z_STREAM_ERROR; + strm->msg = NULL; /* in case we return an error */ + if (strm->zalloc == NULL) { + strm->zalloc = PREFIX(zcalloc); + strm->opaque = NULL; + } + if (strm->zfree == NULL) + strm->zfree = PREFIX(zcfree); + state = ZALLOC_INFLATE_STATE(strm); + if (state == NULL) + return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state *)state; + state->strm = strm; + state->window = NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ + state->chunksize = functable.chunksize(); + ret = PREFIX(inflateReset2)(strm, windowBits); + if (ret != Z_OK) { + ZFREE_STATE(strm, state); + strm->state = NULL; + } + return ret; +} + +#ifndef ZLIB_COMPAT +int32_t Z_EXPORT PREFIX(inflateInit)(PREFIX3(stream) *strm) { + return PREFIX(inflateInit2)(strm, DEF_WBITS); +} +#endif + +/* Function used by zlib.h and zlib-ng version 2.0 macros */ +int32_t Z_EXPORT PREFIX(inflateInit_)(PREFIX3(stream) *strm, const char *version, int32_t stream_size) { + if (CHECK_VER_STSIZE(version, stream_size)) + return Z_VERSION_ERROR; + return PREFIX(inflateInit2)(strm, DEF_WBITS); +} + +/* Function used by zlib.h and zlib-ng version 2.0 macros */ +int32_t Z_EXPORT PREFIX(inflateInit2_)(PREFIX3(stream) *strm, int32_t windowBits, const char *version, int32_t stream_size) { + if (CHECK_VER_STSIZE(version, stream_size)) + return Z_VERSION_ERROR; + return PREFIX(inflateInit2)(strm, windowBits); +} + +int32_t Z_EXPORT PREFIX(inflatePrime)(PREFIX3(stream) *strm, int32_t bits, int32_t value) { + struct inflate_state *state; + + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + if (bits == 0) + return Z_OK; + INFLATE_PRIME_HOOK(strm, bits, value); /* hook for IBM Z DFLTCC */ + state = (struct inflate_state *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + (unsigned int)bits > 32) + return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += (unsigned)value << state->bits; + state->bits += (unsigned int)bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. This returns fixed tables from inffixed_tbl.h. + */ + +void Z_INTERNAL PREFIX(fixedtables)(struct inflate_state *state) { + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +int Z_INTERNAL PREFIX(inflate_ensure_window)(struct inflate_state *state) { + /* if it hasn't been done already, allocate space for the window */ + if (state->window == NULL) { + unsigned wsize = 1U << state->wbits; + state->window = (unsigned char *)ZALLOC_WINDOW(state->strm, wsize + state->chunksize, sizeof(unsigned char)); + if (state->window == NULL) + return Z_MEM_ERROR; +#ifdef Z_MEMORY_SANITIZER + /* This is _not_ to subvert the memory sanitizer but to instead unposion some + data we willingly and purposefully load uninitialized into vector registers + in order to safely read the last < chunksize bytes of the window. */ + __msan_unpoison(state->window + wsize, state->chunksize); +#endif + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + return Z_OK; +} + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +static int32_t updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t len, int32_t cksum) { + struct inflate_state *state; + uint32_t dist; + + state = (struct inflate_state *)strm->state; + + if (PREFIX(inflate_ensure_window)(state)) return 1; + + /* len state->wsize or less output bytes into the circular window */ + if (len >= state->wsize) { + /* Only do this if the caller specifies to checksum bytes AND the platform requires + * it (s/390 being the primary exception to this. Also, for now, do the adler checksums + * if not a gzip based header. The inline adler checksums will come in the near future, + * possibly the next commit */ + if (INFLATE_NEED_CHECKSUM(strm) && cksum) { + /* We have to split the checksum over non-copied and copied bytes */ + if (len > state->wsize) + inf_chksum(strm, end - len, len - state->wsize); + inf_chksum_cpy(strm, state->window, end - state->wsize, state->wsize); + } else { + memcpy(state->window, end - state->wsize, state->wsize); + } + + state->wnext = 0; + state->whave = state->wsize; + } else { + dist = state->wsize - state->wnext; + /* Only do this if the caller specifies to checksum bytes AND the platform requires + * We need to maintain the correct order here for the checksum */ + dist = MIN(dist, len); + if (INFLATE_NEED_CHECKSUM(strm) && cksum) { + inf_chksum_cpy(strm, state->window + state->wnext, end - len, dist); + } else { + memcpy(state->window + state->wnext, end - len, dist); + } + len -= dist; + if (len) { + if (INFLATE_NEED_CHECKSUM(strm) && cksum) { + inf_chksum_cpy(strm, state->window, end - len, len); + } else { + memcpy(state->window, end - len, len); + } + + state->wnext = len; + state->whave = state->wsize; + } else { + state->wnext += dist; + if (state->wnext == state->wsize) + state->wnext = 0; + if (state->whave < state->wsize) + state->whave += dist; + } + } + return 0; +} + +/* + Private macros for inflate() + Look in inflate_p.h for macros shared with inflateBack() +*/ + +/* Get a byte of input into the bit accumulator, or return from inflate() if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += ((unsigned)(*next++) << bits); \ + bits += 8; \ + } while (0) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { + struct inflate_state *state; + const unsigned char *next; /* next input */ + unsigned char *put; /* next output */ + unsigned have, left; /* available input and output */ + uint32_t hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + uint32_t in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int32_t ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const uint16_t order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (inflateStateCheck(strm) || strm->next_out == NULL || + (strm->next_in == NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state *)strm->state; + if (state->mode == TYPE) /* skip check */ + state->mode = TYPEDO; + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = MAX_WBITS; + state->check = CRC32_INITIAL_VALUE; + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + if (state->head != NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + SET_BAD("incorrect header check"); + break; + } + if (BITS(4) != Z_DEFLATED) { + SET_BAD("unknown compression method"); + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + if (len > MAX_WBITS || len > state->wbits) { + SET_BAD("invalid window size"); + break; + } + state->dmax = 1U << len; + state->flags = 0; /* indicate zlib header */ + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = ADLER32_INITIAL_VALUE; + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + SET_BAD("unknown compression method"); + break; + } + if (state->flags & 0xe000) { + SET_BAD("unknown header flags set"); + break; + } + if (state->head != NULL) + state->head->text = (int)((hold >> 8) & 1); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + Z_FALLTHROUGH; + + case TIME: + NEEDBITS(32); + if (state->head != NULL) + state->head->time = hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + Z_FALLTHROUGH; + + case OS: + NEEDBITS(16); + if (state->head != NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + Z_FALLTHROUGH; + + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (uint16_t)hold; + if (state->head != NULL) + state->head->extra_len = (uint16_t)hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + } else if (state->head != NULL) { + state->head->extra = NULL; + } + state->mode = EXTRA; + Z_FALLTHROUGH; + + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) + copy = have; + if (copy) { + if (state->head != NULL && state->head->extra != NULL) { + len = state->head->extra_len - state->length; + if (len < state->head->extra_max) { + memcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + } + if ((state->flags & 0x0200) && (state->wrap & 4)) { + state->check = PREFIX(crc32)(state->check, next, copy); + } + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) + goto inf_leave; + } + state->length = 0; + state->mode = NAME; + Z_FALLTHROUGH; + + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != NULL && state->head->name != NULL && state->length < state->head->name_max) + state->head->name[state->length++] = (unsigned char)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = PREFIX(crc32)(state->check, next, copy); + have -= copy; + next += copy; + if (len) + goto inf_leave; + } else if (state->head != NULL) { + state->head->name = NULL; + } + state->length = 0; + state->mode = COMMENT; + Z_FALLTHROUGH; + + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != NULL && state->head->comment != NULL + && state->length < state->head->comm_max) + state->head->comment[state->length++] = (unsigned char)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = PREFIX(crc32)(state->check, next, copy); + have -= copy; + next += copy; + if (len) + goto inf_leave; + } else if (state->head != NULL) { + state->head->comment = NULL; + } + state->mode = HCRC; + Z_FALLTHROUGH; + + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { + SET_BAD("header crc mismatch"); + break; + } + INITBITS(); + } + if (state->head != NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + /* compute crc32 checksum if not in raw mode */ + if ((state->wrap & 4) && state->flags) + strm->adler = state->check = functable.crc32_fold_reset(&state->crc_fold); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = ZSWAP32(hold); + INITBITS(); + state->mode = DICT; + Z_FALLTHROUGH; + + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = ADLER32_INITIAL_VALUE; + state->mode = TYPE; + Z_FALLTHROUGH; + + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) + goto inf_leave; + Z_FALLTHROUGH; + + case TYPEDO: + /* determine and dispatch block type */ + INFLATE_TYPEDO_HOOK(strm, flush); /* hook for IBM Z DFLTCC */ + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + PREFIX(fixedtables)(state); + Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + SET_BAD("invalid block type"); + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + SET_BAD("invalid stored block lengths"); + break; + } + state->length = (uint16_t)hold; + Tracev((stderr, "inflate: stored length %u\n", state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) + goto inf_leave; + Z_FALLTHROUGH; + + case COPY_: + state->mode = COPY; + Z_FALLTHROUGH; + + case COPY: + /* copy stored block from input to output */ + copy = state->length; + if (copy) { + copy = MIN(copy, have); + copy = MIN(copy, left); + if (copy == 0) + goto inf_leave; + memcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + SET_BAD("too many length or distance symbols"); + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + Z_FALLTHROUGH; + + case LENLENS: + /* get code length code lengths (not a typo) */ + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (uint16_t)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (const code *)(state->next); + state->lenbits = 7; + ret = zng_inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); + if (ret) { + SET_BAD("invalid code lengths set"); + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + Z_FALLTHROUGH; + + case CODELENS: + /* get length and distance code code lengths */ + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if (here.bits <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + SET_BAD("invalid bit length repeat"); + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + SET_BAD("invalid bit length repeat"); + break; + } + while (copy) { + --copy; + state->lens[state->have++] = (uint16_t)len; + } + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) + break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + SET_BAD("invalid code -- missing end-of-block"); + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (10 and 9) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (const code *)(state->next); + state->lenbits = 10; + ret = zng_inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); + if (ret) { + SET_BAD("invalid literal/lengths set"); + break; + } + state->distcode = (const code *)(state->next); + state->distbits = 9; + ret = zng_inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + SET_BAD("invalid distances set"); + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) + goto inf_leave; + Z_FALLTHROUGH; + + case LEN_: + state->mode = LEN; + Z_FALLTHROUGH; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= INFLATE_FAST_MIN_HAVE && left >= INFLATE_FAST_MIN_LEFT) { + RESTORE(); + functable.inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + + /* get a literal, length, or end-of-block code */ + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if (here.bits <= bits) + break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)last.bits + (unsigned)here.bits <= bits) + break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = here.val; + + /* process literal */ + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + + /* process end of block */ + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + + /* invalid code */ + if (here.op & 64) { + SET_BAD("invalid literal/length code"); + break; + } + + /* length code */ + state->extra = (here.op & MAX_BITS); + state->mode = LENEXT; + Z_FALLTHROUGH; + + case LENEXT: + /* get extra bits, if any */ + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + Z_FALLTHROUGH; + + case DIST: + /* get distance code */ + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if (here.bits <= bits) + break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)last.bits + (unsigned)here.bits <= bits) + break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + SET_BAD("invalid distance code"); + break; + } + state->offset = here.val; + state->extra = (here.op & MAX_BITS); + state->mode = DISTEXT; + Z_FALLTHROUGH; + + case DISTEXT: + /* get distance extra bits, if any */ + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + SET_BAD("invalid distance too far back"); + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + Z_FALLTHROUGH; + + case MATCH: + /* copy match from window to output */ + if (left == 0) + goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + SET_BAD("invalid distance too far back"); + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + copy = MIN(copy, state->length); + copy = MIN(copy, left); + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) + state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } else { + from = state->window + (state->wnext - copy); + } + copy = MIN(copy, state->length); + copy = MIN(copy, left); + + put = chunkcopy_safe(put, from, copy, put + left); + } else { + copy = MIN(state->length, left); + + put = functable.chunkmemset_safe(put, state->offset, copy, left); + } + left -= copy; + state->length -= copy; + if (state->length == 0) + state->mode = LEN; + break; + + case LIT: + if (left == 0) + goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + + /* compute crc32 checksum if not in raw mode */ + if (INFLATE_NEED_CHECKSUM(strm) && state->wrap & 4) { + if (out) { + inf_chksum(strm, put - out, out); + } +#ifdef GUNZIP + if (state->flags) + strm->adler = state->check = functable.crc32_fold_final(&state->crc_fold); +#endif + } + out = left; + if ((state->wrap & 4) && ( +#ifdef GUNZIP + state->flags ? hold : +#endif + ZSWAP32(hold)) != state->check) { + SET_BAD("incorrect data check"); + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + Z_FALLTHROUGH; + + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) { + SET_BAD("incorrect length check"); + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + Z_FALLTHROUGH; + + case DONE: + /* inflate stream terminated properly */ + ret = Z_STREAM_END; + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + case MEM: + return Z_MEM_ERROR; + + case SYNC: + + default: /* can't happen, but makes compilers happy */ + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + uint32_t check_bytes = out - strm->avail_out; + if (INFLATE_NEED_UPDATEWINDOW(strm) && + (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH)))) { + /* update sliding window with respective checksum if not in "raw" mode */ + if (updatewindow(strm, strm->next_out, check_bytes, state->wrap & 4)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) { + /* when no sliding window is used, hash the output bytes if no CHECK state */ + if (INFLATE_NEED_CHECKSUM(strm) && !state->wsize && flush == Z_FINISH) { + inf_chksum(strm, put - check_bytes, check_bytes); + } + ret = Z_BUF_ERROR; + } + return ret; +} + +int32_t Z_EXPORT PREFIX(inflateEnd)(PREFIX3(stream) *strm) { + struct inflate_state *state; + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + if (state->window != NULL) + ZFREE_WINDOW(strm, state->window); + ZFREE_STATE(strm, strm->state); + strm->state = NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int32_t Z_EXPORT PREFIX(inflateGetDictionary)(PREFIX3(stream) *strm, uint8_t *dictionary, uint32_t *dictLength) { + struct inflate_state *state; + + /* check state */ + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + + INFLATE_GET_DICTIONARY_HOOK(strm, dictionary, dictLength); /* hook for IBM Z DFLTCC */ + + /* copy dictionary */ + if (state->whave && dictionary != NULL) { + memcpy(dictionary, state->window + state->wnext, state->whave - state->wnext); + memcpy(dictionary + state->whave - state->wnext, state->window, state->wnext); + } + if (dictLength != NULL) + *dictLength = state->whave; + return Z_OK; +} + +int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8_t *dictionary, uint32_t dictLength) { + struct inflate_state *state; + unsigned long dictid; + int32_t ret; + + /* check state */ + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary identifier */ + if (state->mode == DICT) { + dictid = functable.adler32(ADLER32_INITIAL_VALUE, dictionary, dictLength); + if (dictid != state->check) + return Z_DATA_ERROR; + } + + INFLATE_SET_DICTIONARY_HOOK(strm, dictionary, dictLength); /* hook for IBM Z DFLTCC */ + + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength, 0); + if (ret) { + state->mode = MEM; + return Z_MEM_ERROR; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int32_t Z_EXPORT PREFIX(inflateGetHeader)(PREFIX3(stream) *strm, PREFIX(gz_headerp) head) { + struct inflate_state *state; + + /* check state */ + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + if ((state->wrap & 2) == 0) + return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +static uint32_t syncsearch(uint32_t *have, const uint8_t *buf, uint32_t len) { + uint32_t got, next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int32_t Z_EXPORT PREFIX(inflateSync)(PREFIX3(stream) *strm) { + unsigned len; /* number of bytes to look at or looked at */ + int flags; /* temporary to save header status */ + size_t in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state *state; + + /* check parameters */ + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) + return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) + return Z_DATA_ERROR; + if (state->flags == -1) + state->wrap = 0; /* if no header yet, treat as raw */ + else + state->wrap &= ~4; /* no point in computing a check value now */ + flags = state->flags; + in = strm->total_in; + out = strm->total_out; + PREFIX(inflateReset)(strm); + strm->total_in = (z_uintmax_t)in; /* Can't use z_size_t here as it will overflow on 64-bit Windows */ + strm->total_out = (z_uintmax_t)out; + state->flags = flags; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int32_t Z_EXPORT PREFIX(inflateSyncPoint)(PREFIX3(stream) *strm) { + struct inflate_state *state; + + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + INFLATE_SYNC_POINT_HOOK(strm); + state = (struct inflate_state *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *source) { + struct inflate_state *state; + struct inflate_state *copy; + + /* check input */ + if (inflateStateCheck(source) || dest == NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state *)source->state; + + /* allocate space */ + copy = ZALLOC_INFLATE_STATE(source); + if (copy == NULL) + return Z_MEM_ERROR; + + /* copy state */ + memcpy((void *)dest, (void *)source, sizeof(PREFIX3(stream))); + ZCOPY_INFLATE_STATE(copy, state); + copy->strm = dest; + if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + + /* window */ + copy->window = NULL; + if (state->window != NULL) { + if (PREFIX(inflate_ensure_window)(copy)) { + ZFREE_STATE(source, copy); + return Z_MEM_ERROR; + } + ZCOPY_WINDOW(copy->window, state->window, (size_t)state->wsize); + } + + dest->state = (struct internal_state *)copy; + return Z_OK; +} + +int32_t Z_EXPORT PREFIX(inflateUndermine)(PREFIX3(stream) *strm, int32_t subvert) { + struct inflate_state *state; + + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; + return Z_OK; +#else + Z_UNUSED(subvert); + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +int32_t Z_EXPORT PREFIX(inflateValidate)(PREFIX3(stream) *strm, int32_t check) { + struct inflate_state *state; + + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state *)strm->state; + if (check && state->wrap) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + +long Z_EXPORT PREFIX(inflateMark)(PREFIX3(stream) *strm) { + struct inflate_state *state; + + if (inflateStateCheck(strm)) + return -65536; + INFLATE_MARK_HOOK(strm); /* hook for IBM Z DFLTCC */ + state = (struct inflate_state *)strm->state; + return (long)(((unsigned long)((long)state->back)) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} + +unsigned long Z_EXPORT PREFIX(inflateCodesUsed)(PREFIX3(stream) *strm) { + struct inflate_state *state; + if (strm == NULL || strm->state == NULL) + return (unsigned long)-1; + state = (struct inflate_state *)strm->state; + return (unsigned long)(state->next - state->codes); +} diff --git a/3rdparty/zlib-ng/inflate.h b/3rdparty/zlib-ng/inflate.h new file mode 100644 index 000000000000..39cdf5d683c3 --- /dev/null +++ b/3rdparty/zlib-ng/inflate.h @@ -0,0 +1,140 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2019 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +#ifndef INFLATE_H_ +#define INFLATE_H_ + +#include "adler32_fold.h" +#include "crc32_fold.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate(). + NO_GZIP would be used to avoid linking in the crc code when it is not needed. + For shared libraries, gzip decoding should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD = 16180, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* State maintained between inflate() calls -- approximately 7K bytes, not + including the allocated sliding window, which is up to 32K bytes. */ +struct inflate_state { + PREFIX3(stream) *strm; /* pointer back to this zlib stream */ + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip, + bit 2 true to validate check value */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags, 0 if zlib, or + -1 if raw or no header yet */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + PREFIX(gz_headerp) head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + uint32_t wsize; /* window size or zero if not using window */ + uint32_t whave; /* valid bytes in the window */ + uint32_t wnext; /* window write index */ + unsigned char *window; /* allocated sliding window, if needed */ + + struct crc32_fold_s ALIGNED_(16) crc_fold; + + /* bit accumulator */ + uint32_t hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + uint32_t length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const *lencode; /* starting table for length/literal codes */ + code const *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + uint32_t have; /* number of code lengths in lens[] */ + code *next; /* next available space in codes[] */ + uint16_t lens[320]; /* temporary storage for code lengths */ + uint16_t work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ + uint32_t chunksize; /* size of memory copying chunk */ +}; + +int Z_INTERNAL PREFIX(inflate_ensure_window)(struct inflate_state *state); +void Z_INTERNAL PREFIX(fixedtables)(struct inflate_state *state); + +#endif /* INFLATE_H_ */ diff --git a/3rdparty/zlib-ng/inflate_p.h b/3rdparty/zlib-ng/inflate_p.h new file mode 100644 index 000000000000..eff73876daf2 --- /dev/null +++ b/3rdparty/zlib-ng/inflate_p.h @@ -0,0 +1,230 @@ +/* inflate_p.h -- Private inline functions and macros shared with more than one deflate method + * + */ + +#ifndef INFLATE_P_H +#define INFLATE_P_H + +#include + +/* Architecture-specific hooks. */ +#ifdef S390_DFLTCC_INFLATE +# include "arch/s390/dfltcc_inflate.h" +#else +/* Memory management for the inflate state. Useful for allocating arch-specific extension blocks. */ +# define ZALLOC_INFLATE_STATE(strm) ((struct inflate_state *)ZALLOC(strm, 1, sizeof(struct inflate_state))) +# define ZFREE_STATE(strm, addr) ZFREE(strm, addr) +# define ZCOPY_INFLATE_STATE(dst, src) memcpy(dst, src, sizeof(struct inflate_state)) +/* Memory management for the window. Useful for allocation the aligned window. */ +# define ZALLOC_WINDOW(strm, items, size) ZALLOC(strm, items, size) +# define ZCOPY_WINDOW(dest, src, n) memcpy(dest, src, n) +# define ZFREE_WINDOW(strm, addr) ZFREE(strm, addr) +/* Invoked at the end of inflateResetKeep(). Useful for initializing arch-specific extension blocks. */ +# define INFLATE_RESET_KEEP_HOOK(strm) do {} while (0) +/* Invoked at the beginning of inflatePrime(). Useful for updating arch-specific buffers. */ +# define INFLATE_PRIME_HOOK(strm, bits, value) do {} while (0) +/* Invoked at the beginning of each block. Useful for plugging arch-specific inflation code. */ +# define INFLATE_TYPEDO_HOOK(strm, flush) do {} while (0) +/* Returns whether zlib-ng should compute a checksum. Set to 0 if arch-specific inflation code already does that. */ +# define INFLATE_NEED_CHECKSUM(strm) 1 +/* Returns whether zlib-ng should update a window. Set to 0 if arch-specific inflation code already does that. */ +# define INFLATE_NEED_UPDATEWINDOW(strm) 1 +/* Invoked at the beginning of inflateMark(). Useful for updating arch-specific pointers and offsets. */ +# define INFLATE_MARK_HOOK(strm) do {} while (0) +/* Invoked at the beginning of inflateSyncPoint(). Useful for performing arch-specific state checks. */ +# define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0) +/* Invoked at the beginning of inflateSetDictionary(). Useful for checking arch-specific window data. */ +# define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) +/* Invoked at the beginning of inflateGetDictionary(). Useful for adjusting arch-specific window data. */ +# define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) +#endif + +/* + * Macros shared by inflate() and inflateBack() + */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? PREFIX(crc32)(check, buf, len) : functable.adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) functable.adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = PREFIX(crc32)(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = PREFIX(crc32)(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = (z_const unsigned char *)next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Ensure that there is at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate()/inflateBack(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + (hold & ((1U << (unsigned)(n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Set mode=BAD and prepare error message */ +#define SET_BAD(errmsg) \ + do { \ + state->mode = BAD; \ + strm->msg = (char *)errmsg; \ + } while (0) + +#define INFLATE_FAST_MIN_HAVE 15 +#define INFLATE_FAST_MIN_LEFT 260 + +/* Load 64 bits from IN and place the bytes at offset BITS in the result. */ +static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) { + uint64_t chunk; + memcpy(&chunk, in, sizeof(chunk)); + +#if BYTE_ORDER == LITTLE_ENDIAN + return chunk << bits; +#else + return ZSWAP64(chunk) << bits; +#endif +} + +/* Behave like chunkcopy, but avoid writing beyond of legal output. */ +static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, uint64_t len, uint8_t *safe) { + uint64_t safelen = (safe - out) + 1; + len = MIN(len, safelen); + int32_t olap_src = from >= out && from < out + len; + int32_t olap_dst = out >= from && out < from + len; + uint64_t tocopy; + + /* For all cases without overlap, memcpy is ideal */ + if (!(olap_src || olap_dst)) { + memcpy(out, from, (size_t)len); + return out + len; + } + + /* Complete overlap: Source == destination */ + if (out == from) { + return out + len; + } + + /* We are emulating a self-modifying copy loop here. To do this in a way that doesn't produce undefined behavior, + * we have to get a bit clever. First if the overlap is such that src falls between dst and dst+len, we can do the + * initial bulk memcpy of the nonoverlapping region. Then, we can leverage the size of this to determine the safest + * atomic memcpy size we can pick such that we have non-overlapping regions. This effectively becomes a safe look + * behind or lookahead distance. */ + uint64_t non_olap_size = llabs(from - out); // llabs vs labs for compatibility with windows + + memcpy(out, from, (size_t)non_olap_size); + out += non_olap_size; + from += non_olap_size; + len -= non_olap_size; + + /* So this doesn't give use a worst case scenario of function calls in a loop, + * we want to instead break this down into copy blocks of fixed lengths */ + while (len) { + tocopy = MIN(non_olap_size, len); + len -= tocopy; + + while (tocopy >= 32) { + memcpy(out, from, 32); + out += 32; + from += 32; + tocopy -= 32; + } + + if (tocopy >= 16) { + memcpy(out, from, 16); + out += 16; + from += 16; + tocopy -= 16; + } + + if (tocopy >= 8) { + memcpy(out, from, 8); + out += 8; + from += 8; + tocopy -= 8; + } + + if (tocopy >= 4) { + memcpy(out, from, 4); + out += 4; + from += 4; + tocopy -= 4; + } + + if (tocopy >= 2) { + memcpy(out, from, 2); + out += 2; + from += 2; + tocopy -= 2; + } + + if (tocopy) { + *out++ = *from++; + } + } + + return out; +} + +#endif diff --git a/3rdparty/zlib-ng/inftrees.c b/3rdparty/zlib-ng/inftrees.c new file mode 100644 index 000000000000..423f7b461d7c --- /dev/null +++ b/3rdparty/zlib-ng/inftrees.c @@ -0,0 +1,295 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2023 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "zutil.h" +#include "inftrees.h" + +const char PREFIX(inflate_copyright)[] = " inflate 1.3.0 Copyright 1995-2023 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int Z_INTERNAL zng_inflate_table(codetype type, uint16_t *lens, unsigned codes, + code * *table, unsigned *bits, uint16_t *work) { + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code *next; /* next available space in table */ + const uint16_t *base; /* base value table to use */ + const uint16_t *extra; /* extra bits table to use */ + unsigned match; /* use base and extra for symbol >= match */ + uint16_t count[MAX_BITS+1]; /* number of codes of each length */ + uint16_t offs[MAX_BITS+1]; /* offsets in table for each length */ + static const uint16_t lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const uint16_t lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202}; + static const uint16_t dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const uint16_t dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAX_BITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAX_BITS; max >= 1; max--) + if (count[max] != 0) break; + root = MIN(root, max); + if (UNLIKELY(max == 0)) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (uint16_t)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + root = MAX(root, min); + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAX_BITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAX_BITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (uint16_t)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + match = 20; + break; + case LENS: + base = lbase; + extra = lext; + match = 257; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + match = 0; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if (LIKELY(work[sym] >= match)) { + here.op = (unsigned char)(extra[work[sym] - match]); + here.val = base[work[sym] - match]; + } else if (work[sym] + 1U < match) { + here.op = (unsigned char)0; + here.val = work[sym]; + } else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } else { + huff = 0; + } + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) + break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) + break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used > ENOUGH_LENS) || (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (uint16_t)(next - *table); + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (UNLIKELY(huff != 0)) { + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (uint16_t)0; + next[huff] = here; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/3rdparty/zlib-ng/inftrees.h b/3rdparty/zlib-ng/inftrees.h new file mode 100644 index 000000000000..ad2be151f2c0 --- /dev/null +++ b/3rdparty/zlib-ng/inftrees.h @@ -0,0 +1,66 @@ +#ifndef INFTREES_H_ +#define INFTREES_H_ + +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2022 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + uint16_t val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1924, which is the sum of 1332 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distributions. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 10 15" for literal/length codes + returns 1332, and "enough 30 9 15" for distance codes returns 592. + The initial root table size (10 or 9) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 1332 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int Z_INTERNAL zng_inflate_table (codetype type, uint16_t *lens, unsigned codes, + code * *table, unsigned *bits, uint16_t *work); + +#endif /* INFTREES_H_ */ diff --git a/3rdparty/zlib-ng/insert_string.c b/3rdparty/zlib-ng/insert_string.c new file mode 100644 index 000000000000..cfe39837f86a --- /dev/null +++ b/3rdparty/zlib-ng/insert_string.c @@ -0,0 +1,21 @@ +/* insert_string.c -- insert_string integer hash variant + * + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + */ + +#include "zbuild.h" +#include "deflate.h" + +#define HASH_SLIDE 16 + +#define HASH_CALC(s, h, val) h = ((val * 2654435761U) >> HASH_SLIDE); +#define HASH_CALC_VAR h +#define HASH_CALC_VAR_INIT uint32_t h = 0 + +#define UPDATE_HASH update_hash_c +#define INSERT_STRING insert_string_c +#define QUICK_INSERT_STRING quick_insert_string_c + +#include "insert_string_tpl.h" diff --git a/3rdparty/zlib-ng/insert_string_roll.c b/3rdparty/zlib-ng/insert_string_roll.c new file mode 100644 index 000000000000..dfea347bccb7 --- /dev/null +++ b/3rdparty/zlib-ng/insert_string_roll.c @@ -0,0 +1,24 @@ +/* insert_string_roll.c -- insert_string rolling hash variant + * + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + */ + +#include "zbuild.h" +#include "deflate.h" + +#define HASH_SLIDE 5 + +#define HASH_CALC(s, h, val) h = ((h << HASH_SLIDE) ^ ((uint8_t)val)) +#define HASH_CALC_VAR s->ins_h +#define HASH_CALC_VAR_INIT +#define HASH_CALC_READ val = strstart[0] +#define HASH_CALC_MASK (32768u - 1u) +#define HASH_CALC_OFFSET (STD_MIN_MATCH-1) + +#define UPDATE_HASH update_hash_roll +#define INSERT_STRING insert_string_roll +#define QUICK_INSERT_STRING quick_insert_string_roll + +#include "insert_string_tpl.h" diff --git a/3rdparty/zlib-ng/insert_string_tpl.h b/3rdparty/zlib-ng/insert_string_tpl.h new file mode 100644 index 000000000000..c84617730ac3 --- /dev/null +++ b/3rdparty/zlib-ng/insert_string_tpl.h @@ -0,0 +1,108 @@ +#ifndef INSERT_STRING_H_ +#define INSERT_STRING_H_ + +/* insert_string.h -- Private insert_string functions shared with more than + * one insert string implementation + * + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * Authors: + * Wajdi Feghali + * Jim Guilford + * Vinodh Gopal + * Erdinc Ozturk + * Jim Kukunas + * + * Portions are Copyright (C) 2016 12Sided Technology, LLC. + * Author: + * Phil Vachon + * + * For conditions of distribution and use, see copyright notice in zlib.h + * + */ + +#ifndef HASH_CALC_OFFSET +# define HASH_CALC_OFFSET 0 +#endif +#ifndef HASH_CALC_MASK +# define HASH_CALC_MASK HASH_MASK +#endif +#ifndef HASH_CALC_READ +# if BYTE_ORDER == LITTLE_ENDIAN +# define HASH_CALC_READ \ + memcpy(&val, strstart, sizeof(val)); +# else +# define HASH_CALC_READ \ + val = ((uint32_t)(strstart[0])); \ + val |= ((uint32_t)(strstart[1]) << 8); \ + val |= ((uint32_t)(strstart[2]) << 16); \ + val |= ((uint32_t)(strstart[3]) << 24); +# endif +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +Z_INTERNAL uint32_t UPDATE_HASH(deflate_state *const s, uint32_t h, uint32_t val) { + (void)s; + HASH_CALC(s, h, val); + return h & HASH_CALC_MASK; +} + +/* =========================================================================== + * Quick insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + */ +Z_INTERNAL Pos QUICK_INSERT_STRING(deflate_state *const s, uint32_t str) { + Pos head; + uint8_t *strstart = s->window + str + HASH_CALC_OFFSET; + uint32_t val, hm; + + HASH_CALC_VAR_INIT; + HASH_CALC_READ; + HASH_CALC(s, HASH_CALC_VAR, val); + HASH_CALC_VAR &= HASH_CALC_MASK; + hm = HASH_CALC_VAR; + + head = s->head[hm]; + if (LIKELY(head != str)) { + s->prev[str & s->w_mask] = head; + s->head[hm] = (Pos)str; + } + return head; +} + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * IN assertion: all calls to INSERT_STRING are made with consecutive + * input characters and the first STD_MIN_MATCH bytes of str are valid + * (except for the last STD_MIN_MATCH-1 bytes of the input file). + */ +Z_INTERNAL void INSERT_STRING(deflate_state *const s, uint32_t str, uint32_t count) { + uint8_t *strstart = s->window + str + HASH_CALC_OFFSET; + uint8_t *strend = strstart + count; + + for (Pos idx = (Pos)str; strstart < strend; idx++, strstart++) { + uint32_t val, hm; + + HASH_CALC_VAR_INIT; + HASH_CALC_READ; + HASH_CALC(s, HASH_CALC_VAR, val); + HASH_CALC_VAR &= HASH_CALC_MASK; + hm = HASH_CALC_VAR; + + Pos head = s->head[hm]; + if (LIKELY(head != idx)) { + s->prev[idx & s->w_mask] = head; + s->head[hm] = idx; + } + } +} +#endif diff --git a/3rdparty/zlib-ng/match_tpl.h b/3rdparty/zlib-ng/match_tpl.h new file mode 100644 index 000000000000..d076798520ee --- /dev/null +++ b/3rdparty/zlib-ng/match_tpl.h @@ -0,0 +1,289 @@ +/* match_tpl.h -- find longest match template for compare256 variants + * + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Portions copyright (C) 2014-2021 Konstantin Nosov + * Fast-zlib optimized longest_match + * https://github.com/gildor2/fast_zlib + */ + +#include "zbuild.h" +#include "zutil_p.h" +#include "deflate.h" +#include "functable.h" + +#ifndef MATCH_TPL_H +#define MATCH_TPL_H + +#define EARLY_EXIT_TRIGGER_LEVEL 5 + +#endif + +/* Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is garbage. + * + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >=1 + * OUT assertion: the match length is not greater than s->lookahead + */ +Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { + unsigned int strstart = s->strstart; + const unsigned wmask = s->w_mask; + unsigned char *window = s->window; + unsigned char *scan = window + strstart; + Z_REGISTER unsigned char *mbase_start = window; + Z_REGISTER unsigned char *mbase_end; + const Pos *prev = s->prev; + Pos limit; +#ifdef LONGEST_MATCH_SLOW + Pos limit_base; +#else + int32_t early_exit; +#endif + uint32_t chain_length, nice_match, best_len, offset; + uint32_t lookahead = s->lookahead; + Pos match_offset = 0; +#ifdef UNALIGNED_OK + uint8_t scan_start[8]; +#endif + uint8_t scan_end[8]; + +#define GOTO_NEXT_CHAIN \ + if (--chain_length && (cur_match = prev[cur_match & wmask]) > limit) \ + continue; \ + return best_len; + + /* The code is optimized for STD_MAX_MATCH-2 multiple of 16. */ + Assert(STD_MAX_MATCH == 258, "Code too clever"); + + best_len = s->prev_length ? s->prev_length : STD_MIN_MATCH-1; + + /* Calculate read offset which should only extend an extra byte + * to find the next best match length. + */ + offset = best_len-1; +#ifdef UNALIGNED_OK + if (best_len >= sizeof(uint32_t)) { + offset -= 2; +#ifdef UNALIGNED64_OK + if (best_len >= sizeof(uint64_t)) + offset -= 4; +#endif + } +#endif + +#ifdef UNALIGNED64_OK + memcpy(scan_start, scan, sizeof(uint64_t)); + memcpy(scan_end, scan+offset, sizeof(uint64_t)); +#elif defined(UNALIGNED_OK) + memcpy(scan_start, scan, sizeof(uint32_t)); + memcpy(scan_end, scan+offset, sizeof(uint32_t)); +#else + scan_end[0] = *(scan+offset); + scan_end[1] = *(scan+offset+1); +#endif + mbase_end = (mbase_start+offset); + + /* Do not waste too much time if we already have a good match */ + chain_length = s->max_chain_length; + if (best_len >= s->good_match) + chain_length >>= 2; + nice_match = (uint32_t)s->nice_match; + + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0 + */ + limit = strstart > MAX_DIST(s) ? (Pos)(strstart - MAX_DIST(s)) : 0; +#ifdef LONGEST_MATCH_SLOW + limit_base = limit; + if (best_len >= STD_MIN_MATCH) { + /* We're continuing search (lazy evaluation). */ + uint32_t i, hash; + Pos pos; + + /* Find a most distant chain starting from scan with index=1 (index=0 corresponds + * to cur_match). We cannot use s->prev[strstart+1,...] immediately, because + * these strings are not yet inserted into the hash table. + */ + hash = s->update_hash(s, 0, scan[1]); + hash = s->update_hash(s, hash, scan[2]); + + for (i = 3; i <= best_len; i++) { + hash = s->update_hash(s, hash, scan[i]); + + /* If we're starting with best_len >= 3, we can use offset search. */ + pos = s->head[hash]; + if (pos < cur_match) { + match_offset = (Pos)(i - 2); + cur_match = pos; + } + } + + /* Update offset-dependent variables */ + limit = limit_base+match_offset; + if (cur_match <= limit) + goto break_matching; + mbase_start -= match_offset; + mbase_end -= match_offset; + } +#else + early_exit = s->level < EARLY_EXIT_TRIGGER_LEVEL; +#endif + Assert((unsigned long)strstart <= s->window_size - MIN_LOOKAHEAD, "need lookahead"); + for (;;) { + if (cur_match >= strstart) + break; + + /* Skip to next match if the match length cannot increase or if the match length is + * less than 2. Note that the checks below for insufficient lookahead only occur + * occasionally for performance reasons. + * Therefore uninitialized memory will be accessed and conditional jumps will be made + * that depend on those values. However the length of the match is limited to the + * lookahead, so the output of deflate is not affected by the uninitialized values. + */ +#ifdef UNALIGNED_OK + if (best_len < sizeof(uint32_t)) { + for (;;) { + if (zng_memcmp_2(mbase_end+cur_match, scan_end) == 0 && + zng_memcmp_2(mbase_start+cur_match, scan_start) == 0) + break; + GOTO_NEXT_CHAIN; + } +# ifdef UNALIGNED64_OK + } else if (best_len >= sizeof(uint64_t)) { + for (;;) { + if (zng_memcmp_8(mbase_end+cur_match, scan_end) == 0 && + zng_memcmp_8(mbase_start+cur_match, scan_start) == 0) + break; + GOTO_NEXT_CHAIN; + } +# endif + } else { + for (;;) { + if (zng_memcmp_4(mbase_end+cur_match, scan_end) == 0 && + zng_memcmp_4(mbase_start+cur_match, scan_start) == 0) + break; + GOTO_NEXT_CHAIN; + } + } +#else + for (;;) { + if (mbase_end[cur_match] == scan_end[0] && mbase_end[cur_match+1] == scan_end[1] && + mbase_start[cur_match] == scan[0] && mbase_start[cur_match+1] == scan[1]) + break; + GOTO_NEXT_CHAIN; + } +#endif + uint32_t len = COMPARE256(scan+2, mbase_start+cur_match+2) + 2; + Assert(scan+len <= window+(unsigned)(s->window_size-1), "wild scan"); + + if (len > best_len) { + uint32_t match_start = cur_match - match_offset; + s->match_start = match_start; + + /* Do not look for matches beyond the end of the input. */ + if (len > lookahead) + return lookahead; + best_len = len; + if (best_len >= nice_match) + return best_len; + + offset = best_len-1; +#ifdef UNALIGNED_OK + if (best_len >= sizeof(uint32_t)) { + offset -= 2; +#ifdef UNALIGNED64_OK + if (best_len >= sizeof(uint64_t)) + offset -= 4; +#endif + } +#endif + +#ifdef UNALIGNED64_OK + memcpy(scan_end, scan+offset, sizeof(uint64_t)); +#elif defined(UNALIGNED_OK) + memcpy(scan_end, scan+offset, sizeof(uint32_t)); +#else + scan_end[0] = *(scan+offset); + scan_end[1] = *(scan+offset+1); +#endif + +#ifdef LONGEST_MATCH_SLOW + /* Look for a better string offset */ + if (UNLIKELY(len > STD_MIN_MATCH && match_start + len < strstart)) { + Pos pos, next_pos; + uint32_t i, hash; + unsigned char *scan_endstr; + + /* Go back to offset 0 */ + cur_match -= match_offset; + match_offset = 0; + next_pos = cur_match; + for (i = 0; i <= len - STD_MIN_MATCH; i++) { + pos = prev[(cur_match + i) & wmask]; + if (pos < next_pos) { + /* Hash chain is more distant, use it */ + if (pos <= limit_base + i) + goto break_matching; + next_pos = pos; + match_offset = (Pos)i; + } + } + /* Switch cur_match to next_pos chain */ + cur_match = next_pos; + + /* Try hash head at len-(STD_MIN_MATCH-1) position to see if we could get + * a better cur_match at the end of string. Using (STD_MIN_MATCH-1) lets + * us include one more byte into hash - the byte which will be checked + * in main loop now, and which allows to grow match by 1. + */ + scan_endstr = scan + len - (STD_MIN_MATCH+1); + + hash = s->update_hash(s, 0, scan_endstr[0]); + hash = s->update_hash(s, hash, scan_endstr[1]); + hash = s->update_hash(s, hash, scan_endstr[2]); + + pos = s->head[hash]; + if (pos < cur_match) { + match_offset = (Pos)(len - (STD_MIN_MATCH+1)); + if (pos <= limit_base + match_offset) + goto break_matching; + cur_match = pos; + } + + /* Update offset-dependent variables */ + limit = limit_base+match_offset; + mbase_start = window-match_offset; + mbase_end = (mbase_start+offset); + continue; + } +#endif + mbase_end = (mbase_start+offset); + } +#ifndef LONGEST_MATCH_SLOW + else if (UNLIKELY(early_exit)) { + /* The probability of finding a match later if we here is pretty low, so for + * performance it's best to outright stop here for the lower compression levels + */ + break; + } +#endif + GOTO_NEXT_CHAIN; + } + return best_len; + +#ifdef LONGEST_MATCH_SLOW +break_matching: + + if (best_len < s->lookahead) + return best_len; + + return s->lookahead; +#endif +} + +#undef LONGEST_MATCH_SLOW +#undef LONGEST_MATCH +#undef COMPARE256 diff --git a/3rdparty/zlib-ng/slide_hash.c b/3rdparty/zlib-ng/slide_hash.c new file mode 100644 index 000000000000..b9fbbdb69f86 --- /dev/null +++ b/3rdparty/zlib-ng/slide_hash.c @@ -0,0 +1,52 @@ +/* slide_hash.c -- slide hash table C implementation + * + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "deflate.h" + +/* =========================================================================== + * Slide the hash table when sliding the window down (could be avoided with 32 + * bit values at the expense of memory usage). We slide even when level == 0 to + * keep the hash table consistent if we switch back to level > 0 later. + */ +static inline void slide_hash_c_chain(Pos *table, uint32_t entries, uint16_t wsize) { +#ifdef NOT_TWEAK_COMPILER + table += entries; + do { + unsigned m; + m = *--table; + *table = (Pos)(m >= wsize ? m-wsize : 0); + /* If entries is not on any hash chain, prev[entries] is garbage but + * its value will never be used. + */ + } while (--entries); +#else + { + /* As of I make this change, gcc (4.8.*) isn't able to vectorize + * this hot loop using saturated-subtraction on x86-64 architecture. + * To avoid this defect, we can change the loop such that + * o. the pointer advance forward, and + * o. demote the variable 'm' to be local to the loop, and + * choose type "Pos" (instead of 'unsigned int') for the + * variable to avoid unnecessary zero-extension. + */ + unsigned int i; + Pos *q = table; + for (i = 0; i < entries; i++) { + Pos m = *q; + Pos t = (Pos)wsize; + *q++ = (Pos)(m >= t ? m-t: 0); + } + } +#endif /* NOT_TWEAK_COMPILER */ +} + +Z_INTERNAL void slide_hash_c(deflate_state *s) { + uint16_t wsize = (uint16_t)s->w_size; + + slide_hash_c_chain(s->head, HASH_SIZE, wsize); + slide_hash_c_chain(s->prev, wsize, wsize); +} diff --git a/3rdparty/zlib-ng/trees.c b/3rdparty/zlib-ng/trees.c new file mode 100644 index 000000000000..5bb88389baa3 --- /dev/null +++ b/3rdparty/zlib-ng/trees.c @@ -0,0 +1,818 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2021 Jean-loup Gailly + * detect_data_type() function provided freely by Cosmin Truta, 2006 + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +#include "zbuild.h" +#include "deflate.h" +#include "trees.h" +#include "trees_emit.h" +#include "trees_tbl.h" + +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const int *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + unsigned int max_length; /* max bit length for the codes */ +}; + +static const static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +static const static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +static const static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +static void init_block (deflate_state *s); +static void pqdownheap (deflate_state *s, ct_data *tree, int k); +static void gen_bitlen (deflate_state *s, tree_desc *desc); +static void build_tree (deflate_state *s, tree_desc *desc); +static void scan_tree (deflate_state *s, ct_data *tree, int max_code); +static void send_tree (deflate_state *s, ct_data *tree, int max_code); +static int build_bl_tree (deflate_state *s); +static void send_all_trees (deflate_state *s, int lcodes, int dcodes, int blcodes); +static void compress_block (deflate_state *s, const ct_data *ltree, const ct_data *dtree); +static int detect_data_type (deflate_state *s); +static void bi_flush (deflate_state *s); + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void Z_INTERNAL zng_tr_init(deflate_state *s) { + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef ZLIB_DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +static void init_block(deflate_state *s) { + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) + s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) + s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) + s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->sym_next = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +static void pqdownheap(deflate_state *s, ct_data *tree, int k) { + /* tree: the tree to restore */ + /* k: node to move down */ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) + break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; + k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +static void gen_bitlen(deflate_state *s, tree_desc *desc) { + /* desc: the tree descriptor */ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const int *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + unsigned int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + unsigned int bits; /* bit length */ + int xbits; /* extra bits */ + uint16_t f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) + s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max + 1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1u; + if (bits > max_length){ + bits = max_length; + overflow++; + } + tree[n].Len = (uint16_t)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) /* not a leaf node */ + continue; + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) + xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (unsigned long)f * (unsigned int)(bits + xbits); + if (stree) + s->static_len += (unsigned long)f * (unsigned int)(stree[n].Len + xbits); + } + if (overflow == 0) + return; + + Tracev((stderr, "\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length - 1; + while (s->bl_count[bits] == 0) + bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2u; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) + continue; + if (tree[m].Len != bits) { + Tracev((stderr, "code %d bits %d->%u\n", m, tree[m].Len, bits)); + s->opt_len += (unsigned long)(bits * tree[m].Freq); + s->opt_len -= (unsigned long)(tree[m].Len * tree[m].Freq); + tree[m].Len = (uint16_t)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +Z_INTERNAL void gen_codes(ct_data *tree, int max_code, uint16_t *bl_count) { + /* tree: the tree to decorate */ + /* max_code: largest code with non zero frequency */ + /* bl_count: number of codes at each bit length */ + uint16_t next_code[MAX_BITS+1]; /* next code value for each bit length */ + unsigned int code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + code = (code + bl_count[bits-1]) << 1; + next_code[bits] = (uint16_t)code; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert(code + bl_count[MAX_BITS]-1 == (1 << MAX_BITS)-1, "inconsistent bit counts"); + Tracev((stderr, "\ngen_codes: max_code %d ", max_code)); + + for (n = 0; n <= max_code; n++) { + int len = tree[n].Len; + if (len == 0) + continue; + /* Now reverse the bits */ + tree[n].Code = PREFIX(bi_reverse)(next_code[len]++, len); + + Tracecv(tree != static_ltree, (stderr, "\nn %3d %c l %2d c %4x (%x) ", + n, (isgraph(n & 0xff) ? n : ' '), len, tree[n].Code, next_code[len]-1)); + } +} + +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +static void build_tree(deflate_state *s, tree_desc *desc) { + /* desc: the tree descriptor */ + ct_data *tree = desc->dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0; + s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; + if (stree) + s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) + pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (unsigned char)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (uint16_t)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr, "\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +static void scan_tree(deflate_state *s, ct_data *tree, int max_code) { + /* tree: the tree to be scanned */ + /* max_code: and its largest code of non zero frequency */ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + uint16_t count = 0; /* repeat count of the current code */ + uint16_t max_count = 7; /* max repeat count */ + uint16_t min_count = 4; /* min repeat count */ + + if (nextlen == 0) + max_count = 138, min_count = 3; + + tree[max_code+1].Len = (uint16_t)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) + s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; + prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +static void send_tree(deflate_state *s, ct_data *tree, int max_code) { + /* tree: the tree to be scanned */ + /* max_code and its largest code of non zero frequency */ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) + max_count = 138, min_count = 3; + + // Temp local variables + uint32_t bi_valid = s->bi_valid; + uint64_t bi_buf = s->bi_buf; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { + send_code(s, curlen, s->bl_tree, bi_buf, bi_valid); + } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree, bi_buf, bi_valid); + count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree, bi_buf, bi_valid); + send_bits(s, count-3, 2, bi_buf, bi_valid); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree, bi_buf, bi_valid); + send_bits(s, count-3, 3, bi_buf, bi_valid); + + } else { + send_code(s, REPZ_11_138, s->bl_tree, bi_buf, bi_valid); + send_bits(s, count-11, 7, bi_buf, bi_valid); + } + count = 0; + prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } + + // Store back temp variables + s->bi_buf = bi_buf; + s->bi_valid = bi_valid; +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +static int build_bl_tree(deflate_state *s) { + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) + break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*((unsigned long)max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %lu, stat %lu", s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +static void send_all_trees(deflate_state *s, int lcodes, int dcodes, int blcodes) { + int rank; /* index in bl_order */ + + Assert(lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert(lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); + + // Temp local variables + uint32_t bi_valid = s->bi_valid; + uint64_t bi_buf = s->bi_buf; + + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5, bi_buf, bi_valid); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5, bi_buf, bi_valid); + send_bits(s, blcodes-4, 4, bi_buf, bi_valid); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2u ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3, bi_buf, bi_valid); + } + Tracev((stderr, "\nbl tree: sent %lu", s->bits_sent)); + + // Store back temp variables + s->bi_buf = bi_buf; + s->bi_valid = bi_valid; + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %lu", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %lu", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void Z_INTERNAL zng_tr_stored_block(deflate_state *s, char *buf, uint32_t stored_len, int last) { + /* buf: input block */ + /* stored_len: length of input block */ + /* last: one if this is the last block for a file */ + zng_tr_emit_tree(s, STORED_BLOCK, last); /* send block type */ + zng_tr_emit_align(s); /* align on byte boundary */ + cmpr_bits_align(s); + put_short(s, (uint16_t)stored_len); + put_short(s, (uint16_t)~stored_len); + cmpr_bits_add(s, 32); + sent_bits_add(s, 32); + if (stored_len) { + memcpy(s->pending_buf + s->pending, (unsigned char *)buf, stored_len); + s->pending += stored_len; + cmpr_bits_add(s, stored_len << 3); + sent_bits_add(s, stored_len << 3); + } +} + +/* =========================================================================== + * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) + */ +void Z_INTERNAL zng_tr_flush_bits(deflate_state *s) { + bi_flush(s); +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + */ +void Z_INTERNAL zng_tr_align(deflate_state *s) { + zng_tr_emit_tree(s, STATIC_TREES, 0); + zng_tr_emit_end_block(s, static_ltree, 0); + bi_flush(s); +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and write out the encoded block. + */ +void Z_INTERNAL zng_tr_flush_block(deflate_state *s, char *buf, uint32_t stored_len, int last) { + /* buf: input block, or NULL if too old */ + /* stored_len: length of input block */ + /* last: one if this is the last block for a file */ + unsigned long opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (UNLIKELY(s->sym_next == 0)) { + /* Emit an empty static tree block with no codes */ + opt_lenb = static_lenb = 0; + s->static_len = 7; + } else if (s->level > 0) { + /* Check if the file is binary or text */ + if (s->strm->data_type == Z_UNKNOWN) + s->strm->data_type = detect_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %lu, stat %lu", s->opt_len, s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %lu, stat %lu", s->opt_len, s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7) >> 3; + static_lenb = (s->static_len+3+7) >> 3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %u lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->sym_next / 3)); + + if (static_lenb <= opt_lenb || s->strategy == Z_FIXED) + opt_lenb = static_lenb; + + } else { + Assert(buf != NULL, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + + if (stored_len+4 <= opt_lenb && buf != NULL) { + /* 4: two words for the lengths + * The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + zng_tr_stored_block(s, buf, stored_len, last); + + } else if (static_lenb == opt_lenb) { + zng_tr_emit_tree(s, STATIC_TREES, last); + compress_block(s, (const ct_data *)static_ltree, (const ct_data *)static_dtree); + cmpr_bits_add(s, s->static_len); + } else { + zng_tr_emit_tree(s, DYN_TREES, last); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, max_blindex+1); + compress_block(s, (const ct_data *)s->dyn_ltree, (const ct_data *)s->dyn_dtree); + cmpr_bits_add(s, s->opt_len); + } + Assert(s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and unsigned long implemented on 32 bits. + */ + init_block(s); + + if (last) { + zng_tr_emit_align(s); + } + Tracev((stderr, "\ncomprlen %lu(%lu) ", s->compressed_len>>3, s->compressed_len-7*last)); +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +static void compress_block(deflate_state *s, const ct_data *ltree, const ct_data *dtree) { + /* ltree: literal tree */ + /* dtree: distance tree */ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned sx = 0; /* running index in sym_buf */ + + if (s->sym_next != 0) { + do { + dist = s->sym_buf[sx++] & 0xff; + dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8; + lc = s->sym_buf[sx++]; + if (dist == 0) { + zng_emit_lit(s, ltree, lc); + } else { + zng_emit_dist(s, ltree, dtree, lc, dist); + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and sym_buf is ok: */ + Assert(s->pending < s->lit_bufsize + sx, "pending_buf overflow"); + } while (sx < s->sym_next); + } + + zng_emit_end_block(s, ltree, 0); +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +static int detect_data_type(deflate_state *s) { + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long black_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>= 1) + if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("white-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +static void bi_flush(deflate_state *s) { + if (s->bi_valid == 64) { + put_uint64(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else { + if (s->bi_valid >= 32) { + put_uint32(s, (uint32_t)s->bi_buf); + s->bi_buf >>= 32; + s->bi_valid -= 32; + } + if (s->bi_valid >= 16) { + put_short(s, (uint16_t)s->bi_buf); + s->bi_buf >>= 16; + s->bi_valid -= 16; + } + if (s->bi_valid >= 8) { + put_byte(s, s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } + } +} + +/* =========================================================================== + * Reverse the first len bits of a code using bit manipulation + */ +Z_INTERNAL uint16_t PREFIX(bi_reverse)(unsigned code, int len) { + /* code: the value to invert */ + /* len: its bit length */ + Assert(len >= 1 && len <= 15, "code length must be 1-15"); +#define bitrev8(b) \ + (uint8_t)((((uint8_t)(b) * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32) + return (bitrev8(code >> 8) | (uint16_t)bitrev8(code) << 8) >> (16 - len); +} diff --git a/3rdparty/zlib-ng/trees.h b/3rdparty/zlib-ng/trees.h new file mode 100644 index 000000000000..e57f926489f4 --- /dev/null +++ b/3rdparty/zlib-ng/trees.h @@ -0,0 +1,40 @@ +#ifndef TREES_H_ +#define TREES_H_ + +/* Constants */ + +#define DIST_CODE_LEN 512 +/* see definition of array dist_code in trees.c */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +static const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +static const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static const int extra_blbits[BL_CODES] /* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +static const unsigned char bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; + /* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + + +/* Function definitions */ +void gen_codes (ct_data *tree, int max_code, uint16_t *bl_count); + +#endif diff --git a/3rdparty/zlib-ng/trees_emit.h b/3rdparty/zlib-ng/trees_emit.h new file mode 100644 index 000000000000..922daae509f5 --- /dev/null +++ b/3rdparty/zlib-ng/trees_emit.h @@ -0,0 +1,227 @@ +#ifndef TREES_EMIT_H_ +#define TREES_EMIT_H_ + +#include "zbuild.h" +#include "trees.h" + +#ifdef ZLIB_DEBUG +# include +# include +#endif + + +/* trees.h */ +extern Z_INTERNAL const ct_data static_ltree[L_CODES+2]; +extern Z_INTERNAL const ct_data static_dtree[D_CODES]; + +extern const unsigned char Z_INTERNAL zng_dist_code[DIST_CODE_LEN]; +extern const unsigned char Z_INTERNAL zng_length_code[STD_MAX_MATCH-STD_MIN_MATCH+1]; + +extern Z_INTERNAL const int base_length[LENGTH_CODES]; +extern Z_INTERNAL const int base_dist[D_CODES]; + +/* Bit buffer and deflate code stderr tracing */ +#ifdef ZLIB_DEBUG +# define send_bits_trace(s, value, length) { \ + Tracevv((stderr, " l %2d v %4llx ", (int)(length), (long long)(value))); \ + Assert(length > 0 && length <= BIT_BUF_SIZE, "invalid length"); \ + } +# define send_code_trace(s, c) \ + if (z_verbose > 2) { \ + fprintf(stderr, "\ncd %3d ", (c)); \ + } +#else +# define send_bits_trace(s, value, length) +# define send_code_trace(s, c) +#endif + +/* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (64 - bi_valid) bits from value, leaving (width - (64-bi_valid)) + * unused bits in value. + */ +#define send_bits(s, t_val, t_len, bi_buf, bi_valid) {\ + uint64_t val = (uint64_t)t_val;\ + uint32_t len = (uint32_t)t_len;\ + uint32_t total_bits = bi_valid + len;\ + send_bits_trace(s, val, len);\ + sent_bits_add(s, len);\ + if (total_bits < BIT_BUF_SIZE) {\ + bi_buf |= val << bi_valid;\ + bi_valid = total_bits;\ + } else if (bi_valid == BIT_BUF_SIZE) {\ + put_uint64(s, bi_buf);\ + bi_buf = val;\ + bi_valid = len;\ + } else {\ + bi_buf |= val << bi_valid;\ + put_uint64(s, bi_buf);\ + bi_buf = val >> (BIT_BUF_SIZE - bi_valid);\ + bi_valid = total_bits - BIT_BUF_SIZE;\ + }\ +} + +/* Send a code of the given tree. c and tree must not have side effects */ +#ifdef ZLIB_DEBUG +# define send_code(s, c, tree, bi_buf, bi_valid) { \ + send_code_trace(s, c); \ + send_bits(s, tree[c].Code, tree[c].Len, bi_buf, bi_valid); \ +} +#else +# define send_code(s, c, tree, bi_buf, bi_valid) \ + send_bits(s, tree[c].Code, tree[c].Len, bi_buf, bi_valid) +#endif + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +static void bi_windup(deflate_state *s) { + if (s->bi_valid > 56) { + put_uint64(s, s->bi_buf); + } else { + if (s->bi_valid > 24) { + put_uint32(s, (uint32_t)s->bi_buf); + s->bi_buf >>= 32; + s->bi_valid -= 32; + } + if (s->bi_valid > 8) { + put_short(s, (uint16_t)s->bi_buf); + s->bi_buf >>= 16; + s->bi_valid -= 16; + } + if (s->bi_valid > 0) { + put_byte(s, s->bi_buf); + } + } + s->bi_buf = 0; + s->bi_valid = 0; +} + +/* =========================================================================== + * Emit literal code + */ +static inline uint32_t zng_emit_lit(deflate_state *s, const ct_data *ltree, unsigned c) { + uint32_t bi_valid = s->bi_valid; + uint64_t bi_buf = s->bi_buf; + + send_code(s, c, ltree, bi_buf, bi_valid); + + s->bi_valid = bi_valid; + s->bi_buf = bi_buf; + + Tracecv(isgraph(c & 0xff), (stderr, " '%c' ", c)); + + return ltree[c].Len; +} + +/* =========================================================================== + * Emit match distance/length code + */ +static inline uint32_t zng_emit_dist(deflate_state *s, const ct_data *ltree, const ct_data *dtree, + uint32_t lc, uint32_t dist) { + uint32_t c, extra; + uint8_t code; + uint64_t match_bits; + uint32_t match_bits_len; + uint32_t bi_valid = s->bi_valid; + uint64_t bi_buf = s->bi_buf; + + /* Send the length code, len is the match length - STD_MIN_MATCH */ + code = zng_length_code[lc]; + c = code+LITERALS+1; + Assert(c < L_CODES, "bad l_code"); + send_code_trace(s, c); + + match_bits = ltree[c].Code; + match_bits_len = ltree[c].Len; + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + match_bits |= ((uint64_t)lc << match_bits_len); + match_bits_len += extra; + } + + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert(code < D_CODES, "bad d_code"); + send_code_trace(s, code); + + /* Send the distance code */ + match_bits |= ((uint64_t)dtree[code].Code << match_bits_len); + match_bits_len += dtree[code].Len; + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + match_bits |= ((uint64_t)dist << match_bits_len); + match_bits_len += extra; + } + + send_bits(s, match_bits, match_bits_len, bi_buf, bi_valid); + + s->bi_valid = bi_valid; + s->bi_buf = bi_buf; + + return match_bits_len; +} + +/* =========================================================================== + * Emit end block + */ +static inline void zng_emit_end_block(deflate_state *s, const ct_data *ltree, const int last) { + uint32_t bi_valid = s->bi_valid; + uint64_t bi_buf = s->bi_buf; + send_code(s, END_BLOCK, ltree, bi_buf, bi_valid); + s->bi_valid = bi_valid; + s->bi_buf = bi_buf; + Tracev((stderr, "\n+++ Emit End Block: Last: %u Pending: %u Total Out: %" PRIu64 "\n", + last, s->pending, (uint64_t)s->strm->total_out)); + Z_UNUSED(last); +} + +/* =========================================================================== + * Emit literal and count bits + */ +static inline void zng_tr_emit_lit(deflate_state *s, const ct_data *ltree, unsigned c) { + cmpr_bits_add(s, zng_emit_lit(s, ltree, c)); +} + +/* =========================================================================== + * Emit match and count bits + */ +static inline void zng_tr_emit_dist(deflate_state *s, const ct_data *ltree, const ct_data *dtree, + uint32_t lc, uint32_t dist) { + cmpr_bits_add(s, zng_emit_dist(s, ltree, dtree, lc, dist)); +} + +/* =========================================================================== + * Emit start of block + */ +static inline void zng_tr_emit_tree(deflate_state *s, int type, const int last) { + uint32_t bi_valid = s->bi_valid; + uint64_t bi_buf = s->bi_buf; + uint32_t header_bits = (type << 1) + last; + send_bits(s, header_bits, 3, bi_buf, bi_valid); + cmpr_bits_add(s, 3); + s->bi_valid = bi_valid; + s->bi_buf = bi_buf; + Tracev((stderr, "\n--- Emit Tree: Last: %u\n", last)); +} + +/* =========================================================================== + * Align bit buffer on a byte boundary and count bits + */ +static inline void zng_tr_emit_align(deflate_state *s) { + bi_windup(s); /* align on byte boundary */ + sent_bits_align(s); +} + +/* =========================================================================== + * Emit an end block and align bit buffer if last block + */ +static inline void zng_tr_emit_end_block(deflate_state *s, const ct_data *ltree, const int last) { + zng_emit_end_block(s, ltree, last); + cmpr_bits_add(s, 7); + if (last) + zng_tr_emit_align(s); +} + +#endif diff --git a/3rdparty/zlib-ng/trees_tbl.h b/3rdparty/zlib-ng/trees_tbl.h new file mode 100644 index 000000000000..a3912b7fd767 --- /dev/null +++ b/3rdparty/zlib-ng/trees_tbl.h @@ -0,0 +1,132 @@ +#ifndef TREES_TBL_H_ +#define TREES_TBL_H_ + +/* header created automatically with maketrees.c */ + +Z_INTERNAL const ct_data static_ltree[L_CODES+2] = { +{{ 12},{8}}, {{140},{8}}, {{ 76},{8}}, {{204},{8}}, {{ 44},{8}}, +{{172},{8}}, {{108},{8}}, {{236},{8}}, {{ 28},{8}}, {{156},{8}}, +{{ 92},{8}}, {{220},{8}}, {{ 60},{8}}, {{188},{8}}, {{124},{8}}, +{{252},{8}}, {{ 2},{8}}, {{130},{8}}, {{ 66},{8}}, {{194},{8}}, +{{ 34},{8}}, {{162},{8}}, {{ 98},{8}}, {{226},{8}}, {{ 18},{8}}, +{{146},{8}}, {{ 82},{8}}, {{210},{8}}, {{ 50},{8}}, {{178},{8}}, +{{114},{8}}, {{242},{8}}, {{ 10},{8}}, {{138},{8}}, {{ 74},{8}}, +{{202},{8}}, {{ 42},{8}}, {{170},{8}}, {{106},{8}}, {{234},{8}}, +{{ 26},{8}}, {{154},{8}}, {{ 90},{8}}, {{218},{8}}, {{ 58},{8}}, +{{186},{8}}, {{122},{8}}, {{250},{8}}, {{ 6},{8}}, {{134},{8}}, +{{ 70},{8}}, {{198},{8}}, {{ 38},{8}}, {{166},{8}}, {{102},{8}}, +{{230},{8}}, {{ 22},{8}}, {{150},{8}}, {{ 86},{8}}, {{214},{8}}, +{{ 54},{8}}, {{182},{8}}, {{118},{8}}, {{246},{8}}, {{ 14},{8}}, +{{142},{8}}, {{ 78},{8}}, {{206},{8}}, {{ 46},{8}}, {{174},{8}}, +{{110},{8}}, {{238},{8}}, {{ 30},{8}}, {{158},{8}}, {{ 94},{8}}, +{{222},{8}}, {{ 62},{8}}, {{190},{8}}, {{126},{8}}, {{254},{8}}, +{{ 1},{8}}, {{129},{8}}, {{ 65},{8}}, {{193},{8}}, {{ 33},{8}}, +{{161},{8}}, {{ 97},{8}}, {{225},{8}}, {{ 17},{8}}, {{145},{8}}, +{{ 81},{8}}, {{209},{8}}, {{ 49},{8}}, {{177},{8}}, {{113},{8}}, +{{241},{8}}, {{ 9},{8}}, {{137},{8}}, {{ 73},{8}}, {{201},{8}}, +{{ 41},{8}}, {{169},{8}}, {{105},{8}}, {{233},{8}}, {{ 25},{8}}, +{{153},{8}}, {{ 89},{8}}, {{217},{8}}, {{ 57},{8}}, {{185},{8}}, +{{121},{8}}, {{249},{8}}, {{ 5},{8}}, {{133},{8}}, {{ 69},{8}}, +{{197},{8}}, {{ 37},{8}}, {{165},{8}}, {{101},{8}}, {{229},{8}}, +{{ 21},{8}}, {{149},{8}}, {{ 85},{8}}, {{213},{8}}, {{ 53},{8}}, +{{181},{8}}, {{117},{8}}, {{245},{8}}, {{ 13},{8}}, {{141},{8}}, +{{ 77},{8}}, {{205},{8}}, {{ 45},{8}}, {{173},{8}}, {{109},{8}}, +{{237},{8}}, {{ 29},{8}}, {{157},{8}}, {{ 93},{8}}, {{221},{8}}, +{{ 61},{8}}, {{189},{8}}, {{125},{8}}, {{253},{8}}, {{ 19},{9}}, +{{275},{9}}, {{147},{9}}, {{403},{9}}, {{ 83},{9}}, {{339},{9}}, +{{211},{9}}, {{467},{9}}, {{ 51},{9}}, {{307},{9}}, {{179},{9}}, +{{435},{9}}, {{115},{9}}, {{371},{9}}, {{243},{9}}, {{499},{9}}, +{{ 11},{9}}, {{267},{9}}, {{139},{9}}, {{395},{9}}, {{ 75},{9}}, +{{331},{9}}, {{203},{9}}, {{459},{9}}, {{ 43},{9}}, {{299},{9}}, +{{171},{9}}, {{427},{9}}, {{107},{9}}, {{363},{9}}, {{235},{9}}, +{{491},{9}}, {{ 27},{9}}, {{283},{9}}, {{155},{9}}, {{411},{9}}, +{{ 91},{9}}, {{347},{9}}, {{219},{9}}, {{475},{9}}, {{ 59},{9}}, +{{315},{9}}, {{187},{9}}, {{443},{9}}, {{123},{9}}, {{379},{9}}, +{{251},{9}}, {{507},{9}}, {{ 7},{9}}, {{263},{9}}, {{135},{9}}, +{{391},{9}}, {{ 71},{9}}, {{327},{9}}, {{199},{9}}, {{455},{9}}, +{{ 39},{9}}, {{295},{9}}, {{167},{9}}, {{423},{9}}, {{103},{9}}, +{{359},{9}}, {{231},{9}}, {{487},{9}}, {{ 23},{9}}, {{279},{9}}, +{{151},{9}}, {{407},{9}}, {{ 87},{9}}, {{343},{9}}, {{215},{9}}, +{{471},{9}}, {{ 55},{9}}, {{311},{9}}, {{183},{9}}, {{439},{9}}, +{{119},{9}}, {{375},{9}}, {{247},{9}}, {{503},{9}}, {{ 15},{9}}, +{{271},{9}}, {{143},{9}}, {{399},{9}}, {{ 79},{9}}, {{335},{9}}, +{{207},{9}}, {{463},{9}}, {{ 47},{9}}, {{303},{9}}, {{175},{9}}, +{{431},{9}}, {{111},{9}}, {{367},{9}}, {{239},{9}}, {{495},{9}}, +{{ 31},{9}}, {{287},{9}}, {{159},{9}}, {{415},{9}}, {{ 95},{9}}, +{{351},{9}}, {{223},{9}}, {{479},{9}}, {{ 63},{9}}, {{319},{9}}, +{{191},{9}}, {{447},{9}}, {{127},{9}}, {{383},{9}}, {{255},{9}}, +{{511},{9}}, {{ 0},{7}}, {{ 64},{7}}, {{ 32},{7}}, {{ 96},{7}}, +{{ 16},{7}}, {{ 80},{7}}, {{ 48},{7}}, {{112},{7}}, {{ 8},{7}}, +{{ 72},{7}}, {{ 40},{7}}, {{104},{7}}, {{ 24},{7}}, {{ 88},{7}}, +{{ 56},{7}}, {{120},{7}}, {{ 4},{7}}, {{ 68},{7}}, {{ 36},{7}}, +{{100},{7}}, {{ 20},{7}}, {{ 84},{7}}, {{ 52},{7}}, {{116},{7}}, +{{ 3},{8}}, {{131},{8}}, {{ 67},{8}}, {{195},{8}}, {{ 35},{8}}, +{{163},{8}}, {{ 99},{8}}, {{227},{8}} +}; + +Z_INTERNAL const ct_data static_dtree[D_CODES] = { +{{ 0},{5}}, {{16},{5}}, {{ 8},{5}}, {{24},{5}}, {{ 4},{5}}, +{{20},{5}}, {{12},{5}}, {{28},{5}}, {{ 2},{5}}, {{18},{5}}, +{{10},{5}}, {{26},{5}}, {{ 6},{5}}, {{22},{5}}, {{14},{5}}, +{{30},{5}}, {{ 1},{5}}, {{17},{5}}, {{ 9},{5}}, {{25},{5}}, +{{ 5},{5}}, {{21},{5}}, {{13},{5}}, {{29},{5}}, {{ 3},{5}}, +{{19},{5}}, {{11},{5}}, {{27},{5}}, {{ 7},{5}}, {{23},{5}} +}; + +const unsigned char Z_INTERNAL zng_dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const unsigned char Z_INTERNAL zng_length_code[STD_MAX_MATCH-STD_MIN_MATCH+1] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +Z_INTERNAL const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +Z_INTERNAL const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + +#endif /* TREES_TBL_H_ */ diff --git a/3rdparty/zlib-ng/uncompr.c b/3rdparty/zlib-ng/uncompr.c new file mode 100644 index 000000000000..311eca2b06bf --- /dev/null +++ b/3rdparty/zlib-ng/uncompr.c @@ -0,0 +1,80 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "zutil.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. *sourceLen is + the byte length of the source buffer. Upon entry, *destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, + *destLen is the size of the decompressed data and *sourceLen is the number + of source bytes consumed. Upon return, source + *sourceLen points to the + first unused input byte. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, or + Z_DATA_ERROR if the input data was corrupted, including if the input data is + an incomplete zlib stream. +*/ +int Z_EXPORT PREFIX(uncompress2)(unsigned char *dest, z_uintmax_t *destLen, const unsigned char *source, z_uintmax_t *sourceLen) { + PREFIX3(stream) stream; + int err; + const unsigned int max = (unsigned int)-1; + z_uintmax_t len, left; + unsigned char buf[1]; /* for detection of incomplete stream when *destLen == 0 */ + + len = *sourceLen; + if (*destLen) { + left = *destLen; + *destLen = 0; + } else { + left = 1; + dest = buf; + } + + stream.next_in = (z_const unsigned char *)source; + stream.avail_in = 0; + stream.zalloc = NULL; + stream.zfree = NULL; + stream.opaque = NULL; + + err = PREFIX(inflateInit)(&stream); + if (err != Z_OK) return err; + + stream.next_out = dest; + stream.avail_out = 0; + + do { + if (stream.avail_out == 0) { + stream.avail_out = left > (unsigned long)max ? max : (unsigned int)left; + left -= stream.avail_out; + } + if (stream.avail_in == 0) { + stream.avail_in = len > (unsigned long)max ? max : (unsigned int)len; + len -= stream.avail_in; + } + err = PREFIX(inflate)(&stream, Z_NO_FLUSH); + } while (err == Z_OK); + + *sourceLen -= len + stream.avail_in; + if (dest != buf) + *destLen = (z_size_t)stream.total_out; + else if (stream.total_out && err == Z_BUF_ERROR) + left = 1; + + PREFIX(inflateEnd)(&stream); + return err == Z_STREAM_END ? Z_OK : + err == Z_NEED_DICT ? Z_DATA_ERROR : + err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR : + err; +} + +int Z_EXPORT PREFIX(uncompress)(unsigned char *dest, z_uintmax_t *destLen, const unsigned char *source, z_uintmax_t sourceLen) { + return PREFIX(uncompress2)(dest, destLen, source, &sourceLen); +} diff --git a/3rdparty/zlib-ng/zbuild.h b/3rdparty/zlib-ng/zbuild.h new file mode 100644 index 000000000000..d550b4c582c3 --- /dev/null +++ b/3rdparty/zlib-ng/zbuild.h @@ -0,0 +1,260 @@ +#ifndef _ZBUILD_H +#define _ZBUILD_H + +#define _POSIX_SOURCE 1 /* fileno */ +#ifndef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200809L /* snprintf, posix_memalign, strdup */ +#endif +#ifndef _ISOC11_SOURCE +# define _ISOC11_SOURCE 1 /* aligned_alloc */ +#endif +#ifdef __OpenBSD__ +# define _BSD_SOURCE 1 +#endif + +#include +#include +#include +#include + +/* Determine compiler version of C Standard */ +#ifdef __STDC_VERSION__ +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +# if __STDC_VERSION__ >= 201112L +# ifndef STDC11 +# define STDC11 +# endif +# endif +#endif + +#ifndef Z_HAS_ATTRIBUTE +# if defined(__has_attribute) +# define Z_HAS_ATTRIBUTE(a) __has_attribute(a) +# else +# define Z_HAS_ATTRIBUTE(a) 0 +# endif +#endif + +#ifndef Z_FALLTHROUGH +# if Z_HAS_ATTRIBUTE(__fallthrough__) || (defined(__GNUC__) && (__GNUC__ >= 7)) +# define Z_FALLTHROUGH __attribute__((__fallthrough__)) +# else +# define Z_FALLTHROUGH do {} while(0) /* fallthrough */ +# endif +#endif + +#ifndef Z_TARGET +# if Z_HAS_ATTRIBUTE(__target__) +# define Z_TARGET(x) __attribute__((__target__(x))) +# else +# define Z_TARGET(x) +# endif +#endif + +/* This has to be first include that defines any types */ +#if defined(_MSC_VER) +# if defined(_WIN64) + typedef __int64 ssize_t; +# else + typedef long ssize_t; +# endif + +# if defined(_WIN64) + #define SSIZE_MAX _I64_MAX +# else + #define SSIZE_MAX LONG_MAX +# endif +#endif + +/* MS Visual Studio does not allow inline in C, only C++. + But it provides __inline instead, so use that. */ +#if defined(_MSC_VER) && !defined(inline) && !defined(__cplusplus) +# define inline __inline +#endif + +#if defined(ZLIB_COMPAT) +# define PREFIX(x) x +# define PREFIX2(x) ZLIB_ ## x +# define PREFIX3(x) z_ ## x +# define PREFIX4(x) x ## 64 +# define zVersion zlibVersion +#else +# define PREFIX(x) zng_ ## x +# define PREFIX2(x) ZLIBNG_ ## x +# define PREFIX3(x) zng_ ## x +# define PREFIX4(x) zng_ ## x +# define zVersion zlibng_version +# define z_size_t size_t +#endif + +/* In zlib-compat some functions and types use unsigned long, but zlib-ng use size_t */ +#if defined(ZLIB_COMPAT) +# define z_uintmax_t unsigned long +#else +# define z_uintmax_t size_t +#endif + +/* Minimum of a and b. */ +#define MIN(a, b) ((a) > (b) ? (b) : (a)) +/* Maximum of a and b. */ +#define MAX(a, b) ((a) < (b) ? (b) : (a)) +/* Ignore unused variable warning */ +#define Z_UNUSED(var) (void)(var) + +#if defined(HAVE_VISIBILITY_INTERNAL) +# define Z_INTERNAL __attribute__((visibility ("internal"))) +#elif defined(HAVE_VISIBILITY_HIDDEN) +# define Z_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define Z_INTERNAL +#endif + +/* Symbol versioning helpers, allowing multiple versions of a function to exist. + * Functions using this must also be added to zlib-ng.map for each version. + * Double @@ means this is the default for newly compiled applications to link against. + * Single @ means this is kept for backwards compatibility. + * This is only used for Zlib-ng native API, and only on platforms supporting this. + */ +#if defined(HAVE_SYMVER) +# define ZSYMVER(func,alias,ver) __asm__(".symver " func ", " alias "@ZLIB_NG_" ver); +# define ZSYMVER_DEF(func,alias,ver) __asm__(".symver " func ", " alias "@@ZLIB_NG_" ver); +#else +# define ZSYMVER(func,alias,ver) +# define ZSYMVER_DEF(func,alias,ver) +#endif + +#ifndef __cplusplus +# define Z_REGISTER register +#else +# define Z_REGISTER +#endif + +/* Reverse the bytes in a value. Use compiler intrinsics when + possible to take advantage of hardware implementations. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1300) +# include +# pragma intrinsic(_byteswap_ulong) +# define ZSWAP16(q) _byteswap_ushort(q) +# define ZSWAP32(q) _byteswap_ulong(q) +# define ZSWAP64(q) _byteswap_uint64(q) + +#elif defined(__clang__) || (defined(__GNUC__) && \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) +# define ZSWAP16(q) __builtin_bswap16(q) +# define ZSWAP32(q) __builtin_bswap32(q) +# define ZSWAP64(q) __builtin_bswap64(q) + +#elif defined(__GNUC__) && (__GNUC__ >= 2) && defined(__linux__) +# include +# define ZSWAP16(q) bswap_16(q) +# define ZSWAP32(q) bswap_32(q) +# define ZSWAP64(q) bswap_64(q) + +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) +# include +# define ZSWAP16(q) bswap16(q) +# define ZSWAP32(q) bswap32(q) +# define ZSWAP64(q) bswap64(q) +#elif defined(__OpenBSD__) +# include +# define ZSWAP16(q) swap16(q) +# define ZSWAP32(q) swap32(q) +# define ZSWAP64(q) swap64(q) +#elif defined(__INTEL_COMPILER) +/* ICC does not provide a two byte swap. */ +# define ZSWAP16(q) ((((q) & 0xff) << 8) | (((q) & 0xff00) >> 8)) +# define ZSWAP32(q) _bswap(q) +# define ZSWAP64(q) _bswap64(q) + +#else +# define ZSWAP16(q) ((((q) & 0xff) << 8) | (((q) & 0xff00) >> 8)) +# define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) +# define ZSWAP64(q) \ + (((q & 0xFF00000000000000u) >> 56u) | \ + ((q & 0x00FF000000000000u) >> 40u) | \ + ((q & 0x0000FF0000000000u) >> 24u) | \ + ((q & 0x000000FF00000000u) >> 8u) | \ + ((q & 0x00000000FF000000u) << 8u) | \ + ((q & 0x0000000000FF0000u) << 24u) | \ + ((q & 0x000000000000FF00u) << 40u) | \ + ((q & 0x00000000000000FFu) << 56u)) +#endif + +/* Only enable likely/unlikely if the compiler is known to support it */ +#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__INTEL_COMPILER) || defined(__clang__) +# define LIKELY_NULL(x) __builtin_expect((x) != 0, 0) +# define LIKELY(x) __builtin_expect(!!(x), 1) +# define UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +# define LIKELY_NULL(x) x +# define LIKELY(x) x +# define UNLIKELY(x) x +#endif /* (un)likely */ + +#if defined(HAVE_ATTRIBUTE_ALIGNED) +# define ALIGNED_(x) __attribute__ ((aligned(x))) +#elif defined(_MSC_VER) +# define ALIGNED_(x) __declspec(align(x)) +#endif + +/* Diagnostic functions */ +#ifdef ZLIB_DEBUG +# include + extern int Z_INTERNAL z_verbose; + extern void Z_INTERNAL z_error(const char *m); +# define Assert(cond, msg) {if (!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose >= 0) fprintf x;} +# define Tracev(x) {if (z_verbose > 0) fprintf x;} +# define Tracevv(x) {if (z_verbose > 1) fprintf x;} +# define Tracec(c, x) {if (z_verbose > 0 && (c)) fprintf x;} +# define Tracecv(c, x) {if (z_verbose > 1 && (c)) fprintf x;} +#else +# define Assert(cond, msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c, x) +# define Tracecv(c, x) +#endif + +#ifndef NO_UNALIGNED +# if defined(__x86_64__) || defined(_M_X64) || defined(__amd64__) || defined(_M_AMD64) +# define UNALIGNED_OK +# define UNALIGNED64_OK +# elif defined(__i386__) || defined(__i486__) || defined(__i586__) || \ + defined(__i686__) || defined(_X86_) || defined(_M_IX86) +# define UNALIGNED_OK +# elif defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) +# if (defined(__GNUC__) && defined(__ARM_FEATURE_UNALIGNED)) || !defined(__GNUC__) +# define UNALIGNED_OK +# define UNALIGNED64_OK +# endif +# elif defined(__arm__) || (_M_ARM >= 7) +# if (defined(__GNUC__) && defined(__ARM_FEATURE_UNALIGNED)) || !defined(__GNUC__) +# define UNALIGNED_OK +# endif +# elif defined(__powerpc64__) || defined(__ppc64__) +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define UNALIGNED_OK +# define UNALIGNED64_OK +# endif +# endif +#endif + +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# define Z_MEMORY_SANITIZER 1 +# include +# endif +#endif + +#ifndef Z_MEMORY_SANITIZER +# define __msan_unpoison(a, size) do { Z_UNUSED(a); Z_UNUSED(size); } while (0) +#endif + +#endif diff --git a/3rdparty/zlib-ng/zconf.h.in b/3rdparty/zlib-ng/zconf.h.in new file mode 100644 index 000000000000..7a6e281e849d --- /dev/null +++ b/3rdparty/zlib-ng/zconf.h.in @@ -0,0 +1,206 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ZCONF_H +#define ZCONF_H + +#include "zlib_name_mangling.h" + +#if !defined(_WIN32) && defined(__WIN32__) +# define _WIN32 +#endif + +/* Clang macro for detecting declspec support + * https://clang.llvm.org/docs/LanguageExtensions.html#has-declspec-attribute + */ +#ifndef __has_declspec_attribute +# define __has_declspec_attribute(x) 0 +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# define MAX_MEM_LEVEL 9 +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MIN_WBITS +# define MIN_WBITS 8 /* 256 LZ77 window */ +#endif +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + +/* Type declarations */ + + +#ifndef OF /* function prototypes */ +# define OF(args) args +#endif + +#ifdef ZLIB_INTERNAL +# define Z_INTERNAL ZLIB_INTERNAL +#endif + +/* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +#if defined(ZLIB_DLL) && (defined(_WIN32) || (__has_declspec_attribute(dllexport) && __has_declspec_attribute(dllimport))) +# ifdef Z_INTERNAL +# define Z_EXTERN extern __declspec(dllexport) +# else +# define Z_EXTERN extern __declspec(dllimport) +# endif +#endif + +/* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +#if defined(ZLIB_WINAPI) && defined(_WIN32) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define Z_EXPORT WINAPI +# define Z_EXPORTVA WINAPIV +#endif + +#ifndef Z_EXTERN +# define Z_EXTERN extern +#endif +#ifndef Z_EXPORT +# define Z_EXPORT +#endif +#ifndef Z_EXPORTVA +# define Z_EXPORTVA +#endif + +/* Conditional exports */ +#define ZNG_CONDEXPORT Z_INTERNAL + +/* For backwards compatibility */ + +#ifndef ZEXTERN +# define ZEXTERN Z_EXTERN +#endif +#ifndef ZEXPORT +# define ZEXPORT Z_EXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA Z_EXPORTVA +#endif +#ifndef FAR +# define FAR +#endif + +/* Legacy zlib typedefs for backwards compatibility. Don't assume stdint.h is defined. */ +typedef unsigned char Byte; +typedef Byte Bytef; + +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +typedef char charf; +typedef int intf; +typedef uInt uIntf; +typedef uLong uLongf; + +typedef void const *voidpc; +typedef void *voidpf; +typedef void *voidp; + +typedef unsigned int z_crc_t; + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by configure/cmake/etc */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef NEED_PTRDIFF_T /* may be set to #if 1 by configure/cmake/etc */ +typedef PTRDIFF_TYPE ptrdiff_t; +#endif + +#include /* for off_t */ + +#include /* for wchar_t and NULL */ + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifndef z_off_t +# define z_off_t off_t +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(__MSYS__) +# define z_off64_t _off64_t +# elif defined(_WIN32) && !defined(__GNUC__) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +typedef size_t z_size_t; + +#endif /* ZCONF_H */ diff --git a/3rdparty/zlib-ng/zendian.h b/3rdparty/zlib-ng/zendian.h new file mode 100644 index 000000000000..28177a609ff1 --- /dev/null +++ b/3rdparty/zlib-ng/zendian.h @@ -0,0 +1,60 @@ +/* zendian.h -- define BYTE_ORDER for endian tests + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ENDIAN_H_ +#define ENDIAN_H_ + +/* First check whether the compiler knows the target __BYTE_ORDER__. */ +#if defined(__BYTE_ORDER__) +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# if !defined(LITTLE_ENDIAN) +# define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ +# endif +# if !defined(BYTE_ORDER) +# define BYTE_ORDER LITTLE_ENDIAN +# endif +# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# if !defined(BIG_ENDIAN) +# define BIG_ENDIAN __ORDER_BIG_ENDIAN__ +# endif +# if !defined(BYTE_ORDER) +# define BYTE_ORDER BIG_ENDIAN +# endif +# endif +#elif defined(__MINGW32__) +# include +#elif defined(_WIN32) +# define LITTLE_ENDIAN 1234 +# define BIG_ENDIAN 4321 +# if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64) || defined (_M_ARM) || defined (_M_ARM64) || defined (_M_ARM64EC) +# define BYTE_ORDER LITTLE_ENDIAN +# else +# error Unknown endianness! +# endif +#elif defined(__linux__) +# include +#elif defined(__APPLE__) +# include +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) +# include +#elif defined(__sun) || defined(sun) +# include +# if !defined(LITTLE_ENDIAN) +# define LITTLE_ENDIAN 4321 +# endif +# if !defined(BIG_ENDIAN) +# define BIG_ENDIAN 1234 +# endif +# if !defined(BYTE_ORDER) +# if defined(_BIG_ENDIAN) +# define BYTE_ORDER BIG_ENDIAN +# else +# define BYTE_ORDER LITTLE_ENDIAN +# endif +# endif +#else +# include +#endif + +#endif diff --git a/3rdparty/zlib-ng/zlib.h.in b/3rdparty/zlib-ng/zlib.h.in new file mode 100644 index 000000000000..eabb94afe09c --- /dev/null +++ b/3rdparty/zlib-ng/zlib.h.in @@ -0,0 +1,1859 @@ +#ifndef ZLIB_H_ +#define ZLIB_H_ +/* zlib.h -- interface of the 'zlib-ng' compression library + Forked from and compatible with zlib 1.2.13 + + Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files https://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifdef ZNGLIB_H_ +# error Include zlib-ng.h for zlib-ng API or zlib.h for zlib-compat API but not both +#endif + +#ifndef RC_INVOKED +#include +#include + +#include "zconf.h" + +#ifndef ZCONF_H +# error Missing zconf.h add binary output directory to include directories +#endif +#endif /* RC_INVOKED */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIBNG_VERSION "2.1.6" +#define ZLIBNG_VERNUM 0x020106F0L /* MMNNRRSM: major minor revision status modified */ +#define ZLIBNG_VER_MAJOR 2 +#define ZLIBNG_VER_MINOR 1 +#define ZLIBNG_VER_REVISION 6 +#define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release (DEPRECATED) */ +#define ZLIBNG_VER_STATUSH 0xF /* Hex values: 0=devel, 1-E=beta, F=Release */ +#define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ + +#define ZLIB_VERSION "1.3.0.zlib-ng" +#define ZLIB_VERNUM 0x130f +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 3 +#define ZLIB_VER_REVISION 0 +#define ZLIB_VER_SUBREVISION 15 /* 15=fork (0xf) */ + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef void *(*alloc_func) (void *opaque, unsigned int items, unsigned int size); +typedef void (*free_func) (void *opaque, void *address); + +struct internal_state; + +typedef struct z_stream_s { + z_const unsigned char *next_in; /* next input byte */ + uint32_t avail_in; /* number of bytes available at next_in */ + unsigned long total_in; /* total number of input bytes read so far */ + + unsigned char *next_out; /* next output byte will go here */ + uint32_t avail_out; /* remaining free space at next_out */ + unsigned long total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + void *opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + unsigned long adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + unsigned long reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream *z_streamp; /* Obsolete type, retained for compatibility only */ + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + unsigned long time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + unsigned char *extra; /* pointer to extra field or NULL if none */ + unsigned int extra_len; /* extra field length (valid if extra != NULL) */ + unsigned int extra_max; /* space at extra (only when reading header) */ + unsigned char *name; /* pointer to zero-terminated file name or NULL */ + unsigned int name_max; /* space at name (only when reading header) */ + unsigned char *comment; /* pointer to zero-terminated comment or NULL */ + unsigned int comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used when writing a gzip file) */ +} gz_header; + +typedef gz_header *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL NULL /* for compatibility with zlib, was for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +Z_EXTERN const char * Z_EXPORT zlibVersion(void); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +Z_EXTERN int Z_EXPORT deflateInit (z_stream *strm, int level); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. total_in, total_out, adler, and msg are initialized. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +Z_EXTERN int Z_EXPORT deflate(z_stream *strm, int flush); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more output + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six when the flush marker begins, in order to avoid + repeated flush markers upon calling deflate() again when avail_out == 0. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL) or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +Z_EXTERN int Z_EXPORT deflateEnd(z_stream *strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +Z_EXTERN int Z_EXPORT inflateInit (z_stream *strm); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. total_in, total_out, adler, and + msg are initialized. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +Z_EXTERN int Z_EXPORT inflate(z_stream *strm, int flush); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress is possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +Z_EXTERN int Z_EXPORT inflateEnd(z_stream *strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +Z_EXTERN int Z_EXPORT deflateInit2 (z_stream *strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy); + + This is another version of deflateInit with more compression options. The + fields zalloc, zfree and opaque must be initialized before by the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +Z_EXTERN int Z_EXPORT deflateSetDictionary(z_stream *strm, + const unsigned char *dictionary, + unsigned int dictLength); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +Z_EXTERN int Z_EXPORT deflateGetDictionary (z_stream *strm, unsigned char *dictionary, unsigned int *dictLength); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +Z_EXTERN int Z_EXPORT deflateCopy(z_stream *dest, z_stream *source); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +Z_EXTERN int Z_EXPORT deflateReset(z_stream *strm); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. total_in, total_out, adler, and msg are initialized. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +Z_EXTERN int Z_EXPORT deflateParams(z_stream *strm, int level, int strategy); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if there have been any deflate() calls since the + state was initialized or reset, then the input available so far is + compressed with the old level and strategy using deflate(strm, Z_BLOCK). + There are three approaches for the compression levels 0, 1..3, and 4..9 + respectively. The new level and strategy will take effect at the next call + of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +Z_EXTERN int Z_EXPORT deflateTune(z_stream *strm, int good_length, int max_lazy, int nice_length, int max_chain); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +Z_EXTERN unsigned long Z_EXPORT deflateBound(z_stream *strm, unsigned long sourceLen); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +Z_EXTERN int Z_EXPORT deflatePending(z_stream *strm, uint32_t *pending, int *bits); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +Z_EXTERN int Z_EXPORT deflatePrime(z_stream *strm, int bits, int value); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +Z_EXTERN int Z_EXPORT deflateSetHeader(z_stream *strm, gz_headerp head); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not NULL, name and comment are terminated with + a zero byte, and that if extra is not NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to the current operating system, with no + extra, name, or comment fields. The gzip header is returned to the default + state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +Z_EXTERN int Z_EXPORT inflateInit2(z_stream *strm, int windowBits); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will *not* automatically decode concatenated gzip members. + inflate() will return Z_STREAM_END at the end of the gzip member. The state + would need to be reset to continue decoding a subsequent gzip member. This + *must* be done if there is more data after a gzip member, in order for the + decompression to be compliant with the gzip standard (RFC 1952). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +Z_EXTERN int Z_EXPORT inflateSetDictionary(z_stream *strm, const unsigned char *dictionary, unsigned int dictLength); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +Z_EXTERN int Z_EXPORT inflateGetDictionary(z_stream *strm, unsigned char *dictionary, unsigned int *dictLength); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +Z_EXTERN int Z_EXPORT inflateSync(z_stream *strm); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +Z_EXTERN int Z_EXPORT inflateCopy(z_stream *dest, z_stream *source); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +Z_EXTERN int Z_EXPORT inflateReset(z_stream *strm); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + total_in, total_out, adler, and msg are initialized. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +Z_EXTERN int Z_EXPORT inflateReset2(z_stream *strm, int windowBits); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL), or if + the windowBits parameter is invalid. +*/ + +Z_EXTERN int Z_EXPORT inflatePrime(z_stream *strm, int bits, int value); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +Z_EXTERN long Z_EXPORT inflateMark(z_stream *strm); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +Z_EXTERN int Z_EXPORT inflateGetHeader(z_stream *strm, gz_headerp head); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not NULL and the respective field is not + present in the header, then that field is set to NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +Z_EXTERN int Z_EXPORT inflateBackInit (z_stream *strm, int windowBits, unsigned char *window); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef uint32_t (*in_func) (void *, z_const unsigned char * *); +typedef int (*out_func) (void *, unsigned char *, uint32_t); + +Z_EXTERN int Z_EXPORT inflateBack(z_stream *strm, in_func in, void *in_desc, out_func out, void *out_desc); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is NULL, then in() will be called + immediately for input. If strm->next_in is not NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be NULL only if in() returned an error. If + strm->next_in is not NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +Z_EXTERN int Z_EXPORT inflateBackEnd(z_stream *strm); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +Z_EXTERN unsigned long Z_EXPORT zlibCompileFlags(void); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of unsigned int + 3.2: size of unsigned long + 5.4: size of void * (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed (not supported by zlib-ng) + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +Z_EXTERN int Z_EXPORT compress(unsigned char *dest, unsigned long *destLen, const unsigned char *source, unsigned long sourceLen); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +Z_EXTERN int Z_EXPORT compress2(unsigned char *dest, unsigned long *destLen, const unsigned char *source, + unsigned long sourceLen, int level); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +Z_EXTERN unsigned long Z_EXPORT compressBound(unsigned long sourceLen); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +Z_EXTERN int Z_EXPORT uncompress(unsigned char *dest, unsigned long *destLen, const unsigned char *source, unsigned long sourceLen); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + + +Z_EXTERN int Z_EXPORT uncompress2 (unsigned char *dest, unsigned long *destLen, + const unsigned char *source, unsigned long *sourceLen); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +Z_EXTERN gzFile Z_EXPORT gzopen(const char *path, const char *mode); + + Open the gzip (.gz) file at path for reading and decompressing, or + compressing and writing. The mode parameter is as in fopen ("rb" or "wb") + but can also include a compression level ("wb9") or a strategy: 'f' for + filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", + 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression + as in "wb9F". (See the description of deflateInit2 for more information + about the strategy parameter.) 'T' will request transparent writing or + appending with no compression and not using the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +Z_EXTERN gzFile Z_EXPORT gzdopen(int fd, const char *mode); +/* + Associate a gzFile with the file descriptor fd. File descriptors are + obtained from calls like open, dup, creat, pipe or fileno (if the file has + been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +Z_EXTERN int Z_EXPORT gzbuffer(gzFile file, unsigned size); +/* + Set the internal buffer size used by this library's functions for file to + size. The default buffer size is 8192 bytes. This function must be called + after gzopen() or gzdopen(), and before any other calls that read or write + the file. The buffer memory allocation is always deferred to the first read + or write. Three times that size in buffer space is allocated. A larger + buffer size of, for example, 64K or 128K bytes will noticeably increase the + speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +Z_EXTERN int Z_EXPORT gzsetparams(gzFile file, int level, int strategy); +/* + Dynamically update the compression level and strategy for file. See the + description of deflateInit2 for the meaning of these parameters. Previously + provided data is flushed before applying the parameter changes. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +Z_EXTERN int Z_EXPORT gzread(gzFile file, void *buf, unsigned len); +/* + Read and decompress up to len uncompressed bytes from file into buf. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +Z_EXTERN size_t Z_EXPORT gzfread (void *buf, size_t size, size_t nitems, gzFile file); +/* + Read and decompress up to nitems items of size size from file into buf, + otherwise operating as gzread() does. This duplicates the interface of + stdio's fread(), with size_t request and return types. If the library + defines size_t, then z_size_t is identical to size_t. If not, then z_size_t + is an unsigned integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevertheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, resetting and retrying on end-of-file, when size is not 1. +*/ + +Z_EXTERN int Z_EXPORT gzwrite(gzFile file, void const *buf, unsigned len); +/* + Compress and write the len uncompressed bytes at buf to file. gzwrite + returns the number of uncompressed bytes written or 0 in case of error. +*/ + +Z_EXTERN size_t Z_EXPORT gzfwrite(void const *buf, size_t size, size_t nitems, gzFile file); +/* + Compress and write nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +Z_EXTERN int Z_EXPORTVA gzprintf(gzFile file, const char *format, ...); +/* + Convert, format, compress, and write the arguments (...) to file under + control of the string format, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf(), + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +Z_EXTERN int Z_EXPORT gzputs(gzFile file, const char *s); +/* + Compress and write the given null-terminated string s to file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +Z_EXTERN char * Z_EXPORT gzgets(gzFile file, char *buf, int len); +/* + Read and decompress bytes from file into buf, until len-1 characters are + read, or until a newline character is read and transferred to buf, or an + end-of-file condition is encountered. If any characters are read or if len + is one, the string is terminated with a null character. If no characters + are read due to an end-of-file or len is less than one, then the buffer is + left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +Z_EXTERN int Z_EXPORT gzputc(gzFile file, int c); +/* + Compress and write c, converted to an unsigned char, into file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +Z_EXTERN int Z_EXPORT gzgetc(gzFile file); +/* + Read and decompress one byte from file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +Z_EXTERN int Z_EXPORT gzungetc(int c, gzFile file); +/* + Push c back onto the stream for file to be read as the first character on + the next read. At least one character of push-back is always allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +Z_EXTERN int Z_EXPORT gzflush(gzFile file, int flush); +/* + Flush all pending output to file. The parameter flush is as in the + deflate() function. The return value is the zlib error number (see function + gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +Z_EXTERN z_off_t Z_EXPORT gzseek (gzFile file, z_off_t offset, int whence); + + Set the starting position to offset relative to whence for the next gzread + or gzwrite on file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +Z_EXTERN int Z_EXPORT gzrewind(gzFile file); +/* + Rewind file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). +*/ + +/* +Z_EXTERN z_off_t Z_EXPORT gztell(gzFile file); + + Return the starting position for the next gzread or gzwrite on file. + This position represents a number of bytes in the uncompressed data stream, + and is zero when starting, even if appending or reading a gzip stream from + the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +Z_EXTERN z_off_t Z_EXPORT gzoffset(gzFile file); + + Return the current compressed (actual) read or write offset of file. This + offset includes the count of bytes that precede the gzip stream, for example + when appending or when using gzdopen() for reading. When reading, the + offset does not include as yet unused buffered input. This information can + be used for a progress indicator. On error, gzoffset() returns -1. +*/ + +Z_EXTERN int Z_EXPORT gzeof(gzFile file); +/* + Return true (1) if the end-of-file indicator for file has been set while + reading, false (0) otherwise. Note that the end-of-file indicator is set + only if the read tried to go past the end of the input, but came up short. + Therefore, just like feof(), gzeof() may return false even if there is no + more data to read, in the event that the last read request was for the exact + number of bytes remaining in the input file. This will happen if the input + file size is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +Z_EXTERN int Z_EXPORT gzdirect(gzFile file); +/* + Return true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +Z_EXTERN int Z_EXPORT gzclose(gzFile file); +/* + Flush all pending output for file, if necessary, close file and + deallocate the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +Z_EXTERN int Z_EXPORT gzclose_r(gzFile file); +Z_EXTERN int Z_EXPORT gzclose_w(gzFile file); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +Z_EXTERN const char * Z_EXPORT gzerror(gzFile file, int *errnum); +/* + Return the error message for the last error which occurred on file. + errnum is set to zlib error number. If an error occurred in the file system + and not in the compression library, errnum is set to Z_ERRNO and the + application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +Z_EXTERN void Z_EXPORT gzclearerr(gzFile file); +/* + Clear the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +Z_EXTERN unsigned long Z_EXPORT adler32(unsigned long adler, const unsigned char *buf, unsigned int len); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. An Adler-32 value is in the range of a 32-bit + unsigned integer. If buf is Z_NULL, this function returns the required + initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uint32_t adler = adler32(0L, NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +Z_EXTERN unsigned long Z_EXPORT adler32_z(unsigned long adler, const unsigned char *buf, size_t len); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +Z_EXTERN unsigned long Z_EXPORT adler32_combine(unsigned long adler1, unsigned long adler2, z_off_t len2); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +Z_EXTERN unsigned long Z_EXPORT crc32(unsigned long crc, const unsigned char *buf, unsigned int len); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. + If buf is Z_NULL, this function returns the required initial value for the + crc. Pre- and post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the application. + + Usage example: + + uint32_t crc = crc32(0L, NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +Z_EXTERN unsigned long Z_EXPORT crc32_z(unsigned long crc, const unsigned char *buf, size_t len); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +Z_EXTERN unsigned long Z_EXPORT crc32_combine(unsigned long crc1, unsigned long crc2, z_off64_t len2); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + +/* +Z_EXTERN unsigned long Z_EXPORT crc32_combine_gen(z_off_t len2); + + Return the operator corresponding to length len2, to be used with + crc32_combine_op(). +*/ + +Z_EXTERN unsigned long Z_EXPORT crc32_combine_op(unsigned long crc1, unsigned long crc2, + const unsigned long op); +/* + Give the same result as crc32_combine(), using op in place of len2. op is + is generated from len2 by crc32_combine_gen(). This will be faster than + crc32_combine() if the generated op is used more than once. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +Z_EXTERN int Z_EXPORT deflateInit_(z_stream *strm, int level, const char *version, int stream_size); +Z_EXTERN int Z_EXPORT inflateInit_(z_stream *strm, const char *version, int stream_size); +Z_EXTERN int Z_EXPORT deflateInit2_(z_stream *strm, int level, int method, int windowBits, int memLevel, + int strategy, const char *version, int stream_size); +Z_EXTERN int Z_EXPORT inflateInit2_(z_stream *strm, int windowBits, const char *version, int stream_size); +Z_EXTERN int Z_EXPORT inflateBackInit_(z_stream *strm, int windowBits, unsigned char *window, + const char *version, int stream_size); +#define @ZLIB_SYMBOL_PREFIX@deflateInit(strm, level) deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +#define @ZLIB_SYMBOL_PREFIX@inflateInit(strm) inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +#define @ZLIB_SYMBOL_PREFIX@deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm), (level), (method), (windowBits), (memLevel), \ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +#define @ZLIB_SYMBOL_PREFIX@inflateInit2(strm, windowBits) inflateInit2_((strm), (windowBits), ZLIB_VERSION, (int)sizeof(z_stream)) +#define @ZLIB_SYMBOL_PREFIX@inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), ZLIB_VERSION, (int)sizeof(z_stream)) + + +#ifndef Z_SOLO +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +Z_EXTERN int Z_EXPORT gzgetc_(gzFile file); /* backward compatibility */ +# define @ZLIB_SYMBOL_PREFIX@gzgetc(g) ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (@ZLIB_SYMBOL_PREFIX@gzgetc)(g)) + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + Z_EXTERN gzFile Z_EXPORT gzopen64(const char *, const char *); + Z_EXTERN z_off64_t Z_EXPORT gzseek64(gzFile, z_off64_t, int); + Z_EXTERN z_off64_t Z_EXPORT gztell64(gzFile); + Z_EXTERN z_off64_t Z_EXPORT gzoffset64(gzFile); + Z_EXTERN unsigned long Z_EXPORT adler32_combine64(unsigned long, unsigned long, z_off64_t); + Z_EXTERN unsigned long Z_EXPORT crc32_combine64(unsigned long, unsigned long, z_off64_t); + Z_EXTERN unsigned long Z_EXPORT crc32_combine_gen64(z_off64_t); +#endif +#endif + +#if !defined(Z_SOLO) && !defined(Z_INTERNAL) && defined(Z_WANT64) +# define @ZLIB_SYMBOL_PREFIX@gzopen @ZLIB_SYMBOL_PREFIX@gzopen64 +# define @ZLIB_SYMBOL_PREFIX@gzseek @ZLIB_SYMBOL_PREFIX@gzseek64 +# define @ZLIB_SYMBOL_PREFIX@gztell @ZLIB_SYMBOL_PREFIX@gztell64 +# define @ZLIB_SYMBOL_PREFIX@gzoffset @ZLIB_SYMBOL_PREFIX@gzoffset64 +# define @ZLIB_SYMBOL_PREFIX@adler32_combine @ZLIB_SYMBOL_PREFIX@adler32_combine64 +# define @ZLIB_SYMBOL_PREFIX@crc32_combine @ZLIB_SYMBOL_PREFIX@crc32_combine64 +# define @ZLIB_SYMBOL_PREFIX@crc32_combine_gen @ZLIB_SYMBOL_PREFIX@crc32_combine_gen64 +# ifndef Z_LARGE64 + Z_EXTERN gzFile Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzopen64(const char *, const char *); + Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzseek64(gzFile, z_off_t, int); + Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gztell64(gzFile); + Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzoffset64(gzFile); + Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@adler32_combine64(unsigned long, unsigned long, z_off_t); + Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine64(unsigned long, unsigned long, z_off_t); + Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine_gen64(z_off64_t); +# endif +#else +# ifndef Z_SOLO + Z_EXTERN gzFile Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzopen(const char *, const char *); + Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzseek(gzFile, z_off_t, int); + Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gztell(gzFile); + Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzoffset(gzFile); +# endif + Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@adler32_combine(unsigned long, unsigned long, z_off_t); + Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine(unsigned long, unsigned long, z_off_t); + Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine_gen(z_off_t); +#endif + +/* undocumented functions */ +Z_EXTERN const char * Z_EXPORT zError (int); +Z_EXTERN int Z_EXPORT inflateSyncPoint (z_stream *); +Z_EXTERN const uint32_t * Z_EXPORT get_crc_table (void); +Z_EXTERN int Z_EXPORT inflateUndermine (z_stream *, int); +Z_EXTERN int Z_EXPORT inflateValidate (z_stream *, int); +Z_EXTERN unsigned long Z_EXPORT inflateCodesUsed (z_stream *); +Z_EXTERN int Z_EXPORT inflateResetKeep (z_stream *); +Z_EXTERN int Z_EXPORT deflateResetKeep (z_stream *); + +#ifndef Z_SOLO +#if defined(_WIN32) + Z_EXTERN gzFile Z_EXPORT gzopen_w(const wchar_t *path, const char *mode); +#endif +Z_EXTERN int Z_EXPORTVA gzvprintf(gzFile file, const char *format, va_list va); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H_ */ diff --git a/3rdparty/zlib-ng/zlib_name_mangling.h.empty b/3rdparty/zlib-ng/zlib_name_mangling.h.empty new file mode 100644 index 000000000000..b24cb834a6a6 --- /dev/null +++ b/3rdparty/zlib-ng/zlib_name_mangling.h.empty @@ -0,0 +1,8 @@ +/* zlib_name_mangling.h has been automatically generated from + * zlib_name_mangling.h.empty because ZLIB_SYMBOL_PREFIX was NOT set. + */ + +#ifndef ZLIB_NAME_MANGLING_H +#define ZLIB_NAME_MANGLING_H + +#endif /* ZLIB_NAME_MANGLING_H */ diff --git a/3rdparty/zlib-ng/zutil.c b/3rdparty/zlib-ng/zutil.c new file mode 100644 index 000000000000..270a28c74201 --- /dev/null +++ b/3rdparty/zlib-ng/zutil.c @@ -0,0 +1,159 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2017 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "zutil_p.h" +#include "zutil.h" + +z_const char * const PREFIX(z_errmsg)[10] = { + (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ + (z_const char *)"stream end", /* Z_STREAM_END 1 */ + (z_const char *)"", /* Z_OK 0 */ + (z_const char *)"file error", /* Z_ERRNO (-1) */ + (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ + (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ + (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ + (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ + (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ + (z_const char *)"" +}; + +const char PREFIX3(vstring)[] = + " zlib-ng 2.1.6"; + +#ifdef ZLIB_COMPAT +const char * Z_EXPORT zlibVersion(void) { + return ZLIB_VERSION; +} +#else +const char * Z_EXPORT zlibng_version(void) { + return ZLIBNG_VERSION; +} +#endif + +unsigned long Z_EXPORT PREFIX(zlibCompileFlags)(void) { + unsigned long flags; + + flags = 0; + switch ((int)(sizeof(unsigned int))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(unsigned long))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(void *))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef ZLIB_DEBUG + flags += 1 << 8; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif + /* Bit 13 reserved for DYNAMIC_CRC_TABLE */ +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif + return flags; +} + +#ifdef ZLIB_DEBUG +# include +# ifndef verbose +# define verbose 0 +# endif +int Z_INTERNAL z_verbose = verbose; + +void Z_INTERNAL z_error(const char *m) { + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * Z_EXPORT PREFIX(zError)(int err) { + return ERR_MSG(err); +} + +void Z_INTERNAL *PREFIX(zcalloc)(void *opaque, unsigned items, unsigned size) { + Z_UNUSED(opaque); + return zng_alloc((size_t)items * (size_t)size); +} + +void Z_INTERNAL PREFIX(zcfree)(void *opaque, void *ptr) { + Z_UNUSED(opaque); + zng_free(ptr); +} + +/* Since we support custom memory allocators, some which might not align memory as we expect, + * we have to ask for extra memory and return an aligned pointer. */ +void Z_INTERNAL *PREFIX3(alloc_aligned)(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align) { + uintptr_t return_ptr, original_ptr; + uint32_t alloc_size, align_diff; + void *ptr; + + /* If no custom calloc function used then call zlib-ng's aligned calloc */ + if (zalloc == PREFIX(zcalloc)) + return PREFIX(zcalloc)(opaque, items, size); + + /* Allocate enough memory for proper alignment and to store the original memory pointer */ + alloc_size = sizeof(void *) + (items * size) + align; + ptr = zalloc(opaque, 1, alloc_size); + if (!ptr) + return NULL; + + /* Calculate return pointer address with space enough to store original pointer */ + align_diff = align - ((uintptr_t)ptr % align); + return_ptr = (uintptr_t)ptr + align_diff; + if (align_diff < sizeof(void *)) + return_ptr += align; + + /* Store the original pointer for free() */ + original_ptr = return_ptr - sizeof(void *); + memcpy((void *)original_ptr, &ptr, sizeof(void *)); + + /* Return properly aligned pointer in allocation */ + return (void *)return_ptr; +} + +void Z_INTERNAL PREFIX3(free_aligned)(zng_cfree_func zfree, void *opaque, void *ptr) { + /* If no custom cfree function used then call zlib-ng's aligned cfree */ + if (zfree == PREFIX(zcfree)) { + PREFIX(zcfree)(opaque, ptr); + return; + } + if (!ptr) + return; + + /* Calculate offset to original memory allocation pointer */ + void *original_ptr = (void *)((uintptr_t)ptr - sizeof(void *)); + void *free_ptr = *(void **)original_ptr; + + /* Free original memory allocation */ + zfree(opaque, free_ptr); +} diff --git a/3rdparty/zlib-ng/zutil.h b/3rdparty/zlib-ng/zutil.h new file mode 100644 index 000000000000..663616b44d89 --- /dev/null +++ b/3rdparty/zlib-ng/zutil.h @@ -0,0 +1,148 @@ +#ifndef ZUTIL_H_ +#define ZUTIL_H_ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +typedef unsigned char uch; /* Included for compatibility with external code only */ +typedef uint16_t ush; /* Included for compatibility with external code only */ +typedef unsigned long ulg; + +extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) PREFIX(z_errmsg)[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm, err) return (strm->msg = ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#define MAX_BITS 15 +/* all codes must not exceed MAX_BITS bits */ +#define MAX_DIST_EXTRA_BITS 13 +/* maximum number of extra distance bits */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define STD_MIN_MATCH 3 +#define STD_MAX_MATCH 258 +/* The minimum and maximum match lengths mandated by the deflate standard */ + +#define WANT_MIN_MATCH 4 +/* The minimum wanted match length, affects deflate_quick, deflate_fast, deflate_medium and deflate_slow */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + +#define ADLER32_INITIAL_VALUE 1 /* initial adler-32 hash value */ +#define CRC32_INITIAL_VALUE 0 /* initial crc-32 hash value */ + +#define ZLIB_WRAPLEN 6 /* zlib format overhead */ +#define GZIP_WRAPLEN 18 /* gzip format overhead */ + +#define DEFLATE_HEADER_BITS 3 +#define DEFLATE_EOBS_BITS 15 +#define DEFLATE_PAD_BITS 6 +#define DEFLATE_BLOCK_OVERHEAD ((DEFLATE_HEADER_BITS + DEFLATE_EOBS_BITS + DEFLATE_PAD_BITS) >> 3) +/* deflate block overhead: 3 bits for block start + 15 bits for block end + padding to nearest byte */ + +#define DEFLATE_QUICK_LIT_MAX_BITS 9 +#define DEFLATE_QUICK_OVERHEAD(x) ((x * (DEFLATE_QUICK_LIT_MAX_BITS - 8) + 7) >> 3) +/* deflate_quick worst-case overhead: 9 bits per literal, round up to next byte (+7) */ + + + /* target dependencies */ + +#ifdef AMIGA +# define OS_CODE 1 +#endif + +#ifdef __370__ +# if __TARGET_LIB__ < 0x20000000 +# define OS_CODE 4 +# elif __TARGET_LIB__ < 0x40000000 +# define OS_CODE 11 +# else +# define OS_CODE 8 +# endif +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 5 +#endif + +#ifdef OS2 +# define OS_CODE 6 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 7 +#endif + +#ifdef __acorn +# define OS_CODE 13 +#endif + +#if defined(_WIN32) && !defined(__CYGWIN__) +# define OS_CODE 10 +#endif + +#ifdef __APPLE__ +# define OS_CODE 19 +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 3 /* assume Unix */ +#endif + + /* macros */ + +#define CHECK_VER_STSIZE(_ver,_stsize) ((_ver) == NULL || (_ver)[0] != PREFIX2(VERSION)[0] || (_stsize) != (int32_t)sizeof(PREFIX3(stream))) + + /* memory allocation functions */ + +void Z_INTERNAL *PREFIX(zcalloc)(void *opaque, unsigned items, unsigned size); +void Z_INTERNAL PREFIX(zcfree)(void *opaque, void *ptr); + +typedef void *zng_calloc_func(void *opaque, unsigned items, unsigned size); +typedef void zng_cfree_func(void *opaque, void *ptr); + +void Z_INTERNAL *PREFIX3(alloc_aligned)(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align); +void Z_INTERNAL PREFIX3(free_aligned)(zng_cfree_func zfree, void *opaque, void *ptr); + +#define ZALLOC(strm, items, size) PREFIX3(alloc_aligned)((strm)->zalloc, (strm)->opaque, (items), (size), 64) +#define ZFREE(strm, addr) PREFIX3(free_aligned)((strm)->zfree, (strm)->opaque, (void *)(addr)) + +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H_ */ diff --git a/3rdparty/zlib-ng/zutil_p.h b/3rdparty/zlib-ng/zutil_p.h new file mode 100644 index 000000000000..caec91d50d36 --- /dev/null +++ b/3rdparty/zlib-ng/zutil_p.h @@ -0,0 +1,71 @@ +/* zutil_p.h -- Private inline functions used internally in zlib-ng + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ZUTIL_P_H +#define ZUTIL_P_H + +#if defined(__APPLE__) || defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_ALIGNED_ALLOC) +# include +#elif defined(__FreeBSD__) +# include +# include +#else +# include +#endif + +/* Function to allocate 16 or 64-byte aligned memory */ +static inline void *zng_alloc(size_t size) { +#ifdef HAVE_POSIX_MEMALIGN + void *ptr; + return posix_memalign(&ptr, 64, size) ? NULL : ptr; +#elif defined(_WIN32) + return (void *)_aligned_malloc(size, 64); +#elif defined(__APPLE__) + return (void *)malloc(size); /* MacOS always aligns to 16 bytes */ +#elif defined(HAVE_ALIGNED_ALLOC) + return (void *)aligned_alloc(64, size); +#else + return (void *)memalign(64, size); +#endif +} + +/* Function that can free aligned memory */ +static inline void zng_free(void *ptr) { +#if defined(_WIN32) + _aligned_free(ptr); +#else + free(ptr); +#endif +} + +/* Use memcpy instead of memcmp to avoid older compilers not converting memcmp calls to + unaligned comparisons when unaligned access is supported. */ +static inline int32_t zng_memcmp_2(const void *src0, const void *src1) { + uint16_t src0_cmp, src1_cmp; + + memcpy(&src0_cmp, src0, sizeof(src0_cmp)); + memcpy(&src1_cmp, src1, sizeof(src1_cmp)); + + return src0_cmp != src1_cmp; +} + +static inline int32_t zng_memcmp_4(const void *src0, const void *src1) { + uint32_t src0_cmp, src1_cmp; + + memcpy(&src0_cmp, src0, sizeof(src0_cmp)); + memcpy(&src1_cmp, src1, sizeof(src1_cmp)); + + return src0_cmp != src1_cmp; +} + +static inline int32_t zng_memcmp_8(const void *src0, const void *src1) { + uint64_t src0_cmp, src1_cmp; + + memcpy(&src0_cmp, src0, sizeof(src0_cmp)); + memcpy(&src1_cmp, src1, sizeof(src1_cmp)); + + return src0_cmp != src1_cmp; +} + +#endif diff --git a/CMakeLists.txt b/CMakeLists.txt index 5da9c2a695ee..dc0d1ce9ee21 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -484,6 +484,9 @@ OCV_OPTION(WITH_CANN "Include CANN support" OFF OCV_OPTION(WITH_FLATBUFFERS "Include Flatbuffers support (required by DNN/TFLite importer)" ON VISIBLE_IF TRUE VERIFY HAVE_FLATBUFFERS) +OCV_OPTION(WITH_ZLIB_NG "Use zlib-ng instead of zlib" OFF + VISIBLE_IF TRUE + VERIFY HAVE_ZLIB_NG) # OpenCV build components # =================================================== @@ -1425,7 +1428,11 @@ endif() # ========================== MEDIA IO ========================== status("") status(" Media I/O: ") -status(" ZLib:" ZLIB_FOUND THEN "${ZLIB_LIBRARIES} (ver ${ZLIB_VERSION_STRING})" ELSE "build (ver ${ZLIB_VERSION_STRING})") +if(WITH_ZLIB_NG OR HAVE_ZLIB_NG) + status(" ZLib-Ng:" "build (zlib ver ${ZLIB_VERSION_STRING}, zlib-ng ver ${ZLIBNG_VERSION_STRING})") +else() + status(" ZLib:" ZLIB_FOUND THEN "${ZLIB_LIBRARIES} (ver ${ZLIB_VERSION_STRING})" ELSE "build (ver ${ZLIB_VERSION_STRING})") +endif() if(WITH_JPEG OR HAVE_JPEG) if(NOT HAVE_JPEG) diff --git a/cmake/OpenCVFindLibsGrfmt.cmake b/cmake/OpenCVFindLibsGrfmt.cmake index a76a9ed44a71..c1136067124e 100644 --- a/cmake/OpenCVFindLibsGrfmt.cmake +++ b/cmake/OpenCVFindLibsGrfmt.cmake @@ -3,10 +3,23 @@ # ---------------------------------------------------------------------------- # --- zlib (required) --- -if(BUILD_ZLIB) - ocv_clear_vars(ZLIB_FOUND) +if(WITH_ZLIB_NG) + ocv_clear_vars(ZLIB_LIBRARY ZLIB_LIBRARIES ZLIB_INCLUDE_DIR) + set(ZLIB_LIBRARY zlib CACHE INTERNAL "") + add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/zlib-ng") + set(ZLIB_INCLUDE_DIR "${${ZLIB_LIBRARY}_BINARY_DIR}" CACHE INTERNAL "") + set(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) + set(ZLIB_LIBRARIES ${ZLIB_LIBRARY}) + + ocv_parse_header_version(ZLIB "${${ZLIB_LIBRARY}_SOURCE_DIR}/zlib.h.in" ZLIB_VERSION) + ocv_parse_header_version(ZLIBNG "${${ZLIB_LIBRARY}_SOURCE_DIR}/zlib.h.in" ZLIBNG_VERSION) + + set(HAVE_ZLIB_NG YES) else() - ocv_clear_internal_cache_vars(ZLIB_LIBRARY ZLIB_INCLUDE_DIR) + if(BUILD_ZLIB) + ocv_clear_vars(ZLIB_FOUND) + else() + ocv_clear_internal_cache_vars(ZLIB_LIBRARY ZLIB_INCLUDE_DIR) if(ANDROID) set(_zlib_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) set(CMAKE_FIND_LIBRARY_SUFFIXES .so) @@ -23,18 +36,19 @@ else() set(ZLIB_LIBRARY_RELEASE z) endif() endif() -endif() + endif() -if(NOT ZLIB_FOUND) - ocv_clear_vars(ZLIB_LIBRARY ZLIB_LIBRARIES ZLIB_INCLUDE_DIR) + if(NOT ZLIB_FOUND) + ocv_clear_vars(ZLIB_LIBRARY ZLIB_LIBRARIES ZLIB_INCLUDE_DIR) - set(ZLIB_LIBRARY zlib CACHE INTERNAL "") - add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/zlib") - set(ZLIB_INCLUDE_DIR "${${ZLIB_LIBRARY}_SOURCE_DIR}" "${${ZLIB_LIBRARY}_BINARY_DIR}" CACHE INTERNAL "") - set(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) - set(ZLIB_LIBRARIES ${ZLIB_LIBRARY}) + set(ZLIB_LIBRARY zlib CACHE INTERNAL "") + add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/zlib") + set(ZLIB_INCLUDE_DIR "${${ZLIB_LIBRARY}_SOURCE_DIR}" "${${ZLIB_LIBRARY}_BINARY_DIR}" CACHE INTERNAL "") + set(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) + set(ZLIB_LIBRARIES ${ZLIB_LIBRARY}) - ocv_parse_header_version(ZLIB "${${ZLIB_LIBRARY}_SOURCE_DIR}/zlib.h" ZLIB_VERSION) + ocv_parse_header_version(ZLIB "${${ZLIB_LIBRARY}_SOURCE_DIR}/zlib.h" ZLIB_VERSION) + endif() endif() # --- libavif (optional) --- From 5e09fca0f87efd993e17b94bba28e208719b535e Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Wed, 3 Apr 2024 09:23:23 +0300 Subject: [PATCH 002/119] Skip InferList.TestStreamingInfer --- modules/gapi/test/infer/gapi_infer_ie_test.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/gapi/test/infer/gapi_infer_ie_test.cpp b/modules/gapi/test/infer/gapi_infer_ie_test.cpp index 058896bc8346..6cfdbee39427 100644 --- a/modules/gapi/test/infer/gapi_infer_ie_test.cpp +++ b/modules/gapi/test/infer/gapi_infer_ie_test.cpp @@ -1730,6 +1730,9 @@ TEST(InferROI, TestStreamingInfer) TEST(InferList, TestStreamingInfer) { + if (cvtest::skipUnstableTests) + throw SkipTestException("Skip InferList.TestStreamingInfer as it hangs sporadically"); + initDLDTDataPath(); std::string filepath = findDataFile("cv/video/768x576.avi"); From fb194a4582d3df6fa01bd7c07025bcec6e0636eb Mon Sep 17 00:00:00 2001 From: Kumataro Date: Fri, 19 Apr 2024 15:06:28 +0900 Subject: [PATCH 003/119] imgcodecs: jpeg: refactoring for JpegEncoder --- modules/imgcodecs/src/grfmt_jpeg.cpp | 84 ++++++++++++++++++---------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/modules/imgcodecs/src/grfmt_jpeg.cpp b/modules/imgcodecs/src/grfmt_jpeg.cpp index 87187f131b54..4a2aee12b01f 100644 --- a/modules/imgcodecs/src/grfmt_jpeg.cpp +++ b/modules/imgcodecs/src/grfmt_jpeg.cpp @@ -619,11 +619,6 @@ bool JpegEncoder::write( const Mat& img, const std::vector& params ) std::vector out_buf(1 << 12); -#ifndef JCS_EXTENSIONS - AutoBuffer _buffer; - uchar* buffer; -#endif - struct jpeg_compress_struct cinfo; JpegErrorMgr jerr; JpegDestination dest; @@ -658,14 +653,40 @@ bool JpegEncoder::write( const Mat& img, const std::vector& params ) int _channels = img.channels(); int channels = _channels > 1 ? 3 : 1; + bool doDirectWrite = false; + switch( _channels ) + { + case 1: + cinfo.input_components = 1; + cinfo.in_color_space = JCS_GRAYSCALE; + doDirectWrite = true; // GRAY -> GRAY + break; + case 3: +#ifdef JCS_EXTENSIONS + cinfo.input_components = 3; + cinfo.in_color_space = JCS_EXT_BGR; + doDirectWrite = true; // BGR -> BGR +#else + cinfo.input_components = 3; + cinfo.in_color_space = JCS_RGB; + doDirectWrite = false; // BGR -> RGB +#endif + break; + case 4: #ifdef JCS_EXTENSIONS - cinfo.input_components = _channels; - cinfo.in_color_space = _channels == 3 ? JCS_EXT_BGR - : _channels == 4 ? JCS_EXT_BGRX : JCS_GRAYSCALE; + cinfo.input_components = 4; + cinfo.in_color_space = JCS_EXT_BGRX; + doDirectWrite = true; // BGRX -> BGRX #else - cinfo.input_components = channels; - cinfo.in_color_space = channels > 1 ? JCS_RGB : JCS_GRAYSCALE; + cinfo.input_components = 3; + cinfo.in_color_space = JCS_RGB; + doDirectWrite = false; // BGRA -> RGB #endif + break; + default: + CV_Error(cv::Error::StsError, cv::format("Unsupported number of _channels: %06d", _channels) ); + break; + } int quality = 95; int progressive = 0; @@ -781,30 +802,35 @@ bool JpegEncoder::write( const Mat& img, const std::vector& params ) jpeg_start_compress( &cinfo, TRUE ); -#ifndef JCS_EXTENSIONS - if( channels > 1 ) - _buffer.allocate(width*channels); - buffer = _buffer.data(); -#endif - - for( int y = 0; y < height; y++ ) + if( doDirectWrite ) { - uchar *data = img.data + img.step*y, *ptr = data; - -#ifndef JCS_EXTENSIONS - if( _channels == 3 ) + for( int y = 0; y < height; y++ ) { - icvCvt_BGR2RGB_8u_C3R( data, 0, buffer, 0, Size(width,1) ); - ptr = buffer; + uchar *data = const_cast(img.ptr(y)); + jpeg_write_scanlines( &cinfo, &data, 1 ); } - else if( _channels == 4 ) + } + else + { + CV_Check(_channels, (_channels == 3) || (_channels == 4), "Unsupported number of channels(indirect write)"); + + AutoBuffer _buffer; + _buffer.allocate(width*channels); + uchar *buffer = _buffer.data(); + + for( int y = 0; y < height; y++ ) { - icvCvt_BGRA2BGR_8u_C4C3R( data, 0, buffer, 0, Size(width,1), 2 ); - ptr = buffer; + uchar *data = const_cast(img.ptr(y)); + if( _channels == 3 ) + { + icvCvt_BGR2RGB_8u_C3R( data, 0, buffer, 0, Size(width,1) ); + } + else // if( _channels == 4 ) + { + icvCvt_BGRA2BGR_8u_C4C3R( data, 0, buffer, 0, Size(width,1), 2 ); + } + jpeg_write_scanlines( &cinfo, &buffer, 1 ); } -#endif - - jpeg_write_scanlines( &cinfo, &ptr, 1 ); } jpeg_finish_compress( &cinfo ); From 26798e1f7c90b556eee5b7efbe695c7e93439b02 Mon Sep 17 00:00:00 2001 From: Kumataro Date: Fri, 19 Apr 2024 19:20:05 +0900 Subject: [PATCH 004/119] imgcodecs: tiff: test: ASSERT_NO_THROW() for imwrite/imread --- modules/imgcodecs/test/test_tiff.cpp | 78 +++++++++++++++++++++------- 1 file changed, 59 insertions(+), 19 deletions(-) diff --git a/modules/imgcodecs/test/test_tiff.cpp b/modules/imgcodecs/test/test_tiff.cpp index 8ff7db52ebe7..ee40c54b59dd 100644 --- a/modules/imgcodecs/test/test_tiff.cpp +++ b/modules/imgcodecs/test/test_tiff.cpp @@ -685,15 +685,22 @@ TEST(Imgcodecs_Tiff, readWrite_unsigned) const string root = cvtest::TS::ptr()->get_data_path(); const string filenameInput = root + "readwrite/gray_8u.tif"; const string filenameOutput = cv::tempfile(".tiff"); - const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED); + + Mat img; + ASSERT_NO_THROW(img = cv::imread(filenameInput, IMREAD_UNCHANGED)); ASSERT_FALSE(img.empty()); ASSERT_EQ(CV_8UC1, img.type()); Mat matS8; img.convertTo(matS8, CV_8SC1); - ASSERT_TRUE(cv::imwrite(filenameOutput, matS8)); - const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED); + bool ret_imwrite = false; + ASSERT_NO_THROW(ret_imwrite = cv::imwrite(filenameOutput, matS8)); + ASSERT_TRUE(ret_imwrite); + + Mat img2; + ASSERT_NO_THROW(img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED)); + ASSERT_FALSE(img2.empty()); ASSERT_EQ(img2.type(), matS8.type()); ASSERT_EQ(img2.size(), matS8.size()); EXPECT_LE(cvtest::norm(matS8, img2, NORM_INF | NORM_RELATIVE), 1e-3); @@ -705,12 +712,19 @@ TEST(Imgcodecs_Tiff, readWrite_32FC1) const string root = cvtest::TS::ptr()->get_data_path(); const string filenameInput = root + "readwrite/test32FC1.tiff"; const string filenameOutput = cv::tempfile(".tiff"); - const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED); + + Mat img; + ASSERT_NO_THROW(img = cv::imread(filenameInput, IMREAD_UNCHANGED)); ASSERT_FALSE(img.empty()); ASSERT_EQ(CV_32FC1,img.type()); - ASSERT_TRUE(cv::imwrite(filenameOutput, img)); - const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED); + bool ret_imwrite = false; + ASSERT_NO_THROW(ret_imwrite = cv::imwrite(filenameOutput, img)); + ASSERT_TRUE(ret_imwrite); + + Mat img2; + ASSERT_NO_THROW(img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED)); + ASSERT_FALSE(img2.empty()); ASSERT_EQ(img2.type(), img.type()); ASSERT_EQ(img2.size(), img.size()); EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3); @@ -722,12 +736,19 @@ TEST(Imgcodecs_Tiff, readWrite_64FC1) const string root = cvtest::TS::ptr()->get_data_path(); const string filenameInput = root + "readwrite/test64FC1.tiff"; const string filenameOutput = cv::tempfile(".tiff"); - const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED); + + Mat img; + ASSERT_NO_THROW(img = cv::imread(filenameInput, IMREAD_UNCHANGED)); ASSERT_FALSE(img.empty()); ASSERT_EQ(CV_64FC1, img.type()); - ASSERT_TRUE(cv::imwrite(filenameOutput, img)); - const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED); + bool ret_imwrite = false; + ASSERT_NO_THROW(ret_imwrite = cv::imwrite(filenameOutput, img)); + ASSERT_TRUE(ret_imwrite); + + Mat img2; + ASSERT_NO_THROW(img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED)); + ASSERT_FALSE(img2.empty()); ASSERT_EQ(img2.type(), img.type()); ASSERT_EQ(img2.size(), img.size()); EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3); @@ -739,12 +760,19 @@ TEST(Imgcodecs_Tiff, readWrite_32FC3_SGILOG) const string root = cvtest::TS::ptr()->get_data_path(); const string filenameInput = root + "readwrite/test32FC3_sgilog.tiff"; const string filenameOutput = cv::tempfile(".tiff"); - const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED); + + Mat img; + ASSERT_NO_THROW(img = cv::imread(filenameInput, IMREAD_UNCHANGED)); ASSERT_FALSE(img.empty()); ASSERT_EQ(CV_32FC3, img.type()); - ASSERT_TRUE(cv::imwrite(filenameOutput, img)); - const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED); + bool ret_imwrite = false; + ASSERT_NO_THROW(ret_imwrite = cv::imwrite(filenameOutput, img)); + ASSERT_TRUE(ret_imwrite); + + Mat img2; + ASSERT_NO_THROW(img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED)); + ASSERT_FALSE(img2.empty()); ASSERT_EQ(img2.type(), img.type()); ASSERT_EQ(img2.size(), img.size()); EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 0.01); @@ -756,7 +784,9 @@ TEST(Imgcodecs_Tiff, readWrite_32FC3_RAW) const string root = cvtest::TS::ptr()->get_data_path(); const string filenameInput = root + "readwrite/test32FC3_raw.tiff"; const string filenameOutput = cv::tempfile(".tiff"); - const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED); + + Mat img; + ASSERT_NO_THROW(img = cv::imread(filenameInput, IMREAD_UNCHANGED)); ASSERT_FALSE(img.empty()); ASSERT_EQ(CV_32FC3, img.type()); @@ -764,8 +794,13 @@ TEST(Imgcodecs_Tiff, readWrite_32FC3_RAW) params.push_back(IMWRITE_TIFF_COMPRESSION); params.push_back(IMWRITE_TIFF_COMPRESSION_NONE); - ASSERT_TRUE(cv::imwrite(filenameOutput, img, params)); - const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED); + bool ret_imwrite = false; + ASSERT_NO_THROW(ret_imwrite = cv::imwrite(filenameOutput, img, params)); + ASSERT_TRUE(ret_imwrite); + + Mat img2; + ASSERT_NO_THROW(img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED)); + ASSERT_FALSE(img2.empty()); ASSERT_EQ(img2.type(), img.type()); ASSERT_EQ(img2.size(), img.size()); EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3); @@ -777,7 +812,8 @@ TEST(Imgcodecs_Tiff, read_palette_color_image) const string root = cvtest::TS::ptr()->get_data_path(); const string filenameInput = root + "readwrite/test_palette_color_image.tif"; - const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED); + Mat img; + ASSERT_NO_THROW(img = cv::imread(filenameInput, IMREAD_UNCHANGED)); ASSERT_FALSE(img.empty()); ASSERT_EQ(CV_8UC3, img.type()); } @@ -787,7 +823,8 @@ TEST(Imgcodecs_Tiff, read_4_bit_palette_color_image) const string root = cvtest::TS::ptr()->get_data_path(); const string filenameInput = root + "readwrite/4-bit_palette_color.tif"; - const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED); + Mat img; + ASSERT_NO_THROW(img = cv::imread(filenameInput, IMREAD_UNCHANGED)); ASSERT_FALSE(img.empty()); ASSERT_EQ(CV_8UC3, img.type()); } @@ -825,9 +862,12 @@ TEST(Imgcodecs_Tiff, readWrite_predictor) params.push_back(IMWRITE_TIFF_PREDICTOR); params.push_back(IMWRITE_TIFF_PREDICTOR_HORIZONTAL); - EXPECT_NO_THROW(cv::imwrite(out, mat, params)); + bool ret_imwrite = false; + ASSERT_NO_THROW(ret_imwrite = cv::imwrite(out, mat, params)); + ASSERT_TRUE(ret_imwrite); - const Mat img = cv::imread(out, IMREAD_UNCHANGED); + Mat img; + ASSERT_NO_THROW(img = cv::imread(out, IMREAD_UNCHANGED)); ASSERT_FALSE(img.empty()); ASSERT_EQ(0, cv::norm(mat, img, cv::NORM_INF)); From 096ccd410b57089c4545de6ad759e7622014b5a1 Mon Sep 17 00:00:00 2001 From: Wanli Date: Mon, 22 Apr 2024 15:59:54 +0800 Subject: [PATCH 005/119] change js_face_recognition sample with yunet --- samples/dnn/js_face_recognition.html | 78 ++++++++++++++++++---------- 1 file changed, 51 insertions(+), 27 deletions(-) diff --git a/samples/dnn/js_face_recognition.html b/samples/dnn/js_face_recognition.html index 5893a5cf1355..3b4ed390d7b4 100644 --- a/samples/dnn/js_face_recognition.html +++ b/samples/dnn/js_face_recognition.html @@ -12,27 +12,40 @@ //! [Run face detection model] function detectFaces(img) { - var blob = cv.blobFromImage(img, 1, {width: 192, height: 144}, [104, 117, 123, 0], false, false); - netDet.setInput(blob); - var out = netDet.forward(); - + netDet.setInputSize(new cv.Size(img.cols, img.rows)); + var out = new cv.Mat(); + netDet.detect(img, out); var faces = []; - for (var i = 0, n = out.data32F.length; i < n; i += 7) { - var confidence = out.data32F[i + 2]; - var left = out.data32F[i + 3] * img.cols; - var top = out.data32F[i + 4] * img.rows; - var right = out.data32F[i + 5] * img.cols; - var bottom = out.data32F[i + 6] * img.rows; + for (var i = 0, n = out.data32F.length; i < n; i += 15) { + var left = out.data32F[i]; + var top = out.data32F[i + 1]; + var right = (out.data32F[i] + out.data32F[i + 2]); + var bottom = (out.data32F[i + 1] + out.data32F[i + 3]); left = Math.min(Math.max(0, left), img.cols - 1); + top = Math.min(Math.max(0, top), img.rows - 1); right = Math.min(Math.max(0, right), img.cols - 1); bottom = Math.min(Math.max(0, bottom), img.rows - 1); - top = Math.min(Math.max(0, top), img.rows - 1); - if (confidence > 0.5 && left < right && top < bottom) { - faces.push({x: left, y: top, width: right - left, height: bottom - top}) + if (left < right && top < bottom) { + faces.push({ + x: left, + y: top, + width: right - left, + height: bottom - top, + x1: out.data32F[i + 4] < 0 || out.data32F[i + 4] > img.cols - 1 ? -1 : out.data32F[i + 4], + y1: out.data32F[i + 5] < 0 || out.data32F[i + 5] > img.rows - 1 ? -1 : out.data32F[i + 5], + x2: out.data32F[i + 6] < 0 || out.data32F[i + 6] > img.cols - 1 ? -1 : out.data32F[i + 6], + y2: out.data32F[i + 7] < 0 || out.data32F[i + 7] > img.rows - 1 ? -1 : out.data32F[i + 7], + x3: out.data32F[i + 8] < 0 || out.data32F[i + 8] > img.cols - 1 ? -1 : out.data32F[i + 8], + y3: out.data32F[i + 9] < 0 || out.data32F[i + 9] > img.rows - 1 ? -1 : out.data32F[i + 9], + x4: out.data32F[i + 10] < 0 || out.data32F[i + 10] > img.cols - 1 ? -1 : out.data32F[i + 10], + y4: out.data32F[i + 11] < 0 || out.data32F[i + 11] > img.rows - 1 ? -1 : out.data32F[i + 11], + x5: out.data32F[i + 12] < 0 || out.data32F[i + 12] > img.cols - 1 ? -1 : out.data32F[i + 12], + y5: out.data32F[i + 13] < 0 || out.data32F[i + 13] > img.rows - 1 ? -1 : out.data32F[i + 13], + confidence: out.data32F[i + 14] + }) } } - blob.delete(); out.delete(); return faces; }; @@ -53,7 +66,7 @@ var vec = face2vec(face); var bestMatchName = 'unknown'; - var bestMatchScore = 0.5; // Actually, the minimum is -1 but we use it as a threshold. + var bestMatchScore = 30; // Threshold for face recognition. for (name in persons) { var personVec = persons[name]; var score = vec.dot(personVec); @@ -69,24 +82,25 @@ function loadModels(callback) { var utils = new Utils(''); - var proto = 'https://raw.githubusercontent.com/opencv/opencv/4.x/samples/dnn/face_detector/deploy_lowres.prototxt'; - var weights = 'https://raw.githubusercontent.com/opencv/opencv_3rdparty/dnn_samples_face_detector_20180205_fp16/res10_300x300_ssd_iter_140000_fp16.caffemodel'; + var detectModel = 'https://media.githubusercontent.com/media/opencv/opencv_zoo/main/models/face_detection_yunet/face_detection_yunet_2023mar.onnx'; var recognModel = 'https://media.githubusercontent.com/media/opencv/opencv_zoo/main/models/face_recognition_sface/face_recognition_sface_2021dec.onnx'; - utils.createFileFromUrl('face_detector.prototxt', proto, () => { - document.getElementById('status').innerHTML = 'Downloading face_detector.caffemodel'; - utils.createFileFromUrl('face_detector.caffemodel', weights, () => { - document.getElementById('status').innerHTML = 'Downloading OpenFace model'; - utils.createFileFromUrl('face_recognition_sface_2021dec.onnx', recognModel, () => { - document.getElementById('status').innerHTML = ''; - netDet = cv.readNetFromCaffe('face_detector.prototxt', 'face_detector.caffemodel'); - netRecogn = cv.readNet('face_recognition_sface_2021dec.onnx'); - callback(); - }); + document.getElementById('status').innerHTML = 'Downloading YuNet model'; + utils.createFileFromUrl('face_detection_yunet_2023mar.onnx', detectModel, () => { + document.getElementById('status').innerHTML = 'Downloading OpenFace model'; + utils.createFileFromUrl('face_recognition_sface_2021dec.onnx', recognModel, () => { + document.getElementById('status').innerHTML = ''; + netDet = new cv.FaceDetectorYN("face_detection_yunet_2023mar.onnx", "", new cv.Size(320, 320), 0.9, 0.3, 5000); + netRecogn = cv.readNet('face_recognition_sface_2021dec.onnx'); + callback(); }); }); }; function main() { + if(!cv.FaceDetectorYN){ + alert(`Error: This sample require OpenCV.js built with FaceDetectorYN. Please rebuild it with FaceDetectorYN or use the latest version of OpenCV.js.`); + return; + } // Create a camera object. var output = document.getElementById('output'); var camera = document.createElement("video"); @@ -146,6 +160,16 @@ var faces = detectFaces(frameBGR); faces.forEach(function(rect) { cv.rectangle(frame, {x: rect.x, y: rect.y}, {x: rect.x + rect.width, y: rect.y + rect.height}, [0, 255, 0, 255]); + if(rect.x1>0 && rect.y1>0) + cv.circle(frame, {x: rect.x1, y: rect.y1}, 2, [255, 0, 0, 255], 2) + if(rect.x2>0 && rect.y2>0) + cv.circle(frame, {x: rect.x2, y: rect.y2}, 2, [0, 0, 255, 255], 2) + if(rect.x3>0 && rect.y3>0) + cv.circle(frame, {x: rect.x3, y: rect.y3}, 2, [0, 255, 0, 255], 2) + if(rect.x4>0 && rect.y4>0) + cv.circle(frame, {x: rect.x4, y: rect.y4}, 2, [255, 0, 255, 255], 2) + if(rect.x5>0 && rect.y5>0) + cv.circle(frame, {x: rect.x5, y: rect.y5}, 2, [0, 255, 255, 255], 2) var face = frameBGR.roi(rect); var name = recognize(face); From ae85e516c03d78a1befa5001c6918dfb42529511 Mon Sep 17 00:00:00 2001 From: LuukvandenBent <94459309+LuukvandenBent@users.noreply.github.com> Date: Mon, 22 Apr 2024 10:12:29 +0200 Subject: [PATCH 006/119] Merge pull request #25423 from LuukvandenBent:CalibrateHandEyeDatatypeFix Calibrate hand eye datatype fix #25423 Fix for issue https://github.com/opencv/opencv/issues/25421. See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/calib3d/src/calibration_handeye.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/modules/calib3d/src/calibration_handeye.cpp b/modules/calib3d/src/calibration_handeye.cpp index 25fa5af053fa..ab20597c8b84 100644 --- a/modules/calib3d/src/calibration_handeye.cpp +++ b/modules/calib3d/src/calibration_handeye.cpp @@ -722,7 +722,11 @@ void calibrateHandEye(InputArrayOfArrays R_gripper2base, InputArrayOfArrays t_gr if(R_gripper2base_[i].size() == Size(3, 3)) R_gripper2base_[i].convertTo(R, CV_64F); else - Rodrigues(R_gripper2base_[i], R); + { + cv::Mat R_temp; + Rodrigues(R_gripper2base_[i], R_temp); + R_temp.convertTo(R, CV_64F); + } Mat t = m(Rect(3, 0, 1, 3)); t_gripper2base_[i].convertTo(t, CV_64F); @@ -740,7 +744,11 @@ void calibrateHandEye(InputArrayOfArrays R_gripper2base, InputArrayOfArrays t_gr if(R_target2cam_[i].size() == Size(3, 3)) R_target2cam_[i].convertTo(R, CV_64F); else - Rodrigues(R_target2cam_[i], R); + { + cv::Mat R_temp; + Rodrigues(R_target2cam_[i], R_temp); + R_temp.convertTo(R, CV_64F); + } Mat t = m(Rect(3, 0, 1, 3)); t_target2cam_[i].convertTo(t, CV_64F); @@ -920,7 +928,9 @@ void calibrateRobotWorldHandEye(InputArrayOfArrays R_world2cam, InputArrayOfArra } else { - Rodrigues(rot, R); + cv::Mat R_temp; + Rodrigues(rot, R_temp); + R_temp.convertTo(R, CV_64F); R_base2gripper_.push_back(R); } Mat tvec = t_base2gripper_tmp[i]; @@ -938,7 +948,9 @@ void calibrateRobotWorldHandEye(InputArrayOfArrays R_world2cam, InputArrayOfArra } else { - Rodrigues(rot, R); + cv::Mat R_temp; + Rodrigues(rot, R_temp); + R_temp.convertTo(R, CV_64F); R_world2cam_.push_back(R); } Mat tvec = t_world2cam_tmp[i]; From 7e56908306934d6e1c337e27a8473d6ea86a8623 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 24 Apr 2024 14:28:31 +0300 Subject: [PATCH 007/119] Merge pull request #25469 from mshabunin:cpp-emd imgproc: refactor EMD to reduce C-API usage #25469 - added more tests for EMD - refactored to remove CvArr - used BufferArea for memory allocations - renamed functions and variables and formatted the code - kept legacy functions intact in separate header --- .../include/opencv2/imgproc/detail/legacy.hpp | 8 + modules/imgproc/src/emd.cpp | 5 +- modules/imgproc/src/emd_new.cpp | 1010 +++++++++++++++++ modules/imgproc/src/precomp.hpp | 2 + modules/imgproc/test/test_emd.cpp | 307 +++-- modules/imgproc/test/test_precomp.hpp | 3 + 6 files changed, 1258 insertions(+), 77 deletions(-) create mode 100644 modules/imgproc/src/emd_new.cpp diff --git a/modules/imgproc/include/opencv2/imgproc/detail/legacy.hpp b/modules/imgproc/include/opencv2/imgproc/detail/legacy.hpp index f9abd8d23ec3..029d9c90e83a 100644 --- a/modules/imgproc/include/opencv2/imgproc/detail/legacy.hpp +++ b/modules/imgproc/include/opencv2/imgproc/detail/legacy.hpp @@ -23,6 +23,14 @@ CV_EXPORTS void findContours_legacy(InputArray image, int method, Point offset = Point()); +CV_EXPORTS float EMD_legacy( InputArray _signature1, InputArray _signature2, + int distType, InputArray _cost, + float* lowerBound, OutputArray _flow ); + +CV_EXPORTS float wrapperEMD_legacy(InputArray _signature1, InputArray _signature2, + int distType, InputArray _cost, + Ptr lowerBound, OutputArray _flow); + #endif } // namespace cv diff --git a/modules/imgproc/src/emd.cpp b/modules/imgproc/src/emd.cpp index 8b7f325e74f7..c4cdd51a41a7 100644 --- a/modules/imgproc/src/emd.cpp +++ b/modules/imgproc/src/emd.cpp @@ -57,6 +57,7 @@ ========================================================================== */ #include "precomp.hpp" +#include "opencv2/imgproc/detail/legacy.hpp" #define MAX_ITERATIONS 500 #define CV_EMD_INF ((float)1e20) @@ -1147,7 +1148,7 @@ icvDistC( const float *x, const float *y, void *user_param ) } -float cv::EMD( InputArray _signature1, InputArray _signature2, +float cv::EMD_legacy( InputArray _signature1, InputArray _signature2, int distType, InputArray _cost, float* lowerBound, OutputArray _flow ) { @@ -1171,7 +1172,7 @@ float cv::EMD( InputArray _signature1, InputArray _signature2, _flow.needed() ? &_cflow : 0, lowerBound, 0 ); } -float cv::wrapperEMD(InputArray _signature1, InputArray _signature2, +float cv::wrapperEMD_legacy(InputArray _signature1, InputArray _signature2, int distType, InputArray _cost, Ptr lowerBound, OutputArray _flow) { diff --git a/modules/imgproc/src/emd_new.cpp b/modules/imgproc/src/emd_new.cpp new file mode 100644 index 000000000000..8e901c795ab4 --- /dev/null +++ b/modules/imgproc/src/emd_new.cpp @@ -0,0 +1,1010 @@ +// 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 + +/* + Partially based on Yossi Rubner code: + ========================================================================= + emd.c + + Last update: 3/14/98 + + An implementation of the Earth Movers Distance. + Based of the solution for the Transportation problem as described in + "Introduction to Mathematical Programming" by F. S. Hillier and + G. J. Lieberman, McGraw-Hill, 1990. + + Copyright (C) 1998 Yossi Rubner + Computer Science Department, Stanford University + E-Mail: rubner@cs.stanford.edu URL: http://vision.stanford.edu/~rubner + ========================================================================== +*/ + +#include "precomp.hpp" + +using namespace cv; + +namespace { + + +//============================================================================== +// Distance functions + +typedef float (*DistFunc)(const float* a, const float* b, int dims); + +static float distL1(const float* x, const float* y, int dims) +{ + double s = 0; + for (int i = 0; i < dims; i++) + { + const double t = x[i] - y[i]; + s += fabs(t); + } + return (float)s; +} + +static float distL2(const float* x, const float* y, int dims) +{ + double s = 0; + for (int i = 0; i < dims; i++) + { + const double t = x[i] - y[i]; + s += t * t; + } + return sqrt((float)s); +} + +static float distC(const float* x, const float* y, int dims) +{ + double s = 0; + for (int i = 0; i < dims; i++) + { + const double t = fabs(x[i] - y[i]); + if (s < t) + s = t; + } + return (float)s; +} + + +//============================================================================== +// Data structures + +/* Node1D is used for lists, representing 1D sparse array */ +struct Node1D +{ + float val; + Node1D* next; +}; + +/* Node2D is used for lists, representing 2D sparse matrix */ +struct Node2D +{ + float val; + int i, j; + Node2D* next[2]; /* next row & next column */ +}; + + +//============================================================================== +// Main class + +struct EMDSolver +{ + static constexpr int MAX_ITERATIONS = 500; + static constexpr float CV_EMD_INF = 1e20f; + static constexpr float CV_EMD_EPS = 1e-5f; + + int ssize, dsize; + + float* cost_buf; + Node2D* data_x; + Node2D* end_x; + Node2D* enter_x; + char* is_x; + + Node2D** rows_x; + Node2D** cols_x; + + Node1D* u; + Node1D* v; + + int* idx1; + int* idx2; + + /* find_loop buffers */ + Node2D** loop; + char* is_used; + + /* russel buffers */ + float* s; + float* d; + float* delta; + + float weight, max_cost; + + utils::BufferArea area, area2; + +public: + float getWeight() const + { + return weight; + } + + float& getCost(int i, int j) + { + return *(this->cost_buf + i * dsize + j); + } + const float& getCost(int i, int j) const + { + return *(this->cost_buf + i * dsize + j); + } + char& getIsX(int i, int j) + { + return *(this->is_x + i * dsize + j); + } + const char& getIsX(int i, int j) const + { + return *(this->is_x + i * dsize + j); + } + + EMDSolver() : + ssize(0), dsize(0), cost_buf(0), data_x(0), end_x(0), enter_x(0), is_x(0), rows_x(0), + cols_x(0), u(0), v(0), idx1(0), idx2(0), loop(0), is_used(0), s(0), d(0), delta(0), + weight(0), max_cost(0) + { + } + +public: + bool init(const Mat& sign1, + const Mat& sign2, + int dims, + DistFunc dfunc, + const Mat& cost, + float* lowerBound); + bool checkLowerBound(const Mat& sign1, + const Mat& sign2, + int dims, + DistFunc dfunc, + float& lowerBound); + bool calcSums(const Mat& sign1, const Mat& sign2); + float calcCost(const Mat& sign1, const Mat& sign2, int dims, DistFunc dfunc, const Mat& cost); + void solve(); + double calcFlow(Mat* flow_) const; + int findBasicVars() const; + float checkOptimal() const; + void callRussel(); + bool checkNewSolution(); + int findLoop() const; + void addBasicVar(int min_i, + int min_j, + Node1D* prev_u_min_i, + Node1D* prev_v_min_j, + Node1D* u_head); +}; + + +//============================================================================== +// Implementations + +bool EMDSolver::init(const Mat& sign1, + const Mat& sign2, + int dims, + DistFunc dfunc, + const Mat& cost, + float* lowerBound) +{ + const int size1 = sign1.size().height; + const int size2 = sign2.size().height; + + area.allocate(this->idx1, size1 + 1); + area.allocate(this->idx2, size2 + 1); + area.allocate(this->s, size1 + 1); + area.allocate(this->d, size2 + 1); + area.commit(); + area.zeroFill(); + + const bool areSumsEqual = calcSums(sign1, sign2); + if (areSumsEqual && lowerBound) + { + if (checkLowerBound(sign1, sign2, dims, dfunc, *lowerBound)) + return false; + } + + area2.allocate(this->u, ssize, 64); + area2.allocate(this->v, dsize, 64); + area2.allocate(this->is_used, ssize + dsize); + area2.allocate(this->delta, ssize * dsize); + area2.allocate(this->cost_buf, ssize * dsize); + area2.allocate(this->is_x, ssize * dsize); + area2.allocate(this->data_x, ssize + dsize, 64); + area2.allocate(this->rows_x, ssize, 64); + area2.allocate(this->cols_x, dsize, 64); + area2.allocate(this->loop, ssize + dsize + 1, 64); + area2.commit(); + area2.zeroFill(); + + this->end_x = this->data_x; + this->max_cost = calcCost(sign1, sign2, dims, dfunc, cost); + callRussel(); + this->enter_x = (this->end_x)++; + return true; +} + + +bool EMDSolver::checkLowerBound(const Mat& sign1, + const Mat& sign2, + int dims, + DistFunc dfunc, + float& lowerBound) +{ + AutoBuffer buf; + buf.allocate(dims * 2); + memset(buf.data(), 0, dims * 2 * sizeof(float)); + + float* xs = buf.data(); + float* xd = buf.data() + dims; + + for (int j = 0; j < sign1.rows; ++j) + { + const float weight_ = sign1.at(j, 0); + for (int i = 0; i < dims; i++) + xs[i] += sign1.at(j, i + 1) * weight_; + } + + for (int j = 0; j < sign2.rows; ++j) + { + const float weight_ = sign2.at(j, 0); + for (int i = 0; i < dims; i++) + xd[i] += sign2.at(j, i + 1) * weight_; + } + + const float lb = dfunc(xs, xd, dims) / this->weight; + const bool result = (lowerBound <= lb); + lowerBound = lb; + return result; +} + + +// return true if total sums of signatures are equal, false otherwise +bool EMDSolver::calcSums(const Mat& sign1, const Mat& sign2) +{ + bool result = true; + /* sum up the supply and demand */ + int ssize_ = 0, dsize_ = 0; + float s_sum = 0, d_sum = 0, diff; + for (int i = 0; i < sign1.size().height; i++) + { + const float weight_ = sign1.at(i, 0); + + if (weight_ > 0) + { + s_sum += weight_; + this->s[ssize_] = weight_; + this->idx1[ssize_++] = i; + } + else if (weight_ < 0) + CV_Error(cv::Error::StsBadArg, "sign1 must not contain negative weights"); + } + + for (int i = 0; i < sign2.size().height; i++) + { + const float weight_ = sign2.at(i, 0); + + if (weight_ > 0) + { + d_sum += weight_; + this->d[dsize_] = weight_; + this->idx2[dsize_++] = i; + } + else if (weight_ < 0) + CV_Error(cv::Error::StsBadArg, "sign2 must not contain negative weights"); + } + + if (ssize_ == 0) + CV_Error(cv::Error::StsBadArg, "sign1 must contain at least one non-zero value"); + if (dsize_ == 0) + CV_Error(cv::Error::StsBadArg, "sign2 must contain at least one non-zero value"); + + /* if supply different than the demand, add a zero-cost dummy cluster */ + diff = s_sum - d_sum; + if (fabs(diff) >= CV_EMD_EPS * s_sum) + { + result = false; + if (diff < 0) + { + this->s[ssize_] = -diff; + this->idx1[ssize_++] = -1; + } + else + { + this->d[dsize_] = diff; + this->idx2[dsize_++] = -1; + } + } + + this->ssize = ssize_; + this->dsize = dsize_; + this->weight = s_sum > d_sum ? s_sum : d_sum; + return result; +} + + +// returns maximum cost over all possible s->d combinations +float EMDSolver::calcCost(const Mat& sign1, + const Mat& sign2, + int dims, + DistFunc dfunc, + const Mat& cost) +{ + if (!dfunc) + { + CV_Assert(!cost.empty()); + } + float result = 0; + + /* compute the distance matrix */ + for (int i = 0; i < ssize; i++) + { + const int ci = this->idx1[i]; + if (ci >= 0) + { + for (int j = 0; j < dsize; j++) + { + const int cj = this->idx2[j]; + if (cj < 0) + getCost(i, j) = 0; + else + { + float val; + if (dfunc) + { + val = dfunc(sign1.ptr(ci, 1), sign2.ptr(cj, 1), dims); + } + else + { + val = cost.at(ci, cj); + } + getCost(i, j) = val; + if (result < val) + result = val; + } + } + } + else + { + for (int j = 0; j < dsize; j++) + getCost(i, j) = 0; + } + } + return result; +} + + +// runs solver iterations +void EMDSolver::solve() +{ + if (ssize > 1 && dsize > 1) + { + const float eps = CV_EMD_EPS * max_cost; + for (int itr = 1; itr < MAX_ITERATIONS; itr++) + { + /* find basic variables */ + if (findBasicVars() < 0) + break; + + /* check for optimality */ + const float min_delta = checkOptimal(); + + if (min_delta == CV_EMD_INF) + CV_Error(cv::Error::StsNoConv, ""); + + /* if no negative deltamin, we found the optimal solution */ + if (min_delta >= -eps) + break; + + /* improve solution */ + if (!checkNewSolution()) + CV_Error(cv::Error::StsNoConv, ""); + } + } +} + +double EMDSolver::calcFlow(Mat* flow_) const +{ + double result = 0.; + Node2D* xp = 0; + for (xp = data_x; xp < end_x; xp++) + { + float val = xp->val; + const int i = xp->i; + const int j = xp->j; + + if (xp == enter_x) + continue; + + const int ci = idx1[i]; + const int cj = idx2[j]; + + if (ci >= 0 && cj >= 0) + { + result += (double)val * getCost(i, j); + if (flow_) + { + flow_->at(ci, cj) = val; + } + } + } + return result; +} + + +int EMDSolver::findBasicVars() const +{ + int i, j; + int u_cfound, v_cfound; + Node1D u0_head, u1_head, *cur_u, *prev_u; + Node1D v0_head, v1_head, *cur_v, *prev_v; + bool found; + + CV_Assert(u != 0 && v != 0); + + /* initialize the rows list (u) and the columns list (v) */ + u0_head.next = u; + for (i = 0; i < ssize; i++) + { + u[i].next = u + i + 1; + } + u[ssize - 1].next = 0; + u1_head.next = 0; + + v0_head.next = ssize > 1 ? v + 1 : 0; + for (i = 1; i < dsize; i++) + { + v[i].next = v + i + 1; + } + v[dsize - 1].next = 0; + v1_head.next = 0; + + /* there are ssize+dsize variables but only ssize+dsize-1 independent equations, + so set v[0]=0 */ + v[0].val = 0; + v1_head.next = v; + v1_head.next->next = 0; + + /* loop until all variables are found */ + u_cfound = v_cfound = 0; + while (u_cfound < ssize || v_cfound < dsize) + { + found = false; + if (v_cfound < dsize) + { + /* loop over all marked columns */ + prev_v = &v1_head; + cur_v = v1_head.next; + found = found || (cur_v != 0); + for (; cur_v != 0; cur_v = cur_v->next) + { + float cur_v_val = cur_v->val; + + j = (int)(cur_v - v); + /* find the variables in column j */ + prev_u = &u0_head; + for (cur_u = u0_head.next; cur_u != 0;) + { + i = (int)(cur_u - u); + if (getIsX(i, j)) + { + /* compute u[i] */ + cur_u->val = getCost(i, j) - cur_v_val; + /* ...and add it to the marked list */ + prev_u->next = cur_u->next; + cur_u->next = u1_head.next; + u1_head.next = cur_u; + cur_u = prev_u->next; + } + else + { + prev_u = cur_u; + cur_u = cur_u->next; + } + } + prev_v->next = cur_v->next; + v_cfound++; + } + } + + if (u_cfound < ssize) + { + /* loop over all marked rows */ + prev_u = &u1_head; + cur_u = u1_head.next; + found = found || (cur_u != 0); + for (; cur_u != 0; cur_u = cur_u->next) + { + float cur_u_val = cur_u->val; + i = (int)(cur_u - u); + /* find the variables in rows i */ + prev_v = &v0_head; + for (cur_v = v0_head.next; cur_v != 0;) + { + j = (int)(cur_v - v); + if (getIsX(i, j)) + { + /* compute v[j] */ + cur_v->val = getCost(i, j) - cur_u_val; + /* ...and add it to the marked list */ + prev_v->next = cur_v->next; + cur_v->next = v1_head.next; + v1_head.next = cur_v; + cur_v = prev_v->next; + } + else + { + prev_v = cur_v; + cur_v = cur_v->next; + } + } + prev_u->next = cur_u->next; + u_cfound++; + } + } + + if (!found) + return -1; + } + + return 0; +} + +float EMDSolver::checkOptimal() const +{ + int i, j, min_i = 0, min_j = 0; + + float min_delta = CV_EMD_INF; + /* find the minimal cij-ui-vj over all i,j */ + for (i = 0; i < ssize; i++) + { + float u_val = u[i].val; + for (j = 0; j < dsize; j++) + { + if (!getIsX(i, j)) + { + const float delta_ = getCost(i, j) - u_val - v[j].val; + if (min_delta > delta_) + { + min_delta = delta_; + min_i = i; + min_j = j; + } + } + } + } + + enter_x->i = min_i; + enter_x->j = min_j; + + return min_delta; +} + +bool EMDSolver::checkNewSolution() +{ + int i, j; + float min_val = CV_EMD_INF; + int steps; + Node2D head {0, 0, 0, {0, 0}}, *cur_x, *next_x, *leave_x = 0; + Node2D* enter_x_ = this->enter_x; + Node2D** loop_ = this->loop; + + /* enter the new basic variable */ + i = enter_x_->i; + j = enter_x_->j; + getIsX(i, j) = 1; + enter_x_->next[0] = this->rows_x[i]; + enter_x->next[1] = this->cols_x[j]; + enter_x_->val = 0; + this->rows_x[i] = enter_x_; + this->cols_x[j] = enter_x_; + + /* find a chain reaction */ + steps = findLoop(); + + if (steps == 0) + return false; + + /* find the largest value in the loop */ + for (i = 1; i < steps; i += 2) + { + float temp = loop_[i]->val; + + if (min_val > temp) + { + leave_x = loop_[i]; + min_val = temp; + } + } + + /* update the loop */ + for (i = 0; i < steps; i += 2) + { + float temp0 = loop_[i]->val + min_val; + float temp1 = loop_[i + 1]->val - min_val; + + loop_[i]->val = temp0; + loop_[i + 1]->val = temp1; + } + + /* remove the leaving basic variable */ + CV_Assert(leave_x != NULL); + i = leave_x->i; + j = leave_x->j; + getIsX(i, j) = 0; + + head.next[0] = this->rows_x[i]; + cur_x = &head; + while ((next_x = cur_x->next[0]) != leave_x) + { + cur_x = next_x; + CV_Assert(cur_x); + } + cur_x->next[0] = next_x->next[0]; + this->rows_x[i] = head.next[0]; + + head.next[1] = this->cols_x[j]; + cur_x = &head; + while ((next_x = cur_x->next[1]) != leave_x) + { + cur_x = next_x; + CV_Assert(cur_x); + } + cur_x->next[1] = next_x->next[1]; + this->cols_x[j] = head.next[1]; + + /* set enter_x to be the new empty slot */ + this->enter_x = leave_x; + + return true; +} + +int EMDSolver::findLoop() const +{ + int i; + + memset(is_used, 0, this->ssize + this->dsize); + + Node2D* new_x = loop[0] = enter_x; + is_used[enter_x - data_x] = 1; + int steps = 1; + + do + { + if ((steps & 1) == 1) + { + /* find an unused x in the row */ + new_x = this->rows_x[new_x->i]; + while (new_x != 0 && is_used[new_x - data_x]) + new_x = new_x->next[0]; + } + else + { + /* find an unused x in the column, or the entering x */ + new_x = this->cols_x[new_x->j]; + while (new_x != 0 && is_used[new_x - data_x] && new_x != enter_x) + new_x = new_x->next[1]; + if (new_x == enter_x) + break; + } + + if (new_x != 0) /* found the next x */ + { + /* add x to the loop */ + loop[steps++] = new_x; + is_used[new_x - data_x] = 1; + } + else /* didn't find the next x */ + { + /* backtrack */ + do + { + i = steps & 1; + new_x = loop[steps - 1]; + do + { + new_x = new_x->next[i]; + } + while (new_x != 0 && is_used[new_x - data_x]); + + if (new_x == 0) + { + is_used[loop[--steps] - data_x] = 0; + } + } + while (new_x == 0 && steps > 0); + + is_used[loop[steps - 1] - data_x] = 0; + loop[steps - 1] = new_x; + is_used[new_x - data_x] = 1; + } + } + while (steps > 0); + + return steps; +} + +void EMDSolver::callRussel() +{ + int i, j, min_i = -1, min_j = -1; + float min_delta, diff; + Node1D u_head, *cur_u, *prev_u; + Node1D v_head, *cur_v, *prev_v; + Node1D *prev_u_min_i = 0, *prev_v_min_j = 0, *remember; + float eps = CV_EMD_EPS * this->max_cost; + + /* initialize the rows list (ur), and the columns list (vr) */ + u_head.next = u; + for (i = 0; i < ssize; i++) + { + u[i].next = u + i + 1; + } + u[ssize - 1].next = 0; + + v_head.next = v; + for (i = 0; i < dsize; i++) + { + v[i].val = -CV_EMD_INF; + v[i].next = v + i + 1; + } + v[dsize - 1].next = 0; + + /* find the maximum row and column values (ur[i] and vr[j]) */ + for (i = 0; i < ssize; i++) + { + float u_val = -CV_EMD_INF; + for (j = 0; j < dsize; j++) + { + float temp = getCost(i, j); + + if (u_val < temp) + u_val = temp; + if (v[j].val < temp) + v[j].val = temp; + } + u[i].val = u_val; + } + + /* compute the delta matrix */ + for (i = 0; i < ssize; i++) + { + float u_val = u[i].val; + float* delta_row = delta + i * dsize; + for (j = 0; j < dsize; j++) + { + delta_row[j] = getCost(i, j) - u_val - v[j].val; + } + } + + /* find the basic variables */ + do + { + /* find the smallest delta[i][j] */ + min_i = -1; + min_delta = CV_EMD_INF; + prev_u = &u_head; + for (cur_u = u_head.next; cur_u != 0; cur_u = cur_u->next) + { + i = (int)(cur_u - u); + float* delta_row = delta + i * dsize; + + prev_v = &v_head; + for (cur_v = v_head.next; cur_v != 0; cur_v = cur_v->next) + { + j = (int)(cur_v - v); + if (min_delta > delta_row[j]) + { + min_delta = delta_row[j]; + min_i = i; + min_j = j; + prev_u_min_i = prev_u; + prev_v_min_j = prev_v; + } + prev_v = cur_v; + } + prev_u = cur_u; + } + + if (min_i < 0) + break; + + /* add x[min_i][min_j] to the basis, and adjust supplies and cost */ + remember = prev_u_min_i->next; + addBasicVar(min_i, min_j, prev_u_min_i, prev_v_min_j, &u_head); + + /* update the necessary delta[][] */ + if (remember == prev_u_min_i->next) /* line min_i was deleted */ + { + for (cur_v = v_head.next; cur_v != 0; cur_v = cur_v->next) + { + j = (int)(cur_v - v); + if (cur_v->val == getCost(min_i, j)) /* column j needs updating */ + { + float max_val = -CV_EMD_INF; + + /* find the new maximum value in the column */ + for (cur_u = u_head.next; cur_u != 0; cur_u = cur_u->next) + { + float temp = getCost((int)(cur_u - u), j); + + if (max_val < temp) + max_val = temp; + } + + /* if needed, adjust the relevant delta[*][j] */ + diff = max_val - cur_v->val; + cur_v->val = max_val; + if (fabs(diff) < eps) + { + for (cur_u = u_head.next; cur_u != 0; cur_u = cur_u->next) + *(delta + (cur_u - u) * dsize + j) += diff; + } + } + } + } + else /* column min_j was deleted */ + { + for (cur_u = u_head.next; cur_u != 0; cur_u = cur_u->next) + { + i = (int)(cur_u - u); + if (cur_u->val == getCost(i, min_j)) /* row i needs updating */ + { + float max_val = -CV_EMD_INF; + + /* find the new maximum value in the row */ + for (cur_v = v_head.next; cur_v != 0; cur_v = cur_v->next) + { + float temp = getCost(i, (int)(cur_v - v)); + + if (max_val < temp) + max_val = temp; + } + + /* if needed, adjust the relevant delta[i][*] */ + diff = max_val - cur_u->val; + cur_u->val = max_val; + + if (fabs(diff) < eps) + { + for (cur_v = v_head.next; cur_v != 0; cur_v = cur_v->next) + *(delta + i * dsize + (cur_v - v)) += diff; + } + } + } + } + } + while (u_head.next != 0 || v_head.next != 0); +} + +void EMDSolver::addBasicVar(int min_i, + int min_j, + Node1D* prev_u_min_i, + Node1D* prev_v_min_j, + Node1D* u_head) +{ + float temp; + + if (this->s[min_i] < this->d[min_j] + this->weight * CV_EMD_EPS) + { /* supply exhausted */ + temp = this->s[min_i]; + this->s[min_i] = 0; + this->d[min_j] -= temp; + } + else /* demand exhausted */ + { + temp = this->d[min_j]; + this->d[min_j] = 0; + this->s[min_i] -= temp; + } + + /* x(min_i,min_j) is a basic variable */ + getIsX(min_i, min_j) = 1; + + end_x->val = temp; + end_x->i = min_i; + end_x->j = min_j; + end_x->next[0] = this->rows_x[min_i]; + end_x->next[1] = this->cols_x[min_j]; + this->rows_x[min_i] = end_x; + this->cols_x[min_j] = end_x; + this->end_x = end_x + 1; + + /* delete supply row only if the empty, and if not last row */ + if (this->s[min_i] == 0 && u_head->next->next != 0) + prev_u_min_i->next = prev_u_min_i->next->next; /* remove row from list */ + else + prev_v_min_j->next = prev_v_min_j->next->next; /* remove column from list */ +} + +} // namespace + + +//============================================================================== +// External interface + +float cv::EMD(InputArray _sign1, + InputArray _sign2, + int distType, + InputArray _cost, + float* lowerBound, + OutputArray _flow) +{ + CV_INSTRUMENT_REGION(); + + Mat sign1 = _sign1.getMat(); + Mat sign2 = _sign2.getMat(); + Mat cost = _cost.getMat(); + + CV_CheckEQ(sign1.cols, sign2.cols, "Signatures must have equal number of columns"); + CV_CheckEQ(sign1.type(), CV_32FC1, "The sign1 must be 32FC1"); + CV_CheckEQ(sign2.type(), CV_32FC1, "The sign2 must be 32FC1"); + + const int dims = sign1.cols - 1; + const int size1 = sign1.rows; + const int size2 = sign2.rows; + + Mat flow; + if (_flow.needed()) + { + _flow.create(sign1.rows, sign2.rows, CV_32F); + flow = _flow.getMat(); + flow = Scalar::all(0); + CV_CheckEQ(flow.type(), CV_32FC1, "Flow matrix must have type 32FC1"); + CV_CheckTrue(flow.rows == size1 && flow.cols == size2, + "Flow matrix size does not match signatures"); + } + + DistFunc dfunc = 0; + if (distType == DIST_USER) + { + if (!cost.empty()) + { + CV_CheckEQ(cost.type(), CV_32FC1, "Cost matrix must have type 32FC1"); + CV_CheckTrue(cost.rows == size1 && cost.cols == size2, + "Cost matrix size does not match signatures"); + CV_CheckTrue(lowerBound == NULL, + "Lower boundary can not be calculated if the cost matrix is used"); + } + else + { + CV_CheckTrue(dfunc == NULL, "Dist function must be set if cost matrix is empty"); + } + } + else + { + CV_CheckNE(dims, 0, "Number of dimensions can be 0 only if a user-defined metric is used"); + switch (distType) + { + case cv::DIST_L1: dfunc = distL1; break; + case cv::DIST_L2: dfunc = distL2; break; + case cv::DIST_C: dfunc = distC; break; + default: CV_Error(cv::Error::StsBadFlag, "Bad or unsupported metric type"); + } + } + + EMDSolver state; + const bool result = state.init(sign1, sign2, dims, dfunc, cost, lowerBound); + if (!result && lowerBound) + { + return *lowerBound; + } + state.solve(); + return (float)(state.calcFlow(_flow.needed() ? &flow : 0) / state.getWeight()); +} + +float cv::wrapperEMD(InputArray _sign1, + InputArray _sign2, + int distType, + InputArray _cost, + Ptr lowerBound, + OutputArray _flow) +{ + return EMD(_sign1, _sign2, distType, _cost, lowerBound.get(), _flow); +} diff --git a/modules/imgproc/src/precomp.hpp b/modules/imgproc/src/precomp.hpp index 29dbce6d5ffe..df35da529c50 100644 --- a/modules/imgproc/src/precomp.hpp +++ b/modules/imgproc/src/precomp.hpp @@ -50,6 +50,8 @@ #include "opencv2/core/private.hpp" #include "opencv2/core/ocl.hpp" #include "opencv2/core/hal/hal.hpp" +#include "opencv2/core/check.hpp" +#include "opencv2/core/utils/buffer_area.private.hpp" #include "opencv2/imgproc/hal/hal.hpp" #include "hal_replacement.hpp" diff --git a/modules/imgproc/test/test_emd.cpp b/modules/imgproc/test/test_emd.cpp index 51f05f374e97..59cd8381a135 100644 --- a/modules/imgproc/test/test_emd.cpp +++ b/modules/imgproc/test/test_emd.cpp @@ -1,93 +1,250 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// Intel License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of Intel Corporation may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ +// 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 +#include "opencv2/imgproc.hpp" #include "test_precomp.hpp" +using namespace cv; +using namespace std; + namespace opencv_test { namespace { -class CV_EMDTest : public cvtest::BaseTest -{ -public: - CV_EMDTest(); -protected: - void run(int); -}; +//============================================================================== +// Utility +template +inline T sqr(T val) +{ + return val * val; +} -CV_EMDTest::CV_EMDTest() +inline static float calcEMD(Mat w1, Mat w2, Mat& flow, int dist, int dims) { + float mass1 = 0.f, mass2 = 0.f, work = 0.f; + for (int i = 0; i < flow.rows; ++i) + { + mass1 += w1.at(i, 0); + for (int j = 0; j < flow.cols; ++j) + { + if (i == 0) + mass2 += w2.at(j, 0); + float dist_ = 0.f; + switch (dist) + { + case DIST_L1: + { + for (int k = 1; k <= dims; ++k) + { + dist_ += abs(w1.at(i, k) - w2.at(j, k)); + } + break; + } + case DIST_L2: + { + for (int k = 1; k <= dims; ++k) + { + dist_ += sqr(w1.at(i, k) - w2.at(j, k)); + } + dist_ = sqrt(dist_); + break; + } + case DIST_C: + { + for (int k = 1; k <= dims; ++k) + { + const float val = abs(w1.at(i, k) - w2.at(j, k)); + if (val > dist_) + dist_ = val; + } + break; + } + } + const float weight = flow.at(i, j); + work += dist_ * weight; + } + } + return work / max(mass1, mass2); } -void CV_EMDTest::run( int ) +//============================================================================== + +TEST(Imgproc_EMD, regression) { - int code = cvtest::TS::OK; - const double success_error_level = 1e-6; - #define M 10000 - double emd0 = 2460./210; - static float cost[] = + // input data + const float M = 10000; + Matx w1 {50, 60, 50, 50}; + Matx w2 {30, 20, 70, 30, 60}; + Matx cost {16, 16, 13, 22, 17, 14, 14, 13, 19, 15, + 19, 19, 20, 23, M, M, 0, M, 0, 0}; + + // expected results + const double emd0 = 2460. / 210; + Matx flow0 {0, 0, 50, 0, 0, 0, 0, 20, 0, 40, 30, 20, 0, 0, 0, 0, 0, 0, 30, 20}; + + // basic call with cost + { + float emd = 0.f; + ASSERT_NO_THROW(emd = EMD(w1, w2, DIST_USER, cost)); + EXPECT_NEAR(emd, emd0, 1e-6 * emd0); + } + + // basic call with cost and flow output { - 16, 16, 13, 22, 17, - 14, 14, 13, 19, 15, - 19, 19, 20, 23, M, - M , 0, M, 0, 0 - }; - static float w1[] = { 50, 60, 50, 50 }, - w2[] = { 30, 20, 70, 30, 60 }; - Mat _w1(4, 1, CV_32F, w1); - Mat _w2(5, 1, CV_32F, w2); - Mat _cost(_w1.rows, _w2.rows, CV_32F, cost); - - float emd = EMD( _w1, _w2, -1, _cost ); - if( fabs( emd - emd0 ) > success_error_level*emd0 ) + Mat flow; + float emd = 0.f; + ASSERT_NO_THROW(emd = EMD(w1, w2, DIST_USER, cost, nullptr, flow)); + EXPECT_NEAR(emd, emd0, 1e-6 * emd0); + EXPECT_MAT_NEAR(Mat(flow0), flow, 1e-6); + } + // no cost and DIST_USER - error { - ts->printf( cvtest::TS::LOG, - "The computed distance is %.2f, while it should be %.2f\n", emd, emd0 ); - code = cvtest::TS::FAIL_BAD_ACCURACY; + Mat flow; + EXPECT_THROW(EMD(w1, w2, DIST_USER, noArray(), nullptr, flow), cv::Exception); + EXPECT_THROW(EMD(w1, w2, DIST_USER), cv::Exception); } +} + +TEST(Imgproc_EMD, distance_types) +{ + // 1D (sum = 210) + Matx w1 {50, 1, 60, 2, 50, 3, 50, 4}; + Matx w2 {30, 1, 20, 2, 70, 3, 30, 4, 60, 5}; + + // 2D (sum = 210) + Matx w3 {50, 0, 0, 60, 0, 1, 50, 1, 0, 50, 1, 1}; + Matx w4 {20, 0, 1, 70, 1, 0, 30, 1, 1, 60, 2, 2, 30, 3, 3}; + + // basic call with all distance types + { + const vector good_types {DIST_L1, DIST_L2, DIST_C}; + for (const auto& dt : good_types) + { + SCOPED_TRACE(cv::format("dt=%d", dt)); + float emd = 0.f; + Mat flow; + // 1D + { + ASSERT_NO_THROW(emd = EMD(w1, w2, dt, noArray(), nullptr, flow)); + const float emd0 = calcEMD(Mat(w1), Mat(w2), flow, dt, 1); + EXPECT_NEAR(emd0, emd, 1e-6); + } + // 2D + { + ASSERT_NO_THROW(emd = EMD(w3, w4, dt, noArray(), nullptr, flow)); + const float emd0 = calcEMD(Mat(w3), Mat(w4), flow, dt, 2); + EXPECT_NEAR(emd0, emd, 1e-6); + } + } + } +} + +typedef testing::TestWithParam Imgproc_EMD_dist; + +TEST_P(Imgproc_EMD_dist, random_flow_verify) +{ + const int dist = GetParam(); + for (size_t iter = 0; iter < 100; ++iter) + { + SCOPED_TRACE(cv::format("iter=%zu", iter)); + RNG& rng = TS::ptr()->get_rng(); + const int dims = rng.uniform(1, 10); + Mat w1(rng.uniform(1, 10), dims + 1, CV_32FC1); + Mat w2(rng.uniform(1, 10), dims + 1, CV_32FC1); - if( code < 0 ) - ts->set_failed_test_info( code ); + // weights > 0 + { + Mat w1_weights = w1.col(0); + Mat w2_weights = w2.col(0); + cvtest::randUni(rng, w1_weights, 0, 100); + cvtest::randUni(rng, w2_weights, 0, 100); + } + + // coord + { + Mat w1_coord = w1.colRange(1, dims + 1); + Mat w2_coord = w2.colRange(1, dims + 1); + cvtest::randUni(rng, w1_coord, -10, +10); + cvtest::randUni(rng, w2_coord, -10, +10); + } + + float emd1 = 0.f, emd2 = 0.f; + const float eps = 1e-5f; + Mat flow; + { + ASSERT_NO_THROW(emd1 = EMD(w1, w2, dist, noArray(), nullptr, flow)); + const float emd0 = calcEMD(w1, w2, flow, dist, dims); + EXPECT_NEAR(emd0, emd1, eps); + } + { + ASSERT_NO_THROW(emd2 = EMD(w2, w1, dist, noArray(), nullptr, flow)); + const float emd0 = calcEMD(w2, w1, flow, dist, dims); + EXPECT_NEAR(emd0, emd2, eps); + } + EXPECT_NEAR(emd1, emd2, eps); + } } -TEST(Imgproc_EMD, regression) { CV_EMDTest test; test.safe_run(); } +INSTANTIATE_TEST_CASE_P(, Imgproc_EMD_dist, testing::Values(DIST_L1, DIST_L2, DIST_C)); + + +TEST(Imgproc_EMD, invalid) +{ + Matx w1 {50, 1, 60, 2, 50, 3, 50, 4}; + Matx w2 {30, 1, 20, 2, 70, 3, 30, 4, 60, 5}; + + // empty signature + { + Mat empty; + EXPECT_THROW(EMD(empty, w2, DIST_USER), cv::Exception); + EXPECT_THROW(EMD(w1, empty, DIST_USER), cv::Exception); + } + + // zero total weight, negative weight + { + Matx wz {0, 0, 0}; + Matx wz1 {0, 1, 0, 2, 0, 3}; + Matx wn {0, 3, -2}; + Matx wn1 {0, 1, 3, 2, -2, 3}; + EXPECT_THROW(EMD(wz, w2, DIST_USER), cv::Exception); + EXPECT_THROW(EMD(wz1, w2, DIST_USER), cv::Exception); + EXPECT_THROW(EMD(wn, w2, DIST_USER), cv::Exception); + EXPECT_THROW(EMD(wn1, w2, DIST_USER), cv::Exception); + } + + // user distance type, but no cost matrix provided or is wrong + { + Mat cost(3, 3, CV_32FC1, Scalar::all(0)), cost8u(4, 5, CV_8UC1, Scalar::all(0)), empty; + EXPECT_THROW(EMD(w1, w2, DIST_USER, noArray()), cv::Exception); + EXPECT_THROW(EMD(w1, w2, DIST_USER, empty), cv::Exception); + EXPECT_THROW(EMD(w1, w2, DIST_USER, cost8u), cv::Exception); + EXPECT_THROW(EMD(w1, w2, DIST_USER, cost), cv::Exception); + } + + // lower_bound is set together with cost + { + Mat cost(4, 5, CV_32FC1, Scalar::all(0)); + float bound = 0.f; + EXPECT_THROW(EMD(w1, w2, DIST_USER, cost, &bound), cv::Exception); + } + + // zero dimensions with non-user distance type + const vector good_types {DIST_L1, DIST_L2, DIST_C}; + for (const auto& dt : good_types) + { + SCOPED_TRACE(cv::format("dt=%d", dt)); + Matx w01 {20, 30, 40, 50}; + Matx w02 {20, 30, 40, 50, 10}; + EXPECT_THROW(EMD(w01, w02, dt), cv::Exception); + } + + // wrong distance type + const vector bad_types {DIST_L12, DIST_FAIR, DIST_WELSCH, DIST_HUBER}; + for (const auto& dt : bad_types) + { + SCOPED_TRACE(cv::format("dt=%d", dt)); + EXPECT_THROW(EMD(w1, w2, dt), cv::Exception); + } +} -}} // namespace -/* End of file. */ +}} // namespace opencv_test diff --git a/modules/imgproc/test/test_precomp.hpp b/modules/imgproc/test/test_precomp.hpp index ce5100914543..4df4a922b511 100644 --- a/modules/imgproc/test/test_precomp.hpp +++ b/modules/imgproc/test/test_precomp.hpp @@ -5,8 +5,11 @@ #define __OPENCV_TEST_PRECOMP_HPP__ #include "opencv2/ts.hpp" +#include "opencv2/ts/ts_gtest.h" +#include "opencv2/ts/ocl_test.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/imgproc/imgproc_c.h" +#include "opencv2/core.hpp" #include "opencv2/core/private.hpp" From ebea65777f30e0090807d410b8ab878517795a32 Mon Sep 17 00:00:00 2001 From: Daria Mityagina Date: Wed, 24 Apr 2024 16:25:00 +0300 Subject: [PATCH 008/119] Merge pull request #24938 from DariaMityagina:icv/dm/add-media-frame-support-to-govbackend G-API OV backend requires cv::MediaFrame #24938 ### Pull Request Readiness Checklist **Background_subtraction demo G-API issue. Update:** Porting to API20 resulted in an error (both for CPU and NPU): ``` [ERROR] OpenCV(4.9.0-dev) /home/runner/work/open_model_zoo/open_model_zoo/cache/opencv/modules/gapi/src/backends/ov/govbackend.cpp:813: error: (-215: assertion not done ) cv::util::holds_alternative(input_meta) in function 'cfgPreProcessing' ``` Adding cv::MediaFrame support to govbackend resulted in the following (tested with CPU): image ### TODO - [ ] **As part of the review process [this comment](https://github.com/opencv/opencv/pull/24938#discussion_r1487694043) was addressed which make it impossible to run the demo. I will bring those changes back in a separate PR [support `PartialShape`]** See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/gapi/src/backends/ov/govbackend.cpp | 166 ++++++++++++++---- .../gapi/test/infer/gapi_infer_ov_tests.cpp | 166 ++++++++++++++++++ 2 files changed, 301 insertions(+), 31 deletions(-) diff --git a/modules/gapi/src/backends/ov/govbackend.cpp b/modules/gapi/src/backends/ov/govbackend.cpp index abbe5f9f5b6c..6b261440999e 100644 --- a/modules/gapi/src/backends/ov/govbackend.cpp +++ b/modules/gapi/src/backends/ov/govbackend.cpp @@ -129,7 +129,7 @@ static int toCV(const ov::element::Type &type) { static void copyFromOV(const ov::Tensor &tensor, cv::Mat &mat) { const auto total = mat.total() * mat.channels(); if (toCV(tensor.get_element_type()) != mat.depth() || - tensor.get_size() != total ) { + tensor.get_size() != total) { std::stringstream ss; ss << "Failed to copy data from ov::Tensor to cv::Mat." << " Data type or number of elements mismatch." @@ -151,6 +151,30 @@ static void copyFromOV(const ov::Tensor &tensor, cv::Mat &mat) { } } +cv::Mat wrapOV(const cv::MediaFrame::View& view, + const cv::GFrameDesc& desc) { + cv::Mat out; + switch (desc.fmt) { + case cv::MediaFormat::BGR: { + out = cv::Mat(desc.size, CV_8UC3, view.ptr[0], view.stride[0]); + return out; + } + case cv::MediaFormat::NV12: { + auto y_plane = cv::Mat(desc.size, CV_8UC1, view.ptr[0], view.stride[0]); + auto uv_plane = cv::Mat(desc.size / 2, CV_8UC2, view.ptr[1], view.stride[1]); + cvtColorTwoPlane(y_plane, uv_plane, out, cv::COLOR_YUV2BGR_NV12); + return out; + } + case cv::MediaFormat::GRAY: { + out = cv::Mat(desc.size, CV_8UC1, view.ptr[0], view.stride[0]); + return out; + } + default: + GAPI_Error("OV Backend: Unsupported media format"); + } + return out; +} + static void copyToOV(const cv::Mat &mat, ov::Tensor &tensor) { // TODO: Ideally there should be check that mat and tensor // dimensions are compatible. @@ -177,6 +201,12 @@ static void copyToOV(const cv::Mat &mat, ov::Tensor &tensor) { } } +static void copyToOV(const cv::MediaFrame &frame, ov::Tensor &tensor) { + const auto view = cv::MediaFrame::View(frame.access(cv::MediaFrame::Access::R)); + auto matFromFrame = wrapOV(view, frame.desc()); + copyToOV(matFromFrame, tensor); +} + std::vector cv::gapi::ov::util::to_ocv(const ::ov::Shape &shape) { return toCV(shape); } @@ -269,8 +299,9 @@ class OVCallContext } // Syntax sugar - cv::GShape inShape(std::size_t input) const; - const cv::Mat& inMat (std::size_t input) const; + cv::GShape inShape (std::size_t input) const; + const cv::Mat& inMat (std::size_t input) const; + const cv::MediaFrame& inFrame (std::size_t input) const; cv::GRunArgP output (std::size_t idx); cv::Mat& outMatR(std::size_t idx); @@ -355,6 +386,10 @@ const cv::Mat& OVCallContext::inMat(std::size_t input) const { return inArg(input); } +const cv::MediaFrame& OVCallContext::inFrame(std::size_t input) const { + return inArg(input); +} + cv::Mat& OVCallContext::outMatR(std::size_t idx) { return *cv::util::get(m_results.at(idx)); } @@ -394,6 +429,8 @@ cv::GArg OVCallContext::packArg(const cv::GArg &arg) { // (and constructed by either bindIn/Out or resetInternal) case cv::GShape::GOPAQUE: return cv::GArg(m_res.slot().at(ref.id)); + case cv::GShape::GFRAME: return cv::GArg(m_res.slot()[ref.id]); + default: cv::util::throw_error(std::logic_error("Unsupported GShape type")); break; @@ -655,6 +692,19 @@ void PostOutputsList::operator()(::ov::InferRequest &infer_request, } } +static void copyToOV(std::shared_ptr ctx, uint32_t input_idx, ov::Tensor &tensor) { + switch (ctx->inShape(input_idx)) { + case cv::GShape::GMAT: + copyToOV(ctx->inMat(input_idx), tensor); + break; + case cv::GShape::GFRAME: + copyToOV(ctx->inFrame(input_idx), tensor); + break; + default: + GAPI_Assert("Unsupported input shape for OV backend"); + } +} + namespace cv { namespace gimpl { namespace ov { @@ -730,6 +780,37 @@ static cv::Mat preprocess(const cv::Mat &in_mat, return out; } +// NB: This function is used to preprocess input image +// for InferROI, InferList, InferList2 kernels. +cv::Mat preprocess(MediaFrame::View& view, + const cv::GFrameDesc& desc, + const cv::Rect& roi, + const ::ov::Shape &model_shape) { + return preprocess(wrapOV(view, desc), roi, model_shape); +} + +static void preprocess_and_copy(std::shared_ptr ctx, + uint32_t input_idx, + const cv::Rect &roi, + const ::ov::Shape &model_shape, + ::ov::Tensor& tensor) { + switch (ctx->inShape(input_idx)) { + case cv::GShape::GMAT: { + auto roi_mat = preprocess(ctx->inMat(input_idx), roi, model_shape); + copyToOV(roi_mat, tensor); + break; + } + case cv::GShape::GFRAME: { + auto currentFrame = ctx->inFrame(input_idx); + auto view = cv::MediaFrame::View(currentFrame.access(cv::MediaFrame::Access::R)); + auto roi_mat = preprocess(view, currentFrame.desc(), roi, model_shape); + copyToOV(roi_mat, tensor); + } + default: + GAPI_Assert("Unsupported input shape for OV backend"); + } +} + static bool isImage(const cv::GMatDesc &desc, const ::ov::Shape &model_shape) { return (model_shape.size() == 4u) && @@ -739,6 +820,16 @@ static bool isImage(const cv::GMatDesc &desc, (desc.depth == CV_8U); } +static bool isImage(const cv::GMetaArg &meta, + const ::ov::Shape &shape) { + if (cv::util::holds_alternative(meta)) { + return true; + } + GAPI_Assert(cv::util::holds_alternative(meta)); + auto matdesc = cv::util::get(meta); + return isImage(matdesc, shape); +} + class PrePostProcWrapper { public: PrePostProcWrapper(std::shared_ptr<::ov::Model> &model, @@ -821,9 +912,8 @@ class PrePostProcWrapper { void cfgPreProcessing(const std::string &input_name, const cv::GMetaArg &input_meta, const bool disable_img_resize = false) { - GAPI_Assert(cv::util::holds_alternative(input_meta)); - const auto &matdesc = cv::util::get(input_meta); - + GAPI_Assert(cv::util::holds_alternative(input_meta) || + cv::util::holds_alternative(input_meta)); const auto explicit_in_tensor_layout = lookUp(m_input_tensor_layout, input_name); const auto explicit_in_model_layout = lookUp(m_input_model_layout, input_name); const auto explicit_resize = lookUp(m_interpolation, input_name); @@ -838,24 +928,35 @@ class PrePostProcWrapper { const auto &input_shape = m_model->input(input_name).get_shape(); auto &input_info = m_ppp.input(input_name); - m_ppp.input(input_name).tensor().set_element_type(toOV(matdesc.depth)); - if (isImage(matdesc, input_shape)) { + auto isMat = cv::util::holds_alternative(input_meta); + auto prec = isMat ? cv::util::get(input_meta).depth : CV_8U; + m_ppp.input(input_name).tensor().set_element_type(toOV(prec)); + + const auto &matdesc = isMat ? cv::util::get(input_meta) : cv::GMatDesc(); + const auto &framedesc = !isMat ? cv::util::get(input_meta) : cv::GFrameDesc(); + if (isImage(input_meta, input_shape)) { // NB: Image case - all necessary preprocessng is configured automatically. GAPI_LOG_DEBUG(NULL, "OV Backend: Input: \"" << input_name << "\" is image."); - if (explicit_in_tensor_layout && - *explicit_in_tensor_layout != "NHWC") { + if (explicit_in_tensor_layout && *explicit_in_tensor_layout != "NHWC") { + std::stringstream desc_str; + if (isMat) { + desc_str << matdesc; + } else { + desc_str << framedesc; + } std::stringstream ss; ss << "OV Backend: Provided tensor layout " << *explicit_in_tensor_layout - << " is not compatible with input data " << matdesc << " for layer \"" - << input_name << "\". Expecting NHWC"; + << " is not compatible with input data " << desc_str.str() << " for layer \"" + << input_name << "\". Expecting NHWC"; util::throw_error(std::logic_error(ss.str())); } else { input_info.tensor().set_layout(::ov::Layout("NHWC")); } if (!disable_img_resize) { - input_info.tensor().set_spatial_static_shape(matdesc.size.height, - matdesc.size.width); + const auto size = isMat ? cv::util::get(input_meta).size : cv::util::get(input_meta).size; + input_info.tensor().set_spatial_static_shape(size.height, + size.width); // NB: Even though resize is automatically configured // user have an opportunity to specify the interpolation algorithm. auto interp = explicit_resize @@ -877,8 +978,8 @@ class PrePostProcWrapper { if (!explicit_in_tensor_layout && model_layout.empty()) { std::stringstream ss; ss << "Resize for input layer: " << input_name - << "can't be configured." - << " Failed to extract H and W positions from layout."; + << "can't be configured." + << " Failed to extract H and W positions from layout."; util::throw_error(std::logic_error(ss.str())); } else { const auto layout = explicit_in_tensor_layout @@ -982,7 +1083,6 @@ struct Infer: public cv::detail::KernelTag { ade::util::toRange(in_metas))) { const auto &input_name = std::get<0>(it); const auto &mm = std::get<1>(it); - ppp.cfgLayouts(input_name); ppp.cfgPreProcessing(input_name, mm); ppp.cfgScaleMean(input_name, mm); @@ -1025,7 +1125,7 @@ struct Infer: public cv::detail::KernelTag { auto input_tensor = infer_request.get_tensor(input_name); // TODO: In some cases wrapping existing data pointer // might be faster than copy. Make it a strategy. - copyToOV(ctx->inMat(i), input_tensor); + copyToOV(ctx, i, input_tensor); } }, std::bind(PostOutputs, _1, _2, ctx) @@ -1054,13 +1154,13 @@ struct InferROI: public cv::detail::KernelTag { const auto &input_name = uu.params.input_names.at(0); const auto &mm = in_metas.at(1u); - GAPI_Assert(cv::util::holds_alternative(mm)); - const auto &matdesc = cv::util::get(mm); - + GAPI_Assert(cv::util::holds_alternative(mm) || + cv::util::holds_alternative(mm)); const bool is_model = cv::util::holds_alternative(uu.params.kind); const auto &input_shape = is_model ? uu.model->input(input_name).get_shape() : uu.compiled_model.input(input_name).get_shape(); - if (!isImage(matdesc, input_shape)) { + + if (!isImage(mm, input_shape)) { util::throw_error(std::runtime_error( "OV Backend: InferROI supports only image as the 1th argument")); } @@ -1111,8 +1211,7 @@ struct InferROI: public cv::detail::KernelTag { auto input_tensor = infer_request.get_tensor(input_name); const auto &shape = input_tensor.get_shape(); const auto &roi = ctx->inArg(0).rref(); - const auto roi_mat = preprocess(ctx->inMat(1), roi, shape); - copyToOV(roi_mat, input_tensor); + preprocess_and_copy(ctx, 1, roi, shape, input_tensor); }, std::bind(PostOutputs, _1, _2, ctx) } @@ -1147,11 +1246,11 @@ struct InferList: public cv::detail::KernelTag { size_t idx = 1u; for (auto &&input_name : uu.params.input_names) { const auto &mm = in_metas[idx++]; - GAPI_Assert(cv::util::holds_alternative(mm)); - const auto &matdesc = cv::util::get(mm); + GAPI_Assert(cv::util::holds_alternative(mm) || + cv::util::holds_alternative(mm)); const auto &input_shape = uu.model->input(input_name).get_shape(); - if (!isImage(matdesc, input_shape)) { + if (!isImage(mm, input_shape)) { util::throw_error(std::runtime_error( "OV Backend: Only image is supported" " as the " + std::to_string(idx) + "th argument for InferList")); @@ -1208,8 +1307,7 @@ struct InferList: public cv::detail::KernelTag { const auto &input_name = ctx->uu.params.input_names[0]; auto input_tensor = infer_request.get_tensor(input_name); const auto &shape = input_tensor.get_shape(); - const auto roi_mat = preprocess(ctx->inMat(1), rc, shape); - copyToOV(roi_mat, input_tensor); + preprocess_and_copy(ctx, 1, rc, shape, input_tensor); }, std::bind(callback, std::placeholders::_1, std::placeholders::_2, pos) } @@ -1247,12 +1345,18 @@ struct InferList2: public cv::detail::KernelTag { const auto &input_name_0 = uu.params.input_names.front(); const auto &mm_0 = in_metas[0u]; - const auto &matdesc = cv::util::get(mm_0); + + if (!(cv::util::holds_alternative(mm_0) || + cv::util::holds_alternative(mm_0))) { + util::throw_error(std::runtime_error( + "OV Backend: Unsupported input meta" + " for 0th argument in OV backend")); + } const bool is_model = cv::util::holds_alternative(uu.params.kind); const auto &input_shape = is_model ? uu.model->input(input_name_0).get_shape() : uu.compiled_model.input(input_name_0).get_shape(); - if (!isImage(matdesc, input_shape)) { + if (!isImage(mm_0, input_shape)) { util::throw_error(std::runtime_error( "OV Backend: InferList2 supports only image as the 0th argument")); } diff --git a/modules/gapi/test/infer/gapi_infer_ov_tests.cpp b/modules/gapi/test/infer/gapi_infer_ov_tests.cpp index 8a15d5e741ee..49652db387f7 100644 --- a/modules/gapi/test/infer/gapi_infer_ov_tests.cpp +++ b/modules/gapi/test/infer/gapi_infer_ov_tests.cpp @@ -319,8 +319,174 @@ struct TestAgeGenderListOV : public BaseAgeGenderOV { } }; +class TestMediaBGR final: public cv::MediaFrame::IAdapter { + cv::Mat m_mat; + using Cb = cv::MediaFrame::View::Callback; + Cb m_cb; + +public: + explicit TestMediaBGR(cv::Mat m, Cb cb = [](){}) + : m_mat(m), m_cb(cb) { + } + cv::GFrameDesc meta() const override { + return cv::GFrameDesc{cv::MediaFormat::BGR, cv::Size(m_mat.cols, m_mat.rows)}; + } + cv::MediaFrame::View access(cv::MediaFrame::Access) override { + cv::MediaFrame::View::Ptrs pp = { m_mat.ptr(), nullptr, nullptr, nullptr }; + cv::MediaFrame::View::Strides ss = { m_mat.step, 0u, 0u, 0u }; + return cv::MediaFrame::View(std::move(pp), std::move(ss), Cb{m_cb}); + } +}; + +struct MediaFrameTestAgeGenderOV: public ::testing::Test { + MediaFrameTestAgeGenderOV() { + initDLDTDataPath(); + xml_path = findDataFile(SUBDIR + "age-gender-recognition-retail-0013.xml", false); + bin_path = findDataFile(SUBDIR + "age-gender-recognition-retail-0013.bin", false); + device = "CPU"; + blob_path = "age-gender-recognition-retail-0013.blob"; + + cv::Size sz{62, 62}; + m_in_mat = cv::Mat(sz, CV_8UC3); + cv::resize(m_in_mat, m_in_mat, sz); + + m_in_y = cv::Mat{sz, CV_8UC1}; + cv::randu(m_in_y, 0, 255); + m_in_uv = cv::Mat{sz / 2, CV_8UC2}; + cv::randu(m_in_uv, 0, 255); + } + + cv::Mat m_in_y; + cv::Mat m_in_uv; + + cv::Mat m_in_mat; + + cv::Mat m_out_ov_age; + cv::Mat m_out_ov_gender; + + cv::Mat m_out_gapi_age; + cv::Mat m_out_gapi_gender; + + std::string xml_path; + std::string bin_path; + std::string blob_path; + std::string device; + std::string image_path; + + using AGInfo = std::tuple; + G_API_NET(AgeGender, , "typed-age-gender"); + + void validate() { + normAssert(m_out_ov_age, m_out_gapi_age, "0: Test age output"); + normAssert(m_out_ov_gender, m_out_gapi_gender, "0: Test gender output"); + } +}; // MediaFrameTestAgeGenderOV + } // anonymous namespace +TEST_F(MediaFrameTestAgeGenderOV, InferMediaInputBGR) +{ + // OpenVINO + AGNetOVComp ref(xml_path, bin_path, device); + ref.cfgPrePostProcessing([](ov::preprocess::PrePostProcessor &ppp) { + ppp.input().tensor().set_element_type(ov::element::u8); + ppp.input().tensor().set_layout("NHWC"); + }); + ref.compile()(m_in_mat, m_out_ov_age, m_out_ov_gender); + + // G-API + cv::GFrame in; + cv::GMat age, gender; + std::tie(age, gender) = cv::gapi::infer(in); + cv::GComputation comp{cv::GIn(in), cv::GOut(age, gender)}; + + auto frame = MediaFrame::Create(m_in_mat); + auto pp = cv::gapi::ov::Params { + xml_path, bin_path, device + }.cfgOutputLayers({ "age_conv3", "prob" }); + + comp.apply(cv::gin(frame), + cv::gout(m_out_gapi_age, m_out_gapi_gender), + cv::compile_args(cv::gapi::networks(pp))); + + validate(); +} + +TEST_F(MediaFrameTestAgeGenderOV, InferROIGenericMediaInputBGR) { + // OpenVINO + cv::Rect roi(cv::Rect(cv::Point{20, 25}, cv::Size{16, 16})); + auto frame = MediaFrame::Create(m_in_mat); + static constexpr const char* tag = "age-gender-generic"; + + // OpenVINO + AGNetOVComp ref(xml_path, bin_path, device); + ref.cfgPrePostProcessing([](ov::preprocess::PrePostProcessor &ppp) { + ppp.input().tensor().set_element_type(ov::element::u8); + ppp.input().tensor().set_layout("NHWC"); + }); + ref.compile()(m_in_mat, roi, m_out_ov_age, m_out_ov_gender); + + // G-API + cv::GFrame in; + cv::GOpaque rr; + GInferInputs inputs; + inputs["data"] = in; + auto outputs = cv::gapi::infer(tag, rr, inputs); + auto age = outputs.at("age_conv3"); + auto gender = outputs.at("prob"); + cv::GComputation comp{cv::GIn(in, rr), cv::GOut(age, gender)}; + + auto pp = AGNetROIGenComp::params(xml_path, bin_path, device); + + comp.apply(cv::gin(frame, roi), cv::gout(m_out_gapi_age, m_out_gapi_gender), + cv::compile_args(cv::gapi::networks(pp))); + + validate(); +} + +class TestMediaNV12 final: public cv::MediaFrame::IAdapter { + cv::Mat m_y; + cv::Mat m_uv; + +public: + TestMediaNV12(cv::Mat y, cv::Mat uv) : m_y(y), m_uv(uv) { + } + cv::GFrameDesc meta() const override { + return cv::GFrameDesc{cv::MediaFormat::NV12, cv::Size(m_y.cols, m_y.rows)}; + } + cv::MediaFrame::View access(cv::MediaFrame::Access) override { + cv::MediaFrame::View::Ptrs pp = { + m_y.ptr(), m_uv.ptr(), nullptr, nullptr + }; + cv::MediaFrame::View::Strides ss = { + m_y.step, m_uv.step, 0u, 0u + }; + return cv::MediaFrame::View(std::move(pp), std::move(ss)); + } +}; + +TEST_F(MediaFrameTestAgeGenderOV, TestMediaNV12AgeGenderOV) +{ + cv::GFrame in; + cv::GOpaque rr; + GInferInputs inputs; + inputs["data"] = in; + static constexpr const char* tag = "age-gender-generic"; + auto outputs = cv::gapi::infer(tag, rr, inputs); + auto age = outputs.at("age_conv3"); + auto gender = outputs.at("prob"); + cv::GComputation comp{cv::GIn(in, rr), cv::GOut(age, gender)}; + + auto frame = MediaFrame::Create(m_in_y, m_in_uv); + auto pp = AGNetROIGenComp::params(xml_path, bin_path, device); + + cv::Rect roi(cv::Rect(cv::Point{20, 25}, cv::Size{16, 16})); + + EXPECT_NO_THROW(comp.apply(cv::gin(frame, roi), + cv::gout(m_out_gapi_age, m_out_gapi_gender), + cv::compile_args(cv::gapi::networks(pp)))); +} + // TODO: Make all of tests below parmetrized to avoid code duplication TEST_F(TestAgeGenderOV, Infer_Tensor) { const auto in_mat = getRandomTensor({1, 3, 62, 62}, CV_32F); From 7bad12c33ba1dbd4fcd02998a58cb6b5e7edffc3 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Wed, 24 Apr 2024 17:24:00 +0300 Subject: [PATCH 009/119] Fixed build warnings introduced in #24938 --- modules/gapi/src/backends/ov/govbackend.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/gapi/src/backends/ov/govbackend.cpp b/modules/gapi/src/backends/ov/govbackend.cpp index 6b261440999e..dde4da2bb768 100644 --- a/modules/gapi/src/backends/ov/govbackend.cpp +++ b/modules/gapi/src/backends/ov/govbackend.cpp @@ -151,7 +151,7 @@ static void copyFromOV(const ov::Tensor &tensor, cv::Mat &mat) { } } -cv::Mat wrapOV(const cv::MediaFrame::View& view, +static cv::Mat wrapOV(const cv::MediaFrame::View& view, const cv::GFrameDesc& desc) { cv::Mat out; switch (desc.fmt) { @@ -782,10 +782,10 @@ static cv::Mat preprocess(const cv::Mat &in_mat, // NB: This function is used to preprocess input image // for InferROI, InferList, InferList2 kernels. -cv::Mat preprocess(MediaFrame::View& view, - const cv::GFrameDesc& desc, - const cv::Rect& roi, - const ::ov::Shape &model_shape) { +static cv::Mat preprocess(MediaFrame::View& view, + const cv::GFrameDesc& desc, + const cv::Rect& roi, + const ::ov::Shape &model_shape) { return preprocess(wrapOV(view, desc), roi, model_shape); } @@ -805,6 +805,7 @@ static void preprocess_and_copy(std::shared_ptr ctx, auto view = cv::MediaFrame::View(currentFrame.access(cv::MediaFrame::Access::R)); auto roi_mat = preprocess(view, currentFrame.desc(), roi, model_shape); copyToOV(roi_mat, tensor); + break; } default: GAPI_Assert("Unsupported input shape for OV backend"); From 2225b257cfd41a957a2fcfea6f757b09c1d67d11 Mon Sep 17 00:00:00 2001 From: inkredibl Date: Thu, 25 Apr 2024 11:05:16 +0300 Subject: [PATCH 010/119] Merge pull request #25488 from inkredibl:doc-fix-findEssentialMat Fix documentation for findEssentialMat to reflect how it actually works. #25488 Documentation for findEssentialMat() incorrectly states that the method uses the same cameraMatrix for both lists of points even though there are two cameraMatrix and distCoeffs. Checked the code and it does the right thing i.e. uses cameraMatrix1, distCoeffs1 for points1 and cameraMatrix2, distCoeffs2 for points2. Updated the documentation for the method to clarify what it does. The code itself is not changed. --- modules/calib3d/include/opencv2/calib3d.hpp | 30 +++++++-------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index 61e3aca8103a..fd35b7d5f360 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -2492,13 +2492,13 @@ CV_EXPORTS_W Mat findFundamentalMat( InputArray points1, InputArray points2, @param points1 Array of N (N \>= 5) 2D points from the first image. The point coordinates should be floating-point (single or double precision). -@param points2 Array of the second image points of the same size and format as points1 . +@param points2 Array of the second image points of the same size and format as points1. @param cameraMatrix Camera intrinsic matrix \f$\cameramatrix{A}\f$ . Note that this function assumes that points1 and points2 are feature points from cameras with the -same camera intrinsic matrix. If this assumption does not hold for your use case, use -#undistortPoints with `P = cv::NoArray()` for both cameras to transform image points -to normalized image coordinates, which are valid for the identity camera intrinsic matrix. When -passing these coordinates, pass the identity matrix for this parameter. +same camera intrinsic matrix. If this assumption does not hold for your use case, use another +function overload or #undistortPoints with `P = cv::NoArray()` for both cameras to transform image +points to normalized image coordinates, which are valid for the identity camera intrinsic matrix. +When passing these coordinates, pass the identity matrix for this parameter. @param method Method for computing an essential matrix. - @ref RANSAC for the RANSAC algorithm. - @ref LMEDS for the LMedS algorithm. @@ -2590,23 +2590,13 @@ Mat findEssentialMat( @param points1 Array of N (N \>= 5) 2D points from the first image. The point coordinates should be floating-point (single or double precision). -@param points2 Array of the second image points of the same size and format as points1 . -@param cameraMatrix1 Camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ . -Note that this function assumes that points1 and points2 are feature points from cameras with the -same camera matrix. If this assumption does not hold for your use case, use -#undistortPoints with `P = cv::NoArray()` for both cameras to transform image points -to normalized image coordinates, which are valid for the identity camera matrix. When -passing these coordinates, pass the identity matrix for this parameter. -@param cameraMatrix2 Camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ . -Note that this function assumes that points1 and points2 are feature points from cameras with the -same camera matrix. If this assumption does not hold for your use case, use -#undistortPoints with `P = cv::NoArray()` for both cameras to transform image points -to normalized image coordinates, which are valid for the identity camera matrix. When -passing these coordinates, pass the identity matrix for this parameter. -@param distCoeffs1 Input vector of distortion coefficients +@param points2 Array of the second image points of the same size and format as points1. +@param cameraMatrix1 Camera matrix for the first camera \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ . +@param cameraMatrix2 Camera matrix for the second camera \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ . +@param distCoeffs1 Input vector of distortion coefficients for the first camera \f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6[, s_1, s_2, s_3, s_4[, \tau_x, \tau_y]]]])\f$ of 4, 5, 8, 12 or 14 elements. If the vector is NULL/empty, the zero distortion coefficients are assumed. -@param distCoeffs2 Input vector of distortion coefficients +@param distCoeffs2 Input vector of distortion coefficients for the second camera \f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6[, s_1, s_2, s_3, s_4[, \tau_x, \tau_y]]]])\f$ of 4, 5, 8, 12 or 14 elements. If the vector is NULL/empty, the zero distortion coefficients are assumed. @param method Method for computing an essential matrix. From d0978cea3909dce1eb4e72aa069e8a8d745c04e5 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Thu, 25 Apr 2024 16:42:48 +0300 Subject: [PATCH 011/119] Added moments interface to HAL. --- modules/imgproc/src/hal_replacement.hpp | 32 ++++++++++++++++++++++ modules/imgproc/src/moments.cpp | 35 +++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index 8882106c821b..ca25fbb47da5 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -1028,6 +1028,38 @@ inline int hal_ni_canny(const uchar* src_data, size_t src_step, uchar* dst_data, #define cv_hal_canny hal_ni_canny //! @endcond +/** + @brief Calculates all of the moments up to the third order of a polygon or rasterized shape for image + @param src_data Source image data + @param src_step Source image step + @param src_type source pints type + @param width Source image width + @param height Source image height + @param binary If it is true, all non-zero image pixels are treated as 1's + @param m Output array of moments (10 values) in the following order: + m00, m10, m01, m20, m11, m02, m30, m21, m12, m03. + @sa moments +*/ +inline int hal_ni_imageMoments(const uchar* src_data, size_t src_step, int src_type, int width, int height, bool binary, double m[10]) +{ return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +/** + @brief Calculates all of the moments up to the third order of a polygon of 2d points + @param src_data Source points (Point 2x32f or 2x32s) + @param src_size Source points count + @param src_type source pints type + @param m Output array of moments (10 values) in the following order: + m00, m10, m01, m20, m11, m02, m30, m21, m12, m03. + @sa moments +*/ +inline int hal_ni_polygonMoments(const uchar* src_data, size_t src_size, int src_type, double m[10]) +{ return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +//! @cond IGNORED +#define cv_hal_imageMoments hal_ni_imageMoments +#define cv_hal_polygonMoments hal_ni_polygonMoments +//! @endcond + //! @} #if defined(__clang__) diff --git a/modules/imgproc/src/moments.cpp b/modules/imgproc/src/moments.cpp index b2320258b160..e89137053cb1 100644 --- a/modules/imgproc/src/moments.cpp +++ b/modules/imgproc/src/moments.cpp @@ -561,6 +561,37 @@ static bool ipp_moments(Mat &src, Moments &m ) } +namespace cv { namespace hal { + +static int moments(const cv::Mat& src, bool binary, cv::Moments& m) +{ + CV_INSTRUMENT_REGION(); + + double m_data[10]; + int status = 0; + int type = src.type(); + int depth = CV_MAT_DEPTH(type); + + if( src.checkVector(2) >= 0 && (depth == CV_32F || depth == CV_32S)) + status = hal_ni_polygonMoments(src.data, src.total()/2, src.type(), m_data); + else + status = hal_ni_imageMoments(src.data, src.step, src.type(), src.cols, src.rows, binary, m_data); + + if (status == CV_HAL_ERROR_OK) + { + m = cv::Moments(m_data[0], m_data[1], m_data[2], m_data[3], m_data[4], + m_data[5], m_data[6], m_data[7], m_data[8], m_data[9]); + } + else if (status != CV_HAL_ERROR_NOT_IMPLEMENTED) + { + CV_Error_(cv::Error::StsInternal, + ("HAL implementation moments ==> " CVAUX_STR(cv_hal_imageMoments) " returned %d (0x%08x)", status, status)); + } + + return status; +} +}} + cv::Moments cv::moments( InputArray _src, bool binary ) { CV_INSTRUMENT_REGION(); @@ -580,6 +611,10 @@ cv::Moments cv::moments( InputArray _src, bool binary ) #endif Mat mat = _src.getMat(); + + if (hal::moments(mat, binary, m) == CV_HAL_ERROR_OK) + return m; + if( mat.checkVector(2) >= 0 && (depth == CV_32F || depth == CV_32S)) return contourMoments(mat); From 8f7e55a60b40a7f4c0ffcae677d2073a22765e71 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Fri, 26 Apr 2024 10:43:03 +0200 Subject: [PATCH 012/119] Replace static numpy allocator by function containing static. That enables the numpy code to be its own library, in case some users want to (e.g. CLIF library). --- modules/core/misc/python/pyopencv_umat.hpp | 2 +- modules/python/src2/cv2_convert.cpp | 10 +++++----- modules/python/src2/cv2_numpy.cpp | 2 -- modules/python/src2/cv2_numpy.hpp | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/modules/core/misc/python/pyopencv_umat.hpp b/modules/core/misc/python/pyopencv_umat.hpp index 63f002503b93..2e91cd5c6593 100644 --- a/modules/core/misc/python/pyopencv_umat.hpp +++ b/modules/core/misc/python/pyopencv_umat.hpp @@ -28,7 +28,7 @@ static void* cv_UMat_context() static Mat cv_UMat_get(const UMat* _self) { Mat m; - m.allocator = &g_numpyAllocator; + m.allocator = &GetNumpyAllocator(); _self->copyTo(m); return m; } diff --git a/modules/python/src2/cv2_convert.cpp b/modules/python/src2/cv2_convert.cpp index 113bff09a895..35766b47c916 100644 --- a/modules/python/src2/cv2_convert.cpp +++ b/modules/python/src2/cv2_convert.cpp @@ -56,7 +56,7 @@ bool pyopencv_to(PyObject* o, Mat& m, const ArgInfo& info) if(!o || o == Py_None) { if( !m.data ) - m.allocator = &g_numpyAllocator; + m.allocator = &GetNumpyAllocator(); return true; } @@ -298,14 +298,14 @@ bool pyopencv_to(PyObject* o, Mat& m, const ArgInfo& info) #endif m = Mat(ndims, size, type, PyArray_DATA(oarr), step); - m.u = g_numpyAllocator.allocate(o, ndims, size, type, step); + m.u = GetNumpyAllocator().allocate(o, ndims, size, type, step); m.addref(); if( !needcopy ) { Py_INCREF(o); } - m.allocator = &g_numpyAllocator; + m.allocator = &GetNumpyAllocator(); return true; } @@ -316,9 +316,9 @@ PyObject* pyopencv_from(const cv::Mat& m) if( !m.data ) Py_RETURN_NONE; cv::Mat temp, *p = (cv::Mat*)&m; - if(!p->u || p->allocator != &g_numpyAllocator) + if(!p->u || p->allocator != &GetNumpyAllocator()) { - temp.allocator = &g_numpyAllocator; + temp.allocator = &GetNumpyAllocator(); ERRWRAP2(m.copyTo(temp)); p = &temp; } diff --git a/modules/python/src2/cv2_numpy.cpp b/modules/python/src2/cv2_numpy.cpp index 63010b60269b..25922d6c6142 100644 --- a/modules/python/src2/cv2_numpy.cpp +++ b/modules/python/src2/cv2_numpy.cpp @@ -6,8 +6,6 @@ #include "cv2_numpy.hpp" #include "cv2_util.hpp" -NumpyAllocator g_numpyAllocator; - using namespace cv; UMatData* NumpyAllocator::allocate(PyObject* o, int dims, const int* sizes, int type, size_t* step) const diff --git a/modules/python/src2/cv2_numpy.hpp b/modules/python/src2/cv2_numpy.hpp index 934333921d78..b37a7a878e6c 100644 --- a/modules/python/src2/cv2_numpy.hpp +++ b/modules/python/src2/cv2_numpy.hpp @@ -18,7 +18,7 @@ class NumpyAllocator : public cv::MatAllocator const cv::MatAllocator* stdAllocator; }; -extern NumpyAllocator g_numpyAllocator; +inline NumpyAllocator& GetNumpyAllocator() {static NumpyAllocator gNumpyAllocator;return gNumpyAllocator;} //====================================================================================================================== From 357b9abaef117665bd2471c495846320aa8877cc Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Sat, 27 Apr 2024 13:33:13 +0200 Subject: [PATCH 013/119] Merge pull request #25450 from savuor:rv/svd_perf Perf tests for SVD and solve() created #25450 fixes #25336 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/core/perf/perf_math.cpp | 228 ++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) diff --git a/modules/core/perf/perf_math.cpp b/modules/core/perf/perf_math.cpp index 16d262e4c927..fe947aec1ab2 100644 --- a/modules/core/perf/perf_math.cpp +++ b/modules/core/perf/perf_math.cpp @@ -36,6 +36,234 @@ PERF_TEST_P(VectorLength, phase64f, testing::Values(128, 1000, 128*1024, 512*102 SANITY_CHECK(angle, 5e-5); } +// generates random vectors, performs Gram-Schmidt orthogonalization on them +Mat randomOrtho(int rows, int ftype, RNG& rng) +{ + Mat result(rows, rows, ftype); + rng.fill(result, RNG::UNIFORM, cv::Scalar(-1), cv::Scalar(1)); + + for (int i = 0; i < rows; i++) + { + Mat v = result.row(i); + + for (int j = 0; j < i; j++) + { + Mat p = result.row(j); + v -= p.dot(v) * p; + } + + v = v * (1. / cv::norm(v)); + } + + return result; +} + +template +Mat buildRandomMat(int rows, int cols, RNG& rng, int rank, bool symmetrical) +{ + int mtype = cv::traits::Depth::value; + Mat u = randomOrtho(rows, mtype, rng); + Mat v = randomOrtho(cols, mtype, rng); + Mat s(rows, cols, mtype, Scalar(0)); + + std::vector singVals(rank); + rng.fill(singVals, RNG::UNIFORM, Scalar(0), Scalar(10)); + std::sort(singVals.begin(), singVals.end()); + auto singIter = singVals.rbegin(); + for (int i = 0; i < rank; i++) + { + s.at(i, i) = *singIter++; + } + + if (symmetrical) + return u * s * u.t(); + else + return u * s * v.t(); +} + +Mat buildRandomMat(int rows, int cols, int mtype, RNG& rng, int rank, bool symmetrical) +{ + if (mtype == CV_32F) + { + return buildRandomMat(rows, cols, rng, rank, symmetrical); + } + else if (mtype == CV_64F) + { + return buildRandomMat(rows, cols, rng, rank, symmetrical); + } + else + { + CV_Error(cv::Error::StsBadArg, "This type is not supported"); + } +} + +CV_ENUM(SolveDecompEnum, DECOMP_LU, DECOMP_SVD, DECOMP_EIG, DECOMP_CHOLESKY, DECOMP_QR) + +enum RankMatrixOptions +{ + RANK_HALF, RANK_MINUS_1, RANK_FULL +}; + +CV_ENUM(RankEnum, RANK_HALF, RANK_MINUS_1, RANK_FULL) + +enum SolutionsOptions +{ + NO_SOLUTIONS, ONE_SOLUTION, MANY_SOLUTIONS +}; + +CV_ENUM(SolutionsEnum, NO_SOLUTIONS, ONE_SOLUTION, MANY_SOLUTIONS) + +typedef perf::TestBaseWithParam> SolveTest; + +PERF_TEST_P(SolveTest, randomMat, ::testing::Combine( + ::testing::Values(31, 64, 100), + ::testing::Values(RANK_HALF, RANK_MINUS_1, RANK_FULL), + ::testing::Values(CV_32F, CV_64F), + ::testing::Values(DECOMP_LU, DECOMP_SVD, DECOMP_EIG, DECOMP_CHOLESKY, DECOMP_QR), + ::testing::Bool(), // normal + ::testing::Values(NO_SOLUTIONS, ONE_SOLUTION, MANY_SOLUTIONS) + )) +{ + auto t = GetParam(); + int size = std::get<0>(t); + auto rankEnum = std::get<1>(t); + int mtype = std::get<2>(t); + int method = std::get<3>(t); + bool normal = std::get<4>(t); + auto solutions = std::get<5>(t); + + bool symmetrical = (method == DECOMP_CHOLESKY || method == DECOMP_LU); + + if (normal) + { + method |= DECOMP_NORMAL; + } + + int rank = size; + switch (rankEnum) + { + case RANK_HALF: rank /= 2; break; + case RANK_MINUS_1: rank -= 1; break; + default: break; + } + + RNG& rng = theRNG(); + Mat A = buildRandomMat(size, size, mtype, rng, rank, symmetrical); + Mat x(size, 1, mtype); + Mat b(size, 1, mtype); + + switch (solutions) + { + // no solutions, let's make b random + case NO_SOLUTIONS: + { + rng.fill(b, RNG::UNIFORM, Scalar(-1), Scalar(1)); + } + break; + // exactly 1 solution, let's combine b from A and x + case ONE_SOLUTION: + { + rng.fill(x, RNG::UNIFORM, Scalar(-10), Scalar(10)); + b = A * x; + } + break; + // infinitely many solutions, let's make b zero + default: + { + b = 0; + } + break; + } + + TEST_CYCLE() cv::solve(A, b, x, method); + + SANITY_CHECK_NOTHING(); +} + +typedef perf::TestBaseWithParam, RankEnum, MatDepth, bool, bool>> SvdTest; + +PERF_TEST_P(SvdTest, decompose, ::testing::Combine( + ::testing::Values(std::make_tuple(5, 15), std::make_tuple(32, 32), std::make_tuple(100, 100)), + ::testing::Values(RANK_HALF, RANK_MINUS_1, RANK_FULL), + ::testing::Values(CV_32F, CV_64F), + ::testing::Bool(), // symmetrical + ::testing::Bool() // needUV + )) +{ + auto t = GetParam(); + auto rc = std::get<0>(t); + auto rankEnum = std::get<1>(t); + int mtype = std::get<2>(t); + bool symmetrical = std::get<3>(t); + bool needUV = std::get<4>(t); + + int rows = std::get<0>(rc); + int cols = std::get<1>(rc); + + if (symmetrical) + { + rows = max(rows, cols); + cols = rows; + } + + int rank = std::min(rows, cols); + switch (rankEnum) + { + case RANK_HALF: rank /= 2; break; + case RANK_MINUS_1: rank -= 1; break; + default: break; + } + + int flags = needUV ? 0 : SVD::NO_UV; + + RNG& rng = theRNG(); + Mat A = buildRandomMat(rows, cols, mtype, rng, rank, symmetrical); + TEST_CYCLE() cv::SVD svd(A, flags); + + SANITY_CHECK_NOTHING(); +} + + +PERF_TEST_P(SvdTest, backSubst, ::testing::Combine( + ::testing::Values(std::make_tuple(5, 15), std::make_tuple(32, 32), std::make_tuple(100, 100)), + ::testing::Values(RANK_HALF, RANK_MINUS_1, RANK_FULL), + ::testing::Values(CV_32F, CV_64F), + // back substitution works the same regardless of source matrix properties + ::testing::Values(true), + // back substitution has no sense without u and v + ::testing::Values(true) // needUV + )) +{ + auto t = GetParam(); + auto rc = std::get<0>(t); + auto rankEnum = std::get<1>(t); + int mtype = std::get<2>(t); + + int rows = std::get<0>(rc); + int cols = std::get<1>(rc); + + int rank = std::min(rows, cols); + switch (rankEnum) + { + case RANK_HALF: rank /= 2; break; + case RANK_MINUS_1: rank -= 1; break; + default: break; + } + + RNG& rng = theRNG(); + Mat A = buildRandomMat(rows, cols, mtype, rng, rank, /* symmetrical */ false); + cv::SVD svd(A); + // preallocate to not spend time on it during backSubst() + Mat dst(cols, 1, mtype); + Mat rhs(rows, 1, mtype); + rng.fill(rhs, RNG::UNIFORM, Scalar(-10), Scalar(10)); + + TEST_CYCLE() svd.backSubst(rhs, dst); + + SANITY_CHECK_NOTHING(); +} + + typedef perf::TestBaseWithParam< testing::tuple > KMeans; PERF_TEST_P_(KMeans, single_iter) From 12e2cc9502bc51bb01ed3fdd2f39ce1533c8236e Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Sat, 27 Apr 2024 13:38:44 +0200 Subject: [PATCH 014/119] Merge pull request #25491 from savuor:rv/hal_norm_hamming HAL for Hamming norm added #25491 fixes #25474 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/core/src/hal_replacement.hpp | 30 ++++++++++++++++++++++++++++ modules/core/src/norm.cpp | 6 ++++++ 2 files changed, 36 insertions(+) diff --git a/modules/core/src/hal_replacement.hpp b/modules/core/src/hal_replacement.hpp index 046b0678a41c..15149453c794 100644 --- a/modules/core/src/hal_replacement.hpp +++ b/modules/core/src/hal_replacement.hpp @@ -214,6 +214,36 @@ inline int hal_ni_not8u(const uchar *src_data, size_t src_step, uchar *dst_data, #define cv_hal_not8u hal_ni_not8u //! @endcond +/** +Hamming norm of a vector +@param a pointer to vector data +@param n length of a vector +@param cellSize how many bits of the vector will be added and treated as a single bit, can be 1 (standard Hamming distance), 2 or 4 +@param result pointer to result output +*/ +//! @addtogroup core_hal_interface_hamming Hamming distance +//! @{ +inline int hal_ni_normHamming8u(const uchar* a, int n, int cellSize, int* result) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +//! @} + +/** +Hamming distance between two vectors +@param a pointer to first vector data +@param b pointer to second vector data +@param n length of vectors +@param cellSize how many bits of the vectors will be added and treated as a single bit, can be 1 (standard Hamming distance), 2 or 4 +@param result pointer to result output +*/ +//! @addtogroup core_hal_interface_hamming Hamming distance +//! @{ +inline int hal_ni_normHammingDiff8u(const uchar* a, const uchar* b, int n, int cellSize, int* result) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +//! @} + +//! @cond IGNORED +#define cv_hal_normHamming8u hal_ni_normHamming8u +#define cv_hal_normHammingDiff8u hal_ni_normHammingDiff8u +//! @endcond + /** Compare: _dst[i] = src1[i] op src2[i]_ @param src1_data first source image data diff --git a/modules/core/src/norm.cpp b/modules/core/src/norm.cpp index 49d781fcb0e6..f2f84c35b84e 100644 --- a/modules/core/src/norm.cpp +++ b/modules/core/src/norm.cpp @@ -52,6 +52,9 @@ static const uchar popCountTable4[] = int normHamming(const uchar* a, int n, int cellSize) { + int output; + CALL_HAL_RET(normHamming8u, cv_hal_normHamming8u, output, a, n, cellSize); + if( cellSize == 1 ) return normHamming(a, n); const uchar* tab = 0; @@ -98,6 +101,9 @@ int normHamming(const uchar* a, int n, int cellSize) int normHamming(const uchar* a, const uchar* b, int n, int cellSize) { + int output; + CALL_HAL_RET(normHammingDiff8u, cv_hal_normHammingDiff8u, output, a, b, n, cellSize); + if( cellSize == 1 ) return normHamming(a, b, n); const uchar* tab = 0; From 6682270b4c6c6182ad84c356ea00753221a636d1 Mon Sep 17 00:00:00 2001 From: Kumataro Date: Sun, 28 Apr 2024 18:39:19 +0900 Subject: [PATCH 015/119] highgui: wayland: reduce cpu usage for cv::waitKey() --- modules/highgui/src/window_wayland.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/highgui/src/window_wayland.cpp b/modules/highgui/src/window_wayland.cpp index 61a2f0e17a8b..01e3f5dd7832 100644 --- a/modules/highgui/src/window_wayland.cpp +++ b/modules/highgui/src/window_wayland.cpp @@ -2425,11 +2425,16 @@ void setWindowTitle_WAYLAND(const cv::String &winname, const cv::String &title) CV_IMPL int cvWaitKey(int delay) { int key = -1; - auto limit = ch::duration_cast(ch::milliseconds(delay)); + auto limit = ch::duration_cast(ch::milliseconds(delay)).count(); auto start_time = ch::duration_cast( ch::steady_clock::now().time_since_epoch()) .count(); + // See https://github.com/opencv/opencv/issues/25501 + // Too long sleep_for() makes no response to Wayland ping-pong mechanism + // So interval is limited to 33ms (1000ms / 30fps). + auto sleep_time_min = ch::duration_cast(ch::milliseconds(33)).count(); + while (true) { auto res = CvWlCore::getInstance().display().run_once(); @@ -2448,11 +2453,11 @@ CV_IMPL int cvWaitKey(int delay) { .count(); auto elapsed = end_time - start_time; - if (limit.count() > 0 && elapsed >= limit.count()) { + if (limit > 0 && elapsed >= limit) { break; } - auto sleep_time = 64000 - elapsed; + auto sleep_time = std::min(limit - elapsed, sleep_time_min); if (sleep_time > 0) { std::this_thread::sleep_for(ch::nanoseconds(sleep_time)); } From b1e01970ef07c90d407b5c6147c16aeb3d39c7d7 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Mon, 29 Apr 2024 14:35:14 +0300 Subject: [PATCH 016/119] Merge pull request #25308 from dkurt:not_normalized_findHomography Not-normalized output from findHomography #25308 ### Pull Request Readiness Checklist resolves https://github.com/opencv/opencv/issues/25133 resolves https://github.com/opencv/opencv/issues/4834 resolves https://github.com/opencv/opencv/issues/22166 resolves https://github.com/opencv/opencv/issues/18592 See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/calib3d/include/opencv2/calib3d.hpp | 4 +-- modules/calib3d/src/fundam.cpp | 31 ++++++++++----------- modules/calib3d/test/test_homography.cpp | 23 +++++++++++++++ 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index fd35b7d5f360..aadfff7b1cd2 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -726,8 +726,8 @@ correctly only when there are more than 50% of inliers. Finally, if there are no noise is rather small, use the default method (method=0). The function is used to find initial intrinsic and extrinsic matrices. Homography matrix is -determined up to a scale. Thus, it is normalized so that \f$h_{33}=1\f$. Note that whenever an \f$H\f$ matrix -cannot be estimated, an empty one will be returned. +determined up to a scale. If \f$h_{33}\f$ is non-zero, the matrix is normalized so that \f$h_{33}=1\f$. +@note Whenever an \f$H\f$ matrix cannot be estimated, an empty one will be returned. @sa getAffineTransform, estimateAffine2D, estimateAffinePartial2D, getPerspectiveTransform, warpPerspective, diff --git a/modules/calib3d/src/fundam.cpp b/modules/calib3d/src/fundam.cpp index ed48645a4df6..599250114b86 100644 --- a/modules/calib3d/src/fundam.cpp +++ b/modules/calib3d/src/fundam.cpp @@ -49,6 +49,13 @@ namespace cv { +static inline double scaleFor(double x){ + return (std::fabs(x) > std::numeric_limits::epsilon()) ? 1./x : 1.; +} +static inline float scaleFor(float x){ + return (std::fabs(x) > std::numeric_limits::epsilon()) ? 1.f/x : 1.f; +} + /** * This class estimates a homography \f$H\in \mathbb{R}^{3\times 3}\f$ * between \f$\mathbf{x} \in \mathbb{R}^3\f$ and @@ -177,8 +184,7 @@ class HomographyEstimatorCallback CV_FINAL : public PointSetRegistrator::Callbac eigen( _LtL, matW, matV ); _Htemp = _invHnorm*_H0; _H0 = _Htemp*_Hnorm2; - _H0.convertTo(_model, _H0.type(), 1./_H0.at(2,2) ); - + _H0.convertTo(_model, _H0.type(), scaleFor(_H0.at(2,2))); return 1; } @@ -197,14 +203,14 @@ class HomographyEstimatorCallback CV_FINAL : public PointSetRegistrator::Callbac const Point2f* M = m1.ptr(); const Point2f* m = m2.ptr(); const double* H = model.ptr(); - float Hf[] = { (float)H[0], (float)H[1], (float)H[2], (float)H[3], (float)H[4], (float)H[5], (float)H[6], (float)H[7] }; + float Hf[] = { (float)H[0], (float)H[1], (float)H[2], (float)H[3], (float)H[4], (float)H[5], (float)H[6], (float)H[7], (float)H[8] }; _err.create(count, 1, CV_32F); float* err = _err.getMat().ptr(); for( i = 0; i < count; i++ ) { - float ww = 1.f/(Hf[6]*M[i].x + Hf[7]*M[i].y + 1.f); + float ww = 1.f/(Hf[6]*M[i].x + Hf[7]*M[i].y + Hf[8]); float dx = (Hf[0]*M[i].x + Hf[1]*M[i].y + Hf[2])*ww - m[i].x; float dy = (Hf[3]*M[i].x + Hf[4]*M[i].y + Hf[5])*ww - m[i].y; err[i] = dx*dx + dy*dy; @@ -231,8 +237,9 @@ class HomographyRefineCallback CV_FINAL : public LMSolver::Callback if( _Jac.needed()) { _Jac.create(count*2, param.rows, CV_64F); + _Jac.setTo(0.); J = _Jac.getMat(); - CV_Assert( J.isContinuous() && J.cols == 8 ); + CV_Assert( J.isContinuous() && J.cols == 9 ); } const Point2f* M = src.ptr(); @@ -244,7 +251,7 @@ class HomographyRefineCallback CV_FINAL : public LMSolver::Callback for( i = 0; i < count; i++ ) { double Mx = M[i].x, My = M[i].y; - double ww = h[6]*Mx + h[7]*My + 1.; + double ww = h[6]*Mx + h[7]*My + h[8]; ww = fabs(ww) > DBL_EPSILON ? 1./ww : 0; double xi = (h[0]*Mx + h[1]*My + h[2])*ww; double yi = (h[3]*Mx + h[4]*My + h[5])*ww; @@ -254,9 +261,7 @@ class HomographyRefineCallback CV_FINAL : public LMSolver::Callback if( Jptr ) { Jptr[0] = Mx*ww; Jptr[1] = My*ww; Jptr[2] = ww; - Jptr[3] = Jptr[4] = Jptr[5] = 0.; Jptr[6] = -Mx*ww*xi; Jptr[7] = -My*ww*xi; - Jptr[8] = Jptr[9] = Jptr[10] = 0.; Jptr[11] = Mx*ww; Jptr[12] = My*ww; Jptr[13] = ww; Jptr[14] = -Mx*ww*yi; Jptr[15] = -My*ww*yi; @@ -419,7 +424,7 @@ cv::Mat cv::findHomography( InputArray _points1, InputArray _points2, dst = dst1; if( method == RANSAC || method == LMEDS ) cb->runKernel( src, dst, H ); - Mat H8(8, 1, CV_64F, H.ptr()); + Mat H8(9, 1, CV_64F, H.ptr()); LMSolver::create(makePtr(src, dst), 10)->run(H8); } } @@ -1002,14 +1007,6 @@ void cv::computeCorrespondEpilines( InputArray _points, int whichImage, } } -static inline double scaleFor(double x){ - return (std::fabs(x) > std::numeric_limits::epsilon()) ? 1./x : 1.; -} -static inline float scaleFor(float x){ - return (std::fabs(x) > std::numeric_limits::epsilon()) ? 1.f/x : 1.f; -} - - void cv::convertPointsFromHomogeneous( InputArray _src, OutputArray _dst ) { CV_INSTRUMENT_REGION(); diff --git a/modules/calib3d/test/test_homography.cpp b/modules/calib3d/test/test_homography.cpp index 41188a066db6..2ceb05f28af5 100644 --- a/modules/calib3d/test/test_homography.cpp +++ b/modules/calib3d/test/test_homography.cpp @@ -704,4 +704,27 @@ TEST(Calib3d_Homography, minPoints) EXPECT_THROW(findHomography(p1, p2, RANSAC, 0.01, mask), cv::Exception); } +TEST(Calib3d_Homography, not_normalized) +{ + Mat_ p1({5, 2}, {-1, -1, -2, -2, -1, 1, -2, 2, -1, 0}); + Mat_ p2({5, 2}, {0, -1, -1, -1, 0, 0, -1, 0, 0, -0.5}); + Mat_ ref({3, 3}, { + 0.74276086, 0., 0.74276086, + 0.18569022, 0.18569022, 0., + -0.37138043, 0., 0. + }); + + for (int method : std::vector({0, RANSAC, LMEDS})) + { + Mat h = findHomography(p1, p2, method); + for (auto it = h.begin(); it != h.end(); ++it) { + ASSERT_FALSE(cvIsNaN(*it)) << format("method %d\nResult:\n", method) << h; + } + if (h.at(0, 0) * ref.at(0, 0) < 0) { + h *= -1; + } + ASSERT_LE(cv::norm(h, ref, NORM_INF), 1e-8) << format("method %d\nResult:\n", method) << h; + } +} + }} // namespace From 2a2ff5525720d110c9c462cd46e0e0655c7fb0fa Mon Sep 17 00:00:00 2001 From: Kumataro Date: Tue, 30 Apr 2024 00:58:29 +0900 Subject: [PATCH 017/119] Merge pull request #25496 from Kumataro:fix25495 highgui: wayland: show "NO" status if dependency is missing #25496 Close #25495 - [doc] Add document to enable Wayland highgui-backend in ubuntu 24.04. - [build] Show "NO" status instead of version if dependency library is missing. - [build] Fix to find Wayland EGL. - [fix] Add some callback stub functions to suppress build warning. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [ ] I agree to contribute to the project under Apache 2 License. - [ ] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ ] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- CMakeLists.txt | 21 +--- .../app/highgui_wayland_ubuntu.markdown | 106 ++++++++++++++++++ doc/tutorials/app/intelperc.markdown | 1 + .../app/table_of_content_app.markdown | 1 + modules/highgui/cmake/detect_wayland.cmake | 8 +- modules/highgui/src/window_wayland.cpp | 58 +++++++++- 6 files changed, 177 insertions(+), 18 deletions(-) create mode 100644 doc/tutorials/app/highgui_wayland_ubuntu.markdown diff --git a/CMakeLists.txt b/CMakeLists.txt index 61f4ee2c154b..badb492beb79 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1366,21 +1366,12 @@ status("") status(" GUI: " "${OPENCV_HIGHGUI_BUILTIN_BACKEND}") if(WITH_WAYLAND OR HAVE_WAYLAND) - if(HAVE_WAYLAND_CLIENT) - status(" Wayland Client:" "YES (ver ${WAYLAND_CLIENT_VERSION})") - endif() - if(HAVE_WAYLAND_CURSOR) - status(" Wayland Cursor:" "YES (ver ${WAYLAND_CURSOR_VERSION})") - endif() - if(HAVE_WAYLAND_PROTOCOL) - status(" Wayland Protocol:" "YES (ver ${WAYLAND_PROTOCOL_VERSION})") - endif() - if(HAVE_WAYLAND_EGL) - status(" Wayland EGL:" "YES (ver ${WAYLAND_EGL_VERSION})") - endif() - if(HAVE_XKBCOMMON) - status(" Xkbcommon:" "YES (ver ${XKBCOMMON_VERSION})") - endif() + status(" Wayland:" HAVE_WAYLAND THEN "(Experimental) YES" ELSE "NO") + status(" Wayland Client:" HAVE_WAYLAND_CLIENT THEN "YES (ver ${WAYLAND_CLIENT_VERSION})" ELSE "NO") + status(" Wayland Cursor:" HAVE_WAYLAND_CURSOR THEN "YES (ver ${WAYLAND_CURSOR_VERSION})" ELSE "NO") + status(" Wayland Protocols:" HAVE_WAYLAND_PROTOCOLS THEN "YES (ver ${WAYLAND_PROTOCOLS_VERSION})" ELSE "NO") + status(" Xkbcommon:" HAVE_XKBCOMMON THEN "YES (ver ${XKBCOMMON_VERSION})" ELSE "NO") + status(" Wayland EGL(Option):" HAVE_WAYLAND_EGL THEN "YES (ver ${WAYLAND_EGL_VERSION})" ELSE "NO") endif() if(WITH_QT OR HAVE_QT) diff --git a/doc/tutorials/app/highgui_wayland_ubuntu.markdown b/doc/tutorials/app/highgui_wayland_ubuntu.markdown new file mode 100644 index 000000000000..2b8020ad19aa --- /dev/null +++ b/doc/tutorials/app/highgui_wayland_ubuntu.markdown @@ -0,0 +1,106 @@ +Using Wayland highgui-backend in Ubuntu {#tutorial_wayland_ubuntu} +======================================= + +@tableofcontents + +@prev_tutorial{tutorial_intelperc} + +| | | +| -: | :- | +| Original author | Kumataro | +| Compatibility | OpenCV >= 4.10 | +| ^ | Ubuntu 24.04 | + +Goal +----- +This tutorial is to use Wayland highgui-backend in Ubuntu 24.04. + +Wayland highgui-backend is experimental implementation. + +Setup +----- +- Setup Ubuntu 24.04. +- `sudo apt install build-essential git cmake` to build OpenCV. +- `sudo apt install libwayland-dev wayland-protocols libxkbcommon-dev` to enable Wayland highgui-backend. +- (Option) `sudo apt install ninja-build` (or remove `-GNinja` option for cmake command). +- (Option) `sudo apt install libwayland-egl1` to enable Wayland EGL library. + +Get OpenCV from GitHub +---------------------- + +```bash +mkdir work +cd work +git clone --depth=1 https://github.com/opencv/opencv.git +``` + +@note +`--depth=1` option is to limit downloading commits. If you want to see more commit history, please remove this option. + +Build/Install OpenCV with Wayland highgui-backend +------------------------------------------------- + +Run `cmake` with `-DWITH_WAYLAND=ON` option to configure OpenCV. + +```bash +cmake -S opencv -B build4-main -DWITH_WAYLAND=ON -GNinja +``` + +If succeeded, Wayland Client/Cursor/Protocols and Xkbcommon versions are shown. Wayland EGL is option. + +```plaintext +-- +-- GUI: Wayland +-- Wayland: (Experimental) YES +-- Wayland Client: YES (ver 1.22.0) +-- Wayland Cursor: YES (ver 1.22.0) +-- Wayland Protocols: YES (ver 1.34) +-- Xkbcommon: YES (ver 1.6.0) +-- Wayland EGL(Option): YES (ver 18.1.0) +-- GTK+: NO +-- VTK support: NO +``` + +Run `cmake --build` to build, and `sudo cmake --install` to install into your system. + +```bash +cmake --build build4-main +sudo cmake --install build4-main +sudo ldconfig +``` + +Simple Application to try Wayland highgui-backend +------------------------------------------------- +Try this code, so you can see name of currentUIFrramework() and OpenCV logo window with Wayland highgui-backend. + + +```bash +// g++ main.cpp -o a.out -I /usr/local/include/opencv4 -lopencv_core -lopencv_highgui -lopencv_imgcodecs +#include +#include +#include +#include +#include + +int main(void) +{ + std::cout << "cv::currentUIFramework() returns " << cv::currentUIFramework() << std::endl; + + cv::Mat src; + src = cv::imread("opencv-logo.png"); + + cv::namedWindow("src"); + + int key = 0; + do + { + cv::imshow("src", src ); + key = cv::waitKey(50); + } while( key != 'q' ); + return 0; +} +``` + +Limitation/Known problem +------------------------ +- cv::moveWindow() is not implementated. ( See. https://github.com/opencv/opencv/issues/25478 ) diff --git a/doc/tutorials/app/intelperc.markdown b/doc/tutorials/app/intelperc.markdown index 132074faa318..574bfc9e6a58 100644 --- a/doc/tutorials/app/intelperc.markdown +++ b/doc/tutorials/app/intelperc.markdown @@ -4,6 +4,7 @@ Using Creative Senz3D and other Intel RealSense SDK compatible depth sensors {#t @tableofcontents @prev_tutorial{tutorial_orbbec_astra} +@next_tutorial{tutorial_wayland_ubuntu} ![hardwares](images/realsense.jpg) diff --git a/doc/tutorials/app/table_of_content_app.markdown b/doc/tutorials/app/table_of_content_app.markdown index 8e05dfaf0774..6671f6b541fb 100644 --- a/doc/tutorials/app/table_of_content_app.markdown +++ b/doc/tutorials/app/table_of_content_app.markdown @@ -8,3 +8,4 @@ Application utils (highgui, imgcodecs, videoio modules) {#tutorial_table_of_cont - @subpage tutorial_kinect_openni - @subpage tutorial_orbbec_astra - @subpage tutorial_intelperc +- @subpage tutorial_wayland_ubuntu diff --git a/modules/highgui/cmake/detect_wayland.cmake b/modules/highgui/cmake/detect_wayland.cmake index 24e70d1b85b7..7fcb5bd7a997 100644 --- a/modules/highgui/cmake/detect_wayland.cmake +++ b/modules/highgui/cmake/detect_wayland.cmake @@ -9,7 +9,7 @@ macro(ocv_wayland_generate protocol_file output_file) list(APPEND WAYLAND_PROTOCOL_SOURCES ${output_file}.h ${output_file}.c) endmacro() -ocv_clear_vars(HAVE_WAYLAND_CLIENT HAVE_WAYLAND_CURSOR HAVE_XKBCOMMON HAVE_WAYLAND_PROTOCOLS) +ocv_clear_vars(HAVE_WAYLAND_CLIENT HAVE_WAYLAND_CURSOR HAVE_XKBCOMMON HAVE_WAYLAND_PROTOCOLS HAVE_WAYLAND_EGL) if(WITH_WAYLAND) ocv_check_modules(WAYLAND_CLIENT wayland-client) if(WAYLAND_CLIENT_FOUND) @@ -32,4 +32,10 @@ if(WITH_WAYLAND) if(HAVE_WAYLAND_CLIENT AND HAVE_WAYLAND_CURSOR AND HAVE_XKBCOMMON AND HAVE_WAYLAND_PROTOCOLS) set(HAVE_WAYLAND TRUE) endif() + + # WAYLAND_EGL is option + ocv_check_modules(WAYLAND_EGL wayland-egl) + if(WAYLAND_EGL_FOUND) + set(HAVE_WAYLAND_EGL ON) + endif() endif() diff --git a/modules/highgui/src/window_wayland.cpp b/modules/highgui/src/window_wayland.cpp index 61a2f0e17a8b..ca2811ffe245 100644 --- a/modules/highgui/src/window_wayland.cpp +++ b/modules/highgui/src/window_wayland.cpp @@ -231,7 +231,13 @@ class cv_wl_mouse { &handle_pointer_motion, &handle_pointer_button, &handle_pointer_axis, &handle_pointer_frame, &handle_pointer_axis_source, &handle_pointer_axis_stop, - &handle_pointer_axis_discrete + &handle_pointer_axis_discrete, +#if WL_POINTER_AXIS_VALUE120_SINCE_VERSION >= 8 + &handle_axis_value120, +#endif +#if WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION >= 9 + &handle_axis_relative_direction, +#endif }; cv_wl_window *focus_window_{}; @@ -277,6 +283,27 @@ class cv_wl_mouse { CV_UNUSED(axis); CV_UNUSED(discrete); } + +#if WL_POINTER_AXIS_VALUE120_SINCE_VERSION >= 8 + static void + handle_axis_value120(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t value120) { + CV_UNUSED(data); + CV_UNUSED(wl_pointer); + CV_UNUSED(axis); + CV_UNUSED(value120); + } +#endif + +#if WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION >= 9 + static void + handle_axis_relative_direction(void *data, struct wl_pointer *wl_pointer, uint32_t axis, uint32_t direction) { + CV_UNUSED(data); + CV_UNUSED(wl_pointer); + CV_UNUSED(axis); + CV_UNUSED(direction); + } +#endif + }; class cv_wl_keyboard { @@ -695,7 +722,13 @@ class cv_wl_window { }; struct xdg_toplevel *xdg_toplevel_; struct xdg_toplevel_listener xdgtop_listener_{ - &handle_toplevel_configure, &handle_toplevel_close + &handle_toplevel_configure, &handle_toplevel_close, +#if XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION >= 4 + &handle_toplevel_configure_bounds, +#endif +#if XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION >= 5 + &handle_toplevel_wm_capabilities, +#endif }; bool wait_for_configure_ = true; @@ -742,6 +775,27 @@ class cv_wl_window { static void handle_toplevel_close(void *data, struct xdg_toplevel *surface); +#if XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION >= 4 + static void + handle_toplevel_configure_bounds(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height) + { + CV_UNUSED(data); + CV_UNUSED(xdg_toplevel); + CV_UNUSED(width); + CV_UNUSED(height); + } +#endif + +#if XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION >= 5 + static void + handle_toplevel_wm_capabilities(void *data, struct xdg_toplevel *xdg_toplevel, struct wl_array *capabilities) + { + CV_UNUSED(data); + CV_UNUSED(xdg_toplevel); + CV_UNUSED(capabilities); + } +#endif + static void handle_frame_callback(void *data, struct wl_callback *cb, uint32_t time); }; From 716826cccd68bcadaf824e2a60fd1e8c33e12fdf Mon Sep 17 00:00:00 2001 From: Kumataro Date: Tue, 30 Apr 2024 10:01:32 +0900 Subject: [PATCH 018/119] highgui: wayland: support imshow() without pre-calling namedWindow() --- modules/highgui/src/window_wayland.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/highgui/src/window_wayland.cpp b/modules/highgui/src/window_wayland.cpp index ca2811ffe245..9ab0351eddea 100644 --- a/modules/highgui/src/window_wayland.cpp +++ b/modules/highgui/src/window_wayland.cpp @@ -2460,11 +2460,17 @@ CV_IMPL void cvSetMouseCallback(const char *window_name, CvMouseCallback on_mous } CV_IMPL void cvShowImage(const char *name, const CvArr *arr) { - auto cv_core = CvWlCore::getInstance(); - auto window = cv_core.get_window(name); + // see https://github.com/opencv/opencv/issues/25497 + /* + * To reuse the result of getInstance() repeatedly looks like better efficient implementation. + * However, it defined as static shared_ptr member variable in CvWlCore. + * If it reaches out of scope, cv_wl_core::~cv_wl_core() is called and all windows will be destroyed. + * For workaround, avoid it. + */ + auto window = CvWlCore::getInstance().get_window(name); if (!window) { - cv_core.create_window(name, cv::WINDOW_AUTOSIZE); - if (!(window = cv_core.get_window(name))) + CvWlCore::getInstance().create_window(name, cv::WINDOW_AUTOSIZE); + if (!(window = CvWlCore::getInstance().get_window(name))) CV_Error_(StsNoMem, ("Failed to create window: %s", name)); } From e3fc850ec226d61ad16a85fe4cb8b2376f62beff Mon Sep 17 00:00:00 2001 From: xndcn Date: Tue, 30 Apr 2024 16:58:51 +0800 Subject: [PATCH 019/119] Fix doc about uniform parameter for imgproc calcBackProject function It is said "see above" because calcBackProject is listed under calcHist function in source file, while it is listed before due to the lexicographic ordering. --- modules/imgproc/include/opencv2/imgproc.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index c686e37bd68d..40300cb464f7 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -3284,7 +3284,7 @@ images[0].channels() + images[1].channels()-1, and so on. size and depth as images[0] . @param ranges Array of arrays of the histogram bin boundaries in each dimension. See #calcHist . @param scale Optional scale factor for the output back projection. -@param uniform Flag indicating whether the histogram is uniform or not (see above). +@param uniform Flag indicating whether the histogram is uniform or not (see #calcHist). @sa calcHist, compareHist */ From 22de887c00664a88b7877b2611dbb9e73f05a339 Mon Sep 17 00:00:00 2001 From: zihaomu Date: Tue, 30 Apr 2024 18:07:21 +0800 Subject: [PATCH 020/119] fix statckblur big kernel case --- modules/imgproc/src/stackblur.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/stackblur.cpp b/modules/imgproc/src/stackblur.cpp index 6becbe5c4147..a69e4b41017e 100644 --- a/modules/imgproc/src/stackblur.cpp +++ b/modules/imgproc/src/stackblur.cpp @@ -547,7 +547,7 @@ class ParallelStackBlurRow : public ParallelLoopBody } else { - size_t bufSize = CN * (width + radius) * sizeof(TBuf) + 2 * CN * sizeof(TBuf); + size_t bufSize = CN * (width + kernelSize) * sizeof(TBuf) + 2 * CN * sizeof(TBuf); AutoBuffer _buf(bufSize + 16); uchar* bufptr = alignPtr(_buf.data(), 16); TBuf* diffVal = (TBuf*)bufptr; From f3f29fa62cdc18f0655aace0b75ed65bef6536bb Mon Sep 17 00:00:00 2001 From: Alexander Lyulkov Date: Thu, 2 May 2024 14:37:40 +0300 Subject: [PATCH 021/119] Added more OpenVINO layers to dnn --- modules/dnn/src/layers/cumsum_layer.cpp | 38 +++++++++++++++++++ modules/dnn/src/layers/expand_layer.cpp | 27 ++++++++++++- .../dnn/src/layers/gather_elements_layer.cpp | 24 +++++++++++- modules/dnn/src/layers/gather_layer.cpp | 18 ++++++++- modules/dnn/src/layers/scatterND_layer.cpp | 17 ++++++++- modules/dnn/src/layers/scatter_layer.cpp | 26 ++++++++++++- modules/dnn/src/layers/tile_layer.cpp | 15 +++++++- 7 files changed, 158 insertions(+), 7 deletions(-) diff --git a/modules/dnn/src/layers/cumsum_layer.cpp b/modules/dnn/src/layers/cumsum_layer.cpp index ae1c825f1904..565d09abaac1 100644 --- a/modules/dnn/src/layers/cumsum_layer.cpp +++ b/modules/dnn/src/layers/cumsum_layer.cpp @@ -3,6 +3,8 @@ // of this distribution and at http://opencv.org/license.html. #include "../precomp.hpp" +#include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" #include "layers_common.hpp" #include @@ -32,6 +34,12 @@ class CumSumLayerImpl CV_FINAL : public CumSumLayer return exclusive_raw == 0; } + virtual bool supportBackend(int backendId) CV_OVERRIDE + { + return backendId == DNN_BACKEND_OPENCV || + backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; + } + void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE { CV_TRACE_FUNCTION(); @@ -120,6 +128,36 @@ class CumSumLayerImpl CV_FINAL : public CumSumLayer } } +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + std::shared_ptr cumsum; + if (nodes.size() == 2) + { + int32_t axis_shape = 1; + auto axis_scalar = std::make_shared( + nodes[1].dynamicCast()->node, + std::make_shared(ov::element::i32, ov::Shape{}, &axis_shape), + false); + cumsum = std::make_shared( + nodes[0].dynamicCast()->node, + std::make_shared(axis_scalar, ov::element::i32), + exclusive_raw, + reverse_raw); + } + else + { + cumsum = std::make_shared( + nodes[0].dynamicCast()->node, + std::make_shared(ov::element::i32, ov::Shape{}, &axis_raw), + exclusive_raw, + reverse_raw); + } + return Ptr(new InfEngineNgraphNode(cumsum)); + } +#endif // HAVE_DNN_NGRAPH + int axis_raw; int exclusive_raw; int reverse_raw; diff --git a/modules/dnn/src/layers/expand_layer.cpp b/modules/dnn/src/layers/expand_layer.cpp index 752e741a97cd..09f2d78c4f10 100644 --- a/modules/dnn/src/layers/expand_layer.cpp +++ b/modules/dnn/src/layers/expand_layer.cpp @@ -3,6 +3,8 @@ // of this distribution and at http://opencv.org/license.html. #include "../precomp.hpp" +#include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" #include namespace cv { namespace dnn { @@ -27,8 +29,10 @@ class ExpandLayerImpl CV_FINAL : public ExpandLayer const_input_1d = params.get("const_input_1d", false); } - virtual bool supportBackend(int backendId) CV_OVERRIDE { - return backendId == DNN_BACKEND_OPENCV; + virtual bool supportBackend(int backendId) CV_OVERRIDE + { + return backendId == DNN_BACKEND_OPENCV || + backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; } virtual bool getMemoryShapes(const std::vector &inputs, @@ -137,6 +141,25 @@ class ExpandLayerImpl CV_FINAL : public ExpandLayer } } +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto input_shape = nodes[0].dynamicCast()->node.get_shape(); + CV_CheckGE(target_shape.size(), input_shape.size(), ""); + + std::vector output_shape(target_shape.begin(), target_shape.end()); + for (int i = 1; i < input_shape.size() + 1; ++i) + output_shape[output_shape.size() - i] = std::max( + (int32_t)input_shape[input_shape.size() - i], + output_shape[output_shape.size() - i]); + + auto shape_node = std::make_shared(ov::element::i32, ov::Shape{output_shape.size()}, output_shape.data()); + auto expand = std::make_shared(nodes[0].dynamicCast()->node, shape_node); + return Ptr(new InfEngineNgraphNode(expand)); + } +#endif // HAVE_DNN_NGRAPH + private: MatShape target_shape; bool const_input_1d; diff --git a/modules/dnn/src/layers/gather_elements_layer.cpp b/modules/dnn/src/layers/gather_elements_layer.cpp index da3ae939df55..de15b439a904 100644 --- a/modules/dnn/src/layers/gather_elements_layer.cpp +++ b/modules/dnn/src/layers/gather_elements_layer.cpp @@ -3,6 +3,8 @@ // of this distribution and at http://opencv.org/license.html. #include "../precomp.hpp" +#include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" #include namespace cv { namespace dnn { @@ -30,7 +32,8 @@ class GatherElementsLayerImpl CV_FINAL : public GatherElementsLayer virtual bool supportBackend(int backendId) CV_OVERRIDE { - return backendId == DNN_BACKEND_OPENCV; + return backendId == DNN_BACKEND_OPENCV || + backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; } virtual bool getMemoryShapes(const std::vector &inputs, @@ -148,6 +151,25 @@ class GatherElementsLayerImpl CV_FINAL : public GatherElementsLayer }; } +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + int32_t indicesBoundValue = nodes[0].dynamicCast()->node.get_shape()[axis]; + auto indicesBound = std::make_shared(ov::element::i32, ov::Shape{}, &indicesBoundValue); + auto indices = std::make_shared(nodes[1].dynamicCast()->node, ov::element::i32); + auto indicesNonNegative = std::make_shared( + std::make_shared(indices, indicesBound), + indicesBound); + + auto gatherElements = std::make_shared( + nodes[0].dynamicCast()->node, + indicesNonNegative, + axis); + return Ptr(new InfEngineNgraphNode(gatherElements)); + } +#endif // HAVE_DNN_NGRAPH + private: int axis; }; diff --git a/modules/dnn/src/layers/gather_layer.cpp b/modules/dnn/src/layers/gather_layer.cpp index 32b76886a3eb..7b731e6d545e 100644 --- a/modules/dnn/src/layers/gather_layer.cpp +++ b/modules/dnn/src/layers/gather_layer.cpp @@ -3,6 +3,8 @@ // of this distribution and at http://opencv.org/license.html. #include "../precomp.hpp" +#include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" #include "layers_common.hpp" @@ -20,7 +22,8 @@ class GatherLayerImpl CV_FINAL : public GatherLayer virtual bool supportBackend(int backendId) CV_OVERRIDE { - return backendId == DNN_BACKEND_OPENCV; + return backendId == DNN_BACKEND_OPENCV || + backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; } virtual bool getMemoryShapes(const std::vector &inputs, @@ -113,6 +116,19 @@ class GatherLayerImpl CV_FINAL : public GatherLayer } } +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto axisNode = std::make_shared(ov::element::i32, ov::Shape{}, &m_axis); + auto gather = std::make_shared( + nodes[0].dynamicCast()->node, + std::make_shared(nodes[1].dynamicCast()->node, ov::element::i32), + axisNode); + return Ptr(new InfEngineNgraphNode(gather)); + } +#endif // HAVE_DNN_NGRAPH + private: // The axis to gather along int m_axis; diff --git a/modules/dnn/src/layers/scatterND_layer.cpp b/modules/dnn/src/layers/scatterND_layer.cpp index 64ddcd0c4f3c..e64cbfae3e06 100644 --- a/modules/dnn/src/layers/scatterND_layer.cpp +++ b/modules/dnn/src/layers/scatterND_layer.cpp @@ -3,6 +3,8 @@ // of this distribution and at http://opencv.org/license.html. #include "../precomp.hpp" +#include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" #include "layers_common.hpp" #include // for std::max & std::min @@ -42,7 +44,8 @@ class ScatterNDLayerImpl CV_FINAL : public ScatterNDLayer virtual bool supportBackend(int backendId) CV_OVERRIDE { - return backendId == DNN_BACKEND_OPENCV; + return backendId == DNN_BACKEND_OPENCV || + (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && reduction == REDUCTION::NONE); } virtual bool getMemoryShapes(const std::vector &inputs, @@ -207,6 +210,18 @@ class ScatterNDLayerImpl CV_FINAL : public ScatterNDLayer CV_Error(Error::StsBadArg, "Unsupported reduction."); }; } + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto scatterND = std::make_shared( + nodes[0].dynamicCast()->node, + std::make_shared(nodes[1].dynamicCast()->node, ov::element::i32), + nodes[2].dynamicCast()->node); + return Ptr(new InfEngineNgraphNode(scatterND)); + } +#endif // HAVE_DNN_NGRAPH }; Ptr ScatterNDLayer::create(const LayerParams& params) diff --git a/modules/dnn/src/layers/scatter_layer.cpp b/modules/dnn/src/layers/scatter_layer.cpp index b4bcdee82e80..58d2c2daead7 100644 --- a/modules/dnn/src/layers/scatter_layer.cpp +++ b/modules/dnn/src/layers/scatter_layer.cpp @@ -3,6 +3,8 @@ // of this distribution and at http://opencv.org/license.html. #include "../precomp.hpp" +#include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" #include "layers_common.hpp" #include // for std::max & std::min @@ -43,7 +45,8 @@ class ScatterLayerImpl CV_FINAL : public ScatterLayer virtual bool supportBackend(int backendId) CV_OVERRIDE { - return backendId == DNN_BACKEND_OPENCV; + return backendId == DNN_BACKEND_OPENCV || + (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && reduction == REDUCTION::NONE); } virtual bool getMemoryShapes(const std::vector &inputs, @@ -203,6 +206,27 @@ class ScatterLayerImpl CV_FINAL : public ScatterLayer }; } +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + int32_t indicesBoundValue = nodes[0].dynamicCast()->node.get_shape()[axis]; + auto indicesBound = std::make_shared(ov::element::i32, ov::Shape{}, &indicesBoundValue); + auto indices = std::make_shared(nodes[1].dynamicCast()->node, ov::element::i32); + auto indicesNonNegative = std::make_shared( + std::make_shared(indices, indicesBound), + indicesBound); + + auto axis_node = std::make_shared(ov::element::i32, ov::Shape{}, &axis); + auto scatterElements = std::make_shared( + nodes[0].dynamicCast()->node, + indicesNonNegative, + nodes[2].dynamicCast()->node, + axis_node); + return Ptr(new InfEngineNgraphNode(scatterElements)); + } +#endif // HAVE_DNN_NGRAPH + private: // Attributes int axis; diff --git a/modules/dnn/src/layers/tile_layer.cpp b/modules/dnn/src/layers/tile_layer.cpp index abaf96bd4afb..1357b9e89e46 100644 --- a/modules/dnn/src/layers/tile_layer.cpp +++ b/modules/dnn/src/layers/tile_layer.cpp @@ -4,6 +4,8 @@ #include "../precomp.hpp" #include "layers_common.hpp" +#include "../op_inf_engine.hpp" +#include "../ie_ngraph.hpp" #include @@ -31,7 +33,8 @@ class TileLayerImpl CV_FINAL : public TileLayer virtual bool supportBackend(int backendId) CV_OVERRIDE { - return backendId == DNN_BACKEND_OPENCV; + return backendId == DNN_BACKEND_OPENCV || + backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; } virtual bool getMemoryShapes(const std::vector &inputs, @@ -85,6 +88,16 @@ class TileLayerImpl CV_FINAL : public TileLayer tmp.copyTo(out); } +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector >& inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto repeats_node = std::make_shared(ov::element::i32, ov::Shape{repeats.size()}, repeats.data()); + auto tile = std::make_shared(nodes[0].dynamicCast()->node, repeats_node); + return Ptr(new InfEngineNgraphNode(tile)); + } +#endif // HAVE_DNN_NGRAPH + private: std::vector repeats; }; From 1c9efbd4bed6983b4cfbbb872e259455c7833882 Mon Sep 17 00:00:00 2001 From: Kumataro Date: Thu, 2 May 2024 20:40:27 +0900 Subject: [PATCH 022/119] Merge pull request #25523 from Kumataro:fix25522 videoio: obsensor: remove OB_EXT_CMD10 to suppress warning #25523 Close #25522 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/videoio/src/cap_obsensor/obsensor_uvc_stream_channel.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/videoio/src/cap_obsensor/obsensor_uvc_stream_channel.cpp b/modules/videoio/src/cap_obsensor/obsensor_uvc_stream_channel.cpp index eec7634ecaa5..76a963748bae 100644 --- a/modules/videoio/src/cap_obsensor/obsensor_uvc_stream_channel.cpp +++ b/modules/videoio/src/cap_obsensor/obsensor_uvc_stream_channel.cpp @@ -45,7 +45,6 @@ const uint8_t OB_EXT_CMD6[16] = { 0x47, 0x4d, 0x04, 0x00, 0x02, 0x00, 0x7c, 0x00 const uint8_t OB_EXT_CMD7[16] = { 0x47, 0x4d, 0x04, 0x00, 0x02, 0x00, 0xfe, 0x12, 0x55, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }; const uint8_t OB_EXT_CMD8[16] = { 0x47, 0x4d, 0x04, 0x00, 0x02, 0x00, 0xfe, 0x13, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }; const uint8_t OB_EXT_CMD9[16] = { 0x47, 0x4d, 0x04, 0x00, 0x02, 0x00, 0xfa, 0x13, 0x4b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }; -const uint8_t OB_EXT_CMD10[16] = { 0x47, 0x4d, 0x04, 0x00, 0x02, 0x00, 0xfa, 0x13, 0x3f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 }; const uint8_t OB_EXT_CMD11[16] = { 0x47, 0x4d, 0x04, 0x00, 0x02, 0x00, 0xfe, 0x13, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const uint8_t OB_EXT_CMD12[16] = { 0x47, 0x4d, 0x04, 0x00, 0x02, 0x00, 0xfe, 0x13, 0x3f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 }; const uint8_t OB_EXT_CMD13[16] = { 0x47, 0x4d, 0x04, 0x00, 0x02, 0x00, 0xfa, 0x13, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; From c999cb3c5e4ca8e5e5600ff16e7c3130db6cde57 Mon Sep 17 00:00:00 2001 From: NlSEMONO <86743730+NlSEMONO@users.noreply.github.com> Date: Thu, 2 May 2024 11:38:18 -0400 Subject: [PATCH 023/119] Update text_detection.cpp --- samples/dnn/text_detection.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/dnn/text_detection.cpp b/samples/dnn/text_detection.cpp index 24902abfd726..d97ec7bc9ba7 100644 --- a/samples/dnn/text_detection.cpp +++ b/samples/dnn/text_detection.cpp @@ -31,8 +31,8 @@ const char* keys = "{ help h | | Print help message. }" "{ input i | | Path to input image or video file. Skip this argument to capture frames from a camera.}" "{ detModel dmp | | Path to a binary .pb file contains trained detector network.}" - "{ width | 320 | Preprocess input image by resizing to a specific width. It should be multiple by 32. }" - "{ height | 320 | Preprocess input image by resizing to a specific height. It should be multiple by 32. }" + "{ width | 320 | Preprocess input image by resizing to a specific width. It should be a multiple of 32. }" + "{ height | 320 | Preprocess input image by resizing to a specific height. It should be a multiple of 32. }" "{ thr | 0.5 | Confidence threshold. }" "{ nms | 0.4 | Non-maximum suppression threshold. }" "{ recModel rmp | | Path to a binary .onnx file contains trained CRNN text recognition model. " From ed47cce1c54b743c6851b3c514ba1ff821108dd8 Mon Sep 17 00:00:00 2001 From: Wanli Date: Wed, 17 Apr 2024 23:38:46 +0800 Subject: [PATCH 024/119] change fcn8s-heavy-pascal tests from caffe to onnx --- modules/dnn/include/opencv2/dnn/dnn.hpp | 5 ++ modules/dnn/src/model.cpp | 16 +++- modules/dnn/test/imagenet_cls_test_alexnet.py | 15 ++++ modules/dnn/test/pascal_semsegm_test_fcn.py | 82 +++++++++++++------ modules/dnn/test/test_model.cpp | 18 ++-- 5 files changed, 101 insertions(+), 35 deletions(-) diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index 71cb01ad21bf..b86d0e8ec4e4 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -1444,6 +1444,11 @@ CV__DNN_INLINE_NS_BEGIN */ CV_WRAP Model& setInputSwapRB(bool swapRB); + /** @brief Set output names for frame. + * @param[in] outNames Names for output layers. + */ + CV_WRAP Model& setOutputNames(const std::vector& outNames); + /** @brief Set preprocessing parameters for frame. * @param[in] size New input size. * @param[in] mean Scalar with mean values which are subtracted from channels. diff --git a/modules/dnn/src/model.cpp b/modules/dnn/src/model.cpp index bc8e2ebe33f6..6d045e494520 100644 --- a/modules/dnn/src/model.cpp +++ b/modules/dnn/src/model.cpp @@ -90,6 +90,11 @@ struct Model::Impl { swapRB = swapRB_; } + /*virtual*/ + void setOutputNames(const std::vector& outNames_) + { + outNames = outNames_; + } /*virtual*/ void processFrame(InputArray frame, OutputArrayOfArrays outs) @@ -204,6 +209,13 @@ Model& Model::setInputSwapRB(bool swapRB) return *this; } +Model& Model::setOutputNames(const std::vector& outNames) +{ + CV_DbgAssert(impl); + impl->setOutputNames(outNames); + return *this; +} + void Model::setInputParams(double scale, const Size& size, const Scalar& mean, bool swapRB, bool crop) { @@ -381,7 +393,9 @@ void SegmentationModel::segment(InputArray frame, OutputArray mask) { std::vector outs; impl->processFrame(frame, outs); - CV_Assert(outs.size() == 1); + // default output is the first one + if(outs.size() > 1) + outs.resize(1); Mat score = outs[0]; const int chns = score.size[1]; diff --git a/modules/dnn/test/imagenet_cls_test_alexnet.py b/modules/dnn/test/imagenet_cls_test_alexnet.py index 0d2564c1b7a0..30910cbb4484 100644 --- a/modules/dnn/test/imagenet_cls_test_alexnet.py +++ b/modules/dnn/test/imagenet_cls_test_alexnet.py @@ -155,6 +155,21 @@ def get_output(self, input_blob): self.net.setInput(input_blob, self.in_blob_name) return self.net.forward(self.out_blob_name) +class DNNOnnxModel(Framework): + net = object + + def __init__(self, onnx_file, in_blob_name, out_blob_name): + self.net = cv.dnn.readNetFromONNX(onnx_file) + self.in_blob_name = in_blob_name + self.out_blob_name = out_blob_name + + def get_name(self): + return 'DNN (ONNX)' + + def get_output(self, input_blob): + self.net.setInput(input_blob, self.in_blob_name) + return self.net.forward(self.out_blob_name) + class ClsAccEvaluation: log = sys.stdout diff --git a/modules/dnn/test/pascal_semsegm_test_fcn.py b/modules/dnn/test/pascal_semsegm_test_fcn.py index d79f6be13bb7..8754d3b7f9e1 100644 --- a/modules/dnn/test/pascal_semsegm_test_fcn.py +++ b/modules/dnn/test/pascal_semsegm_test_fcn.py @@ -5,7 +5,7 @@ import argparse import time -from imagenet_cls_test_alexnet import CaffeModel, DnnCaffeModel +from imagenet_cls_test_alexnet import CaffeModel, DNNOnnxModel try: import cv2 as cv except ImportError: @@ -58,14 +58,14 @@ def __init__(self): pass @staticmethod - def process(img): - image_data = np.array(img).transpose(2, 0, 1).astype(np.float32) - mean = np.ones(image_data.shape) - mean[0] *= 104 - mean[1] *= 117 - mean[2] *= 123 - image_data -= mean - image_data = np.expand_dims(image_data, 0) + def process(img, framework): + image_data = None + if framework == "Caffe": + image_data = cv.dnn.blobFromImage(img, scalefactor=1.0, mean=(123.0, 117.0, 104.0), swapRB=True) + elif framework == "DNN (ONNX)": + image_data = cv.dnn.blobFromImage(img, scalefactor=0.019, mean=(123.675, 116.28, 103.53), swapRB=True) + else: + raise ValueError("Unknown framework") return image_data @@ -105,10 +105,10 @@ class PASCALDataFetch(DatasetImageFetch): colors = [] i = 0 - def __init__(self, img_dir, segm_dir, names_file, segm_cls_colors_file, preproc): + def __init__(self, img_dir, segm_dir, names_file, segm_cls_colors, preproc): self.img_dir = img_dir self.segm_dir = segm_dir - self.colors = self.read_colors(segm_cls_colors_file) + self.colors = self.read_colors(segm_cls_colors) self.data_prepoc = preproc self.i = 0 @@ -117,26 +117,30 @@ def __init__(self, img_dir, segm_dir, names_file, segm_cls_colors_file, preproc) self.names.append(l.rstrip()) @staticmethod - def read_colors(img_classes_file): + def read_colors(colors): result = [] - with open(img_classes_file) as f: - for l in f.readlines(): - color = np.array(map(int, l.split()[1:])) - result.append(DatasetImageFetch.pix_to_c(color)) + for color in colors: + result.append(DatasetImageFetch.pix_to_c(color)) return result def __iter__(self): return self - def next(self): + def __next__(self): if self.i < len(self.names): name = self.names[self.i] self.i += 1 segm_file = self.segm_dir + name + ".png" img_file = self.img_dir + name + ".jpg" gt = self.color_to_gt(cv.imread(segm_file, cv.IMREAD_COLOR)[:, :, ::-1], self.colors) - img = self.data_prepoc.process(cv.imread(img_file, cv.IMREAD_COLOR)[:, :, ::-1]) - return img, gt + img = cv.imread(img_file, cv.IMREAD_COLOR) + img_caffe = self.data_prepoc.process(img[:, :, ::-1], "Caffe") + img_dnn = self.data_prepoc.process(img[:, :, ::-1], "DNN (ONNX)") + img_dict = { + "Caffe": img_caffe, + "DNN (ONNX)": img_dnn + } + return img_dict, gt else: self.i = 0 raise StopIteration @@ -160,12 +164,13 @@ def process(self, frameworks, data_fetcher): blobs_l_inf_diff = [sys.float_info.min] * len(frameworks) inference_time = [0.0] * len(frameworks) - for in_blob, gt in data_fetcher: + for in_blob_dict, gt in data_fetcher: frameworks_out = [] samples_handled += 1 for i in range(len(frameworks)): start = time.time() - out = frameworks[i].get_output(in_blob) + framework_name = frameworks[i].get_name() + out = frameworks[i].get_output(in_blob_dict[framework_name]) end = time.time() segm = eval_segm_result(out) conf_mats[i] += get_conf_mat(gt, segm[0]) @@ -198,28 +203,53 @@ def process(self, frameworks, data_fetcher): log_str = frameworks[0].get_name() + " vs " + frameworks[i].get_name() + ':' print('Final l1 diff', log_str, blobs_l1_diff[i] / blobs_l1_diff_count[i], file=self.log) +# PASCAL VOC 2012 classes colors +colors_pascal_voc_2012 = [ + [0, 0, 0], + [128, 0, 0], + [0, 128, 0], + [128, 128, 0], + [0, 0, 128], + [128, 0, 128], + [0, 128, 128], + [128, 128, 128], + [64, 0, 0], + [192, 0, 0], + [64, 128, 0], + [192, 128, 0], + [64, 0, 128], + [192, 0, 128], + [64, 128, 128], + [192, 128, 128], + [0, 64, 0], + [128, 64, 0], + [0, 192, 0], + [128, 192, 0], + [0, 64, 128], +] + if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--imgs_dir", help="path to PASCAL VOC 2012 images dir, data/VOC2012/JPEGImages") parser.add_argument("--segm_dir", help="path to PASCAL VOC 2012 segmentation dir, data/VOC2012/SegmentationClass/") parser.add_argument("--val_names", help="path to file with validation set image names, download it here: " "https://github.com/shelhamer/fcn.berkeleyvision.org/blob/master/data/pascal/seg11valid.txt") - parser.add_argument("--cls_file", help="path to file with colors for classes, download it here: " - "https://github.com/opencv/opencv/blob/4.x/samples/data/dnn/pascal-classes.txt") parser.add_argument("--prototxt", help="path to caffe prototxt, download it here: " "https://github.com/opencv/opencv/blob/4.x/samples/data/dnn/fcn8s-heavy-pascal.prototxt") parser.add_argument("--caffemodel", help="path to caffemodel file, download it here: " "http://dl.caffe.berkeleyvision.org/fcn8s-heavy-pascal.caffemodel") - parser.add_argument("--log", help="path to logging file") + parser.add_argument("--onnxmodel", help="path to onnx model file, download it here: " + "https://github.com/onnx/models/raw/491ce05590abb7551d7fae43c067c060eeb575a6/validated/vision/object_detection_segmentation/fcn/model/fcn-resnet50-12.onnx") + parser.add_argument("--log", help="path to logging file", default='log.txt') parser.add_argument("--in_blob", help="name for input blob", default='data') parser.add_argument("--out_blob", help="name for output blob", default='score') args = parser.parse_args() prep = MeanChannelsPreproc() - df = PASCALDataFetch(args.imgs_dir, args.segm_dir, args.val_names, args.cls_file, prep) + df = PASCALDataFetch(args.imgs_dir, args.segm_dir, args.val_names, colors_pascal_voc_2012, prep) fw = [CaffeModel(args.prototxt, args.caffemodel, args.in_blob, args.out_blob, True), - DnnCaffeModel(args.prototxt, args.caffemodel, '', args.out_blob)] + DNNOnnxModel(args.onnxmodel, args.in_blob, args.out_blob)] segm_eval = SemSegmEvaluation(args.log) segm_eval.process(fw, df) diff --git a/modules/dnn/test/test_model.cpp b/modules/dnn/test/test_model.cpp index 6cfdc3821951..1a533f6a3fb9 100644 --- a/modules/dnn/test/test_model.cpp +++ b/modules/dnn/test/test_model.cpp @@ -100,7 +100,7 @@ class Test_Model : public DNNTestLayer void testSegmentationModel(const std::string& weights_file, const std::string& config_file, const std::string& inImgPath, const std::string& outImgPath, float norm, const Size& size = {-1, -1}, Scalar mean = Scalar(), - double scale = 1.0, bool swapRB = false, bool crop = false) + double scale = 1.0, bool swapRB = false, bool crop = false, const std::string outname = "") { checkBackend(); @@ -115,6 +115,9 @@ class Test_Model : public DNNTestLayer model.setPreferableBackend(backend); model.setPreferableTarget(target); + if(!outname.empty()) + model.setOutputNames({outname}); + model.segment(frame, mask); normAssert(mask, exp, "", norm, norm); } @@ -669,20 +672,19 @@ TEST_P(Test_Model, Segmentation) if ((backend == DNN_BACKEND_OPENCV && (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_CPU_FP16)) || (backend == DNN_BACKEND_CUDA && target == DNN_TARGET_CUDA_FP16)) { - norm = 2.0f; // l1 = 0.01 lInf = 2 + norm = 7.0f; // l1 = 0.01 lInf = 7 } std::string inp = _tf("dog416.png"); - std::string weights_file = _tf("fcn8s-heavy-pascal.prototxt"); - std::string config_file = _tf("fcn8s-heavy-pascal.caffemodel", false); + std::string weights_file = _tf("onnx/models/fcn-resnet50-12.onnx"); std::string exp = _tf("segmentation_exp.png"); Size size{128, 128}; - double scale = 1.0; - Scalar mean = Scalar(); - bool swapRB = false; + double scale = 0.019; + Scalar mean = Scalar(0.485*255, 0.456*255, 0.406*255); + bool swapRB = true; - testSegmentationModel(weights_file, config_file, inp, exp, norm, size, mean, scale, swapRB); + testSegmentationModel(weights_file, "", inp, exp, norm, size, mean, scale, swapRB, false, "out"); } TEST_P(Test_Model, TextRecognition) From 5aaa570fefaf22c4e8537288d85feec16cae9480 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Thu, 2 May 2024 20:38:23 +0300 Subject: [PATCH 025/119] Fixed SyntaxWarning: invalid escape sequence '\w' in header parser. --- modules/python/src2/hdr_parser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/python/src2/hdr_parser.py b/modules/python/src2/hdr_parser.py index d4a5b26a9f25..fa2d0077d959 100755 --- a/modules/python/src2/hdr_parser.py +++ b/modules/python/src2/hdr_parser.py @@ -513,9 +513,9 @@ def parse_func_decl(self, decl_str, mat="Mat", docstring=""): if rettype == classname or rettype == "~" + classname: rettype, funcname = "", rettype else: - if bool(re.match('\w+\s+\(\*\w+\)\s*\(.*\)', decl_str)): + if bool(re.match(r'\w+\s+\(\*\w+\)\s*\(.*\)', decl_str)): return [] # function typedef - elif bool(re.match('\w+\s+\(\w+::\*\w+\)\s*\(.*\)', decl_str)): + elif bool(re.match(r'\w+\s+\(\w+::\*\w+\)\s*\(.*\)', decl_str)): return [] # class method typedef elif bool(re.match('[A-Z_]+', decl_start)): return [] # it seems to be a macro instantiation From bc95f27e56d89e486c25e76db0573b610bee6496 Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Thu, 2 May 2024 19:50:08 +0200 Subject: [PATCH 026/119] Merge pull request #25509 from savuor:rv/hal_otsu HAL added for Otsu threshold #25509 fixes #25393 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/imgproc/src/hal_replacement.hpp | 19 +++++++++++++++++++ modules/imgproc/src/thresh.cpp | 11 ++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index ca25fbb47da5..28bfd310900f 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -856,6 +856,25 @@ inline int hal_ni_threshold(const uchar* src_data, size_t src_step, uchar* dst_d #define cv_hal_threshold hal_ni_threshold //! @endcond +/** + @brief Performs threshold filtering using threshold estimated by Otsu algorithm + @param src_data Source image data + @param src_step Source image step + @param dst_data Destination image data + @param dst_step Destination image step + @param width Source image width + @param height Source image height + @param depth Depths of source and destination image + @param maxValue Value assigned to the pixels for which the condition is satisfied + @param thresholdType Thresholding type + @param thresh Calculated threshold value +*/ +inline int hal_ni_threshold_otsu(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int depth, double maxValue, int thresholdType, double* thresh) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +//! @cond IGNORED +#define cv_hal_threshold_otsu hal_ni_threshold_otsu +//! @endcond + /** @brief Calculate box filter @param src_data Source image data diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index 8d82c14a50cb..a8c89059a780 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -1545,6 +1545,10 @@ double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double m ocl_threshold(_src, _dst, thresh, maxval, type), thresh) Mat src = _src.getMat(); + + _dst.create( src.size(), src.type() ); + Mat dst = _dst.getMat(); + int automatic_thresh = (type & ~cv::THRESH_MASK); type &= THRESH_MASK; @@ -1553,6 +1557,10 @@ double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double m { int src_type = src.type(); CV_CheckType(src_type, src_type == CV_8UC1 || src_type == CV_16UC1, "THRESH_OTSU mode"); + + CALL_HAL_RET(thresholdOtsu, cv_hal_threshold_otsu, thresh, src.data, src.step, dst.data, dst.step, + src.cols, src.rows, src_type, maxval, type); + thresh = src.type() == CV_8UC1 ? getThreshVal_Otsu_8u( src ) : getThreshVal_Otsu_16u( src ); } @@ -1562,9 +1570,6 @@ double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double m thresh = getThreshVal_Triangle_8u( src ); } - _dst.create( src.size(), src.type() ); - Mat dst = _dst.getMat(); - if( src.depth() == CV_8U ) { int ithresh = cvFloor(thresh); From 02c3132f02ea063dd4a8e60ab65002e6ea41a715 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 3 May 2024 08:40:43 +0300 Subject: [PATCH 027/119] Fix moments integration to OpenCV HAL. --- modules/imgproc/src/moments.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/src/moments.cpp b/modules/imgproc/src/moments.cpp index e89137053cb1..e485104a26d4 100644 --- a/modules/imgproc/src/moments.cpp +++ b/modules/imgproc/src/moments.cpp @@ -573,9 +573,9 @@ static int moments(const cv::Mat& src, bool binary, cv::Moments& m) int depth = CV_MAT_DEPTH(type); if( src.checkVector(2) >= 0 && (depth == CV_32F || depth == CV_32S)) - status = hal_ni_polygonMoments(src.data, src.total()/2, src.type(), m_data); + status = cv_hal_polygonMoments(src.data, src.total()/2, src.type(), m_data); else - status = hal_ni_imageMoments(src.data, src.step, src.type(), src.cols, src.rows, binary, m_data); + status = cv_hal_imageMoments(src.data, src.step, src.type(), src.cols, src.rows, binary, m_data); if (status == CV_HAL_ERROR_OK) { From 9fe5615f2fe6aa7a3f0f676d7bbd5229d3ade087 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 3 May 2024 11:05:08 +0300 Subject: [PATCH 028/119] Got rid of deprecated convertFp16 in imgcodecs module. --- modules/imgcodecs/src/grfmt_exr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgcodecs/src/grfmt_exr.cpp b/modules/imgcodecs/src/grfmt_exr.cpp index 786b9d176b2b..65a0e5e03bfe 100644 --- a/modules/imgcodecs/src/grfmt_exr.cpp +++ b/modules/imgcodecs/src/grfmt_exr.cpp @@ -729,7 +729,7 @@ bool ExrEncoder::write( const Mat& img, const std::vector& params ) Mat exrMat; if( type == HALF ) { - convertFp16(img, exrMat); + img.convertTo(exrMat, CV_16F); buffer = (char *)const_cast( exrMat.ptr() ); bufferstep = exrMat.step; size = 2; From d8e18f4576654492c78125bafdf5179692aa44ad Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 3 May 2024 16:14:22 +0300 Subject: [PATCH 029/119] Made fcn-resnet50-12.onnx model optional. --- modules/dnn/test/test_model.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnn/test/test_model.cpp b/modules/dnn/test/test_model.cpp index 1a533f6a3fb9..902526930fe4 100644 --- a/modules/dnn/test/test_model.cpp +++ b/modules/dnn/test/test_model.cpp @@ -676,7 +676,7 @@ TEST_P(Test_Model, Segmentation) } std::string inp = _tf("dog416.png"); - std::string weights_file = _tf("onnx/models/fcn-resnet50-12.onnx"); + std::string weights_file = _tf("onnx/models/fcn-resnet50-12.onnx", false); std::string exp = _tf("segmentation_exp.png"); Size size{128, 128}; From b94cb5bc68b77d38d30c3b81c185f3fdcdcc9ea9 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 3 May 2024 12:51:57 +0300 Subject: [PATCH 030/119] HAL interface for meanStdDev. --- modules/core/src/hal_replacement.hpp | 21 +++++++++ modules/core/src/mean.dispatch.cpp | 69 +++++++++++++++++++++++----- 2 files changed, 78 insertions(+), 12 deletions(-) diff --git a/modules/core/src/hal_replacement.hpp b/modules/core/src/hal_replacement.hpp index 15149453c794..498cd6370019 100644 --- a/modules/core/src/hal_replacement.hpp +++ b/modules/core/src/hal_replacement.hpp @@ -843,6 +843,27 @@ inline int hal_ni_minMaxIdx(const uchar* src_data, size_t src_step, int width, i #define cv_hal_minMaxIdx hal_ni_minMaxIdx //! @endcond +/** + @brief calculates the mean and the standard deviation of array elements independently for each channel + @param src_data Source image + @param src_step Source image + @param width Source image dimensions + @param height Source image dimensions + @param src_type Type of source image + @param mean_val Array of per-channel mean values. May be nullptr, if mean value is not required. + @param stddev_val Array of per-channel standard deviation values. May be nullptr, if stddev value is not required. + @param mask Specified array region. + @param mask_step Mask array step. + @sa meanStdDev +*/ +inline int hal_ni_meanStdDev(const uchar* src_data, size_t src_step, int width, int height, + int src_type, double* mean_val, double* stddev_val, uchar* mask, size_t mask_step) +{ return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +//! @cond IGNORED +#define cv_hal_meanStdDev hal_ni_meanStdDev +//! @endcond + /** @brief hal_flip @param src_type source and destination image type diff --git a/modules/core/src/mean.dispatch.cpp b/modules/core/src/mean.dispatch.cpp index 0f94e5421a85..b6ea92625546 100644 --- a/modules/core/src/mean.dispatch.cpp +++ b/modules/core/src/mean.dispatch.cpp @@ -525,12 +525,55 @@ void meanStdDev(InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray Mat src = _src.getMat(), mask = _mask.getMat(); + CV_Assert(mask.empty() || src.size == mask.size); + CV_OVX_RUN(!ovx::skipSmallImages(src.cols, src.rows), openvx_meanStdDev(src, _mean, _sdv, mask)) CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_meanStdDev(src, _mean, _sdv, mask)); int k, cn = src.channels(), depth = src.depth(); + Mat mean_mat, stddev_mat; + + if(_mean.needed()) + { + if( !_mean.fixedSize() ) + _mean.create(cn, 1, CV_64F, -1, true); + + mean_mat = _mean.getMat(); + int dcn = (int)mean_mat.total(); + CV_Assert( mean_mat.type() == CV_64F && mean_mat.isContinuous() && + (mean_mat.cols == 1 || mean_mat.rows == 1) && dcn >= cn ); + } + + if (_sdv.needed()) + { + if( !_sdv.fixedSize() ) + _sdv.create(cn, 1, CV_64F, -1, true); + + stddev_mat = _sdv.getMat(); + int dcn = (int)stddev_mat.total(); + CV_Assert( stddev_mat.type() == CV_64F && stddev_mat.isContinuous() && + (stddev_mat.cols == 1 || stddev_mat.rows == 1) && dcn >= cn ); + } + + if (src.isContinuous() && mask.isContinuous()) + { + CALL_HAL(meanStdDev, cv_hal_meanStdDev, src.data, 0, (int)src.total(), 1, src.type(), + _mean.needed() ? mean_mat.ptr() : nullptr, + _sdv.needed() ? stddev_mat.ptr() : nullptr, + mask.data, 0); + } + else + { + if (src.dims <= 2) + { + CALL_HAL(meanStdDev, cv_hal_meanStdDev, src.data, src.step, src.cols, src.rows, src.type(), + _mean.needed() ? mean_mat.ptr() : nullptr, + _sdv.needed() ? stddev_mat.ptr() : nullptr, + mask.data, mask.step); + } + } SumSqrFunc func = getSumSqrFunc(depth); @@ -600,20 +643,22 @@ void meanStdDev(InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray sq[k] = std::sqrt(std::max(sq[k]*scale - s[k]*s[k], 0.)); } - for( j = 0; j < 2; j++ ) + if (_mean.needed()) { - const double* sptr = j == 0 ? s : sq; - _OutputArray _dst = j == 0 ? _mean : _sdv; - if( !_dst.needed() ) - continue; + const double* sptr = s; + int dcn = (int)mean_mat.total(); + double* dptr = mean_mat.ptr(); + for( k = 0; k < cn; k++ ) + dptr[k] = sptr[k]; + for( ; k < dcn; k++ ) + dptr[k] = 0; + } - if( !_dst.fixedSize() ) - _dst.create(cn, 1, CV_64F, -1, true); - Mat dst = _dst.getMat(); - int dcn = (int)dst.total(); - CV_Assert( dst.type() == CV_64F && dst.isContinuous() && - (dst.cols == 1 || dst.rows == 1) && dcn >= cn ); - double* dptr = dst.ptr(); + if (_sdv.needed()) + { + const double* sptr = sq; + int dcn = (int)stddev_mat.total(); + double* dptr = stddev_mat.ptr(); for( k = 0; k < cn; k++ ) dptr[k] = sptr[k]; for( ; k < dcn; k++ ) From af4531b3789d959b802c39b1753beb0f32dd63fc Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Fri, 3 May 2024 20:10:41 +0300 Subject: [PATCH 031/119] python: adapt test to NumPy 2.x --- modules/python/test/test_misc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/python/test/test_misc.py b/modules/python/test/test_misc.py index bcd315269966..08ab04d53d9e 100644 --- a/modules/python/test/test_misc.py +++ b/modules/python/test/test_misc.py @@ -451,7 +451,7 @@ def test_parse_to_float_convertible(self): try_to_convert = partial(self._try_to_convert, cv.utils.dumpFloat) min_float, max_float = get_limits(ctypes.c_float) for convertible in (2, -13, 1.24, np.float32(32.45), float(32), np.double(12.23), - np.float32(-12.3), np.float64(3.22), np.float_(-1.5), min_float, + np.float32(-12.3), np.float64(3.22), min_float, max_float, np.inf, -np.inf, float('Inf'), -float('Inf'), np.double(np.inf), np.double(-np.inf), np.double(float('Inf')), np.double(-float('Inf'))): @@ -495,7 +495,7 @@ def test_parse_to_double_convertible(self): min_float, max_float = get_limits(ctypes.c_float) min_double, max_double = get_limits(ctypes.c_double) for convertible in (2, -13, 1.24, np.float32(32.45), float(2), np.double(12.23), - np.float32(-12.3), np.float64(3.22), np.float_(-1.5), min_float, + np.float32(-12.3), np.float64(3.22), min_float, max_float, min_double, max_double, np.inf, -np.inf, float('Inf'), -float('Inf'), np.double(np.inf), np.double(-np.inf), np.double(float('Inf')), np.double(-float('Inf'))): From c4ce94232b79781059b6c93ae714f1b5473775f5 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 24 Apr 2024 15:23:57 +0300 Subject: [PATCH 032/119] imgproc: fixed alignment issue and improved test for boundingRect --- modules/imgproc/src/geometry.cpp | 28 ++-- modules/imgproc/test/test_boundingrect.cpp | 180 +++++++-------------- 2 files changed, 76 insertions(+), 132 deletions(-) diff --git a/modules/imgproc/src/geometry.cpp b/modules/imgproc/src/geometry.cpp index 8cf247478711..ae582fcafc08 100644 --- a/modules/imgproc/src/geometry.cpp +++ b/modules/imgproc/src/geometry.cpp @@ -698,15 +698,16 @@ static Rect pointSetBoundingRect( const Mat& points ) return Rect(); #if CV_SIMD // TODO: enable for CV_SIMD_SCALABLE, loop tail related. - const int64_t* pts = points.ptr(); - if( !is_float ) { + const int32_t* pts = points.ptr(); + int64_t firstval = 0; + std::memcpy(&firstval, pts, sizeof(pts[0]) * 2); v_int32 minval, maxval; - minval = maxval = v_reinterpret_as_s32(vx_setall_s64(*pts)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y + minval = maxval = v_reinterpret_as_s32(vx_setall_s64(firstval)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y for( i = 1; i <= npoints - VTraits::vlanes()/2; i+= VTraits::vlanes()/2 ) { - v_int32 ptXY2 = v_reinterpret_as_s32(vx_load(pts + i)); + v_int32 ptXY2 = vx_load(pts + 2 * i); minval = v_min(ptXY2, minval); maxval = v_max(ptXY2, maxval); } @@ -714,7 +715,7 @@ static Rect pointSetBoundingRect( const Mat& points ) maxval = v_max(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval)))); if( i <= npoints - VTraits::vlanes()/4 ) { - v_int32 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + i)))); + v_int32 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + 2 * i)))); minval = v_min(ptXY, minval); maxval = v_max(ptXY, maxval); i += VTraits::vlanes()/2; @@ -732,10 +733,10 @@ static Rect pointSetBoundingRect( const Mat& points ) if( i < npoints ) { v_int32x4 minval2, maxval2; - minval2 = maxval2 = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); + minval2 = maxval2 = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + 2 * i)))); for( i++; i < npoints; i++ ) { - v_int32x4 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); + v_int32x4 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + 2 * i)))); minval2 = v_min(ptXY, minval2); maxval2 = v_max(ptXY, maxval2); } @@ -748,11 +749,14 @@ static Rect pointSetBoundingRect( const Mat& points ) } else { + const float* pts = points.ptr(); + int64_t firstval = 0; + std::memcpy(&firstval, pts, sizeof(pts[0]) * 2); v_float32 minval, maxval; - minval = maxval = v_reinterpret_as_f32(vx_setall_s64(*pts)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y + minval = maxval = v_reinterpret_as_f32(vx_setall_s64(firstval)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y for( i = 1; i <= npoints - VTraits::vlanes()/2; i+= VTraits::vlanes()/2 ) { - v_float32 ptXY2 = v_reinterpret_as_f32(vx_load(pts + i)); + v_float32 ptXY2 = vx_load(pts + 2 * i); minval = v_min(ptXY2, minval); maxval = v_max(ptXY2, maxval); } @@ -760,7 +764,7 @@ static Rect pointSetBoundingRect( const Mat& points ) maxval = v_max(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval)))); if( i <= npoints - VTraits::vlanes()/4 ) { - v_float32 ptXY = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + i)))); + v_float32 ptXY = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + 2 * i)))); minval = v_min(ptXY, minval); maxval = v_max(ptXY, maxval); i += VTraits::vlanes()/4; @@ -778,10 +782,10 @@ static Rect pointSetBoundingRect( const Mat& points ) if( i < npoints ) { v_float32x4 minval2, maxval2; - minval2 = maxval2 = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); + minval2 = maxval2 = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + 2 * i)))); for( i++; i < npoints; i++ ) { - v_float32x4 ptXY = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); + v_float32x4 ptXY = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + 2 * i)))); minval2 = v_min(ptXY, minval2); maxval2 = v_max(ptXY, maxval2); } diff --git a/modules/imgproc/test/test_boundingrect.cpp b/modules/imgproc/test/test_boundingrect.cpp index d3e5495b4fa3..cf70b66e04d2 100644 --- a/modules/imgproc/test/test_boundingrect.cpp +++ b/modules/imgproc/test/test_boundingrect.cpp @@ -1,146 +1,86 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ +// 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 +#include "opencv2/core/types.hpp" #include "test_precomp.hpp" -namespace opencv_test { namespace { - -#define IMGPROC_BOUNDINGRECT_ERROR_DIFF 1 +using namespace cv; +using namespace std; -#define MESSAGE_ERROR_DIFF "Bounding rectangle found by boundingRect function is incorrect." - -class CV_BoundingRectTest: public cvtest::ArrayTest -{ -public: - CV_BoundingRectTest(); - ~CV_BoundingRectTest(); - -protected: - void run (int); - -private: - template void generate_src_points(vector >& src, int n); - template cv::Rect get_bounding_rect(const vector > src); - template bool checking_function_work(vector >& src, int type); -}; +namespace opencv_test { namespace { -CV_BoundingRectTest::CV_BoundingRectTest() {} -CV_BoundingRectTest::~CV_BoundingRectTest() {} -template void CV_BoundingRectTest::generate_src_points(vector >& src, int n) +template +cv::Rect calcBoundingRect(Mat pts) { - src.clear(); - for (int i = 0; i < n; ++i) - src.push_back(Point_(cv::randu(), cv::randu())); + CV_Assert(pts.type() == CV_32FC2 || pts.type() == CV_32SC2); + CV_Assert(pts.size().width == 1 && pts.size().height > 0); + const int N = pts.size().height; + // NOTE: using ::lowest(), not ::min() + T min_w = std::numeric_limits::max(), max_w = std::numeric_limits::lowest(); + T min_h = min_w, max_h = max_w; + for (int i = 0; i < N; ++i) + { + const Point_ & pt = pts.at>(i, 0); + min_w = std::min(pt.x, min_w); + max_w = std::max(pt.x, max_w); + min_h = std::min(pt.y, min_h); + max_h = std::max(pt.y, max_h); + } + return Rect(cvFloor(min_w), cvFloor(min_h), cvFloor(max_w) - cvFloor(min_w) + 1, cvFloor(max_h) - cvFloor(min_h) + 1); } -template cv::Rect CV_BoundingRectTest::get_bounding_rect(const vector > src) -{ - int n = (int)src.size(); - T min_w = std::numeric_limits::max(), max_w = std::numeric_limits::min(); - T min_h = min_w, max_h = max_w; +typedef ::testing::TestWithParam Imgproc_BoundingRect_Types; - for (int i = 0; i < n; ++i) +TEST_P(Imgproc_BoundingRect_Types, accuracy) +{ + const int depth = GetParam(); + RNG& rng = ::cvtest::TS::ptr()->get_rng(); + for (int k = 0; k < 1000; ++k) { - min_w = std::min(src.at(i).x, min_w); - max_w = std::max(src.at(i).x, max_w); - min_h = std::min(src.at(i).y, min_h); - max_h = std::max(src.at(i).y, max_h); + SCOPED_TRACE(cv::format("k=%d", k)); + const int sz = rng.uniform(1, 10000); + Mat src(sz, 1, CV_MAKETYPE(depth, 2)); + rng.fill(src, RNG::UNIFORM, Scalar(-100000, -100000), Scalar(100000, 100000)); + Rect reference; + if (depth == CV_32F) + reference = calcBoundingRect(src); + else if (depth == CV_32S) + reference = calcBoundingRect(src); + else + CV_Error(Error::StsError, "Test error"); + Rect result = cv::boundingRect(src); + EXPECT_EQ(reference, result); } - - return Rect((int)min_w, (int)min_h, (int)max_w-(int)min_w + 1, (int)max_h-(int)min_h + 1); } -template bool CV_BoundingRectTest::checking_function_work(vector >& src, int type) +TEST_P(Imgproc_BoundingRect_Types, alignment) { - const int MAX_COUNT_OF_POINTS = 1000; - const int N = 10000; - - for (int k = 0; k < N; ++k) + const int depth = GetParam(); + const int SZ = 100; + int idata[SZ]; + float fdata[SZ]; + for (int i = 0; i < SZ; ++i) { - - RNG& rng = ts->get_rng(); - - int n = rng.next()%MAX_COUNT_OF_POINTS + 1; - - generate_src_points (src, n); - - cv::Rect right = get_bounding_rect (src); - - cv::Rect rect[2] = { boundingRect(src), boundingRect(Mat(src)) }; - - for (int i = 0; i < 2; ++i) if (rect[i] != right) + idata[i] = i; + fdata[i] = (float)i; + } + for (int i = 0; i < 10; ++i) + { + for (int len = 1; len < 40; ++len) { - cout << endl; cout << "Checking for the work of boundingRect function..." << endl; - cout << "Type of src points: "; - switch (type) - { - case 0: {cout << "INT"; break;} - case 1: {cout << "FLOAT"; break;} - default: break; - } - cout << endl; - cout << "Src points are stored as "; if (i == 0) cout << "VECTOR" << endl; else cout << "MAT" << endl; - cout << "Number of points: " << n << endl; - cout << "Right rect (x, y, w, h): [" << right.x << ", " << right.y << ", " << right.width << ", " << right.height << "]" << endl; - cout << "Result rect (x, y, w, h): [" << rect[i].x << ", " << rect[i].y << ", " << rect[i].width << ", " << rect[i].height << "]" << endl; - cout << endl; - CV_Error(IMGPROC_BOUNDINGRECT_ERROR_DIFF, MESSAGE_ERROR_DIFF); + SCOPED_TRACE(cv::format("i=%d, len=%d", i, len)); + Mat sub(len, 1, CV_MAKETYPE(depth, 2), (depth == CV_32S) ? (void*)(idata + i) : (void*)(fdata + i)); + EXPECT_NO_THROW(boundingRect(sub)); } - } - - return true; } -void CV_BoundingRectTest::run(int) -{ - vector src_veci; if (!checking_function_work(src_veci, 0)) return; - vector src_vecf; checking_function_work(src_vecf, 1); -} +INSTANTIATE_TEST_CASE_P(, Imgproc_BoundingRect_Types, ::testing::Values(CV_32S, CV_32F)); -TEST (Imgproc_BoundingRect, accuracy) { CV_BoundingRectTest test; test.safe_run(); } -TEST (Imgproc_BoundingRect, bug_24217) +TEST(Imgproc_BoundingRect, bug_24217) { for (int image_width = 3; image_width < 20; image_width++) { From a8df49f1704e3079c07fde237bad73163f3e4ff9 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Fri, 3 May 2024 22:09:19 +0300 Subject: [PATCH 033/119] doc: fixed modern Javadoc issue --- modules/imgproc/include/opencv2/imgproc.hpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 40300cb464f7..5da8cf3ef460 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -4030,16 +4030,6 @@ CV_EXPORTS_W void findContours( InputArray image, OutputArrayOfArrays contours, CV_EXPORTS void findContours( InputArray image, OutputArrayOfArrays contours, int mode, int method, Point offset = Point()); -/** @example samples/cpp/squares.cpp -A program using pyramid scaling, Canny, contours and contour simplification to find -squares in a list of images (pic1-6.png). Returns sequence of squares detected on the image. -*/ - -/** @example samples/tapi/squares.cpp -A program using pyramid scaling, Canny, contours and contour simplification to find -squares in the input image. -*/ - //! @brief Find contours using link runs algorithm //! //! This function implements an algorithm different from cv::findContours: From 4081a309bf88ac49325cee944e7d20ba76b8d26a Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Fri, 3 May 2024 22:09:33 +0300 Subject: [PATCH 034/119] doc: disabled inheritance graphs --- doc/Doxyfile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 5cc7a31ea086..d757c6f92e5a 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -319,7 +319,7 @@ DOT_FONTPATH = DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10" DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10" DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4" -CLASS_GRAPH = YES +CLASS_GRAPH = NO COLLABORATION_GRAPH = YES GROUP_GRAPHS = NO UML_LOOK = YES From 71271614263facf6daa4e90e549fd42a6869f01e Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Mon, 6 May 2024 20:43:52 +0300 Subject: [PATCH 035/119] videoio: decreased log level for failed backends in VideoCapture and VideoWriter open --- modules/videoio/src/cap.cpp | 48 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/modules/videoio/src/cap.cpp b/modules/videoio/src/cap.cpp index be159062e3f2..f8572aad08f6 100644 --- a/modules/videoio/src/cap.cpp +++ b/modules/videoio/src/cap.cpp @@ -161,9 +161,9 @@ bool VideoCapture::open(const String& filename, int apiPreference, const std::ve { throw; } - CV_LOG_ERROR(NULL, - cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", - info.name, e.what())); + CV_LOG_WARNING(NULL, + cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", + info.name, e.what())); } catch (const std::exception& e) { @@ -171,8 +171,8 @@ bool VideoCapture::open(const String& filename, int apiPreference, const std::ve { throw; } - CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", - info.name, e.what())); + CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", + info.name, e.what())); } catch (...) { @@ -180,9 +180,9 @@ bool VideoCapture::open(const String& filename, int apiPreference, const std::ve { throw; } - CV_LOG_ERROR(NULL, - cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", - info.name)); + CV_LOG_WARNING(NULL, + cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", + info.name)); } } else @@ -299,9 +299,9 @@ bool VideoCapture::open(int cameraNum, int apiPreference, const std::vector { throw; } - CV_LOG_ERROR(NULL, - cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", - info.name, e.what())); + CV_LOG_WARNING(NULL, + cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", + info.name, e.what())); } catch (const std::exception& e) { @@ -309,8 +309,8 @@ bool VideoCapture::open(int cameraNum, int apiPreference, const std::vector { throw; } - CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", - info.name, e.what())); + CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", + info.name, e.what())); } catch (...) { @@ -318,9 +318,9 @@ bool VideoCapture::open(int cameraNum, int apiPreference, const std::vector { throw; } - CV_LOG_ERROR(NULL, - cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", - info.name)); + CV_LOG_WARNING(NULL, + cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", + info.name)); } } else @@ -640,20 +640,20 @@ bool VideoWriter::open(const String& filename, int apiPreference, int fourcc, do } catch (const cv::Exception& e) { - CV_LOG_ERROR(NULL, - cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", - info.name, e.what())); + CV_LOG_WARNING(NULL, + cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", + info.name, e.what())); } catch (const std::exception& e) { - CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", - info.name, e.what())); + CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", + info.name, e.what())); } catch (...) { - CV_LOG_ERROR(NULL, - cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", - info.name)); + CV_LOG_WARNING(NULL, + cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", + info.name)); } } else From 392fd4edd1cde889b65b5cf5b886ec3d950d139c Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Tue, 7 May 2024 18:24:43 +0300 Subject: [PATCH 036/119] Tune sanity threshold in Moments performance test for Android aarch64. --- modules/imgproc/perf/perf_moments.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/perf/perf_moments.cpp b/modules/imgproc/perf/perf_moments.cpp index 7f52e70b7690..5d9c0366a174 100644 --- a/modules/imgproc/perf/perf_moments.cpp +++ b/modules/imgproc/perf/perf_moments.cpp @@ -35,7 +35,7 @@ PERF_TEST_P(MomentsFixture_val, Moments1, mat += 1; - SANITY_CHECK_MOMENTS(m, 2e-4, ERROR_RELATIVE); + SANITY_CHECK_MOMENTS(m, 3.3e-4, ERROR_RELATIVE); } } // namespace From faa259ab344f247c88bd9c4259f77aff3a27aa49 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov <2536374+asmorkalov@users.noreply.github.com> Date: Tue, 7 May 2024 20:46:17 +0300 Subject: [PATCH 037/119] Merge pull request #25553 from asmorkalov:as/HAL_min_max_idx Fix HAL interface for hal_ni_minMaxIdx #25553 Fixes https://github.com/opencv/opencv/issues/25540 The original implementation call HAL with the same parameters independently from amount of channels. The patch uses HAL correctly for the case cn > 1. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/core/include/opencv2/core.hpp | 7 ++----- modules/core/src/minmax.cpp | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index be800333f8b7..f6372ac03e55 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -912,11 +912,8 @@ CV_EXPORTS_W void reduceArgMax(InputArray src, OutputArray dst, int axis, bool l The function cv::minMaxIdx finds the minimum and maximum element values and their positions. The extremums are searched across the whole array or, if mask is not an empty array, in the specified -array region. The function does not work with multi-channel arrays. If you need to find minimum or -maximum elements across all the channels, use Mat::reshape first to reinterpret the array as -single-channel. Or you may extract the particular channel using either extractImageCOI, or -mixChannels, or split. In case of a sparse matrix, the minimum is found among non-zero elements -only. +array region. In case of a sparse matrix, the minimum is found among non-zero elements +only. Multi-channel input is supported without mask and extremums indexes (should be nullptr). @note When minIdx is not NULL, it must have at least 2 elements (as well as maxIdx), even if src is a single-row or single-column matrix. In OpenCV (following MATLAB) each array has at least 2 dimensions, i.e. single-column matrix is Mx1 matrix (and therefore minIdx/maxIdx will be diff --git a/modules/core/src/minmax.cpp b/modules/core/src/minmax.cpp index ff3786886e1f..b5aa4c84627f 100644 --- a/modules/core/src/minmax.cpp +++ b/modules/core/src/minmax.cpp @@ -1510,9 +1510,19 @@ void cv::minMaxIdx(InputArray _src, double* minVal, Mat src = _src.getMat(), mask = _mask.getMat(); + int _minIdx, _maxIdx; + int* min_offset = (cn == 1) ? minIdx : &_minIdx; + int* max_offset = (cn == 1) ? maxIdx : &_maxIdx; if (src.dims <= 2) - CALL_HAL(minMaxIdx, cv_hal_minMaxIdx, src.data, src.step, src.cols, src.rows, src.depth(), minVal, maxVal, - minIdx, maxIdx, mask.data); + { + CALL_HAL(minMaxIdx, cv_hal_minMaxIdx, src.data, src.step, src.cols*cn, src.rows, src.depth(), + minVal, maxVal, min_offset, max_offset, mask.data); + } + else if (src.isContinuous()) + { + CALL_HAL(minMaxIdx, cv_hal_minMaxIdx, src.data, 0, (int)src.total()*cn, 1, src.depth(), + minVal, maxVal, min_offset, max_offset, mask.data); + } CV_OVX_RUN(!ovx::skipSmallImages(src.cols, src.rows), openvx_minMaxIdx(src, minVal, maxVal, minIdx, maxIdx, mask)) From 5bd64e09a360e9fa342fbd951a3635f065bc478e Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Wed, 8 May 2024 16:45:08 +0200 Subject: [PATCH 038/119] Merge pull request #25554 from savuor:rv/hal_lut Merge pull request #25554 from savuor:rv/hal_lut HAL for LUT added #25554 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/core/src/hal_replacement.hpp | 26 ++++++++++++++++++++++++++ modules/core/src/lut.cpp | 3 +++ 2 files changed, 29 insertions(+) diff --git a/modules/core/src/hal_replacement.hpp b/modules/core/src/hal_replacement.hpp index 498cd6370019..bbdfc1e180ec 100644 --- a/modules/core/src/hal_replacement.hpp +++ b/modules/core/src/hal_replacement.hpp @@ -214,6 +214,32 @@ inline int hal_ni_not8u(const uchar *src_data, size_t src_step, uchar *dst_data, #define cv_hal_not8u hal_ni_not8u //! @endcond +/** +Lookup table replacement +Table consists of 256 elements of a size from 1 to 8 bytes having 1 channel or src_channels +For 8s input type 128 is added to LUT index +Destination should have the same element type and number of channels as lookup table elements +@param src_data Source image data +@param src_step Source image step +@param src_type Sorce image type +@param lut_data Pointer to lookup table +@param lut_channel_size Size of each channel in bytes +@param lut_channels Number of channels in lookup table +@param dst_data Destination data +@param dst_step Destination step +@param width Width of images +@param height Height of images +@sa LUT +*/ +//! @addtogroup core_hal_interface_lut Lookup table +//! @{ +inline int hal_ni_lut(const uchar *src_data, size_t src_step, size_t src_type, const uchar* lut_data, size_t lut_channel_size, size_t lut_channels, uchar *dst_data, size_t dst_step, int width, int height) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +//! @} + +//! @cond IGNORED +#define cv_hal_lut hal_ni_lut +//! @endcond + /** Hamming norm of a vector @param a pointer to vector data diff --git a/modules/core/src/lut.cpp b/modules/core/src/lut.cpp index f5dc205082a0..cb2b9e7b5677 100644 --- a/modules/core/src/lut.cpp +++ b/modules/core/src/lut.cpp @@ -377,6 +377,9 @@ void cv::LUT( InputArray _src, InputArray _lut, OutputArray _dst ) CV_OVX_RUN(!ovx::skipSmallImages(src.cols, src.rows), openvx_LUT(src, dst, lut)) + CALL_HAL(LUT, cv_hal_lut, src.data, src.step, src.type(), lut.data, + lut.elemSize1(), lutcn, dst.data, dst.step, src.rows, src.cols); + #if !IPP_DISABLE_PERF_LUT CV_IPP_RUN(_src.dims() <= 2, ipp_lut(src, lut, dst)); #endif From 1f1ba7e40276043fe363102d34a0781920ff29f3 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov <2536374+asmorkalov@users.noreply.github.com> Date: Wed, 8 May 2024 18:57:02 +0300 Subject: [PATCH 039/119] Merge pull request #25563 from asmorkalov:as/HAL_min_max_idx Transform offset to indeces for MatND in minMaxIdx HAL #25563 Address comments in https://github.com/opencv/opencv/pull/25553 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/core/src/minmax.cpp | 25 ++++++++++++++++++------- modules/core/test/test_arithm.cpp | 27 ++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/modules/core/src/minmax.cpp b/modules/core/src/minmax.cpp index b5aa4c84627f..8d4d185a5468 100644 --- a/modules/core/src/minmax.cpp +++ b/modules/core/src/minmax.cpp @@ -1510,18 +1510,29 @@ void cv::minMaxIdx(InputArray _src, double* minVal, Mat src = _src.getMat(), mask = _mask.getMat(); - int _minIdx, _maxIdx; - int* min_offset = (cn == 1) ? minIdx : &_minIdx; - int* max_offset = (cn == 1) ? maxIdx : &_maxIdx; if (src.dims <= 2) { - CALL_HAL(minMaxIdx, cv_hal_minMaxIdx, src.data, src.step, src.cols*cn, src.rows, src.depth(), - minVal, maxVal, min_offset, max_offset, mask.data); + CALL_HAL(minMaxIdx, cv_hal_minMaxIdx, src.data, src.step, src.cols*cn, src.rows, + src.depth(), minVal, maxVal, minIdx, maxIdx, mask.data); } else if (src.isContinuous()) { - CALL_HAL(minMaxIdx, cv_hal_minMaxIdx, src.data, 0, (int)src.total()*cn, 1, src.depth(), - minVal, maxVal, min_offset, max_offset, mask.data); + int res = cv_hal_minMaxIdx(src.data, 0, (int)src.total()*cn, 1, src.depth(), + minVal, maxVal, minIdx, maxIdx, mask.data); + + if (res == CV_HAL_ERROR_OK) + { + if (minIdx) + ofs2idx(src, minIdx[0], minIdx); + if (maxIdx) + ofs2idx(src, maxIdx[0], maxIdx); + return; + } + else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) + { + CV_Error_(cv::Error::StsInternal, + ("HAL implementation minMaxIdx ==> " CVAUX_STR(cv_hal_minMaxIdx) " returned %d (0x%08x)", res, res)); + } } CV_OVX_RUN(!ovx::skipSmallImages(src.cols, src.rows), diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index 73c755b0fa18..7733d3351924 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -2446,6 +2446,32 @@ TEST(Core_minMaxIdx, regression_9207_2) EXPECT_EQ(14, maxIdx[1]); } +TEST(Core_MinMaxIdx, MatND) +{ + const int shape[3] = {5,5,3}; + cv::Mat src = cv::Mat(3, shape, CV_8UC1); + src.setTo(1); + src.data[1] = 0; + src.data[5*5*3-2] = 2; + + int minIdx[3]; + int maxIdx[3]; + double minVal, maxVal; + + cv::minMaxIdx(src, &minVal, &maxVal, minIdx, maxIdx); + + EXPECT_EQ(0, minVal); + EXPECT_EQ(2, maxVal); + + EXPECT_EQ(0, minIdx[0]); + EXPECT_EQ(0, minIdx[1]); + EXPECT_EQ(1, minIdx[2]); + + EXPECT_EQ(4, maxIdx[0]); + EXPECT_EQ(4, maxIdx[1]); + EXPECT_EQ(1, maxIdx[2]); +} + TEST(Core_Set, regression_11044) { Mat testFloat(Size(3, 3), CV_32FC1); @@ -2807,7 +2833,6 @@ TEST(Core_MinMaxIdx, rows_overflow) } } - TEST(Core_Magnitude, regression_19506) { for (int N = 1; N <= 64; ++N) From 55eebe81c3bd8a7145a329efc5aaaa423da23098 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Thu, 9 May 2024 08:30:36 +0300 Subject: [PATCH 040/119] Synchornized cv::moments documentation with actual implementation. --- modules/imgproc/include/opencv2/imgproc.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 5da8cf3ef460..677450f68eb9 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -3793,8 +3793,8 @@ CV_EXPORTS_W void demosaicing(InputArray src, OutputArray dst, int code, int dst The function computes moments, up to the 3rd order, of a vector shape or a rasterized shape. The results are returned in the structure cv::Moments. -@param array Raster image (single-channel, 8-bit or floating-point 2D array) or an array ( -\f$1 \times N\f$ or \f$N \times 1\f$ ) of 2D points (Point or Point2f ). +@param array Single chanel raster image (CV_8U, CV_16U, CV_16S, CV_32F, CV_64F) or an array ( +\f$1 \times N\f$ or \f$N \times 1\f$ ) of 2D points (Point or Point2f). @param binaryImage If it is true, all non-zero image pixels are treated as 1's. The parameter is used for images only. @returns moments. From 1d9a4120fa7dbeab6316c255d283c16cd006a35e Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Thu, 9 May 2024 07:37:55 +0200 Subject: [PATCH 041/119] Merge pull request #25565 from savuor:rv/hal_eq_hist Merge pull request #25565 from savuor/rv/hal_eq_hist HAL for equalizeHist() added #25565 fixes #25530 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/imgproc/src/hal_replacement.hpp | 15 +++++++++++++++ modules/imgproc/src/histogram.cpp | 2 ++ 2 files changed, 17 insertions(+) diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index 28bfd310900f..304877cb8bdc 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -903,6 +903,21 @@ inline int hal_ni_boxFilter(const uchar* src_data, size_t src_step, uchar* dst_d #define cv_hal_boxFilter hal_ni_boxFilter //! @endcond +/** + @brief Equalizes the histogram of a grayscale image + @param src_data Source image data + @param src_step Source image step + @param dst_data Destination image data + @param dst_step Destination image step + @param width Source image width + @param height Source image height +*/ +inline int hal_ni_equalize_hist(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +//! @cond IGNORED +#define cv_hal_equalize_hist hal_ni_equalize_hist +//! @endcond + /** @brief Blurs an image using a generic Gaussian filter. @param src_data Source image data diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 99d5e7b1d8ba..02e97ba1296b 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -3452,6 +3452,8 @@ void cv::equalizeHist( InputArray _src, OutputArray _dst ) CV_OVX_RUN(!ovx::skipSmallImages(src.cols, src.rows), openvx_equalize_hist(src, dst)) + CALL_HAL(equalizeHist, cv_hal_equalize_hist, src.data, src.step, dst.data, dst.step, src.cols, src.rows); + Mutex histogramLockInstance; const int hist_sz = EqualizeHistCalcHist_Invoker::HIST_SZ; From 78c9793d5b30ac3faaeed8cc633d2661016870de Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Mon, 13 May 2024 14:16:31 +0300 Subject: [PATCH 042/119] doc: fix env change method in the environment reference --- .../introduction/env_reference/env_reference.markdown | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/tutorials/introduction/env_reference/env_reference.markdown b/doc/tutorials/introduction/env_reference/env_reference.markdown index 0e4f7fe0be3a..c25ea9e533d9 100644 --- a/doc/tutorials/introduction/env_reference/env_reference.markdown +++ b/doc/tutorials/introduction/env_reference/env_reference.markdown @@ -46,10 +46,16 @@ MY_ENV_VARIABLE=true ./my_app ```.py import os -os.environ["MY_ENV_VARIABLE"] = True +os.environ["MY_ENV_VARIABLE"] = "True" # value must be a string import cv2 # variables set after this may not have effect ``` +@note This method may not work on all operating systems and/or Python distributions. For example, it works on Ubuntu Linux with system Python interpreter, but doesn't work on Windows 10 with the official Python package. It depends on the ability of a process to change its own environment (OpenCV uses `getenv` from C++ runtime to read variables). + +@note See also: +- https://docs.python.org/3.12/library/os.html#os.environ +- https://stackoverflow.com/questions/69199708/setenvironmentvariable-does-not-seem-to-set-values-that-can-be-retrieved-by-ge + ## Types From 8dc9ff5624fafc4bde69b108ce6e4a468ae3a294 Mon Sep 17 00:00:00 2001 From: Kumataro Date: Mon, 13 May 2024 20:26:24 +0900 Subject: [PATCH 043/119] Merge pull request #25551 from Kumataro:fix25550 highgui: wayland: fix to pass highgui test #25551 Close #25550 - optimize Mat to XRGB8888 conversion with OpenCV functions - extend to support CV_8S/16U/16S/32F/64F - extend to support 1/4 channels - fix to update value timing - initilize slider_ value if value is not nullptr. - Update user-ptr value and call on_change() function if cv_wl_trackbar::draw() is not called. - Update usage of WAYLAND/XDG macro to avoid reference undefined macro. - Update documents ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/highgui/include/opencv2/highgui.hpp | 13 ++ modules/highgui/src/precomp.hpp | 1 + modules/highgui/src/window.cpp | 2 + modules/highgui/src/window_wayland.cpp | 138 +++++++++++++++----- modules/highgui/test/test_gui.cpp | 10 ++ 5 files changed, 133 insertions(+), 31 deletions(-) diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index 8175bd08718f..35b64bceae90 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -366,6 +366,11 @@ for image display). **waitKey(25)** will display a frame and wait approximately press (suitable for displaying a video frame-by-frame). To remove the window, use cv::destroyWindow. @note [__Windows Backend Only__] Pressing Ctrl+C will copy the image to the clipboard. Pressing Ctrl+S will show a dialog to save the image. +@note [__Wayland Backend Only__] Supoorting format is extended. +- If the image is 8-bit signed, the pixels are biased by 128. That is, the + value range [-128,127] is mapped to [0,255]. +- If the image is 16-bit signed, the pixels are divided by 256 and biased by 128. That is, the + value range [-32768,32767] is mapped to [0,255]. @param winname Name of the window. @param mat Image to be shown. @@ -394,6 +399,8 @@ CV_EXPORTS_W void resizeWindow(const String& winname, const cv::Size& size); @param winname Name of the window. @param x The new x-coordinate of the window. @param y The new y-coordinate of the window. + +@note [__Wayland Backend Only__] This function is not supported by the Wayland protocol limitation. */ CV_EXPORTS_W void moveWindow(const String& winname, int x, int y); @@ -404,6 +411,8 @@ The function setWindowProperty enables changing properties of a window. @param winname Name of the window. @param prop_id Window property to edit. The supported operation flags are: (cv::WindowPropertyFlags) @param prop_value New value of the window property. The supported flags are: (cv::WindowFlags) + +@note [__Wayland Backend Only__] This function is not supported. */ CV_EXPORTS_W void setWindowProperty(const String& winname, int prop_id, double prop_value); @@ -421,6 +430,8 @@ The function getWindowProperty returns properties of a window. @param prop_id Window property to retrieve. The following operation flags are available: (cv::WindowPropertyFlags) @sa setWindowProperty + +@note [__Wayland Backend Only__] This function is not supported. */ CV_EXPORTS_W double getWindowProperty(const String& winname, int prop_id); @@ -431,6 +442,8 @@ The function getWindowImageRect returns the client screen coordinates, width and @param winname Name of the window. @sa resizeWindow moveWindow + +@note [__Wayland Backend Only__] This function is not supported by the Wayland protocol limitation. */ CV_EXPORTS_W Rect getWindowImageRect(const String& winname); diff --git a/modules/highgui/src/precomp.hpp b/modules/highgui/src/precomp.hpp index 9f0ea59b6044..2bbfd6c14a0d 100644 --- a/modules/highgui/src/precomp.hpp +++ b/modules/highgui/src/precomp.hpp @@ -98,6 +98,7 @@ void cvSetModeWindow_WinRT(const char* name, double prop_value); CvRect cvGetWindowRect_W32(const char* name); CvRect cvGetWindowRect_GTK(const char* name); CvRect cvGetWindowRect_COCOA(const char* name); +CvRect cvGetWindowRect_WAYLAND(const char* name); double cvGetModeWindow_W32(const char* name); double cvGetModeWindow_GTK(const char* name); diff --git a/modules/highgui/src/window.cpp b/modules/highgui/src/window.cpp index a41e2313c8b0..e6972b300b02 100644 --- a/modules/highgui/src/window.cpp +++ b/modules/highgui/src/window.cpp @@ -436,6 +436,8 @@ cv::Rect cv::getWindowImageRect(const String& winname) return cvGetWindowRect_GTK(winname.c_str()); #elif defined (HAVE_COCOA) return cvGetWindowRect_COCOA(winname.c_str()); + #elif defined (HAVE_WAYLAND) + return cvGetWindowRect_WAYLAND(winname.c_str()); #else return Rect(-1, -1, -1, -1); #endif diff --git a/modules/highgui/src/window_wayland.cpp b/modules/highgui/src/window_wayland.cpp index 44f30bd0befb..ee1d50207d56 100644 --- a/modules/highgui/src/window_wayland.cpp +++ b/modules/highgui/src/window_wayland.cpp @@ -84,20 +84,73 @@ static int xkb_keysym_to_ascii(xkb_keysym_t keysym) { return static_cast(keysym & 0xff); } +static void write_mat_to_xrgb8888(cv::Mat const &img_, void *data) { + // Validate destination data. + CV_CheckFalse((data == nullptr), "Destination Address must not be nullptr."); + + // Validate source img parameters. + CV_CheckFalse(img_.empty(), "Source Mat must not be empty."); + const int ncn = img_.channels(); + CV_CheckType(img_.type(), + ( (ncn == 1) || (ncn == 3) || (ncn == 4)), + "Unsupported channels, please convert to 1, 3 or 4 channels" + ); -static void draw_xrgb8888(void *d, uint8_t a, uint8_t r, uint8_t g, uint8_t b) { - *((uint32_t *) d) = ((a << 24) | (r << 16) | (g << 8) | b); -} - -static void write_mat_to_xrgb8888(cv::Mat const &img, void *data) { - CV_Assert(data != nullptr); - CV_Assert(img.isContinuous()); + // The supported Mat depth is according to imshow() specification. + const int depth = CV_MAT_DEPTH(img_.type()); + CV_CheckDepth(img_.type(), + ( (depth == CV_8U) || (depth == CV_8S) || + (depth == CV_16U) || (depth == CV_16S) || + (depth == CV_32F) || (depth == CV_64F) ), + "Unsupported depth, please convert to CV_8U" + ); - for (int y = 0; y < img.rows; y++) { - for (int x = 0; x < img.cols; x++) { - auto p = img.at(y, x); - draw_xrgb8888((char *) data + (y * img.cols + x) * 4, 0x00, p[2], p[1], p[0]); - } + // Convert to CV_8U + cv::Mat img; + const int mtype = CV_MAKE_TYPE(CV_8U, ncn); + switch(CV_MAT_DEPTH(depth)) + { + case CV_8U: + img = img_; // do nothing. + break; + case CV_8S: + // [-128,127] -> [0,255] + img_.convertTo(img, mtype, 1.0, 128); + break; + case CV_16U: + // [0,65535] -> [0,255] + img_.convertTo(img, mtype, 1.0/255. ); + break; + case CV_16S: + // [-32768,32767] -> [0,255] + img_.convertTo(img, mtype, 1.0/255. , 128); + break; + case CV_32F: + case CV_64F: + // [0, 1] -> [0,255] + img_.convertTo(img, mtype, 255.); + break; + default: + // it cannot be reachable. + break; + } + CV_CheckDepthEQ(CV_MAT_DEPTH(img.type()), CV_8U, "img should be CV_8U"); + + // XRGB8888 in Little Endian(Wayland Request) = [B8:G8:R8:X8] in data array. + // X is not used to show. So we can use cvtColor() with GRAY2BGRA or BGR2BGRA or copyTo(). + cv::Mat dst(img.size(), CV_MAKE_TYPE(CV_8U, 4), (uint8_t*)data); + if(ncn == 1) + { + cvtColor(img, dst, cv::COLOR_GRAY2BGRA); + } + else if(ncn == 3) + { + cvtColor(img, dst, cv::COLOR_BGR2BGRA); + } + else + { + CV_CheckTrue(ncn==4, "Unexpected channels"); + img.copyTo(dst); } } @@ -232,10 +285,10 @@ class cv_wl_mouse { &handle_pointer_axis, &handle_pointer_frame, &handle_pointer_axis_source, &handle_pointer_axis_stop, &handle_pointer_axis_discrete, -#if WL_POINTER_AXIS_VALUE120_SINCE_VERSION >= 8 +#ifdef WL_POINTER_AXIS_VALUE120_SINCE_VERSION &handle_axis_value120, #endif -#if WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION >= 9 +#ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION &handle_axis_relative_direction, #endif }; @@ -284,7 +337,7 @@ class cv_wl_mouse { CV_UNUSED(discrete); } -#if WL_POINTER_AXIS_VALUE120_SINCE_VERSION >= 8 +#ifdef WL_POINTER_AXIS_VALUE120_SINCE_VERSION static void handle_axis_value120(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t value120) { CV_UNUSED(data); @@ -294,7 +347,7 @@ class cv_wl_mouse { } #endif -#if WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION >= 9 +#ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION static void handle_axis_relative_direction(void *data, struct wl_pointer *wl_pointer, uint32_t axis, uint32_t direction) { CV_UNUSED(data); @@ -686,7 +739,7 @@ class cv_wl_window { void show_image(cv::Mat const &image); - void create_trackbar(std::string const &name, int *value, int count, CvTrackbarCallback2 on_change, void *userdata); + int create_trackbar(std::string const &name, int *value, int count, CvTrackbarCallback2 on_change, void *userdata); weak_ptr get_trackbar(std::string const &) const; @@ -723,10 +776,10 @@ class cv_wl_window { struct xdg_toplevel *xdg_toplevel_; struct xdg_toplevel_listener xdgtop_listener_{ &handle_toplevel_configure, &handle_toplevel_close, -#if XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION >= 4 +#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION &handle_toplevel_configure_bounds, #endif -#if XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION >= 5 +#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION &handle_toplevel_wm_capabilities, #endif }; @@ -775,7 +828,7 @@ class cv_wl_window { static void handle_toplevel_close(void *data, struct xdg_toplevel *surface); -#if XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION >= 4 +#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION static void handle_toplevel_configure_bounds(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height) { @@ -786,7 +839,7 @@ class cv_wl_window { } #endif -#if XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION >= 5 +#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION static void handle_toplevel_wm_capabilities(void *data, struct xdg_toplevel *xdg_toplevel, struct wl_array *capabilities) { @@ -1527,13 +1580,7 @@ cv_wl_viewer::cv_wl_viewer(cv_wl_window *window, int flags) } void cv_wl_viewer::set_image(cv::Mat const &image) { - if (image.type() == CV_8UC1) { - cv::Mat bgr; - cv::cvtColor(image, bgr, CV_GRAY2BGR); - image_ = bgr.clone(); - } else { - image_ = image.clone(); - } + image_ = image.clone(); image_changed_ = true; } @@ -1642,6 +1689,11 @@ cv_wl_trackbar::cv_wl_trackbar(cv_wl_window *window, std::string name, on_change_.value = value; on_change_.data = data; on_change_.callback = on_change; + + // initilize slider_.value if value is not nullptr. + if (value != nullptr){ + set_pos(*value); + } } std::string const &cv_wl_trackbar::name() const { @@ -1657,6 +1709,12 @@ void cv_wl_trackbar::set_pos(int value) { slider_.value = value; slider_moved_ = true; window_->show(); + + // Update user-ptr value and call on_change() function if cv_wl_trackbar::draw() is not called. + if(slider_moved_) { + on_change_.update(slider_.value); + on_change_.call(slider_.value); + } } } @@ -1666,6 +1724,12 @@ void cv_wl_trackbar::set_max(int maxval) { slider_.value = maxval; slider_moved_ = true; window_->show(); + + // Update user-ptr and call on_change() function if cv_wl_trackbar::draw() is not called. + if(slider_moved_) { + on_change_.update(slider_.value); + on_change_.call(slider_.value); + } } } @@ -1836,8 +1900,9 @@ void cv_wl_window::show_image(cv::Mat const &image) { this->show(); } -void cv_wl_window::create_trackbar(std::string const &name, int *value, int count, CvTrackbarCallback2 on_change, +int cv_wl_window::create_trackbar(std::string const &name, int *value, int count, CvTrackbarCallback2 on_change, void *userdata) { + int ret = 0; auto exists = this->get_trackbar(name).lock(); if (!exists) { auto trackbar = @@ -1846,7 +1911,9 @@ void cv_wl_window::create_trackbar(std::string const &name, int *value, int coun ); widgets_.emplace_back(trackbar); widget_geometries_.emplace_back(0, 0, 0, 0); + ret = 1; } + return ret; } weak_ptr cv_wl_window::get_trackbar(std::string const &trackbar_name) const { @@ -2324,6 +2391,7 @@ std::string const &cv_wl_core::get_window_name(void *handle) { } bool cv_wl_core::create_window(std::string const &name, int flags) { + CV_CheckTrue(display_ != nullptr, "Display is not connected."); auto window = std::make_shared(display_, name, flags); auto result = windows_.insert(std::make_pair(name, window)); handles_[window.get()] = window->get_title(); @@ -2402,6 +2470,13 @@ CV_IMPL void cvResizeWindow(const char *name, int width, int height) { throw_system_error("Could not get window name", errno) } +CvRect cvGetWindowRect_WAYLAND(const char* name) +{ + CV_UNUSED(name); + CV_LOG_ONCE_WARNING(nullptr, "Function not implemented: User cannot get window rect in Wayland"); + return cvRect(-1, -1, -1, -1); +} + CV_IMPL int cvCreateTrackbar(const char *name_bar, const char *window_name, int *value, int count, CvTrackbarCallback on_change) { CV_UNUSED(name_bar); @@ -2416,10 +2491,11 @@ CV_IMPL int cvCreateTrackbar(const char *name_bar, const char *window_name, int CV_IMPL int cvCreateTrackbar2(const char *trackbar_name, const char *window_name, int *val, int count, CvTrackbarCallback2 on_notify, void *userdata) { + int ret = 0; if (auto window = CvWlCore::getInstance().get_window(window_name)) - window->create_trackbar(trackbar_name, val, count, on_notify, userdata); + ret = window->create_trackbar(trackbar_name, val, count, on_notify, userdata); - return 0; + return ret; } CV_IMPL int cvGetTrackbarPos(const char *trackbar_name, const char *window_name) { diff --git a/modules/highgui/test/test_gui.cpp b/modules/highgui/test/test_gui.cpp index 8991e8072b9a..41304ddf43fe 100644 --- a/modules/highgui/test/test_gui.cpp +++ b/modules/highgui/test/test_gui.cpp @@ -48,6 +48,16 @@ inline void verify_size(const std::string &nm, const cv::Mat &img) { EXPECT_NO_THROW(imshow(nm, img)); EXPECT_EQ(-1, waitKey(200)); + + // see https://github.com/opencv/opencv/issues/25550 + // Wayland backend is not supported getWindowImageRect(). + string framework; + EXPECT_NO_THROW(framework = currentUIFramework()); + if(framework == "WAYLAND") + { + return; + } + Rect rc; EXPECT_NO_THROW(rc = getWindowImageRect(nm)); EXPECT_EQ(rc.size(), img.size()); From 023d80549299d60d164807663b93d4418540c05b Mon Sep 17 00:00:00 2001 From: Letu Ren Date: Mon, 13 May 2024 19:32:00 +0800 Subject: [PATCH 044/119] Fix zlib-ng version parse Currently, zlib-ng version is 'zlib ver #define ZLIB_VERSION "1.3.0.zlib-ng"'. Because ocv_parse_header_version only accepts dot and numbers and doesn't accepts 1.3.0.zlib-ng. This patch changes ocv_parse_header_version to accept all characters between parentheses. --- cmake/OpenCVUtils.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/OpenCVUtils.cmake b/cmake/OpenCVUtils.cmake index 444aa7cedd57..16babb4937ee 100644 --- a/cmake/OpenCVUtils.cmake +++ b/cmake/OpenCVUtils.cmake @@ -1438,7 +1438,7 @@ macro(ocv_parse_header_version LIBNAME HDR_PATH LIBVER) file(STRINGS "${HDR_PATH}" ${LIBNAME}_H REGEX "^#define[ \t]+${LIBVER}[ \t]+\"[^\"]*\".*$" LIMIT_COUNT 1) endif() if(${LIBNAME}_H) - string(REGEX REPLACE "^.*[ \t]${LIBVER}[ \t]+\"([0-9\.]+)\"$" "\\1" ${LIBNAME}_VERSION_STRING "${${LIBNAME}_H}") + string(REGEX REPLACE "^.*[ \t]${LIBVER}[ \t]+\"(.+)\"$" "\\1" ${LIBNAME}_VERSION_STRING "${${LIBNAME}_H}") endif() endmacro() From 1614b8df4e41aba2c368d936f9a5de6a07658a00 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Tue, 14 May 2024 12:45:14 +0300 Subject: [PATCH 045/119] imgproc: fix allocation issue in EMD --- modules/imgproc/src/emd_new.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/modules/imgproc/src/emd_new.cpp b/modules/imgproc/src/emd_new.cpp index 8e901c795ab4..59a6b2434276 100644 --- a/modules/imgproc/src/emd_new.cpp +++ b/modules/imgproc/src/emd_new.cpp @@ -98,7 +98,7 @@ struct EMDSolver int ssize, dsize; float* cost_buf; - Node2D* data_x; + AutoBuffer data_x; Node2D* end_x; Node2D* enter_x; char* is_x; @@ -149,7 +149,7 @@ struct EMDSolver } EMDSolver() : - ssize(0), dsize(0), cost_buf(0), data_x(0), end_x(0), enter_x(0), is_x(0), rows_x(0), + ssize(0), dsize(0), cost_buf(0), end_x(0), enter_x(0), is_x(0), rows_x(0), cols_x(0), u(0), v(0), idx1(0), idx2(0), loop(0), is_used(0), s(0), d(0), delta(0), weight(0), max_cost(0) { @@ -217,14 +217,15 @@ bool EMDSolver::init(const Mat& sign1, area2.allocate(this->delta, ssize * dsize); area2.allocate(this->cost_buf, ssize * dsize); area2.allocate(this->is_x, ssize * dsize); - area2.allocate(this->data_x, ssize + dsize, 64); area2.allocate(this->rows_x, ssize, 64); area2.allocate(this->cols_x, dsize, 64); area2.allocate(this->loop, ssize + dsize + 1, 64); area2.commit(); area2.zeroFill(); - this->end_x = this->data_x; + this->data_x.allocate(ssize + dsize); + + this->end_x = this->data_x.data(); this->max_cost = calcCost(sign1, sign2, dims, dfunc, cost); callRussel(); this->enter_x = (this->end_x)++; @@ -413,8 +414,8 @@ void EMDSolver::solve() double EMDSolver::calcFlow(Mat* flow_) const { double result = 0.; - Node2D* xp = 0; - for (xp = data_x; xp < end_x; xp++) + const Node2D* xp = 0; + for (xp = data_x.data(); xp < end_x; xp++) { float val = xp->val; const int i = xp->i; @@ -673,7 +674,7 @@ int EMDSolver::findLoop() const memset(is_used, 0, this->ssize + this->dsize); Node2D* new_x = loop[0] = enter_x; - is_used[enter_x - data_x] = 1; + is_used[enter_x - data_x.data()] = 1; int steps = 1; do @@ -682,14 +683,14 @@ int EMDSolver::findLoop() const { /* find an unused x in the row */ new_x = this->rows_x[new_x->i]; - while (new_x != 0 && is_used[new_x - data_x]) + while (new_x != 0 && is_used[new_x - data_x.data()]) new_x = new_x->next[0]; } else { /* find an unused x in the column, or the entering x */ new_x = this->cols_x[new_x->j]; - while (new_x != 0 && is_used[new_x - data_x] && new_x != enter_x) + while (new_x != 0 && is_used[new_x - data_x.data()] && new_x != enter_x) new_x = new_x->next[1]; if (new_x == enter_x) break; @@ -699,7 +700,7 @@ int EMDSolver::findLoop() const { /* add x to the loop */ loop[steps++] = new_x; - is_used[new_x - data_x] = 1; + is_used[new_x - data_x.data()] = 1; } else /* didn't find the next x */ { @@ -712,18 +713,18 @@ int EMDSolver::findLoop() const { new_x = new_x->next[i]; } - while (new_x != 0 && is_used[new_x - data_x]); + while (new_x != 0 && is_used[new_x - data_x.data()]); if (new_x == 0) { - is_used[loop[--steps] - data_x] = 0; + is_used[loop[--steps] - data_x.data()] = 0; } } while (new_x == 0 && steps > 0); - is_used[loop[steps - 1] - data_x] = 0; + is_used[loop[steps - 1] - data_x.data()] = 0; loop[steps - 1] = new_x; - is_used[new_x - data_x] = 1; + is_used[new_x - data_x.data()] = 1; } } while (steps > 0); From 7fc8a490f8554939cd44e644075c45facde13757 Mon Sep 17 00:00:00 2001 From: Letu Ren Date: Tue, 14 May 2024 22:22:05 +0800 Subject: [PATCH 046/119] set policy 0148 explicitly Currently, there is an warning when CMake >= 3.27, CMake Warning (dev) at cmake/OpenCVUtils.cmake:144 (find_package): Policy CMP0148 is not set: The FindPythonInterp and FindPythonLibs modules are removed. Run "cmake --help-policy CMP0148" for policy details. Use the cmake_policy command to set the policy and suppress this warning. This patch sets policy 0148 explicitly to suppress the warning. --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9753cf05aaeb..8d79f2a2ba29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,6 +85,10 @@ if(POLICY CMP0146) cmake_policy(SET CMP0146 OLD) # CMake 3.27+: use CMake FindCUDA if available. endif() +if(POLICY CMP0148) + cmake_policy(SET CMP0148 OLD) # CMake 3.27+: use CMake FindPythonInterp and FindPythonLib if available. +endif() + # # Configure OpenCV CMake hooks # From 03507e06b40450244a0489abba8e989d9b337d18 Mon Sep 17 00:00:00 2001 From: alexlyulkov Date: Tue, 14 May 2024 17:41:19 +0300 Subject: [PATCH 047/119] Merge pull request #25518 from alexlyulkov:al/fixed-gemm-openvino Fixed OpenVINO gemm layer #25518 Fixed OpenVINO gemm layer The problem was that our layer didn't properly handle all the possible gemm options in OpenVINO mode Fixes #25472 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/dnn/src/layers/gemm_layer.cpp | 74 ++++++++++--------- ..._conformance_layer_parser_denylist.inl.hpp | 2 - 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/modules/dnn/src/layers/gemm_layer.cpp b/modules/dnn/src/layers/gemm_layer.cpp index bbbb10d2dfb1..ac0914c2c210 100644 --- a/modules/dnn/src/layers/gemm_layer.cpp +++ b/modules/dnn/src/layers/gemm_layer.cpp @@ -289,48 +289,54 @@ class GemmLayerImpl CV_FINAL : public GemmLayer { virtual Ptr initNgraph(const std::vector >& inputs, const std::vector >& nodes) CV_OVERRIDE { - auto ieInpNode = nodes[0].dynamicCast()->node; - std::shared_ptr matmul; + ov::Output nodeA = nodes[0].dynamicCast()->node; + ov::Output nodeB; + if (const_B) + nodeB = std::make_shared(ov::element::f32, getShape(blobs[0]), blobs[0].data); + else + nodeB = nodes[1].dynamicCast()->node; + + int flatten_axis = nodeA.get_shape().size() - nodeB.get_shape().size(); + if (flatten_axis > 0) { + std::vector shape(1 + flatten_axis, 0); + shape[shape.size() - 1] = -1; + nodeA = std::make_shared( + nodeA, + std::make_shared(ov::element::i32, ov::Shape{shape.size()}, shape.data()), + true); + } - if (nodes.size() == 2) + std::shared_ptr nodeAB = std::make_shared(nodeA, nodeB, trans_a, trans_b); + if (alpha != 1.0f) { - auto& inp2 = nodes[1].dynamicCast()->node; - matmul = std::make_shared(ieInpNode, inp2, trans_a, trans_b); + nodeAB = std::make_shared( + nodeAB, + std::make_shared(ov::element::f32, ov::Shape{1}, &alpha)); } - else + + if (!have_bias) + return Ptr(new InfEngineNgraphNode(nodeAB)); + + ov::Output nodeC; + if (const_C) { - std::shared_ptr ieWeights = std::make_shared(ov::element::f32, getShape(blobs[0]), blobs[0].data); - - int flatten_axis = ieInpNode.get_shape().size() - ieWeights->get_shape().size(); - if (flatten_axis > 0) { - std::vector shape(1 + flatten_axis, 0); - shape[shape.size() - 1] = -1; - ieInpNode = std::make_shared( - ieInpNode, - std::make_shared(ov::element::i32, ov::Shape{shape.size()}, shape.data()), - true - ); - } - matmul = std::make_shared(ieInpNode, ieWeights, trans_a, trans_b); + auto shape_C = blobs.back().total() == blobs.back().size[0] ? ov::Shape{blobs.back().total()} : getShape(blobs.back()); + nodeC = std::make_shared(ov::element::f32, shape_C, blobs.back().data); } - if (alpha != 1.0f) { - matmul = std::make_shared(matmul, - std::make_shared(ov::element::f32, ov::Shape{1}, &alpha) - ); + else + { + nodeC = nodes.back().dynamicCast()->node; } - if (have_bias && const_C) { - Mat bias = blobs.back(); - auto shape = bias.total() == bias.size[0] ? ov::Shape{bias.total()} : getShape(bias); - std::shared_ptr bias_node = std::make_shared(ov::element::f32, shape, bias.data); - if (beta != 1.0f) { - bias_node = std::make_shared(bias_node, - std::make_shared(ov::element::f32, ov::Shape{1}, &beta) - ); - } - matmul = std::make_shared(matmul, bias_node, ov::op::AutoBroadcastType::NUMPY); + if (beta != 1.0f) + { + nodeC = std::make_shared( + nodeC, + std::make_shared(ov::element::f32, ov::Shape{1}, &beta)); } - return Ptr(new InfEngineNgraphNode(matmul)); + + auto nodeGemm = std::make_shared(nodeAB, nodeC, ov::op::AutoBroadcastType::NUMPY); + return Ptr(new InfEngineNgraphNode(nodeGemm)); } #endif // HAVE_DNN_NGRAPH diff --git a/modules/dnn/test/test_onnx_conformance_layer_parser_denylist.inl.hpp b/modules/dnn/test/test_onnx_conformance_layer_parser_denylist.inl.hpp index 68f49e5fa4d1..cb008e9670c4 100644 --- a/modules/dnn/test/test_onnx_conformance_layer_parser_denylist.inl.hpp +++ b/modules/dnn/test/test_onnx_conformance_layer_parser_denylist.inl.hpp @@ -121,8 +121,6 @@ "test_gemm_all_attributes", "test_gemm_alpha", "test_gemm_beta", -"test_gemm_default_matrix_bias", -"test_gemm_default_no_bias", "test_gemm_default_scalar_bias", "test_gemm_default_single_elem_vector_bias", "test_gemm_default_vector_bias", From 47a6ffb73c5f921a6a5941568258fcd2b0825d3b Mon Sep 17 00:00:00 2001 From: Kumataro Date: Wed, 15 May 2024 17:00:46 +0900 Subject: [PATCH 048/119] Merge pull request #25561 from Kumataro:fix25560 highgui: wayland: expand image width if title bar cannot be shown Close #25560 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/highgui/src/window_wayland.cpp | 27 ++++++++++++++++++++++++++ modules/highgui/test/test_gui.cpp | 15 ++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/modules/highgui/src/window_wayland.cpp b/modules/highgui/src/window_wayland.cpp index ee1d50207d56..3bf87c06ec22 100644 --- a/modules/highgui/src/window_wayland.cpp +++ b/modules/highgui/src/window_wayland.cpp @@ -623,6 +623,9 @@ class cv_wl_viewer : public cv_wl_widget { cv::Rect last_img_area_; bool image_changed_ = false; + int real_img_width = 0; + cv::Scalar const outarea_color_ = CV_RGB(0, 0, 0); + void *param_ = nullptr; CvMouseCallback callback_ = nullptr; }; @@ -1582,6 +1585,28 @@ cv_wl_viewer::cv_wl_viewer(cv_wl_window *window, int flags) void cv_wl_viewer::set_image(cv::Mat const &image) { image_ = image.clone(); image_changed_ = true; + + // See https://github.com/opencv/opencv/issues/25560 + // If image_ width is too small enough to show title and buttons, expand it. + + // Keep real image width to limit x position for callback functions + real_img_width = image_.size().width; + + // Minimum width of title is not defined, so use button width * 3 instead of it. + const int view_min_width = cv_wl_titlebar::btn_width * 3 + cv_wl_titlebar::titlebar_min_width; + + const int margin = view_min_width - real_img_width; + if(margin > 0) + { + copyMakeBorder(image_, // src + image_, // dst + 0, // top + 0, // bottom + 0, // left + margin, // right + cv::BORDER_CONSTANT, // borderType + outarea_color_ ); // value(color) + } } void cv_wl_viewer::set_mouse_callback(CvMouseCallback callback, void *param) { @@ -1634,6 +1659,8 @@ void cv_wl_viewer::on_mouse(int event, cv::Point const &p, int flag) { int x = static_cast((p.x - last_img_area_.x) * ((double) image_.size().width / last_img_area_.width)); int y = static_cast((p.y - last_img_area_.y) * ((double) image_.size().height / last_img_area_.height)); + + x = cv::min(x, real_img_width); callback_(event, x, y, flag, param_); } } diff --git a/modules/highgui/test/test_gui.cpp b/modules/highgui/test/test_gui.cpp index 41304ddf43fe..96ecbb9341df 100644 --- a/modules/highgui/test/test_gui.cpp +++ b/modules/highgui/test/test_gui.cpp @@ -215,6 +215,21 @@ TEST(Highgui_GUI, trackbar) EXPECT_NO_THROW(destroyAllWindows()); } +// See https://github.com/opencv/opencv/issues/25560 +#if !defined(ENABLE_PLUGINS) +TEST(Highgui_GUI, DISABLED_small_width_image) +#else +TEST(Highgui_GUI, small_width_image) +#endif +{ + const std::string window_name("trackbar_test_window"); + cv::Mat src(1,1,CV_8UC3,cv::Scalar(0)); + EXPECT_NO_THROW(destroyAllWindows()); + ASSERT_NO_THROW(namedWindow(window_name)); + ASSERT_NO_THROW(imshow(window_name, src)); + EXPECT_NO_THROW(waitKey(10)); + EXPECT_NO_THROW(destroyAllWindows()); +} TEST(Highgui_GUI, currentUIFramework) { From 2e07ec1f8723a7f489b2671bf69cdc1d25f8f948 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Wed, 15 May 2024 12:47:22 +0300 Subject: [PATCH 049/119] Restored and extended Highgui test logic for small windows. --- modules/highgui/test/test_gui.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/highgui/test/test_gui.cpp b/modules/highgui/test/test_gui.cpp index 96ecbb9341df..5b72545faf5f 100644 --- a/modules/highgui/test/test_gui.cpp +++ b/modules/highgui/test/test_gui.cpp @@ -216,7 +216,11 @@ TEST(Highgui_GUI, trackbar) } // See https://github.com/opencv/opencv/issues/25560 -#if !defined(ENABLE_PLUGINS) +#if (!defined(ENABLE_PLUGINS) \ + && !defined HAVE_GTK \ + && !defined HAVE_QT \ + && !defined HAVE_WIN32UI \ + && !defined HAVE_WAYLAND) TEST(Highgui_GUI, DISABLED_small_width_image) #else TEST(Highgui_GUI, small_width_image) From c034c46e6945fa20cf192868628a01d58dae243b Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Wed, 15 May 2024 15:41:23 +0300 Subject: [PATCH 050/119] Disable more streaming test in G-API due to instability. --- modules/gapi/test/infer/gapi_infer_ie_test.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/gapi/test/infer/gapi_infer_ie_test.cpp b/modules/gapi/test/infer/gapi_infer_ie_test.cpp index 6cfdbee39427..3998d68099fd 100644 --- a/modules/gapi/test/infer/gapi_infer_ie_test.cpp +++ b/modules/gapi/test/infer/gapi_infer_ie_test.cpp @@ -1582,6 +1582,9 @@ TEST(Infer, SetInvalidNumberOfRequests) TEST(Infer, TestStreamingInfer) { + if (cvtest::skipUnstableTests) + throw SkipTestException("Skip InferROI.TestStreamingInfer as it hangs sporadically"); + initDLDTDataPath(); std::string filepath = findDataFile("cv/video/768x576.avi"); From 76d9f7aaeb8c9ba8aea80bdb155b60c78da1e309 Mon Sep 17 00:00:00 2001 From: Laurent Berger Date: Wed, 15 May 2024 16:08:52 +0200 Subject: [PATCH 051/119] Merge pull request #25591 from LaurentBerger:I25589 Remove dnn::layer::allocate in doc #25591 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work #25589 - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/dnn/include/opencv2/dnn/dnn.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index b86d0e8ec4e4..13cd1754736d 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -214,7 +214,7 @@ CV__DNN_INLINE_NS_BEGIN /** @brief This interface class allows to build new Layers - are building blocks of networks. * - * Each class, derived from Layer, must implement allocate() methods to declare own outputs and forward() to compute outputs. + * Each class, derived from Layer, must implement forward() method to compute outputs. * Also before using the new layer into networks you must register your layer by using one of @ref dnnLayerFactory "LayerFactory" macros. */ class CV_EXPORTS_W Layer : public Algorithm From 50091091673588a1625683b2868e8c79e3f3e6be Mon Sep 17 00:00:00 2001 From: unknown <3591626+LaurentBerger@users.noreply.github.com> Date: Wed, 15 May 2024 16:16:07 +0200 Subject: [PATCH 052/119] typo --- modules/dnn/include/opencv2/dnn/dnn.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index 13cd1754736d..9d0c36d5fe07 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -229,7 +229,7 @@ CV__DNN_INLINE_NS_BEGIN * @param[in] input vector of already allocated input blobs * @param[out] output vector of already allocated output blobs * - * If this method is called after network has allocated all memory for input and output blobs + * This method is called after network has allocated all memory for input and output blobs * and before inferencing. */ CV_DEPRECATED_EXTERNAL @@ -239,7 +239,7 @@ CV__DNN_INLINE_NS_BEGIN * @param[in] inputs vector of already allocated input blobs * @param[out] outputs vector of already allocated output blobs * - * If this method is called after network has allocated all memory for input and output blobs + * This method is called after network has allocated all memory for input and output blobs * and before inferencing. */ CV_WRAP virtual void finalize(InputArrayOfArrays inputs, OutputArrayOfArrays outputs); From 7713c84465b1bbfea112d87ad61312b190a1505d Mon Sep 17 00:00:00 2001 From: CNOCycle <24318472+CNOCycle@users.noreply.github.com> Date: Thu, 16 May 2024 01:07:25 +0800 Subject: [PATCH 053/119] Merge pull request #25297 from CNOCycle:tflite/transpose Support Transpose op in TFlite #25297 **Merge with extra**: https://github.com/opencv/opencv_extra/pull/1168 The purpose of this PR is to introduce support for the Transpose op in TFlite format and to add a shape comparison between the output tensors and the references. In some occasional cases, the shape of the output tensor is `[1,4,1,1]`, while the shape of the reference tensor is `[1,4]`. Consequently, the norm check incorrectly reports that the test has passed, as the residual is zero. Below is a Python script for generating testing data. The generated data can be integrated into the repo `opencv_extra`. ```python import numpy as np import tensorflow as tf PREFIX_TFL = '/path/to/opencv_extra/testdata/dnn/tflite/' def generator(input_tensor, model, saved_name): # convert keras model to .tflite format converter = tf.lite.TFLiteConverter.from_keras_model(model) #converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.optimizations = [None] tflite_model = converter.convert() with open(f'{PREFIX_TFL}/{saved_name}.tflite', 'wb') as f: f.write(tflite_model) # save the input tensor to .npy if input_tensor.ndim == 4: opencv_tensor = np.transpose(input_tensor, (0,3,1,2)) else: opencv_tensor = input_tensor opencv_tensor = np.copy(opencv_tensor, order='C').astype(np.float32) np.save(f'{PREFIX_TFL}/{saved_name}_inp.npy', opencv_tensor) # generate output tenosr and save it to .npy mat_out = model(input_tensor).numpy() mat_out = np.copy(mat_out, order='C').astype(np.float32) if mat_out.ndim == 4: mat_out = np.transpose(mat_out, (0,3,1,2)) interpreter = tf.lite.Interpreter(model_content=tflite_model) out_name = interpreter.get_output_details()[0]['name'] np.save(f'{PREFIX_TFL}/{saved_name}_out_{out_name}.npy', mat_out) def build_transpose(): model_name = "keras_permute" mat_in = np.array([[[1,2,3], [4,5,6]]], dtype=np.float32) model = tf.keras.Sequential() model.add(tf.keras.Input(shape=(2,3))) model.add(tf.keras.layers.Permute((2,1))) model.summary() generator(mat_in, model, model_name) if __name__ == '__main__': build_transpose() ``` ### Pull Request Readiness Checklist - [x] I agree to contribute to the project under Apache 2 License. - [X] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [X] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [X] The feature is well documented and sample code can be built with the project CMake --- modules/dnn/src/tflite/tflite_importer.cpp | 45 ++++++++++++++++++++++ modules/dnn/test/test_tflite_importer.cpp | 9 +++++ 2 files changed, 54 insertions(+) diff --git a/modules/dnn/src/tflite/tflite_importer.cpp b/modules/dnn/src/tflite/tflite_importer.cpp index 8850cd9ad219..1c048ad9d026 100644 --- a/modules/dnn/src/tflite/tflite_importer.cpp +++ b/modules/dnn/src/tflite/tflite_importer.cpp @@ -70,6 +70,7 @@ class TFLiteImporter { void parseFullyConnected(const Operator& op, const std::string& opcode, LayerParams& layerParams); void parseSoftmax(const Operator& op, const std::string& opcode, LayerParams& layerParams); void parseCast(const Operator& op, const std::string& opcode, LayerParams& layerParams); + void parseTranspose(const Operator& op, const std::string& opcode, LayerParams& layerParams); void parseFusedActivation(const Operator& op, ActivationFunctionType activ); void parseActivation(const Operator& op, const std::string& opcode, LayerParams& layerParams, bool isFused); @@ -284,6 +285,7 @@ TFLiteImporter::DispatchMap TFLiteImporter::buildDispatchMap() dispatch["SOFTMAX"] = &TFLiteImporter::parseSoftmax; dispatch["CAST"] = &TFLiteImporter::parseCast; dispatch["TFLite_Detection_PostProcess"] = &TFLiteImporter::parseDetectionPostProcess; + dispatch["TRANSPOSE"] = &TFLiteImporter::parseTranspose; return dispatch; } @@ -719,6 +721,49 @@ void TFLiteImporter::parseResize(const Operator& op, const std::string& opcode, addLayer(layerParams, op); } +void TFLiteImporter::parseTranspose(const Operator& op, const std::string& opcode, LayerParams& layerParams) +{ + layerParams.type = "Permute"; + std::vector perm = allTensors[op.inputs()->Get(1)]; + + DataLayout inpLayout = layouts[op.inputs()->Get(0)]; + if (inpLayout == DNN_LAYOUT_NHWC && perm.size() == 4) { + + // OpenCV operates under the assumption that NCHW format, whereas TFLite defaults to NHWC. + // Therfore, to align these layouts, the axes of the permutation vector should be adjusted accordingly. + // For implementation details, please refer to the disscusion: + // https://github.com/opencv/opencv/pull/25297#issuecomment-2049762298 + + if (perm[0] != 0) { + CV_Error(Error::StsParseError, "The first axis should not be permuted."); + } + if (perm[1] == 1 && perm[2] == 2 && perm[3] == 3) { + std::vector orderLP = {0, 1, 2, 3}; + layerParams.set("order", DictValue::arrayInt(orderLP.data(), orderLP.size())); + layouts[op.outputs()->Get(0)] = DNN_LAYOUT_NCHW; + } + else if (perm[1] == 1 && perm[2] == 3 && perm[3] == 2) { + std::vector orderLP = {0, 3, 2, 1}; + layerParams.set("order", DictValue::arrayInt(orderLP.data(), orderLP.size())); + } + else if (perm[1] == 2 && perm[2] == 1 && perm[3] == 3) { + std::vector orderLP = {0, 1, 3, 2}; + layerParams.set("order", DictValue::arrayInt(orderLP.data(), orderLP.size())); + layouts[op.outputs()->Get(0)] = DNN_LAYOUT_NCHW; + } + else if (perm[1] == 2 && perm[2] == 3 && perm[3] == 1) { + std::vector orderLP = {0, 2, 3, 1}; + layerParams.set("order", DictValue::arrayInt(orderLP.data(), orderLP.size())); + } + + } + else { + layerParams.set("order", DictValue::arrayInt(perm.data(), perm.size())); + } + + addLayer(layerParams, op); +} + int TFLiteImporter::addPermuteLayer(const std::vector& order, const std::string& permName, const std::pair& inpId, int dtype) { diff --git a/modules/dnn/test/test_tflite_importer.cpp b/modules/dnn/test/test_tflite_importer.cpp index 7ad62bf3081a..7621b44ff53d 100644 --- a/modules/dnn/test/test_tflite_importer.cpp +++ b/modules/dnn/test/test_tflite_importer.cpp @@ -251,6 +251,15 @@ TEST_P(Test_TFLite, fully_connected) { testLayer("fully_connected"); } +TEST_P(Test_TFLite, permute) { + testLayer("permutation_3d"); + // Temporarily disabled as TFLiteConverter produces a incorrect graph in this case + //testLayer("permutation_4d_0123"); + testLayer("permutation_4d_0132"); + testLayer("permutation_4d_0213"); + testLayer("permutation_4d_0231"); +} + INSTANTIATE_TEST_CASE_P(/**/, Test_TFLite, dnnBackendsAndTargets()); }} // namespace From 7d6b6161ccde3f1da9e653f2be4897b6e40b91b9 Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Wed, 15 May 2024 22:24:21 +0300 Subject: [PATCH 054/119] Update imgcodecs tests --- modules/highgui/src/window_w32.cpp | 2 +- modules/imgcodecs/perf/perf_jpeg.cpp | 5 +++++ modules/imgcodecs/perf/perf_png.cpp | 5 +++++ modules/imgcodecs/test/test_grfmt.cpp | 6 ++++++ modules/imgcodecs/test/test_read_write.cpp | 2 ++ 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 98f876a34fbd..32b239290407 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -2161,7 +2161,7 @@ static void showSaveDialog(CvWindow& window) #ifdef HAVE_TIFF "TIFF Files (*.tiff;*.tif)\0*.tiff;*.tif\0" #endif -#ifdef HAVE_JASPER +#if defined(HAVE_JASPER) || defined(HAVE_OPENJPEG) "JPEG-2000 files (*.jp2)\0*.jp2\0" #endif #ifdef HAVE_WEBP diff --git a/modules/imgcodecs/perf/perf_jpeg.cpp b/modules/imgcodecs/perf/perf_jpeg.cpp index 694e2e698e6a..7063ca909c9c 100644 --- a/modules/imgcodecs/perf/perf_jpeg.cpp +++ b/modules/imgcodecs/perf/perf_jpeg.cpp @@ -5,6 +5,9 @@ namespace opencv_test { + +#ifdef HAVE_JPEG + using namespace perf; PERF_TEST(JPEG, Decode) @@ -35,4 +38,6 @@ PERF_TEST(JPEG, Encode) SANITY_CHECK_NOTHING(); } +#endif // HAVE_JPEG + } // namespace \ No newline at end of file diff --git a/modules/imgcodecs/perf/perf_png.cpp b/modules/imgcodecs/perf/perf_png.cpp index 7893d841c487..1af4780882fb 100644 --- a/modules/imgcodecs/perf/perf_png.cpp +++ b/modules/imgcodecs/perf/perf_png.cpp @@ -6,6 +6,9 @@ namespace opencv_test { + +#if defined(HAVE_PNG) || defined(HAVE_SPNG) + using namespace perf; typedef perf::TestBaseWithParam PNG; @@ -38,4 +41,6 @@ PERF_TEST(PNG, encode) SANITY_CHECK_NOTHING(); } +#endif // HAVE_PNG + } // namespace diff --git a/modules/imgcodecs/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp index 826f3d983653..1e0bf47b4713 100644 --- a/modules/imgcodecs/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -87,11 +87,17 @@ const string all_images[] = "readwrite/uint16-mono2.dcm", "readwrite/uint8-rgb.dcm", #endif +#if defined(HAVE_PNG) || defined(HAVE_SPNG) "readwrite/color_palette_alpha.png", +#endif +#ifdef HAVE_TIFF "readwrite/multipage.tif", +#endif "readwrite/ordinary.bmp", "readwrite/rle8.bmp", +#ifdef HAVE_JPEG "readwrite/test_1_c1.jpg", +#endif #ifdef HAVE_IMGCODEC_HDR "readwrite/rle.hdr" #endif diff --git a/modules/imgcodecs/test/test_read_write.cpp b/modules/imgcodecs/test/test_read_write.cpp index 2320147a4ecc..39c02ca95cea 100644 --- a/modules/imgcodecs/test/test_read_write.cpp +++ b/modules/imgcodecs/test/test_read_write.cpp @@ -303,6 +303,7 @@ TEST(Imgcodecs_Image, write_umat) EXPECT_EQ(0, remove(dst_name.c_str())); } +#ifdef HAVE_TIFF TEST(Imgcodecs_Image, multipage_collection_size) { const string root = cvtest::TS::ptr()->get_data_path(); @@ -479,6 +480,7 @@ TEST(ImgCodecs, multipage_collection_two_iterator_operatorpp) EXPECT_TRUE(cv::norm(img1, img[i], NORM_INF) == 0); } } +#endif TEST(Imgcodecs_Params, imwrite_regression_22752) From 5f3a505a2da2b71c1bdd2ddbd9eb9ba62bf17f5a Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Thu, 16 May 2024 11:17:35 +0300 Subject: [PATCH 055/119] Added Ubuntu 24.04 to regular CI. --- .github/workflows/PR-4.x.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/PR-4.x.yaml b/.github/workflows/PR-4.x.yaml index 579aa7fb20c6..58858fe495e8 100644 --- a/.github/workflows/PR-4.x.yaml +++ b/.github/workflows/PR-4.x.yaml @@ -21,6 +21,9 @@ jobs: Ubuntu2204-x64: uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-U22.yaml@main + Ubuntu2404-x64: + uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-U24.yaml@main + Ubuntu2004-x64-CUDA: if: "${{ contains(github.event.pull_request.labels.*.name, 'category: dnn') }} || ${{ contains(github.event.pull_request.labels.*.name, 'category: dnn (onnx)') }}" uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-U20-Cuda.yaml@main From d29ad2fb719227d2647466b65a928eac6a907c13 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov <2536374+asmorkalov@users.noreply.github.com> Date: Thu, 16 May 2024 15:29:06 +0300 Subject: [PATCH 056/119] Merge pull request #25443 from asmorkalov:as/kleidicv_hal Integrate ARM KleidiCV as OpenCV HAL #25443 The library source code with license: https://gitlab.arm.com/kleidi/kleidicv/ ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- 3rdparty/kleidicv/CMakeLists.txt | 23 +++++++++++++++++++ CMakeLists.txt | 14 ++++++++++- .../config_reference.markdown | 1 + 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 3rdparty/kleidicv/CMakeLists.txt diff --git a/3rdparty/kleidicv/CMakeLists.txt b/3rdparty/kleidicv/CMakeLists.txt new file mode 100644 index 000000000000..0dd50ae08a76 --- /dev/null +++ b/3rdparty/kleidicv/CMakeLists.txt @@ -0,0 +1,23 @@ +project(kleidicv_hal) + +set(KLEIDICV_SOURCE_PATH "" CACHE PATH "Directory containing KleidiCV sources") +ocv_update(KLEIDICV_SRC_COMMIT "a9971ba8bf1d8b008a32c6ed8fea05cd8eb16748") +ocv_update(KLEIDICV_SRC_HASH "53d1d80620395a12c7fee91460499368") + +if(KLEIDICV_SOURCE_PATH) + set(THE_ROOT "${KLEIDICV_SOURCE_PATH}") +else() + ocv_download(FILENAME "kleidicv-${KLEIDICV_SRC_COMMIT}.tar.gz" + HASH ${KLEIDICV_SRC_HASH} + URL + "${OPENCV_KLEIDICV_URL}" + "$ENV{OPENCV_KLEIDICV_URL}" + "https://gitlab.arm.com/kleidi/kleidicv/-/archive/${KLEIDICV_SRC_COMMIT}/" + DESTINATION_DIR "${OpenCV_BINARY_DIR}/3rdparty/kleidicv/" + ID KLEIDICV + STATUS res + UNPACK RELATIVE_URL) + set(THE_ROOT "${OpenCV_BINARY_DIR}/3rdparty/kleidicv/kleidicv-${KLEIDICV_SRC_COMMIT}") +endif() + +include("${THE_ROOT}/adapters/opencv/CMakeLists.txt") diff --git a/CMakeLists.txt b/CMakeLists.txt index 9753cf05aaeb..92d93f2fe14c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,6 @@ FATAL: In-source builds are not allowed. ") endif() - include(cmake/OpenCVMinDepVersions.cmake) if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore) @@ -258,6 +257,8 @@ OCV_OPTION(WITH_CAP_IOS "Enable iOS video capture" ON VERIFY HAVE_CAP_IOS) OCV_OPTION(WITH_CAROTENE "Use NVidia carotene acceleration library for ARM platform" (NOT CV_DISABLE_OPTIMIZATION) VISIBLE_IF (ARM OR AARCH64) AND NOT IOS AND NOT XROS) +OCV_OPTION(WITH_KLEIDICV "Use KleidiCV library for ARM platforms" OFF + VISIBLE_IF (AARCH64 AND (ANDROID OR UNIX AND NOT IOS AND NOT XROS))) OCV_OPTION(WITH_CPUFEATURES "Use cpufeatures Android library" ON VISIBLE_IF ANDROID VERIFY HAVE_CPUFEATURES) @@ -966,6 +967,13 @@ if(HAVE_OPENVX) endif() endif() +if(WITH_KLEIDICV) + ocv_debug_message(STATUS "Enable KleidiCV acceleration") + if(NOT ";${OpenCV_HAL};" MATCHES ";kleidicv;") + set(OpenCV_HAL "kleidicv;${OpenCV_HAL}") + endif() +endif() + if(WITH_CAROTENE) ocv_debug_message(STATUS "Enable carotene acceleration") if(NOT ";${OpenCV_HAL};" MATCHES ";carotene;") @@ -990,6 +998,10 @@ foreach(hal ${OpenCV_HAL}) else() message(STATUS "Carotene: NEON is not available, disabling carotene...") endif() + elseif(hal STREQUAL "kleidicv") + add_subdirectory(3rdparty/kleidicv) + ocv_hal_register(KLEIDICV_HAL_LIBRARIES KLEIDICV_HAL_HEADERS KLEIDICV_HAL_INCLUDE_DIRS) + list(APPEND OpenCV_USED_HAL "KleidiCV (ver ${KLEIDICV_HAL_VERSION})") elseif(hal STREQUAL "openvx") add_subdirectory(3rdparty/openvx) ocv_hal_register(OPENVX_HAL_LIBRARIES OPENVX_HAL_HEADERS OPENVX_HAL_INCLUDE_DIRS) diff --git a/doc/tutorials/introduction/config_reference/config_reference.markdown b/doc/tutorials/introduction/config_reference/config_reference.markdown index dba280485fd3..7ced9a2536b1 100644 --- a/doc/tutorials/introduction/config_reference/config_reference.markdown +++ b/doc/tutorials/introduction/config_reference/config_reference.markdown @@ -623,6 +623,7 @@ Following build options are utilized in `opencv_contrib` modules, as stated [pre `CMAKE_TOOLCHAIN_FILE` `WITH_CAROTENE` +`WITH_KLEIDICV` `WITH_CPUFEATURES` `WITH_EIGEN` `WITH_OPENVX` From 00440477826a0e7bceaeeaede8351eada5caf38c Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov <2536374+asmorkalov@users.noreply.github.com> Date: Fri, 17 May 2024 10:48:40 +0300 Subject: [PATCH 057/119] Merge pull request #25598 from asmorkalov:as/tables_range_check_core Check range for type-dependant function tables #25598 Address https://github.com/opencv/opencv/issues/24703 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/core/src/arithm.cpp | 26 +++++++++++++----------- modules/core/src/channels.cpp | 3 ++- modules/core/src/convert.simd.hpp | 2 +- modules/core/src/convert_scale.simd.hpp | 4 ++-- modules/core/src/count_non_zero.simd.hpp | 2 +- modules/core/src/has_non_zero.simd.hpp | 2 +- modules/core/src/lut.cpp | 4 ++-- modules/core/src/mathfuncs.cpp | 2 +- modules/core/src/matmul.dispatch.cpp | 2 +- modules/core/src/matmul.simd.hpp | 4 ++-- modules/core/src/matrix_operations.cpp | 4 ++-- modules/core/src/matrix_sparse.cpp | 6 ++++-- modules/core/src/mean.simd.hpp | 2 +- modules/core/src/merge.dispatch.cpp | 2 +- modules/core/src/minmax.cpp | 2 +- modules/core/src/rand.cpp | 2 +- modules/core/src/split.dispatch.cpp | 2 +- modules/core/src/sum.simd.hpp | 2 +- 18 files changed, 39 insertions(+), 34 deletions(-) diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index 9e690fef2fb9..f4ca2d7da966 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -329,7 +329,7 @@ static void binary_op( InputArray _src1, InputArray _src2, OutputArray _dst, static BinaryFuncC* getMaxTab() { - static BinaryFuncC maxTab[] = + static BinaryFuncC maxTab[CV_DEPTH_MAX] = { (BinaryFuncC)GET_OPTIMIZED(cv::hal::max8u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::max8s), (BinaryFuncC)GET_OPTIMIZED(cv::hal::max16u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::max16s), @@ -343,7 +343,7 @@ static BinaryFuncC* getMaxTab() static BinaryFuncC* getMinTab() { - static BinaryFuncC minTab[] = + static BinaryFuncC minTab[CV_DEPTH_MAX] = { (BinaryFuncC)GET_OPTIMIZED(cv::hal::min8u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::min8s), (BinaryFuncC)GET_OPTIMIZED(cv::hal::min16u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::min16s), @@ -617,7 +617,9 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, Mat src1 = psrc1->getMat(), src2 = psrc2->getMat(), dst = _dst.getMat(); Size sz = getContinuousSize2D(src1, src2, dst, src1.channels()); - tab[depth1](src1.ptr(), src1.step, src2.ptr(), src2.step, dst.ptr(), dst.step, sz.width, sz.height, usrdata); + BinaryFuncC func = tab[depth1]; + CV_Assert(func); + func(src1.ptr(), src1.step, src2.ptr(), src2.step, dst.ptr(), dst.step, sz.width, sz.height, usrdata); return; } @@ -868,7 +870,7 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, static BinaryFuncC* getAddTab() { - static BinaryFuncC addTab[] = + static BinaryFuncC addTab[CV_DEPTH_MAX] = { (BinaryFuncC)GET_OPTIMIZED(cv::hal::add8u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::add8s), (BinaryFuncC)GET_OPTIMIZED(cv::hal::add16u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::add16s), @@ -882,7 +884,7 @@ static BinaryFuncC* getAddTab() static BinaryFuncC* getSubTab() { - static BinaryFuncC subTab[] = + static BinaryFuncC subTab[CV_DEPTH_MAX] = { (BinaryFuncC)GET_OPTIMIZED(cv::hal::sub8u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::sub8s), (BinaryFuncC)GET_OPTIMIZED(cv::hal::sub16u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::sub16s), @@ -896,7 +898,7 @@ static BinaryFuncC* getSubTab() static BinaryFuncC* getAbsDiffTab() { - static BinaryFuncC absDiffTab[] = + static BinaryFuncC absDiffTab[CV_DEPTH_MAX] = { (BinaryFuncC)GET_OPTIMIZED(cv::hal::absdiff8u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::absdiff8s), (BinaryFuncC)GET_OPTIMIZED(cv::hal::absdiff16u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::absdiff16s), @@ -949,7 +951,7 @@ namespace cv static BinaryFuncC* getMulTab() { - static BinaryFuncC mulTab[] = + static BinaryFuncC mulTab[CV_DEPTH_MAX] = { (BinaryFuncC)cv::hal::mul8u, (BinaryFuncC)cv::hal::mul8s, (BinaryFuncC)cv::hal::mul16u, (BinaryFuncC)cv::hal::mul16s, (BinaryFuncC)cv::hal::mul32s, (BinaryFuncC)cv::hal::mul32f, @@ -961,7 +963,7 @@ static BinaryFuncC* getMulTab() static BinaryFuncC* getDivTab() { - static BinaryFuncC divTab[] = + static BinaryFuncC divTab[CV_DEPTH_MAX] = { (BinaryFuncC)cv::hal::div8u, (BinaryFuncC)cv::hal::div8s, (BinaryFuncC)cv::hal::div16u, (BinaryFuncC)cv::hal::div16s, (BinaryFuncC)cv::hal::div32s, (BinaryFuncC)cv::hal::div32f, @@ -973,7 +975,7 @@ static BinaryFuncC* getDivTab() static BinaryFuncC* getRecipTab() { - static BinaryFuncC recipTab[] = + static BinaryFuncC recipTab[CV_DEPTH_MAX] = { (BinaryFuncC)cv::hal::recip8u, (BinaryFuncC)cv::hal::recip8s, (BinaryFuncC)cv::hal::recip16u, (BinaryFuncC)cv::hal::recip16s, (BinaryFuncC)cv::hal::recip32s, (BinaryFuncC)cv::hal::recip32f, @@ -1021,7 +1023,7 @@ UMat UMat::mul(InputArray m, double scale) const static BinaryFuncC* getAddWeightedTab() { - static BinaryFuncC addWeightedTab[] = + static BinaryFuncC addWeightedTab[CV_DEPTH_MAX] = { (BinaryFuncC)GET_OPTIMIZED(cv::hal::addWeighted8u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::addWeighted8s), (BinaryFuncC)GET_OPTIMIZED(cv::hal::addWeighted16u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::addWeighted16s), (BinaryFuncC)GET_OPTIMIZED(cv::hal::addWeighted32s), (BinaryFuncC)cv::hal::addWeighted32f, @@ -1052,7 +1054,7 @@ namespace cv static BinaryFuncC getCmpFunc(int depth) { - static BinaryFuncC cmpTab[] = + static BinaryFuncC cmpTab[CV_DEPTH_MAX] = { (BinaryFuncC)GET_OPTIMIZED(cv::hal::cmp8u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::cmp8s), (BinaryFuncC)GET_OPTIMIZED(cv::hal::cmp16u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::cmp16s), @@ -1588,7 +1590,7 @@ typedef void (*InRangeFunc)( const uchar* src1, size_t step1, const uchar* src2, static InRangeFunc getInRangeFunc(int depth) { - static InRangeFunc inRangeTab[] = + static InRangeFunc inRangeTab[CV_DEPTH_MAX] = { (InRangeFunc)GET_OPTIMIZED(inRange8u), (InRangeFunc)GET_OPTIMIZED(inRange8s), (InRangeFunc)GET_OPTIMIZED(inRange16u), (InRangeFunc)GET_OPTIMIZED(inRange16s), (InRangeFunc)GET_OPTIMIZED(inRange32s), (InRangeFunc)GET_OPTIMIZED(inRange32f), diff --git a/modules/core/src/channels.cpp b/modules/core/src/channels.cpp index efaeb91068a7..3ee7088a4f2c 100644 --- a/modules/core/src/channels.cpp +++ b/modules/core/src/channels.cpp @@ -79,7 +79,7 @@ typedef void (*MixChannelsFunc)( const void** src, const int* sdelta, static MixChannelsFunc getMixchFunc(int depth) { - static MixChannelsFunc mixchTab[] = + static MixChannelsFunc mixchTab[CV_DEPTH_MAX] = { mixChannels8u, mixChannels8u, mixChannels16u, mixChannels16u, mixChannels32s, mixChannels32s, @@ -146,6 +146,7 @@ void cv::mixChannels( const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, cons NAryMatIterator it(arrays, ptrs, (int)(nsrcs + ndsts)); int total = (int)it.size, blocksize = std::min(total, (int)((BLOCK_SIZE + esz1-1)/esz1)); MixChannelsFunc func = getMixchFunc(depth); + CV_Assert(func); for( i = 0; i < it.nplanes; i++, ++it ) { diff --git a/modules/core/src/convert.simd.hpp b/modules/core/src/convert.simd.hpp index 524c43a16ed8..d6c18a70b5be 100644 --- a/modules/core/src/convert.simd.hpp +++ b/modules/core/src/convert.simd.hpp @@ -372,7 +372,7 @@ DEF_CPY_FUNC(64s, int64) BinaryFunc getConvertFunc(int sdepth, int ddepth) { - static BinaryFunc cvtTab[][8] = + static BinaryFunc cvtTab[CV_DEPTH_MAX][CV_DEPTH_MAX] = { { (cvt8u), (cvt8s8u), (cvt16u8u), diff --git a/modules/core/src/convert_scale.simd.hpp b/modules/core/src/convert_scale.simd.hpp index ef6aa343e262..b5322ed88834 100644 --- a/modules/core/src/convert_scale.simd.hpp +++ b/modules/core/src/convert_scale.simd.hpp @@ -299,7 +299,7 @@ DEF_CVT_SCALE_FUNC(16f, cvt1_32f, hfloat, hfloat, float) BinaryFunc getCvtScaleAbsFunc(int depth) { - static BinaryFunc cvtScaleAbsTab[] = + static BinaryFunc cvtScaleAbsTab[CV_DEPTH_MAX] = { (BinaryFunc)cvtScaleAbs8u, (BinaryFunc)cvtScaleAbs8s8u, (BinaryFunc)cvtScaleAbs16u8u, (BinaryFunc)cvtScaleAbs16s8u, (BinaryFunc)cvtScaleAbs32s8u, (BinaryFunc)cvtScaleAbs32f8u, @@ -311,7 +311,7 @@ BinaryFunc getCvtScaleAbsFunc(int depth) BinaryFunc getConvertScaleFunc(int sdepth, int ddepth) { - static BinaryFunc cvtScaleTab[][8] = + static BinaryFunc cvtScaleTab[CV_DEPTH_MAX][CV_DEPTH_MAX] = { { (BinaryFunc)GET_OPTIMIZED(cvtScale8u), (BinaryFunc)GET_OPTIMIZED(cvtScale8s8u), (BinaryFunc)GET_OPTIMIZED(cvtScale16u8u), diff --git a/modules/core/src/count_non_zero.simd.hpp b/modules/core/src/count_non_zero.simd.hpp index ce7c75aa5444..9de616fe8ae5 100644 --- a/modules/core/src/count_non_zero.simd.hpp +++ b/modules/core/src/count_non_zero.simd.hpp @@ -196,7 +196,7 @@ static int countNonZero64f( const double* src, int len ) CountNonZeroFunc getCountNonZeroTab(int depth) { - static CountNonZeroFunc countNonZeroTab[] = + static CountNonZeroFunc countNonZeroTab[CV_DEPTH_MAX] = { (CountNonZeroFunc)GET_OPTIMIZED(countNonZero8u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero8u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero16u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero16u), diff --git a/modules/core/src/has_non_zero.simd.hpp b/modules/core/src/has_non_zero.simd.hpp index e9f9b683d695..29a1de0113cd 100644 --- a/modules/core/src/has_non_zero.simd.hpp +++ b/modules/core/src/has_non_zero.simd.hpp @@ -310,7 +310,7 @@ static bool hasNonZero64f( const double* src, size_t len ) HasNonZeroFunc getHasNonZeroTab(int depth) { - static HasNonZeroFunc hasNonZeroTab[] = + static HasNonZeroFunc hasNonZeroTab[CV_DEPTH_MAX] = { (HasNonZeroFunc)GET_OPTIMIZED(hasNonZero8u), (HasNonZeroFunc)GET_OPTIMIZED(hasNonZero8u), (HasNonZeroFunc)GET_OPTIMIZED(hasNonZero16u), (HasNonZeroFunc)GET_OPTIMIZED(hasNonZero16u), diff --git a/modules/core/src/lut.cpp b/modules/core/src/lut.cpp index cb2b9e7b5677..c2464ef4980d 100644 --- a/modules/core/src/lut.cpp +++ b/modules/core/src/lut.cpp @@ -68,7 +68,7 @@ static void LUT8u_64f( const uchar* src, const double* lut, double* dst, int len typedef void (*LUTFunc)( const uchar* src, const uchar* lut, uchar* dst, int len, int cn, int lutcn ); -static LUTFunc lutTab[] = +static LUTFunc lutTab[CV_DEPTH_MAX] = { (LUTFunc)LUT8u_8u, (LUTFunc)LUT8u_8s, (LUTFunc)LUT8u_16u, (LUTFunc)LUT8u_16s, (LUTFunc)LUT8u_32s, (LUTFunc)LUT8u_32f, (LUTFunc)LUT8u_64f, 0 @@ -330,7 +330,7 @@ class LUTParallelBody : public ParallelLoopBody void operator()( const cv::Range& range ) const CV_OVERRIDE { - CV_DbgAssert(*ok); + CV_Assert(*ok); const int row0 = range.start; const int row1 = range.end; diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index 1aa16aaceb0e..764d2d9b03d3 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -1184,7 +1184,7 @@ static void iPow64f(const double* src, double* dst, int len, int power) typedef void (*IPowFunc)( const uchar* src, uchar* dst, int len, int power ); -static IPowFunc ipowTab[] = +static IPowFunc ipowTab[CV_DEPTH_MAX] = { (IPowFunc)iPow8u, (IPowFunc)iPow8s, (IPowFunc)iPow16u, (IPowFunc)iPow16s, (IPowFunc)iPow32s, (IPowFunc)iPow32f, (IPowFunc)iPow64f, 0 diff --git a/modules/core/src/matmul.dispatch.cpp b/modules/core/src/matmul.dispatch.cpp index a72301b4c3f2..81953265d7f3 100644 --- a/modules/core/src/matmul.dispatch.cpp +++ b/modules/core/src/matmul.dispatch.cpp @@ -979,7 +979,7 @@ typedef double (*DotProdFunc)(const uchar* src1, const uchar* src2, int len); static DotProdFunc getDotProdFunc(int depth) { - static DotProdFunc dotProdTab[] = + static DotProdFunc dotProdTab[CV_DEPTH_MAX] = { (DotProdFunc)GET_OPTIMIZED(dotProd_8u), (DotProdFunc)GET_OPTIMIZED(dotProd_8s), (DotProdFunc)dotProd_16u, (DotProdFunc)dotProd_16s, diff --git a/modules/core/src/matmul.simd.hpp b/modules/core/src/matmul.simd.hpp index fb0c6ddefed6..ce3a48799e35 100644 --- a/modules/core/src/matmul.simd.hpp +++ b/modules/core/src/matmul.simd.hpp @@ -1792,7 +1792,7 @@ diagtransform_64f(const double* src, double* dst, const double* m, int len, int TransformFunc getTransformFunc(int depth) { - static TransformFunc transformTab[] = + static TransformFunc transformTab[CV_DEPTH_MAX] = { (TransformFunc)transform_8u, (TransformFunc)transform_8s, (TransformFunc)transform_16u, (TransformFunc)transform_16s, (TransformFunc)transform_32s, (TransformFunc)transform_32f, @@ -1804,7 +1804,7 @@ TransformFunc getTransformFunc(int depth) TransformFunc getDiagTransformFunc(int depth) { - static TransformFunc diagTransformTab[] = + static TransformFunc diagTransformTab[CV_DEPTH_MAX] = { (TransformFunc)diagtransform_8u, (TransformFunc)diagtransform_8s, (TransformFunc)diagtransform_16u, (TransformFunc)diagtransform_16s, (TransformFunc)diagtransform_32s, (TransformFunc)diagtransform_32f, diff --git a/modules/core/src/matrix_operations.cpp b/modules/core/src/matrix_operations.cpp index 8bb8c66e5cf1..2992f00e739e 100644 --- a/modules/core/src/matrix_operations.cpp +++ b/modules/core/src/matrix_operations.cpp @@ -1259,7 +1259,7 @@ void cv::sort( InputArray _src, OutputArray _dst, int flags ) Mat dst = _dst.getMat(); CV_IPP_RUN_FAST(ipp_sort(src, dst, flags)); - static SortFunc tab[] = + static SortFunc tab[CV_DEPTH_MAX] = { sort_, sort_, sort_, sort_, sort_, sort_, sort_, 0 @@ -1284,7 +1284,7 @@ void cv::sortIdx( InputArray _src, OutputArray _dst, int flags ) CV_IPP_RUN_FAST(ipp_sortIdx(src, dst, flags)); - static SortFunc tab[] = + static SortFunc tab[CV_DEPTH_MAX] = { sortIdx_, sortIdx_, sortIdx_, sortIdx_, sortIdx_, sortIdx_, sortIdx_, 0 diff --git a/modules/core/src/matrix_sparse.cpp b/modules/core/src/matrix_sparse.cpp index 7a02e5961d21..cfc769e79163 100644 --- a/modules/core/src/matrix_sparse.cpp +++ b/modules/core/src/matrix_sparse.cpp @@ -37,7 +37,7 @@ typedef void (*ConvertScaleData)(const void* from, void* to, int cn, double alph static ConvertData getConvertElem(int fromType, int toType) { - static ConvertData tab[][8] = + static ConvertData tab[CV_DEPTH_MAX][CV_DEPTH_MAX] = {{ convertData_, convertData_, convertData_, convertData_, convertData_, convertData_, @@ -82,7 +82,7 @@ static ConvertData getConvertElem(int fromType, int toType) static ConvertScaleData getConvertScaleElem(int fromType, int toType) { - static ConvertScaleData tab[][8] = + static ConvertScaleData tab[CV_DEPTH_MAX][CV_DEPTH_MAX] = {{ convertScaleData_, convertScaleData_, convertScaleData_, convertScaleData_, convertScaleData_, convertScaleData_, @@ -389,6 +389,7 @@ void SparseMat::convertTo( SparseMat& m, int rtype, double alpha ) const if( alpha == 1 ) { ConvertData cvtfunc = getConvertElem(type(), rtype); + CV_Assert(cvtfunc); for( size_t i = 0; i < N; i++, ++from ) { const Node* n = from.node(); @@ -399,6 +400,7 @@ void SparseMat::convertTo( SparseMat& m, int rtype, double alpha ) const else { ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype); + CV_Assert(cvtfunc); for( size_t i = 0; i < N; i++, ++from ) { const Node* n = from.node(); diff --git a/modules/core/src/mean.simd.hpp b/modules/core/src/mean.simd.hpp index e34293ee385d..c6bbc20b892a 100644 --- a/modules/core/src/mean.simd.hpp +++ b/modules/core/src/mean.simd.hpp @@ -311,7 +311,7 @@ static int sqsum64f( const double* src, const uchar* mask, double* sum, double* SumSqrFunc getSumSqrFunc(int depth) { CV_INSTRUMENT_REGION(); - static SumSqrFunc sumSqrTab[] = + static SumSqrFunc sumSqrTab[CV_DEPTH_MAX] = { (SumSqrFunc)GET_OPTIMIZED(sqsum8u), (SumSqrFunc)sqsum8s, (SumSqrFunc)sqsum16u, (SumSqrFunc)sqsum16s, (SumSqrFunc)sqsum32s, (SumSqrFunc)GET_OPTIMIZED(sqsum32f), (SumSqrFunc)sqsum64f, 0 diff --git a/modules/core/src/merge.dispatch.cpp b/modules/core/src/merge.dispatch.cpp index abde21e0df4c..19a62d22b040 100644 --- a/modules/core/src/merge.dispatch.cpp +++ b/modules/core/src/merge.dispatch.cpp @@ -50,7 +50,7 @@ typedef void (*MergeFunc)(const uchar** src, uchar* dst, int len, int cn); static MergeFunc getMergeFunc(int depth) { - static MergeFunc mergeTab[] = + static MergeFunc mergeTab[CV_DEPTH_MAX] = { (MergeFunc)GET_OPTIMIZED(cv::hal::merge8u), (MergeFunc)GET_OPTIMIZED(cv::hal::merge8u), (MergeFunc)GET_OPTIMIZED(cv::hal::merge16u), (MergeFunc)GET_OPTIMIZED(cv::hal::merge16u), diff --git a/modules/core/src/minmax.cpp b/modules/core/src/minmax.cpp index 8d4d185a5468..859fa9e54c38 100644 --- a/modules/core/src/minmax.cpp +++ b/modules/core/src/minmax.cpp @@ -834,7 +834,7 @@ typedef void (*MinMaxIdxFunc)(const uchar*, const uchar*, int*, int*, size_t*, s static MinMaxIdxFunc getMinmaxTab(int depth) { - static MinMaxIdxFunc minmaxTab[] = + static MinMaxIdxFunc minmaxTab[CV_DEPTH_MAX] = { (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_8u), (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_8s), (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_16u), (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_16s), diff --git a/modules/core/src/rand.cpp b/modules/core/src/rand.cpp index a6301afe346e..ee4afd7ef5e1 100644 --- a/modules/core/src/rand.cpp +++ b/modules/core/src/rand.cpp @@ -215,7 +215,7 @@ static void randf_16f( hfloat* arr, int len, uint64* state, const Vec2f* p, floa typedef void (*RandFunc)(uchar* arr, int len, uint64* state, const void* p, void* tempbuf, bool small_flag); -static RandFunc randTab[][8] = +static RandFunc randTab[CV_DEPTH_MAX][CV_DEPTH_MAX] = { { (RandFunc)randi_8u, (RandFunc)randi_8s, (RandFunc)randi_16u, (RandFunc)randi_16s, diff --git a/modules/core/src/split.dispatch.cpp b/modules/core/src/split.dispatch.cpp index fc5e073497af..e2a47b704dc5 100644 --- a/modules/core/src/split.dispatch.cpp +++ b/modules/core/src/split.dispatch.cpp @@ -53,7 +53,7 @@ typedef void (*SplitFunc)(const uchar* src, uchar** dst, int len, int cn); static SplitFunc getSplitFunc(int depth) { - static SplitFunc splitTab[] = + static SplitFunc splitTab[CV_DEPTH_MAX] = { (SplitFunc)GET_OPTIMIZED(cv::hal::split8u), (SplitFunc)GET_OPTIMIZED(cv::hal::split8u), (SplitFunc)GET_OPTIMIZED(cv::hal::split16u), (SplitFunc)GET_OPTIMIZED(cv::hal::split16u), diff --git a/modules/core/src/sum.simd.hpp b/modules/core/src/sum.simd.hpp index e20cd39b7052..f790fc733a7a 100644 --- a/modules/core/src/sum.simd.hpp +++ b/modules/core/src/sum.simd.hpp @@ -434,7 +434,7 @@ static int sum64f( const double* src, const uchar* mask, double* dst, int len, i SumFunc getSumFunc(int depth) { - static SumFunc sumTab[] = + static SumFunc sumTab[CV_DEPTH_MAX] = { (SumFunc)GET_OPTIMIZED(sum8u), (SumFunc)sum8s, (SumFunc)sum16u, (SumFunc)sum16s, From bc0618b688bde681a8caa8619a55766fc9e6a32f Mon Sep 17 00:00:00 2001 From: Yuantao Feng Date: Fri, 17 May 2024 16:07:05 +0800 Subject: [PATCH 058/119] Merge pull request #25582 from fengyuentau:dnn/dump_pbtxt Current net exporter `dump` and `dumpToFile` exports the network structure (and its params) to a .dot file which works with `graphviz`. This is hard to use and not friendly to new user. What's worse, the produced picture is not looking pretty. dnn: better net exporter that works with netron #25582 This PR introduces new exporter `dumpToPbtxt` and uses this new exporter by default with environment variable `OPENCV_DNN_NETWORK_DUMP`. It mimics the string output of a onnx model but modified with dnn-specific changes, see below for an example. ![image](https://github.com/opencv/opencv/assets/17219438/0644bed1-da71-4019-8466-88390698e4df) ## Usage Call `cv::dnn::Net::dumpToPbtxt`: ```cpp TEST(DumpNet, dumpToPbtxt) { std::string path = "/path/to/model.onnx"; auto net = readNet(path); Mat input(std::vector{1, 3, 640, 480}, CV_32F); net.setInput(input); net.dumpToPbtxt("yunet.pbtxt"); } ``` Set `export OPENCV_DNN_NETWORK_DUMP=1` ```cpp TEST(DumpNet, env) { std::string path = "/path/to/model.onnx"; auto net = readNet(path); Mat input(std::vector{1, 3, 640, 480}, CV_32F); net.setInput(input); net.forward(); } ``` --- Note: - `pbtxt` is registered as one of the ONNX model suffix in netron. So you can see `module: ai.onnx` and such in the model. - We can get the string output of an ONNX model with the following script ```python import onnx net = onnx.load("/path/to/model.onnx") net_str = str(net) file = open("/path/to/model.pbtxt", "w") file.write(net_str) file.close() ``` ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- apps/model-diagnostics/model_diagnostics.cpp | 86 +++++- modules/dnn/include/opencv2/dnn/dnn.hpp | 8 + modules/dnn/src/net.cpp | 10 + modules/dnn/src/net_impl.cpp | 267 ++++++++++++++++++- modules/dnn/src/net_impl.hpp | 1 + 5 files changed, 367 insertions(+), 5 deletions(-) diff --git a/apps/model-diagnostics/model_diagnostics.cpp b/apps/model-diagnostics/model_diagnostics.cpp index 6970c8507108..365833c9e535 100644 --- a/apps/model-diagnostics/model_diagnostics.cpp +++ b/apps/model-diagnostics/model_diagnostics.cpp @@ -32,12 +32,36 @@ static std::string checkFileExists(const std::string& fileName) "Please, specify a full path to the file."); } +static std::vector parseShape(const std::string &shape_str) { + std::stringstream ss(shape_str); + std::string item; + std::vector items; + + while (std::getline(ss, item, ',')) { + items.push_back(item); + } + + std::vector shape; + for (size_t i = 0; i < items.size(); i++) { + shape.push_back(std::stoi(items[i])); + } + return shape; +} + std::string diagnosticKeys = "{ model m | | Path to the model file. }" "{ config c | | Path to the model configuration file. }" - "{ framework f | | [Optional] Name of the model framework. }"; - - + "{ framework f | | [Optional] Name of the model framework. }" + "{ input0_name | | [Optional] Name of input0. Use with input0_shape}" + "{ input0_shape | | [Optional] Shape of input0. Use with input0_name}" + "{ input1_name | | [Optional] Name of input1. Use with input1_shape}" + "{ input1_shape | | [Optional] Shape of input1. Use with input1_name}" + "{ input2_name | | [Optional] Name of input2. Use with input2_shape}" + "{ input2_shape | | [Optional] Shape of input2. Use with input2_name}" + "{ input3_name | | [Optional] Name of input3. Use with input3_shape}" + "{ input3_shape | | [Optional] Shape of input3. Use with input3_name}" + "{ input4_name | | [Optional] Name of input4. Use with input4_shape}" + "{ input4_shape | | [Optional] Shape of input4. Use with input4_name}"; int main( int argc, const char** argv ) { @@ -55,6 +79,17 @@ int main( int argc, const char** argv ) std::string config = checkFileExists(argParser.get("config")); std::string frameworkId = argParser.get("framework"); + std::string input0_name = argParser.get("input0_name"); + std::string input0_shape = argParser.get("input0_shape"); + std::string input1_name = argParser.get("input1_name"); + std::string input1_shape = argParser.get("input1_shape"); + std::string input2_name = argParser.get("input2_name"); + std::string input2_shape = argParser.get("input2_shape"); + std::string input3_name = argParser.get("input3_name"); + std::string input3_shape = argParser.get("input3_shape"); + std::string input4_name = argParser.get("input4_name"); + std::string input4_shape = argParser.get("input4_shape"); + CV_Assert(!model.empty()); enableModelDiagnostics(true); @@ -63,5 +98,50 @@ int main( int argc, const char** argv ) Net ocvNet = readNet(model, config, frameworkId); + std::vector input_names; + std::vector> input_shapes; + if (!input0_name.empty() || !input0_shape.empty()) { + CV_CheckFalse(input0_name.empty(), "input0_name cannot be empty"); + CV_CheckFalse(input0_shape.empty(), "input0_shape cannot be empty"); + input_names.push_back(input0_name); + input_shapes.push_back(parseShape(input0_shape)); + } + if (!input1_name.empty() || !input1_shape.empty()) { + CV_CheckFalse(input1_name.empty(), "input1_name cannot be empty"); + CV_CheckFalse(input1_shape.empty(), "input1_shape cannot be empty"); + input_names.push_back(input1_name); + input_shapes.push_back(parseShape(input1_shape)); + } + if (!input2_name.empty() || !input2_shape.empty()) { + CV_CheckFalse(input2_name.empty(), "input2_name cannot be empty"); + CV_CheckFalse(input2_shape.empty(), "input2_shape cannot be empty"); + input_names.push_back(input2_name); + input_shapes.push_back(parseShape(input2_shape)); + } + if (!input3_name.empty() || !input3_shape.empty()) { + CV_CheckFalse(input3_name.empty(), "input3_name cannot be empty"); + CV_CheckFalse(input3_shape.empty(), "input3_shape cannot be empty"); + input_names.push_back(input3_name); + input_shapes.push_back(parseShape(input3_shape)); + } + if (!input4_name.empty() || !input4_shape.empty()) { + CV_CheckFalse(input4_name.empty(), "input4_name cannot be empty"); + CV_CheckFalse(input4_shape.empty(), "input4_shape cannot be empty"); + input_names.push_back(input4_name); + input_shapes.push_back(parseShape(input4_shape)); + } + + if (!input_names.empty() && !input_shapes.empty() && input_names.size() == input_shapes.size()) { + ocvNet.setInputsNames(input_names); + for (size_t i = 0; i < input_names.size(); i++) { + Mat input(input_shapes[i], CV_32F); + ocvNet.setInput(input, input_names[i]); + } + + size_t dot_index = model.rfind('.'); + std::string graph_filename = model.substr(0, dot_index) + ".pbtxt"; + ocvNet.dumpToPbtxt(graph_filename); + } + return 0; } diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index 9d0c36d5fe07..fd9129010475 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -518,6 +518,14 @@ CV__DNN_INLINE_NS_BEGIN * @see dump() */ CV_WRAP void dumpToFile(CV_WRAP_FILE_PATH const String& path); + /** @brief Dump net structure, hyperparameters, backend, target and fusion to pbtxt file + * @param path path to output file with .pbtxt extension + * + * Use Netron (https://netron.app) to open the target file to visualize the model. + * Call method after setInput(). To see correct backend, target and fusion run after forward(). + */ + CV_WRAP void dumpToPbtxt(CV_WRAP_FILE_PATH const String& path); + /** @brief Adds new layer to the net. * @param name unique name of the adding layer. * @param type typename of the adding layer (type must be registered in LayerRegister). diff --git a/modules/dnn/src/net.cpp b/modules/dnn/src/net.cpp index 30894d0c24e6..b4ed3570f881 100644 --- a/modules/dnn/src/net.cpp +++ b/modules/dnn/src/net.cpp @@ -216,6 +216,16 @@ void Net::dumpToFile(const String& path) file.close(); } +void Net::dumpToPbtxt(const String& path) +{ + CV_TRACE_FUNCTION(); + CV_Assert(impl); + CV_Assert(!empty()); + std::ofstream file(path.c_str()); + file << impl->dumpToPbtxt(true); + file.close(); +} + Ptr Net::getLayer(int layerId) const { CV_Assert(impl); diff --git a/modules/dnn/src/net_impl.cpp b/modules/dnn/src/net_impl.cpp index 936299922b11..28db8c0566fa 100644 --- a/modules/dnn/src/net_impl.cpp +++ b/modules/dnn/src/net_impl.cpp @@ -1830,15 +1830,278 @@ string Net::Impl::dump(bool forceAllocation) const return out.str(); } +static void dumpTensorToString(std::ostringstream &out, const Mat &m, const int num_indent_spaces = 4) { + string indent_spaces(num_indent_spaces, ' '); + + int type = 1; + /* Check TensorProto::DataType from https://github.com/onnx/onnx/blob/main/onnx/onnx.proto */ + switch (m.type()) { + case CV_32F: break; + case CV_8U: type = 2; break; + case CV_8S: type = 3; break; + case CV_16U: type = 4; break; + case CV_16S: type = 5; break; + case CV_32S: type = 6; break; +#if CV_VERSION_MAJOR > 4 + case CV_64S: type = 7; break; + // STRING: 8 + case CV_BOOL: type = 9; break; +#endif + case CV_16F: type = 10; break; + case CV_64F: type = 11; break; +#if CV_VERSION_MAJOR > 4 + case CV_32U: type = 12; break; + case CV_64U: type = 13; break; + // COMPLEX64: 14 + // COMPLEX128: 15 + case CV_16BF: type = 16; break; +#endif + default: CV_Error(Error::StsUnsupportedFormat, "Type of mat is not supported"); + } + const auto &mshape = shape(m); + + out << indent_spaces << "type {\n" + << indent_spaces << " tensor_type {\n" + << indent_spaces << " elem_type: " << type << "\n"; + out << indent_spaces << " shape {\n"; + for (size_t i = 0; i < mshape.size(); i++) { + out << indent_spaces << format(" dim { dim_value: %d }\n", mshape[i]); + } + out << indent_spaces << " }\n" // shape{} + << indent_spaces << " }\n" // tensor_type{} + << indent_spaces << "}\n"; // type{} +} + + +static void dumpParamToString(std::ostringstream &out, const std::string &key, const DictValue &value, const int num_indent_spaces = 2) { + std::string indent_spaces(num_indent_spaces, ' '); + + out << indent_spaces << "attribute {\n" + << indent_spaces << format(" name: \"%s\"\n", key.c_str()); + if (value.size() == 1) { + if (value.isString()) { + out << indent_spaces << format(" type: STRING\n") + << indent_spaces << format(" s: \"%s\"\n", value.getStringValue(0).c_str()); + } else if (value.isInt()) { + out << indent_spaces << format(" type: INT\n") + << indent_spaces << format(" i: %d\n", value.getIntValue(0)); + } else if (value.isReal()) { + out << indent_spaces << format(" type: FLOAT\n") + << indent_spaces << format(" f: %f\n", value.getRealValue(0)); + } else { + out << indent_spaces << format(" type: UNKNOWN-SCALAR\n"); + } + } else { + if (value.isString()) { + out << indent_spaces << format(" type: STRINGS\n"); + } else if (value.isInt()) { + out << indent_spaces << format(" type: INTS\n"); + } else if (value.isReal()) { + out << indent_spaces << format(" type: FLOATS\n"); + } else { + out << indent_spaces << format(" type: UNKNOWN-ARRAY\n"); + } + for (int i = 0; i < value.size(); i++) { + if (value.isString()) { + out << indent_spaces << format(" strings: \"%s\"\n", value.getStringValue(i).c_str()); + } else if (value.isInt()) { + out << indent_spaces << format(" ints: %d\n", value.getIntValue(i)); + } else if (value.isReal()) { + out << indent_spaces << format(" floats: %f\n", value.getRealValue()); + } + } + } + out << indent_spaces << "}\n"; // attribute{} +} + +static void dumpLayerToString(std::ostringstream &out, + const std::vector &inputs, + const std::vector &outputs, + const std::string &name, + const std::string &op_type, + const LayerParams ¶ms, + const std::string &backend_name, + const std::string &target_name, + const int num_indent_spaces = 2) { + std::string indent_spaces(num_indent_spaces, ' '); + + for (size_t i = 0; i < inputs.size(); i++) { + out << indent_spaces << format("input: \"%s\"\n", inputs[i].c_str()); + } + for (size_t i = 0; i < outputs.size(); i++) { + out << indent_spaces << format("output: \"%s\"\n", outputs[i].c_str()); + } + if (!name.empty()) { + out << indent_spaces << format("name: \"%s\"\n", name.c_str()); + } + if (!op_type.empty()) { + out << indent_spaces << format("op_type: \"%s\"\n", op_type.c_str()); + } + if (!params.name.empty()) { + for (auto param_iter = params.begin(); param_iter != params.end(); param_iter++) { + auto key = param_iter->first; + auto value = param_iter->second; + dumpParamToString(out, key, value, num_indent_spaces); + } + } + if (!backend_name.empty()) { + DictValue dvb(backend_name); + dumpParamToString(out, "Backend", dvb, num_indent_spaces); + } + if (!target_name.empty()) { + DictValue dvt(target_name); + dumpParamToString(out, "Target", dvt, num_indent_spaces); + } +} + +string Net::Impl::dumpToPbtxt(bool forceAllocation) const { + if (forceAllocation && !netWasAllocated) { + const_cast(this)->setUpNet(); + } + + std::ostringstream out; + const std::map &map = layers; + std::map value_info; + + Backend prefBackend = (Backend)preferableBackend; + Target prefTarget = (Target)preferableTarget; + + auto GetBackendName = [] (int backendId) { + std::string backend = "Unknown"; + switch (backendId) { + case DNN_BACKEND_DEFAULT: backend = "DEFAULT"; break; + #if CV_VERSION_MAJOR <= 4 + case DNN_BACKEND_HALIDE: backend = "HALIDE"; break; + #endif + case DNN_BACKEND_INFERENCE_ENGINE: // fallthru + case DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019: // fallthru + case DNN_BACKEND_INFERENCE_ENGINE_NGRAPH: backend = "OpenVINO"; break; + case DNN_BACKEND_OPENCV: backend = "OCV"; break; + case DNN_BACKEND_VKCOM: backend = "VULKAN"; break; + case DNN_BACKEND_CUDA: backend = "CUDA"; break; + case DNN_BACKEND_WEBNN: backend = "WEBNN"; break; + case DNN_BACKEND_TIMVX: backend = "TIMVX"; break; + case DNN_BACKEND_CANN: backend = "CANN"; break; + } + return backend; + }; + auto GetTargetName = [] (int targetId) { + std::string target = "Unknown"; + switch (targetId) { + case DNN_TARGET_CPU: target = "CPU"; break; + case DNN_TARGET_OPENCL: target = "OCL"; break; + case DNN_TARGET_OPENCL_FP16: target = "OCL_FP16"; break; + case DNN_TARGET_MYRIAD: target = "MYRIAD"; break; + case DNN_TARGET_VULKAN: target = "VULKAN"; break; + case DNN_TARGET_FPGA: target = "FPGA"; break; + case DNN_TARGET_CUDA: target = "CUDA"; break; + case DNN_TARGET_CUDA_FP16: target = "CUDA_FP16"; break; + case DNN_TARGET_HDDL: target = "HDDL"; break; + case DNN_TARGET_NPU: target = "NPU"; break; + case DNN_TARGET_CPU_FP16: target = "CPU_FP16"; break; + } + return target; + }; + + const int num_indent_spaces = 2; + std::string indent_spaces(num_indent_spaces, ' '); + out << "producer_name: \"opencv dnn\"\n" + << "producer_version: \"" << getVersionString() << "\"\n" + << "graph {\n"; + // Add nodes, inputs and outputs + for (std::map::const_iterator iter = map.begin(); iter != map.end(); iter++) { + auto &ld = iter->second; + if (ld.id == 0) { + for (int i = 0; i < ld.outputBlobs.size(); i++) { + const auto &name = netInputLayer->outNames.empty() ? cv::format("%s_%d", ld.name.c_str(), i) : netInputLayer->outNames[i]; + out << indent_spaces << "input {\n" + << indent_spaces << format(" name: \"%s\"\n", name.c_str()); + // Add shape + if (!ld.outputBlobs.empty()) { + dumpTensorToString(out, ld.outputBlobs[i], num_indent_spaces + 2); + } + out << indent_spaces << "}\n"; // input{} + } + } else if (ld.consumers.size() == 0) { + out << indent_spaces << "output {\n" + << indent_spaces << format(" name: \"%s\"\n", ld.name.c_str()); + // Add shape + if (!ld.outputBlobs.empty()) { + dumpTensorToString(out, ld.outputBlobs.front(), num_indent_spaces + 2); + } + out << indent_spaces << "}\n"; // output{} + } else { + out << indent_spaces << "node {\n"; + const auto &name = ld.name; + const auto &op_type = "cv::dnn::" + ld.type; + std::vector inputs, outputs; + // Collect names of inputs + for (size_t i = 0; i < ld.inputBlobsId.size(); i++) { + int lid = ld.inputBlobsId[i].lid; + int oid = ld.inputBlobsId[i].oid; + std::string name; + if (lid == 0) { + name = netInputLayer->outNames.empty() ? cv::format("%s_%d", ld.name.c_str(), oid) : netInputLayer->outNames[oid]; + } else { + name = format("%s_output%d", map.find(lid)->second.name.c_str(), oid); + if (!ld.inputBlobs.empty()) { + value_info.insert({name, ld.inputBlobs[i]}); + } + } + inputs.push_back(name); + } + // Collect names of outputs + for (size_t i = 0; i < ld.consumers.size(); i++) { + int lid = ld.consumers[i].lid; + const auto &layer_output_layer = map.find(lid)->second; + std::string name; + if (layer_output_layer.consumers.size() == 0) { + name = layer_output_layer.name; + } else { + name = format("%s_output%zu", ld.name.c_str(), i); + } + outputs.push_back(name); + } + const auto ¶ms = ld.params; + // Collect backend and target + const Backend backend = ld.backendNodes.find(prefBackend) == ld.backendNodes.end() ? DNN_BACKEND_OPENCV : prefBackend; + const std::string backend_name = GetBackendName(backend); + const Target target = ld.layerInstance.empty() ? DNN_TARGET_CPU : (Target)(ld.layerInstance->preferableTarget); + const std::string target_name = GetTargetName(target); + dumpLayerToString(out, inputs, outputs, name, op_type, params, backend_name, target_name, num_indent_spaces + 2); + out << indent_spaces << "}\n"; // node{} + } + } + // Add value_info + for (std::map::const_iterator iter = value_info.begin(); iter != value_info.end(); iter++) { + out << indent_spaces << "value_info {\n" + << indent_spaces << format(" name: \"%s\"\n", iter->first.c_str()); + dumpTensorToString(out, *(iter->second), num_indent_spaces + 2); + out << indent_spaces << "}\n"; // value_info{} + } + out << "}\n"; // graph{} + + // Add preferable backend and target as metadata + out << "metadata_props {\n"; + out << indent_spaces << format(" key: \"%s\"", "Preferable Backend") + << indent_spaces << format(" value: \"%s\"", GetBackendName(prefBackend).c_str()); + out << "}\n"; // metadata_props{} + out << "metadata_props {\n"; + out << indent_spaces << format(" key: \"%s\"", "Preferable Target") + << indent_spaces << format(" value: \"%s\"", GetTargetName(prefTarget).c_str()); + out << "}\n"; // metadata_props{} + + return out.str(); +} void Net::Impl::dumpNetworkToFile() const { #ifndef OPENCV_DNN_DISABLE_NETWORK_AUTO_DUMP string dumpFileNameBase = getDumpFileNameBase(); - string dumpFileName = dumpFileNameBase + ".dot"; + string dumpFileName = dumpFileNameBase + ".pbtxt"; try { - string dumpStr = dump(); + string dumpStr = dumpToPbtxt(); std::ofstream out(dumpFileName.c_str(), std::ios::out | std::ios::binary); out << dumpStr; } diff --git a/modules/dnn/src/net_impl.hpp b/modules/dnn/src/net_impl.hpp index a11db8fb30e1..ba907e14b788 100644 --- a/modules/dnn/src/net_impl.hpp +++ b/modules/dnn/src/net_impl.hpp @@ -278,6 +278,7 @@ struct Net::Impl : public detail::NetImplBase AsyncArray getBlobAsync(String outputName); string dump(bool forceAllocation = false) const; + string dumpToPbtxt(bool forceAllocation = false) const; void dumpNetworkToFile() const; From 5f509e2ec1e70c08671285e8b9497b95f0bb5773 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 17 May 2024 11:44:20 +0300 Subject: [PATCH 059/119] Skip Test_Caffe_layers.Concat with Vulkan due to sporadic failures. --- modules/dnn/test/test_layers.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/dnn/test/test_layers.cpp b/modules/dnn/test/test_layers.cpp index a0171c9d91e9..48c968fb6a42 100644 --- a/modules/dnn/test/test_layers.cpp +++ b/modules/dnn/test/test_layers.cpp @@ -307,6 +307,11 @@ TEST_P(Test_Caffe_layers, Dropout) TEST_P(Test_Caffe_layers, Concat) { + if (cvtest::skipUnstableTests && (backend == DNN_BACKEND_VKCOM)) + { + throw SkipTestException("Test_Caffe_layers.Concat test produces unstable result with Vulkan"); + } + #if defined(INF_ENGINE_RELEASE) #if INF_ENGINE_VER_MAJOR_GE(2019010000) && INF_ENGINE_VER_MAJOR_LT(2019020000) if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD) From 6350bfbf79562f257b58843b31e88a3245ee31a4 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Fri, 17 May 2024 15:01:05 +0300 Subject: [PATCH 060/119] Merge pull request #25564 from mshabunin:cleanup-imgproc-2 imgproc: C-API cleanup, drawContours refactor #25564 Changes: * moved several macros from types_c.h to cvdef.h (assuming we will continue using them) * removed some cases of C-API usage in _imgproc_ module (`CV_TERMCRIT_*` and `CV_CMP_*`) * refactored `drawContours` to use C++ API instead of calling `cvDrawContours` + test for filled contours with holes (case with non-filled contours is simpler and is covered in some other tests) #### Note: There is one case where old drawContours behavior doesn't match the new one - when `contourIdx == -1` (means "draw all contours") and `maxLevel == 0` (means draw only selected contours, but not what is inside). From the docs: > **contourIdx** Parameter indicating a contour to draw. If it is negative, all the contours are drawn. > **maxLevel** Maximal level for drawn contours. If it is 0, only the specified contour is drawn. If it is 1, the function draws the contour(s) and all the nested contours. If it is 2, the function draws the contours, all the nested contours, all the nested-to-nested contours, and so on. This parameter is only taken into account when there is hierarchy available. Old behavior - only one first contour is drawn: ![actual_screenshot_08 05 2024](https://github.com/opencv/opencv/assets/3304494/d0ae1d64-ddad-46bb-8acc-6f696874f71b) a New behavior (also expected by the test) - all contours are drawn: ![expected_screenshot_08 05 2024](https://github.com/opencv/opencv/assets/3304494/57ccd980-9dde-4006-90ee-19d6ce76912a) --- modules/core/include/opencv2/core/cvdef.h | 16 ++ modules/core/include/opencv2/core/types_c.h | 20 +-- modules/imgproc/src/cornersubpix.cpp | 4 +- modules/imgproc/src/drawing.cpp | 164 +++++++++----------- modules/imgproc/src/grabcut.cpp | 4 +- modules/imgproc/src/moments.cpp | 2 +- modules/imgproc/src/precomp.hpp | 1 + modules/imgproc/src/segmentation.cpp | 4 +- modules/imgproc/test/test_contours.cpp | 2 +- modules/imgproc/test/test_convhull.cpp | 6 - modules/imgproc/test/test_drawing.cpp | 107 +++++++++++++ 11 files changed, 210 insertions(+), 120 deletions(-) diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index 30f2ce5649a5..748ecb9eceeb 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -201,6 +201,14 @@ namespace cv { # define CV_ICC __INTEL_COMPILER #endif +#if defined _WIN32 +# define CV_CDECL __cdecl +# define CV_STDCALL __stdcall +#else +# define CV_CDECL +# define CV_STDCALL +#endif + #ifndef CV_INLINE # if defined __cplusplus # define CV_INLINE static inline @@ -482,6 +490,7 @@ Cv64suf; * Matrix type (Mat) * \****************************************************************************************/ +#define CV_MAX_DIM 32 #define CV_MAT_CN_MASK ((CV_CN_MAX - 1) << CV_CN_SHIFT) #define CV_MAT_CN(flags) ((((flags) & CV_MAT_CN_MASK) >> CV_CN_SHIFT) + 1) #define CV_MAT_TYPE_MASK (CV_DEPTH_MAX*CV_CN_MAX - 1) @@ -508,6 +517,13 @@ Cv64suf; # define MAX(a,b) ((a) < (b) ? (b) : (a)) #endif +/** min & max without jumps */ +#define CV_IMIN(a, b) ((a) ^ (((a)^(b)) & (((a) < (b)) - 1))) +#define CV_IMAX(a, b) ((a) ^ (((a)^(b)) & (((a) > (b)) - 1))) +#define CV_SWAP(a,b,t) ((t) = (a), (a) = (b), (b) = (t)) +#define CV_CMP(a,b) (((a) > (b)) - ((a) < (b))) +#define CV_SIGN(a) CV_CMP((a),0) + ///////////////////////////////////////// Enum operators /////////////////////////////////////// /** diff --git a/modules/core/include/opencv2/core/types_c.h b/modules/core/include/opencv2/core/types_c.h index 32f3c8c99998..02d4a4f68058 100644 --- a/modules/core/include/opencv2/core/types_c.h +++ b/modules/core/include/opencv2/core/types_c.h @@ -90,13 +90,7 @@ #include #endif // SKIP_INCLUDES -#if defined _WIN32 -# define CV_CDECL __cdecl -# define CV_STDCALL __stdcall -#else -# define CV_CDECL -# define CV_STDCALL -#endif + #ifndef CV_DEFAULT # ifdef __cplusplus @@ -203,21 +197,13 @@ enum { * Common macros and inline functions * \****************************************************************************************/ -#define CV_SWAP(a,b,t) ((t) = (a), (a) = (b), (b) = (t)) - -/** min & max without jumps */ -#define CV_IMIN(a, b) ((a) ^ (((a)^(b)) & (((a) < (b)) - 1))) - -#define CV_IMAX(a, b) ((a) ^ (((a)^(b)) & (((a) > (b)) - 1))) - /** absolute value without jumps */ #ifndef __cplusplus # define CV_IABS(a) (((a) ^ ((a) < 0 ? -1 : 0)) - ((a) < 0 ? -1 : 0)) #else # define CV_IABS(a) abs(a) #endif -#define CV_CMP(a,b) (((a) > (b)) - ((a) < (b))) -#define CV_SIGN(a) CV_CMP((a),0) + #define cvInvSqrt(value) ((float)(1./sqrt(value))) #define cvSqrt(value) ((float)sqrt(value)) @@ -675,8 +661,6 @@ CV_INLINE int cvIplDepth( int type ) #define CV_MATND_MAGIC_VAL 0x42430000 #define CV_TYPE_NAME_MATND "opencv-nd-matrix" -#define CV_MAX_DIM 32 - #ifdef __cplusplus typedef struct CvMatND CvMatND; CV_EXPORTS CvMatND cvMatND(const cv::Mat& m); diff --git a/modules/imgproc/src/cornersubpix.cpp b/modules/imgproc/src/cornersubpix.cpp index 24fd59910b1b..af5bd999dce2 100644 --- a/modules/imgproc/src/cornersubpix.cpp +++ b/modules/imgproc/src/cornersubpix.cpp @@ -49,8 +49,8 @@ void cv::cornerSubPix( InputArray _image, InputOutputArray _corners, const int MAX_ITERS = 100; int win_w = win.width * 2 + 1, win_h = win.height * 2 + 1; int i, j, k; - int max_iters = (criteria.type & CV_TERMCRIT_ITER) ? MIN(MAX(criteria.maxCount, 1), MAX_ITERS) : MAX_ITERS; - double eps = (criteria.type & CV_TERMCRIT_EPS) ? MAX(criteria.epsilon, 0.) : 0; + int max_iters = (criteria.type & TermCriteria::MAX_ITER) ? MIN(MAX(criteria.maxCount, 1), MAX_ITERS) : MAX_ITERS; + double eps = (criteria.type & TermCriteria::EPS) ? MAX(criteria.epsilon, 0.) : 0; eps *= eps; // use square of error in comparison operations cv::Mat src = _image.getMat(), cornersmat = _corners.getMat(); diff --git a/modules/imgproc/src/drawing.cpp b/modules/imgproc/src/drawing.cpp index 355525eb6ca4..4d0f26f7a09b 100644 --- a/modules/imgproc/src/drawing.cpp +++ b/modules/imgproc/src/drawing.cpp @@ -39,6 +39,7 @@ // //M*/ #include "precomp.hpp" +using namespace cv; namespace cv { @@ -2468,35 +2469,6 @@ void cv::polylines(InputOutputArray img, InputArrayOfArrays pts, polylines(img, (const Point**)ptsptr, npts, (int)ncontours, isClosed, color, thickness, lineType, shift); } -namespace -{ -using namespace cv; - -static void addChildContour(InputArrayOfArrays contours, - size_t ncontours, - const Vec4i* hierarchy, - int i, std::vector& seq, - std::vector& block) -{ - for( ; i >= 0; i = hierarchy[i][0] ) - { - Mat ci = contours.getMat(i); - cvMakeSeqHeaderForArray(CV_SEQ_POLYGON, sizeof(CvSeq), sizeof(Point), - !ci.empty() ? (void*)ci.ptr() : 0, (int)ci.total(), - &seq[i], &block[i] ); - - int h_next = hierarchy[i][0], h_prev = hierarchy[i][1], - v_next = hierarchy[i][2], v_prev = hierarchy[i][3]; - seq[i].h_next = (0 <= h_next && h_next < (int)ncontours) ? &seq[h_next] : 0; - seq[i].h_prev = (0 <= h_prev && h_prev < (int)ncontours) ? &seq[h_prev] : 0; - seq[i].v_next = (0 <= v_next && v_next < (int)ncontours) ? &seq[v_next] : 0; - seq[i].v_prev = (0 <= v_prev && v_prev < (int)ncontours) ? &seq[v_prev] : 0; - - if( v_next >= 0 ) - addChildContour(contours, ncontours, hierarchy, v_next, seq, block); - } -} -} void cv::drawContours( InputOutputArray _image, InputArrayOfArrays _contours, int contourIdx, const Scalar& color, int thickness, @@ -2504,83 +2476,99 @@ void cv::drawContours( InputOutputArray _image, InputArrayOfArrays _contours, int maxLevel, Point offset ) { CV_INSTRUMENT_REGION(); - - Mat image = _image.getMat(), hierarchy = _hierarchy.getMat(); - CvMat _cimage = cvMat(image); - - size_t ncontours = _contours.total(); - size_t i = 0, first = 0, last = ncontours; - std::vector seq; - std::vector block; - - if( !last ) + CV_Assert( thickness <= MAX_THICKNESS ); + const size_t ncontours = _contours.total(); + if (!ncontours) return; + CV_Assert(ncontours <= (size_t)std::numeric_limits::max()); + if (lineType == cv::LINE_AA && _image.depth() != CV_8U) + lineType = 8; + Mat image = _image.getMat(), hierarchy = _hierarchy.getMat(); - seq.resize(last); - block.resize(last); - - for( i = first; i < last; i++ ) - seq[i].first = 0; - - if( contourIdx >= 0 ) - { - CV_Assert( 0 <= contourIdx && contourIdx < (int)last ); - first = contourIdx; - last = contourIdx + 1; - } - - for( i = first; i < last; i++ ) + if (thickness >= 0) // contour lines { - Mat ci = _contours.getMat((int)i); - if( ci.empty() ) - continue; - int npoints = ci.checkVector(2, CV_32S); - CV_Assert( npoints > 0 ); - cvMakeSeqHeaderForArray( CV_SEQ_POLYGON, sizeof(CvSeq), sizeof(Point), - ci.ptr(), npoints, &seq[i], &block[i] ); - } - - if( hierarchy.empty() || maxLevel == 0 ) - for( i = first; i < last; i++ ) + double color_buf[4] {}; + scalarToRawData(color, color_buf, _image.type(), 0 ); + int i = 0, end = (int)ncontours; + if (contourIdx >= 0) { - seq[i].h_next = i < last-1 ? &seq[i+1] : 0; - seq[i].h_prev = i > first ? &seq[i-1] : 0; + i = contourIdx; + end = i + 1; } - else - { - size_t count = last - first; - CV_Assert(hierarchy.total() == ncontours && hierarchy.type() == CV_32SC4 ); - const Vec4i* h = hierarchy.ptr(); - - if( count == ncontours ) + for (; i < end; ++i) { - for( i = first; i < last; i++ ) + Mat cnt = _contours.getMat(i); + if (cnt.empty()) + continue; + const int npoints = cnt.checkVector(2, CV_32S); + CV_Assert(npoints > 0); + for (int j = 0; j < npoints; ++j) { - int h_next = h[i][0], h_prev = h[i][1], - v_next = h[i][2], v_prev = h[i][3]; - seq[i].h_next = (size_t)h_next < count ? &seq[h_next] : 0; - seq[i].h_prev = (size_t)h_prev < count ? &seq[h_prev] : 0; - seq[i].v_next = (size_t)v_next < count ? &seq[v_next] : 0; - seq[i].v_prev = (size_t)v_prev < count ? &seq[v_prev] : 0; + const bool isLastIter = j == npoints - 1; + const Point pt1 = cnt.at(j); + const Point pt2 = cnt.at(isLastIter ? 0 : j + 1); + cv::ThickLine(image, pt1 + offset, pt2 + offset, color_buf, thickness, lineType, 2, 0); } } + } + else // filled polygons + { + int i = 0, end = (int)ncontours; + if (contourIdx >= 0) + { + i = contourIdx; + end = i + 1; + } + std::vector indexesToFill; + if (hierarchy.empty() || maxLevel == 0) + { + for (; i != end; ++i) + indexesToFill.push_back(i); + } else { - int child = h[first][2]; - if( child >= 0 ) + std::stack indexes; + for (; i != end; ++i) { - addChildContour(_contours, ncontours, h, child, seq, block); - seq[first].v_next = &seq[child]; + // either all from the top level or a single contour + if (hierarchy.at(i)[3] < 0 || contourIdx >= 0) + indexes.push(i); + } + while (!indexes.empty()) + { + // get current element + const int cur = indexes.top(); + indexes.pop(); + + // check current element depth + int curLevel = -1; + int par = cur; + while (par >= 0) + { + par = hierarchy.at(par)[3]; // parent + ++curLevel; + } + if (curLevel <= maxLevel) + { + indexesToFill.push_back(cur); + } + + int next = hierarchy.at(cur)[2]; // first child + while (next > 0) + { + indexes.push(next); + next = hierarchy.at(next)[0]; // next sibling + } } } + std::vector contoursToFill; + for (const int & idx : indexesToFill) + contoursToFill.push_back(_contours.getMat(idx)); + fillPoly(image, contoursToFill, color, lineType, 0, offset); } - - cvDrawContours( &_cimage, &seq[first], cvScalar(color), cvScalar(color), contourIdx >= 0 ? - -maxLevel : maxLevel, thickness, lineType, cvPoint(offset) ); } - static const int CodeDeltas[8][2] = { {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1} }; diff --git a/modules/imgproc/src/grabcut.cpp b/modules/imgproc/src/grabcut.cpp index 695c0dd6c542..358747843ef0 100644 --- a/modules/imgproc/src/grabcut.cpp +++ b/modules/imgproc/src/grabcut.cpp @@ -389,14 +389,14 @@ static void initGMMs( const Mat& img, const Mat& mask, GMM& bgdGMM, GMM& fgdGMM int num_clusters = GMM::componentsCount; num_clusters = std::min(num_clusters, (int)bgdSamples.size()); kmeans( _bgdSamples, num_clusters, bgdLabels, - TermCriteria( CV_TERMCRIT_ITER, kMeansItCount, 0.0), 0, kMeansType ); + TermCriteria( TermCriteria::MAX_ITER, kMeansItCount, 0.0), 0, kMeansType ); } { Mat _fgdSamples( (int)fgdSamples.size(), 3, CV_32FC1, &fgdSamples[0][0] ); int num_clusters = GMM::componentsCount; num_clusters = std::min(num_clusters, (int)fgdSamples.size()); kmeans( _fgdSamples, num_clusters, fgdLabels, - TermCriteria( CV_TERMCRIT_ITER, kMeansItCount, 0.0), 0, kMeansType ); + TermCriteria( TermCriteria::MAX_ITER, kMeansItCount, 0.0), 0, kMeansType ); } bgdGMM.initLearning(); diff --git a/modules/imgproc/src/moments.cpp b/modules/imgproc/src/moments.cpp index e485104a26d4..786573bbcb16 100644 --- a/modules/imgproc/src/moments.cpp +++ b/modules/imgproc/src/moments.cpp @@ -651,7 +651,7 @@ cv::Moments cv::moments( InputArray _src, bool binary ) if( binary ) { cv::Mat tmp(tileSize, CV_8U, nzbuf); - cv::compare( src, 0, tmp, CV_CMP_NE ); + cv::compare( src, 0, tmp, cv::CMP_NE ); src = tmp; } diff --git a/modules/imgproc/src/precomp.hpp b/modules/imgproc/src/precomp.hpp index df35da529c50..33a921c78a94 100644 --- a/modules/imgproc/src/precomp.hpp +++ b/modules/imgproc/src/precomp.hpp @@ -61,6 +61,7 @@ #include #include #include +#include #define GET_OPTIMIZED(func) (func) diff --git a/modules/imgproc/src/segmentation.cpp b/modules/imgproc/src/segmentation.cpp index 0476c4a244bb..c6dad4ba5749 100644 --- a/modules/imgproc/src/segmentation.cpp +++ b/modules/imgproc/src/segmentation.cpp @@ -373,11 +373,11 @@ void cv::pyrMeanShiftFiltering( InputArray _src, OutputArray _dst, if( src0.size() != dst0.size() ) CV_Error( cv::Error::StsUnmatchedSizes, "The input and output images must have the same size" ); - if( !(termcrit.type & CV_TERMCRIT_ITER) ) + if( !(termcrit.type & TermCriteria::MAX_ITER) ) termcrit.maxCount = 5; termcrit.maxCount = MAX(termcrit.maxCount,1); termcrit.maxCount = MIN(termcrit.maxCount,100); - if( !(termcrit.type & CV_TERMCRIT_EPS) ) + if( !(termcrit.type & TermCriteria::EPS) ) termcrit.epsilon = 1.f; termcrit.epsilon = MAX(termcrit.epsilon, 0.f); diff --git a/modules/imgproc/test/test_contours.cpp b/modules/imgproc/test/test_contours.cpp index 8c6ddc7df7c0..fbd3cabff8f0 100644 --- a/modules/imgproc/test/test_contours.cpp +++ b/modules/imgproc/test/test_contours.cpp @@ -289,7 +289,7 @@ int CV_FindContourTest::validate_test_results( int /*test_case_idx*/ ) { int code = cvtest::TS::OK; - cvCmpS( img[0], 0, img[0], CV_CMP_GT ); + cvCmpS( img[0], 0, img[0], cv::CMP_GT ); if( count != count2 ) { diff --git a/modules/imgproc/test/test_convhull.cpp b/modules/imgproc/test/test_convhull.cpp index 2501a3807501..de45bf2c72cb 100644 --- a/modules/imgproc/test/test_convhull.cpp +++ b/modules/imgproc/test/test_convhull.cpp @@ -1956,12 +1956,6 @@ int CV_ContourMomentsTest::validate_test_results( int test_case_idx ) if( code < 0 ) { -#if 0 - cvCmpS( img, 0, img, CV_CMP_GT ); - cvNamedWindow( "test", 1 ); - cvShowImage( "test", img ); - cvWaitKey(); -#endif ts->set_failed_test_info( code ); } diff --git a/modules/imgproc/test/test_drawing.cpp b/modules/imgproc/test/test_drawing.cpp index cdd2a01b4b23..a6b125bcd1b8 100644 --- a/modules/imgproc/test/test_drawing.cpp +++ b/modules/imgproc/test/test_drawing.cpp @@ -928,4 +928,111 @@ TEST(Drawing, circle_memory_access) cv::circle(matrix, cv::Point(-1, -1), 0, kBlue, 2, 8, 16); } +inline static Mat mosaic2x2(Mat &img) +{ + const Size sz = img.size(); + Mat res(sz * 2, img.type(), Scalar::all(0)); + img.copyTo(res(Rect(Point(0, 0), sz))); + img.copyTo(res(Rect(Point(0, sz.height), sz))); + img.copyTo(res(Rect(Point(sz.width, 0), sz))); + img.copyTo(res(Rect(Point(sz.width, sz.height), sz))); + return res; +} + +TEST(Drawing, contours_filled) +{ + const Scalar white(255); + const Scalar black(0); + const Size sz(100, 100); + + Mat img(sz, CV_8UC1, black); + rectangle(img, Point(20, 20), Point(80, 80), white, -1); + rectangle(img, Point(30, 30), Point(70, 70), black, -1); + rectangle(img, Point(40, 40), Point(60, 60), white, -1); + img = mosaic2x2(img); + + Mat img1(sz, CV_8UC1, black); + rectangle(img1, Point(20, 20), Point(80, 80), white, -1); + img1 = mosaic2x2(img1); + + Mat img2(sz, CV_8UC1, black); + rectangle(img2, Point(20, 20), Point(80, 80), white, -1); + rectangle(img2, Point(30, 30), Point(70, 70), black, -1); + img2 = mosaic2x2(img2); + + Mat img3(sz, CV_8UC1, black); + rectangle(img3, Point(40, 40), Point(60, 60), white, -1); + img3 = mosaic2x2(img3); + + // inverted contours - corners and left edge adjusted + Mat imgi(sz, CV_8UC1, black); + rectangle(imgi, Point(29, 29), Point(71, 71), white, -1); + rectangle(imgi, Point(41, 41), Point(59, 59), black, -1); + imgi.at(Point(29, 29)) = 0; + imgi.at(Point(29, 71)) = 0; + imgi = mosaic2x2(imgi); + + vector> contours; + vector hierarchy; + findContours(img, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE); + ASSERT_EQ(12u, contours.size()); + + // NOTE: + // assuming contour tree has following structure (idx = 0, 1, ...): + // idx (top level) + // - idx + 1 + // - idx + 2 + // idx + 3 (top level) + // - idx + 4 + // - idx + 5 + // ... + const vector top_contours {0, 3, 6, 9}; + { + // all contours + Mat res(img.size(), CV_8UC1, Scalar::all(0)); + drawContours(res, contours, -1, white, -1, cv::LINE_8, hierarchy); + EXPECT_LT(cvtest::norm(img, res, NORM_INF), 1); + } + { + // all contours + Mat res(img.size(), CV_8UC1, Scalar::all(0)); + drawContours(res, contours, -1, white, -1, cv::LINE_8, hierarchy, 3); + EXPECT_LT(cvtest::norm(img, res, NORM_INF), 1); + } + { + // all contours + Mat res(img.size(), CV_8UC1, Scalar::all(0)); + drawContours(res, contours, -1, white, -1, cv::LINE_8, hierarchy, 0); + EXPECT_LT(cvtest::norm(img, res, NORM_INF), 1); + } + { + // all external contours one by one + Mat res(img.size(), CV_8UC1, Scalar::all(0)); + for (int idx : top_contours) + drawContours(res, contours, idx, white, -1, cv::LINE_8, hierarchy, 0); + EXPECT_LT(cvtest::norm(img1, res, NORM_INF), 1); + } + { + // all external contours + 1-level deep hole (one by one) + Mat res(img.size(), CV_8UC1, Scalar::all(0)); + for (int idx : top_contours) + drawContours(res, contours, idx, white, -1, cv::LINE_8, hierarchy, 1); + EXPECT_LT(cvtest::norm(img2, res, NORM_INF), 1); + } + { + // 2-level deep contours + Mat res(img.size(), CV_8UC1, Scalar::all(0)); + for (int idx : top_contours) + drawContours(res, contours, idx + 2, white, -1, cv::LINE_8, hierarchy); + EXPECT_LT(cvtest::norm(img3, res, NORM_INF), 1); + } + { + // holes become inverted here, LINE_8 -> LINE_4 + Mat res(img.size(), CV_8UC1, Scalar::all(0)); + for (int idx : top_contours) + drawContours(res, contours, idx + 1, white, -1, cv::LINE_4, hierarchy); + EXPECT_LT(cvtest::norm(imgi, res, NORM_INF), 1); + } +} + }} // namespace From e05ad56f6e7fa6dfcb8bc9962db9234a093679e8 Mon Sep 17 00:00:00 2001 From: Cristian Dobre <69245609+cristidbr-adapta@users.noreply.github.com> Date: Mon, 20 May 2024 09:53:22 +0300 Subject: [PATCH 061/119] Merge pull request #24903 from cristidbr-adapta:feature-barcode-detector-parameters Feature barcode detector parameters #24903 Attempt to solve #24902 without changing the default detector behaviour. Megre with extra: https://github.com/opencv/opencv_extra/pull/1150 **Introduces new parameters and methods to `cv::barcode::BarcodeDetector`**. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- .../include/opencv2/objdetect/barcode.hpp | 46 ++++++++++ modules/objdetect/src/barcode.cpp | 69 ++++++++++++++- .../src/barcode_detector/bardetect.cpp | 34 +++++--- .../src/barcode_detector/bardetect.hpp | 6 +- modules/objdetect/test/test_barcode.cpp | 85 ++++++++++++++++++- 5 files changed, 222 insertions(+), 18 deletions(-) diff --git a/modules/objdetect/include/opencv2/objdetect/barcode.hpp b/modules/objdetect/include/opencv2/objdetect/barcode.hpp index 788889ad4062..c20b67c0b29e 100644 --- a/modules/objdetect/include/opencv2/objdetect/barcode.hpp +++ b/modules/objdetect/include/opencv2/objdetect/barcode.hpp @@ -57,6 +57,52 @@ class CV_EXPORTS_W_SIMPLE BarcodeDetector : public cv::GraphicalCodeDetector CV_OUT std::vector &decoded_info, CV_OUT std::vector &decoded_type, OutputArray points = noArray()) const; + + /** @brief Get detector downsampling threshold. + * + * @return detector downsampling threshold + */ + CV_WRAP double getDownsamplingThreshold() const; + + /** @brief Set detector downsampling threshold. + * + * By default, the detect method resizes the input image to this limit if the smallest image size is is greater than the threshold. + * Increasing this value can improve detection accuracy and the number of results at the expense of performance. + * Correlates with detector scales. Setting this to a large value will disable downsampling. + * @param thresh downsampling limit to apply (default 512) + * @see setDetectorScales + */ + CV_WRAP BarcodeDetector& setDownsamplingThreshold(double thresh); + + /** @brief Returns detector box filter sizes. + * + * @param sizes output parameter for returning the sizes. + */ + CV_WRAP void getDetectorScales(CV_OUT std::vector& sizes) const; + + /** @brief Set detector box filter sizes. + * + * Adjusts the value and the number of box filters used in the detect step. + * The filter sizes directly correlate with the expected line widths for a barcode. Corresponds to expected barcode distance. + * If the downsampling limit is increased, filter sizes need to be adjusted in an inversely proportional way. + * @param sizes box filter sizes, relative to minimum dimension of the image (default [0.01, 0.03, 0.06, 0.08]) + */ + CV_WRAP BarcodeDetector& setDetectorScales(const std::vector& sizes); + + /** @brief Get detector gradient magnitude threshold. + * + * @return detector gradient magnitude threshold. + */ + CV_WRAP double getGradientThreshold() const; + + /** @brief Set detector gradient magnitude threshold. + * + * Sets the coherence threshold for detected bounding boxes. + * Increasing this value will generate a closer fitted bounding box width and can reduce false-positives. + * Values between 16 and 1024 generally work, while too high of a value will remove valid detections. + * @param thresh gradient magnitude threshold (default 64). + */ + CV_WRAP BarcodeDetector& setGradientThreshold(double thresh); }; //! @} diff --git a/modules/objdetect/src/barcode.cpp b/modules/objdetect/src/barcode.cpp index 172fb5bd771c..1b963e424217 100644 --- a/modules/objdetect/src/barcode.cpp +++ b/modules/objdetect/src/barcode.cpp @@ -142,11 +142,15 @@ struct BarcodeImpl : public GraphicalCodeDetector::Impl public: shared_ptr sr; bool use_nn_sr = false; + double detectorThrDownSample = 512.f; + vector detectorWindowSizes = {0.01f, 0.03f, 0.06f, 0.08f}; + double detectorThrGradMagnitude = 64.f; public: //================= // own methods - BarcodeImpl() = default; + BarcodeImpl() {} + vector initDecode(const Mat &src, const vector> &points) const; bool decodeWithType(InputArray img, InputArray points, @@ -268,8 +272,8 @@ bool BarcodeImpl::detect(InputArray img, OutputArray points) const } Detect bardet; - bardet.init(inarr); - bardet.localization(); + bardet.init(inarr, detectorThrDownSample); + bardet.localization(detectorWindowSizes, detectorThrGradMagnitude); if (!bardet.computeTransformationPoints()) { return false; } vector> pnts2f = bardet.getTransformationPoints(); @@ -370,5 +374,64 @@ bool BarcodeDetector::detectAndDecodeWithType(InputArray img, vector &de return p_->detectAndDecodeWithType(img, decoded_info, decoded_type, points_); } +double BarcodeDetector::getDownsamplingThreshold() const +{ + Ptr p_ = dynamic_pointer_cast(p); + CV_Assert(p_); + + return p_->detectorThrDownSample; +} + +BarcodeDetector& BarcodeDetector::setDownsamplingThreshold(double thresh) +{ + Ptr p_ = dynamic_pointer_cast(p); + CV_Assert(p_); + CV_Assert(thresh >= 64); + + p_->detectorThrDownSample = thresh; + return *this; +} + +void BarcodeDetector::getDetectorScales(CV_OUT std::vector& sizes) const +{ + Ptr p_ = dynamic_pointer_cast(p); + CV_Assert(p_); + + sizes = p_->detectorWindowSizes; +} + +BarcodeDetector& BarcodeDetector::setDetectorScales(const std::vector& sizes) +{ + Ptr p_ = dynamic_pointer_cast(p); + CV_Assert(p_); + CV_Assert(sizes.size() > 0 && sizes.size() <= 16); + + for (const float &size : sizes) { + CV_Assert(size > 0 && size < 1); + } + + p_->detectorWindowSizes = sizes; + + return *this; +} + +double BarcodeDetector::getGradientThreshold() const +{ + Ptr p_ = dynamic_pointer_cast(p); + CV_Assert(p_); + + return p_->detectorThrGradMagnitude; +} + +BarcodeDetector& BarcodeDetector::setGradientThreshold(double thresh) +{ + Ptr p_ = dynamic_pointer_cast(p); + CV_Assert(p_); + CV_Assert(thresh >= 0 && thresh < 1e4); + + p_->detectorThrGradMagnitude = thresh; + return *this; +} + }// namespace barcode } // namespace cv diff --git a/modules/objdetect/src/barcode_detector/bardetect.cpp b/modules/objdetect/src/barcode_detector/bardetect.cpp index b156d1b25d9a..abb30bf5472f 100644 --- a/modules/objdetect/src/barcode_detector/bardetect.cpp +++ b/modules/objdetect/src/barcode_detector/bardetect.cpp @@ -136,13 +136,13 @@ static void NMSBoxes(const std::vector& bboxes, const std::vector 512.0) + if (min_side > detectorThreshDownSamplingLimit) { purpose = SHRINKING; - coeff_expansion = min_side / 512.0; + coeff_expansion = min_side / detectorThreshDownSamplingLimit; width = cvRound(src.size().width / coeff_expansion); height = cvRound(src.size().height / coeff_expansion); Size new_size(width, height); @@ -171,19 +171,19 @@ void Detect::init(const Mat &src) } -void Detect::localization() +void Detect::localization(const std::vector& detectorWindowSizes, double detectorThreshGradientMagnitude) { localization_bbox.clear(); bbox_scores.clear(); // get integral image - preprocess(); + preprocess(detectorThreshGradientMagnitude); // empirical setting - static constexpr float SCALE_LIST[] = {0.01f, 0.03f, 0.06f, 0.08f}; + //static constexpr float SCALE_LIST[] = {0.01f, 0.03f, 0.06f, 0.08f}; const auto min_side = static_cast(std::min(width, height)); int window_size; - for (const float scale:SCALE_LIST) + for (const float scale: detectorWindowSizes) { window_size = cvRound(min_side * scale); if(window_size == 0) { @@ -205,7 +205,20 @@ bool Detect::computeTransformationPoints() transformation_points.reserve(bbox_indices.size()); RotatedRect rect; Point2f temp[4]; - const float THRESHOLD_SCORE = float(width * height) / 300.f; + + /** + * #24902 resolution invariant barcode detector + * + * refactor of THRESHOLD_SCORE = float(width * height) / 300.f + * wrt to rescaled input size - 300 value needs factorization + * only one factor pair matches a common aspect ratio of 4:3 ~ 20x15 + * decomposing this yields THRESHOLD_SCORE = (width / 20) * (height / 15) + * therefore each factor was rescaled based by purpose (refsize was 512) + */ + const float THRESHOLD_WSCALE = (purpose != UNCHANGED) ? 20 : (20 * width / 512.f); + const float THRESHOLD_HSCALE = (purpose != UNCHANGED) ? 15 : (15 * height / 512.f); + const float THRESHOLD_SCORE = (width / THRESHOLD_WSCALE) * (height / THRESHOLD_HSCALE); + NMSBoxes(localization_bbox, bbox_scores, THRESHOLD_SCORE, 0.1f, bbox_indices); for (const auto &bbox_index : bbox_indices) @@ -231,15 +244,14 @@ bool Detect::computeTransformationPoints() } -void Detect::preprocess() +void Detect::preprocess(double detectorGradientMagnitudeThresh) { Mat scharr_x, scharr_y, temp; - static constexpr double THRESHOLD_MAGNITUDE = 64.; Scharr(resized_barcode, scharr_x, CV_32F, 1, 0); Scharr(resized_barcode, scharr_y, CV_32F, 0, 1); // calculate magnitude of gradient and truncate magnitude(scharr_x, scharr_y, temp); - threshold(temp, temp, THRESHOLD_MAGNITUDE, 1, THRESH_BINARY); + threshold(temp, temp, detectorGradientMagnitudeThresh, 1, THRESH_BINARY); temp.convertTo(gradient_magnitude, CV_8U); integral(gradient_magnitude, integral_edges, CV_32F); diff --git a/modules/objdetect/src/barcode_detector/bardetect.hpp b/modules/objdetect/src/barcode_detector/bardetect.hpp index 9f084d20aa13..178fded36f5c 100644 --- a/modules/objdetect/src/barcode_detector/bardetect.hpp +++ b/modules/objdetect/src/barcode_detector/bardetect.hpp @@ -24,9 +24,9 @@ class Detect public: - void init(const Mat &src); + void init(const Mat &src, double detectorThreshDownSamplingLimit); - void localization(); + void localization(const vector& detectorWindowSizes, double detectorGradientMagnitudeThresh); vector> getTransformationPoints() { return transformation_points; } @@ -44,7 +44,7 @@ class Detect int height, width; Mat resized_barcode, gradient_magnitude, coherence, orientation, edge_nums, integral_x_sq, integral_y_sq, integral_xy, integral_edges; - void preprocess(); + void preprocess(double detectorThreshGradientMagnitude); void calCoherence(int window_size); diff --git a/modules/objdetect/test/test_barcode.cpp b/modules/objdetect/test/test_barcode.cpp index 7e295fafa3b5..94542ca39ba5 100644 --- a/modules/objdetect/test/test_barcode.cpp +++ b/modules/objdetect/test/test_barcode.cpp @@ -60,7 +60,7 @@ map testResults { { "single/book.jpg", {"EAN_13", "9787115279460"} }, { "single/bottle_1.jpg", {"EAN_13", "6922255451427"} }, { "single/bottle_2.jpg", {"EAN_13", "6921168509256"} }, - { "multiple/4_barcodes.jpg", {"EAN_13;EAN_13;EAN_13;EAN_13", "9787564350840;9783319200064;9787118081473;9787122276124"} } + { "multiple/4_barcodes.jpg", {"EAN_13;EAN_13;EAN_13;EAN_13", "9787564350840;9783319200064;9787118081473;9787122276124"} }, }; typedef testing::TestWithParam< string > BarcodeDetector_main; @@ -144,4 +144,87 @@ TEST(BarcodeDetector_base, invalid) EXPECT_ANY_THROW(bardet.decodeMulti(zero_image, corners, decoded_info)); } +struct ParamStruct +{ + double down_thresh; + vector scales; + double grad_thresh; + unsigned res_count; +}; + +inline static std::ostream &operator<<(std::ostream &out, const ParamStruct &p) +{ + out << "(" << p.down_thresh << ", "; + for(float val : p.scales) + out << val << ", "; + out << p.grad_thresh << ")"; + return out; +} + +ParamStruct param_list[] = { + { 512, {0.01f, 0.03f, 0.06f, 0.08f}, 64, 4 }, // default values -> 4 codes + { 512, {0.01f, 0.03f, 0.06f, 0.08f}, 1024, 2 }, + { 512, {0.01f, 0.03f, 0.06f, 0.08f}, 2048, 0 }, + { 128, {0.01f, 0.03f, 0.06f, 0.08f}, 64, 3 }, + { 64, {0.01f, 0.03f, 0.06f, 0.08f}, 64, 2 }, + { 128, {0.0000001f}, 64, 1 }, + { 128, {0.0000001f, 0.0001f}, 64, 1 }, + { 128, {0.0000001f, 0.1f}, 64, 1 }, + { 512, {0.1f}, 64, 0 }, +}; + +typedef testing::TestWithParam BarcodeDetector_parameters_tune; + +TEST_P(BarcodeDetector_parameters_tune, accuracy) +{ + const ParamStruct param = GetParam(); + + const string fname = "multiple/4_barcodes.jpg"; + const string image_path = findDataFile(string("barcode/") + fname); + + const Mat img = imread(image_path); + ASSERT_FALSE(img.empty()) << "Can't read image: " << image_path; + + auto bardet = barcode::BarcodeDetector(); + bardet.setDownsamplingThreshold(param.down_thresh); + bardet.setDetectorScales(param.scales); + bardet.setGradientThreshold(param.grad_thresh); + vector points; + bardet.detectMulti(img, points); + EXPECT_EQ(points.size() / 4, param.res_count); +} + +INSTANTIATE_TEST_CASE_P(/**/, BarcodeDetector_parameters_tune, testing::ValuesIn(param_list)); + +TEST(BarcodeDetector_parameters, regression) +{ + const double expected_dt = 1024, expected_gt = 256; + const vector expected_ds = {0.1f}; + vector ds_value = {0.0f}; + + auto bardet = barcode::BarcodeDetector(); + + bardet.setDownsamplingThreshold(expected_dt).setDetectorScales(expected_ds).setGradientThreshold(expected_gt); + + double dt_value = bardet.getDownsamplingThreshold(); + bardet.getDetectorScales(ds_value); + double gt_value = bardet.getGradientThreshold(); + + EXPECT_EQ(expected_dt, dt_value); + EXPECT_EQ(expected_ds, ds_value); + EXPECT_EQ(expected_gt, gt_value); +} + +TEST(BarcodeDetector_parameters, invalid) +{ + auto bardet = barcode::BarcodeDetector(); + + EXPECT_ANY_THROW(bardet.setDownsamplingThreshold(-1)); + EXPECT_ANY_THROW(bardet.setDetectorScales(vector {})); + EXPECT_ANY_THROW(bardet.setDetectorScales(vector {-1})); + EXPECT_ANY_THROW(bardet.setDetectorScales(vector {1.5})); + EXPECT_ANY_THROW(bardet.setDetectorScales(vector (17, 0.5))); + EXPECT_ANY_THROW(bardet.setGradientThreshold(-0.1)); +} + }} // opencv_test:::: From 83e32c4d37a8ddee41e7ecf5c9b42c6caa970a1d Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Mon, 20 May 2024 09:42:17 +0200 Subject: [PATCH 062/119] Merge pull request #25511 from savuor:rv/hal_projectpoints HAL for projectPoints() added #25511 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/calib3d/src/calibration.cpp | 207 ++++++++++++++++++------ modules/calib3d/src/hal_replacement.hpp | 188 +++++++++++++++++++++ 2 files changed, 345 insertions(+), 50 deletions(-) create mode 100644 modules/calib3d/src/hal_replacement.hpp diff --git a/modules/calib3d/src/calibration.cpp b/modules/calib3d/src/calibration.cpp index 50940a80ffdf..c428da6bd5c4 100644 --- a/modules/calib3d/src/calibration.cpp +++ b/modules/calib3d/src/calibration.cpp @@ -41,6 +41,7 @@ //M*/ #include "precomp.hpp" +#include "hal_replacement.hpp" #include "opencv2/imgproc/imgproc_c.h" #include "distortion_model.hpp" #include "calib3d_c_api.h" @@ -516,7 +517,6 @@ CV_IMPL int cvRodrigues2( const CvMat* src, CvMat* dst, CvMat* jacobian ) return 1; } - static const char* cvDistCoeffErr = "Distortion coefficients must be 1x4, 4x1, 1x5, 5x1, 1x8, 8x1, 1x12, 12x1, 1x14 or 14x1 floating-point vector"; static void cvProjectPoints2Internal( const CvMat* objectPoints, @@ -555,7 +555,10 @@ static void cvProjectPoints2Internal( const CvMat* objectPoints, /*!CV_IS_MAT(distCoeffs) ||*/ !CV_IS_MAT(imagePoints) ) CV_Error( cv::Error::StsBadArg, "One of required arguments is not a valid matrix" ); - int total = objectPoints->rows * objectPoints->cols * CV_MAT_CN(objectPoints->type); + int odepth = CV_MAT_DEPTH(objectPoints->type); + int ochans = CV_MAT_CN(objectPoints->type); + int orows = objectPoints->rows, ocols = objectPoints->cols; + int total = orows * ocols * ochans; if(total % 3 != 0) { //we have stopped support of homogeneous coordinates because it cause ambiguity in interpretation of the input data @@ -563,39 +566,22 @@ static void cvProjectPoints2Internal( const CvMat* objectPoints, } count = total / 3; - if( CV_IS_CONT_MAT(objectPoints->type) && - (CV_MAT_DEPTH(objectPoints->type) == CV_32F || CV_MAT_DEPTH(objectPoints->type) == CV_64F)&& - ((objectPoints->rows == 1 && CV_MAT_CN(objectPoints->type) == 3) || - (objectPoints->rows == count && CV_MAT_CN(objectPoints->type)*objectPoints->cols == 3) || - (objectPoints->rows == 3 && CV_MAT_CN(objectPoints->type) == 1 && objectPoints->cols == count))) - { - matM.reset(cvCreateMat( objectPoints->rows, objectPoints->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(objectPoints->type)) )); - cvConvert(objectPoints, matM); - } - else - { -// matM = cvCreateMat( 1, count, CV_64FC3 ); -// cvConvertPointsHomogeneous( objectPoints, matM ); - CV_Error( cv::Error::StsBadArg, "Homogeneous coordinates are not supported" ); - } - - if( CV_IS_CONT_MAT(imagePoints->type) && - (CV_MAT_DEPTH(imagePoints->type) == CV_32F || CV_MAT_DEPTH(imagePoints->type) == CV_64F) && - ((imagePoints->rows == 1 && CV_MAT_CN(imagePoints->type) == 2) || - (imagePoints->rows == count && CV_MAT_CN(imagePoints->type)*imagePoints->cols == 2) || - (imagePoints->rows == 2 && CV_MAT_CN(imagePoints->type) == 1 && imagePoints->cols == count))) - { - _m.reset(cvCreateMat( imagePoints->rows, imagePoints->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(imagePoints->type)) )); - cvConvert(imagePoints, _m); - } - else - { -// _m = cvCreateMat( 1, count, CV_64FC2 ); - CV_Error( cv::Error::StsBadArg, "Homogeneous coordinates are not supported" ); - } - - M = (CvPoint3D64f*)matM->data.db; - m = (CvPoint2D64f*)_m->data.db; + CV_Assert(CV_IS_CONT_MAT(objectPoints->type)); + CV_Assert(odepth == CV_32F || odepth == CV_64F); + // Homogeneous coordinates are not supported + CV_Assert((orows == 1 && ochans == 3) || + (orows == count && ochans*ocols == 3) || + (orows == 3 && ochans == 1 && ocols == count)); + + int idepth = CV_MAT_DEPTH(imagePoints->type); + int ichans = CV_MAT_CN(imagePoints->type); + int irows = imagePoints->rows, icols = imagePoints->cols; + CV_Assert(CV_IS_CONT_MAT(imagePoints->type)); + CV_Assert(idepth == CV_32F || idepth == CV_64F); + // Homogeneous coordinates are not supported + CV_Assert((irows == 1 && ichans == 2) || + (irows == count && ichans*icols == 2) || + (irows == 2 && ichans == 1 && icols == count)); if( (CV_MAT_DEPTH(r_vec->type) != CV_64F && CV_MAT_DEPTH(r_vec->type) != CV_32F) || (((r_vec->rows != 1 && r_vec->cols != 1) || @@ -638,27 +624,148 @@ static void cvProjectPoints2Internal( const CvMat* objectPoints, if( fixedAspectRatio ) fx = fy*aspectRatio; + int delems = 0; if( distCoeffs ) { - if( !CV_IS_MAT(distCoeffs) || - (CV_MAT_DEPTH(distCoeffs->type) != CV_64F && - CV_MAT_DEPTH(distCoeffs->type) != CV_32F) || - (distCoeffs->rows != 1 && distCoeffs->cols != 1) || - (distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) != 4 && - distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) != 5 && - distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) != 8 && - distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) != 12 && - distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) != 14) ) - CV_Error( cv::Error::StsBadArg, cvDistCoeffErr ); - - _k = cvMat( distCoeffs->rows, distCoeffs->cols, - CV_MAKETYPE(CV_64F,CV_MAT_CN(distCoeffs->type)), k ); + CV_Assert(CV_IS_MAT(distCoeffs)); + + int ddepth = CV_MAT_DEPTH(distCoeffs->type); + int dchans = CV_MAT_CN(distCoeffs->type); + int drows = distCoeffs->rows, dcols = distCoeffs->cols; + delems = drows * dcols * dchans; + CV_Assert((ddepth == CV_32F || ddepth == CV_64F) && + (drows == 1 || dcols == 1) && + (delems == 4 || delems == 5 || delems == 8 || delems == 12 || delems == 14)); + + _k = cvMat( drows, dcols, CV_MAKETYPE(CV_64F, dchans), k ); cvConvert( distCoeffs, &_k ); if(k[12] != 0 || k[13] != 0) { - detail::computeTiltProjectionMatrix(k[12], k[13], - &matTilt, &dMatTiltdTauX, &dMatTiltdTauY); + detail::computeTiltProjectionMatrix(k[12], k[13], &matTilt, &dMatTiltdTauX, &dMatTiltdTauY); + } + } + + if (idepth == CV_32F && odepth == CV_32F) + { + float rtMatrix[12] = { (float)R[0], (float)R[1], (float)R[2], (float)t[0], + (float)R[3], (float)R[4], (float)R[5], (float)t[1], + (float)R[6], (float)R[7], (float)R[8], (float)t[2] }; + + cv_camera_intrinsics_pinhole_32f intr; + intr.fx = (float)fx; intr.fy = (float)fy; + intr.cx = (float)cx; intr.cy = (float)cy; + intr.amt_k = 0; intr.amt_p = 0; intr.amt_s = 0; intr.use_tau = false; + + switch (delems) + { + case 0: break; + case 4: // [k_1, k_2, p_1, p_2] + intr.amt_k = 2; intr.amt_p = 2; + break; + case 5: // [k_1, k_2, p_1, p_2, k_3] + intr.amt_k = 3; intr.amt_p = 2; + break; + case 8: // [k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6] + intr.amt_k = 6; intr.amt_p = 2; + break; + case 12: // [k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6, s_1, s_2, s_3, s_4] + intr.amt_k = 6; intr.amt_p = 2; intr.amt_s = 4; + break; + case 14: // [k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6, s_1, s_2, s_3, s_4, tau_x, tau_y] + intr.amt_k = 6; intr.amt_p = 2; intr.amt_s = 4; intr.use_tau = true; + break; + default: + CV_Error(cv::Error::StsInternal, "Wrong number of distortion coefficients"); + } + + intr.k[0] = (float)k[0]; + intr.k[1] = (float)k[1]; + intr.k[2] = (float)k[4]; + intr.k[3] = (float)k[5]; + intr.k[4] = (float)k[6]; + intr.k[5] = (float)k[7]; + + intr.p[0] = (float)k[2]; + intr.p[1] = (float)k[3]; + + for (int ctr = 0; ctr < 4; ctr++) + { + intr.s[ctr] = (float)k[8+ctr]; } + + intr.tau_x = (float)k[12]; + intr.tau_y = (float)k[13]; + + CALL_HAL(projectPoints, cv_hal_project_points_pinhole32f, + objectPoints->data.fl, objectPoints->step, count, + imagePoints->data.fl, imagePoints->step, + rtMatrix, &intr); + } + + _m.reset(cvCreateMat( imagePoints->rows, imagePoints->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(imagePoints->type)) )); + cvConvert(imagePoints, _m); + + matM.reset(cvCreateMat( objectPoints->rows, objectPoints->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(objectPoints->type)) )); + cvConvert(objectPoints, matM); + + M = (CvPoint3D64f*)matM->data.db; + m = (CvPoint2D64f*)_m->data.db; + + if (idepth == CV_64F && odepth == CV_64F) + { + double rtMatrix[12] = { R[0], R[1], R[2], t[0], + R[3], R[4], R[5], t[1], + R[6], R[7], R[8], t[2] }; + + cv_camera_intrinsics_pinhole_64f intr; + intr.fx = fx; intr.fy = fy; + intr.cx = cx; intr.cy = cy; + intr.amt_k = 0; intr.amt_p = 0; intr.amt_s = 0; intr.use_tau = false; + + switch (delems) + { + case 0: break; + case 4: // [k_1, k_2, p_1, p_2] + intr.amt_k = 2; intr.amt_p = 2; + break; + case 5: // [k_1, k_2, p_1, p_2, k_3] + intr.amt_k = 3; intr.amt_p = 2; + break; + case 8: // [k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6] + intr.amt_k = 6; intr.amt_p = 2; + break; + case 12: // [k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6, s_1, s_2, s_3, s_4] + intr.amt_k = 6; intr.amt_p = 2; intr.amt_s = 4; + break; + case 14: // [k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6, s_1, s_2, s_3, s_4, tau_x, tau_y] + intr.amt_k = 6; intr.amt_p = 2; intr.amt_s = 4; intr.use_tau = true; + break; + default: + CV_Error(cv::Error::StsInternal, "Wrong number of distortion coefficients"); + } + + intr.k[0] = k[0]; + intr.k[1] = k[1]; + intr.k[2] = k[4]; + intr.k[3] = k[5]; + intr.k[4] = k[6]; + intr.k[5] = k[7]; + + intr.p[0] = k[2]; + intr.p[1] = k[3]; + + for (int ctr = 0; ctr < 4; ctr++) + { + intr.s[ctr] = k[8+ctr]; + } + + intr.tau_x = k[12]; + intr.tau_y = k[13]; + + CALL_HAL(projectPoints, cv_hal_project_points_pinhole64f, + objectPoints->data.db, objectPoints->step, count, + imagePoints->data.db, imagePoints->step, + rtMatrix, &intr); } if( dpdr ) diff --git a/modules/calib3d/src/hal_replacement.hpp b/modules/calib3d/src/hal_replacement.hpp new file mode 100644 index 000000000000..8874c9127be7 --- /dev/null +++ b/modules/calib3d/src/hal_replacement.hpp @@ -0,0 +1,188 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef OPENCV_CALIB3D_HAL_REPLACEMENT_HPP +#define OPENCV_CALIB3D_HAL_REPLACEMENT_HPP + +#include "opencv2/core/hal/interface.h" + +#if defined(__clang__) // clang or MSVC clang +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +#elif defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4100) +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//! @addtogroup calib3d_hal_interface +//! @note Define your functions to override default implementations: +//! @code +//! #undef hal_add8u +//! #define hal_add8u my_add8u +//! @endcode +//! @{ + +/** + * @brief Camera intrinsics structure, see projectPoints() documentation for details + */ +struct cv_camera_intrinsics_pinhole_32f +{ + // focal length, principal point + float fx, fy, cx, cy; + // radial distortion coefficients + float k[6]; + // amount of radial distortion coefficients passed + int amt_k; + // tangential distortion coefficients + float p[2]; + // amount of tangential distortion coefficients passed + int amt_p; + // prism distortion coefficients + float s[4]; + // amount of prism distortion coefficients passed + int amt_s; + // tilt distortion coefficients + float tau_x, tau_y; + // to use tilt distortion coefficients or not + bool use_tau; +}; + +/** + @brief Project points from 3D world space to 2D screen space using rotation and translation matrix and camera intrinsic parameters + @param src_data Pointer to 3D points array with coordinates interleaved as X, Y, Z, X, Y, Z,.. + @param src_step Step between consecutive 3D points + @param src_size Amount of points + @param dst_data Pointer to resulting projected 2D points with coordinates interleaved as u, v, u, v,.. + @param dst_step Step between consecutive projected 2D points + @param rt_data Pointer to 3x4 array containing rotation-then-translation matrix + @param intr_data Pointer to camera intrinsics structure +*/ +inline int hal_ni_project_points_pinhole32f(const float* src_data, size_t src_step, size_t src_size, + float* dst_data, size_t dst_step, const float* rt_data, + const cv_camera_intrinsics_pinhole_32f* intr_data) +{ return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +//! @cond IGNORED +#define cv_hal_project_points_pinhole32f hal_ni_project_points_pinhole32f +//! @endcond + +/** + * @brief Camera intrinsics structure, see projectPoints() documentation for details + */ +struct cv_camera_intrinsics_pinhole_64f +{ + // focal length, principal point + double fx, fy, cx, cy; + // radial distortion coefficients + double k[6]; + // amount of radial distortion coefficients passed + int amt_k; + // tangential distortion coefficients + double p[2]; + // amount of tangential distortion coefficients passed + int amt_p; + // prism distortion coefficients + double s[4]; + // amount of prism distortion coefficients passed + int amt_s; + // tilt distortion coefficients + double tau_x, tau_y; + // to use tilt distortion coefficients or not + bool use_tau; +}; + +/** + @brief Project points from 3D world space to 2D screen space using rotation and translation matrix and camera intrinsic parameters + @param src_data Pointer to 3D points array with coordinates interleaved as X, Y, Z, X, Y, Z,.. + @param src_step Step between consecutive 3D points + @param src_size Amount of points + @param dst_data Pointer to resulting projected 2D points with coordinates interleaved as u, v, u, v,.. + @param dst_step Step between consecutive projected 2D points + @param rt_data Pointer to 3x4 array containing rotation-then-translation matrix + @param intr_data Pointer to camera intrinsics structure +*/ +inline int hal_ni_project_points_pinhole64f(const double* src_data, size_t src_step, size_t src_size, + double* dst_data, size_t dst_step, const double* rt_data, + const cv_camera_intrinsics_pinhole_64f* intr_data) +{ return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +//! @cond IGNORED +#define cv_hal_project_points_pinhole64f hal_ni_project_points_pinhole64f +//! @endcond + +//! @} + +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(_MSC_VER) +#pragma warning(pop) +#elif defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +#include "custom_hal.hpp" + +//! @cond IGNORED +#define CALL_HAL_RET(name, fun, retval, ...) \ + int res = __CV_EXPAND(fun(__VA_ARGS__, &retval)); \ + if (res == CV_HAL_ERROR_OK) \ + return retval; \ + else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) \ + CV_Error_(cv::Error::StsInternal, \ + ("HAL implementation " CVAUX_STR(name) " ==> " CVAUX_STR(fun) " returned %d (0x%08x)", res, res)); + + +#define CALL_HAL(name, fun, ...) \ + int res = __CV_EXPAND(fun(__VA_ARGS__)); \ + if (res == CV_HAL_ERROR_OK) \ + return; \ + else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) \ + CV_Error_(cv::Error::StsInternal, \ + ("HAL implementation " CVAUX_STR(name) " ==> " CVAUX_STR(fun) " returned %d (0x%08x)", res, res)); +//! @endcond + +#endif From 69af621ef63a508ab9d1abbfa259a6876622e71e Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Mon, 20 May 2024 09:43:18 +0200 Subject: [PATCH 063/119] Merge pull request #25506 from savuor:rv/hal_mul16 HAL mul8x8to16 added #25506 Fixes #25034 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/core/src/arithm.cpp | 196 +++++++++++++++++++-------- modules/core/src/hal_replacement.hpp | 4 + 2 files changed, 146 insertions(+), 54 deletions(-) diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index f4ca2d7da966..5a189867c2ea 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -585,9 +585,14 @@ static bool ocl_arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, #endif +typedef int (*ExtendedTypeFunc)(const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, int width, int height, + void*); + static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, InputArray _mask, int dtype, BinaryFuncC* tab, bool muldiv=false, - void* usrdata=0, int oclop=-1 ) + void* usrdata=0, int oclop=-1, ExtendedTypeFunc extendedFunc = nullptr ) { const _InputArray *psrc1 = &_src1, *psrc2 = &_src2; _InputArray::KindFlag kind1 = psrc1->kind(), kind2 = psrc2->kind(); @@ -617,9 +622,13 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, Mat src1 = psrc1->getMat(), src2 = psrc2->getMat(), dst = _dst.getMat(); Size sz = getContinuousSize2D(src1, src2, dst, src1.channels()); - BinaryFuncC func = tab[depth1]; - CV_Assert(func); - func(src1.ptr(), src1.step, src2.ptr(), src2.step, dst.ptr(), dst.step, sz.width, sz.height, usrdata); + if (!extendedFunc || extendedFunc(src1.ptr(), src1.step, src2.ptr(), src2.step, + dst.ptr(), dst.step, sz.width, sz.height, usrdata) != 0) + { + BinaryFuncC func = tab[depth1]; + CV_Assert(func); + func(src1.ptr(), src1.step, src2.ptr(), src2.step, dst.ptr(), dst.step, sz.width, sz.height, usrdata); + } return; } @@ -750,14 +759,22 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, _buf.allocate(bufesz*blocksize + 64); buf = _buf.data(); if( cvtsrc1 ) + { buf1 = buf, buf = alignPtr(buf + blocksize*wsz, 16); + } if( cvtsrc2 ) + { buf2 = buf, buf = alignPtr(buf + blocksize*wsz, 16); + } wbuf = maskbuf = buf; if( cvtdst ) + { buf = alignPtr(buf + blocksize*wsz, 16); + } if( haveMask ) + { maskbuf = buf; + } for( size_t i = 0; i < it.nplanes; i++, ++it ) { @@ -767,38 +784,44 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, Size bszn(bsz*cn, 1); const uchar *sptr1 = ptrs[0], *sptr2 = ptrs[1]; uchar* dptr = ptrs[2]; - if( cvtsrc1 ) - { - cvtsrc1( sptr1, 1, 0, 1, buf1, 1, bszn, 0 ); - sptr1 = buf1; - } - if( ptrs[0] == ptrs[1] ) - sptr2 = sptr1; - else if( cvtsrc2 ) - { - cvtsrc2( sptr2, 1, 0, 1, buf2, 1, bszn, 0 ); - sptr2 = buf2; - } - - if( !haveMask && !cvtdst ) - func( sptr1, 1, sptr2, 1, dptr, 1, bszn.width, bszn.height, usrdata ); - else + // try to perform operation with conversion in one call + // if fail, use converter functions + uchar* opconverted = haveMask ? maskbuf : dptr; + if (!extendedFunc || extendedFunc(sptr1, 1, sptr2, 1, opconverted, (!haveMask), + bszn.width, bszn.height, usrdata) != 0) { - func( sptr1, 1, sptr2, 1, wbuf, 0, bszn.width, bszn.height, usrdata ); - if( !haveMask ) - cvtdst( wbuf, 1, 0, 1, dptr, 1, bszn, 0 ); - else if( !cvtdst ) + if( cvtsrc1 ) { - copymask( wbuf, 1, ptrs[3], 1, dptr, 1, Size(bsz, 1), &dsz ); - ptrs[3] += bsz; + cvtsrc1( sptr1, 1, 0, 1, buf1, 1, bszn, 0 ); + sptr1 = buf1; } - else + if( ptrs[0] == ptrs[1] ) { - cvtdst( wbuf, 1, 0, 1, maskbuf, 1, bszn, 0 ); - copymask( maskbuf, 1, ptrs[3], 1, dptr, 1, Size(bsz, 1), &dsz ); - ptrs[3] += bsz; + sptr2 = sptr1; } + else if( cvtsrc2 ) + { + cvtsrc2( sptr2, 1, 0, 1, buf2, 1, bszn, 0 ); + sptr2 = buf2; + } + + uchar* fdst = (haveMask || cvtdst) ? wbuf : dptr; + func(sptr1, 1, sptr2, 1, fdst, (!haveMask && !cvtdst), bszn.width, bszn.height, usrdata); + + if (cvtdst) + { + uchar* cdst = haveMask ? maskbuf : dptr; + cvtdst(wbuf, 1, 0, 1, cdst, 1, bszn, 0); + } + opconverted = cvtdst ? maskbuf : wbuf; + } + + if (haveMask) + { + copymask(opconverted, 1, ptrs[3], 1, dptr, 1, Size(bsz, 1), &dsz); + ptrs[3] += bsz; } + ptrs[0] += bsz*esz1; ptrs[1] += bsz*esz2; ptrs[2] += bsz*dsz; } } @@ -814,13 +837,19 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, _buf.allocate(bufesz*blocksize + 64); buf = _buf.data(); if( cvtsrc1 ) - buf1 = buf, buf = alignPtr(buf + blocksize*wsz, 16); + { + buf1 = buf, buf = alignPtr(buf + blocksize * wsz, 16); + } buf2 = buf; buf = alignPtr(buf + blocksize*wsz, 16); wbuf = maskbuf = buf; if( cvtdst ) - buf = alignPtr(buf + blocksize*wsz, 16); + { + buf = alignPtr(buf + blocksize * wsz, 16); + } if( haveMask ) + { maskbuf = buf; + } convertAndUnrollScalar( src2, wtype, buf2, blocksize); @@ -834,34 +863,43 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, const uchar* sptr2 = buf2; uchar* dptr = ptrs[1]; - if( cvtsrc1 ) - { - cvtsrc1( sptr1, 1, 0, 1, buf1, 1, bszn, 0 ); - sptr1 = buf1; - } - + const uchar* extSptr1 = sptr1; + const uchar* extSptr2 = sptr2; if( swapped12 ) - std::swap(sptr1, sptr2); + std::swap(extSptr1, extSptr1); - if( !haveMask && !cvtdst ) - func( sptr1, 1, sptr2, 1, dptr, 1, bszn.width, bszn.height, usrdata ); - else + // try to perform operation with conversion in one call + // if fail, use converter functions + uchar* opconverted = haveMask ? maskbuf : dptr; + if (!extendedFunc || extendedFunc(extSptr1, 1, extSptr2, 1, opconverted, 1, + bszn.width, bszn.height, usrdata) != 0) { - func( sptr1, 1, sptr2, 1, wbuf, 1, bszn.width, bszn.height, usrdata ); - if( !haveMask ) - cvtdst( wbuf, 1, 0, 1, dptr, 1, bszn, 0 ); - else if( !cvtdst ) + if( cvtsrc1 ) { - copymask( wbuf, 1, ptrs[2], 1, dptr, 1, Size(bsz, 1), &dsz ); - ptrs[2] += bsz; + cvtsrc1( sptr1, 1, 0, 1, buf1, 1, bszn, 0 ); + sptr1 = buf1; } - else + + if( swapped12 ) + std::swap(sptr1, sptr2); + + uchar* fdst = ( haveMask || cvtdst ) ? wbuf : dptr; + func( sptr1, 1, sptr2, 1, fdst, 1, bszn.width, bszn.height, usrdata ); + + if (cvtdst) { - cvtdst( wbuf, 1, 0, 1, maskbuf, 1, bszn, 0 ); - copymask( maskbuf, 1, ptrs[2], 1, dptr, 1, Size(bsz, 1), &dsz ); - ptrs[2] += bsz; + uchar* cdst = haveMask ? maskbuf : dptr; + cvtdst(wbuf, 1, 0, 1, cdst, 1, bszn, 0); } + opconverted = cvtdst ? maskbuf : wbuf; + } + + if (haveMask) + { + copymask(opconverted, 1, ptrs[2], 1, dptr, 1, Size(bsz, 1), &dsz); + ptrs[2] += bsz; } + ptrs[0] += bsz*esz1; ptrs[1] += bsz*dsz; } } @@ -949,6 +987,38 @@ void cv::copyTo(InputArray _src, OutputArray _dst, InputArray _mask) namespace cv { +static int mul8u16uWrapper(const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, int width, int height, + void* usrdata) +{ + double scale = *((double*)usrdata); + int res = cv_hal_mul8u16u(src1, step1, src2, step2, (ushort *)dst, step, width, height, scale); + if (res == CV_HAL_ERROR_OK || res == CV_HAL_ERROR_NOT_IMPLEMENTED) + return res; + else + { + CV_Error_(cv::Error::StsInternal, ("HAL implementation mul8u16u ==> " CVAUX_STR(cv_hal_mul8u16u) + " returned %d (0x%08x)", res, res)); + } +} + +static int mul8s16sWrapper(const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, int width, int height, + void* usrdata) +{ + double scale = *((double*)usrdata); + int res = cv_hal_mul8s16s((schar *)src1, step1, (schar *)src2, step2, (short *)dst, step, width, height, scale); + if (res == CV_HAL_ERROR_OK || res == CV_HAL_ERROR_NOT_IMPLEMENTED) + return res; + else + { + CV_Error_(cv::Error::StsInternal, ("HAL implementation mul8s16s ==> " CVAUX_STR(cv_hal_mul8s16s) + " returned %d (0x%08x)", res, res)); + } +} + static BinaryFuncC* getMulTab() { static BinaryFuncC mulTab[CV_DEPTH_MAX] = @@ -961,6 +1031,22 @@ static BinaryFuncC* getMulTab() return mulTab; } +static ExtendedTypeFunc getMulExtFunc(int src1Type, int src2Type, int dstType) +{ + if (src1Type == CV_8U && src2Type == CV_8U && dstType == CV_16U) + { + return mul8u16uWrapper; + } + else if (src1Type == CV_8U && src2Type == CV_8S && dstType == CV_16S) + { + return mul8s16sWrapper; + } + else + { + return nullptr; + } +} + static BinaryFuncC* getDivTab() { static BinaryFuncC divTab[CV_DEPTH_MAX] = @@ -986,12 +1072,14 @@ static BinaryFuncC* getRecipTab() } void multiply(InputArray src1, InputArray src2, - OutputArray dst, double scale, int dtype) + OutputArray dst, double scale, int dtype) { CV_INSTRUMENT_REGION(); + ExtendedTypeFunc mulExtFunc = getMulExtFunc(src1.depth(), src2.depth(), dtype < 0 ? dst.depth() : dtype); arithm_op(src1, src2, dst, noArray(), dtype, getMulTab(), - true, &scale, std::abs(scale - 1.0) < DBL_EPSILON ? OCL_OP_MUL : OCL_OP_MUL_SCALE); + /* muldiv */ true, &scale, std::abs(scale - 1.0) < DBL_EPSILON ? OCL_OP_MUL : OCL_OP_MUL_SCALE, + /* extendedFunc */ mulExtFunc ); } void divide(InputArray src1, InputArray src2, diff --git a/modules/core/src/hal_replacement.hpp b/modules/core/src/hal_replacement.hpp index bbdfc1e180ec..d73c0e2db8a1 100644 --- a/modules/core/src/hal_replacement.hpp +++ b/modules/core/src/hal_replacement.hpp @@ -324,6 +324,8 @@ inline int hal_ni_mul16s(const short *src1_data, size_t src1_step, const short * inline int hal_ni_mul32s(const int *src1_data, size_t src1_step, const int *src2_data, size_t src2_step, int *dst_data, size_t dst_step, int width, int height, double scale) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } inline int hal_ni_mul32f(const float *src1_data, size_t src1_step, const float *src2_data, size_t src2_step, float *dst_data, size_t dst_step, int width, int height, double scale) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } inline int hal_ni_mul64f(const double *src1_data, size_t src1_step, const double *src2_data, size_t src2_step, double *dst_data, size_t dst_step, int width, int height, double scale) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_mul8u16u(const uchar* src1_data, size_t src1_step, const uchar* src2_data, size_t src2_step, ushort* dst_data, size_t dst_step, int width, int height, double scale) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_mul8s16s(const schar* src1_data, size_t src1_step, const schar* src2_data, size_t src2_step, short* dst_data, size_t dst_step, int width, int height, double scale) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } //! @} /** @@ -378,6 +380,8 @@ inline int hal_ni_recip64f(const double *src_data, size_t src_step, double *dst_ #define cv_hal_mul32s hal_ni_mul32s #define cv_hal_mul32f hal_ni_mul32f #define cv_hal_mul64f hal_ni_mul64f +#define cv_hal_mul8u16u hal_ni_mul8u16u +#define cv_hal_mul8s16s hal_ni_mul8s16s #define cv_hal_div8u hal_ni_div8u #define cv_hal_div8s hal_ni_div8s #define cv_hal_div16u hal_ni_div16u From d95ff3ac040245567da1fde60c528e457899b29d Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Mon, 13 May 2024 01:56:35 +0200 Subject: [PATCH 064/119] HAL for sub8x32f added --- modules/core/src/arithm.cpp | 48 ++++++++++++++++++++++++++-- modules/core/src/hal_replacement.hpp | 5 +++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index 5a189867c2ea..1a2eb3d9973e 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -920,6 +920,32 @@ static BinaryFuncC* getAddTab() return addTab; } +static int sub8u32fWrapper(const uchar* src1, size_t step1, const uchar* src2, size_t step2, + uchar* dst, size_t step, int width, int height, void* ) +{ + int res = cv_hal_sub8u32f(src1, step1, src2, step2, (float *)dst, step, width, height); + if (res == CV_HAL_ERROR_OK || res == CV_HAL_ERROR_NOT_IMPLEMENTED) + return res; + else + { + CV_Error_(cv::Error::StsInternal, ("HAL implementation sub8u32f ==> " CVAUX_STR(cv_hal_sub8u32f) + " returned %d (0x%08x)", res, res)); + } +} + +static int sub8s32fWrapper(const uchar* src1, size_t step1, const uchar* src2, size_t step2, + uchar* dst, size_t step, int width, int height, void* ) +{ + int res = cv_hal_sub8s32f((schar*)src1, step1, (schar*)src2, step2, (float *)dst, step, width, height); + if (res == CV_HAL_ERROR_OK || res == CV_HAL_ERROR_NOT_IMPLEMENTED) + return res; + else + { + CV_Error_(cv::Error::StsInternal, ("HAL implementation sub8s32f ==> " CVAUX_STR(cv_hal_sub8s32f) + " returned %d (0x%08x)", res, res)); + } +} + static BinaryFuncC* getSubTab() { static BinaryFuncC subTab[CV_DEPTH_MAX] = @@ -934,6 +960,22 @@ static BinaryFuncC* getSubTab() return subTab; } +static ExtendedTypeFunc getSubExtFunc(int src1Type, int src2Type, int dstType) +{ + if (src1Type == CV_8U && src2Type == CV_8U && dstType == CV_32F) + { + return sub8u32fWrapper; + } + else if (src1Type == CV_8S && src2Type == CV_8S && dstType == CV_32F) + { + return sub8s32fWrapper; + } + else + { + return nullptr; + } +} + static BinaryFuncC* getAbsDiffTab() { static BinaryFuncC absDiffTab[CV_DEPTH_MAX] = @@ -959,11 +1001,13 @@ void cv::add( InputArray src1, InputArray src2, OutputArray dst, } void cv::subtract( InputArray _src1, InputArray _src2, OutputArray _dst, - InputArray mask, int dtype ) + InputArray mask, int dtype ) { CV_INSTRUMENT_REGION(); - arithm_op(_src1, _src2, _dst, mask, dtype, getSubTab(), false, 0, OCL_OP_SUB ); + ExtendedTypeFunc subExtFunc = getSubExtFunc(_src1.depth(), _src2.depth(), dtype < 0 ? _dst.depth() : dtype); + arithm_op(_src1, _src2, _dst, mask, dtype, getSubTab(), false, 0, OCL_OP_SUB, + /* extendedFunc */ subExtFunc); } void cv::absdiff( InputArray src1, InputArray src2, OutputArray dst ) diff --git a/modules/core/src/hal_replacement.hpp b/modules/core/src/hal_replacement.hpp index d73c0e2db8a1..f78608dbade7 100644 --- a/modules/core/src/hal_replacement.hpp +++ b/modules/core/src/hal_replacement.hpp @@ -95,6 +95,9 @@ inline int hal_ni_sub16s(const short *src1_data, size_t src1_step, const short * inline int hal_ni_sub32s(const int *src1_data, size_t src1_step, const int *src2_data, size_t src2_step, int *dst_data, size_t dst_step, int width, int height) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } inline int hal_ni_sub32f(const float *src1_data, size_t src1_step, const float *src2_data, size_t src2_step, float *dst_data, size_t dst_step, int width, int height) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } inline int hal_ni_sub64f(const double *src1_data, size_t src1_step, const double *src2_data, size_t src2_step, double *dst_data, size_t dst_step, int width, int height) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +inline int hal_ni_sub8u32f(const uchar *src1_data, size_t src1_step, const uchar *src2_data, size_t src2_step, float *dst_data, size_t dst_step, int width, int height) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_sub8s32f(const schar *src1_data, size_t src1_step, const schar *src2_data, size_t src2_step, float *dst_data, size_t dst_step, int width, int height) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } //! @} /** @@ -187,6 +190,8 @@ inline int hal_ni_not8u(const uchar *src_data, size_t src_step, uchar *dst_data, #define cv_hal_sub32s hal_ni_sub32s #define cv_hal_sub32f hal_ni_sub32f #define cv_hal_sub64f hal_ni_sub64f +#define cv_hal_sub8u32f hal_ni_sub8u32f +#define cv_hal_sub8s32f hal_ni_sub8s32f #define cv_hal_max8u hal_ni_max8u #define cv_hal_max8s hal_ni_max8s #define cv_hal_max16u hal_ni_max16u From 40faced6c18baa6fbc7c1fbd409d59d6ddecc74f Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Mon, 20 May 2024 13:44:43 +0300 Subject: [PATCH 065/119] OpenJPEG update to 2.5.2. --- 3rdparty/openjpeg/openjp2/bio.c | 26 +-- 3rdparty/openjpeg/openjp2/bio.h | 8 + 3rdparty/openjpeg/openjp2/dwt.c | 4 +- 3rdparty/openjpeg/openjp2/ht_dec.c | 56 +++++- 3rdparty/openjpeg/openjp2/j2k.c | 142 +++++++++------ 3rdparty/openjpeg/openjp2/j2k.h | 21 ++- 3rdparty/openjpeg/openjp2/jp2.c | 142 ++++++--------- .../openjpeg/openjp2/libopenjp2.pc.cmake.in | 11 +- 3rdparty/openjpeg/openjp2/openjpeg.c | 7 +- 3rdparty/openjpeg/openjp2/openjpeg.h | 10 +- .../openjpeg/openjp2/opj_config.h.cmake.in | 6 +- .../openjp2/opj_config_private.h.cmake.in | 3 +- 3rdparty/openjpeg/openjp2/opj_includes.h | 3 +- 3rdparty/openjpeg/openjp2/opj_intmath.h | 11 ++ 3rdparty/openjpeg/openjp2/pi.c | 171 +++++++++--------- 3rdparty/openjpeg/openjp2/t1.c | 12 +- .../openjpeg/openjp2/t1_ht_generate_luts.c | 10 +- 3rdparty/openjpeg/openjp2/t2.c | 27 ++- 3rdparty/openjpeg/openjp2/tcd.c | 151 ++++++++++++---- 3rdparty/openjpeg/openjp2/tcd.h | 27 +-- 3rdparty/openjpeg/openjp2/tgt.c | 4 +- 3rdparty/openjpeg/openjp2/thread.c | 2 +- 22 files changed, 496 insertions(+), 358 deletions(-) diff --git a/3rdparty/openjpeg/openjp2/bio.c b/3rdparty/openjpeg/openjp2/bio.c index 09dcd7f52492..8106df754edb 100644 --- a/3rdparty/openjpeg/openjp2/bio.c +++ b/3rdparty/openjpeg/openjp2/bio.c @@ -43,12 +43,6 @@ /** @name Local static functions */ /*@{*/ -/** -Write a bit -@param bio BIO handle -@param b Bit to write (0 or 1) -*/ -static void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b); /** Read a bit @param bio BIO handle @@ -100,16 +94,6 @@ static OPJ_BOOL opj_bio_bytein(opj_bio_t *bio) return OPJ_TRUE; } -static void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b) -{ - if (bio->ct == 0) { - opj_bio_byteout( - bio); /* MSD: why not check the return value of this function ? */ - } - bio->ct--; - bio->buf |= b << bio->ct; -} - static OPJ_UINT32 opj_bio_getbit(opj_bio_t *bio) { if (bio->ct == 0) { @@ -162,6 +146,16 @@ void opj_bio_init_dec(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len) bio->ct = 0; } +void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b) +{ + if (bio->ct == 0) { + opj_bio_byteout( + bio); /* MSD: why not check the return value of this function ? */ + } + bio->ct--; + bio->buf |= b << bio->ct; +} + void opj_bio_write(opj_bio_t *bio, OPJ_UINT32 v, OPJ_UINT32 n) { OPJ_INT32 i; diff --git a/3rdparty/openjpeg/openjp2/bio.h b/3rdparty/openjpeg/openjp2/bio.h index 448fdda2190c..d482f9ead5a7 100644 --- a/3rdparty/openjpeg/openjp2/bio.h +++ b/3rdparty/openjpeg/openjp2/bio.h @@ -106,6 +106,14 @@ Write bits @param n Number of bits to write */ void opj_bio_write(opj_bio_t *bio, OPJ_UINT32 v, OPJ_UINT32 n); + +/** +Write a bit +@param bio BIO handle +@param b Bit to write (0 or 1) +*/ +void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b); + /** Read bits @param bio BIO handle diff --git a/3rdparty/openjpeg/openjp2/dwt.c b/3rdparty/openjpeg/openjp2/dwt.c index abc500eca6bb..6b18c5dd6e9d 100644 --- a/3rdparty/openjpeg/openjp2/dwt.c +++ b/3rdparty/openjpeg/openjp2/dwt.c @@ -2083,7 +2083,9 @@ static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp, OPJ_SIZE_T h_mem_size; int num_threads; - if (numres == 1U) { + /* Not entirely sure for the return code of w == 0 which is triggered per */ + /* https://github.com/uclouvain/openjpeg/issues/1505 */ + if (numres == 1U || w == 0) { return OPJ_TRUE; } num_threads = opj_thread_pool_get_thread_count(tp); diff --git a/3rdparty/openjpeg/openjp2/ht_dec.c b/3rdparty/openjpeg/openjp2/ht_dec.c index 85e7266919a3..a554b24a6a2c 100644 --- a/3rdparty/openjpeg/openjp2/ht_dec.c +++ b/3rdparty/openjpeg/openjp2/ht_dec.c @@ -55,7 +55,13 @@ #define OPJ_COMPILER_GNUC #endif -#if defined(OPJ_COMPILER_MSVC) && defined(_M_ARM64) +#if defined(OPJ_COMPILER_MSVC) && defined(_M_ARM64) \ + && !defined(_M_ARM64EC) && !defined(_M_CEE_PURE) && !defined(__CUDACC__) \ + && !defined(__INTEL_COMPILER) && !defined(__clang__) +#define MSVC_NEON_INTRINSICS +#endif + +#ifdef MSVC_NEON_INTRINSICS #include #endif @@ -75,7 +81,7 @@ OPJ_UINT32 population_count(OPJ_UINT32 val) { #if defined(OPJ_COMPILER_MSVC) && (defined(_M_IX86) || defined(_M_AMD64)) return (OPJ_UINT32)__popcnt(val); -#elif defined(OPJ_COMPILER_MSVC) && defined(_M_ARM64) +#elif defined(OPJ_COMPILER_MSVC) && defined(MSVC_NEON_INTRINSICS) const __n64 temp = neon_cnt(__uint64ToN64_v(val)); return neon_addv8(temp).n8_i8[0]; #elif (defined OPJ_COMPILER_GNUC) @@ -301,7 +307,7 @@ void mel_decode(dec_mel_t *melp) * @param [in] scup is the length of MEL+VLC segments */ static INLINE -void mel_init(dec_mel_t *melp, OPJ_UINT8* bbuf, int lcup, int scup) +OPJ_BOOL mel_init(dec_mel_t *melp, OPJ_UINT8* bbuf, int lcup, int scup) { int num; int i; @@ -323,7 +329,9 @@ void mel_init(dec_mel_t *melp, OPJ_UINT8* bbuf, int lcup, int scup) OPJ_UINT64 d; int d_bits; - assert(melp->unstuff == OPJ_FALSE || melp->data[0] <= 0x8F); + if (melp->unstuff == OPJ_TRUE && melp->data[0] > 0x8F) { + return OPJ_FALSE; + } d = (melp->size > 0) ? *melp->data : 0xFF; // if buffer is consumed // set data to 0xFF if (melp->size == 1) { @@ -339,6 +347,7 @@ void mel_init(dec_mel_t *melp, OPJ_UINT8* bbuf, int lcup, int scup) } melp->tmp <<= (64 - melp->bits); //push all the way up so the first bit // is the MSB + return OPJ_TRUE; } //************************************************************************/ @@ -1070,7 +1079,7 @@ static OPJ_BOOL opj_t1_allocate_buffers( if (flagssize > t1->flagssize) { opj_aligned_free(t1->flags); - t1->flags = (opj_flag_t*) opj_aligned_malloc(flagssize); + t1->flags = (opj_flag_t*) opj_aligned_malloc(flagssize * sizeof(opj_flag_t)); if (!t1->flags) { /* FIXME event manager error callback */ return OPJ_FALSE; @@ -1078,7 +1087,7 @@ static OPJ_BOOL opj_t1_allocate_buffers( } t1->flagssize = flagssize; - memset(t1->flags, 0, flagssize); + memset(t1->flags, 0, flagssize * sizeof(opj_flag_t)); } t1->w = w; @@ -1087,6 +1096,26 @@ static OPJ_BOOL opj_t1_allocate_buffers( return OPJ_TRUE; } +/** +Decode 1 HT code-block +@param t1 T1 handle +@param cblk Code-block coding parameters +@param orient +@param roishift Region of interest shifting value +@param cblksty Code-block style +@param p_manager the event manager +@param p_manager_mutex mutex for the event manager +@param check_pterm whether PTERM correct termination should be checked +*/ +OPJ_BOOL opj_t1_ht_decode_cblk(opj_t1_t *t1, + opj_tcd_cblk_dec_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 roishift, + OPJ_UINT32 cblksty, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm); + //************************************************************************/ /** @brief Decodes one codeblock, processing the cleanup, siginificance * propagation, and magnitude refinement pass @@ -1194,6 +1223,9 @@ OPJ_BOOL opj_t1_ht_decode_cblk(opj_t1_t *t1, /* Concatenate all chunks */ cblkdata = t1->cblkdatabuffer; + if (cblkdata == NULL) { + return OPJ_FALSE; + } cblk_len = 0; for (i = 0; i < cblk->numchunks; i++) { memcpy(cblkdata + cblk_len, cblk->chunks[i].data, cblk->chunks[i].len); @@ -1381,7 +1413,17 @@ OPJ_BOOL opj_t1_ht_decode_cblk(opj_t1_t *t1, } // init structures - mel_init(&mel, coded_data, lcup, scup); + if (mel_init(&mel, coded_data, lcup, scup) == OPJ_FALSE) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_ERROR, "Malformed HT codeblock. " + "Incorrect MEL segment sequence.\n"); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } rev_init(&vlc, coded_data, lcup, scup); frwd_init(&magsgn, coded_data, lcup - scup, 0xFF); if (num_passes > 1) { // needs to be tested diff --git a/3rdparty/openjpeg/openjp2/j2k.c b/3rdparty/openjpeg/openjp2/j2k.c index d3b2258dfc95..c0551870b2bd 100644 --- a/3rdparty/openjpeg/openjp2/j2k.c +++ b/3rdparty/openjpeg/openjp2/j2k.c @@ -2333,10 +2333,8 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, } /* Compute the number of tiles */ - l_cp->tw = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(l_image->x1 - l_cp->tx0), - (OPJ_INT32)l_cp->tdx); - l_cp->th = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(l_image->y1 - l_cp->ty0), - (OPJ_INT32)l_cp->tdy); + l_cp->tw = opj_uint_ceildiv(l_image->x1 - l_cp->tx0, l_cp->tdx); + l_cp->th = opj_uint_ceildiv(l_image->y1 - l_cp->ty0, l_cp->tdy); /* Check that the number of tiles is valid */ if (l_cp->tw == 0 || l_cp->th == 0 || l_cp->tw > 65535 / l_cp->th) { @@ -2353,12 +2351,12 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, (p_j2k->m_specific_param.m_decoder.m_start_tile_x - l_cp->tx0) / l_cp->tdx; p_j2k->m_specific_param.m_decoder.m_start_tile_y = (p_j2k->m_specific_param.m_decoder.m_start_tile_y - l_cp->ty0) / l_cp->tdy; - p_j2k->m_specific_param.m_decoder.m_end_tile_x = (OPJ_UINT32)opj_int_ceildiv(( - OPJ_INT32)(p_j2k->m_specific_param.m_decoder.m_end_tile_x - l_cp->tx0), - (OPJ_INT32)l_cp->tdx); - p_j2k->m_specific_param.m_decoder.m_end_tile_y = (OPJ_UINT32)opj_int_ceildiv(( - OPJ_INT32)(p_j2k->m_specific_param.m_decoder.m_end_tile_y - l_cp->ty0), - (OPJ_INT32)l_cp->tdy); + p_j2k->m_specific_param.m_decoder.m_end_tile_x = opj_uint_ceildiv( + p_j2k->m_specific_param.m_decoder.m_end_tile_x - l_cp->tx0, + l_cp->tdx); + p_j2k->m_specific_param.m_decoder.m_end_tile_y = opj_uint_ceildiv( + p_j2k->m_specific_param.m_decoder.m_end_tile_y - l_cp->ty0, + l_cp->tdy); } else { p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0; p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0; @@ -3961,9 +3959,12 @@ static OPJ_BOOL opj_j2k_merge_ppm(opj_cp_t *p_cp, opj_event_mgr_t * p_manager) opj_read_bytes(l_data, &l_N_ppm, 4); l_data += 4; l_data_size -= 4; - l_ppm_data_size += - l_N_ppm; /* can't overflow, max 256 markers of max 65536 bytes, that is when PPM markers are not corrupted which is checked elsewhere */ + if (l_ppm_data_size > UINT_MAX - l_N_ppm) { + opj_event_msg(p_manager, EVT_ERROR, "Too large value for Nppm\n"); + return OPJ_FALSE; + } + l_ppm_data_size += l_N_ppm; if (l_data_size >= l_N_ppm) { l_data_size -= l_N_ppm; l_data += l_N_ppm; @@ -6726,7 +6727,7 @@ OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads) return OPJ_FALSE; } -static int opj_j2k_get_default_thread_count() +static int opj_j2k_get_default_thread_count(void) { const char* num_threads_str = getenv("OPJ_NUM_THREADS"); int num_cpus; @@ -7666,6 +7667,27 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, return OPJ_FALSE; } + if (parameters->cp_fixed_alloc) { + if (parameters->cp_matrice == NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "cp_fixed_alloc set, but cp_matrice missing\n"); + return OPJ_FALSE; + } + + if (parameters->tcp_numlayers > J2K_TCD_MATRIX_MAX_LAYER_COUNT) { + opj_event_msg(p_manager, EVT_ERROR, + "tcp_numlayers when cp_fixed_alloc set should not exceed %d\n", + J2K_TCD_MATRIX_MAX_LAYER_COUNT); + return OPJ_FALSE; + } + if (parameters->numresolution > J2K_TCD_MATRIX_MAX_RESOLUTION_COUNT) { + opj_event_msg(p_manager, EVT_ERROR, + "numresolution when cp_fixed_alloc set should not exceed %d\n", + J2K_TCD_MATRIX_MAX_RESOLUTION_COUNT); + return OPJ_FALSE; + } + } + p_j2k->m_specific_param.m_encoder.m_nb_comps = image->numcomps; /* keep a link to cp so that we can destroy it later in j2k_destroy_compress */ @@ -7885,15 +7907,17 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, cp->m_specific_param.m_enc.m_max_comp_size = (OPJ_UINT32) parameters->max_comp_size; cp->rsiz = parameters->rsiz; - cp->m_specific_param.m_enc.m_disto_alloc = (OPJ_UINT32) - parameters->cp_disto_alloc & 1u; - cp->m_specific_param.m_enc.m_fixed_alloc = (OPJ_UINT32) - parameters->cp_fixed_alloc & 1u; - cp->m_specific_param.m_enc.m_fixed_quality = (OPJ_UINT32) - parameters->cp_fixed_quality & 1u; - - /* mod fixed_quality */ - if (parameters->cp_fixed_alloc && parameters->cp_matrice) { + if (parameters->cp_fixed_alloc) { + cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy = FIXED_LAYER; + } else if (parameters->cp_fixed_quality) { + cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy = + FIXED_DISTORTION_RATIO; + } else { + cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy = + RATE_DISTORTION_RATIO; + } + + if (parameters->cp_fixed_alloc) { size_t array_size = (size_t)parameters->tcp_numlayers * (size_t)parameters->numresolution * 3 * sizeof(OPJ_INT32); cp->m_specific_param.m_enc.m_matrice = (OPJ_INT32 *) opj_malloc(array_size); @@ -7931,21 +7955,24 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, /* UniPG>> */ #ifdef USE_JPWL - cp->comment = (char*)opj_malloc(clen + strlen(version) + 11); + const size_t cp_comment_buf_size = clen + strlen(version) + 11; + cp->comment = (char*)opj_malloc(cp_comment_buf_size); if (!cp->comment) { opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to allocate comment string\n"); return OPJ_FALSE; } - sprintf(cp->comment, "%s%s with JPWL", comment, version); + snprintf(cp->comment, cp_comment_buf_size, "%s%s with JPWL", + comment, version); #else - cp->comment = (char*)opj_malloc(clen + strlen(version) + 1); + const size_t cp_comment_buf_size = clen + strlen(version) + 1; + cp->comment = (char*)opj_malloc(cp_comment_buf_size); if (!cp->comment) { opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to allocate comment string\n"); return OPJ_FALSE; } - sprintf(cp->comment, "%s%s", comment, version); + snprintf(cp->comment, cp_comment_buf_size, "%s%s", comment, version); #endif /* <tw = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(image->x1 - cp->tx0), - (OPJ_INT32)cp->tdx); - cp->th = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(image->y1 - cp->ty0), - (OPJ_INT32)cp->tdy); + cp->tw = opj_uint_ceildiv(image->x1 - cp->tx0, cp->tdx); + cp->th = opj_uint_ceildiv(image->y1 - cp->ty0, cp->tdy); /* Check that the number of tiles is valid */ if (cp->tw > 65535 / cp->th) { opj_event_msg(p_manager, EVT_ERROR, @@ -8051,22 +8076,25 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { opj_tcp_t *tcp = &cp->tcps[tileno]; + const OPJ_BOOL fixed_distoratio = + cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy == + FIXED_DISTORTION_RATIO; tcp->numlayers = (OPJ_UINT32)parameters->tcp_numlayers; for (j = 0; j < tcp->numlayers; j++) { if (OPJ_IS_CINEMA(cp->rsiz) || OPJ_IS_IMF(cp->rsiz)) { - if (cp->m_specific_param.m_enc.m_fixed_quality) { + if (fixed_distoratio) { tcp->distoratio[j] = parameters->tcp_distoratio[j]; } tcp->rates[j] = parameters->tcp_rates[j]; } else { - if (cp->m_specific_param.m_enc.m_fixed_quality) { /* add fixed_quality */ + if (fixed_distoratio) { tcp->distoratio[j] = parameters->tcp_distoratio[j]; } else { tcp->rates[j] = parameters->tcp_rates[j]; } } - if (!cp->m_specific_param.m_enc.m_fixed_quality && + if (!fixed_distoratio && tcp->rates[j] <= 1.0) { tcp->rates[j] = 0.0; /* force lossless */ } @@ -10160,10 +10188,8 @@ static OPJ_BOOL opj_j2k_update_image_dimensions(opj_image_t* p_image, return OPJ_FALSE; } - l_img_comp->x0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->x0, - (OPJ_INT32)l_img_comp->dx); - l_img_comp->y0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->y0, - (OPJ_INT32)l_img_comp->dy); + l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx); + l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy); l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx); l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy); @@ -10366,8 +10392,8 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k, p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw; p_image->x1 = l_image->x1; } else { - p_j2k->m_specific_param.m_decoder.m_end_tile_x = (OPJ_UINT32)opj_int_ceildiv( - p_end_x - (OPJ_INT32)l_cp->tx0, (OPJ_INT32)l_cp->tdx); + p_j2k->m_specific_param.m_decoder.m_end_tile_x = opj_uint_ceildiv(( + OPJ_UINT32)p_end_x - l_cp->tx0, l_cp->tdx); p_image->x1 = (OPJ_UINT32)p_end_x; } @@ -10390,8 +10416,8 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k, p_j2k->m_specific_param.m_decoder.m_end_tile_y = l_cp->th; p_image->y1 = l_image->y1; } else { - p_j2k->m_specific_param.m_decoder.m_end_tile_y = (OPJ_UINT32)opj_int_ceildiv( - p_end_y - (OPJ_INT32)l_cp->ty0, (OPJ_INT32)l_cp->tdy); + p_j2k->m_specific_param.m_decoder.m_end_tile_y = opj_uint_ceildiv(( + OPJ_UINT32)p_end_y - l_cp->ty0, l_cp->tdy); p_image->y1 = (OPJ_UINT32)p_end_y; } /* ----- */ @@ -11078,6 +11104,10 @@ static OPJ_BOOL opj_j2k_read_SQcd_SQcc(opj_j2k_t *p_j2k, l_tccp->stepsizes[l_band_no].mant = 0; } } + + if (*p_header_size < l_num_band) { + return OPJ_FALSE; + } *p_header_size = *p_header_size - l_num_band; } else { for (l_band_no = 0; l_band_no < l_num_band; l_band_no++) { @@ -11088,6 +11118,10 @@ static OPJ_BOOL opj_j2k_read_SQcd_SQcc(opj_j2k_t *p_j2k, l_tccp->stepsizes[l_band_no].mant = l_tmp & 0x7ff; } } + + if (*p_header_size < 2 * l_num_band) { + return OPJ_FALSE; + } *p_header_size = *p_header_size - 2 * l_num_band; } @@ -11315,9 +11349,12 @@ static void opj_j2k_dump_MH_info(opj_j2k_t* p_j2k, FILE* out_stream) fprintf(out_stream, "Codestream info from main header: {\n"); - fprintf(out_stream, "\t tx0=%d, ty0=%d\n", p_j2k->m_cp.tx0, p_j2k->m_cp.ty0); - fprintf(out_stream, "\t tdx=%d, tdy=%d\n", p_j2k->m_cp.tdx, p_j2k->m_cp.tdy); - fprintf(out_stream, "\t tw=%d, th=%d\n", p_j2k->m_cp.tw, p_j2k->m_cp.th); + fprintf(out_stream, "\t tx0=%" PRIu32 ", ty0=%" PRIu32 "\n", p_j2k->m_cp.tx0, + p_j2k->m_cp.ty0); + fprintf(out_stream, "\t tdx=%" PRIu32 ", tdy=%" PRIu32 "\n", p_j2k->m_cp.tdx, + p_j2k->m_cp.tdy); + fprintf(out_stream, "\t tw=%" PRIu32 ", th=%" PRIu32 "\n", p_j2k->m_cp.tw, + p_j2k->m_cp.th); opj_j2k_dump_tile_info(p_j2k->m_specific_param.m_decoder.m_default_tcp, (OPJ_INT32)p_j2k->m_private_image->numcomps, out_stream); fprintf(out_stream, "}\n"); @@ -11947,7 +11984,7 @@ static OPJ_BOOL opj_j2k_move_data_from_codec_to_output_image(opj_j2k_t * p_j2k, p_image->comps[compno].data = p_j2k->m_output_image->comps[compno].data; #if 0 char fn[256]; - sprintf(fn, "/tmp/%d.raw", compno); + snprintf(fn, sizeof fn, "/tmp/%d.raw", compno); FILE *debug = fopen(fn, "wb"); fwrite(p_image->comps[compno].data, sizeof(OPJ_INT32), p_image->comps[compno].w * p_image->comps[compno].h, debug); @@ -12073,10 +12110,8 @@ OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k, l_img_comp->factor = p_j2k->m_private_image->comps[compno].factor; - l_img_comp->x0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->x0, - (OPJ_INT32)l_img_comp->dx); - l_img_comp->y0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->y0, - (OPJ_INT32)l_img_comp->dy); + l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx); + l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy); l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx); l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy); @@ -12456,12 +12491,9 @@ static void opj_get_tile_dimensions(opj_image_t * l_image, *l_width = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0); *l_height = (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0); - *l_offset_x = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->x0, - (OPJ_INT32)l_img_comp->dx); - *l_offset_y = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->y0, - (OPJ_INT32)l_img_comp->dy); - *l_image_width = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->x1 - - (OPJ_INT32)l_image->x0, (OPJ_INT32)l_img_comp->dx); + *l_offset_x = opj_uint_ceildiv(l_image->x0, l_img_comp->dx); + *l_offset_y = opj_uint_ceildiv(l_image->y0, l_img_comp->dy); + *l_image_width = opj_uint_ceildiv(l_image->x1 - l_image->x0, l_img_comp->dx); *l_stride = *l_image_width - *l_width; *l_tile_offset = ((OPJ_UINT32)l_tilec->x0 - *l_offset_x) + (( OPJ_UINT32)l_tilec->y0 - *l_offset_y) * *l_image_width; diff --git a/3rdparty/openjpeg/openjp2/j2k.h b/3rdparty/openjpeg/openjp2/j2k.h index 04fba645affe..e0b9688a353f 100644 --- a/3rdparty/openjpeg/openjp2/j2k.h +++ b/3rdparty/openjpeg/openjp2/j2k.h @@ -113,6 +113,9 @@ The functions in J2K.C have for goal to read/write the several parts of the code #define J2K_MAX_POCS 32 /**< Maximum number of POCs */ +#define J2K_TCD_MATRIX_MAX_LAYER_COUNT 10 +#define J2K_TCD_MATRIX_MAX_RESOLUTION_COUNT 10 + /* ----------------------------------------------------------------------- */ /** @@ -272,7 +275,7 @@ typedef struct opj_tcp { OPJ_UINT32 ppt_data_size; /** size of ppt_data*/ OPJ_UINT32 ppt_len; - /** add fixed_quality */ + /** PSNR values */ OPJ_FLOAT32 distoratio[100]; /** tile-component coding parameters */ opj_tccp_t *tccps; @@ -314,6 +317,14 @@ typedef struct opj_tcp { } opj_tcp_t; +/** +Rate allocation strategy +*/ +typedef enum { + RATE_DISTORTION_RATIO = 0, /** allocation by rate/distortion */ + FIXED_DISTORTION_RATIO = 1, /** allocation by fixed distortion ratio (PSNR) (fixed quality) */ + FIXED_LAYER = 2, /** allocation by fixed layer (number of passes per layer / resolution / subband) */ +} J2K_QUALITY_LAYER_ALLOCATION_STRATEGY; typedef struct opj_encoding_param { @@ -325,12 +336,8 @@ typedef struct opj_encoding_param { OPJ_INT32 *m_matrice; /** Flag determining tile part generation*/ OPJ_BYTE m_tp_flag; - /** allocation by rate/distortion */ - OPJ_BITFIELD m_disto_alloc : 1; - /** allocation by fixed layer */ - OPJ_BITFIELD m_fixed_alloc : 1; - /** add fixed_quality */ - OPJ_BITFIELD m_fixed_quality : 1; + /** Quality layer allocation strategy */ + J2K_QUALITY_LAYER_ALLOCATION_STRATEGY m_quality_layer_alloc_strategy; /** Enabling Tile part generation*/ OPJ_BITFIELD m_tp_on : 1; } diff --git a/3rdparty/openjpeg/openjp2/jp2.c b/3rdparty/openjpeg/openjp2/jp2.c index 17572195e391..6015190e1f5b 100644 --- a/3rdparty/openjpeg/openjp2/jp2.c +++ b/3rdparty/openjpeg/openjp2/jp2.c @@ -1108,7 +1108,7 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image, pcol = cmap[i].pcol; src = old_comps[cmp].data; assert(src); /* verified above */ - max = new_comps[pcol].w * new_comps[pcol].h; + max = new_comps[i].w * new_comps[i].h; /* Direct use: */ if (cmap[i].mtyp == 0) { @@ -1594,22 +1594,10 @@ static OPJ_BOOL opj_jp2_read_colr(opj_jp2_t *jp2, return OPJ_TRUE; } -OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2, - opj_stream_private_t *p_stream, - opj_image_t* p_image, - opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_jp2_apply_color_postprocessing(opj_jp2_t *jp2, + opj_image_t* p_image, + opj_event_mgr_t * p_manager) { - if (!p_image) { - return OPJ_FALSE; - } - - /* J2K decoding */ - if (! opj_j2k_decode(jp2->j2k, p_stream, p_image, p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, - "Failed to decode the codestream in the JP2 file\n"); - return OPJ_FALSE; - } - if (jp2->j2k->m_specific_param.m_decoder.m_numcomps_to_decode) { /* Bypass all JP2 component transforms */ return OPJ_TRUE; @@ -1620,21 +1608,6 @@ OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2, return OPJ_FALSE; } - /* Set Image Color Space */ - if (jp2->enumcs == 16) { - p_image->color_space = OPJ_CLRSPC_SRGB; - } else if (jp2->enumcs == 17) { - p_image->color_space = OPJ_CLRSPC_GRAY; - } else if (jp2->enumcs == 18) { - p_image->color_space = OPJ_CLRSPC_SYCC; - } else if (jp2->enumcs == 24) { - p_image->color_space = OPJ_CLRSPC_EYCC; - } else if (jp2->enumcs == 12) { - p_image->color_space = OPJ_CLRSPC_CMYK; - } else { - p_image->color_space = OPJ_CLRSPC_UNKNOWN; - } - if (jp2->color.jp2_pclr) { /* Part 1, I.5.3.4: Either both or none : */ if (!jp2->color.jp2_pclr->cmap) { @@ -1650,17 +1623,30 @@ OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2, if (jp2->color.jp2_cdef) { opj_jp2_apply_cdef(p_image, &(jp2->color), p_manager); } - - if (jp2->color.icc_profile_buf) { - p_image->icc_profile_buf = jp2->color.icc_profile_buf; - p_image->icc_profile_len = jp2->color.icc_profile_len; - jp2->color.icc_profile_buf = NULL; - } } return OPJ_TRUE; } +OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2, + opj_stream_private_t *p_stream, + opj_image_t* p_image, + opj_event_mgr_t * p_manager) +{ + if (!p_image) { + return OPJ_FALSE; + } + + /* J2K decoding */ + if (! opj_j2k_decode(jp2->j2k, p_stream, p_image, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Failed to decode the codestream in the JP2 file\n"); + return OPJ_FALSE; + } + + return opj_jp2_apply_color_postprocessing(jp2, p_image, p_manager); +} + static OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2, opj_stream_private_t *stream, opj_event_mgr_t * p_manager @@ -2843,6 +2829,8 @@ OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream, opj_event_mgr_t * p_manager ) { + int ret; + /* preconditions */ assert(jp2 != 00); assert(p_stream != 00); @@ -2876,10 +2864,34 @@ OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream, return OPJ_FALSE; } - return opj_j2k_read_header(p_stream, - jp2->j2k, - p_image, - p_manager); + ret = opj_j2k_read_header(p_stream, + jp2->j2k, + p_image, + p_manager); + + if (p_image && *p_image) { + /* Set Image Color Space */ + if (jp2->enumcs == 16) { + (*p_image)->color_space = OPJ_CLRSPC_SRGB; + } else if (jp2->enumcs == 17) { + (*p_image)->color_space = OPJ_CLRSPC_GRAY; + } else if (jp2->enumcs == 18) { + (*p_image)->color_space = OPJ_CLRSPC_SYCC; + } else if (jp2->enumcs == 24) { + (*p_image)->color_space = OPJ_CLRSPC_EYCC; + } else if (jp2->enumcs == 12) { + (*p_image)->color_space = OPJ_CLRSPC_CMYK; + } else { + (*p_image)->color_space = OPJ_CLRSPC_UNKNOWN; + } + + if (jp2->color.icc_profile_buf) { + (*p_image)->icc_profile_buf = jp2->color.icc_profile_buf; + (*p_image)->icc_profile_len = jp2->color.icc_profile_len; + jp2->color.icc_profile_buf = NULL; + } + } + return ret; } static OPJ_BOOL opj_jp2_setup_encoding_validation(opj_jp2_t *jp2, @@ -3123,53 +3135,7 @@ OPJ_BOOL opj_jp2_get_tile(opj_jp2_t *p_jp2, return OPJ_FALSE; } - if (p_jp2->j2k->m_specific_param.m_decoder.m_numcomps_to_decode) { - /* Bypass all JP2 component transforms */ - return OPJ_TRUE; - } - - if (!opj_jp2_check_color(p_image, &(p_jp2->color), p_manager)) { - return OPJ_FALSE; - } - - /* Set Image Color Space */ - if (p_jp2->enumcs == 16) { - p_image->color_space = OPJ_CLRSPC_SRGB; - } else if (p_jp2->enumcs == 17) { - p_image->color_space = OPJ_CLRSPC_GRAY; - } else if (p_jp2->enumcs == 18) { - p_image->color_space = OPJ_CLRSPC_SYCC; - } else if (p_jp2->enumcs == 24) { - p_image->color_space = OPJ_CLRSPC_EYCC; - } else if (p_jp2->enumcs == 12) { - p_image->color_space = OPJ_CLRSPC_CMYK; - } else { - p_image->color_space = OPJ_CLRSPC_UNKNOWN; - } - - if (p_jp2->color.jp2_pclr) { - /* Part 1, I.5.3.4: Either both or none : */ - if (!p_jp2->color.jp2_pclr->cmap) { - opj_jp2_free_pclr(&(p_jp2->color)); - } else { - if (!opj_jp2_apply_pclr(p_image, &(p_jp2->color), p_manager)) { - return OPJ_FALSE; - } - } - } - - /* Apply the color space if needed */ - if (p_jp2->color.jp2_cdef) { - opj_jp2_apply_cdef(p_image, &(p_jp2->color), p_manager); - } - - if (p_jp2->color.icc_profile_buf) { - p_image->icc_profile_buf = p_jp2->color.icc_profile_buf; - p_image->icc_profile_len = p_jp2->color.icc_profile_len; - p_jp2->color.icc_profile_buf = NULL; - } - - return OPJ_TRUE; + return opj_jp2_apply_color_postprocessing(p_jp2, p_image, p_manager); } /* ----------------------------------------------------------------------- */ diff --git a/3rdparty/openjpeg/openjp2/libopenjp2.pc.cmake.in b/3rdparty/openjpeg/openjp2/libopenjp2.pc.cmake.in index 62159b00a4b1..2ade312b2948 100644 --- a/3rdparty/openjpeg/openjp2/libopenjp2.pc.cmake.in +++ b/3rdparty/openjpeg/openjp2/libopenjp2.pc.cmake.in @@ -1,9 +1,9 @@ prefix=@CMAKE_INSTALL_PREFIX@ -bindir=${prefix}/@OPENJPEG_INSTALL_BIN_DIR@ -mandir=${prefix}/@OPENJPEG_INSTALL_MAN_DIR@ -docdir=${prefix}/@OPENJPEG_INSTALL_DOC_DIR@ -libdir=${prefix}/@OPENJPEG_INSTALL_LIB_DIR@ -includedir=${prefix}/@OPENJPEG_INSTALL_INCLUDE_DIR@ +bindir=@bindir@ +mandir=@mandir@ +docdir=@docdir@ +libdir=@libdir@ +includedir=@includedir@ Name: openjp2 Description: JPEG2000 library (Part 1 and 2) @@ -12,3 +12,4 @@ Version: @OPENJPEG_VERSION@ Libs: -L${libdir} -lopenjp2 Libs.private: -lm Cflags: -I${includedir} +Cflags.private: -DOPJ_STATIC diff --git a/3rdparty/openjpeg/openjp2/openjpeg.c b/3rdparty/openjpeg/openjp2/openjpeg.c index 29d3ee528ccc..382d8f4f0f12 100644 --- a/3rdparty/openjpeg/openjp2/openjpeg.c +++ b/3rdparty/openjpeg/openjp2/openjpeg.c @@ -144,6 +144,11 @@ static void opj_close_from_file(void* p_user_data) /* ---------------------------------------------------------------------- */ #ifdef _WIN32 #ifndef OPJ_STATIC + +/* declaration to avoid warning: no previous prototype for 'DllMain' */ +BOOL APIENTRY +DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved); + BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { @@ -433,7 +438,7 @@ OPJ_BOOL OPJ_CALLCONV opj_setup_decoder(opj_codec_t *p_codec, return OPJ_FALSE; } -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_decoder_set_strict_mode(opj_codec_t *p_codec, +OPJ_BOOL OPJ_CALLCONV opj_decoder_set_strict_mode(opj_codec_t *p_codec, OPJ_BOOL strict) { if (p_codec) { diff --git a/3rdparty/openjpeg/openjp2/openjpeg.h b/3rdparty/openjpeg/openjp2/openjpeg.h index ebce53db0d82..67d168bb5785 100644 --- a/3rdparty/openjpeg/openjp2/openjpeg.h +++ b/3rdparty/openjpeg/openjp2/openjpeg.h @@ -122,7 +122,7 @@ typedef float OPJ_FLOAT32; typedef double OPJ_FLOAT64; typedef unsigned char OPJ_BYTE; -#include "opj_stdint.h" +#include typedef int8_t OPJ_INT8; typedef uint8_t OPJ_UINT8; @@ -138,6 +138,8 @@ typedef int64_t OPJ_OFF_T; /* 64-bit file offset type */ #include typedef size_t OPJ_SIZE_T; +#include "opj_config.h" + /* Avoid compile-time warning because parameter is not used */ #define OPJ_ARG_NOT_USED(x) (void)(x) @@ -405,7 +407,7 @@ typedef struct opj_cparameters { int cp_disto_alloc; /** allocation by fixed layer */ int cp_fixed_alloc; - /** add fixed_quality */ + /** allocation by fixed quality (PSNR) */ int cp_fixed_quality; /** fixed layer */ int *cp_matrice; @@ -829,9 +831,9 @@ typedef struct opj_tile_info { int pdy[33]; /** information concerning packets inside tile */ opj_packet_info_t *packet; - /** add fixed_quality */ + /** number of pixels of the tile */ int numpix; - /** add fixed_quality */ + /** distortion of the tile */ double distotile; /** number of markers */ int marknum; diff --git a/3rdparty/openjpeg/openjp2/opj_config.h.cmake.in b/3rdparty/openjpeg/openjp2/opj_config.h.cmake.in index 5f762ca3daa9..64884b65248d 100644 --- a/3rdparty/openjpeg/openjp2/opj_config.h.cmake.in +++ b/3rdparty/openjpeg/openjp2/opj_config.h.cmake.in @@ -1,5 +1,7 @@ +#ifndef OPJ_CONFIG_H_INCLUDED +#define OPJ_CONFIG_H_INCLUDED + /* create opj_config.h for CMake */ -#cmakedefine OPJ_HAVE_STDINT_H @OPJ_HAVE_STDINT_H@ /*--------------------------------------------------------------------------*/ /* OpenJPEG Versioning */ @@ -8,3 +10,5 @@ #define OPJ_VERSION_MAJOR @OPENJPEG_VERSION_MAJOR@ #define OPJ_VERSION_MINOR @OPENJPEG_VERSION_MINOR@ #define OPJ_VERSION_BUILD @OPENJPEG_VERSION_BUILD@ + +#endif diff --git a/3rdparty/openjpeg/openjp2/opj_config_private.h.cmake.in b/3rdparty/openjpeg/openjp2/opj_config_private.h.cmake.in index c41f9066242d..c559282c578b 100644 --- a/3rdparty/openjpeg/openjp2/opj_config_private.h.cmake.in +++ b/3rdparty/openjpeg/openjp2/opj_config_private.h.cmake.in @@ -1,5 +1,4 @@ /* create opj_config_private.h for CMake */ -#cmakedefine OPJ_HAVE_INTTYPES_H @OPJ_HAVE_INTTYPES_H@ #define OPJ_PACKAGE_VERSION "@PACKAGE_VERSION@" @@ -11,6 +10,8 @@ /*#cmakedefine HAVE_SYS_STAT_H @HAVE_SYS_STAT_H@*/ /*#cmakedefine HAVE_SYS_TYPES_H @HAVE_SYS_TYPES_H@ */ /*#cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@*/ +/*#cmakedefine HAVE_INTTYPES_H @HAVE_INTTYPES_H@ */ +/*#cmakedefine HAVE_STDINT_H @HAVE_STDINT_H@ */ #cmakedefine _LARGEFILE_SOURCE #cmakedefine _LARGE_FILES diff --git a/3rdparty/openjpeg/openjp2/opj_includes.h b/3rdparty/openjpeg/openjp2/opj_includes.h index 0a8628c96b30..13613ce521c1 100644 --- a/3rdparty/openjpeg/openjp2/opj_includes.h +++ b/3rdparty/openjpeg/openjp2/opj_includes.h @@ -55,6 +55,8 @@ #include #include #include +#include +#include /* Use fseeko() and ftello() if they are available since they use @@ -218,7 +220,6 @@ typedef unsigned int OPJ_BITFIELD; #define OPJ_UNUSED(x) (void)x -#include "opj_inttypes.h" #include "opj_clock.h" #include "opj_malloc.h" #include "event.h" diff --git a/3rdparty/openjpeg/openjp2/opj_intmath.h b/3rdparty/openjpeg/openjp2/opj_intmath.h index 1b0c9d033283..cce7a3cafa72 100644 --- a/3rdparty/openjpeg/openjp2/opj_intmath.h +++ b/3rdparty/openjpeg/openjp2/opj_intmath.h @@ -173,6 +173,17 @@ static INLINE OPJ_UINT32 opj_uint_ceildiv(OPJ_UINT32 a, OPJ_UINT32 b) return (OPJ_UINT32)(((OPJ_UINT64)a + b - 1) / b); } +/** +Divide an integer and round upwards +@return Returns a divided by b +*/ +static INLINE OPJ_UINT32 opj_uint64_ceildiv_res_uint32(OPJ_UINT64 a, + OPJ_UINT64 b) +{ + assert(b); + return (OPJ_UINT32)((a + b - 1) / b); +} + /** Divide an integer by a power of 2 and round upwards @return Returns a divided by 2^b diff --git a/3rdparty/openjpeg/openjp2/pi.c b/3rdparty/openjpeg/openjp2/pi.c index 38f1ba5a70f3..15ac331425d9 100644 --- a/3rdparty/openjpeg/openjp2/pi.c +++ b/3rdparty/openjpeg/openjp2/pi.c @@ -411,41 +411,37 @@ static OPJ_BOOL opj_pi_next_rpcl(opj_pi_iterator_t * pi) } res = &comp->resolutions[pi->resno]; levelno = comp->numresolutions - 1 - pi->resno; - /* Avoids division by zero */ - /* Relates to id_000004,sig_06,src_000679,op_arith8,pos_49,val_-17 */ - /* of https://github.com/uclouvain/openjpeg/issues/938 */ - if (levelno >= 32 || - ((comp->dx << levelno) >> levelno) != comp->dx || - ((comp->dy << levelno) >> levelno) != comp->dy) { - continue; - } - if ((comp->dx << levelno) > INT_MAX || - (comp->dy << levelno) > INT_MAX) { + + if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << levelno) >> levelno) != comp->dx || + (OPJ_UINT32)(((OPJ_UINT64)comp->dy << levelno) >> levelno) != comp->dy) { continue; } - trx0 = opj_uint_ceildiv(pi->tx0, (comp->dx << levelno)); - try0 = opj_uint_ceildiv(pi->ty0, (comp->dy << levelno)); - trx1 = opj_uint_ceildiv(pi->tx1, (comp->dx << levelno)); - try1 = opj_uint_ceildiv(pi->ty1, (comp->dy << levelno)); + + trx0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx0, + ((OPJ_UINT64)comp->dx << levelno)); + try0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty0, + ((OPJ_UINT64)comp->dy << levelno)); + trx1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx1, + ((OPJ_UINT64)comp->dx << levelno)); + try1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty1, + ((OPJ_UINT64)comp->dy << levelno)); rpx = res->pdx + levelno; rpy = res->pdy + levelno; - /* To avoid divisions by zero / undefined behaviour on shift */ - /* in below tests */ - /* Fixes reading id:000026,sig:08,src:002419,op:int32,pos:60,val:+32 */ - /* of https://github.com/uclouvain/openjpeg/issues/938 */ - if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx || - rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) { + if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << rpx) >> rpx) != comp->dx || + (OPJ_UINT32)(((OPJ_UINT64)comp->dy << rpy) >> rpy) != comp->dy) { continue; } /* See ISO-15441. B.12.1.3 Resolution level-position-component-layer progression */ - if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && - ((try0 << levelno) % (1U << rpy))))) { + if (!(((OPJ_UINT64)pi->y % ((OPJ_UINT64)comp->dy << rpy) == 0) || + ((pi->y == pi->ty0) && + (((OPJ_UINT64)try0 << levelno) % ((OPJ_UINT64)1U << rpy))))) { continue; } - if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && - ((trx0 << levelno) % (1U << rpx))))) { + if (!(((OPJ_UINT64)pi->x % ((OPJ_UINT64)comp->dx << rpx) == 0) || + ((pi->x == pi->tx0) && + (((OPJ_UINT64)trx0 << levelno) % ((OPJ_UINT64)1U << rpx))))) { continue; } @@ -457,11 +453,11 @@ static OPJ_BOOL opj_pi_next_rpcl(opj_pi_iterator_t * pi) continue; } - prci = opj_uint_floordivpow2(opj_uint_ceildiv(pi->x, - (comp->dx << levelno)), res->pdx) + prci = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->x, + ((OPJ_UINT64)comp->dx << levelno)), res->pdx) - opj_uint_floordivpow2(trx0, res->pdx); - prcj = opj_uint_floordivpow2(opj_uint_ceildiv(pi->y, - (comp->dy << levelno)), res->pdy) + prcj = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->y, + ((OPJ_UINT64)comp->dy << levelno)), res->pdy) - opj_uint_floordivpow2(try0, res->pdy); pi->precno = prci + prcj * res->pw; for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { @@ -549,41 +545,37 @@ static OPJ_BOOL opj_pi_next_pcrl(opj_pi_iterator_t * pi) OPJ_UINT32 prci, prcj; res = &comp->resolutions[pi->resno]; levelno = comp->numresolutions - 1 - pi->resno; - /* Avoids division by zero */ - /* Relates to id_000004,sig_06,src_000679,op_arith8,pos_49,val_-17 */ - /* of https://github.com/uclouvain/openjpeg/issues/938 */ - if (levelno >= 32 || - ((comp->dx << levelno) >> levelno) != comp->dx || - ((comp->dy << levelno) >> levelno) != comp->dy) { - continue; - } - if ((comp->dx << levelno) > INT_MAX || - (comp->dy << levelno) > INT_MAX) { + + if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << levelno) >> levelno) != comp->dx || + (OPJ_UINT32)(((OPJ_UINT64)comp->dy << levelno) >> levelno) != comp->dy) { continue; } - trx0 = opj_uint_ceildiv(pi->tx0, (comp->dx << levelno)); - try0 = opj_uint_ceildiv(pi->ty0, (comp->dy << levelno)); - trx1 = opj_uint_ceildiv(pi->tx1, (comp->dx << levelno)); - try1 = opj_uint_ceildiv(pi->ty1, (comp->dy << levelno)); + + trx0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx0, + ((OPJ_UINT64)comp->dx << levelno)); + try0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty0, + ((OPJ_UINT64)comp->dy << levelno)); + trx1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx1, + ((OPJ_UINT64)comp->dx << levelno)); + try1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty1, + ((OPJ_UINT64)comp->dy << levelno)); rpx = res->pdx + levelno; rpy = res->pdy + levelno; - /* To avoid divisions by zero / undefined behaviour on shift */ - /* in below tests */ - /* Relates to id:000019,sig:08,src:001098,op:flip1,pos:49 */ - /* of https://github.com/uclouvain/openjpeg/issues/938 */ - if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx || - rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) { + if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << rpx) >> rpx) != comp->dx || + (OPJ_UINT32)(((OPJ_UINT64)comp->dy << rpy) >> rpy) != comp->dy) { continue; } /* See ISO-15441. B.12.1.4 Position-component-resolution level-layer progression */ - if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && - ((try0 << levelno) % (1U << rpy))))) { + if (!(((OPJ_UINT64)pi->y % ((OPJ_UINT64)comp->dy << rpy) == 0) || + ((pi->y == pi->ty0) && + (((OPJ_UINT64)try0 << levelno) % ((OPJ_UINT64)1U << rpy))))) { continue; } - if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && - ((trx0 << levelno) % (1U << rpx))))) { + if (!(((OPJ_UINT64)pi->x % ((OPJ_UINT64)comp->dx << rpx) == 0) || + ((pi->x == pi->tx0) && + (((OPJ_UINT64)trx0 << levelno) % ((OPJ_UINT64)1U << rpx))))) { continue; } @@ -595,11 +587,11 @@ static OPJ_BOOL opj_pi_next_pcrl(opj_pi_iterator_t * pi) continue; } - prci = opj_uint_floordivpow2(opj_uint_ceildiv(pi->x, - (comp->dx << levelno)), res->pdx) + prci = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->x, + ((OPJ_UINT64)comp->dx << levelno)), res->pdx) - opj_uint_floordivpow2(trx0, res->pdx); - prcj = opj_uint_floordivpow2(opj_uint_ceildiv(pi->y, - (comp->dy << levelno)), res->pdy) + prcj = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->y, + ((OPJ_UINT64)comp->dy << levelno)), res->pdy) - opj_uint_floordivpow2(try0, res->pdy); pi->precno = prci + prcj * res->pw; for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { @@ -685,40 +677,37 @@ static OPJ_BOOL opj_pi_next_cprl(opj_pi_iterator_t * pi) OPJ_UINT32 prci, prcj; res = &comp->resolutions[pi->resno]; levelno = comp->numresolutions - 1 - pi->resno; - /* Avoids division by zero on id_000004,sig_06,src_000679,op_arith8,pos_49,val_-17 */ - /* of https://github.com/uclouvain/openjpeg/issues/938 */ - if (levelno >= 32 || - ((comp->dx << levelno) >> levelno) != comp->dx || - ((comp->dy << levelno) >> levelno) != comp->dy) { - continue; - } - if ((comp->dx << levelno) > INT_MAX || - (comp->dy << levelno) > INT_MAX) { + + if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << levelno) >> levelno) != comp->dx || + (OPJ_UINT32)(((OPJ_UINT64)comp->dy << levelno) >> levelno) != comp->dy) { continue; } - trx0 = opj_uint_ceildiv(pi->tx0, (comp->dx << levelno)); - try0 = opj_uint_ceildiv(pi->ty0, (comp->dy << levelno)); - trx1 = opj_uint_ceildiv(pi->tx1, (comp->dx << levelno)); - try1 = opj_uint_ceildiv(pi->ty1, (comp->dy << levelno)); + + trx0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx0, + ((OPJ_UINT64)comp->dx << levelno)); + try0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty0, + ((OPJ_UINT64)comp->dy << levelno)); + trx1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx1, + ((OPJ_UINT64)comp->dx << levelno)); + try1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty1, + ((OPJ_UINT64)comp->dy << levelno)); rpx = res->pdx + levelno; rpy = res->pdy + levelno; - /* To avoid divisions by zero / undefined behaviour on shift */ - /* in below tests */ - /* Fixes reading id:000019,sig:08,src:001098,op:flip1,pos:49 */ - /* of https://github.com/uclouvain/openjpeg/issues/938 */ - if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx || - rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) { + if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << rpx) >> rpx) != comp->dx || + (OPJ_UINT32)(((OPJ_UINT64)comp->dy << rpy) >> rpy) != comp->dy) { continue; } /* See ISO-15441. B.12.1.5 Component-position-resolution level-layer progression */ - if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && - ((try0 << levelno) % (1U << rpy))))) { + if (!(((OPJ_UINT64)pi->y % ((OPJ_UINT64)comp->dy << rpy) == 0) || + ((pi->y == pi->ty0) && + (((OPJ_UINT64)try0 << levelno) % ((OPJ_UINT64)1U << rpy))))) { continue; } - if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && - ((trx0 << levelno) % (1U << rpx))))) { + if (!(((OPJ_UINT64)pi->x % ((OPJ_UINT64)comp->dx << rpx) == 0) || + ((pi->x == pi->tx0) && + (((OPJ_UINT64)trx0 << levelno) % ((OPJ_UINT64)1U << rpx))))) { continue; } @@ -730,11 +719,11 @@ static OPJ_BOOL opj_pi_next_cprl(opj_pi_iterator_t * pi) continue; } - prci = opj_uint_floordivpow2(opj_uint_ceildiv(pi->x, - (comp->dx << levelno)), res->pdx) + prci = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->x, + ((OPJ_UINT64)comp->dx << levelno)), res->pdx) - opj_uint_floordivpow2(trx0, res->pdx); - prcj = opj_uint_floordivpow2(opj_uint_ceildiv(pi->y, - (comp->dy << levelno)), res->pdy) + prcj = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->y, + ((OPJ_UINT64)comp->dy << levelno)), res->pdy) - opj_uint_floordivpow2(try0, res->pdy); pi->precno = (OPJ_UINT32)(prci + prcj * res->pw); for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { @@ -837,18 +826,24 @@ static void opj_get_encoding_parameters(const opj_image_t *p_image, /* use custom size for precincts */ for (resno = 0; resno < l_tccp->numresolutions; ++resno) { - OPJ_UINT32 l_dx, l_dy; + OPJ_UINT64 l_dx, l_dy; /* precinct width and height */ l_pdx = l_tccp->prcw[resno]; l_pdy = l_tccp->prch[resno]; - l_dx = l_img_comp->dx * (1u << (l_pdx + l_tccp->numresolutions - 1 - resno)); - l_dy = l_img_comp->dy * (1u << (l_pdy + l_tccp->numresolutions - 1 - resno)); + l_dx = l_img_comp->dx * ((OPJ_UINT64)1u << (l_pdx + l_tccp->numresolutions - 1 - + resno)); + l_dy = l_img_comp->dy * ((OPJ_UINT64)1u << (l_pdy + l_tccp->numresolutions - 1 - + resno)); /* take the minimum size for dx for each comp and resolution */ - *p_dx_min = opj_uint_min(*p_dx_min, l_dx); - *p_dy_min = opj_uint_min(*p_dy_min, l_dy); + if (l_dx <= UINT_MAX) { + *p_dx_min = opj_uint_min(*p_dx_min, (OPJ_UINT32)l_dx); + } + if (l_dy <= UINT_MAX) { + *p_dy_min = opj_uint_min(*p_dy_min, (OPJ_UINT32)l_dy); + } /* various calculations of extents */ l_level_no = l_tccp->numresolutions - 1 - resno; diff --git a/3rdparty/openjpeg/openjp2/t1.c b/3rdparty/openjpeg/openjp2/t1.c index f5fd233917d2..52e466eb974a 100644 --- a/3rdparty/openjpeg/openjp2/t1.c +++ b/3rdparty/openjpeg/openjp2/t1.c @@ -1410,7 +1410,6 @@ static void opj_t1_dec_clnpass( } -/** mod fixed_quality */ static OPJ_FLOAT64 opj_t1_getwmsedec( OPJ_INT32 nmsedec, OPJ_UINT32 compno, @@ -2313,7 +2312,7 @@ OPJ_BOOL opj_t1_encode_cblks(opj_tcd_t* tcd, OPJ_UINT32 compno, resno, bandno, precno, cblkno; opj_mutex_t* mutex = opj_mutex_create(); - tile->distotile = 0; /* fixed_quality */ + tile->distotile = 0; for (compno = 0; compno < tile->numcomps; ++compno) { opj_tcd_tilecomp_t* tilec = &tile->comps[compno]; @@ -2401,7 +2400,6 @@ static int opj_t1_enc_is_term_pass(opj_tcd_cblk_enc_t* cblk, } -/** mod fixed_quality */ static OPJ_FLOAT64 opj_t1_encode_cblk(opj_t1_t *t1, opj_tcd_cblk_enc_t* cblk, OPJ_UINT32 orient, @@ -2443,6 +2441,13 @@ static OPJ_FLOAT64 opj_t1_encode_cblk(opj_t1_t *t1, OPJ_INT32 tmp = *datap; if (tmp < 0) { OPJ_UINT32 tmp_unsigned; + if (tmp == INT_MIN) { + /* To avoid undefined behaviour when negating INT_MIN */ + /* but if we go here, it means we have supplied an input */ + /* with more bit depth than we we can really support. */ + /* Cf https://github.com/uclouvain/openjpeg/issues/1432 */ + tmp = INT_MIN + 1; + } max = opj_int_max(max, -tmp); tmp_unsigned = opj_to_smr(tmp); memcpy(datap, &tmp_unsigned, sizeof(OPJ_INT32)); @@ -2498,7 +2503,6 @@ static OPJ_FLOAT64 opj_t1_encode_cblk(opj_t1_t *t1, break; } - /* fixed_quality */ tempwmsedec = opj_t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, stepsize, numcomps, mct_norms, mct_numcomps) ; cumwmsedec += tempwmsedec; diff --git a/3rdparty/openjpeg/openjp2/t1_ht_generate_luts.c b/3rdparty/openjpeg/openjp2/t1_ht_generate_luts.c index 6876e3fd7f0a..22382a5a4af5 100644 --- a/3rdparty/openjpeg/openjp2/t1_ht_generate_luts.c +++ b/3rdparty/openjpeg/openjp2/t1_ht_generate_luts.c @@ -38,12 +38,7 @@ #include #include #include - -typedef int OPJ_BOOL; -#define OPJ_TRUE 1 -#define OPJ_FALSE 0 - -#include "opj_stdint.h" +#include typedef int8_t OPJ_INT8; typedef uint8_t OPJ_UINT8; @@ -53,6 +48,9 @@ typedef int32_t OPJ_INT32; typedef uint32_t OPJ_UINT32; typedef int64_t OPJ_INT64; typedef uint64_t OPJ_UINT64; +typedef int OPJ_BOOL; +#define OPJ_TRUE 1 +#define OPJ_FALSE 0 //************************************************************************/ /** @brief HT decoding tables, as given in the standard diff --git a/3rdparty/openjpeg/openjp2/t2.c b/3rdparty/openjpeg/openjp2/t2.c index ebda005267e6..781a6a59a165 100644 --- a/3rdparty/openjpeg/openjp2/t2.c +++ b/3rdparty/openjpeg/openjp2/t2.c @@ -167,9 +167,9 @@ static OPJ_BOOL opj_t2_init_seg(opj_tcd_cblk_dec_t* cblk, static void opj_t2_putcommacode(opj_bio_t *bio, OPJ_INT32 n) { while (--n >= 0) { - opj_bio_write(bio, 1, 1); + opj_bio_putbit(bio, 1); } - opj_bio_write(bio, 0, 1); + opj_bio_putbit(bio, 0); } static OPJ_UINT32 opj_t2_getcommacode(opj_bio_t *bio) @@ -184,7 +184,7 @@ static OPJ_UINT32 opj_t2_getcommacode(opj_bio_t *bio) static void opj_t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n) { if (n == 1) { - opj_bio_write(bio, 0, 1); + opj_bio_putbit(bio, 0); } else if (n == 2) { opj_bio_write(bio, 2, 2); } else if (n <= 5) { @@ -801,7 +801,7 @@ static OPJ_BOOL opj_t2_encode_packet(OPJ_UINT32 tileno, } } #endif - opj_bio_write(bio, packet_empty ? 0 : 1, 1); /* Empty header bit */ + opj_bio_putbit(bio, packet_empty ? 0 : 1); /* Empty header bit */ /* Writing Packet header */ band = res->bands; @@ -849,7 +849,7 @@ static OPJ_BOOL opj_t2_encode_packet(OPJ_UINT32 tileno, if (!cblk->numpasses) { opj_tgt_encode(bio, prc->incltree, cblkno, (OPJ_INT32)(layno + 1)); } else { - opj_bio_write(bio, layer->numpasses != 0, 1); + opj_bio_putbit(bio, layer->numpasses != 0); } /* if cblk not included, go to the next cblk */ @@ -978,7 +978,9 @@ static OPJ_BOOL opj_t2_encode_packet(OPJ_UINT32 tileno, return OPJ_FALSE; } - memcpy(c, layer->data, layer->len); + if (p_t2_mode == FINAL_PASS) { + memcpy(c, layer->data, layer->len); + } cblk->numpasses += layer->numpasses; c += layer->len; length -= layer->len; @@ -1227,9 +1229,17 @@ static OPJ_BOOL opj_t2_read_packet_header(opj_t2_t* p_t2, while (!opj_tgt_decode(l_bio, l_prc->imsbtree, cblkno, (OPJ_INT32)i)) { ++i; } - l_cblk->Mb = (OPJ_UINT32)l_band->numbps; - l_cblk->numbps = (OPJ_UINT32)l_band->numbps + 1 - i; + if ((OPJ_UINT32)l_band->numbps + 1 < i) { + /* Not totally sure what we should do in that situation, + * but that avoids the integer overflow of + * https://github.com/uclouvain/openjpeg/pull/1488 + * while keeping the regression test suite happy. + */ + l_cblk->numbps = (OPJ_UINT32)(l_band->numbps + 1 - (int)i); + } else { + l_cblk->numbps = (OPJ_UINT32)l_band->numbps + 1 - i; + } l_cblk->numlenbits = 3; } @@ -1590,6 +1600,7 @@ static OPJ_BOOL opj_t2_skip_packet_data(opj_t2_t* p_t2, "skip: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno); + return OPJ_TRUE; } } diff --git a/3rdparty/openjpeg/openjp2/tcd.c b/3rdparty/openjpeg/openjp2/tcd.c index 8f0aac0aa078..687aa61bb094 100644 --- a/3rdparty/openjpeg/openjp2/tcd.c +++ b/3rdparty/openjpeg/openjp2/tcd.c @@ -42,6 +42,8 @@ #include "opj_includes.h" #include "opj_common.h" +// #define DEBUG_RATE_ALLOC + /* ----------------------------------------------------------------------- */ /* TODO MSD: */ @@ -143,6 +145,9 @@ static OPJ_BOOL opj_tcd_code_block_enc_allocate_data(opj_tcd_cblk_enc_t * */ static void opj_tcd_code_block_enc_deallocate(opj_tcd_precinct_t * p_precinct); +static +void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, + OPJ_UINT32 final); /** Free the memory allocated for encoding @@ -224,6 +229,7 @@ opj_tcd_t* opj_tcd_create(OPJ_BOOL p_is_decoder) /* ----------------------------------------------------------------------- */ +static void opj_tcd_rateallocate_fixed(opj_tcd_t *tcd) { OPJ_UINT32 layno; @@ -234,17 +240,23 @@ void opj_tcd_rateallocate_fixed(opj_tcd_t *tcd) } -void opj_tcd_makelayer(opj_tcd_t *tcd, - OPJ_UINT32 layno, - OPJ_FLOAT64 thresh, - OPJ_UINT32 final) +/* ----------------------------------------------------------------------- */ + +/** Returns OPJ_TRUE if the layer allocation is unchanged w.r.t to the previous + * invokation with a different threshold */ +static +OPJ_BOOL opj_tcd_makelayer(opj_tcd_t *tcd, + OPJ_UINT32 layno, + OPJ_FLOAT64 thresh, + OPJ_UINT32 final) { OPJ_UINT32 compno, resno, bandno, precno, cblkno; OPJ_UINT32 passno; opj_tcd_tile_t *tcd_tile = tcd->tcd_image->tiles; + OPJ_BOOL layer_allocation_is_same = OPJ_TRUE; - tcd_tile->distolayer[layno] = 0; /* fixed_quality */ + tcd_tile->distolayer[layno] = 0; for (compno = 0; compno < tcd_tile->numcomps; compno++) { opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; @@ -304,7 +316,10 @@ void opj_tcd_makelayer(opj_tcd_t *tcd, } } - layer->numpasses = n - cblk->numpassesinlayers; + if (layer->numpasses != n - cblk->numpassesinlayers) { + layer_allocation_is_same = OPJ_FALSE; + layer->numpasses = n - cblk->numpassesinlayers; + } if (!layer->numpasses) { layer->disto = 0; @@ -323,7 +338,7 @@ void opj_tcd_makelayer(opj_tcd_t *tcd, cblk->passes[cblk->numpassesinlayers - 1].distortiondec; } - tcd_tile->distolayer[layno] += layer->disto; /* fixed_quality */ + tcd_tile->distolayer[layno] += layer->disto; if (final) { cblk->numpassesinlayers = n; @@ -333,14 +348,17 @@ void opj_tcd_makelayer(opj_tcd_t *tcd, } } } + return layer_allocation_is_same; } +/** For m_quality_layer_alloc_strategy == FIXED_LAYER */ +static void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, OPJ_UINT32 final) { OPJ_UINT32 compno, resno, bandno, precno, cblkno; OPJ_INT32 value; /*, matrice[tcd_tcp->numlayers][tcd_tile->comps[0].numresolutions][3]; */ - OPJ_INT32 matrice[10][10][3]; + OPJ_INT32 matrice[J2K_TCD_MATRIX_MAX_LAYER_COUNT][J2K_TCD_MATRIX_MAX_RESOLUTION_COUNT][3]; OPJ_UINT32 i, j, k; opj_cp_t *cp = tcd->cp; @@ -440,6 +458,11 @@ void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, } } +/** Rate allocation for the following methods: + * - allocation by rate/distortio (m_quality_layer_alloc_strategy == RATE_DISTORTION_RATIO) + * - allocation by fixed quality (m_quality_layer_alloc_strategy == FIXED_DISTORTION_RATIO) + */ +static OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, OPJ_BYTE *dest, OPJ_UINT32 * p_data_written, @@ -450,8 +473,8 @@ OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, OPJ_UINT32 compno, resno, bandno, precno, cblkno, layno; OPJ_UINT32 passno; OPJ_FLOAT64 min, max; - OPJ_FLOAT64 cumdisto[100]; /* fixed_quality */ - const OPJ_FLOAT64 K = 1; /* 1.1; fixed_quality */ + OPJ_FLOAT64 cumdisto[100]; + const OPJ_FLOAT64 K = 1; OPJ_FLOAT64 maxSE = 0; opj_cp_t *cp = tcd->cp; @@ -461,7 +484,7 @@ OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, min = DBL_MAX; max = 0; - tcd_tile->numpix = 0; /* fixed_quality */ + tcd_tile->numpix = 0; for (compno = 0; compno < tcd_tile->numcomps; compno++) { opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; @@ -511,9 +534,12 @@ OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, } } /* passno */ - /* fixed_quality */ - tcd_tile->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0)); - tilec->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0)); + { + const OPJ_SIZE_T cblk_pix_count = (OPJ_SIZE_T)((cblk->x1 - cblk->x0) * + (cblk->y1 - cblk->y0)); + tcd_tile->numpix += cblk_pix_count; + tilec->numpix += cblk_pix_count; + } } /* cbklno */ } /* precno */ } /* bandno */ @@ -527,8 +553,8 @@ OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, /* index file */ if (cstr_info) { opj_tile_info_t *tile_info = &cstr_info->tile[tcd->tcd_tileno]; - tile_info->numpix = tcd_tile->numpix; - tile_info->distotile = tcd_tile->distotile; + tile_info->numpix = (int)tcd_tile->numpix; + tile_info->distotile = (int)tcd_tile->distotile; tile_info->thresh = (OPJ_FLOAT64 *) opj_malloc(tcd_tcp->numlayers * sizeof( OPJ_FLOAT64)); if (!tile_info->thresh) { @@ -545,35 +571,54 @@ OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, OPJ_FLOAT64 goodthresh = 0; OPJ_FLOAT64 stable_thresh = 0; OPJ_UINT32 i; - OPJ_FLOAT64 distotarget; /* fixed_quality */ + OPJ_FLOAT64 distotarget; - /* fixed_quality */ distotarget = tcd_tile->distotile - ((K * maxSE) / pow((OPJ_FLOAT32)10, tcd_tcp->distoratio[layno] / 10)); /* Don't try to find an optimal threshold but rather take everything not included yet, if - -r xx,yy,zz,0 (disto_alloc == 1 and rates == 0) - -q xx,yy,zz,0 (fixed_quality == 1 and distoratio == 0) + -r xx,yy,zz,0 (m_quality_layer_alloc_strategy == RATE_DISTORTION_RATIO and rates == NULL) + -q xx,yy,zz,0 (m_quality_layer_alloc_strategy == FIXED_DISTORTION_RATIO and distoratio == NULL) ==> possible to have some lossy layers and the last layer for sure lossless */ - if (((cp->m_specific_param.m_enc.m_disto_alloc == 1) && + if (((cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy == + RATE_DISTORTION_RATIO) && (tcd_tcp->rates[layno] > 0.0f)) || - ((cp->m_specific_param.m_enc.m_fixed_quality == 1) && + ((cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy == + FIXED_DISTORTION_RATIO) && (tcd_tcp->distoratio[layno] > 0.0))) { opj_t2_t*t2 = opj_t2_create(tcd->image, cp); OPJ_FLOAT64 thresh = 0; + OPJ_BOOL last_layer_allocation_ok = OPJ_FALSE; if (t2 == 00) { return OPJ_FALSE; } for (i = 0; i < 128; ++i) { - OPJ_FLOAT64 distoachieved = 0; /* fixed_quality */ - - thresh = (lo + hi) / 2; - - opj_tcd_makelayer(tcd, layno, thresh, 0); + OPJ_FLOAT64 distoachieved = 0; + OPJ_BOOL layer_allocation_is_same; + + OPJ_FLOAT64 new_thresh = (lo + hi) / 2; + /* Stop iterating when the threshold has stabilized enough */ + /* 0.5 * 1e-5 is somewhat arbitrary, but has been selected */ + /* so that this doesn't change the results of the regression */ + /* test suite. */ + if (fabs(new_thresh - thresh) <= 0.5 * 1e-5 * thresh) { + break; + } + thresh = new_thresh; +#ifdef DEBUG_RATE_ALLOC + opj_event_msg(p_manager, EVT_INFO, "layno=%u, iter=%u, thresh=%g", + layno, i, new_thresh); +#endif - if (cp->m_specific_param.m_enc.m_fixed_quality) { /* fixed_quality */ + layer_allocation_is_same = opj_tcd_makelayer(tcd, layno, thresh, 0) && i != 0; +#ifdef DEBUG_RATE_ALLOC + opj_event_msg(p_manager, EVT_INFO, "--> layer_allocation_is_same = %d", + layer_allocation_is_same); +#endif + if (cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy == + FIXED_DISTORTION_RATIO) { if (OPJ_IS_CINEMA(cp->rsiz) || OPJ_IS_IMF(cp->rsiz)) { if (! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, p_data_written, maxlen, cstr_info, NULL, tcd->cur_tp_num, tcd->tp_pos, @@ -605,17 +650,41 @@ OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, } lo = thresh; } - } else { - if (! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, - p_data_written, maxlen, cstr_info, NULL, tcd->cur_tp_num, tcd->tp_pos, - tcd->cur_pino, - THRESH_CALC, p_manager)) { - /* TODO: what to do with l ??? seek / tell ??? */ - /* opj_event_msg(tcd->cinfo, EVT_INFO, "rate alloc: len=%d, max=%d\n", l, maxlen); */ + } else { /* Disto/rate based optimization */ + /* Check if the layer allocation done by opj_tcd_makelayer() + * is compatible of the maximum rate allocation. If not, + * retry with a higher threshold. + * If OK, try with a lower threshold. + * Call opj_t2_encode_packets() only if opj_tcd_makelayer() + * has resulted in different truncation points since its last + * call. */ + if ((layer_allocation_is_same && !last_layer_allocation_ok) || + (!layer_allocation_is_same && + ! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, + p_data_written, maxlen, cstr_info, NULL, tcd->cur_tp_num, tcd->tp_pos, + tcd->cur_pino, + THRESH_CALC, p_manager))) { + +#ifdef DEBUG_RATE_ALLOC + if (!layer_allocation_is_same) { + opj_event_msg(p_manager, EVT_INFO, + "--> check rate alloc failed (> maxlen=%u)\n", maxlen); + } +#endif + last_layer_allocation_ok = OPJ_FALSE; lo = thresh; continue; } +#ifdef DEBUG_RATE_ALLOC + if (!layer_allocation_is_same) { + opj_event_msg(p_manager, EVT_INFO, + "--> check rate alloc success (len=%u <= maxlen=%u)\n", *p_data_written, + maxlen); + } +#endif + + last_layer_allocation_ok = OPJ_TRUE; hi = thresh; stable_thresh = thresh; } @@ -635,7 +704,6 @@ OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, opj_tcd_makelayer(tcd, layno, goodthresh, 1); - /* fixed_quality */ cumdisto[layno] = (layno == 0) ? tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); } @@ -2247,6 +2315,9 @@ static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd) l_max = (OPJ_INT32)((1U << l_img_comp->prec) - 1); } + if (l_width == 0 || l_height == 0) { + continue; + } if (l_tccp->qmfbid == 1) { for (j = 0; j < l_height; ++j) { @@ -2599,10 +2670,10 @@ static OPJ_BOOL opj_tcd_rate_allocate_encode(opj_tcd_t *p_tcd, p_cstr_info->index_write = 0; } - if (l_cp->m_specific_param.m_enc.m_disto_alloc || - l_cp->m_specific_param.m_enc.m_fixed_quality) { - /* fixed_quality */ - /* Normal Rate/distortion allocation */ + if (l_cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy == + RATE_DISTORTION_RATIO || + l_cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy == + FIXED_DISTORTION_RATIO) { if (! opj_tcd_rateallocate(p_tcd, p_dest_data, &l_nb_written, p_max_dest_size, p_cstr_info, p_manager)) { return OPJ_FALSE; diff --git a/3rdparty/openjpeg/openjp2/tcd.h b/3rdparty/openjpeg/openjp2/tcd.h index 340c2bf8a646..f659869a1344 100644 --- a/3rdparty/openjpeg/openjp2/tcd.h +++ b/3rdparty/openjpeg/openjp2/tcd.h @@ -222,8 +222,8 @@ typedef struct opj_tcd_tilecomp { OPJ_UINT32 win_x1; OPJ_UINT32 win_y1; - /* add fixed_quality */ - OPJ_INT32 numpix; + /* number of pixels */ + OPJ_SIZE_T numpix; } opj_tcd_tilecomp_t; @@ -235,9 +235,9 @@ typedef struct opj_tcd_tile { OPJ_INT32 x0, y0, x1, y1; OPJ_UINT32 numcomps; /* number of components in tile */ opj_tcd_tilecomp_t *comps; /* Components information */ - OPJ_INT32 numpix; /* add fixed_quality */ - OPJ_FLOAT64 distotile; /* add fixed_quality */ - OPJ_FLOAT64 distolayer[100]; /* add fixed_quality */ + OPJ_SIZE_T numpix; /* number of pixels */ + OPJ_FLOAT64 distotile; /* distortion of the tile */ + OPJ_FLOAT64 distolayer[100]; /* distortion per layer */ OPJ_UINT32 packno; /* packet number */ } opj_tcd_tile_t; @@ -369,23 +369,6 @@ OPJ_BOOL opj_tcd_init(opj_tcd_t *p_tcd, OPJ_BOOL opj_tcd_init_decode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, opj_event_mgr_t* p_manager); -void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, - OPJ_UINT32 final); - -void opj_tcd_rateallocate_fixed(opj_tcd_t *tcd); - -void opj_tcd_makelayer(opj_tcd_t *tcd, - OPJ_UINT32 layno, - OPJ_FLOAT64 thresh, - OPJ_UINT32 final); - -OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, - OPJ_BYTE *dest, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 len, - opj_codestream_info_t *cstr_info, - opj_event_mgr_t *p_manager); - /** * Gets the maximum tile size that will be taken by the tile once decoded. */ diff --git a/3rdparty/openjpeg/openjp2/tgt.c b/3rdparty/openjpeg/openjp2/tgt.c index 0cbad12c42ef..711d753f46c1 100644 --- a/3rdparty/openjpeg/openjp2/tgt.c +++ b/3rdparty/openjpeg/openjp2/tgt.c @@ -287,12 +287,12 @@ void opj_tgt_encode(opj_bio_t *bio, opj_tgt_tree_t *tree, OPJ_UINT32 leafno, while (low < threshold) { if (low >= node->value) { if (!node->known) { - opj_bio_write(bio, 1, 1); + opj_bio_putbit(bio, 1); node->known = 1; } break; } - opj_bio_write(bio, 0, 1); + opj_bio_putbit(bio, 0); ++low; } diff --git a/3rdparty/openjpeg/openjp2/thread.c b/3rdparty/openjpeg/openjp2/thread.c index f2fca2ee4af8..240810b1c44b 100644 --- a/3rdparty/openjpeg/openjp2/thread.c +++ b/3rdparty/openjpeg/openjp2/thread.c @@ -221,7 +221,7 @@ struct opj_thread_t { HANDLE hThread; }; -unsigned int __stdcall opj_thread_callback_adapter(void *info) +static unsigned int __stdcall opj_thread_callback_adapter(void *info) { opj_thread_t* thread = (opj_thread_t*) info; HANDLE hEvent = NULL; From 0b39a51be8777de8e9a7c47d58d8cc596afa4f9b Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Tue, 21 May 2024 11:33:30 +0300 Subject: [PATCH 066/119] pre: OpenCV 4.10.0 (version++). --- .../cross_referencing/tutorial_cross_referencing.markdown | 4 ++-- modules/core/include/opencv2/core/version.hpp | 4 ++-- modules/dnn/include/opencv2/dnn/version.hpp | 2 +- modules/python/package/setup.py | 2 +- platforms/maven/opencv-it/pom.xml | 2 +- platforms/maven/opencv/pom.xml | 2 +- platforms/maven/pom.xml | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown b/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown index a4a5300d78b5..6d43761e1456 100644 --- a/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown +++ b/doc/tutorials/introduction/cross_referencing/tutorial_cross_referencing.markdown @@ -46,14 +46,14 @@ Open your Doxyfile using your favorite text editor and search for the key `TAGFILES`. Change it as follows: @code -TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/4.9.0 +TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/4.10.0 @endcode If you had other definitions already, you can append the line using a `\`: @code TAGFILES = ./docs/doxygen-tags/libstdc++.tag=https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen \ - ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/4.9.0 + ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/4.10.0 @endcode Doxygen can now use the information from the tag file to link to the OpenCV diff --git a/modules/core/include/opencv2/core/version.hpp b/modules/core/include/opencv2/core/version.hpp index 483e0e62804a..18bea5f3a4a6 100644 --- a/modules/core/include/opencv2/core/version.hpp +++ b/modules/core/include/opencv2/core/version.hpp @@ -6,9 +6,9 @@ #define OPENCV_VERSION_HPP #define CV_VERSION_MAJOR 4 -#define CV_VERSION_MINOR 9 +#define CV_VERSION_MINOR 10 #define CV_VERSION_REVISION 0 -#define CV_VERSION_STATUS "-dev" +#define CV_VERSION_STATUS "-pre" #define CVAUX_STR_EXP(__A) #__A #define CVAUX_STR(__A) CVAUX_STR_EXP(__A) diff --git a/modules/dnn/include/opencv2/dnn/version.hpp b/modules/dnn/include/opencv2/dnn/version.hpp index f1dd1641eae3..f83d90dab410 100644 --- a/modules/dnn/include/opencv2/dnn/version.hpp +++ b/modules/dnn/include/opencv2/dnn/version.hpp @@ -6,7 +6,7 @@ #define OPENCV_DNN_VERSION_HPP /// Use with major OpenCV version only. -#define OPENCV_DNN_API_VERSION 20231225 +#define OPENCV_DNN_API_VERSION 20240521 #if !defined CV_DOXYGEN && !defined CV_STATIC_ANALYSIS && !defined CV_DNN_DONT_ADD_INLINE_NS #define CV__DNN_INLINE_NS __CV_CAT(dnn4_v, OPENCV_DNN_API_VERSION) diff --git a/modules/python/package/setup.py b/modules/python/package/setup.py index 1e2f22bcc59c..068f6180cb1f 100644 --- a/modules/python/package/setup.py +++ b/modules/python/package/setup.py @@ -19,7 +19,7 @@ def main(): os.chdir(SCRIPT_DIR) package_name = 'opencv' - package_version = os.environ.get('OPENCV_VERSION', '4.9.0') # TODO + package_version = os.environ.get('OPENCV_VERSION', '4.10.0') # TODO long_description = 'Open Source Computer Vision Library Python bindings' # TODO diff --git a/platforms/maven/opencv-it/pom.xml b/platforms/maven/opencv-it/pom.xml index f8dcf6d6a220..6b0e0f54d3c8 100644 --- a/platforms/maven/opencv-it/pom.xml +++ b/platforms/maven/opencv-it/pom.xml @@ -4,7 +4,7 @@ org.opencv opencv-parent - 4.9.0 + 4.10.0 org.opencv opencv-it diff --git a/platforms/maven/opencv/pom.xml b/platforms/maven/opencv/pom.xml index e2477b8dc134..8e5221f0a987 100644 --- a/platforms/maven/opencv/pom.xml +++ b/platforms/maven/opencv/pom.xml @@ -4,7 +4,7 @@ org.opencv opencv-parent - 4.9.0 + 4.10.0 org.opencv opencv diff --git a/platforms/maven/pom.xml b/platforms/maven/pom.xml index de455da9985a..c0b4f776973e 100644 --- a/platforms/maven/pom.xml +++ b/platforms/maven/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.opencv opencv-parent - 4.9.0 + 4.10.0 pom OpenCV Parent POM From e52540162fe40a341fc468b90049139b3523a87d Mon Sep 17 00:00:00 2001 From: HAN Liutong Date: Tue, 21 May 2024 19:10:19 +0800 Subject: [PATCH 067/119] Merge pull request #25586 from hanliutong:rvv-64f Fix v_round and enable unit tests for scalable universal intrinsic 64F type. #25586 This may be a legacy issue from the previous PR #24325. I don't quite remember why the float 64 part of the unit test was not enabled at that time. Whatever, this patch enables the unit tests for scalable 64F type , and makes the necessary modifications to the RVV backend to make the tests pass. This patch is compiled by GCC 14 and LLVM 17 &18, and tested on QEMU and k230. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [ ] I agree to contribute to the project under Apache 2 License. - [ ] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ ] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- .../core/hal/intrin_rvv_compat_overloaded.hpp | 7 +++- .../opencv2/core/hal/intrin_rvv_scalable.hpp | 26 ++++++++++++- modules/core/test/test_intrin_utils.hpp | 38 ++++++++++++++++--- modules/core/test/test_operations.cpp | 4 -- 4 files changed, 63 insertions(+), 12 deletions(-) diff --git a/modules/core/include/opencv2/core/hal/intrin_rvv_compat_overloaded.hpp b/modules/core/include/opencv2/core/hal/intrin_rvv_compat_overloaded.hpp index 914ad2897894..2a323069fd9a 100644 --- a/modules/core/include/opencv2/core/hal/intrin_rvv_compat_overloaded.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_rvv_compat_overloaded.hpp @@ -200,9 +200,14 @@ inline static vuint32mf2_t vmul(const vuint32mf2_t & op1, uint32_t op2, size_t v return vmul_vx_u32mf2(op1, op2, vl); } -inline static vuint32mf2_t vreinterpret_u32mf2(vint32mf2_t val) +inline static vuint32mf2_t vreinterpret_u32mf2(const vint32mf2_t& val) { return vreinterpret_v_i32mf2_u32mf2(val); } +inline static vuint32mf2_t vreinterpret_u32mf2(const vuint16mf2_t& val) +{ + return vreinterpret_v_u16mf2_u32mf2(val); +} + #endif //OPENCV_HAL_INTRIN_RVV_COMPAT_OVERLOAD_HPP diff --git a/modules/core/include/opencv2/core/hal/intrin_rvv_scalable.hpp b/modules/core/include/opencv2/core/hal/intrin_rvv_scalable.hpp index 87531ede1ee7..0159e4325a3a 100644 --- a/modules/core/include/opencv2/core/hal/intrin_rvv_scalable.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_rvv_scalable.hpp @@ -1528,6 +1528,26 @@ OPENCV_HAL_IMPL_RVV_ZIP(v_uint32, vuint32m2_t, u32, 32, 64, OPENCV_HAL_NOP, OPEN OPENCV_HAL_IMPL_RVV_ZIP(v_int32, vint32m2_t, i32, 32, 64, vreinterpret_u32m2, vreinterpret_u32m1) OPENCV_HAL_IMPL_RVV_ZIP(v_float32, vfloat32m2_t, f32, 32, 64, vreinterpret_u32m2, vreinterpret_u32m1) +#if CV_SIMD_SCALABLE_64F +inline void v_zip(const v_float64& a0, const v_float64& a1, v_float64& b0, v_float64& b1) { \ + vuint16mf4_t idx0 = vid_v_u16mf4(VTraits::vlanes()); + vuint16mf4_t idx1 = vadd(idx0, VTraits::vlanes(), VTraits::vlanes()); + vuint16mf2_t idx = vreinterpret_u16mf2(( \ + vor(vzext_vf2(idx0, VTraits::vlanes()), \ + vreinterpret_u32mf2(vslide1up(vreinterpret_u16mf2(vzext_vf2(idx1, VTraits::vlanes())), 0, VTraits::vlanes())), \ + VTraits::vlanes()))); +#if 0 + vfloat64m2_t temp = __riscv_vcreate_v_f64m1_f64m2(a0, a1); +#else // TODO: clean up when RVV Intrinsic is frozen. + vfloat64m2_t temp = vlmul_ext_f64m2(a0); + temp = vset(temp, 1, a1); +#endif + temp = vrgatherei16(temp, idx, VTraits::vlanes()*2); + b0 = vget_f64m1(temp, 0); \ + b1 = vget_f64m1(temp, 1); \ +} +#endif + #define OPENCV_HAL_IMPL_RVV_UNPACKS(_Tpvec, width) \ inline _Tpvec v_combine_low(const _Tpvec& a, const _Tpvec& b) \ { \ @@ -1859,12 +1879,14 @@ inline v_int32 v_trunc(const v_float32& a) #if CV_SIMD_SCALABLE_64F inline v_int32 v_round(const v_float64& a) { - return vfncvt_x(vlmul_ext_f64m2(vfadd(a, 1e-6, VTraits::vlanes())), VTraits::vlanes()); + return vfncvt_x(vlmul_ext_f64m2(a), VTraits::vlanes()); } inline v_int32 v_round(const v_float64& a, const v_float64& b) { - return vfncvt_x(vset(vlmul_ext_f64m2(vfadd(a, 1e-6, VTraits::vlanes())), 1, b), VTraits::vlanes()); + // return vfncvt_x(vset(vlmul_ext_f64m2(vfadd(a, 1e-6, VTraits::vlanes())), 1, b), VTraits::vlanes()); + // Fix https://github.com/opencv/opencv/issues/24746 + return vfncvt_x(vset(vlmul_ext_f64m2(a), 1, b), VTraits::vlanes()); } inline v_int32 v_floor(const v_float64& a) diff --git a/modules/core/test/test_intrin_utils.hpp b/modules/core/test/test_intrin_utils.hpp index a8c565ec46e0..08138d194dcf 100644 --- a/modules/core/test/test_intrin_utils.hpp +++ b/modules/core/test/test_intrin_utils.hpp @@ -281,7 +281,7 @@ template struct TheTest v_uint64 vu64 = v_reinterpret_as_u64(r1); out.a.clear(); v_store((uint64*)out.a.d, vu64); EXPECT_EQ(data.a, out.a); v_int64 vs64 = v_reinterpret_as_s64(r1); out.a.clear(); v_store((int64*)out.a.d, vs64); EXPECT_EQ(data.a, out.a); v_float32 vf32 = v_reinterpret_as_f32(r1); out.a.clear(); v_store((float*)out.a.d, vf32); EXPECT_EQ(data.a, out.a); -#if CV_SIMD_64F +#if (CV_SIMD_64F || CV_SIMD_SCALABLE_64F) v_float64 vf64 = v_reinterpret_as_f64(r1); out.a.clear(); v_store((double*)out.a.d, vf64); EXPECT_EQ(data.a, out.a); #endif @@ -747,7 +747,7 @@ template struct TheTest TheTest & test_dotprod_expand_f64() { - #if CV_SIMD_64F + #if (CV_SIMD_64F || CV_SIMD_SCALABLE_64F) Data dataA, dataB; dataA += std::numeric_limits::max() - VTraits::vlanes(); dataB += std::numeric_limits::min(); @@ -1385,6 +1385,33 @@ template struct TheTest return *this; } +#if (CV_SIMD_64F || CV_SIMD_SCALABLE_64F) + TheTest & test_round_pair_f64() + { + typedef typename V_RegTraits::round_reg Ri; + Data data1, data1_border, data2; + // See https://github.com/opencv/opencv/issues/24213 + // https://github.com/opencv/opencv/issues/24163 + // https://github.com/opencv/opencv/pull/24271 + data1_border *= 0.5; + data1 *= 1.1; + data2 += 10; + R a1 = data1, a1_border = data1_border, a2 = data2; + + Data resA = v_round(a1, a1), + resB = v_round(a1_border, a1_border), + resC = v_round(a2, a2); + + for (int i = 0; i < VTraits::vlanes(); ++i) + { + EXPECT_EQ(cvRound(data1[i]), resA[i]); + EXPECT_EQ(cvRound(data1_border[i]), resB[i]); + EXPECT_EQ(cvRound(data2[i]), resC[i]); + } + + return *this; + } +#endif TheTest & test_float_cvt32() { @@ -1405,7 +1432,7 @@ template struct TheTest TheTest & test_float_cvt64() { -#if CV_SIMD_64F +#if (CV_SIMD_64F || CV_SIMD_SCALABLE_64F) typedef v_float64 Rt; Data dataA; dataA *= 1.1; @@ -1431,7 +1458,7 @@ template struct TheTest TheTest & test_cvt64_double() { -#if CV_SIMD_64F +#if (CV_SIMD_64F || CV_SIMD_SCALABLE_64F) Data dataA(std::numeric_limits::max()), dataB(std::numeric_limits::min()); dataB += VTraits::vlanes(); @@ -1994,7 +2021,7 @@ void test_hal_intrin_float32() void test_hal_intrin_float64() { DUMP_ENTRY(v_float64); -#if CV_SIMD_64F +#if (CV_SIMD_64F || CV_SIMD_SCALABLE_64F) TheTest() .test_loadstore() .test_addsub() @@ -2008,6 +2035,7 @@ void test_hal_intrin_float64() .test_mask() .test_unpack() .test_float_math() + .test_round_pair_f64() .test_float_cvt32() .test_reverse() .test_extract<0>().test_extract<1>() diff --git a/modules/core/test/test_operations.cpp b/modules/core/test/test_operations.cpp index d985a1c2b68b..d5622dabb46f 100644 --- a/modules/core/test/test_operations.cpp +++ b/modules/core/test/test_operations.cpp @@ -1574,11 +1574,7 @@ TEST(Core_Arithm, scalar_handling_19599) // https://github.com/opencv/opencv/is typedef tuple Arith_Regression24163Param; typedef testing::TestWithParam Core_Arith_Regression24163; -#if defined __riscv -TEST_P(Core_Arith_Regression24163, DISABLED_test_for_ties_to_even) -#else TEST_P(Core_Arith_Regression24163, test_for_ties_to_even) -#endif { const int matDepth = get<0>(GetParam()); const int matHeight= get<1>(GetParam()); From 49f80cb3c42a91a8baa966b38664bdae4296db22 Mon Sep 17 00:00:00 2001 From: Yuantao Feng Date: Tue, 21 May 2024 21:58:16 +0800 Subject: [PATCH 068/119] Merge pull request #24804 from fengyuentau:fix_lapack_warnings core: try to solve warnings caused by Apple's new LAPACK interface #24804 Resolves https://github.com/opencv/opencv/issues/24660 Apple's BLAS documentation: https://developer.apple.com/documentation/accelerate/blas?language=objc New interface since macOS >= 13.3, iOS >= 16.4. Todo: - [x] Detect macOS version. - [x] ~Detect iOS versions (major and minor version).~ No calling of Accelerate New LAPACK on iOS. - [x] Solve calling `cblas_cgemm` and `cblas_zgemm`. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- cmake/OpenCVFindLAPACK.cmake | 15 ++++ modules/core/src/hal_internal.cpp | 143 ++++++++++++++++++++++-------- 2 files changed, 122 insertions(+), 36 deletions(-) diff --git a/cmake/OpenCVFindLAPACK.cmake b/cmake/OpenCVFindLAPACK.cmake index 9b1b60f19ec3..d559ab88b90f 100644 --- a/cmake/OpenCVFindLAPACK.cmake +++ b/cmake/OpenCVFindLAPACK.cmake @@ -106,11 +106,26 @@ macro(ocv_lapack_check) list(APPEND __link_directories ${LAPACK_LINK_LIBRARIES}) endif() + set(LAPACK_TRY_COMPILE_DEF "") + if(LAPACK_IMPL STREQUAL "LAPACK/Apple" AND NOT IOS) # https://github.com/opencv/opencv/issues/24660 + # Get macOS version + execute_process(COMMAND sw_vers -productVersion + OUTPUT_VARIABLE MACOS_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + # Enable Accelerate New LAPACK if macOS >= 13.3 + if (MACOS_VERSION VERSION_GREATER "13.3" OR MACOS_VERSION VERSION_EQUAL "13.3") + set(LAPACK_TRY_COMPILE_DEF "-DACCELERATE_NEW_LAPACK") + add_compile_definitions(ACCELERATE_NEW_LAPACK) + add_compile_definitions(ACCELERATE_LAPACK_ILP64) + endif() + endif() + try_compile(__VALID_LAPACK "${OpenCV_BINARY_DIR}" "${OpenCV_SOURCE_DIR}/cmake/checks/lapack_check.cpp" CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${LAPACK_INCLUDE_DIR}\;${CMAKE_BINARY_DIR}" "-DLINK_DIRECTORIES:STRING=${__link_directories}" + COMPILE_DEFINITIONS ${LAPACK_TRY_COMPILE_DEF} LINK_LIBRARIES ${LAPACK_LIBRARIES} OUTPUT_VARIABLE TRY_OUT ) diff --git a/modules/core/src/hal_internal.cpp b/modules/core/src/hal_internal.cpp index 28227688c0a2..377c68801589 100644 --- a/modules/core/src/hal_internal.cpp +++ b/modules/core/src/hal_internal.cpp @@ -111,8 +111,18 @@ set_value(fptype *dst, size_t dst_ld, fptype value, size_t m, size_t n) template static inline int lapack_LU(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n, int* info) { - int lda = (int)(a_step / sizeof(fptype)), sign = 0; - int* piv = new int[m]; +#if defined (ACCELERATE_NEW_LAPACK) && defined (ACCELERATE_LAPACK_ILP64) + cv::AutoBuffer piv_buff(m); + long lda = (long)(a_step / sizeof(fptype)); + long _m = static_cast(m), _n = static_cast(n); + long _info[1]; +#else + cv::AutoBuffer piv_buff(m); + int lda = (int)(a_step / sizeof(fptype)); + int _m = m, _n = n; + int* _info = info; +#endif + auto piv = piv_buff.data(); transpose_square_inplace(a, lda, m); @@ -121,9 +131,9 @@ lapack_LU(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n, int* if(n == 1 && b_step == sizeof(fptype)) { if(typeid(fptype) == typeid(float)) - sgesv_(&m, &n, (float*)a, &lda, piv, (float*)b, &m, info); + sgesv_(&_m, &_n, (float*)a, &lda, piv, (float*)b, &_m, _info); else if(typeid(fptype) == typeid(double)) - dgesv_(&m, &n, (double*)a, &lda, piv, (double*)b, &m, info); + dgesv_(&_m, &_n, (double*)a, &lda, piv, (double*)b, &_m, _info); } else { @@ -133,9 +143,9 @@ lapack_LU(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n, int* transpose(b, ldb, tmpB, m, m, n); if(typeid(fptype) == typeid(float)) - sgesv_(&m, &n, (float*)a, &lda, piv, (float*)tmpB, &m, info); + sgesv_(&_m, &_n, (float*)a, &lda, piv, (float*)tmpB, &_m, _info); else if(typeid(fptype) == typeid(double)) - dgesv_(&m, &n, (double*)a, &lda, piv, (double*)tmpB, &m, info); + dgesv_(&_m, &_n, (double*)a, &lda, piv, (double*)tmpB, &_m, _info); transpose(tmpB, m, b, ldb, n, m); delete[] tmpB; @@ -144,11 +154,16 @@ lapack_LU(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n, int* else { if(typeid(fptype) == typeid(float)) - sgetrf_(&m, &m, (float*)a, &lda, piv, info); + sgetrf_(&_m, &_m, (float*)a, &lda, piv, _info); else if(typeid(fptype) == typeid(double)) - dgetrf_(&m, &m, (double*)a, &lda, piv, info); + dgetrf_(&_m, &_m, (double*)a, &lda, piv, _info); } +#if defined (ACCELERATE_NEW_LAPACK) && defined (ACCELERATE_LAPACK_ILP64) + *info = static_cast(_info[0]); +#endif + + int sign = 0; if(*info == 0) { for(int i = 0; i < m; i++) @@ -158,15 +173,21 @@ lapack_LU(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n, int* else *info = 0; //in opencv LU function zero means error - delete[] piv; return CV_HAL_ERROR_OK; } template static inline int lapack_Cholesky(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n, bool* info) { +#if defined (ACCELERATE_NEW_LAPACK) && defined (ACCELERATE_LAPACK_ILP64) + long _m = static_cast(m), _n = static_cast(n); + long lapackStatus = 0; + long lda = (long)(a_step / sizeof(fptype)); +#else + int _m = m, _n = n; int lapackStatus = 0; int lda = (int)(a_step / sizeof(fptype)); +#endif char L[] = {'L', '\0'}; if(b) @@ -174,9 +195,9 @@ lapack_Cholesky(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n if(n == 1 && b_step == sizeof(fptype)) { if(typeid(fptype) == typeid(float)) - OCV_LAPACK_FUNC(sposv)(L, &m, &n, (float*)a, &lda, (float*)b, &m, &lapackStatus); + OCV_LAPACK_FUNC(sposv)(L, &_m, &_n, (float*)a, &lda, (float*)b, &_m, &lapackStatus); else if(typeid(fptype) == typeid(double)) - OCV_LAPACK_FUNC(dposv)(L, &m, &n, (double*)a, &lda, (double*)b, &m, &lapackStatus); + OCV_LAPACK_FUNC(dposv)(L, &_m, &_n, (double*)a, &lda, (double*)b, &_m, &lapackStatus); } else { @@ -185,9 +206,9 @@ lapack_Cholesky(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n transpose(b, ldb, tmpB, m, m, n); if(typeid(fptype) == typeid(float)) - OCV_LAPACK_FUNC(sposv)(L, &m, &n, (float*)a, &lda, (float*)tmpB, &m, &lapackStatus); + OCV_LAPACK_FUNC(sposv)(L, &_m, &_n, (float*)a, &lda, (float*)tmpB, &_m, &lapackStatus); else if(typeid(fptype) == typeid(double)) - OCV_LAPACK_FUNC(dposv)(L, &m, &n, (double*)a, &lda, (double*)tmpB, &m, &lapackStatus); + OCV_LAPACK_FUNC(dposv)(L, &_m, &_n, (double*)a, &lda, (double*)tmpB, &_m, &lapackStatus); transpose(tmpB, m, b, ldb, n, m); delete[] tmpB; @@ -196,9 +217,9 @@ lapack_Cholesky(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n else { if(typeid(fptype) == typeid(float)) - OCV_LAPACK_FUNC(spotrf)(L, &m, (float*)a, &lda, &lapackStatus); + OCV_LAPACK_FUNC(spotrf)(L, &_m, (float*)a, &lda, &lapackStatus); else if(typeid(fptype) == typeid(double)) - OCV_LAPACK_FUNC(dpotrf)(L, &m, (double*)a, &lda, &lapackStatus); + OCV_LAPACK_FUNC(dpotrf)(L, &_m, (double*)a, &lda, &lapackStatus); } if(lapackStatus == 0) *info = true; @@ -210,11 +231,24 @@ lapack_Cholesky(fptype* a, size_t a_step, int m, fptype* b, size_t b_step, int n template static inline int lapack_SVD(fptype* a, size_t a_step, fptype *w, fptype* u, size_t u_step, fptype* vt, size_t v_step, int m, int n, int flags, int* info) { +#if defined (ACCELERATE_NEW_LAPACK) && defined (ACCELERATE_LAPACK_ILP64) + long _m = static_cast(m), _n = static_cast(n); + long _info[1]; + long lda = (long)(a_step / sizeof(fptype)); + long ldv = (long)(v_step / sizeof(fptype)); + long ldu = (long)(u_step / sizeof(fptype)); + long lwork = -1; + cv::AutoBuffer iworkBuf_(8 * std::min(m, n)); +#else + int _m = m, _n = n; + int* _info = info; int lda = (int)(a_step / sizeof(fptype)); int ldv = (int)(v_step / sizeof(fptype)); int ldu = (int)(u_step / sizeof(fptype)); int lwork = -1; - int* iworkBuf = new int[8*std::min(m, n)]; + cv::AutoBuffer iworkBuf_(8 * std::min(m, n)); +#endif + auto iworkBuf = iworkBuf_.data(); fptype work1 = 0; //A already transposed and m>=n @@ -238,9 +272,9 @@ lapack_SVD(fptype* a, size_t a_step, fptype *w, fptype* u, size_t u_step, fptype } if(typeid(fptype) == typeid(float)) - OCV_LAPACK_FUNC(sgesdd)(mode, &m, &n, (float*)a, &lda, (float*)w, (float*)u, &ldu, (float*)vt, &ldv, (float*)&work1, &lwork, iworkBuf, info); + OCV_LAPACK_FUNC(sgesdd)(mode, &_m, &_n, (float*)a, &lda, (float*)w, (float*)u, &ldu, (float*)vt, &ldv, (float*)&work1, &lwork, iworkBuf, _info); else if(typeid(fptype) == typeid(double)) - OCV_LAPACK_FUNC(dgesdd)(mode, &m, &n, (double*)a, &lda, (double*)w, (double*)u, &ldu, (double*)vt, &ldv, (double*)&work1, &lwork, iworkBuf, info); + OCV_LAPACK_FUNC(dgesdd)(mode, &_m, &_n, (double*)a, &lda, (double*)w, (double*)u, &ldu, (double*)vt, &ldv, (double*)&work1, &lwork, iworkBuf, _info); lwork = (int)round(work1); //optimal buffer size fptype* buffer = new fptype[lwork + 1]; @@ -251,9 +285,13 @@ lapack_SVD(fptype* a, size_t a_step, fptype *w, fptype* u, size_t u_step, fptype CV_ANNOTATE_MEMORY_IS_INITIALIZED(buffer, sizeof(fptype) * (lwork + 1)); if(typeid(fptype) == typeid(float)) - OCV_LAPACK_FUNC(sgesdd)(mode, &m, &n, (float*)a, &lda, (float*)w, (float*)u, &ldu, (float*)vt, &ldv, (float*)buffer, &lwork, iworkBuf, info); + OCV_LAPACK_FUNC(sgesdd)(mode, &_m, &_n, (float*)a, &lda, (float*)w, (float*)u, &ldu, (float*)vt, &ldv, (float*)buffer, &lwork, iworkBuf, _info); else if(typeid(fptype) == typeid(double)) - OCV_LAPACK_FUNC(dgesdd)(mode, &m, &n, (double*)a, &lda, (double*)w, (double*)u, &ldu, (double*)vt, &ldv, (double*)buffer, &lwork, iworkBuf, info); + OCV_LAPACK_FUNC(dgesdd)(mode, &_m, &_n, (double*)a, &lda, (double*)w, (double*)u, &ldu, (double*)vt, &ldv, (double*)buffer, &lwork, iworkBuf, _info); + +#if defined (ACCELERATE_NEW_LAPACK) && defined (ACCELERATE_LAPACK_ILP64) + *info = static_cast(_info[0]); +#endif // Make sure MSAN sees the memory as having been written. // MSAN does not think it has been written because a different language was called. @@ -276,7 +314,6 @@ lapack_SVD(fptype* a, size_t a_step, fptype *w, fptype* u, size_t u_step, fptype delete[] u; } - delete[] iworkBuf; delete[] buffer; return CV_HAL_ERROR_OK; } @@ -284,14 +321,27 @@ lapack_SVD(fptype* a, size_t a_step, fptype *w, fptype* u, size_t u_step, fptype template static inline int lapack_QR(fptype* a, size_t a_step, int m, int n, int k, fptype* b, size_t b_step, fptype* dst, int* info) { +#if defined (ACCELERATE_NEW_LAPACK) && defined (ACCELERATE_LAPACK_ILP64) + long _m = static_cast(m), _n = static_cast(n), _k = static_cast(k); + long _info[1]; + long lda = (long)(a_step / sizeof(fptype)); + long lwork = -1; + long ldtmpA; +#else + int _m = m, _n = n, _k = k; + int* _info = info; int lda = (int)(a_step / sizeof(fptype)); + int lwork = -1; + int ldtmpA; +#endif + char mode[] = { 'N', '\0' }; if(m < n) return CV_HAL_ERROR_NOT_IMPLEMENTED; std::vector tmpAMemHolder; fptype* tmpA; - int ldtmpA; + if (m == n) { transpose_square_inplace(a, lda, m); @@ -306,7 +356,6 @@ lapack_QR(fptype* a, size_t a_step, int m, int n, int k, fptype* b, size_t b_ste transpose(a, lda, tmpA, m, m, n); } - int lwork = -1; fptype work1 = 0.; if (b) @@ -314,18 +363,18 @@ lapack_QR(fptype* a, size_t a_step, int m, int n, int k, fptype* b, size_t b_ste if (k == 1 && b_step == sizeof(fptype)) { if (typeid(fptype) == typeid(float)) - OCV_LAPACK_FUNC(sgels)(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)b, &m, (float*)&work1, &lwork, info); + OCV_LAPACK_FUNC(sgels)(mode, &_m, &_n, &_k, (float*)tmpA, &ldtmpA, (float*)b, &_m, (float*)&work1, &lwork, _info); else if (typeid(fptype) == typeid(double)) - OCV_LAPACK_FUNC(dgels)(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)b, &m, (double*)&work1, &lwork, info); + OCV_LAPACK_FUNC(dgels)(mode, &_m, &_n, &_k, (double*)tmpA, &ldtmpA, (double*)b, &_m, (double*)&work1, &lwork, _info); lwork = cvRound(work1); //optimal buffer size std::vector workBufMemHolder(lwork + 1); fptype* buffer = &workBufMemHolder.front(); if (typeid(fptype) == typeid(float)) - OCV_LAPACK_FUNC(sgels)(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)b, &m, (float*)buffer, &lwork, info); + OCV_LAPACK_FUNC(sgels)(mode, &_m, &_n, &_k, (float*)tmpA, &ldtmpA, (float*)b, &_m, (float*)buffer, &lwork, _info); else if (typeid(fptype) == typeid(double)) - OCV_LAPACK_FUNC(dgels)(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)b, &m, (double*)buffer, &lwork, info); + OCV_LAPACK_FUNC(dgels)(mode, &_m, &_n, &_k, (double*)tmpA, &ldtmpA, (double*)b, &_m, (double*)buffer, &lwork, _info); } else { @@ -335,18 +384,18 @@ lapack_QR(fptype* a, size_t a_step, int m, int n, int k, fptype* b, size_t b_ste transpose(b, ldb, tmpB, m, m, k); if (typeid(fptype) == typeid(float)) - OCV_LAPACK_FUNC(sgels)(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)tmpB, &m, (float*)&work1, &lwork, info); + OCV_LAPACK_FUNC(sgels)(mode, &_m, &_n, &_k, (float*)tmpA, &ldtmpA, (float*)tmpB, &_m, (float*)&work1, &lwork, _info); else if (typeid(fptype) == typeid(double)) - OCV_LAPACK_FUNC(dgels)(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)tmpB, &m, (double*)&work1, &lwork, info); + OCV_LAPACK_FUNC(dgels)(mode, &_m, &_n, &_k, (double*)tmpA, &ldtmpA, (double*)tmpB, &_m, (double*)&work1, &lwork, _info); lwork = cvRound(work1); //optimal buffer size std::vector workBufMemHolder(lwork + 1); fptype* buffer = &workBufMemHolder.front(); if (typeid(fptype) == typeid(float)) - OCV_LAPACK_FUNC(sgels)(mode, &m, &n, &k, (float*)tmpA, &ldtmpA, (float*)tmpB, &m, (float*)buffer, &lwork, info); + OCV_LAPACK_FUNC(sgels)(mode, &_m, &_n, &_k, (float*)tmpA, &ldtmpA, (float*)tmpB, &_m, (float*)buffer, &lwork, _info); else if (typeid(fptype) == typeid(double)) - OCV_LAPACK_FUNC(dgels)(mode, &m, &n, &k, (double*)tmpA, &ldtmpA, (double*)tmpB, &m, (double*)buffer, &lwork, info); + OCV_LAPACK_FUNC(dgels)(mode, &_m, &_n, &_k, (double*)tmpA, &ldtmpA, (double*)tmpB, &_m, (double*)buffer, &lwork, _info); transpose(tmpB, m, b, ldb, k, m); } @@ -354,18 +403,18 @@ lapack_QR(fptype* a, size_t a_step, int m, int n, int k, fptype* b, size_t b_ste else { if (typeid(fptype) == typeid(float)) - sgeqrf_(&m, &n, (float*)tmpA, &ldtmpA, (float*)dst, (float*)&work1, &lwork, info); + sgeqrf_(&_m, &_n, (float*)tmpA, &ldtmpA, (float*)dst, (float*)&work1, &lwork, _info); else if (typeid(fptype) == typeid(double)) - dgeqrf_(&m, &n, (double*)tmpA, &ldtmpA, (double*)dst, (double*)&work1, &lwork, info); + dgeqrf_(&_m, &_n, (double*)tmpA, &ldtmpA, (double*)dst, (double*)&work1, &lwork, _info); lwork = cvRound(work1); //optimal buffer size std::vector workBufMemHolder(lwork + 1); fptype* buffer = &workBufMemHolder.front(); if (typeid(fptype) == typeid(float)) - sgeqrf_(&m, &n, (float*)tmpA, &ldtmpA, (float*)dst, (float*)buffer, &lwork, info); + sgeqrf_(&_m, &_n, (float*)tmpA, &ldtmpA, (float*)dst, (float*)buffer, &lwork, _info); else if (typeid(fptype) == typeid(double)) - dgeqrf_(&m, &n, (double*)tmpA, &ldtmpA, (double*)dst, (double*)buffer, &lwork, info); + dgeqrf_(&_m, &_n, (double*)tmpA, &ldtmpA, (double*)dst, (double*)buffer, &lwork, _info); } CV_ANNOTATE_MEMORY_IS_INITIALIZED(info, sizeof(int)); @@ -374,6 +423,10 @@ lapack_QR(fptype* a, size_t a_step, int m, int n, int k, fptype* b, size_t b_ste else transpose(tmpA, m, a, lda, n, m); +#if defined (ACCELERATE_NEW_LAPACK) && defined (ACCELERATE_LAPACK_ILP64) + *info = static_cast(_info[0]); +#endif + if (*info != 0) *info = 0; else @@ -458,7 +511,6 @@ lapack_gemm(const fptype *src1, size_t src1_step, const fptype *src2, size_t src return CV_HAL_ERROR_OK; } - template static inline int lapack_gemm_c(const fptype *src1, size_t src1_step, const fptype *src2, size_t src2_step, fptype alpha, const fptype *src3, size_t src3_step, fptype beta, fptype *dst, size_t dst_step, int a_m, int a_n, int d_n, int flags) @@ -529,10 +581,29 @@ lapack_gemm_c(const fptype *src1, size_t src1_step, const fptype *src2, size_t s else if(src3_step == 0 && beta != 0.0) set_value((std::complex*)dst, lddst, std::complex(0.0, 0.0), d_m, d_n); + // FIXME: this is a workaround. Support ILP64 in HAL API. +#if defined (ACCELERATE_NEW_LAPACK) && defined (ACCELERATE_LAPACK_ILP64) + int M = a_m, N = d_n, K = a_n; + if(typeid(fptype) == typeid(float)) { + auto src1_cast = (std::complex*)(src1); + auto src2_cast = (std::complex*)(src2); + auto dst_cast = (std::complex*)(dst); + long lda = ldsrc1, ldb = ldsrc2, ldc = lddst; + cblas_cgemm(CblasRowMajor, transA, transB, M, N, K, (std::complex*)&cAlpha, src1_cast, lda, src2_cast, ldb, (std::complex*)&cBeta, dst_cast, ldc); + } + else if(typeid(fptype) == typeid(double)) { + auto src1_cast = (std::complex*)(src1); + auto src2_cast = (std::complex*)(src2); + auto dst_cast = (std::complex*)(dst); + long lda = ldsrc1, ldb = ldsrc2, ldc = lddst; + cblas_zgemm(CblasRowMajor, transA, transB, M, N, K, (std::complex*)&cAlpha, src1_cast, lda, src2_cast, ldb, (std::complex*)&cBeta, dst_cast, ldc); + } +#else if(typeid(fptype) == typeid(float)) cblas_cgemm(CblasRowMajor, transA, transB, a_m, d_n, a_n, (float*)reinterpret_cast(cAlpha), (float*)src1, ldsrc1, (float*)src2, ldsrc2, (float*)reinterpret_cast(cBeta), (float*)dst, lddst); else if(typeid(fptype) == typeid(double)) cblas_zgemm(CblasRowMajor, transA, transB, a_m, d_n, a_n, (double*)reinterpret_cast(cAlpha), (double*)src1, ldsrc1, (double*)src2, ldsrc2, (double*)reinterpret_cast(cBeta), (double*)dst, lddst); +#endif return CV_HAL_ERROR_OK; } From 5696413bbc4594da7df758df8af82ed78ac9326f Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 22 May 2024 08:53:39 +0000 Subject: [PATCH 069/119] ffmpeg/4.x: update FFmpeg wrapper 2024.05 --- 3rdparty/ffmpeg/ffmpeg.cmake | 10 +++++----- modules/videoio/test/test_ffmpeg.cpp | 4 +--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/3rdparty/ffmpeg/ffmpeg.cmake b/3rdparty/ffmpeg/ffmpeg.cmake index fa6299751ce1..f55882e59f14 100644 --- a/3rdparty/ffmpeg/ffmpeg.cmake +++ b/3rdparty/ffmpeg/ffmpeg.cmake @@ -1,8 +1,8 @@ -# Binaries branch name: ffmpeg/4.x_20231225 -# Binaries were created for OpenCV: 62f1a7410d5e5e03d6cee5c95549bf61d5ee98db -ocv_update(FFMPEG_BINARIES_COMMIT "fbac408a47977ee4265f39e7659d33f1dfef5216") -ocv_update(FFMPEG_FILE_HASH_BIN32 "9b755ecbbade0a5b78332e9b4ef2dd1b") -ocv_update(FFMPEG_FILE_HASH_BIN64 "cb4db51ee9a423e6168b9d08bee61efc") +# Binaries branch name: ffmpeg/4.x_20240522 +# Binaries were created for OpenCV: 8393885a39dac1e650bf5d0aaff84c04ad8bcdd3 +ocv_update(FFMPEG_BINARIES_COMMIT "394dca6ceb3085c979415e6385996b6570e94153") +ocv_update(FFMPEG_FILE_HASH_BIN32 "bdfbd1efb295f3e54c07d2cb7a843bf9") +ocv_update(FFMPEG_FILE_HASH_BIN64 "bfef029900f788480a363d6dc05c4f0e") ocv_update(FFMPEG_FILE_HASH_CMAKE "8862c87496e2e8c375965e1277dee1c7") function(download_win_ffmpeg script_var) diff --git a/modules/videoio/test/test_ffmpeg.cpp b/modules/videoio/test/test_ffmpeg.cpp index 88f0c8f4bd9a..f4920e75c2f4 100644 --- a/modules/videoio/test/test_ffmpeg.cpp +++ b/modules/videoio/test/test_ffmpeg.cpp @@ -266,8 +266,7 @@ TEST_P(videoio_container_get, read) ASSERT_EQ(bitrate, bitrateProp); const double fpsProp = container.get(CAP_PROP_FPS); ASSERT_EQ(fps, fpsProp); - // remove when PR fixing raw video CAP_PROP_POS_MSEC return value is merged and windows dll is updated -#ifndef _WIN32 + vector displayTimeMs; int iFrame = 1; while (container.grab()) { @@ -283,7 +282,6 @@ TEST_P(videoio_container_get, read) const int frameTimeMs = static_cast(1000.0 / fps); ASSERT_NEAR(frameTimeMs, *minTimeMsIt, 1); ASSERT_NEAR(frameTimeMs, *maxTimeMsIt, 1); -#endif } const videoio_container_get_params_t videoio_container_get_params[] = From 28d029c15863ada0d0db3d41b64c00e9887399ab Mon Sep 17 00:00:00 2001 From: lackhole Date: Wed, 22 May 2024 20:01:54 +0900 Subject: [PATCH 070/119] Replace non-ascii character --- modules/core/include/opencv2/core.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index f6372ac03e55..b58a3a6ccbbe 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -1807,7 +1807,7 @@ CV_EXPORTS_W void transpose(InputArray src, OutputArray dst); * @note Input should be continuous single-channel matrix. * @param src input array. * @param order a permutation of [0,1,..,N-1] where N is the number of axes of src. - * The i’th axis of dst will correspond to the axis numbered order[i] of the input. + * The i'th axis of dst will correspond to the axis numbered order[i] of the input. * @param dst output array of the same type as src. */ CV_EXPORTS_W void transposeND(InputArray src, const std::vector& order, OutputArray dst); From e765c9f9c84437b0d3d3457e7b7f4aa358b7e0c1 Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Wed, 22 May 2024 15:45:10 +0300 Subject: [PATCH 071/119] Merge pull request #25580 from sturkmen72:libpng_1_6_43 3rdparty: update libpng 1.6.43 #25580 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- 3rdparty/libpng/CHANGES | 117 +++- 3rdparty/libpng/CMakeLists.txt | 202 ++++++- 3rdparty/libpng/LICENSE | 4 +- 3rdparty/libpng/README | 305 +++++----- 3rdparty/libpng/arm/arm_init.c | 31 +- 3rdparty/libpng/arm/filter_neon_intrinsics.c | 2 +- 3rdparty/libpng/arm/palette_neon_intrinsics.c | 14 +- .../libpng/intel/filter_sse2_intrinsics.c | 2 +- .../libpng/loongarch/filter_lsx_intrinsics.c | 412 ++++++++++++++ .../libpng/loongarch/loongarch_lsx_init.c | 65 +++ .../libpng/mips/filter_mmi_inline_assembly.c | 525 ++++++++++++++++++ 3rdparty/libpng/mips/filter_msa_intrinsics.c | 14 +- 3rdparty/libpng/mips/mips_init.c | 99 +++- .../20190528-fix-leak-png_handle_exif.diff | 17 - .../libpng/patches/20190910-msa-patch.diff | 53 -- 3rdparty/libpng/png.c | 114 ++-- 3rdparty/libpng/png.h | 65 +-- 3rdparty/libpng/pngconf.h | 8 +- 3rdparty/libpng/pngerror.c | 34 +- 3rdparty/libpng/pngget.c | 268 ++++----- 3rdparty/libpng/pngpread.c | 16 +- 3rdparty/libpng/pngpriv.h | 187 +++++-- 3rdparty/libpng/pngread.c | 19 +- 3rdparty/libpng/pngrtran.c | 36 +- 3rdparty/libpng/pngrutil.c | 49 +- 3rdparty/libpng/pngset.c | 89 +-- 3rdparty/libpng/pngstruct.h | 12 +- 3rdparty/libpng/pngtrans.c | 14 +- 3rdparty/libpng/pngwrite.c | 45 +- 3rdparty/libpng/pngwutil.c | 14 +- CMakeLists.txt | 24 + 31 files changed, 2097 insertions(+), 759 deletions(-) create mode 100644 3rdparty/libpng/loongarch/filter_lsx_intrinsics.c create mode 100644 3rdparty/libpng/loongarch/loongarch_lsx_init.c create mode 100644 3rdparty/libpng/mips/filter_mmi_inline_assembly.c delete mode 100644 3rdparty/libpng/patches/20190528-fix-leak-png_handle_exif.diff delete mode 100644 3rdparty/libpng/patches/20190910-msa-patch.diff diff --git a/3rdparty/libpng/CHANGES b/3rdparty/libpng/CHANGES index f0b0a9342c3d..441b57ecf1ab 100644 --- a/3rdparty/libpng/CHANGES +++ b/3rdparty/libpng/CHANGES @@ -204,7 +204,7 @@ Version 0.97 [January, 1998] Added simple sRGB support (Glenn R-P) Easier conditional compiling, e.g., define PNG_READ/WRITE_NOT_FULLY_SUPPORTED; - all configurable options can be selected from command-line instead + all configurable options can be selected from command line instead of having to edit pngconf.h (Glenn R-P) Fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P) Added more conditions for png_do_background, to avoid changing @@ -942,7 +942,7 @@ Version 1.0.8 [July 24, 2000] Version 1.0.9beta1 [November 10, 2000] Fixed typo in scripts/makefile.hpux Updated makevms.com in scripts and contrib/* and contrib/* (Martin Zinser) - Fixed seqence-point bug in contrib/pngminus/png2pnm (Martin Zinser) + Fixed sequence-point bug in contrib/pngminus/png2pnm (Martin Zinser) Changed "cdrom.com" in documentation to "libpng.org" Revised pnggccrd.c to get it all working, and updated makefile.gcmmx (Greg). Changed type of "params" from voidp to png_voidp in png_read|write_png(). @@ -2295,7 +2295,7 @@ Version 1.4.0beta58 [May 14, 2009] Clarified usage of sig_bit versus sig_bit_p in example.c (Vincent Torri) Version 1.4.0beta59 [May 15, 2009] - Reformated sources in libpng style (3-space intentation, comment format) + Reformatted sources in libpng style (3-space indentation, comment format) Fixed typo in libpng docs (PNG_FILTER_AVE should be PNG_FILTER_AVG) Added sections about the git repository and our coding style to the documentation @@ -2661,7 +2661,7 @@ Version 1.4.1beta06 [January 28, 2010] Version 1.4.1beta07 [February 6, 2010] Folded some long lines in the source files. - Added defineable PNG_USER_CHUNK_CACHE_MAX, PNG_USER_CHUNK_MALLOC_MAX, + Added definable PNG_USER_CHUNK_CACHE_MAX, PNG_USER_CHUNK_MALLOC_MAX, and a PNG_USER_LIMITS_SUPPORTED flag. Eliminated use of png_ptr->irowbytes and reused the slot in png_ptr as png_ptr->png_user_chunk_malloc_max. @@ -3886,7 +3886,7 @@ Version 1.6.0beta06 [January 24, 2012] Version 1.6.0beta07 [January 28, 2012] Eliminated Intel icc/icl compiler warnings. The Intel (GCC derived) compiler issues slightly different warnings from those issued by the - current vesions of GCC. This eliminates those warnings by + current versions of GCC. This eliminates those warnings by adding/removing casts and small code rewrites. Updated configure.ac from autoupdate: added --enable-werror option. Also some layout regularization and removal of introduced tab characters @@ -3919,7 +3919,7 @@ Version 1.6.0beta08 [February 1, 2012] version checking to configure.ac Improved pngstest speed by not doing redundant tests and add const to the background parameter of png_image_finish_read. The --background - option is now done automagically only when required, so that commandline + option is now done automagically only when required, so that command-line option no longer exists. Cleaned up pngpriv.h to consistently declare all functions and data. Also eliminated PNG_CONST_DATA, which is apparently not needed but we @@ -4052,7 +4052,7 @@ Version 1.6.0beta16 [March 6, 2012] (in fact this is harmless, but the PNG data produced may be sub-optimal). Version 1.6.0beta17 [March 10, 2012] - Fixed PNG_LIBPNG_BUILD_BASE_TYPE definition. + Fixed PNG_LIBPNG_BUILD_BASE_TYPE definition. Reject all iCCP chunks after the first, even if the first one is invalid. Deflate/inflate was reworked to move common zlib calls into single functions [rw]util.c. A new shared keyword check routine was also added @@ -4962,7 +4962,7 @@ Version 1.6.13beta01 [July 4, 2014] Changed "if defined(__ARM_NEON__)" to "if (defined(__ARM_NEON__) || defined(__ARM_NEON))" (James Wu). Fixed clang no-warning builds: png_digit was defined but never used. - + Version 1.6.13beta02 [July 21, 2014] Fixed an incorrect separator ("/" should be "\") in scripts/makefile.vcwin32 (bug report from Wolfgang S. Kechel). Bug was introduced in libpng-1.6.11. @@ -5453,7 +5453,7 @@ Version 1.6.21beta01 [December 11, 2015] Version 1.6.21beta02 [December 14, 2015] Moved png_check_keyword() from pngwutil.c to pngset.c Removed LE/BE dependencies in pngvalid, to 'fix' the current problem - in the BigEndian tests by not testing it, making the BE code the same + in the BigEndian tests by not testing it, making the BE code the same as the LE version. Fixes to pngvalid for various reduced build configurations (eliminate unused statics) and a fix for the case in rgb_to_gray when the digitize option @@ -5517,7 +5517,7 @@ Version 1.6.22beta03 [March 9, 2016] Added a common-law trademark notice and export control information to the LICENSE file, png.h, and the man page. Restored "& 0xff" in png_save_uint_16() and png_save_uint_32() that - were accidentally removed from libpng-1.6.17. + were accidentally removed from libpng-1.6.17. Changed PNG_INFO_cHNK and PNG_FREE_cHNK from 0xnnnn to 0xnnnnU in png.h (Robert C. Seacord). Removed dubious "#if INT_MAX" test from png.h that was added to @@ -5927,7 +5927,7 @@ Version 1.6.32beta03 [August 2, 2017] (Bug report from the OSS-fuzz project). Version 1.6.32beta04 [August 2, 2017] - Replaced local eXIf_buf with info_ptr-eXIf_buf in png_handle_eXIf(). + Replaced local eXIf_buf with info_ptr->eXIf_buf in png_handle_eXIf(). Update libpng.3 and libpng-manual.txt about eXIf functions. Version 1.6.32beta05 [August 2, 2017] @@ -5950,7 +5950,7 @@ Version 1.6.32beta09 [August 3, 2017] Require cmake-2.8.8 in CMakeLists.txt. Revised symlink creation, no longer using deprecated cmake LOCATION feature (Clifford Yapp). Fixed five-byte error in the calculation of IDAT maximum possible size. - + Version 1.6.32beta10 [August 5, 2017] Moved chunk-length check into a png_check_chunk_length() private function (Suggested by Max Stepin). @@ -6103,6 +6103,99 @@ Version 1.6.37 [April 14, 2019] Added makefiles for AddressSanitizer-enabled builds. Cleaned up various makefiles. +Version 1.6.38 [September 14, 2022] + Added configurations and scripts for continuous integration. + Fixed various errors in the handling of tRNS, hIST and eXIf. + Implemented many stability improvements across all platforms. + Updated the internal documentation. + +Version 1.6.39 [November 20, 2022] + Changed the error handler of oversized chunks (i.e. larger than + PNG_USER_CHUNK_MALLOC_MAX) from png_chunk_error to png_benign_error. + Fixed a buffer overflow error in contrib/tools/pngfix. + Fixed a memory leak (CVE-2019-6129) in contrib/tools/pngcp. + Disabled the ARM Neon optimizations by default in the CMake file, + following the default behavior of the configure script. + Allowed configure.ac to work with the trunk version of autoconf. + Removed the support for "install" targets from the legacy makefiles; + removed the obsolete makefile.cegcc. + Cleaned up the code and updated the internal documentation. + +Version 1.6.40 [June 21, 2023] + Fixed the eXIf chunk multiplicity checks. + Fixed a memory leak in pCAL processing. + Corrected the validity report about tRNS inside png_get_valid(). + Fixed various build issues on *BSD, Mac and Windows. + Updated the configurations and the scripts for continuous integration. + Cleaned up the code, the build scripts, and the documentation. + +Version 1.6.41 [January 24, 2024] + Added SIMD-optimized code for the LoongArch LSX hardware. + (Contributed by GuXiWei, JinBo and ZhangLixia) + Fixed the run-time discovery of MIPS MSA hardware. + (Contributed by Sui Jingfeng) + Fixed an off-by-one error in the function png_do_check_palette_indexes(), + which failed to recognize errors that might have existed in the first + column of a broken palette-encoded image. This was a benign regression + accidentally introduced in libpng-1.6.33. No pixel was harmed. + (Contributed by Adam Richter; reviewed by John Bowler) + Fixed, improved and modernized the contrib/pngminus programs, i.e., + png2pnm.c and pnm2png.c + Removed old and peculiar portability hacks that were meant to silence + warnings issued by gcc version 7.1 alone. + (Contributed by John Bowler) + Fixed and modernized the CMake file, and raised the minimum required + CMake version from 3.1 to 3.6. + (Contributed by Clinton Ingram, Timothy Lyanguzov, Tyler Kropp, et al.) + Allowed the configure script to disable the building of auxiliary tools + and tests, thus catching up with the CMake file. + (Contributed by Carlo Bramini) + Fixed a build issue on Mac. + (Contributed by Zixu Wang) + Moved the Autoconf macro files to scripts/autoconf. + Moved the CMake files (except for the main CMakeLists.txt) to + scripts/cmake and moved the list of their contributing authors to + scripts/cmake/AUTHORS.md + Updated the CI configurations and scripts. + Relicensed the CI scripts to the MIT License. + Improved the test coverage. + (Contributed by John Bowler) + +Version 1.6.42 [January 29, 2024] + Fixed the implementation of the macro function png_check_sig(). + This was an API regression, introduced in libpng-1.6.41. + (Reported by Matthieu Darbois) + Fixed and updated the libpng manual. + +Version 1.6.43 [February 23, 2024] + Fixed the row width check in png_check_IHDR(). + This corrected a bug that was specific to the 16-bit platforms, + and removed a spurious compiler warning from the 64-bit builds. + (Reported by Jacek Caban; fixed by John Bowler) + Added eXIf chunk support to the push-mode reader in pngpread.c. + (Contributed by Chris Blume) + Added contrib/pngexif for the benefit of the users who would like + to inspect the content of eXIf chunks. + Added contrib/conftest/basic.dfa, a basic build-time configuration. + (Contributed by John Bowler) + Fixed a preprocessor condition in pngread.c that broke build-time + configurations like contrib/conftest/pngcp.dfa. + (Contributed by John Bowler) + Added CMake build support for LoongArch LSX. + (Contributed by GuXiWei) + Fixed a CMake build error that occurred under a peculiar state of the + dependency tree. This was a regression introduced in libpng-1.6.41. + (Contributed by Dan Rosser) + Marked the installed libpng headers as system headers in CMake. + (Contributed by Benjamin Buch) + Updated the build support for RISCOS. + (Contributed by Cameron Cawley) + Updated the makefiles to allow cross-platform builds to initialize + conventional make variables like AR and ARFLAGS. + Added various improvements to the CI scripts in areas like version + consistency verification and text linting. + Added version consistency verification to pngtest.c also. + Send comments/corrections/commendations to png-mng-implement at lists.sf.net. Subscription is required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement diff --git a/3rdparty/libpng/CMakeLists.txt b/3rdparty/libpng/CMakeLists.txt index 973f39cafafa..a7701c9fed7a 100644 --- a/3rdparty/libpng/CMakeLists.txt +++ b/3rdparty/libpng/CMakeLists.txt @@ -9,17 +9,15 @@ else() project(${PNG_LIBRARY} C) endif() -if(NOT WIN32) - find_library(M_LIBRARY - NAMES m - PATHS /usr/lib /usr/local/lib - ) - if(NOT M_LIBRARY) - message(STATUS "math lib 'libm' not found; floating point support disabled") +if(UNIX AND NOT APPLE AND NOT BEOS AND NOT HAIKU AND NOT EMSCRIPTEN) + find_library(M_LIBRARY m) + if(M_LIBRARY) + set(M_LIBRARY m) + else() + set(M_LIBRARY "") endif() else() - # not needed on windows - set(M_LIBRARY "") + # libm is not available or not needed. endif() ocv_include_directories("${CMAKE_CURRENT_SOURCE_DIR}" ${ZLIB_INCLUDE_DIRS}) @@ -27,45 +25,191 @@ ocv_include_directories("${CMAKE_CURRENT_SOURCE_DIR}" ${ZLIB_INCLUDE_DIRS}) file(GLOB lib_srcs *.c) file(GLOB lib_hdrs *.h) +# CMake currently sets CMAKE_SYSTEM_PROCESSOR to one of x86_64 or arm64 on macOS, +# based upon the OS architecture, not the target architecture. As such, we need +# to check CMAKE_OSX_ARCHITECTURES to identify which hardware-specific flags to +# enable. Note that this will fail if you attempt to build a universal binary in +# a single CMake invocation. +if(APPLE AND CMAKE_OSX_ARCHITECTURES) + set(TARGET_ARCH ${CMAKE_OSX_ARCHITECTURES}) +else() + set(TARGET_ARCH ${CMAKE_SYSTEM_PROCESSOR}) +endif() + +OCV_OPTION(PNG_HARDWARE_OPTIMIZATIONS "Enable Hardware Optimizations, if available for this platform" (NOT CV_DISABLE_OPTIMIZATION)) + +if(PNG_HARDWARE_OPTIMIZATIONS) -if(ARM OR AARCH64) - if(ENABLE_NEON) - if(NOT AARCH64) +# Set definitions and sources for ARM. +if(TARGET_ARCH MATCHES "^(ARM|arm|aarch)") + if(TARGET_ARCH MATCHES "^(ARM64|arm64|aarch64)") + set(PNG_ARM_NEON_POSSIBLE_VALUES on off) + set(PNG_ARM_NEON "on" + CACHE STRING "Enable ARM NEON optimizations: on|off; on is default") + else() + set(PNG_ARM_NEON_POSSIBLE_VALUES check on off) + set(PNG_ARM_NEON "off" + CACHE STRING "Enable ARM NEON optimizations: check|on|off; off is default") + endif() + set_property(CACHE PNG_ARM_NEON + PROPERTY STRINGS ${PNG_ARM_NEON_POSSIBLE_VALUES}) + list(FIND PNG_ARM_NEON_POSSIBLE_VALUES ${PNG_ARM_NEON} index) + if(index EQUAL -1) + message(FATAL_ERROR "PNG_ARM_NEON must be one of [${PNG_ARM_NEON_POSSIBLE_VALUES}]") + elseif(NOT PNG_ARM_NEON STREQUAL "off") + list(APPEND lib_srcs arm/arm_init.c arm/filter_neon_intrinsics.c arm/palette_neon_intrinsics.c) + if(NOT MSVC) list(APPEND lib_srcs arm/filter_neon.S) endif() - list(APPEND lib_srcs arm/arm_init.c arm/filter_neon_intrinsics.c arm/palette_neon_intrinsics.c) - add_definitions(-DPNG_ARM_NEON_OPT=2) + if(PNG_ARM_NEON STREQUAL "on") + add_definitions(-DPNG_ARM_NEON_OPT=2) + elseif(PNG_ARM_NEON STREQUAL "check") + add_definitions(-DPNG_ARM_NEON_CHECK_SUPPORTED) + endif() else() add_definitions(-DPNG_ARM_NEON_OPT=0) # NEON assembler is not supported endif() endif() -if(";${CPU_BASELINE_FINAL};" MATCHES "SSE2" - AND (NOT MSVC OR (MSVC_VERSION GREATER 1799))) # MSVS2013+ (issue #7232) - list(APPEND lib_srcs intel/intel_init.c intel/filter_sse2_intrinsics.c) - add_definitions(-DPNG_INTEL_SSE) +# Set definitions and sources for PowerPC. +if(TARGET_ARCH MATCHES "^(powerpc|ppc64)") + set(PNG_POWERPC_VSX_POSSIBLE_VALUES on off) + set(PNG_POWERPC_VSX "on" + CACHE STRING "Enable POWERPC VSX optimizations: on|off; on is default") + set_property(CACHE PNG_POWERPC_VSX + PROPERTY STRINGS ${PNG_POWERPC_VSX_POSSIBLE_VALUES}) + list(FIND PNG_POWERPC_VSX_POSSIBLE_VALUES ${PNG_POWERPC_VSX} index) + if(index EQUAL -1) + message(FATAL_ERROR "PNG_POWERPC_VSX must be one of [${PNG_POWERPC_VSX_POSSIBLE_VALUES}]") + elseif(NOT PNG_POWERPC_VSX STREQUAL "off") + list(APPEND lib_srcs powerpc/powerpc_init.c powerpc/filter_vsx_intrinsics.c) + if(PNG_POWERPC_VSX STREQUAL "on") + add_definitions(-DPNG_POWERPC_VSX_OPT=2) + endif() + else() + add_definitions(-DPNG_POWERPC_VSX_OPT=0) + endif() endif() -# set definitions and sources for MIPS -if(";${CPU_BASELINE_FINAL};" MATCHES "MSA") +# Set definitions and sources for Intel. +if(TARGET_ARCH MATCHES "^(i[3-6]86|x86|AMD64)") + set(PNG_INTEL_SSE_POSSIBLE_VALUES on off) + set(PNG_INTEL_SSE "on" + CACHE STRING "Enable INTEL_SSE optimizations: on|off; on is default") + set_property(CACHE PNG_INTEL_SSE + PROPERTY STRINGS ${PNG_INTEL_SSE_POSSIBLE_VALUES}) + list(FIND PNG_INTEL_SSE_POSSIBLE_VALUES ${PNG_INTEL_SSE} index) + if(index EQUAL -1) + message(FATAL_ERROR "PNG_INTEL_SSE must be one of [${PNG_INTEL_SSE_POSSIBLE_VALUES}]") + elseif(NOT PNG_INTEL_SSE STREQUAL "off") + list(APPEND lib_srcs intel/intel_init.c intel/filter_sse2_intrinsics.c) + if(PNG_INTEL_SSE STREQUAL "on") + add_definitions(-DPNG_INTEL_SSE_OPT=1) + endif() + else() + add_definitions(-DPNG_INTEL_SSE_OPT=0) + endif() +endif() + +# Set definitions and sources for MIPS. +if(TARGET_ARCH MATCHES "^(mipsel|mips64el)") + set(PNG_MIPS_MSA_POSSIBLE_VALUES on off) + set(PNG_MIPS_MSA "on" + CACHE STRING "Enable MIPS_MSA optimizations: on|off; on is default") + set_property(CACHE PNG_MIPS_MSA + PROPERTY STRINGS ${PNG_MIPS_MSA_POSSIBLE_VALUES}) + list(FIND PNG_MIPS_MSA_POSSIBLE_VALUES ${PNG_MIPS_MSA} index_msa) + if(index_msa EQUAL -1) + message(FATAL_ERROR "PNG_MIPS_MSA must be one of [${PNG_MIPS_MSA_POSSIBLE_VALUES}]") + endif() + + set(PNG_MIPS_MMI_POSSIBLE_VALUES on off) + set(PNG_MIPS_MMI "on" + CACHE STRING "Enable MIPS_MMI optimizations: on|off; on is default") + set_property(CACHE PNG_MIPS_MMI + PROPERTY STRINGS ${PNG_MIPS_MMI_POSSIBLE_VALUES}) + list(FIND PNG_MIPS_MMI_POSSIBLE_VALUES ${PNG_MIPS_MMI} index_mmi) + if(index_mmi EQUAL -1) + message(FATAL_ERROR "PNG_MIPS_MMI must be one of [${PNG_MIPS_MMI_POSSIBLE_VALUES}]") + endif() + + if(PNG_MIPS_MSA STREQUAL "on" AND PNG_MIPS_MMI STREQUAL "on") + list(APPEND lib_srcs mips/mips_init.c mips/filter_msa_intrinsics.c mips/filter_mmi_inline_assembly.c) + add_definitions(-DPNG_MIPS_MSA_OPT=2) + add_definitions(-DPNG_MIPS_MMI_OPT=1) + elseif(PNG_MIPS_MSA STREQUAL "on") list(APPEND lib_srcs mips/mips_init.c mips/filter_msa_intrinsics.c) add_definitions(-DPNG_MIPS_MSA_OPT=2) - ocv_warnings_disable(CMAKE_C_FLAGS -Wshadow) -else() + add_definitions(-DPNG_MIPS_MMI_OPT=0) + elseif(PNG_MIPS_MMI STREQUAL "on") + list(APPEND lib_srcs mips/mips_init.c mips/filter_mmi_inline_assembly.c) + add_definitions(-DPNG_MIPS_MSA_OPT=0) + add_definitions(-DPNG_MIPS_MMI_OPT=1) + else() add_definitions(-DPNG_MIPS_MSA_OPT=0) + add_definitions(-DPNG_MIPS_MMI_OPT=0) + endif() endif() -if(PPC64LE OR PPC64) - # VSX3 features are backwards compatible - if(";${CPU_BASELINE_FINAL};" MATCHES "VSX.*" - AND NOT PPC64) - list(APPEND lib_srcs powerpc/powerpc_init.c powerpc/filter_vsx_intrinsics.c) - add_definitions(-DPNG_POWERPC_VSX_OPT=2) +# Set definitions and sources for LoongArch. +if(TARGET_ARCH MATCHES "^(loongarch)") + include(CheckCCompilerFlag) + set(PNG_LOONGARCH_LSX_POSSIBLE_VALUES on off) + set(PNG_LOONGARCH_LSX "on" + CACHE STRING "Enable LOONGARCH_LSX optimizations: on|off; on is default") + set_property(CACHE PNG_LOONGARCH_LSX + PROPERTY STRINGS ${PNG_LOONGARCH_LSX_POSSIBLE_VALUES}) + list(FIND PNG_LOONGARCH_LSX_POSSIBLE_VALUES ${PNG_LOONGARCH_LSX} index) + if(index EQUAL -1) + message(FATAL_ERROR "PNG_LOONGARCH_LSX must be one of [${PNG_LOONGARCH_LSX_POSSIBLE_VALUES}]") + elseif(NOT PNG_LOONGARCH_LSX STREQUAL "off") + CHECK_C_COMPILER_FLAG("-mlsx" COMPILER_SUPPORTS_LSX) + if(COMPILER_SUPPORTS_LSX) + set(libpng_loongarch_sources + loongarch/loongarch_lsx_init.c + loongarch/filter_lsx_intrinsics.c) + set_source_files_properties(${libpng_loongarch_sources} + PROPERTIES + COMPILE_FLAGS "-mlsx") + list(APPEND lib_srcs ${libpng_loongarch_sources}) + add_definitions(-DPNG_LOONGARCH_LSX_OPT=1) + else() + message(FATAL_ERROR "Compiler does not support -mlsx option") + endif() else() - add_definitions(-DPNG_POWERPC_VSX_OPT=0) + add_definitions(-DPNG_LOONGARCH_LSX_OPT=0) endif() endif() +else(PNG_HARDWARE_OPTIMIZATIONS) + +# Set definitions and sources for ARM. +if(TARGET_ARCH MATCHES "^(ARM|arm|aarch)") + add_definitions(-DPNG_ARM_NEON_OPT=0) +endif() + +# Set definitions and sources for PowerPC. +if(TARGET_ARCH MATCHES "^(powerpc|ppc64)") + add_definitions(-DPNG_POWERPC_VSX_OPT=0) +endif() + +# Set definitions and sources for Intel. +if(TARGET_ARCH MATCHES "^(i[3-6]86|x86|AMD64)") + add_definitions(-DPNG_INTEL_SSE_OPT=0) +endif() + +# Set definitions and sources for MIPS. +if(TARGET_ARCH MATCHES "^(mipsel|mips64el)") + add_definitions(-DPNG_MIPS_MSA_OPT=0) +endif() + +# Set definitions and sources for LoongArch. +if(TARGET_ARCH MATCHES "^(loongarch)") + add_definitions(-DPNG_LOONGARCH_LSX_OPT=0) +endif() + +endif(PNG_HARDWARE_OPTIMIZATIONS) + # ---------------------------------------------------------------------------------- # Define the library target: # ---------------------------------------------------------------------------------- diff --git a/3rdparty/libpng/LICENSE b/3rdparty/libpng/LICENSE index e0c5b531cf54..25f298f0fcfd 100644 --- a/3rdparty/libpng/LICENSE +++ b/3rdparty/libpng/LICENSE @@ -4,8 +4,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE PNG Reference Library License version 2 --------------------------------------- - * Copyright (c) 1995-2019 The PNG Reference Library Authors. - * Copyright (c) 2018-2019 Cosmin Truta. + * Copyright (c) 1995-2024 The PNG Reference Library Authors. + * Copyright (c) 2018-2024 Cosmin Truta. * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. * Copyright (c) 1996-1997 Andreas Dilger. * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. diff --git a/3rdparty/libpng/README b/3rdparty/libpng/README index cfc1f0e3dc97..a6ca3ae9f940 100644 --- a/3rdparty/libpng/README +++ b/3rdparty/libpng/README @@ -1,178 +1,179 @@ -README for libpng version 1.6.37 - April 14, 2019 -================================================= - -See the note about version numbers near the top of png.h. -See INSTALL for instructions on how to install libpng. - -Libpng comes in several distribution formats. Get libpng-*.tar.gz or -libpng-*.tar.xz or if you want UNIX-style line endings in the text -files, or lpng*.7z or lpng*.zip if you want DOS-style line endings. - -Version 0.89 was the first official release of libpng. Don't let the -fact that it's the first release fool you. The libpng library has been -in extensive use and testing since mid-1995. By late 1997 it had -finally gotten to the stage where there hadn't been significant -changes to the API in some time, and people have a bad feeling about -libraries with versions < 1.0. Version 1.0.0 was released in -March 1998. - -**** -Note that some of the changes to the png_info structure render this -version of the library binary incompatible with libpng-0.89 or -earlier versions if you are using a shared library. The type of the -"filler" parameter for png_set_filler() has changed from png_byte to -png_uint_32, which will affect shared-library applications that use -this function. +README for libpng version 1.6.43 +================================ -To avoid problems with changes to the internals of the png info_struct, -new APIs have been made available in 0.95 to avoid direct application -access to info_ptr. These functions are the png_set_ and -png_get_ functions. These functions should be used when -accessing/storing the info_struct data, rather than manipulating it -directly, to avoid such problems in the future. +See the note about version numbers near the top of `png.h`. +See `INSTALL` for instructions on how to install libpng. -It is important to note that the APIs did not make current programs -that access the info struct directly incompatible with the new -library, through libpng-1.2.x. In libpng-1.4.x, which was meant to -be a transitional release, members of the png_struct and the -info_struct can still be accessed, but the compiler will issue a -warning about deprecated usage. Since libpng-1.5.0, direct access -to these structs is not allowed, and the definitions of the structs -reside in private pngstruct.h and pnginfo.h header files that are not -accessible to applications. It is strongly suggested that new -programs use the new APIs (as shown in example.c and pngtest.c), and -older programs be converted to the new format, to facilitate upgrades -in the future. -**** - -Additions since 0.90 include the ability to compile libpng as a -Windows DLL, and new APIs for accessing data in the info struct. -Experimental functions include the ability to set weighting and cost -factors for row filter selection, direct reads of integers from buffers -on big-endian processors that support misaligned data access, faster -methods of doing alpha composition, and more accurate 16->8 bit color -conversion. +Libpng comes in several distribution formats. Get `libpng-*.tar.gz` +or `libpng-*.tar.xz` if you want UNIX-style line endings in the text +files, or `lpng*.7z` or `lpng*.zip` if you want DOS-style line endings. -The additions since 0.89 include the ability to read from a PNG stream -which has had some (or all) of the signature bytes read by the calling -application. This also allows the reading of embedded PNG streams that -do not have the PNG file signature. As well, it is now possible to set -the library action on the detection of chunk CRC errors. It is possible -to set different actions based on whether the CRC error occurred in a -critical or an ancillary chunk. +For a detailed description on using libpng, read `libpng-manual.txt`. +For examples of libpng in a program, see `example.c` and `pngtest.c`. +For usage information and restrictions (what little they are) on libpng, +see `png.h`. For a description on using zlib (the compression library +used by libpng) and zlib's restrictions, see `zlib.h`. -For a detailed description on using libpng, read libpng-manual.txt. -For examples of libpng in a program, see example.c and pngtest.c. For -usage information and restrictions (what little they are) on libpng, -see png.h. For a description on using zlib (the compression library -used by libpng) and zlib's restrictions, see zlib.h - -I have included a general makefile, as well as several machine and -compiler specific ones, but you may have to modify one for your own -needs. - -You should use zlib 1.0.4 or later to run this, but it MAY work with +You should use zlib 1.0.4 or later to run this, but it _may_ work with versions as old as zlib 0.95. Even so, there are bugs in older zlib versions which can cause the output of invalid compression streams for some images. You should also note that zlib is a compression library that is useful for more things than just PNG files. You can use zlib as a drop-in -replacement for fread() and fwrite(), if you are so inclined. +replacement for `fread()` and `fwrite()`, if you are so inclined. zlib should be available at the same place that libpng is, or at -https://zlib.net. +https://zlib.net . You may also want a copy of the PNG specification. It is available as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find these at http://www.libpng.org/pub/png/pngdocs.html . -This code is currently being archived at libpng.sourceforge.io in the -[DOWNLOAD] area, and at http://libpng.download/src . +This code is currently being archived at https://libpng.sourceforge.io +in the download area, and at http://libpng.download/src . This release, based in a large way on Glenn's, Guy's and Andreas' earlier work, was created and will be supported by myself and the PNG development group. -Send comments/corrections/commendations to png-mng-implement at -lists.sourceforge.net (subscription required; visit +Send comments, corrections and commendations to `png-mng-implement` +at `lists.sourceforge.net`. (Subscription is required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe). - -Send general questions about the PNG specification to png-mng-misc -at lists.sourceforge.net (subscription required; visit -https://lists.sourceforge.net/lists/listinfo/png-mng-misc to -subscribe). - -Files in this distribution: - - ANNOUNCE => Announcement of this version, with recent changes - AUTHORS => List of contributing authors - CHANGES => Description of changes between libpng versions - KNOWNBUG => List of known bugs and deficiencies - LICENSE => License to use and redistribute libpng - README => This file - TODO => Things not implemented in the current library - TRADEMARK => Trademark information - example.c => Example code for using libpng functions - libpng.3 => manual page for libpng (includes libpng-manual.txt) - libpng-manual.txt => Description of libpng and its functions - libpngpf.3 => manual page for libpng's private functions - png.5 => manual page for the PNG format - png.c => Basic interface functions common to library - png.h => Library function and interface declarations (public) - pngpriv.h => Library function and interface declarations (private) - pngconf.h => System specific library configuration (public) - pngstruct.h => png_struct declaration (private) - pnginfo.h => png_info struct declaration (private) - pngdebug.h => debugging macros (private) - pngerror.c => Error/warning message I/O functions - pngget.c => Functions for retrieving info from struct - pngmem.c => Memory handling functions - pngbar.png => PNG logo, 88x31 - pngnow.png => PNG logo, 98x31 - pngpread.c => Progressive reading functions - pngread.c => Read data/helper high-level functions - pngrio.c => Lowest-level data read I/O functions - pngrtran.c => Read data transformation functions - pngrutil.c => Read data utility functions - pngset.c => Functions for storing data into the info_struct - pngtest.c => Library test program - pngtest.png => Library test sample image - pngtrans.c => Common data transformation functions - pngwio.c => Lowest-level write I/O functions - pngwrite.c => High-level write functions - pngwtran.c => Write data transformations - pngwutil.c => Write utility functions - arm => Contains optimized code for the ARM platform - powerpc => Contains optimized code for the PowerPC platform - contrib => Contributions - arm-neon => Optimized code for ARM-NEON platform - powerpc-vsx => Optimized code for POWERPC-VSX platform - examples => Example programs - gregbook => source code for PNG reading and writing, from - Greg Roelofs' "PNG: The Definitive Guide", - O'Reilly, 1999 - libtests => Test programs - mips-msa => Optimized code for MIPS-MSA platform - pngminim => Minimal decoder, encoder, and progressive decoder - programs demonstrating use of pngusr.dfa - pngminus => Simple pnm2png and png2pnm programs - pngsuite => Test images - testpngs - tools => Various tools - visupng => Contains a MSVC workspace for VisualPng - intel => Optimized code for INTEL-SSE2 platform - mips => Optimized code for MIPS platform - projects => Contains project files and workspaces for - building a DLL - owatcom => Contains a WATCOM project for building libpng - visualc71 => Contains a Microsoft Visual C++ (MSVC) - workspace for building libpng and zlib - vstudio => Contains a Microsoft Visual C++ (MSVC) - workspace for building libpng and zlib - scripts => Directory containing scripts for building libpng: - (see scripts/README.txt for the list of scripts) +to subscribe.) + +Send general questions about the PNG specification to `png-mng-misc` +at `lists.sourceforge.net`. (Subscription is required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-misc +to subscribe.) + +Historical notes +---------------- + +The libpng library has been in extensive use and testing since mid-1995. +Version 0.89, published a year later, was the first official release. +By late 1997, it had finally gotten to the stage where there hadn't +been significant changes to the API in some time, and people have a bad +feeling about libraries with versions below 1.0. Version 1.0.0 was +released in March 1998. + +Note that some of the changes to the `png_info` structure render this +version of the library binary incompatible with libpng-0.89 or +earlier versions if you are using a shared library. The type of the +`filler` parameter for `png_set_filler()` has changed from `png_byte` +to `png_uint_32`, which will affect shared-library applications that +use this function. + +To avoid problems with changes to the internals of the `info_struct`, +new APIs have been made available in 0.95 to avoid direct application +access to `info_ptr`. These functions are the `png_set_` and +`png_get_` functions. These functions should be used when +accessing/storing the `info_struct` data, rather than manipulating it +directly, to avoid such problems in the future. + +It is important to note that the APIs did not make current programs +that access the info struct directly incompatible with the new +library, through libpng-1.2.x. In libpng-1.4.x, which was meant to +be a transitional release, members of the `png_struct` and the +`info_struct` can still be accessed, but the compiler will issue a +warning about deprecated usage. Since libpng-1.5.0, direct access +to these structs is not allowed, and the definitions of the structs +reside in private `pngstruct.h` and `pnginfo.h` header files that are +not accessible to applications. It is strongly suggested that new +programs use the new APIs (as shown in `example.c` and `pngtest.c`), +and older programs be converted to the new format, to facilitate +upgrades in the future. + +The additions since 0.89 include the ability to read from a PNG stream +which has had some (or all) of the signature bytes read by the calling +application. This also allows the reading of embedded PNG streams that +do not have the PNG file signature. As well, it is now possible to set +the library action on the detection of chunk CRC errors. It is possible +to set different actions based on whether the CRC error occurred in a +critical or an ancillary chunk. + +The additions since 0.90 include the ability to compile libpng as a +Windows DLL, and new APIs for accessing data in the `info_struct`. +Experimental functions included the ability to set weighting and cost +factors for row filter selection, direct reads of integers from buffers +on big-endian processors that support misaligned data access, faster +methods of doing alpha composition, and more accurate 16-to-8 bit color +conversion. Some of these experimental functions, such as the weighted +filter heuristics, have since been removed. + +Files included in this distribution +----------------------------------- + + ANNOUNCE => Announcement of this version, with recent changes + AUTHORS => List of contributing authors + CHANGES => Description of changes between libpng versions + INSTALL => Instructions to install libpng + LICENSE => License to use and redistribute libpng + README => This file + TODO => Things not implemented in the current library + TRADEMARK => Trademark information + example.c => Example code for using libpng functions + libpng.3 => Manual page for libpng (includes libpng-manual.txt) + libpng-manual.txt => Description of libpng and its functions + libpngpf.3 => Manual page for libpng's private functions (deprecated) + png.5 => Manual page for the PNG format + png.c => Basic interface functions common to library + png.h => Library function and interface declarations (public) + pngpriv.h => Library function and interface declarations (private) + pngconf.h => System specific library configuration (public) + pngstruct.h => png_struct declaration (private) + pnginfo.h => png_info struct declaration (private) + pngdebug.h => debugging macros (private) + pngerror.c => Error/warning message I/O functions + pngget.c => Functions for retrieving info from struct + pngmem.c => Memory handling functions + pngbar.png => PNG logo, 88x31 + pngnow.png => PNG logo, 98x31 + pngpread.c => Progressive reading functions + pngread.c => Read data/helper high-level functions + pngrio.c => Lowest-level data read I/O functions + pngrtran.c => Read data transformation functions + pngrutil.c => Read data utility functions + pngset.c => Functions for storing data into the info_struct + pngtest.c => Library test program + pngtest.png => Library test sample image + pngtrans.c => Common data transformation functions + pngwio.c => Lowest-level write I/O functions + pngwrite.c => High-level write functions + pngwtran.c => Write data transformations + pngwutil.c => Write utility functions + arm/ => Optimized code for ARM Neon + intel/ => Optimized code for INTEL SSE2 + loongarch/ => Optimized code for LoongArch LSX + mips/ => Optimized code for MIPS MSA and MIPS MMI + powerpc/ => Optimized code for PowerPC VSX + ci/ => Scripts for continuous integration + contrib/ => External contributions + arm-neon/ => Optimized code for the ARM-NEON platform + mips-msa/ => Optimized code for the MIPS-MSA platform + powerpc-vsx/ => Optimized code for the POWERPC-VSX platform + examples/ => Examples of libpng usage + gregbook/ => Source code for PNG reading and writing, from + "PNG: The Definitive Guide" by Greg Roelofs, + O'Reilly, 1999 + libtests/ => Test programs + oss-fuzz/ => Files used by the OSS-Fuzz project for fuzz-testing + libpng + pngexif/ => Program to inspect the EXIF information in PNG files + pngminim/ => Minimal decoder, encoder, and progressive decoder + programs demonstrating the use of pngusr.dfa + pngminus/ => Simple pnm2png and png2pnm programs + pngsuite/ => Test images + testpngs/ => Test images + tools/ => Various tools + visupng/ => VisualPng, a Windows viewer for PNG images + projects/ => Project files and workspaces for various IDEs + owatcom/ => OpenWatcom project + visualc71/ => Microsoft Visual C++ 7.1 workspace + vstudio/ => Microsoft Visual Studio workspace + scripts/ => Scripts and makefiles for building libpng + (see scripts/README.txt for the complete list) + tests/ => Test scripts Good luck, and happy coding! diff --git a/3rdparty/libpng/arm/arm_init.c b/3rdparty/libpng/arm/arm_init.c index a34ecdbef735..84d05556f816 100644 --- a/3rdparty/libpng/arm/arm_init.c +++ b/3rdparty/libpng/arm/arm_init.c @@ -1,7 +1,7 @@ /* arm_init.c - NEON optimised filter functions * - * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2018-2022 Cosmin Truta * Copyright (c) 2014,2016 Glenn Randers-Pehrson * Written by Mans Rullgard, 2011. * @@ -10,9 +10,7 @@ * and license in png.h */ -/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are - * called. - */ +/* This module requires POSIX 1003.1 functions. */ #define _POSIX_SOURCE 1 #include "../pngpriv.h" @@ -33,21 +31,26 @@ * has partial support is contrib/arm-neon/linux.c - a generic Linux * implementation which reads /proc/cpufino. */ +#include /* for sig_atomic_t */ + #ifndef PNG_ARM_NEON_FILE -# ifdef __linux__ -# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c" +# if defined(__aarch64__) || defined(_M_ARM64) + /* ARM Neon is expected to be unconditionally available on ARM64. */ +# error "PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on ARM64" +# elif defined(__ARM_NEON__) || defined(__ARM_NEON) + /* ARM Neon is expected to be available on the target CPU architecture. */ +# error "PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on this CPU arch" +# elif defined(__linux__) +# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c" +# else +# error "No support for run-time ARM Neon checking; use compile-time options" # endif #endif -#ifdef PNG_ARM_NEON_FILE - -#include /* for sig_atomic_t */ static int png_have_neon(png_structp png_ptr); -#include PNG_ARM_NEON_FILE - -#else /* PNG_ARM_NEON_FILE */ -# error "PNG_ARM_NEON_FILE undefined: no support for run-time ARM NEON checks" -#endif /* PNG_ARM_NEON_FILE */ +#ifdef PNG_ARM_NEON_FILE +# include PNG_ARM_NEON_FILE +#endif #endif /* PNG_ARM_NEON_CHECK_SUPPORTED */ #ifndef PNG_ALIGNED_MEMORY_SUPPORTED diff --git a/3rdparty/libpng/arm/filter_neon_intrinsics.c b/3rdparty/libpng/arm/filter_neon_intrinsics.c index 553c0be21c10..4466d48b20a5 100644 --- a/3rdparty/libpng/arm/filter_neon_intrinsics.c +++ b/3rdparty/libpng/arm/filter_neon_intrinsics.c @@ -18,7 +18,7 @@ /* This code requires -mfpu=neon on the command line: */ #if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */ -#if defined(_MSC_VER) && defined(_M_ARM64) +#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64) # include #else # include diff --git a/3rdparty/libpng/arm/palette_neon_intrinsics.c b/3rdparty/libpng/arm/palette_neon_intrinsics.c index b4d1fd2abfa2..92c7d6f9f6f9 100644 --- a/3rdparty/libpng/arm/palette_neon_intrinsics.c +++ b/3rdparty/libpng/arm/palette_neon_intrinsics.c @@ -14,7 +14,7 @@ #if PNG_ARM_NEON_IMPLEMENTATION == 1 -#if defined(_MSC_VER) && defined(_M_ARM64) +#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64) # include #else # include @@ -30,8 +30,6 @@ png_riffle_palette_neon(png_structrp png_ptr) int num_trans = png_ptr->num_trans; int i; - png_debug(1, "in png_riffle_palette_neon"); - /* Initially black, opaque. */ uint8x16x4_t w = {{ vdupq_n_u8(0x00), @@ -40,6 +38,8 @@ png_riffle_palette_neon(png_structrp png_ptr) vdupq_n_u8(0xff), }}; + png_debug(1, "in png_riffle_palette_neon"); + /* First, riffle the RGB colours into an RGBA8 palette. * The alpha component is set to opaque for now. */ @@ -65,11 +65,12 @@ png_do_expand_palette_rgba8_neon(png_structrp png_ptr, png_row_infop row_info, png_uint_32 row_width = row_info->width; const png_uint_32 *riffled_palette = (const png_uint_32 *)png_ptr->riffled_palette; - const png_int_32 pixels_per_chunk = 4; - int i; + const png_uint_32 pixels_per_chunk = 4; + png_uint_32 i; png_debug(1, "in png_do_expand_palette_rgba8_neon"); + PNG_UNUSED(row) if (row_width < pixels_per_chunk) return 0; @@ -109,10 +110,11 @@ png_do_expand_palette_rgb8_neon(png_structrp png_ptr, png_row_infop row_info, png_uint_32 row_width = row_info->width; png_const_bytep palette = (png_const_bytep)png_ptr->palette; const png_uint_32 pixels_per_chunk = 8; - int i; + png_uint_32 i; png_debug(1, "in png_do_expand_palette_rgb8_neon"); + PNG_UNUSED(row) if (row_width <= pixels_per_chunk) return 0; diff --git a/3rdparty/libpng/intel/filter_sse2_intrinsics.c b/3rdparty/libpng/intel/filter_sse2_intrinsics.c index f52aaa800a43..d3c0fe9e2d68 100644 --- a/3rdparty/libpng/intel/filter_sse2_intrinsics.c +++ b/3rdparty/libpng/intel/filter_sse2_intrinsics.c @@ -259,7 +259,7 @@ void png_read_filter_row_paeth3_sse2(png_row_infop row_info, png_bytep row, a = d; d = _mm_unpacklo_epi8(load4(row ), zero); /* (p-a) == (a+b-c - a) == (b-c) */ - + pa = _mm_sub_epi16(b,c); /* (p-b) == (a+b-c - b) == (a-c) */ diff --git a/3rdparty/libpng/loongarch/filter_lsx_intrinsics.c b/3rdparty/libpng/loongarch/filter_lsx_intrinsics.c new file mode 100644 index 000000000000..af6cc763a078 --- /dev/null +++ b/3rdparty/libpng/loongarch/filter_lsx_intrinsics.c @@ -0,0 +1,412 @@ +/* filter_lsx_intrinsics.c - LSX optimized filter functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * All rights reserved. + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2016 Glenn Randers-Pehrson + * Contributed by Jin Bo (jinbo@loongson.cn) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "../pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +#if PNG_LOONGARCH_LSX_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */ + +#include + +#define LSX_LD(psrc) __lsx_vld((psrc), 0) + +#define LSX_LD_2(psrc, stride, out0, out1) \ +{ \ + out0 = LSX_LD(psrc); \ + out1 = LSX_LD(psrc + stride); \ +} + +#define LSX_LD_4(psrc, stride, out0, out1, out2, out3) \ +{ \ + LSX_LD_2(psrc, stride, out0, out1); \ + LSX_LD_2(psrc + stride * 2, stride, out2, out3); \ +} + +#define LSX_ST(in, pdst) __lsx_vst(in, (pdst), 0) + +#define LSX_ST_2(in0, in1, pdst, stride) \ +{ \ + LSX_ST(in0, pdst); \ + LSX_ST(in1, pdst + stride); \ +} + +#define LSX_ST_4(in0, in1, in2, in3, pdst, stride) \ +{ \ + LSX_ST_2(in0, in1, pdst, stride); \ + LSX_ST_2(in2, in3, pdst + stride * 2, stride); \ +} + +#define LSX_ADD_B(in0, in1, out0) \ +{ \ + out0 = __lsx_vadd_b(in0, in1); \ +} + +#define LSX_ADD_B_2(in0, in1, in2, in3, out0, out1) \ +{ \ + LSX_ADD_B(in0, in1, out0); \ + LSX_ADD_B(in2, in3, out1); \ +} + +#define LSX_ADD_B_4(in0, in1, in2, in3, in4, in5, \ + in6, in7, out0, out1, out2, out3) \ +{ \ + LSX_ADD_B_2(in0, in1, in2, in3, out0, out1); \ + LSX_ADD_B_2(in4, in5, in6, in7, out2, out3); \ +} + +#define LSX_ABS_B_3(in0, in1, in2, out0, out1, out2) \ +{ \ + out0 = __lsx_vadda_h(in0, zero); \ + out1 = __lsx_vadda_h(in1, zero); \ + out2 = __lsx_vadda_h(in2, zero); \ +} + +#define LSX_ILVL_B(in_h, in_l, out0) \ +{ \ + out0 = __lsx_vilvl_b(in_h, in_l); \ +} + +#define LSX_ILVL_B_2(in0_h, in0_l, in1_h, in1_l, out0, out1) \ +{ \ + LSX_ILVL_B(in0_h, in0_l, out0); \ + LSX_ILVL_B(in1_h, in1_l, out1); \ +} + +#define LSX_HSUB_HU_BU_2(in0, in1, out0, out1) \ +{ \ + out0 = __lsx_vhsubw_hu_bu(in0, in0); \ + out1 = __lsx_vhsubw_hu_bu(in1, in1); \ +} + +#define LSX_CMP_PICK_SMALLER(in0, in1, in2, in3, in4, in5, out0) \ +{ \ + __m128i _cmph, _cmpb, _in0, _in3; \ + _cmph = __lsx_vslt_h(in1, in0); \ + _cmpb = __lsx_vpickev_b(_cmph, _cmph); \ + _in0 = __lsx_vmin_bu(in0,in1); \ + _in3 = __lsx_vbitsel_v(in3, in4, _cmpb); \ + _cmph = __lsx_vslt_h(in2, _in0); \ + _cmpb = __lsx_vpickev_b(_cmph, _cmph); \ + _in3 = __lsx_vbitsel_v(_in3, in5, _cmpb); \ + out0 = __lsx_vadd_b(out0, _in3); \ +} + +void png_read_filter_row_up_lsx(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + size_t n = row_info->rowbytes; + png_bytep rp = row; + png_const_bytep pp = prev_row; + __m128i vec_0, vec_1, vec_2, vec_3; + __m128i vec_4, vec_5, vec_6, vec_7; + + while (n >= 64) + { + LSX_LD_4(rp, 16, vec_0, vec_1, vec_2, vec_3); + LSX_LD_4(pp, 16, vec_4, vec_5, vec_6, vec_7); + pp += 64; + LSX_ADD_B_4(vec_0 ,vec_4, vec_1, vec_5, vec_2, vec_6, + vec_3, vec_7, vec_0, vec_1, vec_2, vec_3); + LSX_ST_4(vec_0, vec_1, vec_2, vec_3, rp, 16); + rp += 64; + n -= 64; + } + if (n & 63) + { + if (n >= 32) + { + LSX_LD_2(rp, 16, vec_0, vec_1); + LSX_LD_2(pp, 16, vec_2, vec_3); + pp += 32; + LSX_ADD_B_2(vec_0, vec_2, vec_1, vec_3, vec_0, vec_1); + LSX_ST_2(vec_0, vec_1, rp, 16); + rp += 32; + n -= 32; + } + if (n & 31) + { + if (n >= 16) + { + vec_0 = LSX_LD(rp); + vec_1 = LSX_LD(pp); + pp += 16; + LSX_ADD_B(vec_0, vec_1, vec_0); + LSX_ST(vec_0, rp); + rp += 16; + n -= 16; + } + if (n >= 8) + { + vec_0 = __lsx_vldrepl_d(rp, 0); + vec_1 = __lsx_vldrepl_d(pp, 0); + vec_0 = __lsx_vadd_b(vec_0, vec_1); + __lsx_vstelm_d(vec_0, rp, 0, 0); + rp += 8; + pp += 8; + n -= 8; + } + while (n--) + { + *rp = *rp + *pp++; + rp++; + } + } + } +} + +void png_read_filter_row_sub3_lsx(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + size_t n = row_info->rowbytes; + png_uint_32 tmp; + png_bytep nxt = row; + __m128i vec_0, vec_1; + + PNG_UNUSED(prev_row); + + vec_0 = __lsx_vldrepl_w(nxt, 0); + nxt += 3; + n -= 3; + + while (n >= 3) + { + vec_1 = __lsx_vldrepl_w(nxt, 0); + vec_1 = __lsx_vadd_b(vec_1, vec_0); + __lsx_vstelm_h(vec_1, nxt, 0, 0); + vec_0 = vec_1; + nxt += 2; + __lsx_vstelm_b(vec_1, nxt, 0, 2); + nxt += 1; + n -= 3; + } + + row = nxt - 3; + while (n--) + { + *nxt = *nxt + *row++; + nxt++; + } +} + +void png_read_filter_row_sub4_lsx(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + size_t n = row_info->rowbytes; + __m128i vec_0, vec_1; + + PNG_UNUSED(prev_row); + + vec_0 = __lsx_vldrepl_w(row, 0); + row += 4; + n -= 4; + + while (n >= 4) + { + vec_1 = __lsx_vldrepl_w(row, 0); + vec_1 = __lsx_vadd_b(vec_1, vec_0); + __lsx_vstelm_w(vec_1, row, 0, 0); + vec_0 = vec_1; + row += 4; + n -= 4; + } +} + +void png_read_filter_row_avg3_lsx(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + size_t n = row_info->rowbytes; + png_bytep nxt = row; + png_const_bytep prev_nxt = prev_row; + __m128i vec_0, vec_1, vec_2; + + vec_0 = __lsx_vldrepl_w(nxt, 0); + vec_1 = __lsx_vldrepl_w(prev_nxt, 0); + prev_nxt += 3; + vec_1 = __lsx_vsrli_b(vec_1, 1); + vec_1 = __lsx_vadd_b(vec_1, vec_0); + __lsx_vstelm_h(vec_1, nxt, 0, 0); + nxt += 2; + __lsx_vstelm_b(vec_1, nxt, 0, 2); + nxt += 1; + n -= 3; + + while (n >= 3) + { + vec_2 = vec_1; + vec_0 = __lsx_vldrepl_w(nxt, 0); + vec_1 = __lsx_vldrepl_w(prev_nxt, 0); + prev_nxt += 3; + + vec_1 = __lsx_vavg_bu(vec_1, vec_2); + vec_1 = __lsx_vadd_b(vec_1, vec_0); + + __lsx_vstelm_h(vec_1, nxt, 0, 0); + nxt += 2; + __lsx_vstelm_b(vec_1, nxt, 0, 2); + nxt += 1; + n -= 3; + } + + row = nxt - 3; + while (n--) + { + vec_2 = __lsx_vldrepl_b(row, 0); + row++; + vec_0 = __lsx_vldrepl_b(nxt, 0); + vec_1 = __lsx_vldrepl_b(prev_nxt, 0); + prev_nxt++; + + vec_1 = __lsx_vavg_bu(vec_1, vec_2); + vec_1 = __lsx_vadd_b(vec_1, vec_0); + + __lsx_vstelm_b(vec_1, nxt, 0, 0); + nxt++; + } +} + +void png_read_filter_row_avg4_lsx(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + size_t n = row_info->rowbytes; + __m128i vec_0, vec_1, vec_2; + + vec_0 = __lsx_vldrepl_w(row, 0); + vec_1 = __lsx_vldrepl_w(prev_row, 0); + prev_row += 4; + vec_1 = __lsx_vsrli_b(vec_1, 1); + vec_1 = __lsx_vadd_b(vec_1, vec_0); + __lsx_vstelm_w(vec_1, row, 0, 0); + row += 4; + n -= 4; + + while (n >= 4) + { + vec_2 = vec_1; + vec_0 = __lsx_vldrepl_w(row, 0); + vec_1 = __lsx_vldrepl_w(prev_row, 0); + prev_row += 4; + + vec_1 = __lsx_vavg_bu(vec_1, vec_2); + vec_1 = __lsx_vadd_b(vec_1, vec_0); + + __lsx_vstelm_w(vec_1, row, 0, 0); + row += 4; + n -= 4; + } +} + +void png_read_filter_row_paeth3_lsx(png_row_infop row_info, + png_bytep row, + png_const_bytep prev_row) +{ + size_t n = row_info->rowbytes; + png_bytep nxt = row; + png_const_bytep prev_nxt = prev_row; + __m128i vec_a, vec_b, vec_c, vec_d; + __m128i vec_pa, vec_pb, vec_pc; + __m128i zero = {0}; + + vec_a = __lsx_vldrepl_w(nxt, 0); + vec_b = __lsx_vldrepl_w(prev_nxt, 0); + prev_nxt += 3; + vec_d = __lsx_vadd_b(vec_a, vec_b); + __lsx_vstelm_h(vec_d, nxt, 0, 0); + nxt += 2; + __lsx_vstelm_b(vec_d, nxt, 0, 2); + nxt += 1; + n -= 3; + + while (n >= 3) + { + vec_a = vec_d; + vec_c = vec_b; + vec_b = __lsx_vldrepl_w(prev_nxt, 0); + prev_nxt += 3; + vec_d = __lsx_vldrepl_w(nxt, 0); + + LSX_ILVL_B_2(vec_b, vec_c, vec_a, vec_c, vec_pa, vec_pb); + LSX_HSUB_HU_BU_2(vec_pa, vec_pb, vec_pa, vec_pb); + vec_pc = __lsx_vadd_h(vec_pa, vec_pb); + LSX_ABS_B_3(vec_pa, vec_pb, vec_pc, vec_pa, vec_pb, vec_pc); + LSX_CMP_PICK_SMALLER(vec_pa, vec_pb, vec_pc, vec_a, vec_b, vec_c, vec_d); + + __lsx_vstelm_h(vec_d, nxt, 0, 0); + nxt += 2; + __lsx_vstelm_b(vec_d, nxt, 0, 2); + nxt += 1; + n -= 3; + } + + prev_row = prev_nxt - 3; + row = nxt - 3; + while (n--) + { + vec_a = __lsx_vldrepl_b(row, 0); + row++; + vec_b = __lsx_vldrepl_b(prev_nxt, 0); + prev_nxt++; + vec_c = __lsx_vldrepl_b(prev_row, 0); + prev_row++; + vec_d = __lsx_vldrepl_b(nxt, 0); + + LSX_ILVL_B_2(vec_b, vec_c, vec_a, vec_c, vec_pa, vec_pb); + LSX_HSUB_HU_BU_2(vec_pa, vec_pb, vec_pa, vec_pb); + vec_pc = __lsx_vadd_h(vec_pa, vec_pb); + LSX_ABS_B_3(vec_pa, vec_pb, vec_pc, vec_pa, vec_pb, vec_pc); + LSX_CMP_PICK_SMALLER(vec_pa, vec_pb, vec_pc, vec_a, vec_b, vec_c, vec_d); + + __lsx_vstelm_b(vec_d, nxt, 0, 0); + nxt++; + } +} + +void png_read_filter_row_paeth4_lsx(png_row_infop row_info, + png_bytep row, + png_const_bytep prev_row) +{ + size_t n = row_info->rowbytes; + __m128i vec_a, vec_b, vec_c, vec_d; + __m128i vec_pa, vec_pb, vec_pc; + __m128i zero = {0}; + + vec_a = __lsx_vldrepl_w(row, 0); + vec_b = __lsx_vldrepl_w(prev_row, 0); + prev_row += 4; + vec_d = __lsx_vadd_b(vec_a, vec_b); + __lsx_vstelm_w(vec_d, row, 0, 0); + row += 4; + n -= 4; + + while (n >= 4) + { + vec_a = vec_d; + vec_c = vec_b; + vec_b = __lsx_vldrepl_w(prev_row, 0); + prev_row += 4; + vec_d = __lsx_vldrepl_w(row, 0); + + LSX_ILVL_B_2(vec_b, vec_c, vec_a, vec_c, vec_pa, vec_pb); + LSX_HSUB_HU_BU_2(vec_pa, vec_pb, vec_pa, vec_pb); + vec_pc = __lsx_vadd_h(vec_pa, vec_pb); + LSX_ABS_B_3(vec_pa, vec_pb, vec_pc, vec_pa, vec_pb, vec_pc); + LSX_CMP_PICK_SMALLER(vec_pa, vec_pb, vec_pc, vec_a, vec_b, vec_c, vec_d); + + __lsx_vstelm_w(vec_d, row, 0, 0); + row += 4; + n -= 4; + } +} + +#endif /* PNG_LOONGARCH_LSX_IMPLEMENTATION == 1 (intrinsics) */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/3rdparty/libpng/loongarch/loongarch_lsx_init.c b/3rdparty/libpng/loongarch/loongarch_lsx_init.c new file mode 100644 index 000000000000..2c80fe81b687 --- /dev/null +++ b/3rdparty/libpng/loongarch/loongarch_lsx_init.c @@ -0,0 +1,65 @@ +/* loongarch_lsx_init.c - LSX optimized filter functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * All rights reserved. + * Contributed by Jin Bo + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "../pngpriv.h" + +#ifdef PNG_READ_SUPPORTED +#if PNG_LOONGARCH_LSX_IMPLEMENTATION == 1 + +#include + +#define LA_HWCAP_LSX (1<<4) +static int png_has_lsx(void) +{ + int flags = 0; + int flag = (int)getauxval(AT_HWCAP); + + if (flag & LA_HWCAP_LSX) + return 1; + + return 0; +} + +void +png_init_filter_functions_lsx(png_structp pp, unsigned int bpp) +{ + /* IMPORTANT: any new external functions used here must be declared using + * PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the + * 'prefix' option to configure works: + * + * ./configure --with-libpng-prefix=foobar_ + * + * Verify you have got this right by running the above command, doing a build + * and examining pngprefix.h; it must contain a #define for every external + * function you add. (Notice that this happens automatically for the + * initialization function.) + */ + + if (png_has_lsx()) + { + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_lsx; + if (bpp == 3) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_lsx; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_lsx; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_lsx; + } + else if (bpp == 4) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_lsx; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_lsx; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_lsx; + } + } +} + +#endif /* PNG_LOONGARCH_LSX_IMPLEMENTATION == 1 */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/3rdparty/libpng/mips/filter_mmi_inline_assembly.c b/3rdparty/libpng/mips/filter_mmi_inline_assembly.c new file mode 100644 index 000000000000..b330a4653810 --- /dev/null +++ b/3rdparty/libpng/mips/filter_mmi_inline_assembly.c @@ -0,0 +1,525 @@ +/* filter_mmi_intrinsics.c - MMI optimized filter functions + * + * Copyright (c) 2024 Cosmin Truta + * Written by zhanglixia and guxiwei, 2023 + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "../pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +#if PNG_MIPS_MMI_IMPLEMENTATION == 2 /* Inline Assembly */ + +/* Functions in this file look at most 3 pixels (a,b,c) to predict the 4th (d). + * They're positioned like this: + * prev: c b + * row: a d + * The Sub filter predicts d=a, Avg d=(a+b)/2, and Paeth predicts d to be + * whichever of a, b, or c is closest to p=a+b-c. + */ + +void png_read_filter_row_up_mmi(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + int istop = row_info->rowbytes; + double rp,pp; + __asm__ volatile ( + "1: \n\t" + "ldc1 %[rp], 0x00(%[row]) \n\t" + "ldc1 %[pp], 0x00(%[prev_row]) \n\t" + "paddb %[rp], %[rp], %[pp] \n\t" + "sdc1 %[rp], 0x00(%[row]) \n\t" + + "daddiu %[row], %[row], 0x08 \n\t" + "daddiu %[prev_row], %[prev_row], 0x08 \n\t" + "daddiu %[istop], %[istop], -0x08 \n\t" + "bgtz %[istop], 1b \n\t" + : [rp]"=&f"(rp), [pp]"=&f"(pp) + : [row]"r"(row), [prev_row]"r"(prev_row), + [istop]"r"(istop) + : "memory" + ); +} + +void png_read_filter_row_sub3_mmi(png_row_infop row_info, png_bytep row, + png_const_bytep prev) +{ + int istop = row_info->rowbytes; + double rp, pp, dest; + double eight, sixteen, twenty_four, forty_eight; + double tmp0; + double ftmp[2]; + + __asm__ volatile ( + "li %[tmp0], 0x08 \n\t" + "dmtc1 %[tmp0], %[eight] \n\t" + "li %[tmp0], 0x10 \n\t" + "dmtc1 %[tmp0], %[sixteen] \n\t" + "li %[tmp0], 0x18 \n\t" + "dmtc1 %[tmp0], %[twenty_four] \n\t" + "li %[tmp0], 0x30 \n\t" + "dmtc1 %[tmp0], %[forty_eight] \n\t" + "xor %[dest], %[dest], %[dest] \n\t" + + "1: \n\t" + "gsldrc1 %[rp], 0x00(%[row]) \n\t" + "gsldlc1 %[rp], 0x07(%[row]) \n\t" + "gsldrc1 %[pp], 0x08(%[row]) \n\t" + "gsldlc1 %[pp], 0x0f(%[row]) \n\t" + + "paddb %[ftmp0], %[dest], %[rp] \n\t" + "swc1 %[ftmp0], 0x00(%[row]) \n\t" + + "dsrl %[ftmp1], %[rp], %[twenty_four] \n\t" + "paddb %[dest], %[ftmp1], %[ftmp0] \n\t" + "gsswrc1 %[dest], 0x03(%[row]) \n\t" + "gsswlc1 %[dest], 0x06(%[row]) \n\t" + + "dsrl %[ftmp0], %[rp], %[forty_eight] \n\t" + "dsll %[ftmp1], %[pp], %[sixteen] \n\t" + "or %[ftmp0], %[ftmp0], %[ftmp1] \n\t" + "paddb %[dest], %[dest], %[ftmp0] \n\t" + "gsswrc1 %[dest], 0x06(%[row]) \n\t" + "gsswlc1 %[dest], 0x09(%[row]) \n\t" + + "dsrl %[ftmp0], %[pp], %[eight] \n\t" + "paddb %[dest], %[dest], %[ftmp0] \n\t" + "gsswrc1 %[dest], 0x09(%[row]) \n\t" + "daddiu %[row], %[row], 0x0c \n\t" + "daddiu %[istop], %[istop], -0x0c \n\t" + "bgtz %[istop], 1b \n\t" + : [rp]"=&f"(rp), [pp]"=&f"(pp), [dest]"=&f"(dest), + [tmp0]"=&r"(tmp0), [ftmp0]"=&f"(ftmp[0]), + [ftmp1]"=&f"(ftmp[1]), [eight]"=&f"(eight), + [sixteen]"=&f"(sixteen), [twenty_four]"=&f"(twenty_four), + [forty_eight]"=&f"(forty_eight) + : [row]"r"(row), [istop]"r"(istop) + : "memory" + ); + + PNG_UNUSED(prev) +} + +void png_read_filter_row_sub4_mmi(png_row_infop row_info, png_bytep row, + png_const_bytep prev) +{ + /* The Sub filter predicts each pixel as the previous pixel, a. + * There is no pixel to the left of the first pixel. It's encoded directly. + * That works with our main loop if we just say that left pixel was zero. + */ + int istop = row_info->rowbytes; + double rp,pp; + + __asm__ volatile ( + "1: \n\t" + "lwc1 %[pp], 0x00(%[row]) \n\t" + "lwc1 %[rp], 0x04(%[row]) \n\t" + "paddb %[rp], %[rp], %[pp] \n\t" + "swc1 %[rp], 0x04(%[row]) \n\t" + + "daddiu %[row], %[row], 0x04 \n\t" + "daddiu %[istop], %[istop], -0x04 \n\t" + "bgtz %[istop], 1b \n\t" + : [rp]"=&f"(rp), [pp]"=&f"(pp) + : [row]"r"(row), [istop]"r"(istop) + : "memory" + ); + + PNG_UNUSED(prev) +} + +void png_read_filter_row_avg3_mmi(png_row_infop row_info, png_bytep row, + png_const_bytep prev) +{ + int istop = row_info->rowbytes; + double rp, pp, rp1, pp1; + double tmp0; + double ftmp[3]; + double one, dest; + double eight, sixteen, twenty_four, forty_eight; + + __asm__ volatile ( + "li %[tmp0], 0x08 \n\t" + "dmtc1 %[tmp0], %[eight] \n\t" + "li %[tmp0], 0x10 \n\t" + "dmtc1 %[tmp0], %[sixteen] \n\t" + "li %[tmp0], 0x18 \n\t" + "dmtc1 %[tmp0], %[twenty_four] \n\t" + "li %[tmp0], 0x30 \n\t" + "dmtc1 %[tmp0], %[forty_eight] \n\t" + "xor %[dest], %[dest], %[dest] \n\t" + + "li %[tmp0], 0x01 \n\t" + "ins %[tmp0], %[tmp0], 8, 8 \n\t" + "dmtc1 %[tmp0], %[one] \n\t" + "pshufh %[one], %[one], %[dest] \n\t" + + "1: \n\t" + "gsldrc1 %[rp], 0x00(%[row]) \n\t" + "gsldlc1 %[rp], 0x07(%[row]) \n\t" + "gsldrc1 %[pp], 0x00(%[prev]) \n\t" + "gsldlc1 %[pp], 0x07(%[prev]) \n\t" + "gsldrc1 %[rp1], 0x08(%[row]) \n\t" + "gsldlc1 %[rp1], 0x0f(%[row]) \n\t" + "gsldrc1 %[pp1], 0x08(%[prev]) \n\t" + "gsldlc1 %[pp1], 0x0f(%[prev]) \n\t" + + "xor %[ftmp0], %[pp], %[dest] \n\t" + "pavgb %[ftmp1], %[pp], %[dest] \n\t" + "and %[ftmp0], %[ftmp0], %[one] \n\t" + "psubb %[ftmp1], %[ftmp1], %[ftmp0] \n\t" + "paddb %[dest], %[rp], %[ftmp1] \n\t" + "swc1 %[dest], 0x00(%[row]) \n\t" + + "dsrl %[ftmp0], %[rp], %[twenty_four] \n\t" + "dsrl %[ftmp1], %[pp], %[twenty_four] \n\t" + + "xor %[ftmp2], %[ftmp1], %[dest] \n\t" + "pavgb %[ftmp1], %[ftmp1], %[dest] \n\t" + "and %[ftmp2], %[ftmp2], %[one] \n\t" + "psubb %[ftmp1], %[ftmp1], %[ftmp2] \n\t" + "paddb %[dest], %[ftmp0], %[ftmp1] \n\t" + "gsswrc1 %[dest], 0x03(%[row]) \n\t" + "gsswlc1 %[dest], 0x06(%[row]) \n\t" + + "dsrl %[ftmp0], %[rp], %[forty_eight] \n\t" + "dsll %[ftmp1], %[rp1], %[sixteen] \n\t" + "or %[ftmp0], %[ftmp0], %[ftmp1] \n\t" + "dsrl %[ftmp2], %[pp], %[forty_eight] \n\t" + "dsll %[ftmp1], %[pp1], %[sixteen] \n\t" + "or %[ftmp1], %[ftmp2], %[ftmp1] \n\t" + + "xor %[ftmp2], %[ftmp1], %[dest] \n\t" + "pavgb %[ftmp1], %[ftmp1], %[dest] \n\t" + "and %[ftmp2], %[ftmp2], %[one] \n\t" + "psubb %[ftmp1], %[ftmp1], %[ftmp2] \n\t" + "paddb %[dest], %[ftmp0], %[ftmp1] \n\t" + "gsswrc1 %[dest], 0x06(%[row]) \n\t" + "gsswlc1 %[dest], 0x09(%[row]) \n\t" + + "dsrl %[ftmp0], %[rp1], %[eight] \n\t" + "dsrl %[ftmp1], %[pp1], %[eight] \n\t" + + "xor %[ftmp2], %[ftmp1], %[dest] \n\t" + "pavgb %[ftmp1], %[ftmp1], %[dest] \n\t" + "and %[ftmp2], %[ftmp2], %[one] \n\t" + "psubb %[ftmp1], %[ftmp1], %[ftmp2] \n\t" + "paddb %[dest], %[ftmp0], %[ftmp1] \n\t" + "gsswrc1 %[dest], 0x09(%[row]) \n\t" + "daddiu %[row], %[row], 0x0c \n\t" + "daddiu %[prev], %[prev], 0x0c \n\t" + "daddiu %[istop], %[istop], -0x0c \n\t" + "bgtz %[istop], 1b \n\t" + : [rp]"=&f"(rp), [pp]"=&f"(pp), [rp1]"=&f"(rp1), + [pp1]"=&f"(pp1), [tmp0]"=&r"(tmp0), [ftmp0]"=&f"(ftmp[0]), + [ftmp1]"=&f"(ftmp[1]), [ftmp2]"=&f"(ftmp[2]), [one]"=&f"(one), + [dest]"=&f"(dest), [eight]"=&f"(eight), [sixteen]"=&f"(sixteen), + [twenty_four]"=&f"(twenty_four), [forty_eight]"=&f"(forty_eight) + : [row]"r"(row), [prev]"r"(prev), [istop]"r"(istop) + : "memory" + ); +} + +void png_read_filter_row_avg4_mmi(png_row_infop row_info, png_bytep row, + png_const_bytep prev) +{ + int istop = row_info->rowbytes; + double rp,pp; + double dest; + double ftmp[2]; + double tmp; + + __asm__ volatile ( + "xor %[dest], %[dest], %[dest] \n\t" + "li %[tmp], 0x01 \n\t" + "ins %[tmp], %[tmp], 8, 8 \n\t" + "dmtc1 %[tmp], %[ftmp1] \n\t" + "pshufh %[ftmp1], %[ftmp1], %[dest] \n\t" + + "1: \n\t" + "lwc1 %[rp], 0x00(%[row]) \n\t" + "lwc1 %[pp], 0x00(%[prev]) \n\t" + "xor %[ftmp0], %[pp], %[dest] \n\t" + "pavgb %[pp], %[pp], %[dest] \n\t" + "and %[ftmp0], %[ftmp0], %[ftmp1] \n\t" + "psubb %[pp], %[pp], %[ftmp0] \n\t" + "paddb %[dest], %[rp], %[pp] \n\t" + "swc1 %[dest], 0x00(%[row]) \n\t" + "daddiu %[row], %[row], 0x04 \n\t" + "daddiu %[prev], %[prev], 0x04 \n\t" + "daddiu %[istop], %[istop], -0x04 \n\t" + "bgtz %[istop], 1b \n\t" + : [rp]"=&f"(rp), [pp]"=&f"(pp), [ftmp0]"=&f"(ftmp[0]), + [ftmp1]"=&f"(ftmp[1]), [dest]"=&f"(dest), [tmp]"=&r"(tmp) + : [row]"r"(row), [prev]"r"(prev), [istop]"r"(istop) + : "memory" + ); +} + +void png_read_filter_row_paeth3_mmi(png_row_infop row_info, png_bytep row, + png_const_bytep prev) +{ + /* Paeth tries to predict pixel d using the pixel to the left of it, a, + * and two pixels from the previous row, b and c: + * prev: c b + * row: a d + * The Paeth function predicts d to be whichever of a, b, or c is nearest to + * p=a+b-c. + * + * The first pixel has no left context, and so uses an Up filter, p = b. + * This works naturally with our main loop's p = a+b-c if we force a and c + * to zero. + * Here we zero b and d, which become c and a respectively at the start of + * the loop. + */ + int istop = row_info->rowbytes; + double rp, pp, rp1, pp1, zero; + double a, b, c, d, pa, pb, pc; + double tmp0; + double ftmp[3]; + double eight, sixteen, twenty_four, forty_eight; + + __asm__ volatile ( + "xor %[a], %[a], %[a] \n\t" + "xor %[c], %[c], %[c] \n\t" + "xor %[zero], %[zero], %[zero] \n\t" + "li %[tmp0], 0x08 \n\t" + "dmtc1 %[tmp0], %[eight] \n\t" + "li %[tmp0], 0x10 \n\t" + "dmtc1 %[tmp0], %[sixteen] \n\t" + "li %[tmp0], 0x18 \n\t" + "dmtc1 %[tmp0], %[twenty_four] \n\t" + "li %[tmp0], 0x30 \n\t" + "dmtc1 %[tmp0], %[forty_eight] \n\t" + + "1: \n\t" + "gsldrc1 %[rp], 0x00(%[row]) \n\t" + "gsldlc1 %[rp], 0x07(%[row]) \n\t" + "gsldrc1 %[pp], 0x00(%[prev]) \n\t" + "gsldlc1 %[pp], 0x07(%[prev]) \n\t" + "gsldrc1 %[rp1], 0x08(%[row]) \n\t" + "gsldlc1 %[rp1], 0x0f(%[row]) \n\t" + "gsldrc1 %[pp1], 0x08(%[prev]) \n\t" + "gsldlc1 %[pp1], 0x0f(%[prev]) \n\t" + + "punpcklbh %[b], %[pp], %[zero] \n\t" + "punpcklbh %[d], %[rp], %[zero] \n\t" + "packushb %[ftmp0], %[c], %[c] \n\t" + "packushb %[ftmp1], %[a], %[a] \n\t" + "pasubub %[pa], %[pp], %[ftmp0] \n\t" + "pasubub %[pb], %[ftmp1], %[ftmp0] \n\t" + "psubh %[ftmp0], %[b], %[c] \n\t" + "psubh %[ftmp1], %[a], %[c] \n\t" + "paddh %[pc], %[ftmp0], %[ftmp1] \n\t" + "pcmpgth %[ftmp0], %[zero], %[pc] \n\t" + "xor %[pc], %[pc], %[ftmp0] \n\t" + "psubh %[pc], %[pc], %[ftmp0] \n\t" + "punpcklbh %[pa], %[pa], %[zero] \n\t" + "punpcklbh %[pb], %[pb], %[zero] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pb] \n\t" + "and %[ftmp1], %[b], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "pminsh %[pa], %[pa], %[pb] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pc] \n\t" + "and %[ftmp1], %[c], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "paddb %[a], %[a], %[d] \n\t" + "packushb %[d], %[a], %[a] \n\t" + "punpcklbh %[c], %[pp], %[zero] \n\t" + "swc1 %[d], 0x00(%[row]) \n\t" + + "dsrl %[ftmp0], %[rp], %[twenty_four] \n\t" + "dsrl %[ftmp2], %[pp], %[twenty_four] \n\t" + + "punpcklbh %[b], %[ftmp2], %[zero] \n\t" + "punpcklbh %[d], %[ftmp0], %[zero] \n\t" + "packushb %[ftmp0], %[c], %[c] \n\t" + "packushb %[ftmp1], %[a], %[a] \n\t" + "pasubub %[pa], %[ftmp2], %[ftmp0] \n\t" + "pasubub %[pb], %[ftmp1], %[ftmp0] \n\t" + "psubh %[ftmp0], %[b], %[c] \n\t" + "psubh %[ftmp1], %[a], %[c] \n\t" + "paddh %[pc], %[ftmp0], %[ftmp1] \n\t" + "pcmpgth %[ftmp0], %[zero], %[pc] \n\t" + "xor %[pc], %[pc], %[ftmp0] \n\t" + "psubh %[pc], %[pc], %[ftmp0] \n\t" + "punpcklbh %[pa], %[pa], %[zero] \n\t" + "punpcklbh %[pb], %[pb], %[zero] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pb] \n\t" + "and %[ftmp1], %[b], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "pminsh %[pa], %[pa], %[pb] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pc] \n\t" + "and %[ftmp1], %[c], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "paddb %[a], %[a], %[d] \n\t" + "packushb %[d], %[a], %[a] \n\t" + "punpcklbh %[c], %[ftmp2], %[zero] \n\t" + "gsswrc1 %[d], 0x03(%[row]) \n\t" + "gsswlc1 %[d], 0x06(%[row]) \n\t" + + "dsrl %[ftmp0], %[rp], %[forty_eight] \n\t" + "dsll %[ftmp1], %[rp1], %[sixteen] \n\t" + "or %[ftmp0], %[ftmp0], %[ftmp1] \n\t" + "dsrl %[ftmp2], %[pp], %[forty_eight] \n\t" + "dsll %[ftmp1], %[pp1], %[sixteen] \n\t" + "or %[ftmp2], %[ftmp2], %[ftmp1] \n\t" + + "punpcklbh %[b], %[ftmp2], %[zero] \n\t" + "punpcklbh %[d], %[ftmp0], %[zero] \n\t" + "packushb %[ftmp0], %[c], %[c] \n\t" + "packushb %[ftmp1], %[a], %[a] \n\t" + "pasubub %[pa], %[ftmp2], %[ftmp0] \n\t" + "pasubub %[pb], %[ftmp1], %[ftmp0] \n\t" + "psubh %[ftmp0], %[b], %[c] \n\t" + "psubh %[ftmp1], %[a], %[c] \n\t" + "paddh %[pc], %[ftmp0], %[ftmp1] \n\t" + "pcmpgth %[ftmp0], %[zero], %[pc] \n\t" + "xor %[pc], %[pc], %[ftmp0] \n\t" + "psubh %[pc], %[pc], %[ftmp0] \n\t" + "punpcklbh %[pa], %[pa], %[zero] \n\t" + "punpcklbh %[pb], %[pb], %[zero] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pb] \n\t" + "and %[ftmp1], %[b], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "pminsh %[pa], %[pa], %[pb] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pc] \n\t" + "and %[ftmp1], %[c], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "paddb %[a], %[a], %[d] \n\t" + "packushb %[d], %[a], %[a] \n\t" + "punpcklbh %[c], %[ftmp2], %[zero] \n\t" + "gsswrc1 %[d], 0x06(%[row]) \n\t" + "gsswlc1 %[d], 0x09(%[row]) \n\t" + + "dsrl %[ftmp0], %[rp1], %[eight] \n\t" + "dsrl %[ftmp2], %[pp1], %[eight] \n\t" + + "punpcklbh %[b], %[ftmp2], %[zero] \n\t" + "punpcklbh %[d], %[ftmp0], %[zero] \n\t" + "packushb %[ftmp0], %[c], %[c] \n\t" + "packushb %[ftmp1], %[a], %[a] \n\t" + "pasubub %[pa], %[ftmp2], %[ftmp0] \n\t" + "pasubub %[pb], %[ftmp1], %[ftmp0] \n\t" + "psubh %[ftmp0], %[b], %[c] \n\t" + "psubh %[ftmp1], %[a], %[c] \n\t" + "paddh %[pc], %[ftmp0], %[ftmp1] \n\t" + "pcmpgth %[ftmp0], %[zero], %[pc] \n\t" + "xor %[pc], %[pc], %[ftmp0] \n\t" + "psubh %[pc], %[pc], %[ftmp0] \n\t" + "punpcklbh %[pa], %[pa], %[zero] \n\t" + "punpcklbh %[pb], %[pb], %[zero] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pb] \n\t" + "and %[ftmp1], %[b], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "pminsh %[pa], %[pa], %[pb] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pc] \n\t" + "and %[ftmp1], %[c], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "paddb %[a], %[a], %[d] \n\t" + "packushb %[d], %[a], %[a] \n\t" + "punpcklbh %[c], %[ftmp2], %[zero] \n\t" + "gsswrc1 %[d], 0x09(%[row]) \n\t" + + "daddiu %[row], %[row], 0x0c \n\t" + "daddiu %[prev], %[prev], 0x0c \n\t" + "daddiu %[istop], %[istop], -0x0c \n\t" + "bgtz %[istop], 1b \n\t" + : [rp]"=&f"(rp), [pp]"=&f"(pp), [rp1]"=&f"(rp1), [pp1]"=&f"(pp1), + [zero]"=&f"(zero), [a]"=&f"(a),[b]"=&f"(b), [c]"=&f"(c), + [d]"=&f"(d), [pa]"=&f"(pa), [pb]"=&f"(pb), [pc]"=&f"(pc), + [tmp0]"=&r"(tmp0), [ftmp0]"=&f"(ftmp[0]), [ftmp1]"=&f"(ftmp[1]), + [ftmp2]"=&f"(ftmp[2]), [eight]"=&f"(eight), [sixteen]"=&f"(sixteen), + [twenty_four]"=&f"(twenty_four), [forty_eight]"=&f"(forty_eight) + : [row]"r"(row), [prev]"r"(prev), [istop]"r"(istop) + : "memory" + ); +} + +void png_read_filter_row_paeth4_mmi(png_row_infop row_info, png_bytep row, + png_const_bytep prev) +{ + /* Paeth tries to predict pixel d using the pixel to the left of it, a, + * and two pixels from the previous row, b and c: + * prev: c b + * row: a d + * The Paeth function predicts d to be whichever of a, b, or c is nearest to + * p=a+b-c. + * + * The first pixel has no left context, and so uses an Up filter, p = b. + * This works naturally with our main loop's p = a+b-c if we force a and c + * to zero. + * Here we zero b and d, which become c and a respectively at the start of + * the loop. + */ + int istop = row_info->rowbytes; + double rp, pp, zero; + double a, b, c, d, pa, pb, pc; + double ftmp[2]; + + __asm__ volatile ( + "xor %[a], %[a], %[a] \n\t" + "xor %[c], %[c], %[c] \n\t" + "xor %[zero], %[zero], %[zero] \n\t" + + "1: \n\t" + "lwc1 %[rp], 0x00(%[row]) \n\t" + "lwc1 %[pp], 0x00(%[prev]) \n\t" + "punpcklbh %[b], %[pp], %[zero] \n\t" + "punpcklbh %[d], %[rp], %[zero] \n\t" + + "packushb %[ftmp0], %[c], %[c] \n\t" + "packushb %[ftmp1], %[a], %[a] \n\t" + "pasubub %[pa], %[pp], %[ftmp0] \n\t" + "pasubub %[pb], %[ftmp1], %[ftmp0] \n\t" + "psubh %[ftmp0], %[b], %[c] \n\t" + "psubh %[ftmp1], %[a], %[c] \n\t" + "paddh %[pc], %[ftmp0], %[ftmp1] \n\t" + "pcmpgth %[ftmp0], %[zero], %[pc] \n\t" + "xor %[pc], %[pc], %[ftmp0] \n\t" + "psubh %[pc], %[pc], %[ftmp0] \n\t" + + "punpcklbh %[pa], %[pa], %[zero] \n\t" + "punpcklbh %[pb], %[pb], %[zero] \n\t" + + "pcmpgth %[ftmp0], %[pa], %[pb] \n\t" + "and %[ftmp1], %[b], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "pminsh %[pa], %[pa], %[pb] \n\t" + + "pcmpgth %[ftmp0], %[pa], %[pc] \n\t" + "and %[ftmp1], %[c], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "paddb %[a], %[a], %[d] \n\t" + "packushb %[d], %[a], %[a] \n\t" + "swc1 %[d], 0x00(%[row]) \n\t" + "punpcklbh %[c], %[pp], %[zero] \n\t" + "daddiu %[row], %[row], 0x04 \n\t" + "daddiu %[prev], %[prev], 0x04 \n\t" + "daddiu %[istop], %[istop], -0x04 \n\t" + "bgtz %[istop], 1b \n\t" + : [rp]"=&f"(rp), [pp]"=&f"(pp), [zero]"=&f"(zero), + [a]"=&f"(a), [b]"=&f"(b), [c]"=&f"(c), [d]"=&f"(d), + [pa]"=&f"(pa), [pb]"=&f"(pb), [pc]"=&f"(pc), + [ftmp0]"=&f"(ftmp[0]), [ftmp1]"=&f"(ftmp[1]) + : [row]"r"(row), [prev]"r"(prev), [istop]"r"(istop) + : "memory" + ); +} + +#endif /* PNG_MIPS_MMI_IMPLEMENTATION > 0 */ +#endif /* READ */ diff --git a/3rdparty/libpng/mips/filter_msa_intrinsics.c b/3rdparty/libpng/mips/filter_msa_intrinsics.c index a579179421cc..1b734f4d9a7e 100644 --- a/3rdparty/libpng/mips/filter_msa_intrinsics.c +++ b/3rdparty/libpng/mips/filter_msa_intrinsics.c @@ -1,9 +1,9 @@ /* filter_msa_intrinsics.c - MSA optimised filter functions * - * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 2016 Glenn Randers-Pehrson - * Written by Mandar Sahastrabuddhe, August 2016. + * Written by Mandar Sahastrabuddhe, August 2016 * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -11,7 +11,6 @@ */ #include -#include #include "../pngpriv.h" #ifdef PNG_READ_SUPPORTED @@ -20,6 +19,7 @@ #if PNG_MIPS_MSA_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */ #include +#include /* libpng row pointers are not necessarily aligned to any particular boundary, * however this code will only work with appropriate alignment. mips/mips_init.c @@ -379,8 +379,8 @@ void png_read_filter_row_up_msa(png_row_infop row_info, png_bytep row, LD_UB4(pp, 16, src4, src5, src6, src7); pp += 64; - ADD4(src0, src4, src1, src5, src2, src6, src3, src7, - src0, src1, src2, src3); + ADD4(src0, src4, src1, src5, src2, src6, src3, src7, + src0, src1, src2, src3); ST_UB4(src0, src1, src2, src3, rp, 16); rp += 64; @@ -400,7 +400,7 @@ void png_read_filter_row_up_msa(png_row_infop row_info, png_bytep row, LD_UB4(pp, 16, src4, src5, src6, src7); ADD4(src0, src4, src1, src5, src2, src6, src3, src7, - src0, src1, src2, src3); + src0, src1, src2, src3); ST_UB4(src0, src1, src2, src3, rp, 16); rp += 64; @@ -425,7 +425,7 @@ void png_read_filter_row_up_msa(png_row_infop row_info, png_bytep row, LD_UB2(rp, 16, src0, src1); LD_UB2(pp, 16, src4, src5); - ADD2(src0, src4, src1, src5, src0, src1); + ADD2(src0, src4, src1, src5, src0, src1); ST_UB2(src0, src1, rp, 16); rp += 32; diff --git a/3rdparty/libpng/mips/mips_init.c b/3rdparty/libpng/mips/mips_init.c index 6a061cccfa77..5c6fa1dbf117 100644 --- a/3rdparty/libpng/mips/mips_init.c +++ b/3rdparty/libpng/mips/mips_init.c @@ -1,9 +1,10 @@ /* mips_init.c - MSA optimised filter functions * - * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 2016 Glenn Randers-Pehrson - * Written by Mandar Sahastrabuddhe, 2016. + * Written by Mandar Sahastrabuddhe, 2016 + * Updated by guxiwei, 2023 * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -20,8 +21,9 @@ #ifdef PNG_READ_SUPPORTED -#if PNG_MIPS_MSA_OPT > 0 -#ifdef PNG_MIPS_MSA_CHECK_SUPPORTED /* Do run-time checks */ +#if PNG_MIPS_MSA_IMPLEMENTATION == 1 || PNG_MIPS_MMI_IMPLEMENTATION > 0 + +#ifdef PNG_MIPS_MSA_CHECK_SUPPORTED /* Do MIPS MSA run-time checks */ /* WARNING: it is strongly recommended that you do not build libpng with * run-time checks for CPU features if at all possible. In the case of the MIPS * MSA instructions there is no processor-specific way of detecting the @@ -51,13 +53,83 @@ static int png_have_msa(png_structp png_ptr); #endif /* PNG_MIPS_MSA_FILE */ #endif /* PNG_MIPS_MSA_CHECK_SUPPORTED */ +#ifdef PNG_MIPS_MMI_CHECK_SUPPORTED /* Do MIPS MMI run-times checks */ +#ifndef PNG_MIPS_MMI_FILE +# ifdef __linux__ +# define PNG_MIPS_MMI_FILE "contrib/mips-mmi/linux.c" +# endif +#endif + +#ifdef PNG_MIPS_MMI_FILE + +#include /* for sig_atomic_t */ +static int png_have_mmi(); +#include PNG_MIPS_MMI_FILE + +#else /* PNG_MIPS_MMI_FILE */ +# error "PNG_MIPS_MMI_FILE undefined: no support for run-time MIPS MMI checks" +#endif /* PNG_MIPS_MMI_FILE */ +#endif /* PNG_MIPS_MMI_CHECK_SUPPORTED*/ + #ifndef PNG_ALIGNED_MEMORY_SUPPORTED # error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED" #endif +/* MIPS supports two optimizations: MMI and MSA. The appropriate + * optimization is chosen at runtime + */ void -png_init_filter_functions_msa(png_structp pp, unsigned int bpp) +png_init_filter_functions_mips(png_structp pp, unsigned int bpp) { +#if PNG_MIPS_MMI_IMPLEMENTATION > 0 +#ifdef PNG_MIPS_MMI_API_SUPPORTED + switch ((pp->options >> PNG_MIPS_MMI) & 3) + { + case PNG_OPTION_UNSET: +#endif /* PNG_MIPS_MMI_API_SUPPORTED */ +#ifdef PNG_MIPS_MMI_CHECK_SUPPORTED + { + static volatile sig_atomic_t no_mmi = -1; /* not checked */ + + if (no_mmi < 0) + no_mmi = !png_have_mmi(); + + if (no_mmi) + goto MIPS_MSA_INIT; + } +#ifdef PNG_MIPS_MMI_API_SUPPORTED + break; +#endif +#endif /* PNG_MIPS_MMI_CHECK_SUPPORTED */ + +#ifdef PNG_MIPS_MMI_API_SUPPORTED + default: /* OFF or INVALID */ + goto MIPS_MSA_INIT; + + case PNG_OPTION_ON: + /* Option turned on */ + break; + } +#endif + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_mmi; + if (bpp == 3) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_mmi; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_mmi; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth3_mmi; + } + else if (bpp == 4) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_mmi; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_mmi; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth4_mmi; + } +#endif /* PNG_MIPS_MMI_IMPLEMENTATION > 0 */ + +MIPS_MSA_INIT: +#if PNG_MIPS_MSA_IMPLEMENTATION == 1 /* The switch statement is compiled in for MIPS_MSA_API, the call to * png_have_msa is compiled in for MIPS_MSA_CHECK. If both are defined * the check is only performed if the API has not set the MSA option on @@ -73,6 +145,7 @@ png_init_filter_functions_msa(png_structp pp, unsigned int bpp) * this case will fall through to the 'default' below, which just * returns. */ +#endif /* PNG_MIPS_MSA_API_SUPPORTED */ #ifdef PNG_MIPS_MSA_CHECK_SUPPORTED { static volatile sig_atomic_t no_msa = -1; /* not checked */ @@ -83,9 +156,12 @@ png_init_filter_functions_msa(png_structp pp, unsigned int bpp) if (no_msa) return; } -#endif /* PNG_MIPS_MSA_CHECK_SUPPORTED */ +#ifdef PNG_MIPS_MSA_API_SUPPORTED break; +#endif +#endif /* PNG_MIPS_MSA_CHECK_SUPPORTED */ +#ifdef PNG_MIPS_MSA_API_SUPPORTED default: /* OFF or INVALID */ return; @@ -93,6 +169,8 @@ png_init_filter_functions_msa(png_structp pp, unsigned int bpp) /* Option turned on */ break; } +#endif + /* IMPORTANT: any new external functions used here must be declared using * PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the * 'prefix' option to configure works: @@ -112,16 +190,15 @@ png_init_filter_functions_msa(png_structp pp, unsigned int bpp) pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_msa; pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_msa; } + else if (bpp == 4) { pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_msa; pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_msa; pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_msa; } -#else - (void)pp; - (void)bpp; -#endif /* PNG_MIPS_MSA_API_SUPPORTED */ +#endif /* PNG_MIPS_MSA_IMPLEMENTATION == 1 */ + return; } -#endif /* PNG_MIPS_MSA_OPT > 0 */ +#endif /* PNG_MIPS_MSA_IMPLEMENTATION == 1 || PNG_MIPS_MMI_IMPLEMENTATION > 0 */ #endif /* READ */ diff --git a/3rdparty/libpng/patches/20190528-fix-leak-png_handle_exif.diff b/3rdparty/libpng/patches/20190528-fix-leak-png_handle_exif.diff deleted file mode 100644 index f2dbc4dd5e8f..000000000000 --- a/3rdparty/libpng/patches/20190528-fix-leak-png_handle_exif.diff +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/3rdparty/libpng/pngrutil.c b/3rdparty/libpng/pngrutil.c -index d5fa08c397..4db3de990b 100644 ---- a/3rdparty/libpng/pngrutil.c -+++ b/3rdparty/libpng/pngrutil.c -@@ -2087,10 +2087,8 @@ png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) - } - } - -- if (png_crc_finish(png_ptr, 0) != 0) -- return; -- -- png_set_eXIf_1(png_ptr, info_ptr, length, info_ptr->eXIf_buf); -+ if (png_crc_finish(png_ptr, 0) == 0) -+ png_set_eXIf_1(png_ptr, info_ptr, length, info_ptr->eXIf_buf); - - png_free(png_ptr, info_ptr->eXIf_buf); - info_ptr->eXIf_buf = NULL; diff --git a/3rdparty/libpng/patches/20190910-msa-patch.diff b/3rdparty/libpng/patches/20190910-msa-patch.diff deleted file mode 100644 index 42f49f991adb..000000000000 --- a/3rdparty/libpng/patches/20190910-msa-patch.diff +++ /dev/null @@ -1,53 +0,0 @@ -diff --git a/3rdparty/libpng/mips/mips_init.c b/3rdparty/libpng/mips/mips_init.c -index 8dd283deef..6a061cccfa 100644 ---- a/3rdparty/libpng/mips/mips_init.c -+++ b/3rdparty/libpng/mips/mips_init.c -@@ -73,7 +73,6 @@ png_init_filter_functions_msa(png_structp pp, unsigned int bpp) - * this case will fall through to the 'default' below, which just - * returns. - */ --#endif /* PNG_MIPS_MSA_API_SUPPORTED */ - #ifdef PNG_MIPS_MSA_CHECK_SUPPORTED - { - static volatile sig_atomic_t no_msa = -1; /* not checked */ -@@ -84,12 +83,9 @@ png_init_filter_functions_msa(png_structp pp, unsigned int bpp) - if (no_msa) - return; - } --#ifdef PNG_MIPS_MSA_API_SUPPORTED -- break; --#endif - #endif /* PNG_MIPS_MSA_CHECK_SUPPORTED */ -+ break; - --#ifdef PNG_MIPS_MSA_API_SUPPORTED - default: /* OFF or INVALID */ - return; - -@@ -97,8 +93,6 @@ png_init_filter_functions_msa(png_structp pp, unsigned int bpp) - /* Option turned on */ - break; - } --#endif -- - /* IMPORTANT: any new external functions used here must be declared using - * PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the - * 'prefix' option to configure works: -@@ -118,13 +112,16 @@ png_init_filter_functions_msa(png_structp pp, unsigned int bpp) - pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_msa; - pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_msa; - } -- - else if (bpp == 4) - { - pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_msa; - pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_msa; - pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_msa; - } -+#else -+ (void)pp; -+ (void)bpp; -+#endif /* PNG_MIPS_MSA_API_SUPPORTED */ - } - #endif /* PNG_MIPS_MSA_OPT > 0 */ - #endif /* READ */ diff --git a/3rdparty/libpng/png.c b/3rdparty/libpng/png.c index 757c755f97c9..9ed315700924 100644 --- a/3rdparty/libpng/png.c +++ b/3rdparty/libpng/png.c @@ -1,7 +1,7 @@ /* png.c - location for general purpose libpng functions * - * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -14,27 +14,7 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_37 Your_png_h_is_not_version_1_6_37; - -#ifdef __GNUC__ -/* The version tests may need to be added to, but the problem warning has - * consistently been fixed in GCC versions which obtain wide-spread release. - * The problem is that many versions of GCC rearrange comparison expressions in - * the optimizer in such a way that the results of the comparison will change - * if signed integer overflow occurs. Such comparisons are not permitted in - * ANSI C90, however GCC isn't clever enough to work out that that do not occur - * below in png_ascii_from_fp and png_muldiv, so it produces a warning with - * -Wextra. Unfortunately this is highly dependent on the optimizer and the - * machine architecture so the warning comes and goes unpredictably and is - * impossible to "fix", even were that a good idea. - */ -#if __GNUC__ == 7 && __GNUC_MINOR__ == 1 -#define GCC_STRICT_OVERFLOW 1 -#endif /* GNU 7.1.x */ -#endif /* GNU */ -#ifndef GCC_STRICT_OVERFLOW -#define GCC_STRICT_OVERFLOW 0 -#endif +typedef png_libpng_version_1_6_43 Your_png_h_is_not_version_1_6_43; /* Tells libpng that we have already handled the first "num_bytes" bytes * of the PNG file signature. If the PNG data is embedded into another @@ -73,21 +53,21 @@ png_set_sig_bytes(png_structrp png_ptr, int num_bytes) int PNGAPI png_sig_cmp(png_const_bytep sig, size_t start, size_t num_to_check) { - png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + static const png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; if (num_to_check > 8) num_to_check = 8; else if (num_to_check < 1) - return (-1); + return -1; if (start > 7) - return (-1); + return -1; if (start + num_to_check > 8) num_to_check = 8 - start; - return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check))); + return memcmp(&sig[start], &png_signature[start], num_to_check); } #endif /* READ */ @@ -447,7 +427,6 @@ png_info_init_3,(png_infopp ptr_ptr, size_t png_info_struct_size), memset(info_ptr, 0, (sizeof *info_ptr)); } -/* The following API is not called internally */ void PNGAPI png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr, int freer, png_uint_32 mask) @@ -686,9 +665,9 @@ png_voidp PNGAPI png_get_io_ptr(png_const_structrp png_ptr) { if (png_ptr == NULL) - return (NULL); + return NULL; - return (png_ptr->io_ptr); + return png_ptr->io_ptr; } #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) @@ -720,7 +699,7 @@ png_init_io(png_structrp png_ptr, png_FILE_p fp) * * Where UNSIGNED_MAX is the appropriate maximum unsigned value, so when the * negative integral value is added the result will be an unsigned value - * correspnding to the 2's complement representation. + * corresponding to the 2's complement representation. */ void PNGAPI png_save_int_32(png_bytep buf, png_int_32 i) @@ -752,7 +731,7 @@ png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime) { size_t pos = 0; - char number_buf[5]; /* enough for a four-digit year */ + char number_buf[5] = {0, 0, 0, 0, 0}; /* enough for a four-digit year */ # define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string)) # define APPEND_NUMBER(format, value)\ @@ -815,8 +794,8 @@ png_get_copyright(png_const_structrp png_ptr) return PNG_STRING_COPYRIGHT #else return PNG_STRING_NEWLINE \ - "libpng version 1.6.37" PNG_STRING_NEWLINE \ - "Copyright (c) 2018-2019 Cosmin Truta" PNG_STRING_NEWLINE \ + "libpng version 1.6.43" PNG_STRING_NEWLINE \ + "Copyright (c) 2018-2024 Cosmin Truta" PNG_STRING_NEWLINE \ "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \ PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ @@ -977,7 +956,7 @@ png_reset_zstream(png_structrp png_ptr) return Z_STREAM_ERROR; /* WARNING: this resets the window bits to the maximum! */ - return (inflateReset(&png_ptr->zstream)); + return inflateReset(&png_ptr->zstream); } #endif /* READ */ @@ -986,7 +965,7 @@ png_uint_32 PNGAPI png_access_version_number(void) { /* Version of *.c files used when building libpng */ - return((png_uint_32)PNG_LIBPNG_VER); + return (png_uint_32)PNG_LIBPNG_VER; } #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) @@ -1842,14 +1821,14 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, } # ifdef PNG_WARNINGS_SUPPORTED else - { - char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/ + { + char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114 */ - pos = png_safecat(message, (sizeof message), pos, - png_format_number(number, number+(sizeof number), - PNG_NUMBER_FORMAT_x, value)); - pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/ - } + pos = png_safecat(message, (sizeof message), pos, + png_format_number(number, number+(sizeof number), + PNG_NUMBER_FORMAT_x, value)); + pos = png_safecat(message, (sizeof message), pos, "h: "); /* +2 = 116 */ + } # endif /* The 'reason' is an arbitrary message, allow +79 maximum 195 */ pos = png_safecat(message, (sizeof message), pos, reason); @@ -2532,17 +2511,6 @@ png_colorspace_set_rgb_coefficients(png_structrp png_ptr) #endif /* COLORSPACE */ -#ifdef __GNUC__ -/* This exists solely to work round a warning from GNU C. */ -static int /* PRIVATE */ -png_gt(size_t a, size_t b) -{ - return a > b; -} -#else -# define png_gt(a,b) ((a) > (b)) -#endif - void /* PRIVATE */ png_check_IHDR(png_const_structrp png_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, @@ -2564,8 +2532,16 @@ png_check_IHDR(png_const_structrp png_ptr, error = 1; } - if (png_gt(((width + 7) & (~7U)), - ((PNG_SIZE_MAX + /* The bit mask on the first line below must be at least as big as a + * png_uint_32. "~7U" is not adequate on 16-bit systems because it will + * be an unsigned 16-bit value. Casting to (png_alloc_size_t) makes the + * type of the result at least as bit (in bits) as the RHS of the > operator + * which also avoids a common warning on 64-bit systems that the comparison + * of (png_uint_32) against the constant value on the RHS will always be + * false. + */ + if (((width + 7) & ~(png_alloc_size_t)7) > + (((PNG_SIZE_MAX - 48 /* big_row_buf hack */ - 1) /* filter byte */ / 8) /* 8-byte RGBA pixels */ @@ -2710,7 +2686,7 @@ png_check_IHDR(png_const_structrp png_ptr, int /* PRIVATE */ png_check_fp_number(png_const_charp string, size_t size, int *statep, - png_size_tp whereami) + size_t *whereami) { int state = *statep; size_t i = *whereami; @@ -2891,14 +2867,6 @@ png_pow10(int power) /* Function to format a floating point value in ASCII with a given * precision. */ -#if GCC_STRICT_OVERFLOW -#pragma GCC diagnostic push -/* The problem arises below with exp_b10, which can never overflow because it - * comes, originally, from frexp and is therefore limited to a range which is - * typically +/-710 (log2(DBL_MAX)/log2(DBL_MIN)). - */ -#pragma GCC diagnostic warning "-Wstrict-overflow=2" -#endif /* GCC_STRICT_OVERFLOW */ void /* PRIVATE */ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size, double fp, unsigned int precision) @@ -3220,10 +3188,6 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size, /* Here on buffer too small. */ png_error(png_ptr, "ASCII conversion buffer too small"); } -#if GCC_STRICT_OVERFLOW -#pragma GCC diagnostic pop -#endif /* GCC_STRICT_OVERFLOW */ - # endif /* FLOATING_POINT */ # ifdef PNG_FIXED_POINT_SUPPORTED @@ -3251,7 +3215,7 @@ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, if (num <= 0x80000000) /* else overflowed */ { unsigned int ndigits = 0, first = 16 /* flag value */; - char digits[10]; + char digits[10] = {0}; while (num) { @@ -3336,15 +3300,6 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text) * the nearest .00001). Overflow and divide by zero are signalled in * the result, a boolean - true on success, false on overflow. */ -#if GCC_STRICT_OVERFLOW /* from above */ -/* It is not obvious which comparison below gets optimized in such a way that - * signed overflow would change the result; looking through the code does not - * reveal any tests which have the form GCC complains about, so presumably the - * optimizer is moving an add or subtract into the 'if' somewhere. - */ -#pragma GCC diagnostic push -#pragma GCC diagnostic warning "-Wstrict-overflow=2" -#endif /* GCC_STRICT_OVERFLOW */ int png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, png_int_32 divisor) @@ -3459,9 +3414,6 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, return 0; } -#if GCC_STRICT_OVERFLOW -#pragma GCC diagnostic pop -#endif /* GCC_STRICT_OVERFLOW */ #endif /* READ_GAMMA || INCH_CONVERSIONS */ #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) diff --git a/3rdparty/libpng/png.h b/3rdparty/libpng/png.h index 139eb0dc0f36..83d390312606 100644 --- a/3rdparty/libpng/png.h +++ b/3rdparty/libpng/png.h @@ -1,9 +1,9 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.37 - April 14, 2019 + * libpng version 1.6.43 * - * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -15,7 +15,7 @@ * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger * libpng versions 0.97, January 1998, through 1.6.35, July 2018: * Glenn Randers-Pehrson - * libpng versions 1.6.36, December 2018, through 1.6.37, April 2019: + * libpng versions 1.6.36, December 2018, through 1.6.43, February 2024: * Cosmin Truta * See also "Contributing Authors", below. */ @@ -27,8 +27,8 @@ * PNG Reference Library License version 2 * --------------------------------------- * - * * Copyright (c) 1995-2019 The PNG Reference Library Authors. - * * Copyright (c) 2018-2019 Cosmin Truta. + * * Copyright (c) 1995-2024 The PNG Reference Library Authors. + * * Copyright (c) 2018-2024 Cosmin Truta. * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. * * Copyright (c) 1996-1997 Andreas Dilger. * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -239,7 +239,7 @@ * ... * 1.5.30 15 10530 15.so.15.30[.0] * ... - * 1.6.37 16 10637 16.so.16.37[.0] + * 1.6.43 16 10643 16.so.16.43[.0] * * Henceforth the source version will match the shared-library major and * minor numbers; the shared-library major version number will be used for @@ -255,9 +255,6 @@ * to the info_ptr or png_ptr members through png.h, and the compiled * application is loaded with a different version of the library. * - * DLLNUM will change each time there are forward or backward changes - * in binary compatibility (e.g., when a new feature is added). - * * See libpng.txt or libpng.3 for more information. The PNG specification * is available as a W3C Recommendation and as an ISO/IEC Standard; see * @@ -278,19 +275,21 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.37" -#define PNG_HEADER_VERSION_STRING " libpng version 1.6.37 - April 14, 2019\n" +#define PNG_LIBPNG_VER_STRING "1.6.43" +#define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n" -#define PNG_LIBPNG_VER_SONUM 16 -#define PNG_LIBPNG_VER_DLLNUM 16 +/* The versions of shared library builds should stay in sync, going forward */ +#define PNG_LIBPNG_VER_SHAREDLIB 16 +#define PNG_LIBPNG_VER_SONUM PNG_LIBPNG_VER_SHAREDLIB /* [Deprecated] */ +#define PNG_LIBPNG_VER_DLLNUM PNG_LIBPNG_VER_SHAREDLIB /* [Deprecated] */ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 6 -#define PNG_LIBPNG_VER_RELEASE 37 +#define PNG_LIBPNG_VER_RELEASE 43 /* This should be zero for a public release, or non-zero for a - * development version. [Deprecated] + * development version. */ #define PNG_LIBPNG_VER_BUILD 0 @@ -318,7 +317,7 @@ * From version 1.0.1 it is: * XXYYZZ, where XX=major, YY=minor, ZZ=release */ -#define PNG_LIBPNG_VER 10637 /* 1.6.37 */ +#define PNG_LIBPNG_VER 10643 /* 1.6.43 */ /* Library configuration: these options cannot be changed after * the library has been built. @@ -428,7 +427,7 @@ extern "C" { /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_6_37; +typedef char* png_libpng_version_1_6_43; /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. * @@ -849,7 +848,7 @@ PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); #define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ /* Added to libpng-1.5.4 */ #define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ -#if INT_MAX >= 0x8000 /* else this might break */ +#if ~0U > 0xffffU /* or else this might break on a 16-bit machine */ #define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ #endif @@ -908,15 +907,15 @@ PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); /* Check sig[start] through sig[start + num_to_check - 1] to see if it's a * PNG file. Returns zero if the supplied bytes match the 8-byte PNG * signature, and non-zero otherwise. Having num_to_check == 0 or - * start > 7 will always fail (ie return non-zero). + * start > 7 will always fail (i.e. return non-zero). */ PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start, size_t num_to_check)); /* Simple signature checking function. This is the same as calling - * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + * png_check_sig(sig, n) := (png_sig_cmp(sig, 0, n) == 0). */ -#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) +#define png_check_sig(sig, n) (png_sig_cmp((sig), 0, (n)) == 0) /* DEPRECATED */ /* Allocate and initialize png_ptr struct for reading, and any other memory. */ PNG_EXPORTA(4, png_structp, png_create_read_struct, @@ -1446,7 +1445,7 @@ PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, * mainly useful for testing, as the defaults should work with most users. * Those users who are tight on memory or want faster performance at the * expense of compression can modify them. See the compression library - * header file (zlib.h) for an explination of the compression functions. + * header file (zlib.h) for an explanation of the compression functions. */ /* Set the filtering method(s) used by libpng. Currently, the only valid @@ -1501,7 +1500,7 @@ PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 * (0 - no compression, 9 - "maximal" compression). Note that tests have * shown that zlib compression levels 3-6 usually perform as well as level 9 - * for PNG images, and do considerably fewer caclulations. In the future, + * for PNG images, and do considerably fewer calculations. In the future, * these values may not correspond directly to the zlib compression levels. */ #ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED @@ -1730,12 +1729,9 @@ PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr)); PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 free_me, int num)); -/* Reassign responsibility for freeing existing data, whether allocated +/* Reassign the responsibility for freeing existing data, whether allocated * by libpng or by the application; this works on the png_info structure passed - * in, it does not change the state for other png_info structures. - * - * It is unlikely that this function works correctly as of 1.6.0 and using it - * may result either in memory leaks or double free of allocated data. + * in, without changing the state for other png_info structures. */ PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, png_inforp info_ptr, int freer, png_uint_32 mask)); @@ -3207,11 +3203,18 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, #ifdef PNG_MIPS_MSA_API_SUPPORTED # define PNG_MIPS_MSA 6 /* HARDWARE: MIPS Msa SIMD instructions supported */ #endif -#define PNG_IGNORE_ADLER32 8 +#ifdef PNG_DISABLE_ADLER32_CHECK_SUPPORTED +# define PNG_IGNORE_ADLER32 8 /* SOFTWARE: disable Adler32 check on IDAT */ +#endif #ifdef PNG_POWERPC_VSX_API_SUPPORTED -# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions supported */ +# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions + * supported */ #endif -#define PNG_OPTION_NEXT 12 /* Next option - numbers must be even */ +#ifdef PNG_MIPS_MMI_API_SUPPORTED +# define PNG_MIPS_MMI 12 /* HARDWARE: MIPS MMI SIMD instructions supported */ +#endif + +#define PNG_OPTION_NEXT 14 /* Next option - numbers must be even */ /* Return values: NOTE: there are four values and 'off' is *not* zero */ #define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ diff --git a/3rdparty/libpng/pngconf.h b/3rdparty/libpng/pngconf.h index 927a769dbee8..000d7b1a8a6e 100644 --- a/3rdparty/libpng/pngconf.h +++ b/3rdparty/libpng/pngconf.h @@ -1,9 +1,9 @@ /* pngconf.h - machine-configurable file for libpng * - * libpng version 1.6.37 + * libpng version 1.6.43 * - * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -180,8 +180,8 @@ * compiler-specific macros to the values required to change the calling * conventions of the various functions. */ -#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ - defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \ + defined(__CYGWIN__) /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or * MinGW on any architecture currently supported by Windows. Also includes * Watcom builds but these need special treatment because they are not diff --git a/3rdparty/libpng/pngerror.c b/3rdparty/libpng/pngerror.c index ec3a709b9d2c..29ebda794377 100644 --- a/3rdparty/libpng/pngerror.c +++ b/3rdparty/libpng/pngerror.c @@ -1,7 +1,7 @@ /* pngerror.c - stub functions for i/o and memory allocation * - * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -255,7 +255,7 @@ void png_warning_parameter_unsigned(png_warning_parameters p, int number, int format, png_alloc_size_t value) { - char buffer[PNG_NUMBER_BUFFER_SIZE]; + char buffer[PNG_NUMBER_BUFFER_SIZE] = {0}; png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value)); } @@ -265,7 +265,7 @@ png_warning_parameter_signed(png_warning_parameters p, int number, int format, { png_alloc_size_t u; png_charp str; - char buffer[PNG_NUMBER_BUFFER_SIZE]; + char buffer[PNG_NUMBER_BUFFER_SIZE] = {0}; /* Avoid overflow by doing the negate in a png_alloc_size_t: */ u = (png_alloc_size_t)value; @@ -858,7 +858,7 @@ png_get_error_ptr(png_const_structrp png_ptr) if (png_ptr == NULL) return NULL; - return ((png_voidp)png_ptr->error_ptr); + return (png_voidp)png_ptr->error_ptr; } @@ -933,31 +933,25 @@ png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message) #endif int /* PRIVATE */ -png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg) +png_safe_execute(png_imagep image, int (*function)(png_voidp), png_voidp arg) { - volatile png_imagep image = image_in; - volatile int result; - volatile png_voidp saved_error_buf; + png_voidp saved_error_buf = image->opaque->error_buf; jmp_buf safe_jmpbuf; + int result; - /* Safely execute function(arg) with png_error returning to this function. */ - saved_error_buf = image->opaque->error_buf; - result = setjmp(safe_jmpbuf) == 0; - - if (result != 0) + /* Safely execute function(arg), with png_error returning back here. */ + if (setjmp(safe_jmpbuf) == 0) { - image->opaque->error_buf = safe_jmpbuf; result = function(arg); + image->opaque->error_buf = saved_error_buf; + return result; } + /* On png_error, return via longjmp, pop the jmpbuf, and free the image. */ image->opaque->error_buf = saved_error_buf; - - /* And do the cleanup prior to any failure return. */ - if (result == 0) - png_image_free(image); - - return result; + png_image_free(image); + return 0; } #endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */ #endif /* READ || WRITE */ diff --git a/3rdparty/libpng/pngget.c b/3rdparty/libpng/pngget.c index 5abf1efd9f73..1084b268ff90 100644 --- a/3rdparty/libpng/pngget.c +++ b/3rdparty/libpng/pngget.c @@ -1,7 +1,7 @@ /* pngget.c - retrieval of values from info struct * - * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -21,18 +21,29 @@ png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr, png_uint_32 flag) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->valid & flag); + { +#ifdef PNG_READ_tRNS_SUPPORTED + /* png_handle_PLTE() may have canceled a valid tRNS chunk but left the + * 'valid' flag for the detection of duplicate chunks. Do not report a + * valid tRNS chunk in this case. + */ + if (flag == PNG_INFO_tRNS && png_ptr->num_trans == 0) + return 0; +#endif - return(0); + return info_ptr->valid & flag; + } + + return 0; } size_t PNGAPI png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->rowbytes); + return info_ptr->rowbytes; - return(0); + return 0; } #ifdef PNG_INFO_IMAGE_SUPPORTED @@ -40,9 +51,9 @@ png_bytepp PNGAPI png_get_rows(png_const_structrp png_ptr, png_const_inforp info_ptr) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->row_pointers); + return info_ptr->row_pointers; - return(0); + return 0; } #endif @@ -54,7 +65,7 @@ png_get_image_width(png_const_structrp png_ptr, png_const_inforp info_ptr) if (png_ptr != NULL && info_ptr != NULL) return info_ptr->width; - return (0); + return 0; } png_uint_32 PNGAPI @@ -63,7 +74,7 @@ png_get_image_height(png_const_structrp png_ptr, png_const_inforp info_ptr) if (png_ptr != NULL && info_ptr != NULL) return info_ptr->height; - return (0); + return 0; } png_byte PNGAPI @@ -72,7 +83,7 @@ png_get_bit_depth(png_const_structrp png_ptr, png_const_inforp info_ptr) if (png_ptr != NULL && info_ptr != NULL) return info_ptr->bit_depth; - return (0); + return 0; } png_byte PNGAPI @@ -81,7 +92,7 @@ png_get_color_type(png_const_structrp png_ptr, png_const_inforp info_ptr) if (png_ptr != NULL && info_ptr != NULL) return info_ptr->color_type; - return (0); + return 0; } png_byte PNGAPI @@ -90,7 +101,7 @@ png_get_filter_type(png_const_structrp png_ptr, png_const_inforp info_ptr) if (png_ptr != NULL && info_ptr != NULL) return info_ptr->filter_type; - return (0); + return 0; } png_byte PNGAPI @@ -99,7 +110,7 @@ png_get_interlace_type(png_const_structrp png_ptr, png_const_inforp info_ptr) if (png_ptr != NULL && info_ptr != NULL) return info_ptr->interlace_type; - return (0); + return 0; } png_byte PNGAPI @@ -108,7 +119,7 @@ png_get_compression_type(png_const_structrp png_ptr, png_const_inforp info_ptr) if (png_ptr != NULL && info_ptr != NULL) return info_ptr->compression_type; - return (0); + return 0; } png_uint_32 PNGAPI @@ -116,21 +127,20 @@ png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr) { #ifdef PNG_pHYs_SUPPORTED + png_debug(1, "in png_get_x_pixels_per_meter"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0) - { - png_debug1(1, "in %s retrieval function", - "png_get_x_pixels_per_meter"); - - if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) - return (info_ptr->x_pixels_per_unit); - } + { + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) + return info_ptr->x_pixels_per_unit; + } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return (0); + return 0; } png_uint_32 PNGAPI @@ -138,42 +148,41 @@ png_get_y_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr) { #ifdef PNG_pHYs_SUPPORTED + png_debug(1, "in png_get_y_pixels_per_meter"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0) { - png_debug1(1, "in %s retrieval function", - "png_get_y_pixels_per_meter"); - if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) - return (info_ptr->y_pixels_per_unit); + return info_ptr->y_pixels_per_unit; } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return (0); + return 0; } png_uint_32 PNGAPI png_get_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr) { #ifdef PNG_pHYs_SUPPORTED + png_debug(1, "in png_get_pixels_per_meter"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0) { - png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter"); - if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER && info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit) - return (info_ptr->x_pixels_per_unit); + return info_ptr->x_pixels_per_unit; } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return (0); + return 0; } #ifdef PNG_FLOATING_POINT_SUPPORTED @@ -182,21 +191,21 @@ png_get_pixel_aspect_ratio(png_const_structrp png_ptr, png_const_inforp info_ptr) { #ifdef PNG_READ_pHYs_SUPPORTED + png_debug(1, "in png_get_pixel_aspect_ratio"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0) { - png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio"); - if (info_ptr->x_pixels_per_unit != 0) - return ((float)((float)info_ptr->y_pixels_per_unit - /(float)info_ptr->x_pixels_per_unit)); + return (float)info_ptr->y_pixels_per_unit + / (float)info_ptr->x_pixels_per_unit; } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return ((float)0.0); + return (float)0.0; } #endif @@ -206,6 +215,8 @@ png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr) { #ifdef PNG_READ_pHYs_SUPPORTED + png_debug(1, "in png_get_pixel_aspect_ratio_fixed"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0 && info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 && @@ -214,8 +225,6 @@ png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr, { png_fixed_point res; - png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed"); - /* The following casts work because a PNG 4 byte integer only has a valid * range of 0..2^31-1; otherwise the cast might overflow. */ @@ -236,80 +245,80 @@ png_int_32 PNGAPI png_get_x_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr) { #ifdef PNG_oFFs_SUPPORTED + png_debug(1, "in png_get_x_offset_microns"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0) { - png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns"); - if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) - return (info_ptr->x_offset); + return info_ptr->x_offset; } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return (0); + return 0; } png_int_32 PNGAPI png_get_y_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr) { #ifdef PNG_oFFs_SUPPORTED + png_debug(1, "in png_get_y_offset_microns"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0) { - png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns"); - if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) - return (info_ptr->y_offset); + return info_ptr->y_offset; } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return (0); + return 0; } png_int_32 PNGAPI png_get_x_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr) { #ifdef PNG_oFFs_SUPPORTED + png_debug(1, "in png_get_x_offset_pixels"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0) { - png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels"); - if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) - return (info_ptr->x_offset); + return info_ptr->x_offset; } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return (0); + return 0; } png_int_32 PNGAPI png_get_y_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr) { #ifdef PNG_oFFs_SUPPORTED + png_debug(1, "in png_get_y_offset_pixels"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0) { - png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels"); - if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) - return (info_ptr->y_offset); + return info_ptr->y_offset; } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return (0); + return 0; } #ifdef PNG_INCH_CONVERSIONS_SUPPORTED @@ -423,11 +432,11 @@ png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr, { png_uint_32 retval = 0; + png_debug1(1, "in %s retrieval function", "pHYs"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0) { - png_debug1(1, "in %s retrieval function", "pHYs"); - if (res_x != NULL) { *res_x = info_ptr->x_pixels_per_unit; @@ -453,7 +462,7 @@ png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr, } } - return (retval); + return retval; } #endif /* pHYs */ #endif /* INCH_CONVERSIONS */ @@ -467,9 +476,9 @@ png_byte PNGAPI png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->channels); + return info_ptr->channels; - return (0); + return 0; } #ifdef PNG_READ_SUPPORTED @@ -477,9 +486,9 @@ png_const_bytep PNGAPI png_get_signature(png_const_structrp png_ptr, png_const_inforp info_ptr) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->signature); + return info_ptr->signature; - return (NULL); + return NULL; } #endif @@ -488,17 +497,17 @@ png_uint_32 PNGAPI png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr, png_color_16p *background) { + png_debug1(1, "in %s retrieval function", "bKGD"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0 && background != NULL) { - png_debug1(1, "in %s retrieval function", "bKGD"); - *background = &(info_ptr->background); - return (PNG_INFO_bKGD); + return PNG_INFO_bKGD; } - return (0); + return 0; } #endif @@ -513,6 +522,8 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x, double *red_y, double *green_x, double *green_y, double *blue_x, double *blue_y) { + png_debug1(1, "in %s retrieval function", "cHRM"); + /* Quiet API change: this code used to only return the end points if a cHRM * chunk was present, but the end points can also come from iCCP or sRGB * chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and @@ -522,8 +533,6 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr, if (png_ptr != NULL && info_ptr != NULL && (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) { - png_debug1(1, "in %s retrieval function", "cHRM"); - if (white_x != NULL) *white_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.whitex, "cHRM white X"); @@ -548,10 +557,10 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr, if (blue_y != NULL) *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey, "cHRM blue Y"); - return (PNG_INFO_cHRM); + return PNG_INFO_cHRM; } - return (0); + return 0; } png_uint_32 PNGAPI @@ -560,11 +569,11 @@ png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr, double *green_Y, double *green_Z, double *blue_X, double *blue_Y, double *blue_Z) { + png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) { - png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)"); - if (red_X != NULL) *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X, "cHRM red X"); @@ -592,10 +601,10 @@ png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr, if (blue_Z != NULL) *blue_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z"); - return (PNG_INFO_cHRM); + return PNG_INFO_cHRM; } - return (0); + return 0; } # endif @@ -608,11 +617,11 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, png_fixed_point *int_blue_Z) { + png_debug1(1, "in %s retrieval function", "cHRM_XYZ"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) { - png_debug1(1, "in %s retrieval function", "cHRM_XYZ"); - if (int_red_X != NULL) *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X; if (int_red_Y != NULL) @@ -631,10 +640,10 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y; if (int_blue_Z != NULL) *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z; - return (PNG_INFO_cHRM); + return PNG_INFO_cHRM; } - return (0); + return 0; } png_uint_32 PNGAPI @@ -664,10 +673,10 @@ png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, *blue_x = info_ptr->colorspace.end_points_xy.bluex; if (blue_y != NULL) *blue_y = info_ptr->colorspace.end_points_xy.bluey; - return (PNG_INFO_cHRM); + return PNG_INFO_cHRM; } - return (0); + return 0; } # endif #endif @@ -685,10 +694,10 @@ png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, file_gamma != NULL) { *file_gamma = info_ptr->colorspace.gamma; - return (PNG_INFO_gAMA); + return PNG_INFO_gAMA; } - return (0); + return 0; } # endif @@ -705,10 +714,10 @@ png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr, { *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma, "png_get_gAMA"); - return (PNG_INFO_gAMA); + return PNG_INFO_gAMA; } - return (0); + return 0; } # endif #endif @@ -724,10 +733,10 @@ png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr, (info_ptr->valid & PNG_INFO_sRGB) != 0 && file_srgb_intent != NULL) { *file_srgb_intent = info_ptr->colorspace.rendering_intent; - return (PNG_INFO_sRGB); + return PNG_INFO_sRGB; } - return (0); + return 0; } #endif @@ -751,10 +760,10 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, */ if (compression_type != NULL) *compression_type = PNG_COMPRESSION_TYPE_BASE; - return (PNG_INFO_iCCP); + return PNG_INFO_iCCP; } - return (0); + return 0; } #endif @@ -764,13 +773,15 @@ int PNGAPI png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr, png_sPLT_tpp spalettes) { + png_debug1(1, "in %s retrieval function", "sPLT"); + if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) { *spalettes = info_ptr->splt_palettes; return info_ptr->splt_palettes_num; } - return (0); + return 0; } #endif @@ -796,10 +807,10 @@ png_get_eXIf_1(png_const_structrp png_ptr, png_const_inforp info_ptr, { *num_exif = info_ptr->num_exif; *exif = info_ptr->exif; - return (PNG_INFO_eXIf); + return PNG_INFO_eXIf; } - return (0); + return 0; } #endif @@ -814,10 +825,10 @@ png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr, (info_ptr->valid & PNG_INFO_hIST) != 0 && hist != NULL) { *hist = info_ptr->hist; - return (PNG_INFO_hIST); + return PNG_INFO_hIST; } - return (0); + return 0; } #endif @@ -830,7 +841,7 @@ png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr, png_debug1(1, "in %s retrieval function", "IHDR"); if (png_ptr == NULL || info_ptr == NULL) - return (0); + return 0; if (width != NULL) *width = info_ptr->width; @@ -862,7 +873,7 @@ png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr, info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, info_ptr->compression_type, info_ptr->filter_type); - return (1); + return 1; } #ifdef PNG_oFFs_SUPPORTED @@ -879,10 +890,10 @@ png_get_oFFs(png_const_structrp png_ptr, png_const_inforp info_ptr, *offset_x = info_ptr->x_offset; *offset_y = info_ptr->y_offset; *unit_type = (int)info_ptr->offset_unit_type; - return (PNG_INFO_oFFs); + return PNG_INFO_oFFs; } - return (0); + return 0; } #endif @@ -906,10 +917,10 @@ png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, *nparams = (int)info_ptr->pcal_nparams; *units = info_ptr->pcal_units; *params = info_ptr->pcal_params; - return (PNG_INFO_pCAL); + return PNG_INFO_pCAL; } - return (0); + return 0; } #endif @@ -921,6 +932,8 @@ png_uint_32 PNGAPI png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, png_fixed_point *width, png_fixed_point *height) { + png_debug1(1, "in %s retrieval function", "sCAL"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL) != 0) { @@ -932,10 +945,10 @@ png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width"); *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height), "sCAL height"); - return (PNG_INFO_sCAL); + return PNG_INFO_sCAL; } - return(0); + return 0; } # endif /* FLOATING_ARITHMETIC */ # endif /* FIXED_POINT */ @@ -944,32 +957,36 @@ png_uint_32 PNGAPI png_get_sCAL(png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, double *width, double *height) { + png_debug1(1, "in %s retrieval function", "sCAL(float)"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL) != 0) { *unit = info_ptr->scal_unit; *width = atof(info_ptr->scal_s_width); *height = atof(info_ptr->scal_s_height); - return (PNG_INFO_sCAL); + return PNG_INFO_sCAL; } - return(0); + return 0; } # endif /* FLOATING POINT */ png_uint_32 PNGAPI png_get_sCAL_s(png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, png_charpp width, png_charpp height) { + png_debug1(1, "in %s retrieval function", "sCAL(str)"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL) != 0) { *unit = info_ptr->scal_unit; *width = info_ptr->scal_s_width; *height = info_ptr->scal_s_height; - return (PNG_INFO_sCAL); + return PNG_INFO_sCAL; } - return(0); + return 0; } #endif /* sCAL */ @@ -1004,7 +1021,7 @@ png_get_pHYs(png_const_structrp png_ptr, png_const_inforp info_ptr, } } - return (retval); + return retval; } #endif /* pHYs */ @@ -1020,10 +1037,10 @@ png_get_PLTE(png_const_structrp png_ptr, png_inforp info_ptr, *palette = info_ptr->palette; *num_palette = info_ptr->num_palette; png_debug1(3, "num_palette = %d", *num_palette); - return (PNG_INFO_PLTE); + return PNG_INFO_PLTE; } - return (0); + return 0; } #ifdef PNG_sBIT_SUPPORTED @@ -1037,10 +1054,10 @@ png_get_sBIT(png_const_structrp png_ptr, png_inforp info_ptr, (info_ptr->valid & PNG_INFO_sBIT) != 0 && sig_bit != NULL) { *sig_bit = &(info_ptr->sig_bit); - return (PNG_INFO_sBIT); + return PNG_INFO_sBIT; } - return (0); + return 0; } #endif @@ -1051,7 +1068,7 @@ png_get_text(png_const_structrp png_ptr, png_inforp info_ptr, { if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) { - png_debug1(1, "in 0x%lx retrieval function", + png_debug1(1, "in text retrieval function, chunk typeid = 0x%lx", (unsigned long)png_ptr->chunk_name); if (text_ptr != NULL) @@ -1066,7 +1083,7 @@ png_get_text(png_const_structrp png_ptr, png_inforp info_ptr, if (num_text != NULL) *num_text = 0; - return(0); + return 0; } #endif @@ -1081,10 +1098,10 @@ png_get_tIME(png_const_structrp png_ptr, png_inforp info_ptr, (info_ptr->valid & PNG_INFO_tIME) != 0 && mod_time != NULL) { *mod_time = &(info_ptr->mod_time); - return (PNG_INFO_tIME); + return PNG_INFO_tIME; } - return (0); + return 0; } #endif @@ -1094,11 +1111,12 @@ png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color) { png_uint_32 retval = 0; + + png_debug1(1, "in %s retrieval function", "tRNS"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0) { - png_debug1(1, "in %s retrieval function", "tRNS"); - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { if (trans_alpha != NULL) @@ -1130,7 +1148,7 @@ png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr, } } - return (retval); + return retval; } #endif @@ -1145,13 +1163,13 @@ png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr, return info_ptr->unknown_chunks_num; } - return (0); + return 0; } #endif #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED png_byte PNGAPI -png_get_rgb_to_gray_status (png_const_structrp png_ptr) +png_get_rgb_to_gray_status(png_const_structrp png_ptr) { return (png_byte)(png_ptr ? png_ptr->rgb_to_gray_status : 0); } @@ -1192,27 +1210,27 @@ png_get_compression_buffer_size(png_const_structrp png_ptr) /* These functions were added to libpng 1.2.6 and were enabled * by default in libpng-1.4.0 */ png_uint_32 PNGAPI -png_get_user_width_max (png_const_structrp png_ptr) +png_get_user_width_max(png_const_structrp png_ptr) { return (png_ptr ? png_ptr->user_width_max : 0); } png_uint_32 PNGAPI -png_get_user_height_max (png_const_structrp png_ptr) +png_get_user_height_max(png_const_structrp png_ptr) { return (png_ptr ? png_ptr->user_height_max : 0); } /* This function was added to libpng 1.4.0 */ png_uint_32 PNGAPI -png_get_chunk_cache_max (png_const_structrp png_ptr) +png_get_chunk_cache_max(png_const_structrp png_ptr) { return (png_ptr ? png_ptr->user_chunk_cache_max : 0); } /* This function was added to libpng 1.4.1 */ png_alloc_size_t PNGAPI -png_get_chunk_malloc_max (png_const_structrp png_ptr) +png_get_chunk_malloc_max(png_const_structrp png_ptr) { return (png_ptr ? png_ptr->user_chunk_malloc_max : 0); } @@ -1221,13 +1239,13 @@ png_get_chunk_malloc_max (png_const_structrp png_ptr) /* These functions were added to libpng 1.4.0 */ #ifdef PNG_IO_STATE_SUPPORTED png_uint_32 PNGAPI -png_get_io_state (png_const_structrp png_ptr) +png_get_io_state(png_const_structrp png_ptr) { return png_ptr->io_state; } png_uint_32 PNGAPI -png_get_io_chunk_type (png_const_structrp png_ptr) +png_get_io_chunk_type(png_const_structrp png_ptr) { return png_ptr->chunk_name; } @@ -1241,7 +1259,7 @@ png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr) if (png_ptr != NULL && info_ptr != NULL) return png_ptr->num_palette_max; - return (-1); + return -1; } # endif #endif diff --git a/3rdparty/libpng/pngpread.c b/3rdparty/libpng/pngpread.c index e283627b77cd..ffab19c08c06 100644 --- a/3rdparty/libpng/pngpread.c +++ b/3rdparty/libpng/pngpread.c @@ -1,7 +1,7 @@ /* pngpread.c - read a png file in push mode * - * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -145,10 +145,10 @@ png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) num_to_check); png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check); - if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0) { if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4) != 0) png_error(png_ptr, "Not a PNG file"); else @@ -294,6 +294,14 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); } +#endif +#ifdef PNG_READ_eXIf_SUPPORTED + else if (png_ptr->chunk_name == png_eXIf) + { + PNG_PUSH_SAVE_BUFFER_IF_FULL + png_handle_eXIf(png_ptr, info_ptr, png_ptr->push_length); + } + #endif #ifdef PNG_READ_sRGB_SUPPORTED else if (chunk_name == png_sRGB) @@ -1089,7 +1097,7 @@ png_voidp PNGAPI png_get_progressive_ptr(png_const_structrp png_ptr) { if (png_ptr == NULL) - return (NULL); + return NULL; return png_ptr->io_ptr; } diff --git a/3rdparty/libpng/pngpriv.h b/3rdparty/libpng/pngpriv.h index 583c26f9bdec..9bfdb7134218 100644 --- a/3rdparty/libpng/pngpriv.h +++ b/3rdparty/libpng/pngpriv.h @@ -1,7 +1,7 @@ /* pngpriv.h - private declarations for use inside libpng * - * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -36,7 +36,7 @@ * still required (as of 2011-05-02.) */ #ifndef _POSIX_SOURCE -# define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ +# define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ #endif #ifndef PNG_VERSION_INFO_ONLY @@ -174,7 +174,7 @@ # else /* !defined __ARM_NEON__ */ /* The 'intrinsics' code simply won't compile without this -mfpu=neon: */ -# if !defined(__aarch64__) +# if !defined(__aarch64__) && !defined(_M_ARM64) /* The assembler code currently does not work on ARM64 */ # define PNG_ARM_NEON_IMPLEMENTATION 2 # endif /* __aarch64__ */ @@ -185,16 +185,32 @@ /* Use the intrinsics code by default. */ # define PNG_ARM_NEON_IMPLEMENTATION 1 # endif +#else /* PNG_ARM_NEON_OPT == 0 */ +# define PNG_ARM_NEON_IMPLEMENTATION 0 #endif /* PNG_ARM_NEON_OPT > 0 */ #ifndef PNG_MIPS_MSA_OPT -# if defined(__mips_msa) && (__mips_isa_rev >= 5) && defined(PNG_ALIGNED_MEMORY_SUPPORTED) +# if defined(__mips_msa) && (__mips_isa_rev >= 5) && \ + defined(PNG_ALIGNED_MEMORY_SUPPORTED) # define PNG_MIPS_MSA_OPT 2 # else # define PNG_MIPS_MSA_OPT 0 # endif #endif +#ifndef PNG_MIPS_MMI_OPT +# ifdef PNG_MIPS_MMI +# if defined(__mips_loongson_mmi) && (_MIPS_SIM == _ABI64) && \ + defined(PNG_ALIGNED_MEMORY_SUPPORTED) +# define PNG_MIPS_MMI_OPT 1 +# else +# define PNG_MIPS_MMI_OPT 0 +# endif +# else +# define PNG_MIPS_MMI_OPT 0 +# endif +#endif + #ifndef PNG_POWERPC_VSX_OPT # if defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__) # define PNG_POWERPC_VSX_OPT 2 @@ -203,13 +219,21 @@ # endif #endif +#ifndef PNG_LOONGARCH_LSX_OPT +# if defined(__loongarch_sx) +# define PNG_LOONGARCH_LSX_OPT 1 +# else +# define PNG_LOONGARCH_LSX_OPT 0 +# endif +#endif + #ifndef PNG_INTEL_SSE_OPT # ifdef PNG_INTEL_SSE /* Only check for SSE if the build configuration has been modified to * enable SSE optimizations. This means that these optimizations will * be off by default. See contrib/intel for more details. */ -# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \ +# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \ defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ (defined(_M_IX86_FP) && _M_IX86_FP >= 2) # define PNG_INTEL_SSE_OPT 1 @@ -246,7 +270,6 @@ #endif #if PNG_MIPS_MSA_OPT > 0 -# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_msa # ifndef PNG_MIPS_MSA_IMPLEMENTATION # if defined(__mips_msa) # if defined(__clang__) @@ -262,14 +285,41 @@ # ifndef PNG_MIPS_MSA_IMPLEMENTATION # define PNG_MIPS_MSA_IMPLEMENTATION 1 +# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_mips # endif +#else +# define PNG_MIPS_MSA_IMPLEMENTATION 0 #endif /* PNG_MIPS_MSA_OPT > 0 */ +#if PNG_MIPS_MMI_OPT > 0 +# ifndef PNG_MIPS_MMI_IMPLEMENTATION +# if defined(__mips_loongson_mmi) && (_MIPS_SIM == _ABI64) +# define PNG_MIPS_MMI_IMPLEMENTATION 2 +# else /* !defined __mips_loongson_mmi || _MIPS_SIM != _ABI64 */ +# define PNG_MIPS_MMI_IMPLEMENTATION 0 +# endif /* __mips_loongson_mmi && _MIPS_SIM == _ABI64 */ +# endif /* !PNG_MIPS_MMI_IMPLEMENTATION */ + +# if PNG_MIPS_MMI_IMPLEMENTATION > 0 +# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_mips +# endif +#else +# define PNG_MIPS_MMI_IMPLEMENTATION 0 +#endif /* PNG_MIPS_MMI_OPT > 0 */ + #if PNG_POWERPC_VSX_OPT > 0 # define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_vsx # define PNG_POWERPC_VSX_IMPLEMENTATION 1 +#else +# define PNG_POWERPC_VSX_IMPLEMENTATION 0 #endif +#if PNG_LOONGARCH_LSX_OPT > 0 +# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_lsx +# define PNG_LOONGARCH_LSX_IMPLEMENTATION 1 +#else +# define PNG_LOONGARCH_LSX_IMPLEMENTATION 0 +#endif /* Is this a build of a DLL where compilation of the object modules requires * different preprocessor settings to those required for a simple library? If @@ -492,16 +542,7 @@ static_cast(static_cast(value)) #else # define png_voidcast(type, value) (value) -# ifdef _WIN64 -# ifdef __GNUC__ - typedef unsigned long long png_ptruint; -# else - typedef unsigned __int64 png_ptruint; -# endif -# else - typedef unsigned long png_ptruint; -# endif -# define png_constcast(type, value) ((type)(png_ptruint)(const void*)(value)) +# define png_constcast(type, value) ((type)(void*)(const void*)(value)) # define png_aligncast(type, value) ((void*)(value)) # define png_aligncastconst(type, value) ((const void*)(value)) #endif /* __cplusplus */ @@ -517,18 +558,8 @@ */ # include -# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ - defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) - /* We need to check that hasn't already been included earlier - * as it seems it doesn't agree with , yet we should really use - * if possible. - */ -# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) -# include -# endif -# else -# include -# endif +# include + # if defined(_AMIGA) && defined(__SASC) && defined(_M68881) /* Amiga SAS/C: We must include builtin FPU functions when compiling using * MATH=68881 @@ -543,9 +574,8 @@ # include #endif -#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \ - defined(_WIN32) || defined(__WIN32__) -# include /* defines _WINDOWS_ macro */ +#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__) +# include #endif #endif /* PNG_VERSION_INFO_ONLY */ @@ -554,24 +584,20 @@ * functions that are passed far data must be model-independent. */ -/* Memory model/platform independent fns */ +/* Platform-independent functions */ #ifndef PNG_ABORT -# ifdef _WINDOWS_ -# define PNG_ABORT() ExitProcess(0) -# else -# define PNG_ABORT() abort() -# endif +# define PNG_ABORT() abort() #endif /* These macros may need to be architecture dependent. */ -#define PNG_ALIGN_NONE 0 /* do not use data alignment */ -#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */ +#define PNG_ALIGN_NONE 0 /* do not use data alignment */ +#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */ #ifdef offsetof -# define PNG_ALIGN_OFFSET 2 /* use offsetof to determine alignment */ +# define PNG_ALIGN_OFFSET 2 /* use offsetof to determine alignment */ #else # define PNG_ALIGN_OFFSET -1 /* prevent the use of this */ #endif -#define PNG_ALIGN_SIZE 3 /* use sizeof to determine alignment */ +#define PNG_ALIGN_SIZE 3 /* use sizeof to determine alignment */ #ifndef PNG_ALIGN_TYPE /* Default to using aligned access optimizations and requiring alignment to a @@ -585,26 +611,25 @@ /* This is used because in some compiler implementations non-aligned * structure members are supported, so the offsetof approach below fails. * Set PNG_ALIGN_SIZE=0 for compiler combinations where unaligned access - * is good for performance. Do not do this unless you have tested the result - * and understand it. + * is good for performance. Do not do this unless you have tested the + * result and understand it. */ -# define png_alignof(type) (sizeof (type)) +# define png_alignof(type) (sizeof(type)) #else # if PNG_ALIGN_TYPE == PNG_ALIGN_OFFSET -# define png_alignof(type) offsetof(struct{char c; type t;}, t) +# define png_alignof(type) offsetof(struct{char c; type t;}, t) # else -# if PNG_ALIGN_TYPE == PNG_ALIGN_ALWAYS -# define png_alignof(type) (1) -# endif - /* Else leave png_alignof undefined to prevent use thereof */ +# if PNG_ALIGN_TYPE == PNG_ALIGN_ALWAYS +# define png_alignof(type) 1 +# endif + /* Else leave png_alignof undefined to prevent use thereof */ # endif #endif -/* This implicitly assumes alignment is always to a power of 2. */ +/* This implicitly assumes alignment is always a multiple of 2. */ #ifdef png_alignof -# define png_isaligned(ptr, type)\ - (((type)((const char*)ptr-(const char*)0) & \ - (type)(png_alignof(type)-1)) == 0) +# define png_isaligned(ptr, type) \ + (((type)(size_t)((const void*)(ptr)) & (type)(png_alignof(type)-1)) == 0) #else # define png_isaligned(ptr, type) 0 #endif @@ -635,7 +660,7 @@ #define PNG_BACKGROUND_IS_GRAY 0x800U #define PNG_HAVE_PNG_SIGNATURE 0x1000U #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */ - /* 0x4000U (unused) */ +#define PNG_WROTE_eXIf 0x4000U #define PNG_IS_READ_STRUCT 0x8000U /* Else is a write struct */ /* Flags for the transformations the PNG library does on the image data */ @@ -1315,7 +1340,7 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); #endif -#if PNG_MIPS_MSA_OPT > 0 +#if PNG_MIPS_MSA_IMPLEMENTATION == 1 PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_msa,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_msa,(png_row_infop @@ -1332,6 +1357,23 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_msa,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); #endif +#if PNG_MIPS_MMI_IMPLEMENTATION > 0 +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_mmi,(png_row_infop row_info, + png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_mmi,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_mmi,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_mmi,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_mmi,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_mmi,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_mmi,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +#endif + #if PNG_POWERPC_VSX_OPT > 0 PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_vsx,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); @@ -1364,6 +1406,23 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); #endif +#if PNG_LOONGARCH_LSX_IMPLEMENTATION == 1 +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_lsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_lsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_lsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_lsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_lsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_lsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_lsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +#endif + /* Choose the best filter to use and filter the row data */ PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr, png_row_infop row_info),PNG_EMPTY); @@ -1919,7 +1978,7 @@ PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, */ #define PNG_FP_INVALID 512 /* Available for callers as a distinct value */ -/* Result codes for the parser (boolean - true meants ok, false means +/* Result codes for the parser (boolean - true means ok, false means * not ok yet.) */ #define PNG_FP_MAYBE 0 /* The number may be valid in the future */ @@ -1955,7 +2014,7 @@ PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, * the problem character.) This has not been tested within libpng. */ PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string, - size_t size, int *statep, png_size_tp whereami),PNG_EMPTY); + size_t size, int *statep, size_t *whereami),PNG_EMPTY); /* This is the same but it checks a complete string and returns true * only if it just contains a floating point number. As of 1.5.4 this @@ -2103,17 +2162,27 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); #endif -#if PNG_MIPS_MSA_OPT > 0 -PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_msa, +#if PNG_MIPS_MSA_IMPLEMENTATION == 1 +PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_mips, (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); #endif +# if PNG_MIPS_MMI_IMPLEMENTATION > 0 +PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_mips, + (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); +# endif + # if PNG_INTEL_SSE_IMPLEMENTATION > 0 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); # endif #endif +#if PNG_LOONGARCH_LSX_OPT > 0 +PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_lsx, + (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); +#endif + PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr, png_const_charp key, png_bytep new_key), PNG_EMPTY); diff --git a/3rdparty/libpng/pngread.c b/3rdparty/libpng/pngread.c index 8fa7d9f1628f..07a39df6e2e3 100644 --- a/3rdparty/libpng/pngread.c +++ b/3rdparty/libpng/pngread.c @@ -1,7 +1,7 @@ /* pngread.c - read a PNG file * - * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -568,7 +568,11 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) #endif #ifdef PNG_READ_TRANSFORMS_SUPPORTED - if (png_ptr->transformations) + if (png_ptr->transformations +# ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED + || png_ptr->num_palette_max >= 0 +# endif + ) png_do_read_transformations(png_ptr, &row_info); #endif @@ -785,7 +789,7 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED /* Report invalid palette index; added at libng-1.5.10 */ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - png_ptr->num_palette_max > png_ptr->num_palette) + png_ptr->num_palette_max >= png_ptr->num_palette) png_benign_error(png_ptr, "Read palette index exceeding num_palette"); #endif @@ -1049,6 +1053,8 @@ void PNGAPI png_read_png(png_structrp png_ptr, png_inforp info_ptr, int transforms, voidp params) { + png_debug(1, "in png_read_png"); + if (png_ptr == NULL || info_ptr == NULL) return; @@ -3452,7 +3458,6 @@ png_image_read_background(png_voidp argument) for (pass = 0; pass < passes; ++pass) { - png_bytep row = png_voidcast(png_bytep, display->first_row); unsigned int startx, stepx, stepy; png_uint_32 y; @@ -3557,8 +3562,6 @@ png_image_read_background(png_voidp argument) inrow += 2; /* gray and alpha channel */ } - - row += display->row_bytes; } } } @@ -3765,13 +3768,13 @@ png_image_read_direct(png_voidp argument) mode = PNG_ALPHA_PNG; output_gamma = PNG_DEFAULT_sRGB; } - + if ((change & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) { mode = PNG_ALPHA_OPTIMIZED; change &= ~PNG_FORMAT_FLAG_ASSOCIATED_ALPHA; } - + /* If 'do_local_background' is set check for the presence of gamma * correction; this is part of the work-round for the libpng bug * described above. diff --git a/3rdparty/libpng/pngrtran.c b/3rdparty/libpng/pngrtran.c index 9a8fad9f4aa7..1526123e025c 100644 --- a/3rdparty/libpng/pngrtran.c +++ b/3rdparty/libpng/pngrtran.c @@ -1,7 +1,7 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -21,7 +21,7 @@ #ifdef PNG_ARM_NEON_IMPLEMENTATION # if PNG_ARM_NEON_IMPLEMENTATION == 1 # define PNG_ARM_NEON_INTRINSICS_AVAILABLE -# if defined(_MSC_VER) && defined(_M_ARM64) +# if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64) # include # else # include @@ -290,21 +290,20 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, int compose = 0; png_fixed_point file_gamma; - png_debug(1, "in png_set_alpha_mode"); + png_debug(1, "in png_set_alpha_mode_fixed"); if (png_rtran_ok(png_ptr, 0) == 0) return; output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/); - /* Validate the value to ensure it is in a reasonable range. The value + /* Validate the value to ensure it is in a reasonable range. The value * is expected to be 1 or greater, but this range test allows for some - * viewing correction values. The intent is to weed out users of this API - * who use the inverse of the gamma value accidentally! Since some of these - * values are reasonable this may have to be changed: + * viewing correction values. The intent is to weed out the API users + * who might use the inverse of the gamma value accidentally! * - * 1.6.x: changed from 0.07..3 to 0.01..100 (to accommodate the optimal 16-bit - * gamma of 36, and its reciprocal.) + * In libpng 1.6.0, we changed from 0.07..3 to 0.01..100, to accommodate + * the optimal 16-bit gamma of 36 and its reciprocal. */ if (output_gamma < 1000 || output_gamma > 10000000) png_error(png_ptr, "output gamma out of expected range"); @@ -441,7 +440,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, int i; png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, - (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)num_palette); for (i = 0; i < num_palette; i++) png_ptr->quantize_index[i] = (png_byte)i; } @@ -458,7 +457,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, /* Initialize an array to sort colors */ png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, - (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)num_palette); /* Initialize the quantize_sort array */ for (i = 0; i < num_palette; i++) @@ -592,11 +591,9 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, /* Initialize palette index arrays */ png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, - (png_alloc_size_t)((png_uint_32)num_palette * - (sizeof (png_byte)))); + (png_alloc_size_t)num_palette); png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, - (png_alloc_size_t)((png_uint_32)num_palette * - (sizeof (png_byte)))); + (png_alloc_size_t)num_palette); /* Initialize the sort array */ for (i = 0; i < num_palette; i++) @@ -761,12 +758,11 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, size_t num_entries = ((size_t)1 << total_bits); png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, - (png_alloc_size_t)(num_entries * (sizeof (png_byte)))); + (png_alloc_size_t)(num_entries)); - distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries * - (sizeof (png_byte)))); + distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)num_entries); - memset(distance, 0xff, num_entries * (sizeof (png_byte))); + memset(distance, 0xff, num_entries); for (i = 0; i < num_palette; i++) { @@ -970,7 +966,7 @@ void PNGFAPI png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, png_fixed_point red, png_fixed_point green) { - png_debug(1, "in png_set_rgb_to_gray"); + png_debug(1, "in png_set_rgb_to_gray_fixed"); /* Need the IHDR here because of the check on color_type below. */ /* TODO: fix this */ diff --git a/3rdparty/libpng/pngrutil.c b/3rdparty/libpng/pngrutil.c index 4db3de990bdc..d31dc21dae89 100644 --- a/3rdparty/libpng/pngrutil.c +++ b/3rdparty/libpng/pngrutil.c @@ -1,7 +1,7 @@ /* pngrutil.c - utilities to read a PNG file * - * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -26,7 +26,7 @@ png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf) if (uval > PNG_UINT_31_MAX) png_error(png_ptr, "PNG unsigned integer out of range"); - return (uval); + return uval; } #if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED) @@ -140,7 +140,7 @@ png_read_sig(png_structrp png_ptr, png_inforp info_ptr) if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0) { if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4) != 0) png_error(png_ptr, "Not a PNG file"); else png_error(png_ptr, "PNG file corrupted by ASCII conversion"); @@ -171,7 +171,7 @@ png_read_chunk_header(png_structrp png_ptr) /* Put the chunk name into png_ptr->chunk_name. */ png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4); - png_debug2(0, "Reading %lx chunk, length = %lu", + png_debug2(0, "Reading chunk typeid = 0x%lx, length = %lu", (unsigned long)png_ptr->chunk_name, (unsigned long)length); /* Reset the crc and run it over the chunk name. */ @@ -238,10 +238,10 @@ png_crc_finish(png_structrp png_ptr, png_uint_32 skip) else png_chunk_error(png_ptr, "CRC error"); - return (1); + return 1; } - return (0); + return 0; } /* Compare the CRC stored in the PNG file with that calculated by libpng from @@ -277,11 +277,11 @@ png_crc_error(png_structrp png_ptr) if (need_crc != 0) { crc = png_get_uint_32(crc_bytes); - return ((int)(crc != png_ptr->crc)); + return crc != png_ptr->crc; } else - return (0); + return 0; } #if defined(PNG_READ_iCCP_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) ||\ @@ -301,7 +301,6 @@ png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn) if (buffer != NULL && new_size > png_ptr->read_buffer_size) { - png_ptr->read_buffer = NULL; png_ptr->read_buffer = NULL; png_ptr->read_buffer_size = 0; png_free(png_ptr, buffer); @@ -422,8 +421,7 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; } -#if ZLIB_VERNUM >= 0x1290 && \ - defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_IGNORE_ADLER32) +#ifdef PNG_DISABLE_ADLER32_CHECK_SUPPORTED if (((png_ptr->options >> PNG_IGNORE_ADLER32) & 3) == PNG_OPTION_ON) /* Turn off validation of the ADLER32 checksum in IDAT chunks */ ret = inflateValidate(&png_ptr->zstream, 0); @@ -2076,14 +2074,17 @@ png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_byte buf[1]; png_crc_read(png_ptr, buf, 1); info_ptr->eXIf_buf[i] = buf[0]; - if (i == 1 && buf[0] != 'M' && buf[0] != 'I' - && info_ptr->eXIf_buf[0] != buf[0]) + if (i == 1) { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "incorrect byte-order specifier"); - png_free(png_ptr, info_ptr->eXIf_buf); - info_ptr->eXIf_buf = NULL; - return; + if ((buf[0] != 'M' && buf[0] != 'I') || + (info_ptr->eXIf_buf[0] != buf[0])) + { + png_crc_finish(png_ptr, length - 2); + png_chunk_benign_error(png_ptr, "incorrect byte-order specifier"); + png_free(png_ptr, info_ptr->eXIf_buf); + info_ptr->eXIf_buf = NULL; + return; + } } } @@ -2124,8 +2125,9 @@ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) num = length / 2 ; - if (num != (unsigned int) png_ptr->num_palette || - num > (unsigned int) PNG_MAX_PALETTE_LENGTH) + if (length != num * 2 || + num != (unsigned int)png_ptr->num_palette || + num > (unsigned int)PNG_MAX_PALETTE_LENGTH) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "invalid"); @@ -3183,7 +3185,7 @@ png_check_chunk_length(png_const_structrp png_ptr, png_uint_32 length) { png_debug2(0," length = %lu, limit = %lu", (unsigned long)length,(unsigned long)limit); - png_chunk_error(png_ptr, "chunk data is too large"); + png_benign_error(png_ptr, "chunk data is too large"); } } @@ -4619,14 +4621,13 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) */ { png_bytep temp = png_ptr->big_row_buf + 32; - int extra = (int)((temp - (png_bytep)0) & 0x0f); + size_t extra = (size_t)temp & 0x0f; png_ptr->row_buf = temp - extra - 1/*filter byte*/; temp = png_ptr->big_prev_row + 32; - extra = (int)((temp - (png_bytep)0) & 0x0f); + extra = (size_t)temp & 0x0f; png_ptr->prev_row = temp - extra - 1/*filter byte*/; } - #else /* Use 31 bytes of padding before and 17 bytes after row_buf. */ png_ptr->row_buf = png_ptr->big_row_buf + 31; diff --git a/3rdparty/libpng/pngset.c b/3rdparty/libpng/pngset.c index ec75dbe36903..eb1c8c7a35af 100644 --- a/3rdparty/libpng/pngset.c +++ b/3rdparty/libpng/pngset.c @@ -1,7 +1,7 @@ /* pngset.c - storage of image information into info struct * - * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -137,46 +137,40 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, #ifdef PNG_eXIf_SUPPORTED void PNGAPI png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr, - png_bytep eXIf_buf) + png_bytep exif) { png_warning(png_ptr, "png_set_eXIf does not work; use png_set_eXIf_1"); PNG_UNUSED(info_ptr) - PNG_UNUSED(eXIf_buf) + PNG_UNUSED(exif) } void PNGAPI png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr, - png_uint_32 num_exif, png_bytep eXIf_buf) + png_uint_32 num_exif, png_bytep exif) { - int i; + png_bytep new_exif; png_debug1(1, "in %s storage function", "eXIf"); - if (png_ptr == NULL || info_ptr == NULL) + if (png_ptr == NULL || info_ptr == NULL || + (png_ptr->mode & PNG_WROTE_eXIf) != 0) return; - if (info_ptr->exif) - { - png_free(png_ptr, info_ptr->exif); - info_ptr->exif = NULL; - } - - info_ptr->num_exif = num_exif; - - info_ptr->exif = png_voidcast(png_bytep, png_malloc_warn(png_ptr, - info_ptr->num_exif)); + new_exif = png_voidcast(png_bytep, png_malloc_warn(png_ptr, num_exif)); - if (info_ptr->exif == NULL) + if (new_exif == NULL) { png_warning(png_ptr, "Insufficient memory for eXIf chunk data"); return; } - info_ptr->free_me |= PNG_FREE_EXIF; + memcpy(new_exif, exif, (size_t)num_exif); - for (i = 0; i < (int) info_ptr->num_exif; i++) - info_ptr->exif[i] = eXIf_buf[i]; + png_free_data(png_ptr, info_ptr, PNG_FREE_EXIF, 0); + info_ptr->num_exif = num_exif; + info_ptr->exif = new_exif; + info_ptr->free_me |= PNG_FREE_EXIF; info_ptr->valid |= PNG_INFO_eXIf; } #endif /* eXIf */ @@ -237,15 +231,13 @@ png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr, if (info_ptr->hist == NULL) { png_warning(png_ptr, "Insufficient memory for hIST chunk data"); - return; } - info_ptr->free_me |= PNG_FREE_HIST; - for (i = 0; i < info_ptr->num_palette; i++) info_ptr->hist[i] = hist[i]; + info_ptr->free_me |= PNG_FREE_HIST; info_ptr->valid |= PNG_INFO_hIST; } #endif @@ -367,6 +359,8 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, memcpy(info_ptr->pcal_purpose, purpose, length); + info_ptr->free_me |= PNG_FREE_PCAL; + png_debug(3, "storing X0, X1, type, and nparams in info"); info_ptr->pcal_X0 = X0; info_ptr->pcal_X1 = X1; @@ -383,7 +377,6 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, if (info_ptr->pcal_units == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL units"); - return; } @@ -395,7 +388,6 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, if (info_ptr->pcal_params == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL params"); - return; } @@ -413,7 +405,6 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, if (info_ptr->pcal_params[i] == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL parameter"); - return; } @@ -421,7 +412,6 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, } info_ptr->valid |= PNG_INFO_pCAL; - info_ptr->free_me |= PNG_FREE_PCAL; } #endif @@ -478,18 +468,17 @@ png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, if (info_ptr->scal_s_height == NULL) { - png_free (png_ptr, info_ptr->scal_s_width); + png_free(png_ptr, info_ptr->scal_s_width); info_ptr->scal_s_width = NULL; png_warning(png_ptr, "Memory allocation failed while processing sCAL"); - return; } memcpy(info_ptr->scal_s_height, sheight, lengthh); - info_ptr->valid |= PNG_INFO_sCAL; info_ptr->free_me |= PNG_FREE_SCAL; + info_ptr->valid |= PNG_INFO_sCAL; } # ifdef PNG_FLOATING_POINT_SUPPORTED @@ -625,11 +614,10 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, if (num_palette > 0) memcpy(png_ptr->palette, palette, (unsigned int)num_palette * (sizeof (png_color))); + info_ptr->palette = png_ptr->palette; info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; - info_ptr->free_me |= PNG_FREE_PLTE; - info_ptr->valid |= PNG_INFO_PLTE; } @@ -775,11 +763,11 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, { int i; - png_debug1(1, "in %lx storage function", png_ptr == NULL ? 0xabadca11U : - (unsigned long)png_ptr->chunk_name); + png_debug1(1, "in text storage function, chunk typeid = 0x%lx", + png_ptr == NULL ? 0xabadca11UL : (unsigned long)png_ptr->chunk_name); if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL) - return(0); + return 0; /* Make sure we have enough space in the "text" array in info_struct * to hold all of the incoming text_ptr objects. This compare can't overflow @@ -959,7 +947,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, png_debug1(3, "transferred text chunk %d", info_ptr->num_text); } - return(0); + return 0; } #endif @@ -1019,6 +1007,9 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, info_ptr->trans_alpha = png_voidcast(png_bytep, png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); memcpy(info_ptr->trans_alpha, trans_alpha, (size_t)num_trans); + + info_ptr->free_me |= PNG_FREE_TRNS; + info_ptr->valid |= PNG_INFO_tRNS; } png_ptr->trans_alpha = info_ptr->trans_alpha; } @@ -1051,8 +1042,8 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, if (num_trans != 0) { - info_ptr->valid |= PNG_INFO_tRNS; info_ptr->free_me |= PNG_FREE_TRNS; + info_ptr->valid |= PNG_INFO_tRNS; } } #endif @@ -1072,6 +1063,8 @@ png_set_sPLT(png_const_structrp png_ptr, { png_sPLT_tp np; + png_debug1(1, "in %s storage function", "sPLT"); + if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL) return; @@ -1086,11 +1079,11 @@ png_set_sPLT(png_const_structrp png_ptr, { /* Out of memory or too many chunks */ png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR); - return; } png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = np; info_ptr->free_me |= PNG_FREE_SPLT; @@ -1244,11 +1237,11 @@ png_set_unknown_chunks(png_const_structrp png_ptr, { png_chunk_report(png_ptr, "too many unknown chunks", PNG_CHUNK_WRITE_ERROR); - return; } png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = np; /* safe because it is initialized */ info_ptr->free_me |= PNG_FREE_UNKN; @@ -1326,7 +1319,7 @@ png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr, #ifdef PNG_MNG_FEATURES_SUPPORTED png_uint_32 PNGAPI -png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features) +png_permit_mng_features(png_structrp png_ptr, png_uint_32 mng_features) { png_debug(1, "in png_permit_mng_features"); @@ -1546,7 +1539,7 @@ void PNGAPI png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr, png_bytepp row_pointers) { - png_debug1(1, "in %s storage function", "rows"); + png_debug(1, "in png_set_rows"); if (png_ptr == NULL || info_ptr == NULL) return; @@ -1565,6 +1558,8 @@ png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr, void PNGAPI png_set_compression_buffer_size(png_structrp png_ptr, size_t size) { + png_debug(1, "in png_set_compression_buffer_size"); + if (png_ptr == NULL) return; @@ -1633,9 +1628,11 @@ png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask) #ifdef PNG_SET_USER_LIMITS_SUPPORTED /* This function was added to libpng 1.2.6 */ void PNGAPI -png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max, +png_set_user_limits(png_structrp png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max) { + png_debug(1, "in png_set_user_limits"); + /* Images with dimensions larger than these limits will be * rejected by png_set_IHDR(). To accept any PNG datastream * regardless of dimensions, set both limits to 0x7fffffff. @@ -1649,17 +1646,21 @@ png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max, /* This function was added to libpng 1.4.0 */ void PNGAPI -png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max) +png_set_chunk_cache_max(png_structrp png_ptr, png_uint_32 user_chunk_cache_max) { + png_debug(1, "in png_set_chunk_cache_max"); + if (png_ptr != NULL) png_ptr->user_chunk_cache_max = user_chunk_cache_max; } /* This function was added to libpng 1.4.1 */ void PNGAPI -png_set_chunk_malloc_max (png_structrp png_ptr, +png_set_chunk_malloc_max(png_structrp png_ptr, png_alloc_size_t user_chunk_malloc_max) { + png_debug(1, "in png_set_chunk_malloc_max"); + if (png_ptr != NULL) png_ptr->user_chunk_malloc_max = user_chunk_malloc_max; } diff --git a/3rdparty/libpng/pngstruct.h b/3rdparty/libpng/pngstruct.h index 8bdc7ce46dbb..e591d94d5870 100644 --- a/3rdparty/libpng/pngstruct.h +++ b/3rdparty/libpng/pngstruct.h @@ -1,7 +1,7 @@ /* pngstruct.h - header file for PNG reference library * - * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 2018-2022 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -334,18 +334,8 @@ struct png_struct_def size_t current_buffer_size; /* amount of data now in current_buffer */ int process_mode; /* what push library is currently doing */ int cur_palette; /* current push library palette index */ - #endif /* PROGRESSIVE_READ */ -#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) -/* For the Borland special 64K segment handler */ - png_bytepp offset_table_ptr; - png_bytep offset_table; - png_uint_16 offset_table_number; - png_uint_16 offset_table_count; - png_uint_16 offset_table_count_free; -#endif - #ifdef PNG_READ_QUANTIZE_SUPPORTED png_bytep palette_lookup; /* lookup table for quantizing */ png_bytep quantize_index; /* index translation for palette files */ diff --git a/3rdparty/libpng/pngtrans.c b/3rdparty/libpng/pngtrans.c index 1100f46ebec2..62cb21edf1f5 100644 --- a/3rdparty/libpng/pngtrans.c +++ b/3rdparty/libpng/pngtrans.c @@ -1,7 +1,7 @@ /* pngtrans.c - transforms the data in a row (used by both readers and writers) * - * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -103,10 +103,10 @@ png_set_interlace_handling(png_structrp png_ptr) if (png_ptr != 0 && png_ptr->interlaced != 0) { png_ptr->transformations |= PNG_INTERLACE; - return (7); + return 7; } - return (1); + return 1; } #endif @@ -498,6 +498,8 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) png_bytep dp = row; /* destination pointer */ png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */ + png_debug(1, "in png_do_strip_channel"); + /* At the start sp will point to the first byte to copy and dp to where * it is copied to. ep always points just beyond the end of the row, so * the loop simply copies (channels-1) channels until sp reaches ep. @@ -698,6 +700,8 @@ png_do_bgr(png_row_infop row_info, png_bytep row) void /* PRIVATE */ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info) { + png_debug(1, "in png_do_check_palette_indexes"); + if (png_ptr->num_palette < (1 << row_info->bit_depth) && png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */ { @@ -708,7 +712,7 @@ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info) * forms produced on either GCC or MSVC. */ int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width); - png_bytep rp = png_ptr->row_buf + row_info->rowbytes - 1; + png_bytep rp = png_ptr->row_buf + row_info->rowbytes; switch (row_info->bit_depth) { @@ -833,7 +837,7 @@ png_voidp PNGAPI png_get_user_transform_ptr(png_const_structrp png_ptr) { if (png_ptr == NULL) - return (NULL); + return NULL; return png_ptr->user_transform_ptr; } diff --git a/3rdparty/libpng/pngwrite.c b/3rdparty/libpng/pngwrite.c index 59377a4ddea2..77e412f43d58 100644 --- a/3rdparty/libpng/pngwrite.c +++ b/3rdparty/libpng/pngwrite.c @@ -1,7 +1,7 @@ /* pngwrite.c - general routines to write a PNG file * - * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -75,10 +75,10 @@ write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr, * library. If you have a new chunk to add, make a function to write it, * and put it in the correct location here. If you want the chunk written * after the image data, put it in png_write_end(). I strongly encourage - * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing - * the chunk, as that will keep the code from breaking if you want to just - * write a plain PNG file. If you have long comments, I suggest writing - * them in png_write_end(), and compressing them. + * you to supply a PNG_INFO_ flag, and check info_ptr->valid before + * writing the chunk, as that will keep the code from breaking if you want + * to just write a plain PNG file. If you have long comments, I suggest + * writing them in png_write_end(), and compressing them. */ void PNGAPI png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) @@ -239,7 +239,10 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) #ifdef PNG_WRITE_eXIf_SUPPORTED if ((info_ptr->valid & PNG_INFO_eXIf) != 0) + { png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif); + png_ptr->mode |= PNG_WROTE_eXIf; + } #endif #ifdef PNG_WRITE_hIST_SUPPORTED @@ -366,7 +369,8 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr) png_error(png_ptr, "No IDATs written into file"); #ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED - if (png_ptr->num_palette_max > png_ptr->num_palette) + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + png_ptr->num_palette_max >= png_ptr->num_palette) png_benign_error(png_ptr, "Wrote palette index exceeding num_palette"); #endif @@ -439,8 +443,9 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr) #endif #ifdef PNG_WRITE_eXIf_SUPPORTED - if ((info_ptr->valid & PNG_INFO_eXIf) != 0) - png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif); + if ((info_ptr->valid & PNG_INFO_eXIf) != 0 && + (png_ptr->mode & PNG_WROTE_eXIf) == 0) + png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif); #endif #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED @@ -489,6 +494,16 @@ png_convert_from_time_t(png_timep ptime, time_t ttime) png_debug(1, "in png_convert_from_time_t"); tbuf = gmtime(&ttime); + if (tbuf == NULL) + { + /* TODO: add a safe function which takes a png_ptr argument and raises + * a png_error if the ttime argument is invalid and the call to gmtime + * fails as a consequence. + */ + memset(ptime, 0, sizeof(*ptime)); + return; + } + png_convert_from_struct_tm(ptime, tbuf); } #endif @@ -700,12 +715,12 @@ png_write_row(png_structrp png_ptr, png_const_bytep row) /* 1.5.6: moved from png_struct to be a local structure: */ png_row_info row_info; - if (png_ptr == NULL) - return; - png_debug2(1, "in png_write_row (row %u, pass %d)", png_ptr->row_number, png_ptr->pass); + if (png_ptr == NULL) + return; + /* Initialize transformations and other stuff if first time */ if (png_ptr->row_number == 0 && png_ptr->pass == 0) { @@ -1196,6 +1211,8 @@ png_set_compression_strategy(png_structrp png_ptr, int strategy) void PNGAPI png_set_compression_window_bits(png_structrp png_ptr, int window_bits) { + png_debug(1, "in png_set_compression_window_bits"); + if (png_ptr == NULL) return; @@ -1279,6 +1296,8 @@ png_set_text_compression_strategy(png_structrp png_ptr, int strategy) void PNGAPI png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits) { + png_debug(1, "in png_set_text_compression_window_bits"); + if (png_ptr == NULL) return; @@ -1316,6 +1335,8 @@ png_set_text_compression_method(png_structrp png_ptr, int method) void PNGAPI png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn) { + png_debug(1, "in png_set_write_status_fn"); + if (png_ptr == NULL) return; @@ -1343,6 +1364,8 @@ void PNGAPI png_write_png(png_structrp png_ptr, png_inforp info_ptr, int transforms, voidp params) { + png_debug(1, "in png_write_png"); + if (png_ptr == NULL || info_ptr == NULL) return; diff --git a/3rdparty/libpng/pngwutil.c b/3rdparty/libpng/pngwutil.c index 16345e4c0baa..14cc4ce367fc 100644 --- a/3rdparty/libpng/pngwutil.c +++ b/3rdparty/libpng/pngwutil.c @@ -1,7 +1,7 @@ /* pngwutil.c - utilities to write a PNG file * - * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -1747,7 +1747,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, { png_uint_32 purpose_len; size_t units_len, total_len; - png_size_tp params_len; + size_t *params_len; png_byte buf[10]; png_byte new_purpose[80]; int i; @@ -1769,7 +1769,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, png_debug1(3, "pCAL units length = %d", (int)units_len); total_len = purpose_len + units_len + 10; - params_len = (png_size_tp)png_malloc(png_ptr, + params_len = (size_t *)png_malloc(png_ptr, (png_alloc_size_t)((png_alloc_size_t)nparams * (sizeof (size_t)))); /* Find the length of each parameter, making sure we don't count the @@ -2311,7 +2311,7 @@ png_setup_sub_row(png_structrp png_ptr, png_uint_32 bpp, break; } - return (sum); + return sum; } static void /* PRIVATE */ @@ -2361,7 +2361,7 @@ png_setup_up_row(png_structrp png_ptr, size_t row_bytes, size_t lmins) break; } - return (sum); + return sum; } static void /* PRIVATE */ png_setup_up_row_only(png_structrp png_ptr, size_t row_bytes) @@ -2417,7 +2417,7 @@ png_setup_avg_row(png_structrp png_ptr, png_uint_32 bpp, break; } - return (sum); + return sum; } static void /* PRIVATE */ png_setup_avg_row_only(png_structrp png_ptr, png_uint_32 bpp, @@ -2500,7 +2500,7 @@ png_setup_paeth_row(png_structrp png_ptr, png_uint_32 bpp, break; } - return (sum); + return sum; } static void /* PRIVATE */ png_setup_paeth_row_only(png_structrp png_ptr, png_uint_32 bpp, diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a724859be03..136de5c79f8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1489,6 +1489,30 @@ if(WITH_SPNG) endif() elseif(WITH_PNG OR HAVE_PNG) status(" PNG:" PNG_FOUND THEN "${PNG_LIBRARY} (ver ${PNG_VERSION_STRING})" ELSE "build (ver ${PNG_VERSION_STRING})") + if(BUILD_PNG AND PNG_HARDWARE_OPTIMIZATIONS) + status(" SIMD Support Request:" "YES") + if(PNG_INTEL_SSE) + status(" SIMD Support:" "YES (Intel SSE)") + elseif(PNG_POWERPC_VSX) + status(" SIMD Support:" "YES (PowerPC VSX)") + elseif(PNG_ARM_NEON) + status(" SIMD Support:" "YES (Arm NEON)") + elseif(PNG_MIPS_MSA OR PNG_MIPS_MMI) + if(PNG_MIPS_MSA AND PNG_MIPS_MMI) + status(" SIMD Support:" "YES (Mips MSA & MMI)") + elseif(PNG_MIPS_MSA AND NOT PNG_MIPS_MMI) + status(" SIMD Support:" "YES (Mips MSA)") + else() + status(" SIMD Support:" "YES (Mips MMI)") + endif() + elseif(PNG_LOONGARCH_LSX) + status(" SIMD Support:" "YES (LoongArch LSX)") + else() + status(" SIMD Support:" "NO") + endif() + elseif(BUILD_PNG) + status(" SIMD Support Request:" "NO") + endif() endif() if(WITH_TIFF OR HAVE_TIFF) From f85014534f2126b0878e0658c547f9cbce0e0de7 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Thu, 23 May 2024 10:30:33 +0300 Subject: [PATCH 072/119] Fixed width and height order in HAL call for LUT. --- modules/core/src/lut.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/lut.cpp b/modules/core/src/lut.cpp index c2464ef4980d..031f113bec23 100644 --- a/modules/core/src/lut.cpp +++ b/modules/core/src/lut.cpp @@ -378,7 +378,7 @@ void cv::LUT( InputArray _src, InputArray _lut, OutputArray _dst ) openvx_LUT(src, dst, lut)) CALL_HAL(LUT, cv_hal_lut, src.data, src.step, src.type(), lut.data, - lut.elemSize1(), lutcn, dst.data, dst.step, src.rows, src.cols); + lut.elemSize1(), lutcn, dst.data, dst.step, src.cols, src.rows); #if !IPP_DISABLE_PERF_LUT CV_IPP_RUN(_src.dims() <= 2, ipp_lut(src, lut, dst)); From 500207785ad8e8327a68dffe1edc8549c589e3b7 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Thu, 23 May 2024 10:41:03 +0200 Subject: [PATCH 073/119] Disambiguate cv::format Otherwise, this test does not compile with C++20, which includes std::format. --- modules/calib3d/test/test_homography.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/calib3d/test/test_homography.cpp b/modules/calib3d/test/test_homography.cpp index 2ceb05f28af5..6a9cdcdd725f 100644 --- a/modules/calib3d/test/test_homography.cpp +++ b/modules/calib3d/test/test_homography.cpp @@ -718,12 +718,12 @@ TEST(Calib3d_Homography, not_normalized) { Mat h = findHomography(p1, p2, method); for (auto it = h.begin(); it != h.end(); ++it) { - ASSERT_FALSE(cvIsNaN(*it)) << format("method %d\nResult:\n", method) << h; + ASSERT_FALSE(cvIsNaN(*it)) << cv::format("method %d\nResult:\n", method) << h; } if (h.at(0, 0) * ref.at(0, 0) < 0) { h *= -1; } - ASSERT_LE(cv::norm(h, ref, NORM_INF), 1e-8) << format("method %d\nResult:\n", method) << h; + ASSERT_LE(cv::norm(h, ref, NORM_INF), 1e-8) << cv::format("method %d\nResult:\n", method) << h; } } From f8ad6eb71bd4b615b1311efc9c2c9620fbfec6fc Mon Sep 17 00:00:00 2001 From: ache Date: Thu, 23 May 2024 10:59:09 +0200 Subject: [PATCH 074/119] Delete option --memory-init-file of em++ --- modules/js/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/js/CMakeLists.txt b/modules/js/CMakeLists.txt index 19f0b197904a..47cba260e165 100644 --- a/modules/js/CMakeLists.txt +++ b/modules/js/CMakeLists.txt @@ -69,7 +69,7 @@ if(COMPILE_FLAGS) set_target_properties(${the_module} PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) endif() -set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} --memory-init-file 0 -s TOTAL_MEMORY=128MB -s WASM_MEM_MAX=1GB -s ALLOW_MEMORY_GROWTH=1") +set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s TOTAL_MEMORY=128MB -s WASM_MEM_MAX=1GB -s ALLOW_MEMORY_GROWTH=1") set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s MODULARIZE=1") set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s EXPORT_NAME=\"'cv'\" -s DEMANGLE_SUPPORT=1") set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s FORCE_FILESYSTEM=1 --use-preload-plugins --bind --post-js ${JS_HELPER} ${COMPILE_FLAGS}") From 16b5096ed079d34296aa22277766ee85f403b2de Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov <2536374+asmorkalov@users.noreply.github.com> Date: Thu, 23 May 2024 16:55:44 +0300 Subject: [PATCH 075/119] Merge pull request #25618 from asmorkalov:as/kleidicv_0.1.0 KleidiCV HAL update to version 0.1.0. #25618 Original integration PR: https://github.com/opencv/opencv/pull/25443 Force the library for testing with CI ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- 3rdparty/kleidicv/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/3rdparty/kleidicv/CMakeLists.txt b/3rdparty/kleidicv/CMakeLists.txt index 0dd50ae08a76..26e485441603 100644 --- a/3rdparty/kleidicv/CMakeLists.txt +++ b/3rdparty/kleidicv/CMakeLists.txt @@ -1,8 +1,8 @@ project(kleidicv_hal) set(KLEIDICV_SOURCE_PATH "" CACHE PATH "Directory containing KleidiCV sources") -ocv_update(KLEIDICV_SRC_COMMIT "a9971ba8bf1d8b008a32c6ed8fea05cd8eb16748") -ocv_update(KLEIDICV_SRC_HASH "53d1d80620395a12c7fee91460499368") +ocv_update(KLEIDICV_SRC_COMMIT "0.1.0") +ocv_update(KLEIDICV_SRC_HASH "9388f28cf2fbe3338197b2b57d491468") if(KLEIDICV_SOURCE_PATH) set(THE_ROOT "${KLEIDICV_SOURCE_PATH}") From 6fb3f6333150a777e835fc7c48e49750591bf7fe Mon Sep 17 00:00:00 2001 From: Benjamin Buch Date: Thu, 23 May 2024 16:05:19 +0200 Subject: [PATCH 076/119] Support VS 2022 17.1x.y With 17.10.0 the MSVC toolset was set to 19.40.x which breaks the compatibility test in the OpenCV's CMake Config files. --- cmake/templates/OpenCVConfig.root-WIN32.cmake.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/templates/OpenCVConfig.root-WIN32.cmake.in b/cmake/templates/OpenCVConfig.root-WIN32.cmake.in index b0f254ebe80f..62e36272f350 100644 --- a/cmake/templates/OpenCVConfig.root-WIN32.cmake.in +++ b/cmake/templates/OpenCVConfig.root-WIN32.cmake.in @@ -137,7 +137,7 @@ elseif(MSVC) set(OpenCV_RUNTIME vc14) # selecting previous compatible runtime version endif() endif() - elseif(MSVC_VERSION MATCHES "^193[0-9]$") + elseif(MSVC_VERSION MATCHES "^19[34][0-9]$") set(OpenCV_RUNTIME vc17) check_one_config(has_VS2022) if(NOT has_VS2022) From 4824354e4673a58d8620975ce98bb93d13cf7220 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov <2536374+asmorkalov@users.noreply.github.com> Date: Thu, 23 May 2024 17:14:01 +0300 Subject: [PATCH 077/119] Merge pull request #25631 from asmorkalov:as/png_build_fix Fixed CMake Missing variable is: CMAKE_ASM_COMPILE_OBJECT in PNG build #25631 Error message with `-DBUILD_PNG=ON` on ARM64: ``` -- Configuring done CMake Error: Error required internal CMake variable not set, cmake may not be built correctly. Missing variable is: CMAKE_ASM_COMPILE_OBJECT -- Generating done CMake Generate step failed. Build files cannot be regenerated correctly. ``` ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- 3rdparty/libpng/CMakeLists.txt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/3rdparty/libpng/CMakeLists.txt b/3rdparty/libpng/CMakeLists.txt index a7701c9fed7a..d05031b9f5fd 100644 --- a/3rdparty/libpng/CMakeLists.txt +++ b/3rdparty/libpng/CMakeLists.txt @@ -3,11 +3,7 @@ # # ---------------------------------------------------------------------------- -if(ENABLE_NEON) - project(${PNG_LIBRARY} C ASM) -else() - project(${PNG_LIBRARY} C) -endif() +project(${PNG_LIBRARY} C) if(UNIX AND NOT APPLE AND NOT BEOS AND NOT HAIKU AND NOT EMSCRIPTEN) find_library(M_LIBRARY m) @@ -59,6 +55,7 @@ if(TARGET_ARCH MATCHES "^(ARM|arm|aarch)") elseif(NOT PNG_ARM_NEON STREQUAL "off") list(APPEND lib_srcs arm/arm_init.c arm/filter_neon_intrinsics.c arm/palette_neon_intrinsics.c) if(NOT MSVC) + enable_language(ASM) list(APPEND lib_srcs arm/filter_neon.S) endif() if(PNG_ARM_NEON STREQUAL "on") From 6bee2facf3e3def81fb140ba5650cf62a8e938f3 Mon Sep 17 00:00:00 2001 From: Letu Ren Date: Fri, 24 May 2024 14:56:50 +0800 Subject: [PATCH 078/119] Use leftarrow in color conversion Doc --- modules/imgproc/doc/colors.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/doc/colors.markdown b/modules/imgproc/doc/colors.markdown index 9827f5e62dfe..cc780137b300 100644 --- a/modules/imgproc/doc/colors.markdown +++ b/modules/imgproc/doc/colors.markdown @@ -67,7 +67,7 @@ If \f$H<0\f$ then \f$H \leftarrow H+360\f$ . On output \f$0 \leq V \leq 1\f$, \f The values are then converted to the destination data type: - 8-bit images: \f$V \leftarrow 255 V, S \leftarrow 255 S, H \leftarrow H/2 \text{(to fit to 0 to 255)}\f$ -- 16-bit images: (currently not supported) \f$V <- 65535 V, S <- 65535 S, H <- H\f$ +- 16-bit images: (currently not supported) \f$V \leftarrow 65535 V, S \leftarrow 65535 S, H \leftarrow H\f$ - 32-bit images: H, S, and V are left as is @see cv::COLOR_BGR2HSV, cv::COLOR_RGB2HSV, cv::COLOR_HSV2BGR, cv::COLOR_HSV2RGB @@ -92,7 +92,7 @@ If \f$H<0\f$ then \f$H \leftarrow H+360\f$ . On output \f$0 \leq L \leq 1\f$, \f The values are then converted to the destination data type: - 8-bit images: \f$V \leftarrow 255 \cdot V, S \leftarrow 255 \cdot S, H \leftarrow H/2 \; \text{(to fit to 0 to 255)}\f$ -- 16-bit images: (currently not supported) \f$V <- 65535 \cdot V, S <- 65535 \cdot S, H <- H\f$ +- 16-bit images: (currently not supported) \f$V \leftarrow 65535 \cdot V, S \leftarrow 65535 \cdot S, H \leftarrow H\f$ - 32-bit images: H, S, V are left as is @see cv::COLOR_BGR2HLS, cv::COLOR_RGB2HLS, cv::COLOR_HLS2BGR, cv::COLOR_HLS2RGB From f85818ba6f9031c450475a7453dee0acce31a881 Mon Sep 17 00:00:00 2001 From: Benjamin Buch Date: Fri, 24 May 2024 11:10:09 +0200 Subject: [PATCH 079/119] Support VS 2022 17.1x.y in OpenCVDetectCXXCompiler.cmake With 17.10.0 the MSVC toolset was set to 19.40.x which breaks the compatibility test in the OpenCV's CMake Config files. --- cmake/OpenCVDetectCXXCompiler.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/OpenCVDetectCXXCompiler.cmake b/cmake/OpenCVDetectCXXCompiler.cmake index 1743aca11f16..448afd46eafb 100644 --- a/cmake/OpenCVDetectCXXCompiler.cmake +++ b/cmake/OpenCVDetectCXXCompiler.cmake @@ -176,7 +176,7 @@ elseif(MSVC) set(OpenCV_RUNTIME vc15) elseif(MSVC_VERSION MATCHES "^192[0-9]$") set(OpenCV_RUNTIME vc16) - elseif(MSVC_VERSION MATCHES "^193[0-9]$") + elseif(MSVC_VERSION MATCHES "^19[34][0-9]$") set(OpenCV_RUNTIME vc17) else() message(WARNING "OpenCV does not recognize MSVC_VERSION \"${MSVC_VERSION}\". Cannot set OpenCV_RUNTIME") From 7e3f6875c166ffe92fc214c17bd8100d59b29a0e Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Fri, 24 May 2024 23:45:53 +0200 Subject: [PATCH 080/119] Prevent signed integer overflow in LshTable This change keeps everything as size_t and the expression is valid because maxk_block > 0 in hte loop. --- modules/flann/include/opencv2/flann/lsh_table.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/flann/include/opencv2/flann/lsh_table.h b/modules/flann/include/opencv2/flann/lsh_table.h index 3b8ffd40750e..3f51457cbb09 100644 --- a/modules/flann/include/opencv2/flann/lsh_table.h +++ b/modules/flann/include/opencv2/flann/lsh_table.h @@ -424,7 +424,7 @@ inline size_t LshTable::getKey(const unsigned char* feature) cons size_t mask_block = mask_[i / sizeof(size_t)]; while (mask_block) { // Get the lowest set bit in the mask block - size_t lowest_bit = mask_block & (-(ptrdiff_t)mask_block); + size_t lowest_bit = mask_block & ~(mask_block - 1); // Add it to the current subsignature if necessary subsignature += (feature_block & lowest_bit) ? bit_index : 0; // Reset the bit in the mask block From b267f1791c6901addd97570a222995b93934ac6f Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Sat, 25 May 2024 10:23:31 +0200 Subject: [PATCH 081/119] Merge pull request #25633 from savuor:rv/rotate_tests Tests for cv::rotate() added #25633 fixes #25449 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/core/perf/opencl/perf_arithm.cpp | 30 +++++++++++++++ modules/core/perf/perf_arithm.cpp | 27 +++++++++++++ modules/core/test/test_arithm.cpp | 48 ++++++++++++++++++++++++ 3 files changed, 105 insertions(+) diff --git a/modules/core/perf/opencl/perf_arithm.cpp b/modules/core/perf/opencl/perf_arithm.cpp index 8d1e7a6288bb..04d343a13635 100644 --- a/modules/core/perf/opencl/perf_arithm.cpp +++ b/modules/core/perf/opencl/perf_arithm.cpp @@ -374,6 +374,36 @@ OCL_PERF_TEST_P(FlipFixture, Flip, SANITY_CHECK(dst); } +///////////// Rotate //////////////////////// + +enum +{ + ROTATE_90_CLOCKWISE = 0, ROTATE_180, ROTATE_90_COUNTERCLOCKWISE +}; + +CV_ENUM(RotateType, ROTATE_90_CLOCKWISE, ROTATE_180, ROTATE_90_COUNTERCLOCKWISE) + +typedef tuple RotateParams; +typedef TestBaseWithParam RotateFixture; + +OCL_PERF_TEST_P(RotateFixture, rotate, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, RotateType::all())) +{ + const RotateParams params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params); + const int rotateCode = get<2>(params); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type), dst(srcSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::rotate(src, dst, rotateCode); + + SANITY_CHECK_NOTHING(); +} + ///////////// minMaxLoc //////////////////////// typedef Size_MatType MinMaxLocFixture; diff --git a/modules/core/perf/perf_arithm.cpp b/modules/core/perf/perf_arithm.cpp index c4cc7500a79d..f14382059c5e 100644 --- a/modules/core/perf/perf_arithm.cpp +++ b/modules/core/perf/perf_arithm.cpp @@ -452,6 +452,33 @@ INSTANTIATE_TEST_CASE_P(/*nothing*/ , BinaryOpTest, ) ); +///////////// Rotate //////////////////////// + +typedef perf::TestBaseWithParam> RotateTest; + +PERF_TEST_P_(RotateTest, rotate) +{ + Size sz = get<0>(GetParam()); + int rotatecode = get<1>(GetParam()); + int type = get<2>(GetParam()); + cv::Mat a(sz, type), b(sz, type); + + declare.in(a, WARMUP_RNG).out(b); + + TEST_CYCLE() cv::rotate(a, b, rotatecode); + + SANITY_CHECK_NOTHING(); +} + +INSTANTIATE_TEST_CASE_P(/*nothing*/ , RotateTest, + testing::Combine( + testing::Values(szVGA, sz720p, sz1080p), + testing::Values(ROTATE_180, ROTATE_90_CLOCKWISE, ROTATE_90_COUNTERCLOCKWISE), + testing::Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_8SC1, CV_16SC1, CV_16SC2, CV_16SC3, CV_16SC4, CV_32SC1, CV_32FC1) + ) +); + + ///////////// PatchNaNs //////////////////////// template diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index 7733d3351924..ed15c5dcbac9 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -831,6 +831,7 @@ struct ConvertScaleAbsOp : public BaseElemWiseOp namespace reference { +// does not support inplace operation static void flip(const Mat& src, Mat& dst, int flipcode) { CV_Assert(src.dims == 2); @@ -852,6 +853,26 @@ static void flip(const Mat& src, Mat& dst, int flipcode) } } +static void rotate(const Mat& src, Mat& dst, int rotateMode) +{ + Mat tmp; + switch (rotateMode) + { + case ROTATE_90_CLOCKWISE: + cvtest::transpose(src, tmp); + reference::flip(tmp, dst, 1); + break; + case ROTATE_180: + reference::flip(src, dst, -1); + break; + case ROTATE_90_COUNTERCLOCKWISE: + cvtest::transpose(src, tmp); + reference::flip(tmp, dst, 0); + break; + default: + break; + } +} static void setIdentity(Mat& dst, const Scalar& s) { @@ -898,6 +919,32 @@ struct FlipOp : public BaseElemWiseOp int flipcode; }; +struct RotateOp : public BaseElemWiseOp +{ + RotateOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) { rotatecode = 0; } + void getRandomSize(RNG& rng, vector& size) + { + cvtest::randomSize(rng, 2, 2, ARITHM_MAX_SIZE_LOG, size); + } + void op(const vector& src, Mat& dst, const Mat&) + { + cv::rotate(src[0], dst, rotatecode); + } + void refop(const vector& src, Mat& dst, const Mat&) + { + reference::rotate(src[0], dst, rotatecode); + } + void generateScalars(int, RNG& rng) + { + rotatecode = rng.uniform(0, 3); + } + double getMaxErr(int) + { + return 0; + } + int rotatecode; +}; + struct TransposeOp : public BaseElemWiseOp { TransposeOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} @@ -1550,6 +1597,7 @@ INSTANTIATE_TEST_CASE_P(Core_InRangeS, ElemWiseTest, ::testing::Values(ElemWiseO INSTANTIATE_TEST_CASE_P(Core_InRange, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new InRangeOp))); INSTANTIATE_TEST_CASE_P(Core_Flip, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new FlipOp))); +INSTANTIATE_TEST_CASE_P(Core_Rotate, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new RotateOp))); INSTANTIATE_TEST_CASE_P(Core_Transpose, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new TransposeOp))); INSTANTIATE_TEST_CASE_P(Core_SetIdentity, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new SetIdentityOp))); From cc49aee04e36b01f3b775863b7b5c633f06b41b9 Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Sat, 25 May 2024 10:25:50 +0200 Subject: [PATCH 082/119] Merge pull request #25634 from savuor:rv/boxfilter_tests Tests for cvSmooth -> tests for boxFilter #25634 fixes #25448 ### Motivation The obsolete function `cvSmooth` has two modes in which it calls `cv::boxFilter()` inside with and without normalization. This function is covered by tests exactly for that modes. This means that by replacing `cvSmooth` call by `cv::boxFilter()` we will leave the coverage untouched (but more obvious) and remove that obsolete function from tests. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/imgproc/test/test_filter.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/imgproc/test/test_filter.cpp b/modules/imgproc/test/test_filter.cpp index a0ccf4372f3f..a6e45709f379 100644 --- a/modules/imgproc/test/test_filter.cpp +++ b/modules/imgproc/test/test_filter.cpp @@ -772,9 +772,8 @@ void CV_BlurTest::get_test_array_types_and_sizes( int test_case_idx, void CV_BlurTest::run_func() { - cvSmooth( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0], - test_array[OUTPUT][0], normalize ? CV_BLUR : CV_BLUR_NO_SCALE, - aperture_size.width, aperture_size.height ); + cv::boxFilter(inplace ? test_mat[OUTPUT][0] : test_mat[INPUT][0], test_mat[OUTPUT][0], + test_mat[OUTPUT][0].type(), aperture_size, cv::Point(-1, -1), normalize, cv::BORDER_REPLICATE); } From 7b31cc731416c66993ca90636d31e9a6447f03e5 Mon Sep 17 00:00:00 2001 From: John Stechschulte Date: Sat, 25 May 2024 04:28:13 -0400 Subject: [PATCH 083/119] Merge pull request #24897 from JStech:fix-handeye Fix handeye #24897 Fixes to the hand-eye calibration methods, from #24871. The Tsai method is sensitive to poses separated by small rotations, so I filter those out. The Horaud and Daniilidis methods use quaternions (and dual quaternions), where $q$ and $-q$ represent the same transform. However, these methods depend on the gripper motion and camera motion having the same sign for the real part. The fix was simply to multiply the (dual) quaternions by -1 if their real part is negative. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] ~~The feature is well documented and sample code can be built with the project CMake~~ N/A --- modules/calib3d/include/opencv2/calib3d.hpp | 1 + modules/calib3d/src/calibration_handeye.cpp | 79 +++++++++---- .../test/test_calibration_hand_eye.cpp | 106 ++++++++++++++++++ 3 files changed, 162 insertions(+), 24 deletions(-) diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index aadfff7b1cd2..0280e05e2184 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -48,6 +48,7 @@ #include "opencv2/core/types.hpp" #include "opencv2/features2d.hpp" #include "opencv2/core/affine.hpp" +#include "opencv2/core/utils/logger.hpp" /** @defgroup calib3d Camera Calibration and 3D Reconstruction diff --git a/modules/calib3d/src/calibration_handeye.cpp b/modules/calib3d/src/calibration_handeye.cpp index ab20597c8b84..cd4999a61831 100644 --- a/modules/calib3d/src/calibration_handeye.cpp +++ b/modules/calib3d/src/calibration_handeye.cpp @@ -289,13 +289,12 @@ static void calibrateHandEyeTsai(const std::vector& Hg, const std::vector& Hg, const std::vector 1.7 || Pcij_norm > 1.7) { + continue; + } + + vec_Hgij.push_back(Hgij); + vec_Hcij.push_back(Hcij); + //Left-hand side: skew(Pgij+Pcij) skew(Pgij+Pcij).copyTo(A(Rect(0, idx*3, 3, 3))); //Right-hand side: Pcij - Pgij Mat diff = Pcij - Pgij; diff.copyTo(B(Rect(0, idx*3, 1, 3))); + idx++; } } + // insufficient data + if (idx < 2) { + CV_LOG_ERROR(NULL, "Hand-eye calibration failed! Not enough informative motions--include larger rotations."); + return; + } + A.resize(3*idx); + B.resize(3*idx); + Mat Pcg_; //Rotation from camera to gripper is obtained from the set of equations: // skew(Pgij+Pcij) * Pcg_ = Pcij - Pgij (eq 12) @@ -327,28 +350,24 @@ static void calibrateHandEyeTsai(const std::vector& Hg, const std::vector(idx)]; - //Defines coordinate transformation from Ci to Cj - //Hci is from CW (calibration target) to Ci (camera) - //Hcj is from CW (calibration target) to Cj (camera) - Mat Hcij = vec_Hcij[static_cast(idx)]; - - //Left-hand side: (Rgij - I) - Mat diff = Hgij(Rect(0,0,3,3)) - Mat::eye(3,3,CV_64FC1); - diff.copyTo(A(Rect(0, idx*3, 3, 3))); - - //Right-hand side: Rcg*Tcij - Tgij - diff = Rcg*Hcij(Rect(3, 0, 1, 3)) - Hgij(Rect(3, 0, 1, 3)); - diff.copyTo(B(Rect(0, idx*3, 1, 3))); - } + //Defines coordinate transformation from Gi to Gj + //Hgi is from Gi (gripper) to RW (robot base) + //Hgj is from Gj (gripper) to RW (robot base) + Mat Hgij = vec_Hgij[i]; + //Defines coordinate transformation from Ci to Cj + //Hci is from CW (calibration target) to Ci (camera) + //Hcj is from CW (calibration target) to Cj (camera) + Mat Hcij = vec_Hcij[i]; + + //Left-hand side: (Rgij - I) + Mat diff = Hgij(Rect(0,0,3,3)) - Mat::eye(3,3,CV_64FC1); + diff.copyTo(A(Rect(0, static_cast(i)*3, 3, 3))); + + //Right-hand side: Rcg*Tcij - Tgij + diff = Rcg*Hcij(Rect(3, 0, 1, 3)) - Hgij(Rect(3, 0, 1, 3)); + diff.copyTo(B(Rect(0, static_cast(i)*3, 1, 3))); } Mat Tcg; @@ -449,6 +468,9 @@ static void calibrateHandEyeHoraud(const std::vector& Hg, const std::vector Mat Rcij = Hcij(Rect(0, 0, 3, 3)); Mat qgij = rot2quat(Rgij); + if (qgij.at(0, 0) < 0) { + qgij *= -1; + } double r0 = qgij.at(0,0); double rx = qgij.at(1,0); double ry = qgij.at(2,0); @@ -461,6 +483,9 @@ static void calibrateHandEyeHoraud(const std::vector& Hg, const std::vector rz, -ry, rx, r0); Mat qcij = rot2quat(Rcij); + if (qcij.at(0, 0) < 0) { + qcij *= -1; + } r0 = qcij.at(0,0); rx = qcij.at(1,0); ry = qcij.at(2,0); @@ -618,7 +643,13 @@ static void calibrateHandEyeDaniilidis(const std::vector& Hg, const std::ve Mat Hcij = Hc[j] * homogeneousInverse(Hc[i]); Mat dualqa = homogeneous2dualQuaternion(Hgij); + if (dualqa.at(0, 0) < 0) { + dualqa *= -1; + } Mat dualqb = homogeneous2dualQuaternion(Hcij); + if (dualqb.at(0, 0) < 0) { + dualqb *= -1; + } Mat a = dualqa(Rect(0, 1, 1, 3)); Mat b = dualqb(Rect(0, 1, 1, 3)); diff --git a/modules/calib3d/test/test_calibration_hand_eye.cpp b/modules/calib3d/test/test_calibration_hand_eye.cpp index aa8b34d6d962..edfc5fec0ef6 100644 --- a/modules/calib3d/test/test_calibration_hand_eye.cpp +++ b/modules/calib3d/test/test_calibration_hand_eye.cpp @@ -756,4 +756,110 @@ TEST(Calib3d_CalibrateRobotWorldHandEye, regression) } } +TEST(Calib3d_CalibrateHandEye, regression_24871) +{ + std::vector R_target2cam, t_target2cam; + std::vector R_gripper2base, t_gripper2base; + Mat T_true_cam2gripper; + + T_true_cam2gripper = (cv::Mat_(4, 4) << 0, 0, -1, 0.1, + 1, 0, 0, 0.2, + 0, -1, 0, 0.3, + 0, 0, 0, 1); + + R_target2cam.push_back((cv::Mat_(3, 3) << + 0.04964505493834381, 0.5136826827431226, 0.8565427426404346, + -0.3923117691818854, 0.7987004864191318, -0.4562554205214679, + -0.9184916136152514, -0.3133809733274676, 0.2411752915926112)); + t_target2cam.push_back((cv::Mat_(3, 1) << + -1.588728904724121, + 0.07843752950429916, + -1.002813339233398)); + + R_gripper2base.push_back((cv::Mat_(3, 3) << + -0.4143743581399177, -0.6105088815982459, -0.6749613298595637, + -0.1598851232573451, -0.6812625208693498, 0.71436554019614, + -0.895952364066927, 0.4039310376145889, 0.1846864320259794)); + t_gripper2base.push_back((cv::Mat_(3, 1) << + -1.249274406461827, + -1.916570771580279, + 2.005069553422765)); + + R_target2cam.push_back((cv::Mat_(3, 3) << + -0.3048000068139332, 0.6971848192711539, 0.6488684640388026, + -0.9377589344241749, -0.3387497187353627, -0.07652979135179161, + 0.1664486009369332, -0.6318084803439735, 0.7570422097951847)); + t_target2cam.push_back((cv::Mat_(3, 1) << + -1.906493663787842, + -0.07281044125556946, + 0.6088893413543701)); + + R_gripper2base.push_back((cv::Mat_(3, 3) << + 0.7262439860936567, -0.201662933718935, -0.6571923111439066, + -0.4640017362244384, -0.8491808316335328, -0.2521791108852766, + -0.5072199339965884, 0.4880819361030014, -0.7102844234575628)); + t_gripper2base.push_back((cv::Mat_(3, 1) << + -0.7375172846804027, + -2.579760910816792, + 1.336561572270101)); + + R_target2cam.push_back((cv::Mat_(3, 3) << + -0.590234879685801, -0.7051138289845309, -0.3929850823848928, + 0.6017371069678565, -0.7088332765096816, 0.3680595606834615, + -0.5380847896941907, -0.01923211603859842, 0.8426712792141644)); + t_target2cam.push_back((cv::Mat_(3, 1) << + -0.9809040427207947, + -0.2707894444465637, + -0.2577074766159058)); + + R_gripper2base.push_back((cv::Mat_(3, 3) << + 0.2541996332132083, 0.6186461729765909, 0.7434106934499181, + 0.2194912986375709, 0.711701808961156, -0.6673111005698995, + -0.9419161938817396, 0.3328024155303503, 0.04512688689130734)); + t_gripper2base.push_back((cv::Mat_(3, 1) << + -1.040123533893404, + -0.1303773962721222, + 1.068029475621886)); + + R_target2cam.push_back((cv::Mat_(3, 3) << + 0.7643667483125168, -0.08523002870239212, 0.63912386614923, + -0.2583463792779588, 0.8676987164647345, 0.424683512464778, + -0.5907627462764713, -0.489729292214425, 0.6412211770980741)); + t_target2cam.push_back((cv::Mat_(3, 1) << + -1.58987033367157, + -1.924914002418518, + -0.3109001517295837)); + + R_gripper2base.push_back((cv::Mat_(3, 3) << + 0.116348305340805, -0.9917998080681939, 0.0528792261688552, + -0.2760629007224059, 0.01884966191381591, 0.9609547154213178, + -0.9540714578526358, -0.1264034452126562, -0.2716060057313114)); + t_gripper2base.push_back((cv::Mat_(3, 1) << + -2.551899142554571, + -2.986937398237611, + 1.317613923218308)); + + Mat R_true_cam2gripper; + Mat t_true_cam2gripper; + R_true_cam2gripper = T_true_cam2gripper(Rect(0, 0, 3, 3)); + t_true_cam2gripper = T_true_cam2gripper(Rect(3, 0, 1, 3)); + + std::vector methods = {CALIB_HAND_EYE_TSAI, + CALIB_HAND_EYE_PARK, + CALIB_HAND_EYE_HORAUD, + CALIB_HAND_EYE_ANDREFF, + CALIB_HAND_EYE_DANIILIDIS}; + + for (auto method : methods) { + SCOPED_TRACE(cv::format("method=%s", getMethodName(method).c_str())); + + Matx33d R_cam2gripper_est; + Matx31d t_cam2gripper_est; + calibrateHandEye(R_gripper2base, t_gripper2base, R_target2cam, t_target2cam, R_cam2gripper_est, t_cam2gripper_est, method); + + EXPECT_TRUE(cv::norm(R_cam2gripper_est - R_true_cam2gripper) < 1e-9); + EXPECT_TRUE(cv::norm(t_cam2gripper_est - t_true_cam2gripper) < 1e-9); + } +} + }} // namespace From d97df262f6d25971e05c19731179996041f9e07f Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov <2536374+asmorkalov@users.noreply.github.com> Date: Sat, 25 May 2024 13:03:12 +0300 Subject: [PATCH 084/119] Merge pull request #25623 from asmorkalov:as/jpegturbo_3.0.3 Libjpeg-turbo update to version 3.0.3 #25623 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- 3rdparty/libjpeg-turbo/CMakeLists.txt | 103 +- 3rdparty/libjpeg-turbo/LICENSE.md | 33 +- 3rdparty/libjpeg-turbo/README.ijg | 26 +- 3rdparty/libjpeg-turbo/README.md | 84 +- 3rdparty/libjpeg-turbo/jconfig.h.in | 68 +- 3rdparty/libjpeg-turbo/jconfig.h.win.in | 33 - 3rdparty/libjpeg-turbo/jconfigint.h.in | 44 +- .../{src/jversion.h => jversion.h.in} | 14 +- 3rdparty/libjpeg-turbo/src/cjpeg.c | 841 +++++ 3rdparty/libjpeg-turbo/src/cmyk.h | 61 + 3rdparty/libjpeg-turbo/src/djpeg.c | 932 +++++ 3rdparty/libjpeg-turbo/src/example.c | 643 ++++ 3rdparty/libjpeg-turbo/src/jcapimin.c | 27 +- 3rdparty/libjpeg-turbo/src/jcapistd.c | 53 +- 3rdparty/libjpeg-turbo/src/jccoefct.c | 47 +- 3rdparty/libjpeg-turbo/src/jccolext.c | 64 +- 3rdparty/libjpeg-turbo/src/jccolor.c | 240 +- 3rdparty/libjpeg-turbo/src/jcdctmgr.c | 94 +- 3rdparty/libjpeg-turbo/src/jcdiffct.c | 411 +++ 3rdparty/libjpeg-turbo/src/jchuff.c | 202 +- 3rdparty/libjpeg-turbo/src/jchuff.h | 16 +- 3rdparty/libjpeg-turbo/src/jcinit.c | 111 +- 3rdparty/libjpeg-turbo/src/jclhuff.c | 587 +++ 3rdparty/libjpeg-turbo/src/jclossls.c | 319 ++ 3rdparty/libjpeg-turbo/src/jcmainct.c | 45 +- 3rdparty/libjpeg-turbo/src/jcmarker.c | 36 +- 3rdparty/libjpeg-turbo/src/jcmaster.c | 312 +- 3rdparty/libjpeg-turbo/src/jcmaster.h | 43 + 3rdparty/libjpeg-turbo/src/jcparam.c | 52 +- 3rdparty/libjpeg-turbo/src/jcphuff.c | 90 +- 3rdparty/libjpeg-turbo/src/jcprepct.c | 88 +- 3rdparty/libjpeg-turbo/src/jcsample.c | 103 +- 3rdparty/libjpeg-turbo/src/jcstest.c | 126 + 3rdparty/libjpeg-turbo/src/jctrans.c | 16 +- 3rdparty/libjpeg-turbo/src/jdapimin.c | 21 +- 3rdparty/libjpeg-turbo/src/jdapistd.c | 162 +- 3rdparty/libjpeg-turbo/src/jdatadst-tj.c | 198 + 3rdparty/libjpeg-turbo/src/jdatadst.c | 10 - 3rdparty/libjpeg-turbo/src/jdatasrc-tj.c | 194 + 3rdparty/libjpeg-turbo/src/jdatasrc.c | 6 - 3rdparty/libjpeg-turbo/src/jdcoefct.c | 77 +- 3rdparty/libjpeg-turbo/src/jdcoefct.h | 5 + 3rdparty/libjpeg-turbo/src/jdcol565.c | 62 +- 3rdparty/libjpeg-turbo/src/jdcolext.c | 48 +- 3rdparty/libjpeg-turbo/src/jdcolor.c | 193 +- 3rdparty/libjpeg-turbo/src/jdct.h | 135 +- 3rdparty/libjpeg-turbo/src/jddctmgr.c | 61 +- 3rdparty/libjpeg-turbo/src/jddiffct.c | 403 ++ 3rdparty/libjpeg-turbo/src/jdhuff.c | 20 +- 3rdparty/libjpeg-turbo/src/jdhuff.h | 7 +- 3rdparty/libjpeg-turbo/src/jdinput.c | 63 +- 3rdparty/libjpeg-turbo/src/jdlhuff.c | 302 ++ 3rdparty/libjpeg-turbo/src/jdlossls.c | 289 ++ 3rdparty/libjpeg-turbo/src/jdmainct.c | 112 +- 3rdparty/libjpeg-turbo/src/jdmainct.h | 15 +- 3rdparty/libjpeg-turbo/src/jdmarker.c | 26 +- 3rdparty/libjpeg-turbo/src/jdmaster.c | 635 ++-- 3rdparty/libjpeg-turbo/src/jdmerge.c | 72 +- 3rdparty/libjpeg-turbo/src/jdmerge.h | 9 +- 3rdparty/libjpeg-turbo/src/jdmrg565.c | 43 +- 3rdparty/libjpeg-turbo/src/jdmrgext.c | 40 +- 3rdparty/libjpeg-turbo/src/jdphuff.c | 4 +- 3rdparty/libjpeg-turbo/src/jdpostct.c | 109 +- 3rdparty/libjpeg-turbo/src/jdsample.c | 128 +- 3rdparty/libjpeg-turbo/src/jdsample.h | 9 +- 3rdparty/libjpeg-turbo/src/jdtrans.c | 12 +- 3rdparty/libjpeg-turbo/src/jerror.c | 18 +- 3rdparty/libjpeg-turbo/src/jerror.h | 17 +- 3rdparty/libjpeg-turbo/src/jfdctfst.c | 2 +- 3rdparty/libjpeg-turbo/src/jfdctint.c | 4 +- 3rdparty/libjpeg-turbo/src/jidctflt.c | 14 +- 3rdparty/libjpeg-turbo/src/jidctfst.c | 18 +- 3rdparty/libjpeg-turbo/src/jidctint.c | 136 +- 3rdparty/libjpeg-turbo/src/jidctred.c | 38 +- 3rdparty/libjpeg-turbo/src/jinclude.h | 16 +- 3rdparty/libjpeg-turbo/src/jlossls.h | 101 + 3rdparty/libjpeg-turbo/src/jmemmgr.c | 194 +- 3rdparty/libjpeg-turbo/src/jmemsys.h | 31 - 3rdparty/libjpeg-turbo/src/jmorecfg.h | 39 +- .../src/{jpeg_nbits_table.h => jpeg_nbits.c} | 38 +- 3rdparty/libjpeg-turbo/src/jpeg_nbits.h | 43 + .../src/{jpegcomp.h => jpegapicomp.h} | 2 +- 3rdparty/libjpeg-turbo/src/jpegint.h | 226 +- 3rdparty/libjpeg-turbo/src/jpeglib.h | 153 +- 3rdparty/libjpeg-turbo/src/jquant1.c | 164 +- 3rdparty/libjpeg-turbo/src/jquant2.c | 130 +- 3rdparty/libjpeg-turbo/src/jsamplecomp.h | 336 ++ 3rdparty/libjpeg-turbo/src/jsimd.h | 12 +- 3rdparty/libjpeg-turbo/src/jsimd_none.c | 431 --- 3rdparty/libjpeg-turbo/src/jutils.c | 25 +- 3rdparty/libjpeg-turbo/src/jversion.h.in | 12 +- 3rdparty/libjpeg-turbo/src/libjpeg.map.in | 11 + 3rdparty/libjpeg-turbo/src/libjpeg.txt | 3282 +++++++++++++++++ 3rdparty/libjpeg-turbo/src/rdbmp.c | 689 ++++ 3rdparty/libjpeg-turbo/src/rdcolmap.c | 261 ++ 3rdparty/libjpeg-turbo/src/rdgif.c | 720 ++++ 3rdparty/libjpeg-turbo/src/rdjpgcom.c | 493 +++ 3rdparty/libjpeg-turbo/src/rdppm.c | 890 +++++ 3rdparty/libjpeg-turbo/src/rdswitch.c | 428 +++ 3rdparty/libjpeg-turbo/src/rdtarga.c | 507 +++ .../libjpeg-turbo/src/simd/CMakeLists.txt | 76 +- .../src/simd/arm/aarch32/jsimd.c | 14 +- .../src/simd/arm/aarch64/jsimd.c | 19 +- .../libjpeg-turbo/src/simd/arm/jcphuff-neon.c | 187 +- .../libjpeg-turbo/src/simd/arm/jdcolor-neon.c | 1 - .../libjpeg-turbo/src/simd/arm/jdmerge-neon.c | 1 - .../src/simd/arm/jidctint-neon.c | 1 - .../src/simd/i386/jccolext-avx2.asm | 22 +- .../src/simd/i386/jccolext-mmx.asm | 22 +- .../src/simd/i386/jccolext-sse2.asm | 22 +- .../src/simd/i386/jccolor-avx2.asm | 6 +- .../src/simd/i386/jccolor-mmx.asm | 6 +- .../src/simd/i386/jccolor-sse2.asm | 6 +- .../src/simd/i386/jcgray-avx2.asm | 6 +- .../src/simd/i386/jcgray-mmx.asm | 6 +- .../src/simd/i386/jcgray-sse2.asm | 6 +- .../src/simd/i386/jcgryext-avx2.asm | 22 +- .../src/simd/i386/jcgryext-mmx.asm | 22 +- .../src/simd/i386/jcgryext-sse2.asm | 22 +- .../src/simd/i386/jchuff-sse2.asm | 17 +- .../src/simd/i386/jcsample-avx2.asm | 18 +- .../src/simd/i386/jcsample-mmx.asm | 14 +- .../src/simd/i386/jcsample-sse2.asm | 18 +- .../src/simd/i386/jdcolext-avx2.asm | 20 +- .../src/simd/i386/jdcolext-mmx.asm | 20 +- .../src/simd/i386/jdcolext-sse2.asm | 20 +- .../src/simd/i386/jdcolor-avx2.asm | 6 +- .../src/simd/i386/jdcolor-mmx.asm | 6 +- .../src/simd/i386/jdcolor-sse2.asm | 6 +- .../src/simd/i386/jdmerge-avx2.asm | 6 +- .../src/simd/i386/jdmerge-mmx.asm | 6 +- .../src/simd/i386/jdmerge-sse2.asm | 6 +- .../src/simd/i386/jdmrgext-avx2.asm | 20 +- .../src/simd/i386/jdmrgext-mmx.asm | 20 +- .../src/simd/i386/jdmrgext-sse2.asm | 20 +- .../src/simd/i386/jdsample-avx2.asm | 58 +- .../src/simd/i386/jdsample-mmx.asm | 58 +- .../src/simd/i386/jdsample-sse2.asm | 58 +- .../src/simd/i386/jfdctflt-3dn.asm | 16 +- .../src/simd/i386/jfdctflt-sse.asm | 16 +- .../src/simd/i386/jfdctfst-mmx.asm | 16 +- .../src/simd/i386/jfdctfst-sse2.asm | 12 +- .../src/simd/i386/jfdctint-avx2.asm | 24 +- .../src/simd/i386/jfdctint-mmx.asm | 16 +- .../src/simd/i386/jfdctint-sse2.asm | 12 +- .../src/simd/i386/jidctflt-3dn.asm | 22 +- .../src/simd/i386/jidctflt-sse.asm | 38 +- .../src/simd/i386/jidctflt-sse2.asm | 38 +- .../src/simd/i386/jidctfst-mmx.asm | 18 +- .../src/simd/i386/jidctfst-sse2.asm | 14 +- .../src/simd/i386/jidctint-avx2.asm | 26 +- .../src/simd/i386/jidctint-mmx.asm | 18 +- .../src/simd/i386/jidctint-sse2.asm | 14 +- .../src/simd/i386/jidctred-mmx.asm | 18 +- .../src/simd/i386/jidctred-sse2.asm | 16 +- .../src/simd/i386/jquant-3dn.asm | 6 +- .../src/simd/i386/jquant-mmx.asm | 8 +- .../src/simd/i386/jquant-sse.asm | 6 +- .../src/simd/i386/jquantf-sse2.asm | 6 +- .../src/simd/i386/jquanti-sse2.asm | 6 +- 3rdparty/libjpeg-turbo/src/simd/i386/jsimd.c | 84 +- 3rdparty/libjpeg-turbo/src/simd/jsimd.h | 12 +- 3rdparty/libjpeg-turbo/src/simd/mips/jsimd.c | 14 +- .../libjpeg-turbo/src/simd/mips64/jsimd.c | 14 +- .../libjpeg-turbo/src/simd/nasm/jsimdext.inc | 66 +- .../libjpeg-turbo/src/simd/powerpc/jsimd.c | 27 +- .../src/simd/x86_64/jccolext-avx2.asm | 24 +- .../src/simd/x86_64/jccolext-sse2.asm | 24 +- .../src/simd/x86_64/jccolor-avx2.asm | 6 +- .../src/simd/x86_64/jccolor-sse2.asm | 6 +- .../src/simd/x86_64/jcgray-avx2.asm | 6 +- .../src/simd/x86_64/jcgray-sse2.asm | 6 +- .../src/simd/x86_64/jcgryext-avx2.asm | 24 +- .../src/simd/x86_64/jcgryext-sse2.asm | 24 +- .../src/simd/x86_64/jchuff-sse2.asm | 72 +- .../src/simd/x86_64/jcphuff-sse2.asm | 42 +- .../src/simd/x86_64/jcsample-avx2.asm | 14 +- .../src/simd/x86_64/jcsample-sse2.asm | 14 +- .../src/simd/x86_64/jdcolext-avx2.asm | 24 +- .../src/simd/x86_64/jdcolext-sse2.asm | 24 +- .../src/simd/x86_64/jdcolor-avx2.asm | 6 +- .../src/simd/x86_64/jdcolor-sse2.asm | 6 +- .../src/simd/x86_64/jdmerge-avx2.asm | 6 +- .../src/simd/x86_64/jdmerge-sse2.asm | 6 +- .../src/simd/x86_64/jdmrgext-avx2.asm | 30 +- .../src/simd/x86_64/jdmrgext-sse2.asm | 30 +- .../src/simd/x86_64/jdsample-avx2.asm | 56 +- .../src/simd/x86_64/jdsample-sse2.asm | 46 +- .../src/simd/x86_64/jfdctflt-sse.asm | 28 +- .../src/simd/x86_64/jfdctfst-sse2.asm | 28 +- .../src/simd/x86_64/jfdctint-avx2.asm | 24 +- .../src/simd/x86_64/jfdctint-sse2.asm | 28 +- .../src/simd/x86_64/jidctflt-sse2.asm | 48 +- .../src/simd/x86_64/jidctfst-sse2.asm | 30 +- .../src/simd/x86_64/jidctint-avx2.asm | 28 +- .../src/simd/x86_64/jidctint-sse2.asm | 30 +- .../src/simd/x86_64/jidctred-sse2.asm | 36 +- .../src/simd/x86_64/jquantf-sse2.asm | 14 +- .../src/simd/x86_64/jquanti-avx2.asm | 14 +- .../src/simd/x86_64/jquanti-sse2.asm | 14 +- .../libjpeg-turbo/src/simd/x86_64/jsimd.c | 60 +- .../src/simd/x86_64/jsimdcpu.asm | 4 + 3rdparty/libjpeg-turbo/src/structure.txt | 981 +++++ 3rdparty/libjpeg-turbo/src/tjbench.c | 1323 +++++++ 3rdparty/libjpeg-turbo/src/tjutil.c | 70 + 3rdparty/libjpeg-turbo/src/tjutil.h | 53 + 3rdparty/libjpeg-turbo/src/transupp.c | 2377 ++++++++++++ 3rdparty/libjpeg-turbo/src/transupp.h | 231 ++ 3rdparty/libjpeg-turbo/src/turbojpeg-jni.c | 1400 +++++++ 3rdparty/libjpeg-turbo/src/turbojpeg-mapfile | 108 + .../libjpeg-turbo/src/turbojpeg-mapfile.jni | 142 + 3rdparty/libjpeg-turbo/src/turbojpeg-mp.c | 541 +++ 3rdparty/libjpeg-turbo/src/turbojpeg.c | 2921 +++++++++++++++ 3rdparty/libjpeg-turbo/src/turbojpeg.h | 2328 ++++++++++++ 214 files changed, 30204 insertions(+), 3515 deletions(-) delete mode 100644 3rdparty/libjpeg-turbo/jconfig.h.win.in rename 3rdparty/libjpeg-turbo/{src/jversion.h => jversion.h.in} (79%) create mode 100644 3rdparty/libjpeg-turbo/src/cjpeg.c create mode 100644 3rdparty/libjpeg-turbo/src/cmyk.h create mode 100644 3rdparty/libjpeg-turbo/src/djpeg.c create mode 100644 3rdparty/libjpeg-turbo/src/example.c create mode 100644 3rdparty/libjpeg-turbo/src/jcdiffct.c create mode 100644 3rdparty/libjpeg-turbo/src/jclhuff.c create mode 100644 3rdparty/libjpeg-turbo/src/jclossls.c create mode 100644 3rdparty/libjpeg-turbo/src/jcmaster.h create mode 100644 3rdparty/libjpeg-turbo/src/jcstest.c create mode 100644 3rdparty/libjpeg-turbo/src/jdatadst-tj.c create mode 100644 3rdparty/libjpeg-turbo/src/jdatasrc-tj.c create mode 100644 3rdparty/libjpeg-turbo/src/jddiffct.c create mode 100644 3rdparty/libjpeg-turbo/src/jdlhuff.c create mode 100644 3rdparty/libjpeg-turbo/src/jdlossls.c create mode 100644 3rdparty/libjpeg-turbo/src/jlossls.h rename 3rdparty/libjpeg-turbo/src/{jpeg_nbits_table.h => jpeg_nbits.c} (99%) create mode 100644 3rdparty/libjpeg-turbo/src/jpeg_nbits.h rename 3rdparty/libjpeg-turbo/src/{jpegcomp.h => jpegapicomp.h} (98%) create mode 100644 3rdparty/libjpeg-turbo/src/jsamplecomp.h delete mode 100644 3rdparty/libjpeg-turbo/src/jsimd_none.c create mode 100644 3rdparty/libjpeg-turbo/src/libjpeg.map.in create mode 100644 3rdparty/libjpeg-turbo/src/libjpeg.txt create mode 100644 3rdparty/libjpeg-turbo/src/rdbmp.c create mode 100644 3rdparty/libjpeg-turbo/src/rdcolmap.c create mode 100644 3rdparty/libjpeg-turbo/src/rdgif.c create mode 100644 3rdparty/libjpeg-turbo/src/rdjpgcom.c create mode 100644 3rdparty/libjpeg-turbo/src/rdppm.c create mode 100644 3rdparty/libjpeg-turbo/src/rdswitch.c create mode 100644 3rdparty/libjpeg-turbo/src/rdtarga.c create mode 100644 3rdparty/libjpeg-turbo/src/structure.txt create mode 100644 3rdparty/libjpeg-turbo/src/tjbench.c create mode 100644 3rdparty/libjpeg-turbo/src/tjutil.c create mode 100644 3rdparty/libjpeg-turbo/src/tjutil.h create mode 100644 3rdparty/libjpeg-turbo/src/transupp.c create mode 100644 3rdparty/libjpeg-turbo/src/transupp.h create mode 100644 3rdparty/libjpeg-turbo/src/turbojpeg-jni.c create mode 100644 3rdparty/libjpeg-turbo/src/turbojpeg-mapfile create mode 100644 3rdparty/libjpeg-turbo/src/turbojpeg-mapfile.jni create mode 100644 3rdparty/libjpeg-turbo/src/turbojpeg-mp.c create mode 100644 3rdparty/libjpeg-turbo/src/turbojpeg.c create mode 100644 3rdparty/libjpeg-turbo/src/turbojpeg.h diff --git a/3rdparty/libjpeg-turbo/CMakeLists.txt b/3rdparty/libjpeg-turbo/CMakeLists.txt index a995707852b5..79ffab9cd3f8 100644 --- a/3rdparty/libjpeg-turbo/CMakeLists.txt +++ b/3rdparty/libjpeg-turbo/CMakeLists.txt @@ -1,12 +1,43 @@ project(${JPEG_LIBRARY} C) +macro(boolean_number var) + if(${var}) + set(${var} 1 ${ARGN}) + else() + set(${var} 0 ${ARGN}) + endif() +endmacro() + ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter -Wsign-compare -Wshorten-64-to-32 -Wimplicit-fallthrough) +if(APPLE) + ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-variable) # NEON flags are not used on Mac +endif() -set(VERSION_MAJOR 2) -set(VERSION_MINOR 1) -set(VERSION_REVISION 3) -set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}) -set(LIBJPEG_TURBO_VERSION_NUMBER 2001003) +if(CV_GCC AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13) + # src/jchuff.c:1042:22: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] + ocv_warnings_disable(CMAKE_C_FLAGS -Wstringop-overflow) +endif() + +set(VERSION 3.0.3) +set(COPYRIGHT_YEAR "1991-2024") +string(REPLACE "." ";" VERSION_TRIPLET ${VERSION}) +list(GET VERSION_TRIPLET 0 VERSION_MAJOR) +list(GET VERSION_TRIPLET 1 VERSION_MINOR) +list(GET VERSION_TRIPLET 2 VERSION_REVISION) +function(pad_number NUMBER OUTPUT_LEN) + string(LENGTH "${${NUMBER}}" INPUT_LEN) + if(INPUT_LEN LESS OUTPUT_LEN) + math(EXPR ZEROES "${OUTPUT_LEN} - ${INPUT_LEN} - 1") + set(NUM ${${NUMBER}}) + foreach(C RANGE ${ZEROES}) + set(NUM "0${NUM}") + endforeach() + set(${NUMBER} ${NUM} PARENT_SCOPE) + endif() +endfunction() +pad_number(VERSION_MINOR 3) +pad_number(VERSION_REVISION 3) +set(LIBJPEG_TURBO_VERSION_NUMBER ${VERSION_MAJOR}${VERSION_MINOR}${VERSION_REVISION}) string(TIMESTAMP BUILD "opencv-${OPENCV_VERSION}-libjpeg-turbo") if(CMAKE_BUILD_TYPE STREQUAL "Debug") @@ -66,8 +97,8 @@ include(CheckCSourceCompiles) include(CheckIncludeFiles) include(CheckTypeSize) -check_type_size("size_t" SIZEOF_SIZE_T) -check_type_size("unsigned long" SIZEOF_UNSIGNED_LONG) +check_type_size("size_t" SIZE_T) +check_type_size("unsigned long" UNSIGNED_LONG) if(SIZEOF_SIZE_T EQUAL SIZEOF_UNSIGNED_LONG) check_c_source_compiles("int main(int argc, char **argv) { unsigned long a = argc; return __builtin_ctzl(a); }" @@ -110,26 +141,27 @@ set(JPEG_LIB_VERSION "${VERSION}-${JPEG_LIB_VERSION}" PARENT_SCOPE) set(THREAD_LOCAL "") # WITH_TURBOJPEG is not used +add_definitions(-DNO_GETENV -DNO_PUTENV) + if(MSVC) add_definitions(-W3 -wd4996 -wd4018) endif() -if(WIN32) - configure_file(jconfig.h.win.in jconfig.h) -else() - configure_file(jconfig.h.in jconfig.h) -endif() -configure_file(jconfigint.h.in jconfigint.h) - include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src) -set(JPEG_SOURCES jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c - jcicc.c jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c - jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c jdatadst.c - jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c jdicc.c jdinput.c - jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c jdpostct.c jdsample.c - jdtrans.c jerror.c jfdctflt.c jfdctfst.c jfdctint.c jidctflt.c jidctfst.c - jidctint.c jidctred.c jquant1.c jquant2.c jutils.c jmemmgr.c jmemnobs.c) +set(JPEG16_SOURCES jcapistd.c jccolor.c jcdiffct.c jclossls.c jcmainct.c + jcprepct.c jcsample.c jdapistd.c jdcolor.c jddiffct.c jdlossls.c jdmainct.c + jdpostct.c jdsample.c jutils.c) + +set(JPEG12_SOURCES ${JPEG16_SOURCES} jccoefct.c jcdctmgr.c jdcoefct.c + jddctmgr.c jdmerge.c jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c + jidctred.c jquant1.c jquant2.c) + +set(JPEG_SOURCES ${JPEG12_SOURCES} jcapimin.c jchuff.c jcicc.c jcinit.c + jclhuff.c jcmarker.c jcmaster.c jcomapi.c jcparam.c jcphuff.c jctrans.c + jdapimin.c jdatadst.c jdatasrc.c jdhuff.c jdicc.c jdinput.c jdlhuff.c + jdmarker.c jdmaster.c jdphuff.c jdtrans.c jerror.c jfdctflt.c jmemmgr.c + jmemnobs.c jpeg_nbits.c) if(WITH_ARITH_ENC OR WITH_ARITH_DEC) set(JPEG_SOURCES ${JPEG_SOURCES} jaricom.c) @@ -143,7 +175,7 @@ if(WITH_ARITH_DEC) set(JPEG_SOURCES ${JPEG_SOURCES} jdarith.c) endif() -if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang") +if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") # Use the maximum optimization level for release builds foreach(var CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO) if(${var} MATCHES "-O2") @@ -166,6 +198,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") endif() endif() +include(CheckTypeSize) +check_type_size("size_t" SIZE_T) +check_type_size("unsigned long" UNSIGNED_LONG) + if(ENABLE_LIBJPEG_TURBO_SIMD) add_subdirectory(src/simd) if(NEON_INTRINSICS) @@ -181,19 +217,28 @@ if(WITH_SIMD) if(MSVC_IDE OR XCODE) set_source_files_properties(${SIMD_OBJS} PROPERTIES GENERATED 1) endif() -else() - add_library(jsimd OBJECT src/jsimd_none.c) - set_target_properties(jsimd PROPERTIES FOLDER "3rdparty") - if(NOT WIN32 AND (CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED)) - set_target_properties(jsimd PROPERTIES POSITION_INDEPENDENT_CODE 1) - endif() + set(SIMD_TARGET_OBJECTS $) endif() +configure_file(jversion.h.in jversion.h) +configure_file(jconfig.h.in jconfig.h) +configure_file(jconfigint.h.in jconfigint.h) + +ocv_list_add_prefix(JPEG16_SOURCES src/) +ocv_list_add_prefix(JPEG12_SOURCES src/) ocv_list_add_prefix(JPEG_SOURCES src/) set(JPEG_SOURCES ${JPEG_SOURCES} ${SIMD_OBJS}) -add_library(${JPEG_LIBRARY} STATIC ${OPENCV_3RDPARTY_EXCLUDE_FROM_ALL} ${JPEG_SOURCES} $ ${SIMD_OBJS}) +add_library(jpeg12-static OBJECT ${JPEG12_SOURCES}) +set_property(TARGET jpeg12-static PROPERTY COMPILE_FLAGS + "-DBITS_IN_JSAMPLE=12") +add_library(jpeg16-static OBJECT ${JPEG16_SOURCES}) +set_property(TARGET jpeg16-static PROPERTY COMPILE_FLAGS + "-DBITS_IN_JSAMPLE=16") +add_library(${JPEG_LIBRARY} STATIC ${JPEG_SOURCES} ${SIMD_TARGET_OBJECTS} + ${SIMD_OBJS} $ + $) set_target_properties(${JPEG_LIBRARY} PROPERTIES OUTPUT_NAME ${JPEG_LIBRARY} diff --git a/3rdparty/libjpeg-turbo/LICENSE.md b/3rdparty/libjpeg-turbo/LICENSE.md index d753e1d76aa0..2204864fa118 100644 --- a/3rdparty/libjpeg-turbo/LICENSE.md +++ b/3rdparty/libjpeg-turbo/LICENSE.md @@ -1,30 +1,33 @@ libjpeg-turbo Licenses ====================== -libjpeg-turbo is covered by three compatible BSD-style open source licenses: +libjpeg-turbo is covered by two compatible BSD-style open source licenses: - The IJG (Independent JPEG Group) License, which is listed in [README.ijg](README.ijg) - This license applies to the libjpeg API library and associated programs - (any code inherited from libjpeg, and any modifications to that code.) + This license applies to the libjpeg API library and associated programs, + including any code inherited from libjpeg and any modifications to that + code. Note that the libjpeg-turbo SIMD source code bears the + [zlib License](https://opensource.org/licenses/Zlib), but in the context of + the overall libjpeg API library, the terms of the zlib License are subsumed + by the terms of the IJG License. - The Modified (3-clause) BSD License, which is listed below - This license covers the TurboJPEG API library and associated programs, as - well as the build system. - -- The [zlib License](https://opensource.org/licenses/Zlib) - - This license is a subset of the other two, and it covers the libjpeg-turbo - SIMD extensions. + This license applies to the TurboJPEG API library and associated programs, as + well as the build system. Note that the TurboJPEG API library wraps the + libjpeg API library, so in the context of the overall TurboJPEG API library, + both the terms of the IJG License and the terms of the Modified (3-clause) + BSD License apply. Complying with the libjpeg-turbo Licenses ========================================= This section provides a roll-up of the libjpeg-turbo licensing terms, to the -best of our understanding. +best of our understanding. This is not a license in and of itself. It is +intended solely for clarification. 1. If you are distributing a modified version of the libjpeg-turbo source, then: @@ -38,7 +41,7 @@ best of our understanding. - Clauses 1 and 3 of the zlib License 2. You must add your own copyright notice to the header of each source - file you modified, so others can tell that you modified that file (if + file you modified, so others can tell that you modified that file. (If there is not an existing copyright header in that file, then you can simply add a notice stating that you modified the file.) @@ -91,7 +94,7 @@ best of our understanding. The Modified (3-clause) BSD License =================================== -Copyright (C)2009-2022 D. R. Commander. All Rights Reserved.
+Copyright (C)2009-2023 D. R. Commander. All Rights Reserved.
Copyright (C)2015 Viktor Szathmáry. All Rights Reserved. Redistribution and use in source and binary forms, with or without @@ -119,8 +122,8 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Why Three Licenses? -=================== +Why Two Licenses? +================= The zlib License could have been used instead of the Modified (3-clause) BSD License, and since the IJG License effectively subsumes the distribution diff --git a/3rdparty/libjpeg-turbo/README.ijg b/3rdparty/libjpeg-turbo/README.ijg index 9453c195010f..8f3768265f68 100644 --- a/3rdparty/libjpeg-turbo/README.ijg +++ b/3rdparty/libjpeg-turbo/README.ijg @@ -43,7 +43,7 @@ User documentation: change.log Version-to-version change highlights. Programmer and internal documentation: libjpeg.txt How to use the JPEG library in your own programs. - example.txt Sample code for calling the JPEG library. + example.c Sample code for calling the JPEG library. structure.txt Overview of the JPEG library's internal structure. coderules.txt Coding style rules --- please read if you contribute code. @@ -68,17 +68,17 @@ other abrupt features may not compress well with JPEG, and a higher JPEG quality may have to be used to avoid visible compression artifacts with such images. -JPEG is lossy, meaning that the output pixels are not necessarily identical to -the input pixels. However, on photographic content and other "smooth" images, -very good compression ratios can be obtained with no visible compression -artifacts, and extremely high compression ratios are possible if you are -willing to sacrifice image quality (by reducing the "quality" setting in the -compressor.) - -This software implements JPEG baseline, extended-sequential, and progressive -compression processes. Provision is made for supporting all variants of these -processes, although some uncommon parameter settings aren't implemented yet. -We have made no provision for supporting the hierarchical or lossless +JPEG is normally lossy, meaning that the output pixels are not necessarily +identical to the input pixels. However, on photographic content and other +"smooth" images, very good compression ratios can be obtained with no visible +compression artifacts, and extremely high compression ratios are possible if +you are willing to sacrifice image quality (by reducing the "quality" setting +in the compressor.) + +This software implements JPEG baseline, extended-sequential, progressive, and +lossless compression processes. Provision is made for supporting all variants +of these processes, although some uncommon parameter settings aren't +implemented yet. We have made no provision for supporting the hierarchical processes defined in the standard. We provide a set of library routines for reading and writing JPEG image files, @@ -241,7 +241,7 @@ This software implements ITU T.81 | ISO/IEC 10918 with some extensions from ITU T.871 | ISO/IEC 10918-5 (JPEG File Interchange Format-- see REFERENCES). Informally, the term "JPEG image" or "JPEG file" most often refers to JFIF or a subset thereof, but there are other formats containing the name "JPEG" that -are incompatible with the DCT-based JPEG standard or with JFIF (for instance, +are incompatible with the original JPEG standard or with JFIF (for instance, JPEG 2000 and JPEG XR). This software therefore does not support these formats. Indeed, one of the original reasons for developing this free software was to help force convergence on a common, interoperable format standard for diff --git a/3rdparty/libjpeg-turbo/README.md b/3rdparty/libjpeg-turbo/README.md index 01e391ea7c08..923e61d231c1 100644 --- a/3rdparty/libjpeg-turbo/README.md +++ b/3rdparty/libjpeg-turbo/README.md @@ -21,7 +21,26 @@ derivative of libjpeg v6b developed by Miyasaka Masaru. The TigerVNC and VirtualGL projects made numerous enhancements to the codec in 2009, and in early 2010, libjpeg-turbo spun off into an independent project, with the goal of making high-speed JPEG compression/decompression technology available to a -broader range of users and developers. +broader range of users and developers. libjpeg-turbo is an ISO/IEC and ITU-T +reference implementation of the JPEG standard. + +More information about libjpeg-turbo can be found at +. + + +Funding +======= + +libjpeg-turbo is an independent open source project, but we rely on patronage +and funded development in order to maintain that independence. The easiest way +to ensure that libjpeg-turbo remains community-focused and free of any one +organization's agenda is to +[sponsor our project through GitHub](https://github.com/sponsors/libjpeg-turbo). +All sponsorship money goes directly toward funding the labor necessary to +maintain libjpeg-turbo, support the user community, and implement bug fixes and +strategically important features. + +[![Sponsor libjpeg-turbo](https://img.shields.io/github/sponsors/libjpeg-turbo?label=Sponsor&logo=GitHub)](https://github.com/sponsors/libjpeg-turbo) License @@ -245,16 +264,6 @@ programs that need them, without breaking ABI compatibility for programs that don't, and it allows those functions to be provided in the "official" libjpeg-turbo binaries. -Those who are concerned about maintaining strict conformance with the libjpeg -v6b or v7 API can pass an argument of `-DWITH_MEM_SRCDST=0` to `cmake` prior to -building libjpeg-turbo. This will restore the pre-1.3 behavior, in which -`jpeg_mem_src()` and `jpeg_mem_dest()` are only included when emulating the -libjpeg v8 API/ABI. - -On Un*x systems, including the in-memory source/destination managers changes -the dynamic library version from 62.2.0 to 62.3.0 if using libjpeg v6b API/ABI -emulation and from 7.2.0 to 7.3.0 if using libjpeg v7 API/ABI emulation. - Note that, on most Un*x systems, the dynamic linker will not look for a function in a library until that function is actually used. Thus, if a program is built against libjpeg-turbo 1.3+ and uses `jpeg_mem_src()` or @@ -274,30 +283,35 @@ Mathematical Compatibility ========================== For the most part, libjpeg-turbo should produce identical output to libjpeg -v6b. The one exception to this is when using the floating point DCT/IDCT, in -which case the outputs of libjpeg v6b and libjpeg-turbo can differ for the -following reasons: - -- The SSE/SSE2 floating point DCT implementation in libjpeg-turbo is ever so - slightly more accurate than the implementation in libjpeg v6b, but not by - any amount perceptible to human vision (generally in the range of 0.01 to - 0.08 dB gain in PNSR.) - -- When not using the SIMD extensions, libjpeg-turbo uses the more accurate - (and slightly faster) floating point IDCT algorithm introduced in libjpeg - v8a as opposed to the algorithm used in libjpeg v6b. It should be noted, - however, that this algorithm basically brings the accuracy of the floating - point IDCT in line with the accuracy of the accurate integer IDCT. The - floating point DCT/IDCT algorithms are mainly a legacy feature, and they do - not produce significantly more accuracy than the accurate integer algorithms - (to put numbers on this, the typical difference in PNSR between the two - algorithms is less than 0.10 dB, whereas changing the quality level by 1 in - the upper range of the quality scale is typically more like a 1.0 dB - difference.) - -- If the floating point algorithms in libjpeg-turbo are not implemented using - SIMD instructions on a particular platform, then the accuracy of the - floating point DCT/IDCT can depend on the compiler settings. +v6b. There are two exceptions: + +1. When decompressing a JPEG image that uses 4:4:0 chrominance subsampling, the +outputs of libjpeg v6b and libjpeg-turbo can differ because libjpeg-turbo +implements a "fancy" (smooth) 4:4:0 upsampling algorithm and libjpeg did not. + +2. When using the floating point DCT/IDCT, the outputs of libjpeg v6b and +libjpeg-turbo can differ for the following reasons: + + - The SSE/SSE2 floating point DCT implementation in libjpeg-turbo is ever + so slightly more accurate than the implementation in libjpeg v6b, but not + by any amount perceptible to human vision (generally in the range of 0.01 + to 0.08 dB gain in PNSR.) + + - When not using the SIMD extensions, libjpeg-turbo uses the more accurate + (and slightly faster) floating point IDCT algorithm introduced in libjpeg + v8a as opposed to the algorithm used in libjpeg v6b. It should be noted, + however, that this algorithm basically brings the accuracy of the + floating point IDCT in line with the accuracy of the accurate integer + IDCT. The floating point DCT/IDCT algorithms are mainly a legacy + feature, and they do not produce significantly more accuracy than the + accurate integer algorithms. (To put numbers on this, the typical + difference in PNSR between the two algorithms is less than 0.10 dB, + whereas changing the quality level by 1 in the upper range of the quality + scale is typically more like a 1.0 dB difference.) + + - If the floating point algorithms in libjpeg-turbo are not implemented + using SIMD instructions on a particular platform, then the accuracy of + the floating point DCT/IDCT can depend on the compiler settings. While libjpeg-turbo does emulate the libjpeg v8 API/ABI, under the hood it is still using the same algorithms as libjpeg v6b, so there are several specific diff --git a/3rdparty/libjpeg-turbo/jconfig.h.in b/3rdparty/libjpeg-turbo/jconfig.h.in index d4284d97b812..6cb82962ffeb 100644 --- a/3rdparty/libjpeg-turbo/jconfig.h.in +++ b/3rdparty/libjpeg-turbo/jconfig.h.in @@ -9,60 +9,52 @@ /* libjpeg-turbo version in integer form */ #define LIBJPEG_TURBO_VERSION_NUMBER @LIBJPEG_TURBO_VERSION_NUMBER@ -/* Support arithmetic encoding */ +/* Support arithmetic encoding when using 8-bit samples */ #cmakedefine C_ARITH_CODING_SUPPORTED 1 -/* Support arithmetic decoding */ +/* Support arithmetic decoding when using 8-bit samples */ #cmakedefine D_ARITH_CODING_SUPPORTED 1 /* Support in-memory source/destination managers */ -#cmakedefine MEM_SRCDST_SUPPORTED 1 +#define MEM_SRCDST_SUPPORTED 1 -/* Use accelerated SIMD routines. */ +/* Use accelerated SIMD routines when using 8-bit samples */ #cmakedefine WITH_SIMD 1 -/* - * Define BITS_IN_JSAMPLE as either - * 8 for 8-bit sample values (the usual setting) - * 12 for 12-bit sample values - * Only 8 and 12 are legal data precisions for lossy JPEG according to the - * JPEG standard, and the IJG code does not support anything else! - * We do not support run-time selection of data precision, sorry. +/* This version of libjpeg-turbo supports run-time selection of data precision, + * so BITS_IN_JSAMPLE is no longer used to specify the data precision at build + * time. However, some downstream software expects the macro to be defined. + * Since 12-bit data precision is an opt-in feature that requires explicitly + * calling 12-bit-specific libjpeg API functions and using 12-bit-specific data + * types, the unmodified portion of the libjpeg API still behaves as if it were + * built for 8-bit precision, and JSAMPLE is still literally an 8-bit data + * type. Thus, it is correct to define BITS_IN_JSAMPLE to 8 here. */ +#ifndef BITS_IN_JSAMPLE +#define BITS_IN_JSAMPLE 8 +#endif -#define BITS_IN_JSAMPLE @BITS_IN_JSAMPLE@ /* use 8 or 12 */ +#ifdef _WIN32 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_LOCALE_H 1 +#undef RIGHT_SHIFT_IS_UNSIGNED -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STDDEF_H 1 +/* Define "boolean" as unsigned char, not int, per Windows custom */ +#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +typedef unsigned char boolean; +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STDLIB_H 1 +/* Define "INT32" as int, not long, per Windows custom */ +#if !(defined(_BASETSD_H_) || defined(_BASETSD_H)) /* don't conflict if basetsd.h already read */ +typedef short INT16; +typedef signed int INT32; +#endif +#define XMD_H /* prevent jmorecfg.h from redefining it */ -/* Define if you need to include to get size_t. */ -#cmakedefine NEED_SYS_TYPES_H 1 - -/* Define if you have BSD-like bzero and bcopy in rather than - memset/memcpy in . */ -#cmakedefine NEED_BSD_STRINGS 1 - -/* Define to 1 if the system has the type `unsigned char'. */ -#cmakedefine HAVE_UNSIGNED_CHAR 1 - -/* Define to 1 if the system has the type `unsigned short'. */ -#cmakedefine HAVE_UNSIGNED_SHORT 1 - -/* Compiler does not support pointers to undefined structures. */ -#cmakedefine INCOMPLETE_TYPES_BROKEN 1 +#else /* Define if your (broken) compiler shifts signed values as if they were unsigned. */ #cmakedefine RIGHT_SHIFT_IS_UNSIGNED 1 -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ +#endif diff --git a/3rdparty/libjpeg-turbo/jconfig.h.win.in b/3rdparty/libjpeg-turbo/jconfig.h.win.in deleted file mode 100644 index 13cceef01d13..000000000000 --- a/3rdparty/libjpeg-turbo/jconfig.h.win.in +++ /dev/null @@ -1,33 +0,0 @@ -#define JPEG_LIB_VERSION @JPEG_LIB_VERSION@ -#define LIBJPEG_TURBO_VERSION @VERSION@ -#define LIBJPEG_TURBO_VERSION_NUMBER @LIBJPEG_TURBO_VERSION_NUMBER@ - -#cmakedefine C_ARITH_CODING_SUPPORTED -#cmakedefine D_ARITH_CODING_SUPPORTED -#cmakedefine MEM_SRCDST_SUPPORTED -#cmakedefine WITH_SIMD - -#define BITS_IN_JSAMPLE @BITS_IN_JSAMPLE@ /* use 8 or 12 */ - -#define HAVE_STDDEF_H -#define HAVE_STDLIB_H -#undef NEED_SYS_TYPES_H -#undef NEED_BSD_STRINGS - -#define HAVE_UNSIGNED_CHAR -#define HAVE_UNSIGNED_SHORT -#undef INCOMPLETE_TYPES_BROKEN -#undef RIGHT_SHIFT_IS_UNSIGNED - -/* Define "boolean" as unsigned char, not int, per Windows custom */ -#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ -typedef unsigned char boolean; -#endif -#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ - -/* Define "INT32" as int, not long, per Windows custom */ -#if !(defined(_BASETSD_H_) || defined(_BASETSD_H)) /* don't conflict if basetsd.h already read */ -typedef short INT16; -typedef signed int INT32; -#endif -#define XMD_H /* prevent jmorecfg.h from redefining it */ diff --git a/3rdparty/libjpeg-turbo/jconfigint.h.in b/3rdparty/libjpeg-turbo/jconfigint.h.in index a46979df1e83..5c14e32a1d15 100644 --- a/3rdparty/libjpeg-turbo/jconfigint.h.in +++ b/3rdparty/libjpeg-turbo/jconfigint.h.in @@ -1,19 +1,14 @@ /* libjpeg-turbo build number */ #define BUILD "@BUILD@" +/* How to hide global symbols. */ +#define HIDDEN @HIDDEN@ + /* Compiler's inline keyword */ #undef inline /* How to obtain function inlining. */ -#ifndef INLINE -#if defined(__GNUC__) -#define INLINE inline __attribute__((always_inline)) -#elif defined(_MSC_VER) -#define INLINE __forceinline -#else -#define INLINE -#endif -#endif +#define INLINE @INLINE@ /* How to obtain thread-local storage */ #define THREAD_LOCAL @THREAD_LOCAL@ @@ -25,7 +20,7 @@ #define VERSION "@VERSION@" /* The size of `size_t', as computed by sizeof. */ -#define SIZEOF_SIZE_T @SIZEOF_SIZE_T@ +#define SIZEOF_SIZE_T @SIZE_T@ /* Define if your compiler has __builtin_ctzl() and sizeof(unsigned long) == sizeof(size_t). */ #cmakedefine HAVE_BUILTIN_CTZL @@ -50,3 +45,32 @@ #else #define FALLTHROUGH #endif + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + */ + +#ifndef BITS_IN_JSAMPLE +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ +#endif + +#undef C_ARITH_CODING_SUPPORTED +#undef D_ARITH_CODING_SUPPORTED +#undef WITH_SIMD + +#if BITS_IN_JSAMPLE == 8 + +/* Support arithmetic encoding */ +#cmakedefine C_ARITH_CODING_SUPPORTED 1 + +/* Support arithmetic decoding */ +#cmakedefine D_ARITH_CODING_SUPPORTED 1 + +/* Use accelerated SIMD routines. */ +#cmakedefine WITH_SIMD 1 + +#endif diff --git a/3rdparty/libjpeg-turbo/src/jversion.h b/3rdparty/libjpeg-turbo/jversion.h.in similarity index 79% rename from 3rdparty/libjpeg-turbo/src/jversion.h rename to 3rdparty/libjpeg-turbo/jversion.h.in index 2ab534af4147..fc0ce3e09e3b 100644 --- a/3rdparty/libjpeg-turbo/src/jversion.h +++ b/3rdparty/libjpeg-turbo/jversion.h.in @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding. * libjpeg-turbo Modifications: - * Copyright (C) 2010, 2012-2021, D. R. Commander. + * Copyright (C) 2010, 2012-2024, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -36,19 +36,21 @@ * their code */ -#define JCOPYRIGHT \ - "Copyright (C) 2009-2021 D. R. Commander\n" \ +#define JCOPYRIGHT1 \ + "Copyright (C) 2009-2024 D. R. Commander\n" \ "Copyright (C) 2015, 2020 Google, Inc.\n" \ "Copyright (C) 2019-2020 Arm Limited\n" \ "Copyright (C) 2015-2016, 2018 Matthieu Darbois\n" \ "Copyright (C) 2011-2016 Siarhei Siamashka\n" \ - "Copyright (C) 2015 Intel Corporation\n" \ + "Copyright (C) 2015 Intel Corporation\n" +#define JCOPYRIGHT2 \ "Copyright (C) 2013-2014 Linaro Limited\n" \ "Copyright (C) 2013-2014 MIPS Technologies, Inc.\n" \ "Copyright (C) 2009, 2012 Pierre Ossman for Cendio AB\n" \ "Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \ "Copyright (C) 1999-2006 MIYASAKA Masaru\n" \ - "Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding" + "Copyright (C) 1999 Ken Murchison\n" \ + "Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding\n" #define JCOPYRIGHT_SHORT \ - "Copyright (C) 1991-2021 The libjpeg-turbo Project and many others" + "Copyright (C) @COPYRIGHT_YEAR@ The libjpeg-turbo Project and many others" diff --git a/3rdparty/libjpeg-turbo/src/cjpeg.c b/3rdparty/libjpeg-turbo/src/cjpeg.c new file mode 100644 index 000000000000..44c39bec20da --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/cjpeg.c @@ -0,0 +1,841 @@ +/* + * cjpeg.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2003-2011 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2010, 2013-2014, 2017, 2019-2022, 2024, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains a command-line user interface for the JPEG compressor. + * It should work on any system with Unix- or MS-DOS-style command lines. + * + * Two different command line styles are permitted, depending on the + * compile-time switch TWO_FILE_COMMANDLINE: + * cjpeg [options] inputfile outputfile + * cjpeg [options] [inputfile] + * In the second style, output is always to standard output, which you'd + * normally redirect to a file or pipe to some other program. Input is + * either from a named file or from standard input (typically redirected). + * The second style is convenient on Unix but is unhelpful on systems that + * don't support pipes. Also, you MUST use the first style if your system + * doesn't do binary I/O to stdin/stdout. + * To simplify script writing, the "-outfile" switch is provided. The syntax + * cjpeg [options] -outfile outputfile inputfile + * works regardless of which command line style is used. + */ + +#ifdef _MSC_VER +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#ifdef CJPEG_FUZZER +#define JPEG_INTERNALS +#endif +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include "jversion.h" /* for version message */ +#include "jconfigint.h" + + +/* Create the add-on message string table. */ + +#define JMESSAGE(code, string) string, + +static const char * const cdjpeg_message_table[] = { +#include "cderror.h" + NULL +}; + + +/* + * This routine determines what format the input file is, + * and selects the appropriate input-reading module. + * + * To determine which family of input formats the file belongs to, + * we may look only at the first byte of the file, since C does not + * guarantee that more than one character can be pushed back with ungetc. + * Looking at additional bytes would require one of these approaches: + * 1) assume we can fseek() the input file (fails for piped input); + * 2) assume we can push back more than one character (works in + * some C implementations, but unportable); + * 3) provide our own buffering (breaks input readers that want to use + * stdio directly); + * or 4) don't put back the data, and modify the input_init methods to assume + * they start reading after the start of file. + * #1 is attractive for MS-DOS but is untenable on Unix. + * + * The most portable solution for file types that can't be identified by their + * first byte is to make the user tell us what they are. This is also the + * only approach for "raw" file types that contain only arbitrary values. + * We presently apply this method for Targa files. Most of the time Targa + * files start with 0x00, so we recognize that case. Potentially, however, + * a Targa file could start with any byte value (byte 0 is the length of the + * seldom-used ID field), so we provide a switch to force Targa input mode. + */ + +static boolean is_targa; /* records user -targa switch */ + + +LOCAL(cjpeg_source_ptr) +select_file_type(j_compress_ptr cinfo, FILE *infile) +{ + int c; + + if (is_targa) { +#ifdef TARGA_SUPPORTED + return jinit_read_targa(cinfo); +#else + ERREXIT(cinfo, JERR_TGA_NOTCOMP); +#endif + } + + if ((c = getc(infile)) == EOF) + ERREXIT(cinfo, JERR_INPUT_EMPTY); + if (ungetc(c, infile) == EOF) + ERREXIT(cinfo, JERR_UNGETC_FAILED); + + switch (c) { +#ifdef BMP_SUPPORTED + case 'B': + return jinit_read_bmp(cinfo, TRUE); +#endif +#ifdef GIF_SUPPORTED + case 'G': + if (cinfo->data_precision == 16) { +#ifdef C_LOSSLESS_SUPPORTED + return j16init_read_gif(cinfo); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + break; +#endif + } else if (cinfo->data_precision == 12) + return j12init_read_gif(cinfo); + else + return jinit_read_gif(cinfo); +#endif +#ifdef PPM_SUPPORTED + case 'P': + if (cinfo->data_precision == 16) { +#ifdef C_LOSSLESS_SUPPORTED + return j16init_read_ppm(cinfo); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + break; +#endif + } else if (cinfo->data_precision == 12) + return j12init_read_ppm(cinfo); + else + return jinit_read_ppm(cinfo); +#endif +#ifdef TARGA_SUPPORTED + case 0x00: + return jinit_read_targa(cinfo); +#endif + default: + ERREXIT(cinfo, JERR_UNKNOWN_FORMAT); + break; + } + + return NULL; /* suppress compiler warnings */ +} + + +/* + * Argument-parsing code. + * The switch parser is designed to be useful with DOS-style command line + * syntax, ie, intermixed switches and file names, where only the switches + * to the left of a given file name affect processing of that file. + * The main program in this file doesn't actually use this capability... + */ + + +static const char *progname; /* program name for error messages */ +static char *icc_filename; /* for -icc switch */ +static char *outfilename; /* for -outfile switch */ +static boolean memdst; /* for -memdst switch */ +static boolean report; /* for -report switch */ +static boolean strict; /* for -strict switch */ + + +#ifdef CJPEG_FUZZER + +#include + +struct my_error_mgr { + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; +}; + +void my_error_exit(j_common_ptr cinfo) +{ + struct my_error_mgr *myerr = (struct my_error_mgr *)cinfo->err; + + longjmp(myerr->setjmp_buffer, 1); +} + +static void my_emit_message_fuzzer(j_common_ptr cinfo, int msg_level) +{ + if (msg_level < 0) + cinfo->err->num_warnings++; +} + +#define HANDLE_ERROR() { \ + if (cinfo.global_state > CSTATE_START) { \ + if (memdst && outbuffer) \ + (*cinfo.dest->term_destination) (&cinfo); \ + jpeg_abort_compress(&cinfo); \ + } \ + jpeg_destroy_compress(&cinfo); \ + if (input_file != stdin && input_file != NULL) \ + fclose(input_file); \ + if (memdst) \ + free(outbuffer); \ + return EXIT_FAILURE; \ +} + +#endif + + +LOCAL(void) +usage(void) +/* complain about bad command line */ +{ + fprintf(stderr, "usage: %s [switches] ", progname); +#ifdef TWO_FILE_COMMANDLINE + fprintf(stderr, "inputfile outputfile\n"); +#else + fprintf(stderr, "[inputfile]\n"); +#endif + + fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -quality N[,...] Compression quality (0..100; 5-95 is most useful range,\n"); + fprintf(stderr, " default is 75)\n"); + fprintf(stderr, " -grayscale Create monochrome JPEG file\n"); + fprintf(stderr, " -rgb Create RGB JPEG file\n"); +#ifdef ENTROPY_OPT_SUPPORTED + fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n"); +#endif +#ifdef C_PROGRESSIVE_SUPPORTED + fprintf(stderr, " -progressive Create progressive JPEG file\n"); +#endif +#ifdef TARGA_SUPPORTED + fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n"); +#endif + fprintf(stderr, "Switches for advanced users:\n"); + fprintf(stderr, " -precision N Create JPEG file with N-bit data precision\n"); +#ifdef C_LOSSLESS_SUPPORTED + fprintf(stderr, " (N is 8, 12, or 16; default is 8; if N is 16, then -lossless\n"); + fprintf(stderr, " must also be specified)\n"); +#else + fprintf(stderr, " (N is 8 or 12; default is 8)\n"); +#endif +#ifdef C_LOSSLESS_SUPPORTED + fprintf(stderr, " -lossless psv[,Pt] Create lossless JPEG file\n"); +#endif +#ifdef C_ARITH_CODING_SUPPORTED + fprintf(stderr, " -arithmetic Use arithmetic coding\n"); +#endif +#ifdef DCT_ISLOW_SUPPORTED + fprintf(stderr, " -dct int Use accurate integer DCT method%s\n", + (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : "")); +#endif +#ifdef DCT_IFAST_SUPPORTED + fprintf(stderr, " -dct fast Use less accurate integer DCT method [legacy feature]%s\n", + (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : "")); +#endif +#ifdef DCT_FLOAT_SUPPORTED + fprintf(stderr, " -dct float Use floating-point DCT method [legacy feature]%s\n", + (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : "")); +#endif + fprintf(stderr, " -icc FILE Embed ICC profile contained in FILE\n"); + fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n"); +#ifdef INPUT_SMOOTHING_SUPPORTED + fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n"); +#endif + fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); + fprintf(stderr, " -outfile name Specify name for output file\n"); + fprintf(stderr, " -memdst Compress to memory instead of file (useful for benchmarking)\n"); + fprintf(stderr, " -report Report compression progress\n"); + fprintf(stderr, " -strict Treat all warnings as fatal\n"); + fprintf(stderr, " -verbose or -debug Emit debug output\n"); + fprintf(stderr, " -version Print version information and exit\n"); + fprintf(stderr, "Switches for wizards:\n"); + fprintf(stderr, " -baseline Force baseline quantization tables\n"); + fprintf(stderr, " -qtables FILE Use quantization tables given in FILE\n"); + fprintf(stderr, " -qslots N[,...] Set component quantization tables\n"); + fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n"); +#ifdef C_MULTISCAN_FILES_SUPPORTED + fprintf(stderr, " -scans FILE Create multi-scan JPEG per script FILE\n"); +#endif + exit(EXIT_FAILURE); +} + + +LOCAL(int) +parse_switches(j_compress_ptr cinfo, int argc, char **argv, + int last_file_arg_seen, boolean for_real) +/* Parse optional switches. + * Returns argv[] index of first file-name argument (== argc if none). + * Any file names with indexes <= last_file_arg_seen are ignored; + * they have presumably been processed in a previous iteration. + * (Pass 0 for last_file_arg_seen on the first or only iteration.) + * for_real is FALSE on the first (dummy) pass; we may skip any expensive + * processing. + */ +{ + int argn; + char *arg; +#ifdef C_LOSSLESS_SUPPORTED + int psv, pt = 0; +#endif + boolean force_baseline; + boolean simple_progressive; + char *qualityarg = NULL; /* saves -quality parm if any */ + char *qtablefile = NULL; /* saves -qtables filename if any */ + char *qslotsarg = NULL; /* saves -qslots parm if any */ + char *samplearg = NULL; /* saves -sample parm if any */ + char *scansarg = NULL; /* saves -scans parm if any */ + + /* Set up default JPEG parameters. */ + + force_baseline = FALSE; /* by default, allow 16-bit quantizers */ + simple_progressive = FALSE; + is_targa = FALSE; + icc_filename = NULL; + outfilename = NULL; + memdst = FALSE; + report = FALSE; + strict = FALSE; + cinfo->err->trace_level = 0; + + /* Scan command line options, adjust parameters */ + + for (argn = 1; argn < argc; argn++) { + arg = argv[argn]; + if (*arg != '-') { + /* Not a switch, must be a file name argument */ + if (argn <= last_file_arg_seen) { + outfilename = NULL; /* -outfile applies to just one input file */ + continue; /* ignore this name if previously processed */ + } + break; /* else done parsing switches */ + } + arg++; /* advance past switch marker character */ + + if (keymatch(arg, "arithmetic", 1)) { + /* Use arithmetic coding. */ +#ifdef C_ARITH_CODING_SUPPORTED + cinfo->arith_code = TRUE; +#else + fprintf(stderr, "%s: sorry, arithmetic coding not supported\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "baseline", 1)) { + /* Force baseline-compatible output (8-bit quantizer values). */ + force_baseline = TRUE; + + } else if (keymatch(arg, "dct", 2)) { + /* Select DCT algorithm. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "int", 1)) { + cinfo->dct_method = JDCT_ISLOW; + } else if (keymatch(argv[argn], "fast", 2)) { + cinfo->dct_method = JDCT_IFAST; + } else if (keymatch(argv[argn], "float", 2)) { + cinfo->dct_method = JDCT_FLOAT; + } else + usage(); + + } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { + /* Enable debug printouts. */ + /* On first -d, print version identification */ + static boolean printed_version = FALSE; + + if (!printed_version) { + fprintf(stderr, "%s version %s (build %s)\n", + PACKAGE_NAME, VERSION, BUILD); + fprintf(stderr, JCOPYRIGHT1); + fprintf(stderr, JCOPYRIGHT2 "\n"); + fprintf(stderr, "Emulating The Independent JPEG Group's software, version %s\n\n", + JVERSION); + printed_version = TRUE; + } + cinfo->err->trace_level++; + + } else if (keymatch(arg, "version", 4)) { + fprintf(stderr, "%s version %s (build %s)\n", + PACKAGE_NAME, VERSION, BUILD); + exit(EXIT_SUCCESS); + + } else if (keymatch(arg, "grayscale", 2) || + keymatch(arg, "greyscale", 2)) { + /* Force a monochrome JPEG file to be generated. */ + jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); + + } else if (keymatch(arg, "rgb", 3)) { + /* Force an RGB JPEG file to be generated. */ + jpeg_set_colorspace(cinfo, JCS_RGB); + + } else if (keymatch(arg, "icc", 1)) { + /* Set ICC filename. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + icc_filename = argv[argn]; + + } else if (keymatch(arg, "lossless", 1)) { + /* Enable lossless mode. */ +#ifdef C_LOSSLESS_SUPPORTED + char ch = ',', *ptr; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d%c", &psv, &ch) < 1 || ch != ',') + usage(); + ptr = argv[argn]; + while (*ptr && *ptr++ != ','); /* advance to next segment of arg + string */ + if (*ptr) + sscanf(ptr, "%d", &pt); + jpeg_enable_lossless(cinfo, psv, pt); +#else + fprintf(stderr, "%s: sorry, lossless output was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "maxmemory", 3)) { + /* Maximum memory in Kb (or Mb with 'm'). */ + long lval; + char ch = 'x'; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) + usage(); + if (ch == 'm' || ch == 'M') + lval *= 1000L; + cinfo->mem->max_memory_to_use = lval * 1000L; + + } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) { + /* Enable entropy parm optimization. */ +#ifdef ENTROPY_OPT_SUPPORTED + cinfo->optimize_coding = TRUE; +#else + fprintf(stderr, "%s: sorry, entropy optimization was not compiled in\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "outfile", 4)) { + /* Set output file name. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + outfilename = argv[argn]; /* save it away for later use */ + + } else if (keymatch(arg, "precision", 3)) { + /* Set data precision. */ + int val; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d", &val) != 1) + usage(); +#ifdef C_LOSSLESS_SUPPORTED + if (val != 8 && val != 12 && val != 16) +#else + if (val != 8 && val != 12) +#endif + usage(); + cinfo->data_precision = val; + + } else if (keymatch(arg, "progressive", 3)) { + /* Select simple progressive mode. */ +#ifdef C_PROGRESSIVE_SUPPORTED + simple_progressive = TRUE; + /* We must postpone execution until num_components is known. */ +#else + fprintf(stderr, "%s: sorry, progressive output was not compiled in\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "memdst", 2)) { + /* Use in-memory destination manager */ + memdst = TRUE; + + } else if (keymatch(arg, "quality", 1)) { + /* Quality ratings (quantization table scaling factors). */ + if (++argn >= argc) /* advance to next argument */ + usage(); + qualityarg = argv[argn]; + + } else if (keymatch(arg, "qslots", 2)) { + /* Quantization table slot numbers. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + qslotsarg = argv[argn]; + /* Must delay setting qslots until after we have processed any + * colorspace-determining switches, since jpeg_set_colorspace sets + * default quant table numbers. + */ + + } else if (keymatch(arg, "qtables", 2)) { + /* Quantization tables fetched from file. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + qtablefile = argv[argn]; + /* We postpone actually reading the file in case -quality comes later. */ + + } else if (keymatch(arg, "report", 3)) { + report = TRUE; + + } else if (keymatch(arg, "restart", 1)) { + /* Restart interval in MCU rows (or in MCUs with 'b'). */ + long lval; + char ch = 'x'; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) + usage(); + if (lval < 0 || lval > 65535L) + usage(); + if (ch == 'b' || ch == 'B') { + cinfo->restart_interval = (unsigned int)lval; + cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */ + } else { + cinfo->restart_in_rows = (int)lval; + /* restart_interval will be computed during startup */ + } + + } else if (keymatch(arg, "sample", 2)) { + /* Set sampling factors. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + samplearg = argv[argn]; + /* Must delay setting sample factors until after we have processed any + * colorspace-determining switches, since jpeg_set_colorspace sets + * default sampling factors. + */ + + } else if (keymatch(arg, "scans", 4)) { + /* Set scan script. */ +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (++argn >= argc) /* advance to next argument */ + usage(); + scansarg = argv[argn]; + /* We must postpone reading the file in case -progressive appears. */ +#else + fprintf(stderr, "%s: sorry, multi-scan output was not compiled in\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "smooth", 2)) { + /* Set input smoothing factor. */ + int val; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d", &val) != 1) + usage(); + if (val < 0 || val > 100) + usage(); + cinfo->smoothing_factor = val; + + } else if (keymatch(arg, "strict", 2)) { + strict = TRUE; + + } else if (keymatch(arg, "targa", 1)) { + /* Input file is Targa format. */ + is_targa = TRUE; + + } else { + usage(); /* bogus switch */ + } + } + + /* Post-switch-scanning cleanup */ + + if (for_real) { + + /* Set quantization tables for selected quality. */ + /* Some or all may be overridden if -qtables is present. */ + if (qualityarg != NULL) /* process -quality if it was present */ + if (!set_quality_ratings(cinfo, qualityarg, force_baseline)) + usage(); + + if (qtablefile != NULL) /* process -qtables if it was present */ + if (!read_quant_tables(cinfo, qtablefile, force_baseline)) + usage(); + + if (qslotsarg != NULL) /* process -qslots if it was present */ + if (!set_quant_slots(cinfo, qslotsarg)) + usage(); + + if (samplearg != NULL) /* process -sample if it was present */ + if (!set_sample_factors(cinfo, samplearg)) + usage(); + +#ifdef C_PROGRESSIVE_SUPPORTED + if (simple_progressive) /* process -progressive; -scans can override */ + jpeg_simple_progression(cinfo); +#endif + +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (scansarg != NULL) /* process -scans if it was present */ + if (!read_scan_script(cinfo, scansarg)) + usage(); +#endif + } + + return argn; /* return index of next arg (file name) */ +} + + +METHODDEF(void) +my_emit_message(j_common_ptr cinfo, int msg_level) +{ + if (msg_level < 0) { + /* Treat warning as fatal */ + cinfo->err->error_exit(cinfo); + } else { + if (cinfo->err->trace_level >= msg_level) + cinfo->err->output_message(cinfo); + } +} + + +/* + * The main program. + */ + +int +main(int argc, char **argv) +{ + struct jpeg_compress_struct cinfo; +#ifdef CJPEG_FUZZER + struct my_error_mgr myerr; + struct jpeg_error_mgr &jerr = myerr.pub; +#else + struct jpeg_error_mgr jerr; +#endif + struct cdjpeg_progress_mgr progress; + int file_index; + cjpeg_source_ptr src_mgr; + FILE *input_file = NULL; + FILE *icc_file; + JOCTET *icc_profile = NULL; + long icc_len = 0; + FILE *output_file = NULL; + unsigned char *outbuffer = NULL; + unsigned long outsize = 0; + JDIMENSION num_scanlines; + + progname = argv[0]; + if (progname == NULL || progname[0] == 0) + progname = "cjpeg"; /* in case C library doesn't provide it */ + + /* Initialize the JPEG compression object with default error handling. */ + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + /* Add some application-specific error messages (from cderror.h) */ + jerr.addon_message_table = cdjpeg_message_table; + jerr.first_addon_message = JMSG_FIRSTADDONCODE; + jerr.last_addon_message = JMSG_LASTADDONCODE; + + /* Initialize JPEG parameters. + * Much of this may be overridden later. + * In particular, we don't yet know the input file's color space, + * but we need to provide some value for jpeg_set_defaults() to work. + */ + + cinfo.in_color_space = JCS_RGB; /* arbitrary guess */ + jpeg_set_defaults(&cinfo); + + /* Scan command line to find file names. + * It is convenient to use just one switch-parsing routine, but the switch + * values read here are ignored; we will rescan the switches after opening + * the input file. + */ + + file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); + + if (strict) + jerr.emit_message = my_emit_message; + +#ifdef TWO_FILE_COMMANDLINE + if (!memdst) { + /* Must have either -outfile switch or explicit output file name */ + if (outfilename == NULL) { + if (file_index != argc - 2) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + outfilename = argv[file_index + 1]; + } else { + if (file_index != argc - 1) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + } + } +#else + /* Unix style: expect zero or one file name */ + if (file_index < argc - 1) { + fprintf(stderr, "%s: only one input file\n", progname); + usage(); + } +#endif /* TWO_FILE_COMMANDLINE */ + + /* Open the input file. */ + if (file_index < argc) { + if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); + exit(EXIT_FAILURE); + } + } else { + /* default input file is stdin */ + input_file = read_stdin(); + } + + /* Open the output file. */ + if (outfilename != NULL) { + if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, outfilename); + exit(EXIT_FAILURE); + } + } else if (!memdst) { + /* default output file is stdout */ + output_file = write_stdout(); + } + + if (icc_filename != NULL) { + if ((icc_file = fopen(icc_filename, READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, icc_filename); + exit(EXIT_FAILURE); + } + if (fseek(icc_file, 0, SEEK_END) < 0 || + (icc_len = ftell(icc_file)) < 1 || + fseek(icc_file, 0, SEEK_SET) < 0) { + fprintf(stderr, "%s: can't determine size of %s\n", progname, + icc_filename); + exit(EXIT_FAILURE); + } + if ((icc_profile = (JOCTET *)malloc(icc_len)) == NULL) { + fprintf(stderr, "%s: can't allocate memory for ICC profile\n", progname); + fclose(icc_file); + exit(EXIT_FAILURE); + } + if (fread(icc_profile, icc_len, 1, icc_file) < 1) { + fprintf(stderr, "%s: can't read ICC profile from %s\n", progname, + icc_filename); + free(icc_profile); + fclose(icc_file); + exit(EXIT_FAILURE); + } + fclose(icc_file); + } + +#ifdef CJPEG_FUZZER + jerr.error_exit = my_error_exit; + jerr.emit_message = my_emit_message_fuzzer; + if (setjmp(myerr.setjmp_buffer)) + HANDLE_ERROR() +#endif + + if (report) { + start_progress_monitor((j_common_ptr)&cinfo, &progress); + progress.report = report; + } + + /* Figure out the input file format, and set up to read it. */ + src_mgr = select_file_type(&cinfo, input_file); + src_mgr->input_file = input_file; +#ifdef CJPEG_FUZZER + src_mgr->max_pixels = 1048576; +#endif + + /* Read the input file header to obtain file size & colorspace. */ + (*src_mgr->start_input) (&cinfo, src_mgr); + + /* Now that we know input colorspace, fix colorspace-dependent defaults */ + jpeg_default_colorspace(&cinfo); + + /* Adjust default compression parameters by re-parsing the options */ + file_index = parse_switches(&cinfo, argc, argv, 0, TRUE); + + /* Specify data destination for compression */ + if (memdst) + jpeg_mem_dest(&cinfo, &outbuffer, &outsize); + else + jpeg_stdio_dest(&cinfo, output_file); + +#ifdef CJPEG_FUZZER + if (setjmp(myerr.setjmp_buffer)) + HANDLE_ERROR() +#endif + + /* Start compressor */ + jpeg_start_compress(&cinfo, TRUE); + + if (icc_profile != NULL) + jpeg_write_icc_profile(&cinfo, icc_profile, (unsigned int)icc_len); + + /* Process data */ + if (cinfo.data_precision == 16) { +#ifdef C_LOSSLESS_SUPPORTED + while (cinfo.next_scanline < cinfo.image_height) { + num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr); + (void)jpeg16_write_scanlines(&cinfo, src_mgr->buffer16, num_scanlines); + } +#else + ERREXIT1(&cinfo, JERR_BAD_PRECISION, cinfo.data_precision); +#endif + } else if (cinfo.data_precision == 12) { + while (cinfo.next_scanline < cinfo.image_height) { + num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr); + (void)jpeg12_write_scanlines(&cinfo, src_mgr->buffer12, num_scanlines); + } + } else { + while (cinfo.next_scanline < cinfo.image_height) { + num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr); + (void)jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines); + } + } + + /* Finish compression and release memory */ + (*src_mgr->finish_input) (&cinfo, src_mgr); + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + /* Close files, if we opened them */ + if (input_file != stdin) + fclose(input_file); + if (output_file != stdout && output_file != NULL) + fclose(output_file); + + if (report) + end_progress_monitor((j_common_ptr)&cinfo); + + if (memdst) { +#ifndef CJPEG_FUZZER + fprintf(stderr, "Compressed size: %lu bytes\n", outsize); +#endif + free(outbuffer); + } + + free(icc_profile); + + /* All done. */ + return (jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); +} diff --git a/3rdparty/libjpeg-turbo/src/cmyk.h b/3rdparty/libjpeg-turbo/src/cmyk.h new file mode 100644 index 000000000000..23891249cfd1 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/cmyk.h @@ -0,0 +1,61 @@ +/* + * cmyk.h + * + * Copyright (C) 2017-2018, 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains convenience functions for performing quick & dirty + * CMYK<->RGB conversion. This algorithm is suitable for testing purposes + * only. Properly converting between CMYK and RGB requires a color management + * system. + */ + +#ifndef CMYK_H +#define CMYK_H + +#include +#define JPEG_INTERNALS +#include +#include "jsamplecomp.h" + + +/* Fully reversible */ + +INLINE +LOCAL(void) +rgb_to_cmyk(_JSAMPLE r, _JSAMPLE g, _JSAMPLE b, + _JSAMPLE *c, _JSAMPLE *m, _JSAMPLE *y, _JSAMPLE *k) +{ + double ctmp = 1.0 - ((double)r / (double)_MAXJSAMPLE); + double mtmp = 1.0 - ((double)g / (double)_MAXJSAMPLE); + double ytmp = 1.0 - ((double)b / (double)_MAXJSAMPLE); + double ktmp = MIN(MIN(ctmp, mtmp), ytmp); + + if (ktmp == 1.0) ctmp = mtmp = ytmp = 0.0; + else { + ctmp = (ctmp - ktmp) / (1.0 - ktmp); + mtmp = (mtmp - ktmp) / (1.0 - ktmp); + ytmp = (ytmp - ktmp) / (1.0 - ktmp); + } + *c = (_JSAMPLE)((double)_MAXJSAMPLE - ctmp * (double)_MAXJSAMPLE + 0.5); + *m = (_JSAMPLE)((double)_MAXJSAMPLE - mtmp * (double)_MAXJSAMPLE + 0.5); + *y = (_JSAMPLE)((double)_MAXJSAMPLE - ytmp * (double)_MAXJSAMPLE + 0.5); + *k = (_JSAMPLE)((double)_MAXJSAMPLE - ktmp * (double)_MAXJSAMPLE + 0.5); +} + + +/* Fully reversible only for C/M/Y/K values generated with rgb_to_cmyk() */ + +INLINE +LOCAL(void) +cmyk_to_rgb(_JSAMPLE c, _JSAMPLE m, _JSAMPLE y, _JSAMPLE k, + _JSAMPLE *r, _JSAMPLE *g, _JSAMPLE *b) +{ + *r = (_JSAMPLE)((double)c * (double)k / (double)_MAXJSAMPLE + 0.5); + *g = (_JSAMPLE)((double)m * (double)k / (double)_MAXJSAMPLE + 0.5); + *b = (_JSAMPLE)((double)y * (double)k / (double)_MAXJSAMPLE + 0.5); +} + + +#endif /* CMYK_H */ diff --git a/3rdparty/libjpeg-turbo/src/djpeg.c b/3rdparty/libjpeg-turbo/src/djpeg.c new file mode 100644 index 000000000000..1baedddeff89 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/djpeg.c @@ -0,0 +1,932 @@ +/* + * djpeg.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2013-2019 by Guido Vollbeding. + * libjpeg-turbo Modifications: + * Copyright (C) 2010-2011, 2013-2017, 2019-2020, 2022-2024, D. R. Commander. + * Copyright (C) 2015, Google, Inc. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains a command-line user interface for the JPEG decompressor. + * It should work on any system with Unix- or MS-DOS-style command lines. + * + * Two different command line styles are permitted, depending on the + * compile-time switch TWO_FILE_COMMANDLINE: + * djpeg [options] inputfile outputfile + * djpeg [options] [inputfile] + * In the second style, output is always to standard output, which you'd + * normally redirect to a file or pipe to some other program. Input is + * either from a named file or from standard input (typically redirected). + * The second style is convenient on Unix but is unhelpful on systems that + * don't support pipes. Also, you MUST use the first style if your system + * doesn't do binary I/O to stdin/stdout. + * To simplify script writing, the "-outfile" switch is provided. The syntax + * djpeg [options] -outfile outputfile inputfile + * works regardless of which command line style is used. + */ + +#ifdef _MSC_VER +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include "jversion.h" /* for version message */ +#include "jconfigint.h" + +#include /* to declare isprint() */ + + +/* Create the add-on message string table. */ + +#define JMESSAGE(code, string) string, + +static const char * const cdjpeg_message_table[] = { +#include "cderror.h" + NULL +}; + + +/* + * This list defines the known output image formats + * (not all of which need be supported by a given version). + * You can change the default output format by defining DEFAULT_FMT; + * indeed, you had better do so if you undefine PPM_SUPPORTED. + */ + +typedef enum { + FMT_BMP, /* BMP format (Windows flavor) */ + FMT_GIF, /* GIF format (LZW-compressed) */ + FMT_GIF0, /* GIF format (uncompressed) */ + FMT_OS2, /* BMP format (OS/2 flavor) */ + FMT_PPM, /* PPM/PGM (PBMPLUS formats) */ + FMT_TARGA, /* Targa format */ + FMT_TIFF /* TIFF format */ +} IMAGE_FORMATS; + +#ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */ +#define DEFAULT_FMT FMT_PPM +#endif + +static IMAGE_FORMATS requested_fmt; + + +/* + * Argument-parsing code. + * The switch parser is designed to be useful with DOS-style command line + * syntax, ie, intermixed switches and file names, where only the switches + * to the left of a given file name affect processing of that file. + * The main program in this file doesn't actually use this capability... + */ + + +static const char *progname; /* program name for error messages */ +static char *icc_filename; /* for -icc switch */ +static JDIMENSION max_scans; /* for -maxscans switch */ +static char *outfilename; /* for -outfile switch */ +static boolean memsrc; /* for -memsrc switch */ +static boolean report; /* for -report switch */ +static boolean skip, crop; +static JDIMENSION skip_start, skip_end; +static JDIMENSION crop_x, crop_y, crop_width, crop_height; +static boolean strict; /* for -strict switch */ +#define INPUT_BUF_SIZE 4096 + + +LOCAL(void) +usage(void) +/* complain about bad command line */ +{ + fprintf(stderr, "usage: %s [switches] ", progname); +#ifdef TWO_FILE_COMMANDLINE + fprintf(stderr, "inputfile outputfile\n"); +#else + fprintf(stderr, "[inputfile]\n"); +#endif + + fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -colors N Reduce image to no more than N colors\n"); + fprintf(stderr, " -fast Fast, low-quality processing\n"); + fprintf(stderr, " -grayscale Force grayscale output\n"); + fprintf(stderr, " -rgb Force RGB output\n"); + fprintf(stderr, " -rgb565 Force RGB565 output\n"); +#ifdef IDCT_SCALING_SUPPORTED + fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n"); +#endif +#ifdef BMP_SUPPORTED + fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n", + (DEFAULT_FMT == FMT_BMP ? " (default)" : "")); +#endif +#ifdef GIF_SUPPORTED + fprintf(stderr, " -gif Select GIF output format (LZW-compressed)%s\n", + (DEFAULT_FMT == FMT_GIF ? " (default)" : "")); + fprintf(stderr, " -gif0 Select GIF output format (uncompressed)%s\n", + (DEFAULT_FMT == FMT_GIF0 ? " (default)" : "")); +#endif +#ifdef BMP_SUPPORTED + fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n", + (DEFAULT_FMT == FMT_OS2 ? " (default)" : "")); +#endif +#ifdef PPM_SUPPORTED + fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n", + (DEFAULT_FMT == FMT_PPM ? " (default)" : "")); +#endif +#ifdef TARGA_SUPPORTED + fprintf(stderr, " -targa Select Targa output format%s\n", + (DEFAULT_FMT == FMT_TARGA ? " (default)" : "")); +#endif + fprintf(stderr, "Switches for advanced users:\n"); +#ifdef DCT_ISLOW_SUPPORTED + fprintf(stderr, " -dct int Use accurate integer DCT method%s\n", + (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : "")); +#endif +#ifdef DCT_IFAST_SUPPORTED + fprintf(stderr, " -dct fast Use less accurate integer DCT method [legacy feature]%s\n", + (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : "")); +#endif +#ifdef DCT_FLOAT_SUPPORTED + fprintf(stderr, " -dct float Use floating-point DCT method [legacy feature]%s\n", + (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : "")); +#endif + fprintf(stderr, " -dither fs Use F-S dithering (default)\n"); + fprintf(stderr, " -dither none Don't use dithering in quantization\n"); + fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)\n"); + fprintf(stderr, " -icc FILE Extract ICC profile to FILE\n"); +#ifdef QUANT_2PASS_SUPPORTED + fprintf(stderr, " -map FILE Map to colors used in named image file\n"); +#endif + fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n"); +#ifdef QUANT_1PASS_SUPPORTED + fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n"); +#endif + fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); + fprintf(stderr, " -maxscans N Maximum number of scans to allow in input file\n"); + fprintf(stderr, " -outfile name Specify name for output file\n"); + fprintf(stderr, " -memsrc Load input file into memory before decompressing\n"); + fprintf(stderr, " -report Report decompression progress\n"); + fprintf(stderr, " -skip Y0,Y1 Decompress all rows except those between Y0 and Y1 (inclusive)\n"); + fprintf(stderr, " -crop WxH+X+Y Decompress only a rectangular subregion of the image\n"); + fprintf(stderr, " [requires PBMPLUS (PPM/PGM), GIF, or Targa output format]\n"); + fprintf(stderr, " -strict Treat all warnings as fatal\n"); + fprintf(stderr, " -verbose or -debug Emit debug output\n"); + fprintf(stderr, " -version Print version information and exit\n"); + exit(EXIT_FAILURE); +} + + +LOCAL(int) +parse_switches(j_decompress_ptr cinfo, int argc, char **argv, + int last_file_arg_seen, boolean for_real) +/* Parse optional switches. + * Returns argv[] index of first file-name argument (== argc if none). + * Any file names with indexes <= last_file_arg_seen are ignored; + * they have presumably been processed in a previous iteration. + * (Pass 0 for last_file_arg_seen on the first or only iteration.) + * for_real is FALSE on the first (dummy) pass; we may skip any expensive + * processing. + */ +{ + int argn; + char *arg; + + /* Set up default JPEG parameters. */ + requested_fmt = DEFAULT_FMT; /* set default output file format */ + icc_filename = NULL; + max_scans = 0; + outfilename = NULL; + memsrc = FALSE; + report = FALSE; + skip = FALSE; + crop = FALSE; + strict = FALSE; + cinfo->err->trace_level = 0; + + /* Scan command line options, adjust parameters */ + + for (argn = 1; argn < argc; argn++) { + arg = argv[argn]; + if (*arg != '-') { + /* Not a switch, must be a file name argument */ + if (argn <= last_file_arg_seen) { + outfilename = NULL; /* -outfile applies to just one input file */ + continue; /* ignore this name if previously processed */ + } + break; /* else done parsing switches */ + } + arg++; /* advance past switch marker character */ + + if (keymatch(arg, "bmp", 1)) { + /* BMP output format (Windows flavor). */ + requested_fmt = FMT_BMP; + + } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) || + keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) { + /* Do color quantization. */ + int val; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d", &val) != 1) + usage(); + cinfo->desired_number_of_colors = val; + cinfo->quantize_colors = TRUE; + + } else if (keymatch(arg, "dct", 2)) { + /* Select IDCT algorithm. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "int", 1)) { + cinfo->dct_method = JDCT_ISLOW; + } else if (keymatch(argv[argn], "fast", 2)) { + cinfo->dct_method = JDCT_IFAST; + } else if (keymatch(argv[argn], "float", 2)) { + cinfo->dct_method = JDCT_FLOAT; + } else + usage(); + + } else if (keymatch(arg, "dither", 2)) { + /* Select dithering algorithm. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "fs", 2)) { + cinfo->dither_mode = JDITHER_FS; + } else if (keymatch(argv[argn], "none", 2)) { + cinfo->dither_mode = JDITHER_NONE; + } else if (keymatch(argv[argn], "ordered", 2)) { + cinfo->dither_mode = JDITHER_ORDERED; + } else + usage(); + + } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { + /* Enable debug printouts. */ + /* On first -d, print version identification */ + static boolean printed_version = FALSE; + + if (!printed_version) { + fprintf(stderr, "%s version %s (build %s)\n", + PACKAGE_NAME, VERSION, BUILD); + fprintf(stderr, JCOPYRIGHT1); + fprintf(stderr, JCOPYRIGHT2 "\n"); + fprintf(stderr, "Emulating The Independent JPEG Group's software, version %s\n\n", + JVERSION); + printed_version = TRUE; + } + cinfo->err->trace_level++; + + } else if (keymatch(arg, "version", 4)) { + fprintf(stderr, "%s version %s (build %s)\n", + PACKAGE_NAME, VERSION, BUILD); + exit(EXIT_SUCCESS); + + } else if (keymatch(arg, "fast", 1)) { + /* Select recommended processing options for quick-and-dirty output. */ + cinfo->two_pass_quantize = FALSE; + cinfo->dither_mode = JDITHER_ORDERED; + if (!cinfo->quantize_colors) /* don't override an earlier -colors */ + cinfo->desired_number_of_colors = 216; + cinfo->dct_method = JDCT_FASTEST; + cinfo->do_fancy_upsampling = FALSE; + + } else if (keymatch(arg, "gif", 1)) { + /* GIF output format (LZW-compressed). */ + requested_fmt = FMT_GIF; + + } else if (keymatch(arg, "gif0", 4)) { + /* GIF output format (uncompressed). */ + requested_fmt = FMT_GIF0; + + } else if (keymatch(arg, "grayscale", 2) || + keymatch(arg, "greyscale", 2)) { + /* Force monochrome output. */ + cinfo->out_color_space = JCS_GRAYSCALE; + + } else if (keymatch(arg, "rgb", 2)) { + /* Force RGB output. */ + cinfo->out_color_space = JCS_RGB; + + } else if (keymatch(arg, "rgb565", 2)) { + /* Force RGB565 output. */ + cinfo->out_color_space = JCS_RGB565; + + } else if (keymatch(arg, "icc", 1)) { + /* Set ICC filename. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + icc_filename = argv[argn]; +#ifdef SAVE_MARKERS_SUPPORTED + jpeg_save_markers(cinfo, JPEG_APP0 + 2, 0xFFFF); +#endif + + } else if (keymatch(arg, "map", 3)) { + /* Quantize to a color map taken from an input file. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (for_real) { /* too expensive to do twice! */ +#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */ + FILE *mapfile; + + if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); + exit(EXIT_FAILURE); + } + if (cinfo->data_precision == 12) + read_color_map_12(cinfo, mapfile); + else + read_color_map(cinfo, mapfile); + fclose(mapfile); + cinfo->quantize_colors = TRUE; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + + } else if (keymatch(arg, "maxmemory", 3)) { + /* Maximum memory in Kb (or Mb with 'm'). */ + long lval; + char ch = 'x'; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) + usage(); + if (ch == 'm' || ch == 'M') + lval *= 1000L; + cinfo->mem->max_memory_to_use = lval * 1000L; + + } else if (keymatch(arg, "maxscans", 4)) { + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%u", &max_scans) != 1) + usage(); + + } else if (keymatch(arg, "nosmooth", 3)) { + /* Suppress fancy upsampling */ + cinfo->do_fancy_upsampling = FALSE; + + } else if (keymatch(arg, "onepass", 3)) { + /* Use fast one-pass quantization. */ + cinfo->two_pass_quantize = FALSE; + + } else if (keymatch(arg, "os2", 3)) { + /* BMP output format (OS/2 flavor). */ + requested_fmt = FMT_OS2; + + } else if (keymatch(arg, "outfile", 4)) { + /* Set output file name. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + outfilename = argv[argn]; /* save it away for later use */ + + } else if (keymatch(arg, "memsrc", 2)) { + /* Use in-memory source manager */ + memsrc = TRUE; + + } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) { + /* PPM/PGM output format. */ + requested_fmt = FMT_PPM; + + } else if (keymatch(arg, "report", 2)) { + report = TRUE; + + } else if (keymatch(arg, "scale", 2)) { + /* Scale the output image by a fraction M/N. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%u/%u", + &cinfo->scale_num, &cinfo->scale_denom) != 2) + usage(); + + } else if (keymatch(arg, "skip", 2)) { + if (++argn >= argc) + usage(); + if (sscanf(argv[argn], "%u,%u", &skip_start, &skip_end) != 2 || + skip_start > skip_end) + usage(); + skip = TRUE; + + } else if (keymatch(arg, "crop", 2)) { + char c; + if (++argn >= argc) + usage(); + if (sscanf(argv[argn], "%u%c%u+%u+%u", &crop_width, &c, &crop_height, + &crop_x, &crop_y) != 5 || + (c != 'X' && c != 'x') || crop_width < 1 || crop_height < 1) + usage(); + crop = TRUE; + + } else if (keymatch(arg, "strict", 2)) { + strict = TRUE; + + } else if (keymatch(arg, "targa", 1)) { + /* Targa output format. */ + requested_fmt = FMT_TARGA; + + } else { + usage(); /* bogus switch */ + } + } + + return argn; /* return index of next arg (file name) */ +} + + +/* + * Marker processor for COM and interesting APPn markers. + * This replaces the library's built-in processor, which just skips the marker. + * We want to print out the marker as text, to the extent possible. + * Note this code relies on a non-suspending data source. + */ + +LOCAL(unsigned int) +jpeg_getc(j_decompress_ptr cinfo) +/* Read next byte */ +{ + struct jpeg_source_mgr *datasrc = cinfo->src; + + if (datasrc->bytes_in_buffer == 0) { + if (!(*datasrc->fill_input_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } + datasrc->bytes_in_buffer--; + return *datasrc->next_input_byte++; +} + + +METHODDEF(boolean) +print_text_marker(j_decompress_ptr cinfo) +{ + boolean traceit = (cinfo->err->trace_level >= 1); + long length; + unsigned int ch; + unsigned int lastch = 0; + + length = jpeg_getc(cinfo) << 8; + length += jpeg_getc(cinfo); + length -= 2; /* discount the length word itself */ + + if (traceit) { + if (cinfo->unread_marker == JPEG_COM) + fprintf(stderr, "Comment, length %ld:\n", (long)length); + else /* assume it is an APPn otherwise */ + fprintf(stderr, "APP%d, length %ld:\n", + cinfo->unread_marker - JPEG_APP0, (long)length); + } + + while (--length >= 0) { + ch = jpeg_getc(cinfo); + if (traceit) { + /* Emit the character in a readable form. + * Nonprintables are converted to \nnn form, + * while \ is converted to \\. + * Newlines in CR, CR/LF, or LF form will be printed as one newline. + */ + if (ch == '\r') { + fprintf(stderr, "\n"); + } else if (ch == '\n') { + if (lastch != '\r') + fprintf(stderr, "\n"); + } else if (ch == '\\') { + fprintf(stderr, "\\\\"); + } else if (isprint(ch)) { + putc(ch, stderr); + } else { + fprintf(stderr, "\\%03o", ch); + } + lastch = ch; + } + } + + if (traceit) + fprintf(stderr, "\n"); + + return TRUE; +} + + +METHODDEF(void) +my_emit_message(j_common_ptr cinfo, int msg_level) +{ + if (msg_level < 0) { + /* Treat warning as fatal */ + cinfo->err->error_exit(cinfo); + } else { + if (cinfo->err->trace_level >= msg_level) + cinfo->err->output_message(cinfo); + } +} + + +/* + * The main program. + */ + +int +main(int argc, char **argv) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + struct cdjpeg_progress_mgr progress; + int file_index; + djpeg_dest_ptr dest_mgr = NULL; + FILE *input_file; + FILE *output_file; + unsigned char *inbuffer = NULL; + unsigned long insize = 0; + JDIMENSION num_scanlines; + + progname = argv[0]; + if (progname == NULL || progname[0] == 0) + progname = "djpeg"; /* in case C library doesn't provide it */ + + /* Initialize the JPEG decompression object with default error handling. */ + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + /* Add some application-specific error messages (from cderror.h) */ + jerr.addon_message_table = cdjpeg_message_table; + jerr.first_addon_message = JMSG_FIRSTADDONCODE; + jerr.last_addon_message = JMSG_LASTADDONCODE; + + /* Insert custom marker processor for COM and APP12. + * APP12 is used by some digital camera makers for textual info, + * so we provide the ability to display it as text. + * If you like, additional APPn marker types can be selected for display, + * but don't try to override APP0 or APP14 this way (see libjpeg.txt). + */ + jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker); + jpeg_set_marker_processor(&cinfo, JPEG_APP0 + 12, print_text_marker); + + /* Scan command line to find file names. */ + /* It is convenient to use just one switch-parsing routine, but the switch + * values read here are ignored; we will rescan the switches after opening + * the input file. + * (Exception: tracing level set here controls verbosity for COM markers + * found during jpeg_read_header...) + */ + + file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); + + if (strict) + jerr.emit_message = my_emit_message; + +#ifdef TWO_FILE_COMMANDLINE + /* Must have either -outfile switch or explicit output file name */ + if (outfilename == NULL) { + if (file_index != argc - 2) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + outfilename = argv[file_index + 1]; + } else { + if (file_index != argc - 1) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + } +#else + /* Unix style: expect zero or one file name */ + if (file_index < argc - 1) { + fprintf(stderr, "%s: only one input file\n", progname); + usage(); + } +#endif /* TWO_FILE_COMMANDLINE */ + + /* Open the input file. */ + if (file_index < argc) { + if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); + exit(EXIT_FAILURE); + } + } else { + /* default input file is stdin */ + input_file = read_stdin(); + } + + /* Open the output file. */ + if (outfilename != NULL) { + if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, outfilename); + exit(EXIT_FAILURE); + } + } else { + /* default output file is stdout */ + output_file = write_stdout(); + } + + if (report || max_scans != 0) { + start_progress_monitor((j_common_ptr)&cinfo, &progress); + progress.report = report; + progress.max_scans = max_scans; + } + + /* Specify data source for decompression */ + if (memsrc) { + size_t nbytes; + do { + inbuffer = (unsigned char *)realloc(inbuffer, insize + INPUT_BUF_SIZE); + if (inbuffer == NULL) { + fprintf(stderr, "%s: memory allocation failure\n", progname); + exit(EXIT_FAILURE); + } + nbytes = fread(&inbuffer[insize], 1, INPUT_BUF_SIZE, input_file); + if (nbytes < INPUT_BUF_SIZE && ferror(input_file)) { + if (file_index < argc) + fprintf(stderr, "%s: can't read from %s\n", progname, + argv[file_index]); + else + fprintf(stderr, "%s: can't read from stdin\n", progname); + } + insize += (unsigned long)nbytes; + } while (nbytes == INPUT_BUF_SIZE); + fprintf(stderr, "Compressed size: %lu bytes\n", insize); + jpeg_mem_src(&cinfo, inbuffer, insize); + } else + jpeg_stdio_src(&cinfo, input_file); + + /* Read file header, set default decompression parameters */ + (void)jpeg_read_header(&cinfo, TRUE); + + /* Adjust default decompression parameters by re-parsing the options */ + file_index = parse_switches(&cinfo, argc, argv, 0, TRUE); + + /* Initialize the output module now to let it override any crucial + * option settings (for instance, GIF wants to force color quantization). + */ + switch (requested_fmt) { +#ifdef BMP_SUPPORTED + case FMT_BMP: + dest_mgr = jinit_write_bmp(&cinfo, FALSE, TRUE); + break; + case FMT_OS2: + dest_mgr = jinit_write_bmp(&cinfo, TRUE, TRUE); + break; +#endif +#ifdef GIF_SUPPORTED + case FMT_GIF: + if (cinfo.data_precision == 16) + ERREXIT1(&cinfo, JERR_BAD_PRECISION, cinfo.data_precision); + else if (cinfo.data_precision == 12) + dest_mgr = j12init_write_gif(&cinfo, TRUE); + else + dest_mgr = jinit_write_gif(&cinfo, TRUE); + break; + case FMT_GIF0: + dest_mgr = jinit_write_gif(&cinfo, FALSE); + break; +#endif +#ifdef PPM_SUPPORTED + case FMT_PPM: + if (cinfo.data_precision == 16) +#ifdef D_LOSSLESS_SUPPORTED + dest_mgr = j16init_write_ppm(&cinfo); +#else + ERREXIT1(&cinfo, JERR_BAD_PRECISION, cinfo.data_precision); +#endif + else if (cinfo.data_precision == 12) + dest_mgr = j12init_write_ppm(&cinfo); + else + dest_mgr = jinit_write_ppm(&cinfo); + break; +#endif +#ifdef TARGA_SUPPORTED + case FMT_TARGA: + dest_mgr = jinit_write_targa(&cinfo); + break; +#endif + default: + ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT); + break; + } + dest_mgr->output_file = output_file; + + /* Start decompressor */ + (void)jpeg_start_decompress(&cinfo); + + /* Skip rows */ + if (skip) { + JDIMENSION tmp; + + /* Check for valid skip_end. We cannot check this value until after + * jpeg_start_decompress() is called. Note that we have already verified + * that skip_start <= skip_end. + */ + if (skip_end > cinfo.output_height - 1) { + fprintf(stderr, "%s: skip region exceeds image height %u\n", progname, + cinfo.output_height); + exit(EXIT_FAILURE); + } + + /* Write output file header. This is a hack to ensure that the destination + * manager creates an output image of the proper size. + */ + tmp = cinfo.output_height; + cinfo.output_height -= (skip_end - skip_start + 1); + (*dest_mgr->start_output) (&cinfo, dest_mgr); + cinfo.output_height = tmp; + + if (cinfo.data_precision == 16) + ERREXIT(&cinfo, JERR_NOTIMPL); + else if (cinfo.data_precision == 12) { + /* Process data */ + while (cinfo.output_scanline < skip_start) { + num_scanlines = jpeg12_read_scanlines(&cinfo, dest_mgr->buffer12, + dest_mgr->buffer_height); + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); + } + if ((tmp = jpeg12_skip_scanlines(&cinfo, skip_end - skip_start + 1)) != + skip_end - skip_start + 1) { + fprintf(stderr, "%s: jpeg12_skip_scanlines() returned %u rather than %u\n", + progname, tmp, skip_end - skip_start + 1); + exit(EXIT_FAILURE); + } + while (cinfo.output_scanline < cinfo.output_height) { + num_scanlines = jpeg12_read_scanlines(&cinfo, dest_mgr->buffer12, + dest_mgr->buffer_height); + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); + } + } else { + /* Process data */ + while (cinfo.output_scanline < skip_start) { + num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, + dest_mgr->buffer_height); + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); + } + if ((tmp = jpeg_skip_scanlines(&cinfo, skip_end - skip_start + 1)) != + skip_end - skip_start + 1) { + fprintf(stderr, "%s: jpeg_skip_scanlines() returned %u rather than %u\n", + progname, tmp, skip_end - skip_start + 1); + exit(EXIT_FAILURE); + } + while (cinfo.output_scanline < cinfo.output_height) { + num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, + dest_mgr->buffer_height); + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); + } + } + + /* Decompress a subregion */ + } else if (crop) { + JDIMENSION tmp; + + /* Check for valid crop dimensions. We cannot check these values until + * after jpeg_start_decompress() is called. + */ + if (crop_x + crop_width > cinfo.output_width || + crop_y + crop_height > cinfo.output_height) { + fprintf(stderr, "%s: crop dimensions exceed image dimensions %u x %u\n", + progname, cinfo.output_width, cinfo.output_height); + exit(EXIT_FAILURE); + } + + if (cinfo.data_precision == 16) + ERREXIT(&cinfo, JERR_NOTIMPL); + else if (cinfo.data_precision == 12) + jpeg12_crop_scanline(&cinfo, &crop_x, &crop_width); + else + jpeg_crop_scanline(&cinfo, &crop_x, &crop_width); + if (dest_mgr->calc_buffer_dimensions) + (*dest_mgr->calc_buffer_dimensions) (&cinfo, dest_mgr); + else + ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT); + + /* Write output file header. This is a hack to ensure that the destination + * manager creates an output image of the proper size. + */ + tmp = cinfo.output_height; + cinfo.output_height = crop_height; + (*dest_mgr->start_output) (&cinfo, dest_mgr); + cinfo.output_height = tmp; + + if (cinfo.data_precision == 16) + ERREXIT(&cinfo, JERR_NOTIMPL); + else if (cinfo.data_precision == 12) { + /* Process data */ + if ((tmp = jpeg12_skip_scanlines(&cinfo, crop_y)) != crop_y) { + fprintf(stderr, "%s: jpeg12_skip_scanlines() returned %u rather than %u\n", + progname, tmp, crop_y); + exit(EXIT_FAILURE); + } + while (cinfo.output_scanline < crop_y + crop_height) { + num_scanlines = jpeg12_read_scanlines(&cinfo, dest_mgr->buffer12, + dest_mgr->buffer_height); + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); + } + if ((tmp = + jpeg12_skip_scanlines(&cinfo, cinfo.output_height - crop_y - + crop_height)) != + cinfo.output_height - crop_y - crop_height) { + fprintf(stderr, "%s: jpeg12_skip_scanlines() returned %u rather than %u\n", + progname, tmp, cinfo.output_height - crop_y - crop_height); + exit(EXIT_FAILURE); + } + } else { + /* Process data */ + if ((tmp = jpeg_skip_scanlines(&cinfo, crop_y)) != crop_y) { + fprintf(stderr, "%s: jpeg_skip_scanlines() returned %u rather than %u\n", + progname, tmp, crop_y); + exit(EXIT_FAILURE); + } + while (cinfo.output_scanline < crop_y + crop_height) { + num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, + dest_mgr->buffer_height); + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); + } + if ((tmp = + jpeg_skip_scanlines(&cinfo, + cinfo.output_height - crop_y - crop_height)) != + cinfo.output_height - crop_y - crop_height) { + fprintf(stderr, "%s: jpeg_skip_scanlines() returned %u rather than %u\n", + progname, tmp, cinfo.output_height - crop_y - crop_height); + exit(EXIT_FAILURE); + } + } + + /* Normal full-image decompress */ + } else { + /* Write output file header */ + (*dest_mgr->start_output) (&cinfo, dest_mgr); + + if (cinfo.data_precision == 16) { +#ifdef D_LOSSLESS_SUPPORTED + /* Process data */ + while (cinfo.output_scanline < cinfo.output_height) { + num_scanlines = jpeg16_read_scanlines(&cinfo, dest_mgr->buffer16, + dest_mgr->buffer_height); + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); + } +#else + ERREXIT1(&cinfo, JERR_BAD_PRECISION, cinfo.data_precision); +#endif + } else if (cinfo.data_precision == 12) { + /* Process data */ + while (cinfo.output_scanline < cinfo.output_height) { + num_scanlines = jpeg12_read_scanlines(&cinfo, dest_mgr->buffer12, + dest_mgr->buffer_height); + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); + } + } else { + /* Process data */ + while (cinfo.output_scanline < cinfo.output_height) { + num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, + dest_mgr->buffer_height); + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); + } + } + } + + /* Hack: count final pass as done in case finish_output does an extra pass. + * The library won't have updated completed_passes. + */ + if (report || max_scans != 0) + progress.pub.completed_passes = progress.pub.total_passes; + + if (icc_filename != NULL) { + FILE *icc_file; + JOCTET *icc_profile; + unsigned int icc_len; + + if ((icc_file = fopen(icc_filename, WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, icc_filename); + exit(EXIT_FAILURE); + } + if (jpeg_read_icc_profile(&cinfo, &icc_profile, &icc_len)) { + if (fwrite(icc_profile, icc_len, 1, icc_file) < 1) { + fprintf(stderr, "%s: can't read ICC profile from %s\n", progname, + icc_filename); + free(icc_profile); + fclose(icc_file); + exit(EXIT_FAILURE); + } + free(icc_profile); + fclose(icc_file); + } else if (cinfo.err->msg_code != JWRN_BOGUS_ICC) + fprintf(stderr, "%s: no ICC profile data in JPEG file\n", progname); + } + + /* Finish decompression and release memory. + * I must do it in this order because output module has allocated memory + * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory. + */ + (*dest_mgr->finish_output) (&cinfo, dest_mgr); + (void)jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + + /* Close files, if we opened them */ + if (input_file != stdin) + fclose(input_file); + if (output_file != stdout) + fclose(output_file); + + if (report || max_scans != 0) + end_progress_monitor((j_common_ptr)&cinfo); + + if (memsrc) + free(inbuffer); + + /* All done. */ + exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); + return 0; /* suppress no-return-value warnings */ +} diff --git a/3rdparty/libjpeg-turbo/src/example.c b/3rdparty/libjpeg-turbo/src/example.c new file mode 100644 index 000000000000..78b658a0ab51 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/example.c @@ -0,0 +1,643 @@ +/* + * example.c + * + * This file was part of the Independent JPEG Group's software. + * Copyright (C) 1992-1996, Thomas G. Lane. + * libjpeg-turbo Modifications: + * Copyright (C) 2017, 2019, 2022-2023, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file illustrates how to use the IJG code as a subroutine library + * to read or write JPEG image files with 8-bit or 12-bit data precision. You + * should look at this code in conjunction with the documentation file + * libjpeg.txt. + * + * We present these routines in the same coding style used in the JPEG code + * (ANSI function definitions, etc); but you are of course free to code your + * routines in a different style if you prefer. + */ + +/* First-time users of libjpeg-turbo might be better served by looking at + * tjexample.c, which uses the more straightforward TurboJPEG API. Note that + * this example, like cjpeg and djpeg, interleaves disk I/O with JPEG + * compression/decompression, so it is not suitable for benchmarking purposes. + */ + +#ifdef _MSC_VER +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#include +#include +#include + +#ifdef _WIN32 +#define strcasecmp stricmp +#define strncasecmp strnicmp +#endif + +/* + * Include file for users of JPEG library. + * You will need to have included system headers that define at least + * the typedefs FILE and size_t before you can include jpeglib.h. + * (stdio.h is sufficient on ANSI-conforming systems.) + * You may also wish to include "jerror.h". + */ + +#include "jpeglib.h" +#include "jerror.h" + +/* + * is used for the optional error recovery mechanism shown in + * the second part of the example. + */ + +#include + + + +/******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/ + +/* This half of the example shows how to feed data into the JPEG compressor. + * We present a minimal version that does not worry about refinements such + * as error recovery (the JPEG code will just exit() if it gets an error). + */ + + +/* + * IMAGE DATA FORMATS: + * + * The standard input image format is a rectangular array of pixels, with + * each pixel having the same number of "component" values (color channels). + * Each pixel row is an array of JSAMPLEs (which typically are unsigned chars) + * or J12SAMPLEs (which typically are shorts). If you are working with color + * data, then the color values for each pixel must be adjacent in the row; for + * example, R,G,B,R,G,B,R,G,B,... for 24-bit RGB color. + * + * For this example, we'll assume that this data structure matches the way + * our application has stored the image in memory, so we can just pass a + * pointer to our image buffer. In particular, let's say that the image is + * RGB color and is described by: + */ + +#define WIDTH 640 /* Number of columns in image */ +#define HEIGHT 480 /* Number of rows in image */ + + +/* + * Sample routine for JPEG compression. We assume that the target file name, + * a compression quality factor, and a data precision are passed in. + */ + +METHODDEF(void) +write_JPEG_file(char *filename, int quality, int data_precision) +{ + /* This struct contains the JPEG compression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + * It is possible to have several such structures, representing multiple + * compression/decompression processes, in existence at once. We refer + * to any one struct (and its associated working data) as a "JPEG object". + */ + struct jpeg_compress_struct cinfo; + /* This struct represents a JPEG error handler. It is declared separately + * because applications often want to supply a specialized error handler + * (see the second half of this file for an example). But here we just + * take the easy way out and use the standard error handler, which will + * print a message on stderr and call exit() if compression fails. + * Note that this struct must live as long as the main JPEG parameter + * struct, to avoid dangling-pointer problems. + */ + struct jpeg_error_mgr jerr; + /* More stuff */ + FILE *outfile; /* target file */ + JSAMPARRAY image_buffer = NULL; + /* Points to large array of R,G,B-order data */ + JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ + J12SAMPARRAY image_buffer12 = NULL; + /* Points to large array of R,G,B-order 12-bit + data */ + J12SAMPROW row_pointer12[1]; /* pointer to J12SAMPLE row[s] */ + int row_stride; /* physical row width in image buffer */ + int row, col; + + /* Step 1: allocate and initialize JPEG compression object */ + + /* We have to set up the error handler first, in case the initialization + * step fails. (Unlikely, but it could happen if you are out of memory.) + * This routine fills in the contents of struct jerr, and returns jerr's + * address which we place into the link field in cinfo. + */ + cinfo.err = jpeg_std_error(&jerr); + /* Now we can initialize the JPEG compression object. */ + jpeg_create_compress(&cinfo); + + /* Step 2: specify data destination (eg, a file) */ + /* Note: steps 2 and 3 can be done in either order. */ + + /* Here we use the library-supplied code to send compressed data to a + * stdio stream. You can also write your own code to do something else. + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to write binary files. + */ + if ((outfile = fopen(filename, "wb")) == NULL) + ERREXIT(&cinfo, JERR_FILE_WRITE); + jpeg_stdio_dest(&cinfo, outfile); + + /* Step 3: set parameters for compression */ + + /* First we supply a description of the input image. + * Four fields of the cinfo struct must be filled in: + */ + cinfo.image_width = WIDTH; /* image width and height, in pixels */ + cinfo.image_height = HEIGHT; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + cinfo.data_precision = data_precision; /* data precision of input image */ + /* Now use the library's routine to set default compression parameters. + * (You must set at least cinfo.in_color_space before calling this, + * since the defaults depend on the source color space.) + */ + jpeg_set_defaults(&cinfo); + /* Now you can set any non-default parameters you wish to. + * Here we just illustrate the use of quality (quantization table) scaling: + */ + jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); + /* Use 4:4:4 subsampling (default is 4:2:0) */ + cinfo.comp_info[0].h_samp_factor = cinfo.comp_info[0].v_samp_factor = 1; + + /* Step 4: Start compressor */ + + /* TRUE ensures that we will write a complete interchange-JPEG file. + * Pass TRUE unless you are very sure of what you're doing. + */ + jpeg_start_compress(&cinfo, TRUE); + + /* Step 5: allocate and initialize image buffer */ + + row_stride = WIDTH * 3; /* J[12]SAMPLEs per row in image_buffer */ + /* Make a sample array that will go away when done with image. Note that, + * for the purposes of this example, we could also create a one-row-high + * sample array and initialize it for each successive scanline written in the + * scanline loop below. + */ + if (cinfo.data_precision == 12) { + image_buffer12 = (J12SAMPARRAY)(*cinfo.mem->alloc_sarray) + ((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, HEIGHT); + + /* Initialize image buffer with a repeating pattern */ + for (row = 0; row < HEIGHT; row++) { + for (col = 0; col < WIDTH; col++) { + image_buffer12[row][col * 3] = + (col * (MAXJ12SAMPLE + 1) / WIDTH) % (MAXJ12SAMPLE + 1); + image_buffer12[row][col * 3 + 1] = + (row * (MAXJ12SAMPLE + 1) / HEIGHT) % (MAXJ12SAMPLE + 1); + image_buffer12[row][col * 3 + 2] = + (row * (MAXJ12SAMPLE + 1) / HEIGHT + + col * (MAXJ12SAMPLE + 1) / WIDTH) % (MAXJ12SAMPLE + 1); + } + } + } else { + image_buffer = (*cinfo.mem->alloc_sarray) + ((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, HEIGHT); + + for (row = 0; row < HEIGHT; row++) { + for (col = 0; col < WIDTH; col++) { + image_buffer[row][col * 3] = + (col * (MAXJSAMPLE + 1) / WIDTH) % (MAXJSAMPLE + 1); + image_buffer[row][col * 3 + 1] = + (row * (MAXJSAMPLE + 1) / HEIGHT) % (MAXJSAMPLE + 1); + image_buffer[row][col * 3 + 2] = + (row * (MAXJSAMPLE + 1) / HEIGHT + col * (MAXJSAMPLE + 1) / WIDTH) % + (MAXJSAMPLE + 1); + } + } + } + + /* Step 6: while (scan lines remain to be written) */ + /* jpeg_write_scanlines(...); */ + + /* Here we use the library's state variable cinfo.next_scanline as the + * loop counter, so that we don't have to keep track ourselves. + * To keep things simple, we pass one scanline per call; you can pass + * more if you wish, though. + */ + if (cinfo.data_precision == 12) { + while (cinfo.next_scanline < cinfo.image_height) { + /* jpeg12_write_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could pass + * more than one scanline at a time if that's more convenient. + */ + row_pointer12[0] = image_buffer12[cinfo.next_scanline]; + (void)jpeg12_write_scanlines(&cinfo, row_pointer12, 1); + } + } else { + while (cinfo.next_scanline < cinfo.image_height) { + /* jpeg_write_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could pass + * more than one scanline at a time if that's more convenient. + */ + row_pointer[0] = image_buffer[cinfo.next_scanline]; + (void)jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + } + + /* Step 7: Finish compression */ + + jpeg_finish_compress(&cinfo); + /* After finish_compress, we can close the output file. */ + fclose(outfile); + + /* Step 8: release JPEG compression object */ + + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_compress(&cinfo); + + /* And we're done! */ +} + + +/* + * SOME FINE POINTS: + * + * In the above loop, we ignored the return value of jpeg_write_scanlines, + * which is the number of scanlines actually written. We could get away + * with this because we were only relying on the value of cinfo.next_scanline, + * which will be incremented correctly. If you maintain additional loop + * variables then you should be careful to increment them properly. + * Actually, for output to a stdio stream you needn't worry, because + * then jpeg_write_scanlines will write all the lines passed (or else exit + * with a fatal error). Partial writes can only occur if you use a data + * destination module that can demand suspension of the compressor. + * (If you don't know what that's for, you don't need it.) + * + * Scanlines MUST be supplied in top-to-bottom order if you want your JPEG + * files to be compatible with everyone else's. If you cannot readily read + * your data in that order, you'll need an intermediate array to hold the + * image. See rdtarga.c or rdbmp.c for examples of handling bottom-to-top + * source data using the JPEG code's internal virtual-array mechanisms. + */ + + + +/******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/ + +/* This half of the example shows how to read data from the JPEG decompressor. + * It's a bit more refined than the above, in that we show: + * (a) how to modify the JPEG library's standard error-reporting behavior; + * (b) how to allocate workspace using the library's memory manager. + * + * Just to make this example a little different from the first one, we'll + * assume that we do not intend to put the whole image into an in-memory + * buffer, but to send it line-by-line someplace else. We need a one- + * scanline-high JSAMPLE or J12SAMPLE array as a work buffer, and we will let + * the JPEG memory manager allocate it for us. This approach is actually quite + * useful because we don't need to remember to deallocate the buffer + * separately: it will go away automatically when the JPEG object is cleaned + * up. + */ + + +/* + * ERROR HANDLING: + * + * The JPEG library's standard error handler (jerror.c) is divided into + * several "methods" which you can override individually. This lets you + * adjust the behavior without duplicating a lot of code, which you might + * have to update with each future release. + * + * Our example here shows how to override the "error_exit" method so that + * control is returned to the library's caller when a fatal error occurs, + * rather than calling exit() as the standard error_exit method does. + * + * We use C's setjmp/longjmp facility to return control. This means that the + * routine which calls the JPEG library must first execute a setjmp() call to + * establish the return point. We want the replacement error_exit to do a + * longjmp(). But we need to make the setjmp buffer accessible to the + * error_exit routine. To do this, we make a private extension of the + * standard JPEG error handler object. (If we were using C++, we'd say we + * were making a subclass of the regular error handler.) + * + * Here's the extended error handler struct: + */ + +struct my_error_mgr { + struct jpeg_error_mgr pub; /* "public" fields */ + + jmp_buf setjmp_buffer; /* for return to caller */ +}; + +typedef struct my_error_mgr *my_error_ptr; + +/* + * Here's the routine that will replace the standard error_exit method: + */ + +METHODDEF(void) +my_error_exit(j_common_ptr cinfo) +{ + /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ + my_error_ptr myerr = (my_error_ptr)cinfo->err; + + /* Always display the message. */ + /* We could postpone this until after returning, if we chose. */ + (*cinfo->err->output_message) (cinfo); + + /* Return control to the setjmp point */ + longjmp(myerr->setjmp_buffer, 1); +} + + +METHODDEF(int) do_read_JPEG_file(struct jpeg_decompress_struct *cinfo, + char *infilename, char *outfilename); + +/* + * Sample routine for JPEG decompression. We assume that the source file name + * is passed in. We want to return 1 on success, 0 on error. + */ + +METHODDEF(int) +read_JPEG_file(char *infilename, char *outfilename) +{ + /* This struct contains the JPEG decompression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + */ + struct jpeg_decompress_struct cinfo; + + return do_read_JPEG_file(&cinfo, infilename, outfilename); +} + +/* + * We call the libjpeg API from within a separate function, because modifying + * the local non-volatile jpeg_decompress_struct instance below the setjmp() + * return point and then accessing the instance after setjmp() returns would + * result in undefined behavior that may potentially overwrite all or part of + * the structure. + */ + +METHODDEF(int) +do_read_JPEG_file(struct jpeg_decompress_struct *cinfo, char *infilename, + char *outfilename) +{ + /* We use our private extension JPEG error handler. + * Note that this struct must live as long as the main JPEG parameter + * struct, to avoid dangling-pointer problems. + */ + struct my_error_mgr jerr; + /* More stuff */ + FILE *infile; /* source file */ + FILE *outfile; /* output file */ + JSAMPARRAY buffer = NULL; /* Output row buffer */ + J12SAMPARRAY buffer12 = NULL; /* 12-bit output row buffer */ + int col; + int row_stride; /* physical row width in output buffer */ + int little_endian = 1; + + /* In this example we want to open the input and output files before doing + * anything else, so that the setjmp() error recovery below can assume the + * files are open. + * + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to read/write binary files. + */ + + if ((infile = fopen(infilename, "rb")) == NULL) { + fprintf(stderr, "can't open %s\n", infilename); + return 0; + } + if ((outfile = fopen(outfilename, "wb")) == NULL) { + fprintf(stderr, "can't open %s\n", outfilename); + fclose(infile); + return 0; + } + + /* Step 1: allocate and initialize JPEG decompression object */ + + /* We set up the normal JPEG error routines, then override error_exit. */ + cinfo->err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object, close the input file, and return. + */ + jpeg_destroy_decompress(cinfo); + fclose(infile); + fclose(outfile); + return 0; + } + /* Now we can initialize the JPEG decompression object. */ + jpeg_create_decompress(cinfo); + + /* Step 2: specify data source (eg, a file) */ + + jpeg_stdio_src(cinfo, infile); + + /* Step 3: read file parameters with jpeg_read_header() */ + + (void)jpeg_read_header(cinfo, TRUE); + /* We can ignore the return value from jpeg_read_header since + * (a) suspension is not possible with the stdio data source, and + * (b) we passed TRUE to reject a tables-only JPEG file as an error. + * See libjpeg.txt for more info. + */ + + /* emit header for raw PPM format */ + fprintf(outfile, "P6\n%d %d\n%d\n", WIDTH, HEIGHT, + cinfo->data_precision == 12 ? MAXJ12SAMPLE : MAXJSAMPLE); + + /* Step 4: set parameters for decompression */ + + /* In this example, we don't need to change any of the defaults set by + * jpeg_read_header(), so we do nothing here. + */ + + /* Step 5: Start decompressor */ + + (void)jpeg_start_decompress(cinfo); + /* We can ignore the return value since suspension is not possible + * with the stdio data source. + */ + + /* We may need to do some setup of our own at this point before reading + * the data. After jpeg_start_decompress() we have the correct scaled + * output image dimensions available, as well as the output colormap + * if we asked for color quantization. + * In this example, we need to make an output work buffer of the right size. + */ + /* Samples per row in output buffer */ + row_stride = cinfo->output_width * cinfo->output_components; + /* Make a one-row-high sample array that will go away when done with image */ + if (cinfo->data_precision == 12) + buffer12 = (J12SAMPARRAY)(*cinfo->mem->alloc_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, row_stride, 1); + else + buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, row_stride, 1); + + /* Step 6: while (scan lines remain to be read) */ + /* jpeg_read_scanlines(...); */ + + /* Here we use the library's state variable cinfo->output_scanline as the + * loop counter, so that we don't have to keep track ourselves. + */ + if (cinfo->data_precision == 12) { + while (cinfo->output_scanline < cinfo->output_height) { + /* jpeg12_read_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could ask for + * more than one scanline at a time if that's more convenient. + */ + (void)jpeg12_read_scanlines(cinfo, buffer12, 1); + if (*(char *)&little_endian == 1) { + /* Swap MSB and LSB in each sample */ + for (col = 0; col < row_stride; col++) + buffer12[0][col] = ((buffer12[0][col] & 0xFF) << 8) | + ((buffer12[0][col] >> 8) & 0xFF); + } + fwrite(buffer12[0], 1, row_stride * sizeof(J12SAMPLE), outfile); + } + } else { + while (cinfo->output_scanline < cinfo->output_height) { + /* jpeg_read_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could ask for + * more than one scanline at a time if that's more convenient. + */ + (void)jpeg_read_scanlines(cinfo, buffer, 1); + fwrite(buffer[0], 1, row_stride, outfile); + } + } + + /* Step 7: Finish decompression */ + + (void)jpeg_finish_decompress(cinfo); + /* We can ignore the return value since suspension is not possible + * with the stdio data source. + */ + + /* Step 8: Release JPEG decompression object */ + + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_decompress(cinfo); + + /* After finish_decompress, we can close the input and output files. + * Here we postpone it until after no more JPEG errors are possible, + * so as to simplify the setjmp error logic above. (Actually, I don't + * think that jpeg_destroy can do an error exit, but why assume anything...) + */ + fclose(infile); + fclose(outfile); + + /* At this point you may want to check to see whether any corrupt-data + * warnings occurred (test whether jerr.pub.num_warnings is nonzero). + */ + + /* And we're done! */ + return 1; +} + + +/* + * SOME FINE POINTS: + * + * In the above code, we ignored the return value of jpeg_read_scanlines, + * which is the number of scanlines actually read. We could get away with + * this because we asked for only one line at a time and we weren't using + * a suspending data source. See libjpeg.txt for more info. + * + * We cheated a bit by calling alloc_sarray() after jpeg_start_decompress(); + * we should have done it beforehand to ensure that the space would be + * counted against the JPEG max_memory setting. In some systems the above + * code would risk an out-of-memory error. However, in general we don't + * know the output image dimensions before jpeg_start_decompress(), unless we + * call jpeg_calc_output_dimensions(). See libjpeg.txt for more about this. + * + * Scanlines are returned in the same order as they appear in the JPEG file, + * which is standardly top-to-bottom. If you must emit data bottom-to-top, + * you can use one of the virtual arrays provided by the JPEG memory manager + * to invert the data. See wrbmp.c for an example. + */ + + +LOCAL(void) +usage(const char *progname) +{ + fprintf(stderr, "usage: %s compress [switches] outputfile[.jpg]\n", + progname); + fprintf(stderr, " %s decompress inputfile[.jpg] outputfile[.ppm]\n", + progname); + fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -precision N Create JPEG file with N-bit data precision\n"); + fprintf(stderr, " (N is 8 or 12; default is 8)\n"); + fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is most useful range,\n"); + fprintf(stderr, " default is 75)\n"); + + exit(EXIT_FAILURE); +} + + +typedef enum { + COMPRESS, + DECOMPRESS +} EXAMPLE_MODE; + + +int +main(int argc, char **argv) +{ + int argn, quality = 75; + int data_precision = 8; + EXAMPLE_MODE mode = -1; + char *arg, *filename = NULL; + + if (argc < 3) + usage(argv[0]); + + if (!strcasecmp(argv[1], "compress")) + mode = COMPRESS; + else if (!strcasecmp(argv[1], "decompress")) + mode = DECOMPRESS; + else + usage(argv[0]); + + for (argn = 2; argn < argc; argn++) { + arg = argv[argn]; + if (*arg != '-') { + filename = arg; + /* Not a switch, must be a file name argument */ + break; /* done parsing switches */ + } + arg++; /* advance past switch marker character */ + + if (!strncasecmp(arg, "p", 1)) { + /* Set data precision. */ + if (++argn >= argc) /* advance to next argument */ + usage(argv[0]); + if (sscanf(argv[argn], "%d", &data_precision) < 1 || + (data_precision != 8 && data_precision != 12)) + usage(argv[0]); + } else if (!strncasecmp(arg, "q", 1)) { + /* Quality rating (quantization table scaling factor). */ + if (++argn >= argc) /* advance to next argument */ + usage(argv[0]); + if (sscanf(argv[argn], "%d", &quality) < 1 || quality < 0 || + quality > 100) + usage(argv[0]); + if (quality < 1) + quality = 1; + } + } + + if (!filename) + usage(argv[0]); + + if (mode == COMPRESS) + write_JPEG_file(filename, quality, data_precision); + else if (mode == DECOMPRESS) { + if (argc - argn < 2) + usage(argv[0]); + + read_JPEG_file(argv[argn], argv[argn + 1]); + } + + return 0; +} diff --git a/3rdparty/libjpeg-turbo/src/jcapimin.c b/3rdparty/libjpeg-turbo/src/jcapimin.c index 84e7ecc9a73e..cbb3d13e1cef 100644 --- a/3rdparty/libjpeg-turbo/src/jcapimin.c +++ b/3rdparty/libjpeg-turbo/src/jcapimin.c @@ -23,6 +23,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jcmaster.h" /* @@ -90,8 +91,18 @@ jpeg_CreateCompress(j_compress_ptr cinfo, int version, size_t structsize) cinfo->input_gamma = 1.0; /* in case application forgets */ + cinfo->data_precision = BITS_IN_JSAMPLE; + /* OK, I'm ready */ cinfo->global_state = CSTATE_START; + + /* The master struct is used to store extension parameters, so we allocate it + * here. + */ + cinfo->master = (struct jpeg_comp_master *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT, + sizeof(my_comp_master)); + memset(cinfo->master, 0, sizeof(my_comp_master)); } @@ -183,8 +194,20 @@ jpeg_finish_compress(j_compress_ptr cinfo) /* We bypass the main controller and invoke coef controller directly; * all work is being done from the coefficient buffer. */ - if (!(*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE)NULL)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); + if (cinfo->data_precision == 16) { +#ifdef C_LOSSLESS_SUPPORTED + if (!(*cinfo->coef->compress_data_16) (cinfo, (J16SAMPIMAGE)NULL)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); +#endif + } else if (cinfo->data_precision == 12) { + if (!(*cinfo->coef->compress_data_12) (cinfo, (J12SAMPIMAGE)NULL)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } else { + if (!(*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE)NULL)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } } (*cinfo->master->finish_pass) (cinfo); } diff --git a/3rdparty/libjpeg-turbo/src/jcapistd.c b/3rdparty/libjpeg-turbo/src/jcapistd.c index aa2aad9f66cd..2053028f2bf0 100644 --- a/3rdparty/libjpeg-turbo/src/jcapistd.c +++ b/3rdparty/libjpeg-turbo/src/jcapistd.c @@ -1,8 +1,10 @@ /* * jcapistd.c * + * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -18,8 +20,11 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE == 8 + /* * Compression initialization. * Before calling this, all parameters and a data destination must be set up. @@ -51,13 +56,15 @@ jpeg_start_compress(j_compress_ptr cinfo, boolean write_all_tables) jinit_compress_master(cinfo); /* Set up for the first pass */ (*cinfo->master->prepare_for_pass) (cinfo); - /* Ready for application to drive first pass through jpeg_write_scanlines - * or jpeg_write_raw_data. + /* Ready for application to drive first pass through _jpeg_write_scanlines + * or _jpeg_write_raw_data. */ cinfo->next_scanline = 0; cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); } +#endif + /* * Write some scanlines of data to the JPEG compressor. @@ -67,7 +74,7 @@ jpeg_start_compress(j_compress_ptr cinfo, boolean write_all_tables) * the data destination module has requested suspension of the compressor, * or if more than image_height scanlines are passed in. * - * Note: we warn about excess calls to jpeg_write_scanlines() since + * Note: we warn about excess calls to _jpeg_write_scanlines() since * this likely signals an application programmer error. However, * excess scanlines passed in the last valid call are *silently* ignored, * so that the application need not adjust num_lines for end-of-image @@ -75,11 +82,15 @@ jpeg_start_compress(j_compress_ptr cinfo, boolean write_all_tables) */ GLOBAL(JDIMENSION) -jpeg_write_scanlines(j_compress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION num_lines) +_jpeg_write_scanlines(j_compress_ptr cinfo, _JSAMPARRAY scanlines, + JDIMENSION num_lines) { +#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) JDIMENSION row_ctr, rows_left; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + if (cinfo->global_state != CSTATE_SCANNING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->next_scanline >= cinfo->image_height) @@ -93,9 +104,9 @@ jpeg_write_scanlines(j_compress_ptr cinfo, JSAMPARRAY scanlines, } /* Give master control module another chance if this is first call to - * jpeg_write_scanlines. This lets output of the frame/scan headers be + * _jpeg_write_scanlines. This lets output of the frame/scan headers be * delayed so that application can write COM, etc, markers between - * jpeg_start_compress and jpeg_write_scanlines. + * jpeg_start_compress and _jpeg_write_scanlines. */ if (cinfo->master->call_pass_startup) (*cinfo->master->pass_startup) (cinfo); @@ -106,23 +117,35 @@ jpeg_write_scanlines(j_compress_ptr cinfo, JSAMPARRAY scanlines, num_lines = rows_left; row_ctr = 0; - (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); + (*cinfo->main->_process_data) (cinfo, scanlines, &row_ctr, num_lines); cinfo->next_scanline += row_ctr; return row_ctr; +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + return 0; +#endif } +#if BITS_IN_JSAMPLE != 16 + /* * Alternate entry point to write raw data. * Processes exactly one iMCU row per call, unless suspended. */ GLOBAL(JDIMENSION) -jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data, - JDIMENSION num_lines) +_jpeg_write_raw_data(j_compress_ptr cinfo, _JSAMPIMAGE data, + JDIMENSION num_lines) { JDIMENSION lines_per_iMCU_row; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_NOTIMPL); + if (cinfo->global_state != CSTATE_RAW_OK) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->next_scanline >= cinfo->image_height) { @@ -138,9 +161,9 @@ jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data, } /* Give master control module another chance if this is first call to - * jpeg_write_raw_data. This lets output of the frame/scan headers be + * _jpeg_write_raw_data. This lets output of the frame/scan headers be * delayed so that application can write COM, etc, markers between - * jpeg_start_compress and jpeg_write_raw_data. + * jpeg_start_compress and _jpeg_write_raw_data. */ if (cinfo->master->call_pass_startup) (*cinfo->master->pass_startup) (cinfo); @@ -151,7 +174,7 @@ jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data, ERREXIT(cinfo, JERR_BUFFER_SIZE); /* Directly compress the row. */ - if (!(*cinfo->coef->compress_data) (cinfo, data)) { + if (!(*cinfo->coef->_compress_data) (cinfo, data)) { /* If compressor did not consume the whole row, suspend processing. */ return 0; } @@ -160,3 +183,5 @@ jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data, cinfo->next_scanline += lines_per_iMCU_row; return lines_per_iMCU_row; } + +#endif /* BITS_IN_JSAMPLE != 16 */ diff --git a/3rdparty/libjpeg-turbo/src/jccoefct.c b/3rdparty/libjpeg-turbo/src/jccoefct.c index 068232a527d1..2a5dde2d07e8 100644 --- a/3rdparty/libjpeg-turbo/src/jccoefct.c +++ b/3rdparty/libjpeg-turbo/src/jccoefct.c @@ -3,19 +3,20 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1997, Thomas G. Lane. - * It was modified by The libjpeg-turbo Project to include only code and - * information relevant to libjpeg-turbo. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * * This file contains the coefficient buffer controller for compression. - * This controller is the top level of the JPEG compressor proper. + * This controller is the top level of the lossy JPEG compressor proper. * The coefficient buffer lies between forward-DCT and entropy encoding steps. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" /* We use a full-image coefficient buffer when doing Huffman optimization, @@ -58,11 +59,12 @@ typedef my_coef_controller *my_coef_ptr; /* Forward declarations */ -METHODDEF(boolean) compress_data(j_compress_ptr cinfo, JSAMPIMAGE input_buf); +METHODDEF(boolean) compress_data(j_compress_ptr cinfo, _JSAMPIMAGE input_buf); #ifdef FULL_COEF_BUFFER_SUPPORTED METHODDEF(boolean) compress_first_pass(j_compress_ptr cinfo, - JSAMPIMAGE input_buf); -METHODDEF(boolean) compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf); + _JSAMPIMAGE input_buf); +METHODDEF(boolean) compress_output(j_compress_ptr cinfo, + _JSAMPIMAGE input_buf); #endif @@ -106,18 +108,18 @@ start_pass_coef(j_compress_ptr cinfo, J_BUF_MODE pass_mode) case JBUF_PASS_THRU: if (coef->whole_image[0] != NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_data; + coef->pub._compress_data = compress_data; break; #ifdef FULL_COEF_BUFFER_SUPPORTED case JBUF_SAVE_AND_PASS: if (coef->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_first_pass; + coef->pub._compress_data = compress_first_pass; break; case JBUF_CRANK_DEST: if (coef->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_output; + coef->pub._compress_data = compress_output; break; #endif default: @@ -138,7 +140,7 @@ start_pass_coef(j_compress_ptr cinfo, J_BUF_MODE pass_mode) */ METHODDEF(boolean) -compress_data(j_compress_ptr cinfo, JSAMPIMAGE input_buf) +compress_data(j_compress_ptr cinfo, _JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr)cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ @@ -172,10 +174,10 @@ compress_data(j_compress_ptr cinfo, JSAMPIMAGE input_buf) for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->iMCU_row_num < last_iMCU_row || yoffset + yindex < compptr->last_row_height) { - (*cinfo->fdct->forward_DCT) (cinfo, compptr, - input_buf[compptr->component_index], - coef->MCU_buffer[blkn], - ypos, xpos, (JDIMENSION)blockcnt); + (*cinfo->fdct->_forward_DCT) (cinfo, compptr, + input_buf[compptr->component_index], + coef->MCU_buffer[blkn], + ypos, xpos, (JDIMENSION)blockcnt); if (blockcnt < compptr->MCU_width) { /* Create some dummy blocks at the right edge of the image. */ jzero_far((void *)coef->MCU_buffer[blkn + blockcnt], @@ -242,7 +244,7 @@ compress_data(j_compress_ptr cinfo, JSAMPIMAGE input_buf) */ METHODDEF(boolean) -compress_first_pass(j_compress_ptr cinfo, JSAMPIMAGE input_buf) +compress_first_pass(j_compress_ptr cinfo, _JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr)cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; @@ -279,10 +281,10 @@ compress_first_pass(j_compress_ptr cinfo, JSAMPIMAGE input_buf) */ for (block_row = 0; block_row < block_rows; block_row++) { thisblockrow = buffer[block_row]; - (*cinfo->fdct->forward_DCT) (cinfo, compptr, - input_buf[ci], thisblockrow, - (JDIMENSION)(block_row * DCTSIZE), - (JDIMENSION)0, blocks_across); + (*cinfo->fdct->_forward_DCT) (cinfo, compptr, + input_buf[ci], thisblockrow, + (JDIMENSION)(block_row * DCTSIZE), + (JDIMENSION)0, blocks_across); if (ndummy > 0) { /* Create dummy blocks at the right edge of the image. */ thisblockrow += blocks_across; /* => first dummy block */ @@ -338,7 +340,7 @@ compress_first_pass(j_compress_ptr cinfo, JSAMPIMAGE input_buf) */ METHODDEF(boolean) -compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf) +compress_output(j_compress_ptr cinfo, _JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr)cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ @@ -402,10 +404,13 @@ compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf) */ GLOBAL(void) -jinit_c_coef_controller(j_compress_ptr cinfo, boolean need_full_buffer) +_jinit_c_coef_controller(j_compress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_coef_controller)); diff --git a/3rdparty/libjpeg-turbo/src/jccolext.c b/3rdparty/libjpeg-turbo/src/jccolext.c index 303b322ce674..8eba36c4dffe 100644 --- a/3rdparty/libjpeg-turbo/src/jccolext.c +++ b/3rdparty/libjpeg-turbo/src/jccolext.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2009-2012, 2015, D. R. Commander. + * Copyright (C) 2009-2012, 2015, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -29,15 +29,16 @@ INLINE LOCAL(void) -rgb_ycc_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, +rgb_ycc_convert_internal(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int r, g, b; register JLONG *ctab = cconvert->rgb_ycc_tab; - register JSAMPROW inptr; - register JSAMPROW outptr0, outptr1, outptr2; + register _JSAMPROW inptr; + register _JSAMPROW outptr0, outptr1, outptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; @@ -48,26 +49,29 @@ rgb_ycc_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf, outptr2 = output_buf[2][output_row]; output_row++; for (col = 0; col < num_cols; col++) { - r = inptr[RGB_RED]; - g = inptr[RGB_GREEN]; - b = inptr[RGB_BLUE]; + r = RANGE_LIMIT(inptr[RGB_RED]); + g = RANGE_LIMIT(inptr[RGB_GREEN]); + b = RANGE_LIMIT(inptr[RGB_BLUE]); inptr += RGB_PIXELSIZE; - /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + /* If the inputs are 0.._MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't * need the general RIGHT_SHIFT macro. */ /* Y */ - outptr0[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + - ctab[b + B_Y_OFF]) >> SCALEBITS); + outptr0[col] = (_JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + + ctab[b + B_Y_OFF]) >> SCALEBITS); /* Cb */ - outptr1[col] = (JSAMPLE)((ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] + - ctab[b + B_CB_OFF]) >> SCALEBITS); + outptr1[col] = (_JSAMPLE)((ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] + + ctab[b + B_CB_OFF]) >> SCALEBITS); /* Cr */ - outptr2[col] = (JSAMPLE)((ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] + - ctab[b + B_CR_OFF]) >> SCALEBITS); + outptr2[col] = (_JSAMPLE)((ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] + + ctab[b + B_CR_OFF]) >> SCALEBITS); } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -83,15 +87,16 @@ rgb_ycc_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf, INLINE LOCAL(void) -rgb_gray_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, +rgb_gray_convert_internal(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int r, g, b; register JLONG *ctab = cconvert->rgb_ycc_tab; - register JSAMPROW inptr; - register JSAMPROW outptr; + register _JSAMPROW inptr; + register _JSAMPROW outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; @@ -100,15 +105,18 @@ rgb_gray_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf, outptr = output_buf[0][output_row]; output_row++; for (col = 0; col < num_cols; col++) { - r = inptr[RGB_RED]; - g = inptr[RGB_GREEN]; - b = inptr[RGB_BLUE]; + r = RANGE_LIMIT(inptr[RGB_RED]); + g = RANGE_LIMIT(inptr[RGB_GREEN]); + b = RANGE_LIMIT(inptr[RGB_BLUE]); inptr += RGB_PIXELSIZE; /* Y */ - outptr[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + - ctab[b + B_Y_OFF]) >> SCALEBITS); + outptr[col] = (_JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + + ctab[b + B_Y_OFF]) >> SCALEBITS); } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -119,12 +127,12 @@ rgb_gray_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf, INLINE LOCAL(void) -rgb_rgb_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, +rgb_rgb_convert_internal(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { - register JSAMPROW inptr; - register JSAMPROW outptr0, outptr1, outptr2; + register _JSAMPROW inptr; + register _JSAMPROW outptr0, outptr1, outptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; diff --git a/3rdparty/libjpeg-turbo/src/jccolor.c b/3rdparty/libjpeg-turbo/src/jccolor.c index bdc563c723ca..cd3a6a7a567a 100644 --- a/3rdparty/libjpeg-turbo/src/jccolor.c +++ b/3rdparty/libjpeg-turbo/src/jccolor.c @@ -5,7 +5,7 @@ * Copyright (C) 1991-1996, Thomas G. Lane. * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009-2012, 2015, D. R. Commander. + * Copyright (C) 2009-2012, 2015, 2022, D. R. Commander. * Copyright (C) 2014, MIPS Technologies, Inc., California. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -17,16 +17,20 @@ #include "jinclude.h" #include "jpeglib.h" #include "jsimd.h" -#include "jconfigint.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) + /* Private subobject */ typedef struct { struct jpeg_color_converter pub; /* public fields */ +#if BITS_IN_JSAMPLE != 16 /* Private state for RGB->YCC conversion */ JLONG *rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ +#endif } my_color_converter; typedef my_color_converter *my_cconvert_ptr; @@ -36,14 +40,14 @@ typedef my_color_converter *my_cconvert_ptr; /* * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * normalized to the range 0.._MAXJSAMPLE rather than -0.5 .. 0.5. * The conversion equations to be implemented are therefore * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B - * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE - * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE + * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + _CENTERJSAMPLE + * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + _CENTERJSAMPLE * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) - * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, - * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and + * Note: older versions of the IJG code used a zero offset of _MAXJSAMPLE/2, + * rather than _CENTERJSAMPLE, for Cb and Cr. This gave equal positive and * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) * were not represented exactly. Now we sacrifice exact representation of * maximum red and maximum blue in order to get exact grayscales. @@ -54,16 +58,16 @@ typedef my_color_converter *my_cconvert_ptr; * * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times R,G,B for all possible values. - * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * For 8-bit samples this is very reasonable (only 256 entries per table); * for 12-bit samples it is still acceptable. It's not very reasonable for * 16-bit samples, but if you want lossless storage you shouldn't be changing * colorspace anyway. - * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included + * The _CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included * in the tables to save adding them separately in the inner loop. */ #define SCALEBITS 16 /* speediest right-shift on some machines */ -#define CBCR_OFFSET ((JLONG)CENTERJSAMPLE << SCALEBITS) +#define CBCR_OFFSET ((JLONG)_CENTERJSAMPLE << SCALEBITS) #define ONE_HALF ((JLONG)1 << (SCALEBITS - 1)) #define FIX(x) ((JLONG)((x) * (1L << SCALEBITS) + 0.5)) @@ -74,15 +78,27 @@ typedef my_color_converter *my_cconvert_ptr; */ #define R_Y_OFF 0 /* offset to R => Y section */ -#define G_Y_OFF (1 * (MAXJSAMPLE + 1)) /* offset to G => Y section */ -#define B_Y_OFF (2 * (MAXJSAMPLE + 1)) /* etc. */ -#define R_CB_OFF (3 * (MAXJSAMPLE + 1)) -#define G_CB_OFF (4 * (MAXJSAMPLE + 1)) -#define B_CB_OFF (5 * (MAXJSAMPLE + 1)) +#define G_Y_OFF (1 * (_MAXJSAMPLE + 1)) /* offset to G => Y section */ +#define B_Y_OFF (2 * (_MAXJSAMPLE + 1)) /* etc. */ +#define R_CB_OFF (3 * (_MAXJSAMPLE + 1)) +#define G_CB_OFF (4 * (_MAXJSAMPLE + 1)) +#define B_CB_OFF (5 * (_MAXJSAMPLE + 1)) #define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ -#define G_CR_OFF (6 * (MAXJSAMPLE + 1)) -#define B_CR_OFF (7 * (MAXJSAMPLE + 1)) -#define TABLE_SIZE (8 * (MAXJSAMPLE + 1)) +#define G_CR_OFF (6 * (_MAXJSAMPLE + 1)) +#define B_CR_OFF (7 * (_MAXJSAMPLE + 1)) +#define TABLE_SIZE (8 * (_MAXJSAMPLE + 1)) + +/* 12-bit samples use a 16-bit data type, so it is possible to pass + * out-of-range sample values (< 0 or > 4095) to jpeg_write_scanlines(). + * Thus, we mask the incoming 12-bit samples to guard against overrunning + * or underrunning the conversion tables. + */ + +#if BITS_IN_JSAMPLE == 12 +#define RANGE_LIMIT(value) ((value) & 0xFFF) +#else +#define RANGE_LIMIT(value) (value) +#endif /* Include inline routines for colorspace extensions */ @@ -197,6 +213,7 @@ typedef my_color_converter *my_cconvert_ptr; METHODDEF(void) rgb_ycc_start(j_compress_ptr cinfo) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; JLONG *rgb_ycc_tab; JLONG i; @@ -206,15 +223,15 @@ rgb_ycc_start(j_compress_ptr cinfo) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, (TABLE_SIZE * sizeof(JLONG))); - for (i = 0; i <= MAXJSAMPLE; i++) { + for (i = 0; i <= _MAXJSAMPLE; i++) { rgb_ycc_tab[i + R_Y_OFF] = FIX(0.29900) * i; rgb_ycc_tab[i + G_Y_OFF] = FIX(0.58700) * i; rgb_ycc_tab[i + B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; rgb_ycc_tab[i + R_CB_OFF] = (-FIX(0.16874)) * i; rgb_ycc_tab[i + G_CB_OFF] = (-FIX(0.33126)) * i; /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. - * This ensures that the maximum output will round to MAXJSAMPLE - * not MAXJSAMPLE+1, and thus that we don't have to range-limit. + * This ensures that the maximum output will round to _MAXJSAMPLE + * not _MAXJSAMPLE+1, and thus that we don't have to range-limit. */ rgb_ycc_tab[i + B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF - 1; /* B=>Cb and R=>Cr tables are the same @@ -223,6 +240,9 @@ rgb_ycc_start(j_compress_ptr cinfo) rgb_ycc_tab[i + G_CR_OFF] = (-FIX(0.41869)) * i; rgb_ycc_tab[i + B_CR_OFF] = (-FIX(0.08131)) * i; } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -231,8 +251,8 @@ rgb_ycc_start(j_compress_ptr cinfo) */ METHODDEF(void) -rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) +rgb_ycc_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { switch (cinfo->in_color_space) { case JCS_EXT_RGB: @@ -279,8 +299,8 @@ rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, */ METHODDEF(void) -rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) +rgb_gray_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { switch (cinfo->in_color_space) { case JCS_EXT_RGB: @@ -324,8 +344,8 @@ rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, */ METHODDEF(void) -rgb_rgb_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) +rgb_rgb_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { switch (cinfo->in_color_space) { case JCS_EXT_RGB: @@ -373,14 +393,15 @@ rgb_rgb_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, */ METHODDEF(void) -cmyk_ycck_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) +cmyk_ycck_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int r, g, b; register JLONG *ctab = cconvert->rgb_ycc_tab; - register JSAMPROW inptr; - register JSAMPROW outptr0, outptr1, outptr2, outptr3; + register _JSAMPROW inptr; + register _JSAMPROW outptr0, outptr1, outptr2, outptr3; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; @@ -392,28 +413,31 @@ cmyk_ycck_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, outptr3 = output_buf[3][output_row]; output_row++; for (col = 0; col < num_cols; col++) { - r = MAXJSAMPLE - inptr[0]; - g = MAXJSAMPLE - inptr[1]; - b = MAXJSAMPLE - inptr[2]; + r = _MAXJSAMPLE - RANGE_LIMIT(inptr[0]); + g = _MAXJSAMPLE - RANGE_LIMIT(inptr[1]); + b = _MAXJSAMPLE - RANGE_LIMIT(inptr[2]); /* K passes through as-is */ outptr3[col] = inptr[3]; inptr += 4; - /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + /* If the inputs are 0.._MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't * need the general RIGHT_SHIFT macro. */ /* Y */ - outptr0[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + - ctab[b + B_Y_OFF]) >> SCALEBITS); + outptr0[col] = (_JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + + ctab[b + B_Y_OFF]) >> SCALEBITS); /* Cb */ - outptr1[col] = (JSAMPLE)((ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] + - ctab[b + B_CB_OFF]) >> SCALEBITS); + outptr1[col] = (_JSAMPLE)((ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] + + ctab[b + B_CB_OFF]) >> SCALEBITS); /* Cr */ - outptr2[col] = (JSAMPLE)((ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] + - ctab[b + B_CR_OFF]) >> SCALEBITS); + outptr2[col] = (_JSAMPLE)((ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] + + ctab[b + B_CR_OFF]) >> SCALEBITS); } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -424,11 +448,11 @@ cmyk_ycck_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, */ METHODDEF(void) -grayscale_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) +grayscale_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { - register JSAMPROW inptr; - register JSAMPROW outptr; + register _JSAMPROW inptr; + register _JSAMPROW outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; int instride = cinfo->input_components; @@ -452,11 +476,11 @@ grayscale_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, */ METHODDEF(void) -null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) +null_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { - register JSAMPROW inptr; - register JSAMPROW outptr, outptr0, outptr1, outptr2, outptr3; + register _JSAMPROW inptr; + register _JSAMPROW outptr, outptr0, outptr1, outptr2, outptr3; register JDIMENSION col; register int ci; int nc = cinfo->num_components; @@ -524,10 +548,13 @@ null_method(j_compress_ptr cinfo) */ GLOBAL(void) -jinit_color_converter(j_compress_ptr cinfo) +_jinit_color_converter(j_compress_ptr cinfo) { my_cconvert_ptr cconvert; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_color_converter)); @@ -574,123 +601,116 @@ jinit_color_converter(j_compress_ptr cinfo) break; } - /* Check num_components, set conversion method based on requested space */ + /* Check num_components, set conversion method based on requested space. + * NOTE: We do not allow any lossy color conversion algorithms in lossless + * mode. + */ switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: + if (cinfo->master->lossless && + cinfo->in_color_space != cinfo->jpeg_color_space) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); if (cinfo->num_components != 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_GRAYSCALE) - cconvert->pub.color_convert = grayscale_convert; - else if (cinfo->in_color_space == JCS_RGB || - cinfo->in_color_space == JCS_EXT_RGB || - cinfo->in_color_space == JCS_EXT_RGBX || - cinfo->in_color_space == JCS_EXT_BGR || - cinfo->in_color_space == JCS_EXT_BGRX || - cinfo->in_color_space == JCS_EXT_XBGR || - cinfo->in_color_space == JCS_EXT_XRGB || - cinfo->in_color_space == JCS_EXT_RGBA || - cinfo->in_color_space == JCS_EXT_BGRA || - cinfo->in_color_space == JCS_EXT_ABGR || - cinfo->in_color_space == JCS_EXT_ARGB) { + cconvert->pub._color_convert = grayscale_convert; + else if (IsExtRGB(cinfo->in_color_space)) { +#ifdef WITH_SIMD if (jsimd_can_rgb_gray()) - cconvert->pub.color_convert = jsimd_rgb_gray_convert; - else { + cconvert->pub._color_convert = jsimd_rgb_gray_convert; + else +#endif + { cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = rgb_gray_convert; + cconvert->pub._color_convert = rgb_gray_convert; } } else if (cinfo->in_color_space == JCS_YCbCr) - cconvert->pub.color_convert = grayscale_convert; + cconvert->pub._color_convert = grayscale_convert; else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_RGB: + if (cinfo->master->lossless && !IsExtRGB(cinfo->in_color_space)) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (rgb_red[cinfo->in_color_space] == 0 && rgb_green[cinfo->in_color_space] == 1 && rgb_blue[cinfo->in_color_space] == 2 && rgb_pixelsize[cinfo->in_color_space] == 3) { -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_c_can_null_convert()) - cconvert->pub.color_convert = jsimd_c_null_convert; + cconvert->pub._color_convert = jsimd_c_null_convert; else #endif - cconvert->pub.color_convert = null_convert; - } else if (cinfo->in_color_space == JCS_RGB || - cinfo->in_color_space == JCS_EXT_RGB || - cinfo->in_color_space == JCS_EXT_RGBX || - cinfo->in_color_space == JCS_EXT_BGR || - cinfo->in_color_space == JCS_EXT_BGRX || - cinfo->in_color_space == JCS_EXT_XBGR || - cinfo->in_color_space == JCS_EXT_XRGB || - cinfo->in_color_space == JCS_EXT_RGBA || - cinfo->in_color_space == JCS_EXT_BGRA || - cinfo->in_color_space == JCS_EXT_ABGR || - cinfo->in_color_space == JCS_EXT_ARGB) - cconvert->pub.color_convert = rgb_rgb_convert; + cconvert->pub._color_convert = null_convert; + } else if (IsExtRGB(cinfo->in_color_space)) + cconvert->pub._color_convert = rgb_rgb_convert; else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_YCbCr: + if (cinfo->master->lossless && + cinfo->in_color_space != cinfo->jpeg_color_space) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_RGB || - cinfo->in_color_space == JCS_EXT_RGB || - cinfo->in_color_space == JCS_EXT_RGBX || - cinfo->in_color_space == JCS_EXT_BGR || - cinfo->in_color_space == JCS_EXT_BGRX || - cinfo->in_color_space == JCS_EXT_XBGR || - cinfo->in_color_space == JCS_EXT_XRGB || - cinfo->in_color_space == JCS_EXT_RGBA || - cinfo->in_color_space == JCS_EXT_BGRA || - cinfo->in_color_space == JCS_EXT_ABGR || - cinfo->in_color_space == JCS_EXT_ARGB) { + if (IsExtRGB(cinfo->in_color_space)) { +#ifdef WITH_SIMD if (jsimd_can_rgb_ycc()) - cconvert->pub.color_convert = jsimd_rgb_ycc_convert; - else { + cconvert->pub._color_convert = jsimd_rgb_ycc_convert; + else +#endif + { cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = rgb_ycc_convert; + cconvert->pub._color_convert = rgb_ycc_convert; } } else if (cinfo->in_color_space == JCS_YCbCr) { -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_c_can_null_convert()) - cconvert->pub.color_convert = jsimd_c_null_convert; + cconvert->pub._color_convert = jsimd_c_null_convert; else #endif - cconvert->pub.color_convert = null_convert; + cconvert->pub._color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_CMYK: + if (cinfo->master->lossless && + cinfo->in_color_space != cinfo->jpeg_color_space) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_CMYK) { -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_c_can_null_convert()) - cconvert->pub.color_convert = jsimd_c_null_convert; + cconvert->pub._color_convert = jsimd_c_null_convert; else #endif - cconvert->pub.color_convert = null_convert; + cconvert->pub._color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_YCCK: + if (cinfo->master->lossless && + cinfo->in_color_space != cinfo->jpeg_color_space) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_CMYK) { cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = cmyk_ycck_convert; + cconvert->pub._color_convert = cmyk_ycck_convert; } else if (cinfo->in_color_space == JCS_YCCK) { -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_c_can_null_convert()) - cconvert->pub.color_convert = jsimd_c_null_convert; + cconvert->pub._color_convert = jsimd_c_null_convert; else #endif - cconvert->pub.color_convert = null_convert; + cconvert->pub._color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; @@ -699,12 +719,14 @@ jinit_color_converter(j_compress_ptr cinfo) if (cinfo->jpeg_color_space != cinfo->in_color_space || cinfo->num_components != cinfo->input_components) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_c_can_null_convert()) - cconvert->pub.color_convert = jsimd_c_null_convert; + cconvert->pub._color_convert = jsimd_c_null_convert; else #endif - cconvert->pub.color_convert = null_convert; + cconvert->pub._color_convert = null_convert; break; } } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) */ diff --git a/3rdparty/libjpeg-turbo/src/jcdctmgr.c b/3rdparty/libjpeg-turbo/src/jcdctmgr.c index 7dae17a6e149..7191ee73169c 100644 --- a/3rdparty/libjpeg-turbo/src/jcdctmgr.c +++ b/3rdparty/libjpeg-turbo/src/jcdctmgr.c @@ -6,7 +6,7 @@ * libjpeg-turbo Modifications: * Copyright (C) 1999-2006, MIYASAKA Masaru. * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2011, 2014-2015, D. R. Commander. + * Copyright (C) 2011, 2014-2015, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -28,10 +28,10 @@ typedef void (*forward_DCT_method_ptr) (DCTELEM *data); typedef void (*float_DCT_method_ptr) (FAST_FLOAT *data); -typedef void (*convsamp_method_ptr) (JSAMPARRAY sample_data, +typedef void (*convsamp_method_ptr) (_JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace); -typedef void (*float_convsamp_method_ptr) (JSAMPARRAY sample_data, +typedef void (*float_convsamp_method_ptr) (_JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT *workspace); @@ -265,9 +265,13 @@ start_pass_fdctmgr(j_compress_ptr cinfo) dtbl = fdct->divisors[qtblno]; for (i = 0; i < DCTSIZE2; i++) { #if BITS_IN_JSAMPLE == 8 +#ifdef WITH_SIMD if (!compute_reciprocal(qtbl->quantval[i] << 3, &dtbl[i]) && fdct->quantize == jsimd_quantize) fdct->quantize = quantize; +#else + compute_reciprocal(qtbl->quantval[i] << 3, &dtbl[i]); +#endif #else dtbl[i] = ((DCTELEM)qtbl->quantval[i]) << 3; #endif @@ -305,12 +309,19 @@ start_pass_fdctmgr(j_compress_ptr cinfo) dtbl = fdct->divisors[qtblno]; for (i = 0; i < DCTSIZE2; i++) { #if BITS_IN_JSAMPLE == 8 +#ifdef WITH_SIMD if (!compute_reciprocal( DESCALE(MULTIPLY16V16((JLONG)qtbl->quantval[i], (JLONG)aanscales[i]), CONST_BITS - 3), &dtbl[i]) && fdct->quantize == jsimd_quantize) fdct->quantize = quantize; +#else + compute_reciprocal( + DESCALE(MULTIPLY16V16((JLONG)qtbl->quantval[i], + (JLONG)aanscales[i]), + CONST_BITS-3), &dtbl[i]); +#endif #else dtbl[i] = (DCTELEM) DESCALE(MULTIPLY16V16((JLONG)qtbl->quantval[i], @@ -370,10 +381,10 @@ start_pass_fdctmgr(j_compress_ptr cinfo) */ METHODDEF(void) -convsamp(JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace) +convsamp(_JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace) { register DCTELEM *workspaceptr; - register JSAMPROW elemptr; + register _JSAMPROW elemptr; register int elemr; workspaceptr = workspace; @@ -381,19 +392,19 @@ convsamp(JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace) elemptr = sample_data[elemr] + start_col; #if DCTSIZE == 8 /* unroll the inner loop */ - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; #else { register int elemc; for (elemc = DCTSIZE; elemc > 0; elemc--) - *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = (*elemptr++) - _CENTERJSAMPLE; } #endif } @@ -488,7 +499,7 @@ quantize(JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace) METHODDEF(void) forward_DCT(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + _JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks) /* This version is used for integer DCT implementations. */ { @@ -522,30 +533,30 @@ forward_DCT(j_compress_ptr cinfo, jpeg_component_info *compptr, #ifdef DCT_FLOAT_SUPPORTED METHODDEF(void) -convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col, +convsamp_float(_JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT *workspace) { register FAST_FLOAT *workspaceptr; - register JSAMPROW elemptr; + register _JSAMPROW elemptr; register int elemr; workspaceptr = workspace; for (elemr = 0; elemr < DCTSIZE; elemr++) { elemptr = sample_data[elemr] + start_col; #if DCTSIZE == 8 /* unroll the inner loop */ - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); #else { register int elemc; for (elemc = DCTSIZE; elemc > 0; elemc--) - *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - _CENTERJSAMPLE); } #endif } @@ -577,7 +588,7 @@ quantize_float(JCOEFPTR coef_block, FAST_FLOAT *divisors, METHODDEF(void) forward_DCT_float(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + _JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks) /* This version is used for floating-point DCT implementations. */ @@ -617,11 +628,14 @@ forward_DCT_float(j_compress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jinit_forward_dct(j_compress_ptr cinfo) +_jinit_forward_dct(j_compress_ptr cinfo) { my_fdct_ptr fdct; int i; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + fdct = (my_fdct_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_fdct_controller)); @@ -632,28 +646,34 @@ jinit_forward_dct(j_compress_ptr cinfo) switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: - fdct->pub.forward_DCT = forward_DCT; + fdct->pub._forward_DCT = forward_DCT; +#ifdef WITH_SIMD if (jsimd_can_fdct_islow()) fdct->dct = jsimd_fdct_islow; else - fdct->dct = jpeg_fdct_islow; +#endif + fdct->dct = _jpeg_fdct_islow; break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: - fdct->pub.forward_DCT = forward_DCT; + fdct->pub._forward_DCT = forward_DCT; +#ifdef WITH_SIMD if (jsimd_can_fdct_ifast()) fdct->dct = jsimd_fdct_ifast; else - fdct->dct = jpeg_fdct_ifast; +#endif + fdct->dct = _jpeg_fdct_ifast; break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: - fdct->pub.forward_DCT = forward_DCT_float; + fdct->pub._forward_DCT = forward_DCT_float; +#ifdef WITH_SIMD if (jsimd_can_fdct_float()) fdct->float_dct = jsimd_fdct_float; else +#endif fdct->float_dct = jpeg_fdct_float; break; #endif @@ -671,25 +691,33 @@ jinit_forward_dct(j_compress_ptr cinfo) case JDCT_IFAST: #endif #if defined(DCT_ISLOW_SUPPORTED) || defined(DCT_IFAST_SUPPORTED) +#ifdef WITH_SIMD if (jsimd_can_convsamp()) fdct->convsamp = jsimd_convsamp; else +#endif fdct->convsamp = convsamp; +#ifdef WITH_SIMD if (jsimd_can_quantize()) fdct->quantize = jsimd_quantize; else +#endif fdct->quantize = quantize; break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: +#ifdef WITH_SIMD if (jsimd_can_convsamp_float()) fdct->float_convsamp = jsimd_convsamp_float; else +#endif fdct->float_convsamp = convsamp_float; +#ifdef WITH_SIMD if (jsimd_can_quantize_float()) fdct->float_quantize = jsimd_quantize_float; else +#endif fdct->float_quantize = quantize_float; break; #endif diff --git a/3rdparty/libjpeg-turbo/src/jcdiffct.c b/3rdparty/libjpeg-turbo/src/jcdiffct.c new file mode 100644 index 000000000000..0bae0689191e --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/jcdiffct.c @@ -0,0 +1,411 @@ +/* + * jcdiffct.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1994-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains the difference buffer controller for compression. + * This controller is the top level of the lossless JPEG compressor proper. + * The difference buffer lies between the prediction/differencing and entropy + * encoding steps. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jlossls.h" /* Private declarations for lossless codec */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* We use a full-image sample buffer when doing Huffman optimization, + * and also for writing multiple-scan JPEG files. In all cases, the + * full-image buffer is filled during the first pass, and the scaling, + * prediction and differencing steps are run during subsequent passes. + */ +#ifdef ENTROPY_OPT_SUPPORTED +#define FULL_SAMP_BUFFER_SUPPORTED +#else +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define FULL_SAMP_BUFFER_SUPPORTED +#endif +#endif + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + _JSAMPROW cur_row[MAX_COMPONENTS]; /* row of point-transformed samples */ + _JSAMPROW prev_row[MAX_COMPONENTS]; /* previous row of Pt'd samples */ + JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */ + + /* In multi-pass modes, we need a virtual sample array for each component. */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +} my_diff_controller; + +typedef my_diff_controller *my_diff_ptr; + + +/* Forward declarations */ +METHODDEF(boolean) compress_data(j_compress_ptr cinfo, _JSAMPIMAGE input_buf); +#ifdef FULL_SAMP_BUFFER_SUPPORTED +METHODDEF(boolean) compress_first_pass(j_compress_ptr cinfo, + _JSAMPIMAGE input_buf); +METHODDEF(boolean) compress_output(j_compress_ptr cinfo, + _JSAMPIMAGE input_buf); +#endif + + +LOCAL(void) +start_iMCU_row(j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + diff->MCU_rows_per_iMCU_row = 1; + } else { + if (diff->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + diff->mcu_ctr = 0; + diff->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_diff(j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + + /* Because it is hitching a ride on the jpeg_forward_dct struct, + * start_pass_lossless() will be called at the start of the initial pass. + * This ensures that it will be called at the start of the Huffman + * optimization and output passes as well. + */ + if (pass_mode == JBUF_CRANK_DEST) + (*cinfo->fdct->start_pass) (cinfo); + + diff->iMCU_row_num = 0; + start_iMCU_row(cinfo); + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (diff->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + diff->pub._compress_data = compress_data; + break; +#ifdef FULL_SAMP_BUFFER_SUPPORTED + case JBUF_SAVE_AND_PASS: + if (diff->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + diff->pub._compress_data = compress_first_pass; + break; + case JBUF_CRANK_DEST: + if (diff->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + diff->pub._compress_data = compress_output; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +#define SWAP_ROWS(rowa, rowb) { \ + _JSAMPROW temp = rowa; \ + rowa = rowb; rowb = temp; \ +} + +/* + * Process some data in the single-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the image. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(boolean) +compress_data(j_compress_ptr cinfo, _JSAMPIMAGE input_buf) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION MCU_count; /* number of MCUs encoded */ + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int ci, compi, yoffset, samp_row, samp_rows, samps_across; + jpeg_component_info *compptr; + + /* Loop to write as much as one whole iMCU row */ + for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row; + yoffset++) { + + MCU_col_num = diff->mcu_ctr; + + /* Scale and predict each scanline of the MCU row separately. + * + * Note: We only do this if we are at the start of an MCU row, ie, + * we don't want to reprocess a row suspended by the output. + */ + if (MCU_col_num == 0) { + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + compi = compptr->component_index; + if (diff->iMCU_row_num < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + samp_rows = + (int)(compptr->height_in_blocks % compptr->v_samp_factor); + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + else { + /* Fill dummy difference rows at the bottom edge with zeros, which + * will encode to the smallest amount of data. + */ + for (samp_row = samp_rows; samp_row < compptr->v_samp_factor; + samp_row++) + memset(diff->diff_buf[compi][samp_row], 0, + jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor) * sizeof(JDIFF)); + } + } + samps_across = compptr->width_in_blocks; + + for (samp_row = 0; samp_row < samp_rows; samp_row++) { + (*losslessc->scaler_scale) (cinfo, + input_buf[compi][samp_row], + diff->cur_row[compi], + samps_across); + (*losslessc->predict_difference[compi]) + (cinfo, compi, diff->cur_row[compi], diff->prev_row[compi], + diff->diff_buf[compi][samp_row], samps_across); + SWAP_ROWS(diff->cur_row[compi], diff->prev_row[compi]); + } + } + } + /* Try to write the MCU row (or remaining portion of suspended MCU row). */ + MCU_count = + (*cinfo->entropy->encode_mcus) (cinfo, + diff->diff_buf, yoffset, MCU_col_num, + cinfo->MCUs_per_row - MCU_col_num); + if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) { + /* Suspension forced; update state counters and exit */ + diff->MCU_vert_offset = yoffset; + diff->mcu_ctr += MCU_col_num; + return FALSE; + } + /* Completed an MCU row, but perhaps not an iMCU row */ + diff->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + diff->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +#ifdef FULL_SAMP_BUFFER_SUPPORTED + +/* + * Process some data in the first pass of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the image. + * This amount of data is read from the source buffer and saved into the + * virtual arrays. + * + * We must also emit the data to the compressor. This is conveniently + * done by calling compress_output() after we've loaded the current strip + * of the virtual arrays. + * + * NB: input_buf contains a plane for each component in image. All components + * are loaded into the virtual arrays in this pass. However, it may be that + * only a subset of the components are emitted to the compressor during + * this first pass; be careful about looking at the scan-dependent variables + * (MCU dimensions, etc). + */ + +METHODDEF(boolean) +compress_first_pass(j_compress_ptr cinfo, _JSAMPIMAGE input_buf) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION samps_across; + int ci, samp_row, samp_rows; + _JSAMPARRAY buffer; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, diff->whole_image[ci], + diff->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, TRUE); + + /* Count non-dummy sample rows in this iMCU row. */ + if (diff->iMCU_row_num < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + samp_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor); + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + } + samps_across = compptr->width_in_blocks; + + /* Perform point transform scaling and prediction/differencing for all + * non-dummy rows in this iMCU row. Each call on these functions + * processes a complete row of samples. + */ + for (samp_row = 0; samp_row < samp_rows; samp_row++) { + memcpy(buffer[samp_row], input_buf[ci][samp_row], + samps_across * sizeof(_JSAMPLE)); + } + } + /* NB: compress_output will increment iMCU_row_num if successful. + * A suspension return will result in redoing all the work above next time. + */ + + /* Emit data to the compressor, sharing code with subsequent passes */ + return compress_output(cinfo, input_buf); +} + + +/* + * Process some data in subsequent passes of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the compressor. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output(j_compress_ptr cinfo, _JSAMPIMAGE input_buf) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + int ci, compi; + _JSAMPARRAY buffer[MAX_COMPS_IN_SCAN]; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. + * NB: during first pass, this is safe only because the buffers will + * already be aligned properly, so jmemmgr.c won't need to do any I/O. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + compi = compptr->component_index; + buffer[compi] = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, diff->whole_image[compi], + diff->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, FALSE); + } + + return compress_data(cinfo, buffer); +} + +#endif /* FULL_SAMP_BUFFER_SUPPORTED */ + + +/* + * Initialize difference buffer controller. + */ + +GLOBAL(void) +_jinit_c_diff_controller(j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_diff_ptr diff; + int ci, row; + jpeg_component_info *compptr; + + diff = (my_diff_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + sizeof(my_diff_controller)); + cinfo->coef = (struct jpeg_c_coef_controller *)diff; + diff->pub.start_pass = start_pass_diff; + + /* Create the prediction row buffers. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->cur_row[ci] = *(_JSAMPARRAY)(*cinfo->mem->alloc_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, + (JDIMENSION)jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor), + (JDIMENSION)1); + diff->prev_row[ci] = *(_JSAMPARRAY)(*cinfo->mem->alloc_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, + (JDIMENSION)jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor), + (JDIMENSION)1); + } + + /* Create the difference buffer. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->diff_buf[ci] = + ALLOC_DARRAY(JPOOL_IMAGE, + (JDIMENSION)jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor), + (JDIMENSION)compptr->v_samp_factor); + /* Prefill difference rows with zeros. We do this because only actual + * data is placed in the buffers during prediction/differencing, leaving + * any dummy differences at the right edge as zeros, which will encode + * to the smallest amount of data. + */ + for (row = 0; row < compptr->v_samp_factor; row++) + memset(diff->diff_buf[ci][row], 0, + jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor) * sizeof(JDIFF)); + } + + /* Create the sample buffer. */ + if (need_full_buffer) { +#ifdef FULL_SAMP_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor differences in each direction. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION)jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor), + (JDIMENSION)jround_up((long)compptr->height_in_blocks, + (long)compptr->v_samp_factor), + (JDIMENSION)compptr->v_samp_factor); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else + diff->whole_image[0] = NULL; /* flag for no virtual arrays */ +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/3rdparty/libjpeg-turbo/src/jchuff.c b/3rdparty/libjpeg-turbo/src/jchuff.c index f4dfa1cb5403..488c9b5c3a7f 100644 --- a/3rdparty/libjpeg-turbo/src/jchuff.c +++ b/3rdparty/libjpeg-turbo/src/jchuff.c @@ -3,11 +3,14 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2009-2011, 2014-2016, 2018-2022, D. R. Commander. + * Copyright (C) 2009-2011, 2014-2016, 2018-2024, D. R. Commander. * Copyright (C) 2015, Matthieu Darbois. * Copyright (C) 2018, Matthias Räncker. * Copyright (C) 2020, Arm Limited. + * Copyright (C) 2022, Felix Hanau. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -26,44 +29,13 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#ifdef WITH_SIMD #include "jsimd.h" -#include "jconfigint.h" -#include - -/* - * NOTE: If USE_CLZ_INTRINSIC is defined, then clz/bsr instructions will be - * used for bit counting rather than the lookup table. This will reduce the - * memory footprint by 64k, which is important for some mobile applications - * that create many isolated instances of libjpeg-turbo (web browsers, for - * instance.) This may improve performance on some mobile platforms as well. - * This feature is enabled by default only on Arm processors, because some x86 - * chips have a slow implementation of bsr, and the use of clz/bsr cannot be - * shown to have a significant performance impact even on the x86 chips that - * have a fast implementation of it. When building for Armv6, you can - * explicitly disable the use of clz/bsr by adding -mthumb to the compiler - * flags (this defines __thumb__). - */ - -/* NOTE: Both GCC and Clang define __GNUC__ */ -#if (defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))) || \ - defined(_M_ARM) || defined(_M_ARM64) -#if !defined(__thumb__) || defined(__thumb2__) -#define USE_CLZ_INTRINSIC -#endif -#endif - -#ifdef USE_CLZ_INTRINSIC -#if defined(_MSC_VER) && !defined(__clang__) -#define JPEG_NBITS_NONZERO(x) (32 - _CountLeadingZeros(x)) -#else -#define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x)) -#endif -#define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0) #else -#include "jpeg_nbits_table.h" -#define JPEG_NBITS(x) (jpeg_nbits_table[x]) -#define JPEG_NBITS_NONZERO(x) JPEG_NBITS(x) +#include "jchuff.h" /* Declarations shared with jc*huff.c */ #endif +#include +#include "jpeg_nbits.h" /* Expanded entropy encoder object for Huffman encoding. @@ -102,7 +74,9 @@ typedef bit_buf_type simd_bit_buf_type; typedef struct { union { bit_buf_type c; +#ifdef WITH_SIMD simd_bit_buf_type simd; +#endif } put_buffer; /* current bit accumulation buffer */ int free_bits; /* # of bits available in it */ /* (Neon GAS: # of bits now in it) */ @@ -127,7 +101,9 @@ typedef struct { long *ac_count_ptrs[NUM_HUFF_TBLS]; #endif +#ifdef WITH_SIMD int simd; +#endif } huff_entropy_encoder; typedef huff_entropy_encoder *huff_entropy_ptr; @@ -141,7 +117,9 @@ typedef struct { size_t free_in_buffer; /* # of byte spaces remaining in buffer */ savable_state cur; /* Current bit buffer & DC state */ j_compress_ptr cinfo; /* dump_buffer needs access to this */ +#ifdef WITH_SIMD int simd; +#endif } working_state; @@ -180,7 +158,9 @@ start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics) entropy->pub.finish_pass = finish_pass_huff; } +#ifdef WITH_SIMD entropy->simd = jsimd_can_huff_encode_one_block(); +#endif for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; @@ -220,6 +200,7 @@ start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics) } /* Initialize bit buffer to empty */ +#ifdef WITH_SIMD if (entropy->simd) { entropy->saved.put_buffer.simd = 0; #if defined(__aarch64__) && !defined(NEON_INTRINSICS) @@ -227,7 +208,9 @@ start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics) #else entropy->saved.free_bits = SIMD_BIT_BUF_SIZE; #endif - } else { + } else +#endif + { entropy->saved.put_buffer.c = 0; entropy->saved.free_bits = BIT_BUF_SIZE; } @@ -242,7 +225,7 @@ start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics) * Compute the derived values for a Huffman table. * This routine also performs some validation checks on the table. * - * Note this is also used by jcphuff.c. + * Note this is also used by jcphuff.c and jclhuff.c. */ GLOBAL(void) @@ -318,12 +301,12 @@ jpeg_make_c_derived_tbl(j_compress_ptr cinfo, boolean isDC, int tblno, memset(dtbl->ehufco, 0, sizeof(dtbl->ehufco)); memset(dtbl->ehufsi, 0, sizeof(dtbl->ehufsi)); - /* This is also a convenient place to check for out-of-range - * and duplicated VAL entries. We allow 0..255 for AC symbols - * but only 0..15 for DC. (We could constrain them further - * based on data depth and mode, but this seems enough.) + /* This is also a convenient place to check for out-of-range and duplicated + * VAL entries. We allow 0..255 for AC symbols but only 0..15 for DC in + * lossy mode and 0..16 for DC in lossless mode. (We could constrain them + * further based on data depth and mode, but this seems enough.) */ - maxsymbol = isDC ? 15 : 255; + maxsymbol = isDC ? (cinfo->master->lossless ? 16 : 15) : 255; for (p = 0; p < lastp; p++) { i = htbl->huffval[p]; @@ -500,6 +483,7 @@ flush_bits(working_state *state) simd_bit_buf_type put_buffer; int put_bits; int localbuf = 0; +#ifdef WITH_SIMD if (state->simd) { #if defined(__aarch64__) && !defined(NEON_INTRINSICS) put_bits = state->cur.free_bits; @@ -507,7 +491,9 @@ flush_bits(working_state *state) put_bits = SIMD_BIT_BUF_SIZE - state->cur.free_bits; #endif put_buffer = state->cur.put_buffer.simd; - } else { + } else +#endif + { put_bits = BIT_BUF_SIZE - state->cur.free_bits; put_buffer = state->cur.put_buffer.c; } @@ -525,6 +511,7 @@ flush_bits(working_state *state) EMIT_BYTE(temp) } +#ifdef WITH_SIMD if (state->simd) { /* and reset bit buffer to empty */ state->cur.put_buffer.simd = 0; #if defined(__aarch64__) && !defined(NEON_INTRINSICS) @@ -532,7 +519,9 @@ flush_bits(working_state *state) #else state->cur.free_bits = SIMD_BIT_BUF_SIZE; #endif - } else { + } else +#endif + { state->cur.put_buffer.c = 0; state->cur.free_bits = BIT_BUF_SIZE; } @@ -542,6 +531,8 @@ flush_bits(working_state *state) } +#ifdef WITH_SIMD + /* Encode a single block's worth of coefficients */ LOCAL(boolean) @@ -561,6 +552,8 @@ encode_one_block_simd(working_state *state, JCOEFPTR block, int last_dc_val, return TRUE; } +#endif + LOCAL(boolean) encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, c_derived_tbl *dctbl, c_derived_tbl *actbl) @@ -569,6 +562,7 @@ encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, bit_buf_type put_buffer; JOCTET _buffer[BUFSIZE], *buffer; int localbuf = 0; + int max_coef_bits = state->cinfo->data_precision + 2; free_bits = state->cur.free_bits; put_buffer = state->cur.put_buffer.c; @@ -589,6 +583,11 @@ encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, /* Find the number of bits needed for the magnitude of the coefficient */ nbits = JPEG_NBITS(nbits); + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > max_coef_bits + 1) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); /* Emit the Huffman-coded symbol for the number of bits. * Emit that number of bits of the value, if positive, @@ -614,6 +613,9 @@ encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, temp += nbits; \ nbits ^= temp; \ nbits = JPEG_NBITS_NONZERO(nbits); \ + /* Check for out-of-range coefficient values */ \ + if (nbits > max_coef_bits) \ + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); \ /* if run length > 15, must emit special run-length-16 codes (0xF0) */ \ while (r >= 16 * 16) { \ r -= 16 * 16; \ @@ -695,7 +697,9 @@ encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data) state.free_in_buffer = cinfo->dest->free_in_buffer; state.cur = entropy->saved; state.cinfo = cinfo; +#ifdef WITH_SIMD state.simd = entropy->simd; +#endif /* Emit restart marker if needed */ if (cinfo->restart_interval) { @@ -705,6 +709,7 @@ encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data) } /* Encode the MCU data blocks */ +#ifdef WITH_SIMD if (entropy->simd) { for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; @@ -717,7 +722,9 @@ encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* Update last_dc_val */ state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; } - } else { + } else +#endif + { for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; @@ -765,7 +772,9 @@ finish_pass_huff(j_compress_ptr cinfo) state.free_in_buffer = cinfo->dest->free_in_buffer; state.cur = entropy->saved; state.cinfo = cinfo; +#ifdef WITH_SIMD state.simd = entropy->simd; +#endif /* Flush out the last data */ if (!flush_bits(&state)) @@ -801,6 +810,7 @@ htest_one_block(j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, register int temp; register int nbits; register int k, r; + int max_coef_bits = cinfo->data_precision + 2; /* Encode the DC coefficient difference per section F.1.2.1 */ @@ -817,7 +827,7 @@ htest_one_block(j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, /* Check for out-of-range coefficient values. * Since we're encoding a difference, the range limit is twice as much. */ - if (nbits > MAX_COEF_BITS + 1) + if (nbits > max_coef_bits + 1) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count the Huffman symbol for the number of bits */ @@ -846,7 +856,7 @@ htest_one_block(j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, while ((temp >>= 1)) nbits++; /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) + if (nbits > max_coef_bits) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count Huffman symbol for run length / number of bits */ @@ -901,7 +911,7 @@ encode_mcu_gather(j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* * Generate the best Huffman code table for the given counts, fill htbl. - * Note this is also used by jcphuff.c. + * Note this is also used by jcphuff.c and jclhuff.c. * * The JPEG standard requires that no symbol be assigned a codeword of all * one bits (so that padding bits added at the end of a compressed segment @@ -933,11 +943,15 @@ jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]) { #define MAX_CLEN 32 /* assumed maximum initial code length */ UINT8 bits[MAX_CLEN + 1]; /* bits[k] = # of symbols with code length k */ + int bit_pos[MAX_CLEN + 1]; /* # of symbols with smaller code length */ int codesize[257]; /* codesize[k] = code length of symbol k */ + int nz_index[257]; /* index of nonzero symbol in the original freq + array */ int others[257]; /* next symbol in current branch of tree */ int c1, c2; int p, i, j; - long v; + int num_nz_symbols; + long v, v2; /* This algorithm is explained in section K.2 of the JPEG standard */ @@ -952,28 +966,41 @@ jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]) * will be placed last in the largest codeword category. */ + /* Group nonzero frequencies together so we can more easily find the + * smallest. + */ + num_nz_symbols = 0; + for (i = 0; i < 257; i++) { + if (freq[i]) { + nz_index[num_nz_symbols] = i; + freq[num_nz_symbols] = freq[i]; + num_nz_symbols++; + } + } + /* Huffman's basic algorithm to assign optimal code lengths to symbols */ for (;;) { - /* Find the smallest nonzero frequency, set c1 = its symbol */ - /* In case of ties, take the larger symbol number */ + /* Find the two smallest nonzero frequencies; set c1, c2 = their symbols */ + /* In case of ties, take the larger symbol number. Since we have grouped + * the nonzero symbols together, checking for zero symbols is not + * necessary. + */ c1 = -1; - v = 1000000000L; - for (i = 0; i <= 256; i++) { - if (freq[i] && freq[i] <= v) { - v = freq[i]; - c1 = i; - } - } - - /* Find the next smallest nonzero frequency, set c2 = its symbol */ - /* In case of ties, take the larger symbol number */ c2 = -1; v = 1000000000L; - for (i = 0; i <= 256; i++) { - if (freq[i] && freq[i] <= v && i != c1) { - v = freq[i]; - c2 = i; + v2 = 1000000000L; + for (i = 0; i < num_nz_symbols; i++) { + if (freq[i] <= v2) { + if (freq[i] <= v) { + c2 = c1; + v2 = v; + v = freq[i]; + c1 = i; + } else { + v2 = freq[i]; + c2 = i; + } } } @@ -983,7 +1010,10 @@ jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]) /* Else merge the two counts/trees */ freq[c1] += freq[c2]; - freq[c2] = 0; + /* Set the frequency to a very high value instead of zero, so we don't have + * to check for zero values. + */ + freq[c2] = 1000000001L; /* Increment the codesize of everything in c1's tree branch */ codesize[c1]++; @@ -1003,15 +1033,24 @@ jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]) } /* Now count the number of symbols of each code length */ - for (i = 0; i <= 256; i++) { - if (codesize[i]) { - /* The JPEG standard seems to think that this can't happen, */ - /* but I'm paranoid... */ - if (codesize[i] > MAX_CLEN) - ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); - - bits[codesize[i]]++; - } + for (i = 0; i < num_nz_symbols; i++) { + /* The JPEG standard seems to think that this can't happen, */ + /* but I'm paranoid... */ + if (codesize[i] > MAX_CLEN) + ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); + + bits[codesize[i]]++; + } + + /* Count the number of symbols with a length smaller than i bits, so we can + * construct the symbol table more efficiently. Note that this includes the + * pseudo-symbol 256, but since it is the last symbol, it will not affect the + * table. + */ + p = 0; + for (i = 1; i <= MAX_CLEN; i++) { + bit_pos[i] = p; + p += bits[i]; } /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure @@ -1051,14 +1090,9 @@ jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]) * changes made above, but Rec. ITU-T T.81 | ISO/IEC 10918-1 seems to think * this works. */ - p = 0; - for (i = 1; i <= MAX_CLEN; i++) { - for (j = 0; j <= 255; j++) { - if (codesize[j] == i) { - htbl->huffval[p] = (UINT8)j; - p++; - } - } + for (i = 0; i < num_nz_symbols - 1; i++) { + htbl->huffval[bit_pos[codesize[i]]] = (UINT8)nz_index[i]; + bit_pos[codesize[i]]++; } /* Set sent_table FALSE so updated table will be written to JPEG file. */ diff --git a/3rdparty/libjpeg-turbo/src/jchuff.h b/3rdparty/libjpeg-turbo/src/jchuff.h index 314a2325c9e5..21f17b89b098 100644 --- a/3rdparty/libjpeg-turbo/src/jchuff.h +++ b/3rdparty/libjpeg-turbo/src/jchuff.h @@ -3,8 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. - * It was modified by The libjpeg-turbo Project to include only code relevant - * to libjpeg-turbo. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -19,11 +19,13 @@ * Hence the magnitude should always fit in 10 or 14 bits respectively. */ -#if BITS_IN_JSAMPLE == 8 -#define MAX_COEF_BITS 10 -#else -#define MAX_COEF_BITS 14 -#endif +/* The progressive Huffman encoder uses an unsigned 16-bit data type to store + * absolute values of coefficients, because it is possible to inject a + * coefficient value of -32768 into the encoder by attempting to transform a + * malformed 12-bit JPEG image, and the absolute value of -32768 would overflow + * a signed 16-bit integer. + */ +typedef unsigned short UJCOEF; /* Derived data constructed for each Huffman table */ diff --git a/3rdparty/libjpeg-turbo/src/jcinit.c b/3rdparty/libjpeg-turbo/src/jcinit.c index 157353a22e9d..fe8a13a8d98b 100644 --- a/3rdparty/libjpeg-turbo/src/jcinit.c +++ b/3rdparty/libjpeg-turbo/src/jcinit.c @@ -3,8 +3,10 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2020, D. R. Commander. + * Copyright (C) 2020, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -21,7 +23,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" /* @@ -38,34 +40,101 @@ jinit_compress_master(j_compress_ptr cinfo) /* Preprocessing */ if (!cinfo->raw_data_in) { - jinit_color_converter(cinfo); - jinit_downsampler(cinfo); - jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); + if (cinfo->data_precision == 16) { +#ifdef C_LOSSLESS_SUPPORTED + j16init_color_converter(cinfo); + j16init_downsampler(cinfo); + j16init_c_prep_controller(cinfo, + FALSE /* never need full buffer here */); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); +#endif + } else if (cinfo->data_precision == 12) { + j12init_color_converter(cinfo); + j12init_downsampler(cinfo); + j12init_c_prep_controller(cinfo, + FALSE /* never need full buffer here */); + } else { + jinit_color_converter(cinfo); + jinit_downsampler(cinfo); + jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); + } } - /* Forward DCT */ - jinit_forward_dct(cinfo); - /* Entropy encoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { -#ifdef C_ARITH_CODING_SUPPORTED - jinit_arith_encoder(cinfo); + + if (cinfo->master->lossless) { +#ifdef C_LOSSLESS_SUPPORTED + /* Prediction, sample differencing, and point transform */ + if (cinfo->data_precision == 16) + j16init_lossless_compressor(cinfo); + else if (cinfo->data_precision == 12) + j12init_lossless_compressor(cinfo); + else + jinit_lossless_compressor(cinfo); + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + jinit_lhuff_encoder(cinfo); + } + + /* Need a full-image difference buffer in any multi-pass mode. */ + if (cinfo->data_precision == 16) + j16init_c_diff_controller(cinfo, (boolean)(cinfo->num_scans > 1 || + cinfo->optimize_coding)); + else if (cinfo->data_precision == 12) + j12init_c_diff_controller(cinfo, (boolean)(cinfo->num_scans > 1 || + cinfo->optimize_coding)); + else + jinit_c_diff_controller(cinfo, (boolean)(cinfo->num_scans > 1 || + cinfo->optimize_coding)); #else - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - if (cinfo->progressive_mode) { + if (cinfo->data_precision == 16) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + /* Forward DCT */ + if (cinfo->data_precision == 12) + j12init_forward_dct(cinfo); + else + jinit_forward_dct(cinfo); + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef C_ARITH_CODING_SUPPORTED + jinit_arith_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + if (cinfo->progressive_mode) { #ifdef C_PROGRESSIVE_SUPPORTED - jinit_phuff_encoder(cinfo); + jinit_phuff_encoder(cinfo); #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif - } else - jinit_huff_encoder(cinfo); + } else + jinit_huff_encoder(cinfo); + } + + /* Need a full-image coefficient buffer in any multi-pass mode. */ + if (cinfo->data_precision == 12) + j12init_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 || + cinfo->optimize_coding)); + else + jinit_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 || + cinfo->optimize_coding)); } - /* Need a full-image coefficient buffer in any multi-pass mode. */ - jinit_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 || - cinfo->optimize_coding)); - jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); + if (cinfo->data_precision == 16) +#ifdef C_LOSSLESS_SUPPORTED + j16init_c_main_controller(cinfo, FALSE /* never need full buffer here */); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); +#endif + else if (cinfo->data_precision == 12) + j12init_c_main_controller(cinfo, FALSE /* never need full buffer here */); + else + jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); jinit_marker_writer(cinfo); diff --git a/3rdparty/libjpeg-turbo/src/jclhuff.c b/3rdparty/libjpeg-turbo/src/jclhuff.c new file mode 100644 index 000000000000..ae4154532edf --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/jclhuff.c @@ -0,0 +1,587 @@ +/* + * jclhuff.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains Huffman entropy encoding routines for lossless JPEG. + * + * Much of the complexity here has to do with supporting output suspension. + * If the data destination module demands suspension, we want to be able to + * back up to the start of the current MCU. To do this, we copy state + * variables into local working storage, and update them back to the + * permanent JPEG objects only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jlossls.h" /* Private declarations for lossless codec */ +#include "jchuff.h" /* Declarations shared with jc*huff.c */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* The legal range of a spatial difference is + * -32767 .. +32768. + * Hence the magnitude should always fit in 16 bits. + */ + +#define MAX_DIFF_BITS 16 + + +/* Expanded entropy encoder object for Huffman encoding in lossless mode. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + size_t put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ +} savable_state; + + +typedef struct { + int ci, yoffset, MCU_width; +} lhe_input_ptr_info; + + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + savable_state saved; /* Bit buffer at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + c_derived_tbl *derived_tbls[NUM_HUFF_TBLS]; + + /* Pointers to derived tables to be used for each data unit within an MCU */ + c_derived_tbl *cur_tbls[C_MAX_BLOCKS_IN_MCU]; + +#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ + long *count_ptrs[NUM_HUFF_TBLS]; + + /* Pointers to stats tables to be used for each data unit within an MCU */ + long *cur_counts[C_MAX_BLOCKS_IN_MCU]; +#endif + + /* Pointers to the proper input difference row for each group of data units + * within an MCU. For each component, there are Vi groups of Hi data units. + */ + JDIFFROW input_ptr[C_MAX_BLOCKS_IN_MCU]; + + /* Number of input pointers in use for the current MCU. This is the sum + * of all Vi in the MCU. + */ + int num_input_ptrs; + + /* Information used for positioning the input pointers within the input + * difference rows. + */ + lhe_input_ptr_info input_ptr_info[C_MAX_BLOCKS_IN_MCU]; + + /* Index of the proper input pointer for each data unit within an MCU */ + int input_ptr_index[C_MAX_BLOCKS_IN_MCU]; + +} lhuff_entropy_encoder; + +typedef lhuff_entropy_encoder *lhuff_entropy_ptr; + +/* Working state while writing an MCU. + * This struct contains all the fields that are needed by subroutines. + */ + +typedef struct { + JOCTET *next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + j_compress_ptr cinfo; /* dump_buffer needs access to this */ +} working_state; + + +/* Forward declarations */ +METHODDEF(JDIMENSION) encode_mcus_huff(j_compress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU); +METHODDEF(void) finish_pass_huff(j_compress_ptr cinfo); +#ifdef ENTROPY_OPT_SUPPORTED +METHODDEF(JDIMENSION) encode_mcus_gather(j_compress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU); +METHODDEF(void) finish_pass_gather(j_compress_ptr cinfo); +#endif + + +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_lhuff(j_compress_ptr cinfo, boolean gather_statistics) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + int ci, dctbl, sampn, ptrn, yoffset, xoffset; + jpeg_component_info *compptr; + + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + entropy->pub.encode_mcus = encode_mcus_gather; + entropy->pub.finish_pass = finish_pass_gather; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + entropy->pub.encode_mcus = encode_mcus_huff; + entropy->pub.finish_pass = finish_pass_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + /* Check for invalid table indexes */ + /* (make_c_derived_tbl does this in the other path) */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->count_ptrs[dctbl] == NULL) + entropy->count_ptrs[dctbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + 257 * sizeof(long)); + memset(entropy->count_ptrs[dctbl], 0, 257 * sizeof(long)); +#endif + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, + &entropy->derived_tbls[dctbl]); + } + } + + /* Precalculate encoding info for each sample in an MCU of this scan */ + for (sampn = 0, ptrn = 0; sampn < cinfo->blocks_in_MCU;) { + compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]]; + ci = compptr->component_index; + for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) { + /* Precalculate the setup info for each input pointer */ + entropy->input_ptr_info[ptrn].ci = ci; + entropy->input_ptr_info[ptrn].yoffset = yoffset; + entropy->input_ptr_info[ptrn].MCU_width = compptr->MCU_width; + for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) { + /* Precalculate the input pointer index for each sample */ + entropy->input_ptr_index[sampn] = ptrn; + /* Precalculate which tables to use for each sample */ + entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no]; + entropy->cur_counts[sampn] = entropy->count_ptrs[compptr->dc_tbl_no]; + } + } + } + entropy->num_input_ptrs = ptrn; + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file */ + +/* Emit a byte, taking 'action' if must suspend. */ +#define emit_byte(state, val, action) { \ + *(state)->next_output_byte++ = (JOCTET)(val); \ + if (--(state)->free_in_buffer == 0) \ + if (!dump_buffer(state)) \ + { action; } \ +} + + +LOCAL(boolean) +dump_buffer(working_state *state) +/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ +{ + struct jpeg_destination_mgr *dest = state->cinfo->dest; + + if (!(*dest->empty_output_buffer) (state->cinfo)) + return FALSE; + /* After a successful buffer dump, must reset buffer pointers */ + state->next_output_byte = dest->next_output_byte; + state->free_in_buffer = dest->free_in_buffer; + return TRUE; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(boolean) +emit_bits(working_state *state, unsigned int code, int size) +/* Emit some bits; return TRUE if successful, FALSE if must suspend */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register size_t put_buffer = (size_t)code; + register int put_bits = state->cur.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + + put_buffer &= (((size_t)1) << size) - 1; /* mask off any extra bits in code */ + + put_bits += size; /* new number of bits in buffer */ + + put_buffer <<= 24 - put_bits; /* align incoming bits */ + + put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int)((put_buffer >> 16) & 0xFF); + + emit_byte(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; + } + + state->cur.put_buffer = put_buffer; /* update state variables */ + state->cur.put_bits = put_bits; + + return TRUE; +} + + +LOCAL(boolean) +flush_bits(working_state *state) +{ + if (!emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ + return FALSE; + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_bits = 0; + return TRUE; +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart(working_state *state, int restart_num) +{ + if (!flush_bits(state)) + return FALSE; + + emit_byte(state, 0xFF, return FALSE); + emit_byte(state, JPEG_RST0 + restart_num, return FALSE); + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +/* + * Encode and output nMCU MCUs' worth of Huffman-compressed differences. + */ + +METHODDEF(JDIMENSION) +encode_mcus_huff(j_compress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, + JDIMENSION nMCU) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + working_state state; + int sampn, ci, yoffset, MCU_width, ptrn; + JDIMENSION mcu_num; + + /* Load up working state */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + state.cur = entropy->saved; + state.cinfo = cinfo; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (!emit_restart(&state, entropy->next_restart_num)) + return 0; + } + + /* Set input pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) { + ci = entropy->input_ptr_info[ptrn].ci; + yoffset = entropy->input_ptr_info[ptrn].yoffset; + MCU_width = entropy->input_ptr_info[ptrn].MCU_width; + entropy->input_ptr[ptrn] = + diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width); + } + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->blocks_in_MCU; sampn++) { + register int temp, temp2; + register int nbits; + c_derived_tbl *dctbl = entropy->cur_tbls[sampn]; + + /* Encode the difference per section H.1.2.2 */ + + /* Input the sample difference */ + temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++; + + if (temp & 0x8000) { /* instead of temp < 0 */ + temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */ + if (temp == 0) /* special case: magnitude = 32768 */ + temp2 = temp = 0x8000; + temp2 = ~temp; /* one's complement of magnitude */ + } else { + temp &= 0x7FFF; /* abs value mod 2^16 */ + temp2 = temp; /* magnitude */ + } + + /* Find the number of bits needed for the magnitude of the difference */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range difference values. + */ + if (nbits > MAX_DIFF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Emit the Huffman-coded symbol for the number of bits */ + if (!emit_bits(&state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + return mcu_num; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits && /* emit_bits rejects calls with size 0 */ + nbits != 16) /* special case: no bits should be emitted */ + if (!emit_bits(&state, (unsigned int)temp2, nbits)) + return mcu_num; + } + + /* Completed MCU, so update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + entropy->saved = state.cur; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + } + + return nMCU; +} + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff(j_compress_ptr cinfo) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + working_state state; + + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + state.cur = entropy->saved; + state.cinfo = cinfo; + + /* Flush out the last data */ + if (!flush_bits(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + entropy->saved = state.cur; +} + + +/* + * Huffman coding optimization. + * + * We first scan the supplied data and count the number of uses of each symbol + * that is to be Huffman-coded. (This process MUST agree with the code above.) + * Then we build a Huffman coding tree for the observed counts. + * Symbols which are not needed at all for the particular image are not + * assigned any code, which saves space in the DHT marker as well as in + * the compressed data. + */ + +#ifdef ENTROPY_OPT_SUPPORTED + +/* + * Trial-encode nMCU MCUs' worth of Huffman-compressed differences. + * No data is actually output, so no suspension return is possible. + */ + +METHODDEF(JDIMENSION) +encode_mcus_gather(j_compress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, + JDIMENSION nMCU) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + int sampn, ci, yoffset, MCU_width, ptrn; + JDIMENSION mcu_num; + + /* Take care of restart intervals if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + /* Update restart state */ + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; + } + + /* Set input pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) { + ci = entropy->input_ptr_info[ptrn].ci; + yoffset = entropy->input_ptr_info[ptrn].yoffset; + MCU_width = entropy->input_ptr_info[ptrn].MCU_width; + entropy->input_ptr[ptrn] = + diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width); + } + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->blocks_in_MCU; sampn++) { + register int temp; + register int nbits; + long *counts = entropy->cur_counts[sampn]; + + /* Encode the difference per section H.1.2.2 */ + + /* Input the sample difference */ + temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++; + + if (temp & 0x8000) { /* instead of temp < 0 */ + temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */ + if (temp == 0) /* special case: magnitude = 32768 */ + temp = 0x8000; + } else + temp &= 0x7FFF; /* abs value mod 2^16 */ + + /* Find the number of bits needed for the magnitude of the difference */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range difference values. + */ + if (nbits > MAX_DIFF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count the Huffman symbol for the number of bits */ + counts[nbits]++; + } + } + + return nMCU; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather(j_compress_ptr cinfo) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + int ci, dctbl; + jpeg_component_info *compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + memset(did_dc, 0, sizeof(did_dc)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + if (!did_dc[dctbl]) { + htblptr = &cinfo->dc_huff_tbl_ptrs[dctbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[dctbl]); + did_dc[dctbl] = TRUE; + } + } +} + + +#endif /* ENTROPY_OPT_SUPPORTED */ + + +/* + * Module initialization routine for Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_lhuff_encoder(j_compress_ptr cinfo) +{ + lhuff_entropy_ptr entropy; + int i; + + entropy = (lhuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + sizeof(lhuff_entropy_encoder)); + cinfo->entropy = (struct jpeg_entropy_encoder *)entropy; + entropy->pub.start_pass = start_pass_lhuff; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; +#ifdef ENTROPY_OPT_SUPPORTED + entropy->count_ptrs[i] = NULL; +#endif + } +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/3rdparty/libjpeg-turbo/src/jclossls.c b/3rdparty/libjpeg-turbo/src/jclossls.c new file mode 100644 index 000000000000..e9ba92a7dfea --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/jclossls.c @@ -0,0 +1,319 @@ +/* + * jclossls.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1998, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains prediction, sample differencing, and point transform + * routines for the lossless JPEG compressor. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jlossls.h" + +#ifdef C_LOSSLESS_SUPPORTED + + +/************************** Sample differencing **************************/ + +/* + * In order to avoid a performance penalty for checking which predictor is + * being used and which row is being processed for each call of the + * undifferencer, and to promote optimization, we have separate differencing + * functions for each predictor selection value. + * + * We are able to avoid duplicating source code by implementing the predictors + * and differencers as macros. Each of the differencing functions is simply a + * wrapper around a DIFFERENCE macro with the appropriate PREDICTOR macro + * passed as an argument. + */ + +/* Forward declarations */ +LOCAL(void) reset_predictor(j_compress_ptr cinfo, int ci); + + +/* Predictor for the first column of the first row: 2^(P-Pt-1) */ +#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1)) + +/* Predictor for the first column of the remaining rows: Rb */ +#define INITIAL_PREDICTOR2 prev_row[0] + + +/* + * 1-Dimensional differencer routine. + * + * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR + * is used as the special case predictor for the first column, which must be + * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples + * use PREDICTOR1. + */ + +#define DIFFERENCE_1D(INITIAL_PREDICTOR) \ + lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct; \ + boolean restart = FALSE; \ + int samp, Ra; \ + \ + samp = *input_buf++; \ + *diff_buf++ = samp - INITIAL_PREDICTOR; \ + \ + while (--width) { \ + Ra = samp; \ + samp = *input_buf++; \ + *diff_buf++ = samp - PREDICTOR1; \ + } \ + \ + /* Account for restart interval (no-op if not using restarts) */ \ + if (cinfo->restart_interval) { \ + if (--(losslessc->restart_rows_to_go[ci]) == 0) { \ + reset_predictor(cinfo, ci); \ + restart = TRUE; \ + } \ + } + + +/* + * 2-Dimensional differencer routine. + * + * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is + * used as the special case predictor for the first column. The remaining + * samples use PREDICTOR, which is a function of Ra, Rb, and Rc. + * + * Because prev_row and output_buf may point to the same storage area (in an + * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc + * before writing the current reconstructed sample value into output_buf. + */ + +#define DIFFERENCE_2D(PREDICTOR) \ + lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct; \ + int samp, Ra, Rb, Rc; \ + \ + Rb = *prev_row++; \ + samp = *input_buf++; \ + *diff_buf++ = samp - PREDICTOR2; \ + \ + while (--width) { \ + Rc = Rb; \ + Rb = *prev_row++; \ + Ra = samp; \ + samp = *input_buf++; \ + *diff_buf++ = samp - PREDICTOR; \ + } \ + \ + /* Account for restart interval (no-op if not using restarts) */ \ + if (cinfo->restart_interval) { \ + if (--losslessc->restart_rows_to_go[ci] == 0) \ + reset_predictor(cinfo, ci); \ + } + + +/* + * Differencers for the second and subsequent rows in a scan or restart + * interval. The first sample in the row is differenced using the vertical + * predictor (2). The rest of the samples are differenced using the predictor + * specified in the scan header. + */ + +METHODDEF(void) +jpeg_difference1(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_1D(INITIAL_PREDICTOR2); + (void)(restart); +} + +METHODDEF(void) +jpeg_difference2(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR2); + (void)(Ra); + (void)(Rc); +} + +METHODDEF(void) +jpeg_difference3(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR3); + (void)(Ra); +} + +METHODDEF(void) +jpeg_difference4(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR4); +} + +METHODDEF(void) +jpeg_difference5(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR5); +} + +METHODDEF(void) +jpeg_difference6(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR6); +} + +METHODDEF(void) +jpeg_difference7(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR7); + (void)(Rc); +} + + +/* + * Differencer for the first row in a scan or restart interval. The first + * sample in the row is differenced using the special predictor constant + * x = 2 ^ (P-Pt-1). The rest of the samples are differenced using the + * 1-D horizontal predictor (1). + */ + +METHODDEF(void) +jpeg_difference_first_row(j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, _JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_1D(INITIAL_PREDICTORx); + + /* + * Now that we have differenced the first row, we want to use the + * differencer that corresponds to the predictor specified in the + * scan header. + * + * Note that we don't do this if we have just reset the predictor + * for a new restart interval. + */ + if (!restart) { + switch (cinfo->Ss) { + case 1: + losslessc->predict_difference[ci] = jpeg_difference1; + break; + case 2: + losslessc->predict_difference[ci] = jpeg_difference2; + break; + case 3: + losslessc->predict_difference[ci] = jpeg_difference3; + break; + case 4: + losslessc->predict_difference[ci] = jpeg_difference4; + break; + case 5: + losslessc->predict_difference[ci] = jpeg_difference5; + break; + case 6: + losslessc->predict_difference[ci] = jpeg_difference6; + break; + case 7: + losslessc->predict_difference[ci] = jpeg_difference7; + break; + } + } +} + +/* + * Reset predictor at the start of a pass or restart interval. + */ + +LOCAL(void) +reset_predictor(j_compress_ptr cinfo, int ci) +{ + lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct; + + /* Initialize restart counter */ + losslessc->restart_rows_to_go[ci] = + cinfo->restart_interval / cinfo->MCUs_per_row; + + /* Set difference function to first row function */ + losslessc->predict_difference[ci] = jpeg_difference_first_row; +} + + +/********************** Sample downscaling by 2^Pt ***********************/ + +METHODDEF(void) +simple_downscale(j_compress_ptr cinfo, + _JSAMPROW input_buf, _JSAMPROW output_buf, JDIMENSION width) +{ + do { + *output_buf++ = (_JSAMPLE)RIGHT_SHIFT(*input_buf++, cinfo->Al); + } while (--width); +} + + +METHODDEF(void) +noscale(j_compress_ptr cinfo, + _JSAMPROW input_buf, _JSAMPROW output_buf, JDIMENSION width) +{ + memcpy(output_buf, input_buf, width * sizeof(_JSAMPLE)); +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_lossless(j_compress_ptr cinfo) +{ + lossless_comp_ptr losslessc = (lossless_comp_ptr)cinfo->fdct; + int ci; + + /* Set scaler function based on Pt */ + if (cinfo->Al) + losslessc->scaler_scale = simple_downscale; + else + losslessc->scaler_scale = noscale; + + /* Check that the restart interval is an integer multiple of the number + * of MCUs in an MCU row. + */ + if (cinfo->restart_interval % cinfo->MCUs_per_row != 0) + ERREXIT2(cinfo, JERR_BAD_RESTART, + cinfo->restart_interval, cinfo->MCUs_per_row); + + /* Set predictors for start of pass */ + for (ci = 0; ci < cinfo->num_components; ci++) + reset_predictor(cinfo, ci); +} + + +/* + * Initialize the lossless compressor. + */ + +GLOBAL(void) +_jinit_lossless_compressor(j_compress_ptr cinfo) +{ + lossless_comp_ptr losslessc; + + /* Create subobject in permanent pool */ + losslessc = (lossless_comp_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT, + sizeof(jpeg_lossless_compressor)); + cinfo->fdct = (struct jpeg_forward_dct *)losslessc; + losslessc->pub.start_pass = start_pass_lossless; +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/3rdparty/libjpeg-turbo/src/jcmainct.c b/3rdparty/libjpeg-turbo/src/jcmainct.c index 3f23028c467e..fe8fc0b1acde 100644 --- a/3rdparty/libjpeg-turbo/src/jcmainct.c +++ b/3rdparty/libjpeg-turbo/src/jcmainct.c @@ -3,8 +3,10 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. - * It was modified by The libjpeg-turbo Project to include only code relevant - * to libjpeg-turbo. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -16,8 +18,11 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) + /* Private buffer controller object */ typedef struct { @@ -32,7 +37,7 @@ typedef struct { * (we allocate one for each component). In the full-image case, this * points to the currently accessible strips of the virtual arrays. */ - JSAMPARRAY buffer[MAX_COMPONENTS]; + _JSAMPARRAY buffer[MAX_COMPONENTS]; } my_main_controller; typedef my_main_controller *my_main_ptr; @@ -40,7 +45,7 @@ typedef my_main_controller *my_main_ptr; /* Forward declarations */ METHODDEF(void) process_data_simple_main(j_compress_ptr cinfo, - JSAMPARRAY input_buf, + _JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail); @@ -65,7 +70,7 @@ start_pass_main(j_compress_ptr cinfo, J_BUF_MODE pass_mode) main_ptr->rowgroup_ctr = 0; main_ptr->suspended = FALSE; main_ptr->pass_mode = pass_mode; /* save mode for use by process_data */ - main_ptr->pub.process_data = process_data_simple_main; + main_ptr->pub._process_data = process_data_simple_main; } @@ -76,28 +81,28 @@ start_pass_main(j_compress_ptr cinfo, J_BUF_MODE pass_mode) */ METHODDEF(void) -process_data_simple_main(j_compress_ptr cinfo, JSAMPARRAY input_buf, +process_data_simple_main(j_compress_ptr cinfo, _JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail) { my_main_ptr main_ptr = (my_main_ptr)cinfo->main; + JDIMENSION data_unit = cinfo->master->lossless ? 1 : DCTSIZE; while (main_ptr->cur_iMCU_row < cinfo->total_iMCU_rows) { /* Read input data if we haven't filled the main buffer yet */ - if (main_ptr->rowgroup_ctr < DCTSIZE) - (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, - in_rows_avail, main_ptr->buffer, - &main_ptr->rowgroup_ctr, - (JDIMENSION)DCTSIZE); + if (main_ptr->rowgroup_ctr < data_unit) + (*cinfo->prep->_pre_process_data) (cinfo, input_buf, in_row_ctr, + in_rows_avail, main_ptr->buffer, + &main_ptr->rowgroup_ctr, data_unit); /* If we don't have a full iMCU row buffered, return to application for * more data. Note that preprocessor will always pad to fill the iMCU row * at the bottom of the image. */ - if (main_ptr->rowgroup_ctr != DCTSIZE) + if (main_ptr->rowgroup_ctr != data_unit) return; /* Send the completed row to the compressor */ - if (!(*cinfo->coef->compress_data) (cinfo, main_ptr->buffer)) { + if (!(*cinfo->coef->_compress_data) (cinfo, main_ptr->buffer)) { /* If compressor did not consume the whole row, then we must need to * suspend processing and return to the application. In this situation * we pretend we didn't yet consume the last input row; otherwise, if @@ -128,11 +133,15 @@ process_data_simple_main(j_compress_ptr cinfo, JSAMPARRAY input_buf, */ GLOBAL(void) -jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer) +_jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer) { my_main_ptr main_ptr; int ci; jpeg_component_info *compptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); main_ptr = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, @@ -153,10 +162,12 @@ jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer) /* Allocate a strip buffer for each component */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - main_ptr->buffer[ci] = (*cinfo->mem->alloc_sarray) + main_ptr->buffer[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, - compptr->width_in_blocks * DCTSIZE, - (JDIMENSION)(compptr->v_samp_factor * DCTSIZE)); + compptr->width_in_blocks * data_unit, + (JDIMENSION)(compptr->v_samp_factor * data_unit)); } } } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) */ diff --git a/3rdparty/libjpeg-turbo/src/jcmarker.c b/3rdparty/libjpeg-turbo/src/jcmarker.c index 801fbab4ef01..a064d4dd9e78 100644 --- a/3rdparty/libjpeg-turbo/src/jcmarker.c +++ b/3rdparty/libjpeg-turbo/src/jcmarker.c @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2003-2010 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2010, D. R. Commander. + * Copyright (C) 2010, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -15,7 +17,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" typedef enum { /* JPEG marker codes */ @@ -497,25 +499,26 @@ write_file_header(j_compress_ptr cinfo) METHODDEF(void) write_frame_header(j_compress_ptr cinfo) { - int ci, prec; + int ci, prec = 0; boolean is_baseline; jpeg_component_info *compptr; - /* Emit DQT for each quantization table. - * Note that emit_dqt() suppresses any duplicate tables. - */ - prec = 0; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - prec += emit_dqt(cinfo, compptr->quant_tbl_no); + if (!cinfo->master->lossless) { + /* Emit DQT for each quantization table. + * Note that emit_dqt() suppresses any duplicate tables. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prec += emit_dqt(cinfo, compptr->quant_tbl_no); + } + /* now prec is nonzero iff there are any 16-bit quant tables. */ } - /* now prec is nonzero iff there are any 16-bit quant tables. */ /* Check for a non-baseline specification. * Note we assume that Huffman table numbers won't be changed later. */ if (cinfo->arith_code || cinfo->progressive_mode || - cinfo->data_precision != 8) { + cinfo->master->lossless || cinfo->data_precision != 8) { is_baseline = FALSE; } else { is_baseline = TRUE; @@ -540,6 +543,8 @@ write_frame_header(j_compress_ptr cinfo) } else { if (cinfo->progressive_mode) emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ + else if (cinfo->master->lossless) + emit_sof(cinfo, M_SOF3); /* SOF code for lossless Huffman */ else if (is_baseline) emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ else @@ -574,10 +579,11 @@ write_scan_header(j_compress_ptr cinfo) for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; /* DC needs no table for refinement scan */ - if (cinfo->Ss == 0 && cinfo->Ah == 0) + if ((cinfo->Ss == 0 && cinfo->Ah == 0) || cinfo->master->lossless) emit_dht(cinfo, compptr->dc_tbl_no, FALSE); - /* AC needs no table when not present */ - if (cinfo->Se) + /* AC needs no table when not present, and lossless mode uses only DC + tables. */ + if (cinfo->Se && !cinfo->master->lossless) emit_dht(cinfo, compptr->ac_tbl_no, TRUE); } } diff --git a/3rdparty/libjpeg-turbo/src/jcmaster.c b/3rdparty/libjpeg-turbo/src/jcmaster.c index c2b260003181..161019763d4b 100644 --- a/3rdparty/libjpeg-turbo/src/jcmaster.c +++ b/3rdparty/libjpeg-turbo/src/jcmaster.c @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2003-2010 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2010, 2016, 2018, D. R. Commander. + * Copyright (C) 2010, 2016, 2018, 2022-2024, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -18,40 +20,8 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" -#include "jconfigint.h" - - -/* Private state */ - -typedef enum { - main_pass, /* input data, also do first output step */ - huff_opt_pass, /* Huffman code optimization pass */ - output_pass /* data output pass */ -} c_pass_type; - -typedef struct { - struct jpeg_comp_master pub; /* public fields */ - - c_pass_type pass_type; /* the type of the current pass */ - - int pass_number; /* # of passes completed */ - int total_passes; /* total # of passes needed */ - - int scan_number; /* current index in scan_info[] */ - - /* - * This is here so we can add libjpeg-turbo version/build information to the - * global string table without introducing a new global symbol. Adding this - * information to the global string table allows one to examine a binary - * object and determine which version of libjpeg-turbo it was built from or - * linked against. - */ - const char *jpeg_version; - -} my_comp_master; - -typedef my_comp_master *my_master_ptr; +#include "jpegapicomp.h" +#include "jcmaster.h" /* @@ -69,15 +39,124 @@ GLOBAL(void) jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo) /* Do computations that are needed before master selection phase */ { + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + /* Hardwire it to "no scaling" */ cinfo->jpeg_width = cinfo->image_width; cinfo->jpeg_height = cinfo->image_height; - cinfo->min_DCT_h_scaled_size = DCTSIZE; - cinfo->min_DCT_v_scaled_size = DCTSIZE; + cinfo->min_DCT_h_scaled_size = data_unit; + cinfo->min_DCT_v_scaled_size = data_unit; } #endif +LOCAL(boolean) +using_std_huff_tables(j_compress_ptr cinfo) +{ + int i; + + static const UINT8 bits_dc_luminance[17] = { + /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 + }; + static const UINT8 val_dc_luminance[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 + }; + + static const UINT8 bits_dc_chrominance[17] = { + /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 + }; + static const UINT8 val_dc_chrominance[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 + }; + + static const UINT8 bits_ac_luminance[17] = { + /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d + }; + static const UINT8 val_ac_luminance[] = { + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa + }; + + static const UINT8 bits_ac_chrominance[17] = { + /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 + }; + static const UINT8 val_ac_chrominance[] = { + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa + }; + + if (cinfo->dc_huff_tbl_ptrs[0] == NULL || + cinfo->ac_huff_tbl_ptrs[0] == NULL || + cinfo->dc_huff_tbl_ptrs[1] == NULL || + cinfo->ac_huff_tbl_ptrs[1] == NULL) + return FALSE; + + for (i = 2; i < NUM_HUFF_TBLS; i++) { + if (cinfo->dc_huff_tbl_ptrs[i] != NULL || + cinfo->ac_huff_tbl_ptrs[i] != NULL) + return FALSE; + } + + if (memcmp(cinfo->dc_huff_tbl_ptrs[0]->bits, bits_dc_luminance, + sizeof(bits_dc_luminance)) || + memcmp(cinfo->dc_huff_tbl_ptrs[0]->huffval, val_dc_luminance, + sizeof(val_dc_luminance)) || + memcmp(cinfo->ac_huff_tbl_ptrs[0]->bits, bits_ac_luminance, + sizeof(bits_ac_luminance)) || + memcmp(cinfo->ac_huff_tbl_ptrs[0]->huffval, val_ac_luminance, + sizeof(val_ac_luminance)) || + memcmp(cinfo->dc_huff_tbl_ptrs[1]->bits, bits_dc_chrominance, + sizeof(bits_dc_chrominance)) || + memcmp(cinfo->dc_huff_tbl_ptrs[1]->huffval, val_dc_chrominance, + sizeof(val_dc_chrominance)) || + memcmp(cinfo->ac_huff_tbl_ptrs[1]->bits, bits_ac_chrominance, + sizeof(bits_ac_chrominance)) || + memcmp(cinfo->ac_huff_tbl_ptrs[1]->huffval, val_ac_chrominance, + sizeof(val_ac_chrominance))) + return FALSE; + + return TRUE; +} + + LOCAL(void) initial_setup(j_compress_ptr cinfo, boolean transcode_only) /* Do computations that are needed before master selection phase */ @@ -86,6 +165,7 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only) jpeg_component_info *compptr; long samplesperrow; JDIMENSION jd_samplesperrow; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; #if JPEG_LIB_VERSION >= 70 #if JPEG_LIB_VERSION >= 80 @@ -110,8 +190,12 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only) if ((long)jd_samplesperrow != samplesperrow) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) +#ifdef C_LOSSLESS_SUPPORTED + if (cinfo->data_precision != 8 && cinfo->data_precision != 12 && + cinfo->data_precision != 16) +#else + if (cinfo->data_precision != 8 && cinfo->data_precision != 12) +#endif ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ @@ -142,17 +226,17 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only) compptr->component_index = ci; /* For compression, we never do DCT scaling. */ #if JPEG_LIB_VERSION >= 70 - compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = DCTSIZE; + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = data_unit; #else - compptr->DCT_scaled_size = DCTSIZE; + compptr->DCT_scaled_size = data_unit; #endif - /* Size in DCT blocks */ + /* Size in data units */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor, - (long)(cinfo->max_h_samp_factor * DCTSIZE)); + (long)(cinfo->max_h_samp_factor * data_unit)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_height * (long)compptr->v_samp_factor, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); /* Size in samples */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor, @@ -165,15 +249,19 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only) } /* Compute number of fully interleaved MCU rows (number of times that - * main controller will call coefficient controller). + * main controller will call coefficient or difference controller). */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_height, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); } -#ifdef C_MULTISCAN_FILES_SUPPORTED +#if defined(C_MULTISCAN_FILES_SUPPORTED) || defined(C_LOSSLESS_SUPPORTED) +#define NEED_SCAN_SCRIPT +#endif + +#ifdef NEED_SCAN_SCRIPT LOCAL(void) validate_script(j_compress_ptr cinfo) @@ -194,13 +282,29 @@ validate_script(j_compress_ptr cinfo) if (cinfo->num_scans <= 0) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); +#ifndef C_MULTISCAN_FILES_SUPPORTED + if (cinfo->num_scans > 1) + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + + scanptr = cinfo->scan_info; + if (scanptr->Ss != 0 && scanptr->Se == 0) { +#ifdef C_LOSSLESS_SUPPORTED + cinfo->master->lossless = TRUE; + cinfo->progressive_mode = FALSE; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; * for progressive JPEG, no scan can have this. */ - scanptr = cinfo->scan_info; - if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2 - 1) { + else if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2 - 1) { #ifdef C_PROGRESSIVE_SUPPORTED cinfo->progressive_mode = TRUE; + cinfo->master->lossless = FALSE; last_bitpos_ptr = &last_bitpos[0][0]; for (ci = 0; ci < cinfo->num_components; ci++) for (coefi = 0; coefi < DCTSIZE2; coefi++) @@ -209,7 +313,7 @@ validate_script(j_compress_ptr cinfo) ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - cinfo->progressive_mode = FALSE; + cinfo->progressive_mode = cinfo->master->lossless = FALSE; for (ci = 0; ci < cinfo->num_components; ci++) component_sent[ci] = FALSE; } @@ -241,13 +345,10 @@ validate_script(j_compress_ptr cinfo) * out-of-range reconstructed DC values during the first DC scan, * which might cause problems for some decoders. */ -#if BITS_IN_JSAMPLE == 8 -#define MAX_AH_AL 10 -#else -#define MAX_AH_AL 13 -#endif + int max_Ah_Al = cinfo->data_precision == 12 ? 13 : 10; + if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || - Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) + Ah < 0 || Ah > max_Ah_Al || Al < 0 || Al > max_Ah_Al) ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); if (Ss == 0) { if (Se != 0) /* DC and AC together not OK */ @@ -275,9 +376,25 @@ validate_script(j_compress_ptr cinfo) } #endif } else { - /* For sequential JPEG, all progression parameters must be these: */ - if (Ss != 0 || Se != DCTSIZE2 - 1 || Ah != 0 || Al != 0) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); +#ifdef C_LOSSLESS_SUPPORTED + if (cinfo->master->lossless) { + /* The JPEG spec simply gives the range 0..15 for Al (Pt), but that + * seems wrong: the upper bound ought to depend on data precision. + * Perhaps they really meant 0..N-1 for N-bit precision, which is what + * we allow here. Values greater than or equal to the data precision + * will result in a blank image. + */ + if (Ss < 1 || Ss > 7 || /* predictor selection value */ + Se != 0 || Ah != 0 || + Al < 0 || Al >= cinfo->data_precision) /* point transform */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else +#endif + { + /* For sequential JPEG, all progression parameters must be these: */ + if (Ss != 0 || Se != DCTSIZE2 - 1 || Ah != 0 || Al != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } /* Make sure components are not sent twice */ for (ci = 0; ci < ncomps; ci++) { thisi = scanptr->component_index[ci]; @@ -309,7 +426,7 @@ validate_script(j_compress_ptr cinfo) } } -#endif /* C_MULTISCAN_FILES_SUPPORTED */ +#endif /* NEED_SCAN_SCRIPT */ LOCAL(void) @@ -318,7 +435,7 @@ select_scan_parameters(j_compress_ptr cinfo) { int ci; -#ifdef C_MULTISCAN_FILES_SUPPORTED +#ifdef NEED_SCAN_SCRIPT if (cinfo->scan_info != NULL) { /* Prepare for current scan --- the script is already validated */ my_master_ptr master = (my_master_ptr)cinfo->master; @@ -344,10 +461,12 @@ select_scan_parameters(j_compress_ptr cinfo) for (ci = 0; ci < cinfo->num_components; ci++) { cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; } - cinfo->Ss = 0; - cinfo->Se = DCTSIZE2 - 1; - cinfo->Ah = 0; - cinfo->Al = 0; + if (!cinfo->master->lossless) { + cinfo->Ss = 0; + cinfo->Se = DCTSIZE2 - 1; + cinfo->Ah = 0; + cinfo->Al = 0; + } } } @@ -359,6 +478,7 @@ per_scan_setup(j_compress_ptr cinfo) { int ci, mcublks, tmp; jpeg_component_info *compptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; if (cinfo->comps_in_scan == 1) { @@ -373,7 +493,7 @@ per_scan_setup(j_compress_ptr cinfo) compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; - compptr->MCU_sample_width = DCTSIZE; + compptr->MCU_sample_width = data_unit; compptr->last_col_width = 1; /* For noninterleaved scans, it is convenient to define last_row_height * as the number of block rows present in the last iMCU row. @@ -396,10 +516,10 @@ per_scan_setup(j_compress_ptr cinfo) /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_width, - (long)(cinfo->max_h_samp_factor * DCTSIZE)); + (long)(cinfo->max_h_samp_factor * data_unit)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long)cinfo->_jpeg_height, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); cinfo->blocks_in_MCU = 0; @@ -409,7 +529,7 @@ per_scan_setup(j_compress_ptr cinfo) compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; + compptr->MCU_sample_width = compptr->MCU_width * data_unit; /* Figure number of non-dummy blocks in last MCU column & row */ tmp = (int)(compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; @@ -481,7 +601,8 @@ prepare_for_pass(j_compress_ptr cinfo) /* Do Huffman optimization for a scan after the first one. */ select_scan_parameters(cinfo); per_scan_setup(cinfo); - if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { + if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code || + cinfo->master->lossless) { (*cinfo->entropy->start_pass) (cinfo, TRUE); (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); master->pub.call_pass_startup = FALSE; @@ -590,22 +711,17 @@ finish_pass_master(j_compress_ptr cinfo) GLOBAL(void) jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only) { - my_master_ptr master; + my_master_ptr master = (my_master_ptr)cinfo->master; + boolean empty_huff_tables = TRUE; + int i; - master = (my_master_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - sizeof(my_comp_master)); - cinfo->master = (struct jpeg_comp_master *)master; master->pub.prepare_for_pass = prepare_for_pass; master->pub.pass_startup = pass_startup; master->pub.finish_pass = finish_pass_master; master->pub.is_last_pass = FALSE; - /* Validate parameters, determine derived values */ - initial_setup(cinfo, transcode_only); - if (cinfo->scan_info != NULL) { -#ifdef C_MULTISCAN_FILES_SUPPORTED +#ifdef NEED_SCAN_SCRIPT validate_script(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); @@ -615,8 +731,42 @@ jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only) cinfo->num_scans = 1; } - if (cinfo->progressive_mode && !cinfo->arith_code) /* TEMPORARY HACK ??? */ - cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ + /* Disable smoothing and subsampling in lossless mode, since those are lossy + * algorithms. Set the JPEG colorspace to the input colorspace. Disable raw + * (downsampled) data input, because it isn't particularly useful without + * subsampling and has not been tested in lossless mode. + */ + if (cinfo->master->lossless) { + int ci; + jpeg_component_info *compptr; + + cinfo->raw_data_in = FALSE; + cinfo->smoothing_factor = 0; + jpeg_default_colorspace(cinfo); + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) + compptr->h_samp_factor = compptr->v_samp_factor = 1; + } + + /* Validate parameters, determine derived values */ + initial_setup(cinfo, transcode_only); + + if (cinfo->master->lossless || /* TEMPORARY HACK ??? */ + (cinfo->progressive_mode && !cinfo->arith_code)) + cinfo->optimize_coding = TRUE; /* assume default tables no good for + progressive mode or lossless mode */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if (cinfo->dc_huff_tbl_ptrs[i] != NULL || + cinfo->ac_huff_tbl_ptrs[i] != NULL) { + empty_huff_tables = FALSE; + break; + } + } + if (cinfo->data_precision == 12 && !cinfo->arith_code && + !cinfo->optimize_coding && + (empty_huff_tables || using_std_huff_tables(cinfo))) + cinfo->optimize_coding = TRUE; /* assume default tables no good for 12-bit + data precision */ /* Initialize my private state */ if (transcode_only) { diff --git a/3rdparty/libjpeg-turbo/src/jcmaster.h b/3rdparty/libjpeg-turbo/src/jcmaster.h new file mode 100644 index 000000000000..3b13289b6915 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/jcmaster.h @@ -0,0 +1,43 @@ +/* + * jcmaster.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1995, Thomas G. Lane. + * libjpeg-turbo Modifications: + * Copyright (C) 2016, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains master control structure for the JPEG compressor. + */ + +/* Private state */ + +typedef enum { + main_pass, /* input data, also do first output step */ + huff_opt_pass, /* Huffman code optimization pass */ + output_pass /* data output pass */ +} c_pass_type; + +typedef struct { + struct jpeg_comp_master pub; /* public fields */ + + c_pass_type pass_type; /* the type of the current pass */ + + int pass_number; /* # of passes completed */ + int total_passes; /* total # of passes needed */ + + int scan_number; /* current index in scan_info[] */ + + /* + * This is here so we can add libjpeg-turbo version/build information to the + * global string table without introducing a new global symbol. Adding this + * information to the global string table allows one to examine a binary + * object and determine which version of libjpeg-turbo it was built from or + * linked against. + */ + const char *jpeg_version; + +} my_comp_master; + +typedef my_comp_master *my_master_ptr; diff --git a/3rdparty/libjpeg-turbo/src/jcparam.c b/3rdparty/libjpeg-turbo/src/jcparam.c index 5bc7174dcb54..d1dee4da3df8 100644 --- a/3rdparty/libjpeg-turbo/src/jcparam.c +++ b/3rdparty/libjpeg-turbo/src/jcparam.c @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2003-2008 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2009-2011, 2018, D. R. Commander. + * Copyright (C) 2009-2011, 2018, 2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -202,7 +204,6 @@ jpeg_set_defaults(j_compress_ptr cinfo) cinfo->scale_num = 1; /* 1:1 scaling */ cinfo->scale_denom = 1; #endif - cinfo->data_precision = BITS_IN_JSAMPLE; /* Set up two quantization tables using default quality of 75 */ jpeg_set_quality(cinfo, 75, TRUE); /* Set up two Huffman tables */ @@ -232,7 +233,7 @@ jpeg_set_defaults(j_compress_ptr cinfo) * tables will be computed. This test can be removed if default tables * are supplied that are valid for the desired precision. */ - if (cinfo->data_precision > 8) + if (cinfo->data_precision == 12 && !cinfo->arith_code) cinfo->optimize_coding = TRUE; /* By default, use the simpler non-cosited sampling alignment */ @@ -296,7 +297,10 @@ jpeg_default_colorspace(j_compress_ptr cinfo) case JCS_EXT_BGRA: case JCS_EXT_ABGR: case JCS_EXT_ARGB: - jpeg_set_colorspace(cinfo, JCS_YCbCr); + if (cinfo->master->lossless) + jpeg_set_colorspace(cinfo, JCS_RGB); + else + jpeg_set_colorspace(cinfo, JCS_YCbCr); break; case JCS_YCbCr: jpeg_set_colorspace(cinfo, JCS_YCbCr); @@ -475,6 +479,11 @@ jpeg_simple_progression(j_compress_ptr cinfo) if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->master->lossless) { + cinfo->master->lossless = FALSE; + jpeg_default_colorspace(cinfo); + } + /* Figure space needed for script. Calculation must match code below! */ if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { /* Custom script for YCbCr color images. */ @@ -539,3 +548,38 @@ jpeg_simple_progression(j_compress_ptr cinfo) } #endif /* C_PROGRESSIVE_SUPPORTED */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* + * Enable lossless mode. + */ + +GLOBAL(void) +jpeg_enable_lossless(j_compress_ptr cinfo, int predictor_selection_value, + int point_transform) +{ + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + cinfo->master->lossless = TRUE; + cinfo->Ss = predictor_selection_value; + cinfo->Se = 0; + cinfo->Ah = 0; + cinfo->Al = point_transform; + + /* The JPEG spec simply gives the range 0..15 for Al (Pt), but that seems + * wrong: the upper bound ought to depend on data precision. Perhaps they + * really meant 0..N-1 for N-bit precision, which is what we allow here. + * Values greater than or equal to the data precision will result in a blank + * image. + */ + if (cinfo->Ss < 1 || cinfo->Ss > 7 || + cinfo->Al < 0 || cinfo->Al >= cinfo->data_precision) + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/3rdparty/libjpeg-turbo/src/jcphuff.c b/3rdparty/libjpeg-turbo/src/jcphuff.c index 872e570bff0b..484e2d857f05 100644 --- a/3rdparty/libjpeg-turbo/src/jcphuff.c +++ b/3rdparty/libjpeg-turbo/src/jcphuff.c @@ -3,9 +3,11 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1995-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2011, 2015, 2018, 2021-2022, D. R. Commander. - * Copyright (C) 2016, 2018, Matthieu Darbois. + * Copyright (C) 2011, 2015, 2018, 2021-2022, 2024, D. R. Commander. + * Copyright (C) 2016, 2018, 2022, Matthieu Darbois. * Copyright (C) 2020, Arm Limited. * Copyright (C) 2021, Alex Richardson. * For conditions of distribution and use, see the accompanying README.ijg @@ -21,8 +23,11 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#ifdef WITH_SIMD #include "jsimd.h" -#include "jconfigint.h" +#else +#include "jchuff.h" /* Declarations shared with jc*huff.c */ +#endif #include #ifdef HAVE_INTRIN_H @@ -39,40 +44,7 @@ #ifdef C_PROGRESSIVE_SUPPORTED -/* - * NOTE: If USE_CLZ_INTRINSIC is defined, then clz/bsr instructions will be - * used for bit counting rather than the lookup table. This will reduce the - * memory footprint by 64k, which is important for some mobile applications - * that create many isolated instances of libjpeg-turbo (web browsers, for - * instance.) This may improve performance on some mobile platforms as well. - * This feature is enabled by default only on Arm processors, because some x86 - * chips have a slow implementation of bsr, and the use of clz/bsr cannot be - * shown to have a significant performance impact even on the x86 chips that - * have a fast implementation of it. When building for Armv6, you can - * explicitly disable the use of clz/bsr by adding -mthumb to the compiler - * flags (this defines __thumb__). - */ - -/* NOTE: Both GCC and Clang define __GNUC__ */ -#if (defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))) || \ - defined(_M_ARM) || defined(_M_ARM64) -#if !defined(__thumb__) || defined(__thumb2__) -#define USE_CLZ_INTRINSIC -#endif -#endif - -#ifdef USE_CLZ_INTRINSIC -#if defined(_MSC_VER) && !defined(__clang__) -#define JPEG_NBITS_NONZERO(x) (32 - _CountLeadingZeros(x)) -#else -#define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x)) -#endif -#define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0) -#else -#include "jpeg_nbits_table.h" -#define JPEG_NBITS(x) (jpeg_nbits_table[x]) -#define JPEG_NBITS_NONZERO(x) JPEG_NBITS(x) -#endif +#include "jpeg_nbits.h" /* Expanded entropy encoder object for progressive Huffman encoding. */ @@ -83,11 +55,11 @@ typedef struct { /* Pointer to routine to prepare data for encode_mcu_AC_first() */ void (*AC_first_prepare) (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *values, size_t *zerobits); + int Al, UJCOEF *values, size_t *zerobits); /* Pointer to routine to prepare data for encode_mcu_AC_refine() */ int (*AC_refine_prepare) (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *absvalues, size_t *bits); + int Al, UJCOEF *absvalues, size_t *bits); /* Mode flag: TRUE for optimization, FALSE for actual data output */ boolean gather_statistics; @@ -157,14 +129,14 @@ METHODDEF(boolean) encode_mcu_DC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data); METHODDEF(void) encode_mcu_AC_first_prepare (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, - JCOEF *values, size_t *zerobits); + UJCOEF *values, size_t *zerobits); METHODDEF(boolean) encode_mcu_AC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data); METHODDEF(boolean) encode_mcu_DC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data); METHODDEF(int) encode_mcu_AC_refine_prepare (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, - JCOEF *absvalues, size_t *bits); + UJCOEF *absvalues, size_t *bits); METHODDEF(boolean) encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data); METHODDEF(void) finish_pass_phuff(j_compress_ptr cinfo); @@ -224,18 +196,22 @@ start_pass_phuff(j_compress_ptr cinfo, boolean gather_statistics) entropy->pub.encode_mcu = encode_mcu_DC_first; else entropy->pub.encode_mcu = encode_mcu_AC_first; +#ifdef WITH_SIMD if (jsimd_can_encode_mcu_AC_first_prepare()) entropy->AC_first_prepare = jsimd_encode_mcu_AC_first_prepare; else +#endif entropy->AC_first_prepare = encode_mcu_AC_first_prepare; } else { if (is_DC_band) entropy->pub.encode_mcu = encode_mcu_DC_refine; else { entropy->pub.encode_mcu = encode_mcu_AC_refine; +#ifdef WITH_SIMD if (jsimd_can_encode_mcu_AC_refine_prepare()) entropy->AC_refine_prepare = jsimd_encode_mcu_AC_refine_prepare; else +#endif entropy->AC_refine_prepare = encode_mcu_AC_refine_prepare; /* AC refinement needs a correction bit buffer */ if (entropy->bit_buffer == NULL) @@ -490,6 +466,7 @@ encode_mcu_DC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data) JBLOCKROW block; jpeg_component_info *compptr; ISHIFT_TEMPS + int max_coef_bits = cinfo->data_precision + 2; entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; @@ -532,7 +509,7 @@ encode_mcu_DC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* Check for out-of-range coefficient values. * Since we're encoding a difference, the range limit is twice as much. */ - if (nbits > MAX_COEF_BITS + 1) + if (nbits > max_coef_bits + 1) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count/emit the Huffman-coded symbol for the number of bits */ @@ -584,8 +561,8 @@ encode_mcu_DC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data) continue; \ /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ \ temp2 ^= temp; \ - values[k] = (JCOEF)temp; \ - values[k + DCTSIZE2] = (JCOEF)temp2; \ + values[k] = (UJCOEF)temp; \ + values[k + DCTSIZE2] = (UJCOEF)temp2; \ zerobits |= ((size_t)1U) << k; \ } \ } @@ -593,7 +570,7 @@ encode_mcu_DC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data) METHODDEF(void) encode_mcu_AC_first_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *values, size_t *bits) + int Al, UJCOEF *values, size_t *bits) { register int k, temp, temp2; size_t zerobits = 0U; @@ -643,7 +620,7 @@ label \ /* Find the number of bits needed for the magnitude of the coefficient */ \ nbits = JPEG_NBITS_NONZERO(temp); /* there must be at least one 1 bit */ \ /* Check for out-of-range coefficient values */ \ - if (nbits > MAX_COEF_BITS) \ + if (nbits > max_coef_bits) \ ERREXIT(cinfo, JERR_BAD_DCT_COEF); \ \ /* Count/emit Huffman symbol for run length / number of bits */ \ @@ -666,11 +643,12 @@ encode_mcu_AC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data) register int nbits, r; int Sl = cinfo->Se - cinfo->Ss + 1; int Al = cinfo->Al; - JCOEF values_unaligned[2 * DCTSIZE2 + 15]; - JCOEF *values; - const JCOEF *cvalue; + UJCOEF values_unaligned[2 * DCTSIZE2 + 15]; + UJCOEF *values; + const UJCOEF *cvalue; size_t zerobits; size_t bits[8 / SIZEOF_SIZE_T]; + int max_coef_bits = cinfo->data_precision + 2; entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; @@ -681,7 +659,7 @@ encode_mcu_AC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data) emit_restart(entropy, entropy->next_restart_num); #ifdef WITH_SIMD - cvalue = values = (JCOEF *)PAD((JUINTPTR)values_unaligned, 16); + cvalue = values = (UJCOEF *)PAD((JUINTPTR)values_unaligned, 16); #else /* Not using SIMD, so alignment is not needed */ cvalue = values = values_unaligned; @@ -815,7 +793,7 @@ encode_mcu_DC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data) zerobits |= ((size_t)1U) << k; \ signbits |= ((size_t)(temp2 + 1)) << k; \ } \ - absvalues[k] = (JCOEF)temp; /* save abs value for main pass */ \ + absvalues[k] = (UJCOEF)temp; /* save abs value for main pass */ \ if (temp == 1) \ EOB = k + koffset; /* EOB = index of last newly-nonzero coef */ \ } \ @@ -824,7 +802,7 @@ encode_mcu_DC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data) METHODDEF(int) encode_mcu_AC_refine_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *absvalues, size_t *bits) + int Al, UJCOEF *absvalues, size_t *bits) { register int k, temp, temp2; int EOB = 0; @@ -931,9 +909,9 @@ encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data) unsigned int BR; int Sl = cinfo->Se - cinfo->Ss + 1; int Al = cinfo->Al; - JCOEF absvalues_unaligned[DCTSIZE2 + 15]; - JCOEF *absvalues; - const JCOEF *cabsvalue, *EOBPTR; + UJCOEF absvalues_unaligned[DCTSIZE2 + 15]; + UJCOEF *absvalues; + const UJCOEF *cabsvalue, *EOBPTR; size_t zerobits, signbits; size_t bits[16 / SIZEOF_SIZE_T]; @@ -946,7 +924,7 @@ encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data) emit_restart(entropy, entropy->next_restart_num); #ifdef WITH_SIMD - cabsvalue = absvalues = (JCOEF *)PAD((JUINTPTR)absvalues_unaligned, 16); + cabsvalue = absvalues = (UJCOEF *)PAD((JUINTPTR)absvalues_unaligned, 16); #else /* Not using SIMD, so alignment is not needed */ cabsvalue = absvalues = absvalues_unaligned; diff --git a/3rdparty/libjpeg-turbo/src/jcprepct.c b/3rdparty/libjpeg-turbo/src/jcprepct.c index f27cc345079e..ac2311c1388e 100644 --- a/3rdparty/libjpeg-turbo/src/jcprepct.c +++ b/3rdparty/libjpeg-turbo/src/jcprepct.c @@ -1,8 +1,10 @@ /* * jcprepct.c * - * This file is part of the Independent JPEG Group's software: + * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg @@ -20,8 +22,11 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) + /* At present, jcsample.c can request context rows only for smoothing. * In the future, we might also need context rows for CCIR601 sampling * or other more-complex downsampling procedures. The code to support @@ -59,7 +64,7 @@ typedef struct { /* Downsampling input buffer. This buffer holds color-converted data * until we have enough to do a downsample step. */ - JSAMPARRAY color_buf[MAX_COMPONENTS]; + _JSAMPARRAY color_buf[MAX_COMPONENTS]; JDIMENSION rows_to_go; /* counts rows remaining in source image */ int next_buf_row; /* index of next row to store in color_buf */ @@ -106,14 +111,14 @@ start_pass_prep(j_compress_ptr cinfo, J_BUF_MODE pass_mode) */ LOCAL(void) -expand_bottom_edge(JSAMPARRAY image_data, JDIMENSION num_cols, int input_rows, +expand_bottom_edge(_JSAMPARRAY image_data, JDIMENSION num_cols, int input_rows, int output_rows) { register int row; for (row = input_rows; row < output_rows; row++) { - jcopy_sample_rows(image_data, input_rows - 1, image_data, row, 1, - num_cols); + _jcopy_sample_rows(image_data, input_rows - 1, image_data, row, 1, + num_cols); } } @@ -128,15 +133,16 @@ expand_bottom_edge(JSAMPARRAY image_data, JDIMENSION num_cols, int input_rows, */ METHODDEF(void) -pre_process_data(j_compress_ptr cinfo, JSAMPARRAY input_buf, +pre_process_data(j_compress_ptr cinfo, _JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + _JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail) { my_prep_ptr prep = (my_prep_ptr)cinfo->prep; int numrows, ci; JDIMENSION inrows; jpeg_component_info *compptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; while (*in_row_ctr < in_rows_avail && *out_row_group_ctr < out_row_groups_avail) { @@ -144,10 +150,10 @@ pre_process_data(j_compress_ptr cinfo, JSAMPARRAY input_buf, inrows = in_rows_avail - *in_row_ctr; numrows = cinfo->max_v_samp_factor - prep->next_buf_row; numrows = (int)MIN((JDIMENSION)numrows, inrows); - (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, - prep->color_buf, - (JDIMENSION)prep->next_buf_row, - numrows); + (*cinfo->cconvert->_color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION)prep->next_buf_row, + numrows); *in_row_ctr += numrows; prep->next_buf_row += numrows; prep->rows_to_go -= numrows; @@ -162,9 +168,9 @@ pre_process_data(j_compress_ptr cinfo, JSAMPARRAY input_buf, } /* If we've filled the conversion buffer, empty it. */ if (prep->next_buf_row == cinfo->max_v_samp_factor) { - (*cinfo->downsample->downsample) (cinfo, - prep->color_buf, (JDIMENSION)0, - output_buf, *out_row_group_ctr); + (*cinfo->downsample->_downsample) (cinfo, + prep->color_buf, (JDIMENSION)0, + output_buf, *out_row_group_ctr); prep->next_buf_row = 0; (*out_row_group_ctr)++; } @@ -174,7 +180,8 @@ pre_process_data(j_compress_ptr cinfo, JSAMPARRAY input_buf, if (prep->rows_to_go == 0 && *out_row_group_ctr < out_row_groups_avail) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - expand_bottom_edge(output_buf[ci], compptr->width_in_blocks * DCTSIZE, + expand_bottom_edge(output_buf[ci], + compptr->width_in_blocks * data_unit, (int)(*out_row_group_ctr * compptr->v_samp_factor), (int)(out_row_groups_avail * compptr->v_samp_factor)); } @@ -192,9 +199,9 @@ pre_process_data(j_compress_ptr cinfo, JSAMPARRAY input_buf, */ METHODDEF(void) -pre_process_context(j_compress_ptr cinfo, JSAMPARRAY input_buf, +pre_process_context(j_compress_ptr cinfo, _JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + _JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail) { my_prep_ptr prep = (my_prep_ptr)cinfo->prep; @@ -208,17 +215,17 @@ pre_process_context(j_compress_ptr cinfo, JSAMPARRAY input_buf, inrows = in_rows_avail - *in_row_ctr; numrows = prep->next_buf_stop - prep->next_buf_row; numrows = (int)MIN((JDIMENSION)numrows, inrows); - (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, - prep->color_buf, - (JDIMENSION)prep->next_buf_row, - numrows); + (*cinfo->cconvert->_color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION)prep->next_buf_row, + numrows); /* Pad at top of image, if first time through */ if (prep->rows_to_go == cinfo->image_height) { for (ci = 0; ci < cinfo->num_components; ci++) { int row; for (row = 1; row <= cinfo->max_v_samp_factor; row++) { - jcopy_sample_rows(prep->color_buf[ci], 0, prep->color_buf[ci], - -row, 1, cinfo->image_width); + _jcopy_sample_rows(prep->color_buf[ci], 0, prep->color_buf[ci], + -row, 1, cinfo->image_width); } } } @@ -240,9 +247,9 @@ pre_process_context(j_compress_ptr cinfo, JSAMPARRAY input_buf, } /* If we've gotten enough data, downsample a row group. */ if (prep->next_buf_row == prep->next_buf_stop) { - (*cinfo->downsample->downsample) (cinfo, prep->color_buf, - (JDIMENSION)prep->this_row_group, - output_buf, *out_row_group_ctr); + (*cinfo->downsample->_downsample) (cinfo, prep->color_buf, + (JDIMENSION)prep->this_row_group, + output_buf, *out_row_group_ctr); (*out_row_group_ctr)++; /* Advance pointers with wraparound as necessary. */ prep->this_row_group += cinfo->max_v_samp_factor; @@ -267,15 +274,16 @@ create_context_buffer(j_compress_ptr cinfo) int rgroup_height = cinfo->max_v_samp_factor; int ci, i; jpeg_component_info *compptr; - JSAMPARRAY true_buffer, fake_buffer; + _JSAMPARRAY true_buffer, fake_buffer; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; /* Grab enough space for fake row pointers for all the components; * we need five row groups' worth of pointers for each component. */ - fake_buffer = (JSAMPARRAY) + fake_buffer = (_JSAMPARRAY) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, (cinfo->num_components * 5 * rgroup_height) * - sizeof(JSAMPROW)); + sizeof(_JSAMPROW)); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { @@ -283,14 +291,14 @@ create_context_buffer(j_compress_ptr cinfo) * We make the buffer wide enough to allow the downsampler to edge-expand * horizontally within the buffer, if it so chooses. */ - true_buffer = (*cinfo->mem->alloc_sarray) + true_buffer = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (JDIMENSION)(((long)compptr->width_in_blocks * DCTSIZE * + (JDIMENSION)(((long)compptr->width_in_blocks * data_unit * cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION)(3 * rgroup_height)); /* Copy true buffer row pointers into the middle of the fake row array */ memcpy(fake_buffer + rgroup_height, true_buffer, - 3 * rgroup_height * sizeof(JSAMPROW)); + 3 * rgroup_height * sizeof(_JSAMPROW)); /* Fill in the above and below wraparound pointers */ for (i = 0; i < rgroup_height; i++) { fake_buffer[i] = true_buffer[2 * rgroup_height + i]; @@ -309,11 +317,15 @@ create_context_buffer(j_compress_ptr cinfo) */ GLOBAL(void) -jinit_c_prep_controller(j_compress_ptr cinfo, boolean need_full_buffer) +_jinit_c_prep_controller(j_compress_ptr cinfo, boolean need_full_buffer) { my_prep_ptr prep; int ci; jpeg_component_info *compptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); if (need_full_buffer) /* safety check */ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); @@ -331,21 +343,23 @@ jinit_c_prep_controller(j_compress_ptr cinfo, boolean need_full_buffer) if (cinfo->downsample->need_context_rows) { /* Set up to provide context rows */ #ifdef CONTEXT_ROWS_SUPPORTED - prep->pub.pre_process_data = pre_process_context; + prep->pub._pre_process_data = pre_process_context; create_context_buffer(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { /* No context, just make it tall enough for one row group */ - prep->pub.pre_process_data = pre_process_data; + prep->pub._pre_process_data = pre_process_data; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) + prep->color_buf[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (JDIMENSION)(((long)compptr->width_in_blocks * DCTSIZE * + (JDIMENSION)(((long)compptr->width_in_blocks * data_unit * cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION)cinfo->max_v_samp_factor); } } } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) */ diff --git a/3rdparty/libjpeg-turbo/src/jcsample.c b/3rdparty/libjpeg-turbo/src/jcsample.c index e8515ebf0fce..30e6e54b4058 100644 --- a/3rdparty/libjpeg-turbo/src/jcsample.c +++ b/3rdparty/libjpeg-turbo/src/jcsample.c @@ -3,10 +3,12 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman for Cendio AB * Copyright (C) 2014, MIPS Technologies, Inc., California. - * Copyright (C) 2015, 2019, D. R. Commander. + * Copyright (C) 2015, 2019, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -54,13 +56,16 @@ #include "jinclude.h" #include "jpeglib.h" #include "jsimd.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) + /* Pointer to routine to downsample a single component */ typedef void (*downsample1_ptr) (j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, - JSAMPARRAY output_data); + _JSAMPARRAY input_data, + _JSAMPARRAY output_data); /* Private subobject */ @@ -91,11 +96,11 @@ start_pass_downsample(j_compress_ptr cinfo) */ LOCAL(void) -expand_right_edge(JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols, +expand_right_edge(_JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols, JDIMENSION output_cols) { - register JSAMPROW ptr; - register JSAMPLE pixval; + register _JSAMPROW ptr; + register _JSAMPLE pixval; register int count; int row; int numcols = (int)(output_cols - input_cols); @@ -118,14 +123,14 @@ expand_right_edge(JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols, */ METHODDEF(void) -sep_downsample(j_compress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_index, JSAMPIMAGE output_buf, +sep_downsample(j_compress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_index, _JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) { my_downsample_ptr downsample = (my_downsample_ptr)cinfo->downsample; int ci; jpeg_component_info *compptr; - JSAMPARRAY in_ptr, out_ptr; + _JSAMPARRAY in_ptr, out_ptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { @@ -145,12 +150,13 @@ sep_downsample(j_compress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) int_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + _JSAMPARRAY input_data, _JSAMPARRAY output_data) { int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - JSAMPROW inptr, outptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * data_unit; + _JSAMPROW inptr, outptr; JLONG outvalue; h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; @@ -177,7 +183,7 @@ int_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, outvalue += (JLONG)(*inptr++); } } - *outptr++ = (JSAMPLE)((outvalue + numpix2) / numpix); + *outptr++ = (_JSAMPLE)((outvalue + numpix2) / numpix); } inrow += v_expand; } @@ -192,14 +198,16 @@ int_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) fullsize_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + _JSAMPARRAY input_data, _JSAMPARRAY output_data) { + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + /* Copy the data */ - jcopy_sample_rows(input_data, 0, output_data, 0, cinfo->max_v_samp_factor, - cinfo->image_width); + _jcopy_sample_rows(input_data, 0, output_data, 0, cinfo->max_v_samp_factor, + cinfo->image_width); /* Edge-expand */ expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width, - compptr->width_in_blocks * DCTSIZE); + compptr->width_in_blocks * data_unit); } @@ -217,12 +225,13 @@ fullsize_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + _JSAMPARRAY input_data, _JSAMPARRAY output_data) { int outrow; JDIMENSION outcol; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr, outptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * data_unit; + register _JSAMPROW inptr, outptr; register int bias; /* Expand input data enough to let all the output samples be generated @@ -237,7 +246,7 @@ h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, inptr = input_data[outrow]; bias = 0; /* bias = 0,1,0,1,... for successive samples */ for (outcol = 0; outcol < output_cols; outcol++) { - *outptr++ = (JSAMPLE)((inptr[0] + inptr[1] + bias) >> 1); + *outptr++ = (_JSAMPLE)((inptr[0] + inptr[1] + bias) >> 1); bias ^= 1; /* 0=>1, 1=>0 */ inptr += 2; } @@ -253,12 +262,13 @@ h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + _JSAMPARRAY input_data, _JSAMPARRAY output_data) { int inrow, outrow; JDIMENSION outcol; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr0, inptr1, outptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * data_unit; + register _JSAMPROW inptr0, inptr1, outptr; register int bias; /* Expand input data enough to let all the output samples be generated @@ -275,8 +285,8 @@ h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, inptr1 = input_data[inrow + 1]; bias = 1; /* bias = 1,2,1,2,... for successive samples */ for (outcol = 0; outcol < output_cols; outcol++) { - *outptr++ = - (JSAMPLE)((inptr0[0] + inptr0[1] + inptr1[0] + inptr1[1] + bias) >> 2); + *outptr++ = (_JSAMPLE) + ((inptr0[0] + inptr0[1] + inptr1[0] + inptr1[1] + bias) >> 2); bias ^= 3; /* 1=>2, 2=>1 */ inptr0 += 2; inptr1 += 2; } @@ -295,12 +305,13 @@ h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + _JSAMPARRAY input_data, _JSAMPARRAY output_data) { int inrow, outrow; JDIMENSION colctr; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * data_unit; + register _JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; JLONG membersum, neighsum, memberscale, neighscale; /* Expand input data enough to let all the output samples be generated @@ -341,7 +352,7 @@ h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, neighsum += neighsum; neighsum += above_ptr[0] + above_ptr[2] + below_ptr[0] + below_ptr[2]; membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE)((membersum + 32768) >> 16); + *outptr++ = (_JSAMPLE)((membersum + 32768) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; for (colctr = output_cols - 2; colctr > 0; colctr--) { @@ -357,7 +368,7 @@ h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, /* form final output scaled up by 2^16 */ membersum = membersum * memberscale + neighsum * neighscale; /* round, descale and output it */ - *outptr++ = (JSAMPLE)((membersum + 32768) >> 16); + *outptr++ = (_JSAMPLE)((membersum + 32768) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; } @@ -368,7 +379,7 @@ h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, neighsum += neighsum; neighsum += above_ptr[-1] + above_ptr[1] + below_ptr[-1] + below_ptr[1]; membersum = membersum * memberscale + neighsum * neighscale; - *outptr = (JSAMPLE)((membersum + 32768) >> 16); + *outptr = (_JSAMPLE)((membersum + 32768) >> 16); inrow += 2; } @@ -383,12 +394,13 @@ h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + _JSAMPARRAY input_data, _JSAMPARRAY output_data) { int outrow; JDIMENSION colctr; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr, above_ptr, below_ptr, outptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * data_unit; + register _JSAMPROW inptr, above_ptr, below_ptr, outptr; JLONG membersum, neighsum, memberscale, neighscale; int colsum, lastcolsum, nextcolsum; @@ -420,7 +432,7 @@ fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, nextcolsum = above_ptr[0] + below_ptr[0] + inptr[0]; neighsum = colsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE)((membersum + 32768) >> 16); + *outptr++ = (_JSAMPLE)((membersum + 32768) >> 16); lastcolsum = colsum; colsum = nextcolsum; for (colctr = output_cols - 2; colctr > 0; colctr--) { @@ -429,7 +441,7 @@ fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, nextcolsum = above_ptr[0] + below_ptr[0] + inptr[0]; neighsum = lastcolsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE)((membersum + 32768) >> 16); + *outptr++ = (_JSAMPLE)((membersum + 32768) >> 16); lastcolsum = colsum; colsum = nextcolsum; } @@ -437,7 +449,7 @@ fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, membersum = *inptr; neighsum = lastcolsum + (colsum - membersum) + colsum; membersum = membersum * memberscale + neighsum * neighscale; - *outptr = (JSAMPLE)((membersum + 32768) >> 16); + *outptr = (_JSAMPLE)((membersum + 32768) >> 16); } } @@ -451,19 +463,22 @@ fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jinit_downsampler(j_compress_ptr cinfo) +_jinit_downsampler(j_compress_ptr cinfo) { my_downsample_ptr downsample; int ci; jpeg_component_info *compptr; boolean smoothok = TRUE; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + downsample = (my_downsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_downsampler)); cinfo->downsample = (struct jpeg_downsampler *)downsample; downsample->pub.start_pass = start_pass_downsample; - downsample->pub.downsample = sep_downsample; + downsample->pub._downsample = sep_downsample; downsample->pub.need_context_rows = FALSE; if (cinfo->CCIR601_sampling) @@ -484,15 +499,17 @@ jinit_downsampler(j_compress_ptr cinfo) } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && compptr->v_samp_factor == cinfo->max_v_samp_factor) { smoothok = FALSE; +#ifdef WITH_SIMD if (jsimd_can_h2v1_downsample()) downsample->methods[ci] = jsimd_h2v1_downsample; else +#endif downsample->methods[ci] = h2v1_downsample; } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) { -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_can_h2v2_smooth_downsample()) downsample->methods[ci] = jsimd_h2v2_smooth_downsample; else @@ -502,9 +519,11 @@ jinit_downsampler(j_compress_ptr cinfo) } else #endif { +#ifdef WITH_SIMD if (jsimd_can_h2v2_downsample()) downsample->methods[ci] = jsimd_h2v2_downsample; else +#endif downsample->methods[ci] = h2v2_downsample; } } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && @@ -520,3 +539,5 @@ jinit_downsampler(j_compress_ptr cinfo) TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); #endif } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) */ diff --git a/3rdparty/libjpeg-turbo/src/jcstest.c b/3rdparty/libjpeg-turbo/src/jcstest.c new file mode 100644 index 000000000000..8b1fe38082b1 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/jcstest.c @@ -0,0 +1,126 @@ +/* + * Copyright (C)2011 D. R. Commander. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* This program demonstrates how to check for the colorspace extension + capabilities of libjpeg-turbo at both compile time and run time. */ + +#include +#include +#include +#include + +#ifndef JCS_EXTENSIONS +#define JCS_EXT_RGB 6 +#endif +#if !defined(JCS_EXTENSIONS) || !defined(JCS_ALPHA_EXTENSIONS) +#define JCS_EXT_RGBA 12 +#endif + +static char lasterror[JMSG_LENGTH_MAX] = "No error"; + +typedef struct _error_mgr { + struct jpeg_error_mgr pub; + jmp_buf jb; +} error_mgr; + +static void my_error_exit(j_common_ptr cinfo) +{ + error_mgr *myerr = (error_mgr *)cinfo->err; + (*cinfo->err->output_message) (cinfo); + longjmp(myerr->jb, 1); +} + +static void my_output_message(j_common_ptr cinfo) +{ + (*cinfo->err->format_message) (cinfo, lasterror); +} + +int main(void) +{ + int jcs_valid = -1, jcs_alpha_valid = -1; + struct jpeg_compress_struct cinfo; + error_mgr jerr; + + printf("libjpeg-turbo colorspace extensions:\n"); +#if JCS_EXTENSIONS + printf(" Present at compile time\n"); +#else + printf(" Not present at compile time\n"); +#endif + + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + jerr.pub.output_message = my_output_message; + + if (setjmp(jerr.jb)) { + /* this will execute if libjpeg has an error */ + jcs_valid = 0; + goto done; + } + + jpeg_create_compress(&cinfo); + cinfo.input_components = 3; + jpeg_set_defaults(&cinfo); + cinfo.in_color_space = JCS_EXT_RGB; + jpeg_default_colorspace(&cinfo); + jcs_valid = 1; + +done: + if (jcs_valid) + printf(" Working properly\n"); + else + printf(" Not working properly. Error returned was:\n %s\n", + lasterror); + + printf("libjpeg-turbo alpha colorspace extensions:\n"); +#if JCS_ALPHA_EXTENSIONS + printf(" Present at compile time\n"); +#else + printf(" Not present at compile time\n"); +#endif + + if (setjmp(jerr.jb)) { + /* this will execute if libjpeg has an error */ + jcs_alpha_valid = 0; + goto done2; + } + + cinfo.in_color_space = JCS_EXT_RGBA; + jpeg_default_colorspace(&cinfo); + jcs_alpha_valid = 1; + +done2: + if (jcs_alpha_valid) + printf(" Working properly\n"); + else + printf(" Not working properly. Error returned was:\n %s\n", + lasterror); + + jpeg_destroy_compress(&cinfo); + return 0; +} diff --git a/3rdparty/libjpeg-turbo/src/jctrans.c b/3rdparty/libjpeg-turbo/src/jctrans.c index e121028ec70d..ae52e3989ee0 100644 --- a/3rdparty/libjpeg-turbo/src/jctrans.c +++ b/3rdparty/libjpeg-turbo/src/jctrans.c @@ -17,7 +17,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" /* Forward declarations */ @@ -42,6 +42,9 @@ LOCAL(void) transencode_coef_controller(j_compress_ptr cinfo, GLOBAL(void) jpeg_write_coefficients(j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays) { + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_NOTIMPL); + if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Mark all tables to be written */ @@ -72,6 +75,9 @@ jpeg_copy_critical_parameters(j_decompress_ptr srcinfo, j_compress_ptr dstinfo) JQUANT_TBL *c_quant, *slot_quant; int tblno, ci, coefi; + if (srcinfo->master->lossless) + ERREXIT(dstinfo, JERR_NOTIMPL); + /* Safety check to ensure start_compress not called yet. */ if (dstinfo->global_state != CSTATE_START) ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); @@ -364,6 +370,13 @@ compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf) } +METHODDEF(boolean) +compress_output_12(j_compress_ptr cinfo, J12SAMPIMAGE input_buf) +{ + return compress_output(cinfo, (JSAMPIMAGE)input_buf); +} + + /* * Initialize coefficient buffer controller. * @@ -386,6 +399,7 @@ transencode_coef_controller(j_compress_ptr cinfo, cinfo->coef = (struct jpeg_c_coef_controller *)coef; coef->pub.start_pass = start_pass_coef; coef->pub.compress_data = compress_output; + coef->pub.compress_data_12 = compress_output_12; /* Save pointer to virtual arrays */ coef->whole_image = coef_arrays; diff --git a/3rdparty/libjpeg-turbo/src/jdapimin.c b/3rdparty/libjpeg-turbo/src/jdapimin.c index f50c27edc323..30d92841a8cb 100644 --- a/3rdparty/libjpeg-turbo/src/jdapimin.c +++ b/3rdparty/libjpeg-turbo/src/jdapimin.c @@ -3,8 +3,10 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1998, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2016, 2022, D. R. Commander. + * Copyright (C) 2016, 2022, 2024, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -23,7 +25,6 @@ #include "jinclude.h" #include "jpeglib.h" #include "jdmaster.h" -#include "jconfigint.h" /* @@ -83,6 +84,8 @@ jpeg_CreateDecompress(j_decompress_ptr cinfo, int version, size_t structsize) /* And initialize the overall input controller. */ jinit_input_controller(cinfo); + cinfo->data_precision = BITS_IN_JSAMPLE; + /* OK, I'm ready */ cinfo->global_state = DSTATE_START; @@ -157,13 +160,19 @@ default_decompress_parms(j_decompress_ptr cinfo) int cid1 = cinfo->comp_info[1].component_id; int cid2 = cinfo->comp_info[2].component_id; - if (cid0 == 1 && cid1 == 2 && cid2 == 3) - cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ - else if (cid0 == 82 && cid1 == 71 && cid2 == 66) + if (cid0 == 1 && cid1 == 2 && cid2 == 3) { + if (cinfo->master->lossless) + cinfo->jpeg_color_space = JCS_RGB; /* assume RGB w/out marker */ + else + cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ + } else if (cid0 == 82 && cid1 == 71 && cid2 == 66) cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ else { TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + if (cinfo->master->lossless) + cinfo->jpeg_color_space = JCS_RGB; /* assume it's RGB */ + else + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ } } /* Always guess RGB is proper output colorspace. */ diff --git a/3rdparty/libjpeg-turbo/src/jdapistd.c b/3rdparty/libjpeg-turbo/src/jdapistd.c index 8827d8abf5c5..1f4492723682 100644 --- a/3rdparty/libjpeg-turbo/src/jdapistd.c +++ b/3rdparty/libjpeg-turbo/src/jdapistd.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2010, 2015-2020, 2022, D. R. Commander. + * Copyright (C) 2010, 2015-2020, 2022-2023, D. R. Commander. * Copyright (C) 2015, Google, Inc. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -19,13 +19,20 @@ */ #include "jinclude.h" +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) #include "jdmainct.h" #include "jdcoefct.h" +#else +#define JPEG_INTERNALS +#include "jpeglib.h" +#endif #include "jdmaster.h" #include "jdmerge.h" #include "jdsample.h" #include "jmemsys.h" +#if BITS_IN_JSAMPLE == 8 + /* Forward declarations */ LOCAL(boolean) output_pass_setup(j_decompress_ptr cinfo); @@ -121,8 +128,20 @@ output_pass_setup(j_decompress_ptr cinfo) } /* Process some data */ last_scanline = cinfo->output_scanline; - (*cinfo->main->process_data) (cinfo, (JSAMPARRAY)NULL, - &cinfo->output_scanline, (JDIMENSION)0); +#ifdef D_LOSSLESS_SUPPORTED + if (cinfo->data_precision == 16) + (*cinfo->main->process_data_16) (cinfo, (J16SAMPARRAY)NULL, + &cinfo->output_scanline, + (JDIMENSION)0); + else +#endif + if (cinfo->data_precision == 12) + (*cinfo->main->process_data_12) (cinfo, (J12SAMPARRAY)NULL, + &cinfo->output_scanline, + (JDIMENSION)0); + else + (*cinfo->main->process_data) (cinfo, (JSAMPARRAY)NULL, + &cinfo->output_scanline, (JDIMENSION)0); if (cinfo->output_scanline == last_scanline) return FALSE; /* No progress made, must suspend */ } @@ -135,33 +154,46 @@ output_pass_setup(j_decompress_ptr cinfo) #endif /* QUANT_2PASS_SUPPORTED */ } /* Ready for application to drive output pass through - * jpeg_read_scanlines or jpeg_read_raw_data. + * _jpeg_read_scanlines or _jpeg_read_raw_data. */ cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; return TRUE; } +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE != 16 /* * Enable partial scanline decompression * * Must be called after jpeg_start_decompress() and before any calls to - * jpeg_read_scanlines() or jpeg_skip_scanlines(). + * _jpeg_read_scanlines() or _jpeg_skip_scanlines(). * * Refer to libjpeg.txt for more information. */ GLOBAL(void) -jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, - JDIMENSION *width) +_jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, + JDIMENSION *width) { int ci, align, orig_downsampled_width; JDIMENSION input_xoffset; boolean reinit_upsampler = FALSE; jpeg_component_info *compptr; +#ifdef UPSAMPLE_MERGING_SUPPORTED my_master_ptr master = (my_master_ptr)cinfo->master; +#endif + + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); - if (cinfo->global_state != DSTATE_SCANNING || cinfo->output_scanline != 0) + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_NOTIMPL); + + if ((cinfo->global_state != DSTATE_SCANNING && + cinfo->global_state != DSTATE_BUFIMAGE) || cinfo->output_scanline != 0) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (!xoffset || !width) @@ -209,11 +241,13 @@ jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, */ *width = *width + input_xoffset - *xoffset; cinfo->output_width = *width; +#ifdef UPSAMPLE_MERGING_SUPPORTED if (master->using_merged_upsample && cinfo->max_v_samp_factor == 2) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; } +#endif /* Set the first and last iMCU columns that we must decompress. These values * will be used in single-scan decompressions. @@ -231,9 +265,11 @@ jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, /* Set downsampled_width to the new output width. */ orig_downsampled_width = compptr->downsampled_width; compptr->downsampled_width = - (JDIMENSION)jdiv_round_up((long)(cinfo->output_width * - compptr->h_samp_factor), - (long)cinfo->max_h_samp_factor); + (JDIMENSION)jdiv_round_up((long)cinfo->output_width * + (long)(compptr->h_samp_factor * + compptr->_DCT_scaled_size), + (long)(cinfo->max_h_samp_factor * + cinfo->_min_DCT_scaled_size)); if (compptr->downsampled_width < 2 && orig_downsampled_width >= 2) reinit_upsampler = TRUE; @@ -249,11 +285,13 @@ jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, if (reinit_upsampler) { cinfo->master->jinit_upsampler_no_alloc = TRUE; - jinit_upsampler(cinfo); + _jinit_upsampler(cinfo); cinfo->master->jinit_upsampler_no_alloc = FALSE; } } +#endif /* BITS_IN_JSAMPLE != 16 */ + /* * Read some scanlines of data from the JPEG decompressor. @@ -263,17 +301,21 @@ jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, * including bottom of image, data source suspension, and operating * modes that emit multiple scanlines at a time. * - * Note: we warn about excess calls to jpeg_read_scanlines() since + * Note: we warn about excess calls to _jpeg_read_scanlines() since * this likely signals an application programmer error. However, * an oversize buffer (max_lines > scanlines remaining) is not an error. */ GLOBAL(JDIMENSION) -jpeg_read_scanlines(j_decompress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION max_lines) +_jpeg_read_scanlines(j_decompress_ptr cinfo, _JSAMPARRAY scanlines, + JDIMENSION max_lines) { +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) JDIMENSION row_ctr; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + if (cinfo->global_state != DSTATE_SCANNING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->output_scanline >= cinfo->output_height) { @@ -290,30 +332,36 @@ jpeg_read_scanlines(j_decompress_ptr cinfo, JSAMPARRAY scanlines, /* Process some data */ row_ctr = 0; - (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); + (*cinfo->main->_process_data) (cinfo, scanlines, &row_ctr, max_lines); cinfo->output_scanline += row_ctr; return row_ctr; +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + return 0; +#endif } -/* Dummy color convert function used by jpeg_skip_scanlines() */ +#if BITS_IN_JSAMPLE != 16 + +/* Dummy color convert function used by _jpeg_skip_scanlines() */ LOCAL(void) -noop_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +noop_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { } -/* Dummy quantize function used by jpeg_skip_scanlines() */ +/* Dummy quantize function used by _jpeg_skip_scanlines() */ LOCAL(void) -noop_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +noop_quantize(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) { } /* - * In some cases, it is best to call jpeg_read_scanlines() and discard the + * In some cases, it is best to call _jpeg_read_scanlines() and discard the * output, rather than skipping the scanlines, because this allows us to * maintain the internal state of the context-based upsampler. In these cases, * we set up and tear down a dummy color converter in order to avoid valgrind @@ -324,49 +372,53 @@ LOCAL(void) read_and_discard_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) { JDIMENSION n; +#ifdef UPSAMPLE_MERGING_SUPPORTED my_master_ptr master = (my_master_ptr)cinfo->master; - JSAMPLE dummy_sample[1] = { 0 }; - JSAMPROW dummy_row = dummy_sample; - JSAMPARRAY scanlines = NULL; - void (*color_convert) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +#endif + _JSAMPLE dummy_sample[1] = { 0 }; + _JSAMPROW dummy_row = dummy_sample; + _JSAMPARRAY scanlines = NULL; + void (*color_convert) (j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) = NULL; - void (*color_quantize) (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) = NULL; + void (*color_quantize) (j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) = NULL; - if (cinfo->cconvert && cinfo->cconvert->color_convert) { - color_convert = cinfo->cconvert->color_convert; - cinfo->cconvert->color_convert = noop_convert; + if (cinfo->cconvert && cinfo->cconvert->_color_convert) { + color_convert = cinfo->cconvert->_color_convert; + cinfo->cconvert->_color_convert = noop_convert; /* This just prevents UBSan from complaining about adding 0 to a NULL * pointer. The pointer isn't actually used. */ scanlines = &dummy_row; } - if (cinfo->cquantize && cinfo->cquantize->color_quantize) { - color_quantize = cinfo->cquantize->color_quantize; - cinfo->cquantize->color_quantize = noop_quantize; + if (cinfo->cquantize && cinfo->cquantize->_color_quantize) { + color_quantize = cinfo->cquantize->_color_quantize; + cinfo->cquantize->_color_quantize = noop_quantize; } +#ifdef UPSAMPLE_MERGING_SUPPORTED if (master->using_merged_upsample && cinfo->max_v_samp_factor == 2) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; scanlines = &upsample->spare_row; } +#endif for (n = 0; n < num_lines; n++) - jpeg_read_scanlines(cinfo, scanlines, 1); + _jpeg_read_scanlines(cinfo, scanlines, 1); if (color_convert) - cinfo->cconvert->color_convert = color_convert; + cinfo->cconvert->_color_convert = color_convert; if (color_quantize) - cinfo->cquantize->color_quantize = color_quantize; + cinfo->cquantize->_color_quantize = color_quantize; } /* - * Called by jpeg_skip_scanlines(). This partially skips a decompress block by - * incrementing the rowgroup counter. + * Called by _jpeg_skip_scanlines(). This partially skips a decompress block + * by incrementing the rowgroup counter. */ LOCAL(void) @@ -405,7 +457,7 @@ increment_simple_rowgroup_ctr(j_decompress_ptr cinfo, JDIMENSION rows) */ GLOBAL(JDIMENSION) -jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) +_jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) { my_main_ptr main_ptr = (my_main_ptr)cinfo->main; my_coef_ptr coef = (my_coef_ptr)cinfo->coef; @@ -416,6 +468,12 @@ jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) JDIMENSION lines_per_iMCU_row, lines_left_in_iMCU_row, lines_after_iMCU_row; JDIMENSION lines_to_skip, lines_to_read; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_NOTIMPL); + /* Two-pass color quantization is not supported. */ if (cinfo->quantize_colors && cinfo->two_pass_quantize) ERREXIT(cinfo, JERR_NOTIMPL); @@ -517,7 +575,7 @@ jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) * all of the entropy decoding occurs in jpeg_start_decompress(), assuming * that the input data source is non-suspending. This makes skipping easy. */ - if (cinfo->inputctl->has_multiple_scans) { + if (cinfo->inputctl->has_multiple_scans || cinfo->buffered_image) { if (cinfo->upsample->need_context_rows) { cinfo->output_scanline += lines_to_skip; cinfo->output_iMCU_row += lines_to_skip / lines_per_iMCU_row; @@ -588,11 +646,17 @@ jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) */ GLOBAL(JDIMENSION) -jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data, - JDIMENSION max_lines) +_jpeg_read_raw_data(j_decompress_ptr cinfo, _JSAMPIMAGE data, + JDIMENSION max_lines) { JDIMENSION lines_per_iMCU_row; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_NOTIMPL); + if (cinfo->global_state != DSTATE_RAW_OK) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->output_scanline >= cinfo->output_height) { @@ -613,7 +677,7 @@ jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data, ERREXIT(cinfo, JERR_BUFFER_SIZE); /* Decompress directly into user's buffer. */ - if (!(*cinfo->coef->decompress_data) (cinfo, data)) + if (!(*cinfo->coef->_decompress_data) (cinfo, data)) return 0; /* suspension forced, can do nothing more */ /* OK, we processed one iMCU row. */ @@ -621,6 +685,10 @@ jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data, return lines_per_iMCU_row; } +#endif /* BITS_IN_JSAMPLE != 16 */ + + +#if BITS_IN_JSAMPLE == 8 /* Additional entry points for buffered-image mode. */ @@ -678,3 +746,5 @@ jpeg_finish_output(j_decompress_ptr cinfo) } #endif /* D_MULTISCAN_FILES_SUPPORTED */ + +#endif /* BITS_IN_JSAMPLE == 8 */ diff --git a/3rdparty/libjpeg-turbo/src/jdatadst-tj.c b/3rdparty/libjpeg-turbo/src/jdatadst-tj.c new file mode 100644 index 000000000000..cce263af747a --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/jdatadst-tj.c @@ -0,0 +1,198 @@ +/* + * jdatadst-tj.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009-2012 by Guido Vollbeding. + * libjpeg-turbo Modifications: + * Copyright (C) 2011, 2014, 2016, 2019, 2022-2023, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains compression data destination routines for the case of + * emitting JPEG data to memory or to a file (or any stdio stream). + * While these routines are sufficient for most applications, + * some will want to use a different destination manager. + * IMPORTANT: we assume that fwrite() will correctly transcribe an array of + * JOCTETs into 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + +void jpeg_mem_dest_tj(j_compress_ptr cinfo, unsigned char **outbuffer, + size_t *outsize, boolean alloc); + + +#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ + + +/* Expanded data destination object for memory output */ + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + unsigned char **outbuffer; /* target buffer */ + size_t *outsize; + unsigned char *newbuffer; /* newly allocated buffer */ + JOCTET *buffer; /* start of buffer */ + size_t bufsize; + boolean alloc; +} my_mem_destination_mgr; + +typedef my_mem_destination_mgr *my_mem_dest_ptr; + + +/* + * Initialize destination --- called by jpeg_start_compress + * before any data is actually written. + */ + +METHODDEF(void) +init_mem_destination(j_compress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Empty the output buffer --- called whenever buffer fills up. + * + * In typical applications, this should write the entire output buffer + * (ignoring the current state of next_output_byte & free_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been dumped. + * + * In applications that need to be able to suspend compression due to output + * overrun, a FALSE return indicates that the buffer cannot be emptied now. + * In this situation, the compressor will return to its caller (possibly with + * an indication that it has not accepted all the supplied scanlines). The + * application should resume compression after it has made more room in the + * output buffer. Note that there are substantial restrictions on the use of + * suspension --- see the documentation. + * + * When suspending, the compressor will back up to a convenient restart point + * (typically the start of the current MCU). next_output_byte & free_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point will be regenerated after resumption, so do not + * write it out when emptying the buffer externally. + */ + +METHODDEF(boolean) +empty_mem_output_buffer(j_compress_ptr cinfo) +{ + size_t nextsize; + JOCTET *nextbuffer; + my_mem_dest_ptr dest = (my_mem_dest_ptr)cinfo->dest; + + if (!dest->alloc) ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Try to allocate new buffer with double size */ + nextsize = dest->bufsize * 2; + nextbuffer = (JOCTET *)malloc(nextsize); + + if (nextbuffer == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); + + memcpy(nextbuffer, dest->buffer, dest->bufsize); + + free(dest->newbuffer); + + dest->newbuffer = nextbuffer; + + dest->pub.next_output_byte = nextbuffer + dest->bufsize; + dest->pub.free_in_buffer = dest->bufsize; + + dest->buffer = nextbuffer; + dest->bufsize = nextsize; + + return TRUE; +} + + +/* + * Terminate destination --- called by jpeg_finish_compress + * after all data has been written. Usually needs to flush buffer. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_mem_destination(j_compress_ptr cinfo) +{ + my_mem_dest_ptr dest = (my_mem_dest_ptr)cinfo->dest; + + if (dest->alloc) *dest->outbuffer = dest->buffer; + *dest->outsize = dest->bufsize - dest->pub.free_in_buffer; +} + + +/* + * Prepare for output to a memory buffer. + * The caller may supply an own initial buffer with appropriate size. + * Otherwise, or when the actual data output exceeds the given size, + * the library adapts the buffer size as necessary. + * The standard library functions malloc/free are used for allocating + * larger memory, so the buffer is available to the application after + * finishing compression, and then the application is responsible for + * freeing the requested memory. + */ + +GLOBAL(void) +jpeg_mem_dest_tj(j_compress_ptr cinfo, unsigned char **outbuffer, + size_t *outsize, boolean alloc) +{ + boolean reused = FALSE; + my_mem_dest_ptr dest; + + if (outbuffer == NULL || outsize == NULL) /* sanity check */ + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same buffer without re-executing jpeg_mem_dest. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT, + sizeof(my_mem_destination_mgr)); + dest = (my_mem_dest_ptr)cinfo->dest; + dest->newbuffer = NULL; + dest->buffer = NULL; + } else if (cinfo->dest->init_destination != init_mem_destination) { + /* It is unsafe to reuse the existing destination manager unless it was + * created by this function. + */ + ERREXIT(cinfo, JERR_BUFFER_SIZE); + } + + dest = (my_mem_dest_ptr)cinfo->dest; + dest->pub.init_destination = init_mem_destination; + dest->pub.empty_output_buffer = empty_mem_output_buffer; + dest->pub.term_destination = term_mem_destination; + if (dest->buffer == *outbuffer && *outbuffer != NULL && alloc) + reused = TRUE; + dest->outbuffer = outbuffer; + dest->outsize = outsize; + dest->alloc = alloc; + + if (*outbuffer == NULL || *outsize == 0) { + if (alloc) { + /* Allocate initial buffer */ + dest->newbuffer = *outbuffer = (unsigned char *)malloc(OUTPUT_BUF_SIZE); + if (dest->newbuffer == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); + *outsize = OUTPUT_BUF_SIZE; + } else + ERREXIT(cinfo, JERR_BUFFER_SIZE); + } + + dest->pub.next_output_byte = dest->buffer = *outbuffer; + if (!reused) + dest->bufsize = *outsize; + dest->pub.free_in_buffer = dest->bufsize; +} diff --git a/3rdparty/libjpeg-turbo/src/jdatadst.c b/3rdparty/libjpeg-turbo/src/jdatadst.c index 6b4fed233971..529f93b49045 100644 --- a/3rdparty/libjpeg-turbo/src/jdatadst.c +++ b/3rdparty/libjpeg-turbo/src/jdatadst.c @@ -38,7 +38,6 @@ typedef my_destination_mgr *my_dest_ptr; #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) /* Expanded data destination object for memory output */ typedef struct { @@ -52,7 +51,6 @@ typedef struct { } my_mem_destination_mgr; typedef my_mem_destination_mgr *my_mem_dest_ptr; -#endif /* @@ -74,13 +72,11 @@ init_destination(j_compress_ptr cinfo) dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) METHODDEF(void) init_mem_destination(j_compress_ptr cinfo) { /* no work necessary here */ } -#endif /* @@ -121,7 +117,6 @@ empty_output_buffer(j_compress_ptr cinfo) return TRUE; } -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) METHODDEF(boolean) empty_mem_output_buffer(j_compress_ptr cinfo) { @@ -150,7 +145,6 @@ empty_mem_output_buffer(j_compress_ptr cinfo) return TRUE; } -#endif /* @@ -179,7 +173,6 @@ term_destination(j_compress_ptr cinfo) ERREXIT(cinfo, JERR_FILE_WRITE); } -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) METHODDEF(void) term_mem_destination(j_compress_ptr cinfo) { @@ -188,7 +181,6 @@ term_mem_destination(j_compress_ptr cinfo) *dest->outbuffer = dest->buffer; *dest->outsize = (unsigned long)(dest->bufsize - dest->pub.free_in_buffer); } -#endif /* @@ -227,7 +219,6 @@ jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile) } -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) /* * Prepare for output to a memory buffer. * The caller may supply an own initial buffer with appropriate size. @@ -284,4 +275,3 @@ jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer, dest->pub.next_output_byte = dest->buffer = *outbuffer; dest->pub.free_in_buffer = dest->bufsize = *outsize; } -#endif diff --git a/3rdparty/libjpeg-turbo/src/jdatasrc-tj.c b/3rdparty/libjpeg-turbo/src/jdatasrc-tj.c new file mode 100644 index 000000000000..a5970b53fe8f --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/jdatasrc-tj.c @@ -0,0 +1,194 @@ +/* + * jdatasrc-tj.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009-2011 by Guido Vollbeding. + * libjpeg-turbo Modifications: + * Copyright (C) 2011, 2016, 2019, 2023, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains decompression data source routines for the case of + * reading JPEG data from memory or from a file (or any stdio stream). + * While these routines are sufficient for most applications, + * some will want to use a different source manager. + * IMPORTANT: we assume that fread() will correctly transcribe an array of + * JOCTETs from 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + +void jpeg_mem_src_tj(j_decompress_ptr cinfo, const unsigned char *inbuffer, + size_t insize); + + +/* + * Initialize source --- called by jpeg_read_header + * before any data is actually read. + */ + +METHODDEF(void) +init_mem_source(j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Fill the input buffer --- called whenever buffer is emptied. + * + * In typical applications, this should read fresh data into the buffer + * (ignoring the current state of next_input_byte & bytes_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been reloaded. It is not necessary to + * fill the buffer entirely, only to obtain at least one more byte. + * + * There is no such thing as an EOF return. If the end of the file has been + * reached, the routine has a choice of ERREXIT() or inserting fake data into + * the buffer. In most cases, generating a warning message and inserting a + * fake EOI marker is the best course of action --- this will allow the + * decompressor to output however much of the image is there. However, + * the resulting error message is misleading if the real problem is an empty + * input file, so we handle that case specially. + * + * In applications that need to be able to suspend compression due to input + * not being available yet, a FALSE return indicates that no more data can be + * obtained right now, but more may be forthcoming later. In this situation, + * the decompressor will return to its caller (with an indication of the + * number of scanlines it has read, if any). The application should resume + * decompression after it has loaded more data into the input buffer. Note + * that there are substantial restrictions on the use of suspension --- see + * the documentation. + * + * When suspending, the decompressor will back up to a convenient restart point + * (typically the start of the current MCU). next_input_byte & bytes_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point must be rescanned after resumption, so move it to + * the front of the buffer rather than discarding it. + */ + +METHODDEF(boolean) +fill_mem_input_buffer(j_decompress_ptr cinfo) +{ + static const JOCTET mybuffer[4] = { + (JOCTET)0xFF, (JOCTET)JPEG_EOI, 0, 0 + }; + + /* The whole JPEG data is expected to reside in the supplied memory + * buffer, so any request for more data beyond the given buffer size + * is treated as an error. + */ + WARNMS(cinfo, JWRN_JPEG_EOF); + + /* Insert a fake EOI marker */ + + cinfo->src->next_input_byte = mybuffer; + cinfo->src->bytes_in_buffer = 2; + + return TRUE; +} + + +/* + * Skip data --- used to skip over a potentially large amount of + * uninteresting data (such as an APPn marker). + * + * Writers of suspendable-input applications must note that skip_input_data + * is not granted the right to give a suspension return. If the skip extends + * beyond the data currently in the buffer, the buffer can be marked empty so + * that the next read will cause a fill_input_buffer call that can suspend. + * Arranging for additional bytes to be discarded before reloading the input + * buffer is the application writer's problem. + */ + +METHODDEF(void) +skip_input_data(j_decompress_ptr cinfo, long num_bytes) +{ + struct jpeg_source_mgr *src = cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long)src->bytes_in_buffer) { + num_bytes -= (long)src->bytes_in_buffer; + (void)(*src->fill_input_buffer) (cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->next_input_byte += (size_t)num_bytes; + src->bytes_in_buffer -= (size_t)num_bytes; + } +} + + +/* + * An additional method that can be provided by data source modules is the + * resync_to_restart method for error recovery in the presence of RST markers. + * For the moment, this source module just uses the default resync method + * provided by the JPEG library. That method assumes that no backtracking + * is possible. + */ + + +/* + * Terminate source --- called by jpeg_finish_decompress + * after all data has been read. Often a no-op. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_source(j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Prepare for input from a supplied memory buffer. + * The buffer must contain the whole JPEG data. + */ + +GLOBAL(void) +jpeg_mem_src_tj(j_decompress_ptr cinfo, const unsigned char *inbuffer, + size_t insize) +{ + struct jpeg_source_mgr *src; + + if (inbuffer == NULL || insize == 0) /* Treat empty input as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + + /* The source object is made permanent so that a series of JPEG images + * can be read from the same buffer by calling jpeg_mem_src only before + * the first one. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT, + sizeof(struct jpeg_source_mgr)); + } else if (cinfo->src->init_source != init_mem_source) { + /* It is unsafe to reuse the existing source manager unless it was created + * by this function. + */ + ERREXIT(cinfo, JERR_BUFFER_SIZE); + } + + src = cinfo->src; + src->init_source = init_mem_source; + src->fill_input_buffer = fill_mem_input_buffer; + src->skip_input_data = skip_input_data; + src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->term_source = term_source; + src->bytes_in_buffer = insize; + src->next_input_byte = (const JOCTET *)inbuffer; +} diff --git a/3rdparty/libjpeg-turbo/src/jdatasrc.c b/3rdparty/libjpeg-turbo/src/jdatasrc.c index e36a30d89449..dc135f43a470 100644 --- a/3rdparty/libjpeg-turbo/src/jdatasrc.c +++ b/3rdparty/libjpeg-turbo/src/jdatasrc.c @@ -56,13 +56,11 @@ init_source(j_decompress_ptr cinfo) src->start_of_file = TRUE; } -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) METHODDEF(void) init_mem_source(j_decompress_ptr cinfo) { /* no work necessary here */ } -#endif /* @@ -123,7 +121,6 @@ fill_input_buffer(j_decompress_ptr cinfo) return TRUE; } -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) METHODDEF(boolean) fill_mem_input_buffer(j_decompress_ptr cinfo) { @@ -144,7 +141,6 @@ fill_mem_input_buffer(j_decompress_ptr cinfo) return TRUE; } -#endif /* @@ -253,7 +249,6 @@ jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile) } -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) /* * Prepare for input from a supplied memory buffer. * The buffer must contain the whole JPEG data. @@ -292,4 +287,3 @@ jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *inbuffer, src->bytes_in_buffer = (size_t)insize; src->next_input_byte = (const JOCTET *)inbuffer; } -#endif diff --git a/3rdparty/libjpeg-turbo/src/jdcoefct.c b/3rdparty/libjpeg-turbo/src/jdcoefct.c index 15e6cded628e..40ce27259ba1 100644 --- a/3rdparty/libjpeg-turbo/src/jdcoefct.c +++ b/3rdparty/libjpeg-turbo/src/jdcoefct.c @@ -5,13 +5,13 @@ * Copyright (C) 1994-1997, Thomas G. Lane. * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2010, 2015-2016, 2019-2020, D. R. Commander. + * Copyright (C) 2010, 2015-2016, 2019-2020, 2022-2023, D. R. Commander. * Copyright (C) 2015, 2020, Google, Inc. * For conditions of distribution and use, see the accompanying README.ijg * file. * * This file contains the coefficient buffer controller for decompression. - * This controller is the top level of the JPEG decompressor proper. + * This controller is the top level of the lossy JPEG decompressor proper. * The coefficient buffer lies between entropy decoding and inverse-DCT steps. * * In buffered-image mode, this controller is the interface between @@ -21,19 +21,20 @@ #include "jinclude.h" #include "jdcoefct.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" +#include "jsamplecomp.h" /* Forward declarations */ METHODDEF(int) decompress_onepass(j_decompress_ptr cinfo, - JSAMPIMAGE output_buf); + _JSAMPIMAGE output_buf); #ifdef D_MULTISCAN_FILES_SUPPORTED -METHODDEF(int) decompress_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf); +METHODDEF(int) decompress_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf); #endif #ifdef BLOCK_SMOOTHING_SUPPORTED LOCAL(boolean) smoothing_ok(j_decompress_ptr cinfo); METHODDEF(int) decompress_smooth_data(j_decompress_ptr cinfo, - JSAMPIMAGE output_buf); + _JSAMPIMAGE output_buf); #endif @@ -62,9 +63,9 @@ start_output_pass(j_decompress_ptr cinfo) /* If multipass, check to see whether to use block smoothing on this pass */ if (coef->pub.coef_arrays != NULL) { if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) - coef->pub.decompress_data = decompress_smooth_data; + coef->pub._decompress_data = decompress_smooth_data; else - coef->pub.decompress_data = decompress_data; + coef->pub._decompress_data = decompress_data; } #endif cinfo->output_iMCU_row = 0; @@ -82,17 +83,17 @@ start_output_pass(j_decompress_ptr cinfo) */ METHODDEF(int) -decompress_onepass(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +decompress_onepass(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf) { my_coef_ptr coef = (my_coef_ptr)cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int blkn, ci, xindex, yindex, yoffset, useful_width; - JSAMPARRAY output_ptr; + _JSAMPARRAY output_ptr; JDIMENSION start_col, output_col; jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; + _inverse_DCT_method_ptr inverse_DCT; /* Loop to process as much as one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; @@ -129,7 +130,7 @@ decompress_onepass(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) blkn += compptr->MCU_blocks; continue; } - inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; + inverse_DCT = cinfo->idct->_inverse_DCT[compptr->component_index]; useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; output_ptr = output_buf[compptr->component_index] + @@ -262,7 +263,7 @@ consume_data(j_decompress_ptr cinfo) */ METHODDEF(int) -decompress_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +decompress_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf) { my_coef_ptr coef = (my_coef_ptr)cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; @@ -270,10 +271,10 @@ decompress_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) int ci, block_row, block_rows; JBLOCKARRAY buffer; JBLOCKROW buffer_ptr; - JSAMPARRAY output_ptr; + _JSAMPARRAY output_ptr; JDIMENSION output_col; jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; + _inverse_DCT_method_ptr inverse_DCT; /* Force some input to be done if we are getting ahead of the input. */ while (cinfo->input_scan_number < cinfo->output_scan_number || @@ -302,7 +303,7 @@ decompress_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) block_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; } - inverse_DCT = cinfo->idct->inverse_DCT[ci]; + inverse_DCT = cinfo->idct->_inverse_DCT[ci]; output_ptr = output_buf[ci]; /* Loop over all DCT blocks to be processed. */ for (block_row = 0; block_row < block_rows; block_row++) { @@ -425,19 +426,20 @@ smoothing_ok(j_decompress_ptr cinfo) */ METHODDEF(int) -decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +decompress_smooth_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf) { my_coef_ptr coef = (my_coef_ptr)cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; JDIMENSION block_num, last_block_column; - int ci, block_row, block_rows, access_rows; + int ci, block_row, block_rows, access_rows, image_block_row, + image_block_rows; JBLOCKARRAY buffer; JBLOCKROW buffer_ptr, prev_prev_block_row, prev_block_row; JBLOCKROW next_block_row, next_next_block_row; - JSAMPARRAY output_ptr; + _JSAMPARRAY output_ptr; JDIMENSION output_col; jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; + _inverse_DCT_method_ptr inverse_DCT; boolean change_dc; JCOEF *workspace; int *coef_bits; @@ -475,7 +477,7 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) if (!compptr->component_needed) continue; /* Count non-dummy DCT block rows in this iMCU row. */ - if (cinfo->output_iMCU_row < last_iMCU_row - 1) { + if (cinfo->output_iMCU_row + 1 < last_iMCU_row) { block_rows = compptr->v_samp_factor; access_rows = block_rows * 3; /* this and next two iMCU rows */ } else if (cinfo->output_iMCU_row < last_iMCU_row) { @@ -496,6 +498,7 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) (JDIMENSION)access_rows, FALSE); buffer += 2 * compptr->v_samp_factor; /* point to current iMCU row */ } else if (cinfo->output_iMCU_row > 0) { + access_rows += compptr->v_samp_factor; /* prior iMCU row too */ buffer = (*cinfo->mem->access_virt_barray) ((j_common_ptr)cinfo, coef->whole_image[ci], (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, @@ -535,32 +538,33 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) Q21 = quanttbl->quantval[Q21_POS]; Q30 = quanttbl->quantval[Q30_POS]; } - inverse_DCT = cinfo->idct->inverse_DCT[ci]; + inverse_DCT = cinfo->idct->_inverse_DCT[ci]; output_ptr = output_buf[ci]; /* Loop over all DCT blocks to be processed. */ + image_block_rows = block_rows * cinfo->total_iMCU_rows; for (block_row = 0; block_row < block_rows; block_row++) { + image_block_row = cinfo->output_iMCU_row * block_rows + block_row; buffer_ptr = buffer[block_row] + cinfo->master->first_MCU_col[ci]; - if (block_row > 0 || cinfo->output_iMCU_row > 0) + if (image_block_row > 0) prev_block_row = buffer[block_row - 1] + cinfo->master->first_MCU_col[ci]; else prev_block_row = buffer_ptr; - if (block_row > 1 || cinfo->output_iMCU_row > 1) + if (image_block_row > 1) prev_prev_block_row = buffer[block_row - 2] + cinfo->master->first_MCU_col[ci]; else prev_prev_block_row = prev_block_row; - if (block_row < block_rows - 1 || cinfo->output_iMCU_row < last_iMCU_row) + if (image_block_row < image_block_rows - 1) next_block_row = buffer[block_row + 1] + cinfo->master->first_MCU_col[ci]; else next_block_row = buffer_ptr; - if (block_row < block_rows - 2 || - cinfo->output_iMCU_row < last_iMCU_row - 1) + if (image_block_row < image_block_rows - 2) next_next_block_row = buffer[block_row + 2] + cinfo->master->first_MCU_col[ci]; else @@ -583,11 +587,11 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) /* Update DC values */ if (block_num == cinfo->master->first_MCU_col[ci] && block_num < last_block_column) { - DC04 = (int)prev_prev_block_row[1][0]; - DC09 = (int)prev_block_row[1][0]; - DC14 = (int)buffer_ptr[1][0]; - DC19 = (int)next_block_row[1][0]; - DC24 = (int)next_next_block_row[1][0]; + DC04 = DC05 = (int)prev_prev_block_row[1][0]; + DC09 = DC10 = (int)prev_block_row[1][0]; + DC14 = DC15 = (int)buffer_ptr[1][0]; + DC19 = DC20 = (int)next_block_row[1][0]; + DC24 = DC25 = (int)next_next_block_row[1][0]; } if (block_num + 1 < last_block_column) { DC05 = (int)prev_prev_block_row[2][0]; @@ -810,10 +814,13 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) */ GLOBAL(void) -jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer) +_jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_coef_controller)); @@ -850,7 +857,7 @@ jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer) (JDIMENSION)access_rows); } coef->pub.consume_data = consume_data; - coef->pub.decompress_data = decompress_data; + coef->pub._decompress_data = decompress_data; coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ #else ERREXIT(cinfo, JERR_NOT_COMPILED); @@ -867,7 +874,7 @@ jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer) coef->MCU_buffer[i] = buffer + i; } coef->pub.consume_data = dummy_consume_data; - coef->pub.decompress_data = decompress_onepass; + coef->pub._decompress_data = decompress_onepass; coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ } diff --git a/3rdparty/libjpeg-turbo/src/jdcoefct.h b/3rdparty/libjpeg-turbo/src/jdcoefct.h index 9a0e78066364..bbe9e970515c 100644 --- a/3rdparty/libjpeg-turbo/src/jdcoefct.h +++ b/3rdparty/libjpeg-turbo/src/jdcoefct.h @@ -6,6 +6,7 @@ * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman for Cendio AB * Copyright (C) 2020, Google, Inc. + * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. */ @@ -14,6 +15,8 @@ #include "jpeglib.h" +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) + /* Block smoothing is only applicable for progressive JPEG, so: */ #ifndef D_PROGRESSIVE_SUPPORTED #undef BLOCK_SMOOTHING_SUPPORTED @@ -81,3 +84,5 @@ start_iMCU_row(j_decompress_ptr cinfo) coef->MCU_ctr = 0; coef->MCU_vert_offset = 0; } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */ diff --git a/3rdparty/libjpeg-turbo/src/jdcol565.c b/3rdparty/libjpeg-turbo/src/jdcol565.c index 53c7bd9187d4..2172d98fdaa4 100644 --- a/3rdparty/libjpeg-turbo/src/jdcol565.c +++ b/3rdparty/libjpeg-turbo/src/jdcol565.c @@ -5,7 +5,7 @@ * Copyright (C) 1991-1997, Thomas G. Lane. * Modifications: * Copyright (C) 2013, Linaro Limited. - * Copyright (C) 2014-2015, D. R. Commander. + * Copyright (C) 2014-2015, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -17,18 +17,19 @@ INLINE LOCAL(void) -ycc_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +ycc_rgb565_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; register int *Crrtab = cconvert->Cr_r_tab; register int *Cbbtab = cconvert->Cb_b_tab; register JLONG *Crgtab = cconvert->Cr_g_tab; @@ -91,23 +92,27 @@ ycc_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, *(INT16 *)outptr = (INT16)rgb; } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } INLINE LOCAL(void) -ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; register int *Crrtab = cconvert->Cr_r_tab; register int *Cbbtab = cconvert->Cb_b_tab; register JLONG *Crgtab = cconvert->Cr_g_tab; @@ -177,17 +182,20 @@ ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, *(INT16 *)outptr = (INT16)rgb; } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } INLINE LOCAL(void) -rgb_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +rgb_rgb565_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; SHIFT_TEMPS @@ -237,14 +245,14 @@ rgb_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) -rgb_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +rgb_rgb565D_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; JDIMENSION num_cols = cinfo->output_width; JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK]; SHIFT_TEMPS @@ -296,11 +304,11 @@ rgb_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) -gray_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +gray_rgb565_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW inptr, outptr; + register _JSAMPROW inptr, outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; @@ -336,13 +344,13 @@ gray_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) -gray_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +gray_rgb565D_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW inptr, outptr; + register _JSAMPROW inptr, outptr; register JDIMENSION col; - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; JDIMENSION num_cols = cinfo->output_width; JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK]; diff --git a/3rdparty/libjpeg-turbo/src/jdcolext.c b/3rdparty/libjpeg-turbo/src/jdcolext.c index 863c7a2fbc76..f22e29d7224e 100644 --- a/3rdparty/libjpeg-turbo/src/jdcolext.c +++ b/3rdparty/libjpeg-turbo/src/jdcolext.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2009, 2011, 2015, D. R. Commander. + * Copyright (C) 2009, 2011, 2015, 2022-2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -28,18 +28,19 @@ INLINE LOCAL(void) -ycc_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +ycc_rgb_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; register int *Crrtab = cconvert->Cr_r_tab; register int *Cbbtab = cconvert->Cb_b_tab; register JLONG *Crgtab = cconvert->Cr_g_tab; @@ -62,14 +63,17 @@ ycc_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS))]; outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; - /* Set unused byte to 0xFF so it can be interpreted as an opaque */ - /* alpha channel value */ + /* Set unused byte to _MAXJSAMPLE so it can be interpreted as an */ + /* opaque alpha channel value */ #ifdef RGB_ALPHA - outptr[RGB_ALPHA] = 0xFF; + outptr[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr += RGB_PIXELSIZE; } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -81,11 +85,11 @@ ycc_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) -gray_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +gray_rgb_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW inptr, outptr; + register _JSAMPROW inptr, outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; @@ -94,10 +98,10 @@ gray_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr = *output_buf++; for (col = 0; col < num_cols; col++) { outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; - /* Set unused byte to 0xFF so it can be interpreted as an opaque */ - /* alpha channel value */ + /* Set unused byte to _MAXJSAMPLE so it can be interpreted as an */ + /* opaque alpha channel value */ #ifdef RGB_ALPHA - outptr[RGB_ALPHA] = 0xFF; + outptr[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr += RGB_PIXELSIZE; } @@ -111,12 +115,12 @@ gray_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) -rgb_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, +rgb_rgb_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW inptr0, inptr1, inptr2; - register JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; @@ -130,10 +134,10 @@ rgb_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr[RGB_RED] = inptr0[col]; outptr[RGB_GREEN] = inptr1[col]; outptr[RGB_BLUE] = inptr2[col]; - /* Set unused byte to 0xFF so it can be interpreted as an opaque */ - /* alpha channel value */ + /* Set unused byte to _MAXJSAMPLE so it can be interpreted as an */ + /* opaque alpha channel value */ #ifdef RGB_ALPHA - outptr[RGB_ALPHA] = 0xFF; + outptr[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr += RGB_PIXELSIZE; } diff --git a/3rdparty/libjpeg-turbo/src/jdcolor.c b/3rdparty/libjpeg-turbo/src/jdcolor.c index 8da2b4eaf2e9..e5c7b58ebfad 100644 --- a/3rdparty/libjpeg-turbo/src/jdcolor.c +++ b/3rdparty/libjpeg-turbo/src/jdcolor.c @@ -6,7 +6,7 @@ * Modified 2011 by Guido Vollbeding. * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009, 2011-2012, 2014-2015, D. R. Commander. + * Copyright (C) 2009, 2011-2012, 2014-2015, 2022, D. R. Commander. * Copyright (C) 2013, Linaro Limited. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -18,14 +18,17 @@ #include "jinclude.h" #include "jpeglib.h" #include "jsimd.h" -#include "jconfigint.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) + /* Private subobject */ typedef struct { struct jpeg_color_deconverter pub; /* public fields */ +#if BITS_IN_JSAMPLE != 16 /* Private state for YCC->RGB conversion */ int *Cr_r_tab; /* => table for Cr to R conversion */ int *Cb_b_tab; /* => table for Cb to B conversion */ @@ -34,6 +37,7 @@ typedef struct { /* Private state for RGB->Y conversion */ JLONG *rgb_y_tab; /* => table for RGB to Y conversion */ +#endif } my_color_deconverter; typedef my_color_deconverter *my_cconvert_ptr; @@ -44,7 +48,7 @@ typedef my_color_deconverter *my_cconvert_ptr; /* * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * normalized to the range 0.._MAXJSAMPLE rather than -0.5 .. 0.5. * The conversion equations to be implemented are therefore * * R = Y + 1.40200 * Cr @@ -53,7 +57,7 @@ typedef my_color_deconverter *my_cconvert_ptr; * * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B * - * where Cb and Cr represent the incoming values less CENTERJSAMPLE. + * where Cb and Cr represent the incoming values less _CENTERJSAMPLE. * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) * * To avoid floating-point arithmetic, we represent the fractional constants @@ -64,7 +68,7 @@ typedef my_color_deconverter *my_cconvert_ptr; * * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times Cb and Cr for all possible values. - * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * For 8-bit samples this is very reasonable (only 256 entries per table); * for 12-bit samples it is still acceptable. It's not very reasonable for * 16-bit samples, but if you want lossless storage you shouldn't be changing * colorspace anyway. @@ -85,9 +89,9 @@ typedef my_color_deconverter *my_cconvert_ptr; */ #define R_Y_OFF 0 /* offset to R => Y section */ -#define G_Y_OFF (1 * (MAXJSAMPLE + 1)) /* offset to G => Y section */ -#define B_Y_OFF (2 * (MAXJSAMPLE + 1)) /* etc. */ -#define TABLE_SIZE (3 * (MAXJSAMPLE + 1)) +#define G_Y_OFF (1 * (_MAXJSAMPLE + 1)) /* offset to G => Y section */ +#define B_Y_OFF (2 * (_MAXJSAMPLE + 1)) /* etc. */ +#define TABLE_SIZE (3 * (_MAXJSAMPLE + 1)) /* Include inline routines for colorspace extensions */ @@ -210,6 +214,7 @@ typedef my_color_deconverter *my_cconvert_ptr; LOCAL(void) build_ycc_rgb_table(j_decompress_ptr cinfo) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; int i; JLONG x; @@ -217,20 +222,20 @@ build_ycc_rgb_table(j_decompress_ptr cinfo) cconvert->Cr_r_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(int)); + (_MAXJSAMPLE + 1) * sizeof(int)); cconvert->Cb_b_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(int)); + (_MAXJSAMPLE + 1) * sizeof(int)); cconvert->Cr_g_tab = (JLONG *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(JLONG)); + (_MAXJSAMPLE + 1) * sizeof(JLONG)); cconvert->Cb_g_tab = (JLONG *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(JLONG)); + (_MAXJSAMPLE + 1) * sizeof(JLONG)); - for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + for (i = 0, x = -_CENTERJSAMPLE; i <= _MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0.._MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - _CENTERJSAMPLE */ /* Cr=>R value is nearest int to 1.40200 * x */ cconvert->Cr_r_tab[i] = (int) RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); @@ -243,6 +248,9 @@ build_ycc_rgb_table(j_decompress_ptr cinfo) /* We also add in ONE_HALF so that need not do it in inner loop */ cconvert->Cb_g_tab[i] = (-FIX(0.34414)) * x + ONE_HALF; } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -251,8 +259,8 @@ build_ycc_rgb_table(j_decompress_ptr cinfo) */ METHODDEF(void) -ycc_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +ycc_rgb_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { switch (cinfo->out_color_space) { case JCS_EXT_RGB: @@ -301,6 +309,7 @@ ycc_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, LOCAL(void) build_rgb_y_table(j_decompress_ptr cinfo) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; JLONG *rgb_y_tab; JLONG i; @@ -310,11 +319,14 @@ build_rgb_y_table(j_decompress_ptr cinfo) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, (TABLE_SIZE * sizeof(JLONG))); - for (i = 0; i <= MAXJSAMPLE; i++) { + for (i = 0; i <= _MAXJSAMPLE; i++) { rgb_y_tab[i + R_Y_OFF] = FIX(0.29900) * i; rgb_y_tab[i + G_Y_OFF] = FIX(0.58700) * i; rgb_y_tab[i + B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -323,14 +335,15 @@ build_rgb_y_table(j_decompress_ptr cinfo) */ METHODDEF(void) -rgb_gray_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +rgb_gray_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int r, g, b; register JLONG *ctab = cconvert->rgb_y_tab; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; @@ -345,10 +358,13 @@ rgb_gray_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, g = inptr1[col]; b = inptr2[col]; /* Y */ - outptr[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + - ctab[b + B_Y_OFF]) >> SCALEBITS); + outptr[col] = (_JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + + ctab[b + B_Y_OFF]) >> SCALEBITS); } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -358,10 +374,10 @@ rgb_gray_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -null_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +null_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - register JSAMPROW inptr, inptr0, inptr1, inptr2, inptr3, outptr; + register _JSAMPROW inptr, inptr0, inptr1, inptr2, inptr3, outptr; register JDIMENSION col; register int num_components = cinfo->num_components; JDIMENSION num_cols = cinfo->output_width; @@ -419,11 +435,11 @@ null_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -grayscale_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +grayscale_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { - jcopy_sample_rows(input_buf[0], (int)input_row, output_buf, 0, num_rows, - cinfo->output_width); + _jcopy_sample_rows(input_buf[0], (int)input_row, output_buf, 0, num_rows, + cinfo->output_width); } @@ -432,8 +448,8 @@ grayscale_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -gray_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +gray_rgb_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { switch (cinfo->out_color_space) { case JCS_EXT_RGB: @@ -477,8 +493,8 @@ gray_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -rgb_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +rgb_rgb_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { switch (cinfo->out_color_space) { case JCS_EXT_RGB: @@ -525,17 +541,18 @@ rgb_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -ycck_cmyk_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +ycck_cmyk_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { +#if BITS_IN_JSAMPLE != 16 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2, inptr3; + register _JSAMPROW outptr; + register _JSAMPROW inptr0, inptr1, inptr2, inptr3; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; register int *Crrtab = cconvert->Cr_r_tab; register int *Cbbtab = cconvert->Cb_b_tab; register JLONG *Crgtab = cconvert->Cr_g_tab; @@ -554,16 +571,19 @@ ycck_cmyk_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, cb = inptr1[col]; cr = inptr2[col]; /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ - outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ + outptr[0] = range_limit[_MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ + outptr[1] = range_limit[_MAXJSAMPLE - (y + /* green */ ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS)))]; - outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ + outptr[2] = range_limit[_MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ /* K passes through unchanged */ outptr[3] = inptr3[col]; outptr += 4; } } +#else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); +#endif } @@ -653,8 +673,8 @@ static INLINE boolean is_big_endian(void) METHODDEF(void) -ycc_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +ycc_rgb565_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { if (is_big_endian()) ycc_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); @@ -664,8 +684,8 @@ ycc_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -ycc_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +ycc_rgb565D_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { if (is_big_endian()) ycc_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); @@ -675,8 +695,8 @@ ycc_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -rgb_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +rgb_rgb565_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { if (is_big_endian()) rgb_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); @@ -686,8 +706,8 @@ rgb_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -rgb_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +rgb_rgb565D_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { if (is_big_endian()) rgb_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); @@ -697,8 +717,8 @@ rgb_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -gray_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +gray_rgb565_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { if (is_big_endian()) gray_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); @@ -708,8 +728,8 @@ gray_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -gray_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) +gray_rgb565D_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) { if (is_big_endian()) gray_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); @@ -734,11 +754,14 @@ start_pass_dcolor(j_decompress_ptr cinfo) */ GLOBAL(void) -jinit_color_deconverter(j_decompress_ptr cinfo) +_jinit_color_deconverter(j_decompress_ptr cinfo) { my_cconvert_ptr cconvert; int ci; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_color_deconverter)); @@ -773,19 +796,24 @@ jinit_color_deconverter(j_decompress_ptr cinfo) /* Set out_color_components and conversion method based on requested space. * Also clear the component_needed flags for any unused components, * so that earlier pipeline stages can avoid useless computation. + * NOTE: We do not allow any lossy color conversion algorithms in lossless + * mode. */ switch (cinfo->out_color_space) { case JCS_GRAYSCALE: + if (cinfo->master->lossless && + cinfo->jpeg_color_space != cinfo->out_color_space) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); cinfo->out_color_components = 1; if (cinfo->jpeg_color_space == JCS_GRAYSCALE || cinfo->jpeg_color_space == JCS_YCbCr) { - cconvert->pub.color_convert = grayscale_convert; + cconvert->pub._color_convert = grayscale_convert; /* For color->grayscale conversion, only the Y (0) component is needed */ for (ci = 1; ci < cinfo->num_components; ci++) cinfo->comp_info[ci].component_needed = FALSE; } else if (cinfo->jpeg_color_space == JCS_RGB) { - cconvert->pub.color_convert = rgb_gray_convert; + cconvert->pub._color_convert = rgb_gray_convert; build_rgb_y_table(cinfo); } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); @@ -802,65 +830,78 @@ jinit_color_deconverter(j_decompress_ptr cinfo) case JCS_EXT_BGRA: case JCS_EXT_ABGR: case JCS_EXT_ARGB: + if (cinfo->master->lossless && cinfo->jpeg_color_space != JCS_RGB) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); cinfo->out_color_components = rgb_pixelsize[cinfo->out_color_space]; if (cinfo->jpeg_color_space == JCS_YCbCr) { +#ifdef WITH_SIMD if (jsimd_can_ycc_rgb()) - cconvert->pub.color_convert = jsimd_ycc_rgb_convert; - else { - cconvert->pub.color_convert = ycc_rgb_convert; + cconvert->pub._color_convert = jsimd_ycc_rgb_convert; + else +#endif + { + cconvert->pub._color_convert = ycc_rgb_convert; build_ycc_rgb_table(cinfo); } } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { - cconvert->pub.color_convert = gray_rgb_convert; + cconvert->pub._color_convert = gray_rgb_convert; } else if (cinfo->jpeg_color_space == JCS_RGB) { if (rgb_red[cinfo->out_color_space] == 0 && rgb_green[cinfo->out_color_space] == 1 && rgb_blue[cinfo->out_color_space] == 2 && rgb_pixelsize[cinfo->out_color_space] == 3) - cconvert->pub.color_convert = null_convert; + cconvert->pub._color_convert = null_convert; else - cconvert->pub.color_convert = rgb_rgb_convert; + cconvert->pub._color_convert = rgb_rgb_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_RGB565: + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); cinfo->out_color_components = 3; if (cinfo->dither_mode == JDITHER_NONE) { if (cinfo->jpeg_color_space == JCS_YCbCr) { +#ifdef WITH_SIMD if (jsimd_can_ycc_rgb565()) - cconvert->pub.color_convert = jsimd_ycc_rgb565_convert; - else { - cconvert->pub.color_convert = ycc_rgb565_convert; + cconvert->pub._color_convert = jsimd_ycc_rgb565_convert; + else +#endif + { + cconvert->pub._color_convert = ycc_rgb565_convert; build_ycc_rgb_table(cinfo); } } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { - cconvert->pub.color_convert = gray_rgb565_convert; + cconvert->pub._color_convert = gray_rgb565_convert; } else if (cinfo->jpeg_color_space == JCS_RGB) { - cconvert->pub.color_convert = rgb_rgb565_convert; + cconvert->pub._color_convert = rgb_rgb565_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } else { /* only ordered dithering is supported */ if (cinfo->jpeg_color_space == JCS_YCbCr) { - cconvert->pub.color_convert = ycc_rgb565D_convert; + cconvert->pub._color_convert = ycc_rgb565D_convert; build_ycc_rgb_table(cinfo); } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { - cconvert->pub.color_convert = gray_rgb565D_convert; + cconvert->pub._color_convert = gray_rgb565D_convert; } else if (cinfo->jpeg_color_space == JCS_RGB) { - cconvert->pub.color_convert = rgb_rgb565D_convert; + cconvert->pub._color_convert = rgb_rgb565D_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } break; case JCS_CMYK: + if (cinfo->master->lossless && + cinfo->jpeg_color_space != cinfo->out_color_space) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); cinfo->out_color_components = 4; if (cinfo->jpeg_color_space == JCS_YCCK) { - cconvert->pub.color_convert = ycck_cmyk_convert; + cconvert->pub._color_convert = ycck_cmyk_convert; build_ycc_rgb_table(cinfo); } else if (cinfo->jpeg_color_space == JCS_CMYK) { - cconvert->pub.color_convert = null_convert; + cconvert->pub._color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; @@ -869,7 +910,7 @@ jinit_color_deconverter(j_decompress_ptr cinfo) /* Permit null conversion to same output space */ if (cinfo->out_color_space == cinfo->jpeg_color_space) { cinfo->out_color_components = cinfo->num_components; - cconvert->pub.color_convert = null_convert; + cconvert->pub._color_convert = null_convert; } else /* unsupported non-null conversion */ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; @@ -880,3 +921,5 @@ jinit_color_deconverter(j_decompress_ptr cinfo) else cinfo->output_components = cinfo->out_color_components; } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */ diff --git a/3rdparty/libjpeg-turbo/src/jdct.h b/3rdparty/libjpeg-turbo/src/jdct.h index 66d1718b770b..0411a79bc0b9 100644 --- a/3rdparty/libjpeg-turbo/src/jdct.h +++ b/3rdparty/libjpeg-turbo/src/jdct.h @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2015, D. R. Commander. + * Copyright (C) 2015, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -15,13 +15,15 @@ * machine-dependent tuning (e.g., assembly coding). */ +#include "jsamplecomp.h" + /* * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; * the DCT is to be performed in-place in that buffer. Type DCTELEM is int * for 8-bit samples, JLONG for 12-bit samples. (NOTE: Floating-point DCT * implementations use an array of type FAST_FLOAT, instead.) - * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). + * The DCT inputs are expected to be signed (range +-_CENTERJSAMPLE). * The DCT outputs are returned scaled up by a factor of 8; they therefore * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This * convention improves accuracy in integer implementations and saves some @@ -76,78 +78,89 @@ typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ /* * Each IDCT routine is responsible for range-limiting its results and - * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + * converting them to unsigned form (0.._MAXJSAMPLE). The raw outputs could * be quite far out of range if the input data is corrupt, so a bulletproof * range-limiting step is required. We use a mask-and-table-lookup method * to do the combined operations quickly. See the comments with * prepare_range_limit_table (in jdmaster.c) for more info. */ -#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) +#define IDCT_range_limit(cinfo) \ + ((_JSAMPLE *)((cinfo)->sample_range_limit) + _CENTERJSAMPLE) -#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ +#define RANGE_MASK (_MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ /* Extern declarations for the forward and inverse DCT routines. */ -EXTERN(void) jpeg_fdct_islow(DCTELEM *data); -EXTERN(void) jpeg_fdct_ifast(DCTELEM *data); +EXTERN(void) _jpeg_fdct_islow(DCTELEM *data); +EXTERN(void) _jpeg_fdct_ifast(DCTELEM *data); EXTERN(void) jpeg_fdct_float(FAST_FLOAT *data); -EXTERN(void) jpeg_idct_islow(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_ifast(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_float(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_7x7(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_6x6(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_5x5(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_4x4(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_3x3(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_2x2(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_1x1(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_9x9(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_10x10(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_11x11(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_12x12(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_13x13(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_14x14(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_15x15(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); -EXTERN(void) jpeg_idct_16x16(j_decompress_ptr cinfo, - jpeg_component_info *compptr, JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_islow(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_ifast(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_float(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_7x7(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_6x6(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_5x5(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_4x4(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_3x3(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_2x2(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_1x1(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_9x9(j_decompress_ptr cinfo, + jpeg_component_info *compptr, JCOEFPTR coef_block, + _JSAMPARRAY output_buf, JDIMENSION output_col); +EXTERN(void) _jpeg_idct_10x10(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_11x11(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_12x12(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_13x13(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_14x14(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_15x15(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); +EXTERN(void) _jpeg_idct_16x16(j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col); /* diff --git a/3rdparty/libjpeg-turbo/src/jddctmgr.c b/3rdparty/libjpeg-turbo/src/jddctmgr.c index e78d7bebe28a..0bd8c2b591de 100644 --- a/3rdparty/libjpeg-turbo/src/jddctmgr.c +++ b/3rdparty/libjpeg-turbo/src/jddctmgr.c @@ -26,7 +26,7 @@ #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #include "jsimddct.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" /* @@ -100,7 +100,7 @@ start_pass(j_decompress_ptr cinfo) int ci, i; jpeg_component_info *compptr; int method = 0; - inverse_DCT_method_ptr method_ptr = NULL; + _inverse_DCT_method_ptr method_ptr = NULL; JQUANT_TBL *qtbl; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; @@ -109,42 +109,46 @@ start_pass(j_decompress_ptr cinfo) switch (compptr->_DCT_scaled_size) { #ifdef IDCT_SCALING_SUPPORTED case 1: - method_ptr = jpeg_idct_1x1; + method_ptr = _jpeg_idct_1x1; method = JDCT_ISLOW; /* jidctred uses islow-style table */ break; case 2: +#ifdef WITH_SIMD if (jsimd_can_idct_2x2()) method_ptr = jsimd_idct_2x2; else - method_ptr = jpeg_idct_2x2; +#endif + method_ptr = _jpeg_idct_2x2; method = JDCT_ISLOW; /* jidctred uses islow-style table */ break; case 3: - method_ptr = jpeg_idct_3x3; + method_ptr = _jpeg_idct_3x3; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 4: +#ifdef WITH_SIMD if (jsimd_can_idct_4x4()) method_ptr = jsimd_idct_4x4; else - method_ptr = jpeg_idct_4x4; +#endif + method_ptr = _jpeg_idct_4x4; method = JDCT_ISLOW; /* jidctred uses islow-style table */ break; case 5: - method_ptr = jpeg_idct_5x5; + method_ptr = _jpeg_idct_5x5; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 6: -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_can_idct_6x6()) method_ptr = jsimd_idct_6x6; else #endif - method_ptr = jpeg_idct_6x6; + method_ptr = _jpeg_idct_6x6; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 7: - method_ptr = jpeg_idct_7x7; + method_ptr = _jpeg_idct_7x7; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; #endif @@ -152,28 +156,34 @@ start_pass(j_decompress_ptr cinfo) switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: +#ifdef WITH_SIMD if (jsimd_can_idct_islow()) method_ptr = jsimd_idct_islow; else - method_ptr = jpeg_idct_islow; +#endif + method_ptr = _jpeg_idct_islow; method = JDCT_ISLOW; break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: +#ifdef WITH_SIMD if (jsimd_can_idct_ifast()) method_ptr = jsimd_idct_ifast; else - method_ptr = jpeg_idct_ifast; +#endif + method_ptr = _jpeg_idct_ifast; method = JDCT_IFAST; break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: +#ifdef WITH_SIMD if (jsimd_can_idct_float()) method_ptr = jsimd_idct_float; else - method_ptr = jpeg_idct_float; +#endif + method_ptr = _jpeg_idct_float; method = JDCT_FLOAT; break; #endif @@ -184,40 +194,40 @@ start_pass(j_decompress_ptr cinfo) break; #ifdef IDCT_SCALING_SUPPORTED case 9: - method_ptr = jpeg_idct_9x9; + method_ptr = _jpeg_idct_9x9; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 10: - method_ptr = jpeg_idct_10x10; + method_ptr = _jpeg_idct_10x10; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 11: - method_ptr = jpeg_idct_11x11; + method_ptr = _jpeg_idct_11x11; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 12: -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_can_idct_12x12()) method_ptr = jsimd_idct_12x12; else #endif - method_ptr = jpeg_idct_12x12; + method_ptr = _jpeg_idct_12x12; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 13: - method_ptr = jpeg_idct_13x13; + method_ptr = _jpeg_idct_13x13; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 14: - method_ptr = jpeg_idct_14x14; + method_ptr = _jpeg_idct_14x14; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 15: - method_ptr = jpeg_idct_15x15; + method_ptr = _jpeg_idct_15x15; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case 16: - method_ptr = jpeg_idct_16x16; + method_ptr = _jpeg_idct_16x16; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; #endif @@ -225,7 +235,7 @@ start_pass(j_decompress_ptr cinfo) ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->_DCT_scaled_size); break; } - idct->pub.inverse_DCT[ci] = method_ptr; + idct->pub._inverse_DCT[ci] = method_ptr; /* Create multiplier table from quant table. * However, we can skip this if the component is uninteresting * or if we already built the table. Also, if no quant table @@ -327,12 +337,15 @@ start_pass(j_decompress_ptr cinfo) */ GLOBAL(void) -jinit_inverse_dct(j_decompress_ptr cinfo) +_jinit_inverse_dct(j_decompress_ptr cinfo) { my_idct_ptr idct; int ci; jpeg_component_info *compptr; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + idct = (my_idct_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_idct_controller)); diff --git a/3rdparty/libjpeg-turbo/src/jddiffct.c b/3rdparty/libjpeg-turbo/src/jddiffct.c new file mode 100644 index 000000000000..f1d7f61b5209 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/jddiffct.c @@ -0,0 +1,403 @@ +/* + * jddiffct.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1994-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains the [un]difference buffer controller for decompression. + * This controller is the top level of the lossless JPEG decompressor proper. + * The difference buffer lies between the entropy decoding and + * prediction/undifferencing steps. The undifference buffer lies between the + * prediction/undifferencing and scaling steps. + * + * In buffered-image mode, this controller is the interface between + * input-oriented processing and output-oriented processing. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jlossls.h" /* Private declarations for lossless codec */ + + +#ifdef D_LOSSLESS_SUPPORTED + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_coef_controller pub; /* public fields */ + + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + unsigned int restart_rows_to_go; /* MCU rows left in this restart + interval */ + unsigned int MCU_vert_offset; /* counts MCU rows within iMCU row */ + unsigned int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */ + JDIFFARRAY undiff_buf[MAX_COMPONENTS]; /* iMCU row of undiff'd samples */ + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* In multi-pass modes, we need a virtual sample array for each component. */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +#endif +} my_diff_controller; + +typedef my_diff_controller *my_diff_ptr; + +/* Forward declarations */ +METHODDEF(int) decompress_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf); +#ifdef D_MULTISCAN_FILES_SUPPORTED +METHODDEF(int) output_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf); +#endif + + +LOCAL(void) +start_iMCU_row(j_decompress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row (input side) */ +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + diff->MCU_rows_per_iMCU_row = 1; + } else { + if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) + diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + diff->MCU_ctr = 0; + diff->MCU_vert_offset = 0; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass(j_decompress_ptr cinfo) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + + /* Because it is hitching a ride on the jpeg_inverse_dct struct, + * start_pass_lossless() will be called at the start of the output pass. + * This ensures that it will be called at the start of the input pass as + * well. + */ + (*cinfo->idct->start_pass) (cinfo); + + /* Check that the restart interval is an integer multiple of the number + * of MCUs in an MCU row. + */ + if (cinfo->restart_interval % cinfo->MCUs_per_row != 0) + ERREXIT2(cinfo, JERR_BAD_RESTART, + cinfo->restart_interval, cinfo->MCUs_per_row); + + /* Initialize restart counter */ + diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row; + + cinfo->input_iMCU_row = 0; + start_iMCU_row(cinfo); +} + + +/* + * Check for a restart marker & resynchronize decoder, undifferencer. + * Returns FALSE if must suspend. + */ + +METHODDEF(boolean) +process_restart(j_decompress_ptr cinfo) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + + if (!(*cinfo->entropy->process_restart) (cinfo)) + return FALSE; + + (*cinfo->idct->start_pass) (cinfo); + + /* Reset restart counter */ + diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row; + + return TRUE; +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass(j_decompress_ptr cinfo) +{ + cinfo->output_iMCU_row = 0; +} + + +/* + * Decompress and return some data in the supplied buffer. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Input and output must run in lockstep since we have only a one-MCU buffer. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(int) +decompress_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + lossless_decomp_ptr losslessd = (lossless_decomp_ptr)cinfo->idct; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION MCU_count; /* number of MCUs decoded */ + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int ci, compi, row, prev_row; + unsigned int yoffset; + jpeg_component_info *compptr; + + /* Loop to process as much as one whole iMCU row */ + for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row; + yoffset++) { + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (diff->restart_rows_to_go == 0) + if (!process_restart(cinfo)) + return JPEG_SUSPENDED; + } + + MCU_col_num = diff->MCU_ctr; + /* Try to fetch an MCU row (or remaining portion of suspended MCU row). */ + MCU_count = + (*cinfo->entropy->decode_mcus) (cinfo, + diff->diff_buf, yoffset, MCU_col_num, + cinfo->MCUs_per_row - MCU_col_num); + if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) { + /* Suspension forced; update state counters and exit */ + diff->MCU_vert_offset = yoffset; + diff->MCU_ctr += MCU_count; + return JPEG_SUSPENDED; + } + + /* Account for restart interval (no-op if not using restarts) */ + if (cinfo->restart_interval) + diff->restart_rows_to_go--; + + /* Completed an MCU row, but perhaps not an iMCU row */ + diff->MCU_ctr = 0; + } + + /* + * Undifference and scale each scanline of the disassembled MCU row + * separately. We do not process dummy samples at the end of a scanline + * or dummy rows at the end of the image. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + compi = compptr->component_index; + for (row = 0, prev_row = compptr->v_samp_factor - 1; + row < (cinfo->input_iMCU_row == last_iMCU_row ? + compptr->last_row_height : compptr->v_samp_factor); + prev_row = row, row++) { + (*losslessd->predict_undifference[compi]) + (cinfo, compi, diff->diff_buf[compi][row], + diff->undiff_buf[compi][prev_row], diff->undiff_buf[compi][row], + compptr->width_in_blocks); + (*losslessd->scaler_scale) (cinfo, diff->undiff_buf[compi][row], + output_buf[compi][row], + compptr->width_in_blocks); + } + } + + /* Completed the iMCU row, advance counters for next one. + * + * NB: output_data will increment output_iMCU_row. + * This counter is not needed for the single-pass case + * or the input side of the multi-pass case. + */ + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Dummy consume-input routine for single-pass operation. + */ + +METHODDEF(int) +dummy_consume_data(j_decompress_ptr cinfo) +{ + return JPEG_SUSPENDED; /* Always indicate nothing was done */ +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Consume input data and store it in the full-image sample buffer. + * We read as much as one fully interleaved MCU row ("iMCU" row) per call, + * ie, v_samp_factor rows for each component in the scan. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + */ + +METHODDEF(int) +consume_data(j_decompress_ptr cinfo) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + int ci, compi; + _JSAMPARRAY buffer[MAX_COMPS_IN_SCAN]; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + compi = compptr->component_index; + buffer[compi] = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, diff->whole_image[compi], + cinfo->input_iMCU_row * compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, TRUE); + } + + return decompress_data(cinfo, buffer); +} + + +/* + * Output some data from the full-image sample buffer in the multi-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image. + */ + +METHODDEF(int) +output_data(j_decompress_ptr cinfo, _JSAMPIMAGE output_buf) +{ + my_diff_ptr diff = (my_diff_ptr)cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int ci, samp_rows, row; + _JSAMPARRAY buffer; + jpeg_component_info *compptr; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number < cinfo->output_scan_number || + (cinfo->input_scan_number == cinfo->output_scan_number && + cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, diff->whole_image[ci], + cinfo->output_iMCU_row * compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, FALSE); + + if (cinfo->output_iMCU_row < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + samp_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor); + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + } + + for (row = 0; row < samp_rows; row++) { + memcpy(output_buf[ci][row], buffer[row], + compptr->width_in_blocks * sizeof(_JSAMPLE)); + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +/* + * Initialize difference buffer controller. + */ + +GLOBAL(void) +_jinit_d_diff_controller(j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_diff_ptr diff; + int ci; + jpeg_component_info *compptr; + + diff = (my_diff_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + sizeof(my_diff_controller)); + cinfo->coef = (struct jpeg_d_coef_controller *)diff; + diff->pub.start_input_pass = start_input_pass; + diff->pub.start_output_pass = start_output_pass; + + /* Create the [un]difference buffers. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->diff_buf[ci] = + ALLOC_DARRAY(JPOOL_IMAGE, + (JDIMENSION)jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor), + (JDIMENSION)compptr->v_samp_factor); + diff->undiff_buf[ci] = + ALLOC_DARRAY(JPOOL_IMAGE, + (JDIMENSION)jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor), + (JDIMENSION)compptr->v_samp_factor); + } + + if (need_full_buffer) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* Allocate a full-image virtual array for each component. */ + int access_rows; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + access_rows = compptr->v_samp_factor; + diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION)jround_up((long)compptr->width_in_blocks, + (long)compptr->h_samp_factor), + (JDIMENSION)jround_up((long)compptr->height_in_blocks, + (long)compptr->v_samp_factor), + (JDIMENSION)access_rows); + } + diff->pub.consume_data = consume_data; + diff->pub._decompress_data = output_data; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + diff->pub.consume_data = dummy_consume_data; + diff->pub._decompress_data = decompress_data; + diff->whole_image[0] = NULL; /* flag for no virtual arrays */ + } +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/3rdparty/libjpeg-turbo/src/jdhuff.c b/3rdparty/libjpeg-turbo/src/jdhuff.c index 679d22168591..cd8c0847a22e 100644 --- a/3rdparty/libjpeg-turbo/src/jdhuff.c +++ b/3rdparty/libjpeg-turbo/src/jdhuff.c @@ -3,8 +3,10 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2009-2011, 2016, 2018-2019, D. R. Commander. + * Copyright (C) 2009-2011, 2016, 2018-2019, 2022, D. R. Commander. * Copyright (C) 2018, Matthias Räncker. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -24,8 +26,8 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jdhuff.h" /* Declarations shared with jdphuff.c */ -#include "jpegcomp.h" +#include "jdhuff.h" /* Declarations shared with jd*huff.c */ +#include "jpegapicomp.h" #include "jstdhuff.c" @@ -134,7 +136,7 @@ start_pass_huff_decoder(j_decompress_ptr cinfo) * Compute the derived values for a Huffman table. * This routine also performs some validation checks on the table. * - * Note this is also used by jdphuff.c. + * Note this is also used by jdphuff.c and jdlhuff.c. */ GLOBAL(void) @@ -245,14 +247,14 @@ jpeg_make_d_derived_tbl(j_decompress_ptr cinfo, boolean isDC, int tblno, /* Validate symbols as being reasonable. * For AC tables, we make no check, but accept all byte values 0..255. - * For DC tables, we require the symbols to be in range 0..15. - * (Tighter bounds could be applied depending on the data depth and mode, - * but this is sufficient to ensure safe decoding.) + * For DC tables, we require the symbols to be in range 0..15 in lossy mode + * and 0..16 in lossless mode. (Tighter bounds could be applied depending on + * the data depth and mode, but this is sufficient to ensure safe decoding.) */ if (isDC) { for (i = 0; i < numsymbols; i++) { int sym = htbl->huffval[i]; - if (sym < 0 || sym > 15) + if (sym < 0 || sym > (cinfo->master->lossless ? 16 : 15)) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); } } @@ -260,7 +262,7 @@ jpeg_make_d_derived_tbl(j_decompress_ptr cinfo, boolean isDC, int tblno, /* - * Out-of-line code for bit fetching (shared with jdphuff.c). + * Out-of-line code for bit fetching (shared with jdphuff.c and jdlhuff.c). * See jdhuff.h for info about usage. * Note: current values of get_buffer and bits_left are passed as parameters, * but are returned in the corresponding fields of the state struct. diff --git a/3rdparty/libjpeg-turbo/src/jdhuff.h b/3rdparty/libjpeg-turbo/src/jdhuff.h index cfa0b7f55888..3eee002c020a 100644 --- a/3rdparty/libjpeg-turbo/src/jdhuff.h +++ b/3rdparty/libjpeg-turbo/src/jdhuff.h @@ -3,6 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright (C) 2010-2011, 2015-2016, 2021, D. R. Commander. * Copyright (C) 2018, Matthias Räncker. @@ -10,8 +12,9 @@ * file. * * This file contains declarations for Huffman entropy decoding routines - * that are shared between the sequential decoder (jdhuff.c) and the - * progressive decoder (jdphuff.c). No other modules need to see these. + * that are shared between the sequential decoder (jdhuff.c), the progressive + * decoder (jdphuff.c), and the lossless decoder (jdlhuff.c). No other modules + * need to see these. */ #include "jconfigint.h" diff --git a/3rdparty/libjpeg-turbo/src/jdinput.c b/3rdparty/libjpeg-turbo/src/jdinput.c index 1bc5aff1a70a..136bef59d753 100644 --- a/3rdparty/libjpeg-turbo/src/jdinput.c +++ b/3rdparty/libjpeg-turbo/src/jdinput.c @@ -3,6 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright (C) 2010, 2016, 2018, 2022, D. R. Commander. * Copyright (C) 2015, Google, Inc. @@ -11,14 +13,15 @@ * * This file contains input control logic for the JPEG decompressor. * These routines are concerned with controlling the decompressor's input - * processing (marker reading and coefficient decoding). The actual input - * reading is done in jdmarker.c, jdhuff.c, and jdphuff.c. + * processing (marker reading and coefficient/difference decoding). + * The actual input reading is done in jdmarker.c, jdhuff.c, jdphuff.c, + * and jdlhuff.c. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" /* Private state */ @@ -46,6 +49,7 @@ initial_setup(j_decompress_ptr cinfo) { int ci; jpeg_component_info *compptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; /* Make sure image isn't bigger than I can handle */ if ((long)cinfo->image_height > (long)JPEG_MAX_DIMENSION || @@ -53,7 +57,12 @@ initial_setup(j_decompress_ptr cinfo) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int)JPEG_MAX_DIMENSION); /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) +#ifdef D_LOSSLESS_SUPPORTED + if (cinfo->data_precision != 8 && cinfo->data_precision != 12 && + cinfo->data_precision != 16) +#else + if (cinfo->data_precision != 8 && cinfo->data_precision != 12) +#endif ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ @@ -78,36 +87,36 @@ initial_setup(j_decompress_ptr cinfo) } #if JPEG_LIB_VERSION >= 80 - cinfo->block_size = DCTSIZE; + cinfo->block_size = data_unit; cinfo->natural_order = jpeg_natural_order; cinfo->lim_Se = DCTSIZE2 - 1; #endif - /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. - * In the full decompressor, this will be overridden by jdmaster.c; + /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE in lossy + * mode. In the full decompressor, this will be overridden by jdmaster.c; * but in the transcoder, jdmaster.c is not used, so we must do it here. */ #if JPEG_LIB_VERSION >= 70 - cinfo->min_DCT_h_scaled_size = cinfo->min_DCT_v_scaled_size = DCTSIZE; + cinfo->min_DCT_h_scaled_size = cinfo->min_DCT_v_scaled_size = data_unit; #else - cinfo->min_DCT_scaled_size = DCTSIZE; + cinfo->min_DCT_scaled_size = data_unit; #endif /* Compute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { #if JPEG_LIB_VERSION >= 70 - compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = DCTSIZE; + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = data_unit; #else - compptr->DCT_scaled_size = DCTSIZE; + compptr->DCT_scaled_size = data_unit; #endif - /* Size in DCT blocks */ + /* Size in data units */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long)cinfo->image_width * (long)compptr->h_samp_factor, - (long)(cinfo->max_h_samp_factor * DCTSIZE)); + (long)(cinfo->max_h_samp_factor * data_unit)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long)cinfo->image_height * (long)compptr->v_samp_factor, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); /* Set the first and last MCU columns to decompress from multi-scan images. * By default, decompress all of the MCU columns. */ @@ -133,7 +142,7 @@ initial_setup(j_decompress_ptr cinfo) /* Compute number of fully interleaved MCU rows. */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long)cinfo->image_height, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); /* Decide whether file contains multiple scans */ if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) @@ -150,6 +159,7 @@ per_scan_setup(j_decompress_ptr cinfo) { int ci, mcublks, tmp; jpeg_component_info *compptr; + int data_unit = cinfo->master->lossless ? 1 : DCTSIZE; if (cinfo->comps_in_scan == 1) { @@ -160,14 +170,14 @@ per_scan_setup(j_decompress_ptr cinfo) cinfo->MCUs_per_row = compptr->width_in_blocks; cinfo->MCU_rows_in_scan = compptr->height_in_blocks; - /* For noninterleaved scan, always one block per MCU */ + /* For noninterleaved scan, always one data unit per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; compptr->MCU_sample_width = compptr->_DCT_scaled_size; compptr->last_col_width = 1; /* For noninterleaved scans, it is convenient to define last_row_height - * as the number of block rows present in the last iMCU row. + * as the number of data unit rows present in the last iMCU row. */ tmp = (int)(compptr->height_in_blocks % compptr->v_samp_factor); if (tmp == 0) tmp = compptr->v_samp_factor; @@ -187,22 +197,22 @@ per_scan_setup(j_decompress_ptr cinfo) /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long)cinfo->image_width, - (long)(cinfo->max_h_samp_factor * DCTSIZE)); + (long)(cinfo->max_h_samp_factor * data_unit)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long)cinfo->image_height, - (long)(cinfo->max_v_samp_factor * DCTSIZE)); + (long)(cinfo->max_v_samp_factor * data_unit)); cinfo->blocks_in_MCU = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; - /* Sampling factors give # of blocks of component in each MCU */ + /* Sampling factors give # of data units of component in each MCU */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; compptr->MCU_sample_width = compptr->MCU_width * compptr->_DCT_scaled_size; - /* Figure number of non-dummy blocks in last MCU column & row */ + /* Figure number of non-dummy data units in last MCU column & row */ tmp = (int)(compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; compptr->last_col_width = tmp; @@ -281,7 +291,8 @@ METHODDEF(void) start_input_pass(j_decompress_ptr cinfo) { per_scan_setup(cinfo); - latch_quant_tables(cinfo); + if (!cinfo->master->lossless) + latch_quant_tables(cinfo); (*cinfo->entropy->start_pass) (cinfo); (*cinfo->coef->start_input_pass) (cinfo); cinfo->inputctl->consume_input = cinfo->coef->consume_data; @@ -290,8 +301,8 @@ start_input_pass(j_decompress_ptr cinfo) /* * Finish up after inputting a compressed-data scan. - * This is called by the coefficient controller after it's read all - * the expected data of the scan. + * This is called by the coefficient or difference controller after it's read + * all the expected data of the scan. */ METHODDEF(void) @@ -307,8 +318,8 @@ finish_input_pass(j_decompress_ptr cinfo) * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. * * The consume_input method pointer points either here or to the - * coefficient controller's consume_data routine, depending on whether - * we are reading a compressed data segment or inter-segment markers. + * coefficient or difference controller's consume_data routine, depending on + * whether we are reading a compressed data segment or inter-segment markers. */ METHODDEF(int) diff --git a/3rdparty/libjpeg-turbo/src/jdlhuff.c b/3rdparty/libjpeg-turbo/src/jdlhuff.c new file mode 100644 index 000000000000..9964830dba07 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/jdlhuff.c @@ -0,0 +1,302 @@ +/* + * jdlhuff.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains Huffman entropy decoding routines for lossless JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jlossls.h" /* Private declarations for lossless codec */ +#include "jdhuff.h" /* Declarations shared with jd*huff.c */ + + +#ifdef D_LOSSLESS_SUPPORTED + +typedef struct { + int ci, yoffset, MCU_width; +} lhd_output_ptr_info; + +/* + * Expanded entropy decoder object for Huffman decoding in lossless mode. + */ + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + bitread_perm_state bitstate; /* Bit buffer at start of MCU */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl *derived_tbls[NUM_HUFF_TBLS]; + + /* Precalculated info set up by start_pass for use in decode_mcus: */ + + /* Pointers to derived tables to be used for each data unit within an MCU */ + d_derived_tbl *cur_tbls[D_MAX_BLOCKS_IN_MCU]; + + /* Pointers to the proper output difference row for each group of data units + * within an MCU. For each component, there are Vi groups of Hi data units. + */ + JDIFFROW output_ptr[D_MAX_BLOCKS_IN_MCU]; + + /* Number of output pointers in use for the current MCU. This is the sum + * of all Vi in the MCU. + */ + int num_output_ptrs; + + /* Information used for positioning the output pointers within the output + * difference rows. + */ + lhd_output_ptr_info output_ptr_info[D_MAX_BLOCKS_IN_MCU]; + + /* Index of the proper output pointer for each data unit within an MCU */ + int output_ptr_index[D_MAX_BLOCKS_IN_MCU]; + +} lhuff_entropy_decoder; + +typedef lhuff_entropy_decoder *lhuff_entropy_ptr; + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_lhuff_decoder(j_decompress_ptr cinfo) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + int ci, dctbl, sampn, ptrn, yoffset, xoffset; + jpeg_component_info *compptr; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + /* Make sure requested tables are present */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS || + cinfo->dc_huff_tbl_ptrs[dctbl] == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, + &entropy->derived_tbls[dctbl]); + } + + /* Precalculate decoding info for each sample in an MCU of this scan */ + for (sampn = 0, ptrn = 0; sampn < cinfo->blocks_in_MCU;) { + compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]]; + ci = compptr->component_index; + for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) { + /* Precalculate the setup info for each output pointer */ + entropy->output_ptr_info[ptrn].ci = ci; + entropy->output_ptr_info[ptrn].yoffset = yoffset; + entropy->output_ptr_info[ptrn].MCU_width = compptr->MCU_width; + for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) { + /* Precalculate the output pointer index for each sample */ + entropy->output_ptr_index[sampn] = ptrn; + /* Precalculate which table to use for each sample */ + entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no]; + } + } + } + entropy->num_output_ptrs = ptrn; + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->pub.insufficient_data = FALSE; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#define AVOID_TABLES +#ifdef AVOID_TABLES + +#define NEG_1 ((unsigned int)-1) +#define HUFF_EXTEND(x, s) \ + ((x) + ((((x) - (1 << ((s) - 1))) >> 31) & (((NEG_1) << (s)) + 1))) + +#else + +#define HUFF_EXTEND(x, s) \ + ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = { /* entry n is 2**(n-1) */ + 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 +}; + +static const int extend_offset[16] = { /* entry n is (-1 << n) + 1 */ + 0, ((-1) << 1) + 1, ((-1) << 2) + 1, ((-1) << 3) + 1, ((-1) << 4) + 1, + ((-1) << 5) + 1, ((-1) << 6) + 1, ((-1) << 7) + 1, ((-1) << 8) + 1, + ((-1) << 9) + 1, ((-1) << 10) + 1, ((-1) << 11) + 1, ((-1) << 12) + 1, + ((-1) << 13) + 1, ((-1) << 14) + 1, ((-1) << 15) + 1 +}; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart(j_decompress_ptr cinfo) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (!(*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->pub.insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Decode and return nMCU MCUs' worth of Huffman-compressed differences. + * Each MCU is also disassembled and placed accordingly in diff_buf. + * + * MCU_col_num specifies the column of the first MCU being requested within + * the MCU row. This tells us where to position the output row pointers in + * diff_buf. + * + * Returns the number of MCUs decoded. This may be less than nMCU MCUs if + * data source requested suspension. In that case no changes have been made + * to permanent state. (Exception: some output differences may already have + * been assigned. This is harmless for this module, since we'll just + * re-assign them on the next call.) + */ + +METHODDEF(JDIMENSION) +decode_mcus(j_decompress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, JDIMENSION nMCU) +{ + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr)cinfo->entropy; + int sampn, ci, yoffset, MCU_width, ptrn; + JDIMENSION mcu_num; + BITREAD_STATE_VARS; + + /* Set output pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) { + ci = entropy->output_ptr_info[ptrn].ci; + yoffset = entropy->output_ptr_info[ptrn].yoffset; + MCU_width = entropy->output_ptr_info[ptrn].MCU_width; + entropy->output_ptr[ptrn] = + diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width); + } + + /* + * If we've run out of data, zero out the buffers and return. + * By resetting the undifferencer, the output samples will be CENTERJSAMPLE. + * + * NB: We should find a way to do this without interacting with the + * undifferencer module directly. + */ + if (entropy->pub.insufficient_data) { + for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) + jzero_far((void FAR *)entropy->output_ptr[ptrn], + nMCU * entropy->output_ptr_info[ptrn].MCU_width * + sizeof(JDIFF)); + + (*cinfo->idct->start_pass) (cinfo); + + } else { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo, entropy->bitstate); + + /* Outer loop handles the number of MCUs requested */ + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->blocks_in_MCU; sampn++) { + d_derived_tbl *dctbl = entropy->cur_tbls[sampn]; + register int s, r; + + /* Section H.2.2: decode the sample difference */ + HUFF_DECODE(s, br_state, dctbl, return mcu_num, label1); + if (s) { + if (s == 16) /* special case: always output 32768 */ + s = 32768; + else { /* normal case: fetch subsequent bits */ + CHECK_BIT_BUFFER(br_state, s, return mcu_num); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + } + + /* Output the sample difference */ + *entropy->output_ptr[entropy->output_ptr_index[sampn]]++ = (JDIFF)s; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo, entropy->bitstate); + } + } + + return nMCU; +} + + +/* + * Module initialization routine for lossless mode Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_lhuff_decoder(j_decompress_ptr cinfo) +{ + lhuff_entropy_ptr entropy; + int i; + + entropy = (lhuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + sizeof(lhuff_entropy_decoder)); + cinfo->entropy = (struct jpeg_entropy_decoder *)entropy; + entropy->pub.start_pass = start_pass_lhuff_decoder; + entropy->pub.decode_mcus = decode_mcus; + entropy->pub.process_restart = process_restart; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/3rdparty/libjpeg-turbo/src/jdlossls.c b/3rdparty/libjpeg-turbo/src/jdlossls.c new file mode 100644 index 000000000000..4d15e6bbaf2b --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/jdlossls.c @@ -0,0 +1,289 @@ +/* + * jdlossls.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1998, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains prediction, sample undifferencing, point transform, and + * sample scaling routines for the lossless JPEG decompressor. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jlossls.h" + +#ifdef D_LOSSLESS_SUPPORTED + + +/**************** Sample undifferencing (reconstruction) *****************/ + +/* + * In order to avoid a performance penalty for checking which predictor is + * being used and which row is being processed for each call of the + * undifferencer, and to promote optimization, we have separate undifferencing + * functions for each predictor selection value. + * + * We are able to avoid duplicating source code by implementing the predictors + * and undifferencers as macros. Each of the undifferencing functions is + * simply a wrapper around an UNDIFFERENCE macro with the appropriate PREDICTOR + * macro passed as an argument. + */ + +/* Predictor for the first column of the first row: 2^(P-Pt-1) */ +#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1)) + +/* Predictor for the first column of the remaining rows: Rb */ +#define INITIAL_PREDICTOR2 prev_row[0] + + +/* + * 1-Dimensional undifferencer routine. + * + * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR + * is used as the special case predictor for the first column, which must be + * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples + * use PREDICTOR1. + * + * The reconstructed sample is supposed to be calculated modulo 2^16, so we + * logically AND the result with 0xFFFF. + */ + +#define UNDIFFERENCE_1D(INITIAL_PREDICTOR) \ + int Ra; \ + \ + Ra = (*diff_buf++ + INITIAL_PREDICTOR) & 0xFFFF; \ + *undiff_buf++ = Ra; \ + \ + while (--width) { \ + Ra = (*diff_buf++ + PREDICTOR1) & 0xFFFF; \ + *undiff_buf++ = Ra; \ + } + + +/* + * 2-Dimensional undifferencer routine. + * + * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is + * used as the special case predictor for the first column. The remaining + * samples use PREDICTOR, which is a function of Ra, Rb, and Rc. + * + * Because prev_row and output_buf may point to the same storage area (in an + * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc + * before writing the current reconstructed sample value into output_buf. + * + * The reconstructed sample is supposed to be calculated modulo 2^16, so we + * logically AND the result with 0xFFFF. + */ + +#define UNDIFFERENCE_2D(PREDICTOR) \ + int Ra, Rb, Rc; \ + \ + Rb = *prev_row++; \ + Ra = (*diff_buf++ + PREDICTOR2) & 0xFFFF; \ + *undiff_buf++ = Ra; \ + \ + while (--width) { \ + Rc = Rb; \ + Rb = *prev_row++; \ + Ra = (*diff_buf++ + PREDICTOR) & 0xFFFF; \ + *undiff_buf++ = Ra; \ + } + + +/* + * Undifferencers for the second and subsequent rows in a scan or restart + * interval. The first sample in the row is undifferenced using the vertical + * predictor (2). The rest of the samples are undifferenced using the + * predictor specified in the scan header. + */ + +METHODDEF(void) +jpeg_undifference1(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_1D(INITIAL_PREDICTOR2); +} + +METHODDEF(void) +jpeg_undifference2(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR2); + (void)(Rc); +} + +METHODDEF(void) +jpeg_undifference3(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR3); +} + +METHODDEF(void) +jpeg_undifference4(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR4); +} + +METHODDEF(void) +jpeg_undifference5(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR5); +} + +METHODDEF(void) +jpeg_undifference6(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR6); +} + +METHODDEF(void) +jpeg_undifference7(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR7); + (void)(Rc); +} + + +/* + * Undifferencer for the first row in a scan or restart interval. The first + * sample in the row is undifferenced using the special predictor constant + * x=2^(P-Pt-1). The rest of the samples are undifferenced using the + * 1-D horizontal predictor (1). + */ + +METHODDEF(void) +jpeg_undifference_first_row(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + lossless_decomp_ptr losslessd = (lossless_decomp_ptr)cinfo->idct; + + UNDIFFERENCE_1D(INITIAL_PREDICTORx); + + /* + * Now that we have undifferenced the first row, we want to use the + * undifferencer that corresponds to the predictor specified in the + * scan header. + */ + switch (cinfo->Ss) { + case 1: + losslessd->predict_undifference[comp_index] = jpeg_undifference1; + break; + case 2: + losslessd->predict_undifference[comp_index] = jpeg_undifference2; + break; + case 3: + losslessd->predict_undifference[comp_index] = jpeg_undifference3; + break; + case 4: + losslessd->predict_undifference[comp_index] = jpeg_undifference4; + break; + case 5: + losslessd->predict_undifference[comp_index] = jpeg_undifference5; + break; + case 6: + losslessd->predict_undifference[comp_index] = jpeg_undifference6; + break; + case 7: + losslessd->predict_undifference[comp_index] = jpeg_undifference7; + break; + } +} + + +/*********************** Sample upscaling by 2^Pt ************************/ + +METHODDEF(void) +simple_upscale(j_decompress_ptr cinfo, + JDIFFROW diff_buf, _JSAMPROW output_buf, JDIMENSION width) +{ + do { + *output_buf++ = (_JSAMPLE)(*diff_buf++ << cinfo->Al); + } while (--width); +} + +METHODDEF(void) +noscale(j_decompress_ptr cinfo, + JDIFFROW diff_buf, _JSAMPROW output_buf, JDIMENSION width) +{ + do { + *output_buf++ = (_JSAMPLE)(*diff_buf++); + } while (--width); +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_pass_lossless(j_decompress_ptr cinfo) +{ + lossless_decomp_ptr losslessd = (lossless_decomp_ptr)cinfo->idct; + int ci; + + /* Check that the scan parameters Ss, Se, Ah, Al are OK for lossless JPEG. + * + * Ss is the predictor selection value (psv). Legal values for sequential + * lossless JPEG are: 1 <= psv <= 7. + * + * Se and Ah are not used and should be zero. + * + * Al specifies the point transform (Pt). + * Legal values are: 0 <= Pt <= (data precision - 1). + */ + if (cinfo->Ss < 1 || cinfo->Ss > 7 || + cinfo->Se != 0 || cinfo->Ah != 0 || + cinfo->Al < 0 || cinfo->Al >= cinfo->data_precision) + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + + /* Set undifference functions to first row function */ + for (ci = 0; ci < cinfo->num_components; ci++) + losslessd->predict_undifference[ci] = jpeg_undifference_first_row; + + /* Set scaler function based on Pt */ + if (cinfo->Al) + losslessd->scaler_scale = simple_upscale; + else + losslessd->scaler_scale = noscale; +} + + +/* + * Initialize the lossless decompressor. + */ + +GLOBAL(void) +_jinit_lossless_decompressor(j_decompress_ptr cinfo) +{ + lossless_decomp_ptr losslessd; + + /* Create subobject in permanent pool */ + losslessd = (lossless_decomp_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT, + sizeof(jpeg_lossless_decompressor)); + cinfo->idct = (struct jpeg_inverse_dct *)losslessd; + losslessd->pub.start_pass = start_pass_lossless; +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/3rdparty/libjpeg-turbo/src/jdmainct.c b/3rdparty/libjpeg-turbo/src/jdmainct.c index f466b259f0d8..c672b4baf586 100644 --- a/3rdparty/libjpeg-turbo/src/jdmainct.c +++ b/3rdparty/libjpeg-turbo/src/jdmainct.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2010, 2016, D. R. Commander. + * Copyright (C) 2010, 2016, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -18,15 +18,17 @@ #include "jinclude.h" #include "jdmainct.h" -#include "jconfigint.h" +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) + /* * In the current system design, the main buffer need never be a full-image - * buffer; any full-height buffers will be found inside the coefficient or - * postprocessing controllers. Nonetheless, the main controller is not - * trivial. Its responsibility is to provide context rows for upsampling/ - * rescaling, and doing this in an efficient fashion is a bit tricky. + * buffer; any full-height buffers will be found inside the coefficient, + * difference, or postprocessing controllers. Nonetheless, the main controller + * is not trivial. Its responsibility is to provide context rows for + * upsampling/rescaling, and doing this in an efficient fashion is a bit + * tricky. * * Postprocessor input data is counted in "row groups". A row group * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) @@ -38,20 +40,20 @@ * row group (times any additional scale factor that the upsampler is * applying). * - * The coefficient controller will deliver data to us one iMCU row at a time; - * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or - * exactly min_DCT_scaled_size row groups. (This amount of data corresponds - * to one row of MCUs when the image is fully interleaved.) Note that the - * number of sample rows varies across components, but the number of row - * groups does not. Some garbage sample rows may be included in the last iMCU - * row at the bottom of the image. + * The coefficient or difference controller will deliver data to us one iMCU + * row at a time; each iMCU row contains v_samp_factor * DCT_scaled_size sample + * rows, or exactly min_DCT_scaled_size row groups. (This amount of data + * corresponds to one row of MCUs when the image is fully interleaved.) Note + * that the number of sample rows varies across components, but the number of + * row groups does not. Some garbage sample rows may be included in the last + * iMCU row at the bottom of the image. * * Depending on the vertical scaling algorithm used, the upsampler may need * access to the sample row(s) above and below its current input row group. * The upsampler is required to set need_context_rows TRUE at global selection * time if so. When need_context_rows is FALSE, this controller can simply - * obtain one iMCU row at a time from the coefficient controller and dole it - * out as row groups to the postprocessor. + * obtain one iMCU row at a time from the coefficient or difference controller + * and dole it out as row groups to the postprocessor. * * When need_context_rows is TRUE, this controller guarantees that the buffer * passed to postprocessing contains at least one row group's worth of samples @@ -114,16 +116,16 @@ /* Forward declarations */ METHODDEF(void) process_data_simple_main(j_decompress_ptr cinfo, - JSAMPARRAY output_buf, + _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); METHODDEF(void) process_data_context_main(j_decompress_ptr cinfo, - JSAMPARRAY output_buf, + _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) process_data_crank_post(j_decompress_ptr cinfo, - JSAMPARRAY output_buf, + _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); #endif @@ -139,14 +141,15 @@ alloc_funny_pointers(j_decompress_ptr cinfo) int ci, rgroup; int M = cinfo->_min_DCT_scaled_size; jpeg_component_info *compptr; - JSAMPARRAY xbuf; + _JSAMPARRAY xbuf; /* Get top-level space for component array pointers. * We alloc both arrays with one call to save a few cycles. */ - main_ptr->xbuffer[0] = (JSAMPIMAGE) + main_ptr->xbuffer[0] = (_JSAMPIMAGE) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - cinfo->num_components * 2 * sizeof(JSAMPARRAY)); + cinfo->num_components * 2 * + sizeof(_JSAMPARRAY)); main_ptr->xbuffer[1] = main_ptr->xbuffer[0] + cinfo->num_components; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; @@ -156,9 +159,9 @@ alloc_funny_pointers(j_decompress_ptr cinfo) /* Get space for pointer lists --- M+4 row groups in each list. * We alloc both pointer lists with one call to save a few cycles. */ - xbuf = (JSAMPARRAY) + xbuf = (_JSAMPARRAY) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - 2 * (rgroup * (M + 4)) * sizeof(JSAMPROW)); + 2 * (rgroup * (M + 4)) * sizeof(_JSAMPROW)); xbuf += rgroup; /* want one row group at negative offsets */ main_ptr->xbuffer[0][ci] = xbuf; xbuf += rgroup * (M + 4); @@ -180,7 +183,7 @@ make_funny_pointers(j_decompress_ptr cinfo) int ci, i, rgroup; int M = cinfo->_min_DCT_scaled_size; jpeg_component_info *compptr; - JSAMPARRAY buf, xbuf0, xbuf1; + _JSAMPARRAY buf, xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { @@ -220,7 +223,7 @@ set_bottom_pointers(j_decompress_ptr cinfo) my_main_ptr main_ptr = (my_main_ptr)cinfo->main; int ci, i, rgroup, iMCUheight, rows_left; jpeg_component_info *compptr; - JSAMPARRAY xbuf; + _JSAMPARRAY xbuf; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { @@ -259,14 +262,14 @@ start_pass_main(j_decompress_ptr cinfo, J_BUF_MODE pass_mode) switch (pass_mode) { case JBUF_PASS_THRU: if (cinfo->upsample->need_context_rows) { - main_ptr->pub.process_data = process_data_context_main; + main_ptr->pub._process_data = process_data_context_main; make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ main_ptr->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ main_ptr->context_state = CTX_PREPARE_FOR_IMCU; main_ptr->iMCU_row_ctr = 0; } else { /* Simple case with no context needed */ - main_ptr->pub.process_data = process_data_simple_main; + main_ptr->pub._process_data = process_data_simple_main; } main_ptr->buffer_full = FALSE; /* Mark buffer empty */ main_ptr->rowgroup_ctr = 0; @@ -274,7 +277,7 @@ start_pass_main(j_decompress_ptr cinfo, J_BUF_MODE pass_mode) #ifdef QUANT_2PASS_SUPPORTED case JBUF_CRANK_DEST: /* For last pass of 2-pass quantization, just crank the postprocessor */ - main_ptr->pub.process_data = process_data_crank_post; + main_ptr->pub._process_data = process_data_crank_post; break; #endif default: @@ -290,7 +293,7 @@ start_pass_main(j_decompress_ptr cinfo, J_BUF_MODE pass_mode) */ METHODDEF(void) -process_data_simple_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, +process_data_simple_main(j_decompress_ptr cinfo, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_main_ptr main_ptr = (my_main_ptr)cinfo->main; @@ -298,7 +301,7 @@ process_data_simple_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, /* Read input data if we haven't filled the main buffer yet */ if (!main_ptr->buffer_full) { - if (!(*cinfo->coef->decompress_data) (cinfo, main_ptr->buffer)) + if (!(*cinfo->coef->_decompress_data) (cinfo, main_ptr->buffer)) return; /* suspension forced, can do nothing more */ main_ptr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ } @@ -311,9 +314,9 @@ process_data_simple_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, */ /* Feed the postprocessor */ - (*cinfo->post->post_process_data) (cinfo, main_ptr->buffer, - &main_ptr->rowgroup_ctr, rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); + (*cinfo->post->_post_process_data) (cinfo, main_ptr->buffer, + &main_ptr->rowgroup_ctr, rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ if (main_ptr->rowgroup_ctr >= rowgroups_avail) { @@ -329,15 +332,15 @@ process_data_simple_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, */ METHODDEF(void) -process_data_context_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, +process_data_context_main(j_decompress_ptr cinfo, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_main_ptr main_ptr = (my_main_ptr)cinfo->main; /* Read input data if we haven't filled the main buffer yet */ if (!main_ptr->buffer_full) { - if (!(*cinfo->coef->decompress_data) (cinfo, - main_ptr->xbuffer[main_ptr->whichptr])) + if (!(*cinfo->coef->_decompress_data) (cinfo, + main_ptr->xbuffer[main_ptr->whichptr])) return; /* suspension forced, can do nothing more */ main_ptr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ main_ptr->iMCU_row_ctr++; /* count rows received */ @@ -351,11 +354,11 @@ process_data_context_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, switch (main_ptr->context_state) { case CTX_POSTPONED_ROW: /* Call postprocessor using previously set pointers for postponed row */ - (*cinfo->post->post_process_data) (cinfo, - main_ptr->xbuffer[main_ptr->whichptr], - &main_ptr->rowgroup_ctr, - main_ptr->rowgroups_avail, output_buf, - out_row_ctr, out_rows_avail); + (*cinfo->post->_post_process_data) (cinfo, + main_ptr->xbuffer[main_ptr->whichptr], + &main_ptr->rowgroup_ctr, + main_ptr->rowgroups_avail, output_buf, + out_row_ctr, out_rows_avail); if (main_ptr->rowgroup_ctr < main_ptr->rowgroups_avail) return; /* Need to suspend */ main_ptr->context_state = CTX_PREPARE_FOR_IMCU; @@ -375,11 +378,11 @@ process_data_context_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, FALLTHROUGH /*FALLTHROUGH*/ case CTX_PROCESS_IMCU: /* Call postprocessor using previously set pointers */ - (*cinfo->post->post_process_data) (cinfo, - main_ptr->xbuffer[main_ptr->whichptr], - &main_ptr->rowgroup_ctr, - main_ptr->rowgroups_avail, output_buf, - out_row_ctr, out_rows_avail); + (*cinfo->post->_post_process_data) (cinfo, + main_ptr->xbuffer[main_ptr->whichptr], + &main_ptr->rowgroup_ctr, + main_ptr->rowgroups_avail, output_buf, + out_row_ctr, out_rows_avail); if (main_ptr->rowgroup_ctr < main_ptr->rowgroups_avail) return; /* Need to suspend */ /* After the first iMCU, change wraparound pointers to normal state */ @@ -406,12 +409,12 @@ process_data_context_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf, #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) -process_data_crank_post(j_decompress_ptr cinfo, JSAMPARRAY output_buf, +process_data_crank_post(j_decompress_ptr cinfo, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { - (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE)NULL, - (JDIMENSION *)NULL, (JDIMENSION)0, - output_buf, out_row_ctr, out_rows_avail); + (*cinfo->post->_post_process_data) (cinfo, (_JSAMPIMAGE)NULL, + (JDIMENSION *)NULL, (JDIMENSION)0, + output_buf, out_row_ctr, out_rows_avail); } #endif /* QUANT_2PASS_SUPPORTED */ @@ -422,12 +425,15 @@ process_data_crank_post(j_decompress_ptr cinfo, JSAMPARRAY output_buf, */ GLOBAL(void) -jinit_d_main_controller(j_decompress_ptr cinfo, boolean need_full_buffer) +_jinit_d_main_controller(j_decompress_ptr cinfo, boolean need_full_buffer) { my_main_ptr main_ptr; int ci, rgroup, ngroups; jpeg_component_info *compptr; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + main_ptr = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_main_controller)); @@ -453,9 +459,11 @@ jinit_d_main_controller(j_decompress_ptr cinfo, boolean need_full_buffer) ci++, compptr++) { rgroup = (compptr->v_samp_factor * compptr->_DCT_scaled_size) / cinfo->_min_DCT_scaled_size; /* height of a row group of component */ - main_ptr->buffer[ci] = (*cinfo->mem->alloc_sarray) + main_ptr->buffer[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, compptr->width_in_blocks * compptr->_DCT_scaled_size, (JDIMENSION)(rgroup * ngroups)); } } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */ diff --git a/3rdparty/libjpeg-turbo/src/jdmainct.h b/3rdparty/libjpeg-turbo/src/jdmainct.h index 37b201ca8826..914ad11f694e 100644 --- a/3rdparty/libjpeg-turbo/src/jdmainct.h +++ b/3rdparty/libjpeg-turbo/src/jdmainct.h @@ -3,22 +3,27 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. */ #define JPEG_INTERNALS #include "jpeglib.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) + /* Private buffer controller object */ typedef struct { struct jpeg_d_main_controller pub; /* public fields */ /* Pointer to allocated workspace (M or M+2 row groups). */ - JSAMPARRAY buffer[MAX_COMPONENTS]; + _JSAMPARRAY buffer[MAX_COMPONENTS]; boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ @@ -26,7 +31,7 @@ typedef struct { /* Remaining fields are only used in the context case. */ /* These are the master pointers to the funny-order pointer lists. */ - JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ + _JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ int whichptr; /* indicates which pointer set is now in use */ int context_state; /* process_data state machine status */ @@ -53,7 +58,7 @@ set_wraparound_pointers(j_decompress_ptr cinfo) int ci, i, rgroup; int M = cinfo->_min_DCT_scaled_size; jpeg_component_info *compptr; - JSAMPARRAY xbuf0, xbuf1; + _JSAMPARRAY xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { @@ -69,3 +74,5 @@ set_wraparound_pointers(j_decompress_ptr cinfo) } } } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */ diff --git a/3rdparty/libjpeg-turbo/src/jdmarker.c b/3rdparty/libjpeg-turbo/src/jdmarker.c index f7eba615fd5c..acd28ce62c54 100644 --- a/3rdparty/libjpeg-turbo/src/jdmarker.c +++ b/3rdparty/libjpeg-turbo/src/jdmarker.c @@ -3,6 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1998, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright (C) 2012, 2015, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg @@ -237,7 +239,8 @@ get_soi(j_decompress_ptr cinfo) LOCAL(boolean) -get_sof(j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) +get_sof(j_decompress_ptr cinfo, boolean is_prog, boolean is_lossless, + boolean is_arith) /* Process a SOFn marker */ { JLONG length; @@ -246,6 +249,7 @@ get_sof(j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) INPUT_VARS(cinfo); cinfo->progressive_mode = is_prog; + cinfo->master->lossless = is_lossless; cinfo->arith_code = is_arith; INPUT_2BYTES(cinfo, length, return FALSE); @@ -990,32 +994,40 @@ read_markers(j_decompress_ptr cinfo) case M_SOF0: /* Baseline */ case M_SOF1: /* Extended sequential, Huffman */ - if (!get_sof(cinfo, FALSE, FALSE)) + if (!get_sof(cinfo, FALSE, FALSE, FALSE)) return JPEG_SUSPENDED; break; case M_SOF2: /* Progressive, Huffman */ - if (!get_sof(cinfo, TRUE, FALSE)) + if (!get_sof(cinfo, TRUE, FALSE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF3: /* Lossless, Huffman */ + if (!get_sof(cinfo, FALSE, TRUE, FALSE)) return JPEG_SUSPENDED; break; case M_SOF9: /* Extended sequential, arithmetic */ - if (!get_sof(cinfo, FALSE, TRUE)) + if (!get_sof(cinfo, FALSE, FALSE, TRUE)) return JPEG_SUSPENDED; break; case M_SOF10: /* Progressive, arithmetic */ - if (!get_sof(cinfo, TRUE, TRUE)) + if (!get_sof(cinfo, TRUE, FALSE, TRUE)) + return JPEG_SUSPENDED; + break; + + case M_SOF11: /* Lossless, arithmetic */ + if (!get_sof(cinfo, FALSE, TRUE, TRUE)) return JPEG_SUSPENDED; break; /* Currently unsupported SOFn types */ - case M_SOF3: /* Lossless, Huffman */ case M_SOF5: /* Differential sequential, Huffman */ case M_SOF6: /* Differential progressive, Huffman */ case M_SOF7: /* Differential lossless, Huffman */ case M_JPG: /* Reserved for JPEG extensions */ - case M_SOF11: /* Lossless, arithmetic */ case M_SOF13: /* Differential sequential, arithmetic */ case M_SOF14: /* Differential progressive, arithmetic */ case M_SOF15: /* Differential lossless, arithmetic */ diff --git a/3rdparty/libjpeg-turbo/src/jdmaster.c b/3rdparty/libjpeg-turbo/src/jdmaster.c index a3690bf560ba..80a4842ac114 100644 --- a/3rdparty/libjpeg-turbo/src/jdmaster.c +++ b/3rdparty/libjpeg-turbo/src/jdmaster.c @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2002-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2009-2011, 2016, 2019, 2022, D. R. Commander. + * Copyright (C) 2009-2011, 2016, 2019, 2022-2023, D. R. Commander. * Copyright (C) 2013, Linaro Limited. * Copyright (C) 2015, Google, Inc. * For conditions of distribution and use, see the accompanying README.ijg @@ -20,7 +22,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" #include "jdmaster.h" @@ -33,6 +35,9 @@ LOCAL(boolean) use_merged_upsample(j_decompress_ptr cinfo) { #ifdef UPSAMPLE_MERGING_SUPPORTED + /* Colorspace conversion is not supported with lossless JPEG images */ + if (cinfo->master->lossless) + return FALSE; /* Merging is the equivalent of plain box-filter upsampling */ if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) return FALSE; @@ -97,154 +102,154 @@ jpeg_core_output_dimensions(j_decompress_ptr cinfo) int ci; jpeg_component_info *compptr; - /* Compute actual output image dimensions and DCT scaling choices. */ - if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom) { - /* Provide 1/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 1; - cinfo->_min_DCT_v_scaled_size = 1; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 2) { - /* Provide 2/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 2L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 2L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 2; - cinfo->_min_DCT_v_scaled_size = 2; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 3) { - /* Provide 3/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 3L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 3L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 3; - cinfo->_min_DCT_v_scaled_size = 3; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 4) { - /* Provide 4/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 4L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 4L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 4; - cinfo->_min_DCT_v_scaled_size = 4; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 5) { - /* Provide 5/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 5L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 5L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 5; - cinfo->_min_DCT_v_scaled_size = 5; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 6) { - /* Provide 6/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 6L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 6L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 6; - cinfo->_min_DCT_v_scaled_size = 6; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 7) { - /* Provide 7/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 7L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 7L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 7; - cinfo->_min_DCT_v_scaled_size = 7; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 8) { - /* Provide 8/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 8L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 8L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 8; - cinfo->_min_DCT_v_scaled_size = 8; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 9) { - /* Provide 9/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 9L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 9L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 9; - cinfo->_min_DCT_v_scaled_size = 9; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 10) { - /* Provide 10/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 10L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 10L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 10; - cinfo->_min_DCT_v_scaled_size = 10; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 11) { - /* Provide 11/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 11L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 11L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 11; - cinfo->_min_DCT_v_scaled_size = 11; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 12) { - /* Provide 12/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 12L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 12L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 12; - cinfo->_min_DCT_v_scaled_size = 12; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 13) { - /* Provide 13/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 13L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 13L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 13; - cinfo->_min_DCT_v_scaled_size = 13; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 14) { - /* Provide 14/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 14L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 14L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 14; - cinfo->_min_DCT_v_scaled_size = 14; - } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 15) { - /* Provide 15/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 15L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 15L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 15; - cinfo->_min_DCT_v_scaled_size = 15; - } else { - /* Provide 16/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * 16L, (long)DCTSIZE); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * 16L, (long)DCTSIZE); - cinfo->_min_DCT_h_scaled_size = 16; - cinfo->_min_DCT_v_scaled_size = 16; - } + if (!cinfo->master->lossless) { + /* Compute actual output image dimensions and DCT scaling choices. */ + if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom) { + /* Provide 1/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 1; + cinfo->_min_DCT_v_scaled_size = 1; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 2) { + /* Provide 2/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 2L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 2L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 2; + cinfo->_min_DCT_v_scaled_size = 2; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 3) { + /* Provide 3/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 3L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 3L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 3; + cinfo->_min_DCT_v_scaled_size = 3; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 4) { + /* Provide 4/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 4L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 4L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 4; + cinfo->_min_DCT_v_scaled_size = 4; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 5) { + /* Provide 5/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 5L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 5L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 5; + cinfo->_min_DCT_v_scaled_size = 5; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 6) { + /* Provide 6/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 6L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 6L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 6; + cinfo->_min_DCT_v_scaled_size = 6; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 7) { + /* Provide 7/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 7L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 7L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 7; + cinfo->_min_DCT_v_scaled_size = 7; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 8) { + /* Provide 8/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 8L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 8L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 8; + cinfo->_min_DCT_v_scaled_size = 8; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 9) { + /* Provide 9/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 9L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 9L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 9; + cinfo->_min_DCT_v_scaled_size = 9; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 10) { + /* Provide 10/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 10L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 10L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 10; + cinfo->_min_DCT_v_scaled_size = 10; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 11) { + /* Provide 11/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 11L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 11L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 11; + cinfo->_min_DCT_v_scaled_size = 11; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 12) { + /* Provide 12/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 12L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 12L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 12; + cinfo->_min_DCT_v_scaled_size = 12; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 13) { + /* Provide 13/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 13L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 13L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 13; + cinfo->_min_DCT_v_scaled_size = 13; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 14) { + /* Provide 14/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 14L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 14L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 14; + cinfo->_min_DCT_v_scaled_size = 14; + } else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 15) { + /* Provide 15/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 15L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 15L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 15; + cinfo->_min_DCT_v_scaled_size = 15; + } else { + /* Provide 16/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * 16L, (long)DCTSIZE); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * 16L, (long)DCTSIZE); + cinfo->_min_DCT_h_scaled_size = 16; + cinfo->_min_DCT_v_scaled_size = 16; + } - /* Recompute dimensions of components */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - compptr->_DCT_h_scaled_size = cinfo->_min_DCT_h_scaled_size; - compptr->_DCT_v_scaled_size = cinfo->_min_DCT_v_scaled_size; + /* Recompute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->_DCT_h_scaled_size = cinfo->_min_DCT_h_scaled_size; + compptr->_DCT_v_scaled_size = cinfo->_min_DCT_v_scaled_size; + } + } else +#endif /* !IDCT_SCALING_SUPPORTED */ + { + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized DCT_scaled_size, + * and has computed unscaled downsampled_width and downsampled_height. + */ } - -#else /* !IDCT_SCALING_SUPPORTED */ - - /* Hardwire it to "no scaling" */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - /* jdinput.c has already initialized DCT_scaled_size, - * and has computed unscaled downsampled_width and downsampled_height. - */ - -#endif /* IDCT_SCALING_SUPPORTED */ } @@ -273,54 +278,56 @@ jpeg_calc_output_dimensions(j_decompress_ptr cinfo) #ifdef IDCT_SCALING_SUPPORTED - /* In selecting the actual DCT scaling for each component, we try to - * scale up the chroma components via IDCT scaling rather than upsampling. - * This saves time if the upsampler gets to use 1:1 scaling. - * Note this code adapts subsampling ratios which are powers of 2. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - int ssize = cinfo->_min_DCT_scaled_size; - while (ssize < DCTSIZE && - ((cinfo->max_h_samp_factor * cinfo->_min_DCT_scaled_size) % - (compptr->h_samp_factor * ssize * 2) == 0) && - ((cinfo->max_v_samp_factor * cinfo->_min_DCT_scaled_size) % - (compptr->v_samp_factor * ssize * 2) == 0)) { - ssize = ssize * 2; - } + if (!cinfo->master->lossless) { + /* In selecting the actual DCT scaling for each component, we try to + * scale up the chroma components via IDCT scaling rather than upsampling. + * This saves time if the upsampler gets to use 1:1 scaling. + * Note this code adapts subsampling ratios which are powers of 2. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + int ssize = cinfo->_min_DCT_scaled_size; + while (ssize < DCTSIZE && + ((cinfo->max_h_samp_factor * cinfo->_min_DCT_scaled_size) % + (compptr->h_samp_factor * ssize * 2) == 0) && + ((cinfo->max_v_samp_factor * cinfo->_min_DCT_scaled_size) % + (compptr->v_samp_factor * ssize * 2) == 0)) { + ssize = ssize * 2; + } #if JPEG_LIB_VERSION >= 70 - compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = ssize; + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size = ssize; #else - compptr->DCT_scaled_size = ssize; + compptr->DCT_scaled_size = ssize; #endif - } - - /* Recompute downsampled dimensions of components; - * application needs to know these if using raw downsampled data. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Size in samples, after IDCT scaling */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long)cinfo->image_width * - (long)(compptr->h_samp_factor * compptr->_DCT_scaled_size), - (long)(cinfo->max_h_samp_factor * DCTSIZE)); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long)cinfo->image_height * - (long)(compptr->v_samp_factor * compptr->_DCT_scaled_size), - (long)(cinfo->max_v_samp_factor * DCTSIZE)); - } - -#else /* !IDCT_SCALING_SUPPORTED */ - - /* Hardwire it to "no scaling" */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, - * and has computed unscaled downsampled_width and downsampled_height. - */ + } + /* Recompute downsampled dimensions of components; + * application needs to know these if using raw downsampled data. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Size in samples, after IDCT scaling */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long)cinfo->image_width * + (long)(compptr->h_samp_factor * + compptr->_DCT_scaled_size), + (long)(cinfo->max_h_samp_factor * DCTSIZE)); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long)cinfo->image_height * + (long)(compptr->v_samp_factor * + compptr->_DCT_scaled_size), + (long)(cinfo->max_v_samp_factor * DCTSIZE)); + } + } else #endif /* IDCT_SCALING_SUPPORTED */ + { + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, + * and has computed unscaled downsampled_width and downsampled_height. + */ + } /* Report number of components in selected colorspace. */ /* Probably this should be in the color conversion module... */ @@ -409,27 +416,83 @@ prepare_range_limit_table(j_decompress_ptr cinfo) /* Allocate and fill in the sample_range_limit table */ { JSAMPLE *table; + J12SAMPLE *table12; +#ifdef D_LOSSLESS_SUPPORTED + J16SAMPLE *table16; +#endif int i; - table = (JSAMPLE *) - (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (5 * (MAXJSAMPLE + 1) + CENTERJSAMPLE) * sizeof(JSAMPLE)); - table += (MAXJSAMPLE + 1); /* allow negative subscripts of simple table */ - cinfo->sample_range_limit = table; - /* First segment of "simple" table: limit[x] = 0 for x < 0 */ - memset(table - (MAXJSAMPLE + 1), 0, (MAXJSAMPLE + 1) * sizeof(JSAMPLE)); - /* Main part of "simple" table: limit[x] = x */ - for (i = 0; i <= MAXJSAMPLE; i++) - table[i] = (JSAMPLE)i; - table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ - /* End of simple table, rest of first half of post-IDCT table */ - for (i = CENTERJSAMPLE; i < 2 * (MAXJSAMPLE + 1); i++) - table[i] = MAXJSAMPLE; - /* Second half of post-IDCT table */ - memset(table + (2 * (MAXJSAMPLE + 1)), 0, - (2 * (MAXJSAMPLE + 1) - CENTERJSAMPLE) * sizeof(JSAMPLE)); - memcpy(table + (4 * (MAXJSAMPLE + 1) - CENTERJSAMPLE), - cinfo->sample_range_limit, CENTERJSAMPLE * sizeof(JSAMPLE)); + if (cinfo->data_precision == 16) { +#ifdef D_LOSSLESS_SUPPORTED + table16 = (J16SAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + (5 * (MAXJ16SAMPLE + 1) + CENTERJ16SAMPLE) * + sizeof(J16SAMPLE)); + table16 += (MAXJ16SAMPLE + 1); /* allow negative subscripts of simple + table */ + cinfo->sample_range_limit = (JSAMPLE *)table16; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + memset(table16 - (MAXJ16SAMPLE + 1), 0, + (MAXJ16SAMPLE + 1) * sizeof(J16SAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJ16SAMPLE; i++) + table16[i] = (J16SAMPLE)i; + table16 += CENTERJ16SAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJ16SAMPLE; i < 2 * (MAXJ16SAMPLE + 1); i++) + table16[i] = MAXJ16SAMPLE; + /* Second half of post-IDCT table */ + memset(table16 + (2 * (MAXJ16SAMPLE + 1)), 0, + (2 * (MAXJ16SAMPLE + 1) - CENTERJ16SAMPLE) * sizeof(J16SAMPLE)); + memcpy(table16 + (4 * (MAXJ16SAMPLE + 1) - CENTERJ16SAMPLE), + cinfo->sample_range_limit, CENTERJ16SAMPLE * sizeof(J16SAMPLE)); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); +#endif + } else if (cinfo->data_precision == 12) { + table12 = (J12SAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + (5 * (MAXJ12SAMPLE + 1) + CENTERJ12SAMPLE) * + sizeof(J12SAMPLE)); + table12 += (MAXJ12SAMPLE + 1); /* allow negative subscripts of simple + table */ + cinfo->sample_range_limit = (JSAMPLE *)table12; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + memset(table12 - (MAXJ12SAMPLE + 1), 0, + (MAXJ12SAMPLE + 1) * sizeof(J12SAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJ12SAMPLE; i++) + table12[i] = (J12SAMPLE)i; + table12 += CENTERJ12SAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJ12SAMPLE; i < 2 * (MAXJ12SAMPLE + 1); i++) + table12[i] = MAXJ12SAMPLE; + /* Second half of post-IDCT table */ + memset(table12 + (2 * (MAXJ12SAMPLE + 1)), 0, + (2 * (MAXJ12SAMPLE + 1) - CENTERJ12SAMPLE) * sizeof(J12SAMPLE)); + memcpy(table12 + (4 * (MAXJ12SAMPLE + 1) - CENTERJ12SAMPLE), + cinfo->sample_range_limit, CENTERJ12SAMPLE * sizeof(J12SAMPLE)); + } else { + table = (JSAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + (5 * (MAXJSAMPLE + 1) + CENTERJSAMPLE) * sizeof(JSAMPLE)); + table += (MAXJSAMPLE + 1); /* allow negative subscripts of simple table */ + cinfo->sample_range_limit = table; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + memset(table - (MAXJSAMPLE + 1), 0, (MAXJSAMPLE + 1) * sizeof(JSAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJSAMPLE; i++) + table[i] = (JSAMPLE)i; + table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJSAMPLE; i < 2 * (MAXJSAMPLE + 1); i++) + table[i] = MAXJSAMPLE; + /* Second half of post-IDCT table */ + memset(table + (2 * (MAXJSAMPLE + 1)), 0, + (2 * (MAXJSAMPLE + 1) - CENTERJSAMPLE) * sizeof(JSAMPLE)); + memcpy(table + (4 * (MAXJSAMPLE + 1) - CENTERJSAMPLE), + cinfo->sample_range_limit, CENTERJSAMPLE * sizeof(JSAMPLE)); + } } @@ -452,6 +515,17 @@ master_selection(j_decompress_ptr cinfo) long samplesperrow; JDIMENSION jd_samplesperrow; + /* Disable IDCT scaling and raw (downsampled) data output in lossless mode. + * IDCT scaling is not useful in lossless mode, and it must be disabled in + * order to properly calculate the output dimensions. Raw data output isn't + * particularly useful without subsampling and has not been tested in + * lossless mode. + */ + if (cinfo->master->lossless) { + cinfo->raw_data_out = FALSE; + cinfo->scale_num = cinfo->scale_denom = 1; + } + /* Initialize dimensions and other stuff */ jpeg_calc_output_dimensions(cinfo); prepare_range_limit_table(cinfo); @@ -480,7 +554,8 @@ master_selection(j_decompress_ptr cinfo) if (cinfo->raw_data_out) ERREXIT(cinfo, JERR_NOTIMPL); /* 2-pass quantizer only works in 3-component color space. */ - if (cinfo->out_color_components != 3) { + if (cinfo->out_color_components != 3 || + cinfo->out_color_space == JCS_RGB565) { cinfo->enable_1pass_quant = TRUE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; @@ -495,7 +570,12 @@ master_selection(j_decompress_ptr cinfo) if (cinfo->enable_1pass_quant) { #ifdef QUANT_1PASS_SUPPORTED - jinit_1pass_quantizer(cinfo); + if (cinfo->data_precision == 16) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + else if (cinfo->data_precision == 12) + j12init_1pass_quantizer(cinfo); + else + jinit_1pass_quantizer(cinfo); master->quantizer_1pass = cinfo->cquantize; #else ERREXIT(cinfo, JERR_NOT_COMPILED); @@ -505,7 +585,12 @@ master_selection(j_decompress_ptr cinfo) /* We use the 2-pass code to map to external colormaps. */ if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { #ifdef QUANT_2PASS_SUPPORTED - jinit_2pass_quantizer(cinfo); + if (cinfo->data_precision == 16) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + else if (cinfo->data_precision == 12) + j12init_2pass_quantizer(cinfo); + else + jinit_2pass_quantizer(cinfo); master->quantizer_2pass = cinfo->cquantize; #else ERREXIT(cinfo, JERR_NOT_COMPILED); @@ -520,42 +605,122 @@ master_selection(j_decompress_ptr cinfo) if (!cinfo->raw_data_out) { if (master->using_merged_upsample) { #ifdef UPSAMPLE_MERGING_SUPPORTED - jinit_merged_upsampler(cinfo); /* does color conversion too */ + if (cinfo->data_precision == 16) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + else if (cinfo->data_precision == 12) + j12init_merged_upsampler(cinfo); /* does color conversion too */ + else + jinit_merged_upsampler(cinfo); /* does color conversion too */ #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - jinit_color_deconverter(cinfo); - jinit_upsampler(cinfo); + if (cinfo->data_precision == 16) { +#ifdef D_LOSSLESS_SUPPORTED + j16init_color_deconverter(cinfo); + j16init_upsampler(cinfo); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); +#endif + } else if (cinfo->data_precision == 12) { + j12init_color_deconverter(cinfo); + j12init_upsampler(cinfo); + } else { + jinit_color_deconverter(cinfo); + jinit_upsampler(cinfo); + } } - jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); + if (cinfo->data_precision == 16) +#ifdef D_LOSSLESS_SUPPORTED + j16init_d_post_controller(cinfo, cinfo->enable_2pass_quant); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); +#endif + else if (cinfo->data_precision == 12) + j12init_d_post_controller(cinfo, cinfo->enable_2pass_quant); + else + jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); } - /* Inverse DCT */ - jinit_inverse_dct(cinfo); - /* Entropy decoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { -#ifdef D_ARITH_CODING_SUPPORTED - jinit_arith_decoder(cinfo); + + if (cinfo->master->lossless) { +#ifdef D_LOSSLESS_SUPPORTED + /* Prediction, sample undifferencing, point transform, and sample size + * scaling + */ + if (cinfo->data_precision == 16) + j16init_lossless_decompressor(cinfo); + else if (cinfo->data_precision == 12) + j12init_lossless_decompressor(cinfo); + else + jinit_lossless_decompressor(cinfo); + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + jinit_lhuff_decoder(cinfo); + } + + /* Initialize principal buffer controllers. */ + use_c_buffer = cinfo->inputctl->has_multiple_scans || + cinfo->buffered_image; + if (cinfo->data_precision == 16) + j16init_d_diff_controller(cinfo, use_c_buffer); + else if (cinfo->data_precision == 12) + j12init_d_diff_controller(cinfo, use_c_buffer); + else + jinit_d_diff_controller(cinfo, use_c_buffer); #else - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - if (cinfo->progressive_mode) { + if (cinfo->data_precision == 16) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + /* Inverse DCT */ + if (cinfo->data_precision == 12) + j12init_inverse_dct(cinfo); + else + jinit_inverse_dct(cinfo); + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef D_ARITH_CODING_SUPPORTED + jinit_arith_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + if (cinfo->progressive_mode) { #ifdef D_PROGRESSIVE_SUPPORTED - jinit_phuff_decoder(cinfo); + jinit_phuff_decoder(cinfo); #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif - } else - jinit_huff_decoder(cinfo); - } + } else + jinit_huff_decoder(cinfo); + } - /* Initialize principal buffer controllers. */ - use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; - jinit_d_coef_controller(cinfo, use_c_buffer); + /* Initialize principal buffer controllers. */ + use_c_buffer = cinfo->inputctl->has_multiple_scans || + cinfo->buffered_image; + if (cinfo->data_precision == 12) + j12init_d_coef_controller(cinfo, use_c_buffer); + else + jinit_d_coef_controller(cinfo, use_c_buffer); + } - if (!cinfo->raw_data_out) - jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); + if (!cinfo->raw_data_out) { + if (cinfo->data_precision == 16) +#ifdef D_LOSSLESS_SUPPORTED + j16init_d_main_controller(cinfo, + FALSE /* never need full buffer here */); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); +#endif + else if (cinfo->data_precision == 12) + j12init_d_main_controller(cinfo, + FALSE /* never need full buffer here */); + else + jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); + } /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo); diff --git a/3rdparty/libjpeg-turbo/src/jdmerge.c b/3rdparty/libjpeg-turbo/src/jdmerge.c index 3a456d658128..49f2006fc02a 100644 --- a/3rdparty/libjpeg-turbo/src/jdmerge.c +++ b/3rdparty/libjpeg-turbo/src/jdmerge.c @@ -5,7 +5,7 @@ * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009, 2011, 2014-2015, 2020, D. R. Commander. + * Copyright (C) 2009, 2011, 2014-2015, 2020, 2022, D. R. Commander. * Copyright (C) 2013, Linaro Limited. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -42,7 +42,6 @@ #include "jpeglib.h" #include "jdmerge.h" #include "jsimd.h" -#include "jconfigint.h" #ifdef UPSAMPLE_MERGING_SUPPORTED @@ -168,20 +167,20 @@ build_ycc_rgb_table(j_decompress_ptr cinfo) upsample->Cr_r_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(int)); + (_MAXJSAMPLE + 1) * sizeof(int)); upsample->Cb_b_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(int)); + (_MAXJSAMPLE + 1) * sizeof(int)); upsample->Cr_g_tab = (JLONG *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(JLONG)); + (_MAXJSAMPLE + 1) * sizeof(JLONG)); upsample->Cb_g_tab = (JLONG *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (MAXJSAMPLE + 1) * sizeof(JLONG)); + (_MAXJSAMPLE + 1) * sizeof(JLONG)); - for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + for (i = 0, x = -_CENTERJSAMPLE; i <= _MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0.._MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - _CENTERJSAMPLE */ /* Cr=>R value is nearest int to 1.40200 * x */ upsample->Cr_r_tab[i] = (int) RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); @@ -220,14 +219,14 @@ start_pass_merged_upsample(j_decompress_ptr cinfo) */ METHODDEF(void) -merged_2v_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +merged_2v_upsample(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, + JDIMENSION in_row_groups_avail, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) /* 2:1 vertical sampling case: may need a spare row. */ { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; - JSAMPROW work_ptrs[2]; + _JSAMPROW work_ptrs[2]; JDIMENSION num_rows; /* number of rows returned to caller */ if (upsample->spare_full) { @@ -235,8 +234,8 @@ merged_2v_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION size = upsample->out_row_width; if (cinfo->out_color_space == JCS_RGB565) size = cinfo->output_width * 2; - jcopy_sample_rows(&upsample->spare_row, 0, output_buf + *out_row_ctr, 0, 1, - size); + _jcopy_sample_rows(&upsample->spare_row, 0, output_buf + *out_row_ctr, 0, + 1, size); num_rows = 1; upsample->spare_full = FALSE; } else { @@ -271,9 +270,9 @@ merged_2v_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -merged_1v_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +merged_1v_upsample(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, + JDIMENSION in_row_groups_avail, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) /* 1:1 vertical sampling case: much easier, never need a spare row. */ { @@ -303,8 +302,8 @@ merged_1v_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -h2v1_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) +h2v1_merged_upsample(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, _JSAMPARRAY output_buf) { switch (cinfo->out_color_space) { case JCS_EXT_RGB: @@ -348,8 +347,8 @@ h2v1_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -h2v2_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) +h2v2_merged_upsample(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, _JSAMPARRAY output_buf) { switch (cinfo->out_color_space) { case JCS_EXT_RGB: @@ -475,8 +474,8 @@ static INLINE boolean is_big_endian(void) METHODDEF(void) -h2v1_merged_upsample_565(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) +h2v1_merged_upsample_565(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, _JSAMPARRAY output_buf) { if (is_big_endian()) h2v1_merged_upsample_565_be(cinfo, input_buf, in_row_group_ctr, @@ -488,8 +487,8 @@ h2v1_merged_upsample_565(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -h2v1_merged_upsample_565D(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) +h2v1_merged_upsample_565D(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, _JSAMPARRAY output_buf) { if (is_big_endian()) h2v1_merged_upsample_565D_be(cinfo, input_buf, in_row_group_ctr, @@ -501,8 +500,8 @@ h2v1_merged_upsample_565D(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -h2v2_merged_upsample_565(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) +h2v2_merged_upsample_565(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, _JSAMPARRAY output_buf) { if (is_big_endian()) h2v2_merged_upsample_565_be(cinfo, input_buf, in_row_group_ctr, @@ -514,8 +513,8 @@ h2v2_merged_upsample_565(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) -h2v2_merged_upsample_565D(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) +h2v2_merged_upsample_565D(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, _JSAMPARRAY output_buf) { if (is_big_endian()) h2v2_merged_upsample_565D_be(cinfo, input_buf, in_row_group_ctr, @@ -535,10 +534,13 @@ h2v2_merged_upsample_565D(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ GLOBAL(void) -jinit_merged_upsampler(j_decompress_ptr cinfo) +_jinit_merged_upsampler(j_decompress_ptr cinfo) { my_merged_upsample_ptr upsample; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + upsample = (my_merged_upsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_merged_upsampler)); @@ -549,10 +551,12 @@ jinit_merged_upsampler(j_decompress_ptr cinfo) upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; if (cinfo->max_v_samp_factor == 2) { - upsample->pub.upsample = merged_2v_upsample; + upsample->pub._upsample = merged_2v_upsample; +#ifdef WITH_SIMD if (jsimd_can_h2v2_merged_upsample()) upsample->upmethod = jsimd_h2v2_merged_upsample; else +#endif upsample->upmethod = h2v2_merged_upsample; if (cinfo->out_color_space == JCS_RGB565) { if (cinfo->dither_mode != JDITHER_NONE) { @@ -562,14 +566,16 @@ jinit_merged_upsampler(j_decompress_ptr cinfo) } } /* Allocate a spare row buffer */ - upsample->spare_row = (JSAMPROW) + upsample->spare_row = (_JSAMPROW) (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (size_t)(upsample->out_row_width * sizeof(JSAMPLE))); + (size_t)(upsample->out_row_width * sizeof(_JSAMPLE))); } else { - upsample->pub.upsample = merged_1v_upsample; + upsample->pub._upsample = merged_1v_upsample; +#ifdef WITH_SIMD if (jsimd_can_h2v1_merged_upsample()) upsample->upmethod = jsimd_h2v1_merged_upsample; else +#endif upsample->upmethod = h2v1_merged_upsample; if (cinfo->out_color_space == JCS_RGB565) { if (cinfo->dither_mode != JDITHER_NONE) { diff --git a/3rdparty/libjpeg-turbo/src/jdmerge.h b/3rdparty/libjpeg-turbo/src/jdmerge.h index b583396b1065..73cbd605495a 100644 --- a/3rdparty/libjpeg-turbo/src/jdmerge.h +++ b/3rdparty/libjpeg-turbo/src/jdmerge.h @@ -4,13 +4,14 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2020, D. R. Commander. + * Copyright (C) 2020, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. */ #define JPEG_INTERNALS #include "jpeglib.h" +#include "jsamplecomp.h" #ifdef UPSAMPLE_MERGING_SUPPORTED @@ -21,8 +22,8 @@ typedef struct { struct jpeg_upsampler pub; /* public fields */ /* Pointer to routine to do actual upsampling/conversion of one row group */ - void (*upmethod) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf); + void (*upmethod) (j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, + JDIMENSION in_row_group_ctr, _JSAMPARRAY output_buf); /* Private state for YCC->RGB conversion */ int *Cr_r_tab; /* => table for Cr to R conversion */ @@ -35,7 +36,7 @@ typedef struct { * application provides just a one-row buffer; we also use the spare * to discard the dummy last row if the image height is odd. */ - JSAMPROW spare_row; + _JSAMPROW spare_row; boolean spare_full; /* T if spare buffer is occupied */ JDIMENSION out_row_width; /* samples per output row */ diff --git a/3rdparty/libjpeg-turbo/src/jdmrg565.c b/3rdparty/libjpeg-turbo/src/jdmrg565.c index 980a4e216e4d..0c719b912ce6 100644 --- a/3rdparty/libjpeg-turbo/src/jdmrg565.c +++ b/3rdparty/libjpeg-turbo/src/jdmrg565.c @@ -5,7 +5,7 @@ * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: * Copyright (C) 2013, Linaro Limited. - * Copyright (C) 2014-2015, 2018, 2020, D. R. Commander. + * Copyright (C) 2014-2015, 2018, 2020, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -15,18 +15,19 @@ INLINE LOCAL(void) -h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, + _JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + _JSAMPARRAY output_buf) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; - register JSAMPROW outptr; - JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + _JSAMPROW inptr0, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int *Crrtab = upsample->Cr_r_tab; int *Cbbtab = upsample->Cb_b_tab; JLONG *Crgtab = upsample->Cr_g_tab; @@ -86,18 +87,18 @@ h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) h2v1_merged_upsample_565D_internal(j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, + _JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + _JSAMPARRAY output_buf) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; - register JSAMPROW outptr; - JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + _JSAMPROW inptr0, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int *Crrtab = upsample->Cr_r_tab; int *Cbbtab = upsample->Cb_b_tab; JLONG *Crgtab = upsample->Cr_g_tab; @@ -159,18 +160,18 @@ h2v1_merged_upsample_565D_internal(j_decompress_ptr cinfo, INLINE LOCAL(void) -h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + _JSAMPARRAY output_buf) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; - register JSAMPROW outptr0, outptr1; - JSAMPROW inptr00, inptr01, inptr1, inptr2; + register _JSAMPROW outptr0, outptr1; + _JSAMPROW inptr00, inptr01, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int *Crrtab = upsample->Cr_r_tab; int *Cbbtab = upsample->Cb_b_tab; JLONG *Crgtab = upsample->Cr_g_tab; @@ -255,18 +256,18 @@ h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) h2v2_merged_upsample_565D_internal(j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, + _JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + _JSAMPARRAY output_buf) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; - register JSAMPROW outptr0, outptr1; - JSAMPROW inptr00, inptr01, inptr1, inptr2; + register _JSAMPROW outptr0, outptr1; + _JSAMPROW inptr00, inptr01, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int *Crrtab = upsample->Cr_r_tab; int *Cbbtab = upsample->Cb_b_tab; JLONG *Crgtab = upsample->Cr_g_tab; diff --git a/3rdparty/libjpeg-turbo/src/jdmrgext.c b/3rdparty/libjpeg-turbo/src/jdmrgext.c index 9bf4f1a307f3..8139e0a3ed65 100644 --- a/3rdparty/libjpeg-turbo/src/jdmrgext.c +++ b/3rdparty/libjpeg-turbo/src/jdmrgext.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2011, 2015, 2020, D. R. Commander. + * Copyright (C) 2011, 2015, 2020, 2022-2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -21,18 +21,18 @@ INLINE LOCAL(void) -h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +h2v1_merged_upsample_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + _JSAMPARRAY output_buf) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; - register JSAMPROW outptr; - JSAMPROW inptr0, inptr1, inptr2; + register _JSAMPROW outptr; + _JSAMPROW inptr0, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int *Crrtab = upsample->Cr_r_tab; int *Cbbtab = upsample->Cb_b_tab; JLONG *Crgtab = upsample->Cr_g_tab; @@ -57,7 +57,7 @@ h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr[RGB_GREEN] = range_limit[y + cgreen]; outptr[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr[RGB_ALPHA] = 0xFF; + outptr[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr += RGB_PIXELSIZE; y = *inptr0++; @@ -65,7 +65,7 @@ h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr[RGB_GREEN] = range_limit[y + cgreen]; outptr[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr[RGB_ALPHA] = 0xFF; + outptr[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr += RGB_PIXELSIZE; } @@ -81,7 +81,7 @@ h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr[RGB_GREEN] = range_limit[y + cgreen]; outptr[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr[RGB_ALPHA] = 0xFF; + outptr[RGB_ALPHA] = _MAXJSAMPLE; #endif } } @@ -93,18 +93,18 @@ h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, INLINE LOCAL(void) -h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +h2v2_merged_upsample_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + _JSAMPARRAY output_buf) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; - register JSAMPROW outptr0, outptr1; - JSAMPROW inptr00, inptr01, inptr1, inptr2; + register _JSAMPROW outptr0, outptr1; + _JSAMPROW inptr00, inptr01, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ - register JSAMPLE *range_limit = cinfo->sample_range_limit; + register _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int *Crrtab = upsample->Cr_r_tab; int *Cbbtab = upsample->Cb_b_tab; JLONG *Crgtab = upsample->Cr_g_tab; @@ -131,7 +131,7 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr0[RGB_ALPHA] = 0xFF; + outptr0[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr0 += RGB_PIXELSIZE; y = *inptr00++; @@ -139,7 +139,7 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr0[RGB_ALPHA] = 0xFF; + outptr0[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr0 += RGB_PIXELSIZE; y = *inptr01++; @@ -147,7 +147,7 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr1[RGB_ALPHA] = 0xFF; + outptr1[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr1 += RGB_PIXELSIZE; y = *inptr01++; @@ -155,7 +155,7 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr1[RGB_ALPHA] = 0xFF; + outptr1[RGB_ALPHA] = _MAXJSAMPLE; #endif outptr1 += RGB_PIXELSIZE; } @@ -171,14 +171,14 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr0[RGB_ALPHA] = 0xFF; + outptr0[RGB_ALPHA] = _MAXJSAMPLE; #endif y = *inptr01; outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA - outptr1[RGB_ALPHA] = 0xFF; + outptr1[RGB_ALPHA] = _MAXJSAMPLE; #endif } } diff --git a/3rdparty/libjpeg-turbo/src/jdphuff.c b/3rdparty/libjpeg-turbo/src/jdphuff.c index 9680ebcbd06e..bf97333a34c0 100644 --- a/3rdparty/libjpeg-turbo/src/jdphuff.c +++ b/3rdparty/libjpeg-turbo/src/jdphuff.c @@ -3,6 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1995-1997, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: * Copyright (C) 2015-2016, 2018-2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg @@ -23,7 +25,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jdhuff.h" /* Declarations shared with jdhuff.c */ +#include "jdhuff.h" /* Declarations shared with jd*huff.c */ #include diff --git a/3rdparty/libjpeg-turbo/src/jdpostct.c b/3rdparty/libjpeg-turbo/src/jdpostct.c index 6a2cf5c1b31e..d38495f5f316 100644 --- a/3rdparty/libjpeg-turbo/src/jdpostct.c +++ b/3rdparty/libjpeg-turbo/src/jdpostct.c @@ -3,8 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. - * It was modified by The libjpeg-turbo Project to include only code relevant - * to libjpeg-turbo. + * libjpeg-turbo Modifications: + * Copyright (C) 2022-2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -22,8 +22,11 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) + /* Private buffer controller object */ typedef struct { @@ -35,7 +38,7 @@ typedef struct { * for one-pass operation, a strip buffer is sufficient. */ jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ - JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ + _JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ JDIMENSION strip_height; /* buffer size in rows */ /* for two-pass mode only: */ JDIMENSION starting_row; /* row # of first row in current strip */ @@ -46,26 +49,28 @@ typedef my_post_controller *my_post_ptr; /* Forward declarations */ +#if BITS_IN_JSAMPLE != 16 METHODDEF(void) post_process_1pass(j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, + _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, + _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); -#ifdef QUANT_2PASS_SUPPORTED +#endif +#if defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 METHODDEF(void) post_process_prepass(j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, + _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, + _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); METHODDEF(void) post_process_2pass(j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, + _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, + _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); #endif @@ -82,39 +87,42 @@ start_pass_dpost(j_decompress_ptr cinfo, J_BUF_MODE pass_mode) switch (pass_mode) { case JBUF_PASS_THRU: +#if BITS_IN_JSAMPLE != 16 if (cinfo->quantize_colors) { /* Single-pass processing with color quantization. */ - post->pub.post_process_data = post_process_1pass; + post->pub._post_process_data = post_process_1pass; /* We could be doing buffered-image output before starting a 2-pass * color quantization; in that case, jinit_d_post_controller did not * allocate a strip buffer. Use the virtual-array buffer as workspace. */ if (post->buffer == NULL) { - post->buffer = (*cinfo->mem->access_virt_sarray) + post->buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) ((j_common_ptr)cinfo, post->whole_image, (JDIMENSION)0, post->strip_height, TRUE); } - } else { + } else +#endif + { /* For single-pass processing without color quantization, * I have no work to do; just call the upsampler directly. */ - post->pub.post_process_data = cinfo->upsample->upsample; + post->pub._post_process_data = cinfo->upsample->_upsample; } break; -#ifdef QUANT_2PASS_SUPPORTED +#if defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 case JBUF_SAVE_AND_PASS: /* First pass of 2-pass quantization */ if (post->whole_image == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - post->pub.post_process_data = post_process_prepass; + post->pub._post_process_data = post_process_prepass; break; case JBUF_CRANK_DEST: /* Second pass of 2-pass quantization */ if (post->whole_image == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - post->pub.post_process_data = post_process_2pass; + post->pub._post_process_data = post_process_2pass; break; -#endif /* QUANT_2PASS_SUPPORTED */ +#endif /* defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 */ default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; @@ -128,10 +136,12 @@ start_pass_dpost(j_decompress_ptr cinfo, J_BUF_MODE pass_mode) * This is used for color precision reduction as well as one-pass quantization. */ +#if BITS_IN_JSAMPLE != 16 + METHODDEF(void) -post_process_1pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +post_process_1pass(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, + JDIMENSION in_row_groups_avail, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr)cinfo->post; @@ -143,27 +153,29 @@ post_process_1pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, if (max_rows > post->strip_height) max_rows = post->strip_height; num_rows = 0; - (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr, - in_row_groups_avail, post->buffer, &num_rows, - max_rows); + (*cinfo->upsample->_upsample) (cinfo, input_buf, in_row_group_ctr, + in_row_groups_avail, post->buffer, &num_rows, + max_rows); /* Quantize and emit data. */ - (*cinfo->cquantize->color_quantize) (cinfo, post->buffer, - output_buf + *out_row_ctr, - (int)num_rows); + (*cinfo->cquantize->_color_quantize) (cinfo, post->buffer, + output_buf + *out_row_ctr, + (int)num_rows); *out_row_ctr += num_rows; } +#endif -#ifdef QUANT_2PASS_SUPPORTED + +#if defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 /* * Process some data in the first pass of 2-pass quantization. */ METHODDEF(void) -post_process_prepass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +post_process_prepass(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, + JDIMENSION in_row_groups_avail, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr)cinfo->post; @@ -171,23 +183,23 @@ post_process_prepass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, /* Reposition virtual buffer if at start of strip. */ if (post->next_row == 0) { - post->buffer = (*cinfo->mem->access_virt_sarray) + post->buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) ((j_common_ptr)cinfo, post->whole_image, post->starting_row, post->strip_height, TRUE); } /* Upsample some data (up to a strip height's worth). */ old_next_row = post->next_row; - (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr, - in_row_groups_avail, post->buffer, - &post->next_row, post->strip_height); + (*cinfo->upsample->_upsample) (cinfo, input_buf, in_row_group_ctr, + in_row_groups_avail, post->buffer, + &post->next_row, post->strip_height); /* Allow quantizer to scan new data. No data is emitted, */ /* but we advance out_row_ctr so outer loop can tell when we're done. */ if (post->next_row > old_next_row) { num_rows = post->next_row - old_next_row; - (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, - (JSAMPARRAY)NULL, (int)num_rows); + (*cinfo->cquantize->_color_quantize) (cinfo, post->buffer + old_next_row, + (_JSAMPARRAY)NULL, (int)num_rows); *out_row_ctr += num_rows; } @@ -204,9 +216,9 @@ post_process_prepass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ METHODDEF(void) -post_process_2pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +post_process_2pass(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, + JDIMENSION in_row_groups_avail, _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr)cinfo->post; @@ -214,7 +226,7 @@ post_process_2pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, /* Reposition virtual buffer if at start of strip. */ if (post->next_row == 0) { - post->buffer = (*cinfo->mem->access_virt_sarray) + post->buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) ((j_common_ptr)cinfo, post->whole_image, post->starting_row, post->strip_height, FALSE); } @@ -230,9 +242,9 @@ post_process_2pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, num_rows = max_rows; /* Quantize and emit data. */ - (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + post->next_row, - output_buf + *out_row_ctr, - (int)num_rows); + (*cinfo->cquantize->_color_quantize) (cinfo, post->buffer + post->next_row, + output_buf + *out_row_ctr, + (int)num_rows); *out_row_ctr += num_rows; /* Advance if we filled the strip. */ @@ -243,7 +255,7 @@ post_process_2pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, } } -#endif /* QUANT_2PASS_SUPPORTED */ +#endif /* defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 */ /* @@ -251,10 +263,13 @@ post_process_2pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, */ GLOBAL(void) -jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer) +_jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer) { my_post_ptr post; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + post = (my_post_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_post_controller)); @@ -265,6 +280,7 @@ jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer) /* Create the quantization buffer, if needed */ if (cinfo->quantize_colors) { +#if BITS_IN_JSAMPLE != 16 /* The buffer strip height is max_v_samp_factor, which is typically * an efficient number of rows for upsampling to return. * (In the presence of output rescaling, we might want to be smarter?) @@ -285,10 +301,15 @@ jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer) #endif /* QUANT_2PASS_SUPPORTED */ } else { /* One-pass color quantization: just make a strip buffer. */ - post->buffer = (*cinfo->mem->alloc_sarray) + post->buffer = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, cinfo->output_width * cinfo->out_color_components, post->strip_height); } +#else + ERREXIT(cinfo, JERR_NOTIMPL); +#endif } } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */ diff --git a/3rdparty/libjpeg-turbo/src/jdsample.c b/3rdparty/libjpeg-turbo/src/jdsample.c index eaad72a03089..cc8015c97d72 100644 --- a/3rdparty/libjpeg-turbo/src/jdsample.c +++ b/3rdparty/libjpeg-turbo/src/jdsample.c @@ -5,7 +5,7 @@ * Copyright (C) 1991-1996, Thomas G. Lane. * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2010, 2015-2016, D. R. Commander. + * Copyright (C) 2010, 2015-2016, 2022, D. R. Commander. * Copyright (C) 2014, MIPS Technologies, Inc., California. * Copyright (C) 2015, Google, Inc. * Copyright (C) 2019-2020, Arm Limited. @@ -28,10 +28,12 @@ #include "jinclude.h" #include "jdsample.h" #include "jsimd.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) + /* * Initialize for an upsampling pass. */ @@ -57,9 +59,9 @@ start_pass_upsample(j_decompress_ptr cinfo) */ METHODDEF(void) -sep_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, +sep_upsample(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample; @@ -95,9 +97,10 @@ sep_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, if (num_rows > out_rows_avail) num_rows = out_rows_avail; - (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, - (JDIMENSION)upsample->next_row_out, - output_buf + *out_row_ctr, (int)num_rows); + (*cinfo->cconvert->_color_convert) (cinfo, upsample->color_buf, + (JDIMENSION)upsample->next_row_out, + output_buf + *out_row_ctr, + (int)num_rows); /* Adjust counts */ *out_row_ctr += num_rows; @@ -124,7 +127,7 @@ sep_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, METHODDEF(void) fullsize_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { *output_data_ptr = input_data; } @@ -137,7 +140,7 @@ fullsize_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) noop_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { *output_data_ptr = NULL; /* safety check */ } @@ -156,14 +159,14 @@ noop_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample; - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; + _JSAMPARRAY output_data = *output_data_ptr; + register _JSAMPROW inptr, outptr; + register _JSAMPLE invalue; register int h; - JSAMPROW outend; + _JSAMPROW outend; int h_expand, v_expand; int inrow, outrow; @@ -184,8 +187,8 @@ int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, } /* Generate any additional output rows by duplicating the first one */ if (v_expand > 1) { - jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, - v_expand - 1, cinfo->output_width); + _jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, + v_expand - 1, cinfo->output_width); } inrow++; outrow += v_expand; @@ -200,12 +203,12 @@ int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - JSAMPROW outend; + _JSAMPARRAY output_data = *output_data_ptr; + register _JSAMPROW inptr, outptr; + register _JSAMPLE invalue; + _JSAMPROW outend; int inrow; for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { @@ -228,12 +231,12 @@ h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - JSAMPROW outend; + _JSAMPARRAY output_data = *output_data_ptr; + register _JSAMPROW inptr, outptr; + register _JSAMPLE invalue; + _JSAMPROW outend; int inrow, outrow; inrow = outrow = 0; @@ -246,8 +249,8 @@ h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, *outptr++ = invalue; *outptr++ = invalue; } - jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, 1, - cinfo->output_width); + _jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, 1, + cinfo->output_width); inrow++; outrow += 2; } @@ -271,10 +274,10 @@ h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; + _JSAMPARRAY output_data = *output_data_ptr; + register _JSAMPROW inptr, outptr; register int invalue; register JDIMENSION colctr; int inrow; @@ -284,20 +287,20 @@ h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, outptr = output_data[inrow]; /* Special case for first column */ invalue = *inptr++; - *outptr++ = (JSAMPLE)invalue; - *outptr++ = (JSAMPLE)((invalue * 3 + inptr[0] + 2) >> 2); + *outptr++ = (_JSAMPLE)invalue; + *outptr++ = (_JSAMPLE)((invalue * 3 + inptr[0] + 2) >> 2); for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ invalue = (*inptr++) * 3; - *outptr++ = (JSAMPLE)((invalue + inptr[-2] + 1) >> 2); - *outptr++ = (JSAMPLE)((invalue + inptr[0] + 2) >> 2); + *outptr++ = (_JSAMPLE)((invalue + inptr[-2] + 1) >> 2); + *outptr++ = (_JSAMPLE)((invalue + inptr[0] + 2) >> 2); } /* Special case for last column */ invalue = *inptr; - *outptr++ = (JSAMPLE)((invalue * 3 + inptr[-1] + 1) >> 2); - *outptr++ = (JSAMPLE)invalue; + *outptr++ = (_JSAMPLE)((invalue * 3 + inptr[-1] + 1) >> 2); + *outptr++ = (_JSAMPLE)invalue; } } @@ -311,10 +314,10 @@ h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { - JSAMPARRAY output_data = *output_data_ptr; - JSAMPROW inptr0, inptr1, outptr; + _JSAMPARRAY output_data = *output_data_ptr; + _JSAMPROW inptr0, inptr1, outptr; #if BITS_IN_JSAMPLE == 8 int thiscolsum, bias; #else @@ -339,7 +342,7 @@ h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, for (colctr = 0; colctr < compptr->downsampled_width; colctr++) { thiscolsum = (*inptr0++) * 3 + (*inptr1++); - *outptr++ = (JSAMPLE)((thiscolsum + bias) >> 2); + *outptr++ = (_JSAMPLE)((thiscolsum + bias) >> 2); } } inrow++; @@ -357,10 +360,10 @@ h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, METHODDEF(void) h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) + _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) { - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr0, inptr1, outptr; + _JSAMPARRAY output_data = *output_data_ptr; + register _JSAMPROW inptr0, inptr1, outptr; #if BITS_IN_JSAMPLE == 8 register int thiscolsum, lastcolsum, nextcolsum; #else @@ -383,22 +386,22 @@ h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, /* Special case for first column */ thiscolsum = (*inptr0++) * 3 + (*inptr1++); nextcolsum = (*inptr0++) * 3 + (*inptr1++); - *outptr++ = (JSAMPLE)((thiscolsum * 4 + 8) >> 4); - *outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4); + *outptr++ = (_JSAMPLE)((thiscolsum * 4 + 8) >> 4); + *outptr++ = (_JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4); lastcolsum = thiscolsum; thiscolsum = nextcolsum; for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ nextcolsum = (*inptr0++) * 3 + (*inptr1++); - *outptr++ = (JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4); + *outptr++ = (_JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (_JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4); lastcolsum = thiscolsum; thiscolsum = nextcolsum; } /* Special case for last column */ - *outptr++ = (JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE)((thiscolsum * 4 + 7) >> 4); + *outptr++ = (_JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (_JSAMPLE)((thiscolsum * 4 + 7) >> 4); } inrow++; } @@ -410,7 +413,7 @@ h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jinit_upsampler(j_decompress_ptr cinfo) +_jinit_upsampler(j_decompress_ptr cinfo) { my_upsample_ptr upsample; int ci; @@ -418,13 +421,16 @@ jinit_upsampler(j_decompress_ptr cinfo) boolean need_buffer, do_fancy; int h_in_group, v_in_group, h_out_group, v_out_group; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + if (!cinfo->master->jinit_upsampler_no_alloc) { upsample = (my_upsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_upsampler)); cinfo->upsample = (struct jpeg_upsampler *)upsample; upsample->pub.start_pass = start_pass_upsample; - upsample->pub.upsample = sep_upsample; + upsample->pub._upsample = sep_upsample; upsample->pub.need_context_rows = FALSE; /* until we find out differently */ } else upsample = (my_upsample_ptr)cinfo->upsample; @@ -464,21 +470,25 @@ jinit_upsampler(j_decompress_ptr cinfo) } else if (h_in_group * 2 == h_out_group && v_in_group == v_out_group) { /* Special cases for 2h1v upsampling */ if (do_fancy && compptr->downsampled_width > 2) { +#ifdef WITH_SIMD if (jsimd_can_h2v1_fancy_upsample()) upsample->methods[ci] = jsimd_h2v1_fancy_upsample; else +#endif upsample->methods[ci] = h2v1_fancy_upsample; } else { +#ifdef WITH_SIMD if (jsimd_can_h2v1_upsample()) upsample->methods[ci] = jsimd_h2v1_upsample; else +#endif upsample->methods[ci] = h2v1_upsample; } } else if (h_in_group == h_out_group && v_in_group * 2 == v_out_group && do_fancy) { /* Non-fancy upsampling is handled by the generic method */ -#if defined(__arm__) || defined(__aarch64__) || \ - defined(_M_ARM) || defined(_M_ARM64) +#if defined(WITH_SIMD) && (defined(__arm__) || defined(__aarch64__) || \ + defined(_M_ARM) || defined(_M_ARM64)) if (jsimd_can_h1v2_fancy_upsample()) upsample->methods[ci] = jsimd_h1v2_fancy_upsample; else @@ -489,21 +499,25 @@ jinit_upsampler(j_decompress_ptr cinfo) v_in_group * 2 == v_out_group) { /* Special cases for 2h2v upsampling */ if (do_fancy && compptr->downsampled_width > 2) { +#ifdef WITH_SIMD if (jsimd_can_h2v2_fancy_upsample()) upsample->methods[ci] = jsimd_h2v2_fancy_upsample; else +#endif upsample->methods[ci] = h2v2_fancy_upsample; upsample->pub.need_context_rows = TRUE; } else { +#ifdef WITH_SIMD if (jsimd_can_h2v2_upsample()) upsample->methods[ci] = jsimd_h2v2_upsample; else +#endif upsample->methods[ci] = h2v2_upsample; } } else if ((h_out_group % h_in_group) == 0 && (v_out_group % v_in_group) == 0) { /* Generic integral-factors upsampling method */ -#if defined(__mips__) +#if defined(WITH_SIMD) && defined(__mips__) if (jsimd_can_int_upsample()) upsample->methods[ci] = jsimd_int_upsample; else @@ -514,7 +528,7 @@ jinit_upsampler(j_decompress_ptr cinfo) } else ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); if (need_buffer && !cinfo->master->jinit_upsampler_no_alloc) { - upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) + upsample->color_buf[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)jround_up((long)cinfo->output_width, (long)cinfo->max_h_samp_factor), @@ -522,3 +536,5 @@ jinit_upsampler(j_decompress_ptr cinfo) } } } + +#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */ diff --git a/3rdparty/libjpeg-turbo/src/jdsample.h b/3rdparty/libjpeg-turbo/src/jdsample.h index a6bf08a032ac..a8a929809402 100644 --- a/3rdparty/libjpeg-turbo/src/jdsample.h +++ b/3rdparty/libjpeg-turbo/src/jdsample.h @@ -3,19 +3,22 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. */ #define JPEG_INTERNALS #include "jpeglib.h" +#include "jsamplecomp.h" /* Pointer to routine to upsample a single component */ typedef void (*upsample1_ptr) (j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, - JSAMPARRAY *output_data_ptr); + _JSAMPARRAY input_data, + _JSAMPARRAY *output_data_ptr); /* Private subobject */ @@ -29,7 +32,7 @@ typedef struct { * ie do not need rescaling. The corresponding entry of color_buf[] is * simply set to point to the input data array, thereby avoiding copying. */ - JSAMPARRAY color_buf[MAX_COMPONENTS]; + _JSAMPARRAY color_buf[MAX_COMPONENTS]; /* Per-component upsampling method pointers */ upsample1_ptr methods[MAX_COMPONENTS]; diff --git a/3rdparty/libjpeg-turbo/src/jdtrans.c b/3rdparty/libjpeg-turbo/src/jdtrans.c index d7ec4b83b3a4..719813f67672 100644 --- a/3rdparty/libjpeg-turbo/src/jdtrans.c +++ b/3rdparty/libjpeg-turbo/src/jdtrans.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1995-1997, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2020, D. R. Commander. + * Copyright (C) 2020, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -16,7 +16,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jpegcomp.h" +#include "jpegapicomp.h" /* Forward declarations */ @@ -48,6 +48,9 @@ LOCAL(void) transdecode_master_selection(j_decompress_ptr cinfo); GLOBAL(jvirt_barray_ptr *) jpeg_read_coefficients(j_decompress_ptr cinfo) { + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_NOTIMPL); + if (cinfo->global_state == DSTATE_READY) { /* First call: initialize active modules */ transdecode_master_selection(cinfo); @@ -127,7 +130,10 @@ transdecode_master_selection(j_decompress_ptr cinfo) } /* Always get a full-image coefficient buffer. */ - jinit_d_coef_controller(cinfo, TRUE); + if (cinfo->data_precision == 12) + j12init_d_coef_controller(cinfo, TRUE); + else + jinit_d_coef_controller(cinfo, TRUE); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo); diff --git a/3rdparty/libjpeg-turbo/src/jerror.c b/3rdparty/libjpeg-turbo/src/jerror.c index d54470293758..3a75fec02c17 100644 --- a/3rdparty/libjpeg-turbo/src/jerror.c +++ b/3rdparty/libjpeg-turbo/src/jerror.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1998, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2022, D. R. Commander. + * Copyright (C) 2022, 2024, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -46,7 +46,7 @@ #define JMESSAGE(code, string) string, -const char * const jpeg_std_message_table[] = { +static const char * const jpeg_std_message_table[] = { #include "jerror.h" NULL }; @@ -189,9 +189,9 @@ format_message(j_common_ptr cinfo, char *buffer) /* Format the message into the passed buffer */ if (isstring) - snprintf(buffer, JMSG_LENGTH_MAX, msgtext, err->msg_parm.s); + SNPRINTF(buffer, JMSG_LENGTH_MAX, msgtext, err->msg_parm.s); else - snprintf(buffer, JMSG_LENGTH_MAX, msgtext, + SNPRINTF(buffer, JMSG_LENGTH_MAX, msgtext, err->msg_parm.i[0], err->msg_parm.i[1], err->msg_parm.i[2], err->msg_parm.i[3], err->msg_parm.i[4], err->msg_parm.i[5], @@ -229,23 +229,17 @@ reset_error_mgr(j_common_ptr cinfo) GLOBAL(struct jpeg_error_mgr *) jpeg_std_error(struct jpeg_error_mgr *err) { + memset(err, 0, sizeof(struct jpeg_error_mgr)); + err->error_exit = error_exit; err->emit_message = emit_message; err->output_message = output_message; err->format_message = format_message; err->reset_error_mgr = reset_error_mgr; - err->trace_level = 0; /* default = no tracing */ - err->num_warnings = 0; /* no warnings emitted yet */ - err->msg_code = 0; /* may be useful as a flag for "no error" */ - /* Initialize message table pointers */ err->jpeg_message_table = jpeg_std_message_table; err->last_jpeg_message = (int)JMSG_LASTMSGCODE - 1; - err->addon_message_table = NULL; - err->first_addon_message = 0; /* for safety */ - err->last_addon_message = 0; - return err; } diff --git a/3rdparty/libjpeg-turbo/src/jerror.h b/3rdparty/libjpeg-turbo/src/jerror.h index eb44a1140a2e..71ba03e2a3ed 100644 --- a/3rdparty/libjpeg-turbo/src/jerror.h +++ b/3rdparty/libjpeg-turbo/src/jerror.h @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1997, Thomas G. Lane. * Modified 1997-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2014, 2017, 2021-2022, D. R. Commander. + * Copyright (C) 2014, 2017, 2021-2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -53,7 +55,8 @@ JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") #if JPEG_LIB_VERSION >= 70 JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") #endif -JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCT_COEF, + "DCT coefficient (lossy) or spatial difference (lossless) out of range") JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") #if JPEG_LIB_VERSION >= 70 JMESSAGE(JERR_BAD_DROP_SAMPLING, @@ -69,9 +72,9 @@ JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") JMESSAGE(JERR_BAD_PROGRESSION, - "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") + "Invalid progressive/lossless parameters Ss=%d Se=%d Ah=%d Al=%d") JMESSAGE(JERR_BAD_PROG_SCRIPT, - "Invalid progressive parameters at scan script entry %d") + "Invalid progressive/lossless parameters at scan script entry %d") JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") @@ -108,7 +111,7 @@ JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") #if JPEG_LIB_VERSION >= 70 JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") #endif -JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_BACKING_STORE, "Memory limit exceeded") JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") @@ -180,7 +183,7 @@ JMESSAGE(JTRC_THUMB_PALETTE, JMESSAGE(JTRC_THUMB_RGB, "JFIF extension marker: RGB thumbnail image, length %u") JMESSAGE(JTRC_UNKNOWN_IDS, - "Unrecognized component IDs %d %d %d, assuming YCbCr") + "Unrecognized component IDs %d %d %d, assuming YCbCr (lossy) or RGB (lossless)") JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") @@ -211,6 +214,8 @@ JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker") JMESSAGE(JERR_BAD_DROP_SAMPLING, "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") #endif +JMESSAGE(JERR_BAD_RESTART, + "Invalid restart interval %d; must be an integer multiple of the number of MCUs in an MCU row (%d)") #ifdef JMAKE_ENUM_LIST diff --git a/3rdparty/libjpeg-turbo/src/jfdctfst.c b/3rdparty/libjpeg-turbo/src/jfdctfst.c index 4c9ce0de8faa..26070d19a620 100644 --- a/3rdparty/libjpeg-turbo/src/jfdctfst.c +++ b/3rdparty/libjpeg-turbo/src/jfdctfst.c @@ -114,7 +114,7 @@ */ GLOBAL(void) -jpeg_fdct_ifast(DCTELEM *data) +_jpeg_fdct_ifast(DCTELEM *data) { DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; DCTELEM tmp10, tmp11, tmp12, tmp13; diff --git a/3rdparty/libjpeg-turbo/src/jfdctint.c b/3rdparty/libjpeg-turbo/src/jfdctint.c index c95a3a7fb8a6..974013fa409c 100644 --- a/3rdparty/libjpeg-turbo/src/jfdctint.c +++ b/3rdparty/libjpeg-turbo/src/jfdctint.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2015, 2020, D. R. Commander. + * Copyright (C) 2015, 2020, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -140,7 +140,7 @@ */ GLOBAL(void) -jpeg_fdct_islow(DCTELEM *data) +_jpeg_fdct_islow(DCTELEM *data) { JLONG tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; JLONG tmp10, tmp11, tmp12, tmp13; diff --git a/3rdparty/libjpeg-turbo/src/jidctflt.c b/3rdparty/libjpeg-turbo/src/jidctflt.c index 5aee74e2321e..ee3a31a61682 100644 --- a/3rdparty/libjpeg-turbo/src/jidctflt.c +++ b/3rdparty/libjpeg-turbo/src/jidctflt.c @@ -5,7 +5,7 @@ * Copyright (C) 1994-1998, Thomas G. Lane. * Modified 2010 by Guido Vollbeding. * libjpeg-turbo Modifications: - * Copyright (C) 2014, D. R. Commander. + * Copyright (C) 2014, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -69,9 +69,9 @@ */ GLOBAL(void) -jpeg_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; FAST_FLOAT tmp10, tmp11, tmp12, tmp13; @@ -79,8 +79,8 @@ jpeg_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; FLOAT_MULT_TYPE *quantptr; FAST_FLOAT *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = cinfo->sample_range_limit; + _JSAMPROW outptr; + _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int ctr; FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ #define _0_125 ((FLOAT_MULT_TYPE)0.125) @@ -192,7 +192,7 @@ jpeg_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr, /* Even part */ /* Apply signed->unsigned and prepare float->int conversion */ - z5 = wsptr[0] + ((FAST_FLOAT)CENTERJSAMPLE + (FAST_FLOAT)0.5); + z5 = wsptr[0] + ((FAST_FLOAT)_CENTERJSAMPLE + (FAST_FLOAT)0.5); tmp10 = z5 + wsptr[4]; tmp11 = z5 - wsptr[4]; diff --git a/3rdparty/libjpeg-turbo/src/jidctfst.c b/3rdparty/libjpeg-turbo/src/jidctfst.c index 89a20c937bbe..68119b9942be 100644 --- a/3rdparty/libjpeg-turbo/src/jidctfst.c +++ b/3rdparty/libjpeg-turbo/src/jidctfst.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1998, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2015, D. R. Commander. + * Copyright (C) 2015, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -64,10 +64,10 @@ * The dequantized coefficients are not integers because the AA&N scaling * factors have been incorporated. We represent them scaled up by PASS1_BITS, * so that the first and second IDCT rounds have the same input scaling. - * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to + * For 8-bit samples, we choose IFAST_SCALE_BITS = PASS1_BITS so as to * avoid a descaling shift; this compromises accuracy rather drastically * for small quantization table entries, but it saves a lot of shifts. - * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, + * For 12-bit samples, there's no hope of using 16x16 multiplies anyway, * so we use a much larger scaling factor to preserve accuracy. * * A final compromise is to represent the multiplicative constants to only @@ -168,9 +168,9 @@ */ GLOBAL(void) -jpeg_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; DCTELEM tmp10, tmp11, tmp12, tmp13; @@ -178,8 +178,8 @@ jpeg_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; IFAST_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS /* for DESCALE */ @@ -296,7 +296,7 @@ jpeg_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr, if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ - JSAMPLE dcval = + _JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS + 3) & RANGE_MASK]; outptr[0] = dcval; diff --git a/3rdparty/libjpeg-turbo/src/jidctint.c b/3rdparty/libjpeg-turbo/src/jidctint.c index bb0874801920..c58592d626d8 100644 --- a/3rdparty/libjpeg-turbo/src/jidctint.c +++ b/3rdparty/libjpeg-turbo/src/jidctint.c @@ -5,7 +5,7 @@ * Copyright (C) 1991-1998, Thomas G. Lane. * Modification developed 2002-2018 by Guido Vollbeding. * libjpeg-turbo Modifications: - * Copyright (C) 2015, 2020, D. R. Commander. + * Copyright (C) 2015, 2020, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -170,9 +170,9 @@ */ GLOBAL(void) -jpeg_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp1, tmp2, tmp3; JLONG tmp10, tmp11, tmp12, tmp13; @@ -180,8 +180,8 @@ jpeg_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS @@ -314,8 +314,8 @@ jpeg_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr, if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0], - PASS1_BITS + 3) & RANGE_MASK]; + _JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0], + PASS1_BITS + 3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; @@ -424,17 +424,17 @@ jpeg_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_7x7(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_7x7(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp1, tmp2, tmp10, tmp11, tmp12, tmp13; JLONG z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[7 * 7]; /* buffers data between passes */ SHIFT_TEMPS @@ -573,17 +573,17 @@ jpeg_idct_7x7(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_6x6(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_6x6(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; JLONG z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[6 * 6]; /* buffers data between passes */ SHIFT_TEMPS @@ -694,17 +694,17 @@ jpeg_idct_6x6(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_5x5(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_5x5(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp1, tmp10, tmp11, tmp12; JLONG z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[5 * 5]; /* buffers data between passes */ SHIFT_TEMPS @@ -809,16 +809,16 @@ jpeg_idct_5x5(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_3x3(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_3x3(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp2, tmp10, tmp12; JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[3 * 3]; /* buffers data between passes */ SHIFT_TEMPS @@ -899,17 +899,17 @@ jpeg_idct_3x3(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_9x9(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_9x9(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13, tmp14; JLONG z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 9]; /* buffers data between passes */ SHIFT_TEMPS @@ -1070,9 +1070,9 @@ jpeg_idct_9x9(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_10x10(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_10x10(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp10, tmp11, tmp12, tmp13, tmp14; JLONG tmp20, tmp21, tmp22, tmp23, tmp24; @@ -1080,8 +1080,8 @@ jpeg_idct_10x10(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 10]; /* buffers data between passes */ SHIFT_TEMPS @@ -1265,9 +1265,9 @@ jpeg_idct_10x10(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_11x11(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_11x11(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp10, tmp11, tmp12, tmp13, tmp14; JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; @@ -1275,8 +1275,8 @@ jpeg_idct_11x11(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 11]; /* buffers data between passes */ SHIFT_TEMPS @@ -1459,9 +1459,9 @@ jpeg_idct_11x11(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_12x12(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_12x12(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; @@ -1469,8 +1469,8 @@ jpeg_idct_12x12(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 12]; /* buffers data between passes */ SHIFT_TEMPS @@ -1675,9 +1675,9 @@ jpeg_idct_12x12(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_13x13(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_13x13(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; @@ -1685,8 +1685,8 @@ jpeg_idct_13x13(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 13]; /* buffers data between passes */ SHIFT_TEMPS @@ -1903,9 +1903,9 @@ jpeg_idct_13x13(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_14x14(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_14x14(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; @@ -1913,8 +1913,8 @@ jpeg_idct_14x14(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 14]; /* buffers data between passes */ SHIFT_TEMPS @@ -2129,9 +2129,9 @@ jpeg_idct_14x14(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_15x15(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_15x15(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; @@ -2139,8 +2139,8 @@ jpeg_idct_15x15(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 15]; /* buffers data between passes */ SHIFT_TEMPS @@ -2371,9 +2371,9 @@ jpeg_idct_15x15(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_16x16(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_16x16(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; @@ -2381,8 +2381,8 @@ jpeg_idct_16x16(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8 * 16]; /* buffers data between passes */ SHIFT_TEMPS diff --git a/3rdparty/libjpeg-turbo/src/jidctred.c b/3rdparty/libjpeg-turbo/src/jidctred.c index 1dd65a94d975..6521e3ebbfc7 100644 --- a/3rdparty/libjpeg-turbo/src/jidctred.c +++ b/3rdparty/libjpeg-turbo/src/jidctred.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1998, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2015, D. R. Commander. + * Copyright (C) 2015, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -118,17 +118,17 @@ */ GLOBAL(void) -jpeg_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp2, tmp10, tmp12; JLONG z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE * 4]; /* buffers data between passes */ SHIFT_TEMPS @@ -210,8 +210,8 @@ jpeg_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr, if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0], - PASS1_BITS + 3) & RANGE_MASK]; + _JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0], + PASS1_BITS + 3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; @@ -276,16 +276,16 @@ jpeg_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { JLONG tmp0, tmp10, z1; JCOEFPTR inptr; ISLOW_MULT_TYPE *quantptr; int *wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPROW outptr; + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE * 2]; /* buffers data between passes */ SHIFT_TEMPS @@ -345,8 +345,8 @@ jpeg_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr, #ifndef NO_ZERO_ROW_TEST if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0], - PASS1_BITS + 3) & RANGE_MASK]; + _JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0], + PASS1_BITS + 3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; @@ -387,13 +387,13 @@ jpeg_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr, */ GLOBAL(void) -jpeg_idct_1x1(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) +_jpeg_idct_1x1(j_decompress_ptr cinfo, jpeg_component_info *compptr, + JCOEFPTR coef_block, _JSAMPARRAY output_buf, + JDIMENSION output_col) { int dcval; ISLOW_MULT_TYPE *quantptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + _JSAMPLE *range_limit = IDCT_range_limit(cinfo); SHIFT_TEMPS /* We hardly need an inverse DCT routine for this: just take the diff --git a/3rdparty/libjpeg-turbo/src/jinclude.h b/3rdparty/libjpeg-turbo/src/jinclude.h index 120614b25cf3..56e7a4b296d2 100644 --- a/3rdparty/libjpeg-turbo/src/jinclude.h +++ b/3rdparty/libjpeg-turbo/src/jinclude.h @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1994, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2022, D. R. Commander. + * Copyright (C) 2022-2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -45,6 +45,18 @@ */ +#ifdef _MSC_VER + +#define SNPRINTF(str, n, format, ...) \ + _snprintf_s(str, n, _TRUNCATE, format, ##__VA_ARGS__) + +#else + +#define SNPRINTF snprintf + +#endif + + #ifndef NO_GETENV #ifdef _MSC_VER @@ -111,6 +123,8 @@ static INLINE int GETENV_S(char *buffer, size_t buffer_size, const char *name) #else +#include + /* This provides a similar interface to the Microsoft _putenv_s() function, but * other than parameter validation, it has no advantages over setenv(). */ diff --git a/3rdparty/libjpeg-turbo/src/jlossls.h b/3rdparty/libjpeg-turbo/src/jlossls.h new file mode 100644 index 000000000000..ce4170413452 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/jlossls.h @@ -0,0 +1,101 @@ +/* + * jlossls.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1998, Thomas G. Lane. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This include file contains common declarations for the lossless JPEG + * codec modules. + */ + +#ifndef JLOSSLS_H +#define JLOSSLS_H + +#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) + +#define JPEG_INTERNALS +#include "jpeglib.h" +#include "jsamplecomp.h" + + +#define ALLOC_DARRAY(pool_id, diffsperrow, numrows) \ + (JDIFFARRAY)(*cinfo->mem->alloc_sarray) \ + ((j_common_ptr)cinfo, pool_id, \ + (diffsperrow) * sizeof(JDIFF) / sizeof(_JSAMPLE), numrows) + + +/* + * Table H.1: Predictors for lossless coding. + */ + +#define PREDICTOR1 Ra +#define PREDICTOR2 Rb +#define PREDICTOR3 Rc +#define PREDICTOR4 (int)((JLONG)Ra + (JLONG)Rb - (JLONG)Rc) +#define PREDICTOR5 (int)((JLONG)Ra + RIGHT_SHIFT((JLONG)Rb - (JLONG)Rc, 1)) +#define PREDICTOR6 (int)((JLONG)Rb + RIGHT_SHIFT((JLONG)Ra - (JLONG)Rc, 1)) +#define PREDICTOR7 (int)RIGHT_SHIFT((JLONG)Ra + (JLONG)Rb, 1) + +#endif + + +#ifdef C_LOSSLESS_SUPPORTED + +typedef void (*predict_difference_method_ptr) (j_compress_ptr cinfo, int ci, + _JSAMPROW input_buf, + _JSAMPROW prev_row, + JDIFFROW diff_buf, + JDIMENSION width); + +/* Lossless compressor */ +typedef struct { + struct jpeg_forward_dct pub; /* public fields */ + + /* It is useful to allow each component to have a separate diff method. */ + predict_difference_method_ptr predict_difference[MAX_COMPONENTS]; + + /* MCU rows left in the restart interval for each component */ + unsigned int restart_rows_to_go[MAX_COMPONENTS]; + + /* Sample scaling */ + void (*scaler_scale) (j_compress_ptr cinfo, _JSAMPROW input_buf, + _JSAMPROW output_buf, JDIMENSION width); +} jpeg_lossless_compressor; + +typedef jpeg_lossless_compressor *lossless_comp_ptr; + +#endif /* C_LOSSLESS_SUPPORTED */ + + +#ifdef D_LOSSLESS_SUPPORTED + +typedef void (*predict_undifference_method_ptr) (j_decompress_ptr cinfo, + int comp_index, + JDIFFROW diff_buf, + JDIFFROW prev_row, + JDIFFROW undiff_buf, + JDIMENSION width); + +/* Lossless decompressor */ +typedef struct { + struct jpeg_inverse_dct pub; /* public fields */ + + /* It is useful to allow each component to have a separate undiff method. */ + predict_undifference_method_ptr predict_undifference[MAX_COMPONENTS]; + + /* Sample scaling */ + void (*scaler_scale) (j_decompress_ptr cinfo, JDIFFROW diff_buf, + _JSAMPROW output_buf, JDIMENSION width); +} jpeg_lossless_decompressor; + +typedef jpeg_lossless_decompressor *lossless_decomp_ptr; + +#endif /* D_LOSSLESS_SUPPORTED */ + +#endif /* JLOSSLS_H */ diff --git a/3rdparty/libjpeg-turbo/src/jmemmgr.c b/3rdparty/libjpeg-turbo/src/jmemmgr.c index 8f5a4ab1c78b..dca8f5c22ca7 100644 --- a/3rdparty/libjpeg-turbo/src/jmemmgr.c +++ b/3rdparty/libjpeg-turbo/src/jmemmgr.c @@ -68,10 +68,13 @@ round_up_pow2(size_t a, size_t b) * There isn't any really portable way to determine the worst-case alignment * requirement. This module assumes that the alignment requirement is * multiples of ALIGN_SIZE. - * By default, we define ALIGN_SIZE as sizeof(double). This is necessary on - * some workstations (where doubles really do need 8-byte alignment) and will - * work fine on nearly everything. If your machine has lesser alignment needs, - * you can save a few bytes by making ALIGN_SIZE smaller. + * By default, we define ALIGN_SIZE as the maximum of sizeof(double) and + * sizeof(void *). This is necessary on some workstations (where doubles + * really do need 8-byte alignment) and will work fine on nearly everything. + * We use the maximum of sizeof(double) and sizeof(void *) since sizeof(double) + * may be insufficient, for example, on CHERI-enabled platforms with 16-byte + * pointers and a 16-byte alignment requirement. If your machine has lesser + * alignment needs, you can save a few bytes by making ALIGN_SIZE smaller. * The only place I know of where this will NOT work is certain Macintosh * 680x0 compilers that define double as a 10-byte IEEE extended float. * Doing 10-byte alignment is counterproductive because longwords won't be @@ -81,7 +84,7 @@ round_up_pow2(size_t a, size_t b) #ifndef ALIGN_SIZE /* so can override from jconfig.h */ #ifndef WITH_SIMD -#define ALIGN_SIZE sizeof(double) +#define ALIGN_SIZE MAX(sizeof(void *), sizeof(double)) #else #define ALIGN_SIZE 32 /* Most of the SIMD instructions we support require 16-byte (128-bit) alignment, but AVX2 requires @@ -152,7 +155,9 @@ typedef my_memory_mgr *my_mem_ptr; */ struct jvirt_sarray_control { - JSAMPARRAY mem_buffer; /* => the in-memory buffer */ + JSAMPARRAY mem_buffer; /* => the in-memory buffer (if + cinfo->data_precision is 12, then this is + actually a J12SAMPARRAY) */ JDIMENSION rows_in_array; /* total virtual array height */ JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ @@ -348,9 +353,10 @@ alloc_small(j_common_ptr cinfo, int pool_id, size_t sizeofobject) * request is large enough that it may as well be passed directly to * jpeg_get_large; the pool management just links everything together * so that we can free it all on demand. - * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY - * structures. The routines that create these structures (see below) - * deliberately bunch rows together to ensure a large request size. + * Note: the major use of "large" objects is in + * JSAMPARRAY/J12SAMPARRAY/J16SAMPARRAY and JBLOCKARRAY structures. The + * routines that create these structures (see below) deliberately bunch rows + * together to ensure a large request size. */ METHODDEF(void *) @@ -434,9 +440,22 @@ alloc_sarray(j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JSAMPROW workspace; JDIMENSION rowsperchunk, currow, i; long ltemp; + J12SAMPARRAY result12; + J12SAMPROW workspace12; +#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) + J16SAMPARRAY result16; + J16SAMPROW workspace16; +#endif + int data_precision = cinfo->is_decompressor ? + ((j_decompress_ptr)cinfo)->data_precision : + ((j_compress_ptr)cinfo)->data_precision; + size_t sample_size = data_precision == 16 ? + sizeof(J16SAMPLE) : (data_precision == 12 ? + sizeof(J12SAMPLE) : + sizeof(JSAMPLE)); /* Make sure each row is properly aligned */ - if ((ALIGN_SIZE % sizeof(JSAMPLE)) != 0) + if ((ALIGN_SIZE % sample_size) != 0) out_of_memory(cinfo, 5); /* safety check */ if (samplesperrow > MAX_ALLOC_CHUNK) { @@ -445,11 +464,11 @@ alloc_sarray(j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, out_of_memory(cinfo, 9); } samplesperrow = (JDIMENSION)round_up_pow2(samplesperrow, (2 * ALIGN_SIZE) / - sizeof(JSAMPLE)); + sample_size); /* Calculate max # of rows allowed in one allocation chunk */ ltemp = (MAX_ALLOC_CHUNK - sizeof(large_pool_hdr)) / - ((long)samplesperrow * sizeof(JSAMPLE)); + ((long)samplesperrow * (long)sample_size); if (ltemp <= 0) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); if (ltemp < (long)numrows) @@ -458,24 +477,68 @@ alloc_sarray(j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, rowsperchunk = numrows; mem->last_rowsperchunk = rowsperchunk; - /* Get space for row pointers (small object) */ - result = (JSAMPARRAY)alloc_small(cinfo, pool_id, - (size_t)(numrows * sizeof(JSAMPROW))); + if (data_precision == 16) { +#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) + /* Get space for row pointers (small object) */ + result16 = (J16SAMPARRAY)alloc_small(cinfo, pool_id, + (size_t)(numrows * + sizeof(J16SAMPROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace16 = (J16SAMPROW)alloc_large(cinfo, pool_id, + (size_t)((size_t)rowsperchunk * (size_t)samplesperrow * sample_size)); + for (i = rowsperchunk; i > 0; i--) { + result16[currow++] = workspace16; + workspace16 += samplesperrow; + } + } - /* Get the rows themselves (large objects) */ - currow = 0; - while (currow < numrows) { - rowsperchunk = MIN(rowsperchunk, numrows - currow); - workspace = (JSAMPROW)alloc_large(cinfo, pool_id, - (size_t)((size_t)rowsperchunk * (size_t)samplesperrow * - sizeof(JSAMPLE))); - for (i = rowsperchunk; i > 0; i--) { - result[currow++] = workspace; - workspace += samplesperrow; + return (JSAMPARRAY)result16; +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, data_precision); + return NULL; +#endif + } else if (data_precision == 12) { + /* Get space for row pointers (small object) */ + result12 = (J12SAMPARRAY)alloc_small(cinfo, pool_id, + (size_t)(numrows * + sizeof(J12SAMPROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace12 = (J12SAMPROW)alloc_large(cinfo, pool_id, + (size_t)((size_t)rowsperchunk * (size_t)samplesperrow * sample_size)); + for (i = rowsperchunk; i > 0; i--) { + result12[currow++] = workspace12; + workspace12 += samplesperrow; + } } - } - return result; + return (JSAMPARRAY)result12; + } else { + /* Get space for row pointers (small object) */ + result = (JSAMPARRAY)alloc_small(cinfo, pool_id, + (size_t)(numrows * sizeof(JSAMPROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JSAMPROW)alloc_large(cinfo, pool_id, + (size_t)((size_t)rowsperchunk * (size_t)samplesperrow * sample_size)); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += samplesperrow; + } + } + + return result; + } } @@ -637,6 +700,13 @@ realize_virt_arrays(j_common_ptr cinfo) size_t minheights, max_minheights; jvirt_sarray_ptr sptr; jvirt_barray_ptr bptr; + int data_precision = cinfo->is_decompressor ? + ((j_decompress_ptr)cinfo)->data_precision : + ((j_compress_ptr)cinfo)->data_precision; + size_t sample_size = data_precision == 16 ? + sizeof(J16SAMPLE) : (data_precision == 12 ? + sizeof(J12SAMPLE) : + sizeof(JSAMPLE)); /* Compute the minimum space needed (maxaccess rows in each buffer) * and the maximum space needed (full image height in each buffer). @@ -647,10 +717,10 @@ realize_virt_arrays(j_common_ptr cinfo) for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->mem_buffer == NULL) { /* if not realized yet */ size_t new_space = (long)sptr->rows_in_array * - (long)sptr->samplesperrow * sizeof(JSAMPLE); + (long)sptr->samplesperrow * sample_size; space_per_minheight += (long)sptr->maxaccess * - (long)sptr->samplesperrow * sizeof(JSAMPLE); + (long)sptr->samplesperrow * sample_size; if (SIZE_MAX - maximum_space < new_space) out_of_memory(cinfo, 10); maximum_space += new_space; @@ -705,7 +775,7 @@ realize_virt_arrays(j_common_ptr cinfo) jpeg_open_backing_store(cinfo, &sptr->b_s_info, (long)sptr->rows_in_array * (long)sptr->samplesperrow * - (long)sizeof(JSAMPLE)); + (long)sample_size); sptr->b_s_open = TRUE; } sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, @@ -748,8 +818,15 @@ do_sarray_io(j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) /* Do backing store read or write of a virtual sample array */ { long bytesperrow, file_offset, byte_count, rows, thisrow, i; - - bytesperrow = (long)ptr->samplesperrow * sizeof(JSAMPLE); + int data_precision = cinfo->is_decompressor ? + ((j_decompress_ptr)cinfo)->data_precision : + ((j_compress_ptr)cinfo)->data_precision; + size_t sample_size = data_precision == 16 ? + sizeof(J16SAMPLE) : (data_precision == 12 ? + sizeof(J12SAMPLE) : + sizeof(JSAMPLE)); + + bytesperrow = (long)ptr->samplesperrow * (long)sample_size; file_offset = ptr->cur_start_row * bytesperrow; /* Loop to read or write each allocation chunk in mem_buffer */ for (i = 0; i < (long)ptr->rows_in_mem; i += ptr->rowsperchunk) { @@ -763,14 +840,42 @@ do_sarray_io(j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) if (rows <= 0) /* this chunk might be past end of file! */ break; byte_count = rows * bytesperrow; - if (writing) - (*ptr->b_s_info.write_backing_store) (cinfo, &ptr->b_s_info, - (void *)ptr->mem_buffer[i], - file_offset, byte_count); - else - (*ptr->b_s_info.read_backing_store) (cinfo, &ptr->b_s_info, - (void *)ptr->mem_buffer[i], - file_offset, byte_count); + if (data_precision == 16) { +#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) + J16SAMPARRAY mem_buffer16 = (J16SAMPARRAY)ptr->mem_buffer; + + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, &ptr->b_s_info, + (void *)mem_buffer16[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, &ptr->b_s_info, + (void *)mem_buffer16[i], + file_offset, byte_count); +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, data_precision); +#endif + } else if (data_precision == 12) { + J12SAMPARRAY mem_buffer12 = (J12SAMPARRAY)ptr->mem_buffer; + + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, &ptr->b_s_info, + (void *)mem_buffer12[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, &ptr->b_s_info, + (void *)mem_buffer12[i], + file_offset, byte_count); + } else { + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, &ptr->b_s_info, + (void *)ptr->mem_buffer[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, &ptr->b_s_info, + (void *)ptr->mem_buffer[i], + file_offset, byte_count); + } file_offset += byte_count; } } @@ -818,6 +923,13 @@ access_virt_sarray(j_common_ptr cinfo, jvirt_sarray_ptr ptr, { JDIMENSION end_row = start_row + num_rows; JDIMENSION undef_row; + int data_precision = cinfo->is_decompressor ? + ((j_decompress_ptr)cinfo)->data_precision : + ((j_compress_ptr)cinfo)->data_precision; + size_t sample_size = data_precision == 16 ? + sizeof(J16SAMPLE) : (data_precision == 12 ? + sizeof(J12SAMPLE) : + sizeof(JSAMPLE)); /* debugging check */ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || @@ -873,7 +985,7 @@ access_virt_sarray(j_common_ptr cinfo, jvirt_sarray_ptr ptr, if (writable) ptr->first_undef_row = end_row; if (ptr->pre_zero) { - size_t bytesperrow = (size_t)ptr->samplesperrow * sizeof(JSAMPLE); + size_t bytesperrow = (size_t)ptr->samplesperrow * sample_size; undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ end_row -= ptr->cur_start_row; while (undef_row < end_row) { diff --git a/3rdparty/libjpeg-turbo/src/jmemsys.h b/3rdparty/libjpeg-turbo/src/jmemsys.h index 9229550afde0..ac09ef4c36d3 100644 --- a/3rdparty/libjpeg-turbo/src/jmemsys.h +++ b/3rdparty/libjpeg-turbo/src/jmemsys.h @@ -99,24 +99,6 @@ EXTERN(size_t) jpeg_mem_available(j_common_ptr cinfo, size_t min_bytes_needed, #define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ -#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ - -typedef unsigned short XMSH; /* type of extended-memory handles */ -typedef unsigned short EMSH; /* type of expanded-memory handles */ - -typedef union { - short file_handle; /* DOS file handle if it's a temp file */ - XMSH xms_handle; /* handle if it's a chunk of XMS */ - EMSH ems_handle; /* handle if it's a chunk of EMS */ -} handle_union; - -#endif /* USE_MSDOS_MEMMGR */ - -#ifdef USE_MAC_MEMMGR /* Mac-specific junk */ -#include -#endif /* USE_MAC_MEMMGR */ - - typedef struct backing_store_struct *backing_store_ptr; typedef struct backing_store_struct { @@ -130,22 +112,9 @@ typedef struct backing_store_struct { void (*close_backing_store) (j_common_ptr cinfo, backing_store_ptr info); /* Private fields for system-dependent backing-store management */ -#ifdef USE_MSDOS_MEMMGR - /* For the MS-DOS manager (jmemdos.c), we need: */ - handle_union handle; /* reference to backing-store storage object */ - char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ -#else -#ifdef USE_MAC_MEMMGR - /* For the Mac manager (jmemmac.c), we need: */ - short temp_file; /* file reference number to temp file */ - FSSpec tempSpec; /* the FSSpec for the temp file */ - char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ -#else /* For a typical implementation with temp files, we need: */ FILE *temp_file; /* stdio reference to temp file */ char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ -#endif -#endif } backing_store_info; diff --git a/3rdparty/libjpeg-turbo/src/jmorecfg.h b/3rdparty/libjpeg-turbo/src/jmorecfg.h index b33a991914ee..89c7842c8716 100644 --- a/3rdparty/libjpeg-turbo/src/jmorecfg.h +++ b/3rdparty/libjpeg-turbo/src/jmorecfg.h @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 1997-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2009, 2011, 2014-2015, 2018, 2020, D. R. Commander. + * Copyright (C) 2009, 2011, 2014-2015, 2018, 2020, 2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -41,31 +43,29 @@ * arrays is very slow on your hardware, you might want to change these. */ -#if BITS_IN_JSAMPLE == 8 -/* JSAMPLE should be the smallest type that will hold the values 0..255. - */ +/* JSAMPLE should be the smallest type that will hold the values 0..255. */ typedef unsigned char JSAMPLE; #define GETJSAMPLE(value) ((int)(value)) -#define MAXJSAMPLE 255 -#define CENTERJSAMPLE 128 +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 -#endif /* BITS_IN_JSAMPLE == 8 */ +/* J12SAMPLE should be the smallest type that will hold the values 0..4095. */ -#if BITS_IN_JSAMPLE == 12 -/* JSAMPLE should be the smallest type that will hold the values 0..4095. - * On nearly all machines "short" will do nicely. - */ +typedef short J12SAMPLE; -typedef short JSAMPLE; -#define GETJSAMPLE(value) ((int)(value)) +#define MAXJ12SAMPLE 4095 +#define CENTERJ12SAMPLE 2048 + + +/* J16SAMPLE should be the smallest type that will hold the values 0..65535. */ -#define MAXJSAMPLE 4095 -#define CENTERJSAMPLE 2048 +typedef unsigned short J16SAMPLE; -#endif /* BITS_IN_JSAMPLE == 12 */ +#define MAXJ16SAMPLE 65535 +#define CENTERJ16SAMPLE 32768 /* Representation of a DCT frequency coefficient. @@ -242,14 +242,16 @@ typedef int boolean; #define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define C_LOSSLESS_SUPPORTED /* Lossless JPEG? */ #define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ /* Note: if you selected 12-bit data precision, it is dangerous to turn off * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit * precision, so jchuff.c normally uses entropy optimization to compute * usable tables for higher precision. If you don't want to do optimization, * you'll have to supply different default Huffman tables. - * The exact same statements apply for progressive JPEG: the default tables - * don't work for progressive mode. (This may get fixed, however.) + * The exact same statements apply for progressive and lossless JPEG: + * the default tables don't work for progressive mode or lossless mode. + * (This may get fixed, however.) */ #define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ @@ -257,6 +259,7 @@ typedef int boolean; #define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define D_LOSSLESS_SUPPORTED /* Lossless JPEG? */ #define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ #define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ #define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ diff --git a/3rdparty/libjpeg-turbo/src/jpeg_nbits_table.h b/3rdparty/libjpeg-turbo/src/jpeg_nbits.c similarity index 99% rename from 3rdparty/libjpeg-turbo/src/jpeg_nbits_table.h rename to 3rdparty/libjpeg-turbo/src/jpeg_nbits.c index fcf73878c318..c8ee6b056cbf 100644 --- a/3rdparty/libjpeg-turbo/src/jpeg_nbits_table.h +++ b/3rdparty/libjpeg-turbo/src/jpeg_nbits.c @@ -1,4 +1,32 @@ -static const unsigned char jpeg_nbits_table[65536] = { +/* + * Copyright (C) 2024, D. R. Commander. + * + * For conditions of distribution and use, see the accompanying README.ijg + * file. + */ + +#include "jpeg_nbits.h" +#include "jconfigint.h" + + +#ifndef USE_CLZ_INTRINSIC + +#define INCLUDE_JPEG_NBITS_TABLE + +/* When building for x86[-64] with the SIMD extensions enabled, the C Huffman + * encoders can reuse jpeg_nbits_table from the SSE2 baseline Huffman encoder. + */ +#if (defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || \ + defined(_M_X64)) && defined(WITH_SIMD) +#undef INCLUDE_JPEG_NBITS_TABLE +#endif + +#endif + + +#ifdef INCLUDE_JPEG_NBITS_TABLE + +const unsigned char HIDDEN jpeg_nbits_table[65536] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, @@ -4096,3 +4124,11 @@ static const unsigned char jpeg_nbits_table[65536] = { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; + +#else + +/* Suppress compiler warnings about empty translation unit. */ + +typedef int dummy_jpeg_nbits_table; + +#endif diff --git a/3rdparty/libjpeg-turbo/src/jpeg_nbits.h b/3rdparty/libjpeg-turbo/src/jpeg_nbits.h new file mode 100644 index 000000000000..6481a1228d18 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/jpeg_nbits.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2014, 2021, 2024, D. R. Commander. + * Copyright (C) 2014, Olle Liljenzin. + * Copyright (C) 2020, Arm Limited. + * + * For conditions of distribution and use, see the accompanying README.ijg + * file. + */ + +/* + * NOTE: If USE_CLZ_INTRINSIC is defined, then clz/bsr instructions will be + * used for bit counting rather than the lookup table. This will reduce the + * memory footprint by 64k, which is important for some mobile applications + * that create many isolated instances of libjpeg-turbo (web browsers, for + * instance.) This may improve performance on some mobile platforms as well. + * This feature is enabled by default only on Arm processors, because some x86 + * chips have a slow implementation of bsr, and the use of clz/bsr cannot be + * shown to have a significant performance impact even on the x86 chips that + * have a fast implementation of it. When building for Armv6, you can + * explicitly disable the use of clz/bsr by adding -mthumb to the compiler + * flags (this defines __thumb__). + */ + +/* NOTE: Both GCC and Clang define __GNUC__ */ +#if (defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))) || \ + defined(_M_ARM) || defined(_M_ARM64) +#if !defined(__thumb__) || defined(__thumb2__) +#define USE_CLZ_INTRINSIC +#endif +#endif + +#ifdef USE_CLZ_INTRINSIC +#if defined(_MSC_VER) && !defined(__clang__) +#define JPEG_NBITS_NONZERO(x) (32 - _CountLeadingZeros(x)) +#else +#define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x)) +#endif +#define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0) +#else +extern const unsigned char jpeg_nbits_table[65536]; +#define JPEG_NBITS(x) (jpeg_nbits_table[x]) +#define JPEG_NBITS_NONZERO(x) JPEG_NBITS(x) +#endif diff --git a/3rdparty/libjpeg-turbo/src/jpegcomp.h b/3rdparty/libjpeg-turbo/src/jpegapicomp.h similarity index 98% rename from 3rdparty/libjpeg-turbo/src/jpegcomp.h rename to 3rdparty/libjpeg-turbo/src/jpegapicomp.h index c4834ac0df9d..bb3912eb2f16 100644 --- a/3rdparty/libjpeg-turbo/src/jpegcomp.h +++ b/3rdparty/libjpeg-turbo/src/jpegapicomp.h @@ -1,5 +1,5 @@ /* - * jpegcomp.h + * jpegapicomp.h * * Copyright (C) 2010, 2020, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg diff --git a/3rdparty/libjpeg-turbo/src/jpegint.h b/3rdparty/libjpeg-turbo/src/jpegint.h index 6af9e2a179e8..654142014349 100644 --- a/3rdparty/libjpeg-turbo/src/jpegint.h +++ b/3rdparty/libjpeg-turbo/src/jpegint.h @@ -4,8 +4,10 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 1997-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2015-2016, 2019, 2021, D. R. Commander. + * Copyright (C) 2015-2017, 2019, 2021-2022, D. R. Commander. * Copyright (C) 2015, Google, Inc. * Copyright (C) 2021, Alex Richardson. * For conditions of distribution and use, see the accompanying README.ijg @@ -17,6 +19,17 @@ */ +/* Representation of a spatial difference value. + * This should be a signed value of at least 16 bits; int is usually OK. + */ + +typedef int JDIFF; + +typedef JDIFF FAR *JDIFFROW; /* pointer to one row of difference values */ +typedef JDIFFROW *JDIFFARRAY; /* ptr to some rows (a 2-D diff array) */ +typedef JDIFFARRAY *JDIFFIMAGE; /* a 3-D diff array: top index is color */ + + /* Declarations for both compression & decompression */ typedef enum { /* Operating modes for buffer controllers */ @@ -61,6 +74,9 @@ typedef __UINTPTR_TYPE__ JUINTPTR; typedef size_t JUINTPTR; #endif +#define IsExtRGB(cs) \ + (cs == JCS_RGB || (cs >= JCS_EXT_RGB && cs <= JCS_EXT_ARGB)) + /* * Left shift macro that handles a negative operand without causing any * sanitizer warnings @@ -80,6 +96,7 @@ struct jpeg_comp_master { /* State variables made visible to other modules */ boolean call_pass_startup; /* True if pass_startup must be called */ boolean is_last_pass; /* True during last pass */ + boolean lossless; /* True if lossless mode is enabled */ }; /* Main buffer control (downsampled-data buffer) */ @@ -87,6 +104,12 @@ struct jpeg_c_main_controller { void (*start_pass) (j_compress_ptr cinfo, J_BUF_MODE pass_mode); void (*process_data) (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail); + void (*process_data_12) (j_compress_ptr cinfo, J12SAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail); +#ifdef C_LOSSLESS_SUPPORTED + void (*process_data_16) (j_compress_ptr cinfo, J16SAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail); +#endif }; /* Compression preprocessing (downsampling input buffer control) */ @@ -97,12 +120,32 @@ struct jpeg_c_prep_controller { JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail); + void (*pre_process_data_12) (j_compress_ptr cinfo, J12SAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + J12SAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail); +#ifdef C_LOSSLESS_SUPPORTED + void (*pre_process_data_16) (j_compress_ptr cinfo, J16SAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + J16SAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail); +#endif }; -/* Coefficient buffer control */ +/* Lossy mode: Coefficient buffer control + * Lossless mode: Difference buffer control + */ struct jpeg_c_coef_controller { void (*start_pass) (j_compress_ptr cinfo, J_BUF_MODE pass_mode); boolean (*compress_data) (j_compress_ptr cinfo, JSAMPIMAGE input_buf); + boolean (*compress_data_12) (j_compress_ptr cinfo, J12SAMPIMAGE input_buf); +#ifdef C_LOSSLESS_SUPPORTED + boolean (*compress_data_16) (j_compress_ptr cinfo, J16SAMPIMAGE input_buf); +#endif }; /* Colorspace conversion */ @@ -111,6 +154,14 @@ struct jpeg_color_converter { void (*color_convert) (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows); + void (*color_convert_12) (j_compress_ptr cinfo, J12SAMPARRAY input_buf, + J12SAMPIMAGE output_buf, JDIMENSION output_row, + int num_rows); +#ifdef C_LOSSLESS_SUPPORTED + void (*color_convert_16) (j_compress_ptr cinfo, J16SAMPARRAY input_buf, + J16SAMPIMAGE output_buf, JDIMENSION output_row, + int num_rows); +#endif }; /* Downsampling */ @@ -119,24 +170,47 @@ struct jpeg_downsampler { void (*downsample) (j_compress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_index, JSAMPIMAGE output_buf, JDIMENSION out_row_group_index); + void (*downsample_12) (j_compress_ptr cinfo, J12SAMPIMAGE input_buf, + JDIMENSION in_row_index, J12SAMPIMAGE output_buf, + JDIMENSION out_row_group_index); +#ifdef C_LOSSLESS_SUPPORTED + void (*downsample_16) (j_compress_ptr cinfo, J16SAMPIMAGE input_buf, + JDIMENSION in_row_index, J16SAMPIMAGE output_buf, + JDIMENSION out_row_group_index); +#endif boolean need_context_rows; /* TRUE if need rows above & below */ }; -/* Forward DCT (also controls coefficient quantization) */ +/* Lossy mode: Forward DCT (also controls coefficient quantization) + * Lossless mode: Prediction, sample differencing, and point transform + */ struct jpeg_forward_dct { void (*start_pass) (j_compress_ptr cinfo); + + /* Lossy mode */ /* perhaps this should be an array??? */ void (*forward_DCT) (j_compress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks); + void (*forward_DCT_12) (j_compress_ptr cinfo, jpeg_component_info *compptr, + J12SAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks); }; /* Entropy encoding */ struct jpeg_entropy_encoder { void (*start_pass) (j_compress_ptr cinfo, boolean gather_statistics); + + /* Lossy mode */ boolean (*encode_mcu) (j_compress_ptr cinfo, JBLOCKROW *MCU_data); + /* Lossless mode */ + JDIMENSION (*encode_mcus) (j_compress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, + JDIMENSION nMCU); + void (*finish_pass) (j_compress_ptr cinfo); }; @@ -164,6 +238,7 @@ struct jpeg_decomp_master { /* State variables made visible to other modules */ boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ + boolean lossless; /* True if decompressing a lossless image */ /* Partial decompression variables */ JDIMENSION first_iMCU_col; @@ -193,14 +268,36 @@ struct jpeg_d_main_controller { void (*start_pass) (j_decompress_ptr cinfo, J_BUF_MODE pass_mode); void (*process_data) (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); + void (*process_data_12) (j_decompress_ptr cinfo, J12SAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); +#ifdef D_LOSSLESS_SUPPORTED + void (*process_data_16) (j_decompress_ptr cinfo, J16SAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); +#endif }; -/* Coefficient buffer control */ +/* Lossy mode: Coefficient buffer control + * Lossless mode: Difference buffer control + */ struct jpeg_d_coef_controller { void (*start_input_pass) (j_decompress_ptr cinfo); int (*consume_data) (j_decompress_ptr cinfo); void (*start_output_pass) (j_decompress_ptr cinfo); int (*decompress_data) (j_decompress_ptr cinfo, JSAMPIMAGE output_buf); + int (*decompress_data_12) (j_decompress_ptr cinfo, J12SAMPIMAGE output_buf); +#ifdef D_LOSSLESS_SUPPORTED + int (*decompress_data_16) (j_decompress_ptr cinfo, J16SAMPIMAGE output_buf); +#endif + + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + /* Lossy mode */ /* Pointer to array of coefficient virtual arrays, or NULL if none */ jvirt_barray_ptr *coef_arrays; }; @@ -213,6 +310,20 @@ struct jpeg_d_post_controller { JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); + void (*post_process_data_12) (j_decompress_ptr cinfo, J12SAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + J12SAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail); +#ifdef D_LOSSLESS_SUPPORTED + void (*post_process_data_16) (j_decompress_ptr cinfo, J16SAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + J16SAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail); +#endif }; /* Marker reading & parsing */ @@ -238,24 +349,42 @@ struct jpeg_marker_reader { /* Entropy decoding */ struct jpeg_entropy_decoder { void (*start_pass) (j_decompress_ptr cinfo); + + /* Lossy mode */ boolean (*decode_mcu) (j_decompress_ptr cinfo, JBLOCKROW *MCU_data); + /* Lossless mode */ + JDIMENSION (*decode_mcus) (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, + JDIMENSION nMCU); + boolean (*process_restart) (j_decompress_ptr cinfo); /* This is here to share code between baseline and progressive decoders; */ /* other modules probably should not use it */ boolean insufficient_data; /* set TRUE after emitting warning */ }; -/* Inverse DCT (also performs dequantization) */ +/* Lossy mode: Inverse DCT (also performs dequantization) + * Lossless mode: Prediction, sample undifferencing, point transform, and + * sample size scaling + */ typedef void (*inverse_DCT_method_ptr) (j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col); +typedef void (*inverse_DCT_12_method_ptr) (j_decompress_ptr cinfo, + jpeg_component_info *compptr, + JCOEFPTR coef_block, + J12SAMPARRAY output_buf, + JDIMENSION output_col); struct jpeg_inverse_dct { void (*start_pass) (j_decompress_ptr cinfo); + + /* Lossy mode */ /* It is useful to allow each component to have a separate IDCT method. */ inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; + inverse_DCT_12_method_ptr inverse_DCT_12[MAX_COMPONENTS]; }; /* Upsampling (note that upsampler must also call color converter) */ @@ -265,6 +394,16 @@ struct jpeg_upsampler { JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); + void (*upsample_12) (j_decompress_ptr cinfo, J12SAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, J12SAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); +#ifdef D_LOSSLESS_SUPPORTED + void (*upsample_16) (j_decompress_ptr cinfo, J16SAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, J16SAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); +#endif boolean need_context_rows; /* TRUE if need rows above & below */ }; @@ -275,6 +414,14 @@ struct jpeg_color_deconverter { void (*color_convert) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows); + void (*color_convert_12) (j_decompress_ptr cinfo, J12SAMPIMAGE input_buf, + JDIMENSION input_row, J12SAMPARRAY output_buf, + int num_rows); +#ifdef D_LOSSLESS_SUPPORTED + void (*color_convert_16) (j_decompress_ptr cinfo, J16SAMPIMAGE input_buf, + JDIMENSION input_row, J16SAMPARRAY output_buf, + int num_rows); +#endif }; /* Color quantization or color precision reduction */ @@ -282,6 +429,8 @@ struct jpeg_color_quantizer { void (*start_pass) (j_decompress_ptr cinfo, boolean is_pre_scan); void (*color_quantize) (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows); + void (*color_quantize_12) (j_decompress_ptr cinfo, J12SAMPARRAY input_buf, + J12SAMPARRAY output_buf, int num_rows); void (*finish_pass) (j_decompress_ptr cinfo); void (*new_color_map) (j_decompress_ptr cinfo); }; @@ -323,36 +472,95 @@ EXTERN(void) jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only); EXTERN(void) jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer); +EXTERN(void) j12init_c_main_controller(j_compress_ptr cinfo, + boolean need_full_buffer); EXTERN(void) jinit_c_prep_controller(j_compress_ptr cinfo, boolean need_full_buffer); +EXTERN(void) j12init_c_prep_controller(j_compress_ptr cinfo, + boolean need_full_buffer); EXTERN(void) jinit_c_coef_controller(j_compress_ptr cinfo, boolean need_full_buffer); +EXTERN(void) j12init_c_coef_controller(j_compress_ptr cinfo, + boolean need_full_buffer); EXTERN(void) jinit_color_converter(j_compress_ptr cinfo); +EXTERN(void) j12init_color_converter(j_compress_ptr cinfo); EXTERN(void) jinit_downsampler(j_compress_ptr cinfo); +EXTERN(void) j12init_downsampler(j_compress_ptr cinfo); EXTERN(void) jinit_forward_dct(j_compress_ptr cinfo); +EXTERN(void) j12init_forward_dct(j_compress_ptr cinfo); EXTERN(void) jinit_huff_encoder(j_compress_ptr cinfo); EXTERN(void) jinit_phuff_encoder(j_compress_ptr cinfo); EXTERN(void) jinit_arith_encoder(j_compress_ptr cinfo); EXTERN(void) jinit_marker_writer(j_compress_ptr cinfo); +#ifdef C_LOSSLESS_SUPPORTED +EXTERN(void) j16init_c_main_controller(j_compress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j16init_c_prep_controller(j_compress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j16init_color_converter(j_compress_ptr cinfo); +EXTERN(void) j16init_downsampler(j_compress_ptr cinfo); +EXTERN(void) jinit_c_diff_controller(j_compress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j12init_c_diff_controller(j_compress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j16init_c_diff_controller(j_compress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) jinit_lhuff_encoder(j_compress_ptr cinfo); +EXTERN(void) jinit_lossless_compressor(j_compress_ptr cinfo); +EXTERN(void) j12init_lossless_compressor(j_compress_ptr cinfo); +EXTERN(void) j16init_lossless_compressor(j_compress_ptr cinfo); +#endif + /* Decompression module initialization routines */ EXTERN(void) jinit_master_decompress(j_decompress_ptr cinfo); EXTERN(void) jinit_d_main_controller(j_decompress_ptr cinfo, boolean need_full_buffer); +EXTERN(void) j12init_d_main_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); EXTERN(void) jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer); +EXTERN(void) j12init_d_coef_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); EXTERN(void) jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer); +EXTERN(void) j12init_d_post_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); EXTERN(void) jinit_input_controller(j_decompress_ptr cinfo); EXTERN(void) jinit_marker_reader(j_decompress_ptr cinfo); EXTERN(void) jinit_huff_decoder(j_decompress_ptr cinfo); EXTERN(void) jinit_phuff_decoder(j_decompress_ptr cinfo); EXTERN(void) jinit_arith_decoder(j_decompress_ptr cinfo); EXTERN(void) jinit_inverse_dct(j_decompress_ptr cinfo); +EXTERN(void) j12init_inverse_dct(j_decompress_ptr cinfo); EXTERN(void) jinit_upsampler(j_decompress_ptr cinfo); +EXTERN(void) j12init_upsampler(j_decompress_ptr cinfo); EXTERN(void) jinit_color_deconverter(j_decompress_ptr cinfo); +EXTERN(void) j12init_color_deconverter(j_decompress_ptr cinfo); EXTERN(void) jinit_1pass_quantizer(j_decompress_ptr cinfo); +EXTERN(void) j12init_1pass_quantizer(j_decompress_ptr cinfo); EXTERN(void) jinit_2pass_quantizer(j_decompress_ptr cinfo); +EXTERN(void) j12init_2pass_quantizer(j_decompress_ptr cinfo); EXTERN(void) jinit_merged_upsampler(j_decompress_ptr cinfo); +EXTERN(void) j12init_merged_upsampler(j_decompress_ptr cinfo); +#ifdef D_LOSSLESS_SUPPORTED +EXTERN(void) j16init_d_main_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j16init_d_post_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j16init_upsampler(j_decompress_ptr cinfo); +EXTERN(void) j16init_color_deconverter(j_decompress_ptr cinfo); +EXTERN(void) jinit_d_diff_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j12init_d_diff_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) j16init_d_diff_controller(j_decompress_ptr cinfo, + boolean need_full_buffer); +EXTERN(void) jinit_lhuff_decoder(j_decompress_ptr cinfo); +EXTERN(void) jinit_lossless_decompressor(j_decompress_ptr cinfo); +EXTERN(void) j12init_lossless_decompressor(j_decompress_ptr cinfo); +EXTERN(void) j16init_lossless_decompressor(j_decompress_ptr cinfo); +#endif + /* Memory manager initialization */ EXTERN(void) jinit_memory_mgr(j_common_ptr cinfo); @@ -362,6 +570,14 @@ EXTERN(long) jround_up(long a, long b); EXTERN(void) jcopy_sample_rows(JSAMPARRAY input_array, int source_row, JSAMPARRAY output_array, int dest_row, int num_rows, JDIMENSION num_cols); +EXTERN(void) j12copy_sample_rows(J12SAMPARRAY input_array, int source_row, + J12SAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols); +#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) +EXTERN(void) j16copy_sample_rows(J16SAMPARRAY input_array, int source_row, + J16SAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols); +#endif EXTERN(void) jcopy_block_row(JBLOCKROW input_row, JBLOCKROW output_row, JDIMENSION num_blocks); EXTERN(void) jzero_far(void *target, size_t bytestozero); diff --git a/3rdparty/libjpeg-turbo/src/jpeglib.h b/3rdparty/libjpeg-turbo/src/jpeglib.h index d7664f063092..a59e98c25e58 100644 --- a/3rdparty/libjpeg-turbo/src/jpeglib.h +++ b/3rdparty/libjpeg-turbo/src/jpeglib.h @@ -4,8 +4,11 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2002-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. * libjpeg-turbo Modifications: - * Copyright (C) 2009-2011, 2013-2014, 2016-2017, 2020, D. R. Commander. + * Copyright (C) 2009-2011, 2013-2014, 2016-2017, 2020, 2022-2023, + D. R. Commander. * Copyright (C) 2015, Google, Inc. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -43,6 +46,13 @@ extern "C" { * if you want to be compatible. */ +/* NOTE: In lossless mode, an MCU contains one or more samples rather than one + * or more 8x8 DCT blocks, so the term "data unit" is used to generically + * describe a sample in lossless mode or an 8x8 DCT block in lossy mode. To + * preserve backward API/ABI compatibility, the field and macro names retain + * the "block" terminology. + */ + #define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ #define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ #define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ @@ -57,9 +67,9 @@ extern "C" { * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe * sometimes emits noncompliant files doesn't mean you should too. */ -#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on data units/MCU */ #ifndef D_MAX_BLOCKS_IN_MCU -#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on data units/MCU */ #endif @@ -70,6 +80,20 @@ typedef JSAMPLE *JSAMPROW; /* ptr to one image row of pixel samples. */ typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ +typedef J12SAMPLE *J12SAMPROW; /* ptr to one image row of 12-bit pixel + samples. */ +typedef J12SAMPROW *J12SAMPARRAY; /* ptr to some 12-bit sample rows (a 2-D + 12-bit sample array) */ +typedef J12SAMPARRAY *J12SAMPIMAGE; /* a 3-D 12-bit sample array: top index is + color */ + +typedef J16SAMPLE *J16SAMPROW; /* ptr to one image row of 16-bit pixel + samples. */ +typedef J16SAMPROW *J16SAMPARRAY; /* ptr to some 16-bit sample rows (a 2-D + 16-bit sample array) */ +typedef J16SAMPARRAY *J16SAMPIMAGE; /* a 3-D 16-bit sample array: top index is + color */ + typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ typedef JBLOCK *JBLOCKROW; /* pointer to one row of coefficient blocks */ typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ @@ -135,17 +159,20 @@ typedef struct { /* Remaining fields should be treated as private by applications. */ /* These values are computed during compression or decompression startup: */ - /* Component's size in DCT blocks. - * Any dummy blocks added to complete an MCU are not counted; therefore - * these values do not depend on whether a scan is interleaved or not. + /* Component's size in data units. + * In lossy mode, any dummy blocks added to complete an MCU are not counted; + * therefore these values do not depend on whether a scan is interleaved or + * not. In lossless mode, these are always equal to the image width and + * height. */ JDIMENSION width_in_blocks; JDIMENSION height_in_blocks; - /* Size of a DCT block in samples. Always DCTSIZE for compression. - * For decompression this is the size of the output from one DCT block, + /* Size of a data unit in samples. Always DCTSIZE for lossy compression. + * For lossy decompression this is the size of the output from one DCT block, * reflecting any scaling we choose to apply during the IDCT step. - * Values from 1 to 16 are supported. - * Note that different components may receive different IDCT scalings. + * Values from 1 to 16 are supported. Note that different components may + * receive different IDCT scalings. In lossless mode, this is always equal + * to 1. */ #if JPEG_LIB_VERSION >= 70 int DCT_h_scaled_size; @@ -156,8 +183,10 @@ typedef struct { /* The downsampled dimensions are the component's actual, unpadded number * of samples at the main buffer (preprocessing/compression interface), thus * downsampled_width = ceil(image_width * Hi/Hmax) - * and similarly for height. For decompression, IDCT scaling is included, so + * and similarly for height. For lossy decompression, IDCT scaling is + * included, so * downsampled_width = ceil(image_width * Hi/Hmax * DCT_[h_]scaled_size/DCTSIZE) + * In lossless mode, these are always equal to the image width and height. */ JDIMENSION downsampled_width; /* actual width in samples */ JDIMENSION downsampled_height; /* actual height in samples */ @@ -169,12 +198,12 @@ typedef struct { /* These values are computed before starting a scan of the component. */ /* The decompressor output side may not use these variables. */ - int MCU_width; /* number of blocks per MCU, horizontally */ - int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_width; /* number of data units per MCU, horizontally */ + int MCU_height; /* number of data units per MCU, vertically */ int MCU_blocks; /* MCU_width * MCU_height */ int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_[h_]scaled_size */ - int last_col_width; /* # of non-dummy blocks across in last MCU */ - int last_row_height; /* # of non-dummy blocks down in last MCU */ + int last_col_width; /* # of non-dummy data units across in last MCU */ + int last_row_height; /* # of non-dummy data units down in last MCU */ /* Saved quantization table for component; NULL if none yet saved. * See jdinput.c comments about the need for this information. @@ -192,8 +221,12 @@ typedef struct { typedef struct { int comps_in_scan; /* number of components encoded in this scan */ int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ - int Ss, Se; /* progressive JPEG spectral selection parms */ - int Ah, Al; /* progressive JPEG successive approx. parms */ + int Ss, Se; /* progressive JPEG spectral selection parms + (Ss is the predictor selection value in + lossless mode) */ + int Ah, Al; /* progressive JPEG successive approx. parms + (Al is the point transform value in lossless + mode) */ } jpeg_scan_info; /* The decompressor can save APPn and COM markers in a list of these: */ @@ -238,7 +271,8 @@ typedef enum { JCS_EXT_BGRA, /* blue/green/red/alpha */ JCS_EXT_ABGR, /* alpha/blue/green/red */ JCS_EXT_ARGB, /* alpha/red/green/blue */ - JCS_RGB565 /* 5-bit red/6-bit green/5-bit blue */ + JCS_RGB565 /* 5-bit red/6-bit green/5-bit blue + [decompression only] */ } J_COLOR_SPACE; /* DCT/IDCT algorithm options. */ @@ -419,11 +453,13 @@ struct jpeg_compress_struct { int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ #endif - JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ - /* The coefficient controller receives data in units of MCU rows as defined - * for fully interleaved scans (whether the JPEG file is interleaved or not). - * There are v_samp_factor * DCTSIZE sample rows of each component in an - * "iMCU" (interleaved MCU) row. + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coefficient or + difference controller */ + /* The coefficient or difference controller receives data in units of MCU + * rows as defined for fully interleaved scans (whether the JPEG file is + * interleaved or not). In lossy mode, there are v_samp_factor * DCTSIZE + * sample rows of each component in an "iMCU" (interleaved MCU) row. In + * lossless mode, total_iMCU_rows is always equal to the image height. */ /* @@ -437,12 +473,13 @@ struct jpeg_compress_struct { JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - int blocks_in_MCU; /* # of DCT blocks per MCU */ + int blocks_in_MCU; /* # of data units per MCU */ int MCU_membership[C_MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ + /* i'th data unit in an MCU */ - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for + scan */ #if JPEG_LIB_VERSION >= 80 int block_size; /* the basic DCT block size: 1..16 */ @@ -537,7 +574,12 @@ struct jpeg_decompress_struct { * The map has out_color_components rows and actual_number_of_colors columns. */ int actual_number_of_colors; /* number of entries in use */ - JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array + If data_precision is 12 or 16, then this is + actually a J12SAMPARRAY or a J16SAMPARRAY, + so callers must type-cast it in order to + read/write 12-bit or 16-bit samples from/to + the array. */ /* State variables: these variables indicate the progress of decompression. * The application may examine these but must not modify them. @@ -647,15 +689,21 @@ struct jpeg_decompress_struct { #endif JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ - /* The coefficient controller's input and output progress is measured in - * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows - * in fully interleaved JPEG scans, but are used whether the scan is - * interleaved or not. We define an iMCU row as v_samp_factor DCT block - * rows of each component. Therefore, the IDCT output contains + /* The coefficient or difference controller's input and output progress is + * measured in units of "iMCU" (interleaved MCU) rows. These are the same as + * MCU rows in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. In lossy mode, we define an iMCU row as v_samp_factor + * DCT block rows of each component. Therefore, the IDCT output contains * v_samp_factor*DCT_[v_]scaled_size sample rows of a component per iMCU row. + * In lossless mode, total_iMCU_rows is always equal to the image height. */ - JSAMPLE *sample_range_limit; /* table for fast range-limiting */ + JSAMPLE *sample_range_limit; /* table for fast range-limiting + If data_precision is 12 or 16, then this is + actually a J12SAMPLE pointer or a J16SAMPLE + pointer, so callers must type-cast it in + order to read 12-bit or 16-bit samples from + the array. */ /* * These fields are valid during any one scan. @@ -669,12 +717,13 @@ struct jpeg_decompress_struct { JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - int blocks_in_MCU; /* # of DCT blocks per MCU */ + int blocks_in_MCU; /* # of data units per MCU */ int MCU_membership[D_MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ + /* i'th data unit in an MCU */ - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for + scan */ #if JPEG_LIB_VERSION >= 80 /* These fields are derived from Se of first SOS marker. @@ -835,6 +884,11 @@ struct jpeg_memory_mgr { void *(*alloc_small) (j_common_ptr cinfo, int pool_id, size_t sizeofobject); void *(*alloc_large) (j_common_ptr cinfo, int pool_id, size_t sizeofobject); + /* If cinfo->data_precision is 12 or 16, then this method and the + * access_virt_sarray method actually return a J12SAMPARRAY or a + * J16SAMPARRAY, so callers must type-cast the return value in order to + * read/write 12-bit or 16-bit samples from/to the array. + */ JSAMPARRAY (*alloc_sarray) (j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JDIMENSION numrows); JBLOCKARRAY (*alloc_barray) (j_common_ptr cinfo, int pool_id, @@ -916,13 +970,11 @@ EXTERN(void) jpeg_destroy_decompress(j_decompress_ptr cinfo); EXTERN(void) jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile); EXTERN(void) jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile); -#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) /* Data source and destination managers: memory buffers. */ EXTERN(void) jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer, unsigned long *outsize); EXTERN(void) jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *inbuffer, unsigned long insize); -#endif /* Default parameter setup for compression */ EXTERN(void) jpeg_set_defaults(j_compress_ptr cinfo); @@ -942,6 +994,9 @@ EXTERN(void) jpeg_add_quant_table(j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, boolean force_baseline); EXTERN(int) jpeg_quality_scaling(int quality); +EXTERN(void) jpeg_enable_lossless(j_compress_ptr cinfo, + int predictor_selection_value, + int point_transform); EXTERN(void) jpeg_simple_progression(j_compress_ptr cinfo); EXTERN(void) jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress); EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table(j_common_ptr cinfo); @@ -953,6 +1008,12 @@ EXTERN(void) jpeg_start_compress(j_compress_ptr cinfo, EXTERN(JDIMENSION) jpeg_write_scanlines(j_compress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_write_scanlines(j_compress_ptr cinfo, + J12SAMPARRAY scanlines, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg16_write_scanlines(j_compress_ptr cinfo, + J16SAMPARRAY scanlines, + JDIMENSION num_lines); EXTERN(void) jpeg_finish_compress(j_compress_ptr cinfo); #if JPEG_LIB_VERSION >= 70 @@ -963,6 +1024,9 @@ EXTERN(void) jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo); /* Replaces jpeg_write_scanlines when writing raw downsampled data. */ EXTERN(JDIMENSION) jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data, JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_write_raw_data(j_compress_ptr cinfo, + J12SAMPIMAGE data, + JDIMENSION num_lines); /* Write a special marker. See libjpeg.txt concerning safe usage. */ EXTERN(void) jpeg_write_marker(j_compress_ptr cinfo, int marker, @@ -998,15 +1062,28 @@ EXTERN(boolean) jpeg_start_decompress(j_decompress_ptr cinfo); EXTERN(JDIMENSION) jpeg_read_scanlines(j_decompress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg12_read_scanlines(j_decompress_ptr cinfo, + J12SAMPARRAY scanlines, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg16_read_scanlines(j_decompress_ptr cinfo, + J16SAMPARRAY scanlines, + JDIMENSION max_lines); EXTERN(JDIMENSION) jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_skip_scanlines(j_decompress_ptr cinfo, + JDIMENSION num_lines); EXTERN(void) jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, JDIMENSION *width); +EXTERN(void) jpeg12_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, + JDIMENSION *width); EXTERN(boolean) jpeg_finish_decompress(j_decompress_ptr cinfo); /* Replaces jpeg_read_scanlines when reading raw downsampled data. */ EXTERN(JDIMENSION) jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data, JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg12_read_raw_data(j_decompress_ptr cinfo, + J12SAMPIMAGE data, + JDIMENSION max_lines); /* Additional entry points for buffered-image mode. */ EXTERN(boolean) jpeg_has_multiple_scans(j_decompress_ptr cinfo); diff --git a/3rdparty/libjpeg-turbo/src/jquant1.c b/3rdparty/libjpeg-turbo/src/jquant1.c index 73b83e16e5cc..2e914b919c63 100644 --- a/3rdparty/libjpeg-turbo/src/jquant1.c +++ b/3rdparty/libjpeg-turbo/src/jquant1.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2009, 2015, D. R. Commander. + * Copyright (C) 2009, 2015, 2022-2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -16,8 +16,9 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" -#ifdef QUANT_1PASS_SUPPORTED +#if defined(QUANT_1PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 /* @@ -66,7 +67,7 @@ * worse, since the dither may be too much or too little at a given point. * * The normal calculation would be to form pixel value + dither, range-limit - * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. + * this to 0.._MAXJSAMPLE, and then index into the colorindex table as usual. * We can skip the separate range-limiting step by extending the colorindex * table in both directions. */ @@ -144,13 +145,13 @@ typedef struct { struct jpeg_color_quantizer pub; /* public fields */ /* Initially allocated colormap is saved here */ - JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ + _JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ int sv_actual; /* number of entries in use */ - JSAMPARRAY colorindex; /* Precomputed mapping for speed */ + _JSAMPARRAY colorindex; /* Precomputed mapping for speed */ /* colorindex[i][j] = index of color closest to pixel value j in component i, * premultiplied as described above. Since colormap indexes must fit into - * JSAMPLEs, the entries of this array will too. + * _JSAMPLEs, the entries of this array will too. */ boolean is_padded; /* is the colorindex padded for odither? */ @@ -248,24 +249,24 @@ select_ncolors(j_decompress_ptr cinfo, int Ncolors[]) LOCAL(int) output_value(j_decompress_ptr cinfo, int ci, int j, int maxj) /* Return j'th output value, where j will range from 0 to maxj */ -/* The output values must fall in 0..MAXJSAMPLE in increasing order */ +/* The output values must fall in 0.._MAXJSAMPLE in increasing order */ { - /* We always provide values 0 and MAXJSAMPLE for each component; + /* We always provide values 0 and _MAXJSAMPLE for each component; * any additional values are equally spaced between these limits. * (Forcing the upper and lower values to the limits ensures that * dithering can't produce a color outside the selected gamut.) */ - return (int)(((JLONG)j * MAXJSAMPLE + maxj / 2) / maxj); + return (int)(((JLONG)j * _MAXJSAMPLE + maxj / 2) / maxj); } LOCAL(int) largest_input_value(j_decompress_ptr cinfo, int ci, int j, int maxj) /* Return largest input value that should map to j'th output value */ -/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ +/* Must have largest(j=0) >= 0, and largest(j=maxj) >= _MAXJSAMPLE */ { /* Breakpoints are halfway between values returned by output_value */ - return (int)(((JLONG)(2 * j + 1) * MAXJSAMPLE + maxj) / (2 * maxj)); + return (int)(((JLONG)(2 * j + 1) * _MAXJSAMPLE + maxj) / (2 * maxj)); } @@ -277,7 +278,7 @@ LOCAL(void) create_colormap(j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; - JSAMPARRAY colormap; /* Created colormap */ + _JSAMPARRAY colormap; /* Created colormap */ int total_colors; /* Number of distinct output colors */ int i, j, k, nci, blksize, blkdist, ptr, val; @@ -296,7 +297,7 @@ create_colormap(j_decompress_ptr cinfo) /* The colors are ordered in the map in standard row-major order, */ /* i.e. rightmost (highest-indexed) color changes most rapidly. */ - colormap = (*cinfo->mem->alloc_sarray) + colormap = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)total_colors, (JDIMENSION)cinfo->out_color_components); @@ -315,7 +316,7 @@ create_colormap(j_decompress_ptr cinfo) for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { /* fill in blksize entries beginning at ptr */ for (k = 0; k < blksize; k++) - colormap[i][ptr + k] = (JSAMPLE)val; + colormap[i][ptr + k] = (_JSAMPLE)val; } } blkdist = blksize; /* blksize of this color is blkdist of next */ @@ -337,25 +338,25 @@ LOCAL(void) create_colorindex(j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; - JSAMPROW indexptr; + _JSAMPROW indexptr; int i, j, k, nci, blksize, val, pad; - /* For ordered dither, we pad the color index tables by MAXJSAMPLE in - * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). + /* For ordered dither, we pad the color index tables by _MAXJSAMPLE in + * each direction (input index values can be -_MAXJSAMPLE .. 2*_MAXJSAMPLE). * This is not necessary in the other dithering modes. However, we * flag whether it was done in case user changes dithering mode. */ if (cinfo->dither_mode == JDITHER_ORDERED) { - pad = MAXJSAMPLE * 2; + pad = _MAXJSAMPLE * 2; cquantize->is_padded = TRUE; } else { pad = 0; cquantize->is_padded = FALSE; } - cquantize->colorindex = (*cinfo->mem->alloc_sarray) + cquantize->colorindex = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (JDIMENSION)(MAXJSAMPLE + 1 + pad), + (JDIMENSION)(_MAXJSAMPLE + 1 + pad), (JDIMENSION)cinfo->out_color_components); /* blksize is number of adjacent repeated entries for a component */ @@ -368,24 +369,24 @@ create_colorindex(j_decompress_ptr cinfo) /* adjust colorindex pointers to provide padding at negative indexes. */ if (pad) - cquantize->colorindex[i] += MAXJSAMPLE; + cquantize->colorindex[i] += _MAXJSAMPLE; /* in loop, val = index of current output value, */ /* and k = largest j that maps to current val */ indexptr = cquantize->colorindex[i]; val = 0; k = largest_input_value(cinfo, i, 0, nci - 1); - for (j = 0; j <= MAXJSAMPLE; j++) { + for (j = 0; j <= _MAXJSAMPLE; j++) { while (j > k) /* advance val if past boundary */ k = largest_input_value(cinfo, i, ++val, nci - 1); /* premultiply so that no multiplication needed in main processing */ - indexptr[j] = (JSAMPLE)(val * blksize); + indexptr[j] = (_JSAMPLE)(val * blksize); } /* Pad at both ends if necessary */ if (pad) - for (j = 1; j <= MAXJSAMPLE; j++) { + for (j = 1; j <= _MAXJSAMPLE; j++) { indexptr[-j] = indexptr[0]; - indexptr[MAXJSAMPLE + j] = indexptr[MAXJSAMPLE]; + indexptr[_MAXJSAMPLE + j] = indexptr[_MAXJSAMPLE]; } } } @@ -406,16 +407,16 @@ make_odither_array(j_decompress_ptr cinfo, int ncolors) odither = (ODITHER_MATRIX_PTR) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(ODITHER_MATRIX)); - /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). + /* The inter-value distance for this color is _MAXJSAMPLE/(ncolors-1). * Hence the dither value for the matrix cell with fill order f - * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). + * (f=0..N-1) should be (N-1-2*f)/(2*N) * _MAXJSAMPLE/(ncolors-1). * On 16-bit-int machine, be careful to avoid overflow. */ den = 2 * ODITHER_CELLS * ((JLONG)(ncolors - 1)); for (j = 0; j < ODITHER_SIZE; j++) { for (k = 0; k < ODITHER_SIZE; k++) { num = ((JLONG)(ODITHER_CELLS - 1 - - 2 * ((int)base_dither_matrix[j][k]))) * MAXJSAMPLE; + 2 * ((int)base_dither_matrix[j][k]))) * _MAXJSAMPLE; /* Ensure round towards zero despite C's lack of consistency * about rounding negative values in integer division... */ @@ -460,14 +461,14 @@ create_odither_tables(j_decompress_ptr cinfo) */ METHODDEF(void) -color_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +color_quantize(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) /* General case, no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; - JSAMPARRAY colorindex = cquantize->colorindex; + _JSAMPARRAY colorindex = cquantize->colorindex; register int pixcode, ci; - register JSAMPROW ptrin, ptrout; + register _JSAMPROW ptrin, ptrout; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; @@ -481,23 +482,23 @@ color_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf, for (ci = 0; ci < nc; ci++) { pixcode += colorindex[ci][*ptrin++]; } - *ptrout++ = (JSAMPLE)pixcode; + *ptrout++ = (_JSAMPLE)pixcode; } } } METHODDEF(void) -color_quantize3(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +color_quantize3(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) /* Fast path for out_color_components==3, no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; register int pixcode; - register JSAMPROW ptrin, ptrout; - JSAMPROW colorindex0 = cquantize->colorindex[0]; - JSAMPROW colorindex1 = cquantize->colorindex[1]; - JSAMPROW colorindex2 = cquantize->colorindex[2]; + register _JSAMPROW ptrin, ptrout; + _JSAMPROW colorindex0 = cquantize->colorindex[0]; + _JSAMPROW colorindex1 = cquantize->colorindex[1]; + _JSAMPROW colorindex2 = cquantize->colorindex[2]; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; @@ -509,21 +510,21 @@ color_quantize3(j_decompress_ptr cinfo, JSAMPARRAY input_buf, pixcode = colorindex0[*ptrin++]; pixcode += colorindex1[*ptrin++]; pixcode += colorindex2[*ptrin++]; - *ptrout++ = (JSAMPLE)pixcode; + *ptrout++ = (_JSAMPLE)pixcode; } } } METHODDEF(void) -quantize_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +quantize_ord_dither(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) /* General case, with ordered dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; - register JSAMPROW input_ptr; - register JSAMPROW output_ptr; - JSAMPROW colorindex_ci; + register _JSAMPROW input_ptr; + register _JSAMPROW output_ptr; + _JSAMPROW colorindex_ci; int *dither; /* points to active row of dither matrix */ int row_index, col_index; /* current indexes into dither matrix */ int nc = cinfo->out_color_components; @@ -534,7 +535,7 @@ quantize_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, for (row = 0; row < num_rows; row++) { /* Initialize output values to 0 so can process components separately */ - jzero_far((void *)output_buf[row], (size_t)(width * sizeof(JSAMPLE))); + jzero_far((void *)output_buf[row], (size_t)(width * sizeof(_JSAMPLE))); row_index = cquantize->row_index; for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; @@ -544,11 +545,11 @@ quantize_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, col_index = 0; for (col = width; col > 0; col--) { - /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, + /* Form pixel value + dither, range-limit to 0.._MAXJSAMPLE, * select output value, accumulate into output code for this pixel. * Range-limiting need not be done explicitly, as we have extended * the colorindex table to produce the right answers for out-of-range - * inputs. The maximum dither is +- MAXJSAMPLE; this sets the + * inputs. The maximum dither is +- _MAXJSAMPLE; this sets the * required amount of padding. */ *output_ptr += @@ -566,17 +567,17 @@ quantize_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, METHODDEF(void) -quantize3_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +quantize3_ord_dither(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) /* Fast path for out_color_components==3, with ordered dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; register int pixcode; - register JSAMPROW input_ptr; - register JSAMPROW output_ptr; - JSAMPROW colorindex0 = cquantize->colorindex[0]; - JSAMPROW colorindex1 = cquantize->colorindex[1]; - JSAMPROW colorindex2 = cquantize->colorindex[2]; + register _JSAMPROW input_ptr; + register _JSAMPROW output_ptr; + _JSAMPROW colorindex0 = cquantize->colorindex[0]; + _JSAMPROW colorindex1 = cquantize->colorindex[1]; + _JSAMPROW colorindex2 = cquantize->colorindex[2]; int *dither0; /* points to active row of dither matrix */ int *dither1; int *dither2; @@ -598,7 +599,7 @@ quantize3_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, pixcode = colorindex0[(*input_ptr++) + dither0[col_index]]; pixcode += colorindex1[(*input_ptr++) + dither1[col_index]]; pixcode += colorindex2[(*input_ptr++) + dither2[col_index]]; - *output_ptr++ = (JSAMPLE)pixcode; + *output_ptr++ = (_JSAMPLE)pixcode; col_index = (col_index + 1) & ODITHER_MASK; } row_index = (row_index + 1) & ODITHER_MASK; @@ -608,8 +609,8 @@ quantize3_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, METHODDEF(void) -quantize_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +quantize_fs_dither(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) /* General case, with Floyd-Steinberg dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; @@ -619,10 +620,10 @@ quantize_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, LOCFSERROR bnexterr; /* error for below/next col */ LOCFSERROR delta; register FSERRPTR errorptr; /* => fserrors[] at column before current */ - register JSAMPROW input_ptr; - register JSAMPROW output_ptr; - JSAMPROW colorindex_ci; - JSAMPROW colormap_ci; + register _JSAMPROW input_ptr; + register _JSAMPROW output_ptr; + _JSAMPROW colorindex_ci; + _JSAMPROW colormap_ci; int pixcode; int nc = cinfo->out_color_components; int dir; /* 1 for left-to-right, -1 for right-to-left */ @@ -631,12 +632,12 @@ quantize_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; - JSAMPLE *range_limit = cinfo->sample_range_limit; + _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; SHIFT_TEMPS for (row = 0; row < num_rows; row++) { /* Initialize output values to 0 so can process components separately */ - jzero_far((void *)output_buf[row], (size_t)(width * sizeof(JSAMPLE))); + jzero_far((void *)output_buf[row], (size_t)(width * sizeof(_JSAMPLE))); for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; output_ptr = output_buf[row]; @@ -670,15 +671,15 @@ quantize_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, * Note: errorptr points to *previous* column's array entry. */ cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); - /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. - * The maximum error is +- MAXJSAMPLE; this sets the required size + /* Form pixel value + error, and range-limit to 0.._MAXJSAMPLE. + * The maximum error is +- _MAXJSAMPLE; this sets the required size * of the range_limit array. */ cur += *input_ptr; cur = range_limit[cur]; /* Select output value, accumulate into output code for this pixel */ pixcode = colorindex_ci[cur]; - *output_ptr += (JSAMPLE)pixcode; + *output_ptr += (_JSAMPLE)pixcode; /* Compute actual representation error at this pixel */ /* Note: we can do this even though we don't have the final */ /* pixel code, because the colormap is orthogonal. */ @@ -745,22 +746,22 @@ start_pass_1_quant(j_decompress_ptr cinfo, boolean is_pre_scan) int i; /* Install my colormap. */ - cinfo->colormap = cquantize->sv_colormap; + cinfo->colormap = (JSAMPARRAY)cquantize->sv_colormap; cinfo->actual_number_of_colors = cquantize->sv_actual; /* Initialize for desired dithering mode. */ switch (cinfo->dither_mode) { case JDITHER_NONE: if (cinfo->out_color_components == 3) - cquantize->pub.color_quantize = color_quantize3; + cquantize->pub._color_quantize = color_quantize3; else - cquantize->pub.color_quantize = color_quantize; + cquantize->pub._color_quantize = color_quantize; break; case JDITHER_ORDERED: if (cinfo->out_color_components == 3) - cquantize->pub.color_quantize = quantize3_ord_dither; + cquantize->pub._color_quantize = quantize3_ord_dither; else - cquantize->pub.color_quantize = quantize_ord_dither; + cquantize->pub._color_quantize = quantize_ord_dither; cquantize->row_index = 0; /* initialize state for ordered dither */ /* If user changed to ordered dither from another mode, * we must recreate the color index table with padding. @@ -773,7 +774,7 @@ start_pass_1_quant(j_decompress_ptr cinfo, boolean is_pre_scan) create_odither_tables(cinfo); break; case JDITHER_FS: - cquantize->pub.color_quantize = quantize_fs_dither; + cquantize->pub._color_quantize = quantize_fs_dither; cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ /* Allocate Floyd-Steinberg workspace if didn't already. */ if (cquantize->fserrors[0] == NULL) @@ -818,10 +819,17 @@ new_color_map_1_quant(j_decompress_ptr cinfo) */ GLOBAL(void) -jinit_1pass_quantizer(j_decompress_ptr cinfo) +_jinit_1pass_quantizer(j_decompress_ptr cinfo) { my_cquantize_ptr cquantize; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Color quantization is not supported with lossless JPEG images */ + if (cinfo->master->lossless) + ERREXIT(cinfo, JERR_NOTIMPL); + cquantize = (my_cquantize_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_cquantizer)); @@ -835,9 +843,9 @@ jinit_1pass_quantizer(j_decompress_ptr cinfo) /* Make sure my internal arrays won't overflow */ if (cinfo->out_color_components > MAX_Q_COMPS) ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); - /* Make sure colormap indexes can be represented by JSAMPLEs */ - if (cinfo->desired_number_of_colors > (MAXJSAMPLE + 1)) - ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE + 1); + /* Make sure colormap indexes can be represented by _JSAMPLEs */ + if (cinfo->desired_number_of_colors > (_MAXJSAMPLE + 1)) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, _MAXJSAMPLE + 1); /* Create the colormap and color index table. */ create_colormap(cinfo); @@ -853,4 +861,4 @@ jinit_1pass_quantizer(j_decompress_ptr cinfo) alloc_fs_workspace(cinfo); } -#endif /* QUANT_1PASS_SUPPORTED */ +#endif /* defined(QUANT_1PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 */ diff --git a/3rdparty/libjpeg-turbo/src/jquant2.c b/3rdparty/libjpeg-turbo/src/jquant2.c index 44efb18cadf1..9ba51fa8872b 100644 --- a/3rdparty/libjpeg-turbo/src/jquant2.c +++ b/3rdparty/libjpeg-turbo/src/jquant2.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2009, 2014-2015, 2020, D. R. Commander. + * Copyright (C) 2009, 2014-2015, 2020, 2022-2023, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -23,8 +23,9 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" -#ifdef QUANT_2PASS_SUPPORTED +#if defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 /* @@ -106,7 +107,7 @@ static const int c_scales[3] = { R_SCALE, G_SCALE, B_SCALE }; * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. */ -#define MAXNUMCOLORS (MAXJSAMPLE + 1) /* maximum size of colormap */ +#define MAXNUMCOLORS (_MAXJSAMPLE + 1) /* maximum size of colormap */ /* These will do the right thing for either R,G,B or B,G,R color order, * but you may not like the results for other color orders. @@ -173,7 +174,7 @@ typedef struct { struct jpeg_color_quantizer pub; /* public fields */ /* Space for the eventually created colormap is stashed here */ - JSAMPARRAY sv_colormap; /* colormap allocated at init time */ + _JSAMPARRAY sv_colormap; /* colormap allocated at init time */ int desired; /* desired # of colors = size of colormap */ /* Variables for accumulating image statistics */ @@ -200,11 +201,11 @@ typedef my_cquantizer *my_cquantize_ptr; */ METHODDEF(void) -prescan_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +prescan_quantize(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; - register JSAMPROW ptr; + register _JSAMPROW ptr; register histptr histp; register hist3d histogram = cquantize->histogram; int row; @@ -377,7 +378,7 @@ update_box(j_decompress_ptr cinfo, boxptr boxp) * against making long narrow boxes, and it has the side benefit that * a box is splittable iff norm > 0. * Since the differences are expressed in histogram-cell units, - * we have to shift back to JSAMPLE units to get consistent distances; + * we have to shift back to _JSAMPLE units to get consistent distances; * after which, we scale according to the selected distance scale factors. */ dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; @@ -508,9 +509,12 @@ compute_color(j_decompress_ptr cinfo, boxptr boxp, int icolor) } } - cinfo->colormap[0][icolor] = (JSAMPLE)((c0total + (total >> 1)) / total); - cinfo->colormap[1][icolor] = (JSAMPLE)((c1total + (total >> 1)) / total); - cinfo->colormap[2][icolor] = (JSAMPLE)((c2total + (total >> 1)) / total); + ((_JSAMPARRAY)cinfo->colormap)[0][icolor] = + (_JSAMPLE)((c0total + (total >> 1)) / total); + ((_JSAMPARRAY)cinfo->colormap)[1][icolor] = + (_JSAMPLE)((c1total + (total >> 1)) / total); + ((_JSAMPARRAY)cinfo->colormap)[2][icolor] = + (_JSAMPLE)((c2total + (total >> 1)) / total); } @@ -528,11 +532,11 @@ select_colors(j_decompress_ptr cinfo, int desired_colors) /* Initialize one box containing whole space */ numboxes = 1; boxlist[0].c0min = 0; - boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; + boxlist[0].c0max = _MAXJSAMPLE >> C0_SHIFT; boxlist[0].c1min = 0; - boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; + boxlist[0].c1max = _MAXJSAMPLE >> C1_SHIFT; boxlist[0].c2min = 0; - boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; + boxlist[0].c2max = _MAXJSAMPLE >> C2_SHIFT; /* Shrink it to actually-used volume and set its statistics */ update_box(cinfo, &boxlist[0]); /* Perform median-cut to produce final box list */ @@ -623,7 +627,7 @@ select_colors(j_decompress_ptr cinfo, int desired_colors) LOCAL(int) find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, - JSAMPLE colorlist[]) + _JSAMPLE colorlist[]) /* Locate the colormap entries close enough to an update box to be candidates * for the nearest entry to some cell(s) in the update box. The update box * is specified by the center coordinates of its first cell. The number of @@ -665,7 +669,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, for (i = 0; i < numcolors; i++) { /* We compute the squared-c0-distance term, then add in the other two. */ - x = cinfo->colormap[0][i]; + x = ((_JSAMPARRAY)cinfo->colormap)[0][i]; if (x < minc0) { tdist = (x - minc0) * C0_SCALE; min_dist = tdist * tdist; @@ -688,7 +692,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, } } - x = cinfo->colormap[1][i]; + x = ((_JSAMPARRAY)cinfo->colormap)[1][i]; if (x < minc1) { tdist = (x - minc1) * C1_SCALE; min_dist += tdist * tdist; @@ -710,7 +714,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, } } - x = cinfo->colormap[2][i]; + x = ((_JSAMPARRAY)cinfo->colormap)[2][i]; if (x < minc2) { tdist = (x - minc2) * C2_SCALE; min_dist += tdist * tdist; @@ -744,7 +748,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, ncolors = 0; for (i = 0; i < numcolors; i++) { if (mindist[i] <= minmaxdist) - colorlist[ncolors++] = (JSAMPLE)i; + colorlist[ncolors++] = (_JSAMPLE)i; } return ncolors; } @@ -752,7 +756,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, LOCAL(void) find_best_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, - int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) + int numcolors, _JSAMPLE colorlist[], _JSAMPLE bestcolor[]) /* Find the closest colormap entry for each cell in the update box, * given the list of candidate colors prepared by find_nearby_colors. * Return the indexes of the closest entries in the bestcolor[] array. @@ -763,7 +767,7 @@ find_best_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, int ic0, ic1, ic2; int i, icolor; register JLONG *bptr; /* pointer into bestdist[] array */ - JSAMPLE *cptr; /* pointer into bestcolor[] array */ + _JSAMPLE *cptr; /* pointer into bestcolor[] array */ JLONG dist0, dist1; /* initial distance values */ register JLONG dist2; /* current distance in inner loop */ JLONG xx0, xx1; /* distance increments */ @@ -790,11 +794,11 @@ find_best_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, for (i = 0; i < numcolors; i++) { icolor = colorlist[i]; /* Compute (square of) distance from minc0/c1/c2 to this color */ - inc0 = (minc0 - cinfo->colormap[0][icolor]) * C0_SCALE; + inc0 = (minc0 - ((_JSAMPARRAY)cinfo->colormap)[0][icolor]) * C0_SCALE; dist0 = inc0 * inc0; - inc1 = (minc1 - cinfo->colormap[1][icolor]) * C1_SCALE; + inc1 = (minc1 - ((_JSAMPARRAY)cinfo->colormap)[1][icolor]) * C1_SCALE; dist0 += inc1 * inc1; - inc2 = (minc2 - cinfo->colormap[2][icolor]) * C2_SCALE; + inc2 = (minc2 - ((_JSAMPARRAY)cinfo->colormap)[2][icolor]) * C2_SCALE; dist0 += inc2 * inc2; /* Form the initial difference increments */ inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; @@ -813,7 +817,7 @@ find_best_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2, for (ic2 = BOX_C2_ELEMS - 1; ic2 >= 0; ic2--) { if (dist2 < *bptr) { *bptr = dist2; - *cptr = (JSAMPLE)icolor; + *cptr = (_JSAMPLE)icolor; } dist2 += xx2; xx2 += 2 * STEP_C2 * STEP_C2; @@ -840,13 +844,13 @@ fill_inverse_cmap(j_decompress_ptr cinfo, int c0, int c1, int c2) hist3d histogram = cquantize->histogram; int minc0, minc1, minc2; /* lower left corner of update box */ int ic0, ic1, ic2; - register JSAMPLE *cptr; /* pointer into bestcolor[] array */ + register _JSAMPLE *cptr; /* pointer into bestcolor[] array */ register histptr cachep; /* pointer into main cache array */ /* This array lists the candidate colormap indexes. */ - JSAMPLE colorlist[MAXNUMCOLORS]; + _JSAMPLE colorlist[MAXNUMCOLORS]; int numcolors; /* number of candidate colors */ /* This array holds the actually closest colormap index for each cell. */ - JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + _JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; /* Convert cell coordinates to update box ID */ c0 >>= BOX_C0_LOG; @@ -891,13 +895,13 @@ fill_inverse_cmap(j_decompress_ptr cinfo, int c0, int c1, int c2) */ METHODDEF(void) -pass2_no_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +pass2_no_dither(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) /* This version performs no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; hist3d histogram = cquantize->histogram; - register JSAMPROW inptr, outptr; + register _JSAMPROW inptr, outptr; register histptr cachep; register int c0, c1, c2; int row; @@ -918,15 +922,15 @@ pass2_no_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, if (*cachep == 0) fill_inverse_cmap(cinfo, c0, c1, c2); /* Now emit the colormap index for this cell */ - *outptr++ = (JSAMPLE)(*cachep - 1); + *outptr++ = (_JSAMPLE)(*cachep - 1); } } } METHODDEF(void) -pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) +pass2_fs_dither(j_decompress_ptr cinfo, _JSAMPARRAY input_buf, + _JSAMPARRAY output_buf, int num_rows) /* This version performs Floyd-Steinberg dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; @@ -935,19 +939,19 @@ pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ register FSERRPTR errorptr; /* => fserrors[] at column before current */ - JSAMPROW inptr; /* => current input pixel */ - JSAMPROW outptr; /* => current output pixel */ + _JSAMPROW inptr; /* => current input pixel */ + _JSAMPROW outptr; /* => current output pixel */ histptr cachep; int dir; /* +1 or -1 depending on direction */ int dir3; /* 3*dir, for advancing inptr & errorptr */ int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; - JSAMPLE *range_limit = cinfo->sample_range_limit; + _JSAMPLE *range_limit = (_JSAMPLE *)cinfo->sample_range_limit; int *error_limit = cquantize->error_limiter; - JSAMPROW colormap0 = cinfo->colormap[0]; - JSAMPROW colormap1 = cinfo->colormap[1]; - JSAMPROW colormap2 = cinfo->colormap[2]; + _JSAMPROW colormap0 = ((_JSAMPARRAY)cinfo->colormap)[0]; + _JSAMPROW colormap1 = ((_JSAMPARRAY)cinfo->colormap)[1]; + _JSAMPROW colormap2 = ((_JSAMPARRAY)cinfo->colormap)[2]; SHIFT_TEMPS for (row = 0; row < num_rows; row++) { @@ -992,8 +996,8 @@ pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, cur0 = error_limit[cur0]; cur1 = error_limit[cur1]; cur2 = error_limit[cur2]; - /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. - * The maximum error is +- MAXJSAMPLE (or less with error limiting); + /* Form pixel value + error, and range-limit to 0.._MAXJSAMPLE. + * The maximum error is +- _MAXJSAMPLE (or less with error limiting); * this sets the required size of the range_limit array. */ cur0 += inptr[0]; @@ -1013,7 +1017,7 @@ pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, /* Now emit the colormap index for this cell */ { register int pixcode = *cachep - 1; - *outptr = (JSAMPLE)pixcode; + *outptr = (_JSAMPLE)pixcode; /* Compute representation error for this pixel */ cur0 -= colormap0[pixcode]; cur1 -= colormap1[pixcode]; @@ -1064,7 +1068,7 @@ pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, /* * Initialize the error-limiting transfer function (lookup table). * The raw F-S error computation can potentially compute error values of up to - * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be + * +- _MAXJSAMPLE. But we want the maximum correction applied to a pixel to be * much less, otherwise obviously wrong pixels will be created. (Typical * effects include weird fringes at color-area boundaries, isolated bright * pixels in a dark area, etc.) The standard advice for avoiding this problem @@ -1073,7 +1077,7 @@ pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf, * error buildup. However, that only prevents the error from getting * completely out of hand; Aaron Giles reports that error limiting improves * the results even with corner colors allocated. - * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty + * A simple clamping of the error values to about +- _MAXJSAMPLE/8 works pretty * well, but the smoother transfer function used below is even better. Thanks * to Aaron Giles for this idea. */ @@ -1087,22 +1091,22 @@ init_error_limit(j_decompress_ptr cinfo) int in, out; table = (int *)(*cinfo->mem->alloc_small) - ((j_common_ptr)cinfo, JPOOL_IMAGE, (MAXJSAMPLE * 2 + 1) * sizeof(int)); - table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ + ((j_common_ptr)cinfo, JPOOL_IMAGE, (_MAXJSAMPLE * 2 + 1) * sizeof(int)); + table += _MAXJSAMPLE; /* so can index -_MAXJSAMPLE .. +_MAXJSAMPLE */ cquantize->error_limiter = table; -#define STEPSIZE ((MAXJSAMPLE + 1) / 16) - /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ +#define STEPSIZE ((_MAXJSAMPLE + 1) / 16) + /* Map errors 1:1 up to +- _MAXJSAMPLE/16 */ out = 0; for (in = 0; in < STEPSIZE; in++, out++) { table[in] = out; table[-in] = -out; } - /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ + /* Map errors 1:2 up to +- 3*_MAXJSAMPLE/16 */ for (; in < STEPSIZE * 3; in++, out += (in & 1) ? 0 : 1) { table[in] = out; table[-in] = -out; } - /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ - for (; in <= MAXJSAMPLE; in++) { + /* Clamp the rest to final out value (which is (_MAXJSAMPLE+1)/8) */ + for (; in <= _MAXJSAMPLE; in++) { table[in] = out; table[-in] = -out; } #undef STEPSIZE @@ -1119,7 +1123,7 @@ finish_pass1(j_decompress_ptr cinfo) my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize; /* Select the representative colors and fill in cinfo->colormap */ - cinfo->colormap = cquantize->sv_colormap; + cinfo->colormap = (JSAMPARRAY)cquantize->sv_colormap; select_colors(cinfo, cquantize->desired); /* Force next pass to zero the color index table */ cquantize->needs_zeroed = TRUE; @@ -1151,15 +1155,15 @@ start_pass_2_quant(j_decompress_ptr cinfo, boolean is_pre_scan) if (is_pre_scan) { /* Set up method pointers */ - cquantize->pub.color_quantize = prescan_quantize; + cquantize->pub._color_quantize = prescan_quantize; cquantize->pub.finish_pass = finish_pass1; cquantize->needs_zeroed = TRUE; /* Always zero histogram */ } else { /* Set up method pointers */ if (cinfo->dither_mode == JDITHER_FS) - cquantize->pub.color_quantize = pass2_fs_dither; + cquantize->pub._color_quantize = pass2_fs_dither; else - cquantize->pub.color_quantize = pass2_no_dither; + cquantize->pub._color_quantize = pass2_no_dither; cquantize->pub.finish_pass = finish_pass2; /* Make sure color count is acceptable */ @@ -1215,11 +1219,14 @@ new_color_map_2_quant(j_decompress_ptr cinfo) */ GLOBAL(void) -jinit_2pass_quantizer(j_decompress_ptr cinfo) +_jinit_2pass_quantizer(j_decompress_ptr cinfo) { my_cquantize_ptr cquantize; int i; + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + cquantize = (my_cquantize_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_cquantizer)); @@ -1230,7 +1237,8 @@ jinit_2pass_quantizer(j_decompress_ptr cinfo) cquantize->error_limiter = NULL; /* Make sure jdmaster didn't give me a case I can't handle */ - if (cinfo->out_color_components != 3) + if (cinfo->out_color_components != 3 || + cinfo->out_color_space == JCS_RGB565 || cinfo->master->lossless) ERREXIT(cinfo, JERR_NOTIMPL); /* Allocate the histogram/inverse colormap storage */ @@ -1253,10 +1261,10 @@ jinit_2pass_quantizer(j_decompress_ptr cinfo) /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ if (desired < 8) ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); - /* Make sure colormap indexes can be represented by JSAMPLEs */ + /* Make sure colormap indexes can be represented by _JSAMPLEs */ if (desired > MAXNUMCOLORS) ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); - cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) + cquantize->sv_colormap = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)desired, (JDIMENSION)3); cquantize->desired = desired; } else @@ -1282,4 +1290,4 @@ jinit_2pass_quantizer(j_decompress_ptr cinfo) } } -#endif /* QUANT_2PASS_SUPPORTED */ +#endif /* defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 */ diff --git a/3rdparty/libjpeg-turbo/src/jsamplecomp.h b/3rdparty/libjpeg-turbo/src/jsamplecomp.h new file mode 100644 index 000000000000..f3f275e6e29d --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/jsamplecomp.h @@ -0,0 +1,336 @@ +/* + * jsamplecomp.h + * + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + */ + +/* In source files that must be compiled for multiple data precisions, we + * prefix all precision-dependent data types, macros, methods, fields, and + * function names with an underscore. Including this file replaces those + * precision-independent tokens with their precision-dependent equivalents, + * based on the value of BITS_IN_JSAMPLE. + */ + +#ifndef JSAMPLECOMP_H +#define JSAMPLECOMP_H + +#if BITS_IN_JSAMPLE == 16 + +/* Sample data types and macros (jmorecfg.h) */ +#define _JSAMPLE J16SAMPLE + +#define _MAXJSAMPLE MAXJ16SAMPLE +#define _CENTERJSAMPLE CENTERJ16SAMPLE + +#define _JSAMPROW J16SAMPROW +#define _JSAMPARRAY J16SAMPARRAY +#define _JSAMPIMAGE J16SAMPIMAGE + +/* External functions (jpeglib.h) */ +#define _jpeg_write_scanlines jpeg16_write_scanlines +#define _jpeg_read_scanlines jpeg16_read_scanlines + +/* Internal methods (jpegint.h) */ + +#ifdef C_LOSSLESS_SUPPORTED +/* Use the 16-bit method in the jpeg_c_main_controller structure. */ +#define _process_data process_data_16 +/* Use the 16-bit method in the jpeg_c_prep_controller structure. */ +#define _pre_process_data pre_process_data_16 +/* Use the 16-bit method in the jpeg_c_coef_controller structure. */ +#define _compress_data compress_data_16 +/* Use the 16-bit method in the jpeg_color_converter structure. */ +#define _color_convert color_convert_16 +/* Use the 16-bit method in the jpeg_downsampler structure. */ +#define _downsample downsample_16 +#endif +#ifdef D_LOSSLESS_SUPPORTED +/* Use the 16-bit method in the jpeg_d_main_controller structure. */ +#define _process_data process_data_16 +/* Use the 16-bit method in the jpeg_d_coef_controller structure. */ +#define _decompress_data decompress_data_16 +/* Use the 16-bit method in the jpeg_d_post_controller structure. */ +#define _post_process_data post_process_data_16 +/* Use the 16-bit method in the jpeg_upsampler structure. */ +#define _upsample upsample_16 +/* Use the 16-bit method in the jpeg_color_converter structure. */ +#define _color_convert color_convert_16 +#endif + +/* Global internal functions (jpegint.h) */ +#ifdef C_LOSSLESS_SUPPORTED +#define _jinit_c_main_controller j16init_c_main_controller +#define _jinit_c_prep_controller j16init_c_prep_controller +#define _jinit_color_converter j16init_color_converter +#define _jinit_downsampler j16init_downsampler +#define _jinit_c_diff_controller j16init_c_diff_controller +#define _jinit_lossless_compressor j16init_lossless_compressor +#endif + +#ifdef D_LOSSLESS_SUPPORTED +#define _jinit_d_main_controller j16init_d_main_controller +#define _jinit_d_post_controller j16init_d_post_controller +#define _jinit_upsampler j16init_upsampler +#define _jinit_color_deconverter j16init_color_deconverter +#define _jinit_merged_upsampler j16init_merged_upsampler +#define _jinit_d_diff_controller j16init_d_diff_controller +#define _jinit_lossless_decompressor j16init_lossless_decompressor +#endif + +#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) +#define _jcopy_sample_rows j16copy_sample_rows +#endif + +/* Internal fields (cdjpeg.h) */ + +#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) +/* Use the 16-bit buffer in the cjpeg_source_struct and djpeg_dest_struct + structures. */ +#define _buffer buffer16 +#endif + +/* Image I/O functions (cdjpeg.h) */ +#ifdef C_LOSSLESS_SUPPORTED +#define _jinit_read_gif j16init_read_gif +#define _jinit_read_ppm j16init_read_ppm +#endif + +#ifdef D_LOSSLESS_SUPPORTED +#define _jinit_write_ppm j16init_write_ppm +#endif + +#elif BITS_IN_JSAMPLE == 12 + +/* Sample data types and macros (jmorecfg.h) */ +#define _JSAMPLE J12SAMPLE + +#define _MAXJSAMPLE MAXJ12SAMPLE +#define _CENTERJSAMPLE CENTERJ12SAMPLE + +#define _JSAMPROW J12SAMPROW +#define _JSAMPARRAY J12SAMPARRAY +#define _JSAMPIMAGE J12SAMPIMAGE + +/* External functions (jpeglib.h) */ +#define _jpeg_write_scanlines jpeg12_write_scanlines +#define _jpeg_write_raw_data jpeg12_write_raw_data +#define _jpeg_read_scanlines jpeg12_read_scanlines +#define _jpeg_skip_scanlines jpeg12_skip_scanlines +#define _jpeg_crop_scanline jpeg12_crop_scanline +#define _jpeg_read_raw_data jpeg12_read_raw_data + +/* Internal methods (jpegint.h) */ + +/* Use the 12-bit method in the jpeg_c_main_controller structure. */ +#define _process_data process_data_12 +/* Use the 12-bit method in the jpeg_c_prep_controller structure. */ +#define _pre_process_data pre_process_data_12 +/* Use the 12-bit method in the jpeg_c_coef_controller structure. */ +#define _compress_data compress_data_12 +/* Use the 12-bit method in the jpeg_color_converter structure. */ +#define _color_convert color_convert_12 +/* Use the 12-bit method in the jpeg_downsampler structure. */ +#define _downsample downsample_12 +/* Use the 12-bit method in the jpeg_forward_dct structure. */ +#define _forward_DCT forward_DCT_12 +/* Use the 12-bit method in the jpeg_d_main_controller structure. */ +#define _process_data process_data_12 +/* Use the 12-bit method in the jpeg_d_coef_controller structure. */ +#define _decompress_data decompress_data_12 +/* Use the 12-bit method in the jpeg_d_post_controller structure. */ +#define _post_process_data post_process_data_12 +/* Use the 12-bit method in the jpeg_inverse_dct structure. */ +#define _inverse_DCT_method_ptr inverse_DCT_12_method_ptr +#define _inverse_DCT inverse_DCT_12 +/* Use the 12-bit method in the jpeg_upsampler structure. */ +#define _upsample upsample_12 +/* Use the 12-bit method in the jpeg_color_converter structure. */ +#define _color_convert color_convert_12 +/* Use the 12-bit method in the jpeg_color_quantizer structure. */ +#define _color_quantize color_quantize_12 + +/* Global internal functions (jpegint.h) */ +#define _jinit_c_main_controller j12init_c_main_controller +#define _jinit_c_prep_controller j12init_c_prep_controller +#define _jinit_c_coef_controller j12init_c_coef_controller +#define _jinit_color_converter j12init_color_converter +#define _jinit_downsampler j12init_downsampler +#define _jinit_forward_dct j12init_forward_dct +#ifdef C_LOSSLESS_SUPPORTED +#define _jinit_c_diff_controller j12init_c_diff_controller +#define _jinit_lossless_compressor j12init_lossless_compressor +#endif + +#define _jinit_d_main_controller j12init_d_main_controller +#define _jinit_d_coef_controller j12init_d_coef_controller +#define _jinit_d_post_controller j12init_d_post_controller +#define _jinit_inverse_dct j12init_inverse_dct +#define _jinit_upsampler j12init_upsampler +#define _jinit_color_deconverter j12init_color_deconverter +#define _jinit_1pass_quantizer j12init_1pass_quantizer +#define _jinit_2pass_quantizer j12init_2pass_quantizer +#define _jinit_merged_upsampler j12init_merged_upsampler +#ifdef D_LOSSLESS_SUPPORTED +#define _jinit_d_diff_controller j12init_d_diff_controller +#define _jinit_lossless_decompressor j12init_lossless_decompressor +#endif + +#define _jcopy_sample_rows j12copy_sample_rows + +/* Global internal functions (jdct.h) */ +#define _jpeg_fdct_islow jpeg12_fdct_islow +#define _jpeg_fdct_ifast jpeg12_fdct_ifast + +#define _jpeg_idct_islow jpeg12_idct_islow +#define _jpeg_idct_ifast jpeg12_idct_ifast +#define _jpeg_idct_float jpeg12_idct_float +#define _jpeg_idct_7x7 jpeg12_idct_7x7 +#define _jpeg_idct_6x6 jpeg12_idct_6x6 +#define _jpeg_idct_5x5 jpeg12_idct_5x5 +#define _jpeg_idct_4x4 jpeg12_idct_4x4 +#define _jpeg_idct_3x3 jpeg12_idct_3x3 +#define _jpeg_idct_2x2 jpeg12_idct_2x2 +#define _jpeg_idct_1x1 jpeg12_idct_1x1 +#define _jpeg_idct_9x9 jpeg12_idct_9x9 +#define _jpeg_idct_10x10 jpeg12_idct_10x10 +#define _jpeg_idct_11x11 jpeg12_idct_11x11 +#define _jpeg_idct_12x12 jpeg12_idct_12x12 +#define _jpeg_idct_13x13 jpeg12_idct_13x13 +#define _jpeg_idct_14x14 jpeg12_idct_14x14 +#define _jpeg_idct_15x15 jpeg12_idct_15x15 +#define _jpeg_idct_16x16 jpeg12_idct_16x16 + +/* Internal fields (cdjpeg.h) */ + +/* Use the 12-bit buffer in the cjpeg_source_struct and djpeg_dest_struct + structures. */ +#define _buffer buffer12 + +/* Image I/O functions (cdjpeg.h) */ +#define _jinit_read_gif j12init_read_gif +#define _jinit_write_gif j12init_write_gif +#define _jinit_read_ppm j12init_read_ppm +#define _jinit_write_ppm j12init_write_ppm + +#define _read_color_map read_color_map_12 + +#else /* BITS_IN_JSAMPLE */ + +/* Sample data types and macros (jmorecfg.h) */ +#define _JSAMPLE JSAMPLE + +#define _MAXJSAMPLE MAXJSAMPLE +#define _CENTERJSAMPLE CENTERJSAMPLE + +#define _JSAMPROW JSAMPROW +#define _JSAMPARRAY JSAMPARRAY +#define _JSAMPIMAGE JSAMPIMAGE + +/* External functions (jpeglib.h) */ +#define _jpeg_write_scanlines jpeg_write_scanlines +#define _jpeg_write_raw_data jpeg_write_raw_data +#define _jpeg_read_scanlines jpeg_read_scanlines +#define _jpeg_skip_scanlines jpeg_skip_scanlines +#define _jpeg_crop_scanline jpeg_crop_scanline +#define _jpeg_read_raw_data jpeg_read_raw_data + +/* Internal methods (jpegint.h) */ + +/* Use the 8-bit method in the jpeg_c_main_controller structure. */ +#define _process_data process_data +/* Use the 8-bit method in the jpeg_c_prep_controller structure. */ +#define _pre_process_data pre_process_data +/* Use the 8-bit method in the jpeg_c_coef_controller structure. */ +#define _compress_data compress_data +/* Use the 8-bit method in the jpeg_color_converter structure. */ +#define _color_convert color_convert +/* Use the 8-bit method in the jpeg_downsampler structure. */ +#define _downsample downsample +/* Use the 8-bit method in the jpeg_forward_dct structure. */ +#define _forward_DCT forward_DCT +/* Use the 8-bit method in the jpeg_d_main_controller structure. */ +#define _process_data process_data +/* Use the 8-bit method in the jpeg_d_coef_controller structure. */ +#define _decompress_data decompress_data +/* Use the 8-bit method in the jpeg_d_post_controller structure. */ +#define _post_process_data post_process_data +/* Use the 8-bit method in the jpeg_inverse_dct structure. */ +#define _inverse_DCT_method_ptr inverse_DCT_method_ptr +#define _inverse_DCT inverse_DCT +/* Use the 8-bit method in the jpeg_upsampler structure. */ +#define _upsample upsample +/* Use the 8-bit method in the jpeg_color_converter structure. */ +#define _color_convert color_convert +/* Use the 8-bit method in the jpeg_color_quantizer structure. */ +#define _color_quantize color_quantize + +/* Global internal functions (jpegint.h) */ +#define _jinit_c_main_controller jinit_c_main_controller +#define _jinit_c_prep_controller jinit_c_prep_controller +#define _jinit_c_coef_controller jinit_c_coef_controller +#define _jinit_color_converter jinit_color_converter +#define _jinit_downsampler jinit_downsampler +#define _jinit_forward_dct jinit_forward_dct +#ifdef C_LOSSLESS_SUPPORTED +#define _jinit_c_diff_controller jinit_c_diff_controller +#define _jinit_lossless_compressor jinit_lossless_compressor +#endif + +#define _jinit_d_main_controller jinit_d_main_controller +#define _jinit_d_coef_controller jinit_d_coef_controller +#define _jinit_d_post_controller jinit_d_post_controller +#define _jinit_inverse_dct jinit_inverse_dct +#define _jinit_upsampler jinit_upsampler +#define _jinit_color_deconverter jinit_color_deconverter +#define _jinit_1pass_quantizer jinit_1pass_quantizer +#define _jinit_2pass_quantizer jinit_2pass_quantizer +#define _jinit_merged_upsampler jinit_merged_upsampler +#ifdef D_LOSSLESS_SUPPORTED +#define _jinit_d_diff_controller jinit_d_diff_controller +#define _jinit_lossless_decompressor jinit_lossless_decompressor +#endif + +#define _jcopy_sample_rows jcopy_sample_rows + +/* Global internal functions (jdct.h) */ +#define _jpeg_fdct_islow jpeg_fdct_islow +#define _jpeg_fdct_ifast jpeg_fdct_ifast + +#define _jpeg_idct_islow jpeg_idct_islow +#define _jpeg_idct_ifast jpeg_idct_ifast +#define _jpeg_idct_float jpeg_idct_float +#define _jpeg_idct_7x7 jpeg_idct_7x7 +#define _jpeg_idct_6x6 jpeg_idct_6x6 +#define _jpeg_idct_5x5 jpeg_idct_5x5 +#define _jpeg_idct_4x4 jpeg_idct_4x4 +#define _jpeg_idct_3x3 jpeg_idct_3x3 +#define _jpeg_idct_2x2 jpeg_idct_2x2 +#define _jpeg_idct_1x1 jpeg_idct_1x1 +#define _jpeg_idct_9x9 jpeg_idct_9x9 +#define _jpeg_idct_10x10 jpeg_idct_10x10 +#define _jpeg_idct_11x11 jpeg_idct_11x11 +#define _jpeg_idct_12x12 jpeg_idct_12x12 +#define _jpeg_idct_13x13 jpeg_idct_13x13 +#define _jpeg_idct_14x14 jpeg_idct_14x14 +#define _jpeg_idct_15x15 jpeg_idct_15x15 +#define _jpeg_idct_16x16 jpeg_idct_16x16 + +/* Internal fields (cdjpeg.h) */ + +/* Use the 8-bit buffer in the cjpeg_source_struct and djpeg_dest_struct + structures. */ +#define _buffer buffer + +/* Image I/O functions (cdjpeg.h) */ +#define _jinit_read_gif jinit_read_gif +#define _jinit_write_gif jinit_write_gif +#define _jinit_read_ppm jinit_read_ppm +#define _jinit_write_ppm jinit_write_ppm + +#define _read_color_map read_color_map + +#endif /* BITS_IN_JSAMPLE */ + +#endif /* JSAMPLECOMP_H */ diff --git a/3rdparty/libjpeg-turbo/src/jsimd.h b/3rdparty/libjpeg-turbo/src/jsimd.h index 6c203655ef84..6ae021a651df 100644 --- a/3rdparty/libjpeg-turbo/src/jsimd.h +++ b/3rdparty/libjpeg-turbo/src/jsimd.h @@ -2,8 +2,8 @@ * jsimd.h * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2011, 2014, D. R. Commander. - * Copyright (C) 2015-2016, 2018, Matthieu Darbois. + * Copyright (C) 2011, 2014, 2022, D. R. Commander. + * Copyright (C) 2015-2016, 2018, 2022, Matthieu Darbois. * Copyright (C) 2020, Arm Limited. * * Based on the x86 SIMD extension for IJG JPEG library, @@ -12,6 +12,8 @@ * */ +#ifdef WITH_SIMD + #include "jchuff.h" /* Declarations shared with jcphuff.c */ EXTERN(int) jsimd_can_rgb_ycc(void); @@ -114,10 +116,12 @@ EXTERN(int) jsimd_can_encode_mcu_AC_first_prepare(void); EXTERN(void) jsimd_encode_mcu_AC_first_prepare (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, - JCOEF *values, size_t *zerobits); + UJCOEF *values, size_t *zerobits); EXTERN(int) jsimd_can_encode_mcu_AC_refine_prepare(void); EXTERN(int) jsimd_encode_mcu_AC_refine_prepare (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, - JCOEF *absvalues, size_t *bits); + UJCOEF *absvalues, size_t *bits); + +#endif /* WITH_SIMD */ diff --git a/3rdparty/libjpeg-turbo/src/jsimd_none.c b/3rdparty/libjpeg-turbo/src/jsimd_none.c deleted file mode 100644 index 5b38a9fb5c99..000000000000 --- a/3rdparty/libjpeg-turbo/src/jsimd_none.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * jsimd_none.c - * - * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009-2011, 2014, D. R. Commander. - * Copyright (C) 2015-2016, 2018, Matthieu Darbois. - * Copyright (C) 2020, Arm Limited. - * - * Based on the x86 SIMD extension for IJG JPEG library, - * Copyright (C) 1999-2006, MIYASAKA Masaru. - * For conditions of distribution and use, see copyright notice in jsimdext.inc - * - * This file contains stubs for when there is no SIMD support available. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jsimd.h" -#include "jdct.h" -#include "jsimddct.h" - -GLOBAL(int) -jsimd_can_rgb_ycc(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_rgb_gray(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_ycc_rgb(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_ycc_rgb565(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_c_can_null_convert(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, - int num_rows) -{ -} - -GLOBAL(void) -jsimd_rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, - int num_rows) -{ -} - -GLOBAL(void) -jsimd_ycc_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, - int num_rows) -{ -} - -GLOBAL(void) -jsimd_ycc_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION input_row, JSAMPARRAY output_buf, - int num_rows) -{ -} - -GLOBAL(void) -jsimd_c_null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPIMAGE output_buf, JDIMENSION output_row, - int num_rows) -{ -} - -GLOBAL(int) -jsimd_can_h2v2_downsample(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_h2v1_downsample(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_h2v2_smooth_downsample(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ -} - -GLOBAL(void) -jsimd_h2v2_smooth_downsample(j_compress_ptr cinfo, - jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ -} - -GLOBAL(void) -jsimd_h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ -} - -GLOBAL(int) -jsimd_can_h2v2_upsample(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_h2v1_upsample(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_int_upsample(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) -{ -} - -GLOBAL(void) -jsimd_h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) -{ -} - -GLOBAL(void) -jsimd_h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) -{ -} - -GLOBAL(int) -jsimd_can_h2v2_fancy_upsample(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_h2v1_fancy_upsample(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_h1v2_fancy_upsample(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) -{ -} - -GLOBAL(void) -jsimd_h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) -{ -} - -GLOBAL(void) -jsimd_h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) -{ -} - -GLOBAL(int) -jsimd_can_h2v2_merged_upsample(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_h2v1_merged_upsample(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_h2v2_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) -{ -} - -GLOBAL(void) -jsimd_h2v1_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, - JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) -{ -} - -GLOBAL(int) -jsimd_can_convsamp(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_convsamp_float(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_convsamp(JSAMPARRAY sample_data, JDIMENSION start_col, - DCTELEM *workspace) -{ -} - -GLOBAL(void) -jsimd_convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col, - FAST_FLOAT *workspace) -{ -} - -GLOBAL(int) -jsimd_can_fdct_islow(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_fdct_ifast(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_fdct_float(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_fdct_islow(DCTELEM *data) -{ -} - -GLOBAL(void) -jsimd_fdct_ifast(DCTELEM *data) -{ -} - -GLOBAL(void) -jsimd_fdct_float(FAST_FLOAT *data) -{ -} - -GLOBAL(int) -jsimd_can_quantize(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_quantize_float(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_quantize(JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace) -{ -} - -GLOBAL(void) -jsimd_quantize_float(JCOEFPTR coef_block, FAST_FLOAT *divisors, - FAST_FLOAT *workspace) -{ -} - -GLOBAL(int) -jsimd_can_idct_2x2(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_idct_4x4(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_idct_6x6(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_idct_12x12(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) -{ -} - -GLOBAL(void) -jsimd_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) -{ -} - -GLOBAL(void) -jsimd_idct_6x6(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) -{ -} - -GLOBAL(void) -jsimd_idct_12x12(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) -{ -} - -GLOBAL(int) -jsimd_can_idct_islow(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_idct_ifast(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_can_idct_float(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) -{ -} - -GLOBAL(void) -jsimd_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) -{ -} - -GLOBAL(void) -jsimd_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, - JDIMENSION output_col) -{ -} - -GLOBAL(int) -jsimd_can_huff_encode_one_block(void) -{ - return 0; -} - -GLOBAL(JOCTET *) -jsimd_huff_encode_one_block(void *state, JOCTET *buffer, JCOEFPTR block, - int last_dc_val, c_derived_tbl *dctbl, - c_derived_tbl *actbl) -{ - return NULL; -} - -GLOBAL(int) -jsimd_can_encode_mcu_AC_first_prepare(void) -{ - return 0; -} - -GLOBAL(void) -jsimd_encode_mcu_AC_first_prepare(const JCOEF *block, - const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *values, size_t *zerobits) -{ -} - -GLOBAL(int) -jsimd_can_encode_mcu_AC_refine_prepare(void) -{ - return 0; -} - -GLOBAL(int) -jsimd_encode_mcu_AC_refine_prepare(const JCOEF *block, - const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *absvalues, size_t *bits) -{ - return 0; -} diff --git a/3rdparty/libjpeg-turbo/src/jutils.c b/3rdparty/libjpeg-turbo/src/jutils.c index d86271624a66..24caac19021d 100644 --- a/3rdparty/libjpeg-turbo/src/jutils.c +++ b/3rdparty/libjpeg-turbo/src/jutils.c @@ -17,8 +17,11 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jsamplecomp.h" +#if BITS_IN_JSAMPLE == 8 + /* * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element * of a DCT block read in natural order (left to right, top to bottom). @@ -89,19 +92,24 @@ jround_up(long a, long b) return a - (a % b); } +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE != 16 || \ + defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) GLOBAL(void) -jcopy_sample_rows(JSAMPARRAY input_array, int source_row, - JSAMPARRAY output_array, int dest_row, int num_rows, - JDIMENSION num_cols) +_jcopy_sample_rows(_JSAMPARRAY input_array, int source_row, + _JSAMPARRAY output_array, int dest_row, int num_rows, + JDIMENSION num_cols) /* Copy some rows of samples from one place to another. * num_rows rows are copied from input_array[source_row++] * to output_array[dest_row++]; these areas may overlap for duplication. * The source and destination arrays must be at least as wide as num_cols. */ { - register JSAMPROW inptr, outptr; - register size_t count = (size_t)(num_cols * sizeof(JSAMPLE)); + register _JSAMPROW inptr, outptr; + register size_t count = (size_t)(num_cols * sizeof(_JSAMPLE)); register int row; input_array += source_row; @@ -114,6 +122,11 @@ jcopy_sample_rows(JSAMPARRAY input_array, int source_row, } } +#endif /* BITS_IN_JSAMPLE != 16 || + defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) */ + + +#if BITS_IN_JSAMPLE == 8 GLOBAL(void) jcopy_block_row(JBLOCKROW input_row, JBLOCKROW output_row, @@ -131,3 +144,5 @@ jzero_far(void *target, size_t bytestozero) { memset(target, 0, bytestozero); } + +#endif /* BITS_IN_JSAMPLE == 8 */ diff --git a/3rdparty/libjpeg-turbo/src/jversion.h.in b/3rdparty/libjpeg-turbo/src/jversion.h.in index dca4f08fdb4c..fc0ce3e09e3b 100644 --- a/3rdparty/libjpeg-turbo/src/jversion.h.in +++ b/3rdparty/libjpeg-turbo/src/jversion.h.in @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding. * libjpeg-turbo Modifications: - * Copyright (C) 2010, 2012-2022, D. R. Commander. + * Copyright (C) 2010, 2012-2024, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -36,19 +36,21 @@ * their code */ -#define JCOPYRIGHT \ - "Copyright (C) 2009-2022 D. R. Commander\n" \ +#define JCOPYRIGHT1 \ + "Copyright (C) 2009-2024 D. R. Commander\n" \ "Copyright (C) 2015, 2020 Google, Inc.\n" \ "Copyright (C) 2019-2020 Arm Limited\n" \ "Copyright (C) 2015-2016, 2018 Matthieu Darbois\n" \ "Copyright (C) 2011-2016 Siarhei Siamashka\n" \ - "Copyright (C) 2015 Intel Corporation\n" \ + "Copyright (C) 2015 Intel Corporation\n" +#define JCOPYRIGHT2 \ "Copyright (C) 2013-2014 Linaro Limited\n" \ "Copyright (C) 2013-2014 MIPS Technologies, Inc.\n" \ "Copyright (C) 2009, 2012 Pierre Ossman for Cendio AB\n" \ "Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \ "Copyright (C) 1999-2006 MIYASAKA Masaru\n" \ - "Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding" + "Copyright (C) 1999 Ken Murchison\n" \ + "Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding\n" #define JCOPYRIGHT_SHORT \ "Copyright (C) @COPYRIGHT_YEAR@ The libjpeg-turbo Project and many others" diff --git a/3rdparty/libjpeg-turbo/src/libjpeg.map.in b/3rdparty/libjpeg-turbo/src/libjpeg.map.in new file mode 100644 index 000000000000..b4480d834773 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/libjpeg.map.in @@ -0,0 +1,11 @@ +LIBJPEGTURBO_@JPEG_LIB_VERSION_DECIMAL@ { + @MEM_SRCDST_FUNCTIONS@ + local: + jsimd_*; + jconst_*; +}; + +LIBJPEG_@JPEG_LIB_VERSION_DECIMAL@ { + global: + *; +}; diff --git a/3rdparty/libjpeg-turbo/src/libjpeg.txt b/3rdparty/libjpeg-turbo/src/libjpeg.txt new file mode 100644 index 000000000000..0fe95bb63c43 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/libjpeg.txt @@ -0,0 +1,3282 @@ +USING THE IJG JPEG LIBRARY + +This file was part of the Independent JPEG Group's software: +Copyright (C) 1994-2013, Thomas G. Lane, Guido Vollbeding. +Lossless JPEG Modifications: +Copyright (C) 1999, Ken Murchison. +libjpeg-turbo Modifications: +Copyright (C) 2010, 2014-2018, 2020, 2022-2023, D. R. Commander. +Copyright (C) 2015, Google, Inc. +For conditions of distribution and use, see the accompanying README.ijg file. + + +This file describes how to use the IJG JPEG library within an application +program. Read it if you want to write a program that uses the library. + +The file example.c provides heavily commented code for calling the JPEG +library. Also see jpeglib.h (the include file to be used by application +programs) for full details about data structures and function parameter lists. +The library source code, of course, is the ultimate reference. + +Note that there have been *major* changes from the application interface +presented by IJG version 4 and earlier versions. The old design had several +inherent limitations, and it had accumulated a lot of cruft as we added +features while trying to minimize application-interface changes. We have +sacrificed backward compatibility in the version 5 rewrite, but we think the +improvements justify this. + + +TABLE OF CONTENTS +----------------- + +Overview: + Functions provided by the library + 12-bit and 16-bit Data Precision + Outline of typical usage +Basic library usage: + Data formats + Compression details + Decompression details + Partial image decompression + Mechanics of usage: include files, linking, etc +Advanced features: + Compression parameter selection + Decompression parameter selection + Special color spaces + Error handling + Compressed data handling (source and destination managers) + I/O suspension + Progressive JPEG support + Buffered-image mode + Abbreviated datastreams and multiple images + Special markers + ICC profiles + Raw (downsampled) image data + Really raw data: DCT coefficients + Progress monitoring + Memory management + Memory usage + Library compile-time options + Portability considerations + +You should read at least the overview and basic usage sections before trying +to program with the library. The sections on advanced features can be read +if and when you need them. + + +OVERVIEW +======== + +Functions provided by the library +--------------------------------- + +The IJG JPEG library provides C code to read and write JPEG-compressed image +files. The surrounding application program receives or supplies image data a +scanline at a time, using a straightforward uncompressed image format. All +details of color conversion and other preprocessing/postprocessing can be +handled by the library. + +The library includes a substantial amount of code that is not covered by the +JPEG standard but is necessary for typical applications of JPEG. These +functions preprocess the image before JPEG compression or postprocess it after +decompression. They include colorspace conversion, downsampling/upsampling, +and color quantization. The application indirectly selects use of this code +by specifying the format in which it wishes to supply or receive image data. +For example, if colormapped output is requested, then the decompression +library automatically invokes color quantization. + +A wide range of quality vs. speed tradeoffs are possible in JPEG processing, +and even more so in decompression postprocessing. The decompression library +provides multiple implementations that cover most of the useful tradeoffs, +ranging from very-high-quality down to fast-preview operation. On the +compression side we have generally not provided low-quality choices, since +compression is normally less time-critical. It should be understood that the +low-quality modes may not meet the JPEG standard's accuracy requirements; +nonetheless, they are useful for viewers. + +A word about functions *not* provided by the library. We handle a subset of +the ISO JPEG standard; most baseline, extended-sequential, and progressive +JPEG processes are supported. (Our subset includes all features now in common +use.) Unsupported ISO options include: + * Hierarchical storage + * DNL marker + * Nonintegral subsampling ratios +We support 8-bit (lossy and lossless), 12-bit (lossy and lossless), and 16-bit +(lossless) data precision. + +By itself, the library handles only interchange JPEG datastreams --- in +particular the widely used JFIF file format. The library can be used by +surrounding code to process interchange or abbreviated JPEG datastreams that +are embedded in more complex file formats. (For example, this library is +used by the free LIBTIFF library to support JPEG compression in TIFF.) + + +12-bit and 16-bit Data Precision +-------------------------------- + +The JPEG standard provides for baseline 8-bit and 12-bit DCT processes as well +as 8-bit, 12-bit, and 16-bit lossless (predictive) processes. This code +supports 12-bit-per-component lossy or lossless JPEG if you set +cinfo->data_precision to 12 and 16-bit-per-component lossless JPEG if you set +cinfo->data_precision to 16. Note that this causes the sample size to be +larger than a char, so it affects the surrounding application's image data. +The sample applications cjpeg and djpeg can support 12-bit mode only for PPM, +PGM, and GIF file formats and 16-bit mode only for PPM and PGM file formats. + +Note that, when 12-bit data precision is enabled, the library always compresses +in Huffman optimization mode, in order to generate valid Huffman tables. This +is necessary because our default Huffman tables only cover 8-bit data. If you +need to output 12-bit files in one pass, you'll have to supply suitable default +Huffman tables. You may also want to supply your own DCT quantization tables; +the existing quality-scaling code has been developed for 8-bit use, and +probably doesn't generate especially good tables for 12-bit. + +Functions that are specific to 12-bit data precision have a prefix of "jpeg12_" +instead of "jpeg_" and use the following data types and macros: + + * J12SAMPLE instead of JSAMPLE + * J12SAMPROW instead of JSAMPROW + * J12SAMPARRAY instead of JSAMPARRAY + * J12SAMPIMAGE instead of JSAMPIMAGE + * MAXJ12SAMPLE instead of MAXJSAMPLE + * CENTERJ12SAMPLE instead of CENTERJSAMPLE + +Functions that are specific to 16-bit data precision have a prefix of "jpeg16_" +instead of "jpeg_" and use the following data types and macros: + + * J16SAMPLE instead of JSAMPLE + * J16SAMPROW instead of JSAMPROW + * J16SAMPARRAY instead of JSAMPARRAY + * J16SAMPIMAGE instead of JSAMPIMAGE + * MAXJ16SAMPLE instead of MAXJSAMPLE + * CENTERJ16SAMPLE instead of CENTERJSAMPLE + +This allows 8-bit, 12-bit, and 16-bit data precision to be used in a single +application. (Refer to example.c). Arithmetic coding and SIMD acceleration +are not currently implemented for 12-bit data precision, nor are they +implemented for lossless mode with any data precision. + +Refer to the descriptions of the data_precision compression and decompression +parameters below for further information. + +This documentation uses "J*SAMPLE", "J*SAMPROW", "J*SAMPARRAY", and +"J*SAMPIMAGE" to generically refer to the 8-bit, 12-bit, or 16-bit data types. + + +Outline of typical usage +------------------------ + +The rough outline of a JPEG compression operation is: + + Allocate and initialize a JPEG compression object + Specify the destination for the compressed data (eg, a file) + Set parameters for compression, including image size & colorspace + jpeg_start_compress(...); + while (scan lines remain to be written) + jpeg_write_scanlines(...); /* Use jpeg12_write_scanlines() for + 12-bit data precision and + jpeg16_write_scanlines() for + 16-bit data precision. */ + jpeg_finish_compress(...); + Release the JPEG compression object + +A JPEG compression object holds parameters and working state for the JPEG +library. We make creation/destruction of the object separate from starting +or finishing compression of an image; the same object can be re-used for a +series of image compression operations. This makes it easy to re-use the +same parameter settings for a sequence of images. Re-use of a JPEG object +also has important implications for processing abbreviated JPEG datastreams, +as discussed later. + +The image data to be compressed is supplied to jpeg*_write_scanlines() from +in-memory buffers. If the application is doing file-to-file compression, +reading image data from the source file is the application's responsibility. +The library emits compressed data by calling a "data destination manager", +which typically will write the data into a file; but the application can +provide its own destination manager to do something else. + +Similarly, the rough outline of a JPEG decompression operation is: + + Allocate and initialize a JPEG decompression object + Specify the source of the compressed data (eg, a file) + Call jpeg_read_header() to obtain image info + Set parameters for decompression + jpeg_start_decompress(...); + while (scan lines remain to be read) + jpeg_read_scanlines(...); /* Use jpeg12_read_scanlines() for + 12-bit data precision and + jpeg16_read_scanlines() for + 16-bit data precision. */ + jpeg_finish_decompress(...); + Release the JPEG decompression object + +This is comparable to the compression outline except that reading the +datastream header is a separate step. This is helpful because information +about the image's size, colorspace, etc is available when the application +selects decompression parameters. For example, the application can choose an +output scaling ratio that will fit the image into the available screen size. + +The decompression library obtains compressed data by calling a data source +manager, which typically will read the data from a file; but other behaviors +can be obtained with a custom source manager. Decompressed data is delivered +into in-memory buffers passed to jpeg*_read_scanlines(). + +It is possible to abort an incomplete compression or decompression operation +by calling jpeg_abort(); or, if you do not need to retain the JPEG object, +simply release it by calling jpeg_destroy(). + +JPEG compression and decompression objects are two separate struct types. +However, they share some common fields, and certain routines such as +jpeg_destroy() can work on either type of object. + +The JPEG library has no static variables: all state is in the compression +or decompression object. Therefore it is possible to process multiple +compression and decompression operations concurrently, using multiple JPEG +objects. + +Both compression and decompression can be done in an incremental memory-to- +memory fashion, if suitable source/destination managers are used. See the +section on "I/O suspension" for more details. + + +BASIC LIBRARY USAGE +=================== + +Data formats +------------ + +Before diving into procedural details, it is helpful to understand the +image data format that the JPEG library expects or returns. + +The standard input image format is a rectangular array of pixels, with each +pixel having the same number of "component" or "sample" values (color +channels). You must specify how many components there are and the colorspace +interpretation of the components. Most applications will use RGB data +(three components per pixel) or grayscale data (one component per pixel). +PLEASE NOTE THAT RGB DATA IS THREE SAMPLES PER PIXEL, GRAYSCALE ONLY ONE. +A remarkable number of people manage to miss this, only to find that their +programs don't work with grayscale JPEG files. + +There is no provision for colormapped input. JPEG files are always full-color +or full grayscale (or sometimes another colorspace such as CMYK). You can +feed in a colormapped image by expanding it to full-color format. However +JPEG often doesn't work very well with source data that has been colormapped, +because of dithering noise. This is discussed in more detail in the JPEG FAQ +and the other references mentioned in the README.ijg file. + +Pixels are stored by scanlines, with each scanline running from left to +right. The component values for each pixel are adjacent in the row; for +example, R,G,B,R,G,B,R,G,B,... for 24-bit RGB color. Each scanline is an +array of data type JSAMPLE or J12SAMPLE --- which is typically "unsigned char" +or "short" (respectively), unless you've changed jmorecfg.h. (You can also +change the RGB pixel layout, say to B,G,R order, by modifying jmorecfg.h. But +see the restrictions listed in that file before doing so.) + +A 2-D array of pixels is formed by making a list of pointers to the starts of +scanlines; so the scanlines need not be physically adjacent in memory. Even +if you process just one scanline at a time, you must make a one-element +pointer array to conform to this structure. Pointers to J*SAMPLE rows are of +type J*SAMPROW, and the pointer to the pointer array is of type J*SAMPARRAY. + +The library accepts or supplies one or more complete scanlines per call. +It is not possible to process part of a row at a time. Scanlines are always +processed top-to-bottom. You can process an entire image in one call if you +have it all in memory, but usually it's simplest to process one scanline at +a time. + +For best results, source data values should have the precision specified by +cinfo->data_precision (normally 8 bits). For instance, if you choose to +compress data that's only 6 bits/channel, you should left-justify each value in +a byte before passing it to the compressor. If you need to compress data +that has more than 8 bits/channel, set cinfo->data_precision = 12 or 16. + + +The data format returned by the decompressor is the same in all details, +except that colormapped output is supported. (Again, a JPEG file is never +colormapped. But you can ask the decompressor to perform on-the-fly color +quantization to deliver colormapped output.) If you request colormapped +output then the returned data array contains a single J*SAMPLE per pixel; +its value is an index into a color map. The color map is represented as +a 2-D J*SAMPARRAY in which each row holds the values of one color component, +that is, colormap[i][j] is the value of the i'th color component for pixel +value (map index) j. Note that since the colormap indexes are stored in +J*SAMPLEs, the maximum number of colors is limited by the size of J*SAMPLE +(ie, at most 256 colors for 8-bit data precision, 4096 colors for 12-bit data +precision, and 65536 colors for 16-bit data precision). + + +Compression details +------------------- + +Here we revisit the JPEG compression outline given in the overview. + +1. Allocate and initialize a JPEG compression object. + +A JPEG compression object is a "struct jpeg_compress_struct". (It also has +a bunch of subsidiary structures which are allocated via malloc(), but the +application doesn't control those directly.) This struct can be just a local +variable in the calling routine, if a single routine is going to execute the +whole JPEG compression sequence. Otherwise it can be static or allocated +from malloc(). + +You will also need a structure representing a JPEG error handler. The part +of this that the library cares about is a "struct jpeg_error_mgr". If you +are providing your own error handler, you'll typically want to embed the +jpeg_error_mgr struct in a larger structure; this is discussed later under +"Error handling". For now we'll assume you are just using the default error +handler. The default error handler will print JPEG error/warning messages +on stderr, and it will call exit() if a fatal error occurs. + +You must initialize the error handler structure, store a pointer to it into +the JPEG object's "err" field, and then call jpeg_create_compress() to +initialize the rest of the JPEG object. + +Typical code for this step, if you are using the default error handler, is + + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + ... + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + +jpeg_create_compress allocates a small amount of memory, so it could fail +if you are out of memory. In that case it will exit via the error handler; +that's why the error handler must be initialized first. + + +2. Specify the destination for the compressed data (eg, a file). + +As previously mentioned, the JPEG library delivers compressed data to a +"data destination" module. The library includes one data destination +module which knows how to write to a stdio stream. You can use your own +destination module if you want to do something else, as discussed later. + +If you use the standard destination module, you must open the target stdio +stream beforehand. Typical code for this step looks like: + + FILE *outfile; + ... + if ((outfile = fopen(filename, "wb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_dest(&cinfo, outfile); + +where the last line invokes the standard destination module. + +WARNING: it is critical that the binary compressed data be delivered to the +output file unchanged. On non-Unix systems the stdio library may perform +newline translation or otherwise corrupt binary data. To suppress this +behavior, you may need to use a "b" option to fopen (as shown above), or use +setmode() or another routine to put the stdio stream in binary mode. See +cjpeg.c and djpeg.c for code that has been found to work on many systems. + +You can select the data destination after setting other parameters (step 3), +if that's more convenient. You may not change the destination between +calling jpeg_start_compress() and jpeg_finish_compress(). + + +3. Set parameters for compression, including image size & colorspace. + +You must supply information about the source image by setting the following +fields in the JPEG object (cinfo structure): + + image_width Width of image, in pixels + image_height Height of image, in pixels + input_components Number of color channels (samples per pixel) + in_color_space Color space of source image + +The image dimensions are, hopefully, obvious. JPEG supports image dimensions +of 1 to 64K pixels in either direction. The input color space is typically +RGB or grayscale, and input_components is 3 or 1 accordingly. (See "Special +color spaces", later, for more info.) The in_color_space field must be +assigned one of the J_COLOR_SPACE enum constants, typically JCS_RGB or +JCS_GRAYSCALE. + +JPEG has a large number of compression parameters that determine how the +image is encoded. Most applications don't need or want to know about all +these parameters. You can set all the parameters to reasonable defaults by +calling jpeg_set_defaults(); then, if there are particular values you want +to change, you can do so after that. The "Compression parameter selection" +section tells about all the parameters. + +You must set in_color_space correctly before calling jpeg_set_defaults(), +because the defaults depend on the source image colorspace. However the +other three source image parameters need not be valid until you call +jpeg_start_compress(). There's no harm in calling jpeg_set_defaults() more +than once, if that happens to be convenient. + +Typical code for a 24-bit RGB source image is + + cinfo.image_width = Width; /* image width and height, in pixels */ + cinfo.image_height = Height; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + + jpeg_set_defaults(&cinfo); + /* Make optional parameter settings here */ + + +4. jpeg_start_compress(...); + +After you have established the data destination and set all the necessary +source image info and other parameters, call jpeg_start_compress() to begin +a compression cycle. This will initialize internal state, allocate working +storage, and emit the first few bytes of the JPEG datastream header. + +Typical code: + + jpeg_start_compress(&cinfo, TRUE); + +The "TRUE" parameter ensures that a complete JPEG interchange datastream +will be written. This is appropriate in most cases. If you think you might +want to use an abbreviated datastream, read the section on abbreviated +datastreams, below. + +Once you have called jpeg_start_compress(), you may not alter any JPEG +parameters or other fields of the JPEG object until you have completed +the compression cycle. + + +5. while (scan lines remain to be written) + jpeg_write_scanlines(...); /* Use jpeg12_write_scanlines() for 12-bit + data precision and + jpeg16_write_scanlines() for 16-bit data + precision. */ + +Now write all the required image data by calling jpeg*_write_scanlines() +one or more times. You can pass one or more scanlines in each call, up +to the total image height. In most applications it is convenient to pass +just one or a few scanlines at a time. The expected format for the passed +data is discussed under "Data formats", above. + +Image data should be written in top-to-bottom scanline order. +Rec. ITU-T T.81 | ISO/IEC 10918-1 says, "Applications determine which edges of +a source image are defined as top, bottom, left, and right." However, if you +want your files to be compatible with everyone else's, then top-to-bottom order +must be used. If the source data must be read in bottom-to-top order, then you +can use the JPEG library's virtual array mechanism to invert the data +efficiently. Examples of this can be found in the sample application cjpeg. + +The library maintains a count of the number of scanlines written so far +in the next_scanline field of the JPEG object. Usually you can just use +this variable as the loop counter, so that the loop test looks like +"while (cinfo.next_scanline < cinfo.image_height)". + +Code for this step depends heavily on the way that you store the source data. +example.c shows the following code for the case of a full-size 2-D source +array containing 3-byte RGB pixels: + + JSAMPROW row_pointer[1]; /* pointer to a single row + Use J12SAMPROW for 12-bit data + precision and J16SAMPROW for 16-bit + data precision. */ + + while (cinfo.next_scanline < cinfo.image_height) { + row_pointer[0] = image_buffer[cinfo.next_scanline]; + jpeg_write_scanlines(&cinfo, row_pointer, 1); + /* Use jpeg12_write_scanlines() for + 12-bit data precision and + jpeg16_write_scanlines() for 16-bit + data precision. */ + } + +jpeg*_write_scanlines() returns the number of scanlines actually written. +This will normally be equal to the number passed in, so you can usually +ignore the return value. It is different in just two cases: + * If you try to write more scanlines than the declared image height, + the additional scanlines are ignored. + * If you use a suspending data destination manager, output buffer overrun + will cause the compressor to return before accepting all the passed lines. + This feature is discussed under "I/O suspension", below. The normal + stdio destination manager will NOT cause this to happen. +In any case, the return value is the same as the change in the value of +next_scanline. + + +6. jpeg_finish_compress(...); + +After all the image data has been written, call jpeg_finish_compress() to +complete the compression cycle. This step is ESSENTIAL to ensure that the +last bufferload of data is written to the data destination. +jpeg_finish_compress() also releases working memory associated with the JPEG +object. + +Typical code: + + jpeg_finish_compress(&cinfo); + +If using the stdio destination manager, don't forget to close the output +stdio stream (if necessary) afterwards. + +If you have requested a multi-pass operating mode, such as Huffman code +optimization, jpeg_finish_compress() will perform the additional passes using +data buffered by the first pass. In this case jpeg_finish_compress() may take +quite a while to complete. With the default compression parameters, this will +not happen. + +It is an error to call jpeg_finish_compress() before writing the necessary +total number of scanlines. If you wish to abort compression, call +jpeg_abort() as discussed below. + +After completing a compression cycle, you may dispose of the JPEG object +as discussed next, or you may use it to compress another image. In that case +return to step 2, 3, or 4 as appropriate. If you do not change the +destination manager, the new datastream will be written to the same target. +If you do not change any JPEG parameters, the new datastream will be written +with the same parameters as before. Note that you can change the input image +dimensions freely between cycles, but if you change the input colorspace, you +should call jpeg_set_defaults() to adjust for the new colorspace; and then +you'll need to repeat all of step 3. + + +7. Release the JPEG compression object. + +When you are done with a JPEG compression object, destroy it by calling +jpeg_destroy_compress(). This will free all subsidiary memory (regardless of +the previous state of the object). Or you can call jpeg_destroy(), which +works for either compression or decompression objects --- this may be more +convenient if you are sharing code between compression and decompression +cases. (Actually, these routines are equivalent except for the declared type +of the passed pointer. To avoid gripes from ANSI C compilers, jpeg_destroy() +should be passed a j_common_ptr.) + +If you allocated the jpeg_compress_struct structure from malloc(), freeing +it is your responsibility --- jpeg_destroy() won't. Ditto for the error +handler structure. + +Typical code: + + jpeg_destroy_compress(&cinfo); + + +8. Aborting. + +If you decide to abort a compression cycle before finishing, you can clean up +in either of two ways: + +* If you don't need the JPEG object any more, just call + jpeg_destroy_compress() or jpeg_destroy() to release memory. This is + legitimate at any point after calling jpeg_create_compress() --- in fact, + it's safe even if jpeg_create_compress() fails. + +* If you want to re-use the JPEG object, call jpeg_abort_compress(), or call + jpeg_abort() which works on both compression and decompression objects. + This will return the object to an idle state, releasing any working memory. + jpeg_abort() is allowed at any time after successful object creation. + +Note that cleaning up the data destination, if required, is your +responsibility; neither of these routines will call term_destination(). +(See "Compressed data handling", below, for more about that.) + +jpeg_destroy() and jpeg_abort() are the only safe calls to make on a JPEG +object that has reported an error by calling error_exit (see "Error handling" +for more info). The internal state of such an object is likely to be out of +whack. Either of these two routines will return the object to a known state. + + +Decompression details +--------------------- + +Here we revisit the JPEG decompression outline given in the overview. + +1. Allocate and initialize a JPEG decompression object. + +This is just like initialization for compression, as discussed above, +except that the object is a "struct jpeg_decompress_struct" and you +call jpeg_create_decompress(). Error handling is exactly the same. + +Typical code: + + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + ... + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + +(Both here and in the IJG code, we usually use variable name "cinfo" for +both compression and decompression objects.) + + +2. Specify the source of the compressed data (eg, a file). + +As previously mentioned, the JPEG library reads compressed data from a "data +source" module. The library includes one data source module which knows how +to read from a stdio stream. You can use your own source module if you want +to do something else, as discussed later. + +If you use the standard source module, you must open the source stdio stream +beforehand. Typical code for this step looks like: + + FILE *infile; + ... + if ((infile = fopen(filename, "rb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_src(&cinfo, infile); + +where the last line invokes the standard source module. + +WARNING: it is critical that the binary compressed data be read unchanged. +On non-Unix systems the stdio library may perform newline translation or +otherwise corrupt binary data. To suppress this behavior, you may need to use +a "b" option to fopen (as shown above), or use setmode() or another routine to +put the stdio stream in binary mode. See cjpeg.c and djpeg.c for code that +has been found to work on many systems. + +You may not change the data source between calling jpeg_read_header() and +jpeg_finish_decompress(). If you wish to read a series of JPEG images from +a single source file, you should repeat the jpeg_read_header() to +jpeg_finish_decompress() sequence without reinitializing either the JPEG +object or the data source module; this prevents buffered input data from +being discarded. + + +3. Call jpeg_read_header() to obtain image info. + +Typical code for this step is just + + jpeg_read_header(&cinfo, TRUE); + +This will read the source datastream header markers, up to the beginning +of the compressed data proper. On return, the image dimensions and other +info have been stored in the JPEG object. The application may wish to +consult this information before selecting decompression parameters. + +More complex code is necessary if + * A suspending data source is used --- in that case jpeg_read_header() + may return before it has read all the header data. See "I/O suspension", + below. The normal stdio source manager will NOT cause this to happen. + * Abbreviated JPEG files are to be processed --- see the section on + abbreviated datastreams. Standard applications that deal only in + interchange JPEG files need not be concerned with this case either. + +It is permissible to stop at this point if you just wanted to find out the +image dimensions and other header info for a JPEG file. In that case, +call jpeg_destroy() when you are done with the JPEG object, or call +jpeg_abort() to return it to an idle state before selecting a new data +source and reading another header. + + +4. Set parameters for decompression. + +jpeg_read_header() sets appropriate default decompression parameters based on +the properties of the image (in particular, its colorspace). However, you +may well want to alter these defaults before beginning the decompression. +For example, the default is to produce full color output from a color file. +If you want colormapped output you must ask for it. Other options allow the +returned image to be scaled and allow various speed/quality tradeoffs to be +selected. "Decompression parameter selection", below, gives details. + +If the defaults are appropriate, nothing need be done at this step. + +Note that all default values are set by each call to jpeg_read_header(). +If you reuse a decompression object, you cannot expect your parameter +settings to be preserved across cycles, as you can for compression. +You must set desired parameter values each time. + + +5. jpeg_start_decompress(...); + +Once the parameter values are satisfactory, call jpeg_start_decompress() to +begin decompression. This will initialize internal state, allocate working +memory, and prepare for returning data. + +Typical code is just + + jpeg_start_decompress(&cinfo); + +If you have requested a multi-pass operating mode, such as 2-pass color +quantization, jpeg_start_decompress() will do everything needed before data +output can begin. In this case jpeg_start_decompress() may take quite a while +to complete. With a single-scan (non progressive) JPEG file and default +decompression parameters, this will not happen; jpeg_start_decompress() will +return quickly. + +After this call, the final output image dimensions, including any requested +scaling, are available in the JPEG object; so is the selected colormap, if +colormapped output has been requested. Useful fields include + + output_width image width and height, as scaled + output_height + out_color_components # of color components in out_color_space + output_components # of color components returned per pixel + colormap the selected colormap, if any + actual_number_of_colors number of entries in colormap + +output_components is 1 (a colormap index) when quantizing colors; otherwise it +equals out_color_components. It is the number of J*SAMPLE values that will be +emitted per pixel in the output arrays. + +Typically you will need to allocate data buffers to hold the incoming image. +You will need output_width * output_components J*SAMPLEs per scanline in your +output buffer, and a total of output_height scanlines will be returned. + +Note: if you are using the JPEG library's internal memory manager to allocate +data buffers (as djpeg does), then the manager's protocol requires that you +request large buffers *before* calling jpeg_start_decompress(). This is a +little tricky since the output_XXX fields are not normally valid then. You +can make them valid by calling jpeg_calc_output_dimensions() after setting the +relevant parameters (scaling, output color space, and quantization flag). + + +6. while (scan lines remain to be read) + jpeg_read_scanlines(...); /* Use jpeg12_read_scanlines() for 12-bit + data precision and + jpeg16_read_scanlines() for 16-bit data + precision. */ + +Now you can read the decompressed image data by calling jpeg*_read_scanlines() +one or more times. At each call, you pass in the maximum number of scanlines +to be read (ie, the height of your working buffer); jpeg*_read_scanlines() +will return up to that many lines. The return value is the number of lines +actually read. The format of the returned data is discussed under "Data +formats", above. Don't forget that grayscale and color JPEGs will return +different data formats! + +Image data is returned in top-to-bottom scanline order. If you must write +out the image in bottom-to-top order, you can use the JPEG library's virtual +array mechanism to invert the data efficiently. Examples of this can be +found in the sample application djpeg. + +The library maintains a count of the number of scanlines returned so far +in the output_scanline field of the JPEG object. Usually you can just use +this variable as the loop counter, so that the loop test looks like +"while (cinfo.output_scanline < cinfo.output_height)". (Note that the test +should NOT be against image_height, unless you never use scaling. The +image_height field is the height of the original unscaled image.) +The return value always equals the change in the value of output_scanline. + +If you don't use a suspending data source, it is safe to assume that +jpeg*_read_scanlines() reads at least one scanline per call, until the +bottom of the image has been reached. + +If you use a buffer larger than one scanline, it is NOT safe to assume that +jpeg*_read_scanlines() fills it. (The current implementation returns only a +few scanlines per call, no matter how large a buffer you pass.) So you must +always provide a loop that calls jpeg*_read_scanlines() repeatedly until the +whole image has been read. + + +7. jpeg_finish_decompress(...); + +After all the image data has been read, call jpeg_finish_decompress() to +complete the decompression cycle. This causes working memory associated +with the JPEG object to be released. + +Typical code: + + jpeg_finish_decompress(&cinfo); + +If using the stdio source manager, don't forget to close the source stdio +stream if necessary. + +It is an error to call jpeg_finish_decompress() before reading the correct +total number of scanlines. If you wish to abort decompression, call +jpeg_abort() as discussed below. + +After completing a decompression cycle, you may dispose of the JPEG object as +discussed next, or you may use it to decompress another image. In that case +return to step 2 or 3 as appropriate. If you do not change the source +manager, the next image will be read from the same source. + + +8. Release the JPEG decompression object. + +When you are done with a JPEG decompression object, destroy it by calling +jpeg_destroy_decompress() or jpeg_destroy(). The previous discussion of +destroying compression objects applies here too. + +Typical code: + + jpeg_destroy_decompress(&cinfo); + + +9. Aborting. + +You can abort a decompression cycle by calling jpeg_destroy_decompress() or +jpeg_destroy() if you don't need the JPEG object any more, or +jpeg_abort_decompress() or jpeg_abort() if you want to reuse the object. +The previous discussion of aborting compression cycles applies here too. + + +Partial image decompression +--------------------------- + +Partial image decompression is convenient for performance-critical applications +that wish to view only a portion of a large JPEG image without decompressing +the whole thing. It it also useful in memory-constrained environments (such as +on mobile devices.) This library provides the following functions to support +partial image decompression: + +1. Skipping rows when decompressing + + jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines); + /* Use jpeg12_skip_scanlines() for 12-bit data precision. */ + +This function provides application programmers with the ability to skip over +multiple rows in the JPEG image. + +Suspending data sources are not supported by this function. Calling +jpeg*_skip_scanlines() with a suspending data source will result in undefined +behavior. Two-pass color quantization is also not supported by this function. +Calling jpeg*_skip_scanlines() with two-pass color quantization enabled will +result in an error. + +jpeg*_skip_scanlines() will not allow skipping past the bottom of the image. +If the value of num_lines is large enough to skip past the bottom of the image, +then the function will skip to the end of the image instead. + +If the value of num_lines is valid, then jpeg*_skip_scanlines() will always +skip all of the input rows requested. There is no need to inspect the return +value of the function in that case. + +Best results will be achieved by calling jpeg*_skip_scanlines() for large +chunks of rows. The function should be viewed as a way to quickly jump to a +particular vertical offset in the JPEG image in order to decode a subset of the +image. Used in this manner, it will provide significant performance +improvements. + +Calling jpeg*_skip_scanlines() for small values of num_lines has several +potential drawbacks: + 1) JPEG decompression occurs in blocks, so if jpeg*_skip_scanlines() is + called from the middle of a decompression block, then it is likely that + much of the decompression work has already been done for the first + couple of rows that need to be skipped. + 2) When this function returns, it must leave the decompressor in a state + such that it is ready to read the next line. This may involve + decompressing a block that must be partially skipped. +These issues are especially tricky for cases in which upsampling requires +context rows. In the worst case, jpeg*_skip_scanlines() will perform similarly +to jpeg*_read_scanlines() (since it will actually call jpeg*_read_scanlines().) + +2. Decompressing partial scanlines + + jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset, + JDIMENSION *width) + /* Use jpeg12_crop_scanline() for 12-bit data precision. */ + +This function provides application programmers with the ability to decompress +only a portion of each row in the JPEG image. It must be called after +jpeg_start_decompress() and before any calls to jpeg*_read_scanlines() or +jpeg*_skip_scanlines(). + +If xoffset and width do not form a valid subset of the image row, then this +function will generate an error. Note that if the output image is scaled, then +xoffset and width are relative to the scaled image dimensions. + +xoffset and width are passed by reference because xoffset must fall on an iMCU +boundary. If it doesn't, then it will be moved left to the nearest iMCU +boundary, and width will be increased accordingly. If the calling program does +not like the adjusted values of xoffset and width, then it can call +jpeg*_crop_scanline() again with new values (for instance, if it wants to move +xoffset to the nearest iMCU boundary to the right instead of to the left.) + +After calling this function, cinfo->output_width will be set to the adjusted +width. This value should be used when allocating an output buffer to pass to +jpeg*_read_scanlines(). + +The output image from a partial-width decompression will be identical to the +corresponding image region from a full decode, with one exception: The "fancy" +(smooth) h2v2 (4:2:0) and h2v1 (4:2:2) upsampling algorithms fill in the +missing chroma components by averaging the chroma components from neighboring +pixels, except on the right and left edges of the image (where there are no +neighboring pixels.) When performing a partial-width decompression, these +"fancy" upsampling algorithms may treat the left and right edges of the partial +image region as if they are the left and right edges of the image, meaning that +the upsampling algorithm may be simplified. The result is that the pixels on +the left or right edge of the partial image may not be exactly identical to the +corresponding pixels in the original image. + + +Mechanics of usage: include files, linking, etc +----------------------------------------------- + +Applications using the JPEG library should include the header file jpeglib.h +to obtain declarations of data types and routines. Before including +jpeglib.h, include system headers that define at least the typedefs FILE and +size_t. On ANSI-conforming systems, including is sufficient; on +older Unix systems, you may need to define size_t. + +If the application needs to refer to individual JPEG library error codes, also +include jerror.h to define those symbols. + +jpeglib.h indirectly includes the files jconfig.h and jmorecfg.h. If you are +installing the JPEG header files in a system directory, you will want to +install all four files: jpeglib.h, jerror.h, jconfig.h, jmorecfg.h. + +The most convenient way to include the JPEG code into your executable program +is to prepare a library file ("libjpeg.a", or a corresponding name on non-Unix +machines) and reference it at your link step. If you use only half of the +library (only compression or only decompression), only that much code will be +included from the library, unless your linker is hopelessly brain-damaged. +The supplied build system builds libjpeg.a automatically. + +It may be worth pointing out that the core JPEG library does not actually +require the stdio library: only the default source/destination managers and +error handler need it. You can use the library in a stdio-less environment +if you replace those modules and use jmemnobs.c (or another memory manager of +your own devising). More info about the minimum system library requirements +may be found in jinclude.h. + + +ADVANCED FEATURES +================= + +Compression parameter selection +------------------------------- + +This section describes all the optional parameters you can set for JPEG +compression, as well as the "helper" routines provided to assist in this +task. Proper setting of some parameters requires detailed understanding +of the JPEG standard; if you don't know what a parameter is for, it's best +not to mess with it! See REFERENCES in the README.ijg file for pointers to +more info about JPEG. + +It's a good idea to call jpeg_set_defaults() first, even if you plan to set +all the parameters; that way your code is more likely to work with future JPEG +libraries that have additional parameters. For the same reason, we recommend +you use a helper routine where one is provided, in preference to twiddling +cinfo fields directly. + +The helper routines are: + +jpeg_set_defaults (j_compress_ptr cinfo) + This routine sets all JPEG parameters to reasonable defaults, using + only the input image's color space (field in_color_space, which must + already be set in cinfo). Many applications will only need to use + this routine and perhaps jpeg_set_quality(). + +jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) + Sets the JPEG file's colorspace (field jpeg_color_space) as specified, + and sets other color-space-dependent parameters appropriately. See + "Special color spaces", below, before using this. A large number of + parameters, including all per-component parameters, are set by this + routine; if you want to twiddle individual parameters you should call + jpeg_set_colorspace() before rather than after. + +jpeg_default_colorspace (j_compress_ptr cinfo) + Selects an appropriate JPEG colorspace based on cinfo->in_color_space, + and calls jpeg_set_colorspace(). This is actually a subroutine of + jpeg_set_defaults(). It's broken out in case you want to change + just the colorspace-dependent JPEG parameters. + +jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) + Constructs JPEG quantization tables appropriate for the indicated + quality setting. The quality value is expressed on the 0..100 scale + recommended by IJG (cjpeg's "-quality" switch uses this routine). + Note that the exact mapping from quality values to tables may change + in future IJG releases as more is learned about DCT quantization. + If the force_baseline parameter is TRUE, then the quantization table + entries are constrained to the range 1..255 for full JPEG baseline + compatibility. In the current implementation, this only makes a + difference for quality settings below 25, and it effectively prevents + very small/low quality files from being generated. The IJG decoder + is capable of reading the non-baseline files generated at low quality + settings when force_baseline is FALSE, but other decoders may not be. + +jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, + boolean force_baseline) + Same as jpeg_set_quality() except that the generated tables are the + sample tables given in Annex K (Clause K.1) of + Rec. ITU-T T.81 (1992) | ISO/IEC 10918-1:1994, multiplied by the + specified scale factor (which is expressed as a percentage; thus + scale_factor = 100 reproduces the spec's tables). Note that larger + scale factors give lower quality. This entry point is useful for + conforming to the Adobe PostScript DCT conventions, but we do not + recommend linear scaling as a user-visible quality scale otherwise. + force_baseline again constrains the computed table entries to 1..255. + +int jpeg_quality_scaling (int quality) + Converts a value on the IJG-recommended quality scale to a linear + scaling percentage. Note that this routine may change or go away + in future releases --- IJG may choose to adopt a scaling method that + can't be expressed as a simple scalar multiplier, in which case the + premise of this routine collapses. Caveat user. + +jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline) + [libjpeg v7+ API/ABI emulation only] + Set default quantization tables with linear q_scale_factor[] values + (see below). + +jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) + Allows an arbitrary quantization table to be created. which_tbl + indicates which table slot to fill. basic_table points to an array + of 64 unsigned ints given in normal array order. These values are + multiplied by scale_factor/100 and then clamped to the range 1..65535 + (or to 1..255 if force_baseline is TRUE). + CAUTION: prior to library version 6a, jpeg_add_quant_table expected + the basic table to be given in JPEG zigzag order. If you need to + write code that works with either older or newer versions of this + routine, you must check the library version number. Something like + "#if JPEG_LIB_VERSION >= 61" is the right test. + +jpeg_simple_progression (j_compress_ptr cinfo) + Generates a default scan script for writing a progressive-JPEG file. + This is the recommended method of creating a progressive file, + unless you want to make a custom scan sequence. You must ensure that + the JPEG color space is set correctly before calling this routine. + +jpeg_enable_lossless (j_compress_ptr cinfo, int predictor_selection_value, + int point_transform) + Enables lossless mode with the specified predictor selection value + (1 - 7) and optional point transform (0 - {precision}-1, where + {precision} is the JPEG data precision). A point transform value of 0 + is necessary in order to create a fully lossless JPEG image. (A + non-zero point transform value right-shifts the input samples by the + specified number of bits, which is effectively a form of lossy color + quantization.) In most cases, lossless mode is considerably slower + than, and does not compress as effectively as, lossy mode. Thus, it is + typically used only for applications that require mathematically + lossless compression. Note that the following features will be + unavailable when compressing or decompressing lossless JPEG images: + * Partial image decompression + * Quality/quantization table selection + * DCT/IDCT algorithm selection + * Smoothing + * Downsampling/upsampling + * Color space conversion (the JPEG image will use the same color + space as the input image) + * Color quantization + * IDCT scaling + * Raw (downsampled) data input/output + * Transcoding of DCT coefficients + Any parameters used to enable or configure those features will be + ignored. + + Lossless mode shares no algorithms with lossy mode. Instead, it uses + differential pulse-code modulation (DPCM), an algorithm whereby each + sample is encoded as the difference between the sample's value and a + "predictor", which is based on the values of neighboring samples. If + Ra is the sample immediately to the left of the current sample, Rb is + the sample immediately above the current sample, and Rc is the sample + diagonally to the left and above the current sample, then the + relationship between the predictor selection value and the predictor is + as follows: + + PSV Predictor + -------------- + 1 Ra + 2 Rb + 3 Rc + 4 Ra + Rb – Rc + 5 Ra + (Rb – Rc) / 2 + 6 Rb + (Ra – Rc) / 2 + 7 (Ra + Rb) / 2 + + Predictors 1-3 are 1-dimensional predictors, whereas Predictors 4-7 are + 2-dimensional predictors. The best predictor for a particular image + depends on the image. + + +Compression parameters (cinfo fields) include: + +boolean arith_code + If TRUE, use arithmetic coding. + If FALSE, use Huffman coding. + +int data_precision + To create a 12-bit-per-component JPEG file, set data_precision to 12 + prior to calling jpeg_start_compress() or using the memory manager, + then use jpeg12_write_scanlines() or jpeg12_write_raw_data() instead of + jpeg_write_scanlines() or jpeg_write_raw_data(). To create a + 16-bit-per-component lossless JPEG file, set data_precision to 16 prior + to calling jpeg_start_compress() or using the memory manager, then use + jpeg16_write_scanlines() instead of jpeg_write_scanlines(). Note that + 16-bit data precision requires lossless mode. (See + jpeg_enable_lossless().) + +J_DCT_METHOD dct_method + Selects the algorithm used for the DCT step. Choices are: + JDCT_ISLOW: accurate integer method + JDCT_IFAST: less accurate integer method [legacy feature] + JDCT_FLOAT: floating-point method [legacy feature] + JDCT_DEFAULT: default method (normally JDCT_ISLOW) + JDCT_FASTEST: fastest method (normally JDCT_IFAST) + When the Independent JPEG Group's software was first released in 1991, + the compression time for a 1-megapixel JPEG image on a mainstream PC + was measured in minutes. Thus, JDCT_IFAST provided noticeable + performance benefits. On modern CPUs running libjpeg-turbo, however, + the compression time for a 1-megapixel JPEG image is measured in + milliseconds, and thus the performance benefits of JDCT_IFAST are much + less noticeable. On modern x86/x86-64 CPUs that support AVX2 + instructions, JDCT_IFAST and JDCT_ISLOW have similar performance. On + other types of CPUs, JDCT_IFAST is generally about 5-15% faster than + JDCT_ISLOW. + + For quality levels of 90 and below, there should be little or no + perceptible quality difference between the two algorithms. For quality + levels above 90, however, the difference between JDCT_IFAST and + JDCT_ISLOW becomes more pronounced. With quality=97, for instance, + JDCT_IFAST incurs generally about a 1-3 dB loss in PSNR relative to + JDCT_ISLOW, but this can be larger for some images. Do not use + JDCT_IFAST with quality levels above 97. The algorithm often + degenerates at quality=98 and above and can actually produce a more + lossy image than if lower quality levels had been used. Also, in + libjpeg-turbo, JDCT_IFAST is not fully accelerated for quality levels + above 97, so it will be slower than JDCT_ISLOW. + + JDCT_FLOAT does not produce significantly more accurate results than + JDCT_ISLOW, and it is much slower. JDCT_FLOAT may also give different + results on different machines due to varying roundoff behavior, whereas + the integer methods should give the same results on all machines. + +J_COLOR_SPACE jpeg_color_space +int num_components + The JPEG color space and corresponding number of components; see + "Special color spaces", below, for more info. We recommend using + jpeg_set_color_space() if you want to change these. + +boolean optimize_coding + TRUE causes the compressor to compute optimal Huffman coding tables + for the image. This requires an extra pass over the data and + therefore costs a good deal of space and time. The default is + FALSE, which tells the compressor to use the supplied or default + Huffman tables. In most cases optimal tables save only a few percent + of file size compared to the default tables. Note that when this is + TRUE, you need not supply Huffman tables at all, and any you do + supply will be overwritten. + +unsigned int restart_interval +int restart_in_rows + To emit restart markers in the JPEG file, set one of these nonzero. + Set restart_interval to specify the exact interval in MCU blocks + (samples in lossless mode). Set restart_in_rows to specify the + interval in MCU rows. (If restart_in_rows is not 0, then + restart_interval is set after the image width in MCUs is computed.) + Defaults are zero (no restarts). One restart marker per MCU row is + often a good choice. NOTE: the overhead of restart markers is higher + in grayscale JPEG files than in color files, and MUCH higher in + progressive JPEGs. If you use restarts, you may want to use larger + intervals in those cases. + +const jpeg_scan_info *scan_info +int num_scans + By default, scan_info is NULL; this causes the compressor to write a + single-scan sequential JPEG file. If not NULL, scan_info points to + an array of scan definition records of length num_scans. The + compressor will then write a JPEG file having one scan for each scan + definition record. This is used to generate noninterleaved or + progressive JPEG files. The library checks that the scan array + defines a valid JPEG scan sequence. (jpeg_simple_progression creates + a suitable scan definition array for progressive JPEG.) This is + discussed further under "Progressive JPEG support". + +int smoothing_factor + If non-zero, the input image is smoothed; the value should be 1 for + minimal smoothing to 100 for maximum smoothing. Consult jcsample.c + for details of the smoothing algorithm. The default is zero. + +boolean write_JFIF_header + If TRUE, a JFIF APP0 marker is emitted. jpeg_set_defaults() and + jpeg_set_colorspace() set this TRUE if a JFIF-legal JPEG color space + (ie, YCbCr or grayscale) is selected, otherwise FALSE. + +UINT8 JFIF_major_version +UINT8 JFIF_minor_version + The version number to be written into the JFIF marker. + jpeg_set_defaults() initializes the version to 1.01 (major=minor=1). + You should set it to 1.02 (major=1, minor=2) if you plan to write + any JFIF 1.02 extension markers. + +UINT8 density_unit +UINT16 X_density +UINT16 Y_density + The resolution information to be written into the JFIF marker; + not used otherwise. density_unit may be 0 for unknown, + 1 for dots/inch, or 2 for dots/cm. The default values are 0,1,1 + indicating square pixels of unknown size. + +boolean write_Adobe_marker + If TRUE, an Adobe APP14 marker is emitted. jpeg_set_defaults() and + jpeg_set_colorspace() set this TRUE if JPEG color space RGB, CMYK, + or YCCK is selected, otherwise FALSE. It is generally a bad idea + to set both write_JFIF_header and write_Adobe_marker. In fact, + you probably shouldn't change the default settings at all --- the + default behavior ensures that the JPEG file's color space can be + recognized by the decoder. + +JQUANT_TBL *quant_tbl_ptrs[NUM_QUANT_TBLS] + Pointers to coefficient quantization tables, one per table slot, + or NULL if no table is defined for a slot. Usually these should + be set via one of the above helper routines; jpeg_add_quant_table() + is general enough to define any quantization table. The other + routines will set up table slot 0 for luminance quality and table + slot 1 for chrominance. + +int q_scale_factor[NUM_QUANT_TBLS] + [libjpeg v7+ API/ABI emulation only] + Linear quantization scaling factors (0-100, default 100) + for use with jpeg_default_qtables(). + See rdswitch.c and cjpeg.c for an example of usage. + Note that the q_scale_factor[] values use "linear" scales, so JPEG + quality levels chosen by the user must be converted to these scales + using jpeg_quality_scaling(). Here is an example that corresponds to + cjpeg -quality 90,70: + + jpeg_set_defaults(cinfo); + + /* Set luminance quality 90. */ + cinfo->q_scale_factor[0] = jpeg_quality_scaling(90); + /* Set chrominance quality 70. */ + cinfo->q_scale_factor[1] = jpeg_quality_scaling(70); + + jpeg_default_qtables(cinfo, force_baseline); + + CAUTION: Setting separate quality levels for chrominance and luminance + is mainly only useful if chrominance subsampling is disabled. 2x2 + chrominance subsampling (AKA "4:2:0") is the default, but you can + explicitly disable subsampling as follows: + + cinfo->comp_info[0].v_samp_factor = 1; + cinfo->comp_info[0].h_samp_factor = 1; + +JHUFF_TBL *dc_huff_tbl_ptrs[NUM_HUFF_TBLS] +JHUFF_TBL *ac_huff_tbl_ptrs[NUM_HUFF_TBLS] + Pointers to Huffman coding tables, one per table slot, or NULL if + no table is defined for a slot. Slots 0 and 1 are filled with the + JPEG sample tables by jpeg_set_defaults(). If you need to allocate + more table structures, jpeg_alloc_huff_table() may be used. + Note that optimal Huffman tables can be computed for an image + by setting optimize_coding, as discussed above; there's seldom + any need to mess with providing your own Huffman tables. + + +[libjpeg v7+ API/ABI emulation only] +The actual dimensions of the JPEG image that will be written to the file are +given by the following fields. These are computed from the input image +dimensions and the compression parameters by jpeg_start_compress(). You can +also call jpeg_calc_jpeg_dimensions() to obtain the values that will result +from the current parameter settings. This can be useful if you are trying +to pick a scaling ratio that will get close to a desired target size. + +JDIMENSION jpeg_width Actual dimensions of output image. +JDIMENSION jpeg_height + + +Per-component parameters are stored in the struct cinfo.comp_info[i] for +component number i. Note that components here refer to components of the +JPEG color space, *not* the source image color space. A suitably large +comp_info[] array is allocated by jpeg_set_defaults(); if you choose not +to use that routine, it's up to you to allocate the array. + +int component_id + The one-byte identifier code to be recorded in the JPEG file for + this component. For the standard color spaces, we recommend you + leave the default values alone. + +int h_samp_factor +int v_samp_factor + Horizontal and vertical sampling factors for the component; must + be 1..4 according to the JPEG standard. Note that larger sampling + factors indicate a higher-resolution component; many people find + this behavior quite unintuitive. The default values are 2,2 for + luminance components and 1,1 for chrominance components, except + for grayscale where 1,1 is used. + +int quant_tbl_no + Quantization table number for component. The default value is + 0 for luminance components and 1 for chrominance components. + +int dc_tbl_no +int ac_tbl_no + DC and AC entropy coding table numbers. The default values are + 0 for luminance components and 1 for chrominance components. + +int component_index + Must equal the component's index in comp_info[]. (Beginning in + release v6, the compressor library will fill this in automatically; + you don't have to.) + + +Decompression parameter selection +--------------------------------- + +Decompression parameter selection is somewhat simpler than compression +parameter selection, since all of the JPEG internal parameters are +recorded in the source file and need not be supplied by the application. +(Unless you are working with abbreviated files, in which case see +"Abbreviated datastreams", below.) Decompression parameters control +the postprocessing done on the image to deliver it in a format suitable +for the application's use. Many of the parameters control speed/quality +tradeoffs, in which faster decompression may be obtained at the price of +a poorer-quality image. The defaults select the highest quality (slowest) +processing. + +The following fields in the JPEG object are set by jpeg_read_header() and +may be useful to the application in choosing decompression parameters: + +int data_precision Data precision (bits per component) + If data_precision is 12, then use jpeg12_read_scanlines(), + jpeg12_skip_scanlines(), jpeg12_crop_scanline(), and/or + jpeg12_read_raw_data() instead of jpeg_read_scanlines(), + jpeg_skip_scanlines(), jpeg_crop_scanline(), and/or + jpeg_read_raw_data(). If data_precision is 16, then use + jpeg16_read_scanlines() instead of jpeg_read_scanlines(). + +JDIMENSION image_width Width and height of image +JDIMENSION image_height +int num_components Number of color components +J_COLOR_SPACE jpeg_color_space Colorspace of image +boolean saw_JFIF_marker TRUE if a JFIF APP0 marker was seen + UINT8 JFIF_major_version Version information from JFIF marker + UINT8 JFIF_minor_version + UINT8 density_unit Resolution data from JFIF marker + UINT16 X_density + UINT16 Y_density +boolean saw_Adobe_marker TRUE if an Adobe APP14 marker was seen + UINT8 Adobe_transform Color transform code from Adobe marker + +The JPEG color space, unfortunately, is something of a guess since the JPEG +standard proper does not provide a way to record it. In practice most files +adhere to the JFIF or Adobe conventions, and the decoder will recognize these +correctly. See "Special color spaces", below, for more info. + + +The decompression parameters that determine the basic properties of the +returned image are: + +J_COLOR_SPACE out_color_space + Output color space. jpeg_read_header() sets an appropriate default + based on jpeg_color_space; typically it will be RGB or grayscale. + The application can change this field to request output in a different + colorspace. For example, set it to JCS_GRAYSCALE to get grayscale + output from a color file. (This is useful for previewing: grayscale + output is faster than full color since the color components need not + be processed.) Note that not all possible color space transforms are + currently implemented; you may need to extend jdcolor.c if you want an + unusual conversion. + +unsigned int scale_num, scale_denom + Scale the image by the fraction scale_num/scale_denom. Default is + 1/1, or no scaling. Currently, the only supported scaling ratios + are M/8 with all M from 1 to 16, or any reduced fraction thereof (such + as 1/2, 3/4, etc.) (The library design allows for arbitrary + scaling ratios but this is not likely to be implemented any time soon.) + Smaller scaling ratios permit significantly faster decoding since + fewer pixels need be processed and a simpler IDCT method can be used. + +boolean quantize_colors + If set TRUE, colormapped output will be delivered. Default is FALSE, + meaning that full-color output will be delivered. + +The next three parameters are relevant only if quantize_colors is TRUE. + +int desired_number_of_colors + Maximum number of colors to use in generating a library-supplied color + map (the actual number of colors is returned in a different field). + Default 256. Ignored when the application supplies its own color map. + +boolean two_pass_quantize + If TRUE, an extra pass over the image is made to select a custom color + map for the image. This usually looks a lot better than the one-size- + fits-all colormap that is used otherwise. Default is TRUE. Ignored + when the application supplies its own color map. + +J_DITHER_MODE dither_mode + Selects color dithering method. Supported values are: + JDITHER_NONE no dithering: fast, very low quality + JDITHER_ORDERED ordered dither: moderate speed and quality + JDITHER_FS Floyd-Steinberg dither: slow, high quality + Default is JDITHER_FS. (At present, ordered dither is implemented + only in the single-pass, standard-colormap case. If you ask for + ordered dither when two_pass_quantize is TRUE or when you supply + an external color map, you'll get F-S dithering.) + +When quantize_colors is TRUE, the target color map is described by the next +two fields. colormap is set to NULL by jpeg_read_header(). The application +can supply a color map by setting colormap non-NULL and setting +actual_number_of_colors to the map size. Otherwise, jpeg_start_decompress() +selects a suitable color map and sets these two fields itself. +[Implementation restriction: at present, an externally supplied colormap is +only accepted for 3-component output color spaces.] + +JSAMPARRAY colormap + The color map, represented as a 2-D pixel array of out_color_components + rows and actual_number_of_colors columns. Ignored if not quantizing. + CAUTION: if the JPEG library creates its own colormap, the storage + pointed to by this field is released by jpeg_finish_decompress(). + Copy the colormap somewhere else first, if you want to save it. + CAUTION: if data_precision is 12 or 16, then this is actually a + J12SAMPARRAY or a J16SAMPARRAY, so it must be type-cast in order to + read/write 12-bit or 16-bit samples from/to the array. + +int actual_number_of_colors + The number of colors in the color map. + +Additional decompression parameters that the application may set include: + +J_DCT_METHOD dct_method + Selects the algorithm used for the DCT step. Choices are: + JDCT_ISLOW: accurate integer method + JDCT_IFAST: less accurate integer method [legacy feature] + JDCT_FLOAT: floating-point method [legacy feature] + JDCT_DEFAULT: default method (normally JDCT_ISLOW) + JDCT_FASTEST: fastest method (normally JDCT_IFAST) + When the Independent JPEG Group's software was first released in 1991, + the decompression time for a 1-megapixel JPEG image on a mainstream PC + was measured in minutes. Thus, JDCT_IFAST provided noticeable + performance benefits. On modern CPUs running libjpeg-turbo, however, + the decompression time for a 1-megapixel JPEG image is measured in + milliseconds, and thus the performance benefits of JDCT_IFAST are much + less noticeable. On modern x86/x86-64 CPUs that support AVX2 + instructions, JDCT_IFAST and JDCT_ISLOW have similar performance. On + other types of CPUs, JDCT_IFAST is generally about 5-15% faster than + JDCT_ISLOW. + + If the JPEG image was compressed using a quality level of 85 or below, + then there should be little or no perceptible quality difference + between the two algorithms. When decompressing images that were + compressed using quality levels above 85, however, the difference + between JDCT_IFAST and JDCT_ISLOW becomes more pronounced. With images + compressed using quality=97, for instance, JDCT_IFAST incurs generally + about a 4-6 dB loss in PSNR relative to JDCT_ISLOW, but this can be + larger for some images. If you can avoid it, do not use JDCT_IFAST + when decompressing images that were compressed using quality levels + above 97. The algorithm often degenerates for such images and can + actually produce a more lossy output image than if the JPEG image had + been compressed using lower quality levels. + + JDCT_FLOAT does not produce significantly more accurate results than + JDCT_ISLOW, and it is much slower. JDCT_FLOAT may also give different + results on different machines due to varying roundoff behavior, whereas + the integer methods should give the same results on all machines. + +boolean do_fancy_upsampling + If TRUE, do careful upsampling of chroma components. If FALSE, + a faster but sloppier method is used. Default is TRUE. The visual + impact of the sloppier method is often very small. + +boolean do_block_smoothing + If TRUE, interblock smoothing is applied in early stages of decoding + progressive JPEG files; if FALSE, not. Default is TRUE. Early + progression stages look "fuzzy" with smoothing, "blocky" without. + In any case, block smoothing ceases to be applied after the first few + AC coefficients are known to full accuracy, so it is relevant only + when using buffered-image mode for progressive images. + +boolean enable_1pass_quant +boolean enable_external_quant +boolean enable_2pass_quant + These are significant only in buffered-image mode, which is + described in its own section below. + + +The output image dimensions are given by the following fields. These are +computed from the source image dimensions and the decompression parameters +by jpeg_start_decompress(). You can also call jpeg_calc_output_dimensions() +to obtain the values that will result from the current parameter settings. +This can be useful if you are trying to pick a scaling ratio that will get +close to a desired target size. It's also important if you are using the +JPEG library's memory manager to allocate output buffer space, because you +are supposed to request such buffers *before* jpeg_start_decompress(). + +JDIMENSION output_width Actual dimensions of output image. +JDIMENSION output_height +int out_color_components Number of color components in out_color_space. +int output_components Number of color components returned. +int rec_outbuf_height Recommended height of scanline buffer. + +When quantizing colors, output_components is 1, indicating a single color map +index per pixel. Otherwise it equals out_color_components. The output arrays +are required to be output_width * output_components J*SAMPLEs wide. + +rec_outbuf_height is the recommended minimum height (in scanlines) of the +buffer passed to jpeg*_read_scanlines(). If the buffer is smaller, the +library will still work, but time will be wasted due to unnecessary data +copying. In high-quality modes, rec_outbuf_height is always 1, but some +faster, lower-quality modes set it to larger values (typically 2 to 4). +If you are going to ask for a high-speed processing mode, you may as well +go to the trouble of honoring rec_outbuf_height so as to avoid data copying. +(An output buffer larger than rec_outbuf_height lines is OK, but won't +provide any material speed improvement over that height.) + + +Special color spaces +-------------------- + +The JPEG standard itself is "color blind" and doesn't specify any particular +color space. It is customary to convert color data to a luminance/chrominance +color space before compressing, since this permits greater compression. The +existing de-facto JPEG file format standards specify YCbCr or grayscale data +(JFIF), or grayscale, RGB, YCbCr, CMYK, or YCCK (Adobe). For special +applications such as multispectral images, other color spaces can be used, +but it must be understood that such files will be unportable. + +The JPEG library can handle the most common colorspace conversions (namely +RGB <=> YCbCr and CMYK <=> YCCK). It can also deal with data of an unknown +color space, passing it through without conversion. If you deal extensively +with an unusual color space, you can easily extend the library to understand +additional color spaces and perform appropriate conversions. + +For compression, the source data's color space is specified by field +in_color_space. This is transformed to the JPEG file's color space given +by jpeg_color_space. jpeg_set_defaults() chooses a reasonable JPEG color +space depending on in_color_space, but you can override this by calling +jpeg_set_colorspace(). Of course you must select a supported transformation. +jccolor.c currently supports the following transformations: + RGB => YCbCr + RGB => GRAYSCALE + YCbCr => GRAYSCALE + CMYK => YCCK +plus the null transforms: GRAYSCALE => GRAYSCALE, RGB => RGB, +YCbCr => YCbCr, CMYK => CMYK, YCCK => YCCK, and UNKNOWN => UNKNOWN. + +The de-facto file format standards (JFIF and Adobe) specify APPn markers that +indicate the color space of the JPEG file. It is important to ensure that +these are written correctly, or omitted if the JPEG file's color space is not +one of the ones supported by the de-facto standards. jpeg_set_colorspace() +will set the compression parameters to include or omit the APPn markers +properly, so long as it is told the truth about the JPEG color space. +For example, if you are writing some random 3-component color space without +conversion, don't try to fake out the library by setting in_color_space and +jpeg_color_space to JCS_YCbCr; use JCS_UNKNOWN. You may want to write an +APPn marker of your own devising to identify the colorspace --- see "Special +markers", below. + +When told that the color space is UNKNOWN, the library will default to using +luminance-quality compression parameters for all color components. You may +well want to change these parameters. See the source code for +jpeg_set_colorspace(), in jcparam.c, for details. + +For decompression, the JPEG file's color space is given in jpeg_color_space, +and this is transformed to the output color space out_color_space. +jpeg_read_header's setting of jpeg_color_space can be relied on if the file +conforms to JFIF or Adobe conventions, but otherwise it is no better than a +guess. If you know the JPEG file's color space for certain, you can override +jpeg_read_header's guess by setting jpeg_color_space. jpeg_read_header also +selects a default output color space based on (its guess of) jpeg_color_space; +set out_color_space to override this. Again, you must select a supported +transformation. jdcolor.c currently supports + YCbCr => RGB + YCbCr => GRAYSCALE + RGB => GRAYSCALE + GRAYSCALE => RGB + YCCK => CMYK +as well as the null transforms. (Since GRAYSCALE=>RGB is provided, an +application can force grayscale JPEGs to look like color JPEGs if it only +wants to handle one case.) + +The two-pass color quantizer, jquant2.c, is specialized to handle RGB data +(it weights distances appropriately for RGB colors). You'll need to modify +the code if you want to use it for non-RGB output color spaces. Note that +jquant2.c is used to map to an application-supplied colormap as well as for +the normal two-pass colormap selection process. + +CAUTION: it appears that Adobe Photoshop writes inverted data in CMYK JPEG +files: 0 represents 100% ink coverage, rather than 0% ink as you'd expect. +This is arguably a bug in Photoshop, but if you need to work with Photoshop +CMYK files, you will have to deal with it in your application. We cannot +"fix" this in the library by inverting the data during the CMYK<=>YCCK +transform, because that would break other applications, notably Ghostscript. +Photoshop versions prior to 3.0 write EPS files containing JPEG-encoded CMYK +data in the same inverted-YCCK representation used in bare JPEG files, but +the surrounding PostScript code performs an inversion using the PS image +operator. I am told that Photoshop 3.0 will write uninverted YCCK in +EPS/JPEG files, and will omit the PS-level inversion. (But the data +polarity used in bare JPEG files will not change in 3.0.) In either case, +the JPEG library must not invert the data itself, or else Ghostscript would +read these EPS files incorrectly. + + +Error handling +-------------- + +When the default error handler is used, any error detected inside the JPEG +routines will cause a message to be printed on stderr, followed by exit(). +You can supply your own error handling routines to override this behavior +and to control the treatment of nonfatal warnings and trace/debug messages. +The file example.c illustrates the most common case, which is to have the +application regain control after an error rather than exiting. + +The JPEG library never writes any message directly; it always goes through +the error handling routines. Three classes of messages are recognized: + * Fatal errors: the library cannot continue. + * Warnings: the library can continue, but the data is corrupt, and a + damaged output image is likely to result. + * Trace/informational messages. These come with a trace level indicating + the importance of the message; you can control the verbosity of the + program by adjusting the maximum trace level that will be displayed. + +You may, if you wish, simply replace the entire JPEG error handling module +(jerror.c) with your own code. However, you can avoid code duplication by +only replacing some of the routines depending on the behavior you need. +This is accomplished by calling jpeg_std_error() as usual, but then overriding +some of the method pointers in the jpeg_error_mgr struct, as illustrated by +example.c. + +All of the error handling routines will receive a pointer to the JPEG object +(a j_common_ptr which points to either a jpeg_compress_struct or a +jpeg_decompress_struct; if you need to tell which, test the is_decompressor +field). This struct includes a pointer to the error manager struct in its +"err" field. Frequently, custom error handler routines will need to access +additional data which is not known to the JPEG library or the standard error +handler. The most convenient way to do this is to embed either the JPEG +object or the jpeg_error_mgr struct in a larger structure that contains +additional fields; then casting the passed pointer provides access to the +additional fields. Again, see example.c for one way to do it. (Beginning +with IJG version 6b, there is also a void pointer "client_data" in each +JPEG object, which the application can also use to find related data. +The library does not touch client_data at all.) + +The individual methods that you might wish to override are: + +error_exit (j_common_ptr cinfo) + Receives control for a fatal error. Information sufficient to + generate the error message has been stored in cinfo->err; call + output_message to display it. Control must NOT return to the caller; + generally this routine will exit() or longjmp() somewhere. + Typically you would override this routine to get rid of the exit() + default behavior. Note that if you continue processing, you should + clean up the JPEG object with jpeg_abort() or jpeg_destroy(). + +output_message (j_common_ptr cinfo) + Actual output of any JPEG message. Override this to send messages + somewhere other than stderr. Note that this method does not know + how to generate a message, only where to send it. + +format_message (j_common_ptr cinfo, char *buffer) + Constructs a readable error message string based on the error info + stored in cinfo->err. This method is called by output_message. Few + applications should need to override this method. One possible + reason for doing so is to implement dynamic switching of error message + language. + +emit_message (j_common_ptr cinfo, int msg_level) + Decide whether or not to emit a warning or trace message; if so, + calls output_message. The main reason for overriding this method + would be to abort on warnings. msg_level is -1 for warnings, + 0 and up for trace messages. + +Only error_exit() and emit_message() are called from the rest of the JPEG +library; the other two are internal to the error handler. + +The actual message texts are stored in an array of strings which is pointed to +by the field err->jpeg_message_table. The messages are numbered from 0 to +err->last_jpeg_message, and it is these code numbers that are used in the +JPEG library code. You could replace the message texts (for instance, with +messages in French or German) by changing the message table pointer. See +jerror.h for the default texts. CAUTION: this table will almost certainly +change or grow from one library version to the next. + +It may be useful for an application to add its own message texts that are +handled by the same mechanism. The error handler supports a second "add-on" +message table for this purpose. To define an addon table, set the pointer +err->addon_message_table and the message numbers err->first_addon_message and +err->last_addon_message. If you number the addon messages beginning at 1000 +or so, you won't have to worry about conflicts with the library's built-in +messages. See the sample applications cjpeg/djpeg for an example of using +addon messages (the addon messages are defined in cderror.h). + +Actual invocation of the error handler is done via macros defined in jerror.h: + ERREXITn(...) for fatal errors + WARNMSn(...) for corrupt-data warnings + TRACEMSn(...) for trace and informational messages. +These macros store the message code and any additional parameters into the +error handler struct, then invoke the error_exit() or emit_message() method. +The variants of each macro are for varying numbers of additional parameters. +The additional parameters are inserted into the generated message using +standard printf() format codes. + +See jerror.h and jerror.c for further details. + + +Compressed data handling (source and destination managers) +---------------------------------------------------------- + +The JPEG compression library sends its compressed data to a "destination +manager" module. The default destination manager just writes the data to a +memory buffer or to a stdio stream, but you can provide your own manager to +do something else. Similarly, the decompression library calls a "source +manager" to obtain the compressed data; you can provide your own source +manager if you want the data to come from somewhere other than a memory +buffer or a stdio stream. + +In both cases, compressed data is processed a bufferload at a time: the +destination or source manager provides a work buffer, and the library invokes +the manager only when the buffer is filled or emptied. (You could define a +one-character buffer to force the manager to be invoked for each byte, but +that would be rather inefficient.) The buffer's size and location are +controlled by the manager, not by the library. For example, the memory +source manager just makes the buffer pointer and length point to the original +data in memory. In this case the buffer-reload procedure will be invoked +only if the decompressor ran off the end of the datastream, which would +indicate an erroneous datastream. + +The work buffer is defined as an array of datatype JOCTET, which is generally +"char" or "unsigned char". On a machine where char is not exactly 8 bits +wide, you must define JOCTET as a wider data type and then modify the data +source and destination modules to transcribe the work arrays into 8-bit units +on external storage. + +A data destination manager struct contains a pointer and count defining the +next byte to write in the work buffer and the remaining free space: + + JOCTET *next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + +The library increments the pointer and decrements the count until the buffer +is filled. The manager's empty_output_buffer method must reset the pointer +and count. The manager is expected to remember the buffer's starting address +and total size in private fields not visible to the library. + +A data destination manager provides three methods: + +init_destination (j_compress_ptr cinfo) + Initialize destination. This is called by jpeg_start_compress() + before any data is actually written. It must initialize + next_output_byte and free_in_buffer. free_in_buffer must be + initialized to a positive value. + +empty_output_buffer (j_compress_ptr cinfo) + This is called whenever the buffer has filled (free_in_buffer + reaches zero). In typical applications, it should write out the + *entire* buffer (use the saved start address and buffer length; + ignore the current state of next_output_byte and free_in_buffer). + Then reset the pointer & count to the start of the buffer, and + return TRUE indicating that the buffer has been dumped. + free_in_buffer must be set to a positive value when TRUE is + returned. A FALSE return should only be used when I/O suspension is + desired (this operating mode is discussed in the next section). + +term_destination (j_compress_ptr cinfo) + Terminate destination --- called by jpeg_finish_compress() after all + data has been written. In most applications, this must flush any + data remaining in the buffer. Use either next_output_byte or + free_in_buffer to determine how much data is in the buffer. + +term_destination() is NOT called by jpeg_abort() or jpeg_destroy(). If you +want the destination manager to be cleaned up during an abort, you must do it +yourself. + +You will also need code to create a jpeg_destination_mgr struct, fill in its +method pointers, and insert a pointer to the struct into the "dest" field of +the JPEG compression object. This can be done in-line in your setup code if +you like, but it's probably cleaner to provide a separate routine similar to +the jpeg_stdio_dest() or jpeg_mem_dest() routines of the supplied destination +managers. + +Decompression source managers follow a parallel design, but with some +additional frammishes. The source manager struct contains a pointer and count +defining the next byte to read from the work buffer and the number of bytes +remaining: + + const JOCTET *next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + +The library increments the pointer and decrements the count until the buffer +is emptied. The manager's fill_input_buffer method must reset the pointer and +count. In most applications, the manager must remember the buffer's starting +address and total size in private fields not visible to the library. + +A data source manager provides five methods: + +init_source (j_decompress_ptr cinfo) + Initialize source. This is called by jpeg_read_header() before any + data is actually read. Unlike init_destination(), it may leave + bytes_in_buffer set to 0 (in which case a fill_input_buffer() call + will occur immediately). + +fill_input_buffer (j_decompress_ptr cinfo) + This is called whenever bytes_in_buffer has reached zero and more + data is wanted. In typical applications, it should read fresh data + into the buffer (ignoring the current state of next_input_byte and + bytes_in_buffer), reset the pointer & count to the start of the + buffer, and return TRUE indicating that the buffer has been reloaded. + It is not necessary to fill the buffer entirely, only to obtain at + least one more byte. bytes_in_buffer MUST be set to a positive value + if TRUE is returned. A FALSE return should only be used when I/O + suspension is desired (this mode is discussed in the next section). + +skip_input_data (j_decompress_ptr cinfo, long num_bytes) + Skip num_bytes worth of data. The buffer pointer and count should + be advanced over num_bytes input bytes, refilling the buffer as + needed. This is used to skip over a potentially large amount of + uninteresting data (such as an APPn marker). In some applications + it may be possible to optimize away the reading of the skipped data, + but it's not clear that being smart is worth much trouble; large + skips are uncommon. bytes_in_buffer may be zero on return. + A zero or negative skip count should be treated as a no-op. + +resync_to_restart (j_decompress_ptr cinfo, int desired) + This routine is called only when the decompressor has failed to find + a restart (RSTn) marker where one is expected. Its mission is to + find a suitable point for resuming decompression. For most + applications, we recommend that you just use the default resync + procedure, jpeg_resync_to_restart(). However, if you are able to back + up in the input data stream, or if you have a-priori knowledge about + the likely location of restart markers, you may be able to do better. + Read the read_restart_marker() and jpeg_resync_to_restart() routines + in jdmarker.c if you think you'd like to implement your own resync + procedure. + +term_source (j_decompress_ptr cinfo) + Terminate source --- called by jpeg_finish_decompress() after all + data has been read. Often a no-op. + +For both fill_input_buffer() and skip_input_data(), there is no such thing +as an EOF return. If the end of the file has been reached, the routine has +a choice of exiting via ERREXIT() or inserting fake data into the buffer. +In most cases, generating a warning message and inserting a fake EOI marker +is the best course of action --- this will allow the decompressor to output +however much of the image is there. In pathological cases, the decompressor +may swallow the EOI and again demand data ... just keep feeding it fake EOIs. +jdatasrc.c illustrates the recommended error recovery behavior. + +term_source() is NOT called by jpeg_abort() or jpeg_destroy(). If you want +the source manager to be cleaned up during an abort, you must do it yourself. + +You will also need code to create a jpeg_source_mgr struct, fill in its method +pointers, and insert a pointer to the struct into the "src" field of the JPEG +decompression object. This can be done in-line in your setup code if you +like, but it's probably cleaner to provide a separate routine similar to the +jpeg_stdio_src() or jpeg_mem_src() routines of the supplied source managers. + +For more information, consult the memory and stdio source and destination +managers in jdatasrc.c and jdatadst.c. + + +I/O suspension +-------------- + +Some applications need to use the JPEG library as an incremental memory-to- +memory filter: when the compressed data buffer is filled or emptied, they want +control to return to the outer loop, rather than expecting that the buffer can +be emptied or reloaded within the data source/destination manager subroutine. +The library supports this need by providing an "I/O suspension" mode, which we +describe in this section. + +The I/O suspension mode is not a panacea: nothing is guaranteed about the +maximum amount of time spent in any one call to the library, so it will not +eliminate response-time problems in single-threaded applications. If you +need guaranteed response time, we suggest you "bite the bullet" and implement +a real multi-tasking capability. + +To use I/O suspension, cooperation is needed between the calling application +and the data source or destination manager; you will always need a custom +source/destination manager. (Please read the previous section if you haven't +already.) The basic idea is that the empty_output_buffer() or +fill_input_buffer() routine is a no-op, merely returning FALSE to indicate +that it has done nothing. Upon seeing this, the JPEG library suspends +operation and returns to its caller. The surrounding application is +responsible for emptying or refilling the work buffer before calling the +JPEG library again. + +Compression suspension: + +For compression suspension, use an empty_output_buffer() routine that returns +FALSE; typically it will not do anything else. This will cause the +compressor to return to the caller of jpeg*_write_scanlines(), with the return +value indicating that not all the supplied scanlines have been accepted. +The application must make more room in the output buffer, adjust the output +buffer pointer/count appropriately, and then call jpeg*_write_scanlines() +again, pointing to the first unconsumed scanline. + +When forced to suspend, the compressor will backtrack to a convenient stopping +point (usually the start of the current MCU); it will regenerate some output +data when restarted. Therefore, although empty_output_buffer() is only +called when the buffer is filled, you should NOT write out the entire buffer +after a suspension. Write only the data up to the current position of +next_output_byte/free_in_buffer. The data beyond that point will be +regenerated after resumption. + +Because of the backtracking behavior, a good-size output buffer is essential +for efficiency; you don't want the compressor to suspend often. (In fact, an +overly small buffer could lead to infinite looping, if a single MCU required +more data than would fit in the buffer.) We recommend a buffer of at least +several Kbytes. You may want to insert explicit code to ensure that you don't +call jpeg*_write_scanlines() unless there is a reasonable amount of space in +the output buffer; in other words, flush the buffer before trying to compress +more data. + +The compressor does not allow suspension while it is trying to write JPEG +markers at the beginning and end of the file. This means that: + * At the beginning of a compression operation, there must be enough free + space in the output buffer to hold the header markers (typically 600 or + so bytes). The recommended buffer size is bigger than this anyway, so + this is not a problem as long as you start with an empty buffer. However, + this restriction might catch you if you insert large special markers, such + as a JFIF thumbnail image, without flushing the buffer afterwards. + * When you call jpeg_finish_compress(), there must be enough space in the + output buffer to emit any buffered data and the final EOI marker. In the + current implementation, half a dozen bytes should suffice for this, but + for safety's sake we recommend ensuring that at least 100 bytes are free + before calling jpeg_finish_compress(). + +A more significant restriction is that jpeg_finish_compress() cannot suspend. +This means you cannot use suspension with multi-pass operating modes, namely +Huffman code optimization and multiple-scan output. Those modes write the +whole file during jpeg_finish_compress(), which will certainly result in +buffer overrun. (Note that this restriction applies only to compression, +not decompression. The decompressor supports input suspension in all of its +operating modes.) + +Decompression suspension: + +For decompression suspension, use a fill_input_buffer() routine that simply +returns FALSE (except perhaps during error recovery, as discussed below). +This will cause the decompressor to return to its caller with an indication +that suspension has occurred. This can happen at four places: + * jpeg_read_header(): will return JPEG_SUSPENDED. + * jpeg_start_decompress(): will return FALSE, rather than its usual TRUE. + * jpeg*_read_scanlines(): will return the number of scanlines already + completed (possibly 0). + * jpeg_finish_decompress(): will return FALSE, rather than its usual TRUE. +The surrounding application must recognize these cases, load more data into +the input buffer, and repeat the call. In the case of jpeg*_read_scanlines(), +increment the passed pointers past any scanlines successfully read. + +Just as with compression, the decompressor will typically backtrack to a +convenient restart point before suspending. When fill_input_buffer() is +called, next_input_byte/bytes_in_buffer point to the current restart point, +which is where the decompressor will backtrack to if FALSE is returned. +The data beyond that position must NOT be discarded if you suspend; it needs +to be re-read upon resumption. In most implementations, you'll need to shift +this data down to the start of your work buffer and then load more data after +it. Again, this behavior means that a several-Kbyte work buffer is essential +for decent performance; furthermore, you should load a reasonable amount of +new data before resuming decompression. (If you loaded, say, only one new +byte each time around, you could waste a LOT of cycles.) + +The skip_input_data() source manager routine requires special care in a +suspension scenario. This routine is NOT granted the ability to suspend the +decompressor; it can decrement bytes_in_buffer to zero, but no more. If the +requested skip distance exceeds the amount of data currently in the input +buffer, then skip_input_data() must set bytes_in_buffer to zero and record the +additional skip distance somewhere else. The decompressor will immediately +call fill_input_buffer(), which should return FALSE, which will cause a +suspension return. The surrounding application must then arrange to discard +the recorded number of bytes before it resumes loading the input buffer. +(Yes, this design is rather baroque, but it avoids complexity in the far more +common case where a non-suspending source manager is used.) + +If the input data has been exhausted, we recommend that you emit a warning +and insert dummy EOI markers just as a non-suspending data source manager +would do. This can be handled either in the surrounding application logic or +within fill_input_buffer(); the latter is probably more efficient. If +fill_input_buffer() knows that no more data is available, it can set the +pointer/count to point to a dummy EOI marker and then return TRUE just as +though it had read more data in a non-suspending situation. + +The decompressor does not attempt to suspend within standard JPEG markers; +instead it will backtrack to the start of the marker and reprocess the whole +marker next time. Hence the input buffer must be large enough to hold the +longest standard marker in the file. Standard JPEG markers should normally +not exceed a few hundred bytes each (DHT tables are typically the longest). +We recommend at least a 2K buffer for performance reasons, which is much +larger than any correct marker is likely to be. For robustness against +damaged marker length counts, you may wish to insert a test in your +application for the case that the input buffer is completely full and yet +the decoder has suspended without consuming any data --- otherwise, if this +situation did occur, it would lead to an endless loop. (The library can't +provide this test since it has no idea whether "the buffer is full", or +even whether there is a fixed-size input buffer.) + +The input buffer would need to be 64K to allow for arbitrary COM or APPn +markers, but these are handled specially: they are either saved into allocated +memory, or skipped over by calling skip_input_data(). In the former case, +suspension is handled correctly, and in the latter case, the problem of +buffer overrun is placed on skip_input_data's shoulders, as explained above. +Note that if you provide your own marker handling routine for large markers, +you should consider how to deal with buffer overflow. + +Multiple-buffer management: + +In some applications it is desirable to store the compressed data in a linked +list of buffer areas, so as to avoid data copying. This can be handled by +having empty_output_buffer() or fill_input_buffer() set the pointer and count +to reference the next available buffer; FALSE is returned only if no more +buffers are available. Although seemingly straightforward, there is a +pitfall in this approach: the backtrack that occurs when FALSE is returned +could back up into an earlier buffer. For example, when fill_input_buffer() +is called, the current pointer & count indicate the backtrack restart point. +Since fill_input_buffer() will set the pointer and count to refer to a new +buffer, the restart position must be saved somewhere else. Suppose a second +call to fill_input_buffer() occurs in the same library call, and no +additional input data is available, so fill_input_buffer must return FALSE. +If the JPEG library has not moved the pointer/count forward in the current +buffer, then *the correct restart point is the saved position in the prior +buffer*. Prior buffers may be discarded only after the library establishes +a restart point within a later buffer. Similar remarks apply for output into +a chain of buffers. + +The library will never attempt to backtrack over a skip_input_data() call, +so any skipped data can be permanently discarded. You still have to deal +with the case of skipping not-yet-received data, however. + +It's much simpler to use only a single buffer; when fill_input_buffer() is +called, move any unconsumed data (beyond the current pointer/count) down to +the beginning of this buffer and then load new data into the remaining buffer +space. This approach requires a little more data copying but is far easier +to get right. + + +Progressive JPEG support +------------------------ + +Progressive JPEG rearranges the stored data into a series of scans of +increasing quality. In situations where a JPEG file is transmitted across a +slow communications link, a decoder can generate a low-quality image very +quickly from the first scan, then gradually improve the displayed quality as +more scans are received. The final image after all scans are complete is +identical to that of a regular (sequential) JPEG file of the same quality +setting. Progressive JPEG files are often slightly smaller than equivalent +sequential JPEG files, but the possibility of incremental display is the main +reason for using progressive JPEG. + +The IJG encoder library generates progressive JPEG files when given a +suitable "scan script" defining how to divide the data into scans. +Creation of progressive JPEG files is otherwise transparent to the encoder. +Progressive JPEG files can also be read transparently by the decoder library. +If the decoding application simply uses the library as defined above, it +will receive a final decoded image without any indication that the file was +progressive. Of course, this approach does not allow incremental display. +To perform incremental display, an application needs to use the decoder +library's "buffered-image" mode, in which it receives a decoded image +multiple times. + +Each displayed scan requires about as much work to decode as a full JPEG +image of the same size, so the decoder must be fairly fast in relation to the +data transmission rate in order to make incremental display useful. However, +it is possible to skip displaying the image and simply add the incoming bits +to the decoder's coefficient buffer. This is fast because only Huffman +decoding need be done, not IDCT, upsampling, colorspace conversion, etc. +The IJG decoder library allows the application to switch dynamically between +displaying the image and simply absorbing the incoming bits. A properly +coded application can automatically adapt the number of display passes to +suit the time available as the image is received. Also, a final +higher-quality display cycle can be performed from the buffered data after +the end of the file is reached. + +Progressive compression: + +To create a progressive JPEG file (or a multiple-scan sequential JPEG file), +set the scan_info cinfo field to point to an array of scan descriptors, and +perform compression as usual. Instead of constructing your own scan list, +you can call the jpeg_simple_progression() helper routine to create a +recommended progression sequence; this method should be used by all +applications that don't want to get involved in the nitty-gritty of +progressive scan sequence design. (If you want to provide user control of +scan sequences, you may wish to borrow the scan script reading code found +in rdswitch.c, so that you can read scan script files just like cjpeg's.) +When scan_info is not NULL, the compression library will store DCT'd data +into a buffer array as jpeg*_write_scanlines() is called, and will emit all +the requested scans during jpeg_finish_compress(). This implies that +multiple-scan output cannot be created with a suspending data destination +manager, since jpeg_finish_compress() does not support suspension. We +should also note that the compressor currently forces Huffman optimization +mode when creating a progressive JPEG file, because the default Huffman +tables are unsuitable for progressive files. + +Progressive decompression: + +When buffered-image mode is not used, the decoder library will read all of +a multi-scan file during jpeg_start_decompress(), so that it can provide a +final decoded image. (Here "multi-scan" means either progressive or +multi-scan sequential.) This makes multi-scan files transparent to the +decoding application. However, existing applications that used suspending +input with version 5 of the IJG library will need to be modified to check +for a suspension return from jpeg_start_decompress(). + +To perform incremental display, an application must use the library's +buffered-image mode. This is described in the next section. + + +Buffered-image mode +------------------- + +In buffered-image mode, the library stores the partially decoded image in a +coefficient buffer, from which it can be read out as many times as desired. +This mode is typically used for incremental display of progressive JPEG files, +but it can be used with any JPEG file. Each scan of a progressive JPEG file +adds more data (more detail) to the buffered image. The application can +display in lockstep with the source file (one display pass per input scan), +or it can allow input processing to outrun display processing. By making +input and display processing run independently, it is possible for the +application to adapt progressive display to a wide range of data transmission +rates. + +The basic control flow for buffered-image decoding is + + jpeg_create_decompress() + set data source + jpeg_read_header() + set overall decompression parameters + cinfo.buffered_image = TRUE; /* select buffered-image mode */ + jpeg_start_decompress() + for (each output pass) { + adjust output decompression parameters if required + jpeg_start_output() /* start a new output pass */ + for (all scanlines in image) { + jpeg_read_scanlines() /* Use jpeg12_read_scanlines() for + 12-bit data precision and + jpeg16_read_scanlines() for 16-bit + data precision. */ + display scanlines + } + jpeg_finish_output() /* terminate output pass */ + } + jpeg_finish_decompress() + jpeg_destroy_decompress() + +This differs from ordinary unbuffered decoding in that there is an additional +level of looping. The application can choose how many output passes to make +and how to display each pass. + +The simplest approach to displaying progressive images is to do one display +pass for each scan appearing in the input file. In this case the outer loop +condition is typically + while (!jpeg_input_complete(&cinfo)) +and the start-output call should read + jpeg_start_output(&cinfo, cinfo.input_scan_number); +The second parameter to jpeg_start_output() indicates which scan of the input +file is to be displayed; the scans are numbered starting at 1 for this +purpose. (You can use a loop counter starting at 1 if you like, but using +the library's input scan counter is easier.) The library automatically reads +data as necessary to complete each requested scan, and jpeg_finish_output() +advances to the next scan or end-of-image marker (hence input_scan_number +will be incremented by the time control arrives back at jpeg_start_output()). +With this technique, data is read from the input file only as needed, and +input and output processing run in lockstep. + +After reading the final scan and reaching the end of the input file, the +buffered image remains available; it can be read additional times by +repeating the jpeg_start_output()/jpeg*_read_scanlines()/jpeg_finish_output() +sequence. For example, a useful technique is to use fast one-pass color +quantization for display passes made while the image is arriving, followed by +a final display pass using two-pass quantization for highest quality. This +is done by changing the library parameters before the final output pass. +Changing parameters between passes is discussed in detail below. + +In general the last scan of a progressive file cannot be recognized as such +until after it is read, so a post-input display pass is the best approach if +you want special processing in the final pass. + +When done with the image, be sure to call jpeg_finish_decompress() to release +the buffered image (or just use jpeg_destroy_decompress()). + +If input data arrives faster than it can be displayed, the application can +cause the library to decode input data in advance of what's needed to produce +output. This is done by calling the routine jpeg_consume_input(). +The return value is one of the following: + JPEG_REACHED_SOS: reached an SOS marker (the start of a new scan) + JPEG_REACHED_EOI: reached the EOI marker (end of image) + JPEG_ROW_COMPLETED: completed reading one MCU row of compressed data + JPEG_SCAN_COMPLETED: completed reading last MCU row of current scan + JPEG_SUSPENDED: suspended before completing any of the above +(JPEG_SUSPENDED can occur only if a suspending data source is used.) This +routine can be called at any time after initializing the JPEG object. It +reads some additional data and returns when one of the indicated significant +events occurs. (If called after the EOI marker is reached, it will +immediately return JPEG_REACHED_EOI without attempting to read more data.) + +The library's output processing will automatically call jpeg_consume_input() +whenever the output processing overtakes the input; thus, simple lockstep +display requires no direct calls to jpeg_consume_input(). But by adding +calls to jpeg_consume_input(), you can absorb data in advance of what is +being displayed. This has two benefits: + * You can limit buildup of unprocessed data in your input buffer. + * You can eliminate extra display passes by paying attention to the + state of the library's input processing. + +The first of these benefits only requires interspersing calls to +jpeg_consume_input() with your display operations and any other processing +you may be doing. To avoid wasting cycles due to backtracking, it's best to +call jpeg_consume_input() only after a hundred or so new bytes have arrived. +This is discussed further under "I/O suspension", above. (Note: the JPEG +library currently is not thread-safe. You must not call jpeg_consume_input() +from one thread of control if a different library routine is working on the +same JPEG object in another thread.) + +When input arrives fast enough that more than one new scan is available +before you start a new output pass, you may as well skip the output pass +corresponding to the completed scan. This occurs for free if you pass +cinfo.input_scan_number as the target scan number to jpeg_start_output(). +The input_scan_number field is simply the index of the scan currently being +consumed by the input processor. You can ensure that this is up-to-date by +emptying the input buffer just before calling jpeg_start_output(): call +jpeg_consume_input() repeatedly until it returns JPEG_SUSPENDED or +JPEG_REACHED_EOI. + +The target scan number passed to jpeg_start_output() is saved in the +cinfo.output_scan_number field. The library's output processing calls +jpeg_consume_input() whenever the current input scan number and row within +that scan is less than or equal to the current output scan number and row. +Thus, input processing can "get ahead" of the output processing but is not +allowed to "fall behind". You can achieve several different effects by +manipulating this interlock rule. For example, if you pass a target scan +number greater than the current input scan number, the output processor will +wait until that scan starts to arrive before producing any output. (To avoid +an infinite loop, the target scan number is automatically reset to the last +scan number when the end of image is reached. Thus, if you specify a large +target scan number, the library will just absorb the entire input file and +then perform an output pass. This is effectively the same as what +jpeg_start_decompress() does when you don't select buffered-image mode.) +When you pass a target scan number equal to the current input scan number, +the image is displayed no faster than the current input scan arrives. The +final possibility is to pass a target scan number less than the current input +scan number; this disables the input/output interlock and causes the output +processor to simply display whatever it finds in the image buffer, without +waiting for input. (However, the library will not accept a target scan +number less than one, so you can't avoid waiting for the first scan.) + +When data is arriving faster than the output display processing can advance +through the image, jpeg_consume_input() will store data into the buffered +image beyond the point at which the output processing is reading data out +again. If the input arrives fast enough, it may "wrap around" the buffer to +the point where the input is more than one whole scan ahead of the output. +If the output processing simply proceeds through its display pass without +paying attention to the input, the effect seen on-screen is that the lower +part of the image is one or more scans better in quality than the upper part. +Then, when the next output scan is started, you have a choice of what target +scan number to use. The recommended choice is to use the current input scan +number at that time, which implies that you've skipped the output scans +corresponding to the input scans that were completed while you processed the +previous output scan. In this way, the decoder automatically adapts its +speed to the arriving data, by skipping output scans as necessary to keep up +with the arriving data. + +When using this strategy, you'll want to be sure that you perform a final +output pass after receiving all the data; otherwise your last display may not +be full quality across the whole screen. So the right outer loop logic is +something like this: + do { + absorb any waiting input by calling jpeg_consume_input() + final_pass = jpeg_input_complete(&cinfo); + adjust output decompression parameters if required + jpeg_start_output(&cinfo, cinfo.input_scan_number); + ... + jpeg_finish_output() + } while (!final_pass); +rather than quitting as soon as jpeg_input_complete() returns TRUE. This +arrangement makes it simple to use higher-quality decoding parameters +for the final pass. But if you don't want to use special parameters for +the final pass, the right loop logic is like this: + for (;;) { + absorb any waiting input by calling jpeg_consume_input() + jpeg_start_output(&cinfo, cinfo.input_scan_number); + ... + jpeg_finish_output() + if (jpeg_input_complete(&cinfo) && + cinfo.input_scan_number == cinfo.output_scan_number) + break; + } +In this case you don't need to know in advance whether an output pass is to +be the last one, so it's not necessary to have reached EOF before starting +the final output pass; rather, what you want to test is whether the output +pass was performed in sync with the final input scan. This form of the loop +will avoid an extra output pass whenever the decoder is able (or nearly able) +to keep up with the incoming data. + +When the data transmission speed is high, you might begin a display pass, +then find that much or all of the file has arrived before you can complete +the pass. (You can detect this by noting the JPEG_REACHED_EOI return code +from jpeg_consume_input(), or equivalently by testing jpeg_input_complete().) +In this situation you may wish to abort the current display pass and start a +new one using the newly arrived information. To do so, just call +jpeg_finish_output() and then start a new pass with jpeg_start_output(). + +A variant strategy is to abort and restart display if more than one complete +scan arrives during an output pass; this can be detected by noting +JPEG_REACHED_SOS returns and/or examining cinfo.input_scan_number. This +idea should be employed with caution, however, since the display process +might never get to the bottom of the image before being aborted, resulting +in the lower part of the screen being several passes worse than the upper. +In most cases it's probably best to abort an output pass only if the whole +file has arrived and you want to begin the final output pass immediately. + +When receiving data across a communication link, we recommend always using +the current input scan number for the output target scan number; if a +higher-quality final pass is to be done, it should be started (aborting any +incomplete output pass) as soon as the end of file is received. However, +many other strategies are possible. For example, the application can examine +the parameters of the current input scan and decide whether to display it or +not. If the scan contains only chroma data, one might choose not to use it +as the target scan, expecting that the scan will be small and will arrive +quickly. To skip to the next scan, call jpeg_consume_input() until it +returns JPEG_REACHED_SOS or JPEG_REACHED_EOI. Or just use the next higher +number as the target scan for jpeg_start_output(); but that method doesn't +let you inspect the next scan's parameters before deciding to display it. + + +In buffered-image mode, jpeg_start_decompress() never performs input and +thus never suspends. An application that uses input suspension with +buffered-image mode must be prepared for suspension returns from these +routines: +* jpeg_start_output() performs input only if you request 2-pass quantization + and the target scan isn't fully read yet. (This is discussed below.) +* jpeg*_read_scanlines(), as always, returns the number of scanlines that it + was able to produce before suspending. +* jpeg_finish_output() will read any markers following the target scan, + up to the end of the file or the SOS marker that begins another scan. + (But it reads no input if jpeg_consume_input() has already reached the + end of the file or a SOS marker beyond the target output scan.) +* jpeg_finish_decompress() will read until the end of file, and thus can + suspend if the end hasn't already been reached (as can be tested by + calling jpeg_input_complete()). +jpeg_start_output(), jpeg_finish_output(), and jpeg_finish_decompress() +all return TRUE if they completed their tasks, FALSE if they had to suspend. +In the event of a FALSE return, the application must load more input data +and repeat the call. Applications that use non-suspending data sources need +not check the return values of these three routines. + + +It is possible to change decoding parameters between output passes in the +buffered-image mode. The decoder library currently supports only very +limited changes of parameters. ONLY THE FOLLOWING parameter changes are +allowed after jpeg_start_decompress() is called: +* dct_method can be changed before each call to jpeg_start_output(). + For example, one could use a fast DCT method for early scans, changing + to a higher quality method for the final scan. +* dither_mode can be changed before each call to jpeg_start_output(); + of course this has no impact if not using color quantization. Typically + one would use ordered dither for initial passes, then switch to + Floyd-Steinberg dither for the final pass. Caution: changing dither mode + can cause more memory to be allocated by the library. Although the amount + of memory involved is not large (a scanline or so), it may cause the + initial max_memory_to_use specification to be exceeded, which in the worst + case would result in an out-of-memory failure. +* do_block_smoothing can be changed before each call to jpeg_start_output(). + This setting is relevant only when decoding a progressive JPEG image. + During the first DC-only scan, block smoothing provides a very "fuzzy" look + instead of the very "blocky" look seen without it; which is better seems a + matter of personal taste. But block smoothing is nearly always a win + during later stages, especially when decoding a successive-approximation + image: smoothing helps to hide the slight blockiness that otherwise shows + up on smooth gradients until the lowest coefficient bits are sent. +* Color quantization mode can be changed under the rules described below. + You *cannot* change between full-color and quantized output (because that + would alter the required I/O buffer sizes), but you can change which + quantization method is used. + +When generating color-quantized output, changing quantization method is a +very useful way of switching between high-speed and high-quality display. +The library allows you to change among its three quantization methods: +1. Single-pass quantization to a fixed color cube. + Selected by cinfo.two_pass_quantize = FALSE and cinfo.colormap = NULL. +2. Single-pass quantization to an application-supplied colormap. + Selected by setting cinfo.colormap to point to the colormap (the value of + two_pass_quantize is ignored); also set cinfo.actual_number_of_colors. +3. Two-pass quantization to a colormap chosen specifically for the image. + Selected by cinfo.two_pass_quantize = TRUE and cinfo.colormap = NULL. + (This is the default setting selected by jpeg_read_header, but it is + probably NOT what you want for the first pass of progressive display!) +These methods offer successively better quality and lesser speed. However, +only the first method is available for quantizing in non-RGB color spaces. + +IMPORTANT: because the different quantizer methods have very different +working-storage requirements, the library requires you to indicate which +one(s) you intend to use before you call jpeg_start_decompress(). (If we did +not require this, the max_memory_to_use setting would be a complete fiction.) +You do this by setting one or more of these three cinfo fields to TRUE: + enable_1pass_quant Fixed color cube colormap + enable_external_quant Externally-supplied colormap + enable_2pass_quant Two-pass custom colormap +All three are initialized FALSE by jpeg_read_header(). But +jpeg_start_decompress() automatically sets TRUE the one selected by the +current two_pass_quantize and colormap settings, so you only need to set the +enable flags for any other quantization methods you plan to change to later. + +After setting the enable flags correctly at jpeg_start_decompress() time, you +can change to any enabled quantization method by setting two_pass_quantize +and colormap properly just before calling jpeg_start_output(). The following +special rules apply: +1. You must explicitly set cinfo.colormap to NULL when switching to 1-pass + or 2-pass mode from a different mode, or when you want the 2-pass + quantizer to be re-run to generate a new colormap. +2. To switch to an external colormap, or to change to a different external + colormap than was used on the prior pass, you must call + jpeg_new_colormap() after setting cinfo.colormap. +NOTE: if you want to use the same colormap as was used in the prior pass, +you should not do either of these things. This will save some nontrivial +switchover costs. +(These requirements exist because cinfo.colormap will always be non-NULL +after completing a prior output pass, since both the 1-pass and 2-pass +quantizers set it to point to their output colormaps. Thus you have to +do one of these two things to notify the library that something has changed. +Yup, it's a bit klugy, but it's necessary to do it this way for backwards +compatibility.) + +Note that in buffered-image mode, the library generates any requested colormap +during jpeg_start_output(), not during jpeg_start_decompress(). + +When using two-pass quantization, jpeg_start_output() makes a pass over the +buffered image to determine the optimum color map; it therefore may take a +significant amount of time, whereas ordinarily it does little work. The +progress monitor hook is called during this pass, if defined. It is also +important to realize that if the specified target scan number is greater than +or equal to the current input scan number, jpeg_start_output() will attempt +to consume input as it makes this pass. If you use a suspending data source, +you need to check for a FALSE return from jpeg_start_output() under these +conditions. The combination of 2-pass quantization and a not-yet-fully-read +target scan is the only case in which jpeg_start_output() will consume input. + + +Application authors who support buffered-image mode may be tempted to use it +for all JPEG images, even single-scan ones. This will work, but it is +inefficient: there is no need to create an image-sized coefficient buffer for +single-scan images. Requesting buffered-image mode for such an image wastes +memory. Worse, it can cost time on large images, since the buffered data has +to be swapped out or written to a temporary file. If you are concerned about +maximum performance on baseline JPEG files, you should use buffered-image +mode only when the incoming file actually has multiple scans. This can be +tested by calling jpeg_has_multiple_scans(), which will return a correct +result at any time after jpeg_read_header() completes. + +It is also worth noting that when you use jpeg_consume_input() to let input +processing get ahead of output processing, the resulting pattern of access to +the coefficient buffer is quite nonsequential. It's best to use the memory +manager jmemnobs.c if you can (ie, if you have enough real or virtual main +memory). If not, at least make sure that max_memory_to_use is set as high as +possible. If the JPEG memory manager has to use a temporary file, you will +probably see a lot of disk traffic and poor performance. (This could be +improved with additional work on the memory manager, but we haven't gotten +around to it yet.) + +In some applications it may be convenient to use jpeg_consume_input() for all +input processing, including reading the initial markers; that is, you may +wish to call jpeg_consume_input() instead of jpeg_read_header() during +startup. This works, but note that you must check for JPEG_REACHED_SOS and +JPEG_REACHED_EOI return codes as the equivalent of jpeg_read_header's codes. +Once the first SOS marker has been reached, you must call +jpeg_start_decompress() before jpeg_consume_input() will consume more input; +it'll just keep returning JPEG_REACHED_SOS until you do. If you read a +tables-only file this way, jpeg_consume_input() will return JPEG_REACHED_EOI +without ever returning JPEG_REACHED_SOS; be sure to check for this case. +If this happens, the decompressor will not read any more input until you call +jpeg_abort() to reset it. It is OK to call jpeg_consume_input() even when not +using buffered-image mode, but in that case it's basically a no-op after the +initial markers have been read: it will just return JPEG_SUSPENDED. + + +Abbreviated datastreams and multiple images +------------------------------------------- + +A JPEG compression or decompression object can be reused to process multiple +images. This saves a small amount of time per image by eliminating the +"create" and "destroy" operations, but that isn't the real purpose of the +feature. Rather, reuse of an object provides support for abbreviated JPEG +datastreams. Object reuse can also simplify processing a series of images in +a single input or output file. This section explains these features. + +A JPEG file normally contains several hundred bytes worth of quantization +and Huffman tables. In a situation where many images will be stored or +transmitted with identical tables, this may represent an annoying overhead. +The JPEG standard therefore permits tables to be omitted. The standard +defines three classes of JPEG datastreams: + * "Interchange" datastreams contain an image and all tables needed to decode + the image. These are the usual kind of JPEG file. + * "Abbreviated image" datastreams contain an image, but are missing some or + all of the tables needed to decode that image. + * "Abbreviated table specification" (henceforth "tables-only") datastreams + contain only table specifications. +To decode an abbreviated image, it is necessary to load the missing table(s) +into the decoder beforehand. This can be accomplished by reading a separate +tables-only file. A variant scheme uses a series of images in which the first +image is an interchange (complete) datastream, while subsequent ones are +abbreviated and rely on the tables loaded by the first image. It is assumed +that once the decoder has read a table, it will remember that table until a +new definition for the same table number is encountered. + +It is the application designer's responsibility to figure out how to associate +the correct tables with an abbreviated image. While abbreviated datastreams +can be useful in a closed environment, their use is strongly discouraged in +any situation where data exchange with other applications might be needed. +Caveat designer. + +The JPEG library provides support for reading and writing any combination of +tables-only datastreams and abbreviated images. In both compression and +decompression objects, a quantization or Huffman table will be retained for +the lifetime of the object, unless it is overwritten by a new table definition. + + +To create abbreviated image datastreams, it is only necessary to tell the +compressor not to emit some or all of the tables it is using. Each +quantization and Huffman table struct contains a boolean field "sent_table", +which normally is initialized to FALSE. For each table used by the image, the +header-writing process emits the table and sets sent_table = TRUE unless it is +already TRUE. (In normal usage, this prevents outputting the same table +definition multiple times, as would otherwise occur because the chroma +components typically share tables.) Thus, setting this field to TRUE before +calling jpeg_start_compress() will prevent the table from being written at +all. + +If you want to create a "pure" abbreviated image file containing no tables, +just call "jpeg_suppress_tables(&cinfo, TRUE)" after constructing all the +tables. If you want to emit some but not all tables, you'll need to set the +individual sent_table fields directly. + +To create an abbreviated image, you must also call jpeg_start_compress() +with a second parameter of FALSE, not TRUE. Otherwise jpeg_start_compress() +will force all the sent_table fields to FALSE. (This is a safety feature to +prevent abbreviated images from being created accidentally.) + +To create a tables-only file, perform the same parameter setup that you +normally would, but instead of calling jpeg_start_compress() and so on, call +jpeg_write_tables(&cinfo). This will write an abbreviated datastream +containing only SOI, DQT and/or DHT markers, and EOI. All the quantization +and Huffman tables that are currently defined in the compression object will +be emitted unless their sent_tables flag is already TRUE, and then all the +sent_tables flags will be set TRUE. + +A sure-fire way to create matching tables-only and abbreviated image files +is to proceed as follows: + + create JPEG compression object + set JPEG parameters + set destination to tables-only file + jpeg_write_tables(&cinfo); + set destination to image file + jpeg_start_compress(&cinfo, FALSE); + write data... + jpeg_finish_compress(&cinfo); + +Since the JPEG parameters are not altered between writing the table file and +the abbreviated image file, the same tables are sure to be used. Of course, +you can repeat the jpeg_start_compress() ... jpeg_finish_compress() sequence +many times to produce many abbreviated image files matching the table file. + +You cannot suppress output of the computed Huffman tables when Huffman +optimization is selected. (If you could, there'd be no way to decode the +image...) Generally, you don't want to set optimize_coding = TRUE when +you are trying to produce abbreviated files. + +In some cases you might want to compress an image using tables which are +not stored in the application, but are defined in an interchange or +tables-only file readable by the application. This can be done by setting up +a JPEG decompression object to read the specification file, then copying the +tables into your compression object. See jpeg_copy_critical_parameters() +for an example of copying quantization tables. + + +To read abbreviated image files, you simply need to load the proper tables +into the decompression object before trying to read the abbreviated image. +If the proper tables are stored in the application program, you can just +allocate the table structs and fill in their contents directly. For example, +to load a fixed quantization table into table slot "n": + + if (cinfo.quant_tbl_ptrs[n] == NULL) + cinfo.quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) &cinfo); + quant_ptr = cinfo.quant_tbl_ptrs[n]; /* quant_ptr is JQUANT_TBL* */ + for (i = 0; i < 64; i++) { + /* Qtable[] is desired quantization table, in natural array order */ + quant_ptr->quantval[i] = Qtable[i]; + } + +Code to load a fixed Huffman table is typically (for AC table "n"): + + if (cinfo.ac_huff_tbl_ptrs[n] == NULL) + cinfo.ac_huff_tbl_ptrs[n] = jpeg_alloc_huff_table((j_common_ptr) &cinfo); + huff_ptr = cinfo.ac_huff_tbl_ptrs[n]; /* huff_ptr is JHUFF_TBL* */ + for (i = 1; i <= 16; i++) { + /* counts[i] is number of Huffman codes of length i bits, i=1..16 */ + huff_ptr->bits[i] = counts[i]; + } + for (i = 0; i < 256; i++) { + /* symbols[] is the list of Huffman symbols, in code-length order */ + huff_ptr->huffval[i] = symbols[i]; + } + +(Note that trying to set cinfo.quant_tbl_ptrs[n] to point directly at a +constant JQUANT_TBL object is not safe. If the incoming file happened to +contain a quantization table definition, your master table would get +overwritten! Instead allocate a working table copy and copy the master table +into it, as illustrated above. Ditto for Huffman tables, of course.) + +You might want to read the tables from a tables-only file, rather than +hard-wiring them into your application. The jpeg_read_header() call is +sufficient to read a tables-only file. You must pass a second parameter of +FALSE to indicate that you do not require an image to be present. Thus, the +typical scenario is + + create JPEG decompression object + set source to tables-only file + jpeg_read_header(&cinfo, FALSE); + set source to abbreviated image file + jpeg_read_header(&cinfo, TRUE); + set decompression parameters + jpeg_start_decompress(&cinfo); + read data... + jpeg_finish_decompress(&cinfo); + +In some cases, you may want to read a file without knowing whether it contains +an image or just tables. In that case, pass FALSE and check the return value +from jpeg_read_header(): it will be JPEG_HEADER_OK if an image was found, +JPEG_HEADER_TABLES_ONLY if only tables were found. (A third return value, +JPEG_SUSPENDED, is possible when using a suspending data source manager.) +Note that jpeg_read_header() will not complain if you read an abbreviated +image for which you haven't loaded the missing tables; the missing-table check +occurs later, in jpeg_start_decompress(). + + +It is possible to read a series of images from a single source file by +repeating the jpeg_read_header() ... jpeg_finish_decompress() sequence, +without releasing/recreating the JPEG object or the data source module. +(If you did reinitialize, any partial bufferload left in the data source +buffer at the end of one image would be discarded, causing you to lose the +start of the next image.) When you use this method, stored tables are +automatically carried forward, so some of the images can be abbreviated images +that depend on tables from earlier images. + +If you intend to write a series of images into a single destination file, +you might want to make a specialized data destination module that doesn't +flush the output buffer at term_destination() time. This would speed things +up by some trifling amount. Of course, you'd need to remember to flush the +buffer after the last image. You can make the later images be abbreviated +ones by passing FALSE to jpeg_start_compress(). + + +Special markers +--------------- + +Some applications may need to insert or extract special data in the JPEG +datastream. The JPEG standard provides marker types "COM" (comment) and +"APP0" through "APP15" (application) to hold application-specific data. +Unfortunately, the use of these markers is not specified by the standard. +COM markers are fairly widely used to hold user-supplied text. The JFIF file +format spec uses APP0 markers with specified initial strings to hold certain +data. Adobe applications use APP14 markers beginning with the string "Adobe" +for miscellaneous data. Other APPn markers are rarely seen, but might +contain almost anything. + +If you wish to store user-supplied text, we recommend you use COM markers +and place readable 7-bit ASCII text in them. Newline conventions are not +standardized --- expect to find LF (Unix style), CR/LF (DOS style), or CR +(Mac style). A robust COM reader should be able to cope with random binary +garbage, including nulls, since some applications generate COM markers +containing non-ASCII junk. (But yours should not be one of them.) + +For program-supplied data, use an APPn marker, and be sure to begin it with an +identifying string so that you can tell whether the marker is actually yours. +It's probably best to avoid using APP0 or APP14 for any private markers. +(NOTE: the upcoming SPIFF standard will use APP8 markers; we recommend you +not use APP8 markers for any private purposes, either.) + +Keep in mind that at most 65533 bytes can be put into one marker, but you +can have as many markers as you like. + +By default, the IJG compression library will write a JFIF APP0 marker if the +selected JPEG colorspace is grayscale or YCbCr, or an Adobe APP14 marker if +the selected colorspace is RGB, CMYK, or YCCK. You can disable this, but +we don't recommend it. The decompression library will recognize JFIF and +Adobe markers and will set the JPEG colorspace properly when one is found. + + +You can write special markers immediately following the datastream header by +calling jpeg_write_marker() after jpeg_start_compress() and before the first +call to jpeg*_write_scanlines(). When you do this, the markers appear after +the SOI and the JFIF APP0 and Adobe APP14 markers (if written), but before +all else. Specify the marker type parameter as "JPEG_COM" for COM or +"JPEG_APP0 + n" for APPn. (Actually, jpeg_write_marker will let you write +any marker type, but we don't recommend writing any other kinds of marker.) +For example, to write a user comment string pointed to by comment_text: + jpeg_write_marker(cinfo, JPEG_COM, comment_text, strlen(comment_text)); + +If it's not convenient to store all the marker data in memory at once, +you can instead call jpeg_write_m_header() followed by multiple calls to +jpeg_write_m_byte(). If you do it this way, it's your responsibility to +call jpeg_write_m_byte() exactly the number of times given in the length +parameter to jpeg_write_m_header(). (This method lets you empty the +output buffer partway through a marker, which might be important when +using a suspending data destination module. In any case, if you are using +a suspending destination, you should flush its buffer after inserting +any special markers. See "I/O suspension".) + +Or, if you prefer to synthesize the marker byte sequence yourself, +you can just cram it straight into the data destination module. + +If you are writing JFIF 1.02 extension markers (thumbnail images), don't +forget to set cinfo.JFIF_minor_version = 2 so that the encoder will write the +correct JFIF version number in the JFIF header marker. The library's default +is to write version 1.01, but that's wrong if you insert any 1.02 extension +markers. (We could probably get away with just defaulting to 1.02, but there +used to be broken decoders that would complain about unknown minor version +numbers. To reduce compatibility risks it's safest not to write 1.02 unless +you are actually using 1.02 extensions.) + + +When reading, two methods of handling special markers are available: +1. You can ask the library to save the contents of COM and/or APPn markers +into memory, and then examine them at your leisure afterwards. +2. You can supply your own routine to process COM and/or APPn markers +on-the-fly as they are read. +The first method is simpler to use, especially if you are using a suspending +data source; writing a marker processor that copes with input suspension is +not easy (consider what happens if the marker is longer than your available +input buffer). However, the second method conserves memory since the marker +data need not be kept around after it's been processed. + +For either method, you'd normally set up marker handling after creating a +decompression object and before calling jpeg_read_header(), because the +markers of interest will typically be near the head of the file and so will +be scanned by jpeg_read_header. Once you've established a marker handling +method, it will be used for the life of that decompression object +(potentially many datastreams), unless you change it. Marker handling is +determined separately for COM markers and for each APPn marker code. + + +To save the contents of special markers in memory, call + jpeg_save_markers(cinfo, marker_code, length_limit) +where marker_code is the marker type to save, JPEG_COM or JPEG_APP0+n. +(To arrange to save all the special marker types, you need to call this +routine 17 times, for COM and APP0-APP15.) If the incoming marker is longer +than length_limit data bytes, only length_limit bytes will be saved; this +parameter allows you to avoid chewing up memory when you only need to see the +first few bytes of a potentially large marker. If you want to save all the +data, set length_limit to 0xFFFF; that is enough since marker lengths are only +16 bits. As a special case, setting length_limit to 0 prevents that marker +type from being saved at all. (That is the default behavior, in fact.) + +After jpeg_read_header() completes, you can examine the special markers by +following the cinfo->marker_list pointer chain. All the special markers in +the file appear in this list, in order of their occurrence in the file (but +omitting any markers of types you didn't ask for). Both the original data +length and the saved data length are recorded for each list entry; the latter +will not exceed length_limit for the particular marker type. Note that these +lengths exclude the marker length word, whereas the stored representation +within the JPEG file includes it. (Hence the maximum data length is really +only 65533.) + +It is possible that additional special markers appear in the file beyond the +SOS marker at which jpeg_read_header stops; if so, the marker list will be +extended during reading of the rest of the file. This is not expected to be +common, however. If you are short on memory you may want to reset the length +limit to zero for all marker types after finishing jpeg_read_header, to +ensure that the max_memory_to_use setting cannot be exceeded due to addition +of later markers. + +The marker list remains stored until you call jpeg_finish_decompress or +jpeg_abort, at which point the memory is freed and the list is set to empty. +(jpeg_destroy also releases the storage, of course.) + +Note that the library is internally interested in APP0 and APP14 markers; +if you try to set a small nonzero length limit on these types, the library +will silently force the length up to the minimum it wants. (But you can set +a zero length limit to prevent them from being saved at all.) Also, in a +16-bit environment, the maximum length limit may be constrained to less than +65533 by malloc() limitations. It is therefore best not to assume that the +effective length limit is exactly what you set it to be. + + +If you want to supply your own marker-reading routine, you do it by calling +jpeg_set_marker_processor(). A marker processor routine must have the +signature + boolean jpeg_marker_parser_method (j_decompress_ptr cinfo) +Although the marker code is not explicitly passed, the routine can find it +in cinfo->unread_marker. At the time of call, the marker proper has been +read from the data source module. The processor routine is responsible for +reading the marker length word and the remaining parameter bytes, if any. +Return TRUE to indicate success. (FALSE should be returned only if you are +using a suspending data source and it tells you to suspend. See the standard +marker processors in jdmarker.c for appropriate coding methods if you need to +use a suspending data source.) + +If you override the default APP0 or APP14 processors, it is up to you to +recognize JFIF and Adobe markers if you want colorspace recognition to occur +properly. We recommend copying and extending the default processors if you +want to do that. (A better idea is to save these marker types for later +examination by calling jpeg_save_markers(); that method doesn't interfere +with the library's own processing of these markers.) + +jpeg_set_marker_processor() and jpeg_save_markers() are mutually exclusive +--- if you call one it overrides any previous call to the other, for the +particular marker type specified. + +A simple example of an external COM processor can be found in djpeg.c. +Also, see jpegtran.c for an example of using jpeg_save_markers. + + +ICC profiles +------------ + +Two functions are provided for writing and reading International Color +Consortium (ICC) device profiles embedded in JFIF JPEG image files: + + void jpeg_write_icc_profile (j_compress_ptr cinfo, + const JOCTET *icc_data_ptr, + unsigned int icc_data_len); + boolean jpeg_read_icc_profile (j_decompress_ptr cinfo, + JOCTET **icc_data_ptr, + unsigned int *icc_data_len); + +The ICC has defined a standard for including such data in JPEG "APP2" markers. +The aforementioned functions do not know anything about the internal structure +of the ICC profile data; they just know how to embed the profile data into a +JPEG file while writing it, or to extract the profile data from a JPEG file +while reading it. + +jpeg_write_icc_profile() must be called after calling jpeg_start_compress() and +before the first call to jpeg*_write_scanlines() or jpeg*_write_raw_data(). +This ordering ensures that the APP2 marker(s) will appear after the SOI and +JFIF or Adobe markers, but before all other data. + +jpeg_read_icc_profile() returns TRUE if an ICC profile was found and FALSE +otherwise. If an ICC profile was found, then the function will allocate a +memory region containing the profile and will return a pointer to that memory +region in *icc_data_ptr, as well as the length of the region in *icc_data_len. +This memory region is allocated by the library using malloc() and must be freed +by the caller using free() when the memory region is no longer needed. Callers +wishing to use jpeg_read_icc_profile() must call + + jpeg_save_markers(cinfo, JPEG_APP0 + 2, 0xFFFF); + +prior to calling jpeg_read_header(). jpeg_read_icc_profile() can be called at +any point between jpeg_read_header() and jpeg_finish_decompress(). + + +Raw (downsampled) image data +---------------------------- + +Some applications need to supply already-downsampled image data to the JPEG +compressor, or to receive raw downsampled data from the decompressor. The +library supports this requirement by allowing the application to write or +read raw data, bypassing the normal preprocessing or postprocessing steps. +The interface is different from the standard one and is somewhat harder to +use. If your interest is merely in bypassing color conversion, we recommend +that you use the standard interface and simply set jpeg_color_space = +in_color_space (or jpeg_color_space = out_color_space for decompression). +The mechanism described in this section is necessary only to supply or +receive downsampled image data, in which not all components have the same +dimensions. + + +To compress raw data, you must supply the data in the colorspace to be used +in the JPEG file (please read the earlier section on Special color spaces) +and downsampled to the sampling factors specified in the JPEG parameters. +You must supply the data in the format used internally by the JPEG library, +namely a J*SAMPIMAGE array. This is an array of pointers to two-dimensional +arrays, each of type J*SAMPARRAY. Each 2-D array holds the values for one +color component. This structure is necessary since the components are of +different sizes. If the image dimensions are not a multiple of the MCU size, +you must also pad the data correctly (usually, this is done by replicating +the last column and/or row). The data must be padded to a multiple of a DCT +block in each component: that is, each downsampled row must contain a +multiple of 8 valid samples, and there must be a multiple of 8 sample rows +for each component. (For applications such as conversion of digital TV +images, the standard image size is usually a multiple of the DCT block size, +so that no padding need actually be done.) + +The procedure for compression of raw data is basically the same as normal +compression, except that you call jpeg_write_raw_data() or +jpeg12_write_raw_data() in place of jpeg_write_scanlines() or +jpeg12_write_scanlines(). Before calling jpeg_start_compress(), you must do +the following: + * Set cinfo->raw_data_in to TRUE. (It is set FALSE by jpeg_set_defaults().) + This notifies the library that you will be supplying raw data. + * Ensure jpeg_color_space is correct --- an explicit jpeg_set_colorspace() + call is a good idea. Note that since color conversion is bypassed, + in_color_space is ignored, except that jpeg_set_defaults() uses it to + choose the default jpeg_color_space setting. + * Ensure the sampling factors, cinfo->comp_info[i].h_samp_factor and + cinfo->comp_info[i].v_samp_factor, are correct. Since these indicate the + dimensions of the data you are supplying, it's wise to set them + explicitly, rather than assuming the library's defaults are what you want. + +To pass raw data to the library, call jpeg*_write_raw_data() in place of +jpeg*_write_scanlines(). The routines work similarly except that +jpeg*_write_raw_data takes a J*SAMPIMAGE data array rather than J*SAMPARRAY. +The scanlines count passed to and returned from jpeg*_write_raw_data is +measured in terms of the component with the largest v_samp_factor. + +jpeg*_write_raw_data() processes one MCU row per call, which is to say +v_samp_factor*DCTSIZE sample rows of each component. The passed num_lines +value must be at least max_v_samp_factor*DCTSIZE, and the return value will +be exactly that amount (or possibly some multiple of that amount, in future +library versions). This is true even on the last call at the bottom of the +image; don't forget to pad your data as necessary. + +The required dimensions of the supplied data can be computed for each +component as + cinfo->comp_info[i].width_in_blocks*DCTSIZE samples per row + cinfo->comp_info[i].height_in_blocks*DCTSIZE rows in image +after jpeg_start_compress() has initialized those fields. If the valid data +is smaller than this, it must be padded appropriately. For some sampling +factors and image sizes, additional dummy DCT blocks are inserted to make +the image a multiple of the MCU dimensions. The library creates such dummy +blocks itself; it does not read them from your supplied data. Therefore you +need never pad by more than DCTSIZE samples. An example may help here. +Assume 2h2v downsampling of YCbCr data, that is + cinfo->comp_info[0].h_samp_factor = 2 for Y + cinfo->comp_info[0].v_samp_factor = 2 + cinfo->comp_info[1].h_samp_factor = 1 for Cb + cinfo->comp_info[1].v_samp_factor = 1 + cinfo->comp_info[2].h_samp_factor = 1 for Cr + cinfo->comp_info[2].v_samp_factor = 1 +and suppose that the nominal image dimensions (cinfo->image_width and +cinfo->image_height) are 101x101 pixels. Then jpeg_start_compress() will +compute downsampled_width = 101 and width_in_blocks = 13 for Y, +downsampled_width = 51 and width_in_blocks = 7 for Cb and Cr (and the same +for the height fields). You must pad the Y data to at least 13*8 = 104 +columns and rows, the Cb/Cr data to at least 7*8 = 56 columns and rows. The +MCU height is max_v_samp_factor = 2 DCT rows so you must pass at least 16 +scanlines on each call to jpeg*_write_raw_data(), which is to say 16 actual +sample rows of Y and 8 each of Cb and Cr. A total of 7 MCU rows are needed, +so you must pass a total of 7*16 = 112 "scanlines". The last DCT block row +of Y data is dummy, so it doesn't matter what you pass for it in the data +arrays, but the scanlines count must total up to 112 so that all of the Cb +and Cr data gets passed. + +Output suspension is supported with raw-data compression: if the data +destination module suspends, jpeg*_write_raw_data() will return 0. +In this case the same data rows must be passed again on the next call. + + +Decompression with raw data output implies bypassing all postprocessing: +you cannot ask for rescaling or color quantization, for instance. More +seriously, you must deal with the color space and sampling factors present in +the incoming file. If your application only handles, say, 2h1v YCbCr data, +you must check for and fail on other color spaces or other sampling factors. +The library will not convert to a different color space for you. + +To obtain raw data output, set cinfo->raw_data_out = TRUE before +jpeg_start_decompress() (it is set FALSE by jpeg_read_header()). Be sure to +verify that the color space and sampling factors are ones you can handle. +Then call jpeg_read_raw_data() or jpeg12_read_raw_data() in place of +jpeg_read_scanlines() or jpeg12_read_scanlines(). The decompression process is +otherwise the same as usual. + +jpeg*_read_raw_data() returns one MCU row per call, and thus you must pass a +buffer of at least max_v_samp_factor*DCTSIZE scanlines (scanline counting is +the same as for raw-data compression). The buffer you pass must be large +enough to hold the actual data plus padding to DCT-block boundaries. As with +compression, any entirely dummy DCT blocks are not processed so you need not +allocate space for them, but the total scanline count includes them. The +above example of computing buffer dimensions for raw-data compression is +equally valid for decompression. + +Input suspension is supported with raw-data decompression: if the data source +module suspends, jpeg*_read_raw_data() will return 0. You can also use +buffered-image mode to read raw data in multiple passes. + + +Really raw data: DCT coefficients +--------------------------------- + +It is possible to read or write the contents of a JPEG file as raw DCT +coefficients. This facility is mainly intended for use in lossless +transcoding between different JPEG file formats. Other possible applications +include lossless cropping of a JPEG image, lossless reassembly of a +multi-strip or multi-tile TIFF/JPEG file into a single JPEG datastream, etc. + +To read the contents of a JPEG file as DCT coefficients, open the file and do +jpeg_read_header() as usual. But instead of calling jpeg_start_decompress() +and jpeg*_read_scanlines(), call jpeg_read_coefficients(). This will read the +entire image into a set of virtual coefficient-block arrays, one array per +component. The return value is a pointer to an array of virtual-array +descriptors. Each virtual array can be accessed directly using the JPEG +memory manager's access_virt_barray method (see Memory management, below, +and also read structure.txt's discussion of virtual array handling). Or, +for simple transcoding to a different JPEG file format, the array list can +just be handed directly to jpeg_write_coefficients(). + +Each block in the block arrays contains quantized coefficient values in +normal array order (not JPEG zigzag order). The block arrays contain only +DCT blocks containing real data; any entirely-dummy blocks added to fill out +interleaved MCUs at the right or bottom edges of the image are discarded +during reading and are not stored in the block arrays. (The size of each +block array can be determined from the width_in_blocks and height_in_blocks +fields of the component's comp_info entry.) This is also the data format +expected by jpeg_write_coefficients(). + +When you are done using the virtual arrays, call jpeg_finish_decompress() +to release the array storage and return the decompression object to an idle +state; or just call jpeg_destroy() if you don't need to reuse the object. + +If you use a suspending data source, jpeg_read_coefficients() will return +NULL if it is forced to suspend; a non-NULL return value indicates successful +completion. You need not test for a NULL return value when using a +non-suspending data source. + +It is also possible to call jpeg_read_coefficients() to obtain access to the +decoder's coefficient arrays during a normal decode cycle in buffered-image +mode. This frammish might be useful for progressively displaying an incoming +image and then re-encoding it without loss. To do this, decode in buffered- +image mode as discussed previously, then call jpeg_read_coefficients() after +the last jpeg_finish_output() call. The arrays will be available for your use +until you call jpeg_finish_decompress(). + + +To write the contents of a JPEG file as DCT coefficients, you must provide +the DCT coefficients stored in virtual block arrays. You can either pass +block arrays read from an input JPEG file by jpeg_read_coefficients(), or +allocate virtual arrays from the JPEG compression object and fill them +yourself. In either case, jpeg_write_coefficients() is substituted for +jpeg_start_compress() and jpeg*_write_scanlines(). Thus the sequence is + * Create compression object + * Set all compression parameters as necessary + * Request virtual arrays if needed + * jpeg_write_coefficients() + * jpeg_finish_compress() + * Destroy or re-use compression object +jpeg_write_coefficients() is passed a pointer to an array of virtual block +array descriptors; the number of arrays is equal to cinfo.num_components. + +The virtual arrays need only have been requested, not realized, before +jpeg_write_coefficients() is called. A side-effect of +jpeg_write_coefficients() is to realize any virtual arrays that have been +requested from the compression object's memory manager. Thus, when obtaining +the virtual arrays from the compression object, you should fill the arrays +after calling jpeg_write_coefficients(). The data is actually written out +when you call jpeg_finish_compress(); jpeg_write_coefficients() only writes +the file header. + +When writing raw DCT coefficients, it is crucial that the JPEG quantization +tables and sampling factors match the way the data was encoded, or the +resulting file will be invalid. For transcoding from an existing JPEG file, +we recommend using jpeg_copy_critical_parameters(). This routine initializes +all the compression parameters to default values (like jpeg_set_defaults()), +then copies the critical information from a source decompression object. +The decompression object should have just been used to read the entire +JPEG input file --- that is, it should be awaiting jpeg_finish_decompress(). + +jpeg_write_coefficients() marks all tables stored in the compression object +as needing to be written to the output file (thus, it acts like +jpeg_start_compress(cinfo, TRUE)). This is for safety's sake, to avoid +emitting abbreviated JPEG files by accident. If you really want to emit an +abbreviated JPEG file, call jpeg_suppress_tables(), or set the tables' +individual sent_table flags, between calling jpeg_write_coefficients() and +jpeg_finish_compress(). + + +Progress monitoring +------------------- + +Some applications may need to regain control from the JPEG library every so +often. The typical use of this feature is to produce a percent-done bar or +other progress display. (For a simple example, see cjpeg.c or djpeg.c.) +Although you do get control back frequently during the data-transferring pass +(the jpeg*_read_scanlines or jpeg*_write_scanlines loop), any additional passes +will occur inside jpeg_finish_compress or jpeg_start_decompress; those +routines may take a long time to execute, and you don't get control back +until they are done. + +You can define a progress-monitor routine which will be called periodically +by the library. No guarantees are made about how often this call will occur, +so we don't recommend you use it for mouse tracking or anything like that. +At present, a call will occur once per MCU row, scanline, or sample row +group, whichever unit is convenient for the current processing mode; so the +wider the image, the longer the time between calls. During the data +transferring pass, only one call occurs per call of jpeg*_read_scanlines or +jpeg*_write_scanlines, so don't pass a large number of scanlines at once if +you want fine resolution in the progress count. (If you really need to use +the callback mechanism for time-critical tasks like mouse tracking, you could +insert additional calls inside some of the library's inner loops.) + +To establish a progress-monitor callback, create a struct jpeg_progress_mgr, +fill in its progress_monitor field with a pointer to your callback routine, +and set cinfo->progress to point to the struct. The callback will be called +whenever cinfo->progress is non-NULL. (This pointer is set to NULL by +jpeg_create_compress or jpeg_create_decompress; the library will not change +it thereafter. So if you allocate dynamic storage for the progress struct, +make sure it will live as long as the JPEG object does. Allocating from the +JPEG memory manager with lifetime JPOOL_PERMANENT will work nicely.) You +can use the same callback routine for both compression and decompression. + +The jpeg_progress_mgr struct contains four fields which are set by the library: + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +During any one pass, pass_counter increases from 0 up to (not including) +pass_limit; the step size is usually but not necessarily 1. The pass_limit +value may change from one pass to another. The expected total number of +passes is in total_passes, and the number of passes already completed is in +completed_passes. Thus the fraction of work completed may be estimated as + completed_passes + (pass_counter/pass_limit) + -------------------------------------------- + total_passes +ignoring the fact that the passes may not be equal amounts of work. + +When decompressing, pass_limit can even change within a pass, because it +depends on the number of scans in the JPEG file, which isn't always known in +advance. The computed fraction-of-work-done may jump suddenly (if the library +discovers it has overestimated the number of scans) or even decrease (in the +opposite case). It is not wise to put great faith in the work estimate. + +When using the decompressor's buffered-image mode, the progress monitor work +estimate is likely to be completely unhelpful, because the library has no way +to know how many output passes will be demanded of it. Currently, the library +sets total_passes based on the assumption that there will be one more output +pass if the input file end hasn't yet been read (jpeg_input_complete() isn't +TRUE), but no more output passes if the file end has been reached when the +output pass is started. This means that total_passes will rise as additional +output passes are requested. If you have a way of determining the input file +size, estimating progress based on the fraction of the file that's been read +will probably be more useful than using the library's value. + + +Memory management +----------------- + +This section covers some key facts about the JPEG library's built-in memory +manager. For more info, please read structure.txt's section about the memory +manager, and consult the source code if necessary. + +All memory and temporary file allocation within the library is done via the +memory manager. If necessary, you can replace the "back end" of the memory +manager to control allocation yourself (for example, if you don't want the +library to use malloc() and free() for some reason). + +Some data is allocated "permanently" and will not be freed until the JPEG +object is destroyed. Most data is allocated "per image" and is freed by +jpeg_finish_compress, jpeg_finish_decompress, or jpeg_abort. You can call the +memory manager yourself to allocate structures that will automatically be +freed at these times. Typical code for this is + ptr = (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, size); +Use JPOOL_PERMANENT to get storage that lasts as long as the JPEG object. +Use alloc_large instead of alloc_small for anything bigger than a few Kbytes. +There are also alloc_sarray and alloc_barray routines that automatically +build 2-D sample or block arrays. + +The library's minimum space requirements to process an image depend on the +image's width, but not on its height, because the library ordinarily works +with "strip" buffers that are as wide as the image but just a few rows high. +Some operating modes (eg, two-pass color quantization) require full-image +buffers. Such buffers are treated as "virtual arrays": only the current strip +need be in memory, and the rest can be swapped out to a temporary file. + +When using temporary files, the library will make the in-memory buffers for +its virtual arrays just big enough to stay within a "maximum memory" setting. +Your application can set this limit by setting cinfo->mem->max_memory_to_use +after creating the JPEG object. (Of course, there is still a minimum size for +the buffers, so the max-memory setting is effective only if it is bigger than +the minimum space needed.) If you allocate any large structures yourself, you +must allocate them before jpeg_start_compress() or jpeg_start_decompress() in +order to have them counted against the max memory limit. Also keep in mind +that space allocated with alloc_small() is ignored, on the assumption that +it's too small to be worth worrying about; so a reasonable safety margin +should be left when setting max_memory_to_use. + +NOTE: Unless you develop your own memory manager back end, then temporary files +will never be used. The back end provided in libjpeg-turbo (jmemnobs.c) simply +malloc()s and free()s virtual arrays, and an error occurs if the required +memory exceeds the limit specified in cinfo->mem->max_memory_to_use. + + +Memory usage +------------ + +Working memory requirements while performing compression or decompression +depend on image dimensions, image characteristics (such as colorspace and +JPEG process), and operating mode (application-selected options). + +As of v6b, the decompressor requires: + 1. About 24K in more-or-less-fixed-size data. This varies a bit depending + on operating mode and image characteristics (particularly color vs. + grayscale), but it doesn't depend on image dimensions. + 2. Strip buffers (of size proportional to the image width) for IDCT and + upsampling results. The worst case for commonly used sampling factors + is about 34 bytes * width in pixels for a color image. A grayscale image + only needs about 8 bytes per pixel column. + 3. A full-image DCT coefficient buffer is needed to decode a multi-scan JPEG + file (including progressive JPEGs), or whenever you select buffered-image + mode. This takes 2 bytes/coefficient. At typical 2x2 sampling, that's + 3 bytes per pixel for a color image. Worst case (1x1 sampling) requires + 6 bytes/pixel. For grayscale, figure 2 bytes/pixel. + 4. To perform 2-pass color quantization, the decompressor also needs a + 128K color lookup table and a full-image pixel buffer (3 bytes/pixel). +This does not count any memory allocated by the application, such as a +buffer to hold the final output image. + +The above figures are valid for 8-bit JPEG data precision and a machine with +32-bit ints. For 12-bit and 16-bit JPEG data, double the size of the strip +buffers and quantization pixel buffer. The "fixed-size" data will be somewhat +smaller with 16-bit ints, larger with 64-bit ints. Also, CMYK or other unusual +color spaces will require different amounts of space. + +The full-image coefficient and pixel buffers, if needed at all, do not +have to be fully RAM resident; you can have the library use temporary +files instead when the total memory usage would exceed a limit you set. +(But if your OS supports virtual memory, it's probably better to just use +jmemnobs and let the OS do the swapping.) + +The compressor's memory requirements are similar, except that it has no need +for color quantization. Also, it needs a full-image DCT coefficient buffer +if Huffman-table optimization is asked for, even if progressive mode is not +requested. + +If you need more detailed information about memory usage in a particular +situation, you can enable the MEM_STATS code in jmemmgr.c. + + +Library compile-time options +---------------------------- + +A number of compile-time options are available by modifying jmorecfg.h. + +The maximum number of components (color channels) in the image is determined +by MAX_COMPONENTS. The JPEG standard allows up to 255 components, but we +expect that few applications will need more than four or so. + +On machines with unusual data type sizes, you may be able to improve +performance or reduce memory space by tweaking the various typedefs in +jmorecfg.h. In particular, on some RISC CPUs, access to arrays of "short"s +is quite slow; consider trading memory for speed by making JCOEF, INT16, and +UINT16 be "int" or "unsigned int". UINT8 is also a candidate to become int. +You probably don't want to make J*SAMPLE be int unless you have lots of memory +to burn. + +You can reduce the size of the library by compiling out various optional +functions. To do this, undefine xxx_SUPPORTED symbols as necessary. + +You can also save a few K by not having text error messages in the library; +the standard error message table occupies about 5Kb. This is particularly +reasonable for embedded applications where there's no good way to display +a message anyway. To do this, remove the creation of the message table +(jpeg_std_message_table[]) from jerror.c, and alter format_message to do +something reasonable without it. You could output the numeric value of the +message code number, for example. If you do this, you can also save a couple +more K by modifying the TRACEMSn() macros in jerror.h to expand to nothing; +you don't need trace capability anyway, right? + + +Portability considerations +-------------------------- + +The JPEG library has been written to be extremely portable; the sample +applications cjpeg and djpeg are slightly less so. This section summarizes +the design goals in this area. (If you encounter any bugs that cause the +library to be less portable than is claimed here, we'd appreciate hearing +about them.) + +The code works fine on ANSI C and C++ compilers, using any of the popular +system include file setups, and some not-so-popular ones too. + +The code is not dependent on the exact sizes of the C data types. As +distributed, we make the assumptions that + char is at least 8 bits wide + short is at least 16 bits wide + int is at least 16 bits wide + long is at least 32 bits wide +(These are the minimum requirements of the ANSI C standard.) Wider types will +work fine, although memory may be used inefficiently if char is much larger +than 8 bits or short is much bigger than 16 bits. The code should work +equally well with 16- or 32-bit ints. + +In a system where these assumptions are not met, you may be able to make the +code work by modifying the typedefs in jmorecfg.h. However, you will probably +have difficulty if int is less than 16 bits wide, since references to plain +int abound in the code. + +char can be either signed or unsigned, although the code runs faster if an +unsigned char type is available. If char is wider than 8 bits, you will need +to redefine JOCTET and/or provide custom data source/destination managers so +that JOCTET represents exactly 8 bits of data on external storage. + +The JPEG library proper does not assume ASCII representation of characters. +But some of the image file I/O modules in cjpeg/djpeg do have ASCII +dependencies in file-header manipulation; so does cjpeg's select_file_type() +routine. + +The JPEG library does not rely heavily on the C library. In particular, C +stdio is used only by the data source/destination modules and the error +handler, all of which are application-replaceable. (cjpeg/djpeg are more +heavily dependent on stdio.) malloc and free are called only from the memory +manager "back end" module, so you can use a different memory allocator by +replacing that one file. + +More info about porting the code may be gleaned by reading jconfig.txt, +jmorecfg.h, and jinclude.h. diff --git a/3rdparty/libjpeg-turbo/src/rdbmp.c b/3rdparty/libjpeg-turbo/src/rdbmp.c new file mode 100644 index 000000000000..c2c06fd001cb --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/rdbmp.c @@ -0,0 +1,689 @@ +/* + * rdbmp.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009-2017 by Guido Vollbeding. + * libjpeg-turbo Modifications: + * Modified 2011 by Siarhei Siamashka. + * Copyright (C) 2015, 2017-2018, 2021-2023, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains routines to read input images in Microsoft "BMP" + * format (MS Windows 3.x, OS/2 1.x, and OS/2 2.x flavors). + * Currently, only 8-, 24-, and 32-bit images are supported, not 1-bit or + * 4-bit (feeding such low-depth images into JPEG would be silly anyway). + * Also, we don't support RLE-compressed files. + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume input from + * an ordinary stdio stream. They further assume that reading begins + * at the start of the file; start_input may need work if the + * user interface has already read some data (e.g., to determine that + * the file is indeed BMP format). + * + * This code contributed by James Arthur Boucher. + */ + +#include "cmyk.h" +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef BMP_SUPPORTED + + +/* Macros to deal with unsigned chars as efficiently as compiler allows */ + +typedef unsigned char U_CHAR; +#define UCH(x) ((int)(x)) + + +#define ReadOK(file, buffer, len) \ + (fread(buffer, 1, len, file) == ((size_t)(len))) + +static int alpha_index[JPEG_NUMCS] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1 +}; + + +/* Private version of data source object */ + +typedef struct _bmp_source_struct *bmp_source_ptr; + +typedef struct _bmp_source_struct { + struct cjpeg_source_struct pub; /* public fields */ + + j_compress_ptr cinfo; /* back link saves passing separate parm */ + + JSAMPARRAY colormap; /* BMP colormap (converted to my format) */ + + jvirt_sarray_ptr whole_image; /* Needed to reverse row order */ + JDIMENSION source_row; /* Current source row number */ + JDIMENSION row_width; /* Physical width of scanlines in file */ + + int bits_per_pixel; /* remembers 8-, 24-, or 32-bit format */ + int cmap_length; /* colormap length */ + + boolean use_inversion_array; /* TRUE = preload the whole image, which is + stored in bottom-up order, and feed it to + the calling program in top-down order + + FALSE = the calling program will maintain + its own image buffer and read the rows in + bottom-up order */ + + U_CHAR *iobuffer; /* I/O buffer (used to buffer a single row from + disk if use_inversion_array == FALSE) */ +} bmp_source_struct; + + +LOCAL(int) +read_byte(bmp_source_ptr sinfo) +/* Read next byte from BMP file */ +{ + register FILE *infile = sinfo->pub.input_file; + register int c; + + if ((c = getc(infile)) == EOF) + ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); + return c; +} + + +LOCAL(void) +read_colormap(bmp_source_ptr sinfo, int cmaplen, int mapentrysize) +/* Read the colormap from a BMP file */ +{ + int i, gray = 1; + + switch (mapentrysize) { + case 3: + /* BGR format (occurs in OS/2 files) */ + for (i = 0; i < cmaplen; i++) { + sinfo->colormap[2][i] = (JSAMPLE)read_byte(sinfo); + sinfo->colormap[1][i] = (JSAMPLE)read_byte(sinfo); + sinfo->colormap[0][i] = (JSAMPLE)read_byte(sinfo); + if (sinfo->colormap[2][i] != sinfo->colormap[1][i] || + sinfo->colormap[1][i] != sinfo->colormap[0][i]) + gray = 0; + } + break; + case 4: + /* BGR0 format (occurs in MS Windows files) */ + for (i = 0; i < cmaplen; i++) { + sinfo->colormap[2][i] = (JSAMPLE)read_byte(sinfo); + sinfo->colormap[1][i] = (JSAMPLE)read_byte(sinfo); + sinfo->colormap[0][i] = (JSAMPLE)read_byte(sinfo); + (void)read_byte(sinfo); + if (sinfo->colormap[2][i] != sinfo->colormap[1][i] || + sinfo->colormap[1][i] != sinfo->colormap[0][i]) + gray = 0; + } + break; + default: + ERREXIT(sinfo->cinfo, JERR_BMP_BADCMAP); + break; + } + + if ((sinfo->cinfo->in_color_space == JCS_UNKNOWN || + sinfo->cinfo->in_color_space == JCS_RGB) && gray) + sinfo->cinfo->in_color_space = JCS_GRAYSCALE; + + if (sinfo->cinfo->in_color_space == JCS_GRAYSCALE && !gray) + ERREXIT(sinfo->cinfo, JERR_BAD_IN_COLORSPACE); +} + + +/* + * Read one row of pixels. + * The image has been read into the whole_image array, but is otherwise + * unprocessed. We must read it out in top-to-bottom row order, and if + * it is an 8-bit image, we must expand colormapped pixels to 24bit format. + */ + +METHODDEF(JDIMENSION) +get_8bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 8-bit colormap indexes */ +{ + bmp_source_ptr source = (bmp_source_ptr)sinfo; + register JSAMPARRAY colormap = source->colormap; + int cmaplen = source->cmap_length; + JSAMPARRAY image_ptr; + register int t; + register JSAMPROW inptr, outptr; + register JDIMENSION col; + + if (source->use_inversion_array) { + /* Fetch next row from virtual array */ + source->source_row--; + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, source->whole_image, + source->source_row, (JDIMENSION)1, FALSE); + inptr = image_ptr[0]; + } else { + if (!ReadOK(source->pub.input_file, source->iobuffer, source->row_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + inptr = source->iobuffer; + } + + /* Expand the colormap indexes to real data */ + outptr = source->pub.buffer[0]; + if (cinfo->in_color_space == JCS_GRAYSCALE) { + for (col = cinfo->image_width; col > 0; col--) { + t = *inptr++; + if (t >= cmaplen) + ERREXIT(cinfo, JERR_BMP_OUTOFRANGE); + *outptr++ = colormap[0][t]; + } + } else if (cinfo->in_color_space == JCS_CMYK) { + for (col = cinfo->image_width; col > 0; col--) { + t = *inptr++; + if (t >= cmaplen) + ERREXIT(cinfo, JERR_BMP_OUTOFRANGE); + rgb_to_cmyk(colormap[0][t], colormap[1][t], colormap[2][t], outptr, + outptr + 1, outptr + 2, outptr + 3); + outptr += 4; + } + } else { + register int rindex = rgb_red[cinfo->in_color_space]; + register int gindex = rgb_green[cinfo->in_color_space]; + register int bindex = rgb_blue[cinfo->in_color_space]; + register int aindex = alpha_index[cinfo->in_color_space]; + register int ps = rgb_pixelsize[cinfo->in_color_space]; + + if (aindex >= 0) { + for (col = cinfo->image_width; col > 0; col--) { + t = *inptr++; + if (t >= cmaplen) + ERREXIT(cinfo, JERR_BMP_OUTOFRANGE); + outptr[rindex] = colormap[0][t]; + outptr[gindex] = colormap[1][t]; + outptr[bindex] = colormap[2][t]; + outptr[aindex] = 0xFF; + outptr += ps; + } + } else { + for (col = cinfo->image_width; col > 0; col--) { + t = *inptr++; + if (t >= cmaplen) + ERREXIT(cinfo, JERR_BMP_OUTOFRANGE); + outptr[rindex] = colormap[0][t]; + outptr[gindex] = colormap[1][t]; + outptr[bindex] = colormap[2][t]; + outptr += ps; + } + } + } + + return 1; +} + + +METHODDEF(JDIMENSION) +get_24bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 24-bit pixels */ +{ + bmp_source_ptr source = (bmp_source_ptr)sinfo; + JSAMPARRAY image_ptr; + register JSAMPROW inptr, outptr; + register JDIMENSION col; + + if (source->use_inversion_array) { + /* Fetch next row from virtual array */ + source->source_row--; + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, source->whole_image, + source->source_row, (JDIMENSION)1, FALSE); + inptr = image_ptr[0]; + } else { + if (!ReadOK(source->pub.input_file, source->iobuffer, source->row_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + inptr = source->iobuffer; + } + + /* Transfer data. Note source values are in BGR order + * (even though Microsoft's own documents say the opposite). + */ + outptr = source->pub.buffer[0]; + if (cinfo->in_color_space == JCS_EXT_BGR) { + memcpy(outptr, inptr, source->row_width); + } else if (cinfo->in_color_space == JCS_CMYK) { + for (col = cinfo->image_width; col > 0; col--) { + JSAMPLE b = *inptr++, g = *inptr++, r = *inptr++; + rgb_to_cmyk(r, g, b, outptr, outptr + 1, outptr + 2, outptr + 3); + outptr += 4; + } + } else { + register int rindex = rgb_red[cinfo->in_color_space]; + register int gindex = rgb_green[cinfo->in_color_space]; + register int bindex = rgb_blue[cinfo->in_color_space]; + register int aindex = alpha_index[cinfo->in_color_space]; + register int ps = rgb_pixelsize[cinfo->in_color_space]; + + if (aindex >= 0) { + for (col = cinfo->image_width; col > 0; col--) { + outptr[bindex] = *inptr++; + outptr[gindex] = *inptr++; + outptr[rindex] = *inptr++; + outptr[aindex] = 0xFF; + outptr += ps; + } + } else { + for (col = cinfo->image_width; col > 0; col--) { + outptr[bindex] = *inptr++; + outptr[gindex] = *inptr++; + outptr[rindex] = *inptr++; + outptr += ps; + } + } + } + + return 1; +} + + +METHODDEF(JDIMENSION) +get_32bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 32-bit pixels */ +{ + bmp_source_ptr source = (bmp_source_ptr)sinfo; + JSAMPARRAY image_ptr; + register JSAMPROW inptr, outptr; + register JDIMENSION col; + + if (source->use_inversion_array) { + /* Fetch next row from virtual array */ + source->source_row--; + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, source->whole_image, + source->source_row, (JDIMENSION)1, FALSE); + inptr = image_ptr[0]; + } else { + if (!ReadOK(source->pub.input_file, source->iobuffer, source->row_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + inptr = source->iobuffer; + } + + /* Transfer data. Note source values are in BGR order + * (even though Microsoft's own documents say the opposite). + */ + outptr = source->pub.buffer[0]; + if (cinfo->in_color_space == JCS_EXT_BGRX || + cinfo->in_color_space == JCS_EXT_BGRA) { + memcpy(outptr, inptr, source->row_width); + } else if (cinfo->in_color_space == JCS_CMYK) { + for (col = cinfo->image_width; col > 0; col--) { + JSAMPLE b = *inptr++, g = *inptr++, r = *inptr++; + rgb_to_cmyk(r, g, b, outptr, outptr + 1, outptr + 2, outptr + 3); + inptr++; /* skip the 4th byte (Alpha channel) */ + outptr += 4; + } + } else { + register int rindex = rgb_red[cinfo->in_color_space]; + register int gindex = rgb_green[cinfo->in_color_space]; + register int bindex = rgb_blue[cinfo->in_color_space]; + register int aindex = alpha_index[cinfo->in_color_space]; + register int ps = rgb_pixelsize[cinfo->in_color_space]; + + if (aindex >= 0) { + for (col = cinfo->image_width; col > 0; col--) { + outptr[bindex] = *inptr++; + outptr[gindex] = *inptr++; + outptr[rindex] = *inptr++; + outptr[aindex] = *inptr++; + outptr += ps; + } + } else { + for (col = cinfo->image_width; col > 0; col--) { + outptr[bindex] = *inptr++; + outptr[gindex] = *inptr++; + outptr[rindex] = *inptr++; + inptr++; /* skip the 4th byte (Alpha channel) */ + outptr += ps; + } + } + } + + return 1; +} + + +/* + * This method loads the image into whole_image during the first call on + * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call + * get_8bit_row, get_24bit_row, or get_32bit_row on subsequent calls. + */ + +METHODDEF(JDIMENSION) +preload_image(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + bmp_source_ptr source = (bmp_source_ptr)sinfo; + register FILE *infile = source->pub.input_file; + register JSAMPROW out_ptr; + JSAMPARRAY image_ptr; + JDIMENSION row; + cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress; + + /* Read the data into a virtual array in input-file row order. */ + for (row = 0; row < cinfo->image_height; row++) { + if (progress != NULL) { + progress->pub.pass_counter = (long)row; + progress->pub.pass_limit = (long)cinfo->image_height; + (*progress->pub.progress_monitor) ((j_common_ptr)cinfo); + } + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, source->whole_image, row, (JDIMENSION)1, TRUE); + out_ptr = image_ptr[0]; + if (fread(out_ptr, 1, source->row_width, infile) != source->row_width) { + if (feof(infile)) + ERREXIT(cinfo, JERR_INPUT_EOF); + else + ERREXIT(cinfo, JERR_FILE_READ); + } + } + if (progress != NULL) + progress->completed_extra_passes++; + + /* Set up to read from the virtual array in top-to-bottom order */ + switch (source->bits_per_pixel) { + case 8: + source->pub.get_pixel_rows = get_8bit_row; + break; + case 24: + source->pub.get_pixel_rows = get_24bit_row; + break; + case 32: + source->pub.get_pixel_rows = get_32bit_row; + break; + default: + ERREXIT(cinfo, JERR_BMP_BADDEPTH); + } + source->source_row = cinfo->image_height; + + /* And read the first row */ + return (*source->pub.get_pixel_rows) (cinfo, sinfo); +} + + +/* + * Read the file header; return image size and component count. + */ + +METHODDEF(void) +start_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + bmp_source_ptr source = (bmp_source_ptr)sinfo; + U_CHAR bmpfileheader[14]; + U_CHAR bmpinfoheader[64]; + +#define GET_2B(array, offset) \ + ((unsigned short)UCH(array[offset]) + \ + (((unsigned short)UCH(array[offset + 1])) << 8)) +#define GET_4B(array, offset) \ + ((unsigned int)UCH(array[offset]) + \ + (((unsigned int)UCH(array[offset + 1])) << 8) + \ + (((unsigned int)UCH(array[offset + 2])) << 16) + \ + (((unsigned int)UCH(array[offset + 3])) << 24)) + + int bfOffBits; + int headerSize; + int biWidth; + int biHeight; + unsigned short biPlanes; + unsigned int biCompression; + int biXPelsPerMeter, biYPelsPerMeter; + int biClrUsed = 0; + int mapentrysize = 0; /* 0 indicates no colormap */ + int bPad; + JDIMENSION row_width = 0; + + /* Read and verify the bitmap file header */ + if (!ReadOK(source->pub.input_file, bmpfileheader, 14)) + ERREXIT(cinfo, JERR_INPUT_EOF); + if (GET_2B(bmpfileheader, 0) != 0x4D42) /* 'BM' */ + ERREXIT(cinfo, JERR_BMP_NOT); + bfOffBits = GET_4B(bmpfileheader, 10); + /* We ignore the remaining fileheader fields */ + + /* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows), + * or 64 bytes (OS/2 2.x). Check the first 4 bytes to find out which. + */ + if (!ReadOK(source->pub.input_file, bmpinfoheader, 4)) + ERREXIT(cinfo, JERR_INPUT_EOF); + headerSize = GET_4B(bmpinfoheader, 0); + if (headerSize < 12 || headerSize > 64 || (headerSize + 14) > bfOffBits) + ERREXIT(cinfo, JERR_BMP_BADHEADER); + if (!ReadOK(source->pub.input_file, bmpinfoheader + 4, headerSize - 4)) + ERREXIT(cinfo, JERR_INPUT_EOF); + + switch (headerSize) { + case 12: + /* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */ + biWidth = (int)GET_2B(bmpinfoheader, 4); + biHeight = (int)GET_2B(bmpinfoheader, 6); + biPlanes = GET_2B(bmpinfoheader, 8); + source->bits_per_pixel = (int)GET_2B(bmpinfoheader, 10); + + switch (source->bits_per_pixel) { + case 8: /* colormapped image */ + mapentrysize = 3; /* OS/2 uses RGBTRIPLE colormap */ + TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, biWidth, biHeight); + break; + case 24: /* RGB image */ + case 32: /* RGB image + Alpha channel */ + TRACEMS3(cinfo, 1, JTRC_BMP_OS2, biWidth, biHeight, + source->bits_per_pixel); + break; + default: + ERREXIT(cinfo, JERR_BMP_BADDEPTH); + break; + } + break; + case 40: + case 64: + /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */ + /* or OS/2 2.x header, which has additional fields that we ignore */ + biWidth = (int)GET_4B(bmpinfoheader, 4); + biHeight = (int)GET_4B(bmpinfoheader, 8); + biPlanes = GET_2B(bmpinfoheader, 12); + source->bits_per_pixel = (int)GET_2B(bmpinfoheader, 14); + biCompression = GET_4B(bmpinfoheader, 16); + biXPelsPerMeter = (int)GET_4B(bmpinfoheader, 24); + biYPelsPerMeter = (int)GET_4B(bmpinfoheader, 28); + biClrUsed = GET_4B(bmpinfoheader, 32); + /* biSizeImage, biClrImportant fields are ignored */ + + switch (source->bits_per_pixel) { + case 8: /* colormapped image */ + mapentrysize = 4; /* Windows uses RGBQUAD colormap */ + TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, biWidth, biHeight); + break; + case 24: /* RGB image */ + case 32: /* RGB image + Alpha channel */ + TRACEMS3(cinfo, 1, JTRC_BMP, biWidth, biHeight, source->bits_per_pixel); + break; + default: + ERREXIT(cinfo, JERR_BMP_BADDEPTH); + break; + } + if (biCompression != 0) + ERREXIT(cinfo, JERR_BMP_COMPRESSED); + + if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) { + /* Set JFIF density parameters from the BMP data */ + cinfo->X_density = (UINT16)(biXPelsPerMeter / 100); /* 100 cm per meter */ + cinfo->Y_density = (UINT16)(biYPelsPerMeter / 100); + cinfo->density_unit = 2; /* dots/cm */ + } + break; + default: + ERREXIT(cinfo, JERR_BMP_BADHEADER); + return; + } + + if (biWidth <= 0 || biHeight <= 0) + ERREXIT(cinfo, JERR_BMP_EMPTY); + if (sinfo->max_pixels && + (unsigned long long)biWidth * biHeight > sinfo->max_pixels) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, sinfo->max_pixels); + if (biPlanes != 1) + ERREXIT(cinfo, JERR_BMP_BADPLANES); + + /* Compute distance to bitmap data --- will adjust for colormap below */ + bPad = bfOffBits - (headerSize + 14); + + /* Read the colormap, if any */ + if (mapentrysize > 0) { + if (biClrUsed <= 0) + biClrUsed = 256; /* assume it's 256 */ + else if (biClrUsed > 256) + ERREXIT(cinfo, JERR_BMP_BADCMAP); + /* Allocate space to store the colormap */ + source->colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)biClrUsed, (JDIMENSION)3); + source->cmap_length = (int)biClrUsed; + /* and read it from the file */ + read_colormap(source, (int)biClrUsed, mapentrysize); + /* account for size of colormap */ + bPad -= biClrUsed * mapentrysize; + } + + /* Skip any remaining pad bytes */ + if (bPad < 0) /* incorrect bfOffBits value? */ + ERREXIT(cinfo, JERR_BMP_BADHEADER); + while (--bPad >= 0) { + (void)read_byte(source); + } + + /* Compute row width in file, including padding to 4-byte boundary */ + switch (source->bits_per_pixel) { + case 8: + if (cinfo->in_color_space == JCS_UNKNOWN) + cinfo->in_color_space = JCS_EXT_RGB; + if (IsExtRGB(cinfo->in_color_space)) + cinfo->input_components = rgb_pixelsize[cinfo->in_color_space]; + else if (cinfo->in_color_space == JCS_GRAYSCALE) + cinfo->input_components = 1; + else if (cinfo->in_color_space == JCS_CMYK) + cinfo->input_components = 4; + else + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + row_width = (JDIMENSION)biWidth; + break; + case 24: + if (cinfo->in_color_space == JCS_UNKNOWN) + cinfo->in_color_space = JCS_EXT_BGR; + if (IsExtRGB(cinfo->in_color_space)) + cinfo->input_components = rgb_pixelsize[cinfo->in_color_space]; + else if (cinfo->in_color_space == JCS_CMYK) + cinfo->input_components = 4; + else + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + if ((unsigned long long)biWidth * 3ULL > 0xFFFFFFFFULL) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + row_width = (JDIMENSION)biWidth * 3; + break; + case 32: + if (cinfo->in_color_space == JCS_UNKNOWN) + cinfo->in_color_space = JCS_EXT_BGRA; + if (IsExtRGB(cinfo->in_color_space)) + cinfo->input_components = rgb_pixelsize[cinfo->in_color_space]; + else if (cinfo->in_color_space == JCS_CMYK) + cinfo->input_components = 4; + else + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + if ((unsigned long long)biWidth * 4ULL > 0xFFFFFFFFULL) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + row_width = (JDIMENSION)biWidth * 4; + break; + default: + ERREXIT(cinfo, JERR_BMP_BADDEPTH); + } + while ((row_width & 3) != 0) row_width++; + source->row_width = row_width; + + if (source->use_inversion_array) { + /* Allocate space for inversion array, prepare for preload pass */ + source->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE, + row_width, (JDIMENSION)biHeight, (JDIMENSION)1); + source->pub.get_pixel_rows = preload_image; + if (cinfo->progress != NULL) { + cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress; + progress->total_extra_passes++; /* count file input as separate pass */ + } + } else { + source->iobuffer = (U_CHAR *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, row_width); + switch (source->bits_per_pixel) { + case 8: + source->pub.get_pixel_rows = get_8bit_row; + break; + case 24: + source->pub.get_pixel_rows = get_24bit_row; + break; + case 32: + source->pub.get_pixel_rows = get_32bit_row; + break; + default: + ERREXIT(cinfo, JERR_BMP_BADDEPTH); + } + } + + /* Ensure that biWidth * cinfo->input_components doesn't exceed the maximum + value of the JDIMENSION type. This is only a danger with BMP files, since + their width and height fields are 32-bit integers. */ + if ((unsigned long long)biWidth * + (unsigned long long)cinfo->input_components > 0xFFFFFFFFULL) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + /* Allocate one-row buffer for returned data */ + source->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, + (JDIMENSION)biWidth * (JDIMENSION)cinfo->input_components, (JDIMENSION)1); + source->pub.buffer_height = 1; + + cinfo->data_precision = 8; + cinfo->image_width = (JDIMENSION)biWidth; + cinfo->image_height = (JDIMENSION)biHeight; +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + /* no work */ +} + + +/* + * The module selection routine for BMP format input. + */ + +GLOBAL(cjpeg_source_ptr) +jinit_read_bmp(j_compress_ptr cinfo, boolean use_inversion_array) +{ + bmp_source_ptr source; + + if (cinfo->data_precision != 8) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Create module interface object */ + source = (bmp_source_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + sizeof(bmp_source_struct)); + source->cinfo = cinfo; /* make back link for subroutines */ + /* Fill in method ptrs, except get_pixel_rows which start_input sets */ + source->pub.start_input = start_input_bmp; + source->pub.finish_input = finish_input_bmp; + source->pub.max_pixels = 0; + + source->use_inversion_array = use_inversion_array; + + return (cjpeg_source_ptr)source; +} + +#endif /* BMP_SUPPORTED */ diff --git a/3rdparty/libjpeg-turbo/src/rdcolmap.c b/3rdparty/libjpeg-turbo/src/rdcolmap.c new file mode 100644 index 000000000000..836685e1b80e --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/rdcolmap.c @@ -0,0 +1,261 @@ +/* + * rdcolmap.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1994-1996, Thomas G. Lane. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file implements djpeg's "-map file" switch. It reads a source image + * and constructs a colormap to be supplied to the JPEG decompressor. + * + * Currently, these file formats are supported for the map file: + * GIF: the contents of the GIF's global colormap are used. + * PPM (either text or raw flavor): the entire file is read and + * each unique pixel value is entered in the map. + * Note that reading a large PPM file will be horrendously slow. + * Typically, a PPM-format map file should contain just one pixel + * of each desired color. Such a file can be extracted from an + * ordinary image PPM file with ppmtomap(1). + * + * Rescaling a PPM that has a maxval unequal to _MAXJSAMPLE is not + * currently implemented. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include "jsamplecomp.h" + +#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */ +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) + +/* Portions of this code are based on the PBMPLUS library, which is: +** +** Copyright (C) 1988 by Jef Poskanzer. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +*/ + + +/* + * Add a (potentially) new color to the color map. + */ + +LOCAL(void) +add_map_entry(j_decompress_ptr cinfo, int R, int G, int B) +{ + _JSAMPROW colormap0 = ((_JSAMPARRAY)cinfo->colormap)[0]; + _JSAMPROW colormap1 = ((_JSAMPARRAY)cinfo->colormap)[1]; + _JSAMPROW colormap2 = ((_JSAMPARRAY)cinfo->colormap)[2]; + int ncolors = cinfo->actual_number_of_colors; + int index; + + /* Check for duplicate color. */ + for (index = 0; index < ncolors; index++) { + if (colormap0[index] == R && colormap1[index] == G && + colormap2[index] == B) + return; /* color is already in map */ + } + + /* Check for map overflow. */ + if (ncolors >= (_MAXJSAMPLE + 1)) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, (_MAXJSAMPLE + 1)); + + /* OK, add color to map. */ + colormap0[ncolors] = (_JSAMPLE)R; + colormap1[ncolors] = (_JSAMPLE)G; + colormap2[ncolors] = (_JSAMPLE)B; + cinfo->actual_number_of_colors++; +} + + +/* + * Extract color map from a GIF file. + */ + +LOCAL(void) +read_gif_map(j_decompress_ptr cinfo, FILE *infile) +{ + int header[13]; + int i, colormaplen; + int R, G, B; + + /* Initial 'G' has already been read by read_color_map */ + /* Read the rest of the GIF header and logical screen descriptor */ + for (i = 1; i < 13; i++) { + if ((header[i] = getc(infile)) == EOF) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + } + + /* Verify GIF Header */ + if (header[1] != 'I' || header[2] != 'F') + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + /* There must be a global color map. */ + if ((header[10] & 0x80) == 0) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + /* OK, fetch it. */ + colormaplen = 2 << (header[10] & 0x07); + + for (i = 0; i < colormaplen; i++) { + R = getc(infile); + G = getc(infile); + B = getc(infile); + if (R == EOF || G == EOF || B == EOF) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + add_map_entry(cinfo, + R << (BITS_IN_JSAMPLE - 8), + G << (BITS_IN_JSAMPLE - 8), + B << (BITS_IN_JSAMPLE - 8)); + } +} + + +/* Support routines for reading PPM */ + + +LOCAL(int) +pbm_getc(FILE *infile) +/* Read next char, skipping over any comments */ +/* A comment/newline sequence is returned as a newline */ +{ + register int ch; + + ch = getc(infile); + if (ch == '#') { + do { + ch = getc(infile); + } while (ch != '\n' && ch != EOF); + } + return ch; +} + + +LOCAL(unsigned int) +read_pbm_integer(j_decompress_ptr cinfo, FILE *infile) +/* Read an unsigned decimal integer from the PPM file */ +/* Swallows one trailing character after the integer */ +/* Note that on a 16-bit-int machine, only values up to 64k can be read. */ +/* This should not be a problem in practice. */ +{ + register int ch; + register unsigned int val; + + /* Skip any leading whitespace */ + do { + ch = pbm_getc(infile); + if (ch == EOF) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); + + if (ch < '0' || ch > '9') + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + val = ch - '0'; + while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') { + val *= 10; + val += ch - '0'; + } + return val; +} + + +/* + * Extract color map from a PPM file. + */ + +LOCAL(void) +read_ppm_map(j_decompress_ptr cinfo, FILE *infile) +{ + int c; + unsigned int w, h, maxval, row, col; + int R, G, B; + + /* Initial 'P' has already been read by read_color_map */ + c = getc(infile); /* save format discriminator for a sec */ + + /* while we fetch the remaining header info */ + w = read_pbm_integer(cinfo, infile); + h = read_pbm_integer(cinfo, infile); + maxval = read_pbm_integer(cinfo, infile); + + if (w <= 0 || h <= 0 || maxval <= 0) /* error check */ + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + /* For now, we don't support rescaling from an unusual maxval. */ + if (maxval != (unsigned int)_MAXJSAMPLE) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + switch (c) { + case '3': /* it's a text-format PPM file */ + for (row = 0; row < h; row++) { + for (col = 0; col < w; col++) { + R = read_pbm_integer(cinfo, infile); + G = read_pbm_integer(cinfo, infile); + B = read_pbm_integer(cinfo, infile); + add_map_entry(cinfo, R, G, B); + } + } + break; + + case '6': /* it's a raw-format PPM file */ + for (row = 0; row < h; row++) { + for (col = 0; col < w; col++) { + R = getc(infile); + G = getc(infile); + B = getc(infile); + if (R == EOF || G == EOF || B == EOF) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + add_map_entry(cinfo, R, G, B); + } + } + break; + + default: + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + break; + } +} + + +/* + * Main entry point from djpeg.c. + * Input: opened input file (from file name argument on command line). + * Output: colormap and actual_number_of_colors fields are set in cinfo. + */ + +GLOBAL(void) +_read_color_map(j_decompress_ptr cinfo, FILE *infile) +{ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Allocate space for a color map of maximum supported size. */ + cinfo->colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, + (JDIMENSION)(_MAXJSAMPLE + 1), (JDIMENSION)3); + cinfo->actual_number_of_colors = 0; /* initialize map to empty */ + + /* Read first byte to determine file format */ + switch (getc(infile)) { + case 'G': + read_gif_map(cinfo, infile); + break; + case 'P': + read_ppm_map(cinfo, infile); + break; + default: + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + break; + } +} + +#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */ +#endif /* QUANT_2PASS_SUPPORTED */ diff --git a/3rdparty/libjpeg-turbo/src/rdgif.c b/3rdparty/libjpeg-turbo/src/rdgif.c new file mode 100644 index 000000000000..23e8b9e128b0 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/rdgif.c @@ -0,0 +1,720 @@ +/* + * rdgif.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2019 by Guido Vollbeding. + * libjpeg-turbo Modifications: + * Copyright (C) 2021-2023, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains routines to read input images in GIF format. + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume input from + * an ordinary stdio stream. They further assume that reading begins + * at the start of the file; start_input may need work if the + * user interface has already read some data (e.g., to determine that + * the file is indeed GIF format). + */ + +/* + * This code is loosely based on giftoppm from the PBMPLUS distribution + * of Feb. 1991. That file contains the following copyright notice: + * +-------------------------------------------------------------------+ + * | Copyright 1990, David Koblas. | + * | Permission to use, copy, modify, and distribute this software | + * | and its documentation for any purpose and without fee is hereby | + * | granted, provided that the above copyright notice appear in all | + * | copies and that both that copyright notice and this permission | + * | notice appear in supporting documentation. This software is | + * | provided "as is" without express or implied warranty. | + * +-------------------------------------------------------------------+ + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include "jsamplecomp.h" + +#if defined(GIF_SUPPORTED) && \ + (BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED)) + + +/* Macros to deal with unsigned chars as efficiently as compiler allows */ + +typedef unsigned char U_CHAR; +#define UCH(x) ((int)(x)) + + +#define ReadOK(file, buffer, len) \ + (fread(buffer, 1, len, file) == ((size_t)(len))) + + +#define MAXCOLORMAPSIZE 256 /* max # of colors in a GIF colormap */ +#define NUMCOLORS 3 /* # of colors */ +#define CM_RED 0 /* color component numbers */ +#define CM_GREEN 1 +#define CM_BLUE 2 + +#define MAX_LZW_BITS 12 /* maximum LZW code size */ +#define LZW_TABLE_SIZE (1 << MAX_LZW_BITS) /* # of possible LZW symbols */ + +/* Macros for extracting header data --- note we assume chars may be signed */ + +#define LM_to_uint(array, offset) \ + ((unsigned int)UCH(array[offset]) + \ + (((unsigned int)UCH(array[offset + 1])) << 8)) + +#define BitSet(byte, bit) ((byte) & (bit)) +#define INTERLACE 0x40 /* mask for bit signifying interlaced image */ +#define COLORMAPFLAG 0x80 /* mask for bit signifying colormap presence */ + + +/* + * LZW decompression tables look like this: + * symbol_head[K] = prefix symbol of any LZW symbol K (0..LZW_TABLE_SIZE-1) + * symbol_tail[K] = suffix byte of any LZW symbol K (0..LZW_TABLE_SIZE-1) + * Note that entries 0..end_code of the above tables are not used, + * since those symbols represent raw bytes or special codes. + * + * The stack represents the not-yet-used expansion of the last LZW symbol. + * In the worst case, a symbol could expand to as many bytes as there are + * LZW symbols, so we allocate LZW_TABLE_SIZE bytes for the stack. + * (This is conservative since that number includes the raw-byte symbols.) + */ + + +/* Private version of data source object */ + +typedef struct { + struct cjpeg_source_struct pub; /* public fields */ + + j_compress_ptr cinfo; /* back link saves passing separate parm */ + + _JSAMPARRAY colormap; /* GIF colormap (converted to my format) */ + + /* State for GetCode and LZWReadByte */ + U_CHAR code_buf[256 + 4]; /* current input data block */ + int last_byte; /* # of bytes in code_buf */ + int last_bit; /* # of bits in code_buf */ + int cur_bit; /* next bit index to read */ + boolean first_time; /* flags first call to GetCode */ + boolean out_of_blocks; /* TRUE if hit terminator data block */ + + int input_code_size; /* codesize given in GIF file */ + int clear_code, end_code; /* values for Clear and End codes */ + + int code_size; /* current actual code size */ + int limit_code; /* 2^code_size */ + int max_code; /* first unused code value */ + + /* Private state for LZWReadByte */ + int oldcode; /* previous LZW symbol */ + int firstcode; /* first byte of oldcode's expansion */ + + /* LZW symbol table and expansion stack */ + UINT16 *symbol_head; /* => table of prefix symbols */ + UINT8 *symbol_tail; /* => table of suffix bytes */ + UINT8 *symbol_stack; /* => stack for symbol expansions */ + UINT8 *sp; /* stack pointer */ + + /* State for interlaced image processing */ + boolean is_interlaced; /* TRUE if have interlaced image */ + jvirt_sarray_ptr interlaced_image; /* full image in interlaced order */ + JDIMENSION cur_row_number; /* need to know actual row number */ + JDIMENSION pass2_offset; /* # of pixel rows in pass 1 */ + JDIMENSION pass3_offset; /* # of pixel rows in passes 1&2 */ + JDIMENSION pass4_offset; /* # of pixel rows in passes 1,2,3 */ +} gif_source_struct; + +typedef gif_source_struct *gif_source_ptr; + + +/* Forward declarations */ +METHODDEF(JDIMENSION) get_pixel_rows(j_compress_ptr cinfo, + cjpeg_source_ptr sinfo); +METHODDEF(JDIMENSION) load_interlaced_image(j_compress_ptr cinfo, + cjpeg_source_ptr sinfo); +METHODDEF(JDIMENSION) get_interlaced_row(j_compress_ptr cinfo, + cjpeg_source_ptr sinfo); + + +LOCAL(int) +ReadByte(gif_source_ptr sinfo) +/* Read next byte from GIF file */ +{ + register FILE *infile = sinfo->pub.input_file; + register int c; + + if ((c = getc(infile)) == EOF) + ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); + return c; +} + + +LOCAL(int) +GetDataBlock(gif_source_ptr sinfo, U_CHAR *buf) +/* Read a GIF data block, which has a leading count byte */ +/* A zero-length block marks the end of a data block sequence */ +{ + int count; + + count = ReadByte(sinfo); + if (count > 0) { + if (!ReadOK(sinfo->pub.input_file, buf, count)) + ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); + } + return count; +} + + +LOCAL(void) +SkipDataBlocks(gif_source_ptr sinfo) +/* Skip a series of data blocks, until a block terminator is found */ +{ + U_CHAR buf[256]; + + while (GetDataBlock(sinfo, buf) > 0) + /* skip */; +} + + +LOCAL(void) +ReInitLZW(gif_source_ptr sinfo) +/* (Re)initialize LZW state; shared code for startup and Clear processing */ +{ + sinfo->code_size = sinfo->input_code_size + 1; + sinfo->limit_code = sinfo->clear_code << 1; /* 2^code_size */ + sinfo->max_code = sinfo->clear_code + 2; /* first unused code value */ + sinfo->sp = sinfo->symbol_stack; /* init stack to empty */ +} + + +LOCAL(void) +InitLZWCode(gif_source_ptr sinfo) +/* Initialize for a series of LZWReadByte (and hence GetCode) calls */ +{ + /* GetCode initialization */ + sinfo->last_byte = 2; /* make safe to "recopy last two bytes" */ + sinfo->code_buf[0] = 0; + sinfo->code_buf[1] = 0; + sinfo->last_bit = 0; /* nothing in the buffer */ + sinfo->cur_bit = 0; /* force buffer load on first call */ + sinfo->first_time = TRUE; + sinfo->out_of_blocks = FALSE; + + /* LZWReadByte initialization: */ + /* compute special code values (note that these do not change later) */ + sinfo->clear_code = 1 << sinfo->input_code_size; + sinfo->end_code = sinfo->clear_code + 1; + ReInitLZW(sinfo); +} + + +LOCAL(int) +GetCode(gif_source_ptr sinfo) +/* Fetch the next code_size bits from the GIF data */ +/* We assume code_size is less than 16 */ +{ + register int accum; + int offs, count; + + while (sinfo->cur_bit + sinfo->code_size > sinfo->last_bit) { + /* Time to reload the buffer */ + /* First time, share code with Clear case */ + if (sinfo->first_time) { + sinfo->first_time = FALSE; + return sinfo->clear_code; + } + if (sinfo->out_of_blocks) { + WARNMS(sinfo->cinfo, JWRN_GIF_NOMOREDATA); + return sinfo->end_code; /* fake something useful */ + } + /* preserve last two bytes of what we have -- assume code_size <= 16 */ + sinfo->code_buf[0] = sinfo->code_buf[sinfo->last_byte-2]; + sinfo->code_buf[1] = sinfo->code_buf[sinfo->last_byte-1]; + /* Load more bytes; set flag if we reach the terminator block */ + if ((count = GetDataBlock(sinfo, &sinfo->code_buf[2])) == 0) { + sinfo->out_of_blocks = TRUE; + WARNMS(sinfo->cinfo, JWRN_GIF_NOMOREDATA); + return sinfo->end_code; /* fake something useful */ + } + /* Reset counters */ + sinfo->cur_bit = (sinfo->cur_bit - sinfo->last_bit) + 16; + sinfo->last_byte = 2 + count; + sinfo->last_bit = sinfo->last_byte * 8; + } + + /* Form up next 24 bits in accum */ + offs = sinfo->cur_bit >> 3; /* byte containing cur_bit */ + accum = UCH(sinfo->code_buf[offs + 2]); + accum <<= 8; + accum |= UCH(sinfo->code_buf[offs + 1]); + accum <<= 8; + accum |= UCH(sinfo->code_buf[offs]); + + /* Right-align cur_bit in accum, then mask off desired number of bits */ + accum >>= (sinfo->cur_bit & 7); + sinfo->cur_bit += sinfo->code_size; + return accum & ((1 << sinfo->code_size) - 1); +} + + +LOCAL(int) +LZWReadByte(gif_source_ptr sinfo) +/* Read an LZW-compressed byte */ +{ + register int code; /* current working code */ + int incode; /* saves actual input code */ + + /* If any codes are stacked from a previously read symbol, return them */ + if (sinfo->sp > sinfo->symbol_stack) + return (int)(*(--sinfo->sp)); + + /* Time to read a new symbol */ + code = GetCode(sinfo); + + if (code == sinfo->clear_code) { + /* Reinit state, swallow any extra Clear codes, and */ + /* return next code, which is expected to be a raw byte. */ + ReInitLZW(sinfo); + do { + code = GetCode(sinfo); + } while (code == sinfo->clear_code); + if (code > sinfo->clear_code) { /* make sure it is a raw byte */ + WARNMS(sinfo->cinfo, JWRN_GIF_BADDATA); + code = 0; /* use something valid */ + } + /* make firstcode, oldcode valid! */ + sinfo->firstcode = sinfo->oldcode = code; + return code; + } + + if (code == sinfo->end_code) { + /* Skip the rest of the image, unless GetCode already read terminator */ + if (!sinfo->out_of_blocks) { + SkipDataBlocks(sinfo); + sinfo->out_of_blocks = TRUE; + } + /* Complain that there's not enough data */ + WARNMS(sinfo->cinfo, JWRN_GIF_ENDCODE); + /* Pad data with 0's */ + return 0; /* fake something usable */ + } + + /* Got normal raw byte or LZW symbol */ + incode = code; /* save for a moment */ + + if (code >= sinfo->max_code) { /* special case for not-yet-defined symbol */ + /* code == max_code is OK; anything bigger is bad data */ + if (code > sinfo->max_code) { + WARNMS(sinfo->cinfo, JWRN_GIF_BADDATA); + incode = 0; /* prevent creation of loops in symbol table */ + } + /* this symbol will be defined as oldcode/firstcode */ + *(sinfo->sp++) = (UINT8)sinfo->firstcode; + code = sinfo->oldcode; + } + + /* If it's a symbol, expand it into the stack */ + while (code >= sinfo->clear_code) { + *(sinfo->sp++) = sinfo->symbol_tail[code]; /* tail is a byte value */ + code = sinfo->symbol_head[code]; /* head is another LZW symbol */ + } + /* At this point code just represents a raw byte */ + sinfo->firstcode = code; /* save for possible future use */ + + /* If there's room in table... */ + if ((code = sinfo->max_code) < LZW_TABLE_SIZE) { + /* Define a new symbol = prev sym + head of this sym's expansion */ + sinfo->symbol_head[code] = (UINT16)sinfo->oldcode; + sinfo->symbol_tail[code] = (UINT8)sinfo->firstcode; + sinfo->max_code++; + /* Is it time to increase code_size? */ + if (sinfo->max_code >= sinfo->limit_code && + sinfo->code_size < MAX_LZW_BITS) { + sinfo->code_size++; + sinfo->limit_code <<= 1; /* keep equal to 2^code_size */ + } + } + + sinfo->oldcode = incode; /* save last input symbol for future use */ + return sinfo->firstcode; /* return first byte of symbol's expansion */ +} + + +LOCAL(void) +ReadColorMap(gif_source_ptr sinfo, int cmaplen, _JSAMPARRAY cmap) +/* Read a GIF colormap */ +{ + int i, gray = 1; + + for (i = 0; i < cmaplen; i++) { +#if BITS_IN_JSAMPLE == 8 +#define UPSCALE(x) (x) +#else +#define UPSCALE(x) ((x) << (BITS_IN_JSAMPLE - 8)) +#endif + cmap[CM_RED][i] = (_JSAMPLE)UPSCALE(ReadByte(sinfo)); + cmap[CM_GREEN][i] = (_JSAMPLE)UPSCALE(ReadByte(sinfo)); + cmap[CM_BLUE][i] = (_JSAMPLE)UPSCALE(ReadByte(sinfo)); + if (cmap[CM_RED][i] != cmap[CM_GREEN][i] || + cmap[CM_GREEN][i] != cmap[CM_BLUE][i]) + gray = 0; + } + + if (sinfo->cinfo->in_color_space == JCS_RGB && gray) { + sinfo->cinfo->in_color_space = JCS_GRAYSCALE; + sinfo->cinfo->input_components = 1; + } +} + + +LOCAL(void) +DoExtension(gif_source_ptr sinfo) +/* Process an extension block */ +/* Currently we ignore 'em all */ +{ + int extlabel; + + /* Read extension label byte */ + extlabel = ReadByte(sinfo); + TRACEMS1(sinfo->cinfo, 1, JTRC_GIF_EXTENSION, extlabel); + /* Skip the data block(s) associated with the extension */ + SkipDataBlocks(sinfo); +} + + +/* + * Read the file header; return image size and component count. + */ + +METHODDEF(void) +start_input_gif(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + gif_source_ptr source = (gif_source_ptr)sinfo; + U_CHAR hdrbuf[10]; /* workspace for reading control blocks */ + unsigned int width, height; /* image dimensions */ + int colormaplen, aspectRatio; + int c; + + /* Read and verify GIF Header */ + if (!ReadOK(source->pub.input_file, hdrbuf, 6)) + ERREXIT(cinfo, JERR_GIF_NOT); + if (hdrbuf[0] != 'G' || hdrbuf[1] != 'I' || hdrbuf[2] != 'F') + ERREXIT(cinfo, JERR_GIF_NOT); + /* Check for expected version numbers. + * If unknown version, give warning and try to process anyway; + * this is per recommendation in GIF89a standard. + */ + if ((hdrbuf[3] != '8' || hdrbuf[4] != '7' || hdrbuf[5] != 'a') && + (hdrbuf[3] != '8' || hdrbuf[4] != '9' || hdrbuf[5] != 'a')) + TRACEMS3(cinfo, 1, JTRC_GIF_BADVERSION, hdrbuf[3], hdrbuf[4], hdrbuf[5]); + + /* Read and decipher Logical Screen Descriptor */ + if (!ReadOK(source->pub.input_file, hdrbuf, 7)) + ERREXIT(cinfo, JERR_INPUT_EOF); + width = LM_to_uint(hdrbuf, 0); + height = LM_to_uint(hdrbuf, 2); + if (width == 0 || height == 0) + ERREXIT(cinfo, JERR_GIF_EMPTY); + if (sinfo->max_pixels && + (unsigned long long)width * height > sinfo->max_pixels) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, sinfo->max_pixels); + /* we ignore the color resolution, sort flag, and background color index */ + aspectRatio = UCH(hdrbuf[6]); + if (aspectRatio != 0 && aspectRatio != 49) + TRACEMS(cinfo, 1, JTRC_GIF_NONSQUARE); + + /* Allocate space to store the colormap */ + source->colormap = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)MAXCOLORMAPSIZE, + (JDIMENSION)NUMCOLORS); + colormaplen = 0; /* indicate initialization */ + + /* Read global colormap if header indicates it is present */ + if (BitSet(hdrbuf[4], COLORMAPFLAG)) { + colormaplen = 2 << (hdrbuf[4] & 0x07); + ReadColorMap(source, colormaplen, source->colormap); + } + + /* Scan until we reach start of desired image. + * We don't currently support skipping images, but could add it easily. + */ + for (;;) { + c = ReadByte(source); + + if (c == ';') /* GIF terminator?? */ + ERREXIT(cinfo, JERR_GIF_IMAGENOTFOUND); + + if (c == '!') { /* Extension */ + DoExtension(source); + continue; + } + + if (c != ',') { /* Not an image separator? */ + WARNMS1(cinfo, JWRN_GIF_CHAR, c); + continue; + } + + /* Read and decipher Local Image Descriptor */ + if (!ReadOK(source->pub.input_file, hdrbuf, 9)) + ERREXIT(cinfo, JERR_INPUT_EOF); + /* we ignore top/left position info, also sort flag */ + width = LM_to_uint(hdrbuf, 4); + height = LM_to_uint(hdrbuf, 6); + if (width == 0 || height == 0) + ERREXIT(cinfo, JERR_GIF_EMPTY); + if (sinfo->max_pixels && + (unsigned long long)width * height > sinfo->max_pixels) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, sinfo->max_pixels); + source->is_interlaced = (BitSet(hdrbuf[8], INTERLACE) != 0); + + /* Read local colormap if header indicates it is present */ + /* Note: if we wanted to support skipping images, */ + /* we'd need to skip rather than read colormap for ignored images */ + if (BitSet(hdrbuf[8], COLORMAPFLAG)) { + colormaplen = 2 << (hdrbuf[8] & 0x07); + ReadColorMap(source, colormaplen, source->colormap); + } + + source->input_code_size = ReadByte(source); /* get min-code-size byte */ + if (source->input_code_size < 2 || source->input_code_size > 8) + ERREXIT1(cinfo, JERR_GIF_CODESIZE, source->input_code_size); + + /* Reached desired image, so break out of loop */ + /* If we wanted to skip this image, */ + /* we'd call SkipDataBlocks and then continue the loop */ + break; + } + + /* Prepare to read selected image: first initialize LZW decompressor */ + source->symbol_head = (UINT16 *) + (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE, + LZW_TABLE_SIZE * sizeof(UINT16)); + source->symbol_tail = (UINT8 *) + (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE, + LZW_TABLE_SIZE * sizeof(UINT8)); + source->symbol_stack = (UINT8 *) + (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE, + LZW_TABLE_SIZE * sizeof(UINT8)); + InitLZWCode(source); + + /* + * If image is interlaced, we read it into a full-size sample array, + * decompressing as we go; then get_interlaced_row selects rows from the + * sample array in the proper order. + */ + if (source->is_interlaced) { + /* We request the virtual array now, but can't access it until virtual + * arrays have been allocated. Hence, the actual work of reading the + * image is postponed until the first call to get_pixel_rows. + */ + source->interlaced_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION)width, (JDIMENSION)height, (JDIMENSION)1); + if (cinfo->progress != NULL) { + cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress; + progress->total_extra_passes++; /* count file input as separate pass */ + } + source->pub.get_pixel_rows = load_interlaced_image; + } else { + source->pub.get_pixel_rows = get_pixel_rows; + } + + if (cinfo->in_color_space != JCS_GRAYSCALE) { + cinfo->in_color_space = JCS_RGB; + cinfo->input_components = NUMCOLORS; + } + + /* Create compressor input buffer. */ + source->pub._buffer = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, + (JDIMENSION)width * cinfo->input_components, (JDIMENSION)1); + source->pub.buffer_height = 1; + + /* Pad colormap for safety. */ + for (c = colormaplen; c < source->clear_code; c++) { + source->colormap[CM_RED][c] = + source->colormap[CM_GREEN][c] = + source->colormap[CM_BLUE][c] = _CENTERJSAMPLE; + } + + /* Return info about the image. */ + cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */ + cinfo->image_width = width; + cinfo->image_height = height; + + TRACEMS3(cinfo, 1, JTRC_GIF, width, height, colormaplen); +} + + +/* + * Read one row of pixels. + * This version is used for noninterlaced GIF images: + * we read directly from the GIF file. + */ + +METHODDEF(JDIMENSION) +get_pixel_rows(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + gif_source_ptr source = (gif_source_ptr)sinfo; + register int c; + register _JSAMPROW ptr; + register JDIMENSION col; + register _JSAMPARRAY colormap = source->colormap; + + ptr = source->pub._buffer[0]; + if (cinfo->in_color_space == JCS_GRAYSCALE) { + for (col = cinfo->image_width; col > 0; col--) { + c = LZWReadByte(source); + *ptr++ = colormap[CM_RED][c]; + } + } else { + for (col = cinfo->image_width; col > 0; col--) { + c = LZWReadByte(source); + *ptr++ = colormap[CM_RED][c]; + *ptr++ = colormap[CM_GREEN][c]; + *ptr++ = colormap[CM_BLUE][c]; + } + } + return 1; +} + + +/* + * Read one row of pixels. + * This version is used for the first call on get_pixel_rows when + * reading an interlaced GIF file: we read the whole image into memory. + */ + +METHODDEF(JDIMENSION) +load_interlaced_image(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + gif_source_ptr source = (gif_source_ptr)sinfo; + register _JSAMPROW sptr; + register JDIMENSION col; + JDIMENSION row; + cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress; + + /* Read the interlaced image into the virtual array we've created. */ + for (row = 0; row < cinfo->image_height; row++) { + if (progress != NULL) { + progress->pub.pass_counter = (long)row; + progress->pub.pass_limit = (long)cinfo->image_height; + (*progress->pub.progress_monitor) ((j_common_ptr)cinfo); + } + sptr = *(_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, source->interlaced_image, row, (JDIMENSION)1, + TRUE); + for (col = cinfo->image_width; col > 0; col--) { + *sptr++ = (_JSAMPLE)LZWReadByte(source); + } + } + if (progress != NULL) + progress->completed_extra_passes++; + + /* Replace method pointer so subsequent calls don't come here. */ + source->pub.get_pixel_rows = get_interlaced_row; + /* Initialize for get_interlaced_row, and perform first call on it. */ + source->cur_row_number = 0; + source->pass2_offset = (cinfo->image_height + 7) / 8; + source->pass3_offset = source->pass2_offset + (cinfo->image_height + 3) / 8; + source->pass4_offset = source->pass3_offset + (cinfo->image_height + 1) / 4; + + return get_interlaced_row(cinfo, sinfo); +} + + +/* + * Read one row of pixels. + * This version is used for interlaced GIF images: + * we read from the virtual array. + */ + +METHODDEF(JDIMENSION) +get_interlaced_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + gif_source_ptr source = (gif_source_ptr)sinfo; + register int c; + register _JSAMPROW sptr, ptr; + register JDIMENSION col; + register _JSAMPARRAY colormap = source->colormap; + JDIMENSION irow; + + /* Figure out which row of interlaced image is needed, and access it. */ + switch ((int)(source->cur_row_number & 7)) { + case 0: /* first-pass row */ + irow = source->cur_row_number >> 3; + break; + case 4: /* second-pass row */ + irow = (source->cur_row_number >> 3) + source->pass2_offset; + break; + case 2: /* third-pass row */ + case 6: + irow = (source->cur_row_number >> 2) + source->pass3_offset; + break; + default: /* fourth-pass row */ + irow = (source->cur_row_number >> 1) + source->pass4_offset; + } + sptr = *(_JSAMPARRAY)(*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, source->interlaced_image, irow, (JDIMENSION)1, + FALSE); + /* Scan the row, expand colormap, and output */ + ptr = source->pub._buffer[0]; + if (cinfo->in_color_space == JCS_GRAYSCALE) { + for (col = cinfo->image_width; col > 0; col--) { + c = *sptr++; + *ptr++ = colormap[CM_RED][c]; + } + } else { + for (col = cinfo->image_width; col > 0; col--) { + c = *sptr++; + *ptr++ = colormap[CM_RED][c]; + *ptr++ = colormap[CM_GREEN][c]; + *ptr++ = colormap[CM_BLUE][c]; + } + } + source->cur_row_number++; /* for next time */ + return 1; +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_input_gif(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + /* no work */ +} + + +/* + * The module selection routine for GIF format input. + */ + +GLOBAL(cjpeg_source_ptr) +_jinit_read_gif(j_compress_ptr cinfo) +{ + gif_source_ptr source; + + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Create module interface object */ + source = (gif_source_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + sizeof(gif_source_struct)); + source->cinfo = cinfo; /* make back link for subroutines */ + /* Fill in method ptrs, except get_pixel_rows which start_input sets */ + source->pub.start_input = start_input_gif; + source->pub.finish_input = finish_input_gif; + source->pub.max_pixels = 0; + + return (cjpeg_source_ptr)source; +} + +#endif /* defined(GIF_SUPPORTED) && + (BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED)) */ diff --git a/3rdparty/libjpeg-turbo/src/rdjpgcom.c b/3rdparty/libjpeg-turbo/src/rdjpgcom.c new file mode 100644 index 000000000000..d9a6f85a38c9 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/rdjpgcom.c @@ -0,0 +1,493 @@ +/* + * rdjpgcom.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 2009 by Bill Allombert, Guido Vollbeding. + * libjpeg-turbo Modifications: + * Copyright (C) 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains a very simple stand-alone application that displays + * the text in COM (comment) markers in a JFIF file. + * This may be useful as an example of the minimum logic needed to parse + * JPEG markers. + */ + +#ifdef _MSC_VER +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */ +#include "jinclude.h" /* get auto-config symbols, */ + +#include /* Bill Allombert: use locale for isprint */ +#include /* to declare isupper(), tolower() */ +#ifdef USE_SETMODE +#include /* to declare setmode()'s parameter macros */ +/* If you have setmode() but not , just delete this line: */ +#include /* to declare setmode() */ +#endif + +#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ +#define READ_BINARY "r" +#else +#define READ_BINARY "rb" +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif + + +/* + * These macros are used to read the input file. + * To reuse this code in another application, you might need to change these. + */ + +static FILE *infile; /* input JPEG file */ + +/* Return next input byte, or EOF if no more */ +#define NEXTBYTE() getc(infile) + + +/* Error exit handler */ +#define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE)) + + +/* Read one byte, testing for EOF */ +static int +read_1_byte(void) +{ + int c; + + c = NEXTBYTE(); + if (c == EOF) + ERREXIT("Premature EOF in JPEG file"); + return c; +} + +/* Read 2 bytes, convert to unsigned int */ +/* All 2-byte quantities in JPEG markers are MSB first */ +static unsigned int +read_2_bytes(void) +{ + int c1, c2; + + c1 = NEXTBYTE(); + if (c1 == EOF) + ERREXIT("Premature EOF in JPEG file"); + c2 = NEXTBYTE(); + if (c2 == EOF) + ERREXIT("Premature EOF in JPEG file"); + return (((unsigned int)c1) << 8) + ((unsigned int)c2); +} + + +/* + * JPEG markers consist of one or more 0xFF bytes, followed by a marker + * code byte (which is not an FF). Here are the marker codes of interest + * in this program. (See jdmarker.c for a more complete list.) + */ + +#define M_SOF0 0xC0 /* Start Of Frame N */ +#define M_SOF1 0xC1 /* N indicates which compression process */ +#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */ +#define M_SOF3 0xC3 +#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */ +#define M_SOF6 0xC6 +#define M_SOF7 0xC7 +#define M_SOF9 0xC9 +#define M_SOF10 0xCA +#define M_SOF11 0xCB +#define M_SOF13 0xCD +#define M_SOF14 0xCE +#define M_SOF15 0xCF +#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */ +#define M_EOI 0xD9 /* End Of Image (end of datastream) */ +#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ +#define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */ +#define M_COM 0xFE /* COMment */ + + +/* + * Find the next JPEG marker and return its marker code. + * We expect at least one FF byte, possibly more if the compressor used FFs + * to pad the file. + * There could also be non-FF garbage between markers. The treatment of such + * garbage is unspecified; we choose to skip over it but emit a warning msg. + * NB: this routine must not be used after seeing SOS marker, since it will + * not deal correctly with FF/00 sequences in the compressed image data... + */ + +static int +next_marker(void) +{ + int c; + int discarded_bytes = 0; + + /* Find 0xFF byte; count and skip any non-FFs. */ + c = read_1_byte(); + while (c != 0xFF) { + discarded_bytes++; + c = read_1_byte(); + } + /* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs + * are legal as pad bytes, so don't count them in discarded_bytes. + */ + do { + c = read_1_byte(); + } while (c == 0xFF); + + if (discarded_bytes != 0) { + fprintf(stderr, "Warning: garbage data found in JPEG file\n"); + } + + return c; +} + + +/* + * Read the initial marker, which should be SOI. + * For a JFIF file, the first two bytes of the file should be literally + * 0xFF M_SOI. To be more general, we could use next_marker, but if the + * input file weren't actually JPEG at all, next_marker might read the whole + * file and then return a misleading error message... + */ + +static int +first_marker(void) +{ + int c1, c2; + + c1 = NEXTBYTE(); + c2 = NEXTBYTE(); + if (c1 != 0xFF || c2 != M_SOI) + ERREXIT("Not a JPEG file"); + return c2; +} + + +/* + * Most types of marker are followed by a variable-length parameter segment. + * This routine skips over the parameters for any marker we don't otherwise + * want to process. + * Note that we MUST skip the parameter segment explicitly in order not to + * be fooled by 0xFF bytes that might appear within the parameter segment; + * such bytes do NOT introduce new markers. + */ + +static void +skip_variable(void) +/* Skip over an unknown or uninteresting variable-length marker */ +{ + unsigned int length; + + /* Get the marker parameter length count */ + length = read_2_bytes(); + /* Length includes itself, so must be at least 2 */ + if (length < 2) + ERREXIT("Erroneous JPEG marker length"); + length -= 2; + /* Skip over the remaining bytes */ + while (length > 0) { + (void)read_1_byte(); + length--; + } +} + + +/* + * Process a COM marker. + * We want to print out the marker contents as legible text; + * we must guard against non-text junk and varying newline representations. + */ + +static void +process_COM(int raw) +{ + unsigned int length; + int ch; + int lastch = 0; + + /* Bill Allombert: set locale properly for isprint */ + setlocale(LC_CTYPE, ""); + + /* Get the marker parameter length count */ + length = read_2_bytes(); + /* Length includes itself, so must be at least 2 */ + if (length < 2) + ERREXIT("Erroneous JPEG marker length"); + length -= 2; + + while (length > 0) { + ch = read_1_byte(); + if (raw) { + putc(ch, stdout); + /* Emit the character in a readable form. + * Nonprintables are converted to \nnn form, + * while \ is converted to \\. + * Newlines in CR, CR/LF, or LF form will be printed as one newline. + */ + } else if (ch == '\r') { + printf("\n"); + } else if (ch == '\n') { + if (lastch != '\r') + printf("\n"); + } else if (ch == '\\') { + printf("\\\\"); + } else if (isprint(ch)) { + putc(ch, stdout); + } else { + printf("\\%03o", (unsigned int)ch); + } + lastch = ch; + length--; + } + printf("\n"); + + /* Bill Allombert: revert to C locale */ + setlocale(LC_CTYPE, "C"); +} + + +/* + * Process a SOFn marker. + * This code is only needed if you want to know the image dimensions... + */ + +static void +process_SOFn(int marker) +{ + unsigned int length; + unsigned int image_height, image_width; + int data_precision, num_components; + const char *process; + int ci; + + length = read_2_bytes(); /* usual parameter length count */ + + data_precision = read_1_byte(); + image_height = read_2_bytes(); + image_width = read_2_bytes(); + num_components = read_1_byte(); + + switch (marker) { + case M_SOF0: process = "Baseline"; break; + case M_SOF1: process = "Extended sequential"; break; + case M_SOF2: process = "Progressive"; break; + case M_SOF3: process = "Lossless"; break; + case M_SOF5: process = "Differential sequential"; break; + case M_SOF6: process = "Differential progressive"; break; + case M_SOF7: process = "Differential lossless"; break; + case M_SOF9: process = "Extended sequential, arithmetic coding"; break; + case M_SOF10: process = "Progressive, arithmetic coding"; break; + case M_SOF11: process = "Lossless, arithmetic coding"; break; + case M_SOF13: process = "Differential sequential, arithmetic coding"; break; + case M_SOF14: + process = "Differential progressive, arithmetic coding"; break; + case M_SOF15: process = "Differential lossless, arithmetic coding"; break; + default: process = "Unknown"; break; + } + + printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n", + image_width, image_height, num_components, data_precision); + printf("JPEG process: %s\n", process); + + if (length != (unsigned int)(8 + num_components * 3)) + ERREXIT("Bogus SOF marker length"); + + for (ci = 0; ci < num_components; ci++) { + (void)read_1_byte(); /* Component ID code */ + (void)read_1_byte(); /* H, V sampling factors */ + (void)read_1_byte(); /* Quantization table number */ + } +} + + +/* + * Parse the marker stream until SOS or EOI is seen; + * display any COM markers. + * While the companion program wrjpgcom will always insert COM markers before + * SOFn, other implementations might not, so we scan to SOS before stopping. + * If we were only interested in the image dimensions, we would stop at SOFn. + * (Conversely, if we only cared about COM markers, there would be no need + * for special code to handle SOFn; we could treat it like other markers.) + */ + +static int +scan_JPEG_header(int verbose, int raw) +{ + int marker; + + /* Expect SOI at start of file */ + if (first_marker() != M_SOI) + ERREXIT("Expected SOI marker first"); + + /* Scan miscellaneous markers until we reach SOS. */ + for (;;) { + marker = next_marker(); + switch (marker) { + /* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be, + * treated as SOFn. C4 in particular is actually DHT. + */ + case M_SOF0: /* Baseline */ + case M_SOF1: /* Extended sequential, Huffman */ + case M_SOF2: /* Progressive, Huffman */ + case M_SOF3: /* Lossless, Huffman */ + case M_SOF5: /* Differential sequential, Huffman */ + case M_SOF6: /* Differential progressive, Huffman */ + case M_SOF7: /* Differential lossless, Huffman */ + case M_SOF9: /* Extended sequential, arithmetic */ + case M_SOF10: /* Progressive, arithmetic */ + case M_SOF11: /* Lossless, arithmetic */ + case M_SOF13: /* Differential sequential, arithmetic */ + case M_SOF14: /* Differential progressive, arithmetic */ + case M_SOF15: /* Differential lossless, arithmetic */ + if (verbose) + process_SOFn(marker); + else + skip_variable(); + break; + + case M_SOS: /* stop before hitting compressed data */ + return marker; + + case M_EOI: /* in case it's a tables-only JPEG stream */ + return marker; + + case M_COM: + process_COM(raw); + break; + + case M_APP12: + /* Some digital camera makers put useful textual information into + * APP12 markers, so we print those out too when in -verbose mode. + */ + if (verbose) { + printf("APP12 contains:\n"); + process_COM(raw); + } else + skip_variable(); + break; + + default: /* Anything else just gets skipped */ + skip_variable(); /* we assume it has a parameter count... */ + break; + } + } /* end loop */ +} + + +/* Command line parsing code */ + +static const char *progname; /* program name for error messages */ + + +static void +usage(void) +/* complain about bad command line */ +{ + fprintf(stderr, "rdjpgcom displays any textual comments in a JPEG file.\n"); + + fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname); + + fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -raw Display non-printable characters in comments (unsafe)\n"); + fprintf(stderr, " -verbose Also display dimensions of JPEG image\n"); + + exit(EXIT_FAILURE); +} + + +static int +keymatch(char *arg, const char *keyword, int minchars) +/* Case-insensitive matching of (possibly abbreviated) keyword switches. */ +/* keyword is the constant keyword (must be lower case already), */ +/* minchars is length of minimum legal abbreviation. */ +{ + register int ca, ck; + register int nmatched = 0; + + while ((ca = *arg++) != '\0') { + if ((ck = *keyword++) == '\0') + return 0; /* arg longer than keyword, no good */ + if (isupper(ca)) /* force arg to lcase (assume ck is already) */ + ca = tolower(ca); + if (ca != ck) + return 0; /* no good */ + nmatched++; /* count matched characters */ + } + /* reached end of argument; fail if it's too short for unique abbrev */ + if (nmatched < minchars) + return 0; + return 1; /* A-OK */ +} + + +/* + * The main program. + */ + +int +main(int argc, char **argv) +{ + int argn; + char *arg; + int verbose = 0, raw = 0; + + progname = argv[0]; + if (progname == NULL || progname[0] == 0) + progname = "rdjpgcom"; /* in case C library doesn't provide it */ + + /* Parse switches, if any */ + for (argn = 1; argn < argc; argn++) { + arg = argv[argn]; + if (arg[0] != '-') + break; /* not switch, must be file name */ + arg++; /* advance over '-' */ + if (keymatch(arg, "verbose", 1)) { + verbose++; + } else if (keymatch(arg, "raw", 1)) { + raw = 1; + } else + usage(); + } + + /* Open the input file. */ + /* Unix style: expect zero or one file name */ + if (argn < argc - 1) { + fprintf(stderr, "%s: only one input file\n", progname); + usage(); + } + if (argn < argc) { + if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); + exit(EXIT_FAILURE); + } + } else { + /* default input file is stdin */ +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdin), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open stdin\n", progname); + exit(EXIT_FAILURE); + } +#else + infile = stdin; +#endif + } + + /* Scan the JPEG headers. */ + (void)scan_JPEG_header(verbose, raw); + + /* All done. */ + exit(EXIT_SUCCESS); + return 0; /* suppress no-return-value warnings */ +} diff --git a/3rdparty/libjpeg-turbo/src/rdppm.c b/3rdparty/libjpeg-turbo/src/rdppm.c new file mode 100644 index 000000000000..84e26f7b3f56 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/rdppm.c @@ -0,0 +1,890 @@ +/* + * rdppm.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2009 by Bill Allombert, Guido Vollbeding. + * libjpeg-turbo Modifications: + * Copyright (C) 2015-2017, 2020-2023, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains routines to read input images in PPM/PGM format. + * The extended 2-byte-per-sample raw PPM/PGM formats are supported. + * The PBMPLUS library is NOT required to compile this software + * (but it is highly useful as a set of PPM image manipulation programs). + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume input from + * an ordinary stdio stream. They further assume that reading begins + * at the start of the file; start_input may need work if the + * user interface has already read some data (e.g., to determine that + * the file is indeed PPM format). + */ + +#include "cmyk.h" +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#if defined(PPM_SUPPORTED) && \ + (BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED)) + + +/* Portions of this code are based on the PBMPLUS library, which is: +** +** Copyright (C) 1988 by Jef Poskanzer. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +*/ + + +/* Macros to deal with unsigned chars as efficiently as compiler allows */ + +typedef unsigned char U_CHAR; +#define UCH(x) ((int)(x)) + + +#define ReadOK(file, buffer, len) \ + (fread(buffer, 1, len, file) == ((size_t)(len))) + +static int alpha_index[JPEG_NUMCS] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1 +}; + + +/* Private version of data source object */ + +typedef struct { + struct cjpeg_source_struct pub; /* public fields */ + + /* Usually these two pointers point to the same place: */ + U_CHAR *iobuffer; /* fread's I/O buffer */ + _JSAMPROW pixrow; /* compressor input buffer */ + size_t buffer_width; /* width of I/O buffer */ + _JSAMPLE *rescale; /* => maxval-remapping array, or NULL */ + unsigned int maxval; +} ppm_source_struct; + +typedef ppm_source_struct *ppm_source_ptr; + + +LOCAL(int) +pbm_getc(FILE *infile) +/* Read next char, skipping over any comments */ +/* A comment/newline sequence is returned as a newline */ +{ + register int ch; + + ch = getc(infile); + if (ch == '#') { + do { + ch = getc(infile); + } while (ch != '\n' && ch != EOF); + } + return ch; +} + + +LOCAL(unsigned int) +read_pbm_integer(j_compress_ptr cinfo, FILE *infile, unsigned int maxval) +/* Read an unsigned decimal integer from the PPM file */ +/* Swallows one trailing character after the integer */ +/* Note that on a 16-bit-int machine, only values up to 64k can be read. */ +/* This should not be a problem in practice. */ +{ + register int ch; + register unsigned int val; + + /* Skip any leading whitespace */ + do { + ch = pbm_getc(infile); + if (ch == EOF) + ERREXIT(cinfo, JERR_INPUT_EOF); + } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); + + if (ch < '0' || ch > '9') + ERREXIT(cinfo, JERR_PPM_NONNUMERIC); + + val = ch - '0'; + while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') { + val *= 10; + val += ch - '0'; + if (val > maxval) + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); + } + + return val; +} + + +/* + * Read one row of pixels. + * + * We provide several different versions depending on input file format. + * In all cases, input is scaled to the size of _JSAMPLE. + * + * A really fast path is provided for reading byte/sample raw files with + * maxval = _MAXJSAMPLE, which is the normal case for 8-bit data. + */ + + +METHODDEF(JDIMENSION) +get_text_gray_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading text-format PGM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + FILE *infile = source->pub.input_file; + register _JSAMPROW ptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + unsigned int maxval = source->maxval; + + ptr = source->pub._buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + *ptr++ = rescale[read_pbm_integer(cinfo, infile, maxval)]; + } + return 1; +} + + +#define GRAY_RGB_READ_LOOP(read_op, alpha_set_op) { \ + for (col = cinfo->image_width; col > 0; col--) { \ + ptr[rindex] = ptr[gindex] = ptr[bindex] = read_op; \ + alpha_set_op \ + ptr += ps; \ + } \ +} + +METHODDEF(JDIMENSION) +get_text_gray_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading text-format PGM files with any maxval and + converting to extended RGB */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + FILE *infile = source->pub.input_file; + register _JSAMPROW ptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + unsigned int maxval = source->maxval; + register int rindex = rgb_red[cinfo->in_color_space]; + register int gindex = rgb_green[cinfo->in_color_space]; + register int bindex = rgb_blue[cinfo->in_color_space]; + register int aindex = alpha_index[cinfo->in_color_space]; + register int ps = rgb_pixelsize[cinfo->in_color_space]; + + ptr = source->pub._buffer[0]; + if (maxval == _MAXJSAMPLE) { + if (aindex >= 0) + GRAY_RGB_READ_LOOP((_JSAMPLE)read_pbm_integer(cinfo, infile, maxval), + ptr[aindex] = _MAXJSAMPLE;) + else + GRAY_RGB_READ_LOOP((_JSAMPLE)read_pbm_integer(cinfo, infile, maxval), {}) + } else { + if (aindex >= 0) + GRAY_RGB_READ_LOOP(rescale[read_pbm_integer(cinfo, infile, maxval)], + ptr[aindex] = _MAXJSAMPLE;) + else + GRAY_RGB_READ_LOOP(rescale[read_pbm_integer(cinfo, infile, maxval)], {}) + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_text_gray_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading text-format PGM files with any maxval and + converting to CMYK */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + FILE *infile = source->pub.input_file; + register _JSAMPROW ptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + unsigned int maxval = source->maxval; + + ptr = source->pub._buffer[0]; + if (maxval == _MAXJSAMPLE) { + for (col = cinfo->image_width; col > 0; col--) { + _JSAMPLE gray = (_JSAMPLE)read_pbm_integer(cinfo, infile, maxval); + rgb_to_cmyk(gray, gray, gray, ptr, ptr + 1, ptr + 2, ptr + 3); + ptr += 4; + } + } else { + for (col = cinfo->image_width; col > 0; col--) { + _JSAMPLE gray = rescale[read_pbm_integer(cinfo, infile, maxval)]; + rgb_to_cmyk(gray, gray, gray, ptr, ptr + 1, ptr + 2, ptr + 3); + ptr += 4; + } + } + return 1; +} + + +#define RGB_READ_LOOP(read_op, alpha_set_op) { \ + for (col = cinfo->image_width; col > 0; col--) { \ + ptr[rindex] = read_op; \ + ptr[gindex] = read_op; \ + ptr[bindex] = read_op; \ + alpha_set_op \ + ptr += ps; \ + } \ +} + +METHODDEF(JDIMENSION) +get_text_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading text-format PPM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + FILE *infile = source->pub.input_file; + register _JSAMPROW ptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + unsigned int maxval = source->maxval; + register int rindex = rgb_red[cinfo->in_color_space]; + register int gindex = rgb_green[cinfo->in_color_space]; + register int bindex = rgb_blue[cinfo->in_color_space]; + register int aindex = alpha_index[cinfo->in_color_space]; + register int ps = rgb_pixelsize[cinfo->in_color_space]; + + ptr = source->pub._buffer[0]; + if (maxval == _MAXJSAMPLE) { + if (aindex >= 0) + RGB_READ_LOOP((_JSAMPLE)read_pbm_integer(cinfo, infile, maxval), + ptr[aindex] = _MAXJSAMPLE;) + else + RGB_READ_LOOP((_JSAMPLE)read_pbm_integer(cinfo, infile, maxval), {}) + } else { + if (aindex >= 0) + RGB_READ_LOOP(rescale[read_pbm_integer(cinfo, infile, maxval)], + ptr[aindex] = _MAXJSAMPLE;) + else + RGB_READ_LOOP(rescale[read_pbm_integer(cinfo, infile, maxval)], {}) + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_text_rgb_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading text-format PPM files with any maxval and + converting to CMYK */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + FILE *infile = source->pub.input_file; + register _JSAMPROW ptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + unsigned int maxval = source->maxval; + + ptr = source->pub._buffer[0]; + if (maxval == _MAXJSAMPLE) { + for (col = cinfo->image_width; col > 0; col--) { + _JSAMPLE r = (_JSAMPLE)read_pbm_integer(cinfo, infile, maxval); + _JSAMPLE g = (_JSAMPLE)read_pbm_integer(cinfo, infile, maxval); + _JSAMPLE b = (_JSAMPLE)read_pbm_integer(cinfo, infile, maxval); + rgb_to_cmyk(r, g, b, ptr, ptr + 1, ptr + 2, ptr + 3); + ptr += 4; + } + } else { + for (col = cinfo->image_width; col > 0; col--) { + _JSAMPLE r = rescale[read_pbm_integer(cinfo, infile, maxval)]; + _JSAMPLE g = rescale[read_pbm_integer(cinfo, infile, maxval)]; + _JSAMPLE b = rescale[read_pbm_integer(cinfo, infile, maxval)]; + rgb_to_cmyk(r, g, b, ptr, ptr + 1, ptr + 2, ptr + 3); + ptr += 4; + } + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_scaled_gray_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-byte-format PGM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + register _JSAMPROW ptr; + register U_CHAR *bufferptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + + if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub._buffer[0]; + bufferptr = source->iobuffer; + for (col = cinfo->image_width; col > 0; col--) { + *ptr++ = rescale[UCH(*bufferptr++)]; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_gray_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-byte-format PGM files with any maxval + and converting to extended RGB */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + register _JSAMPROW ptr; + register U_CHAR *bufferptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + unsigned int maxval = source->maxval; + register int rindex = rgb_red[cinfo->in_color_space]; + register int gindex = rgb_green[cinfo->in_color_space]; + register int bindex = rgb_blue[cinfo->in_color_space]; + register int aindex = alpha_index[cinfo->in_color_space]; + register int ps = rgb_pixelsize[cinfo->in_color_space]; + + if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub._buffer[0]; + bufferptr = source->iobuffer; + if (maxval == _MAXJSAMPLE) { + if (aindex >= 0) + GRAY_RGB_READ_LOOP(*bufferptr++, ptr[aindex] = _MAXJSAMPLE;) + else + GRAY_RGB_READ_LOOP(*bufferptr++, {}) + } else { + if (aindex >= 0) + GRAY_RGB_READ_LOOP(rescale[UCH(*bufferptr++)], + ptr[aindex] = _MAXJSAMPLE;) + else + GRAY_RGB_READ_LOOP(rescale[UCH(*bufferptr++)], {}) + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_gray_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-byte-format PGM files with any maxval + and converting to CMYK */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + register _JSAMPROW ptr; + register U_CHAR *bufferptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + unsigned int maxval = source->maxval; + + if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub._buffer[0]; + bufferptr = source->iobuffer; + if (maxval == _MAXJSAMPLE) { + for (col = cinfo->image_width; col > 0; col--) { + _JSAMPLE gray = *bufferptr++; + rgb_to_cmyk(gray, gray, gray, ptr, ptr + 1, ptr + 2, ptr + 3); + ptr += 4; + } + } else { + for (col = cinfo->image_width; col > 0; col--) { + _JSAMPLE gray = rescale[UCH(*bufferptr++)]; + rgb_to_cmyk(gray, gray, gray, ptr, ptr + 1, ptr + 2, ptr + 3); + ptr += 4; + } + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-byte-format PPM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + register _JSAMPROW ptr; + register U_CHAR *bufferptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + unsigned int maxval = source->maxval; + register int rindex = rgb_red[cinfo->in_color_space]; + register int gindex = rgb_green[cinfo->in_color_space]; + register int bindex = rgb_blue[cinfo->in_color_space]; + register int aindex = alpha_index[cinfo->in_color_space]; + register int ps = rgb_pixelsize[cinfo->in_color_space]; + + if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub._buffer[0]; + bufferptr = source->iobuffer; + if (maxval == _MAXJSAMPLE) { + if (aindex >= 0) + RGB_READ_LOOP(*bufferptr++, ptr[aindex] = _MAXJSAMPLE;) + else + RGB_READ_LOOP(*bufferptr++, {}) + } else { + if (aindex >= 0) + RGB_READ_LOOP(rescale[UCH(*bufferptr++)], ptr[aindex] = _MAXJSAMPLE;) + else + RGB_READ_LOOP(rescale[UCH(*bufferptr++)], {}) + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_rgb_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-byte-format PPM files with any maxval and + converting to CMYK */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + register _JSAMPROW ptr; + register U_CHAR *bufferptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + unsigned int maxval = source->maxval; + + if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub._buffer[0]; + bufferptr = source->iobuffer; + if (maxval == _MAXJSAMPLE) { + for (col = cinfo->image_width; col > 0; col--) { + _JSAMPLE r = *bufferptr++; + _JSAMPLE g = *bufferptr++; + _JSAMPLE b = *bufferptr++; + rgb_to_cmyk(r, g, b, ptr, ptr + 1, ptr + 2, ptr + 3); + ptr += 4; + } + } else { + for (col = cinfo->image_width; col > 0; col--) { + _JSAMPLE r = rescale[UCH(*bufferptr++)]; + _JSAMPLE g = rescale[UCH(*bufferptr++)]; + _JSAMPLE b = rescale[UCH(*bufferptr++)]; + rgb_to_cmyk(r, g, b, ptr, ptr + 1, ptr + 2, ptr + 3); + ptr += 4; + } + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_raw_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-byte-format files with maxval = _MAXJSAMPLE. + * In this case we just read right into the _JSAMPLE buffer! + * Note that same code works for PPM and PGM files. + */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + + if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + return 1; +} + + +METHODDEF(JDIMENSION) +get_word_gray_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-word-format PGM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + register _JSAMPROW ptr; + register U_CHAR *bufferptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + unsigned int maxval = source->maxval; + + if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub._buffer[0]; + bufferptr = source->iobuffer; + for (col = cinfo->image_width; col > 0; col--) { + register unsigned int temp; + temp = UCH(*bufferptr++) << 8; + temp |= UCH(*bufferptr++); + if (temp > maxval) + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); + *ptr++ = rescale[temp]; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_word_gray_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-word-format PGM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + register _JSAMPROW ptr; + register U_CHAR *bufferptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + unsigned int maxval = source->maxval; + register int rindex = rgb_red[cinfo->in_color_space]; + register int gindex = rgb_green[cinfo->in_color_space]; + register int bindex = rgb_blue[cinfo->in_color_space]; + register int aindex = alpha_index[cinfo->in_color_space]; + register int ps = rgb_pixelsize[cinfo->in_color_space]; + + if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub._buffer[0]; + bufferptr = source->iobuffer; + for (col = cinfo->image_width; col > 0; col--) { + register unsigned int temp; + temp = UCH(*bufferptr++) << 8; + temp |= UCH(*bufferptr++); + if (temp > maxval) + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); + ptr[rindex] = ptr[gindex] = ptr[bindex] = rescale[temp]; + if (aindex >= 0) + ptr[aindex] = _MAXJSAMPLE; + ptr += ps; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_word_gray_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-word-format PGM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + register _JSAMPROW ptr; + register U_CHAR *bufferptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + unsigned int maxval = source->maxval; + + if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub._buffer[0]; + bufferptr = source->iobuffer; + for (col = cinfo->image_width; col > 0; col--) { + register unsigned int gray; + gray = UCH(*bufferptr++) << 8; + gray |= UCH(*bufferptr++); + if (gray > maxval) + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); + rgb_to_cmyk(rescale[gray], rescale[gray], rescale[gray], ptr, ptr + 1, + ptr + 2, ptr + 3); + ptr += 4; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_word_rgb_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-word-format PPM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + register _JSAMPROW ptr; + register U_CHAR *bufferptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + unsigned int maxval = source->maxval; + register int rindex = rgb_red[cinfo->in_color_space]; + register int gindex = rgb_green[cinfo->in_color_space]; + register int bindex = rgb_blue[cinfo->in_color_space]; + register int aindex = alpha_index[cinfo->in_color_space]; + register int ps = rgb_pixelsize[cinfo->in_color_space]; + + if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub._buffer[0]; + bufferptr = source->iobuffer; + for (col = cinfo->image_width; col > 0; col--) { + register unsigned int temp; + temp = UCH(*bufferptr++) << 8; + temp |= UCH(*bufferptr++); + if (temp > maxval) + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); + ptr[rindex] = rescale[temp]; + temp = UCH(*bufferptr++) << 8; + temp |= UCH(*bufferptr++); + if (temp > maxval) + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); + ptr[gindex] = rescale[temp]; + temp = UCH(*bufferptr++) << 8; + temp |= UCH(*bufferptr++); + if (temp > maxval) + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); + ptr[bindex] = rescale[temp]; + if (aindex >= 0) + ptr[aindex] = _MAXJSAMPLE; + ptr += ps; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_word_rgb_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-word-format PPM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + register _JSAMPROW ptr; + register U_CHAR *bufferptr; + register _JSAMPLE *rescale = source->rescale; + JDIMENSION col; + unsigned int maxval = source->maxval; + + if (!ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub._buffer[0]; + bufferptr = source->iobuffer; + for (col = cinfo->image_width; col > 0; col--) { + register unsigned int r, g, b; + r = UCH(*bufferptr++) << 8; + r |= UCH(*bufferptr++); + if (r > maxval) + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); + g = UCH(*bufferptr++) << 8; + g |= UCH(*bufferptr++); + if (g > maxval) + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); + b = UCH(*bufferptr++) << 8; + b |= UCH(*bufferptr++); + if (b > maxval) + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); + rgb_to_cmyk(rescale[r], rescale[g], rescale[b], ptr, ptr + 1, ptr + 2, + ptr + 3); + ptr += 4; + } + return 1; +} + + +/* + * Read the file header; return image size and component count. + */ + +METHODDEF(void) +start_input_ppm(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + ppm_source_ptr source = (ppm_source_ptr)sinfo; + int c; + unsigned int w, h, maxval; + boolean need_iobuffer, use_raw_buffer, need_rescale; + + if (getc(source->pub.input_file) != 'P') + ERREXIT(cinfo, JERR_PPM_NOT); + + c = getc(source->pub.input_file); /* subformat discriminator character */ + + /* detect unsupported variants (ie, PBM) before trying to read header */ + switch (c) { + case '2': /* it's a text-format PGM file */ + case '3': /* it's a text-format PPM file */ + case '5': /* it's a raw-format PGM file */ + case '6': /* it's a raw-format PPM file */ + break; + default: + ERREXIT(cinfo, JERR_PPM_NOT); + break; + } + + /* fetch the remaining header info */ + w = read_pbm_integer(cinfo, source->pub.input_file, 65535); + h = read_pbm_integer(cinfo, source->pub.input_file, 65535); + maxval = read_pbm_integer(cinfo, source->pub.input_file, 65535); + + if (w <= 0 || h <= 0 || maxval <= 0) /* error check */ + ERREXIT(cinfo, JERR_PPM_NOT); + if (sinfo->max_pixels && (unsigned long long)w * h > sinfo->max_pixels) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, sinfo->max_pixels); + + cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */ + cinfo->image_width = (JDIMENSION)w; + cinfo->image_height = (JDIMENSION)h; + source->maxval = maxval; + + /* initialize flags to most common settings */ + need_iobuffer = TRUE; /* do we need an I/O buffer? */ + use_raw_buffer = FALSE; /* do we map input buffer onto I/O buffer? */ + need_rescale = TRUE; /* do we need a rescale array? */ + + switch (c) { + case '2': /* it's a text-format PGM file */ + if (cinfo->in_color_space == JCS_UNKNOWN || + cinfo->in_color_space == JCS_RGB) + cinfo->in_color_space = JCS_GRAYSCALE; + TRACEMS2(cinfo, 1, JTRC_PGM_TEXT, w, h); + if (cinfo->in_color_space == JCS_GRAYSCALE) + source->pub.get_pixel_rows = get_text_gray_row; + else if (IsExtRGB(cinfo->in_color_space)) + source->pub.get_pixel_rows = get_text_gray_rgb_row; + else if (cinfo->in_color_space == JCS_CMYK) + source->pub.get_pixel_rows = get_text_gray_cmyk_row; + else + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + need_iobuffer = FALSE; + break; + + case '3': /* it's a text-format PPM file */ + if (cinfo->in_color_space == JCS_UNKNOWN) + cinfo->in_color_space = JCS_EXT_RGB; + TRACEMS2(cinfo, 1, JTRC_PPM_TEXT, w, h); + if (IsExtRGB(cinfo->in_color_space)) + source->pub.get_pixel_rows = get_text_rgb_row; + else if (cinfo->in_color_space == JCS_CMYK) + source->pub.get_pixel_rows = get_text_rgb_cmyk_row; + else + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + need_iobuffer = FALSE; + break; + + case '5': /* it's a raw-format PGM file */ + if (cinfo->in_color_space == JCS_UNKNOWN || + cinfo->in_color_space == JCS_RGB) + cinfo->in_color_space = JCS_GRAYSCALE; + TRACEMS2(cinfo, 1, JTRC_PGM, w, h); + if (maxval > 255) { + if (cinfo->in_color_space == JCS_GRAYSCALE) + source->pub.get_pixel_rows = get_word_gray_row; + else if (IsExtRGB(cinfo->in_color_space)) + source->pub.get_pixel_rows = get_word_gray_rgb_row; + else if (cinfo->in_color_space == JCS_CMYK) + source->pub.get_pixel_rows = get_word_gray_cmyk_row; + else + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + } else if (maxval == _MAXJSAMPLE && sizeof(_JSAMPLE) == sizeof(U_CHAR) && + cinfo->in_color_space == JCS_GRAYSCALE) { + source->pub.get_pixel_rows = get_raw_row; + use_raw_buffer = TRUE; + need_rescale = FALSE; + } else { + if (cinfo->in_color_space == JCS_GRAYSCALE) + source->pub.get_pixel_rows = get_scaled_gray_row; + else if (IsExtRGB(cinfo->in_color_space)) + source->pub.get_pixel_rows = get_gray_rgb_row; + else if (cinfo->in_color_space == JCS_CMYK) + source->pub.get_pixel_rows = get_gray_cmyk_row; + else + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + } + break; + + case '6': /* it's a raw-format PPM file */ + if (cinfo->in_color_space == JCS_UNKNOWN) + cinfo->in_color_space = JCS_EXT_RGB; + TRACEMS2(cinfo, 1, JTRC_PPM, w, h); + if (maxval > 255) { + if (IsExtRGB(cinfo->in_color_space)) + source->pub.get_pixel_rows = get_word_rgb_row; + else if (cinfo->in_color_space == JCS_CMYK) + source->pub.get_pixel_rows = get_word_rgb_cmyk_row; + else + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + } else if (maxval == _MAXJSAMPLE && sizeof(_JSAMPLE) == sizeof(U_CHAR) && +#if RGB_RED == 0 && RGB_GREEN == 1 && RGB_BLUE == 2 && RGB_PIXELSIZE == 3 + (cinfo->in_color_space == JCS_EXT_RGB || + cinfo->in_color_space == JCS_RGB)) { +#else + cinfo->in_color_space == JCS_EXT_RGB) { +#endif + source->pub.get_pixel_rows = get_raw_row; + use_raw_buffer = TRUE; + need_rescale = FALSE; + } else { + if (IsExtRGB(cinfo->in_color_space)) + source->pub.get_pixel_rows = get_rgb_row; + else if (cinfo->in_color_space == JCS_CMYK) + source->pub.get_pixel_rows = get_rgb_cmyk_row; + else + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + } + break; + } + + if (IsExtRGB(cinfo->in_color_space)) + cinfo->input_components = rgb_pixelsize[cinfo->in_color_space]; + else if (cinfo->in_color_space == JCS_GRAYSCALE) + cinfo->input_components = 1; + else if (cinfo->in_color_space == JCS_CMYK) + cinfo->input_components = 4; + + /* Allocate space for I/O buffer: 1 or 3 bytes or words/pixel. */ + if (need_iobuffer) { + if (c == '6') + source->buffer_width = (size_t)w * 3 * + ((maxval <= 255) ? sizeof(U_CHAR) : (2 * sizeof(U_CHAR))); + else + source->buffer_width = (size_t)w * + ((maxval <= 255) ? sizeof(U_CHAR) : (2 * sizeof(U_CHAR))); + source->iobuffer = (U_CHAR *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + source->buffer_width); + } + + /* Create compressor input buffer. */ + if (use_raw_buffer) { + /* For unscaled raw-input case, we can just map it onto the I/O buffer. */ + /* Synthesize a _JSAMPARRAY pointer structure */ + source->pixrow = (_JSAMPROW)source->iobuffer; + source->pub._buffer = &source->pixrow; + source->pub.buffer_height = 1; + } else { + /* Need to translate anyway, so make a separate sample buffer. */ + source->pub._buffer = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, + (JDIMENSION)w * cinfo->input_components, (JDIMENSION)1); + source->pub.buffer_height = 1; + } + + /* Compute the rescaling array if required. */ + if (need_rescale) { + long val, half_maxval; + + /* On 16-bit-int machines we have to be careful of maxval = 65535 */ + source->rescale = (_JSAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + (size_t)(((long)MAX(maxval, 255) + 1L) * + sizeof(_JSAMPLE))); + memset(source->rescale, 0, (size_t)(((long)MAX(maxval, 255) + 1L) * + sizeof(_JSAMPLE))); + half_maxval = maxval / 2; + for (val = 0; val <= (long)maxval; val++) { + /* The multiplication here must be done in 32 bits to avoid overflow */ + source->rescale[val] = (_JSAMPLE)((val * _MAXJSAMPLE + half_maxval) / + maxval); + } + } +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_input_ppm(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + /* no work */ +} + + +/* + * The module selection routine for PPM format input. + */ + +GLOBAL(cjpeg_source_ptr) +_jinit_read_ppm(j_compress_ptr cinfo) +{ + ppm_source_ptr source; + + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Create module interface object */ + source = (ppm_source_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + sizeof(ppm_source_struct)); + /* Fill in method ptrs, except get_pixel_rows which start_input sets */ + source->pub.start_input = start_input_ppm; + source->pub.finish_input = finish_input_ppm; + source->pub.max_pixels = 0; + + return (cjpeg_source_ptr)source; +} + +#endif /* defined(PPM_SUPPORTED) && + (BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED)) */ diff --git a/3rdparty/libjpeg-turbo/src/rdswitch.c b/3rdparty/libjpeg-turbo/src/rdswitch.c new file mode 100644 index 000000000000..33449c86ba6f --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/rdswitch.c @@ -0,0 +1,428 @@ +/* + * rdswitch.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1996, Thomas G. Lane. + * libjpeg-turbo Modifications: + * Copyright (C) 2010, 2018, 2022, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains routines to process some of cjpeg's more complicated + * command-line switches. Switches processed here are: + * -qtables file Read quantization tables from text file + * -scans file Read scan script from text file + * -quality N[,N,...] Set quality ratings + * -qslots N[,N,...] Set component quantization table selectors + * -sample HxV[,HxV,...] Set component sampling factors + */ + +#ifdef _MSC_VER +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include /* to declare isdigit(), isspace() */ + + +LOCAL(int) +text_getc(FILE *file) +/* Read next char, skipping over any comments (# to end of line) */ +/* A comment/newline sequence is returned as a newline */ +{ + register int ch; + + ch = getc(file); + if (ch == '#') { + do { + ch = getc(file); + } while (ch != '\n' && ch != EOF); + } + return ch; +} + + +LOCAL(boolean) +read_text_integer(FILE *file, long *result, int *termchar) +/* Read an unsigned decimal integer from a file, store it in result */ +/* Reads one trailing character after the integer; returns it in termchar */ +{ + register int ch; + register long val; + + /* Skip any leading whitespace, detect EOF */ + do { + ch = text_getc(file); + if (ch == EOF) { + *termchar = ch; + return FALSE; + } + } while (isspace(ch)); + + if (!isdigit(ch)) { + *termchar = ch; + return FALSE; + } + + val = ch - '0'; + while ((ch = text_getc(file)) != EOF) { + if (!isdigit(ch)) + break; + val *= 10; + val += ch - '0'; + } + *result = val; + *termchar = ch; + return TRUE; +} + + +#if JPEG_LIB_VERSION < 70 +static int q_scale_factor[NUM_QUANT_TBLS] = { 100, 100, 100, 100 }; +#endif + +GLOBAL(boolean) +read_quant_tables(j_compress_ptr cinfo, char *filename, boolean force_baseline) +/* Read a set of quantization tables from the specified file. + * The file is plain ASCII text: decimal numbers with whitespace between. + * Comments preceded by '#' may be included in the file. + * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values. + * The tables are implicitly numbered 0,1,etc. + * NOTE: does not affect the qslots mapping, which will default to selecting + * table 0 for luminance (or primary) components, 1 for chrominance components. + * You must use -qslots if you want a different component->table mapping. + */ +{ + FILE *fp; + int tblno, i, termchar; + long val; + unsigned int table[DCTSIZE2]; + + if ((fp = fopen(filename, "r")) == NULL) { + fprintf(stderr, "Can't open table file %s\n", filename); + return FALSE; + } + tblno = 0; + + while (read_text_integer(fp, &val, &termchar)) { /* read 1st element of table */ + if (tblno >= NUM_QUANT_TBLS) { + fprintf(stderr, "Too many tables in file %s\n", filename); + fclose(fp); + return FALSE; + } + table[0] = (unsigned int)val; + for (i = 1; i < DCTSIZE2; i++) { + if (!read_text_integer(fp, &val, &termchar)) { + fprintf(stderr, "Invalid table data in file %s\n", filename); + fclose(fp); + return FALSE; + } + table[i] = (unsigned int)val; + } +#if JPEG_LIB_VERSION >= 70 + jpeg_add_quant_table(cinfo, tblno, table, cinfo->q_scale_factor[tblno], + force_baseline); +#else + jpeg_add_quant_table(cinfo, tblno, table, q_scale_factor[tblno], + force_baseline); +#endif + tblno++; + } + + if (termchar != EOF) { + fprintf(stderr, "Non-numeric data in file %s\n", filename); + fclose(fp); + return FALSE; + } + + fclose(fp); + return TRUE; +} + + +#ifdef C_MULTISCAN_FILES_SUPPORTED + +LOCAL(boolean) +read_scan_integer(FILE *file, long *result, int *termchar) +/* Variant of read_text_integer that always looks for a non-space termchar; + * this simplifies parsing of punctuation in scan scripts. + */ +{ + register int ch; + + if (!read_text_integer(file, result, termchar)) + return FALSE; + ch = *termchar; + while (ch != EOF && isspace(ch)) + ch = text_getc(file); + if (isdigit(ch)) { /* oops, put it back */ + if (ungetc(ch, file) == EOF) + return FALSE; + ch = ' '; + } else { + /* Any separators other than ';' and ':' are ignored; + * this allows user to insert commas, etc, if desired. + */ + if (ch != EOF && ch != ';' && ch != ':') + ch = ' '; + } + *termchar = ch; + return TRUE; +} + + +GLOBAL(boolean) +read_scan_script(j_compress_ptr cinfo, char *filename) +/* Read a scan script from the specified text file. + * Each entry in the file defines one scan to be emitted. + * Entries are separated by semicolons ';'. + * An entry contains one to four component indexes, + * optionally followed by a colon ':' and four progressive-JPEG parameters. + * The component indexes denote which component(s) are to be transmitted + * in the current scan. The first component has index 0. + * Sequential JPEG is used if the progressive-JPEG parameters are omitted. + * The file is free format text: any whitespace may appear between numbers + * and the ':' and ';' punctuation marks. Also, other punctuation (such + * as commas or dashes) can be placed between numbers if desired. + * Comments preceded by '#' may be included in the file. + * Note: we do very little validity checking here; + * jcmaster.c will validate the script parameters. + */ +{ + FILE *fp; + int scanno, ncomps, termchar; + long val; + jpeg_scan_info *scanptr; +#define MAX_SCANS 100 /* quite arbitrary limit */ + jpeg_scan_info scans[MAX_SCANS]; + + if ((fp = fopen(filename, "r")) == NULL) { + fprintf(stderr, "Can't open scan definition file %s\n", filename); + return FALSE; + } + scanptr = scans; + scanno = 0; + + while (read_scan_integer(fp, &val, &termchar)) { + if (scanno >= MAX_SCANS) { + fprintf(stderr, "Too many scans defined in file %s\n", filename); + fclose(fp); + return FALSE; + } + scanptr->component_index[0] = (int)val; + ncomps = 1; + while (termchar == ' ') { + if (ncomps >= MAX_COMPS_IN_SCAN) { + fprintf(stderr, "Too many components in one scan in file %s\n", + filename); + fclose(fp); + return FALSE; + } + if (!read_scan_integer(fp, &val, &termchar)) + goto bogus; + scanptr->component_index[ncomps] = (int)val; + ncomps++; + } + scanptr->comps_in_scan = ncomps; + if (termchar == ':') { + if (!read_scan_integer(fp, &val, &termchar) || termchar != ' ') + goto bogus; + scanptr->Ss = (int)val; + if (!read_scan_integer(fp, &val, &termchar) || termchar != ' ') + goto bogus; + scanptr->Se = (int)val; + if (!read_scan_integer(fp, &val, &termchar) || termchar != ' ') + goto bogus; + scanptr->Ah = (int)val; + if (!read_scan_integer(fp, &val, &termchar)) + goto bogus; + scanptr->Al = (int)val; + } else { + /* set non-progressive parameters */ + scanptr->Ss = 0; + scanptr->Se = DCTSIZE2 - 1; + scanptr->Ah = 0; + scanptr->Al = 0; + } + if (termchar != ';' && termchar != EOF) { +bogus: + fprintf(stderr, "Invalid scan entry format in file %s\n", filename); + fclose(fp); + return FALSE; + } + scanptr++, scanno++; + } + + if (termchar != EOF) { + fprintf(stderr, "Non-numeric data in file %s\n", filename); + fclose(fp); + return FALSE; + } + + if (scanno > 0) { + /* Stash completed scan list in cinfo structure. + * NOTE: for cjpeg's use, JPOOL_IMAGE is the right lifetime for this data, + * but if you want to compress multiple images you'd want JPOOL_PERMANENT. + */ + scanptr = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + scanno * sizeof(jpeg_scan_info)); + memcpy(scanptr, scans, scanno * sizeof(jpeg_scan_info)); + cinfo->scan_info = scanptr; + cinfo->num_scans = scanno; + } + + fclose(fp); + return TRUE; +} + +#endif /* C_MULTISCAN_FILES_SUPPORTED */ + + +#if JPEG_LIB_VERSION < 70 +/* These are the sample quantization tables given in Annex K (Clause K.1) of + * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994. + * The spec says that the values given produce "good" quality, and + * when divided by 2, "very good" quality. + */ +static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; +static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + + +LOCAL(void) +jpeg_default_qtables(j_compress_ptr cinfo, boolean force_baseline) +{ + jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, q_scale_factor[0], + force_baseline); + jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, q_scale_factor[1], + force_baseline); +} +#endif + + +GLOBAL(boolean) +set_quality_ratings(j_compress_ptr cinfo, char *arg, boolean force_baseline) +/* Process a quality-ratings parameter string, of the form + * N[,N,...] + * If there are more q-table slots than parameters, the last value is replicated. + */ +{ + int val = 75; /* default value */ + int tblno; + char ch; + + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + if (*arg) { + ch = ','; /* if not set by sscanf, will be ',' */ + if (sscanf(arg, "%d%c", &val, &ch) < 1) + return FALSE; + if (ch != ',') /* syntax check */ + return FALSE; + /* Convert user 0-100 rating to percentage scaling */ +#if JPEG_LIB_VERSION >= 70 + cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val); +#else + q_scale_factor[tblno] = jpeg_quality_scaling(val); +#endif + while (*arg && *arg++ != ','); /* advance to next segment of arg + string */ + } else { + /* reached end of parameter, set remaining factors to last value */ +#if JPEG_LIB_VERSION >= 70 + cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val); +#else + q_scale_factor[tblno] = jpeg_quality_scaling(val); +#endif + } + } + jpeg_default_qtables(cinfo, force_baseline); + return TRUE; +} + + +GLOBAL(boolean) +set_quant_slots(j_compress_ptr cinfo, char *arg) +/* Process a quantization-table-selectors parameter string, of the form + * N[,N,...] + * If there are more components than parameters, the last value is replicated. + */ +{ + int val = 0; /* default table # */ + int ci; + char ch; + + for (ci = 0; ci < MAX_COMPONENTS; ci++) { + if (*arg) { + ch = ','; /* if not set by sscanf, will be ',' */ + if (sscanf(arg, "%d%c", &val, &ch) < 1) + return FALSE; + if (ch != ',') /* syntax check */ + return FALSE; + if (val < 0 || val >= NUM_QUANT_TBLS) { + fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n", + NUM_QUANT_TBLS - 1); + return FALSE; + } + cinfo->comp_info[ci].quant_tbl_no = val; + while (*arg && *arg++ != ','); /* advance to next segment of arg + string */ + } else { + /* reached end of parameter, set remaining components to last table */ + cinfo->comp_info[ci].quant_tbl_no = val; + } + } + return TRUE; +} + + +GLOBAL(boolean) +set_sample_factors(j_compress_ptr cinfo, char *arg) +/* Process a sample-factors parameter string, of the form + * HxV[,HxV,...] + * If there are more components than parameters, "1x1" is assumed for the rest. + */ +{ + int ci, val1, val2; + char ch1, ch2; + + for (ci = 0; ci < MAX_COMPONENTS; ci++) { + if (*arg) { + ch2 = ','; /* if not set by sscanf, will be ',' */ + if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3) + return FALSE; + if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */ + return FALSE; + if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) { + fprintf(stderr, "JPEG sampling factors must be 1..4\n"); + return FALSE; + } + cinfo->comp_info[ci].h_samp_factor = val1; + cinfo->comp_info[ci].v_samp_factor = val2; + while (*arg && *arg++ != ','); /* advance to next segment of arg + string */ + } else { + /* reached end of parameter, set remaining components to 1x1 sampling */ + cinfo->comp_info[ci].h_samp_factor = 1; + cinfo->comp_info[ci].v_samp_factor = 1; + } + } + return TRUE; +} diff --git a/3rdparty/libjpeg-turbo/src/rdtarga.c b/3rdparty/libjpeg-turbo/src/rdtarga.c new file mode 100644 index 000000000000..b78a16539e1c --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/rdtarga.c @@ -0,0 +1,507 @@ +/* + * rdtarga.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2017 by Guido Vollbeding. + * libjpeg-turbo Modifications: + * Copyright (C) 2018, 2021-2023, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains routines to read input images in Targa format. + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume input from + * an ordinary stdio stream. They further assume that reading begins + * at the start of the file; start_input may need work if the + * user interface has already read some data (e.g., to determine that + * the file is indeed Targa format). + * + * Based on code contributed by Lee Daniel Crocker. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef TARGA_SUPPORTED + + +/* Macros to deal with unsigned chars as efficiently as compiler allows */ + +typedef unsigned char U_CHAR; +#define UCH(x) ((int)(x)) + + +#define ReadOK(file, buffer, len) \ + (fread(buffer, 1, len, file) == ((size_t)(len))) + + +/* Private version of data source object */ + +typedef struct _tga_source_struct *tga_source_ptr; + +typedef struct _tga_source_struct { + struct cjpeg_source_struct pub; /* public fields */ + + j_compress_ptr cinfo; /* back link saves passing separate parm */ + + JSAMPARRAY colormap; /* Targa colormap (converted to my format) */ + + jvirt_sarray_ptr whole_image; /* Needed if funny input row order */ + JDIMENSION current_row; /* Current logical row number to read */ + + /* Pointer to routine to extract next Targa pixel from input file */ + void (*read_pixel) (tga_source_ptr sinfo); + + /* Result of read_pixel is delivered here: */ + U_CHAR tga_pixel[4]; + + int pixel_size; /* Bytes per Targa pixel (1 to 4) */ + int cmap_length; /* colormap length */ + + /* State info for reading RLE-coded pixels; both counts must be init to 0 */ + int block_count; /* # of pixels remaining in RLE block */ + int dup_pixel_count; /* # of times to duplicate previous pixel */ + + /* This saves the correct pixel-row-expansion method for preload_image */ + JDIMENSION (*get_pixel_rows) (j_compress_ptr cinfo, cjpeg_source_ptr sinfo); +} tga_source_struct; + + +/* For expanding 5-bit pixel values to 8-bit with best rounding */ + +static const UINT8 c5to8bits[32] = { + 0, 8, 16, 25, 33, 41, 49, 58, + 66, 74, 82, 90, 99, 107, 115, 123, + 132, 140, 148, 156, 165, 173, 181, 189, + 197, 206, 214, 222, 230, 239, 247, 255 +}; + + + +LOCAL(int) +read_byte(tga_source_ptr sinfo) +/* Read next byte from Targa file */ +{ + register FILE *infile = sinfo->pub.input_file; + register int c; + + if ((c = getc(infile)) == EOF) + ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); + return c; +} + + +LOCAL(void) +read_colormap(tga_source_ptr sinfo, int cmaplen, int mapentrysize) +/* Read the colormap from a Targa file */ +{ + int i; + + /* Presently only handles 24-bit BGR format */ + if (mapentrysize != 24) + ERREXIT(sinfo->cinfo, JERR_TGA_BADCMAP); + + for (i = 0; i < cmaplen; i++) { + sinfo->colormap[2][i] = (JSAMPLE)read_byte(sinfo); + sinfo->colormap[1][i] = (JSAMPLE)read_byte(sinfo); + sinfo->colormap[0][i] = (JSAMPLE)read_byte(sinfo); + } +} + + +/* + * read_pixel methods: get a single pixel from Targa file into tga_pixel[] + */ + +METHODDEF(void) +read_non_rle_pixel(tga_source_ptr sinfo) +/* Read one Targa pixel from the input file; no RLE expansion */ +{ + register int i; + + for (i = 0; i < sinfo->pixel_size; i++) { + sinfo->tga_pixel[i] = (U_CHAR)read_byte(sinfo); + } +} + + +METHODDEF(void) +read_rle_pixel(tga_source_ptr sinfo) +/* Read one Targa pixel from the input file, expanding RLE data as needed */ +{ + register int i; + + /* Duplicate previously read pixel? */ + if (sinfo->dup_pixel_count > 0) { + sinfo->dup_pixel_count--; + return; + } + + /* Time to read RLE block header? */ + if (--sinfo->block_count < 0) { /* decrement pixels remaining in block */ + i = read_byte(sinfo); + if (i & 0x80) { /* Start of duplicate-pixel block? */ + sinfo->dup_pixel_count = i & 0x7F; /* number of dups after this one */ + sinfo->block_count = 0; /* then read new block header */ + } else { + sinfo->block_count = i & 0x7F; /* number of pixels after this one */ + } + } + + /* Read next pixel */ + for (i = 0; i < sinfo->pixel_size; i++) { + sinfo->tga_pixel[i] = (U_CHAR)read_byte(sinfo); + } +} + + +/* + * Read one row of pixels. + * + * We provide several different versions depending on input file format. + */ + + +METHODDEF(JDIMENSION) +get_8bit_gray_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 8-bit grayscale pixels */ +{ + tga_source_ptr source = (tga_source_ptr)sinfo; + register JSAMPROW ptr; + register JDIMENSION col; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ + *ptr++ = (JSAMPLE)UCH(source->tga_pixel[0]); + } + return 1; +} + +METHODDEF(JDIMENSION) +get_8bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 8-bit colormap indexes */ +{ + tga_source_ptr source = (tga_source_ptr)sinfo; + register int t; + register JSAMPROW ptr; + register JDIMENSION col; + register JSAMPARRAY colormap = source->colormap; + int cmaplen = source->cmap_length; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ + t = UCH(source->tga_pixel[0]); + if (t >= cmaplen) + ERREXIT(cinfo, JERR_TGA_BADPARMS); + *ptr++ = colormap[0][t]; + *ptr++ = colormap[1][t]; + *ptr++ = colormap[2][t]; + } + return 1; +} + +METHODDEF(JDIMENSION) +get_16bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 16-bit pixels */ +{ + tga_source_ptr source = (tga_source_ptr)sinfo; + register int t; + register JSAMPROW ptr; + register JDIMENSION col; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ + t = UCH(source->tga_pixel[0]); + t += UCH(source->tga_pixel[1]) << 8; + /* We expand 5 bit data to 8 bit sample width. + * The format of the 16-bit (LSB first) input word is + * xRRRRRGGGGGBBBBB + */ + ptr[2] = (JSAMPLE)c5to8bits[t & 0x1F]; + t >>= 5; + ptr[1] = (JSAMPLE)c5to8bits[t & 0x1F]; + t >>= 5; + ptr[0] = (JSAMPLE)c5to8bits[t & 0x1F]; + ptr += 3; + } + return 1; +} + +METHODDEF(JDIMENSION) +get_24bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 24-bit pixels */ +{ + tga_source_ptr source = (tga_source_ptr)sinfo; + register JSAMPROW ptr; + register JDIMENSION col; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ + *ptr++ = (JSAMPLE)UCH(source->tga_pixel[2]); /* change BGR to RGB order */ + *ptr++ = (JSAMPLE)UCH(source->tga_pixel[1]); + *ptr++ = (JSAMPLE)UCH(source->tga_pixel[0]); + } + return 1; +} + +/* + * Targa also defines a 32-bit pixel format with order B,G,R,A. + * We presently ignore the attribute byte, so the code for reading + * these pixels is identical to the 24-bit routine above. + * This works because the actual pixel length is only known to read_pixel. + */ + +#define get_32bit_row get_24bit_row + + +/* + * This method is for re-reading the input data in standard top-down + * row order. The entire image has already been read into whole_image + * with proper conversion of pixel format, but it's in a funny row order. + */ + +METHODDEF(JDIMENSION) +get_memory_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + tga_source_ptr source = (tga_source_ptr)sinfo; + JDIMENSION source_row; + + /* Compute row of source that maps to current_row of normal order */ + /* For now, assume image is bottom-up and not interlaced. */ + /* NEEDS WORK to support interlaced images! */ + source_row = cinfo->image_height - source->current_row - 1; + + /* Fetch that row from virtual array */ + source->pub.buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, source->whole_image, + source_row, (JDIMENSION)1, FALSE); + + source->current_row++; + return 1; +} + + +/* + * This method loads the image into whole_image during the first call on + * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call + * get_memory_row on subsequent calls. + */ + +METHODDEF(JDIMENSION) +preload_image(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + tga_source_ptr source = (tga_source_ptr)sinfo; + JDIMENSION row; + cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress; + + /* Read the data into a virtual array in input-file row order. */ + for (row = 0; row < cinfo->image_height; row++) { + if (progress != NULL) { + progress->pub.pass_counter = (long)row; + progress->pub.pass_limit = (long)cinfo->image_height; + (*progress->pub.progress_monitor) ((j_common_ptr)cinfo); + } + source->pub.buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, source->whole_image, row, (JDIMENSION)1, TRUE); + (*source->get_pixel_rows) (cinfo, sinfo); + } + if (progress != NULL) + progress->completed_extra_passes++; + + /* Set up to read from the virtual array in unscrambled order */ + source->pub.get_pixel_rows = get_memory_row; + source->current_row = 0; + /* And read the first row */ + return get_memory_row(cinfo, sinfo); +} + + +/* + * Read the file header; return image size and component count. + */ + +METHODDEF(void) +start_input_tga(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + tga_source_ptr source = (tga_source_ptr)sinfo; + U_CHAR targaheader[18]; + int idlen, cmaptype, subtype, flags, interlace_type, components; + unsigned int width, height, maplen; + boolean is_bottom_up; + +#define GET_2B(offset) \ + ((unsigned int)UCH(targaheader[offset]) + \ + (((unsigned int)UCH(targaheader[offset + 1])) << 8)) + + if (!ReadOK(source->pub.input_file, targaheader, 18)) + ERREXIT(cinfo, JERR_INPUT_EOF); + + /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */ + if (targaheader[16] == 15) + targaheader[16] = 16; + + idlen = UCH(targaheader[0]); + cmaptype = UCH(targaheader[1]); + subtype = UCH(targaheader[2]); + maplen = GET_2B(5); + width = GET_2B(12); + height = GET_2B(14); + source->pixel_size = UCH(targaheader[16]) >> 3; + flags = UCH(targaheader[17]); /* Image Descriptor byte */ + + is_bottom_up = ((flags & 0x20) == 0); /* bit 5 set => top-down */ + interlace_type = flags >> 6; /* bits 6/7 are interlace code */ + + if (cmaptype > 1 || /* cmaptype must be 0 or 1 */ + source->pixel_size < 1 || source->pixel_size > 4 || + (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */ + interlace_type != 0 || /* currently don't allow interlaced image */ + width == 0 || height == 0) /* image width/height must be non-zero */ + ERREXIT(cinfo, JERR_TGA_BADPARMS); + if (sinfo->max_pixels && + (unsigned long long)width * height > sinfo->max_pixels) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, sinfo->max_pixels); + + if (subtype > 8) { + /* It's an RLE-coded file */ + source->read_pixel = read_rle_pixel; + source->block_count = source->dup_pixel_count = 0; + subtype -= 8; + } else { + /* Non-RLE file */ + source->read_pixel = read_non_rle_pixel; + } + + /* Now should have subtype 1, 2, or 3 */ + components = 3; /* until proven different */ + cinfo->in_color_space = JCS_RGB; + + switch (subtype) { + case 1: /* Colormapped image */ + if (source->pixel_size == 1 && cmaptype == 1) + source->get_pixel_rows = get_8bit_row; + else + ERREXIT(cinfo, JERR_TGA_BADPARMS); + TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height); + break; + case 2: /* RGB image */ + switch (source->pixel_size) { + case 2: + source->get_pixel_rows = get_16bit_row; + break; + case 3: + source->get_pixel_rows = get_24bit_row; + break; + case 4: + source->get_pixel_rows = get_32bit_row; + break; + default: + ERREXIT(cinfo, JERR_TGA_BADPARMS); + break; + } + TRACEMS2(cinfo, 1, JTRC_TGA, width, height); + break; + case 3: /* Grayscale image */ + components = 1; + cinfo->in_color_space = JCS_GRAYSCALE; + if (source->pixel_size == 1) + source->get_pixel_rows = get_8bit_gray_row; + else + ERREXIT(cinfo, JERR_TGA_BADPARMS); + TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height); + break; + default: + ERREXIT(cinfo, JERR_TGA_BADPARMS); + break; + } + + if (is_bottom_up) { + /* Create a virtual array to buffer the upside-down image. */ + source->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION)width * components, (JDIMENSION)height, (JDIMENSION)1); + if (cinfo->progress != NULL) { + cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress; + progress->total_extra_passes++; /* count file input as separate pass */ + } + /* source->pub.buffer will point to the virtual array. */ + source->pub.buffer_height = 1; /* in case anyone looks at it */ + source->pub.get_pixel_rows = preload_image; + } else { + /* Don't need a virtual array, but do need a one-row input buffer. */ + source->whole_image = NULL; + source->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, + (JDIMENSION)width * components, (JDIMENSION)1); + source->pub.buffer_height = 1; + source->pub.get_pixel_rows = source->get_pixel_rows; + } + + while (idlen--) /* Throw away ID field */ + (void)read_byte(source); + + if (maplen > 0) { + if (maplen > 256 || GET_2B(3) != 0) + ERREXIT(cinfo, JERR_TGA_BADCMAP); + /* Allocate space to store the colormap */ + source->colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)maplen, (JDIMENSION)3); + source->cmap_length = (int)maplen; + /* and read it from the file */ + read_colormap(source, (int)maplen, UCH(targaheader[7])); + } else { + if (cmaptype) /* but you promised a cmap! */ + ERREXIT(cinfo, JERR_TGA_BADPARMS); + source->colormap = NULL; + source->cmap_length = 0; + } + + cinfo->input_components = components; + cinfo->data_precision = 8; + cinfo->image_width = width; + cinfo->image_height = height; +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_input_tga(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + /* no work */ +} + + +/* + * The module selection routine for Targa format input. + */ + +GLOBAL(cjpeg_source_ptr) +jinit_read_targa(j_compress_ptr cinfo) +{ + tga_source_ptr source; + + if (cinfo->data_precision != 8) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Create module interface object */ + source = (tga_source_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + sizeof(tga_source_struct)); + source->cinfo = cinfo; /* make back link for subroutines */ + /* Fill in method ptrs, except get_pixel_rows which start_input sets */ + source->pub.start_input = start_input_tga; + source->pub.finish_input = finish_input_tga; + source->pub.max_pixels = 0; + + return (cjpeg_source_ptr)source; +} + +#endif /* TARGA_SUPPORTED */ diff --git a/3rdparty/libjpeg-turbo/src/simd/CMakeLists.txt b/3rdparty/libjpeg-turbo/src/simd/CMakeLists.txt index 50553020041e..023795598a19 100644 --- a/3rdparty/libjpeg-turbo/src/simd/CMakeLists.txt +++ b/3rdparty/libjpeg-turbo/src/simd/CMakeLists.txt @@ -1,13 +1,9 @@ macro(simd_fail message) - message(STATUS "libjpeg-turbo(SIMD): ${message}. Performance will suffer.") - set(WITH_SIMD 0 PARENT_SCOPE) -endmacro() - -macro(boolean_number var) - if(${var}) - set(${var} 1 ${ARGN}) + if(REQUIRE_SIMD) + message(FATAL_ERROR "${message}.") else() - set(${var} 0 ${ARGN}) + message(WARNING "${message}. Performance will suffer.") + set(WITH_SIMD 0 PARENT_SCOPE) endif() endmacro() @@ -45,14 +41,14 @@ elseif(CPU_TYPE STREQUAL "i386") endif() endif() - -include(CheckLanguage) -check_language(ASM_NASM) -if(NOT CMAKE_ASM_NASM_COMPILER) - simd_fail("SIMD extensions disabled: could not find NASM compiler") - return() +if(NOT REQUIRE_SIMD) + include(CheckLanguage) + check_language(ASM_NASM) + if(NOT CMAKE_ASM_NASM_COMPILER) + simd_fail("SIMD extensions disabled: could not find NASM compiler") + return() + endif() endif() - enable_language(ASM_NASM) message(STATUS "CMAKE_ASM_NASM_COMPILER = ${CMAKE_ASM_NASM_COMPILER}") @@ -75,6 +71,8 @@ elseif(CPU_TYPE STREQUAL "i386") endif() endif() +message(STATUS "CMAKE_ASM_NASM_OBJECT_FORMAT = ${CMAKE_ASM_NASM_OBJECT_FORMAT}") + if(NOT CMAKE_ASM_NASM_OBJECT_FORMAT) simd_fail("SIMD extensions disabled: could not determine NASM object format") return() @@ -98,8 +96,21 @@ if(NOT WIN32 AND (CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED)) set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -DPIC") endif() +if(CPU_TYPE STREQUAL "x86_64" AND CMAKE_ASM_NASM_OBJECT_FORMAT MATCHES "^elf") + check_c_source_compiles(" + #if (__CET__ & 3) == 0 + #error \"CET not enabled\" + #endif + int main(void) { return 0; }" HAVE_CET) + + if(HAVE_CET) + set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -D__CET__") + endif() +endif() + string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UC) set(EFFECTIVE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} ${CMAKE_ASM_NASM_FLAGS_${CMAKE_BUILD_TYPE_UC}}") +message(STATUS "CMAKE_ASM_NASM_FLAGS = ${EFFECTIVE_ASM_NASM_FLAGS}") set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -I\"${CMAKE_CURRENT_SOURCE_DIR}/nasm/\" -I\"${CMAKE_CURRENT_SOURCE_DIR}/${CPU_TYPE}/\"") @@ -113,7 +124,6 @@ add_custom_target(jsimdcfg COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/nasm/jsimdcfg.inc.h | ${GREP} -E '^[\;%]|^\ %' | sed 's%_cpp_protection_%%' | sed 's@% define@%define@g' >${CMAKE_CURRENT_SOURCE_DIR}/nasm/jsimdcfg.inc) -set_target_properties(jsimdcfg PROPERTIES FOLDER "3rdparty") if(CPU_TYPE STREQUAL "x86_64") set(SIMD_SOURCES x86_64/jsimdcpu.asm x86_64/jfdctflt-sse.asm @@ -198,16 +208,14 @@ endforeach() if(MSVC_IDE OR XCODE) set(SIMD_OBJS ${SIMD_OBJS} PARENT_SCOPE) - add_library(jsimd OBJECT ${CPU_TYPE}/jsimd.c) - add_custom_target(jsimd-objs DEPENDS ${SIMD_OBJS}) - add_dependencies(jsimd jsimd-objs) - set_target_properties(jsimd PROPERTIES FOLDER "3rdparty") - set_target_properties(jsimd-objs PROPERTIES FOLDER "3rdparty") + add_library(simd OBJECT ${CPU_TYPE}/jsimd.c) + add_custom_target(simd-objs DEPENDS ${SIMD_OBJS}) + add_dependencies(simd simd-objs) else() - add_library(jsimd OBJECT ${SIMD_SOURCES} ${CPU_TYPE}/jsimd.c) + add_library(simd OBJECT ${SIMD_SOURCES} ${CPU_TYPE}/jsimd.c) endif() if(NOT WIN32 AND (CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED)) - set_target_properties(jsimd PROPERTIES POSITION_INDEPENDENT_CODE 1) + set_target_properties(simd PROPERTIES POSITION_INDEPENDENT_CODE 1) endif() @@ -228,7 +236,6 @@ elseif(CPU_TYPE STREQUAL "arm64" OR CPU_TYPE STREQUAL "arm") # following test determines whether -mfloat-abi=softfp should be explicitly # added to the compile flags for the intrinsics implementation of the Neon SIMD # extensions. - if(BITS EQUAL 32) check_c_source_compiles(" #if defined(__ARM_NEON__) || (!defined(__linux__) && !defined(ANDROID) && !defined(__ANDROID__)) @@ -361,7 +368,7 @@ if(NOT NEON_INTRINSICS) -x assembler-with-cpp -c ${CMAKE_CURRENT_BINARY_DIR}/gastest.S RESULT_VARIABLE RESULT OUTPUT_VARIABLE OUTPUT ERROR_VARIABLE ERROR) if(NOT RESULT EQUAL 0) - message(STATUS "libjpeg-turbo(SIMD): GAS appears to be broken. Using the full Neon SIMD intrinsics implementation.") + message(WARNING "GAS appears to be broken. Using the full Neon SIMD intrinsics implementation.") set(NEON_INTRINSICS 1 CACHE INTERNAL "" FORCE) endif() endif() @@ -397,10 +404,10 @@ if(NOT NEON_INTRINSICS) set(SIMD_SOURCES ${SIMD_SOURCES} arm/aarch${BITS}/jsimd_neon.S) endif() -add_library(jsimd OBJECT ${SIMD_SOURCES} arm/aarch${BITS}/jsimd.c) +add_library(simd OBJECT ${SIMD_SOURCES} arm/aarch${BITS}/jsimd.c) if(CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED) - set_target_properties(jsimd PROPERTIES POSITION_INDEPENDENT_CODE 1) + set_target_properties(simd PROPERTIES POSITION_INDEPENDENT_CODE 1) endif() @@ -439,10 +446,10 @@ if(NOT HAVE_DSPR2) return() endif() -add_library(jsimd OBJECT mips/jsimd_dspr2.S mips/jsimd.c) +add_library(simd OBJECT mips/jsimd_dspr2.S mips/jsimd.c) if(CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED) - set_target_properties(jsimd PROPERTIES POSITION_INDEPENDENT_CODE 1) + set_target_properties(simd PROPERTIES POSITION_INDEPENDENT_CODE 1) endif() ############################################################################### @@ -454,6 +461,9 @@ elseif(CPU_TYPE STREQUAL "loongson" OR CPU_TYPE MATCHES "^mips64") set(CMAKE_REQUIRED_FLAGS -Wa,-mloongson-mmi,-mloongson-ext) check_c_source_compiles(" + #if !(defined(__mips__) && __mips_isa_rev < 6) + #error Loongson MMI can't work with MIPS Release 6+ + #endif int main(void) { int c = 0, a = 0, b = 0; asm ( @@ -487,10 +497,10 @@ foreach(file ${SIMD_SOURCES}) " -Wa,-mloongson-mmi,-mloongson-ext") endforeach() -add_library(jsimd OBJECT ${SIMD_SOURCES} mips64/jsimd.c) +add_library(simd OBJECT ${SIMD_SOURCES} mips64/jsimd.c) if(CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED) - set_target_properties(jsimd PROPERTIES POSITION_INDEPENDENT_CODE 1) + set_target_properties(simd PROPERTIES POSITION_INDEPENDENT_CODE 1) endif() ############################################################################### @@ -527,10 +537,10 @@ set(SIMD_SOURCES powerpc/jccolor-altivec.c powerpc/jcgray-altivec.c set_source_files_properties(${SIMD_SOURCES} PROPERTIES COMPILE_FLAGS -maltivec) -add_library(jsimd OBJECT ${SIMD_SOURCES} powerpc/jsimd.c) +add_library(simd OBJECT ${SIMD_SOURCES} powerpc/jsimd.c) if(CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED) - set_target_properties(jsimd PROPERTIES POSITION_INDEPENDENT_CODE 1) + set_target_properties(simd PROPERTIES POSITION_INDEPENDENT_CODE 1) endif() diff --git a/3rdparty/libjpeg-turbo/src/simd/arm/aarch32/jsimd.c b/3rdparty/libjpeg-turbo/src/simd/arm/aarch32/jsimd.c index e3adf23d5013..04d64526fb23 100644 --- a/3rdparty/libjpeg-turbo/src/simd/arm/aarch32/jsimd.c +++ b/3rdparty/libjpeg-turbo/src/simd/arm/aarch32/jsimd.c @@ -4,7 +4,7 @@ * Copyright 2009 Pierre Ossman for Cendio AB * Copyright (C) 2011, Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2009-2011, 2013-2014, 2016, 2018, 2022, D. R. Commander. - * Copyright (C) 2015-2016, 2018, Matthieu Darbois. + * Copyright (C) 2015-2016, 2018, 2022, Matthieu Darbois. * Copyright (C) 2019, Google LLC. * Copyright (C) 2020, Arm Limited. * @@ -25,12 +25,10 @@ #include "../../../jsimddct.h" #include "../../jsimd.h" -#include -#include #include -static unsigned int simd_support = ~0; -static unsigned int simd_huffman = 1; +static THREAD_LOCAL unsigned int simd_support = ~0; +static THREAD_LOCAL unsigned int simd_huffman = 1; #if !defined(__ARM_NEON__) && (defined(__linux__) || defined(ANDROID) || defined(__ANDROID__)) @@ -98,8 +96,6 @@ parse_proc_cpuinfo(int bufsize) /* * Check what SIMD accelerations are supported. - * - * FIXME: This code is racy under a multi-threaded environment. */ LOCAL(void) init_simd(void) @@ -947,7 +943,7 @@ jsimd_can_encode_mcu_AC_first_prepare(void) GLOBAL(void) jsimd_encode_mcu_AC_first_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *values, size_t *zerobits) + int Al, UJCOEF *values, size_t *zerobits) { jsimd_encode_mcu_AC_first_prepare_neon(block, jpeg_natural_order_start, Sl, Al, values, zerobits); @@ -972,7 +968,7 @@ jsimd_can_encode_mcu_AC_refine_prepare(void) GLOBAL(int) jsimd_encode_mcu_AC_refine_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *absvalues, size_t *bits) + int Al, UJCOEF *absvalues, size_t *bits) { return jsimd_encode_mcu_AC_refine_prepare_neon(block, jpeg_natural_order_start, Sl, diff --git a/3rdparty/libjpeg-turbo/src/simd/arm/aarch64/jsimd.c b/3rdparty/libjpeg-turbo/src/simd/arm/aarch64/jsimd.c index 604d5472f6a6..358e1597b165 100644 --- a/3rdparty/libjpeg-turbo/src/simd/arm/aarch64/jsimd.c +++ b/3rdparty/libjpeg-turbo/src/simd/arm/aarch64/jsimd.c @@ -4,7 +4,7 @@ * Copyright 2009 Pierre Ossman for Cendio AB * Copyright (C) 2011, Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2009-2011, 2013-2014, 2016, 2018, 2020, 2022, D. R. Commander. - * Copyright (C) 2015-2016, 2018, Matthieu Darbois. + * Copyright (C) 2015-2016, 2018, 2022, Matthieu Darbois. * Copyright (C) 2020, Arm Limited. * * Based on the x86 SIMD extension for IJG JPEG library, @@ -23,20 +23,17 @@ #include "../../../jdct.h" #include "../../../jsimddct.h" #include "../../jsimd.h" -#include "jconfigint.h" -#include -#include #include #define JSIMD_FASTLD3 1 #define JSIMD_FASTST3 2 #define JSIMD_FASTTBL 4 -static unsigned int simd_support = ~0; -static unsigned int simd_huffman = 1; -static unsigned int simd_features = JSIMD_FASTLD3 | JSIMD_FASTST3 | - JSIMD_FASTTBL; +static THREAD_LOCAL unsigned int simd_support = ~0; +static THREAD_LOCAL unsigned int simd_huffman = 1; +static THREAD_LOCAL unsigned int simd_features = JSIMD_FASTLD3 | + JSIMD_FASTST3 | JSIMD_FASTTBL; #if defined(__linux__) || defined(ANDROID) || defined(__ANDROID__) @@ -111,8 +108,6 @@ parse_proc_cpuinfo(int bufsize) /* * Check what SIMD accelerations are supported. - * - * FIXME: This code is racy under a multi-threaded environment. */ /* @@ -1023,7 +1018,7 @@ jsimd_can_encode_mcu_AC_first_prepare(void) GLOBAL(void) jsimd_encode_mcu_AC_first_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *values, size_t *zerobits) + int Al, UJCOEF *values, size_t *zerobits) { jsimd_encode_mcu_AC_first_prepare_neon(block, jpeg_natural_order_start, Sl, Al, values, zerobits); @@ -1050,7 +1045,7 @@ jsimd_can_encode_mcu_AC_refine_prepare(void) GLOBAL(int) jsimd_encode_mcu_AC_refine_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *absvalues, size_t *bits) + int Al, UJCOEF *absvalues, size_t *bits) { return jsimd_encode_mcu_AC_refine_prepare_neon(block, jpeg_natural_order_start, diff --git a/3rdparty/libjpeg-turbo/src/simd/arm/jcphuff-neon.c b/3rdparty/libjpeg-turbo/src/simd/arm/jcphuff-neon.c index b91c5db478a1..51db3c5f3939 100644 --- a/3rdparty/libjpeg-turbo/src/simd/arm/jcphuff-neon.c +++ b/3rdparty/libjpeg-turbo/src/simd/arm/jcphuff-neon.c @@ -2,6 +2,8 @@ * jcphuff-neon.c - prepare data for progressive Huffman encoding (Arm Neon) * * Copyright (C) 2020-2021, Arm Limited. All Rights Reserved. + * Copyright (C) 2022, Matthieu Darbois. All Rights Reserved. + * Copyright (C) 2022, D. R. Commander. All Rights Reserved. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -21,7 +23,6 @@ */ #define JPEG_INTERNALS -#include "jconfigint.h" #include "../../jinclude.h" #include "../../jpeglib.h" #include "../../jsimd.h" @@ -41,10 +42,10 @@ void jsimd_encode_mcu_AC_first_prepare_neon (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, - JCOEF *values, size_t *zerobits) + UJCOEF *values, size_t *zerobits) { - JCOEF *values_ptr = values; - JCOEF *diff_values_ptr = values + DCTSIZE2; + UJCOEF *values_ptr = values; + UJCOEF *diff_values_ptr = values + DCTSIZE2; /* Rows of coefficients to zero (since they haven't been processed) */ int i, rows_to_zero = 8; @@ -68,23 +69,23 @@ void jsimd_encode_mcu_AC_first_prepare_neon coefs2 = vld1q_lane_s16(block + jpeg_natural_order_start[15], coefs2, 7); /* Isolate sign of coefficients. */ - int16x8_t sign_coefs1 = vshrq_n_s16(coefs1, 15); - int16x8_t sign_coefs2 = vshrq_n_s16(coefs2, 15); + uint16x8_t sign_coefs1 = vreinterpretq_u16_s16(vshrq_n_s16(coefs1, 15)); + uint16x8_t sign_coefs2 = vreinterpretq_u16_s16(vshrq_n_s16(coefs2, 15)); /* Compute absolute value of coefficients and apply point transform Al. */ - int16x8_t abs_coefs1 = vabsq_s16(coefs1); - int16x8_t abs_coefs2 = vabsq_s16(coefs2); - coefs1 = vshlq_s16(abs_coefs1, vdupq_n_s16(-Al)); - coefs2 = vshlq_s16(abs_coefs2, vdupq_n_s16(-Al)); + uint16x8_t abs_coefs1 = vreinterpretq_u16_s16(vabsq_s16(coefs1)); + uint16x8_t abs_coefs2 = vreinterpretq_u16_s16(vabsq_s16(coefs2)); + abs_coefs1 = vshlq_u16(abs_coefs1, vdupq_n_s16(-Al)); + abs_coefs2 = vshlq_u16(abs_coefs2, vdupq_n_s16(-Al)); /* Compute diff values. */ - int16x8_t diff1 = veorq_s16(coefs1, sign_coefs1); - int16x8_t diff2 = veorq_s16(coefs2, sign_coefs2); + uint16x8_t diff1 = veorq_u16(abs_coefs1, sign_coefs1); + uint16x8_t diff2 = veorq_u16(abs_coefs2, sign_coefs2); /* Store transformed coefficients and diff values. */ - vst1q_s16(values_ptr, coefs1); - vst1q_s16(values_ptr + DCTSIZE, coefs2); - vst1q_s16(diff_values_ptr, diff1); - vst1q_s16(diff_values_ptr + DCTSIZE, diff2); + vst1q_u16(values_ptr, abs_coefs1); + vst1q_u16(values_ptr + DCTSIZE, abs_coefs2); + vst1q_u16(diff_values_ptr, diff1); + vst1q_u16(diff_values_ptr + DCTSIZE, diff2); values_ptr += 16; diff_values_ptr += 16; jpeg_natural_order_start += 16; @@ -130,23 +131,23 @@ void jsimd_encode_mcu_AC_first_prepare_neon } /* Isolate sign of coefficients. */ - int16x8_t sign_coefs1 = vshrq_n_s16(coefs1, 15); - int16x8_t sign_coefs2 = vshrq_n_s16(coefs2, 15); + uint16x8_t sign_coefs1 = vreinterpretq_u16_s16(vshrq_n_s16(coefs1, 15)); + uint16x8_t sign_coefs2 = vreinterpretq_u16_s16(vshrq_n_s16(coefs2, 15)); /* Compute absolute value of coefficients and apply point transform Al. */ - int16x8_t abs_coefs1 = vabsq_s16(coefs1); - int16x8_t abs_coefs2 = vabsq_s16(coefs2); - coefs1 = vshlq_s16(abs_coefs1, vdupq_n_s16(-Al)); - coefs2 = vshlq_s16(abs_coefs2, vdupq_n_s16(-Al)); + uint16x8_t abs_coefs1 = vreinterpretq_u16_s16(vabsq_s16(coefs1)); + uint16x8_t abs_coefs2 = vreinterpretq_u16_s16(vabsq_s16(coefs2)); + abs_coefs1 = vshlq_u16(abs_coefs1, vdupq_n_s16(-Al)); + abs_coefs2 = vshlq_u16(abs_coefs2, vdupq_n_s16(-Al)); /* Compute diff values. */ - int16x8_t diff1 = veorq_s16(coefs1, sign_coefs1); - int16x8_t diff2 = veorq_s16(coefs2, sign_coefs2); + uint16x8_t diff1 = veorq_u16(abs_coefs1, sign_coefs1); + uint16x8_t diff2 = veorq_u16(abs_coefs2, sign_coefs2); /* Store transformed coefficients and diff values. */ - vst1q_s16(values_ptr, coefs1); - vst1q_s16(values_ptr + DCTSIZE, coefs2); - vst1q_s16(diff_values_ptr, diff1); - vst1q_s16(diff_values_ptr + DCTSIZE, diff2); + vst1q_u16(values_ptr, abs_coefs1); + vst1q_u16(values_ptr + DCTSIZE, abs_coefs2); + vst1q_u16(diff_values_ptr, diff1); + vst1q_u16(diff_values_ptr + DCTSIZE, diff2); values_ptr += 16; diff_values_ptr += 16; rows_to_zero -= 2; @@ -184,17 +185,17 @@ void jsimd_encode_mcu_AC_first_prepare_neon } /* Isolate sign of coefficients. */ - int16x8_t sign_coefs = vshrq_n_s16(coefs, 15); + uint16x8_t sign_coefs = vreinterpretq_u16_s16(vshrq_n_s16(coefs, 15)); /* Compute absolute value of coefficients and apply point transform Al. */ - int16x8_t abs_coefs = vabsq_s16(coefs); - coefs = vshlq_s16(abs_coefs, vdupq_n_s16(-Al)); + uint16x8_t abs_coefs = vreinterpretq_u16_s16(vabsq_s16(coefs)); + abs_coefs = vshlq_u16(abs_coefs, vdupq_n_s16(-Al)); /* Compute diff values. */ - int16x8_t diff = veorq_s16(coefs, sign_coefs); + uint16x8_t diff = veorq_u16(abs_coefs, sign_coefs); /* Store transformed coefficients and diff values. */ - vst1q_s16(values_ptr, coefs); - vst1q_s16(diff_values_ptr, diff); + vst1q_u16(values_ptr, abs_coefs); + vst1q_u16(diff_values_ptr, diff); values_ptr += 8; diff_values_ptr += 8; rows_to_zero--; @@ -202,8 +203,8 @@ void jsimd_encode_mcu_AC_first_prepare_neon /* Zero remaining memory in the values and diff_values blocks. */ for (i = 0; i < rows_to_zero; i++) { - vst1q_s16(values_ptr, vdupq_n_s16(0)); - vst1q_s16(diff_values_ptr, vdupq_n_s16(0)); + vst1q_u16(values_ptr, vdupq_n_u16(0)); + vst1q_u16(diff_values_ptr, vdupq_n_u16(0)); values_ptr += 8; diff_values_ptr += 8; } @@ -211,23 +212,23 @@ void jsimd_encode_mcu_AC_first_prepare_neon /* Construct zerobits bitmap. A set bit means that the corresponding * coefficient != 0. */ - int16x8_t row0 = vld1q_s16(values + 0 * DCTSIZE); - int16x8_t row1 = vld1q_s16(values + 1 * DCTSIZE); - int16x8_t row2 = vld1q_s16(values + 2 * DCTSIZE); - int16x8_t row3 = vld1q_s16(values + 3 * DCTSIZE); - int16x8_t row4 = vld1q_s16(values + 4 * DCTSIZE); - int16x8_t row5 = vld1q_s16(values + 5 * DCTSIZE); - int16x8_t row6 = vld1q_s16(values + 6 * DCTSIZE); - int16x8_t row7 = vld1q_s16(values + 7 * DCTSIZE); - - uint8x8_t row0_eq0 = vmovn_u16(vceqq_s16(row0, vdupq_n_s16(0))); - uint8x8_t row1_eq0 = vmovn_u16(vceqq_s16(row1, vdupq_n_s16(0))); - uint8x8_t row2_eq0 = vmovn_u16(vceqq_s16(row2, vdupq_n_s16(0))); - uint8x8_t row3_eq0 = vmovn_u16(vceqq_s16(row3, vdupq_n_s16(0))); - uint8x8_t row4_eq0 = vmovn_u16(vceqq_s16(row4, vdupq_n_s16(0))); - uint8x8_t row5_eq0 = vmovn_u16(vceqq_s16(row5, vdupq_n_s16(0))); - uint8x8_t row6_eq0 = vmovn_u16(vceqq_s16(row6, vdupq_n_s16(0))); - uint8x8_t row7_eq0 = vmovn_u16(vceqq_s16(row7, vdupq_n_s16(0))); + uint16x8_t row0 = vld1q_u16(values + 0 * DCTSIZE); + uint16x8_t row1 = vld1q_u16(values + 1 * DCTSIZE); + uint16x8_t row2 = vld1q_u16(values + 2 * DCTSIZE); + uint16x8_t row3 = vld1q_u16(values + 3 * DCTSIZE); + uint16x8_t row4 = vld1q_u16(values + 4 * DCTSIZE); + uint16x8_t row5 = vld1q_u16(values + 5 * DCTSIZE); + uint16x8_t row6 = vld1q_u16(values + 6 * DCTSIZE); + uint16x8_t row7 = vld1q_u16(values + 7 * DCTSIZE); + + uint8x8_t row0_eq0 = vmovn_u16(vceqq_u16(row0, vdupq_n_u16(0))); + uint8x8_t row1_eq0 = vmovn_u16(vceqq_u16(row1, vdupq_n_u16(0))); + uint8x8_t row2_eq0 = vmovn_u16(vceqq_u16(row2, vdupq_n_u16(0))); + uint8x8_t row3_eq0 = vmovn_u16(vceqq_u16(row3, vdupq_n_u16(0))); + uint8x8_t row4_eq0 = vmovn_u16(vceqq_u16(row4, vdupq_n_u16(0))); + uint8x8_t row5_eq0 = vmovn_u16(vceqq_u16(row5, vdupq_n_u16(0))); + uint8x8_t row6_eq0 = vmovn_u16(vceqq_u16(row6, vdupq_n_u16(0))); + uint8x8_t row7_eq0 = vmovn_u16(vceqq_u16(row7, vdupq_n_u16(0))); /* { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 } */ const uint8x8_t bitmap_mask = @@ -274,7 +275,7 @@ void jsimd_encode_mcu_AC_first_prepare_neon int jsimd_encode_mcu_AC_refine_prepare_neon (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, - JCOEF *absvalues, size_t *bits) + UJCOEF *absvalues, size_t *bits) { /* Temporary storage buffers for data used to compute the signbits bitmap and * the end-of-block (EOB) position @@ -282,7 +283,7 @@ int jsimd_encode_mcu_AC_refine_prepare_neon uint8_t coef_sign_bits[64]; uint8_t coef_eq1_bits[64]; - JCOEF *absvalues_ptr = absvalues; + UJCOEF *absvalues_ptr = absvalues; uint8_t *coef_sign_bits_ptr = coef_sign_bits; uint8_t *eq1_bits_ptr = coef_eq1_bits; @@ -316,18 +317,18 @@ int jsimd_encode_mcu_AC_refine_prepare_neon vst1_u8(coef_sign_bits_ptr + DCTSIZE, sign_coefs2); /* Compute absolute value of coefficients and apply point transform Al. */ - int16x8_t abs_coefs1 = vabsq_s16(coefs1); - int16x8_t abs_coefs2 = vabsq_s16(coefs2); - coefs1 = vshlq_s16(abs_coefs1, vdupq_n_s16(-Al)); - coefs2 = vshlq_s16(abs_coefs2, vdupq_n_s16(-Al)); - vst1q_s16(absvalues_ptr, coefs1); - vst1q_s16(absvalues_ptr + DCTSIZE, coefs2); + uint16x8_t abs_coefs1 = vreinterpretq_u16_s16(vabsq_s16(coefs1)); + uint16x8_t abs_coefs2 = vreinterpretq_u16_s16(vabsq_s16(coefs2)); + abs_coefs1 = vshlq_u16(abs_coefs1, vdupq_n_s16(-Al)); + abs_coefs2 = vshlq_u16(abs_coefs2, vdupq_n_s16(-Al)); + vst1q_u16(absvalues_ptr, abs_coefs1); + vst1q_u16(absvalues_ptr + DCTSIZE, abs_coefs2); /* Test whether transformed coefficient values == 1 (used to find EOB * position.) */ - uint8x8_t coefs_eq11 = vmovn_u16(vceqq_s16(coefs1, vdupq_n_s16(1))); - uint8x8_t coefs_eq12 = vmovn_u16(vceqq_s16(coefs2, vdupq_n_s16(1))); + uint8x8_t coefs_eq11 = vmovn_u16(vceqq_u16(abs_coefs1, vdupq_n_u16(1))); + uint8x8_t coefs_eq12 = vmovn_u16(vceqq_u16(abs_coefs2, vdupq_n_u16(1))); vst1_u8(eq1_bits_ptr, coefs_eq11); vst1_u8(eq1_bits_ptr + DCTSIZE, coefs_eq12); @@ -385,18 +386,18 @@ int jsimd_encode_mcu_AC_refine_prepare_neon vst1_u8(coef_sign_bits_ptr + DCTSIZE, sign_coefs2); /* Compute absolute value of coefficients and apply point transform Al. */ - int16x8_t abs_coefs1 = vabsq_s16(coefs1); - int16x8_t abs_coefs2 = vabsq_s16(coefs2); - coefs1 = vshlq_s16(abs_coefs1, vdupq_n_s16(-Al)); - coefs2 = vshlq_s16(abs_coefs2, vdupq_n_s16(-Al)); - vst1q_s16(absvalues_ptr, coefs1); - vst1q_s16(absvalues_ptr + DCTSIZE, coefs2); + uint16x8_t abs_coefs1 = vreinterpretq_u16_s16(vabsq_s16(coefs1)); + uint16x8_t abs_coefs2 = vreinterpretq_u16_s16(vabsq_s16(coefs2)); + abs_coefs1 = vshlq_u16(abs_coefs1, vdupq_n_s16(-Al)); + abs_coefs2 = vshlq_u16(abs_coefs2, vdupq_n_s16(-Al)); + vst1q_u16(absvalues_ptr, abs_coefs1); + vst1q_u16(absvalues_ptr + DCTSIZE, abs_coefs2); /* Test whether transformed coefficient values == 1 (used to find EOB * position.) */ - uint8x8_t coefs_eq11 = vmovn_u16(vceqq_s16(coefs1, vdupq_n_s16(1))); - uint8x8_t coefs_eq12 = vmovn_u16(vceqq_s16(coefs2, vdupq_n_s16(1))); + uint8x8_t coefs_eq11 = vmovn_u16(vceqq_u16(abs_coefs1, vdupq_n_u16(1))); + uint8x8_t coefs_eq12 = vmovn_u16(vceqq_u16(abs_coefs2, vdupq_n_u16(1))); vst1_u8(eq1_bits_ptr, coefs_eq11); vst1_u8(eq1_bits_ptr + DCTSIZE, coefs_eq12); @@ -444,14 +445,14 @@ int jsimd_encode_mcu_AC_refine_prepare_neon vst1_u8(coef_sign_bits_ptr, sign_coefs); /* Compute absolute value of coefficients and apply point transform Al. */ - int16x8_t abs_coefs = vabsq_s16(coefs); - coefs = vshlq_s16(abs_coefs, vdupq_n_s16(-Al)); - vst1q_s16(absvalues_ptr, coefs); + uint16x8_t abs_coefs = vreinterpretq_u16_s16(vabsq_s16(coefs)); + abs_coefs = vshlq_u16(abs_coefs, vdupq_n_s16(-Al)); + vst1q_u16(absvalues_ptr, abs_coefs); /* Test whether transformed coefficient values == 1 (used to find EOB * position.) */ - uint8x8_t coefs_eq1 = vmovn_u16(vceqq_s16(coefs, vdupq_n_s16(1))); + uint8x8_t coefs_eq1 = vmovn_u16(vceqq_u16(abs_coefs, vdupq_n_u16(1))); vst1_u8(eq1_bits_ptr, coefs_eq1); absvalues_ptr += 8; @@ -462,7 +463,7 @@ int jsimd_encode_mcu_AC_refine_prepare_neon /* Zero remaining memory in blocks. */ for (i = 0; i < rows_to_zero; i++) { - vst1q_s16(absvalues_ptr, vdupq_n_s16(0)); + vst1q_u16(absvalues_ptr, vdupq_n_u16(0)); vst1_u8(coef_sign_bits_ptr, vdup_n_u8(0)); vst1_u8(eq1_bits_ptr, vdup_n_u8(0)); absvalues_ptr += 8; @@ -471,23 +472,23 @@ int jsimd_encode_mcu_AC_refine_prepare_neon } /* Construct zerobits bitmap. */ - int16x8_t abs_row0 = vld1q_s16(absvalues + 0 * DCTSIZE); - int16x8_t abs_row1 = vld1q_s16(absvalues + 1 * DCTSIZE); - int16x8_t abs_row2 = vld1q_s16(absvalues + 2 * DCTSIZE); - int16x8_t abs_row3 = vld1q_s16(absvalues + 3 * DCTSIZE); - int16x8_t abs_row4 = vld1q_s16(absvalues + 4 * DCTSIZE); - int16x8_t abs_row5 = vld1q_s16(absvalues + 5 * DCTSIZE); - int16x8_t abs_row6 = vld1q_s16(absvalues + 6 * DCTSIZE); - int16x8_t abs_row7 = vld1q_s16(absvalues + 7 * DCTSIZE); - - uint8x8_t abs_row0_eq0 = vmovn_u16(vceqq_s16(abs_row0, vdupq_n_s16(0))); - uint8x8_t abs_row1_eq0 = vmovn_u16(vceqq_s16(abs_row1, vdupq_n_s16(0))); - uint8x8_t abs_row2_eq0 = vmovn_u16(vceqq_s16(abs_row2, vdupq_n_s16(0))); - uint8x8_t abs_row3_eq0 = vmovn_u16(vceqq_s16(abs_row3, vdupq_n_s16(0))); - uint8x8_t abs_row4_eq0 = vmovn_u16(vceqq_s16(abs_row4, vdupq_n_s16(0))); - uint8x8_t abs_row5_eq0 = vmovn_u16(vceqq_s16(abs_row5, vdupq_n_s16(0))); - uint8x8_t abs_row6_eq0 = vmovn_u16(vceqq_s16(abs_row6, vdupq_n_s16(0))); - uint8x8_t abs_row7_eq0 = vmovn_u16(vceqq_s16(abs_row7, vdupq_n_s16(0))); + uint16x8_t abs_row0 = vld1q_u16(absvalues + 0 * DCTSIZE); + uint16x8_t abs_row1 = vld1q_u16(absvalues + 1 * DCTSIZE); + uint16x8_t abs_row2 = vld1q_u16(absvalues + 2 * DCTSIZE); + uint16x8_t abs_row3 = vld1q_u16(absvalues + 3 * DCTSIZE); + uint16x8_t abs_row4 = vld1q_u16(absvalues + 4 * DCTSIZE); + uint16x8_t abs_row5 = vld1q_u16(absvalues + 5 * DCTSIZE); + uint16x8_t abs_row6 = vld1q_u16(absvalues + 6 * DCTSIZE); + uint16x8_t abs_row7 = vld1q_u16(absvalues + 7 * DCTSIZE); + + uint8x8_t abs_row0_eq0 = vmovn_u16(vceqq_u16(abs_row0, vdupq_n_u16(0))); + uint8x8_t abs_row1_eq0 = vmovn_u16(vceqq_u16(abs_row1, vdupq_n_u16(0))); + uint8x8_t abs_row2_eq0 = vmovn_u16(vceqq_u16(abs_row2, vdupq_n_u16(0))); + uint8x8_t abs_row3_eq0 = vmovn_u16(vceqq_u16(abs_row3, vdupq_n_u16(0))); + uint8x8_t abs_row4_eq0 = vmovn_u16(vceqq_u16(abs_row4, vdupq_n_u16(0))); + uint8x8_t abs_row5_eq0 = vmovn_u16(vceqq_u16(abs_row5, vdupq_n_u16(0))); + uint8x8_t abs_row6_eq0 = vmovn_u16(vceqq_u16(abs_row6, vdupq_n_u16(0))); + uint8x8_t abs_row7_eq0 = vmovn_u16(vceqq_u16(abs_row7, vdupq_n_u16(0))); /* { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 } */ const uint8x8_t bitmap_mask = diff --git a/3rdparty/libjpeg-turbo/src/simd/arm/jdcolor-neon.c b/3rdparty/libjpeg-turbo/src/simd/arm/jdcolor-neon.c index ea4668f1d308..28dbc57243ce 100644 --- a/3rdparty/libjpeg-turbo/src/simd/arm/jdcolor-neon.c +++ b/3rdparty/libjpeg-turbo/src/simd/arm/jdcolor-neon.c @@ -21,7 +21,6 @@ */ #define JPEG_INTERNALS -#include "jconfigint.h" #include "../../jinclude.h" #include "../../jpeglib.h" #include "../../jsimd.h" diff --git a/3rdparty/libjpeg-turbo/src/simd/arm/jdmerge-neon.c b/3rdparty/libjpeg-turbo/src/simd/arm/jdmerge-neon.c index e4f91fdc0ef7..18fb9d8a55ab 100644 --- a/3rdparty/libjpeg-turbo/src/simd/arm/jdmerge-neon.c +++ b/3rdparty/libjpeg-turbo/src/simd/arm/jdmerge-neon.c @@ -21,7 +21,6 @@ */ #define JPEG_INTERNALS -#include "jconfigint.h" #include "../../jinclude.h" #include "../../jpeglib.h" #include "../../jsimd.h" diff --git a/3rdparty/libjpeg-turbo/src/simd/arm/jidctint-neon.c b/3rdparty/libjpeg-turbo/src/simd/arm/jidctint-neon.c index 043b652e6c55..d25112ef7fd2 100644 --- a/3rdparty/libjpeg-turbo/src/simd/arm/jidctint-neon.c +++ b/3rdparty/libjpeg-turbo/src/simd/arm/jidctint-neon.c @@ -22,7 +22,6 @@ */ #define JPEG_INTERNALS -#include "jconfigint.h" #include "../../jinclude.h" #include "../../jpeglib.h" #include "../../jsimd.h" diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jccolext-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jccolext-avx2.asm index c46d684436dd..af6418f0a673 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jccolext-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jccolext-avx2.asm @@ -2,7 +2,7 @@ ; jccolext.asm - colorspace conversion (AVX2) ; ; Copyright (C) 2015, Intel Corporation. -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -49,15 +49,15 @@ EXTN(jsimd_rgb_ycc_convert_avx2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov ecx, JDIMENSION [img_width(eax)] test ecx, ecx @@ -80,9 +80,9 @@ EXTN(jsimd_rgb_ycc_convert_avx2): mov eax, INT [num_rows(eax)] test eax, eax jle near .return - alignx 16, 7 + ALIGNX 16, 7 .rowloop: - pushpic eax + PUSHPIC eax push edx push ebx push edi @@ -93,11 +93,11 @@ EXTN(jsimd_rgb_ycc_convert_avx2): mov edi, JSAMPROW [edi] ; outptr0 mov ebx, JSAMPROW [ebx] ; outptr1 mov edx, JSAMPROW [edx] ; outptr2 - movpic eax, POINTER [gotptr] ; load GOT address (eax) + MOVPIC eax, POINTER [gotptr] ; load GOT address (eax) cmp ecx, byte SIZEOF_YMMWORD jae near .columnloop - alignx 16, 7 + ALIGNX 16, 7 %if RGB_PIXELSIZE == 3 ; --------------- @@ -154,7 +154,7 @@ EXTN(jsimd_rgb_ycc_convert_avx2): vmovdqu ymmA, YMMWORD [esi+0*SIZEOF_YMMWORD] vmovdqu ymmF, YMMWORD [esi+1*SIZEOF_YMMWORD] jmp short .rgb_ycc_cnv - alignx 16, 7 + ALIGNX 16, 7 .columnloop: vmovdqu ymmA, YMMWORD [esi+0*SIZEOF_YMMWORD] @@ -278,7 +278,7 @@ EXTN(jsimd_rgb_ycc_convert_avx2): vmovdqu ymmA, YMMWORD [esi+0*SIZEOF_YMMWORD] vmovdqu ymmF, YMMWORD [esi+1*SIZEOF_YMMWORD] jmp short .rgb_ycc_cnv - alignx 16, 7 + ALIGNX 16, 7 .columnloop: vmovdqu ymmA, YMMWORD [esi+0*SIZEOF_YMMWORD] @@ -552,7 +552,7 @@ EXTN(jsimd_rgb_ycc_convert_avx2): pop edi pop ebx pop edx - poppic eax + POPPIC eax add esi, byte SIZEOF_JSAMPROW ; input_buf add edi, byte SIZEOF_JSAMPROW diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jccolext-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jccolext-mmx.asm index 6357a42b2cf4..dbec80e787ba 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jccolext-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jccolext-mmx.asm @@ -2,7 +2,7 @@ ; jccolext.asm - colorspace conversion (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -49,15 +49,15 @@ EXTN(jsimd_rgb_ycc_convert_mmx): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov ecx, JDIMENSION [img_width(eax)] ; num_cols test ecx, ecx @@ -80,9 +80,9 @@ EXTN(jsimd_rgb_ycc_convert_mmx): mov eax, INT [num_rows(eax)] test eax, eax jle near .return - alignx 16, 7 + ALIGNX 16, 7 .rowloop: - pushpic eax + PUSHPIC eax push edx push ebx push edi @@ -93,11 +93,11 @@ EXTN(jsimd_rgb_ycc_convert_mmx): mov edi, JSAMPROW [edi] ; outptr0 mov ebx, JSAMPROW [ebx] ; outptr1 mov edx, JSAMPROW [edx] ; outptr2 - movpic eax, POINTER [gotptr] ; load GOT address (eax) + MOVPIC eax, POINTER [gotptr] ; load GOT address (eax) cmp ecx, byte SIZEOF_MMWORD jae short .columnloop - alignx 16, 7 + ALIGNX 16, 7 %if RGB_PIXELSIZE == 3 ; --------------- @@ -143,7 +143,7 @@ EXTN(jsimd_rgb_ycc_convert_mmx): movq mmA, MMWORD [esi+0*SIZEOF_MMWORD] movq mmG, MMWORD [esi+1*SIZEOF_MMWORD] jmp short .rgb_ycc_cnv - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movq mmA, MMWORD [esi+0*SIZEOF_MMWORD] @@ -211,7 +211,7 @@ EXTN(jsimd_rgb_ycc_convert_mmx): movq mmA, MMWORD [esi+0*SIZEOF_MMWORD] movq mmF, MMWORD [esi+1*SIZEOF_MMWORD] jmp short .rgb_ycc_cnv - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movq mmA, MMWORD [esi+0*SIZEOF_MMWORD] @@ -449,7 +449,7 @@ EXTN(jsimd_rgb_ycc_convert_mmx): pop edi pop ebx pop edx - poppic eax + POPPIC eax add esi, byte SIZEOF_JSAMPROW ; input_buf add edi, byte SIZEOF_JSAMPROW diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jccolext-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jccolext-sse2.asm index c6c80852ac5b..8d411451788b 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jccolext-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jccolext-sse2.asm @@ -1,7 +1,7 @@ ; ; jccolext.asm - colorspace conversion (SSE2) ; -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -48,15 +48,15 @@ EXTN(jsimd_rgb_ycc_convert_sse2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov ecx, JDIMENSION [img_width(eax)] test ecx, ecx @@ -79,9 +79,9 @@ EXTN(jsimd_rgb_ycc_convert_sse2): mov eax, INT [num_rows(eax)] test eax, eax jle near .return - alignx 16, 7 + ALIGNX 16, 7 .rowloop: - pushpic eax + PUSHPIC eax push edx push ebx push edi @@ -92,11 +92,11 @@ EXTN(jsimd_rgb_ycc_convert_sse2): mov edi, JSAMPROW [edi] ; outptr0 mov ebx, JSAMPROW [ebx] ; outptr1 mov edx, JSAMPROW [edx] ; outptr2 - movpic eax, POINTER [gotptr] ; load GOT address (eax) + MOVPIC eax, POINTER [gotptr] ; load GOT address (eax) cmp ecx, byte SIZEOF_XMMWORD jae near .columnloop - alignx 16, 7 + ALIGNX 16, 7 %if RGB_PIXELSIZE == 3 ; --------------- @@ -147,7 +147,7 @@ EXTN(jsimd_rgb_ycc_convert_sse2): movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD] movdqu xmmF, XMMWORD [esi+1*SIZEOF_XMMWORD] jmp short .rgb_ycc_cnv - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD] @@ -232,7 +232,7 @@ EXTN(jsimd_rgb_ycc_convert_sse2): movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD] movdqu xmmE, XMMWORD [esi+1*SIZEOF_XMMWORD] jmp short .rgb_ycc_cnv - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD] @@ -478,7 +478,7 @@ EXTN(jsimd_rgb_ycc_convert_sse2): pop edi pop ebx pop edx - poppic eax + POPPIC eax add esi, byte SIZEOF_JSAMPROW ; input_buf add edi, byte SIZEOF_JSAMPROW diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jccolor-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jccolor-avx2.asm index 14944e952f19..3d6dfa6f8cbb 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jccolor-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jccolor-avx2.asm @@ -1,7 +1,7 @@ ; ; jccolor.asm - colorspace conversion (AVX2) ; -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; ; Based on the x86 SIMD extension for IJG JPEG library @@ -33,7 +33,7 @@ F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_rgb_ycc_convert_avx2) EXTN(jconst_rgb_ycc_convert_avx2): @@ -46,7 +46,7 @@ PD_ONEHALFM1_CJ times 8 dd (1 << (SCALEBITS - 1)) - 1 + \ (CENTERJSAMPLE << SCALEBITS) PD_ONEHALF times 8 dd (1 << (SCALEBITS - 1)) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jccolor-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jccolor-mmx.asm index 8cb399bdc43f..0527488500f5 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jccolor-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jccolor-mmx.asm @@ -2,7 +2,7 @@ ; jccolor.asm - colorspace conversion (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -33,7 +33,7 @@ F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_rgb_ycc_convert_mmx) EXTN(jconst_rgb_ycc_convert_mmx): @@ -46,7 +46,7 @@ PD_ONEHALFM1_CJ times 2 dd (1 << (SCALEBITS - 1)) - 1 + \ (CENTERJSAMPLE << SCALEBITS) PD_ONEHALF times 2 dd (1 << (SCALEBITS - 1)) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jccolor-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jccolor-sse2.asm index 686d222ff700..ff6a2ecd13af 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jccolor-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jccolor-sse2.asm @@ -1,7 +1,7 @@ ; ; jccolor.asm - colorspace conversion (SSE2) ; -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -32,7 +32,7 @@ F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_rgb_ycc_convert_sse2) EXTN(jconst_rgb_ycc_convert_sse2): @@ -45,7 +45,7 @@ PD_ONEHALFM1_CJ times 4 dd (1 << (SCALEBITS - 1)) - 1 + \ (CENTERJSAMPLE << SCALEBITS) PD_ONEHALF times 4 dd (1 << (SCALEBITS - 1)) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jcgray-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jcgray-avx2.asm index 560ee0c71e2b..564974f84951 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jcgray-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jcgray-avx2.asm @@ -1,7 +1,7 @@ ; ; jcgray.asm - grayscale colorspace conversion (AVX2) ; -; Copyright (C) 2011, 2016, D. R. Commander. +; Copyright (C) 2011, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; ; Based on the x86 SIMD extension for IJG JPEG library @@ -29,7 +29,7 @@ F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_rgb_gray_convert_avx2) EXTN(jconst_rgb_gray_convert_avx2): @@ -38,7 +38,7 @@ PW_F0299_F0337 times 8 dw F_0_299, F_0_337 PW_F0114_F0250 times 8 dw F_0_114, F_0_250 PD_ONEHALF times 8 dd (1 << (SCALEBITS - 1)) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jcgray-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jcgray-mmx.asm index 79fdf082a848..e791ea4aa61b 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jcgray-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jcgray-mmx.asm @@ -2,7 +2,7 @@ ; jcgray.asm - grayscale colorspace conversion (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2011, 2016, D. R. Commander. +; Copyright (C) 2011, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -29,7 +29,7 @@ F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_rgb_gray_convert_mmx) EXTN(jconst_rgb_gray_convert_mmx): @@ -38,7 +38,7 @@ PW_F0299_F0337 times 2 dw F_0_299, F_0_337 PW_F0114_F0250 times 2 dw F_0_114, F_0_250 PD_ONEHALF times 2 dd (1 << (SCALEBITS - 1)) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jcgray-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jcgray-sse2.asm index cb4b28e8f495..70c0177db318 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jcgray-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jcgray-sse2.asm @@ -1,7 +1,7 @@ ; ; jcgray.asm - grayscale colorspace conversion (SSE2) ; -; Copyright (C) 2011, 2016, D. R. Commander. +; Copyright (C) 2011, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -28,7 +28,7 @@ F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_rgb_gray_convert_sse2) EXTN(jconst_rgb_gray_convert_sse2): @@ -37,7 +37,7 @@ PW_F0299_F0337 times 4 dw F_0_299, F_0_337 PW_F0114_F0250 times 4 dw F_0_114, F_0_250 PD_ONEHALF times 4 dd (1 << (SCALEBITS - 1)) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jcgryext-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jcgryext-avx2.asm index 3fa7973d72b4..0fb284aaf919 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jcgryext-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jcgryext-avx2.asm @@ -1,7 +1,7 @@ ; ; jcgryext.asm - grayscale colorspace conversion (AVX2) ; -; Copyright (C) 2011, 2016, D. R. Commander. +; Copyright (C) 2011, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; ; Based on the x86 SIMD extension for IJG JPEG library @@ -49,15 +49,15 @@ EXTN(jsimd_rgb_gray_convert_avx2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov ecx, JDIMENSION [img_width(eax)] test ecx, ecx @@ -76,20 +76,20 @@ EXTN(jsimd_rgb_gray_convert_avx2): mov eax, INT [num_rows(eax)] test eax, eax jle near .return - alignx 16, 7 + ALIGNX 16, 7 .rowloop: - pushpic eax + PUSHPIC eax push edi push esi push ecx ; col mov esi, JSAMPROW [esi] ; inptr mov edi, JSAMPROW [edi] ; outptr0 - movpic eax, POINTER [gotptr] ; load GOT address (eax) + MOVPIC eax, POINTER [gotptr] ; load GOT address (eax) cmp ecx, byte SIZEOF_YMMWORD jae near .columnloop - alignx 16, 7 + ALIGNX 16, 7 %if RGB_PIXELSIZE == 3 ; --------------- @@ -146,7 +146,7 @@ EXTN(jsimd_rgb_gray_convert_avx2): vmovdqu ymmA, YMMWORD [esi+0*SIZEOF_YMMWORD] vmovdqu ymmF, YMMWORD [esi+1*SIZEOF_YMMWORD] jmp short .rgb_gray_cnv - alignx 16, 7 + ALIGNX 16, 7 .columnloop: vmovdqu ymmA, YMMWORD [esi+0*SIZEOF_YMMWORD] @@ -270,7 +270,7 @@ EXTN(jsimd_rgb_gray_convert_avx2): vmovdqu ymmA, YMMWORD [esi+0*SIZEOF_YMMWORD] vmovdqu ymmF, YMMWORD [esi+1*SIZEOF_YMMWORD] jmp short .rgb_gray_cnv - alignx 16, 7 + ALIGNX 16, 7 .columnloop: vmovdqu ymmA, YMMWORD [esi+0*SIZEOF_YMMWORD] @@ -433,7 +433,7 @@ EXTN(jsimd_rgb_gray_convert_avx2): pop ecx ; col pop esi pop edi - poppic eax + POPPIC eax add esi, byte SIZEOF_JSAMPROW ; input_buf add edi, byte SIZEOF_JSAMPROW diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jcgryext-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jcgryext-mmx.asm index 8af42e5a3322..1c69d3829167 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jcgryext-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jcgryext-mmx.asm @@ -2,7 +2,7 @@ ; jcgryext.asm - grayscale colorspace conversion (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2011, 2016, D. R. Commander. +; Copyright (C) 2011, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -49,15 +49,15 @@ EXTN(jsimd_rgb_gray_convert_mmx): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov ecx, JDIMENSION [img_width(eax)] ; num_cols test ecx, ecx @@ -76,20 +76,20 @@ EXTN(jsimd_rgb_gray_convert_mmx): mov eax, INT [num_rows(eax)] test eax, eax jle near .return - alignx 16, 7 + ALIGNX 16, 7 .rowloop: - pushpic eax + PUSHPIC eax push edi push esi push ecx ; col mov esi, JSAMPROW [esi] ; inptr mov edi, JSAMPROW [edi] ; outptr0 - movpic eax, POINTER [gotptr] ; load GOT address (eax) + MOVPIC eax, POINTER [gotptr] ; load GOT address (eax) cmp ecx, byte SIZEOF_MMWORD jae short .columnloop - alignx 16, 7 + ALIGNX 16, 7 %if RGB_PIXELSIZE == 3 ; --------------- @@ -135,7 +135,7 @@ EXTN(jsimd_rgb_gray_convert_mmx): movq mmA, MMWORD [esi+0*SIZEOF_MMWORD] movq mmG, MMWORD [esi+1*SIZEOF_MMWORD] jmp short .rgb_gray_cnv - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movq mmA, MMWORD [esi+0*SIZEOF_MMWORD] @@ -203,7 +203,7 @@ EXTN(jsimd_rgb_gray_convert_mmx): movq mmA, MMWORD [esi+0*SIZEOF_MMWORD] movq mmF, MMWORD [esi+1*SIZEOF_MMWORD] jmp short .rgb_gray_cnv - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movq mmA, MMWORD [esi+0*SIZEOF_MMWORD] @@ -330,7 +330,7 @@ EXTN(jsimd_rgb_gray_convert_mmx): pop ecx ; col pop esi pop edi - poppic eax + POPPIC eax add esi, byte SIZEOF_JSAMPROW ; input_buf add edi, byte SIZEOF_JSAMPROW diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jcgryext-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jcgryext-sse2.asm index c9d6ff1e351c..f710816a443d 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jcgryext-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jcgryext-sse2.asm @@ -1,7 +1,7 @@ ; ; jcgryext.asm - grayscale colorspace conversion (SSE2) ; -; Copyright (C) 2011, 2016, D. R. Commander. +; Copyright (C) 2011, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -48,15 +48,15 @@ EXTN(jsimd_rgb_gray_convert_sse2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov ecx, JDIMENSION [img_width(eax)] test ecx, ecx @@ -75,20 +75,20 @@ EXTN(jsimd_rgb_gray_convert_sse2): mov eax, INT [num_rows(eax)] test eax, eax jle near .return - alignx 16, 7 + ALIGNX 16, 7 .rowloop: - pushpic eax + PUSHPIC eax push edi push esi push ecx ; col mov esi, JSAMPROW [esi] ; inptr mov edi, JSAMPROW [edi] ; outptr0 - movpic eax, POINTER [gotptr] ; load GOT address (eax) + MOVPIC eax, POINTER [gotptr] ; load GOT address (eax) cmp ecx, byte SIZEOF_XMMWORD jae near .columnloop - alignx 16, 7 + ALIGNX 16, 7 %if RGB_PIXELSIZE == 3 ; --------------- @@ -139,7 +139,7 @@ EXTN(jsimd_rgb_gray_convert_sse2): movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD] movdqu xmmF, XMMWORD [esi+1*SIZEOF_XMMWORD] jmp short .rgb_gray_cnv - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD] @@ -224,7 +224,7 @@ EXTN(jsimd_rgb_gray_convert_sse2): movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD] movdqu xmmE, XMMWORD [esi+1*SIZEOF_XMMWORD] jmp short .rgb_gray_cnv - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movdqu xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD] @@ -359,7 +359,7 @@ EXTN(jsimd_rgb_gray_convert_sse2): pop ecx ; col pop esi pop edi - poppic eax + POPPIC eax add esi, byte SIZEOF_JSAMPROW ; input_buf add edi, byte SIZEOF_JSAMPROW diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jchuff-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jchuff-sse2.asm index 278cf5e83af3..4adf5eb51448 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jchuff-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jchuff-sse2.asm @@ -1,7 +1,7 @@ ; ; jchuff-sse2.asm - Huffman entropy encoding (SSE2) ; -; Copyright (C) 2009-2011, 2014-2017, 2019, D. R. Commander. +; Copyright (C) 2009-2011, 2014-2017, 2019, 2024, D. R. Commander. ; Copyright (C) 2015, Matthieu Darbois. ; Copyright (C) 2018, Matthias Räncker. ; @@ -42,7 +42,7 @@ endstruc EXTN(jconst_huff_encode_one_block): - alignz 32 + ALIGNZ 32 jpeg_mask_bits dq 0x0000, 0x0001, 0x0003, 0x0007 dq 0x000f, 0x001f, 0x003f, 0x007f @@ -65,7 +65,8 @@ times 1 << 2 db 3 times 1 << 1 db 2 times 1 << 0 db 1 times 1 db 0 -jpeg_nbits_table: +GLOBAL_DATA(jpeg_nbits_table) +EXTN(jpeg_nbits_table): times 1 db 0 times 1 << 0 db 1 times 1 << 1 db 2 @@ -83,14 +84,14 @@ times 1 << 12 db 13 times 1 << 13 db 14 times 1 << 14 db 15 - alignz 32 + ALIGNZ 32 %ifdef PIC %define NBITS(x) nbits_base + x %else -%define NBITS(x) jpeg_nbits_table + x +%define NBITS(x) EXTN(jpeg_nbits_table) + x %endif -%define MASK_BITS(x) NBITS((x) * 8) + (jpeg_mask_bits - jpeg_nbits_table) +%define MASK_BITS(x) NBITS((x) * 8) + (jpeg_mask_bits - EXTN(jpeg_nbits_table)) ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -235,7 +236,7 @@ times 1 << 14 db 15 ; If PIC is defined, load the address of a symbol defined in this file into a ; register. Equivalent to -; get_GOT %1 +; GET_GOT %1 ; lea %1, [GOTOFF(%1, %2)] ; without using the GOT. ; @@ -469,7 +470,7 @@ EXTN(jsimd_huff_encode_one_block_sse2): pcmpeqw mm_all_0xff, mm_all_0xff ;Z: all_0xff[i] = 0xFF; %endmacro - GET_SYM nbits_base, jpeg_nbits_table, GET_SYM_BEFORE, GET_SYM_AFTER + GET_SYM nbits_base, EXTN(jpeg_nbits_table), GET_SYM_BEFORE, GET_SYM_AFTER psrldq xmm4, 1 * SIZEOF_WORD ;G: w4 = 37 44 45 38 39 46 47 -- shufpd xmm1, xmm5, 10b ;F: w1 = 36 37 44 45 50 51 58 59 diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jcsample-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jcsample-avx2.asm index 0a20802dd890..3d40f1d9fb6a 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jcsample-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jcsample-avx2.asm @@ -3,7 +3,7 @@ ; ; Copyright 2009 Pierre Ossman for Cendio AB ; Copyright (C) 2015, Intel Corporation. -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -70,7 +70,7 @@ EXTN(jsimd_h2v1_downsample_avx2): cld mov esi, JSAMPARRAY [input_data(ebp)] ; input_data - alignx 16, 7 + ALIGNX 16, 7 .expandloop: push eax push ecx @@ -106,7 +106,7 @@ EXTN(jsimd_h2v1_downsample_avx2): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, JSAMPARRAY [output_data(ebp)] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push ecx push edi @@ -117,7 +117,7 @@ EXTN(jsimd_h2v1_downsample_avx2): cmp ecx, byte SIZEOF_YMMWORD jae short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .columnloop_r24: ; ecx can possibly be 8, 16, 24 @@ -141,7 +141,7 @@ EXTN(jsimd_h2v1_downsample_avx2): vpxor ymm1, ymm1, ymm1 mov ecx, SIZEOF_YMMWORD jmp short .downsample - alignx 16, 7 + ALIGNX 16, 7 .columnloop: vmovdqu ymm0, YMMWORD [esi+0*SIZEOF_YMMWORD] @@ -243,7 +243,7 @@ EXTN(jsimd_h2v2_downsample_avx2): cld mov esi, JSAMPARRAY [input_data(ebp)] ; input_data - alignx 16, 7 + ALIGNX 16, 7 .expandloop: push eax push ecx @@ -279,7 +279,7 @@ EXTN(jsimd_h2v2_downsample_avx2): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, JSAMPARRAY [output_data(ebp)] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push ecx push edi @@ -291,7 +291,7 @@ EXTN(jsimd_h2v2_downsample_avx2): cmp ecx, byte SIZEOF_YMMWORD jae short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .columnloop_r24: cmp ecx, 24 @@ -320,7 +320,7 @@ EXTN(jsimd_h2v2_downsample_avx2): vpxor ymm3, ymm3, ymm3 mov ecx, SIZEOF_YMMWORD jmp short .downsample - alignx 16, 7 + ALIGNX 16, 7 .columnloop: vmovdqu ymm0, YMMWORD [edx+0*SIZEOF_YMMWORD] diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jcsample-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jcsample-mmx.asm index 2c223eebe816..38d5b322b65f 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jcsample-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jcsample-mmx.asm @@ -2,7 +2,7 @@ ; jcsample.asm - downsampling (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -69,7 +69,7 @@ EXTN(jsimd_h2v1_downsample_mmx): cld mov esi, JSAMPARRAY [input_data(ebp)] ; input_data - alignx 16, 7 + ALIGNX 16, 7 .expandloop: push eax push ecx @@ -104,7 +104,7 @@ EXTN(jsimd_h2v1_downsample_mmx): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, JSAMPARRAY [output_data(ebp)] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push ecx push edi @@ -112,7 +112,7 @@ EXTN(jsimd_h2v1_downsample_mmx): mov esi, JSAMPROW [esi] ; inptr mov edi, JSAMPROW [edi] ; outptr - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movq mm0, MMWORD [esi+0*SIZEOF_MMWORD] @@ -212,7 +212,7 @@ EXTN(jsimd_h2v2_downsample_mmx): cld mov esi, JSAMPARRAY [input_data(ebp)] ; input_data - alignx 16, 7 + ALIGNX 16, 7 .expandloop: push eax push ecx @@ -247,7 +247,7 @@ EXTN(jsimd_h2v2_downsample_mmx): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, JSAMPARRAY [output_data(ebp)] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push ecx push edi @@ -256,7 +256,7 @@ EXTN(jsimd_h2v2_downsample_mmx): mov edx, JSAMPROW [esi+0*SIZEOF_JSAMPROW] ; inptr0 mov esi, JSAMPROW [esi+1*SIZEOF_JSAMPROW] ; inptr1 mov edi, JSAMPROW [edi] ; outptr - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movq mm0, MMWORD [edx+0*SIZEOF_MMWORD] diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jcsample-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jcsample-sse2.asm index 4fea60d2e210..26c5d7407e1c 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jcsample-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jcsample-sse2.asm @@ -2,7 +2,7 @@ ; jcsample.asm - downsampling (SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -69,7 +69,7 @@ EXTN(jsimd_h2v1_downsample_sse2): cld mov esi, JSAMPARRAY [input_data(ebp)] ; input_data - alignx 16, 7 + ALIGNX 16, 7 .expandloop: push eax push ecx @@ -104,7 +104,7 @@ EXTN(jsimd_h2v1_downsample_sse2): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, JSAMPARRAY [output_data(ebp)] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push ecx push edi @@ -115,14 +115,14 @@ EXTN(jsimd_h2v1_downsample_sse2): cmp ecx, byte SIZEOF_XMMWORD jae short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .columnloop_r8: movdqa xmm0, XMMWORD [esi+0*SIZEOF_XMMWORD] pxor xmm1, xmm1 mov ecx, SIZEOF_XMMWORD jmp short .downsample - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movdqa xmm0, XMMWORD [esi+0*SIZEOF_XMMWORD] @@ -225,7 +225,7 @@ EXTN(jsimd_h2v2_downsample_sse2): cld mov esi, JSAMPARRAY [input_data(ebp)] ; input_data - alignx 16, 7 + ALIGNX 16, 7 .expandloop: push eax push ecx @@ -260,7 +260,7 @@ EXTN(jsimd_h2v2_downsample_sse2): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, JSAMPARRAY [output_data(ebp)] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push ecx push edi @@ -272,7 +272,7 @@ EXTN(jsimd_h2v2_downsample_sse2): cmp ecx, byte SIZEOF_XMMWORD jae short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .columnloop_r8: movdqa xmm0, XMMWORD [edx+0*SIZEOF_XMMWORD] @@ -281,7 +281,7 @@ EXTN(jsimd_h2v2_downsample_sse2): pxor xmm3, xmm3 mov ecx, SIZEOF_XMMWORD jmp short .downsample - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movdqa xmm0, XMMWORD [edx+0*SIZEOF_XMMWORD] diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdcolext-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdcolext-avx2.asm index 015be0416c5c..53ea3128fc14 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdcolext-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdcolext-avx2.asm @@ -2,7 +2,7 @@ ; jdcolext.asm - colorspace conversion (AVX2) ; ; Copyright 2009, 2012 Pierre Ossman for Cendio AB -; Copyright (C) 2012, 2016, D. R. Commander. +; Copyright (C) 2012, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; ; Based on the x86 SIMD extension for IJG JPEG library @@ -50,15 +50,15 @@ EXTN(jsimd_ycc_rgb_convert_avx2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov ecx, JDIMENSION [out_width(eax)] ; num_cols test ecx, ecx @@ -81,7 +81,7 @@ EXTN(jsimd_ycc_rgb_convert_avx2): mov eax, INT [num_rows(eax)] test eax, eax jle near .return - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push eax push edi @@ -94,8 +94,8 @@ EXTN(jsimd_ycc_rgb_convert_avx2): mov ebx, JSAMPROW [ebx] ; inptr1 mov edx, JSAMPROW [edx] ; inptr2 mov edi, JSAMPROW [edi] ; outptr - movpic eax, POINTER [gotptr] ; load GOT address (eax) - alignx 16, 7 + MOVPIC eax, POINTER [gotptr] ; load GOT address (eax) + ALIGNX 16, 7 .columnloop: vmovdqu ymm5, YMMWORD [ebx] ; ymm5=Cb(0123456789ABCDEFGHIJKLMNOPQRSTUV) @@ -295,7 +295,7 @@ EXTN(jsimd_ycc_rgb_convert_avx2): add ebx, byte SIZEOF_YMMWORD ; inptr1 add edx, byte SIZEOF_YMMWORD ; inptr2 jmp near .columnloop - alignx 16, 7 + ALIGNX 16, 7 .column_st64: lea ecx, [ecx+ecx*2] ; imul ecx, RGB_PIXELSIZE @@ -436,7 +436,7 @@ EXTN(jsimd_ycc_rgb_convert_avx2): add ebx, byte SIZEOF_YMMWORD ; inptr1 add edx, byte SIZEOF_YMMWORD ; inptr2 jmp near .columnloop - alignx 16, 7 + ALIGNX 16, 7 .column_st64: cmp ecx, byte SIZEOF_YMMWORD/2 @@ -479,7 +479,7 @@ EXTN(jsimd_ycc_rgb_convert_avx2): %endif ; RGB_PIXELSIZE ; --------------- - alignx 16, 7 + ALIGNX 16, 7 .nextrow: pop ecx diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdcolext-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdcolext-mmx.asm index 5813cfcb66f5..d97faee004af 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdcolext-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdcolext-mmx.asm @@ -2,7 +2,7 @@ ; jdcolext.asm - colorspace conversion (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -49,15 +49,15 @@ EXTN(jsimd_ycc_rgb_convert_mmx): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov ecx, JDIMENSION [out_width(eax)] ; num_cols test ecx, ecx @@ -80,7 +80,7 @@ EXTN(jsimd_ycc_rgb_convert_mmx): mov eax, INT [num_rows(eax)] test eax, eax jle near .return - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push eax push edi @@ -93,8 +93,8 @@ EXTN(jsimd_ycc_rgb_convert_mmx): mov ebx, JSAMPROW [ebx] ; inptr1 mov edx, JSAMPROW [edx] ; inptr2 mov edi, JSAMPROW [edi] ; outptr - movpic eax, POINTER [gotptr] ; load GOT address (eax) - alignx 16, 7 + MOVPIC eax, POINTER [gotptr] ; load GOT address (eax) + ALIGNX 16, 7 .columnloop: movq mm5, MMWORD [ebx] ; mm5=Cb(01234567) @@ -255,7 +255,7 @@ EXTN(jsimd_ycc_rgb_convert_mmx): add edx, byte SIZEOF_MMWORD ; inptr2 add edi, byte RGB_PIXELSIZE*SIZEOF_MMWORD ; outptr jmp near .columnloop - alignx 16, 7 + ALIGNX 16, 7 .column_st16: lea ecx, [ecx+ecx*2] ; imul ecx, RGB_PIXELSIZE @@ -344,7 +344,7 @@ EXTN(jsimd_ycc_rgb_convert_mmx): add edx, byte SIZEOF_MMWORD ; inptr2 add edi, byte RGB_PIXELSIZE*SIZEOF_MMWORD ; outptr jmp near .columnloop - alignx 16, 7 + ALIGNX 16, 7 .column_st16: cmp ecx, byte SIZEOF_MMWORD/2 @@ -369,7 +369,7 @@ EXTN(jsimd_ycc_rgb_convert_mmx): %endif ; RGB_PIXELSIZE ; --------------- - alignx 16, 7 + ALIGNX 16, 7 .nextrow: pop ecx diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdcolext-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdcolext-sse2.asm index d5572b32946c..682efc730fc0 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdcolext-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdcolext-sse2.asm @@ -2,7 +2,7 @@ ; jdcolext.asm - colorspace conversion (SSE2) ; ; Copyright 2009, 2012 Pierre Ossman for Cendio AB -; Copyright (C) 2012, 2016, D. R. Commander. +; Copyright (C) 2012, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -49,15 +49,15 @@ EXTN(jsimd_ycc_rgb_convert_sse2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov ecx, JDIMENSION [out_width(eax)] ; num_cols test ecx, ecx @@ -80,7 +80,7 @@ EXTN(jsimd_ycc_rgb_convert_sse2): mov eax, INT [num_rows(eax)] test eax, eax jle near .return - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push eax push edi @@ -93,8 +93,8 @@ EXTN(jsimd_ycc_rgb_convert_sse2): mov ebx, JSAMPROW [ebx] ; inptr1 mov edx, JSAMPROW [edx] ; inptr2 mov edi, JSAMPROW [edi] ; outptr - movpic eax, POINTER [gotptr] ; load GOT address (eax) - alignx 16, 7 + MOVPIC eax, POINTER [gotptr] ; load GOT address (eax) + ALIGNX 16, 7 .columnloop: movdqa xmm5, XMMWORD [ebx] ; xmm5=Cb(0123456789ABCDEF) @@ -275,7 +275,7 @@ EXTN(jsimd_ycc_rgb_convert_sse2): add ebx, byte SIZEOF_XMMWORD ; inptr1 add edx, byte SIZEOF_XMMWORD ; inptr2 jmp near .columnloop - alignx 16, 7 + ALIGNX 16, 7 .column_st32: lea ecx, [ecx+ecx*2] ; imul ecx, RGB_PIXELSIZE @@ -387,7 +387,7 @@ EXTN(jsimd_ycc_rgb_convert_sse2): add ebx, byte SIZEOF_XMMWORD ; inptr1 add edx, byte SIZEOF_XMMWORD ; inptr2 jmp near .columnloop - alignx 16, 7 + ALIGNX 16, 7 .column_st32: cmp ecx, byte SIZEOF_XMMWORD/2 @@ -423,7 +423,7 @@ EXTN(jsimd_ycc_rgb_convert_sse2): %endif ; RGB_PIXELSIZE ; --------------- - alignx 16, 7 + ALIGNX 16, 7 .nextrow: pop ecx diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdcolor-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdcolor-avx2.asm index e05b60d00179..0f9baf840c58 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdcolor-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdcolor-avx2.asm @@ -3,7 +3,7 @@ ; ; Copyright 2009 Pierre Ossman for Cendio AB ; Copyright (C) 2015, Intel Corporation. -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -32,7 +32,7 @@ F_0_228 equ (131072 - F_1_772) ; FIX(2) - FIX(1.77200) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_ycc_rgb_convert_avx2) EXTN(jconst_ycc_rgb_convert_avx2): @@ -43,7 +43,7 @@ PW_MF0344_F0285 times 8 dw -F_0_344, F_0_285 PW_ONE times 16 dw 1 PD_ONEHALF times 8 dd 1 << (SCALEBITS - 1) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdcolor-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdcolor-mmx.asm index fb7e7bcce4b0..21e833292c0c 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdcolor-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdcolor-mmx.asm @@ -2,7 +2,7 @@ ; jdcolor.asm - colorspace conversion (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -31,7 +31,7 @@ F_0_228 equ (131072 - F_1_772) ; FIX(2) - FIX(1.77200) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_ycc_rgb_convert_mmx) EXTN(jconst_ycc_rgb_convert_mmx): @@ -42,7 +42,7 @@ PW_MF0344_F0285 times 2 dw -F_0_344, F_0_285 PW_ONE times 4 dw 1 PD_ONEHALF times 2 dd 1 << (SCALEBITS - 1) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdcolor-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdcolor-sse2.asm index b736255317e3..481d0e4c9578 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdcolor-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdcolor-sse2.asm @@ -2,7 +2,7 @@ ; jdcolor.asm - colorspace conversion (SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -31,7 +31,7 @@ F_0_228 equ (131072 - F_1_772) ; FIX(2) - FIX(1.77200) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_ycc_rgb_convert_sse2) EXTN(jconst_ycc_rgb_convert_sse2): @@ -42,7 +42,7 @@ PW_MF0344_F0285 times 4 dw -F_0_344, F_0_285 PW_ONE times 8 dw 1 PD_ONEHALF times 4 dd 1 << (SCALEBITS - 1) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdmerge-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdmerge-avx2.asm index 711e6792d0f5..00201dc419da 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdmerge-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdmerge-avx2.asm @@ -2,7 +2,7 @@ ; jdmerge.asm - merged upsampling/color conversion (AVX2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; ; Based on the x86 SIMD extension for IJG JPEG library @@ -32,7 +32,7 @@ F_0_228 equ (131072 - F_1_772) ; FIX(2) - FIX(1.77200) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_merged_upsample_avx2) EXTN(jconst_merged_upsample_avx2): @@ -43,7 +43,7 @@ PW_MF0344_F0285 times 8 dw -F_0_344, F_0_285 PW_ONE times 16 dw 1 PD_ONEHALF times 8 dd 1 << (SCALEBITS - 1) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdmerge-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdmerge-mmx.asm index 6e8311d40816..be28c63f539c 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdmerge-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdmerge-mmx.asm @@ -2,7 +2,7 @@ ; jdmerge.asm - merged upsampling/color conversion (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -31,7 +31,7 @@ F_0_228 equ (131072 - F_1_772) ; FIX(2) - FIX(1.77200) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_merged_upsample_mmx) EXTN(jconst_merged_upsample_mmx): @@ -42,7 +42,7 @@ PW_MF0344_F0285 times 2 dw -F_0_344, F_0_285 PW_ONE times 4 dw 1 PD_ONEHALF times 2 dd 1 << (SCALEBITS - 1) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdmerge-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdmerge-sse2.asm index e32f90aa1778..9b40a67dbd67 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdmerge-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdmerge-sse2.asm @@ -2,7 +2,7 @@ ; jdmerge.asm - merged upsampling/color conversion (SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -31,7 +31,7 @@ F_0_228 equ (131072 - F_1_772) ; FIX(2) - FIX(1.77200) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_merged_upsample_sse2) EXTN(jconst_merged_upsample_sse2): @@ -42,7 +42,7 @@ PW_MF0344_F0285 times 4 dw -F_0_344, F_0_285 PW_ONE times 8 dw 1 PD_ONEHALF times 4 dd 1 << (SCALEBITS - 1) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdmrgext-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdmrgext-avx2.asm index e35f7282bc41..97988eb60272 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdmrgext-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdmrgext-avx2.asm @@ -2,7 +2,7 @@ ; jdmrgext.asm - merged upsampling/color conversion (AVX2) ; ; Copyright 2009, 2012 Pierre Ossman for Cendio AB -; Copyright (C) 2012, 2016, D. R. Commander. +; Copyright (C) 2012, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; ; Based on the x86 SIMD extension for IJG JPEG library @@ -50,15 +50,15 @@ EXTN(jsimd_h2v1_merged_upsample_avx2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov ecx, JDIMENSION [output_width(eax)] ; col test ecx, ecx @@ -79,9 +79,9 @@ EXTN(jsimd_h2v1_merged_upsample_avx2): pop ecx ; col - alignx 16, 7 + ALIGNX 16, 7 .columnloop: - movpic eax, POINTER [gotptr] ; load GOT address (eax) + MOVPIC eax, POINTER [gotptr] ; load GOT address (eax) vmovdqu ymm6, YMMWORD [ebx] ; ymm6=Cb(0123456789ABCDEFGHIJKLMNOPQRSTUV) vmovdqu ymm7, YMMWORD [edx] ; ymm7=Cr(0123456789ABCDEFGHIJKLMNOPQRSTUV) @@ -168,13 +168,13 @@ EXTN(jsimd_h2v1_merged_upsample_avx2): mov al, 2 ; Yctr jmp short .Yloop_1st - alignx 16, 7 + ALIGNX 16, 7 .Yloop_2nd: vmovdqa ymm0, YMMWORD [wk(1)] ; ymm0=(R-Y)H vmovdqa ymm2, YMMWORD [wk(2)] ; ymm2=(G-Y)H vmovdqa ymm4, YMMWORD [wk(0)] ; ymm4=(B-Y)H - alignx 16, 7 + ALIGNX 16, 7 .Yloop_1st: vmovdqu ymm7, YMMWORD [esi] ; ymm7=Y(0123456789ABCDEFGHIJKLMNOPQRSTUV) @@ -301,7 +301,7 @@ EXTN(jsimd_h2v1_merged_upsample_avx2): add ebx, byte SIZEOF_YMMWORD ; inptr1 add edx, byte SIZEOF_YMMWORD ; inptr2 jmp near .columnloop - alignx 16, 7 + ALIGNX 16, 7 .column_st64: lea ecx, [ecx+ecx*2] ; imul ecx, RGB_PIXELSIZE @@ -445,7 +445,7 @@ EXTN(jsimd_h2v1_merged_upsample_avx2): add ebx, byte SIZEOF_YMMWORD ; inptr1 add edx, byte SIZEOF_YMMWORD ; inptr2 jmp near .columnloop - alignx 16, 7 + ALIGNX 16, 7 .column_st64: cmp ecx, byte SIZEOF_YMMWORD/2 diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdmrgext-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdmrgext-mmx.asm index eb3e36b4759b..79cee73dbdec 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdmrgext-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdmrgext-mmx.asm @@ -2,7 +2,7 @@ ; jdmrgext.asm - merged upsampling/color conversion (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -47,15 +47,15 @@ EXTN(jsimd_h2v1_merged_upsample_mmx): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov ecx, JDIMENSION [output_width(eax)] ; col test ecx, ecx @@ -76,9 +76,9 @@ EXTN(jsimd_h2v1_merged_upsample_mmx): pop ecx ; col - alignx 16, 7 + ALIGNX 16, 7 .columnloop: - movpic eax, POINTER [gotptr] ; load GOT address (eax) + MOVPIC eax, POINTER [gotptr] ; load GOT address (eax) movq mm6, MMWORD [ebx] ; mm6=Cb(01234567) movq mm7, MMWORD [edx] ; mm7=Cr(01234567) @@ -171,13 +171,13 @@ EXTN(jsimd_h2v1_merged_upsample_mmx): mov al, 2 ; Yctr jmp short .Yloop_1st - alignx 16, 7 + ALIGNX 16, 7 .Yloop_2nd: movq mm0, MMWORD [wk(1)] ; mm0=(R-Y)H movq mm2, MMWORD [wk(2)] ; mm2=(G-Y)H movq mm4, MMWORD [wk(0)] ; mm4=(B-Y)H - alignx 16, 7 + ALIGNX 16, 7 .Yloop_1st: movq mm7, MMWORD [esi] ; mm7=Y(01234567) @@ -258,7 +258,7 @@ EXTN(jsimd_h2v1_merged_upsample_mmx): add ebx, byte SIZEOF_MMWORD ; inptr1 add edx, byte SIZEOF_MMWORD ; inptr2 jmp near .columnloop - alignx 16, 7 + ALIGNX 16, 7 .column_st16: lea ecx, [ecx+ecx*2] ; imul ecx, RGB_PIXELSIZE @@ -350,7 +350,7 @@ EXTN(jsimd_h2v1_merged_upsample_mmx): add ebx, byte SIZEOF_MMWORD ; inptr1 add edx, byte SIZEOF_MMWORD ; inptr2 jmp near .columnloop - alignx 16, 7 + ALIGNX 16, 7 .column_st16: cmp ecx, byte SIZEOF_MMWORD/2 diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdmrgext-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdmrgext-sse2.asm index c113dc4d27ed..331344358b19 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdmrgext-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdmrgext-sse2.asm @@ -2,7 +2,7 @@ ; jdmrgext.asm - merged upsampling/color conversion (SSE2) ; ; Copyright 2009, 2012 Pierre Ossman for Cendio AB -; Copyright (C) 2012, 2016, D. R. Commander. +; Copyright (C) 2012, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -49,15 +49,15 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov ecx, JDIMENSION [output_width(eax)] ; col test ecx, ecx @@ -78,9 +78,9 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): pop ecx ; col - alignx 16, 7 + ALIGNX 16, 7 .columnloop: - movpic eax, POINTER [gotptr] ; load GOT address (eax) + MOVPIC eax, POINTER [gotptr] ; load GOT address (eax) movdqa xmm6, XMMWORD [ebx] ; xmm6=Cb(0123456789ABCDEF) movdqa xmm7, XMMWORD [edx] ; xmm7=Cr(0123456789ABCDEF) @@ -173,13 +173,13 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): mov al, 2 ; Yctr jmp short .Yloop_1st - alignx 16, 7 + ALIGNX 16, 7 .Yloop_2nd: movdqa xmm0, XMMWORD [wk(1)] ; xmm0=(R-Y)H movdqa xmm2, XMMWORD [wk(2)] ; xmm2=(G-Y)H movdqa xmm4, XMMWORD [wk(0)] ; xmm4=(B-Y)H - alignx 16, 7 + ALIGNX 16, 7 .Yloop_1st: movdqa xmm7, XMMWORD [esi] ; xmm7=Y(0123456789ABCDEF) @@ -280,7 +280,7 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): add ebx, byte SIZEOF_XMMWORD ; inptr1 add edx, byte SIZEOF_XMMWORD ; inptr2 jmp near .columnloop - alignx 16, 7 + ALIGNX 16, 7 .column_st32: lea ecx, [ecx+ecx*2] ; imul ecx, RGB_PIXELSIZE @@ -395,7 +395,7 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): add ebx, byte SIZEOF_XMMWORD ; inptr1 add edx, byte SIZEOF_XMMWORD ; inptr2 jmp near .columnloop - alignx 16, 7 + ALIGNX 16, 7 .column_st32: cmp ecx, byte SIZEOF_XMMWORD/2 diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdsample-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdsample-avx2.asm index a800c35e0835..b0507aa5d610 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdsample-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdsample-avx2.asm @@ -3,7 +3,7 @@ ; ; Copyright 2009 Pierre Ossman for Cendio AB ; Copyright (C) 2015, Intel Corporation. -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -20,7 +20,7 @@ ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fancy_upsample_avx2) EXTN(jconst_fancy_upsample_avx2): @@ -31,7 +31,7 @@ PW_THREE times 16 dw 3 PW_SEVEN times 16 dw 7 PW_EIGHT times 16 dw 8 - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -62,13 +62,13 @@ PW_EIGHT times 16 dw 8 EXTN(jsimd_h2v1_fancy_upsample_avx2): push ebp mov ebp, esp - pushpic ebx + PUSHPIC ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address mov eax, JDIMENSION [downsamp_width(ebp)] ; colctr test eax, eax @@ -81,7 +81,7 @@ EXTN(jsimd_h2v1_fancy_upsample_avx2): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, POINTER [output_data_ptr(ebp)] mov edi, JSAMPARRAY [edi] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push eax ; colctr push edi @@ -104,7 +104,7 @@ EXTN(jsimd_h2v1_fancy_upsample_avx2): and eax, byte -SIZEOF_YMMWORD cmp eax, byte SIZEOF_YMMWORD ja short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .columnloop_last: vpcmpeqb xmm6, xmm6, xmm6 @@ -112,7 +112,7 @@ EXTN(jsimd_h2v1_fancy_upsample_avx2): vperm2i128 ymm6, ymm6, ymm6, 1 ; (---- ---- ... ---- ---- ff) MSB is ff vpand ymm6, ymm6, YMMWORD [esi+0*SIZEOF_YMMWORD] jmp short .upsample - alignx 16, 7 + ALIGNX 16, 7 .columnloop: vmovdqu ymm6, YMMWORD [esi+1*SIZEOF_YMMWORD] @@ -196,7 +196,7 @@ EXTN(jsimd_h2v1_fancy_upsample_avx2): pop esi ; pop edx ; need not be preserved ; pop ecx ; need not be preserved - poppic ebx + POPPIC ebx pop ebp ret @@ -234,15 +234,15 @@ EXTN(jsimd_h2v2_fancy_upsample_avx2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov edx, eax ; edx = original ebp mov eax, JDIMENSION [downsamp_width(edx)] ; colctr @@ -256,7 +256,7 @@ EXTN(jsimd_h2v2_fancy_upsample_avx2): mov esi, JSAMPARRAY [input_data(edx)] ; input_data mov edi, POINTER [output_data_ptr(edx)] mov edi, JSAMPARRAY [edi] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push eax ; colctr push ecx @@ -286,8 +286,8 @@ EXTN(jsimd_h2v2_fancy_upsample_avx2): vmovdqu ymm1, YMMWORD [ecx+0*SIZEOF_YMMWORD] ; ymm1=row[-1][0] vmovdqu ymm2, YMMWORD [esi+0*SIZEOF_YMMWORD] ; ymm2=row[+1][0] - pushpic ebx - movpic ebx, POINTER [gotptr] ; load GOT address + PUSHPIC ebx + MOVPIC ebx, POINTER [gotptr] ; load GOT address vpxor ymm3, ymm3, ymm3 ; ymm3=(all 0's) @@ -328,19 +328,19 @@ EXTN(jsimd_h2v2_fancy_upsample_avx2): vmovdqa YMMWORD [wk(0)], ymm1 vmovdqa YMMWORD [wk(1)], ymm2 - poppic ebx + POPPIC ebx add eax, byte SIZEOF_YMMWORD-1 and eax, byte -SIZEOF_YMMWORD cmp eax, byte SIZEOF_YMMWORD ja short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .columnloop_last: ; -- process the last column block - pushpic ebx - movpic ebx, POINTER [gotptr] ; load GOT address + PUSHPIC ebx + MOVPIC ebx, POINTER [gotptr] ; load GOT address vpcmpeqb xmm1, xmm1, xmm1 vpslldq xmm1, xmm1, (SIZEOF_XMMWORD-2) @@ -353,7 +353,7 @@ EXTN(jsimd_h2v2_fancy_upsample_avx2): vmovdqa YMMWORD [wk(3)], ymm2 ; ymm2=(-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 31) jmp near .upsample - alignx 16, 7 + ALIGNX 16, 7 .columnloop: ; -- process the next column block @@ -362,8 +362,8 @@ EXTN(jsimd_h2v2_fancy_upsample_avx2): vmovdqu ymm1, YMMWORD [ecx+1*SIZEOF_YMMWORD] ; ymm1=row[-1][1] vmovdqu ymm2, YMMWORD [esi+1*SIZEOF_YMMWORD] ; ymm2=row[+1][1] - pushpic ebx - movpic ebx, POINTER [gotptr] ; load GOT address + PUSHPIC ebx + MOVPIC ebx, POINTER [gotptr] ; load GOT address vpxor ymm3, ymm3, ymm3 ; ymm3=(all 0's) @@ -516,7 +516,7 @@ EXTN(jsimd_h2v2_fancy_upsample_avx2): vmovdqu YMMWORD [edi+0*SIZEOF_YMMWORD], ymm1 vmovdqu YMMWORD [edi+1*SIZEOF_YMMWORD], ymm0 - poppic ebx + POPPIC ebx sub eax, byte SIZEOF_YMMWORD add ecx, byte 1*SIZEOF_YMMWORD ; inptr1(above) @@ -590,7 +590,7 @@ EXTN(jsimd_h2v1_upsample_avx2): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, POINTER [output_data_ptr(ebp)] mov edi, JSAMPARRAY [edi] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push edi push esi @@ -598,7 +598,7 @@ EXTN(jsimd_h2v1_upsample_avx2): mov esi, JSAMPROW [esi] ; inptr mov edi, JSAMPROW [edi] ; outptr mov eax, edx ; colctr - alignx 16, 7 + ALIGNX 16, 7 .columnloop: cmp eax, byte SIZEOF_YMMWORD @@ -629,7 +629,7 @@ EXTN(jsimd_h2v1_upsample_avx2): add esi, byte SIZEOF_YMMWORD ; inptr add edi, byte 2*SIZEOF_YMMWORD ; outptr jmp short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .nextrow: pop esi @@ -689,7 +689,7 @@ EXTN(jsimd_h2v2_upsample_avx2): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, POINTER [output_data_ptr(ebp)] mov edi, JSAMPARRAY [edi] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push edi push esi @@ -698,7 +698,7 @@ EXTN(jsimd_h2v2_upsample_avx2): mov ebx, JSAMPROW [edi+0*SIZEOF_JSAMPROW] ; outptr0 mov edi, JSAMPROW [edi+1*SIZEOF_JSAMPROW] ; outptr1 mov eax, edx ; colctr - alignx 16, 7 + ALIGNX 16, 7 .columnloop: cmp eax, byte SIZEOF_YMMWORD @@ -734,7 +734,7 @@ EXTN(jsimd_h2v2_upsample_avx2): add ebx, 2*SIZEOF_YMMWORD ; outptr0 add edi, 2*SIZEOF_YMMWORD ; outptr1 jmp short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .nextrow: pop esi diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdsample-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdsample-mmx.asm index 12c49f0eab57..6f70499c9777 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdsample-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdsample-mmx.asm @@ -2,7 +2,7 @@ ; jdsample.asm - upsampling (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -19,7 +19,7 @@ ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fancy_upsample_mmx) EXTN(jconst_fancy_upsample_mmx): @@ -30,7 +30,7 @@ PW_THREE times 4 dw 3 PW_SEVEN times 4 dw 7 PW_EIGHT times 4 dw 8 - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -61,13 +61,13 @@ PW_EIGHT times 4 dw 8 EXTN(jsimd_h2v1_fancy_upsample_mmx): push ebp mov ebp, esp - pushpic ebx + PUSHPIC ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address mov eax, JDIMENSION [downsamp_width(ebp)] ; colctr test eax, eax @@ -80,7 +80,7 @@ EXTN(jsimd_h2v1_fancy_upsample_mmx): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, POINTER [output_data_ptr(ebp)] mov edi, JSAMPARRAY [edi] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push eax ; colctr push edi @@ -103,14 +103,14 @@ EXTN(jsimd_h2v1_fancy_upsample_mmx): and eax, byte -SIZEOF_MMWORD cmp eax, byte SIZEOF_MMWORD ja short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .columnloop_last: pcmpeqb mm6, mm6 psllq mm6, (SIZEOF_MMWORD-1)*BYTE_BIT pand mm6, MMWORD [esi+0*SIZEOF_MMWORD] jmp short .upsample - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movq mm6, MMWORD [esi+1*SIZEOF_MMWORD] @@ -187,7 +187,7 @@ EXTN(jsimd_h2v1_fancy_upsample_mmx): pop esi ; pop edx ; need not be preserved ; pop ecx ; need not be preserved - poppic ebx + POPPIC ebx pop ebp ret @@ -224,15 +224,15 @@ EXTN(jsimd_h2v2_fancy_upsample_mmx): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov edx, eax ; edx = original ebp mov eax, JDIMENSION [downsamp_width(edx)] ; colctr @@ -246,7 +246,7 @@ EXTN(jsimd_h2v2_fancy_upsample_mmx): mov esi, JSAMPARRAY [input_data(edx)] ; input_data mov edi, POINTER [output_data_ptr(edx)] mov edi, JSAMPARRAY [edi] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push eax ; colctr push ecx @@ -276,8 +276,8 @@ EXTN(jsimd_h2v2_fancy_upsample_mmx): movq mm1, MMWORD [ecx+0*SIZEOF_MMWORD] ; mm1=row[-1][0] movq mm2, MMWORD [esi+0*SIZEOF_MMWORD] ; mm2=row[+1][0] - pushpic ebx - movpic ebx, POINTER [gotptr] ; load GOT address + PUSHPIC ebx + MOVPIC ebx, POINTER [gotptr] ; load GOT address pxor mm3, mm3 ; mm3=(all 0's) movq mm4, mm0 @@ -312,19 +312,19 @@ EXTN(jsimd_h2v2_fancy_upsample_mmx): movq MMWORD [wk(0)], mm1 movq MMWORD [wk(1)], mm2 - poppic ebx + POPPIC ebx add eax, byte SIZEOF_MMWORD-1 and eax, byte -SIZEOF_MMWORD cmp eax, byte SIZEOF_MMWORD ja short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .columnloop_last: ; -- process the last column block - pushpic ebx - movpic ebx, POINTER [gotptr] ; load GOT address + PUSHPIC ebx + MOVPIC ebx, POINTER [gotptr] ; load GOT address pcmpeqb mm1, mm1 psllq mm1, (SIZEOF_MMWORD-2)*BYTE_BIT @@ -337,7 +337,7 @@ EXTN(jsimd_h2v2_fancy_upsample_mmx): movq MMWORD [wk(3)], mm2 jmp short .upsample - alignx 16, 7 + ALIGNX 16, 7 .columnloop: ; -- process the next column block @@ -346,8 +346,8 @@ EXTN(jsimd_h2v2_fancy_upsample_mmx): movq mm1, MMWORD [ecx+1*SIZEOF_MMWORD] ; mm1=row[-1][1] movq mm2, MMWORD [esi+1*SIZEOF_MMWORD] ; mm2=row[+1][1] - pushpic ebx - movpic ebx, POINTER [gotptr] ; load GOT address + PUSHPIC ebx + MOVPIC ebx, POINTER [gotptr] ; load GOT address pxor mm3, mm3 ; mm3=(all 0's) movq mm4, mm0 @@ -486,7 +486,7 @@ EXTN(jsimd_h2v2_fancy_upsample_mmx): movq MMWORD [edi+0*SIZEOF_MMWORD], mm1 movq MMWORD [edi+1*SIZEOF_MMWORD], mm0 - poppic ebx + POPPIC ebx sub eax, byte SIZEOF_MMWORD add ecx, byte 1*SIZEOF_MMWORD ; inptr1(above) @@ -561,7 +561,7 @@ EXTN(jsimd_h2v1_upsample_mmx): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, POINTER [output_data_ptr(ebp)] mov edi, JSAMPARRAY [edi] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push edi push esi @@ -569,7 +569,7 @@ EXTN(jsimd_h2v1_upsample_mmx): mov esi, JSAMPROW [esi] ; inptr mov edi, JSAMPROW [edi] ; outptr mov eax, edx ; colctr - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movq mm0, MMWORD [esi+0*SIZEOF_MMWORD] @@ -599,7 +599,7 @@ EXTN(jsimd_h2v1_upsample_mmx): add esi, byte 2*SIZEOF_MMWORD ; inptr add edi, byte 4*SIZEOF_MMWORD ; outptr jmp short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .nextrow: pop esi @@ -660,7 +660,7 @@ EXTN(jsimd_h2v2_upsample_mmx): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, POINTER [output_data_ptr(ebp)] mov edi, JSAMPARRAY [edi] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push edi push esi @@ -669,7 +669,7 @@ EXTN(jsimd_h2v2_upsample_mmx): mov ebx, JSAMPROW [edi+0*SIZEOF_JSAMPROW] ; outptr0 mov edi, JSAMPROW [edi+1*SIZEOF_JSAMPROW] ; outptr1 mov eax, edx ; colctr - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movq mm0, MMWORD [esi+0*SIZEOF_MMWORD] @@ -704,7 +704,7 @@ EXTN(jsimd_h2v2_upsample_mmx): add ebx, byte 4*SIZEOF_MMWORD ; outptr0 add edi, byte 4*SIZEOF_MMWORD ; outptr1 jmp short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .nextrow: pop esi diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jdsample-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jdsample-sse2.asm index 4e28d2f4b802..f68c5ea54500 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jdsample-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jdsample-sse2.asm @@ -2,7 +2,7 @@ ; jdsample.asm - upsampling (SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -19,7 +19,7 @@ ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fancy_upsample_sse2) EXTN(jconst_fancy_upsample_sse2): @@ -30,7 +30,7 @@ PW_THREE times 8 dw 3 PW_SEVEN times 8 dw 7 PW_EIGHT times 8 dw 8 - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -61,13 +61,13 @@ PW_EIGHT times 8 dw 8 EXTN(jsimd_h2v1_fancy_upsample_sse2): push ebp mov ebp, esp - pushpic ebx + PUSHPIC ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address mov eax, JDIMENSION [downsamp_width(ebp)] ; colctr test eax, eax @@ -80,7 +80,7 @@ EXTN(jsimd_h2v1_fancy_upsample_sse2): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, POINTER [output_data_ptr(ebp)] mov edi, JSAMPARRAY [edi] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push eax ; colctr push edi @@ -103,14 +103,14 @@ EXTN(jsimd_h2v1_fancy_upsample_sse2): and eax, byte -SIZEOF_XMMWORD cmp eax, byte SIZEOF_XMMWORD ja short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .columnloop_last: pcmpeqb xmm6, xmm6 pslldq xmm6, (SIZEOF_XMMWORD-1) pand xmm6, XMMWORD [esi+0*SIZEOF_XMMWORD] jmp short .upsample - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movdqa xmm6, XMMWORD [esi+1*SIZEOF_XMMWORD] @@ -185,7 +185,7 @@ EXTN(jsimd_h2v1_fancy_upsample_sse2): pop esi ; pop edx ; need not be preserved ; pop ecx ; need not be preserved - poppic ebx + POPPIC ebx pop ebp ret @@ -223,15 +223,15 @@ EXTN(jsimd_h2v2_fancy_upsample_sse2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic eax ; make a room for GOT address + PUSHPIC eax ; make a room for GOT address push ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address - movpic POINTER [gotptr], ebx ; save GOT address + GET_GOT ebx ; get GOT address + MOVPIC POINTER [gotptr], ebx ; save GOT address mov edx, eax ; edx = original ebp mov eax, JDIMENSION [downsamp_width(edx)] ; colctr @@ -245,7 +245,7 @@ EXTN(jsimd_h2v2_fancy_upsample_sse2): mov esi, JSAMPARRAY [input_data(edx)] ; input_data mov edi, POINTER [output_data_ptr(edx)] mov edi, JSAMPARRAY [edi] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push eax ; colctr push ecx @@ -275,8 +275,8 @@ EXTN(jsimd_h2v2_fancy_upsample_sse2): movdqa xmm1, XMMWORD [ecx+0*SIZEOF_XMMWORD] ; xmm1=row[-1][0] movdqa xmm2, XMMWORD [esi+0*SIZEOF_XMMWORD] ; xmm2=row[+1][0] - pushpic ebx - movpic ebx, POINTER [gotptr] ; load GOT address + PUSHPIC ebx + MOVPIC ebx, POINTER [gotptr] ; load GOT address pxor xmm3, xmm3 ; xmm3=(all 0's) movdqa xmm4, xmm0 @@ -311,19 +311,19 @@ EXTN(jsimd_h2v2_fancy_upsample_sse2): movdqa XMMWORD [wk(0)], xmm1 movdqa XMMWORD [wk(1)], xmm2 - poppic ebx + POPPIC ebx add eax, byte SIZEOF_XMMWORD-1 and eax, byte -SIZEOF_XMMWORD cmp eax, byte SIZEOF_XMMWORD ja short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .columnloop_last: ; -- process the last column block - pushpic ebx - movpic ebx, POINTER [gotptr] ; load GOT address + PUSHPIC ebx + MOVPIC ebx, POINTER [gotptr] ; load GOT address pcmpeqb xmm1, xmm1 pslldq xmm1, (SIZEOF_XMMWORD-2) @@ -336,7 +336,7 @@ EXTN(jsimd_h2v2_fancy_upsample_sse2): movdqa XMMWORD [wk(3)], xmm2 ; xmm2=(-- -- -- -- -- -- -- 15) jmp near .upsample - alignx 16, 7 + ALIGNX 16, 7 .columnloop: ; -- process the next column block @@ -345,8 +345,8 @@ EXTN(jsimd_h2v2_fancy_upsample_sse2): movdqa xmm1, XMMWORD [ecx+1*SIZEOF_XMMWORD] ; xmm1=row[-1][1] movdqa xmm2, XMMWORD [esi+1*SIZEOF_XMMWORD] ; xmm2=row[+1][1] - pushpic ebx - movpic ebx, POINTER [gotptr] ; load GOT address + PUSHPIC ebx + MOVPIC ebx, POINTER [gotptr] ; load GOT address pxor xmm3, xmm3 ; xmm3=(all 0's) movdqa xmm4, xmm0 @@ -485,7 +485,7 @@ EXTN(jsimd_h2v2_fancy_upsample_sse2): movdqa XMMWORD [edi+0*SIZEOF_XMMWORD], xmm1 movdqa XMMWORD [edi+1*SIZEOF_XMMWORD], xmm0 - poppic ebx + POPPIC ebx sub eax, byte SIZEOF_XMMWORD add ecx, byte 1*SIZEOF_XMMWORD ; inptr1(above) @@ -558,7 +558,7 @@ EXTN(jsimd_h2v1_upsample_sse2): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, POINTER [output_data_ptr(ebp)] mov edi, JSAMPARRAY [edi] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push edi push esi @@ -566,7 +566,7 @@ EXTN(jsimd_h2v1_upsample_sse2): mov esi, JSAMPROW [esi] ; inptr mov edi, JSAMPROW [edi] ; outptr mov eax, edx ; colctr - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movdqa xmm0, XMMWORD [esi+0*SIZEOF_XMMWORD] @@ -596,7 +596,7 @@ EXTN(jsimd_h2v1_upsample_sse2): add esi, byte 2*SIZEOF_XMMWORD ; inptr add edi, byte 4*SIZEOF_XMMWORD ; outptr jmp short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .nextrow: pop esi @@ -655,7 +655,7 @@ EXTN(jsimd_h2v2_upsample_sse2): mov esi, JSAMPARRAY [input_data(ebp)] ; input_data mov edi, POINTER [output_data_ptr(ebp)] mov edi, JSAMPARRAY [edi] ; output_data - alignx 16, 7 + ALIGNX 16, 7 .rowloop: push edi push esi @@ -664,7 +664,7 @@ EXTN(jsimd_h2v2_upsample_sse2): mov ebx, JSAMPROW [edi+0*SIZEOF_JSAMPROW] ; outptr0 mov edi, JSAMPROW [edi+1*SIZEOF_JSAMPROW] ; outptr1 mov eax, edx ; colctr - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movdqa xmm0, XMMWORD [esi+0*SIZEOF_XMMWORD] @@ -699,7 +699,7 @@ EXTN(jsimd_h2v2_upsample_sse2): add ebx, byte 4*SIZEOF_XMMWORD ; outptr0 add edi, byte 4*SIZEOF_XMMWORD ; outptr1 jmp short .columnloop - alignx 16, 7 + ALIGNX 16, 7 .nextrow: pop esi diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jfdctflt-3dn.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jfdctflt-3dn.asm index 322ab1632526..34af2bf0ba0f 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jfdctflt-3dn.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jfdctflt-3dn.asm @@ -2,7 +2,7 @@ ; jfdctflt.asm - floating-point FDCT (3DNow!) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -24,7 +24,7 @@ ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fdct_float_3dnow) EXTN(jconst_fdct_float_3dnow): @@ -34,7 +34,7 @@ PD_0_707 times 2 dd 0.707106781186547524400844 PD_0_541 times 2 dd 0.541196100146196984399723 PD_1_306 times 2 dd 1.306562964876376527856643 - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -63,19 +63,19 @@ EXTN(jsimd_fdct_float_3dnow): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic ebx + PUSHPIC ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved ; push esi ; unused ; push edi ; unused - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process rows. mov edx, POINTER [data(eax)] ; (FAST_FLOAT *) mov ecx, DCTSIZE/2 - alignx 16, 7 + ALIGNX 16, 7 .rowloop: movq mm0, MMWORD [MMBLOCK(0,0,edx,SIZEOF_FAST_FLOAT)] @@ -190,7 +190,7 @@ EXTN(jsimd_fdct_float_3dnow): mov edx, POINTER [data(eax)] ; (FAST_FLOAT *) mov ecx, DCTSIZE/2 - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movq mm0, MMWORD [MMBLOCK(0,0,edx,SIZEOF_FAST_FLOAT)] @@ -307,7 +307,7 @@ EXTN(jsimd_fdct_float_3dnow): ; pop esi ; unused ; pop edx ; need not be preserved ; pop ecx ; need not be preserved - poppic ebx + POPPIC ebx mov esp, ebp ; esp <- aligned ebp pop esp ; esp <- original ebp pop ebp diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jfdctflt-sse.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jfdctflt-sse.asm index 86952c6499cf..d247094b648b 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jfdctflt-sse.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jfdctflt-sse.asm @@ -2,7 +2,7 @@ ; jfdctflt.asm - floating-point FDCT (SSE) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -34,7 +34,7 @@ ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fdct_float_sse) EXTN(jconst_fdct_float_sse): @@ -44,7 +44,7 @@ PD_0_707 times 4 dd 0.707106781186547524400844 PD_0_541 times 4 dd 0.541196100146196984399723 PD_1_306 times 4 dd 1.306562964876376527856643 - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -74,19 +74,19 @@ EXTN(jsimd_fdct_float_sse): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic ebx + PUSHPIC ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved ; push esi ; unused ; push edi ; unused - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process rows. mov edx, POINTER [data(eax)] ; (FAST_FLOAT *) mov ecx, DCTSIZE/4 - alignx 16, 7 + ALIGNX 16, 7 .rowloop: movaps xmm0, XMMWORD [XMMBLOCK(2,0,edx,SIZEOF_FAST_FLOAT)] @@ -222,7 +222,7 @@ EXTN(jsimd_fdct_float_sse): mov edx, POINTER [data(eax)] ; (FAST_FLOAT *) mov ecx, DCTSIZE/4 - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movaps xmm0, XMMWORD [XMMBLOCK(2,0,edx,SIZEOF_FAST_FLOAT)] @@ -358,7 +358,7 @@ EXTN(jsimd_fdct_float_sse): ; pop esi ; unused ; pop edx ; need not be preserved ; pop ecx ; need not be preserved - poppic ebx + POPPIC ebx mov esp, ebp ; esp <- aligned ebp pop esp ; esp <- original ebp pop ebp diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jfdctfst-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jfdctfst-mmx.asm index 80645a50d7e7..8c55a9876dc4 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jfdctfst-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jfdctfst-mmx.asm @@ -2,7 +2,7 @@ ; jfdctfst.asm - fast integer FDCT (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -49,7 +49,7 @@ F_1_306 equ DESCALE(1402911301, 30 - CONST_BITS) ; FIX(1.306562965) %define PRE_MULTIPLY_SCALE_BITS 2 %define CONST_SHIFT (16 - PRE_MULTIPLY_SCALE_BITS - CONST_BITS) - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fdct_ifast_mmx) EXTN(jconst_fdct_ifast_mmx): @@ -59,7 +59,7 @@ PW_F0382 times 4 dw F_0_382 << CONST_SHIFT PW_F0541 times 4 dw F_0_541 << CONST_SHIFT PW_F1306 times 4 dw F_1_306 << CONST_SHIFT - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -88,19 +88,19 @@ EXTN(jsimd_fdct_ifast_mmx): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic ebx + PUSHPIC ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved ; push esi ; unused ; push edi ; unused - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process rows. mov edx, POINTER [data(eax)] ; (DCTELEM *) mov ecx, DCTSIZE/4 - alignx 16, 7 + ALIGNX 16, 7 .rowloop: movq mm0, MMWORD [MMBLOCK(2,0,edx,SIZEOF_DCTELEM)] @@ -241,7 +241,7 @@ EXTN(jsimd_fdct_ifast_mmx): mov edx, POINTER [data(eax)] ; (DCTELEM *) mov ecx, DCTSIZE/4 - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movq mm0, MMWORD [MMBLOCK(2,0,edx,SIZEOF_DCTELEM)] @@ -384,7 +384,7 @@ EXTN(jsimd_fdct_ifast_mmx): ; pop esi ; unused ; pop edx ; need not be preserved ; pop ecx ; need not be preserved - poppic ebx + POPPIC ebx mov esp, ebp ; esp <- aligned ebp pop esp ; esp <- original ebp pop ebp diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jfdctfst-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jfdctfst-sse2.asm index 446fa7a68f78..c1ba533d6d88 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jfdctfst-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jfdctfst-sse2.asm @@ -2,7 +2,7 @@ ; jfdctfst.asm - fast integer FDCT (SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -49,7 +49,7 @@ F_1_306 equ DESCALE(1402911301, 30 - CONST_BITS) ; FIX(1.306562965) %define PRE_MULTIPLY_SCALE_BITS 2 %define CONST_SHIFT (16 - PRE_MULTIPLY_SCALE_BITS - CONST_BITS) - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fdct_ifast_sse2) EXTN(jconst_fdct_ifast_sse2): @@ -59,7 +59,7 @@ PW_F0382 times 8 dw F_0_382 << CONST_SHIFT PW_F0541 times 8 dw F_0_541 << CONST_SHIFT PW_F1306 times 8 dw F_1_306 << CONST_SHIFT - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -89,13 +89,13 @@ EXTN(jsimd_fdct_ifast_sse2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic ebx + PUSHPIC ebx ; push ecx ; unused ; push edx ; need not be preserved ; push esi ; unused ; push edi ; unused - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process rows. @@ -392,7 +392,7 @@ EXTN(jsimd_fdct_ifast_sse2): ; pop esi ; unused ; pop edx ; need not be preserved ; pop ecx ; unused - poppic ebx + POPPIC ebx mov esp, ebp ; esp <- aligned ebp pop esp ; esp <- original ebp pop ebp diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jfdctint-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jfdctint-avx2.asm index 23cf733135bb..21c3d5b22375 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jfdctint-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jfdctint-avx2.asm @@ -2,7 +2,7 @@ ; jfdctint.asm - accurate integer FDCT (AVX2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, 2018, 2020, D. R. Commander. +; Copyright (C) 2009, 2016, 2018, 2020, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -65,7 +65,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; %1-%4: Input/output registers ; %5-%8: Temp registers -%macro dotranspose 8 +%macro DOTRANSPOSE 8 ; %1=(00 01 02 03 04 05 06 07 40 41 42 43 44 45 46 47) ; %2=(10 11 12 13 14 15 16 17 50 51 52 53 54 55 56 57) ; %3=(20 21 22 23 24 25 26 27 60 61 62 63 64 65 66 67) @@ -108,7 +108,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; %5-%8: Temp registers ; %9: Pass (1 or 2) -%macro dodct 9 +%macro DODCT 9 vpsubw %5, %1, %4 ; %5=data1_0-data6_7=tmp6_7 vpaddw %6, %1, %4 ; %6=data1_0+data6_7=tmp1_0 vpaddw %7, %2, %3 ; %7=data3_2+data4_5=tmp3_2 @@ -223,7 +223,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fdct_islow_avx2) EXTN(jconst_fdct_islow_avx2): @@ -242,7 +242,7 @@ PW_DESCALE_P2X times 16 dw 1 << (PASS1_BITS - 1) PW_1_NEG1 times 8 dw 1 times 8 dw -1 - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -262,13 +262,13 @@ PW_1_NEG1 times 8 dw 1 EXTN(jsimd_fdct_islow_avx2): push ebp mov ebp, esp - pushpic ebx + PUSHPIC ebx ; push ecx ; unused ; push edx ; need not be preserved ; push esi ; unused ; push edi ; unused - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process rows. @@ -292,9 +292,9 @@ EXTN(jsimd_fdct_islow_avx2): ; ymm2=(20 21 22 23 24 25 26 27 60 61 62 63 64 65 66 67) ; ymm3=(30 31 32 33 34 35 36 37 70 71 72 73 74 75 76 77) - dotranspose ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7 + DOTRANSPOSE ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7 - dodct ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7, 1 + DODCT ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7, 1 ; ymm0=data0_4, ymm1=data3_1, ymm2=data2_6, ymm3=data7_5 ; ---- Pass 2: process columns. @@ -302,9 +302,9 @@ EXTN(jsimd_fdct_islow_avx2): vperm2i128 ymm4, ymm1, ymm3, 0x20 ; ymm4=data3_7 vperm2i128 ymm1, ymm1, ymm3, 0x31 ; ymm1=data1_5 - dotranspose ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7 + DOTRANSPOSE ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7 - dodct ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7, 2 + DODCT ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7, 2 ; ymm0=data0_4, ymm1=data3_1, ymm2=data2_6, ymm4=data7_5 vperm2i128 ymm3, ymm0, ymm1, 0x30 ; ymm3=data0_1 @@ -322,7 +322,7 @@ EXTN(jsimd_fdct_islow_avx2): ; pop esi ; unused ; pop edx ; need not be preserved ; pop ecx ; unused - poppic ebx + POPPIC ebx pop ebp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jfdctint-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jfdctint-mmx.asm index 34a43b9e5ef6..c2f308ed3b62 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jfdctint-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jfdctint-mmx.asm @@ -2,7 +2,7 @@ ; jfdctint.asm - accurate integer FDCT (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, 2020, D. R. Commander. +; Copyright (C) 2016, 2020, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -63,7 +63,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fdct_islow_mmx) EXTN(jconst_fdct_islow_mmx): @@ -80,7 +80,7 @@ PD_DESCALE_P1 times 2 dd 1 << (DESCALE_P1 - 1) PD_DESCALE_P2 times 2 dd 1 << (DESCALE_P2 - 1) PW_DESCALE_P2X times 4 dw 1 << (PASS1_BITS - 1) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -109,19 +109,19 @@ EXTN(jsimd_fdct_islow_mmx): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic ebx + PUSHPIC ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved ; push esi ; unused ; push edi ; unused - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process rows. mov edx, POINTER [data(eax)] ; (DCTELEM *) mov ecx, DCTSIZE/4 - alignx 16, 7 + ALIGNX 16, 7 .rowloop: movq mm0, MMWORD [MMBLOCK(2,0,edx,SIZEOF_DCTELEM)] @@ -363,7 +363,7 @@ EXTN(jsimd_fdct_islow_mmx): mov edx, POINTER [data(eax)] ; (DCTELEM *) mov ecx, DCTSIZE/4 - alignx 16, 7 + ALIGNX 16, 7 .columnloop: movq mm0, MMWORD [MMBLOCK(2,0,edx,SIZEOF_DCTELEM)] @@ -609,7 +609,7 @@ EXTN(jsimd_fdct_islow_mmx): ; pop esi ; unused ; pop edx ; need not be preserved ; pop ecx ; need not be preserved - poppic ebx + POPPIC ebx mov esp, ebp ; esp <- aligned ebp pop esp ; esp <- original ebp pop ebp diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jfdctint-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jfdctint-sse2.asm index 6f8e18cb9d05..b6e679918d50 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jfdctint-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jfdctint-sse2.asm @@ -2,7 +2,7 @@ ; jfdctint.asm - accurate integer FDCT (SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, 2020, D. R. Commander. +; Copyright (C) 2016, 2020, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -63,7 +63,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fdct_islow_sse2) EXTN(jconst_fdct_islow_sse2): @@ -80,7 +80,7 @@ PD_DESCALE_P1 times 4 dd 1 << (DESCALE_P1 - 1) PD_DESCALE_P2 times 4 dd 1 << (DESCALE_P2 - 1) PW_DESCALE_P2X times 8 dw 1 << (PASS1_BITS - 1) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -110,13 +110,13 @@ EXTN(jsimd_fdct_islow_sse2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic ebx + PUSHPIC ebx ; push ecx ; unused ; push edx ; need not be preserved ; push esi ; unused ; push edi ; unused - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process rows. @@ -622,7 +622,7 @@ EXTN(jsimd_fdct_islow_sse2): ; pop esi ; unused ; pop edx ; need not be preserved ; pop ecx ; unused - poppic ebx + POPPIC ebx mov esp, ebp ; esp <- aligned ebp pop esp ; esp <- original ebp pop ebp diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jidctflt-3dn.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jidctflt-3dn.asm index 87951910d8e5..1f696cb59bcc 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jidctflt-3dn.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jidctflt-3dn.asm @@ -2,7 +2,7 @@ ; jidctflt.asm - floating-point IDCT (3DNow! & MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -24,7 +24,7 @@ ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_float_3dnow) EXTN(jconst_idct_float_3dnow): @@ -36,7 +36,7 @@ PD_2_613 times 2 dd 2.613125929752753055713286 PD_RNDINT_MAGIC times 2 dd 100663296.0 ; (float)(0x00C00000 << 3) PB_CENTERJSAMP times 8 db CENTERJSAMPLE - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -78,7 +78,7 @@ EXTN(jsimd_idct_float_3dnow): push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process columns from input, store into work array. @@ -87,21 +87,21 @@ EXTN(jsimd_idct_float_3dnow): mov esi, JCOEFPTR [coef_block(eax)] ; inptr lea edi, [workspace] ; FAST_FLOAT *wsptr mov ecx, DCTSIZE/2 ; ctr - alignx 16, 7 + ALIGNX 16, 7 .columnloop: %ifndef NO_ZERO_COLUMN_TEST_FLOAT_3DNOW mov eax, dword [DWBLOCK(1,0,esi,SIZEOF_JCOEF)] or eax, dword [DWBLOCK(2,0,esi,SIZEOF_JCOEF)] jnz short .columnDCT - pushpic ebx ; save GOT address + PUSHPIC ebx ; save GOT address mov ebx, dword [DWBLOCK(3,0,esi,SIZEOF_JCOEF)] mov eax, dword [DWBLOCK(4,0,esi,SIZEOF_JCOEF)] or ebx, dword [DWBLOCK(5,0,esi,SIZEOF_JCOEF)] or eax, dword [DWBLOCK(6,0,esi,SIZEOF_JCOEF)] or ebx, dword [DWBLOCK(7,0,esi,SIZEOF_JCOEF)] or eax, ebx - poppic ebx ; restore GOT address + POPPIC ebx ; restore GOT address jnz short .columnDCT ; -- AC terms all zero @@ -127,7 +127,7 @@ EXTN(jsimd_idct_float_3dnow): movq MMWORD [MMBLOCK(1,2,edi,SIZEOF_FAST_FLOAT)], mm1 movq MMWORD [MMBLOCK(1,3,edi,SIZEOF_FAST_FLOAT)], mm1 jmp near .nextcolumn - alignx 16, 7 + ALIGNX 16, 7 %endif .columnDCT: @@ -293,7 +293,7 @@ EXTN(jsimd_idct_float_3dnow): mov edi, JSAMPARRAY [output_buf(eax)] ; (JSAMPROW *) mov eax, JDIMENSION [output_col(eax)] mov ecx, DCTSIZE/2 ; ctr - alignx 16, 7 + ALIGNX 16, 7 .rowloop: ; -- Even part @@ -420,14 +420,14 @@ EXTN(jsimd_idct_float_3dnow): punpckldq mm6, mm4 ; mm6=(00 01 02 03 04 05 06 07) punpckhdq mm7, mm4 ; mm7=(10 11 12 13 14 15 16 17) - pushpic ebx ; save GOT address + PUSHPIC ebx ; save GOT address mov edx, JSAMPROW [edi+0*SIZEOF_JSAMPROW] mov ebx, JSAMPROW [edi+1*SIZEOF_JSAMPROW] movq MMWORD [edx+eax*SIZEOF_JSAMPLE], mm6 movq MMWORD [ebx+eax*SIZEOF_JSAMPLE], mm7 - poppic ebx ; restore GOT address + POPPIC ebx ; restore GOT address add esi, byte 2*SIZEOF_FAST_FLOAT ; wsptr add edi, byte 2*SIZEOF_JSAMPROW diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jidctflt-sse.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jidctflt-sse.asm index b27ecfdf46a0..daeef22afc94 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jidctflt-sse.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jidctflt-sse.asm @@ -2,7 +2,7 @@ ; jidctflt.asm - floating-point IDCT (SSE & MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -23,18 +23,18 @@ ; -------------------------------------------------------------------------- -%macro unpcklps2 2 ; %1=(0 1 2 3) / %2=(4 5 6 7) => %1=(0 1 4 5) +%macro UNPCKLPS2 2 ; %1=(0 1 2 3) / %2=(4 5 6 7) => %1=(0 1 4 5) shufps %1, %2, 0x44 %endmacro -%macro unpckhps2 2 ; %1=(0 1 2 3) / %2=(4 5 6 7) => %1=(2 3 6 7) +%macro UNPCKHPS2 2 ; %1=(0 1 2 3) / %2=(4 5 6 7) => %1=(2 3 6 7) shufps %1, %2, 0xEE %endmacro ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_float_sse) EXTN(jconst_idct_float_sse): @@ -46,7 +46,7 @@ PD_M2_613 times 4 dd -2.613125929752753055713286 PD_0_125 times 4 dd 0.125 ; 1/8 PB_CENTERJSAMP times 8 db CENTERJSAMPLE - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -88,7 +88,7 @@ EXTN(jsimd_idct_float_sse): push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process columns from input, store into work array. @@ -97,7 +97,7 @@ EXTN(jsimd_idct_float_sse): mov esi, JCOEFPTR [coef_block(eax)] ; inptr lea edi, [workspace] ; FAST_FLOAT *wsptr mov ecx, DCTSIZE/4 ; ctr - alignx 16, 7 + ALIGNX 16, 7 .columnloop: %ifndef NO_ZERO_COLUMN_TEST_FLOAT_SSE mov eax, dword [DWBLOCK(1,0,esi,SIZEOF_JCOEF)] @@ -149,7 +149,7 @@ EXTN(jsimd_idct_float_sse): movaps XMMWORD [XMMBLOCK(3,0,edi,SIZEOF_FAST_FLOAT)], xmm3 movaps XMMWORD [XMMBLOCK(3,1,edi,SIZEOF_FAST_FLOAT)], xmm3 jmp near .nextcolumn - alignx 16, 7 + ALIGNX 16, 7 %endif .columnDCT: @@ -325,11 +325,11 @@ EXTN(jsimd_idct_float_sse): unpckhps xmm4, xmm0 ; xmm4=(42 52 43 53) movaps xmm3, xmm6 ; transpose coefficients(phase 2) - unpcklps2 xmm6, xmm7 ; xmm6=(00 10 20 30) - unpckhps2 xmm3, xmm7 ; xmm3=(01 11 21 31) + UNPCKLPS2 xmm6, xmm7 ; xmm6=(00 10 20 30) + UNPCKHPS2 xmm3, xmm7 ; xmm3=(01 11 21 31) movaps xmm0, xmm1 ; transpose coefficients(phase 2) - unpcklps2 xmm1, xmm2 ; xmm1=(02 12 22 32) - unpckhps2 xmm0, xmm2 ; xmm0=(03 13 23 33) + UNPCKLPS2 xmm1, xmm2 ; xmm1=(02 12 22 32) + UNPCKHPS2 xmm0, xmm2 ; xmm0=(03 13 23 33) movaps xmm7, XMMWORD [wk(0)] ; xmm7=(60 70 61 71) movaps xmm2, XMMWORD [wk(1)] ; xmm2=(62 72 63 73) @@ -340,11 +340,11 @@ EXTN(jsimd_idct_float_sse): movaps XMMWORD [XMMBLOCK(3,0,edi,SIZEOF_FAST_FLOAT)], xmm0 movaps xmm6, xmm5 ; transpose coefficients(phase 2) - unpcklps2 xmm5, xmm7 ; xmm5=(40 50 60 70) - unpckhps2 xmm6, xmm7 ; xmm6=(41 51 61 71) + UNPCKLPS2 xmm5, xmm7 ; xmm5=(40 50 60 70) + UNPCKHPS2 xmm6, xmm7 ; xmm6=(41 51 61 71) movaps xmm3, xmm4 ; transpose coefficients(phase 2) - unpcklps2 xmm4, xmm2 ; xmm4=(42 52 62 72) - unpckhps2 xmm3, xmm2 ; xmm3=(43 53 63 73) + UNPCKLPS2 xmm4, xmm2 ; xmm4=(42 52 62 72) + UNPCKHPS2 xmm3, xmm2 ; xmm3=(43 53 63 73) movaps XMMWORD [XMMBLOCK(0,1,edi,SIZEOF_FAST_FLOAT)], xmm5 movaps XMMWORD [XMMBLOCK(1,1,edi,SIZEOF_FAST_FLOAT)], xmm6 @@ -372,7 +372,7 @@ EXTN(jsimd_idct_float_sse): mov edi, JSAMPARRAY [output_buf(eax)] ; (JSAMPROW *) mov eax, JDIMENSION [output_col(eax)] mov ecx, DCTSIZE/4 ; ctr - alignx 16, 7 + ALIGNX 16, 7 .rowloop: ; -- Even part @@ -536,7 +536,7 @@ EXTN(jsimd_idct_float_sse): punpckldq mm5, mm6 ; mm5=(20 21 22 23 24 25 26 27) punpckhdq mm4, mm6 ; mm4=(30 31 32 33 34 35 36 37) - pushpic ebx ; save GOT address + PUSHPIC ebx ; save GOT address mov edx, JSAMPROW [edi+0*SIZEOF_JSAMPROW] mov ebx, JSAMPROW [edi+1*SIZEOF_JSAMPROW] @@ -547,7 +547,7 @@ EXTN(jsimd_idct_float_sse): movq MMWORD [edx+eax*SIZEOF_JSAMPLE], mm5 movq MMWORD [ebx+eax*SIZEOF_JSAMPLE], mm4 - poppic ebx ; restore GOT address + POPPIC ebx ; restore GOT address add esi, byte 4*SIZEOF_FAST_FLOAT ; wsptr add edi, byte 4*SIZEOF_JSAMPROW diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jidctflt-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jidctflt-sse2.asm index c646eaef76ef..c39ffbe71b25 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jidctflt-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jidctflt-sse2.asm @@ -2,7 +2,7 @@ ; jidctflt.asm - floating-point IDCT (SSE & SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -23,18 +23,18 @@ ; -------------------------------------------------------------------------- -%macro unpcklps2 2 ; %1=(0 1 2 3) / %2=(4 5 6 7) => %1=(0 1 4 5) +%macro UNPCKLPS2 2 ; %1=(0 1 2 3) / %2=(4 5 6 7) => %1=(0 1 4 5) shufps %1, %2, 0x44 %endmacro -%macro unpckhps2 2 ; %1=(0 1 2 3) / %2=(4 5 6 7) => %1=(2 3 6 7) +%macro UNPCKHPS2 2 ; %1=(0 1 2 3) / %2=(4 5 6 7) => %1=(2 3 6 7) shufps %1, %2, 0xEE %endmacro ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_float_sse2) EXTN(jconst_idct_float_sse2): @@ -46,7 +46,7 @@ PD_M2_613 times 4 dd -2.613125929752753055713286 PD_RNDINT_MAGIC times 4 dd 100663296.0 ; (float)(0x00C00000 << 3) PB_CENTERJSAMP times 16 db CENTERJSAMPLE - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -88,7 +88,7 @@ EXTN(jsimd_idct_float_sse2): push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process columns from input, store into work array. @@ -97,7 +97,7 @@ EXTN(jsimd_idct_float_sse2): mov esi, JCOEFPTR [coef_block(eax)] ; inptr lea edi, [workspace] ; FAST_FLOAT *wsptr mov ecx, DCTSIZE/4 ; ctr - alignx 16, 7 + ALIGNX 16, 7 .columnloop: %ifndef NO_ZERO_COLUMN_TEST_FLOAT_SSE mov eax, dword [DWBLOCK(1,0,esi,SIZEOF_JCOEF)] @@ -150,7 +150,7 @@ EXTN(jsimd_idct_float_sse2): movaps XMMWORD [XMMBLOCK(3,0,edi,SIZEOF_FAST_FLOAT)], xmm3 movaps XMMWORD [XMMBLOCK(3,1,edi,SIZEOF_FAST_FLOAT)], xmm3 jmp near .nextcolumn - alignx 16, 7 + ALIGNX 16, 7 %endif .columnDCT: @@ -287,11 +287,11 @@ EXTN(jsimd_idct_float_sse2): unpckhps xmm4, xmm0 ; xmm4=(42 52 43 53) movaps xmm3, xmm6 ; transpose coefficients(phase 2) - unpcklps2 xmm6, xmm7 ; xmm6=(00 10 20 30) - unpckhps2 xmm3, xmm7 ; xmm3=(01 11 21 31) + UNPCKLPS2 xmm6, xmm7 ; xmm6=(00 10 20 30) + UNPCKHPS2 xmm3, xmm7 ; xmm3=(01 11 21 31) movaps xmm0, xmm1 ; transpose coefficients(phase 2) - unpcklps2 xmm1, xmm2 ; xmm1=(02 12 22 32) - unpckhps2 xmm0, xmm2 ; xmm0=(03 13 23 33) + UNPCKLPS2 xmm1, xmm2 ; xmm1=(02 12 22 32) + UNPCKHPS2 xmm0, xmm2 ; xmm0=(03 13 23 33) movaps xmm7, XMMWORD [wk(0)] ; xmm7=(60 70 61 71) movaps xmm2, XMMWORD [wk(1)] ; xmm2=(62 72 63 73) @@ -302,11 +302,11 @@ EXTN(jsimd_idct_float_sse2): movaps XMMWORD [XMMBLOCK(3,0,edi,SIZEOF_FAST_FLOAT)], xmm0 movaps xmm6, xmm5 ; transpose coefficients(phase 2) - unpcklps2 xmm5, xmm7 ; xmm5=(40 50 60 70) - unpckhps2 xmm6, xmm7 ; xmm6=(41 51 61 71) + UNPCKLPS2 xmm5, xmm7 ; xmm5=(40 50 60 70) + UNPCKHPS2 xmm6, xmm7 ; xmm6=(41 51 61 71) movaps xmm3, xmm4 ; transpose coefficients(phase 2) - unpcklps2 xmm4, xmm2 ; xmm4=(42 52 62 72) - unpckhps2 xmm3, xmm2 ; xmm3=(43 53 63 73) + UNPCKLPS2 xmm4, xmm2 ; xmm4=(42 52 62 72) + UNPCKHPS2 xmm3, xmm2 ; xmm3=(43 53 63 73) movaps XMMWORD [XMMBLOCK(0,1,edi,SIZEOF_FAST_FLOAT)], xmm5 movaps XMMWORD [XMMBLOCK(1,1,edi,SIZEOF_FAST_FLOAT)], xmm6 @@ -334,7 +334,7 @@ EXTN(jsimd_idct_float_sse2): mov edi, JSAMPARRAY [output_buf(eax)] ; (JSAMPROW *) mov eax, JDIMENSION [output_col(eax)] mov ecx, DCTSIZE/4 ; ctr - alignx 16, 7 + ALIGNX 16, 7 .rowloop: ; -- Even part @@ -464,7 +464,7 @@ EXTN(jsimd_idct_float_sse2): pshufd xmm5, xmm6, 0x4E ; xmm5=(10 11 12 13 14 15 16 17 00 01 02 03 04 05 06 07) pshufd xmm3, xmm7, 0x4E ; xmm3=(30 31 32 33 34 35 36 37 20 21 22 23 24 25 26 27) - pushpic ebx ; save GOT address + PUSHPIC ebx ; save GOT address mov edx, JSAMPROW [edi+0*SIZEOF_JSAMPROW] mov ebx, JSAMPROW [edi+2*SIZEOF_JSAMPROW] @@ -475,7 +475,7 @@ EXTN(jsimd_idct_float_sse2): movq XMM_MMWORD [edx+eax*SIZEOF_JSAMPLE], xmm5 movq XMM_MMWORD [ebx+eax*SIZEOF_JSAMPLE], xmm3 - poppic ebx ; restore GOT address + POPPIC ebx ; restore GOT address add esi, byte 4*SIZEOF_FAST_FLOAT ; wsptr add edi, byte 4*SIZEOF_JSAMPROW diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jidctfst-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jidctfst-mmx.asm index 24622d43693f..19de457f7898 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jidctfst-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jidctfst-mmx.asm @@ -2,7 +2,7 @@ ; jidctfst.asm - fast integer IDCT (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -56,7 +56,7 @@ F_1_613 equ (F_2_613 - (1 << CONST_BITS)) ; FIX(2.613125930) - FIX(1) %define PRE_MULTIPLY_SCALE_BITS 2 %define CONST_SHIFT (16 - PRE_MULTIPLY_SCALE_BITS - CONST_BITS) - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_ifast_mmx) EXTN(jconst_idct_ifast_mmx): @@ -67,7 +67,7 @@ PW_MF1613 times 4 dw -F_1_613 << CONST_SHIFT PW_F1082 times 4 dw F_1_082 << CONST_SHIFT PB_CENTERJSAMP times 8 db CENTERJSAMPLE - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -109,7 +109,7 @@ EXTN(jsimd_idct_ifast_mmx): push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process columns from input, store into work array. @@ -118,7 +118,7 @@ EXTN(jsimd_idct_ifast_mmx): mov esi, JCOEFPTR [coef_block(eax)] ; inptr lea edi, [workspace] ; JCOEF *wsptr mov ecx, DCTSIZE/4 ; ctr - alignx 16, 7 + ALIGNX 16, 7 .columnloop: %ifndef NO_ZERO_COLUMN_TEST_IFAST_MMX mov eax, dword [DWBLOCK(1,0,esi,SIZEOF_JCOEF)] @@ -163,7 +163,7 @@ EXTN(jsimd_idct_ifast_mmx): movq MMWORD [MMBLOCK(3,0,edi,SIZEOF_JCOEF)], mm3 movq MMWORD [MMBLOCK(3,1,edi,SIZEOF_JCOEF)], mm3 jmp near .nextcolumn - alignx 16, 7 + ALIGNX 16, 7 %endif .columnDCT: @@ -326,7 +326,7 @@ EXTN(jsimd_idct_ifast_mmx): mov edi, JSAMPARRAY [output_buf(eax)] ; (JSAMPROW *) mov eax, JDIMENSION [output_col(eax)] mov ecx, DCTSIZE/4 ; ctr - alignx 16, 7 + ALIGNX 16, 7 .rowloop: ; -- Even part @@ -464,7 +464,7 @@ EXTN(jsimd_idct_ifast_mmx): punpckldq mm5, mm4 ; mm5=(20 21 22 23 24 25 26 27) punpckhdq mm1, mm4 ; mm1=(30 31 32 33 34 35 36 37) - pushpic ebx ; save GOT address + PUSHPIC ebx ; save GOT address mov edx, JSAMPROW [edi+0*SIZEOF_JSAMPROW] mov ebx, JSAMPROW [edi+1*SIZEOF_JSAMPROW] @@ -475,7 +475,7 @@ EXTN(jsimd_idct_ifast_mmx): movq MMWORD [edx+eax*SIZEOF_JSAMPLE], mm5 movq MMWORD [ebx+eax*SIZEOF_JSAMPLE], mm1 - poppic ebx ; restore GOT address + POPPIC ebx ; restore GOT address add esi, byte 4*SIZEOF_JCOEF ; wsptr add edi, byte 4*SIZEOF_JSAMPROW diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jidctfst-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jidctfst-sse2.asm index 19704ffa48f3..966311eda764 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jidctfst-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jidctfst-sse2.asm @@ -2,7 +2,7 @@ ; jidctfst.asm - fast integer IDCT (SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -56,7 +56,7 @@ F_1_613 equ (F_2_613 - (1 << CONST_BITS)) ; FIX(2.613125930) - FIX(1) %define PRE_MULTIPLY_SCALE_BITS 2 %define CONST_SHIFT (16 - PRE_MULTIPLY_SCALE_BITS - CONST_BITS) - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_ifast_sse2) EXTN(jconst_idct_ifast_sse2): @@ -67,7 +67,7 @@ PW_MF1613 times 8 dw -F_1_613 << CONST_SHIFT PW_F1082 times 8 dw F_1_082 << CONST_SHIFT PB_CENTERJSAMP times 16 db CENTERJSAMPLE - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -101,13 +101,13 @@ EXTN(jsimd_idct_ifast_sse2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic ebx + PUSHPIC ebx ; push ecx ; unused ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process columns from input. @@ -155,7 +155,7 @@ EXTN(jsimd_idct_ifast_sse2): movdqa XMMWORD [wk(0)], xmm2 ; wk(0)=col1 movdqa XMMWORD [wk(1)], xmm0 ; wk(1)=col3 jmp near .column_end - alignx 16, 7 + ALIGNX 16, 7 %endif .columnDCT: @@ -490,7 +490,7 @@ EXTN(jsimd_idct_ifast_sse2): pop esi ; pop edx ; need not be preserved ; pop ecx ; unused - poppic ebx + POPPIC ebx mov esp, ebp ; esp <- aligned ebp pop esp ; esp <- original ebp pop ebp diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jidctint-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jidctint-avx2.asm index 199c7df3b69c..dd4a3d5e8c83 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jidctint-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jidctint-avx2.asm @@ -2,7 +2,7 @@ ; jidctint.asm - accurate integer IDCT (AVX2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, 2018, 2020, D. R. Commander. +; Copyright (C) 2009, 2016, 2018, 2020, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -65,7 +65,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; %1-%4: Input/output registers ; %5-%8: Temp registers -%macro dotranspose 8 +%macro DOTRANSPOSE 8 ; %5=(00 10 20 30 40 50 60 70 01 11 21 31 41 51 61 71) ; %6=(03 13 23 33 43 53 63 73 02 12 22 32 42 52 62 72) ; %7=(04 14 24 34 44 54 64 74 05 15 25 35 45 55 65 75) @@ -118,7 +118,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; %5-%12: Temp registers ; %9: Pass (1 or 2) -%macro dodct 13 +%macro DODCT 13 ; -- Even part ; (Original) @@ -250,7 +250,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_islow_avx2) EXTN(jconst_idct_islow_avx2): @@ -269,7 +269,7 @@ PB_CENTERJSAMP times 32 db CENTERJSAMPLE PW_1_NEG1 times 8 dw 1 times 8 dw -1 - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -303,13 +303,13 @@ EXTN(jsimd_idct_islow_avx2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic ebx + PUSHPIC ebx ; push ecx ; unused ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process columns. @@ -353,7 +353,7 @@ EXTN(jsimd_idct_islow_avx2): vpshufd ymm3, ymm4, 0xFF ; ymm3=col3_7=(03 03 03 03 03 03 03 03 07 07 07 07 07 07 07 07) jmp near .column_end - alignx 16, 7 + ALIGNX 16, 7 %endif .columnDCT: @@ -371,10 +371,10 @@ EXTN(jsimd_idct_islow_avx2): vperm2i128 ymm2, ymm5, ymm7, 0x20 ; ymm2=in2_6 vperm2i128 ymm3, ymm7, ymm6, 0x31 ; ymm3=in7_5 - dodct ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7, XMMWORD [wk(0)], XMMWORD [wk(1)], XMMWORD [wk(2)], XMMWORD [wk(3)], 1 + DODCT ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7, XMMWORD [wk(0)], XMMWORD [wk(1)], XMMWORD [wk(2)], XMMWORD [wk(3)], 1 ; ymm0=data0_1, ymm1=data3_2, ymm2=data4_5, ymm3=data7_6 - dotranspose ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7 + DOTRANSPOSE ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7 ; ymm0=data0_4, ymm1=data1_5, ymm2=data2_6, ymm3=data3_7 .column_end: @@ -395,10 +395,10 @@ EXTN(jsimd_idct_islow_avx2): vperm2i128 ymm4, ymm3, ymm1, 0x31 ; ymm3=in7_5 vperm2i128 ymm1, ymm3, ymm1, 0x20 ; ymm1=in3_1 - dodct ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7, XMMWORD [wk(0)], XMMWORD [wk(1)], XMMWORD [wk(2)], XMMWORD [wk(3)], 2 + DODCT ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7, XMMWORD [wk(0)], XMMWORD [wk(1)], XMMWORD [wk(2)], XMMWORD [wk(3)], 2 ; ymm0=data0_1, ymm1=data3_2, ymm2=data4_5, ymm4=data7_6 - dotranspose ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7 + DOTRANSPOSE ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7 ; ymm0=data0_4, ymm1=data1_5, ymm2=data2_6, ymm4=data3_7 vpacksswb ymm0, ymm0, ymm1 ; ymm0=data01_45 @@ -442,7 +442,7 @@ EXTN(jsimd_idct_islow_avx2): pop esi ; pop edx ; need not be preserved ; pop ecx ; unused - poppic ebx + POPPIC ebx mov esp, ebp ; esp <- aligned ebp pop esp ; esp <- original ebp pop ebp diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jidctint-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jidctint-mmx.asm index f15c8d34bcb3..e2e1b3ff7985 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jidctint-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jidctint-mmx.asm @@ -2,7 +2,7 @@ ; jidctint.asm - accurate integer IDCT (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, 2020, D. R. Commander. +; Copyright (C) 2016, 2020, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -63,7 +63,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_islow_mmx) EXTN(jconst_idct_islow_mmx): @@ -80,7 +80,7 @@ PD_DESCALE_P1 times 2 dd 1 << (DESCALE_P1 - 1) PD_DESCALE_P2 times 2 dd 1 << (DESCALE_P2 - 1) PB_CENTERJSAMP times 8 db CENTERJSAMPLE - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -122,7 +122,7 @@ EXTN(jsimd_idct_islow_mmx): push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process columns from input, store into work array. @@ -131,7 +131,7 @@ EXTN(jsimd_idct_islow_mmx): mov esi, JCOEFPTR [coef_block(eax)] ; inptr lea edi, [workspace] ; JCOEF *wsptr mov ecx, DCTSIZE/4 ; ctr - alignx 16, 7 + ALIGNX 16, 7 .columnloop: %ifndef NO_ZERO_COLUMN_TEST_ISLOW_MMX mov eax, dword [DWBLOCK(1,0,esi,SIZEOF_JCOEF)] @@ -178,7 +178,7 @@ EXTN(jsimd_idct_islow_mmx): movq MMWORD [MMBLOCK(3,0,edi,SIZEOF_JCOEF)], mm3 movq MMWORD [MMBLOCK(3,1,edi,SIZEOF_JCOEF)], mm3 jmp near .nextcolumn - alignx 16, 7 + ALIGNX 16, 7 %endif .columnDCT: @@ -513,7 +513,7 @@ EXTN(jsimd_idct_islow_mmx): mov edi, JSAMPARRAY [output_buf(eax)] ; (JSAMPROW *) mov eax, JDIMENSION [output_col(eax)] mov ecx, DCTSIZE/4 ; ctr - alignx 16, 7 + ALIGNX 16, 7 .rowloop: ; -- Even part @@ -816,7 +816,7 @@ EXTN(jsimd_idct_islow_mmx): punpckldq mm7, mm5 ; mm7=(20 21 22 23 24 25 26 27) punpckhdq mm4, mm5 ; mm4=(30 31 32 33 34 35 36 37) - pushpic ebx ; save GOT address + PUSHPIC ebx ; save GOT address mov edx, JSAMPROW [edi+0*SIZEOF_JSAMPROW] mov ebx, JSAMPROW [edi+1*SIZEOF_JSAMPROW] @@ -827,7 +827,7 @@ EXTN(jsimd_idct_islow_mmx): movq MMWORD [edx+eax*SIZEOF_JSAMPLE], mm7 movq MMWORD [ebx+eax*SIZEOF_JSAMPLE], mm4 - poppic ebx ; restore GOT address + POPPIC ebx ; restore GOT address add esi, byte 4*SIZEOF_JCOEF ; wsptr add edi, byte 4*SIZEOF_JSAMPROW diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jidctint-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jidctint-sse2.asm index 43e320189b49..42be940d7239 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jidctint-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jidctint-sse2.asm @@ -2,7 +2,7 @@ ; jidctint.asm - accurate integer IDCT (SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, 2020, D. R. Commander. +; Copyright (C) 2016, 2020, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -63,7 +63,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_islow_sse2) EXTN(jconst_idct_islow_sse2): @@ -80,7 +80,7 @@ PD_DESCALE_P1 times 4 dd 1 << (DESCALE_P1 - 1) PD_DESCALE_P2 times 4 dd 1 << (DESCALE_P2 - 1) PB_CENTERJSAMP times 16 db CENTERJSAMPLE - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -114,13 +114,13 @@ EXTN(jsimd_idct_islow_sse2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic ebx + PUSHPIC ebx ; push ecx ; unused ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process columns from input. @@ -172,7 +172,7 @@ EXTN(jsimd_idct_islow_sse2): movdqa XMMWORD [wk(10)], xmm3 ; wk(10)=col5 movdqa XMMWORD [wk(11)], xmm4 ; wk(11)=col7 jmp near .column_end - alignx 16, 7 + ALIGNX 16, 7 %endif .columnDCT: @@ -847,7 +847,7 @@ EXTN(jsimd_idct_islow_sse2): pop esi ; pop edx ; need not be preserved ; pop ecx ; unused - poppic ebx + POPPIC ebx mov esp, ebp ; esp <- aligned ebp pop esp ; esp <- original ebp pop ebp diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jidctred-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jidctred-mmx.asm index e2307e1cb6c6..920dad90bdca 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jidctred-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jidctred-mmx.asm @@ -2,7 +2,7 @@ ; jidctred.asm - reduced-size IDCT (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -69,7 +69,7 @@ F_3_624 equ DESCALE(3891787747, 30 - CONST_BITS) ; FIX(3.624509785) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_red_mmx) EXTN(jconst_idct_red_mmx): @@ -87,7 +87,7 @@ PD_DESCALE_P1_2 times 2 dd 1 << (DESCALE_P1_2 - 1) PD_DESCALE_P2_2 times 2 dd 1 << (DESCALE_P2_2 - 1) PB_CENTERJSAMP times 8 db CENTERJSAMPLE - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -124,13 +124,13 @@ EXTN(jsimd_idct_4x4_mmx): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [workspace] - pushpic ebx + PUSHPIC ebx ; push ecx ; need not be preserved ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process columns from input, store into work array. @@ -139,7 +139,7 @@ EXTN(jsimd_idct_4x4_mmx): mov esi, JCOEFPTR [coef_block(eax)] ; inptr lea edi, [workspace] ; JCOEF *wsptr mov ecx, DCTSIZE/4 ; ctr - alignx 16, 7 + ALIGNX 16, 7 .columnloop: %ifndef NO_ZERO_COLUMN_TEST_4X4_MMX mov eax, dword [DWBLOCK(1,0,esi,SIZEOF_JCOEF)] @@ -181,7 +181,7 @@ EXTN(jsimd_idct_4x4_mmx): movq MMWORD [MMBLOCK(2,0,edi,SIZEOF_JCOEF)], mm2 movq MMWORD [MMBLOCK(3,0,edi,SIZEOF_JCOEF)], mm3 jmp near .nextcolumn - alignx 16, 7 + ALIGNX 16, 7 %endif .columnDCT: @@ -479,7 +479,7 @@ EXTN(jsimd_idct_4x4_mmx): pop esi ; pop edx ; need not be preserved ; pop ecx ; need not be preserved - poppic ebx + POPPIC ebx mov esp, ebp ; esp <- aligned ebp pop esp ; esp <- original ebp pop ebp @@ -512,7 +512,7 @@ EXTN(jsimd_idct_2x2_mmx): push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process columns from input. diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jidctred-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jidctred-sse2.asm index 6e56494e9751..9a6f9946e795 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jidctred-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jidctred-sse2.asm @@ -2,7 +2,7 @@ ; jidctred.asm - reduced-size IDCT (SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -69,7 +69,7 @@ F_3_624 equ DESCALE(3891787747, 30 - CONST_BITS) ; FIX(3.624509785) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_red_sse2) EXTN(jconst_idct_red_sse2): @@ -87,7 +87,7 @@ PD_DESCALE_P1_2 times 4 dd 1 << (DESCALE_P1_2 - 1) PD_DESCALE_P2_2 times 4 dd 1 << (DESCALE_P2_2 - 1) PB_CENTERJSAMP times 16 db CENTERJSAMPLE - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -122,13 +122,13 @@ EXTN(jsimd_idct_4x4_sse2): mov [esp], eax mov ebp, esp ; ebp = aligned ebp lea esp, [wk(0)] - pushpic ebx + PUSHPIC ebx ; push ecx ; unused ; push edx ; need not be preserved push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process columns from input. @@ -171,7 +171,7 @@ EXTN(jsimd_idct_4x4_sse2): pshufd xmm3, xmm3, 0xFA ; xmm3=[col6 col7]=(06 06 06 06 07 07 07 07) jmp near .column_end - alignx 16, 7 + ALIGNX 16, 7 %endif .columnDCT: @@ -400,7 +400,7 @@ EXTN(jsimd_idct_4x4_sse2): pop esi ; pop edx ; need not be preserved ; pop ecx ; unused - poppic ebx + POPPIC ebx mov esp, ebp ; esp <- aligned ebp pop esp ; esp <- original ebp pop ebp @@ -433,7 +433,7 @@ EXTN(jsimd_idct_2x2_sse2): push esi push edi - get_GOT ebx ; get GOT address + GET_GOT ebx ; get GOT address ; ---- Pass 1: process columns from input. diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jquant-3dn.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jquant-3dn.asm index 5cb60caa947a..6436bad1ec9b 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jquant-3dn.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jquant-3dn.asm @@ -2,7 +2,7 @@ ; jquant.asm - sample data conversion and quantization (3DNow! & MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -52,7 +52,7 @@ EXTN(jsimd_convsamp_float_3dnow): mov eax, JDIMENSION [start_col] mov edi, POINTER [workspace] ; (DCTELEM *) mov ecx, DCTSIZE/2 - alignx 16, 7 + ALIGNX 16, 7 .convloop: mov ebx, JSAMPROW [esi+0*SIZEOF_JSAMPROW] ; (JSAMPLE *) mov edx, JSAMPROW [esi+1*SIZEOF_JSAMPROW] ; (JSAMPLE *) @@ -154,7 +154,7 @@ EXTN(jsimd_quantize_float_3dnow): mov edx, POINTER [divisors] mov edi, JCOEFPTR [coef_block] mov eax, DCTSIZE2/16 - alignx 16, 7 + ALIGNX 16, 7 .quantloop: movq mm0, MMWORD [MMBLOCK(0,0,esi,SIZEOF_FAST_FLOAT)] movq mm1, MMWORD [MMBLOCK(0,1,esi,SIZEOF_FAST_FLOAT)] diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jquant-mmx.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jquant-mmx.asm index 61305c625de8..e525ba9e7b1e 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jquant-mmx.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jquant-mmx.asm @@ -2,7 +2,7 @@ ; jquant.asm - sample data conversion and quantization (MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -52,7 +52,7 @@ EXTN(jsimd_convsamp_mmx): mov eax, JDIMENSION [start_col] mov edi, POINTER [workspace] ; (DCTELEM *) mov ecx, DCTSIZE/4 - alignx 16, 7 + ALIGNX 16, 7 .convloop: mov ebx, JSAMPROW [esi+0*SIZEOF_JSAMPROW] ; (JSAMPLE *) mov edx, JSAMPROW [esi+1*SIZEOF_JSAMPROW] ; (JSAMPLE *) @@ -157,10 +157,10 @@ EXTN(jsimd_quantize_mmx): mov edx, POINTER [divisors] mov edi, JCOEFPTR [coef_block] mov ah, 2 - alignx 16, 7 + ALIGNX 16, 7 .quantloop1: mov al, DCTSIZE2/8/2 - alignx 16, 7 + ALIGNX 16, 7 .quantloop2: movq mm2, MMWORD [MMBLOCK(0,0,esi,SIZEOF_DCTELEM)] movq mm3, MMWORD [MMBLOCK(0,1,esi,SIZEOF_DCTELEM)] diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jquant-sse.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jquant-sse.asm index 218adc976f3c..1cf2cc0ce5a5 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jquant-sse.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jquant-sse.asm @@ -2,7 +2,7 @@ ; jquant.asm - sample data conversion and quantization (SSE & MMX) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -52,7 +52,7 @@ EXTN(jsimd_convsamp_float_sse): mov eax, JDIMENSION [start_col] mov edi, POINTER [workspace] ; (DCTELEM *) mov ecx, DCTSIZE/2 - alignx 16, 7 + ALIGNX 16, 7 .convloop: mov ebx, JSAMPROW [esi+0*SIZEOF_JSAMPROW] ; (JSAMPLE *) mov edx, JSAMPROW [esi+1*SIZEOF_JSAMPROW] ; (JSAMPLE *) @@ -150,7 +150,7 @@ EXTN(jsimd_quantize_float_sse): mov edx, POINTER [divisors] mov edi, JCOEFPTR [coef_block] mov eax, DCTSIZE2/16 - alignx 16, 7 + ALIGNX 16, 7 .quantloop: movaps xmm0, XMMWORD [XMMBLOCK(0,0,esi,SIZEOF_FAST_FLOAT)] movaps xmm1, XMMWORD [XMMBLOCK(0,1,esi,SIZEOF_FAST_FLOAT)] diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jquantf-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jquantf-sse2.asm index a881ab50f924..66efd3eecac8 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jquantf-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jquantf-sse2.asm @@ -2,7 +2,7 @@ ; jquantf.asm - sample data conversion and quantization (SSE & SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -52,7 +52,7 @@ EXTN(jsimd_convsamp_float_sse2): mov eax, JDIMENSION [start_col] mov edi, POINTER [workspace] ; (DCTELEM *) mov ecx, DCTSIZE/2 - alignx 16, 7 + ALIGNX 16, 7 .convloop: mov ebx, JSAMPROW [esi+0*SIZEOF_JSAMPROW] ; (JSAMPLE *) mov edx, JSAMPROW [esi+1*SIZEOF_JSAMPROW] ; (JSAMPLE *) @@ -127,7 +127,7 @@ EXTN(jsimd_quantize_float_sse2): mov edx, POINTER [divisors] mov edi, JCOEFPTR [coef_block] mov eax, DCTSIZE2/16 - alignx 16, 7 + ALIGNX 16, 7 .quantloop: movaps xmm0, XMMWORD [XMMBLOCK(0,0,esi,SIZEOF_FAST_FLOAT)] movaps xmm1, XMMWORD [XMMBLOCK(0,1,esi,SIZEOF_FAST_FLOAT)] diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jquanti-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/i386/jquanti-sse2.asm index 0a509408aa13..2a69af9c95ff 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jquanti-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jquanti-sse2.asm @@ -2,7 +2,7 @@ ; jquanti.asm - sample data conversion and quantization (SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -52,7 +52,7 @@ EXTN(jsimd_convsamp_sse2): mov eax, JDIMENSION [start_col] mov edi, POINTER [workspace] ; (DCTELEM *) mov ecx, DCTSIZE/4 - alignx 16, 7 + ALIGNX 16, 7 .convloop: mov ebx, JSAMPROW [esi+0*SIZEOF_JSAMPROW] ; (JSAMPLE *) mov edx, JSAMPROW [esi+1*SIZEOF_JSAMPROW] ; (JSAMPLE *) @@ -133,7 +133,7 @@ EXTN(jsimd_quantize_sse2): mov edx, POINTER [divisors] mov edi, JCOEFPTR [coef_block] mov eax, DCTSIZE2/32 - alignx 16, 7 + ALIGNX 16, 7 .quantloop: movdqa xmm4, XMMWORD [XMMBLOCK(0,0,esi,SIZEOF_DCTELEM)] movdqa xmm5, XMMWORD [XMMBLOCK(1,0,esi,SIZEOF_DCTELEM)] diff --git a/3rdparty/libjpeg-turbo/src/simd/i386/jsimd.c b/3rdparty/libjpeg-turbo/src/simd/i386/jsimd.c index 80bc821ff4e7..b429b0a53208 100644 --- a/3rdparty/libjpeg-turbo/src/simd/i386/jsimd.c +++ b/3rdparty/libjpeg-turbo/src/simd/i386/jsimd.c @@ -2,8 +2,8 @@ * jsimd_i386.c * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009-2011, 2013-2014, 2016, 2018, 2022, D. R. Commander. - * Copyright (C) 2015-2016, 2018, Matthieu Darbois. + * Copyright (C) 2009-2011, 2013-2014, 2016, 2018, 2022-2023, D. R. Commander. + * Copyright (C) 2015-2016, 2018, 2022, Matthieu Darbois. * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -21,7 +21,6 @@ #include "../../jdct.h" #include "../../jsimddct.h" #include "../jsimd.h" -#include "jconfigint.h" /* * In the PIC cases, we have no guarantee that constants will keep @@ -32,13 +31,11 @@ #define IS_ALIGNED_SSE(ptr) (IS_ALIGNED(ptr, 4)) /* 16 byte alignment */ #define IS_ALIGNED_AVX(ptr) (IS_ALIGNED(ptr, 5)) /* 32 byte alignment */ -static unsigned int simd_support = (unsigned int)(~0); -static unsigned int simd_huffman = 1; +static THREAD_LOCAL unsigned int simd_support = (unsigned int)(~0); +static THREAD_LOCAL unsigned int simd_huffman = 1; /* * Check what SIMD accelerations are supported. - * - * FIXME: This code is racy under a multi-threaded environment. */ LOCAL(void) init_simd(void) @@ -161,6 +158,9 @@ jsimd_rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, void (*sse2fct) (JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int); void (*mmxfct) (JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int); + if (simd_support == ~0U) + init_simd(); + switch (cinfo->in_color_space) { case JCS_EXT_RGB: avx2fct = jsimd_extrgb_ycc_convert_avx2; @@ -220,6 +220,9 @@ jsimd_rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, void (*sse2fct) (JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int); void (*mmxfct) (JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int); + if (simd_support == ~0U) + init_simd(); + switch (cinfo->in_color_space) { case JCS_EXT_RGB: avx2fct = jsimd_extrgb_gray_convert_avx2; @@ -279,6 +282,9 @@ jsimd_ycc_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, void (*sse2fct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY, int); void (*mmxfct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY, int); + if (simd_support == ~0U) + init_simd(); + switch (cinfo->out_color_space) { case JCS_EXT_RGB: avx2fct = jsimd_ycc_extrgb_convert_avx2; @@ -382,6 +388,9 @@ GLOBAL(void) jsimd_h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_h2v2_downsample_avx2(cinfo->image_width, cinfo->max_v_samp_factor, compptr->v_samp_factor, @@ -402,6 +411,9 @@ GLOBAL(void) jsimd_h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_h2v1_downsample_avx2(cinfo->image_width, cinfo->max_v_samp_factor, compptr->v_samp_factor, @@ -464,6 +476,9 @@ GLOBAL(void) jsimd_h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_h2v2_upsample_avx2(cinfo->max_v_samp_factor, cinfo->output_width, input_data, output_data_ptr); @@ -479,6 +494,9 @@ GLOBAL(void) jsimd_h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_h2v1_upsample_avx2(cinfo->max_v_samp_factor, cinfo->output_width, input_data, output_data_ptr); @@ -540,6 +558,9 @@ GLOBAL(void) jsimd_h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_h2v2_fancy_upsample_avx2(cinfo->max_v_samp_factor, compptr->downsampled_width, input_data, @@ -558,6 +579,9 @@ GLOBAL(void) jsimd_h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_h2v1_fancy_upsample_avx2(cinfo->max_v_samp_factor, compptr->downsampled_width, input_data, @@ -626,6 +650,9 @@ jsimd_h2v2_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, void (*sse2fct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY); void (*mmxfct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY); + if (simd_support == ~0U) + init_simd(); + switch (cinfo->out_color_space) { case JCS_EXT_RGB: avx2fct = jsimd_h2v2_extrgb_merged_upsample_avx2; @@ -684,6 +711,9 @@ jsimd_h2v1_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, void (*sse2fct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY); void (*mmxfct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY); + if (simd_support == ~0U) + init_simd(); + switch (cinfo->out_color_space) { case JCS_EXT_RGB: avx2fct = jsimd_h2v1_extrgb_merged_upsample_avx2; @@ -788,6 +818,9 @@ GLOBAL(void) jsimd_convsamp(JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_convsamp_avx2(sample_data, start_col, workspace); else if (simd_support & JSIMD_SSE2) @@ -800,6 +833,9 @@ GLOBAL(void) jsimd_convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT *workspace) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_SSE2) jsimd_convsamp_float_sse2(sample_data, start_col, workspace); else if (simd_support & JSIMD_SSE) @@ -870,6 +906,9 @@ jsimd_can_fdct_float(void) GLOBAL(void) jsimd_fdct_islow(DCTELEM *data) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_fdct_islow_avx2(data); else if (simd_support & JSIMD_SSE2) @@ -881,6 +920,9 @@ jsimd_fdct_islow(DCTELEM *data) GLOBAL(void) jsimd_fdct_ifast(DCTELEM *data) { + if (simd_support == ~0U) + init_simd(); + if ((simd_support & JSIMD_SSE2) && IS_ALIGNED_SSE(jconst_fdct_islow_sse2)) jsimd_fdct_ifast_sse2(data); else @@ -890,6 +932,9 @@ jsimd_fdct_ifast(DCTELEM *data) GLOBAL(void) jsimd_fdct_float(FAST_FLOAT *data) { + if (simd_support == ~0U) + init_simd(); + if ((simd_support & JSIMD_SSE) && IS_ALIGNED_SSE(jconst_fdct_float_sse)) jsimd_fdct_float_sse(data); else if (simd_support & JSIMD_3DNOW) @@ -945,6 +990,9 @@ jsimd_can_quantize_float(void) GLOBAL(void) jsimd_quantize(JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_quantize_avx2(coef_block, divisors, workspace); else if (simd_support & JSIMD_SSE2) @@ -957,6 +1005,9 @@ GLOBAL(void) jsimd_quantize_float(JCOEFPTR coef_block, FAST_FLOAT *divisors, FAST_FLOAT *workspace) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_SSE2) jsimd_quantize_float_sse2(coef_block, divisors, workspace); else if (simd_support & JSIMD_SSE) @@ -1020,6 +1071,9 @@ jsimd_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { + if (simd_support == ~0U) + init_simd(); + if ((simd_support & JSIMD_SSE2) && IS_ALIGNED_SSE(jconst_idct_red_sse2)) jsimd_idct_2x2_sse2(compptr->dct_table, coef_block, output_buf, output_col); @@ -1032,6 +1086,9 @@ jsimd_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { + if (simd_support == ~0U) + init_simd(); + if ((simd_support & JSIMD_SSE2) && IS_ALIGNED_SSE(jconst_idct_red_sse2)) jsimd_idct_4x4_sse2(compptr->dct_table, coef_block, output_buf, output_col); @@ -1126,6 +1183,9 @@ jsimd_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_idct_islow_avx2(compptr->dct_table, coef_block, output_buf, output_col); @@ -1142,6 +1202,9 @@ jsimd_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { + if (simd_support == ~0U) + init_simd(); + if ((simd_support & JSIMD_SSE2) && IS_ALIGNED_SSE(jconst_idct_ifast_sse2)) jsimd_idct_ifast_sse2(compptr->dct_table, coef_block, output_buf, output_col); @@ -1155,6 +1218,9 @@ jsimd_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { + if (simd_support == ~0U) + init_simd(); + if ((simd_support & JSIMD_SSE2) && IS_ALIGNED_SSE(jconst_idct_float_sse2)) jsimd_idct_float_sse2(compptr->dct_table, coef_block, output_buf, output_col); @@ -1212,7 +1278,7 @@ jsimd_can_encode_mcu_AC_first_prepare(void) GLOBAL(void) jsimd_encode_mcu_AC_first_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *values, size_t *zerobits) + int Al, UJCOEF *values, size_t *zerobits) { jsimd_encode_mcu_AC_first_prepare_sse2(block, jpeg_natural_order_start, Sl, Al, values, zerobits); @@ -1238,7 +1304,7 @@ jsimd_can_encode_mcu_AC_refine_prepare(void) GLOBAL(int) jsimd_encode_mcu_AC_refine_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *absvalues, size_t *bits) + int Al, UJCOEF *absvalues, size_t *bits) { return jsimd_encode_mcu_AC_refine_prepare_sse2(block, jpeg_natural_order_start, diff --git a/3rdparty/libjpeg-turbo/src/simd/jsimd.h b/3rdparty/libjpeg-turbo/src/simd/jsimd.h index 64747c6360c1..a28754adb9d0 100644 --- a/3rdparty/libjpeg-turbo/src/simd/jsimd.h +++ b/3rdparty/libjpeg-turbo/src/simd/jsimd.h @@ -2,10 +2,10 @@ * simd/jsimd.h * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2011, 2014-2016, 2018, 2020, D. R. Commander. + * Copyright (C) 2011, 2014-2016, 2018, 2020, 2022, D. R. Commander. * Copyright (C) 2013-2014, MIPS Technologies, Inc., California. * Copyright (C) 2014, Linaro Limited. - * Copyright (C) 2015-2016, 2018, Matthieu Darbois. + * Copyright (C) 2015-2016, 2018, 2022, Matthieu Darbois. * Copyright (C) 2016-2018, Loongson Technology Corporation Limited, BeiJing. * Copyright (C) 2020, Arm Limited. * @@ -1243,16 +1243,16 @@ EXTERN(JOCTET *) jsimd_huff_encode_one_block_neon_slowtbl /* Progressive Huffman encoding */ EXTERN(void) jsimd_encode_mcu_AC_first_prepare_sse2 (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, - JCOEF *values, size_t *zerobits); + UJCOEF *values, size_t *zerobits); EXTERN(void) jsimd_encode_mcu_AC_first_prepare_neon (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, - JCOEF *values, size_t *zerobits); + UJCOEF *values, size_t *zerobits); EXTERN(int) jsimd_encode_mcu_AC_refine_prepare_sse2 (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, - JCOEF *absvalues, size_t *bits); + UJCOEF *absvalues, size_t *bits); EXTERN(int) jsimd_encode_mcu_AC_refine_prepare_neon (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al, - JCOEF *absvalues, size_t *bits); + UJCOEF *absvalues, size_t *bits); diff --git a/3rdparty/libjpeg-turbo/src/simd/mips/jsimd.c b/3rdparty/libjpeg-turbo/src/simd/mips/jsimd.c index d2546eed3289..c6e789aa2f2d 100644 --- a/3rdparty/libjpeg-turbo/src/simd/mips/jsimd.c +++ b/3rdparty/libjpeg-turbo/src/simd/mips/jsimd.c @@ -2,9 +2,9 @@ * jsimd_mips.c * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009-2011, 2014, 2016, 2018, 2020, D. R. Commander. + * Copyright (C) 2009-2011, 2014, 2016, 2018, 2020, 2022, D. R. Commander. * Copyright (C) 2013-2014, MIPS Technologies, Inc., California. - * Copyright (C) 2015-2016, 2018, Matthieu Darbois. + * Copyright (C) 2015-2016, 2018, 2022, Matthieu Darbois. * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -23,11 +23,9 @@ #include "../../jsimddct.h" #include "../jsimd.h" -#include -#include #include -static unsigned int simd_support = ~0; +static THREAD_LOCAL unsigned int simd_support = ~0; #if !(defined(__mips_dsp) && (__mips_dsp_rev >= 2)) && defined(__linux__) @@ -57,8 +55,6 @@ parse_proc_cpuinfo(const char *search_string) /* * Check what SIMD accelerations are supported. - * - * FIXME: This code is racy under a multi-threaded environment. */ LOCAL(void) init_simd(void) @@ -1128,7 +1124,7 @@ jsimd_can_encode_mcu_AC_first_prepare(void) GLOBAL(void) jsimd_encode_mcu_AC_first_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *values, size_t *zerobits) + int Al, UJCOEF *values, size_t *zerobits) { } @@ -1141,7 +1137,7 @@ jsimd_can_encode_mcu_AC_refine_prepare(void) GLOBAL(int) jsimd_encode_mcu_AC_refine_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *absvalues, size_t *bits) + int Al, UJCOEF *absvalues, size_t *bits) { return 0; } diff --git a/3rdparty/libjpeg-turbo/src/simd/mips64/jsimd.c b/3rdparty/libjpeg-turbo/src/simd/mips64/jsimd.c index e8f1af562bab..917440b43bf8 100644 --- a/3rdparty/libjpeg-turbo/src/simd/mips64/jsimd.c +++ b/3rdparty/libjpeg-turbo/src/simd/mips64/jsimd.c @@ -2,9 +2,9 @@ * jsimd_mips64.c * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009-2011, 2014, 2016, 2018, D. R. Commander. + * Copyright (C) 2009-2011, 2014, 2016, 2018, 2022, D. R. Commander. * Copyright (C) 2013-2014, MIPS Technologies, Inc., California. - * Copyright (C) 2015, 2018, Matthieu Darbois. + * Copyright (C) 2015, 2018, 2022, Matthieu Darbois. * Copyright (C) 2016-2018, Loongson Technology Corporation Limited, BeiJing. * * Based on the x86 SIMD extension for IJG JPEG library, @@ -24,11 +24,9 @@ #include "../../jsimddct.h" #include "../jsimd.h" -#include -#include #include -static unsigned int simd_support = ~0; +static THREAD_LOCAL unsigned int simd_support = ~0; #if defined(__linux__) @@ -96,8 +94,6 @@ parse_proc_cpuinfo(int bufsize) /* * Check what SIMD accelerations are supported. - * - * FIXME: This code is racy under a multi-threaded environment. */ LOCAL(void) init_simd(void) @@ -851,7 +847,7 @@ jsimd_can_encode_mcu_AC_first_prepare(void) GLOBAL(void) jsimd_encode_mcu_AC_first_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *values, size_t *zerobits) + int Al, UJCOEF *values, size_t *zerobits) { } @@ -864,7 +860,7 @@ jsimd_can_encode_mcu_AC_refine_prepare(void) GLOBAL(int) jsimd_encode_mcu_AC_refine_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *absvalues, size_t *bits) + int Al, UJCOEF *absvalues, size_t *bits) { return 0; } diff --git a/3rdparty/libjpeg-turbo/src/simd/nasm/jsimdext.inc b/3rdparty/libjpeg-turbo/src/simd/nasm/jsimdext.inc index e8d50b034973..b5341ed27586 100644 --- a/3rdparty/libjpeg-turbo/src/simd/nasm/jsimdext.inc +++ b/3rdparty/libjpeg-turbo/src/simd/nasm/jsimdext.inc @@ -2,9 +2,10 @@ ; jsimdext.inc - common declarations ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2010, 2016, 2018-2019, D. R. Commander. +; Copyright (C) 2010, 2016, 2018-2019, 2024, D. R. Commander. ; Copyright (C) 2018, Matthieu Darbois. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library - version 1.02 ; @@ -75,6 +76,14 @@ ; mark stack as non-executable section .note.GNU-stack noalloc noexec nowrite progbits +%ifdef __CET__ +%ifdef __x86_64__ +section .note.gnu.property note alloc noexec align=8 + dd 0x00000004, 0x00000010, 0x00000005, 0x00554e47 + dd 0xc0000002, 0x00000004, 0x00000003, 0x00000000 +%endif +%endif + ; -- segment definition -- ; %ifdef __x86_64__ @@ -271,7 +280,7 @@ const_base: %define GOTOFF(got, sym) (got) + (sym) - const_base -%imacro get_GOT 1 +%imacro GET_GOT 1 ; NOTE: this macro destroys ecx resister. call %%geteip add ecx, byte (%%ref - $) @@ -303,7 +312,7 @@ const_base: %define GOTOFF(got, sym) (got) + (sym) wrt ..gotoff -%imacro get_GOT 1 +%imacro GET_GOT 1 extern GOT_SYMBOL call %%geteip add %1, GOT_SYMBOL + $$ - $ wrt ..gotpc @@ -316,13 +325,13 @@ const_base: %endif ; GOT_SYMBOL == _MACHO_PIC_ ---------------- -%imacro pushpic 1.nolist +%imacro PUSHPIC 1.nolist push %1 %endmacro -%imacro poppic 1.nolist +%imacro POPPIC 1.nolist pop %1 %endmacro -%imacro movpic 2.nolist +%imacro MOVPIC 2.nolist mov %1, %2 %endmacro @@ -330,13 +339,13 @@ const_base: %define GOTOFF(got, sym) (sym) -%imacro get_GOT 1.nolist +%imacro GET_GOT 1.nolist %endmacro -%imacro pushpic 1.nolist +%imacro PUSHPIC 1.nolist %endmacro -%imacro poppic 1.nolist +%imacro POPPIC 1.nolist %endmacro -%imacro movpic 2.nolist +%imacro MOVPIC 2.nolist %endmacro %endif ; PIC ----------------------------------------- @@ -348,7 +357,7 @@ const_base: %define MSKLE(x, y) (~(((y) & 0xFFFF) - ((x) & 0xFFFF)) >> 16) %define FILLB(b, n) (($$-(b)) & ((n)-1)) -%imacro alignx 1-2.nolist 0xFFFF +%imacro ALIGNX 1-2.nolist 0xFFFF %%bs: \ times MSKLE(FILLB(%%bs, %1), %2) & MSKLE(16, FILLB($, %1)) & FILLB($, %1) \ db 0x90 ; nop @@ -370,7 +379,7 @@ const_base: ; Align the next data on {2,4,8,16,..}-byte boundary. ; -%imacro alignz 1.nolist +%imacro ALIGNZ 1.nolist align %1, db 0 ; filling zeros %endmacro @@ -378,7 +387,7 @@ const_base: %ifdef WIN64 -%imacro collect_args 1 +%imacro COLLECT_ARGS 1 sub rsp, SIZEOF_XMMWORD movaps XMMWORD [rsp], xmm6 sub rsp, SIZEOF_XMMWORD @@ -397,17 +406,17 @@ const_base: %endif %if %1 > 4 push r14 - mov r14, [rax+48] + mov r14, [rbp+48] %endif %if %1 > 5 push r15 - mov r15, [rax+56] + mov r15, [rbp+56] %endif push rsi push rdi %endmacro -%imacro uncollect_args 1 +%imacro UNCOLLECT_ARGS 1 pop rdi pop rsi %if %1 > 5 @@ -428,7 +437,7 @@ const_base: add rsp, SIZEOF_XMMWORD %endmacro -%imacro push_xmm 1 +%imacro PUSH_XMM 1 sub rsp, %1 * SIZEOF_XMMWORD movaps XMMWORD [rsp+0*SIZEOF_XMMWORD], xmm8 %if %1 > 1 @@ -442,7 +451,7 @@ const_base: %endif %endmacro -%imacro pop_xmm 1 +%imacro POP_XMM 1 movaps xmm8, XMMWORD [rsp+0*SIZEOF_XMMWORD] %if %1 > 1 movaps xmm9, XMMWORD [rsp+1*SIZEOF_XMMWORD] @@ -458,7 +467,7 @@ const_base: %else -%imacro collect_args 1 +%imacro COLLECT_ARGS 1 push r10 mov r10, rdi %if %1 > 1 @@ -483,7 +492,7 @@ const_base: %endif %endmacro -%imacro uncollect_args 1 +%imacro UNCOLLECT_ARGS 1 %if %1 > 5 pop r15 %endif @@ -502,16 +511,29 @@ const_base: pop r10 %endmacro -%imacro push_xmm 1 +%imacro PUSH_XMM 1 %endmacro -%imacro pop_xmm 1 +%imacro POP_XMM 1 %endmacro %endif %endif +%ifdef __CET__ + +%imacro ENDBR64 0 + dd 0xfa1e0ff3 +%endmacro + +%else + +%imacro ENDBR64 0 +%endmacro + +%endif + ; -------------------------------------------------------------------------- ; Defines picked up from the C headers ; diff --git a/3rdparty/libjpeg-turbo/src/simd/powerpc/jsimd.c b/3rdparty/libjpeg-turbo/src/simd/powerpc/jsimd.c index b9e86dcfac26..461f603633aa 100644 --- a/3rdparty/libjpeg-turbo/src/simd/powerpc/jsimd.c +++ b/3rdparty/libjpeg-turbo/src/simd/powerpc/jsimd.c @@ -2,8 +2,8 @@ * jsimd_powerpc.c * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009-2011, 2014-2016, 2018, D. R. Commander. - * Copyright (C) 2015-2016, 2018, Matthieu Darbois. + * Copyright (C) 2009-2011, 2014-2016, 2018, 2022, D. R. Commander. + * Copyright (C) 2015-2016, 2018, 2022, Matthieu Darbois. * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -27,11 +27,12 @@ #include "../../jsimddct.h" #include "../jsimd.h" -#include -#include #include -#if defined(__OpenBSD__) +#if defined(__APPLE__) +#include +#include +#elif defined(__OpenBSD__) #include #include #include @@ -40,7 +41,7 @@ #include #endif -static unsigned int simd_support = ~0; +static THREAD_LOCAL unsigned int simd_support = ~0; #if !defined(__ALTIVEC__) && (defined(__linux__) || defined(ANDROID) || defined(__ANDROID__)) @@ -108,8 +109,6 @@ parse_proc_cpuinfo(int bufsize) /* * Check what SIMD accelerations are supported. - * - * FIXME: This code is racy under a multi-threaded environment. */ LOCAL(void) init_simd(void) @@ -121,6 +120,10 @@ init_simd(void) int bufsize = 1024; /* an initial guess for the line buffer size limit */ #elif defined(__amigaos4__) uint32 altivec = 0; +#elif defined(__APPLE__) + int mib[2] = { CTL_HW, HW_VECTORUNIT }; + int altivec; + size_t len = sizeof(altivec); #elif defined(__OpenBSD__) int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC }; int altivec; @@ -134,7 +137,7 @@ init_simd(void) simd_support = 0; -#if defined(__ALTIVEC__) || defined(__APPLE__) +#if defined(__ALTIVEC__) simd_support |= JSIMD_ALTIVEC; #elif defined(__linux__) || defined(ANDROID) || defined(__ANDROID__) while (!parse_proc_cpuinfo(bufsize)) { @@ -146,7 +149,7 @@ init_simd(void) IExec->GetCPUInfoTags(GCIT_VectorUnit, &altivec, TAG_DONE); if (altivec == VECTORTYPE_ALTIVEC) simd_support |= JSIMD_ALTIVEC; -#elif defined(__OpenBSD__) +#elif defined(__APPLE__) || defined(__OpenBSD__) if (sysctl(mib, 2, &altivec, &len, NULL, 0) == 0 && altivec != 0) simd_support |= JSIMD_ALTIVEC; #elif defined(__FreeBSD__) @@ -862,7 +865,7 @@ jsimd_can_encode_mcu_AC_first_prepare(void) GLOBAL(void) jsimd_encode_mcu_AC_first_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *values, size_t *zerobits) + int Al, UJCOEF *values, size_t *zerobits) { } @@ -875,7 +878,7 @@ jsimd_can_encode_mcu_AC_refine_prepare(void) GLOBAL(int) jsimd_encode_mcu_AC_refine_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *absvalues, size_t *bits) + int Al, UJCOEF *absvalues, size_t *bits) { return 0; } diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolext-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolext-avx2.asm index ffb527db00e1..39e6f207ca24 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolext-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolext-avx2.asm @@ -1,9 +1,10 @@ ; ; jccolext.asm - colorspace conversion (64-bit AVX2) ; -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -33,21 +34,22 @@ ; r13d = JDIMENSION output_row ; r14d = int num_rows -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_YMMWORD ; ymmword wk[WK_NUM] +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_YMMWORD ; ymmword wk[WK_NUM] %define WK_NUM 8 align 32 GLOBAL_FUNCTION(jsimd_rgb_ycc_convert_avx2) EXTN(jsimd_rgb_ycc_convert_avx2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_YMMWORD) ; align to 256 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 5 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, (SIZEOF_YMMWORD * WK_NUM) + COLLECT_ARGS 5 push rbx mov ecx, r10d @@ -548,9 +550,9 @@ EXTN(jsimd_rgb_ycc_convert_avx2): .return: pop rbx vzeroupper - uncollect_args 5 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 5 + lea rsp, [rbp-8] + pop r15 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolext-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolext-sse2.asm index af70ed6010f6..2073988d33c2 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolext-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolext-sse2.asm @@ -1,8 +1,9 @@ ; ; jccolext.asm - colorspace conversion (64-bit SSE2) ; -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -32,21 +33,22 @@ ; r13d = JDIMENSION output_row ; r14d = int num_rows -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] %define WK_NUM 8 align 32 GLOBAL_FUNCTION(jsimd_rgb_ycc_convert_sse2) EXTN(jsimd_rgb_ycc_convert_sse2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 5 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, (SIZEOF_XMMWORD * WK_NUM) + COLLECT_ARGS 5 push rbx mov ecx, r10d @@ -473,9 +475,9 @@ EXTN(jsimd_rgb_ycc_convert_sse2): .return: pop rbx - uncollect_args 5 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 5 + lea rsp, [rbp-8] + pop r15 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolor-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolor-avx2.asm index 16b78298dc4f..1f069caad99f 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolor-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolor-avx2.asm @@ -1,7 +1,7 @@ ; ; jccolor.asm - colorspace conversion (64-bit AVX2) ; -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; ; Based on the x86 SIMD extension for IJG JPEG library @@ -33,7 +33,7 @@ F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_rgb_ycc_convert_avx2) EXTN(jconst_rgb_ycc_convert_avx2): @@ -46,7 +46,7 @@ PD_ONEHALFM1_CJ times 8 dd (1 << (SCALEBITS - 1)) - 1 + \ (CENTERJSAMPLE << SCALEBITS) PD_ONEHALF times 8 dd (1 << (SCALEBITS - 1)) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolor-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolor-sse2.asm index e2955c213404..c0c1526d8c4d 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolor-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jccolor-sse2.asm @@ -1,7 +1,7 @@ ; ; jccolor.asm - colorspace conversion (64-bit SSE2) ; -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -32,7 +32,7 @@ F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_rgb_ycc_convert_sse2) EXTN(jconst_rgb_ycc_convert_sse2): @@ -45,7 +45,7 @@ PD_ONEHALFM1_CJ times 4 dd (1 << (SCALEBITS - 1)) - 1 + \ (CENTERJSAMPLE << SCALEBITS) PD_ONEHALF times 4 dd (1 << (SCALEBITS - 1)) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgray-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgray-avx2.asm index 591255bb1122..354683ca42f4 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgray-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgray-avx2.asm @@ -1,7 +1,7 @@ ; ; jcgray.asm - grayscale colorspace conversion (64-bit AVX2) ; -; Copyright (C) 2011, 2016, D. R. Commander. +; Copyright (C) 2011, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; ; Based on the x86 SIMD extension for IJG JPEG library @@ -29,7 +29,7 @@ F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_rgb_gray_convert_avx2) EXTN(jconst_rgb_gray_convert_avx2): @@ -38,7 +38,7 @@ PW_F0299_F0337 times 8 dw F_0_299, F_0_337 PW_F0114_F0250 times 8 dw F_0_114, F_0_250 PD_ONEHALF times 8 dd (1 << (SCALEBITS - 1)) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgray-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgray-sse2.asm index e389904f2f85..d27c4b9a82eb 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgray-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgray-sse2.asm @@ -1,7 +1,7 @@ ; ; jcgray.asm - grayscale colorspace conversion (64-bit SSE2) ; -; Copyright (C) 2011, 2016, D. R. Commander. +; Copyright (C) 2011, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -28,7 +28,7 @@ F_0_337 equ (F_0_587 - F_0_250) ; FIX(0.58700) - FIX(0.25000) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_rgb_gray_convert_sse2) EXTN(jconst_rgb_gray_convert_sse2): @@ -37,7 +37,7 @@ PW_F0299_F0337 times 4 dw F_0_299, F_0_337 PW_F0114_F0250 times 4 dw F_0_114, F_0_250 PD_ONEHALF times 4 dd (1 << (SCALEBITS - 1)) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgryext-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgryext-avx2.asm index ddcc2c0a2fe4..d2ae6d63a419 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgryext-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgryext-avx2.asm @@ -1,9 +1,10 @@ ; ; jcgryext.asm - grayscale colorspace conversion (64-bit AVX2) ; -; Copyright (C) 2011, 2016, D. R. Commander. +; Copyright (C) 2011, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -33,21 +34,22 @@ ; r13d = JDIMENSION output_row ; r14d = int num_rows -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_YMMWORD ; ymmword wk[WK_NUM] +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_YMMWORD ; ymmword wk[WK_NUM] %define WK_NUM 2 align 32 GLOBAL_FUNCTION(jsimd_rgb_gray_convert_avx2) EXTN(jsimd_rgb_gray_convert_avx2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_YMMWORD) ; align to 256 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 5 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, byte (SIZEOF_YMMWORD * WK_NUM) + COLLECT_ARGS 5 push rbx mov ecx, r10d @@ -427,9 +429,9 @@ EXTN(jsimd_rgb_gray_convert_avx2): .return: pop rbx vzeroupper - uncollect_args 5 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 5 + lea rsp, [rbp-8] + pop r15 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgryext-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgryext-sse2.asm index f1d399a63b85..3c2834e96463 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgryext-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jcgryext-sse2.asm @@ -1,8 +1,9 @@ ; ; jcgryext.asm - grayscale colorspace conversion (64-bit SSE2) ; -; Copyright (C) 2011, 2016, D. R. Commander. +; Copyright (C) 2011, 2016, 2024, D. R. Commander. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -32,21 +33,22 @@ ; r13d = JDIMENSION output_row ; r14d = int num_rows -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] %define WK_NUM 2 align 32 GLOBAL_FUNCTION(jsimd_rgb_gray_convert_sse2) EXTN(jsimd_rgb_gray_convert_sse2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 5 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, byte (SIZEOF_XMMWORD * WK_NUM) + COLLECT_ARGS 5 push rbx mov ecx, r10d @@ -352,9 +354,9 @@ EXTN(jsimd_rgb_gray_convert_sse2): .return: pop rbx - uncollect_args 5 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 5 + lea rsp, [rbp-8] + pop r15 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jchuff-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jchuff-sse2.asm index 9ea6df946ef9..39aa24650c19 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jchuff-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jchuff-sse2.asm @@ -1,9 +1,10 @@ ; ; jchuff-sse2.asm - Huffman entropy encoding (64-bit SSE2) ; -; Copyright (C) 2009-2011, 2014-2016, 2019, 2021, D. R. Commander. +; Copyright (C) 2009-2011, 2014-2016, 2019, 2021, 2023-2024, D. R. Commander. ; Copyright (C) 2015, Matthieu Darbois. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -38,7 +39,7 @@ endstruc ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_huff_encode_one_block) EXTN(jconst_huff_encode_one_block): @@ -48,7 +49,7 @@ jpeg_mask_bits dd 0x0000, 0x0001, 0x0003, 0x0007 dd 0x00ff, 0x01ff, 0x03ff, 0x07ff dd 0x0fff, 0x1fff, 0x3fff, 0x7fff - alignz 32 + ALIGNZ 32 times 1 << 14 db 15 times 1 << 13 db 14 @@ -66,7 +67,8 @@ times 1 << 2 db 3 times 1 << 1 db 2 times 1 << 0 db 1 times 1 db 0 -jpeg_nbits_table: +GLOBAL_DATA(jpeg_nbits_table) +EXTN(jpeg_nbits_table): times 1 db 0 times 1 << 0 db 1 times 1 << 1 db 2 @@ -85,10 +87,10 @@ times 1 << 13 db 14 times 1 << 14 db 15 times 1 << 15 db 16 - alignz 32 + ALIGNZ 32 %define NBITS(x) nbits_base + x -%define MASK_BITS(x) NBITS((x) * 4) + (jpeg_mask_bits - jpeg_nbits_table) +%define MASK_BITS(x) NBITS((x) * 4) + (jpeg_mask_bits - EXTN(jpeg_nbits_table)) ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -208,15 +210,15 @@ times 1 << 15 db 16 ; rax - buffer ; rbx - temp ; rcx - nbits -; rdx - block --> free_bits +; rdx - code ; rsi - nbits_base ; rdi - t -; rbp - code ; r8 - dctbl --> code_temp ; r9 - actbl ; r10 - state ; r11 - index ; r12 - put_buffer +; r15 - block --> free_bits %define buffer rax %ifdef WIN64 @@ -231,12 +233,11 @@ times 1 << 15 db 16 %define nbitsq rcx %define nbits ecx %define nbitsb cl -%define block rdx +%define codeq rdx +%define code edx %define nbits_base rsi %define t rdi %define td edi -%define codeq rbp -%define code ebp %define dctbl r8 %define actbl r9 %define state r10 @@ -244,6 +245,7 @@ times 1 << 15 db 16 %define indexd r11d %define put_buffer r12 %define put_bufferd r12d +%define block r15 ; Step 1: Re-arrange input data according to jpeg_natural_order ; xx 01 02 03 04 05 06 07 xx 01 08 16 09 02 03 10 @@ -259,6 +261,9 @@ times 1 << 15 db 16 GLOBAL_FUNCTION(jsimd_huff_encode_one_block_sse2) EXTN(jsimd_huff_encode_one_block_sse2): + ENDBR64 + push rbp + mov rbp, rsp %ifdef WIN64 @@ -266,15 +271,15 @@ EXTN(jsimd_huff_encode_one_block_sse2): ; rdx = JOCTET *buffer ; r8 = JCOEFPTR block ; r9 = int last_dc_val -; [rax+48] = c_derived_tbl *dctbl -; [rax+56] = c_derived_tbl *actbl +; [rbp+48] = c_derived_tbl *dctbl +; [rbp+56] = c_derived_tbl *actbl ;X: X = code stream mov buffer, rdx + push r15 mov block, r8 movups xmm3, XMMWORD [block + 0 * SIZEOF_WORD] ;D: w3 = xx 01 02 03 04 05 06 07 push rbx - push rbp movdqa xmm0, xmm3 ;A: w0 = xx 01 02 03 04 05 06 07 push rsi push rdi @@ -284,12 +289,10 @@ EXTN(jsimd_huff_encode_one_block_sse2): movsx code, word [block] ;Z: code = block[0]; pxor xmm4, xmm4 ;A: w4[i] = 0; sub code, r9d ;Z: code -= last_dc_val; - mov dctbl, POINTER [rsp+6*8+4*8] - mov actbl, POINTER [rsp+6*8+5*8] + mov dctbl, POINTER [rbp+48] + mov actbl, POINTER [rbp+56] punpckldq xmm0, xmm1 ;A: w0 = xx 01 08 09 02 03 10 11 - lea nbits_base, [rel jpeg_nbits_table] - add rsp, -DCTSIZE2 * SIZEOF_WORD - mov t, rsp + lea nbits_base, [rel EXTN(jpeg_nbits_table)] %else @@ -301,23 +304,27 @@ EXTN(jsimd_huff_encode_one_block_sse2): ; r9 = c_derived_tbl *actbl ;X: X = code stream + push r15 + mov block, rdx movups xmm3, XMMWORD [block + 0 * SIZEOF_WORD] ;D: w3 = xx 01 02 03 04 05 06 07 push rbx - push rbp movdqa xmm0, xmm3 ;A: w0 = xx 01 02 03 04 05 06 07 push r12 mov state, rdi mov buffer, rsi movups xmm1, XMMWORD [block + 8 * SIZEOF_WORD] ;B: w1 = 08 09 10 11 12 13 14 15 movsx codeq, word [block] ;Z: code = block[0]; - lea nbits_base, [rel jpeg_nbits_table] + lea nbits_base, [rel EXTN(jpeg_nbits_table)] pxor xmm4, xmm4 ;A: w4[i] = 0; sub codeq, rcx ;Z: code -= last_dc_val; punpckldq xmm0, xmm1 ;A: w0 = xx 01 08 09 02 03 10 11 - lea t, [rsp - DCTSIZE2 * SIZEOF_WORD] ; use red zone for t_ %endif + ; Allocate stack space for t array, and realign stack. + add rsp, -DCTSIZE2 * SIZEOF_WORD - 8 + mov t, rsp + pshuflw xmm0, xmm0, 11001001b ;A: w0 = 01 08 xx 09 02 03 10 11 pinsrw xmm0, word [block + 16 * SIZEOF_WORD], 2 ;A: w0 = 01 08 16 09 02 03 10 11 punpckhdq xmm3, xmm1 ;D: w3 = 04 05 12 13 06 07 14 15 @@ -443,9 +450,9 @@ EXTN(jsimd_huff_encode_one_block_sse2): pinsrw xmm5, word [block + 29 * SIZEOF_WORD], 7 ;E: w5 = 42 49 56 57 50 43 36 29 ; (Row 4, offset 1) %undef block -%define free_bitsq rdx -%define free_bitsd edx -%define free_bitsb dl +%define free_bitsq r15 +%define free_bitsd r15d +%define free_bitsb r15b pcmpeqw xmm1, xmm0 ;F: w1[i] = (w1[i] == 0 ? -1 : 0); shl tempq, 48 ;Z: temp <<= 48; pxor xmm2, xmm2 ;E: w2[i] = 0; @@ -534,12 +541,8 @@ EXTN(jsimd_huff_encode_one_block_sse2): test index, index jnz .BLOOP ; } while (index != 0); .ELOOP: ; } /* index != 0 */ - sub td, esp ; t -= (WIN64: &t_[0], UNIX: &t_[64]); -%ifdef WIN64 + sub td, esp ; t -= &t_[0]; cmp td, (DCTSIZE2 - 2) * SIZEOF_WORD ; if (t != 62) -%else - cmp td, -2 * SIZEOF_WORD ; if (t != -2) -%endif je .EFN ; { movzx nbits, byte [actbl + c_derived_tbl.ehufsi + 0] ; nbits = actbl->ehufsi[0]; @@ -556,18 +559,17 @@ EXTN(jsimd_huff_encode_one_block_sse2): ; state->cur.put_buffer.simd = put_buffer; mov byte [state + working_state.cur.free_bits], free_bitsb ; state->cur.free_bits = free_bits; -%ifdef WIN64 - sub rsp, -DCTSIZE2 * SIZEOF_WORD + sub rsp, -DCTSIZE2 * SIZEOF_WORD - 8 pop r12 +%ifdef WIN64 pop rdi pop rsi - pop rbp pop rbx %else - pop r12 - pop rbp pop rbx %endif + pop r15 + pop rbp ret ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jcphuff-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jcphuff-sse2.asm index 01b5c0235faf..0e2740462e69 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jcphuff-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jcphuff-sse2.asm @@ -3,6 +3,8 @@ ; (64-bit SSE2) ; ; Copyright (C) 2016, 2018, Matthieu Darbois +; Copyright (C) 2023, Aliaksiej Kandracienka. +; Copyright (C) 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -281,16 +283,13 @@ GLOBAL_FUNCTION(jsimd_encode_mcu_AC_first_prepare_sse2) EXTN(jsimd_encode_mcu_AC_first_prepare_sse2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [rbp - 16] - collect_args 6 - - movdqa XMMWORD [rbp - 16], ZERO + sub rsp, SIZEOF_XMMWORD + movdqa XMMWORD [rsp], ZERO + COLLECT_ARGS 6 movd AL, r13d pxor ZERO, ZERO @@ -384,10 +383,9 @@ EXTN(jsimd_encode_mcu_AC_first_prepare_sse2): REDUCE0 - movdqa ZERO, XMMWORD [rbp - 16] - uncollect_args 6 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 6 + movdqa ZERO, XMMWORD [rsp] + mov rsp, rbp pop rbp ret @@ -449,16 +447,13 @@ EXTN(jsimd_encode_mcu_AC_first_prepare_sse2): GLOBAL_FUNCTION(jsimd_encode_mcu_AC_refine_prepare_sse2) EXTN(jsimd_encode_mcu_AC_refine_prepare_sse2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [rbp - 16] - collect_args 6 - - movdqa XMMWORD [rbp - 16], ZERO + sub rsp, SIZEOF_XMMWORD + movdqa XMMWORD [rsp], ZERO + COLLECT_ARGS 6 xor SIGN, SIGN xor EOB, EOB @@ -606,10 +601,9 @@ EXTN(jsimd_encode_mcu_AC_refine_prepare_sse2): REDUCE0 mov eax, EOB - movdqa ZERO, XMMWORD [rbp - 16] - uncollect_args 6 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 6 + movdqa ZERO, XMMWORD [rsp] + mov rsp, rbp pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jcsample-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jcsample-avx2.asm index b32527aebeaa..fede6b38b47b 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jcsample-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jcsample-avx2.asm @@ -2,7 +2,7 @@ ; jcsample.asm - downsampling (64-bit AVX2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; Copyright (C) 2018, Matthias Räncker. ; @@ -44,10 +44,10 @@ GLOBAL_FUNCTION(jsimd_h2v1_downsample_avx2) EXTN(jsimd_h2v1_downsample_avx2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 6 + COLLECT_ARGS 6 mov ecx, r13d shl rcx, 3 ; imul rcx,DCTSIZE (rcx = output_cols) @@ -178,7 +178,7 @@ EXTN(jsimd_h2v1_downsample_avx2): .return: vzeroupper - uncollect_args 6 + UNCOLLECT_ARGS 6 pop rbp ret @@ -206,10 +206,10 @@ EXTN(jsimd_h2v1_downsample_avx2): GLOBAL_FUNCTION(jsimd_h2v2_downsample_avx2) EXTN(jsimd_h2v2_downsample_avx2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 6 + COLLECT_ARGS 6 mov ecx, r13d shl rcx, 3 ; imul rcx,DCTSIZE (rcx = output_cols) @@ -358,7 +358,7 @@ EXTN(jsimd_h2v2_downsample_avx2): .return: vzeroupper - uncollect_args 6 + UNCOLLECT_ARGS 6 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jcsample-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jcsample-sse2.asm index 2fcfe4567ab9..0a0ee65e5a1a 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jcsample-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jcsample-sse2.asm @@ -2,7 +2,7 @@ ; jcsample.asm - downsampling (64-bit SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2018, Matthias Räncker. ; ; Based on the x86 SIMD extension for IJG JPEG library @@ -43,10 +43,10 @@ GLOBAL_FUNCTION(jsimd_h2v1_downsample_sse2) EXTN(jsimd_h2v1_downsample_sse2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 6 + COLLECT_ARGS 6 mov ecx, r13d shl rcx, 3 ; imul rcx,DCTSIZE (rcx = output_cols) @@ -160,7 +160,7 @@ EXTN(jsimd_h2v1_downsample_sse2): jg near .rowloop .return: - uncollect_args 6 + UNCOLLECT_ARGS 6 pop rbp ret @@ -188,10 +188,10 @@ EXTN(jsimd_h2v1_downsample_sse2): GLOBAL_FUNCTION(jsimd_h2v2_downsample_sse2) EXTN(jsimd_h2v2_downsample_sse2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 6 + COLLECT_ARGS 6 mov ecx, r13d shl rcx, 3 ; imul rcx,DCTSIZE (rcx = output_cols) @@ -321,7 +321,7 @@ EXTN(jsimd_h2v2_downsample_sse2): jg near .rowloop .return: - uncollect_args 6 + UNCOLLECT_ARGS 6 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolext-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolext-avx2.asm index 2370fda64249..a8384cb5602b 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolext-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolext-avx2.asm @@ -2,9 +2,10 @@ ; jdcolext.asm - colorspace conversion (64-bit AVX2) ; ; Copyright 2009, 2012 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2012, 2016, D. R. Commander. +; Copyright (C) 2009, 2012, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -34,21 +35,22 @@ ; r13 = JSAMPARRAY output_buf ; r14d = int num_rows -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_YMMWORD ; ymmword wk[WK_NUM] +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_YMMWORD ; ymmword wk[WK_NUM] %define WK_NUM 2 align 32 GLOBAL_FUNCTION(jsimd_ycc_rgb_convert_avx2) EXTN(jsimd_ycc_rgb_convert_avx2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_YMMWORD) ; align to 256 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 5 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, byte (WK_NUM * SIZEOF_YMMWORD) + COLLECT_ARGS 5 push rbx mov ecx, r10d ; num_cols @@ -485,9 +487,9 @@ EXTN(jsimd_ycc_rgb_convert_avx2): .return: pop rbx vzeroupper - uncollect_args 5 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 5 + lea rsp, [rbp-8] + pop r15 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolext-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolext-sse2.asm index e07c8d75188c..bfb59abf1232 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolext-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolext-sse2.asm @@ -2,8 +2,9 @@ ; jdcolext.asm - colorspace conversion (64-bit SSE2) ; ; Copyright 2009, 2012 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2012, 2016, D. R. Commander. +; Copyright (C) 2009, 2012, 2016, 2024, D. R. Commander. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -33,21 +34,22 @@ ; r13 = JSAMPARRAY output_buf ; r14d = int num_rows -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] %define WK_NUM 2 align 32 GLOBAL_FUNCTION(jsimd_ycc_rgb_convert_sse2) EXTN(jsimd_ycc_rgb_convert_sse2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 5 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, byte (SIZEOF_XMMWORD * WK_NUM) + COLLECT_ARGS 5 push rbx mov ecx, r10d ; num_cols @@ -428,9 +430,9 @@ EXTN(jsimd_ycc_rgb_convert_sse2): .return: pop rbx - uncollect_args 5 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 5 + lea rsp, [rbp-8] + pop r15 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolor-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolor-avx2.asm index 43de9db04dc6..4d52a0f16a11 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolor-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolor-avx2.asm @@ -2,7 +2,7 @@ ; jdcolor.asm - colorspace conversion (64-bit AVX2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; ; Based on the x86 SIMD extension for IJG JPEG library @@ -32,7 +32,7 @@ F_0_228 equ (131072 - F_1_772) ; FIX(2) - FIX(1.77200) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_ycc_rgb_convert_avx2) EXTN(jconst_ycc_rgb_convert_avx2): @@ -43,7 +43,7 @@ PW_MF0344_F0285 times 8 dw -F_0_344, F_0_285 PW_ONE times 16 dw 1 PD_ONEHALF times 8 dd 1 << (SCALEBITS - 1) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolor-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolor-sse2.asm index b3f1fec07eb5..93d3c8dd4a07 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolor-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdcolor-sse2.asm @@ -2,7 +2,7 @@ ; jdcolor.asm - colorspace conversion (64-bit SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -31,7 +31,7 @@ F_0_228 equ (131072 - F_1_772) ; FIX(2) - FIX(1.77200) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_ycc_rgb_convert_sse2) EXTN(jconst_ycc_rgb_convert_sse2): @@ -42,7 +42,7 @@ PW_MF0344_F0285 times 4 dw -F_0_344, F_0_285 PW_ONE times 8 dw 1 PD_ONEHALF times 4 dd 1 << (SCALEBITS - 1) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmerge-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmerge-avx2.asm index 9515a17013d3..4be435624e4f 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmerge-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmerge-avx2.asm @@ -2,7 +2,7 @@ ; jdmerge.asm - merged upsampling/color conversion (64-bit AVX2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; ; Based on the x86 SIMD extension for IJG JPEG library @@ -32,7 +32,7 @@ F_0_228 equ (131072 - F_1_772) ; FIX(2) - FIX(1.77200) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_merged_upsample_avx2) EXTN(jconst_merged_upsample_avx2): @@ -43,7 +43,7 @@ PW_MF0344_F0285 times 8 dw -F_0_344, F_0_285 PW_ONE times 16 dw 1 PD_ONEHALF times 8 dd 1 << (SCALEBITS - 1) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmerge-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmerge-sse2.asm index aedccc20f6c0..a22f6ac733c5 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmerge-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmerge-sse2.asm @@ -2,7 +2,7 @@ ; jdmerge.asm - merged upsampling/color conversion (64-bit SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -31,7 +31,7 @@ F_0_228 equ (131072 - F_1_772) ; FIX(2) - FIX(1.77200) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_merged_upsample_sse2) EXTN(jconst_merged_upsample_sse2): @@ -42,7 +42,7 @@ PW_MF0344_F0285 times 4 dw -F_0_344, F_0_285 PW_ONE times 8 dw 1 PD_ONEHALF times 4 dd 1 << (SCALEBITS - 1) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmrgext-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmrgext-avx2.asm index 8b264b4f039f..3392f3a38344 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmrgext-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmrgext-avx2.asm @@ -2,9 +2,10 @@ ; jdmrgext.asm - merged upsampling/color conversion (64-bit AVX2) ; ; Copyright 2009, 2012 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2012, 2016, D. R. Commander. +; Copyright (C) 2009, 2012, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -34,21 +35,22 @@ ; r12d = JDIMENSION in_row_group_ctr ; r13 = JSAMPARRAY output_buf -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_YMMWORD ; ymmword wk[WK_NUM] +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_YMMWORD ; ymmword wk[WK_NUM] %define WK_NUM 3 align 32 GLOBAL_FUNCTION(jsimd_h2v1_merged_upsample_avx2) EXTN(jsimd_h2v1_merged_upsample_avx2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_YMMWORD) ; align to 256 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 4 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, SIZEOF_YMMWORD * WK_NUM + COLLECT_ARGS 4 push rbx mov ecx, r10d ; col @@ -479,9 +481,9 @@ EXTN(jsimd_h2v1_merged_upsample_avx2): .return: pop rbx vzeroupper - uncollect_args 4 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 4 + lea rsp, [rbp-8] + pop r15 pop rbp ret @@ -505,10 +507,10 @@ EXTN(jsimd_h2v1_merged_upsample_avx2): GLOBAL_FUNCTION(jsimd_h2v2_merged_upsample_avx2) EXTN(jsimd_h2v2_merged_upsample_avx2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 4 + COLLECT_ARGS 4 push rbx mov eax, r10d @@ -587,7 +589,7 @@ EXTN(jsimd_h2v2_merged_upsample_avx2): add rsp, SIZEOF_JSAMPARRAY*4 pop rbx - uncollect_args 4 + UNCOLLECT_ARGS 4 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmrgext-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmrgext-sse2.asm index eb3ab9dbd945..901db984f963 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmrgext-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdmrgext-sse2.asm @@ -2,8 +2,9 @@ ; jdmrgext.asm - merged upsampling/color conversion (64-bit SSE2) ; ; Copyright 2009, 2012 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2012, 2016, D. R. Commander. +; Copyright (C) 2009, 2012, 2016, 2024, D. R. Commander. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -33,21 +34,22 @@ ; r12d = JDIMENSION in_row_group_ctr ; r13 = JSAMPARRAY output_buf -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] %define WK_NUM 3 align 32 GLOBAL_FUNCTION(jsimd_h2v1_merged_upsample_sse2) EXTN(jsimd_h2v1_merged_upsample_sse2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 4 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, byte (SIZEOF_XMMWORD * WK_NUM) + COLLECT_ARGS 4 push rbx mov ecx, r10d ; col @@ -421,9 +423,9 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): .return: pop rbx - uncollect_args 4 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 4 + lea rsp, [rbp-8] + pop r15 pop rbp ret @@ -447,10 +449,10 @@ EXTN(jsimd_h2v1_merged_upsample_sse2): GLOBAL_FUNCTION(jsimd_h2v2_merged_upsample_sse2) EXTN(jsimd_h2v2_merged_upsample_sse2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 4 + COLLECT_ARGS 4 push rbx mov eax, r10d @@ -529,7 +531,7 @@ EXTN(jsimd_h2v2_merged_upsample_sse2): add rsp, SIZEOF_JSAMPARRAY*4 pop rbx - uncollect_args 4 + UNCOLLECT_ARGS 4 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdsample-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdsample-avx2.asm index 1e4979f933e4..017427a15890 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdsample-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdsample-avx2.asm @@ -2,9 +2,10 @@ ; jdsample.asm - upsampling (64-bit AVX2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2015, Intel Corporation. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -21,7 +22,7 @@ ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fancy_upsample_avx2) EXTN(jconst_fancy_upsample_avx2): @@ -32,7 +33,7 @@ PW_THREE times 16 dw 3 PW_SEVEN times 16 dw 7 PW_EIGHT times 16 dw 8 - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -61,11 +62,11 @@ PW_EIGHT times 16 dw 8 GLOBAL_FUNCTION(jsimd_h2v1_fancy_upsample_avx2) EXTN(jsimd_h2v1_fancy_upsample_avx2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - push_xmm 3 - collect_args 4 + PUSH_XMM 3 + COLLECT_ARGS 4 mov eax, r11d ; colctr test rax, rax @@ -186,8 +187,8 @@ EXTN(jsimd_h2v1_fancy_upsample_avx2): .return: vzeroupper - uncollect_args 4 - pop_xmm 3 + UNCOLLECT_ARGS 4 + POP_XMM 3 pop rbp ret @@ -208,22 +209,23 @@ EXTN(jsimd_h2v1_fancy_upsample_avx2): ; r12 = JSAMPARRAY input_data ; r13 = JSAMPARRAY *output_data_ptr -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_YMMWORD ; ymmword wk[WK_NUM] +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_YMMWORD ; ymmword wk[WK_NUM] %define WK_NUM 4 align 32 GLOBAL_FUNCTION(jsimd_h2v2_fancy_upsample_avx2) EXTN(jsimd_h2v2_fancy_upsample_avx2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 - and rsp, byte (-SIZEOF_YMMWORD) ; align to 256 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - push_xmm 3 - collect_args 4 + mov rbp, rsp + push r15 + and rsp, byte (-SIZEOF_YMMWORD) ; align to 128 bits + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, (SIZEOF_YMMWORD * WK_NUM) + PUSH_XMM 3 + COLLECT_ARGS 4 push rbx mov eax, r11d ; colctr @@ -498,10 +500,10 @@ EXTN(jsimd_h2v2_fancy_upsample_avx2): .return: pop rbx vzeroupper - uncollect_args 4 - pop_xmm 3 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 4 + POP_XMM 3 + lea rsp, [rbp-8] + pop r15 pop rbp ret @@ -524,10 +526,10 @@ EXTN(jsimd_h2v2_fancy_upsample_avx2): GLOBAL_FUNCTION(jsimd_h2v1_upsample_avx2) EXTN(jsimd_h2v1_upsample_avx2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 4 + COLLECT_ARGS 4 mov edx, r11d add rdx, byte (SIZEOF_YMMWORD-1) @@ -590,7 +592,7 @@ EXTN(jsimd_h2v1_upsample_avx2): .return: vzeroupper - uncollect_args 4 + UNCOLLECT_ARGS 4 pop rbp ret @@ -613,10 +615,10 @@ EXTN(jsimd_h2v1_upsample_avx2): GLOBAL_FUNCTION(jsimd_h2v2_upsample_avx2) EXTN(jsimd_h2v2_upsample_avx2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 4 + COLLECT_ARGS 4 push rbx mov edx, r11d @@ -687,7 +689,7 @@ EXTN(jsimd_h2v2_upsample_avx2): .return: pop rbx vzeroupper - uncollect_args 4 + UNCOLLECT_ARGS 4 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdsample-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdsample-sse2.asm index 38dbceec269d..95c4d4c9eded 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jdsample-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jdsample-sse2.asm @@ -2,8 +2,9 @@ ; jdsample.asm - upsampling (64-bit SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -20,7 +21,7 @@ ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fancy_upsample_sse2) EXTN(jconst_fancy_upsample_sse2): @@ -31,7 +32,7 @@ PW_THREE times 8 dw 3 PW_SEVEN times 8 dw 7 PW_EIGHT times 8 dw 8 - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -60,10 +61,10 @@ PW_EIGHT times 8 dw 8 GLOBAL_FUNCTION(jsimd_h2v1_fancy_upsample_sse2) EXTN(jsimd_h2v1_fancy_upsample_sse2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 4 + COLLECT_ARGS 4 mov eax, r11d ; colctr test rax, rax @@ -174,7 +175,7 @@ EXTN(jsimd_h2v1_fancy_upsample_sse2): jg near .rowloop .return: - uncollect_args 4 + UNCOLLECT_ARGS 4 pop rbp ret @@ -195,21 +196,22 @@ EXTN(jsimd_h2v1_fancy_upsample_sse2): ; r12 = JSAMPARRAY input_data ; r13 = JSAMPARRAY *output_data_ptr -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] %define WK_NUM 4 align 32 GLOBAL_FUNCTION(jsimd_h2v2_fancy_upsample_sse2) EXTN(jsimd_h2v2_fancy_upsample_sse2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 4 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, byte (SIZEOF_XMMWORD * WK_NUM) + COLLECT_ARGS 4 push rbx mov eax, r11d ; colctr @@ -472,9 +474,9 @@ EXTN(jsimd_h2v2_fancy_upsample_sse2): .return: pop rbx - uncollect_args 4 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 4 + lea rsp, [rbp-8] + pop r15 pop rbp ret @@ -497,10 +499,10 @@ EXTN(jsimd_h2v2_fancy_upsample_sse2): GLOBAL_FUNCTION(jsimd_h2v1_upsample_sse2) EXTN(jsimd_h2v1_upsample_sse2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 4 + COLLECT_ARGS 4 mov edx, r11d add rdx, byte (2*SIZEOF_XMMWORD)-1 @@ -561,7 +563,7 @@ EXTN(jsimd_h2v1_upsample_sse2): jg short .rowloop .return: - uncollect_args 4 + UNCOLLECT_ARGS 4 pop rbp ret @@ -584,10 +586,10 @@ EXTN(jsimd_h2v1_upsample_sse2): GLOBAL_FUNCTION(jsimd_h2v2_upsample_sse2) EXTN(jsimd_h2v2_upsample_sse2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 4 + COLLECT_ARGS 4 push rbx mov edx, r11d @@ -656,7 +658,7 @@ EXTN(jsimd_h2v2_upsample_sse2): .return: pop rbx - uncollect_args 4 + UNCOLLECT_ARGS 4 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctflt-sse.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctflt-sse.asm index ef2796649bc6..cf46d93d6157 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctflt-sse.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctflt-sse.asm @@ -2,7 +2,8 @@ ; jfdctflt.asm - floating-point FDCT (64-bit SSE) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -34,7 +35,7 @@ ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fdct_float_sse) EXTN(jconst_fdct_float_sse): @@ -44,7 +45,7 @@ PD_0_707 times 4 dd 0.707106781186547524400844 PD_0_541 times 4 dd 0.541196100146196984399723 PD_1_306 times 4 dd 1.306562964876376527856643 - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -58,21 +59,22 @@ PD_1_306 times 4 dd 1.306562964876376527856643 ; r10 = FAST_FLOAT *data -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] %define WK_NUM 2 align 32 GLOBAL_FUNCTION(jsimd_fdct_float_sse) EXTN(jsimd_fdct_float_sse): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 1 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, byte (SIZEOF_XMMWORD * WK_NUM) + COLLECT_ARGS 1 ; ---- Pass 1: process rows. @@ -344,9 +346,9 @@ EXTN(jsimd_fdct_float_sse): dec rcx jnz near .columnloop - uncollect_args 1 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 1 + lea rsp, [rbp-8] + pop r15 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctfst-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctfst-sse2.asm index 2e1bfe6e8c2f..cdc62365857e 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctfst-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctfst-sse2.asm @@ -2,7 +2,8 @@ ; jfdctfst.asm - fast integer FDCT (64-bit SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -49,7 +50,7 @@ F_1_306 equ DESCALE(1402911301, 30 - CONST_BITS) ; FIX(1.306562965) %define PRE_MULTIPLY_SCALE_BITS 2 %define CONST_SHIFT (16 - PRE_MULTIPLY_SCALE_BITS - CONST_BITS) - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fdct_ifast_sse2) EXTN(jconst_fdct_ifast_sse2): @@ -59,7 +60,7 @@ PW_F0382 times 8 dw F_0_382 << CONST_SHIFT PW_F0541 times 8 dw F_0_541 << CONST_SHIFT PW_F1306 times 8 dw F_1_306 << CONST_SHIFT - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -73,21 +74,22 @@ PW_F1306 times 8 dw F_1_306 << CONST_SHIFT ; r10 = DCTELEM *data -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] %define WK_NUM 2 align 32 GLOBAL_FUNCTION(jsimd_fdct_ifast_sse2) EXTN(jsimd_fdct_ifast_sse2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 1 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, byte (SIZEOF_XMMWORD * WK_NUM) + COLLECT_ARGS 1 ; ---- Pass 1: process rows. @@ -378,9 +380,9 @@ EXTN(jsimd_fdct_ifast_sse2): movdqa XMMWORD [XMMBLOCK(5,0,rdx,SIZEOF_DCTELEM)], xmm6 movdqa XMMWORD [XMMBLOCK(1,0,rdx,SIZEOF_DCTELEM)], xmm2 - uncollect_args 1 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 1 + lea rsp, [rbp-8] + pop r15 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctint-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctint-avx2.asm index e56258b48aa3..b6b4c73a509c 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctint-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctint-avx2.asm @@ -2,7 +2,7 @@ ; jfdctint.asm - accurate integer FDCT (64-bit AVX2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, 2018, 2020, D. R. Commander. +; Copyright (C) 2009, 2016, 2018, 2020, 2024, D. R. Commander. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -65,7 +65,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; %1-%4: Input/output registers ; %5-%8: Temp registers -%macro dotranspose 8 +%macro DOTRANSPOSE 8 ; %1=(00 01 02 03 04 05 06 07 40 41 42 43 44 45 46 47) ; %2=(10 11 12 13 14 15 16 17 50 51 52 53 54 55 56 57) ; %3=(20 21 22 23 24 25 26 27 60 61 62 63 64 65 66 67) @@ -108,7 +108,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; %5-%8: Temp registers ; %9: Pass (1 or 2) -%macro dodct 9 +%macro DODCT 9 vpsubw %5, %1, %4 ; %5=data1_0-data6_7=tmp6_7 vpaddw %6, %1, %4 ; %6=data1_0+data6_7=tmp1_0 vpaddw %7, %2, %3 ; %7=data3_2+data4_5=tmp3_2 @@ -223,7 +223,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fdct_islow_avx2) EXTN(jconst_fdct_islow_avx2): @@ -242,7 +242,7 @@ PW_DESCALE_P2X times 16 dw 1 << (PASS1_BITS - 1) PW_1_NEG1 times 8 dw 1 times 8 dw -1 - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -260,10 +260,10 @@ PW_1_NEG1 times 8 dw 1 GLOBAL_FUNCTION(jsimd_fdct_islow_avx2) EXTN(jsimd_fdct_islow_avx2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 1 + COLLECT_ARGS 1 ; ---- Pass 1: process rows. @@ -285,9 +285,9 @@ EXTN(jsimd_fdct_islow_avx2): ; ymm2=(20 21 22 23 24 25 26 27 60 61 62 63 64 65 66 67) ; ymm3=(30 31 32 33 34 35 36 37 70 71 72 73 74 75 76 77) - dotranspose ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7 + DOTRANSPOSE ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7 - dodct ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7, 1 + DODCT ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7, 1 ; ymm0=data0_4, ymm1=data3_1, ymm2=data2_6, ymm3=data7_5 ; ---- Pass 2: process columns. @@ -295,9 +295,9 @@ EXTN(jsimd_fdct_islow_avx2): vperm2i128 ymm4, ymm1, ymm3, 0x20 ; ymm4=data3_7 vperm2i128 ymm1, ymm1, ymm3, 0x31 ; ymm1=data1_5 - dotranspose ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7 + DOTRANSPOSE ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7 - dodct ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7, 2 + DODCT ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7, 2 ; ymm0=data0_4, ymm1=data3_1, ymm2=data2_6, ymm4=data7_5 vperm2i128 ymm3, ymm0, ymm1, 0x30 ; ymm3=data0_1 @@ -311,7 +311,7 @@ EXTN(jsimd_fdct_islow_avx2): vmovdqu YMMWORD [YMMBLOCK(6,0,r10,SIZEOF_DCTELEM)], ymm7 vzeroupper - uncollect_args 1 + UNCOLLECT_ARGS 1 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctint-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctint-sse2.asm index ec1f383ccb73..44e7cd05546b 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctint-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jfdctint-sse2.asm @@ -2,7 +2,8 @@ ; jfdctint.asm - accurate integer FDCT (64-bit SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, 2020, D. R. Commander. +; Copyright (C) 2009, 2016, 2020, 2024, D. R. Commander. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -63,7 +64,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_fdct_islow_sse2) EXTN(jconst_fdct_islow_sse2): @@ -80,7 +81,7 @@ PD_DESCALE_P1 times 4 dd 1 << (DESCALE_P1 - 1) PD_DESCALE_P2 times 4 dd 1 << (DESCALE_P2 - 1) PW_DESCALE_P2X times 8 dw 1 << (PASS1_BITS - 1) - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -94,21 +95,22 @@ PW_DESCALE_P2X times 8 dw 1 << (PASS1_BITS - 1) ; r10 = DCTELEM *data -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] %define WK_NUM 6 align 32 GLOBAL_FUNCTION(jsimd_fdct_islow_sse2) EXTN(jsimd_fdct_islow_sse2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 1 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, byte (SIZEOF_XMMWORD * WK_NUM) + COLLECT_ARGS 1 ; ---- Pass 1: process rows. @@ -608,9 +610,9 @@ EXTN(jsimd_fdct_islow_sse2): movdqa XMMWORD [XMMBLOCK(5,0,rdx,SIZEOF_DCTELEM)], xmm1 movdqa XMMWORD [XMMBLOCK(3,0,rdx,SIZEOF_DCTELEM)], xmm3 - uncollect_args 1 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 1 + lea rsp, [rbp-8] + pop r15 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctflt-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctflt-sse2.asm index 60bf96189613..c7cb39a0729a 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctflt-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctflt-sse2.asm @@ -2,8 +2,9 @@ ; jidctflt.asm - floating-point IDCT (64-bit SSE & SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -24,18 +25,18 @@ ; -------------------------------------------------------------------------- -%macro unpcklps2 2 ; %1=(0 1 2 3) / %2=(4 5 6 7) => %1=(0 1 4 5) +%macro UNPCKLPS2 2 ; %1=(0 1 2 3) / %2=(4 5 6 7) => %1=(0 1 4 5) shufps %1, %2, 0x44 %endmacro -%macro unpckhps2 2 ; %1=(0 1 2 3) / %2=(4 5 6 7) => %1=(2 3 6 7) +%macro UNPCKHPS2 2 ; %1=(0 1 2 3) / %2=(4 5 6 7) => %1=(2 3 6 7) shufps %1, %2, 0xEE %endmacro ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_float_sse2) EXTN(jconst_idct_float_sse2): @@ -47,7 +48,7 @@ PD_M2_613 times 4 dd -2.613125929752753055713286 PD_RNDINT_MAGIC times 4 dd 100663296.0 ; (float)(0x00C00000 << 3) PB_CENTERJSAMP times 16 db CENTERJSAMPLE - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -65,8 +66,7 @@ PB_CENTERJSAMP times 16 db CENTERJSAMPLE ; r12 = JSAMPARRAY output_buf ; r13d = JDIMENSION output_col -%define original_rbp rbp + 0 -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_XMMWORD +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] %define WK_NUM 2 %define workspace wk(0) - DCTSIZE2 * SIZEOF_FAST_FLOAT @@ -76,14 +76,15 @@ PB_CENTERJSAMP times 16 db CENTERJSAMPLE GLOBAL_FUNCTION(jsimd_idct_float_sse2) EXTN(jsimd_idct_float_sse2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp lea rsp, [workspace] - collect_args 4 + COLLECT_ARGS 4 push rbx ; ---- Pass 1: process columns from input, store into work array. @@ -280,11 +281,11 @@ EXTN(jsimd_idct_float_sse2): unpckhps xmm4, xmm0 ; xmm4=(42 52 43 53) movaps xmm3, xmm6 ; transpose coefficients(phase 2) - unpcklps2 xmm6, xmm7 ; xmm6=(00 10 20 30) - unpckhps2 xmm3, xmm7 ; xmm3=(01 11 21 31) + UNPCKLPS2 xmm6, xmm7 ; xmm6=(00 10 20 30) + UNPCKHPS2 xmm3, xmm7 ; xmm3=(01 11 21 31) movaps xmm0, xmm1 ; transpose coefficients(phase 2) - unpcklps2 xmm1, xmm2 ; xmm1=(02 12 22 32) - unpckhps2 xmm0, xmm2 ; xmm0=(03 13 23 33) + UNPCKLPS2 xmm1, xmm2 ; xmm1=(02 12 22 32) + UNPCKHPS2 xmm0, xmm2 ; xmm0=(03 13 23 33) movaps xmm7, XMMWORD [wk(0)] ; xmm7=(60 70 61 71) movaps xmm2, XMMWORD [wk(1)] ; xmm2=(62 72 63 73) @@ -295,11 +296,11 @@ EXTN(jsimd_idct_float_sse2): movaps XMMWORD [XMMBLOCK(3,0,rdi,SIZEOF_FAST_FLOAT)], xmm0 movaps xmm6, xmm5 ; transpose coefficients(phase 2) - unpcklps2 xmm5, xmm7 ; xmm5=(40 50 60 70) - unpckhps2 xmm6, xmm7 ; xmm6=(41 51 61 71) + UNPCKLPS2 xmm5, xmm7 ; xmm5=(40 50 60 70) + UNPCKHPS2 xmm6, xmm7 ; xmm6=(41 51 61 71) movaps xmm3, xmm4 ; transpose coefficients(phase 2) - unpcklps2 xmm4, xmm2 ; xmm4=(42 52 62 72) - unpckhps2 xmm3, xmm2 ; xmm3=(43 53 63 73) + UNPCKLPS2 xmm4, xmm2 ; xmm4=(42 52 62 72) + UNPCKHPS2 xmm3, xmm2 ; xmm3=(43 53 63 73) movaps XMMWORD [XMMBLOCK(0,1,rdi,SIZEOF_FAST_FLOAT)], xmm5 movaps XMMWORD [XMMBLOCK(1,1,rdi,SIZEOF_FAST_FLOAT)], xmm6 @@ -322,7 +323,6 @@ EXTN(jsimd_idct_float_sse2): ; ---- Pass 2: process rows from work array, store into output array. - mov rax, [original_rbp] lea rsi, [workspace] ; FAST_FLOAT *wsptr mov rdi, r12 ; (JSAMPROW *) mov eax, r13d @@ -471,9 +471,9 @@ EXTN(jsimd_idct_float_sse2): jnz near .rowloop pop rbx - uncollect_args 4 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 4 + lea rsp, [rbp-8] + pop r15 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctfst-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctfst-sse2.asm index cb97fdfbb246..fd3bc32c1687 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctfst-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctfst-sse2.asm @@ -2,8 +2,9 @@ ; jidctfst.asm - fast integer IDCT (64-bit SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -57,7 +58,7 @@ F_1_613 equ (F_2_613 - (1 << CONST_BITS)) ; FIX(2.613125930) - FIX(1) %define PRE_MULTIPLY_SCALE_BITS 2 %define CONST_SHIFT (16 - PRE_MULTIPLY_SCALE_BITS - CONST_BITS) - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_ifast_sse2) EXTN(jconst_idct_ifast_sse2): @@ -68,7 +69,7 @@ PW_MF1613 times 8 dw -F_1_613 << CONST_SHIFT PW_F1082 times 8 dw F_1_082 << CONST_SHIFT PB_CENTERJSAMP times 16 db CENTERJSAMPLE - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -86,8 +87,7 @@ PB_CENTERJSAMP times 16 db CENTERJSAMPLE ; r12 = JSAMPARRAY output_buf ; r13d = JDIMENSION output_col -%define original_rbp rbp + 0 -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_XMMWORD +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] %define WK_NUM 2 @@ -95,14 +95,15 @@ PB_CENTERJSAMP times 16 db CENTERJSAMPLE GLOBAL_FUNCTION(jsimd_idct_ifast_sse2) EXTN(jsimd_idct_ifast_sse2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 4 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, byte (SIZEOF_XMMWORD * WK_NUM) + COLLECT_ARGS 4 ; ---- Pass 1: process columns from input. @@ -320,7 +321,6 @@ EXTN(jsimd_idct_ifast_sse2): ; ---- Pass 2: process rows from work array, store into output array. - mov rax, [original_rbp] mov rdi, r12 ; (JSAMPROW *) mov eax, r13d @@ -479,9 +479,9 @@ EXTN(jsimd_idct_ifast_sse2): movq XMM_MMWORD [rdx+rax*SIZEOF_JSAMPLE], xmm6 movq XMM_MMWORD [rsi+rax*SIZEOF_JSAMPLE], xmm2 - uncollect_args 4 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 4 + lea rsp, [rbp-8] + pop r15 pop rbp ret ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctint-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctint-avx2.asm index ca7e317f6e1b..84d125bd4353 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctint-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctint-avx2.asm @@ -2,7 +2,7 @@ ; jidctint.asm - accurate integer IDCT (64-bit AVX2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, 2018, 2020, D. R. Commander. +; Copyright (C) 2009, 2016, 2018, 2020, 2024, D. R. Commander. ; Copyright (C) 2018, Matthias Räncker. ; ; Based on the x86 SIMD extension for IJG JPEG library @@ -66,7 +66,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; %1-%4: Input/output registers ; %5-%8: Temp registers -%macro dotranspose 8 +%macro DOTRANSPOSE 8 ; %5=(00 10 20 30 40 50 60 70 01 11 21 31 41 51 61 71) ; %6=(03 13 23 33 43 53 63 73 02 12 22 32 42 52 62 72) ; %7=(04 14 24 34 44 54 64 74 05 15 25 35 45 55 65 75) @@ -119,7 +119,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; %5-%12: Temp registers ; %9: Pass (1 or 2) -%macro dodct 13 +%macro DODCT 13 ; -- Even part ; (Original) @@ -241,7 +241,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_islow_avx2) EXTN(jconst_idct_islow_avx2): @@ -260,7 +260,7 @@ PB_CENTERJSAMP times 32 db CENTERJSAMPLE PW_1_NEG1 times 8 dw 1 times 8 dw -1 - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -282,11 +282,11 @@ PW_1_NEG1 times 8 dw 1 GLOBAL_FUNCTION(jsimd_idct_islow_avx2) EXTN(jsimd_idct_islow_avx2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp mov rbp, rsp ; rbp = aligned rbp - push_xmm 4 - collect_args 4 + PUSH_XMM 4 + COLLECT_ARGS 4 ; ---- Pass 1: process columns. @@ -343,10 +343,10 @@ EXTN(jsimd_idct_islow_avx2): vperm2i128 ymm2, ymm5, ymm7, 0x20 ; ymm2=in2_6 vperm2i128 ymm3, ymm7, ymm6, 0x31 ; ymm3=in7_5 - dodct ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7, ymm8, ymm9, ymm10, ymm11, 1 + DODCT ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7, ymm8, ymm9, ymm10, ymm11, 1 ; ymm0=data0_1, ymm1=data3_2, ymm2=data4_5, ymm3=data7_6 - dotranspose ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7 + DOTRANSPOSE ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7 ; ymm0=data0_4, ymm1=data1_5, ymm2=data2_6, ymm3=data3_7 .column_end: @@ -363,10 +363,10 @@ EXTN(jsimd_idct_islow_avx2): vperm2i128 ymm4, ymm3, ymm1, 0x31 ; ymm3=in7_5 vperm2i128 ymm1, ymm3, ymm1, 0x20 ; ymm1=in3_1 - dodct ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7, ymm8, ymm9, ymm10, ymm11, 2 + DODCT ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7, ymm8, ymm9, ymm10, ymm11, 2 ; ymm0=data0_1, ymm1=data3_2, ymm2=data4_5, ymm4=data7_6 - dotranspose ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7 + DOTRANSPOSE ymm0, ymm1, ymm2, ymm4, ymm3, ymm5, ymm6, ymm7 ; ymm0=data0_4, ymm1=data1_5, ymm2=data2_6, ymm4=data3_7 vpacksswb ymm0, ymm0, ymm1 ; ymm0=data01_45 @@ -408,8 +408,8 @@ EXTN(jsimd_idct_islow_avx2): movq XMM_MMWORD [rdx+rax*SIZEOF_JSAMPLE], xmm6 movq XMM_MMWORD [rsi+rax*SIZEOF_JSAMPLE], xmm7 - uncollect_args 4 - pop_xmm 4 + UNCOLLECT_ARGS 4 + POP_XMM 4 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctint-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctint-sse2.asm index 7aa869bc0b51..3f098b2c50e8 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctint-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctint-sse2.asm @@ -2,8 +2,9 @@ ; jidctint.asm - accurate integer IDCT (64-bit SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, 2020, D. R. Commander. +; Copyright (C) 2009, 2016, 2020, 2024, D. R. Commander. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -64,7 +65,7 @@ F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS) ; FIX(3.072711026) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_islow_sse2) EXTN(jconst_idct_islow_sse2): @@ -81,7 +82,7 @@ PD_DESCALE_P1 times 4 dd 1 << (DESCALE_P1 - 1) PD_DESCALE_P2 times 4 dd 1 << (DESCALE_P2 - 1) PB_CENTERJSAMP times 16 db CENTERJSAMPLE - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -99,8 +100,7 @@ PB_CENTERJSAMP times 16 db CENTERJSAMPLE ; r12 = JSAMPARRAY output_buf ; r13d = JDIMENSION output_col -%define original_rbp rbp + 0 -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_XMMWORD +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] %define WK_NUM 12 @@ -108,14 +108,15 @@ PB_CENTERJSAMP times 16 db CENTERJSAMPLE GLOBAL_FUNCTION(jsimd_idct_islow_sse2) EXTN(jsimd_idct_islow_sse2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 4 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, (SIZEOF_XMMWORD * WK_NUM) + COLLECT_ARGS 4 ; ---- Pass 1: process columns from input. @@ -512,7 +513,6 @@ EXTN(jsimd_idct_islow_sse2): ; ---- Pass 2: process rows from work array, store into output array. - mov rax, [original_rbp] mov rdi, r12 ; (JSAMPROW *) mov eax, r13d @@ -836,9 +836,9 @@ EXTN(jsimd_idct_islow_sse2): movq XMM_MMWORD [rdx+rax*SIZEOF_JSAMPLE], xmm2 movq XMM_MMWORD [rsi+rax*SIZEOF_JSAMPLE], xmm5 - uncollect_args 4 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 4 + lea rsp, [rbp-8] + pop r15 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctred-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctred-sse2.asm index 4ece9d891cbd..2657cf3cb135 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctred-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jidctred-sse2.asm @@ -2,8 +2,9 @@ ; jidctred.asm - reduced-size IDCT (64-bit SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2018, Matthias Räncker. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on the x86 SIMD extension for IJG JPEG library ; Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -70,7 +71,7 @@ F_3_624 equ DESCALE(3891787747, 30 - CONST_BITS) ; FIX(3.624509785) ; -------------------------------------------------------------------------- SECTION SEG_CONST - alignz 32 + ALIGNZ 32 GLOBAL_DATA(jconst_idct_red_sse2) EXTN(jconst_idct_red_sse2): @@ -88,7 +89,7 @@ PD_DESCALE_P1_2 times 4 dd 1 << (DESCALE_P1_2 - 1) PD_DESCALE_P2_2 times 4 dd 1 << (DESCALE_P2_2 - 1) PB_CENTERJSAMP times 16 db CENTERJSAMPLE - alignz 32 + ALIGNZ 32 ; -------------------------------------------------------------------------- SECTION SEG_TEXT @@ -107,8 +108,7 @@ PB_CENTERJSAMP times 16 db CENTERJSAMPLE ; r12 = JSAMPARRAY output_buf ; r13d = JDIMENSION output_col -%define original_rbp rbp + 0 -%define wk(i) rbp - (WK_NUM - (i)) * SIZEOF_XMMWORD +%define wk(i) r15 - (WK_NUM - (i)) * SIZEOF_XMMWORD ; xmmword wk[WK_NUM] %define WK_NUM 2 @@ -116,14 +116,15 @@ PB_CENTERJSAMP times 16 db CENTERJSAMPLE GLOBAL_FUNCTION(jsimd_idct_4x4_sse2) EXTN(jsimd_idct_4x4_sse2): + ENDBR64 push rbp - mov rax, rsp ; rax = original rbp - sub rsp, byte 4 + mov rbp, rsp + push r15 and rsp, byte (-SIZEOF_XMMWORD) ; align to 128 bits - mov [rsp], rax - mov rbp, rsp ; rbp = aligned rbp - lea rsp, [wk(0)] - collect_args 4 + ; Allocate stack space for wk array. r15 is used to access it. + mov r15, rsp + sub rsp, byte (SIZEOF_XMMWORD * WK_NUM) + COLLECT_ARGS 4 ; ---- Pass 1: process columns from input. @@ -309,7 +310,6 @@ EXTN(jsimd_idct_4x4_sse2): ; ---- Pass 2: process rows, store into output array. - mov rax, [original_rbp] mov rdi, r12 ; (JSAMPROW *) mov eax, r13d @@ -389,9 +389,9 @@ EXTN(jsimd_idct_4x4_sse2): movd XMM_DWORD [rdx+rax*SIZEOF_JSAMPLE], xmm1 movd XMM_DWORD [rsi+rax*SIZEOF_JSAMPLE], xmm3 - uncollect_args 4 - mov rsp, rbp ; rsp <- aligned rbp - pop rsp ; rsp <- original rbp + UNCOLLECT_ARGS 4 + lea rsp, [rbp-8] + pop r15 pop rbp ret @@ -414,10 +414,10 @@ EXTN(jsimd_idct_4x4_sse2): GLOBAL_FUNCTION(jsimd_idct_2x2_sse2) EXTN(jsimd_idct_2x2_sse2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 4 + COLLECT_ARGS 4 push rbx ; ---- Pass 1: process columns from input. @@ -565,7 +565,7 @@ EXTN(jsimd_idct_2x2_sse2): mov word [rsi+rax*SIZEOF_JSAMPLE], cx pop rbx - uncollect_args 4 + UNCOLLECT_ARGS 4 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jquantf-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jquantf-sse2.asm index ab2e3954f633..8bd79662e605 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jquantf-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jquantf-sse2.asm @@ -2,7 +2,7 @@ ; jquantf.asm - sample data conversion and quantization (64-bit SSE & SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2018, Matthias Räncker. ; ; Based on the x86 SIMD extension for IJG JPEG library @@ -37,10 +37,10 @@ GLOBAL_FUNCTION(jsimd_convsamp_float_sse2) EXTN(jsimd_convsamp_float_sse2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 3 + COLLECT_ARGS 3 push rbx pcmpeqw xmm7, xmm7 @@ -89,7 +89,7 @@ EXTN(jsimd_convsamp_float_sse2): jnz short .convloop pop rbx - uncollect_args 3 + UNCOLLECT_ARGS 3 pop rbp ret @@ -110,10 +110,10 @@ EXTN(jsimd_convsamp_float_sse2): GLOBAL_FUNCTION(jsimd_quantize_float_sse2) EXTN(jsimd_quantize_float_sse2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 3 + COLLECT_ARGS 3 mov rsi, r12 mov rdx, r11 @@ -146,7 +146,7 @@ EXTN(jsimd_quantize_float_sse2): dec rax jnz short .quantloop - uncollect_args 3 + UNCOLLECT_ARGS 3 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jquanti-avx2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jquanti-avx2.asm index 70fe81139cc2..c8ebd7966b69 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jquanti-avx2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jquanti-avx2.asm @@ -2,7 +2,7 @@ ; jquanti.asm - sample data conversion and quantization (64-bit AVX2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, 2018, D. R. Commander. +; Copyright (C) 2009, 2016, 2018, 2024, D. R. Commander. ; Copyright (C) 2016, Matthieu Darbois. ; Copyright (C) 2018, Matthias Räncker. ; @@ -38,10 +38,10 @@ GLOBAL_FUNCTION(jsimd_convsamp_avx2) EXTN(jsimd_convsamp_avx2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 3 + COLLECT_ARGS 3 mov eax, r11d @@ -84,7 +84,7 @@ EXTN(jsimd_convsamp_avx2): vmovdqu YMMWORD [YMMBLOCK(6,0,r12,SIZEOF_DCTELEM)], ymm3 vzeroupper - uncollect_args 3 + UNCOLLECT_ARGS 3 pop rbp ret @@ -116,10 +116,10 @@ EXTN(jsimd_convsamp_avx2): GLOBAL_FUNCTION(jsimd_quantize_avx2) EXTN(jsimd_quantize_avx2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 3 + COLLECT_ARGS 3 vmovdqu ymm4, [YMMBLOCK(0,0,r12,SIZEOF_DCTELEM)] vmovdqu ymm5, [YMMBLOCK(2,0,r12,SIZEOF_DCTELEM)] @@ -154,7 +154,7 @@ EXTN(jsimd_quantize_avx2): vmovdqu [YMMBLOCK(6,0,r10,SIZEOF_DCTELEM)], ymm3 vzeroupper - uncollect_args 3 + UNCOLLECT_ARGS 3 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jquanti-sse2.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jquanti-sse2.asm index 3ee442027a5a..352d74055c62 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jquanti-sse2.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jquanti-sse2.asm @@ -2,7 +2,7 @@ ; jquanti.asm - sample data conversion and quantization (64-bit SSE2) ; ; Copyright 2009 Pierre Ossman for Cendio AB -; Copyright (C) 2009, 2016, D. R. Commander. +; Copyright (C) 2009, 2016, 2024, D. R. Commander. ; Copyright (C) 2018, Matthias Räncker. ; ; Based on the x86 SIMD extension for IJG JPEG library @@ -37,10 +37,10 @@ GLOBAL_FUNCTION(jsimd_convsamp_sse2) EXTN(jsimd_convsamp_sse2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 3 + COLLECT_ARGS 3 push rbx pxor xmm6, xmm6 ; xmm6=(all 0's) @@ -84,7 +84,7 @@ EXTN(jsimd_convsamp_sse2): jnz short .convloop pop rbx - uncollect_args 3 + UNCOLLECT_ARGS 3 pop rbp ret @@ -116,10 +116,10 @@ EXTN(jsimd_convsamp_sse2): GLOBAL_FUNCTION(jsimd_quantize_sse2) EXTN(jsimd_quantize_sse2): + ENDBR64 push rbp - mov rax, rsp mov rbp, rsp - collect_args 3 + COLLECT_ARGS 3 mov rsi, r12 mov rdx, r11 @@ -179,7 +179,7 @@ EXTN(jsimd_quantize_sse2): dec rax jnz near .quantloop - uncollect_args 3 + UNCOLLECT_ARGS 3 pop rbp ret diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jsimd.c b/3rdparty/libjpeg-turbo/src/simd/x86_64/jsimd.c index 584a010ad348..3f5ee77eb99b 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jsimd.c +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jsimd.c @@ -2,8 +2,8 @@ * jsimd_x86_64.c * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009-2011, 2014, 2016, 2018, 2022, D. R. Commander. - * Copyright (C) 2015-2016, 2018, Matthieu Darbois. + * Copyright (C) 2009-2011, 2014, 2016, 2018, 2022-2023, D. R. Commander. + * Copyright (C) 2015-2016, 2018, 2022, Matthieu Darbois. * * Based on the x86 SIMD extension for IJG JPEG library, * Copyright (C) 1999-2006, MIYASAKA Masaru. @@ -21,7 +21,6 @@ #include "../../jdct.h" #include "../../jsimddct.h" #include "../jsimd.h" -#include "jconfigint.h" /* * In the PIC cases, we have no guarantee that constants will keep @@ -32,13 +31,11 @@ #define IS_ALIGNED_SSE(ptr) (IS_ALIGNED(ptr, 4)) /* 16 byte alignment */ #define IS_ALIGNED_AVX(ptr) (IS_ALIGNED(ptr, 5)) /* 32 byte alignment */ -static unsigned int simd_support = (unsigned int)(~0); -static unsigned int simd_huffman = 1; +static THREAD_LOCAL unsigned int simd_support = (unsigned int)(~0); +static THREAD_LOCAL unsigned int simd_huffman = 1; /* * Check what SIMD accelerations are supported. - * - * FIXME: This code is racy under a multi-threaded environment. */ LOCAL(void) init_simd(void) @@ -148,6 +145,9 @@ jsimd_rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, void (*avx2fct) (JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int); void (*sse2fct) (JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int); + if (simd_support == ~0U) + init_simd(); + switch (cinfo->in_color_space) { case JCS_EXT_RGB: avx2fct = jsimd_extrgb_ycc_convert_avx2; @@ -197,6 +197,9 @@ jsimd_rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, void (*avx2fct) (JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int); void (*sse2fct) (JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int); + if (simd_support == ~0U) + init_simd(); + switch (cinfo->in_color_space) { case JCS_EXT_RGB: avx2fct = jsimd_extrgb_gray_convert_avx2; @@ -246,6 +249,9 @@ jsimd_ycc_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, void (*avx2fct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY, int); void (*sse2fct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY, int); + if (simd_support == ~0U) + init_simd(); + switch (cinfo->out_color_space) { case JCS_EXT_RGB: avx2fct = jsimd_ycc_extrgb_convert_avx2; @@ -336,6 +342,9 @@ GLOBAL(void) jsimd_h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_h2v2_downsample_avx2(cinfo->image_width, cinfo->max_v_samp_factor, compptr->v_samp_factor, @@ -352,6 +361,9 @@ GLOBAL(void) jsimd_h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_h2v1_downsample_avx2(cinfo->image_width, cinfo->max_v_samp_factor, compptr->v_samp_factor, @@ -406,6 +418,9 @@ GLOBAL(void) jsimd_h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_h2v2_upsample_avx2(cinfo->max_v_samp_factor, cinfo->output_width, input_data, output_data_ptr); @@ -418,6 +433,9 @@ GLOBAL(void) jsimd_h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_h2v1_upsample_avx2(cinfo->max_v_samp_factor, cinfo->output_width, input_data, output_data_ptr); @@ -472,6 +490,9 @@ GLOBAL(void) jsimd_h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_h2v2_fancy_upsample_avx2(cinfo->max_v_samp_factor, compptr->downsampled_width, input_data, @@ -486,6 +507,9 @@ GLOBAL(void) jsimd_h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_h2v1_fancy_upsample_avx2(cinfo->max_v_samp_factor, compptr->downsampled_width, input_data, @@ -545,6 +569,9 @@ jsimd_h2v2_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, void (*avx2fct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY); void (*sse2fct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY); + if (simd_support == ~0U) + init_simd(); + switch (cinfo->out_color_space) { case JCS_EXT_RGB: avx2fct = jsimd_h2v2_extrgb_merged_upsample_avx2; @@ -593,6 +620,9 @@ jsimd_h2v1_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, void (*avx2fct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY); void (*sse2fct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY); + if (simd_support == ~0U) + init_simd(); + switch (cinfo->out_color_space) { case JCS_EXT_RGB: avx2fct = jsimd_h2v1_extrgb_merged_upsample_avx2; @@ -682,6 +712,9 @@ GLOBAL(void) jsimd_convsamp(JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_convsamp_avx2(sample_data, start_col, workspace); else @@ -751,6 +784,9 @@ jsimd_can_fdct_float(void) GLOBAL(void) jsimd_fdct_islow(DCTELEM *data) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_fdct_islow_avx2(data); else @@ -812,6 +848,9 @@ jsimd_can_quantize_float(void) GLOBAL(void) jsimd_quantize(JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_quantize_avx2(coef_block, divisors, workspace); else @@ -966,6 +1005,9 @@ jsimd_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { + if (simd_support == ~0U) + init_simd(); + if (simd_support & JSIMD_AVX2) jsimd_idct_islow_avx2(compptr->dct_table, coef_block, output_buf, output_col); @@ -1036,7 +1078,7 @@ jsimd_can_encode_mcu_AC_first_prepare(void) GLOBAL(void) jsimd_encode_mcu_AC_first_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *values, size_t *zerobits) + int Al, UJCOEF *values, size_t *zerobits) { jsimd_encode_mcu_AC_first_prepare_sse2(block, jpeg_natural_order_start, Sl, Al, values, zerobits); @@ -1060,7 +1102,7 @@ jsimd_can_encode_mcu_AC_refine_prepare(void) GLOBAL(int) jsimd_encode_mcu_AC_refine_prepare(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, - int Al, JCOEF *absvalues, size_t *bits) + int Al, UJCOEF *absvalues, size_t *bits) { return jsimd_encode_mcu_AC_refine_prepare_sse2(block, jpeg_natural_order_start, diff --git a/3rdparty/libjpeg-turbo/src/simd/x86_64/jsimdcpu.asm b/3rdparty/libjpeg-turbo/src/simd/x86_64/jsimdcpu.asm index 705f813d7da6..251bc4cdae29 100644 --- a/3rdparty/libjpeg-turbo/src/simd/x86_64/jsimdcpu.asm +++ b/3rdparty/libjpeg-turbo/src/simd/x86_64/jsimdcpu.asm @@ -3,6 +3,7 @@ ; ; Copyright 2009 Pierre Ossman for Cendio AB ; Copyright (C) 2016, D. R. Commander. +; Copyright (C) 2023, Aliaksiej Kandracienka. ; ; Based on ; x86 SIMD extension for IJG JPEG library @@ -31,6 +32,8 @@ GLOBAL_FUNCTION(jpeg_simd_cpu_support) EXTN(jpeg_simd_cpu_support): + push rbp + mov rbp, rsp push rbx push rdi @@ -79,6 +82,7 @@ EXTN(jpeg_simd_cpu_support): pop rdi pop rbx + pop rbp ret ; For some reason, the OS X linker does not honor the request to align the diff --git a/3rdparty/libjpeg-turbo/src/structure.txt b/3rdparty/libjpeg-turbo/src/structure.txt new file mode 100644 index 000000000000..030b8e8801bd --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/structure.txt @@ -0,0 +1,981 @@ +IJG JPEG LIBRARY: SYSTEM ARCHITECTURE + +This file was part of the Independent JPEG Group's software: +Copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding. +Lossless JPEG Modifications: +Copyright (C) 1999, Ken Murchison. +libjpeg-turbo Modifications: +Copyright (C) 2022-2023, D. R. Commander. +For conditions of distribution and use, see the accompanying README.ijg file. + + +This file provides an overview of the architecture of the IJG JPEG software; +that is, the functions of the various modules in the system and the interfaces +between modules. For more precise details about any data structure or calling +convention, see the include files and comments in the source code. + +We assume that the reader is already somewhat familiar with the JPEG standard. +The README.ijg file includes references for learning about JPEG. The file +libjpeg.txt describes the library from the viewpoint of an application +programmer using the library; it's best to read that file before this one. +Also, the file coderules.txt describes the coding style conventions we use. + +In this document, JPEG-specific terminology follows the JPEG standard: + A "component" means a color channel, e.g., Red or Luminance. + A "sample" is a single component value (i.e., one number in the image data). + A "coefficient" is a frequency coefficient (a DCT transform output number). + A "block" is an 8x8 group of samples or coefficients. + A "data unit" is an abstract data type that is either a block for lossy + (DCT-based) codecs or a sample for lossless (predictive) codecs. + An "MCU" (minimum coded unit) is an interleaved set of data units of size + determined by the sampling factors, or a single data unit in a + noninterleaved scan. +We do not use the terms "pixel" and "sample" interchangeably. When we say +pixel, we mean an element of the full-size image, while a sample is an element +of the downsampled image. Thus the number of samples may vary across +components while the number of pixels does not. (This terminology is not used +rigorously throughout the code, but it is used in places where confusion would +otherwise result.) + + +*** System features *** + +The IJG distribution contains two parts: + * A subroutine library for JPEG compression and decompression. + * cjpeg/djpeg, two sample applications that use the library to transform + JFIF JPEG files to and from several other image formats. +cjpeg/djpeg are of no great intellectual complexity: they merely add a simple +command-line user interface and I/O routines for several uncompressed image +formats. This document concentrates on the library itself. + +We desire the library to be capable of supporting all JPEG baseline, extended +sequential, progressive DCT, and lossless (spatial) processes. Hierarchical +processes are not supported. + +Within these limits, any set of compression parameters allowed by the JPEG +spec should be readable for decompression. (We can be more restrictive about +what formats we can generate.) Although the system design allows for all +parameter values, some uncommon settings are not yet implemented and may +never be; nonintegral sampling ratios are the prime example. + +By itself, the library handles only interchange JPEG datastreams --- in +particular the widely used JFIF file format. The library can be used by +surrounding code to process interchange or abbreviated JPEG datastreams that +are embedded in more complex file formats. (For example, libtiff uses this +library to implement JPEG compression within the TIFF file format.) + +The library includes a substantial amount of code that is not covered by the +JPEG standard but is necessary for typical applications of JPEG. These +functions preprocess the image before JPEG compression or postprocess it after +decompression. They include colorspace conversion, downsampling/upsampling, +and color quantization. This code can be omitted if not needed. + +A wide range of quality vs. speed tradeoffs are possible in JPEG processing, +and even more so in decompression postprocessing. The decompression library +provides multiple implementations that cover most of the useful tradeoffs, +ranging from very-high-quality down to fast-preview operation. On the +compression side we have generally not provided low-quality choices, since +compression is normally less time-critical. It should be understood that the +low-quality modes may not meet the JPEG standard's accuracy requirements; +nonetheless, they are useful for viewers. + + +*** System overview *** + +The compressor and decompressor are each divided into two main sections: +the JPEG compressor or decompressor proper, and the preprocessing or +postprocessing functions. The interface between these two sections is the +image data that Rec. ITU-T T.81 | ISO/IEC 10918-1 regards as its input or +output: this data is in the colorspace to be used for compression, and it is +downsampled to the sampling factors to be used. The preprocessing and +postprocessing steps are responsible for converting a normal image +representation to or from this form. (Those few applications that want to deal +with YCbCr downsampled data can skip the preprocessing or postprocessing step.) + +Looking more closely, the compressor library contains the following main +elements: + + Preprocessing: + * Color space conversion (e.g., RGB to YCbCr). + * Edge expansion and downsampling. Optionally, this step can do simple + smoothing --- this is often helpful for low-quality source data. + Lossy JPEG proper: + * MCU assembly, DCT, quantization. + * Entropy coding (sequential or progressive, Huffman or arithmetic). + Lossless JPEG proper: + * Point transform. + * Prediction, differencing. + * Entropy coding (Huffman or arithmetic) + +In addition to these modules we need overall control, marker generation, +and support code (memory management & error handling). There is also a +module responsible for physically writing the output data --- typically +this is just an interface to fwrite(), but some applications may need to +do something else with the data. + +The decompressor library contains the following main elements: + + Lossy JPEG proper: + * Entropy decoding (sequential or progressive, Huffman or arithmetic). + * Dequantization, inverse DCT, MCU disassembly. + Lossless JPEG proper: + * Entropy decoding (Huffman or arithmetic). + * Prediction, undifferencing. + * Point transform, sample size scaling. + Postprocessing: + * Upsampling. Optionally, this step may be able to do more general + rescaling of the image. + * Color space conversion (e.g., YCbCr to RGB). This step may also + provide gamma adjustment [ currently it does not ]. + * Optional color quantization (e.g., reduction to 256 colors). + * Optional color precision reduction (e.g., 24-bit to 15-bit color). + [This feature is not currently implemented.] + +We also need overall control, marker parsing, and a data source module. +The support code (memory management & error handling) can be shared with +the compression half of the library. + +There may be several implementations of each of these elements, particularly +in the decompressor, where a wide range of speed/quality tradeoffs is very +useful. It must be understood that some of the best speedups involve +merging adjacent steps in the pipeline. For example, upsampling, color space +conversion, and color quantization might all be done at once when using a +low-quality ordered-dither technique. The system architecture is designed to +allow such merging where appropriate. + + +Note: it is convenient to regard edge expansion (padding to block boundaries) +as a preprocessing/postprocessing function, even though +Rec. ITU-T T.81 | ISO/IEC 10918-1 includes it in compression/decompression. We +do this because downsampling/upsampling can be simplified a little if they work +on padded data: it's not necessary to have special cases at the right and +bottom edges. Therefore the interface buffer is always an integral number of +blocks wide and high, and we expect compression preprocessing to pad the source +data properly. Padding will occur only to the next block (8-sample) boundary. +In an interleaved-scan situation, additional dummy blocks may be used to fill +out MCUs, but the MCU assembly and disassembly logic will create or discard +these blocks internally. (This is advantageous for speed reasons, since we +avoid DCTing the dummy blocks. It also permits a small reduction in file size, +because the compressor can choose dummy block contents so as to minimize their +size in compressed form. Finally, it makes the interface buffer specification +independent of whether the file is actually interleaved or not.) Applications +that wish to deal directly with the downsampled data must provide similar +buffering and padding for odd-sized images. + + +*** Poor man's object-oriented programming *** + +It should be clear by now that we have a lot of quasi-independent processing +steps, many of which have several possible behaviors. To avoid cluttering the +code with lots of switch statements, we use a simple form of object-style +programming to separate out the different possibilities. + +For example, two different color quantization algorithms could be implemented +as two separate modules that present the same external interface; at runtime, +the calling code will access the proper module indirectly through an "object". + +We can get the limited features we need while staying within portable C. +The basic tool is a function pointer. An "object" is just a struct +containing one or more function pointer fields, each of which corresponds to +a method name in real object-oriented languages. During initialization we +fill in the function pointers with references to whichever module we have +determined we need to use in this run. Then invocation of the module is done +by indirecting through a function pointer; on most machines this is no more +expensive than a switch statement, which would be the only other way of +making the required run-time choice. The really significant benefit, of +course, is keeping the source code clean and well structured. + +We can also arrange to have private storage that varies between different +implementations of the same kind of object. We do this by making all the +module-specific object structs be separately allocated entities, which will +be accessed via pointers in the master compression or decompression struct. +The "public" fields or methods for a given kind of object are specified by +a commonly known struct. But a module's initialization code can allocate +a larger struct that contains the common struct as its first member, plus +additional private fields. With appropriate pointer casting, the module's +internal functions can access these private fields. (For a simple example, +see jdatadst.c, which implements the external interface specified by struct +jpeg_destination_mgr, but adds extra fields.) + +(Of course this would all be a lot easier if we were using C++, but we are +not yet prepared to assume that everyone has a C++ compiler.) + +An important benefit of this scheme is that it is easy to provide multiple +versions of any method, each tuned to a particular case. While a lot of +precalculation might be done to select an optimal implementation of a method, +the cost per invocation is constant. For example, the upsampling step might +have a "generic" method, plus one or more "hardwired" methods for the most +popular sampling factors; the hardwired methods would be faster because they'd +use straight-line code instead of for-loops. The cost to determine which +method to use is paid only once, at startup, and the selection criteria are +hidden from the callers of the method. + +This plan differs a little bit from usual object-oriented structures, in that +only one instance of each object class will exist during execution. The +reason for having the class structure is that on different runs we may create +different instances (choose to execute different modules). You can think of +the term "method" as denoting the common interface presented by a particular +set of interchangeable functions, and "object" as denoting a group of related +methods, or the total shared interface behavior of a group of modules. + + +*** Overall control structure *** + +We previously mentioned the need for overall control logic in the compression +and decompression libraries. In IJG implementations prior to v5, overall +control was mostly provided by "pipeline control" modules, which proved to be +large, unwieldy, and hard to understand. To improve the situation, the +control logic has been subdivided into multiple modules. The control modules +consist of: + +1. Master control for module selection and initialization. This has two +responsibilities: + + 1A. Startup initialization at the beginning of image processing. + The individual processing modules to be used in this run are selected + and given initialization calls. + + 1B. Per-pass control. This determines how many passes will be performed + and calls each active processing module to configure itself + appropriately at the beginning of each pass. End-of-pass processing, + where necessary, is also invoked from the master control module. + + Method selection is partially distributed, in that a particular processing + module may contain several possible implementations of a particular method, + which it will select among when given its initialization call. The master + control code need only be concerned with decisions that affect more than + one module. + +2. Data buffering control. A separate control module exists for each + inter-processing-step data buffer. This module is responsible for + invoking the processing steps that write or read that data buffer. + +Each buffer controller sees the world as follows: + +input data => processing step A => buffer => processing step B => output data + | | | + ------------------ controller ------------------ + +The controller knows the dataflow requirements of steps A and B: how much data +they want to accept in one chunk and how much they output in one chunk. Its +function is to manage its buffer and call A and B at the proper times. + +A data buffer control module may itself be viewed as a processing step by a +higher-level control module; thus the control modules form a binary tree with +elementary processing steps at the leaves of the tree. + +The control modules are objects. A considerable amount of flexibility can +be had by replacing implementations of a control module. For example: +* Merging of adjacent steps in the pipeline is done by replacing a control + module and its pair of processing-step modules with a single processing- + step module. (Hence the possible merges are determined by the tree of + control modules.) +* In some processing modes, a given interstep buffer need only be a "strip" + buffer large enough to accommodate the desired data chunk sizes. In other + modes, a full-image buffer is needed and several passes are required. + The control module determines which kind of buffer is used and manipulates + virtual array buffers as needed. One or both processing steps may be + unaware of the multi-pass behavior. + +In theory, we might be able to make all of the data buffer controllers +interchangeable and provide just one set of implementations for all. In +practice, each one contains considerable special-case processing for its +particular job. The buffer controller concept should be regarded as an +overall system structuring principle, not as a complete description of the +task performed by any one controller. + + +*** Compression object structure *** + +Here is a sketch of the logical structure of the JPEG compression library in +lossy mode: + + |-- Colorspace conversion + |-- Preprocessing controller --| + | |-- Downsampling +Main controller --| + | |-- Forward DCT, quantize + |-- Coefficient controller --| + |-- Entropy encoding + +... and in lossless mode: + + |-- Colorspace conversion + |-- Preprocessing controller --| + | |-- Downsampling +Main controller --| + | |-- Point transform + | | + |-- Difference controller --|-- Prediction, differencing + | + |-- Lossless mode entropy + encoding + +This sketch also describes the flow of control (subroutine calls) during +typical image data processing. Each of the components shown in the diagram is +an "object" which may have several different implementations available. One +or more source code files contain the actual implementation(s) of each object. + +The objects shown above are: + +* Main controller: buffer controller for the subsampled-data buffer, which + holds the preprocessed input data. This controller invokes preprocessing to + fill the subsampled-data buffer, and JPEG compression to empty it. There is + usually no need for a full-image buffer here; a strip buffer is adequate. + +* Preprocessing controller: buffer controller for the downsampling input data + buffer, which lies between colorspace conversion and downsampling. Note + that a unified conversion/downsampling module would probably replace this + controller entirely. + +* Colorspace conversion: converts application image data into the desired + JPEG color space; also changes the data from pixel-interleaved layout to + separate component planes. Processes one pixel row at a time. + +* Downsampling: performs reduction of chroma components as required. + Optionally may perform pixel-level smoothing as well. Processes a "row + group" at a time, where a row group is defined as Vmax pixel rows of each + component before downsampling, and Vk sample rows afterwards (remember Vk + differs across components). Some downsampling or smoothing algorithms may + require context rows above and below the current row group; the + preprocessing controller is responsible for supplying these rows via proper + buffering. The downsampler is responsible for edge expansion at the right + edge (i.e., extending each sample row to a multiple of 8 samples); but the + preprocessing controller is responsible for vertical edge expansion (i.e., + duplicating the bottom sample row as needed to make a multiple of 8 rows). + +* Coefficient controller: buffer controller for the DCT-coefficient data. + This controller handles MCU assembly, including insertion of dummy DCT + blocks when needed at the right or bottom edge. When performing + Huffman-code optimization or emitting a multiscan JPEG file, this + controller is responsible for buffering the full image. The equivalent of + one fully interleaved MCU row of subsampled data is processed per call, + even when the JPEG file is noninterleaved. + +* Forward DCT and quantization: Perform DCT, quantize, and emit coefficients. + Works on one or more DCT blocks at a time. (Note: the coefficients are now + emitted in normal array order, which the entropy encoder is expected to + convert to zigzag order as necessary. Prior versions of the IJG code did + the conversion to zigzag order within the quantization step.) + +* Entropy encoding: Perform Huffman or arithmetic entropy coding and emit the + coded data to the data destination module. Works on one MCU per call. + For progressive JPEG, the same DCT blocks are fed to the entropy coder + during each pass, and the coder must emit the appropriate subset of + coefficients. + +* Difference controller: buffer controller for the spatial difference data. + When emitting a multiscan JPEG file, this controller is responsible for + buffering the full image. The equivalent of one fully interleaved MCU row + of subsampled data is processed per call, even when the JPEG file is + noninterleaved. + +* Point transform: Downscale the data by the point transform value. + +* Prediction and differencing: Calculate the predictor and subtract it + from the input. Works on one scanline per call. The difference + controller supplies the prior scanline, which is used for prediction. + +* Lossless mode entropy encoding: Perform Huffman or arithmetic entropy coding + and emit the coded data to the data destination module. This module handles + MCU assembly. Works on one MCU row per call. + +In addition to the above objects, the compression library includes these +objects: + +* Master control: determines the number of passes required, controls overall + and per-pass initialization of the other modules. + +* Marker writing: generates JPEG markers (except for RSTn, which is emitted + by the entropy encoder when needed). + +* Data destination manager: writes the output JPEG datastream to its final + destination (e.g., a file). The destination manager supplied with the + library knows how to write to a stdio stream or to a memory buffer; + for other behaviors, the surrounding application may provide its own + destination manager. + +* Memory manager: allocates and releases memory, controls virtual arrays + (with backing store management, where required). + +* Error handler: performs formatting and output of error and trace messages; + determines handling of nonfatal errors. The surrounding application may + override some or all of this object's methods to change error handling. + +* Progress monitor: supports output of "percent-done" progress reports. + This object represents an optional callback to the surrounding application: + if wanted, it must be supplied by the application. + +The error handler, destination manager, and progress monitor objects are +defined as separate objects in order to simplify application-specific +customization of the JPEG library. A surrounding application may override +individual methods or supply its own all-new implementation of one of these +objects. The object interfaces for these objects are therefore treated as +part of the application interface of the library, whereas the other objects +are internal to the library. + +The error handler and memory manager are shared by JPEG compression and +decompression; the progress monitor, if used, may be shared as well. + + +*** Decompression object structure *** + +Here is a sketch of the logical structure of the JPEG decompression library in +lossy mode: + + |-- Entropy decoding + |-- Coefficient controller --| + | |-- Dequantize, Inverse DCT +Main controller --| + | |-- Upsampling + |-- Postprocessing controller --| |-- Colorspace conversion + |-- Color quantization + |-- Color precision reduction + +... and in lossless mode: + + |-- Lossless mode entropy + | decoding + | + |-- Difference controller --|-- Prediction, undifferencing + | | + | |-- Point transform, sample size + | scaling +Main controller --| + | |-- Upsampling + |-- Postprocessing controller --| + |-- Color precision reduction + +As before, this diagram also represents typical control flow. The objects +shown are: + +* Main controller: buffer controller for the subsampled-data buffer, which + holds the output of JPEG decompression proper. This controller's primary + task is to feed the postprocessing procedure. Some upsampling algorithms + may require context rows above and below the current row group; when this + is true, the main controller is responsible for managing its buffer so as + to make context rows available. In the current design, the main buffer is + always a strip buffer; a full-image buffer is never required. + +* Coefficient controller: buffer controller for the DCT-coefficient data. + This controller handles MCU disassembly, including deletion of any dummy + DCT blocks at the right or bottom edge. When reading a multiscan JPEG + file, this controller is responsible for buffering the full image. + (Buffering DCT coefficients, rather than samples, is necessary to support + progressive JPEG.) The equivalent of one fully interleaved MCU row of + subsampled data is processed per call, even when the source JPEG file is + noninterleaved. + +* Entropy decoding: Read coded data from the data source module and perform + Huffman or arithmetic entropy decoding. Works on one MCU per call. + For progressive JPEG decoding, the coefficient controller supplies the prior + coefficients of each MCU (initially all zeroes), which the entropy decoder + modifies in each scan. + +* Dequantization and inverse DCT: like it says. Note that the coefficients + buffered by the coefficient controller have NOT been dequantized; we + merge dequantization and inverse DCT into a single step for speed reasons. + When scaled-down output is asked for, simplified DCT algorithms may be used + that emit fewer samples per DCT block, not the full 8x8. Works on one DCT + block at a time. + +* Difference controller: buffer controller for the spatial difference data. + When reading a multiscan JPEG file, this controller is responsible for + buffering the full image. The equivalent of one fully interleaved MCU row + is processed per call, even when the source JPEG file is noninterleaved. + +* Lossless mode entropy decoding: Read coded data from the data source module + and perform Huffman or arithmetic entropy decoding. Works on one MCU row per + call. + +* Prediction and undifferencing: Calculate the predictor and add it to the + decoded difference. Works on one scanline per call. The difference + controller supplies the prior scanline, which is used for prediction. + +* Point transform and sample size scaling: Upscale the data by the point + transform value and downscale it to fit into the compiled-in sample size. + +* Postprocessing controller: buffer controller for the color quantization + input buffer, when quantization is in use. (Without quantization, this + controller just calls the upsampler.) For two-pass quantization, this + controller is responsible for buffering the full-image data. + +* Upsampling: restores chroma components to full size. (May support more + general output rescaling, too. Note that if undersized DCT outputs have + been emitted by the DCT module, this module must adjust so that properly + sized outputs are created.) Works on one row group at a time. This module + also calls the color conversion module, so its top level is effectively a + buffer controller for the upsampling->color conversion buffer. However, in + all but the highest-quality operating modes, upsampling and color + conversion are likely to be merged into a single step. + +* Colorspace conversion: convert from JPEG color space to output color space, + and change data layout from separate component planes to pixel-interleaved. + Works on one pixel row at a time. + +* Color quantization: reduce the data to colormapped form, using either an + externally specified colormap or an internally generated one. This module + is not used for full-color output. Works on one pixel row at a time; may + require two passes to generate a color map. Note that the output will + always be a single component representing colormap indexes. In the current + design, the output values are JSAMPLEs, J12SAMPLEs, or J16SAMPLEs, so the + library cannot quantize to more than 256 colors when using 8-bit data + precision. This is unlikely to be a problem in practice. + +* Color reduction: this module handles color precision reduction, e.g., + generating 15-bit color (5 bits/primary) from JPEG's 24-bit output. + Not quite clear yet how this should be handled... should we merge it with + colorspace conversion??? + +Note that some high-speed operating modes might condense the entire +postprocessing sequence to a single module (upsample, color convert, and +quantize in one step). + +In addition to the above objects, the decompression library includes these +objects: + +* Master control: determines the number of passes required, controls overall + and per-pass initialization of the other modules. This is subdivided into + input and output control: jdinput.c controls only input-side processing, + while jdmaster.c handles overall initialization and output-side control. + +* Marker reading: decodes JPEG markers (except for RSTn). + +* Data source manager: supplies the input JPEG datastream. The source + manager supplied with the library knows how to read from a stdio stream + or from a memory buffer; for other behaviors, the surrounding application + may provide its own source manager. + +* Memory manager: same as for compression library. + +* Error handler: same as for compression library. + +* Progress monitor: same as for compression library. + +As with compression, the data source manager, error handler, and progress +monitor are candidates for replacement by a surrounding application. + + +*** Decompression input and output separation *** + +To support efficient incremental display of progressive JPEG files, the +decompressor is divided into two sections that can run independently: + +1. Data input includes marker parsing, entropy decoding, and input into the + coefficient controller's DCT coefficient buffer. Note that this + processing is relatively cheap and fast. + +2. Data output reads from the DCT coefficient buffer and performs the IDCT + and all postprocessing steps. + +For a progressive JPEG file, the data input processing is allowed to get +arbitrarily far ahead of the data output processing. (This occurs only +if the application calls jpeg_consume_input(); otherwise input and output +run in lockstep, since the input section is called only when the output +section needs more data.) In this way the application can avoid making +extra display passes when data is arriving faster than the display pass +can run. Furthermore, it is possible to abort an output pass without +losing anything, since the coefficient buffer is read-only as far as the +output section is concerned. See libjpeg.txt for more detail. + +A full-image coefficient array is only created if the JPEG file has multiple +scans (or if the application specifies buffered-image mode anyway). When +reading a single-scan file, the coefficient controller normally creates only +a one-MCU buffer, so input and output processing must run in lockstep in this +case. jpeg_consume_input() is effectively a no-op in this situation. + +The main impact of dividing the decompressor in this fashion is that we must +be very careful with shared variables in the cinfo data structure. Each +variable that can change during the course of decompression must be +classified as belonging to data input or data output, and each section must +look only at its own variables. For example, the data output section may not +depend on any of the variables that describe the current scan in the JPEG +file, because these may change as the data input section advances into a new +scan. + +The progress monitor is (somewhat arbitrarily) defined to treat input of the +file as one pass when buffered-image mode is not used, and to ignore data +input work completely when buffered-image mode is used. Note that the +library has no reliable way to predict the number of passes when dealing +with a progressive JPEG file, nor can it predict the number of output passes +in buffered-image mode. So the work estimate is inherently bogus anyway. + +No comparable division is currently made in the compression library, because +there isn't any real need for it. + + +*** Data formats *** + +Arrays of 8-bit pixel sample values use the following data structure: + + typedef something JSAMPLE; a pixel component value, 0..MAXJSAMPLE + typedef JSAMPLE *JSAMPROW; ptr to a row of samples + typedef JSAMPROW *JSAMPARRAY; ptr to a list of rows + typedef JSAMPARRAY *JSAMPIMAGE; ptr to a list of color-component arrays + +Arrays of 12-bit pixel sample values use the following data structure: + + typedef something J12SAMPLE; a pixel component value, 0..MAXJ12SAMPLE + typedef J12SAMPLE *J12SAMPROW; ptr to a row of samples + typedef J12SAMPROW *J12SAMPARRAY; ptr to a list of rows + typedef J12SAMPARRAY *J12SAMPIMAGE; ptr to a list of color-component arrays + +Arrays of 16-bit pixel sample values use the following data structure: + + typedef something J16SAMPLE; a pixel component value, 0..MAXJ16SAMPLE + typedef J16SAMPLE *J16SAMPROW; ptr to a row of samples + typedef J16SAMPROW *J16SAMPARRAY; ptr to a list of rows + typedef J16SAMPARRAY *J16SAMPIMAGE; ptr to a list of color-component arrays + +The basic element type JSAMPLE (8-bit sample) will be unsigned char, the basic +element type J12SAMPLE (12-bit sample) will be short, and the basic element +type J16SAMPLE (16-bit sample) will be unsigned short. + +With these conventions, J*SAMPLE values can be assumed to be >= 0. This helps +simplify correct rounding during downsampling, etc. The JPEG standard's +specification that 8-bit sample values run from -128..127 is accommodated by +subtracting 128 from the sample value in the DCT step. Similarly, during +decompression the output of the IDCT step will be immediately shifted back to +0..255. (NOTE: different values are required when 12-bit samples are in use. +When 8-bit samples are in use, the code uses MAXJSAMPLE and CENTERJSAMPLE, +which are defined as 255 and 128 respectively. When 12-bit samples are in use, +the code uses MAXJ12SAMPLE and CENTERJ12SAMPLE, which are defined as 4095 and +2048 respectively. When 16-bit samples are in use, the code uses MAXJ16SAMPLE +and CENTERJ16SAMPLE, which are defined as 65535 and 32768 respectively.) + +We use a pointer per row, rather than a two-dimensional J*SAMPLE array. This +choice costs only a small amount of memory and has several benefits: +* Code using the data structure doesn't need to know the allocated width of + the rows. This simplifies edge expansion/compression, since we can work + in an array that's wider than the logical picture width. +* Indexing doesn't require multiplication; this is a performance win on many + machines. +* Arrays with more than 64K total elements can be supported even on machines + where malloc() cannot allocate chunks larger than 64K. +* The rows forming a component array may be allocated at different times + without extra copying. This trick allows some speedups in smoothing steps + that need access to the previous and next rows. + +Note that each color component is stored in a separate array; we don't use the +traditional layout in which the components of a pixel are stored together. +This simplifies coding of modules that work on each component independently, +because they don't need to know how many components there are. Furthermore, +we can read or write each component to a temporary file independently, which +is helpful when dealing with noninterleaved JPEG files. + +In general, a specific sample value is accessed by code such as + image[colorcomponent][row][col] +where col is measured from the image left edge, but row is measured from the +first sample row currently in memory. Either of the first two indexings can +be precomputed by copying the relevant pointer. + + +Since most image-processing applications prefer to work on images in which +the components of a pixel are stored together, the data passed to or from the +surrounding application uses the traditional convention: a single pixel is +represented by N consecutive J*SAMPLE values, and an image row is an array of +(# of color components)*(image width) J*SAMPLEs. One or more rows of data can +be represented by a pointer of type J*SAMPARRAY in this scheme. This scheme is +converted to component-wise storage inside the JPEG library. (Applications +that want to skip JPEG preprocessing or postprocessing will have to contend +with component-wise storage.) + + +Arrays of DCT-coefficient values use the following data structure: + + typedef short JCOEF; a 16-bit signed integer + typedef JCOEF JBLOCK[DCTSIZE2]; an 8x8 block of coefficients + typedef JBLOCK *JBLOCKROW; ptr to one horizontal row of 8x8 blocks + typedef JBLOCKROW *JBLOCKARRAY; ptr to a list of such rows + typedef JBLOCKARRAY *JBLOCKIMAGE; ptr to a list of color component arrays + +The underlying type is at least a 16-bit signed integer; while "short" is big +enough on all machines of interest, on some machines it is preferable to use +"int" for speed reasons, despite the storage cost. Coefficients are grouped +into 8x8 blocks (but we always use #defines DCTSIZE and DCTSIZE2 rather than +"8" and "64"). + +The contents of a coefficient block may be in either "natural" or zigzagged +order, and may be true values or divided by the quantization coefficients, +depending on where the block is in the processing pipeline. In the current +library, coefficient blocks are kept in natural order everywhere; the entropy +codecs zigzag or dezigzag the data as it is written or read. The blocks +contain quantized coefficients everywhere outside the DCT/IDCT subsystems. +(This latter decision may need to be revisited to support variable +quantization a la JPEG Part 3.) + +Notice that the allocation unit is now a row of 8x8 blocks, corresponding to +eight rows of samples. Otherwise the structure is much the same as for +samples, and for the same reasons. + + +*** Suspendable processing *** + +In some applications it is desirable to use the JPEG library as an +incremental, memory-to-memory filter. In this situation the data source or +destination may be a limited-size buffer, and we can't rely on being able to +empty or refill the buffer at arbitrary times. Instead the application would +like to have control return from the library at buffer overflow/underrun, and +then resume compression or decompression at a later time. + +This scenario is supported for simple cases. (For anything more complex, we +recommend that the application "bite the bullet" and develop real multitasking +capability.) The libjpeg.txt file goes into more detail about the usage and +limitations of this capability; here we address the implications for library +structure. + +The essence of the problem is that the entropy codec (coder or decoder) must +be prepared to stop at arbitrary times. In turn, the controllers that call +the entropy codec must be able to stop before having produced or consumed all +the data that they normally would handle in one call. That part is reasonably +straightforward: we make the controller call interfaces include "progress +counters" which indicate the number of data chunks successfully processed, and +we require callers to test the counter rather than just assume all of the data +was processed. + +Rather than trying to restart at an arbitrary point, the current Huffman +codecs are designed to restart at the beginning of the current MCU after a +suspension due to buffer overflow/underrun. At the start of each call, the +codec's internal state is loaded from permanent storage (in the JPEG object +structures) into local variables. On successful completion of the MCU, the +permanent state is updated. (This copying is not very expensive, and may even +lead to *improved* performance if the local variables can be registerized.) +If a suspension occurs, the codec simply returns without updating the state, +thus effectively reverting to the start of the MCU. Note that this implies +leaving some data unprocessed in the source/destination buffer (ie, the +compressed partial MCU). The data source/destination module interfaces are +specified so as to make this possible. This also implies that the data buffer +must be large enough to hold a worst-case compressed MCU; a couple thousand +bytes should be enough. + +In a successive-approximation AC refinement scan, the progressive Huffman +decoder has to be able to undo assignments of newly nonzero coefficients if it +suspends before the MCU is complete, since decoding requires distinguishing +previously-zero and previously-nonzero coefficients. This is a bit tedious +but probably won't have much effect on performance. Other variants of Huffman +decoding need not worry about this, since they will just store the same values +again if forced to repeat the MCU. + +This approach would probably not work for an arithmetic codec, since its +modifiable state is quite large and couldn't be copied cheaply. Instead it +would have to suspend and resume exactly at the point of the buffer end. + +The JPEG marker reader is designed to cope with suspension at an arbitrary +point. It does so by backing up to the start of the marker parameter segment, +so the data buffer must be big enough to hold the largest marker of interest. +Again, a couple KB should be adequate. (A special "skip" convention is used +to bypass COM and APPn markers, so these can be larger than the buffer size +without causing problems; otherwise a 64K buffer would be needed in the worst +case.) + +The JPEG marker writer currently does *not* cope with suspension. +We feel that this is not necessary; it is much easier simply to require +the application to ensure there is enough buffer space before starting. (An +empty 2K buffer is more than sufficient for the header markers; and ensuring +there are a dozen or two bytes available before calling jpeg_finish_compress() +will suffice for the trailer.) This would not work for writing multi-scan +JPEG files, but we simply do not intend to support that capability with +suspension. + + +*** Memory manager services *** + +The JPEG library's memory manager controls allocation and deallocation of +memory, and it manages large "virtual" data arrays on machines where the +operating system does not provide virtual memory. Note that the same +memory manager serves both compression and decompression operations. + +In all cases, allocated objects are tied to a particular compression or +decompression master record, and they will be released when that master +record is destroyed. + +The memory manager does not provide explicit deallocation of objects. +Instead, objects are created in "pools" of free storage, and a whole pool +can be freed at once. This approach helps prevent storage-leak bugs, and +it speeds up operations whenever malloc/free are slow (as they often are). +The pools can be regarded as lifetime identifiers for objects. Two +pools/lifetimes are defined: + * JPOOL_PERMANENT lasts until master record is destroyed + * JPOOL_IMAGE lasts until done with image (JPEG datastream) +Permanent lifetime is used for parameters and tables that should be carried +across from one datastream to another; this includes all application-visible +parameters. Image lifetime is used for everything else. (A third lifetime, +JPOOL_PASS = one processing pass, was originally planned. However it was +dropped as not being worthwhile. The actual usage patterns are such that the +peak memory usage would be about the same anyway; and having per-pass storage +substantially complicates the virtual memory allocation rules --- see below.) + +The memory manager deals with three kinds of object: +1. "Small" objects. Typically these require no more than 10K-20K total. +2. "Large" objects. These may require tens to hundreds of K depending on + image size. Semantically they behave the same as small objects, but we + distinguish them because pool allocation heuristics may differ for large and + small objects (historically, large objects were also referenced by far + pointers on MS-DOS machines.) Note that individual "large" objects cannot + exceed the size allowed by type size_t, which may be 64K or less on some + machines. +3. "Virtual" objects. These are large 2-D arrays of J*SAMPLEs or JBLOCKs + (typically large enough for the entire image being processed). The + memory manager provides stripwise access to these arrays. On machines + without virtual memory, the rest of the array may be swapped out to a + temporary file. + +(Note: J*SAMPARRAY and JBLOCKARRAY data structures are a combination of large +objects for the data proper and small objects for the row pointers. For +convenience and speed, the memory manager provides single routines to create +these structures. Similarly, virtual arrays include a small control block +and a J*SAMPARRAY or JBLOCKARRAY working buffer, all created with one call.) + +In the present implementation, virtual arrays are only permitted to have image +lifespan. (Permanent lifespan would not be reasonable, and pass lifespan is +not very useful since a virtual array's raison d'etre is to store data for +multiple passes through the image.) We also expect that only "small" objects +will be given permanent lifespan, though this restriction is not required by +the memory manager. + +In a non-virtual-memory machine, some performance benefit can be gained by +making the in-memory buffers for virtual arrays be as large as possible. +(For small images, the buffers might fit entirely in memory, so blind +swapping would be very wasteful.) The memory manager will adjust the height +of the buffers to fit within a prespecified maximum memory usage. In order +to do this in a reasonably optimal fashion, the manager needs to allocate all +of the virtual arrays at once. Therefore, there isn't a one-step allocation +routine for virtual arrays; instead, there is a "request" routine that simply +allocates the control block, and a "realize" routine (called just once) that +determines space allocation and creates all of the actual buffers. The +realize routine must allow for space occupied by non-virtual large objects. +(We don't bother to factor in the space needed for small objects, on the +grounds that it isn't worth the trouble.) + +To support all this, we establish the following protocol for doing business +with the memory manager: + 1. Modules must request virtual arrays (which may have only image lifespan) + during the initial setup phase, i.e., in their jinit_xxx routines. + 2. All "large" objects (including J*SAMPARRAYs and JBLOCKARRAYs) must also be + allocated during initial setup. + 3. realize_virt_arrays will be called at the completion of initial setup. + The above conventions ensure that sufficient information is available + for it to choose a good size for virtual array buffers. +Small objects of any lifespan may be allocated at any time. We expect that +the total space used for small objects will be small enough to be negligible +in the realize_virt_arrays computation. + +In a virtual-memory machine, we simply pretend that the available space is +infinite, thus causing realize_virt_arrays to decide that it can allocate all +the virtual arrays as full-size in-memory buffers. The overhead of the +virtual-array access protocol is very small when no swapping occurs. + +A virtual array can be specified to be "pre-zeroed"; when this flag is set, +never-yet-written sections of the array are set to zero before being made +available to the caller. If this flag is not set, never-written sections +of the array contain garbage. (This feature exists primarily because the +equivalent logic would otherwise be needed in jdcoefct.c for progressive +JPEG mode; we may as well make it available for possible other uses.) + +The first write pass on a virtual array is required to occur in top-to-bottom +order; read passes, as well as any write passes after the first one, may +access the array in any order. This restriction exists partly to simplify +the virtual array control logic, and partly because some file systems may not +support seeking beyond the current end-of-file in a temporary file. The main +implication of this restriction is that rearrangement of rows (such as +converting top-to-bottom data order to bottom-to-top) must be handled while +reading data out of the virtual array, not while putting it in. + + +*** Memory manager internal structure *** + +To isolate system dependencies as much as possible, we have broken the +memory manager into two parts. There is a reasonably system-independent +"front end" (jmemmgr.c) and a "back end" that contains only the code +likely to change across systems. All of the memory management methods +outlined above are implemented by the front end. The back end provides +the following routines for use by the front end (none of these routines +are known to the rest of the JPEG code): + +jpeg_mem_init, jpeg_mem_term system-dependent initialization/shutdown + +jpeg_get_small, jpeg_free_small interface to malloc and free library routines + (or their equivalents) + +jpeg_get_large, jpeg_free_large historically was used to interface with + FAR malloc/free on MS-DOS machines; now the + same as jpeg_get_small/jpeg_free_small + +jpeg_mem_available estimate available memory + +jpeg_open_backing_store create a backing-store object + +read_backing_store, manipulate a backing-store object +write_backing_store, +close_backing_store + +On some systems there will be more than one type of backing-store object. +jpeg_open_backing_store is responsible for choosing how to implement a given +object. The read/write/close routines are method pointers in the structure +that describes a given object; this lets them be different for different object +types. + +It may be necessary to ensure that backing store objects are explicitly +released upon abnormal program termination. To support this, we will expect +the main program or surrounding application to arrange to call self_destruct +(typically via jpeg_destroy) upon abnormal termination. This may require a +SIGINT signal handler or equivalent. We don't want to have the back end module +install its own signal handler, because that would pre-empt the surrounding +application's ability to control signal handling. + +The IJG distribution includes several memory manager back end implementations. +Usually the same back end should be suitable for all applications on a given +system, but it is possible for an application to supply its own back end at +need. + + +*** Implications of DNL marker *** + +Some JPEG files may use a DNL marker to postpone definition of the image +height (this would be useful for a fax-like scanner's output, for instance). +In these files the SOF marker claims the image height is 0, and you only +find out the true image height at the end of the first scan. + +We could read these files as follows: +1. Upon seeing zero image height, replace it by 65535 (the maximum allowed). +2. When the DNL is found, update the image height in the global image + descriptor. +This implies that control modules must avoid making copies of the image +height, and must re-test for termination after each MCU row. This would +be easy enough to do. + +In cases where image-size data structures are allocated, this approach will +result in very inefficient use of virtual memory or much-larger-than-necessary +temporary files. This seems acceptable for something that probably won't be a +mainstream usage. People might have to forgo use of memory-hogging options +(such as two-pass color quantization or noninterleaved JPEG files) if they +want efficient conversion of such files. (One could improve efficiency by +demanding a user-supplied upper bound for the height, less than 65536; in most +cases it could be much less.) + +The standard also permits the SOF marker to overestimate the image height, +with a DNL to give the true, smaller height at the end of the first scan. +This would solve the space problems if the overestimate wasn't too great. +However, it implies that you don't even know whether DNL will be used. + +This leads to a couple of very serious objections: +1. Testing for a DNL marker must occur in the inner loop of the decompressor's + Huffman decoder; this implies a speed penalty whether the feature is used + or not. +2. There is no way to hide the last-minute change in image height from an + application using the decoder. Thus *every* application using the IJG + library would suffer a complexity penalty whether it cared about DNL or + not. +We currently do not support DNL because of these problems. + +A different approach is to insist that DNL-using files be preprocessed by a +separate program that reads ahead to the DNL, then goes back and fixes the SOF +marker. This is a much simpler solution and is probably far more efficient. +Even if one wants piped input, buffering the first scan of the JPEG file needs +a lot smaller temp file than is implied by the maximum-height method. For +this approach we'd simply treat DNL as a no-op in the decompressor (at most, +check that it matches the SOF image height). + +We will not worry about making the compressor capable of outputting DNL. +Something similar to the first scheme above could be applied if anyone ever +wants to make that work. diff --git a/3rdparty/libjpeg-turbo/src/tjbench.c b/3rdparty/libjpeg-turbo/src/tjbench.c new file mode 100644 index 000000000000..9dc6427880bb --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/tjbench.c @@ -0,0 +1,1323 @@ +/* + * Copyright (C)2009-2019, 2021-2024 D. R. Commander. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef _MSC_VER +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#include +#include +#include +#include +#include +#include +#include +#if !defined(_MSC_VER) || _MSC_VER > 1600 +#include +#endif +#include +#include "./tjutil.h" +#include "./turbojpeg.h" + + +#define THROW(op, err) { \ + printf("ERROR in line %d while %s:\n%s\n", __LINE__, op, err); \ + retval = -1; goto bailout; \ +} +#define THROW_UNIX(m) THROW(m, strerror(errno)) + +static char tjErrorStr[JMSG_LENGTH_MAX] = "\0"; +static int tjErrorLine = -1, tjErrorCode = -1; + +#define THROW_TJG() { \ + printf("ERROR in line %d\n%s\n", __LINE__, tj3GetErrorStr(NULL)); \ + retval = -1; goto bailout; \ +} + +#define THROW_TJ() { \ + int _tjErrorCode = tj3GetErrorCode(handle); \ + char *_tjErrorStr = tj3GetErrorStr(handle); \ + \ + if (!tj3Get(handle, TJPARAM_STOPONWARNING) && \ + _tjErrorCode == TJERR_WARNING) { \ + if (strncmp(tjErrorStr, _tjErrorStr, JMSG_LENGTH_MAX) || \ + tjErrorCode != _tjErrorCode || tjErrorLine != __LINE__) { \ + strncpy(tjErrorStr, _tjErrorStr, JMSG_LENGTH_MAX); \ + tjErrorStr[JMSG_LENGTH_MAX - 1] = '\0'; \ + tjErrorCode = _tjErrorCode; \ + tjErrorLine = __LINE__; \ + printf("WARNING in line %d:\n%s\n", __LINE__, _tjErrorStr); \ + } \ + } else { \ + printf("%s in line %d:\n%s\n", \ + _tjErrorCode == TJERR_WARNING ? "WARNING" : "ERROR", __LINE__, \ + _tjErrorStr); \ + retval = -1; goto bailout; \ + } \ +} + +#define IS_CROPPED(cr) (cr.x != 0 || cr.y != 0 || cr.w != 0 || cr.h != 0) + +#define CROPPED_WIDTH(width) \ + (IS_CROPPED(cr) ? (cr.w != 0 ? cr.w : TJSCALED(width, sf) - cr.x) : \ + TJSCALED(width, sf)) + +#define CROPPED_HEIGHT(height) \ + (IS_CROPPED(cr) ? (cr.h != 0 ? cr.h : TJSCALED(height, sf) - cr.y) : \ + TJSCALED(height, sf)) + +static int stopOnWarning = 0, bottomUp = 0, noRealloc = 1, fastUpsample = 0, + fastDCT = 0, optimize = 0, progressive = 0, limitScans = 0, maxMemory = 0, + maxPixels = 0, arithmetic = 0, lossless = 0, restartIntervalBlocks = 0, + restartIntervalRows = 0; +static int precision = 8, sampleSize, compOnly = 0, decompOnly = 0, doYUV = 0, + quiet = 0, doTile = 0, pf = TJPF_BGR, yuvAlign = 1, doWrite = 1; +static char *ext = "ppm"; +static const char *pixFormatStr[TJ_NUMPF] = { + "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "GRAY", "", "", "", "", "CMYK" +}; +static const char *subNameLong[TJ_NUMSAMP] = { + "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0", "4:1:1", "4:4:1" +}; +static const char *csName[TJ_NUMCS] = { + "RGB", "YCbCr", "GRAY", "CMYK", "YCCK" +}; +static const char *subName[TJ_NUMSAMP] = { + "444", "422", "420", "GRAY", "440", "411", "441" +}; +static tjscalingfactor *scalingFactors = NULL, sf = { 1, 1 }; +static tjregion cr = { 0, 0, 0, 0 }; +static int nsf = 0, xformOp = TJXOP_NONE, xformOpt = 0; +static int (*customFilter) (short *, tjregion, tjregion, int, int, + tjtransform *); +static double benchTime = 5.0, warmup = 1.0; + + +static char *formatName(int subsamp, int cs, char *buf) +{ + if (quiet == 1) { + if (lossless) + SNPRINTF(buf, 80, "%-2d/LOSSLESS ", precision); + else if (subsamp == TJSAMP_UNKNOWN) + SNPRINTF(buf, 80, "%-2d/%-5s ", precision, csName[cs]); + else + SNPRINTF(buf, 80, "%-2d/%-5s/%-5s", precision, csName[cs], + subNameLong[subsamp]); + return buf; + } else { + if (lossless) + return (char *)"Lossless"; + else if (subsamp == TJSAMP_UNKNOWN) + return (char *)csName[cs]; + else { + SNPRINTF(buf, 80, "%s %s", csName[cs], subNameLong[subsamp]); + return buf; + } + } +} + + +static char *sigfig(double val, int figs, char *buf, int len) +{ + char format[80]; + int digitsAfterDecimal = figs - (int)ceil(log10(fabs(val))); + + if (digitsAfterDecimal < 1) + SNPRINTF(format, 80, "%%.0f"); + else + SNPRINTF(format, 80, "%%.%df", digitsAfterDecimal); + SNPRINTF(buf, len, format, val); + return buf; +} + + +/* Custom DCT filter which produces a negative of the image */ +static int dummyDCTFilter(short *coeffs, tjregion arrayRegion, + tjregion planeRegion, int componentIndex, + int transformIndex, tjtransform *transform) +{ + int i; + + for (i = 0; i < arrayRegion.w * arrayRegion.h; i++) + coeffs[i] = -coeffs[i]; + return 0; +} + + +/* Decompression test */ +static int decomp(unsigned char **jpegBufs, size_t *jpegSizes, void *dstBuf, + int w, int h, int subsamp, int jpegQual, char *fileName, + int tilew, int tileh) +{ + char tempStr[1024], sizeStr[24] = "\0", qualStr[16] = "\0"; + FILE *file = NULL; + tjhandle handle = NULL; + int i, row, col, iter = 0, dstBufAlloc = 0, retval = 0; + double elapsed, elapsedDecode; + int ps = tjPixelSize[pf]; + int scaledw, scaledh, pitch; + int ntilesw = (w + tilew - 1) / tilew, ntilesh = (h + tileh - 1) / tileh; + unsigned char *dstPtr, *dstPtr2, *yuvBuf = NULL; + + if (lossless) sf = TJUNSCALED; + + scaledw = TJSCALED(w, sf); + scaledh = TJSCALED(h, sf); + + if (jpegQual > 0) { + SNPRINTF(qualStr, 16, "_%s%d", lossless ? "PSV" : "Q", jpegQual); + qualStr[15] = 0; + } + + if ((handle = tj3Init(TJINIT_DECOMPRESS)) == NULL) + THROW_TJG(); + if (tj3Set(handle, TJPARAM_STOPONWARNING, stopOnWarning) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_BOTTOMUP, bottomUp) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_FASTUPSAMPLE, fastUpsample) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_FASTDCT, fastDCT) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_SCANLIMIT, limitScans ? 500 : 0) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_MAXMEMORY, maxMemory) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_MAXPIXELS, maxPixels) == -1) + THROW_TJ(); + + if (IS_CROPPED(cr)) { + if (tj3DecompressHeader(handle, jpegBufs[0], jpegSizes[0]) == -1) + THROW_TJ(); + } + if (tj3SetScalingFactor(handle, sf) == -1) + THROW_TJ(); + if (tj3SetCroppingRegion(handle, cr) == -1) + THROW_TJ(); + if (IS_CROPPED(cr)) { + scaledw = cr.w ? cr.w : scaledw - cr.x; + scaledh = cr.h ? cr.h : scaledh - cr.y; + } + pitch = scaledw * ps; + + if (dstBuf == NULL) { +#if ULLONG_MAX > SIZE_MAX + if ((unsigned long long)pitch * (unsigned long long)scaledh * + (unsigned long long)sampleSize > (unsigned long long)((size_t)-1)) + THROW("allocating destination buffer", "Image is too large"); +#endif + if ((dstBuf = malloc((size_t)pitch * scaledh * sampleSize)) == NULL) + THROW_UNIX("allocating destination buffer"); + dstBufAlloc = 1; + } + + /* Set the destination buffer to gray so we know whether the decompressor + attempted to write to it */ + if (precision == 8) + memset((unsigned char *)dstBuf, 127, (size_t)pitch * scaledh); + else if (precision == 12) { + for (i = 0; i < pitch * scaledh; i++) + ((short *)dstBuf)[i] = (short)2047; + } else { + for (i = 0; i < pitch * scaledh; i++) + ((unsigned short *)dstBuf)[i] = (unsigned short)32767; + } + + if (doYUV) { + int width = doTile ? tilew : scaledw; + int height = doTile ? tileh : scaledh; + size_t yuvSize = tj3YUVBufSize(width, yuvAlign, height, subsamp); + + if (yuvSize == 0) + THROW_TJG(); + if ((yuvBuf = (unsigned char *)malloc(yuvSize)) == NULL) + THROW_UNIX("allocating YUV buffer"); + memset(yuvBuf, 127, yuvSize); + } + + /* Benchmark */ + iter = -1; + elapsed = elapsedDecode = 0.; + while (1) { + int tile = 0; + double start = getTime(); + + for (row = 0, dstPtr = dstBuf; row < ntilesh; + row++, dstPtr += (size_t)pitch * tileh * sampleSize) { + for (col = 0, dstPtr2 = dstPtr; col < ntilesw; + col++, tile++, dstPtr2 += ps * tilew * sampleSize) { + int width = doTile ? min(tilew, w - col * tilew) : scaledw; + int height = doTile ? min(tileh, h - row * tileh) : scaledh; + + if (doYUV) { + double startDecode; + + if (tj3DecompressToYUV8(handle, jpegBufs[tile], jpegSizes[tile], + yuvBuf, yuvAlign) == -1) + THROW_TJ(); + startDecode = getTime(); + if (tj3DecodeYUV8(handle, yuvBuf, yuvAlign, dstPtr2, width, pitch, + height, pf) == -1) + THROW_TJ(); + if (iter >= 0) elapsedDecode += getTime() - startDecode; + } else { + if (precision == 8) { + if (tj3Decompress8(handle, jpegBufs[tile], jpegSizes[tile], + dstPtr2, pitch, pf) == -1) + THROW_TJ(); + } else if (precision == 12) { + if (tj3Decompress12(handle, jpegBufs[tile], jpegSizes[tile], + (short *)dstPtr2, pitch, pf) == -1) + THROW_TJ(); + } else { + if (tj3Decompress16(handle, jpegBufs[tile], jpegSizes[tile], + (unsigned short *)dstPtr2, pitch, pf) == -1) + THROW_TJ(); + } + } + } + } + elapsed += getTime() - start; + if (iter >= 0) { + iter++; + if (elapsed >= benchTime) break; + } else if (elapsed >= warmup) { + iter = 0; + elapsed = elapsedDecode = 0.; + } + } + if (doYUV) elapsed -= elapsedDecode; + + if (quiet) { + printf("%-6s%s", + sigfig((double)(w * h) / 1000000. * (double)iter / elapsed, 4, + tempStr, 1024), + quiet == 2 ? "\n" : " "); + if (doYUV) + printf("%s\n", + sigfig((double)(w * h) / 1000000. * (double)iter / elapsedDecode, + 4, tempStr, 1024)); + else if (quiet != 2) printf("\n"); + } else { + printf("%s --> Frame rate: %f fps\n", + doYUV ? "Decomp to YUV" : "Decompress ", (double)iter / elapsed); + printf(" Throughput: %f Megapixels/sec\n", + (double)(w * h) / 1000000. * (double)iter / elapsed); + if (doYUV) { + printf("YUV Decode --> Frame rate: %f fps\n", + (double)iter / elapsedDecode); + printf(" Throughput: %f Megapixels/sec\n", + (double)(w * h) / 1000000. * (double)iter / elapsedDecode); + } + } + + if (!doWrite) goto bailout; + + if (sf.num != 1 || sf.denom != 1) + SNPRINTF(sizeStr, 24, "%d_%d", sf.num, sf.denom); + else if (tilew != w || tileh != h) + SNPRINTF(sizeStr, 24, "%dx%d", tilew, tileh); + else SNPRINTF(sizeStr, 24, "full"); + if (decompOnly) + SNPRINTF(tempStr, 1024, "%s_%s.%s", fileName, sizeStr, ext); + else + SNPRINTF(tempStr, 1024, "%s_%s%s_%s.%s", fileName, + lossless ? "LOSSLS" : subName[subsamp], qualStr, sizeStr, ext); + + if (precision == 8) { + if (tj3SaveImage8(handle, tempStr, (unsigned char *)dstBuf, scaledw, 0, + scaledh, pf) == -1) + THROW_TJ(); + } else if (precision == 12) { + if (tj3SaveImage12(handle, tempStr, (short *)dstBuf, scaledw, 0, scaledh, + pf) == -1) + THROW_TJ(); + } else { + if (tj3SaveImage16(handle, tempStr, (unsigned short *)dstBuf, scaledw, 0, + scaledh, pf) == -1) + THROW_TJ(); + } + +bailout: + if (file) fclose(file); + tj3Destroy(handle); + if (dstBufAlloc) free(dstBuf); + free(yuvBuf); + return retval; +} + + +static int fullTest(tjhandle handle, void *srcBuf, int w, int h, int subsamp, + int jpegQual, char *fileName) +{ + char tempStr[1024], tempStr2[80]; + FILE *file = NULL; + unsigned char **jpegBufs = NULL, *yuvBuf = NULL, *srcPtr, *srcPtr2; + void *tmpBuf = NULL; + double start, elapsed, elapsedEncode; + int row, col, i, tilew = w, tileh = h, retval = 0; + int iter; + size_t totalJpegSize = 0, *jpegSizes = NULL, yuvSize = 0; + int ps = tjPixelSize[pf]; + int ntilesw = 1, ntilesh = 1, pitch = w * ps; + const char *pfStr = pixFormatStr[pf]; + +#if ULLONG_MAX > SIZE_MAX + if ((unsigned long long)pitch * (unsigned long long)h * + (unsigned long long)sampleSize > (unsigned long long)((size_t)-1)) + THROW("allocating temporary image buffer", "Image is too large"); +#endif + if ((tmpBuf = malloc((size_t)pitch * h * sampleSize)) == NULL) + THROW_UNIX("allocating temporary image buffer"); + + if (!quiet) + printf(">>>>> %s (%s) <--> %d-bit JPEG (%s %s%d) <<<<<\n", pfStr, + bottomUp ? "Bottom-up" : "Top-down", precision, + lossless ? "Lossless" : subNameLong[subsamp], + lossless ? "PSV" : "Q", jpegQual); + + for (tilew = doTile ? 8 : w, tileh = doTile ? 8 : h; ; + tilew *= 2, tileh *= 2) { + if (tilew > w) tilew = w; + if (tileh > h) tileh = h; + ntilesw = (w + tilew - 1) / tilew; + ntilesh = (h + tileh - 1) / tileh; + + if ((jpegBufs = (unsigned char **)malloc(sizeof(unsigned char *) * + ntilesw * ntilesh)) == NULL) + THROW_UNIX("allocating JPEG tile array"); + memset(jpegBufs, 0, sizeof(unsigned char *) * ntilesw * ntilesh); + if ((jpegSizes = (size_t *)malloc(sizeof(size_t) * ntilesw * + ntilesh)) == NULL) + THROW_UNIX("allocating JPEG size array"); + memset(jpegSizes, 0, sizeof(size_t) * ntilesw * ntilesh); + + if (noRealloc) { + for (i = 0; i < ntilesw * ntilesh; i++) { + size_t jpegBufSize = tj3JPEGBufSize(tilew, tileh, subsamp); + + if (jpegBufSize == 0) + THROW_TJG(); + if ((jpegBufs[i] = tj3Alloc(jpegBufSize)) == NULL) + THROW_UNIX("allocating JPEG tiles"); + } + } + + /* Compression test */ + if (quiet == 1) + printf("%-4s(%s) %-2d/%-6s %-3d ", pfStr, bottomUp ? "BU" : "TD", + precision, lossless ? "LOSSLS" : subNameLong[subsamp], jpegQual); + if (precision == 8) { + for (i = 0; i < h; i++) + memcpy(&((unsigned char *)tmpBuf)[pitch * i], + &((unsigned char *)srcBuf)[w * ps * i], w * ps); + } else { + for (i = 0; i < h; i++) + memcpy(&((unsigned short *)tmpBuf)[pitch * i], + &((unsigned short *)srcBuf)[w * ps * i], w * ps * sampleSize); + } + + if (tj3Set(handle, TJPARAM_NOREALLOC, noRealloc) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_SUBSAMP, subsamp) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_FASTDCT, fastDCT) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_OPTIMIZE, optimize) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_PROGRESSIVE, progressive) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_ARITHMETIC, arithmetic) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_LOSSLESS, lossless) == -1) + THROW_TJ(); + if (lossless) { + if (tj3Set(handle, TJPARAM_LOSSLESSPSV, jpegQual) == -1) + THROW_TJ(); + } else { + if (tj3Set(handle, TJPARAM_QUALITY, jpegQual) == -1) + THROW_TJ(); + } + if (tj3Set(handle, TJPARAM_RESTARTBLOCKS, restartIntervalBlocks) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_RESTARTROWS, restartIntervalRows) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_MAXMEMORY, maxMemory) == -1) + THROW_TJ(); + + if (doYUV) { + yuvSize = tj3YUVBufSize(tilew, yuvAlign, tileh, subsamp); + if (yuvSize == 0) + THROW_TJG(); + if ((yuvBuf = (unsigned char *)malloc(yuvSize)) == NULL) + THROW_UNIX("allocating YUV buffer"); + memset(yuvBuf, 127, yuvSize); + } + + /* Benchmark */ + iter = -1; + elapsed = elapsedEncode = 0.; + while (1) { + int tile = 0; + + totalJpegSize = 0; + start = getTime(); + for (row = 0, srcPtr = srcBuf; row < ntilesh; + row++, srcPtr += pitch * tileh * sampleSize) { + for (col = 0, srcPtr2 = srcPtr; col < ntilesw; + col++, tile++, srcPtr2 += ps * tilew * sampleSize) { + int width = min(tilew, w - col * tilew); + int height = min(tileh, h - row * tileh); + + if (doYUV) { + double startEncode = getTime(); + + if (tj3EncodeYUV8(handle, srcPtr2, width, pitch, height, pf, + yuvBuf, yuvAlign) == -1) + THROW_TJ(); + if (iter >= 0) elapsedEncode += getTime() - startEncode; + if (tj3CompressFromYUV8(handle, yuvBuf, width, yuvAlign, height, + &jpegBufs[tile], &jpegSizes[tile]) == -1) + THROW_TJ(); + } else { + if (precision == 8) { + if (tj3Compress8(handle, srcPtr2, width, pitch, height, pf, + &jpegBufs[tile], &jpegSizes[tile]) == -1) + THROW_TJ(); + } else if (precision == 12) { + if (tj3Compress12(handle, (short *)srcPtr2, width, pitch, height, + pf, &jpegBufs[tile], &jpegSizes[tile]) == -1) + THROW_TJ(); + } else { + if (tj3Compress16(handle, (unsigned short *)srcPtr2, width, + pitch, height, pf, &jpegBufs[tile], + &jpegSizes[tile]) == -1) + THROW_TJ(); + } + } + totalJpegSize += jpegSizes[tile]; + } + } + elapsed += getTime() - start; + if (iter >= 0) { + iter++; + if (elapsed >= benchTime) break; + } else if (elapsed >= warmup) { + iter = 0; + elapsed = elapsedEncode = 0.; + } + } + if (doYUV) elapsed -= elapsedEncode; + + if (quiet == 1) printf("%-5d %-5d ", tilew, tileh); + if (quiet) { + if (doYUV) + printf("%-6s%s", + sigfig((double)(w * h) / 1000000. * + (double)iter / elapsedEncode, 4, tempStr, 1024), + quiet == 2 ? "\n" : " "); + printf("%-6s%s", + sigfig((double)(w * h) / 1000000. * (double)iter / elapsed, 4, + tempStr, 1024), + quiet == 2 ? "\n" : " "); + printf("%-6s%s", + sigfig((double)(w * h * ps) / (double)totalJpegSize, 4, tempStr2, + 80), + quiet == 2 ? "\n" : " "); + } else { + printf("\n%s size: %d x %d\n", doTile ? "Tile" : "Image", tilew, tileh); + if (doYUV) { + printf("Encode YUV --> Frame rate: %f fps\n", + (double)iter / elapsedEncode); + printf(" Output image size: %lu bytes\n", + (unsigned long)yuvSize); + printf(" Compression ratio: %f:1\n", + (double)(w * h * ps) / (double)yuvSize); + printf(" Throughput: %f Megapixels/sec\n", + (double)(w * h) / 1000000. * (double)iter / elapsedEncode); + printf(" Output bit stream: %f Megabits/sec\n", + (double)yuvSize * 8. / 1000000. * (double)iter / elapsedEncode); + } + printf("%s --> Frame rate: %f fps\n", + doYUV ? "Comp from YUV" : "Compress ", + (double)iter / elapsed); + printf(" Output image size: %lu bytes\n", + (unsigned long)totalJpegSize); + printf(" Compression ratio: %f:1\n", + (double)(w * h * ps) / (double)totalJpegSize); + printf(" Throughput: %f Megapixels/sec\n", + (double)(w * h) / 1000000. * (double)iter / elapsed); + printf(" Output bit stream: %f Megabits/sec\n", + (double)totalJpegSize * 8. / 1000000. * (double)iter / elapsed); + } + if (tilew == w && tileh == h && doWrite) { + SNPRINTF(tempStr, 1024, "%s_%s_%s%d.jpg", fileName, + lossless ? "LOSSLS" : subName[subsamp], + lossless ? "PSV" : "Q", jpegQual); + if ((file = fopen(tempStr, "wb")) == NULL) + THROW_UNIX("opening reference image"); + if (fwrite(jpegBufs[0], jpegSizes[0], 1, file) != 1) + THROW_UNIX("writing reference image"); + fclose(file); file = NULL; + if (!quiet) printf("Reference image written to %s\n", tempStr); + } + + /* Decompression test */ + if (!compOnly) { + if (decomp(jpegBufs, jpegSizes, tmpBuf, w, h, subsamp, jpegQual, + fileName, tilew, tileh) == -1) + goto bailout; + } else if (quiet == 1) printf("N/A\n"); + + for (i = 0; i < ntilesw * ntilesh; i++) { + tj3Free(jpegBufs[i]); + jpegBufs[i] = NULL; + } + free(jpegBufs); jpegBufs = NULL; + free(jpegSizes); jpegSizes = NULL; + if (doYUV) { + free(yuvBuf); yuvBuf = NULL; + } + + if (tilew == w && tileh == h) break; + } + +bailout: + if (file) fclose(file); + if (jpegBufs) { + for (i = 0; i < ntilesw * ntilesh; i++) + tj3Free(jpegBufs[i]); + } + free(jpegBufs); + free(yuvBuf); + free(jpegSizes); + free(tmpBuf); + return retval; +} + + +static int decompTest(char *fileName) +{ + FILE *file = NULL; + tjhandle handle = NULL; + unsigned char **jpegBufs = NULL, *srcBuf = NULL; + size_t *jpegSizes = NULL, srcSize, totalJpegSize; + tjtransform *t = NULL; + double start, elapsed; + int ps = tjPixelSize[pf], tile, row, col, i, iter, retval = 0, decompsrc = 0; + char *temp = NULL, tempStr[80], tempStr2[80]; + /* Original image */ + int w = 0, h = 0, minTile = 16, tilew, tileh, ntilesw = 1, ntilesh = 1, + subsamp = -1, cs = -1; + /* Transformed image */ + int tw, th, ttilew, ttileh, tntilesw, tntilesh, tsubsamp; + + if ((file = fopen(fileName, "rb")) == NULL) + THROW_UNIX("opening file"); + if (fseek(file, 0, SEEK_END) < 0 || + (srcSize = ftell(file)) == (size_t)-1) + THROW_UNIX("determining file size"); + if ((srcBuf = (unsigned char *)malloc(srcSize)) == NULL) + THROW_UNIX("allocating memory"); + if (fseek(file, 0, SEEK_SET) < 0) + THROW_UNIX("setting file position"); + if (fread(srcBuf, srcSize, 1, file) < 1) + THROW_UNIX("reading JPEG data"); + fclose(file); file = NULL; + + temp = strrchr(fileName, '.'); + if (temp != NULL) *temp = '\0'; + + if ((handle = tj3Init(TJINIT_TRANSFORM)) == NULL) + THROW_TJG(); + if (tj3Set(handle, TJPARAM_STOPONWARNING, stopOnWarning) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_BOTTOMUP, bottomUp) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_NOREALLOC, noRealloc) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_FASTUPSAMPLE, fastUpsample) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_FASTDCT, fastDCT) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_SCANLIMIT, limitScans ? 500 : 0) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_MAXMEMORY, maxMemory) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_MAXPIXELS, maxPixels) == -1) + THROW_TJ(); + + if (tj3DecompressHeader(handle, srcBuf, srcSize) == -1) + THROW_TJ(); + w = tj3Get(handle, TJPARAM_JPEGWIDTH); + h = tj3Get(handle, TJPARAM_JPEGHEIGHT); + subsamp = tj3Get(handle, TJPARAM_SUBSAMP); + precision = tj3Get(handle, TJPARAM_PRECISION); + if (tj3Get(handle, TJPARAM_PROGRESSIVE) == 1) + printf("JPEG image uses progressive entropy coding\n\n"); + if (tj3Get(handle, TJPARAM_ARITHMETIC) == 1) + printf("JPEG image uses arithmetic entropy coding\n\n"); + if (tj3Set(handle, TJPARAM_PROGRESSIVE, progressive) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_ARITHMETIC, arithmetic) == -1) + THROW_TJ(); + + lossless = tj3Get(handle, TJPARAM_LOSSLESS); + sampleSize = (precision == 8 ? sizeof(unsigned char) : sizeof(short)); + cs = tj3Get(handle, TJPARAM_COLORSPACE); + if (w < 1 || h < 1) + THROW("reading JPEG header", "Invalid image dimensions"); + if (cs == TJCS_YCCK || cs == TJCS_CMYK) { + pf = TJPF_CMYK; ps = tjPixelSize[pf]; + } + if (lossless) sf = TJUNSCALED; + + if (tj3SetScalingFactor(handle, sf) == -1) + THROW_TJ(); + if (tj3SetCroppingRegion(handle, cr) == -1) + THROW_TJ(); + + if (quiet == 1) { + printf("All performance values in Mpixels/sec\n\n"); + printf("Pixel JPEG %s %s Xform Comp Decomp ", + doTile ? "Tile " : "Image", doTile ? "Tile " : "Image"); + if (doYUV) printf("Decode"); + printf("\n"); + printf("Format Format Width Height Perf Ratio Perf "); + if (doYUV) printf("Perf"); + printf("\n\n"); + } else if (!quiet) + printf(">>>>> %d-bit JPEG (%s) --> %s (%s) <<<<<\n", precision, + formatName(subsamp, cs, tempStr), pixFormatStr[pf], + bottomUp ? "Bottom-up" : "Top-down"); + + if (doTile) { + if (subsamp == TJSAMP_UNKNOWN) + THROW("transforming", + "Could not determine subsampling level of JPEG image"); + minTile = max(tjMCUWidth[subsamp], tjMCUHeight[subsamp]); + } + for (tilew = doTile ? minTile : w, tileh = doTile ? minTile : h; ; + tilew *= 2, tileh *= 2) { + if (tilew > w) tilew = w; + if (tileh > h) tileh = h; + ntilesw = (w + tilew - 1) / tilew; + ntilesh = (h + tileh - 1) / tileh; + + if ((jpegBufs = (unsigned char **)malloc(sizeof(unsigned char *) * + ntilesw * ntilesh)) == NULL) + THROW_UNIX("allocating JPEG tile array"); + memset(jpegBufs, 0, sizeof(unsigned char *) * ntilesw * ntilesh); + if ((jpegSizes = (size_t *)malloc(sizeof(size_t) * ntilesw * + ntilesh)) == NULL) + THROW_UNIX("allocating JPEG size array"); + memset(jpegSizes, 0, sizeof(size_t) * ntilesw * ntilesh); + + if (noRealloc && + (doTile || xformOp != TJXOP_NONE || xformOpt != 0 || customFilter)) { + for (i = 0; i < ntilesw * ntilesh; i++) { + size_t jpegBufSize; + + if (xformOp == TJXOP_TRANSPOSE || xformOp == TJXOP_TRANSVERSE || + xformOp == TJXOP_ROT90 || xformOp == TJXOP_ROT270) + jpegBufSize = tj3JPEGBufSize(tileh, tilew, subsamp); + else + jpegBufSize = tj3JPEGBufSize(tilew, tileh, subsamp); + if (jpegBufSize == 0) + THROW_TJG(); + if ((jpegBufs[i] = tj3Alloc(jpegBufSize)) == NULL) + THROW_UNIX("allocating JPEG tiles"); + } + } + + tw = w; th = h; ttilew = tilew; ttileh = tileh; + if (!quiet) { + printf("\n%s size: %d x %d", doTile ? "Tile" : "Image", ttilew, ttileh); + if (sf.num != 1 || sf.denom != 1 || IS_CROPPED(cr)) + printf(" --> %d x %d", CROPPED_WIDTH(tw), CROPPED_HEIGHT(th)); + printf("\n"); + } else if (quiet == 1) { + printf("%-4s(%s) %-14s ", pixFormatStr[pf], + bottomUp ? "BU" : "TD", formatName(subsamp, cs, tempStr)); + printf("%-5d %-5d ", CROPPED_WIDTH(tilew), CROPPED_HEIGHT(tileh)); + } + + tsubsamp = subsamp; + if (doTile || xformOp != TJXOP_NONE || xformOpt != 0 || customFilter) { + if ((t = (tjtransform *)malloc(sizeof(tjtransform) * ntilesw * + ntilesh)) == NULL) + THROW_UNIX("allocating image transform array"); + + if (xformOp == TJXOP_TRANSPOSE || xformOp == TJXOP_TRANSVERSE || + xformOp == TJXOP_ROT90 || xformOp == TJXOP_ROT270) { + tw = h; th = w; ttilew = tileh; ttileh = tilew; + } + + if (xformOp != TJXOP_NONE && xformOp != TJXOP_TRANSPOSE && + subsamp == TJSAMP_UNKNOWN) + THROW("transforming", + "Could not determine subsampling level of JPEG image"); + if (xformOpt & TJXOPT_GRAY) tsubsamp = TJSAMP_GRAY; + if (xformOp == TJXOP_HFLIP || xformOp == TJXOP_ROT180) + tw = tw - (tw % tjMCUWidth[tsubsamp]); + if (xformOp == TJXOP_VFLIP || xformOp == TJXOP_ROT180) + th = th - (th % tjMCUHeight[tsubsamp]); + if (xformOp == TJXOP_TRANSVERSE || xformOp == TJXOP_ROT90) + tw = tw - (tw % tjMCUHeight[tsubsamp]); + if (xformOp == TJXOP_TRANSVERSE || xformOp == TJXOP_ROT270) + th = th - (th % tjMCUWidth[tsubsamp]); + tntilesw = (tw + ttilew - 1) / ttilew; + tntilesh = (th + ttileh - 1) / ttileh; + + if (xformOp == TJXOP_TRANSPOSE || xformOp == TJXOP_TRANSVERSE || + xformOp == TJXOP_ROT90 || xformOp == TJXOP_ROT270) { + if (tsubsamp == TJSAMP_422) tsubsamp = TJSAMP_440; + else if (tsubsamp == TJSAMP_440) tsubsamp = TJSAMP_422; + else if (tsubsamp == TJSAMP_411) tsubsamp = TJSAMP_441; + else if (tsubsamp == TJSAMP_441) tsubsamp = TJSAMP_411; + } + + for (row = 0, tile = 0; row < tntilesh; row++) { + for (col = 0; col < tntilesw; col++, tile++) { + t[tile].r.w = min(ttilew, tw - col * ttilew); + t[tile].r.h = min(ttileh, th - row * ttileh); + t[tile].r.x = col * ttilew; + t[tile].r.y = row * ttileh; + t[tile].op = xformOp; + t[tile].options = xformOpt | TJXOPT_TRIM; + t[tile].customFilter = customFilter; + if (t[tile].options & TJXOPT_NOOUTPUT && jpegBufs[tile]) { + tj3Free(jpegBufs[tile]); jpegBufs[tile] = NULL; + } + } + } + + iter = -1; + elapsed = 0.; + while (1) { + start = getTime(); + if (tj3Transform(handle, srcBuf, srcSize, tntilesw * tntilesh, + jpegBufs, jpegSizes, t) == -1) + THROW_TJ(); + elapsed += getTime() - start; + if (iter >= 0) { + iter++; + if (elapsed >= benchTime) break; + } else if (elapsed >= warmup) { + iter = 0; + elapsed = 0.; + } + } + + free(t); t = NULL; + + for (tile = 0, totalJpegSize = 0; tile < tntilesw * tntilesh; tile++) + totalJpegSize += jpegSizes[tile]; + + if (quiet) { + printf("%-6s%s%-6s%s", + sigfig((double)(w * h) / 1000000. / elapsed, 4, tempStr, 80), + quiet == 2 ? "\n" : " ", + sigfig((double)(w * h * ps) / (double)totalJpegSize, 4, + tempStr2, 80), + quiet == 2 ? "\n" : " "); + } else { + printf("Transform --> Frame rate: %f fps\n", + 1.0 / elapsed); + printf(" Output image size: %lu bytes\n", + (unsigned long)totalJpegSize); + printf(" Compression ratio: %f:1\n", + (double)(w * h * ps) / (double)totalJpegSize); + printf(" Throughput: %f Megapixels/sec\n", + (double)(w * h) / 1000000. / elapsed); + printf(" Output bit stream: %f Megabits/sec\n", + (double)totalJpegSize * 8. / 1000000. / elapsed); + } + } else { + if (quiet == 1) printf("N/A N/A "); + tj3Free(jpegBufs[0]); + jpegBufs[0] = NULL; + decompsrc = 1; + } + + if (w == tilew) ttilew = tw; + if (h == tileh) ttileh = th; + if (!(xformOpt & TJXOPT_NOOUTPUT)) { + if (decomp(decompsrc ? &srcBuf : jpegBufs, + decompsrc ? &srcSize : jpegSizes, NULL, tw, th, tsubsamp, 0, + fileName, ttilew, ttileh) == -1) + goto bailout; + } else if (quiet == 1) printf("N/A\n"); + + for (i = 0; i < ntilesw * ntilesh; i++) { + tj3Free(jpegBufs[i]); + jpegBufs[i] = NULL; + } + free(jpegBufs); jpegBufs = NULL; + free(jpegSizes); jpegSizes = NULL; + + if (tilew == w && tileh == h) break; + } + +bailout: + if (file) fclose(file); + if (jpegBufs) { + for (i = 0; i < ntilesw * ntilesh; i++) + tj3Free(jpegBufs[i]); + } + free(jpegBufs); + free(jpegSizes); + free(srcBuf); + free(t); + tj3Destroy(handle); + return retval; +} + + +static void usage(char *progName) +{ + int i; + + printf("USAGE: %s\n", progName); + printf(" [options]\n\n"); + printf(" %s\n", progName); + printf(" [options]\n"); + + printf("\nGENERAL OPTIONS\n"); + printf("---------------\n"); + printf("-alloc = Dynamically allocate JPEG buffers\n"); + printf("-benchtime T = Run each benchmark for at least T seconds [default = 5.0]\n"); + printf("-bmp = Use Windows Bitmap format for output images [default = PPM]\n"); + printf(" ** 8-bit data precision only **\n"); + printf("-bottomup = Use bottom-up row order for packed-pixel source/destination buffers\n"); + printf("-componly = Stop after running compression tests. Do not test decompression.\n"); + printf("-lossless = Generate lossless JPEG images when compressing (implies\n"); + printf(" -subsamp 444). PSV is the predictor selection value (1-7).\n"); + printf("-maxmemory = Memory limit (in megabytes) for intermediate buffers used with\n"); + printf(" progressive JPEG compression and decompression, optimized baseline entropy\n"); + printf(" coding, lossless JPEG compression, and lossless transformation\n"); + printf(" [default = no limit]\n"); + printf("-maxpixels = Input image size limit (in pixels) [default = no limit]\n"); + printf("-nowrite = Do not write reference or output images (improves consistency of\n"); + printf(" benchmark results)\n"); + printf("-rgb, -bgr, -rgbx, -bgrx, -xbgr, -xrgb =\n"); + printf(" Use the specified pixel format for packed-pixel source/destination buffers\n"); + printf(" [default = BGR]\n"); + printf("-cmyk = Indirectly test YCCK JPEG compression/decompression\n"); + printf(" (use the CMYK pixel format for packed-pixel source/destination buffers)\n"); + printf("-precision N = Use N-bit data precision when compressing [N is 8, 12, or 16;\n"); + printf(" default = 8; if N is 16, then -lossless must also be specified]\n"); + printf(" (-precision 12 implies -optimize unless -arithmetic is also specified)\n"); + printf("-quiet = Output results in tabular rather than verbose format\n"); + printf("-restart N = When compressing, add a restart marker every N MCU rows (lossy) or\n"); + printf(" N sample rows (lossless) [default = 0 (no restart markers)]. Append 'B'\n"); + printf(" to specify the restart marker interval in MCU blocks (lossy) or samples\n"); + printf(" (lossless).\n"); + printf("-stoponwarning = Immediately discontinue the current\n"); + printf(" compression/decompression/transform operation if a warning (non-fatal\n"); + printf(" error) occurs\n"); + printf("-tile = Compress/transform the input image into separate JPEG tiles of varying\n"); + printf(" sizes (useful for measuring JPEG overhead)\n"); + printf("-warmup T = Run each benchmark for T seconds [default = 1.0] prior to starting\n"); + printf(" the timer, in order to prime the caches and thus improve the consistency\n"); + printf(" of the benchmark results\n"); + + printf("\nLOSSY JPEG OPTIONS\n"); + printf("------------------\n"); + printf("-arithmetic = Use arithmetic entropy coding in JPEG images generated by\n"); + printf(" compression and transform operations (can be combined with -progressive)\n"); + printf("-crop WxH+X+Y = Decompress only the specified region of the JPEG image, where W\n"); + printf(" and H are the width and height of the region (0 = maximum possible width\n"); + printf(" or height) and X and Y are the left and upper boundary of the region, all\n"); + printf(" specified relative to the scaled image dimensions. X must be divible by\n"); + printf(" the scaled MCU width.\n"); + printf("-fastdct = Use the fastest DCT/IDCT algorithm available\n"); + printf("-fastupsample = Use the fastest chrominance upsampling algorithm available\n"); + printf("-optimize = Use optimized baseline entropy coding in JPEG images generated by\n"); + printf(" compession and transform operations\n"); + printf("-progressive = Use progressive entropy coding in JPEG images generated by\n"); + printf(" compression and transform operations (can be combined with -arithmetic;\n"); + printf(" implies -optimize unless -arithmetic is also specified)\n"); + printf("-limitscans = Refuse to decompress or transform progressive JPEG images that\n"); + printf(" have an unreasonably large number of scans\n"); + printf("-scale M/N = When decompressing, scale the width/height of the JPEG image by a\n"); + printf(" factor of M/N (M/N = "); + for (i = 0; i < nsf; i++) { + printf("%d/%d", scalingFactors[i].num, scalingFactors[i].denom); + if (nsf == 2 && i != nsf - 1) printf(" or "); + else if (nsf > 2) { + if (i != nsf - 1) printf(", "); + if (i == nsf - 2) printf("or "); + } + if (i % 8 == 0 && i != 0) printf("\n "); + } + printf(")\n"); + printf("-subsamp S = When compressing, use the specified level of chrominance\n"); + printf(" subsampling (S = 444, 422, 440, 420, 411, 441, or GRAY) [default = test\n"); + printf(" Grayscale, 4:2:0, 4:2:2, and 4:4:4 in sequence]\n"); + printf("-hflip, -vflip, -transpose, -transverse, -rot90, -rot180, -rot270 =\n"); + printf(" Perform the specified lossless transform operation on the input image\n"); + printf(" prior to decompression (these operations are mutually exclusive)\n"); + printf("-grayscale = Transform the input image into a grayscale JPEG image prior to\n"); + printf(" decompression (can be combined with the other transform operations above)\n"); + printf("-copynone = Do not copy any extra markers (including EXIF and ICC profile data)\n"); + printf(" when transforming the input image\n"); + printf("-yuv = Compress from/decompress to intermediate planar YUV images\n"); + printf(" ** 8-bit data precision only **\n"); + printf("-yuvpad N = The number of bytes by which each row in each plane of an\n"); + printf(" intermediate YUV image is evenly divisible (N must be a power of 2)\n"); + printf(" [default = 1]\n"); + + printf("\nNOTE: If the quality/PSV is specified as a range (e.g. 90-100 or 1-4), a\n"); + printf("separate test will be performed for all values in the range.\n\n"); + exit(1); +} + + +int main(int argc, char *argv[]) +{ + void *srcBuf = NULL; + int w = 0, h = 0, i, j, minQual = -1, maxQual = -1; + char *temp; + int minArg = 2, retval = 0, subsamp = -1; + tjhandle handle = NULL; + + if ((scalingFactors = tj3GetScalingFactors(&nsf)) == NULL || nsf == 0) + THROW("executing tj3GetScalingFactors()", tj3GetErrorStr(NULL)); + + if (argc < minArg) usage(argv[0]); + + temp = strrchr(argv[1], '.'); + if (temp != NULL) { + if (!strcasecmp(temp, ".bmp")) ext = "bmp"; + if (!strcasecmp(temp, ".jpg") || !strcasecmp(temp, ".jpeg")) + decompOnly = 1; + } + + printf("\n"); + + if (!decompOnly) { + minArg = 3; + if (argc < minArg) usage(argv[0]); + minQual = atoi(argv[2]); + if ((temp = strchr(argv[2], '-')) != NULL && strlen(temp) > 1 && + sscanf(&temp[1], "%d", &maxQual) == 1 && maxQual > minQual) {} + else maxQual = minQual; + } + + if (argc > minArg) { + for (i = minArg; i < argc; i++) { + if (!strcasecmp(argv[i], "-tile")) { + doTile = 1; xformOpt |= TJXOPT_CROP; + } else if (!strcasecmp(argv[i], "-precision") && i < argc - 1) { + int tempi = atoi(argv[++i]); + + if (tempi != 8 && tempi != 12 && tempi != 16) + usage(argv[0]); + precision = tempi; + } else if (!strcasecmp(argv[i], "-fastupsample")) { + printf("Using fastest upsampling algorithm\n\n"); + fastUpsample = 1; + } else if (!strcasecmp(argv[i], "-fastdct")) { + printf("Using fastest DCT/IDCT algorithm\n\n"); + fastDCT = 1; + } else if (!strcasecmp(argv[i], "-optimize")) { + printf("Using optimized baseline entropy coding\n\n"); + optimize = 1; + xformOpt |= TJXOPT_OPTIMIZE; + } else if (!strcasecmp(argv[i], "-progressive")) { + printf("Using progressive entropy coding\n\n"); + progressive = 1; + xformOpt |= TJXOPT_PROGRESSIVE; + } else if (!strcasecmp(argv[i], "-arithmetic")) { + printf("Using arithmetic entropy coding\n\n"); + arithmetic = 1; + xformOpt |= TJXOPT_ARITHMETIC; + } else if (!strcasecmp(argv[i], "-lossless")) { + lossless = 1; + subsamp = TJSAMP_444; + } else if (!strcasecmp(argv[i], "-rgb")) + pf = TJPF_RGB; + else if (!strcasecmp(argv[i], "-rgbx")) + pf = TJPF_RGBX; + else if (!strcasecmp(argv[i], "-bgr")) + pf = TJPF_BGR; + else if (!strcasecmp(argv[i], "-bgrx")) + pf = TJPF_BGRX; + else if (!strcasecmp(argv[i], "-xbgr")) + pf = TJPF_XBGR; + else if (!strcasecmp(argv[i], "-xrgb")) + pf = TJPF_XRGB; + else if (!strcasecmp(argv[i], "-cmyk")) + pf = TJPF_CMYK; + else if (!strcasecmp(argv[i], "-bottomup")) + bottomUp = 1; + else if (!strcasecmp(argv[i], "-quiet")) + quiet = 1; + else if (!strcasecmp(argv[i], "-qq")) + quiet = 2; + else if (!strcasecmp(argv[i], "-scale") && i < argc - 1) { + int temp1 = 0, temp2 = 0, match = 0; + + if (sscanf(argv[++i], "%d/%d", &temp1, &temp2) == 2) { + for (j = 0; j < nsf; j++) { + if (temp1 == scalingFactors[j].num && + temp2 == scalingFactors[j].denom) { + sf = scalingFactors[j]; + match = 1; break; + } + } + if (!match) usage(argv[0]); + } else usage(argv[0]); + } else if (!strcasecmp(argv[i], "-crop") && i < argc - 1) { + int temp1 = -1, temp2 = -1, temp3 = -1, temp4 = -1; + + if (sscanf(argv[++i], "%dx%d+%d+%d", &temp1, &temp2, &temp3, + &temp4) == 4 && temp1 >= 0 && temp2 >= 0 && temp3 >= 0 && + temp4 >= 0) { + cr.w = temp1; cr.h = temp2; cr.x = temp3; cr.y = temp4; + } else usage(argv[0]); + } else if (!strcasecmp(argv[i], "-hflip")) + xformOp = TJXOP_HFLIP; + else if (!strcasecmp(argv[i], "-vflip")) + xformOp = TJXOP_VFLIP; + else if (!strcasecmp(argv[i], "-transpose")) + xformOp = TJXOP_TRANSPOSE; + else if (!strcasecmp(argv[i], "-transverse")) + xformOp = TJXOP_TRANSVERSE; + else if (!strcasecmp(argv[i], "-rot90")) + xformOp = TJXOP_ROT90; + else if (!strcasecmp(argv[i], "-rot180")) + xformOp = TJXOP_ROT180; + else if (!strcasecmp(argv[i], "-rot270")) + xformOp = TJXOP_ROT270; + else if (!strcasecmp(argv[i], "-grayscale")) + xformOpt |= TJXOPT_GRAY; + else if (!strcasecmp(argv[i], "-custom")) + customFilter = dummyDCTFilter; + else if (!strcasecmp(argv[i], "-nooutput")) + xformOpt |= TJXOPT_NOOUTPUT; + else if (!strcasecmp(argv[i], "-copynone")) + xformOpt |= TJXOPT_COPYNONE; + else if (!strcasecmp(argv[i], "-benchtime") && i < argc - 1) { + double tempd = atof(argv[++i]); + + if (tempd > 0.0) benchTime = tempd; + else usage(argv[0]); + } else if (!strcasecmp(argv[i], "-warmup") && i < argc - 1) { + double tempd = atof(argv[++i]); + + if (tempd >= 0.0) warmup = tempd; + else usage(argv[0]); + printf("Warmup time = %.1f seconds\n\n", warmup); + } else if (!strcasecmp(argv[i], "-alloc")) + noRealloc = 0; + else if (!strcasecmp(argv[i], "-bmp")) + ext = "bmp"; + else if (!strcasecmp(argv[i], "-yuv")) { + printf("Testing planar YUV encoding/decoding\n\n"); + doYUV = 1; + } else if (!strcasecmp(argv[i], "-yuvpad") && i < argc - 1) { + int tempi = atoi(argv[++i]); + + if (tempi >= 1 && (tempi & (tempi - 1)) == 0) yuvAlign = tempi; + else usage(argv[0]); + } else if (!strcasecmp(argv[i], "-subsamp") && i < argc - 1) { + i++; + if (toupper(argv[i][0]) == 'G') subsamp = TJSAMP_GRAY; + else { + int tempi = atoi(argv[i]); + + switch (tempi) { + case 444: subsamp = TJSAMP_444; break; + case 422: subsamp = TJSAMP_422; break; + case 440: subsamp = TJSAMP_440; break; + case 420: subsamp = TJSAMP_420; break; + case 411: subsamp = TJSAMP_411; break; + case 441: subsamp = TJSAMP_441; break; + default: usage(argv[0]); + } + } + } else if (!strcasecmp(argv[i], "-componly")) + compOnly = 1; + else if (!strcasecmp(argv[i], "-nowrite")) + doWrite = 0; + else if (!strcasecmp(argv[i], "-limitscans")) + limitScans = 1; + else if (!strcasecmp(argv[i], "-maxmemory") && i < argc - 1) { + int tempi = atoi(argv[++i]); + + if (tempi < 0) usage(argv[0]); + maxMemory = tempi; + } else if (!strcasecmp(argv[i], "-maxpixels") && i < argc - 1) { + int tempi = atoi(argv[++i]); + + if (tempi < 0) usage(argv[0]); + maxPixels = tempi; + } else if (!strcasecmp(argv[i], "-restart") && i < argc - 1) { + int tempi = -1, nscan; char tempc = 0; + + if ((nscan = sscanf(argv[++i], "%d%c", &tempi, &tempc)) < 1 || + tempi < 0 || tempi > 65535 || + (nscan == 2 && tempc != 'B' && tempc != 'b')) + usage(argv[0]); + + if (tempc == 'B' || tempc == 'b') + restartIntervalBlocks = tempi; + else + restartIntervalRows = tempi; + } else if (!strcasecmp(argv[i], "-stoponwarning")) + stopOnWarning = 1; + else usage(argv[0]); + } + } + + if (precision == 16 && !lossless) { + printf("ERROR: -lossless must be specified along with -precision 16\n"); + retval = -1; goto bailout; + } + if (precision != 8 && doYUV) { + printf("ERROR: -yuv requires 8-bit data precision\n"); + retval = -1; goto bailout; + } + if (lossless && doYUV) { + printf("ERROR: -lossless and -yuv are incompatible\n"); + retval = -1; goto bailout; + } + sampleSize = (precision == 8 ? sizeof(unsigned char) : sizeof(short)); + + if ((sf.num != 1 || sf.denom != 1) && doTile) { + printf("Disabling tiled compression/decompression tests, because those tests do not\n"); + printf("work when scaled decompression is enabled.\n\n"); + doTile = 0; xformOpt &= (~TJXOPT_CROP); + } + + if (IS_CROPPED(cr)) { + if (!decompOnly) { + printf("ERROR: Partial image decompression can only be enabled for JPEG input images\n"); + retval = -1; goto bailout; + } + if (doTile) { + printf("Disabling tiled compression/decompression tests, because those tests do not\n"); + printf("work when partial image decompression is enabled.\n\n"); + doTile = 0; xformOpt &= (~TJXOPT_CROP); + } + if (doYUV) { + printf("ERROR: -crop and -yuv are incompatible\n"); + retval = -1; goto bailout; + } + } + + if (!noRealloc && doTile) { + printf("Disabling tiled compression/decompression tests, because those tests do not\n"); + printf("work when dynamic JPEG buffer allocation is enabled.\n\n"); + doTile = 0; xformOpt &= (~TJXOPT_CROP); + } + + if (!decompOnly) { + if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL) + THROW_TJG(); + if (tj3Set(handle, TJPARAM_STOPONWARNING, stopOnWarning) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_BOTTOMUP, bottomUp) == -1) + THROW_TJ(); + if (tj3Set(handle, TJPARAM_MAXPIXELS, maxPixels) == -1) + THROW_TJ(); + + if (precision == 8) { + if ((srcBuf = tj3LoadImage8(handle, argv[1], &w, 1, &h, &pf)) == NULL) + THROW_TJ(); + } else if (precision == 12) { + if ((srcBuf = tj3LoadImage12(handle, argv[1], &w, 1, &h, &pf)) == NULL) + THROW_TJ(); + } else { + if ((srcBuf = tj3LoadImage16(handle, argv[1], &w, 1, &h, &pf)) == NULL) + THROW_TJ(); + } + temp = strrchr(argv[1], '.'); + if (temp != NULL) *temp = '\0'; + } + + if (quiet == 1 && !decompOnly) { + printf("All performance values in Mpixels/sec\n\n"); + printf("Pixel JPEG JPEG %s %s ", + doTile ? "Tile " : "Image", doTile ? "Tile " : "Image"); + if (doYUV) printf("Encode "); + printf("Comp Comp Decomp "); + if (doYUV) printf("Decode"); + printf("\n"); + printf("Format Format %s Width Height ", + lossless ? "PSV " : "Qual"); + if (doYUV) printf("Perf "); + printf("Perf Ratio Perf "); + if (doYUV) printf("Perf"); + printf("\n\n"); + } + + if (decompOnly) { + decompTest(argv[1]); + printf("\n"); + goto bailout; + } + if (lossless) { + if (minQual < 1 || minQual > 7 || maxQual < 1 || maxQual > 7) { + puts("ERROR: PSV must be between 1 and 7."); + exit(1); + } + } else { + if (minQual < 1 || minQual > 100 || maxQual < 1 || maxQual > 100) { + puts("ERROR: Quality must be between 1 and 100."); + exit(1); + } + } + if (subsamp >= 0 && subsamp < TJ_NUMSAMP) { + for (i = maxQual; i >= minQual; i--) + fullTest(handle, srcBuf, w, h, subsamp, i, argv[1]); + printf("\n"); + } else { + if (pf != TJPF_CMYK) { + for (i = maxQual; i >= minQual; i--) + fullTest(handle, srcBuf, w, h, TJSAMP_GRAY, i, argv[1]); + printf("\n"); + } + for (i = maxQual; i >= minQual; i--) + fullTest(handle, srcBuf, w, h, TJSAMP_420, i, argv[1]); + printf("\n"); + for (i = maxQual; i >= minQual; i--) + fullTest(handle, srcBuf, w, h, TJSAMP_422, i, argv[1]); + printf("\n"); + for (i = maxQual; i >= minQual; i--) + fullTest(handle, srcBuf, w, h, TJSAMP_444, i, argv[1]); + printf("\n"); + } + +bailout: + tj3Destroy(handle); + tj3Free(srcBuf); + return retval; +} diff --git a/3rdparty/libjpeg-turbo/src/tjutil.c b/3rdparty/libjpeg-turbo/src/tjutil.c new file mode 100644 index 000000000000..2018160b161f --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/tjutil.c @@ -0,0 +1,70 @@ +/* + * Copyright (C)2011, 2019 D. R. Commander. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef _WIN32 + +#include +#include "tjutil.h" + +static double getFreq(void) +{ + LARGE_INTEGER freq; + + if (!QueryPerformanceFrequency(&freq)) return 0.0; + return (double)freq.QuadPart; +} + +static double f = -1.0; + +double getTime(void) +{ + LARGE_INTEGER t; + + if (f < 0.0) f = getFreq(); + if (f == 0.0) return (double)GetTickCount() / 1000.; + else { + QueryPerformanceCounter(&t); + return (double)t.QuadPart / f; + } +} + +#else + +#include +#include +#include "tjutil.h" + +double getTime(void) +{ + struct timeval tv; + + if (gettimeofday(&tv, NULL) < 0) return 0.0; + else return (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.); +} + +#endif diff --git a/3rdparty/libjpeg-turbo/src/tjutil.h b/3rdparty/libjpeg-turbo/src/tjutil.h new file mode 100644 index 000000000000..10272e98867e --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/tjutil.h @@ -0,0 +1,53 @@ +/* + * Copyright (C)2011, 2022 D. R. Commander. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef _WIN32 +#ifndef strcasecmp +#define strcasecmp stricmp +#endif +#ifndef strncasecmp +#define strncasecmp strnicmp +#endif +#endif + +#ifdef _MSC_VER +#define SNPRINTF(str, n, format, ...) \ + _snprintf_s(str, n, _TRUNCATE, format, ##__VA_ARGS__) +#else +#define SNPRINTF snprintf +#endif + +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +extern double getTime(void); diff --git a/3rdparty/libjpeg-turbo/src/transupp.c b/3rdparty/libjpeg-turbo/src/transupp.c new file mode 100644 index 000000000000..62587d3865f8 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/transupp.c @@ -0,0 +1,2377 @@ +/* + * transupp.c + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1997-2019, Thomas G. Lane, Guido Vollbeding. + * libjpeg-turbo Modifications: + * Copyright (C) 2010, 2017, 2021-2022, 2024, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains image transformation routines and other utility code + * used by the jpegtran sample application. These are NOT part of the core + * JPEG library. But we keep these routines separate from jpegtran.c to + * ease the task of maintaining jpegtran-like programs that have other user + * interfaces. + */ + +/* Although this file really shouldn't have access to the library internals, + * it's helpful to let it call jround_up() and jcopy_block_row(). + */ +#define JPEG_INTERNALS + +#include "jinclude.h" +#include "jpeglib.h" +#include "transupp.h" /* My own external interface */ +#include "jpegapicomp.h" +#include /* to declare isdigit() */ + + +#if JPEG_LIB_VERSION >= 70 +#define dstinfo_min_DCT_h_scaled_size dstinfo->min_DCT_h_scaled_size +#define dstinfo_min_DCT_v_scaled_size dstinfo->min_DCT_v_scaled_size +#else +#define dstinfo_min_DCT_h_scaled_size DCTSIZE +#define dstinfo_min_DCT_v_scaled_size DCTSIZE +#endif + + +#if TRANSFORMS_SUPPORTED + +/* + * Lossless image transformation routines. These routines work on DCT + * coefficient arrays and thus do not require any lossy decompression + * or recompression of the image. + * Thanks to Guido Vollbeding for the initial design and code of this feature, + * and to Ben Jackson for introducing the cropping feature. + * + * Horizontal flipping is done in-place, using a single top-to-bottom + * pass through the virtual source array. It will thus be much the + * fastest option for images larger than main memory. + * + * The other routines require a set of destination virtual arrays, so they + * need twice as much memory as jpegtran normally does. The destination + * arrays are always written in normal scan order (top to bottom) because + * the virtual array manager expects this. The source arrays will be scanned + * in the corresponding order, which means multiple passes through the source + * arrays for most of the transforms. That could result in much thrashing + * if the image is larger than main memory. + * + * If cropping or trimming is involved, the destination arrays may be smaller + * than the source arrays. Note it is not possible to do horizontal flip + * in-place when a nonzero Y crop offset is specified, since we'd have to move + * data from one block row to another but the virtual array manager doesn't + * guarantee we can touch more than one row at a time. So in that case, + * we have to use a separate destination array. + * + * Some notes about the operating environment of the individual transform + * routines: + * 1. Both the source and destination virtual arrays are allocated from the + * source JPEG object, and therefore should be manipulated by calling the + * source's memory manager. + * 2. The destination's component count should be used. It may be smaller + * than the source's when forcing to grayscale. + * 3. Likewise the destination's sampling factors should be used. When + * forcing to grayscale the destination's sampling factors will be all 1, + * and we may as well take that as the effective iMCU size. + * 4. When "trim" is in effect, the destination's dimensions will be the + * trimmed values but the source's will be untrimmed. + * 5. When "crop" is in effect, the destination's dimensions will be the + * cropped values but the source's will be uncropped. Each transform + * routine is responsible for picking up source data starting at the + * correct X and Y offset for the crop region. (The X and Y offsets + * passed to the transform routines are measured in iMCU blocks of the + * destination.) + * 6. All the routines assume that the source and destination buffers are + * padded out to a full iMCU boundary. This is true, although for the + * source buffer it is an undocumented property of jdcoefct.c. + */ + + +LOCAL(void) +dequant_comp(j_decompress_ptr cinfo, jpeg_component_info *compptr, + jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1) +{ + JDIMENSION blk_x, blk_y; + int offset_y, k; + JQUANT_TBL *qtblptr; + JBLOCKARRAY buffer; + JBLOCKROW block; + JCOEFPTR ptr; + + qtblptr = compptr->quant_table; + for (blk_y = 0; blk_y < compptr->height_in_blocks; + blk_y += compptr->v_samp_factor) { + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr)cinfo, coef_array, blk_y, + (JDIMENSION)compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + block = buffer[offset_y]; + for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { + ptr = block[blk_x]; + for (k = 0; k < DCTSIZE2; k++) + if (qtblptr->quantval[k] != qtblptr1->quantval[k]) + ptr[k] *= qtblptr->quantval[k] / qtblptr1->quantval[k]; + } + } + } +} + + +LOCAL(void) +requant_comp(j_decompress_ptr cinfo, jpeg_component_info *compptr, + jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1) +{ + JDIMENSION blk_x, blk_y; + int offset_y, k; + JQUANT_TBL *qtblptr; + JBLOCKARRAY buffer; + JBLOCKROW block; + JCOEFPTR ptr; + JCOEF temp, qval; + + qtblptr = compptr->quant_table; + for (blk_y = 0; blk_y < compptr->height_in_blocks; + blk_y += compptr->v_samp_factor) { + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr)cinfo, coef_array, blk_y, + (JDIMENSION)compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + block = buffer[offset_y]; + for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { + ptr = block[blk_x]; + for (k = 0; k < DCTSIZE2; k++) { + temp = qtblptr->quantval[k]; + qval = qtblptr1->quantval[k]; + if (temp != qval && qval != 0) { + temp *= ptr[k]; + /* The following quantization code is copied from jcdctmgr.c */ +#ifdef FAST_DIVIDE +#define DIVIDE_BY(a, b) a /= b +#else +#define DIVIDE_BY(a, b) if (a >= b) a /= b; else a = 0 +#endif + if (temp < 0) { + temp = -temp; + temp += qval >> 1; /* for rounding */ + DIVIDE_BY(temp, qval); + temp = -temp; + } else { + temp += qval >> 1; /* for rounding */ + DIVIDE_BY(temp, qval); + } + ptr[k] = temp; + } + } + } + } + } +} + + +/* + * Calculate largest common denominator using Euclid's algorithm. + */ +LOCAL(JCOEF) +largest_common_denominator(JCOEF a, JCOEF b) +{ + JCOEF c; + + do { + c = a % b; + a = b; + b = c; + } while (c); + + return a; +} + + +LOCAL(void) +adjust_quant(j_decompress_ptr srcinfo, jvirt_barray_ptr *src_coef_arrays, + j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays, + boolean trim, j_compress_ptr dstinfo) +{ + jpeg_component_info *compptr1, *compptr2; + JQUANT_TBL *qtblptr1, *qtblptr2, *qtblptr3; + int ci, k; + + for (ci = 0; ci < dstinfo->num_components && ci < dropinfo->num_components; + ci++) { + compptr1 = srcinfo->comp_info + ci; + compptr2 = dropinfo->comp_info + ci; + qtblptr1 = compptr1->quant_table; + if (qtblptr1 == NULL) + ERREXIT1(srcinfo, JERR_NO_QUANT_TABLE, compptr1->quant_tbl_no); + qtblptr2 = compptr2->quant_table; + if (qtblptr2 == NULL) + ERREXIT1(dropinfo, JERR_NO_QUANT_TABLE, compptr2->quant_tbl_no); + for (k = 0; k < DCTSIZE2; k++) { + if (qtblptr1->quantval[k] != qtblptr2->quantval[k]) { + if (trim) + requant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr1); + else { + qtblptr3 = dstinfo->quant_tbl_ptrs[compptr1->quant_tbl_no]; + for (k = 0; k < DCTSIZE2; k++) + if (qtblptr1->quantval[k] != qtblptr2->quantval[k]) + qtblptr3->quantval[k] = + largest_common_denominator(qtblptr1->quantval[k], + qtblptr2->quantval[k]); + dequant_comp(srcinfo, compptr1, src_coef_arrays[ci], qtblptr3); + dequant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr3); + } + break; + } + } + } +} + + +LOCAL(void) +do_drop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays, + JDIMENSION drop_width, JDIMENSION drop_height) +/* Drop (insert) the contents of another image into the source image. If the + * number of components in the drop image is smaller than the number of + * components in the destination image, then we fill in the remaining + * components with zero. This allows for dropping the contents of grayscale + * images into (arbitrarily sampled) color images. + */ +{ + JDIMENSION comp_width, comp_height; + JDIMENSION blk_y, x_drop_blocks, y_drop_blocks; + int ci, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + jpeg_component_info *compptr; + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = drop_width * compptr->h_samp_factor; + comp_height = drop_height * compptr->v_samp_factor; + x_drop_blocks = x_crop_offset * compptr->h_samp_factor; + y_drop_blocks = y_crop_offset * compptr->v_samp_factor; + for (blk_y = 0; blk_y < comp_height; blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], blk_y + y_drop_blocks, + (JDIMENSION)compptr->v_samp_factor, TRUE); + if (ci < dropinfo->num_components) { + src_buffer = (*dropinfo->mem->access_virt_barray) + ((j_common_ptr)dropinfo, drop_coef_arrays[ci], blk_y, + (JDIMENSION)compptr->v_samp_factor, FALSE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + jcopy_block_row(src_buffer[offset_y], + dst_buffer[offset_y] + x_drop_blocks, comp_width); + } + } else { + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + memset(dst_buffer[offset_y] + x_drop_blocks, 0, + comp_width * sizeof(JBLOCK)); + } + } + } + } +} + + +LOCAL(void) +do_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Crop. This is only used when no rotate/flip is requested with the crop. */ +{ + JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; + int ci, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + jpeg_component_info *compptr; + + /* We simply have to copy the right amount of data (the destination's + * image size) starting at the given X and Y offsets in the source. + */ + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION)compptr->v_samp_factor, TRUE); + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], dst_blk_y + y_crop_blocks, + (JDIMENSION)compptr->v_samp_factor, FALSE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, + dst_buffer[offset_y], compptr->width_in_blocks); + } + } + } +} + + +LOCAL(void) +do_crop_ext_zero(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Crop. This is only used when no rotate/flip is requested with the crop. + * Extension: If the destination size is larger than the source, we fill in the + * expanded region with zero (neutral gray). Note that we also have to zero + * partial iMCUs at the right and bottom edge of the source image area in this + * case. + */ +{ + JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height; + JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; + int ci, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + jpeg_component_info *compptr; + + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size); + MCU_rows = srcinfo->output_height / + (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + comp_height = MCU_rows * compptr->v_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION)compptr->v_samp_factor, TRUE); + if (dstinfo->_jpeg_height > srcinfo->output_height) { + if (dst_blk_y < y_crop_blocks || + dst_blk_y >= y_crop_blocks + comp_height) { + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + memset(dst_buffer[offset_y], 0, + compptr->width_in_blocks * sizeof(JBLOCK)); + } + continue; + } + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor, + FALSE); + } else { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor, + FALSE); + } + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + if (dstinfo->_jpeg_width > srcinfo->output_width) { + if (x_crop_blocks > 0) { + memset(dst_buffer[offset_y], 0, x_crop_blocks * sizeof(JBLOCK)); + } + jcopy_block_row(src_buffer[offset_y], + dst_buffer[offset_y] + x_crop_blocks, comp_width); + if (compptr->width_in_blocks > x_crop_blocks + comp_width) { + memset(dst_buffer[offset_y] + x_crop_blocks + comp_width, 0, + (compptr->width_in_blocks - x_crop_blocks - comp_width) * + sizeof(JBLOCK)); + } + } else { + jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, + dst_buffer[offset_y], compptr->width_in_blocks); + } + } + } + } +} + + +LOCAL(void) +do_crop_ext_flat(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Crop. This is only used when no rotate/flip is requested with the crop. + * Extension: The destination width is larger than the source, and we fill in + * the expanded region with the DC coefficient of the adjacent block. Note + * that we also have to fill partial iMCUs at the right and bottom edge of the + * source image area in this case. + */ +{ + JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height; + JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks; + int ci, offset_y; + JCOEF dc; + JBLOCKARRAY src_buffer, dst_buffer; + jpeg_component_info *compptr; + + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size); + MCU_rows = srcinfo->output_height / + (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + comp_height = MCU_rows * compptr->v_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION)compptr->v_samp_factor, TRUE); + if (dstinfo->_jpeg_height > srcinfo->output_height) { + if (dst_blk_y < y_crop_blocks || + dst_blk_y >= y_crop_blocks + comp_height) { + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + memset(dst_buffer[offset_y], 0, + compptr->width_in_blocks * sizeof(JBLOCK)); + } + continue; + } + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor, + FALSE); + } else { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor, + FALSE); + } + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + if (x_crop_blocks > 0) { + memset(dst_buffer[offset_y], 0, x_crop_blocks * sizeof(JBLOCK)); + dc = src_buffer[offset_y][0][0]; + for (dst_blk_x = 0; dst_blk_x < x_crop_blocks; dst_blk_x++) { + dst_buffer[offset_y][dst_blk_x][0] = dc; + } + } + jcopy_block_row(src_buffer[offset_y], + dst_buffer[offset_y] + x_crop_blocks, comp_width); + if (compptr->width_in_blocks > x_crop_blocks + comp_width) { + memset(dst_buffer[offset_y] + x_crop_blocks + comp_width, 0, + (compptr->width_in_blocks - x_crop_blocks - comp_width) * + sizeof(JBLOCK)); + dc = src_buffer[offset_y][comp_width - 1][0]; + for (dst_blk_x = x_crop_blocks + comp_width; + dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { + dst_buffer[offset_y][dst_blk_x][0] = dc; + } + } + } + } + } +} + + +LOCAL(void) +do_crop_ext_reflect(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Crop. This is only used when no rotate/flip is requested with the crop. + * Extension: The destination width is larger than the source, and we fill in + * the expanded region with repeated reflections of the source image. Note + * that we also have to fill partial iMCUs at the right and bottom edge of the + * source image area in this case. + */ +{ + JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, src_blk_x; + JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks; + int ci, k, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JBLOCKROW src_row_ptr, dst_row_ptr; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size); + MCU_rows = srcinfo->output_height / + (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + comp_height = MCU_rows * compptr->v_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION)compptr->v_samp_factor, TRUE); + if (dstinfo->_jpeg_height > srcinfo->output_height) { + if (dst_blk_y < y_crop_blocks || + dst_blk_y >= y_crop_blocks + comp_height) { + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + memset(dst_buffer[offset_y], 0, + compptr->width_in_blocks * sizeof(JBLOCK)); + } + continue; + } + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor, + FALSE); + } else { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor, + FALSE); + } + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + /* Copy source region */ + jcopy_block_row(src_buffer[offset_y], + dst_buffer[offset_y] + x_crop_blocks, comp_width); + if (x_crop_blocks > 0) { + /* Reflect to left */ + dst_row_ptr = dst_buffer[offset_y] + x_crop_blocks; + for (dst_blk_x = x_crop_blocks; dst_blk_x > 0;) { + src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */ + for (src_blk_x = comp_width; src_blk_x > 0 && dst_blk_x > 0; + src_blk_x--, dst_blk_x--) { + dst_ptr = *(--dst_row_ptr); /* destination goes left */ + src_ptr = *src_row_ptr++; /* source goes right */ + /* This unrolled loop doesn't need to know which row it's on. */ + for (k = 0; k < DCTSIZE2; k += 2) { + *dst_ptr++ = *src_ptr++; /* copy even column */ + *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign + change */ + } + } + } + } + if (compptr->width_in_blocks > x_crop_blocks + comp_width) { + /* Reflect to right */ + dst_row_ptr = dst_buffer[offset_y] + x_crop_blocks + comp_width; + for (dst_blk_x = compptr->width_in_blocks - x_crop_blocks - comp_width; + dst_blk_x > 0;) { + src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */ + for (src_blk_x = comp_width; src_blk_x > 0 && dst_blk_x > 0; + src_blk_x--, dst_blk_x--) { + dst_ptr = *dst_row_ptr++; /* destination goes right */ + src_ptr = *(--src_row_ptr); /* source goes left */ + /* This unrolled loop doesn't need to know which row it's on. */ + for (k = 0; k < DCTSIZE2; k += 2) { + *dst_ptr++ = *src_ptr++; /* copy even column */ + *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign + change */ + } + } + } + } + } + } + } +} + + +LOCAL(void) +do_wipe(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + JDIMENSION drop_width, JDIMENSION drop_height) +/* Wipe - discard image contents of specified region and fill with zero + * (neutral gray) + */ +{ + JDIMENSION x_wipe_blocks, wipe_width; + JDIMENSION y_wipe_blocks, wipe_bottom; + int ci, offset_y; + JBLOCKARRAY buffer; + jpeg_component_info *compptr; + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + x_wipe_blocks = x_crop_offset * compptr->h_samp_factor; + wipe_width = drop_width * compptr->h_samp_factor; + y_wipe_blocks = y_crop_offset * compptr->v_samp_factor; + wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks; + for (; y_wipe_blocks < wipe_bottom; + y_wipe_blocks += compptr->v_samp_factor) { + buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks, + (JDIMENSION)compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + memset(buffer[offset_y] + x_wipe_blocks, 0, + wipe_width * sizeof(JBLOCK)); + } + } + } +} + + +LOCAL(void) +do_flatten(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + JDIMENSION drop_width, JDIMENSION drop_height) +/* Flatten - discard image contents of specified region, similarly to wipe, + * but fill with the average of adjacent blocks instead of zero. + */ +{ + JDIMENSION x_wipe_blocks, wipe_width, wipe_right; + JDIMENSION y_wipe_blocks, wipe_bottom, blk_x; + int ci, offset_y, dc_left_value, dc_right_value, average; + JBLOCKARRAY buffer; + jpeg_component_info *compptr; + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + x_wipe_blocks = x_crop_offset * compptr->h_samp_factor; + wipe_width = drop_width * compptr->h_samp_factor; + wipe_right = wipe_width + x_wipe_blocks; + y_wipe_blocks = y_crop_offset * compptr->v_samp_factor; + wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks; + for (; y_wipe_blocks < wipe_bottom; + y_wipe_blocks += compptr->v_samp_factor) { + buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks, + (JDIMENSION)compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + memset(buffer[offset_y] + x_wipe_blocks, 0, + wipe_width * sizeof(JBLOCK)); + if (x_wipe_blocks > 0) { + dc_left_value = buffer[offset_y][x_wipe_blocks - 1][0]; + if (wipe_right < compptr->width_in_blocks) { + dc_right_value = buffer[offset_y][wipe_right][0]; + average = (dc_left_value + dc_right_value) >> 1; + } else { + average = dc_left_value; + } + } else if (wipe_right < compptr->width_in_blocks) { + average = buffer[offset_y][wipe_right][0]; + } else continue; + for (blk_x = x_wipe_blocks; blk_x < wipe_right; blk_x++) { + buffer[offset_y][blk_x][0] = (JCOEF)average; + } + } + } + } +} + + +LOCAL(void) +do_reflect(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays, + JDIMENSION drop_width, JDIMENSION drop_height) +/* Reflect - discard image contents of specified region, similarly to wipe, + * but fill with repeated reflections of the outside region instead of zero. + * NB: y_crop_offset is assumed to be zero. + */ +{ + JDIMENSION x_wipe_blocks, wipe_width; + JDIMENSION y_wipe_blocks, wipe_bottom; + JDIMENSION src_blk_x, dst_blk_x; + int ci, k, offset_y; + JBLOCKARRAY buffer; + JBLOCKROW src_row_ptr, dst_row_ptr; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + x_wipe_blocks = x_crop_offset * compptr->h_samp_factor; + wipe_width = drop_width * compptr->h_samp_factor; + wipe_bottom = drop_height * compptr->v_samp_factor; + for (y_wipe_blocks = 0; y_wipe_blocks < wipe_bottom; + y_wipe_blocks += compptr->v_samp_factor) { + buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks, + (JDIMENSION)compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + if (x_wipe_blocks > 0) { + /* Reflect from left */ + dst_row_ptr = buffer[offset_y] + x_wipe_blocks; + for (dst_blk_x = wipe_width; dst_blk_x > 0;) { + src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */ + for (src_blk_x = x_wipe_blocks; + src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) { + dst_ptr = *dst_row_ptr++; /* destination goes right */ + src_ptr = *(--src_row_ptr); /* source goes left */ + /* this unrolled loop doesn't need to know which row it's on... */ + for (k = 0; k < DCTSIZE2; k += 2) { + *dst_ptr++ = *src_ptr++; /* copy even column */ + *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign change */ + } + } + } + } else if (compptr->width_in_blocks > x_wipe_blocks + wipe_width) { + /* Reflect from right */ + dst_row_ptr = buffer[offset_y] + x_wipe_blocks + wipe_width; + for (dst_blk_x = wipe_width; dst_blk_x > 0;) { + src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */ + src_blk_x = compptr->width_in_blocks - x_wipe_blocks - wipe_width; + for (; src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) { + dst_ptr = *(--dst_row_ptr); /* destination goes left */ + src_ptr = *src_row_ptr++; /* source goes right */ + /* this unrolled loop doesn't need to know which row it's on... */ + for (k = 0; k < DCTSIZE2; k += 2) { + *dst_ptr++ = *src_ptr++; /* copy even column */ + *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign change */ + } + } + } + } else { + memset(buffer[offset_y] + x_wipe_blocks, 0, + wipe_width * sizeof(JBLOCK)); + } + } + } + } +} + + +LOCAL(void) +do_flip_h_no_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays) +/* Horizontal flip; done in-place, so no separate dest array is required. + * NB: this only works when y_crop_offset is zero. + */ +{ + JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks; + int ci, k, offset_y; + JBLOCKARRAY buffer; + JCOEFPTR ptr1, ptr2; + JCOEF temp1, temp2; + jpeg_component_info *compptr; + + /* Horizontal mirroring of DCT blocks is accomplished by swapping + * pairs of blocks in-place. Within a DCT block, we perform horizontal + * mirroring by changing the signs of odd-numbered columns. + * Partial iMCUs at the right edge are left untouched. + */ + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + for (blk_y = 0; blk_y < compptr->height_in_blocks; + blk_y += compptr->v_samp_factor) { + buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], blk_y, + (JDIMENSION)compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + /* Do the mirroring */ + for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) { + ptr1 = buffer[offset_y][blk_x]; + ptr2 = buffer[offset_y][comp_width - blk_x - 1]; + /* this unrolled loop doesn't need to know which row it's on... */ + for (k = 0; k < DCTSIZE2; k += 2) { + temp1 = *ptr1; /* swap even column */ + temp2 = *ptr2; + *ptr1++ = temp2; + *ptr2++ = temp1; + temp1 = *ptr1; /* swap odd column with sign change */ + temp2 = *ptr2; + *ptr1++ = -temp2; + *ptr2++ = -temp1; + } + } + if (x_crop_blocks > 0) { + /* Now left-justify the portion of the data to be kept. + * We can't use a single jcopy_block_row() call because that routine + * depends on memcpy(), whose behavior is unspecified for overlapping + * source and destination areas. Sigh. + */ + for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { + jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks, + buffer[offset_y] + blk_x, (JDIMENSION)1); + } + } + } + } + } +} + + +LOCAL(void) +do_flip_h(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Horizontal flip in general cropping case */ +{ + JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; + int ci, k, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JBLOCKROW src_row_ptr, dst_row_ptr; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Here we must output into a separate array because we can't touch + * different rows of a single virtual array simultaneously. Otherwise, + * this is essentially the same as the routine above. + */ + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION)compptr->v_samp_factor, TRUE); + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], dst_blk_y + y_crop_blocks, + (JDIMENSION)compptr->v_samp_factor, FALSE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + dst_row_ptr = dst_buffer[offset_y]; + src_row_ptr = src_buffer[offset_y]; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x++) { + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Do the mirrorable blocks */ + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; + /* this unrolled loop doesn't need to know which row it's on... */ + for (k = 0; k < DCTSIZE2; k += 2) { + *dst_ptr++ = *src_ptr++; /* copy even column */ + *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign + change */ + } + } else { + /* Copy last partial block(s) verbatim */ + jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, + dst_row_ptr + dst_blk_x, (JDIMENSION)1); + } + } + } + } + } +} + + +LOCAL(void) +do_flip_v(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Vertical flip */ +{ + JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; + int ci, i, j, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JBLOCKROW src_row_ptr, dst_row_ptr; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* We output into a separate array because we can't touch different + * rows of the source virtual array simultaneously. Otherwise, this + * is a pretty straightforward analog of horizontal flip. + * Within a DCT block, vertical mirroring is done by changing the signs + * of odd-numbered rows. + * Partial iMCUs at the bottom edge are copied verbatim. + */ + MCU_rows = srcinfo->output_height / + (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_height = MCU_rows * compptr->v_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION)compptr->v_samp_factor, TRUE); + if (y_crop_blocks + dst_blk_y < comp_height) { + /* Row is within the mirrorable area. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + comp_height - y_crop_blocks - dst_blk_y - + (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, FALSE); + } else { + /* Bottom-edge blocks will be copied verbatim. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, + (JDIMENSION)compptr->v_samp_factor, FALSE); + } + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + if (y_crop_blocks + dst_blk_y < comp_height) { + /* Row is within the mirrorable area. */ + dst_row_ptr = dst_buffer[offset_y]; + src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; + src_row_ptr += x_crop_blocks; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[dst_blk_x]; + for (i = 0; i < DCTSIZE; i += 2) { + /* copy even row */ + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = *src_ptr++; + /* copy odd row with sign change */ + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = -(*src_ptr++); + } + } + } else { + /* Just copy row verbatim. */ + jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, + dst_buffer[offset_y], compptr->width_in_blocks); + } + } + } + } +} + + +LOCAL(void) +do_transpose(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Transpose source into destination */ +{ + JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Transposing pixels within a block just requires transposing the + * DCT coefficients. + * Partial iMCUs at the edges require no special treatment; we simply + * process all the available DCT blocks for every component. + */ + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION)compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + dst_blk_x + x_crop_blocks, + (JDIMENSION)compptr->h_samp_factor, FALSE); + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + src_ptr = + src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j]; + } + } + } + } + } +} + + +LOCAL(void) +do_rot_90(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* 90 degree rotation is equivalent to + * 1. Transposing the image; + * 2. Horizontal mirroring. + * These two steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Because of the horizontal mirror step, we can't process partial iMCUs + * at the (output) right edge properly. They just get transposed and + * not mirrored. + */ + MCU_cols = srcinfo->output_height / + (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION)compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Block is within the mirrorable area. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + comp_width - x_crop_blocks - dst_blk_x - + (JDIMENSION)compptr->h_samp_factor, + (JDIMENSION)compptr->h_samp_factor, FALSE); + } else { + /* Edge blocks are transposed but not mirrored. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + dst_blk_x + x_crop_blocks, + (JDIMENSION)compptr->h_samp_factor, FALSE); + } + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Block is within the mirrorable area. */ + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] + [dst_blk_y + offset_y + y_crop_blocks]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j]; + i++; + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j]; + } + } else { + /* Edge blocks are transposed but not mirrored. */ + src_ptr = src_buffer[offset_x] + [dst_blk_y + offset_y + y_crop_blocks]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j]; + } + } + } + } + } + } +} + + +LOCAL(void) +do_rot_270(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* 270 degree rotation is equivalent to + * 1. Horizontal mirroring; + * 2. Transposing the image. + * These two steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Because of the horizontal mirror step, we can't process partial iMCUs + * at the (output) bottom edge properly. They just get transposed and + * not mirrored. + */ + MCU_rows = srcinfo->output_width / + (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_height = MCU_rows * compptr->v_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION)compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + dst_blk_x + x_crop_blocks, + (JDIMENSION)compptr->h_samp_factor, FALSE); + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + if (y_crop_blocks + dst_blk_y < comp_height) { + /* Block is within the mirrorable area. */ + src_ptr = src_buffer[offset_x] + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j]; + j++; + dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j]; + } + } + } else { + /* Edge blocks are transposed but not mirrored. */ + src_ptr = src_buffer[offset_x] + [dst_blk_y + offset_y + y_crop_blocks]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j]; + } + } + } + } + } + } +} + + +LOCAL(void) +do_rot_180(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* 180 degree rotation is equivalent to + * 1. Vertical mirroring; + * 2. Horizontal mirroring. + * These two steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; + int ci, i, j, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JBLOCKROW src_row_ptr, dst_row_ptr; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size); + MCU_rows = srcinfo->output_height / + (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + comp_height = MCU_rows * compptr->v_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION)compptr->v_samp_factor, TRUE); + if (y_crop_blocks + dst_blk_y < comp_height) { + /* Row is within the vertically mirrorable area. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + comp_height - y_crop_blocks - dst_blk_y - + (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, FALSE); + } else { + /* Bottom-edge rows are only mirrored horizontally. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, + (JDIMENSION)compptr->v_samp_factor, FALSE); + } + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + dst_row_ptr = dst_buffer[offset_y]; + if (y_crop_blocks + dst_blk_y < comp_height) { + /* Row is within the mirrorable area. */ + src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Process the blocks that can be mirrored both ways. */ + src_ptr = + src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; + for (i = 0; i < DCTSIZE; i += 2) { + /* For even row, negate every odd column. */ + for (j = 0; j < DCTSIZE; j += 2) { + *dst_ptr++ = *src_ptr++; + *dst_ptr++ = -(*src_ptr++); + } + /* For odd row, negate every even column. */ + for (j = 0; j < DCTSIZE; j += 2) { + *dst_ptr++ = -(*src_ptr++); + *dst_ptr++ = *src_ptr++; + } + } + } else { + /* Any remaining right-edge blocks are only mirrored vertically. */ + src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x]; + for (i = 0; i < DCTSIZE; i += 2) { + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = *src_ptr++; + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = -(*src_ptr++); + } + } + } + } else { + /* Remaining rows are just mirrored horizontally. */ + src_row_ptr = src_buffer[offset_y]; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x++) { + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Process the blocks that can be mirrored. */ + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = + src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; + for (i = 0; i < DCTSIZE2; i += 2) { + *dst_ptr++ = *src_ptr++; + *dst_ptr++ = -(*src_ptr++); + } + } else { + /* Any remaining right-edge blocks are only copied. */ + jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, + dst_row_ptr + dst_blk_x, (JDIMENSION)1); + } + } + } + } + } + } +} + + +LOCAL(void) +do_transverse(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Transverse transpose is equivalent to + * 1. 180 degree rotation; + * 2. Transposition; + * or + * 1. Horizontal mirroring; + * 2. Transposition; + * 3. Horizontal mirroring. + * These steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + MCU_cols = srcinfo->output_height / + (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size); + MCU_rows = srcinfo->output_width / + (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + comp_height = MCU_rows * compptr->v_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION)compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Block is within the mirrorable area. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + comp_width - x_crop_blocks - dst_blk_x - + (JDIMENSION)compptr->h_samp_factor, + (JDIMENSION)compptr->h_samp_factor, FALSE); + } else { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr)srcinfo, src_coef_arrays[ci], + dst_blk_x + x_crop_blocks, + (JDIMENSION)compptr->h_samp_factor, FALSE); + } + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + if (y_crop_blocks + dst_blk_y < comp_height) { + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Block is within the mirrorable area. */ + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j]; + j++; + dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j]; + } + i++; + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j]; + j++; + dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j]; + } + } + } else { + /* Right-edge blocks are mirrored in y only */ + src_ptr = src_buffer[offset_x] + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j]; + j++; + dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j]; + } + } + } + } else { + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Bottom-edge blocks are mirrored in x only */ + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] + [dst_blk_y + offset_y + y_crop_blocks]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j]; + i++; + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j]; + } + } else { + /* At lower right corner, just transpose, no mirroring */ + src_ptr = src_buffer[offset_x] + [dst_blk_y + offset_y + y_crop_blocks]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j]; + } + } + } + } + } + } + } +} + + +/* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec. + * Returns TRUE if valid integer found, FALSE if not. + * *strptr is advanced over the digit string, and *result is set to its value. + */ + +LOCAL(boolean) +jt_read_integer(const char **strptr, JDIMENSION *result) +{ + const char *ptr = *strptr; + JDIMENSION val = 0; + + for (; isdigit(*ptr); ptr++) { + val = val * 10 + (JDIMENSION)(*ptr - '0'); + } + *result = val; + if (ptr == *strptr) + return FALSE; /* oops, no digits */ + *strptr = ptr; + return TRUE; +} + + +/* Parse a crop specification (written in X11 geometry style). + * The routine returns TRUE if the spec string is valid, FALSE if not. + * + * The crop spec string should have the format + * [{fr}]x[{fr}]{+-}{+-} + * where width, height, xoffset, and yoffset are unsigned integers. + * Each of the elements can be omitted to indicate a default value. + * (A weakness of this style is that it is not possible to omit xoffset + * while specifying yoffset, since they look alike.) + * + * This code is loosely based on XParseGeometry from the X11 distribution. + */ + +GLOBAL(boolean) +jtransform_parse_crop_spec(jpeg_transform_info *info, const char *spec) +{ + info->crop = FALSE; + info->crop_width_set = JCROP_UNSET; + info->crop_height_set = JCROP_UNSET; + info->crop_xoffset_set = JCROP_UNSET; + info->crop_yoffset_set = JCROP_UNSET; + + if (isdigit(*spec)) { + /* fetch width */ + if (!jt_read_integer(&spec, &info->crop_width)) + return FALSE; + if (*spec == 'f' || *spec == 'F') { + spec++; + info->crop_width_set = JCROP_FORCE; + } else if (*spec == 'r' || *spec == 'R') { + spec++; + info->crop_width_set = JCROP_REFLECT; + } else + info->crop_width_set = JCROP_POS; + } + if (*spec == 'x' || *spec == 'X') { + /* fetch height */ + spec++; + if (!jt_read_integer(&spec, &info->crop_height)) + return FALSE; + if (*spec == 'f' || *spec == 'F') { + spec++; + info->crop_height_set = JCROP_FORCE; + } else if (*spec == 'r' || *spec == 'R') { + spec++; + info->crop_height_set = JCROP_REFLECT; + } else + info->crop_height_set = JCROP_POS; + } + if (*spec == '+' || *spec == '-') { + /* fetch xoffset */ + info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; + spec++; + if (!jt_read_integer(&spec, &info->crop_xoffset)) + return FALSE; + } + if (*spec == '+' || *spec == '-') { + /* fetch yoffset */ + info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; + spec++; + if (!jt_read_integer(&spec, &info->crop_yoffset)) + return FALSE; + } + /* We had better have gotten to the end of the string. */ + if (*spec != '\0') + return FALSE; + info->crop = TRUE; + return TRUE; +} + + +/* Trim off any partial iMCUs on the indicated destination edge */ + +LOCAL(void) +trim_right_edge(jpeg_transform_info *info, JDIMENSION full_width) +{ + JDIMENSION MCU_cols; + + MCU_cols = info->output_width / info->iMCU_sample_width; + if (MCU_cols > 0 && info->x_crop_offset + MCU_cols == + full_width / info->iMCU_sample_width) + info->output_width = MCU_cols * info->iMCU_sample_width; +} + +LOCAL(void) +trim_bottom_edge(jpeg_transform_info *info, JDIMENSION full_height) +{ + JDIMENSION MCU_rows; + + MCU_rows = info->output_height / info->iMCU_sample_height; + if (MCU_rows > 0 && info->y_crop_offset + MCU_rows == + full_height / info->iMCU_sample_height) + info->output_height = MCU_rows * info->iMCU_sample_height; +} + + +/* Request any required workspace. + * + * This routine figures out the size that the output image will be + * (which implies that all the transform parameters must be set before + * it is called). + * + * We allocate the workspace virtual arrays from the source decompression + * object, so that all the arrays (both the original data and the workspace) + * will be taken into account while making memory management decisions. + * Hence, this routine must be called after jpeg_read_header (which reads + * the image dimensions) and before jpeg_read_coefficients (which realizes + * the source's virtual arrays). + * + * This function returns FALSE right away if -perfect is given + * and transformation is not perfect. Otherwise returns TRUE. + */ + +GLOBAL(boolean) +jtransform_request_workspace(j_decompress_ptr srcinfo, + jpeg_transform_info *info) +{ + jvirt_barray_ptr *coef_arrays; + boolean need_workspace, transpose_it; + jpeg_component_info *compptr; + JDIMENSION xoffset, yoffset, dtemp; + JDIMENSION width_in_iMCUs, height_in_iMCUs; + JDIMENSION width_in_blocks, height_in_blocks; + int itemp, ci, h_samp_factor, v_samp_factor; + + /* Determine number of components in output image */ + if (info->force_grayscale && + srcinfo->jpeg_color_space == JCS_YCbCr && + srcinfo->num_components == 3) + /* We'll only process the first component */ + info->num_components = 1; + else + /* Process all the components */ + info->num_components = srcinfo->num_components; + + /* Compute output image dimensions and related values. */ +#if JPEG_LIB_VERSION >= 80 + jpeg_core_output_dimensions(srcinfo); +#else + srcinfo->output_width = srcinfo->image_width; + srcinfo->output_height = srcinfo->image_height; +#endif + + /* Return right away if -perfect is given and transformation is not perfect. + */ + if (info->perfect) { + if (info->num_components == 1) { + if (!jtransform_perfect_transform(srcinfo->output_width, + srcinfo->output_height, + srcinfo->_min_DCT_h_scaled_size, + srcinfo->_min_DCT_v_scaled_size, + info->transform)) + return FALSE; + } else { + if (!jtransform_perfect_transform(srcinfo->output_width, + srcinfo->output_height, + srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size, + srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size, + info->transform)) + return FALSE; + } + } + + /* If there is only one output component, force the iMCU size to be 1; + * else use the source iMCU size. (This allows us to do the right thing + * when reducing color to grayscale, and also provides a handy way of + * cleaning up "funny" grayscale images whose sampling factors are not 1x1.) + */ + switch (info->transform) { + case JXFORM_TRANSPOSE: + case JXFORM_TRANSVERSE: + case JXFORM_ROT_90: + case JXFORM_ROT_270: + info->output_width = srcinfo->output_height; + info->output_height = srcinfo->output_width; + if (info->num_components == 1) { + info->iMCU_sample_width = srcinfo->_min_DCT_v_scaled_size; + info->iMCU_sample_height = srcinfo->_min_DCT_h_scaled_size; + } else { + info->iMCU_sample_width = + srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size; + info->iMCU_sample_height = + srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size; + } + break; + default: + info->output_width = srcinfo->output_width; + info->output_height = srcinfo->output_height; + if (info->num_components == 1) { + info->iMCU_sample_width = srcinfo->_min_DCT_h_scaled_size; + info->iMCU_sample_height = srcinfo->_min_DCT_v_scaled_size; + } else { + info->iMCU_sample_width = + srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size; + info->iMCU_sample_height = + srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size; + } + break; + } + + /* If cropping has been requested, compute the crop area's position and + * dimensions, ensuring that its upper left corner falls at an iMCU boundary. + */ + if (info->crop) { + /* Insert default values for unset crop parameters */ + if (info->crop_xoffset_set == JCROP_UNSET) + info->crop_xoffset = 0; /* default to +0 */ + if (info->crop_yoffset_set == JCROP_UNSET) + info->crop_yoffset = 0; /* default to +0 */ + if (info->crop_width_set == JCROP_UNSET) { + if (info->crop_xoffset >= info->output_width) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + info->crop_width = info->output_width - info->crop_xoffset; + } else { + /* Check for crop extension */ + if (info->crop_width > info->output_width) { + /* Crop extension does not work when transforming! */ + if (info->transform != JXFORM_NONE || + info->crop_xoffset >= info->crop_width || + info->crop_xoffset > info->crop_width - info->output_width) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + } else { + if (info->crop_xoffset >= info->output_width || + info->crop_width <= 0 || + info->crop_xoffset > info->output_width - info->crop_width) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + } + } + if (info->crop_height_set == JCROP_UNSET) { + if (info->crop_yoffset >= info->output_height) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + info->crop_height = info->output_height - info->crop_yoffset; + } else { + /* Check for crop extension */ + if (info->crop_height > info->output_height) { + /* Crop extension does not work when transforming! */ + if (info->transform != JXFORM_NONE || + info->crop_yoffset >= info->crop_height || + info->crop_yoffset > info->crop_height - info->output_height) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + } else { + if (info->crop_yoffset >= info->output_height || + info->crop_height <= 0 || + info->crop_yoffset > info->output_height - info->crop_height) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + } + } + /* Convert negative crop offsets into regular offsets */ + if (info->crop_xoffset_set != JCROP_NEG) + xoffset = info->crop_xoffset; + else if (info->crop_width > info->output_width) /* crop extension */ + xoffset = info->crop_width - info->output_width - info->crop_xoffset; + else + xoffset = info->output_width - info->crop_width - info->crop_xoffset; + if (info->crop_yoffset_set != JCROP_NEG) + yoffset = info->crop_yoffset; + else if (info->crop_height > info->output_height) /* crop extension */ + yoffset = info->crop_height - info->output_height - info->crop_yoffset; + else + yoffset = info->output_height - info->crop_height - info->crop_yoffset; + /* Now adjust so that upper left corner falls at an iMCU boundary */ + switch (info->transform) { + case JXFORM_DROP: + /* Ensure the effective drop region will not exceed the requested */ + itemp = info->iMCU_sample_width; + dtemp = itemp - 1 - ((xoffset + itemp - 1) % itemp); + xoffset += dtemp; + if (info->crop_width <= dtemp) + info->drop_width = 0; + else if (xoffset + info->crop_width - dtemp == info->output_width) + /* Matching right edge: include partial iMCU */ + info->drop_width = (info->crop_width - dtemp + itemp - 1) / itemp; + else + info->drop_width = (info->crop_width - dtemp) / itemp; + itemp = info->iMCU_sample_height; + dtemp = itemp - 1 - ((yoffset + itemp - 1) % itemp); + yoffset += dtemp; + if (info->crop_height <= dtemp) + info->drop_height = 0; + else if (yoffset + info->crop_height - dtemp == info->output_height) + /* Matching bottom edge: include partial iMCU */ + info->drop_height = (info->crop_height - dtemp + itemp - 1) / itemp; + else + info->drop_height = (info->crop_height - dtemp) / itemp; + /* Check if sampling factors match for dropping */ + if (info->drop_width != 0 && info->drop_height != 0) + for (ci = 0; ci < info->num_components && + ci < info->drop_ptr->num_components; ci++) { + if (info->drop_ptr->comp_info[ci].h_samp_factor * + srcinfo->max_h_samp_factor != + srcinfo->comp_info[ci].h_samp_factor * + info->drop_ptr->max_h_samp_factor) + ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci, + info->drop_ptr->comp_info[ci].h_samp_factor, + info->drop_ptr->max_h_samp_factor, + srcinfo->comp_info[ci].h_samp_factor, + srcinfo->max_h_samp_factor, 'h'); + if (info->drop_ptr->comp_info[ci].v_samp_factor * + srcinfo->max_v_samp_factor != + srcinfo->comp_info[ci].v_samp_factor * + info->drop_ptr->max_v_samp_factor) + ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci, + info->drop_ptr->comp_info[ci].v_samp_factor, + info->drop_ptr->max_v_samp_factor, + srcinfo->comp_info[ci].v_samp_factor, + srcinfo->max_v_samp_factor, 'v'); + } + break; + case JXFORM_WIPE: + /* Ensure the effective wipe region will cover the requested */ + info->drop_width = (JDIMENSION)jdiv_round_up + ((long)(info->crop_width + (xoffset % info->iMCU_sample_width)), + (long)info->iMCU_sample_width); + info->drop_height = (JDIMENSION)jdiv_round_up + ((long)(info->crop_height + (yoffset % info->iMCU_sample_height)), + (long)info->iMCU_sample_height); + break; + default: + /* Ensure the effective crop region will cover the requested */ + if (info->crop_width_set == JCROP_FORCE || + info->crop_width > info->output_width) + info->output_width = info->crop_width; + else + info->output_width = + info->crop_width + (xoffset % info->iMCU_sample_width); + if (info->crop_height_set == JCROP_FORCE || + info->crop_height > info->output_height) + info->output_height = info->crop_height; + else + info->output_height = + info->crop_height + (yoffset % info->iMCU_sample_height); + } + /* Save x/y offsets measured in iMCUs */ + info->x_crop_offset = xoffset / info->iMCU_sample_width; + info->y_crop_offset = yoffset / info->iMCU_sample_height; + } else { + info->x_crop_offset = 0; + info->y_crop_offset = 0; + } + + /* Figure out whether we need workspace arrays, + * and if so whether they are transposed relative to the source. + */ + need_workspace = FALSE; + transpose_it = FALSE; + switch (info->transform) { + case JXFORM_NONE: + if (info->x_crop_offset != 0 || info->y_crop_offset != 0 || + info->output_width > srcinfo->output_width || + info->output_height > srcinfo->output_height) + need_workspace = TRUE; + /* No workspace needed if neither cropping nor transforming */ + break; + case JXFORM_FLIP_H: + if (info->trim) + trim_right_edge(info, srcinfo->output_width); + if (info->y_crop_offset != 0 || info->slow_hflip) + need_workspace = TRUE; + /* do_flip_h_no_crop doesn't need a workspace array */ + break; + case JXFORM_FLIP_V: + if (info->trim) + trim_bottom_edge(info, srcinfo->output_height); + /* Need workspace arrays having same dimensions as source image. */ + need_workspace = TRUE; + break; + case JXFORM_TRANSPOSE: + /* transpose does NOT have to trim anything */ + /* Need workspace arrays having transposed dimensions. */ + need_workspace = TRUE; + transpose_it = TRUE; + break; + case JXFORM_TRANSVERSE: + if (info->trim) { + trim_right_edge(info, srcinfo->output_height); + trim_bottom_edge(info, srcinfo->output_width); + } + /* Need workspace arrays having transposed dimensions. */ + need_workspace = TRUE; + transpose_it = TRUE; + break; + case JXFORM_ROT_90: + if (info->trim) + trim_right_edge(info, srcinfo->output_height); + /* Need workspace arrays having transposed dimensions. */ + need_workspace = TRUE; + transpose_it = TRUE; + break; + case JXFORM_ROT_180: + if (info->trim) { + trim_right_edge(info, srcinfo->output_width); + trim_bottom_edge(info, srcinfo->output_height); + } + /* Need workspace arrays having same dimensions as source image. */ + need_workspace = TRUE; + break; + case JXFORM_ROT_270: + if (info->trim) + trim_bottom_edge(info, srcinfo->output_width); + /* Need workspace arrays having transposed dimensions. */ + need_workspace = TRUE; + transpose_it = TRUE; + break; + case JXFORM_WIPE: + break; + case JXFORM_DROP: + break; + } + + /* Allocate workspace if needed. + * Note that we allocate arrays padded out to the next iMCU boundary, + * so that transform routines need not worry about missing edge blocks. + */ + if (need_workspace) { + coef_arrays = (jvirt_barray_ptr *) + (*srcinfo->mem->alloc_small) ((j_common_ptr)srcinfo, JPOOL_IMAGE, + sizeof(jvirt_barray_ptr) * info->num_components); + width_in_iMCUs = (JDIMENSION) + jdiv_round_up((long)info->output_width, (long)info->iMCU_sample_width); + height_in_iMCUs = (JDIMENSION) + jdiv_round_up((long)info->output_height, (long)info->iMCU_sample_height); + for (ci = 0; ci < info->num_components; ci++) { + compptr = srcinfo->comp_info + ci; + if (info->num_components == 1) { + /* we're going to force samp factors to 1x1 in this case */ + h_samp_factor = v_samp_factor = 1; + } else if (transpose_it) { + h_samp_factor = compptr->v_samp_factor; + v_samp_factor = compptr->h_samp_factor; + } else { + h_samp_factor = compptr->h_samp_factor; + v_samp_factor = compptr->v_samp_factor; + } + width_in_blocks = width_in_iMCUs * h_samp_factor; + height_in_blocks = height_in_iMCUs * v_samp_factor; + coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) + ((j_common_ptr)srcinfo, JPOOL_IMAGE, FALSE, + width_in_blocks, height_in_blocks, (JDIMENSION)v_samp_factor); + } + info->workspace_coef_arrays = coef_arrays; + } else + info->workspace_coef_arrays = NULL; + + return TRUE; +} + + +/* Transpose destination image parameters */ + +LOCAL(void) +transpose_critical_parameters(j_compress_ptr dstinfo) +{ + int tblno, i, j, ci, itemp; + jpeg_component_info *compptr; + JQUANT_TBL *qtblptr; + JDIMENSION jtemp; + UINT16 qtemp; + + /* Transpose image dimensions */ + jtemp = dstinfo->image_width; + dstinfo->image_width = dstinfo->image_height; + dstinfo->image_height = jtemp; +#if JPEG_LIB_VERSION >= 70 + itemp = dstinfo->min_DCT_h_scaled_size; + dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size; + dstinfo->min_DCT_v_scaled_size = itemp; +#endif + + /* Transpose sampling factors */ + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + itemp = compptr->h_samp_factor; + compptr->h_samp_factor = compptr->v_samp_factor; + compptr->v_samp_factor = itemp; + } + + /* Transpose quantization tables */ + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + qtblptr = dstinfo->quant_tbl_ptrs[tblno]; + if (qtblptr != NULL) { + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < i; j++) { + qtemp = qtblptr->quantval[i * DCTSIZE + j]; + qtblptr->quantval[i * DCTSIZE + j] = + qtblptr->quantval[j * DCTSIZE + i]; + qtblptr->quantval[j * DCTSIZE + i] = qtemp; + } + } + } + } +} + + +/* Adjust Exif image parameters. + * + * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible. + */ + +LOCAL(void) +adjust_exif_parameters(JOCTET *data, unsigned int length, JDIMENSION new_width, + JDIMENSION new_height) +{ + boolean is_motorola; /* Flag for byte order */ + unsigned int number_of_tags, tagnum; + unsigned int firstoffset, offset; + JDIMENSION new_value; + + if (length < 12) return; /* Length of an IFD entry */ + + /* Discover byte order */ + if (data[0] == 0x49 && data[1] == 0x49) + is_motorola = FALSE; + else if (data[0] == 0x4D && data[1] == 0x4D) + is_motorola = TRUE; + else + return; + + /* Check Tag Mark */ + if (is_motorola) { + if (data[2] != 0) return; + if (data[3] != 0x2A) return; + } else { + if (data[3] != 0) return; + if (data[2] != 0x2A) return; + } + + /* Get first IFD offset (offset to IFD0) */ + if (is_motorola) { + if (data[4] != 0) return; + if (data[5] != 0) return; + firstoffset = data[6]; + firstoffset <<= 8; + firstoffset += data[7]; + } else { + if (data[7] != 0) return; + if (data[6] != 0) return; + firstoffset = data[5]; + firstoffset <<= 8; + firstoffset += data[4]; + } + if (firstoffset > length - 2) return; /* check end of data segment */ + + /* Get the number of directory entries contained in this IFD */ + if (is_motorola) { + number_of_tags = data[firstoffset]; + number_of_tags <<= 8; + number_of_tags += data[firstoffset + 1]; + } else { + number_of_tags = data[firstoffset + 1]; + number_of_tags <<= 8; + number_of_tags += data[firstoffset]; + } + if (number_of_tags == 0) return; + firstoffset += 2; + + /* Search for ExifSubIFD offset Tag in IFD0 */ + for (;;) { + if (firstoffset > length - 12) return; /* check end of data segment */ + /* Get Tag number */ + if (is_motorola) { + tagnum = data[firstoffset]; + tagnum <<= 8; + tagnum += data[firstoffset + 1]; + } else { + tagnum = data[firstoffset + 1]; + tagnum <<= 8; + tagnum += data[firstoffset]; + } + if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */ + if (--number_of_tags == 0) return; + firstoffset += 12; + } + + /* Get the ExifSubIFD offset */ + if (is_motorola) { + if (data[firstoffset + 8] != 0) return; + if (data[firstoffset + 9] != 0) return; + offset = data[firstoffset + 10]; + offset <<= 8; + offset += data[firstoffset + 11]; + } else { + if (data[firstoffset + 11] != 0) return; + if (data[firstoffset + 10] != 0) return; + offset = data[firstoffset + 9]; + offset <<= 8; + offset += data[firstoffset + 8]; + } + if (offset > length - 2) return; /* check end of data segment */ + + /* Get the number of directory entries contained in this SubIFD */ + if (is_motorola) { + number_of_tags = data[offset]; + number_of_tags <<= 8; + number_of_tags += data[offset + 1]; + } else { + number_of_tags = data[offset + 1]; + number_of_tags <<= 8; + number_of_tags += data[offset]; + } + if (number_of_tags < 2) return; + offset += 2; + + /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */ + do { + if (offset > length - 12) return; /* check end of data segment */ + /* Get Tag number */ + if (is_motorola) { + tagnum = data[offset]; + tagnum <<= 8; + tagnum += data[offset + 1]; + } else { + tagnum = data[offset + 1]; + tagnum <<= 8; + tagnum += data[offset]; + } + if (tagnum == 0xA002 || tagnum == 0xA003) { + if (tagnum == 0xA002) + new_value = new_width; /* ExifImageWidth Tag */ + else + new_value = new_height; /* ExifImageHeight Tag */ + if (is_motorola) { + data[offset + 2] = 0; /* Format = unsigned long (4 octets) */ + data[offset + 3] = 4; + data[offset + 4] = 0; /* Number Of Components = 1 */ + data[offset + 5] = 0; + data[offset + 6] = 0; + data[offset + 7] = 1; + data[offset + 8] = 0; + data[offset + 9] = 0; + data[offset + 10] = (JOCTET)((new_value >> 8) & 0xFF); + data[offset + 11] = (JOCTET)(new_value & 0xFF); + } else { + data[offset + 2] = 4; /* Format = unsigned long (4 octets) */ + data[offset + 3] = 0; + data[offset + 4] = 1; /* Number Of Components = 1 */ + data[offset + 5] = 0; + data[offset + 6] = 0; + data[offset + 7] = 0; + data[offset + 8] = (JOCTET)(new_value & 0xFF); + data[offset + 9] = (JOCTET)((new_value >> 8) & 0xFF); + data[offset + 10] = 0; + data[offset + 11] = 0; + } + } + offset += 12; + } while (--number_of_tags); +} + + +/* Adjust output image parameters as needed. + * + * This must be called after jpeg_copy_critical_parameters() + * and before jpeg_write_coefficients(). + * + * The return value is the set of virtual coefficient arrays to be written + * (either the ones allocated by jtransform_request_workspace, or the + * original source data arrays). The caller will need to pass this value + * to jpeg_write_coefficients(). + */ + +GLOBAL(jvirt_barray_ptr *) +jtransform_adjust_parameters(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info) +{ + /* If force-to-grayscale is requested, adjust destination parameters */ + if (info->force_grayscale) { + /* First, ensure we have YCbCr or grayscale data, and that the source's + * Y channel is full resolution. (No reasonable person would make Y + * be less than full resolution, so actually coping with that case + * isn't worth extra code space. But we check it to avoid crashing.) + */ + if (((dstinfo->jpeg_color_space == JCS_YCbCr && + dstinfo->num_components == 3) || + (dstinfo->jpeg_color_space == JCS_GRAYSCALE && + dstinfo->num_components == 1)) && + srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor && + srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) { + /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed + * properly. Among other things, it sets the target h_samp_factor & + * v_samp_factor to 1, which typically won't match the source. + * We have to preserve the source's quantization table number, however. + */ + int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no; + jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE); + dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; + } else { + /* Sorry, can't do it */ + ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL); + } + } else if (info->num_components == 1) { + /* For a single-component source, we force the destination sampling factors + * to 1x1, with or without force_grayscale. This is useful because some + * decoders choke on grayscale images with other sampling factors. + */ + dstinfo->comp_info[0].h_samp_factor = 1; + dstinfo->comp_info[0].v_samp_factor = 1; + } + + /* Correct the destination's image dimensions as necessary + * for rotate/flip, resize, and crop operations. + */ +#if JPEG_LIB_VERSION >= 80 + dstinfo->jpeg_width = info->output_width; + dstinfo->jpeg_height = info->output_height; +#endif + + /* Transpose destination image parameters, adjust quantization */ + switch (info->transform) { + case JXFORM_TRANSPOSE: + case JXFORM_TRANSVERSE: + case JXFORM_ROT_90: + case JXFORM_ROT_270: +#if JPEG_LIB_VERSION < 80 + dstinfo->image_width = info->output_height; + dstinfo->image_height = info->output_width; +#endif + transpose_critical_parameters(dstinfo); + break; + case JXFORM_DROP: + if (info->drop_width != 0 && info->drop_height != 0) + adjust_quant(srcinfo, src_coef_arrays, + info->drop_ptr, info->drop_coef_arrays, + info->trim, dstinfo); + break; + default: +#if JPEG_LIB_VERSION < 80 + dstinfo->image_width = info->output_width; + dstinfo->image_height = info->output_height; +#endif + break; + } + + /* Adjust Exif properties */ + if (srcinfo->marker_list != NULL && + srcinfo->marker_list->marker == JPEG_APP0 + 1 && + srcinfo->marker_list->data_length >= 6 && + srcinfo->marker_list->data[0] == 0x45 && + srcinfo->marker_list->data[1] == 0x78 && + srcinfo->marker_list->data[2] == 0x69 && + srcinfo->marker_list->data[3] == 0x66 && + srcinfo->marker_list->data[4] == 0 && + srcinfo->marker_list->data[5] == 0) { + /* Suppress output of JFIF marker */ + dstinfo->write_JFIF_header = FALSE; + /* Adjust Exif image parameters */ +#if JPEG_LIB_VERSION >= 80 + if (dstinfo->jpeg_width != srcinfo->image_width || + dstinfo->jpeg_height != srcinfo->image_height) + /* Align data segment to start of TIFF structure for parsing */ + adjust_exif_parameters(srcinfo->marker_list->data + 6, + srcinfo->marker_list->data_length - 6, + dstinfo->jpeg_width, dstinfo->jpeg_height); +#else + if (dstinfo->image_width != srcinfo->image_width || + dstinfo->image_height != srcinfo->image_height) + /* Align data segment to start of TIFF structure for parsing */ + adjust_exif_parameters(srcinfo->marker_list->data + 6, + srcinfo->marker_list->data_length - 6, + dstinfo->image_width, dstinfo->image_height); +#endif + } + + /* Return the appropriate output data set */ + if (info->workspace_coef_arrays != NULL) + return info->workspace_coef_arrays; + return src_coef_arrays; +} + + +/* Execute the actual transformation, if any. + * + * This must be called *after* jpeg_write_coefficients, because it depends + * on jpeg_write_coefficients to have computed subsidiary values such as + * the per-component width and height fields in the destination object. + * + * Note that some transformations will modify the source data arrays! + */ + +GLOBAL(void) +jtransform_execute_transform(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info) +{ + jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays; + + /* Note: conditions tested here should match those in switch statement + * in jtransform_request_workspace() + */ + switch (info->transform) { + case JXFORM_NONE: + if (info->output_width > srcinfo->output_width || + info->output_height > srcinfo->output_height) { + if (info->output_width > srcinfo->output_width && + info->crop_width_set == JCROP_REFLECT) + do_crop_ext_reflect(srcinfo, dstinfo, + info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + else if (info->output_width > srcinfo->output_width && + info->crop_width_set == JCROP_FORCE) + do_crop_ext_flat(srcinfo, dstinfo, + info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + else + do_crop_ext_zero(srcinfo, dstinfo, + info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + } else if (info->x_crop_offset != 0 || info->y_crop_offset != 0) + do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_FLIP_H: + if (info->y_crop_offset != 0 || info->slow_hflip) + do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + else + do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset, + src_coef_arrays); + break; + case JXFORM_FLIP_V: + do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_TRANSPOSE: + do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_TRANSVERSE: + do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_ROT_90: + do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_ROT_180: + do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_ROT_270: + do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_WIPE: + if (info->crop_width_set == JCROP_REFLECT && + info->y_crop_offset == 0 && info->drop_height == + (JDIMENSION)jdiv_round_up + ((long)info->output_height, (long)info->iMCU_sample_height) && + (info->x_crop_offset == 0 || + info->x_crop_offset + info->drop_width == + (JDIMENSION)jdiv_round_up + ((long)info->output_width, (long)info->iMCU_sample_width))) + do_reflect(srcinfo, dstinfo, info->x_crop_offset, + src_coef_arrays, info->drop_width, info->drop_height); + else if (info->crop_width_set == JCROP_FORCE) + do_flatten(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, info->drop_width, info->drop_height); + else + do_wipe(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, info->drop_width, info->drop_height); + break; + case JXFORM_DROP: + if (info->drop_width != 0 && info->drop_height != 0) + do_drop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, info->drop_ptr, info->drop_coef_arrays, + info->drop_width, info->drop_height); + break; + } +} + +/* jtransform_perfect_transform + * + * Determine whether lossless transformation is perfectly + * possible for a specified image and transformation. + * + * Inputs: + * image_width, image_height: source image dimensions. + * MCU_width, MCU_height: pixel dimensions of MCU. + * transform: transformation identifier. + * Parameter sources from initialized jpeg_struct + * (after reading source header): + * image_width = cinfo.image_width + * image_height = cinfo.image_height + * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size + * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size + * Result: + * TRUE = perfect transformation possible + * FALSE = perfect transformation not possible + * (may use custom action then) + */ + +GLOBAL(boolean) +jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height, + int MCU_width, int MCU_height, + JXFORM_CODE transform) +{ + boolean result = TRUE; /* initialize TRUE */ + + switch (transform) { + case JXFORM_FLIP_H: + case JXFORM_ROT_270: + if (image_width % (JDIMENSION)MCU_width) + result = FALSE; + break; + case JXFORM_FLIP_V: + case JXFORM_ROT_90: + if (image_height % (JDIMENSION)MCU_height) + result = FALSE; + break; + case JXFORM_TRANSVERSE: + case JXFORM_ROT_180: + if (image_width % (JDIMENSION)MCU_width) + result = FALSE; + if (image_height % (JDIMENSION)MCU_height) + result = FALSE; + break; + default: + break; + } + + return result; +} + +#endif /* TRANSFORMS_SUPPORTED */ + + +/* Setup decompression object to save desired markers in memory. + * This must be called before jpeg_read_header() to have the desired effect. + */ + +GLOBAL(void) +jcopy_markers_setup(j_decompress_ptr srcinfo, JCOPY_OPTION option) +{ +#ifdef SAVE_MARKERS_SUPPORTED + int m; + + /* Save comments except under NONE option */ + if (option != JCOPYOPT_NONE && option != JCOPYOPT_ICC) { + jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF); + } + /* Save all types of APPn markers iff ALL option */ + if (option == JCOPYOPT_ALL || option == JCOPYOPT_ALL_EXCEPT_ICC) { + for (m = 0; m < 16; m++) { + if (option == JCOPYOPT_ALL_EXCEPT_ICC && m == 2) + continue; + jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF); + } + } + /* Save only APP2 markers if ICC option selected */ + if (option == JCOPYOPT_ICC) { + jpeg_save_markers(srcinfo, JPEG_APP0 + 2, 0xFFFF); + } +#endif /* SAVE_MARKERS_SUPPORTED */ +} + +/* Copy markers saved in the given source object to the destination object. + * This should be called just after jpeg_start_compress() or + * jpeg_write_coefficients(). + * Note that those routines will have written the SOI, and also the + * JFIF APP0 or Adobe APP14 markers if selected. + */ + +GLOBAL(void) +jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JCOPY_OPTION option) +{ + jpeg_saved_marker_ptr marker; + + /* In the current implementation, we don't actually need to examine the + * option flag here; we just copy everything that got saved. + * But to avoid confusion, we do not output JFIF and Adobe APP14 markers + * if the encoder library already wrote one. + */ + for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) { + if (dstinfo->write_JFIF_header && + marker->marker == JPEG_APP0 && + marker->data_length >= 5 && + marker->data[0] == 0x4A && + marker->data[1] == 0x46 && + marker->data[2] == 0x49 && + marker->data[3] == 0x46 && + marker->data[4] == 0) + continue; /* reject duplicate JFIF */ + if (dstinfo->write_Adobe_marker && + marker->marker == JPEG_APP0 + 14 && + marker->data_length >= 5 && + marker->data[0] == 0x41 && + marker->data[1] == 0x64 && + marker->data[2] == 0x6F && + marker->data[3] == 0x62 && + marker->data[4] == 0x65) + continue; /* reject duplicate Adobe */ + jpeg_write_marker(dstinfo, marker->marker, + marker->data, marker->data_length); + } +} diff --git a/3rdparty/libjpeg-turbo/src/transupp.h b/3rdparty/libjpeg-turbo/src/transupp.h new file mode 100644 index 000000000000..cea1f409214a --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/transupp.h @@ -0,0 +1,231 @@ +/* + * transupp.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1997-2019, Thomas G. Lane, Guido Vollbeding. + * libjpeg-turbo Modifications: + * Copyright (C) 2017, 2021, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains declarations for image transformation routines and + * other utility code used by the jpegtran sample application. These are + * NOT part of the core JPEG library. But we keep these routines separate + * from jpegtran.c to ease the task of maintaining jpegtran-like programs + * that have other user interfaces. + * + * NOTE: all the routines declared here have very specific requirements + * about when they are to be executed during the reading and writing of the + * source and destination files. See the comments in transupp.c, or see + * jpegtran.c for an example of correct usage. + */ + +/* If you happen not to want the image transform support, disable it here */ +#ifndef TRANSFORMS_SUPPORTED +#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */ +#endif + +/* + * Although rotating and flipping data expressed as DCT coefficients is not + * hard, there is an asymmetry in the JPEG format specification for images + * whose dimensions aren't multiples of the iMCU size. The right and bottom + * image edges are padded out to the next iMCU boundary with junk data; but + * no padding is possible at the top and left edges. If we were to flip + * the whole image including the pad data, then pad garbage would become + * visible at the top and/or left, and real pixels would disappear into the + * pad margins --- perhaps permanently, since encoders & decoders may not + * bother to preserve DCT blocks that appear to be completely outside the + * nominal image area. So, we have to exclude any partial iMCUs from the + * basic transformation. + * + * Transpose is the only transformation that can handle partial iMCUs at the + * right and bottom edges completely cleanly. flip_h can flip partial iMCUs + * at the bottom, but leaves any partial iMCUs at the right edge untouched. + * Similarly flip_v leaves any partial iMCUs at the bottom edge untouched. + * The other transforms are defined as combinations of these basic transforms + * and process edge blocks in a way that preserves the equivalence. + * + * The "trim" option causes untransformable partial iMCUs to be dropped; + * this is not strictly lossless, but it usually gives the best-looking + * result for odd-size images. Note that when this option is active, + * the expected mathematical equivalences between the transforms may not hold. + * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim + * followed by -rot 180 -trim trims both edges.) + * + * We also offer a lossless-crop option, which discards data outside a given + * image region but losslessly preserves what is inside. Like the rotate and + * flip transforms, lossless crop is restricted by the JPEG format: the upper + * left corner of the selected region must fall on an iMCU boundary. If this + * does not hold for the given crop parameters, we silently move the upper left + * corner up and/or left to make it so, simultaneously increasing the region + * dimensions to keep the lower right crop corner unchanged. (Thus, the + * output image covers at least the requested region, but may cover more.) + * The adjustment of the region dimensions may be optionally disabled. + * + * A complementary lossless wipe option is provided to discard (gray out) data + * inside a given image region while losslessly preserving what is outside. + * A lossless drop option is also provided, which allows another JPEG image to + * be inserted ("dropped") into the source image data at a given position, + * replacing the existing image data at that position. Both the source image + * and the drop image must have the same subsampling level. It is best if they + * also have the same quantization (quality.) Otherwise, the quantization of + * the output image will be adapted to accommodate the higher of the source + * image quality and the drop image quality. The trim option can be used with + * the drop option to requantize the drop image to match the source image. + * + * We also provide a lossless-resize option, which is kind of a lossless-crop + * operation in the DCT coefficient block domain - it discards higher-order + * coefficients and losslessly preserves lower-order coefficients of a + * sub-block. + * + * Rotate/flip transform, resize, and crop can be requested together in a + * single invocation. The crop is applied last --- that is, the crop region + * is specified in terms of the destination image after transform/resize. + * + * We also offer a "force to grayscale" option, which simply discards the + * chrominance channels of a YCbCr image. This is lossless in the sense that + * the luminance channel is preserved exactly. It's not the same kind of + * thing as the rotate/flip transformations, but it's convenient to handle it + * as part of this package, mainly because the transformation routines have to + * be aware of the option to know how many components to work on. + */ + + +/* + * Codes for supported types of image transformations. + */ + +typedef enum { + JXFORM_NONE, /* no transformation */ + JXFORM_FLIP_H, /* horizontal flip */ + JXFORM_FLIP_V, /* vertical flip */ + JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */ + JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */ + JXFORM_ROT_90, /* 90-degree clockwise rotation */ + JXFORM_ROT_180, /* 180-degree rotation */ + JXFORM_ROT_270, /* 270-degree clockwise (or 90 ccw) */ + JXFORM_WIPE, /* wipe */ + JXFORM_DROP /* drop */ +} JXFORM_CODE; + +/* + * Codes for crop parameters, which can individually be unspecified, + * positive or negative for xoffset or yoffset, + * positive or force or reflect for width or height. + */ + +typedef enum { + JCROP_UNSET, + JCROP_POS, + JCROP_NEG, + JCROP_FORCE, + JCROP_REFLECT +} JCROP_CODE; + +/* + * Transform parameters struct. + * NB: application must not change any elements of this struct after + * calling jtransform_request_workspace. + */ + +typedef struct { + /* Options: set by caller */ + JXFORM_CODE transform; /* image transform operator */ + boolean perfect; /* if TRUE, fail if partial MCUs are requested */ + boolean trim; /* if TRUE, trim partial MCUs as needed */ + boolean force_grayscale; /* if TRUE, convert color image to grayscale */ + boolean crop; /* if TRUE, crop or wipe source image, or drop */ + boolean slow_hflip; /* For best performance, the JXFORM_FLIP_H transform + normally modifies the source coefficients in place. + Setting this to TRUE will instead use a slower, + double-buffered algorithm, which leaves the source + coefficients in tact (necessary if other transformed + images must be generated from the same set of + coefficients. */ + + /* Crop parameters: application need not set these unless crop is TRUE. + * These can be filled in by jtransform_parse_crop_spec(). + */ + JDIMENSION crop_width; /* Width of selected region */ + JCROP_CODE crop_width_set; /* (force-disables adjustment) */ + JDIMENSION crop_height; /* Height of selected region */ + JCROP_CODE crop_height_set; /* (force-disables adjustment) */ + JDIMENSION crop_xoffset; /* X offset of selected region */ + JCROP_CODE crop_xoffset_set; /* (negative measures from right edge) */ + JDIMENSION crop_yoffset; /* Y offset of selected region */ + JCROP_CODE crop_yoffset_set; /* (negative measures from bottom edge) */ + + /* Drop parameters: set by caller for drop request */ + j_decompress_ptr drop_ptr; + jvirt_barray_ptr *drop_coef_arrays; + + /* Internal workspace: caller should not touch these */ + int num_components; /* # of components in workspace */ + jvirt_barray_ptr *workspace_coef_arrays; /* workspace for transformations */ + JDIMENSION output_width; /* cropped destination dimensions */ + JDIMENSION output_height; + JDIMENSION x_crop_offset; /* destination crop offsets measured in iMCUs */ + JDIMENSION y_crop_offset; + JDIMENSION drop_width; /* drop/wipe dimensions measured in iMCUs */ + JDIMENSION drop_height; + int iMCU_sample_width; /* destination iMCU size */ + int iMCU_sample_height; +} jpeg_transform_info; + + +#if TRANSFORMS_SUPPORTED + +/* Parse a crop specification (written in X11 geometry style) */ +EXTERN(boolean) jtransform_parse_crop_spec(jpeg_transform_info *info, + const char *spec); +/* Request any required workspace */ +EXTERN(boolean) jtransform_request_workspace(j_decompress_ptr srcinfo, + jpeg_transform_info *info); +/* Adjust output image parameters */ +EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters + (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, jpeg_transform_info *info); +/* Execute the actual transformation, if any */ +EXTERN(void) jtransform_execute_transform(j_decompress_ptr srcinfo, + j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info); +/* Determine whether lossless transformation is perfectly + * possible for a specified image and transformation. + */ +EXTERN(boolean) jtransform_perfect_transform(JDIMENSION image_width, + JDIMENSION image_height, + int MCU_width, int MCU_height, + JXFORM_CODE transform); + +/* jtransform_execute_transform used to be called + * jtransform_execute_transformation, but some compilers complain about + * routine names that long. This macro is here to avoid breaking any + * old source code that uses the original name... + */ +#define jtransform_execute_transformation jtransform_execute_transform + +#endif /* TRANSFORMS_SUPPORTED */ + + +/* + * Support for copying optional markers from source to destination file. + */ + +typedef enum { + JCOPYOPT_NONE, /* copy no optional markers */ + JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */ + JCOPYOPT_ALL, /* copy all optional markers */ + JCOPYOPT_ALL_EXCEPT_ICC, /* copy all optional markers except APP2 */ + JCOPYOPT_ICC /* copy only ICC profile (APP2) markers */ +} JCOPY_OPTION; + +#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */ + +/* Setup decompression object to save desired markers in memory */ +EXTERN(void) jcopy_markers_setup(j_decompress_ptr srcinfo, + JCOPY_OPTION option); +/* Copy markers saved in the given source object to the destination object */ +EXTERN(void) jcopy_markers_execute(j_decompress_ptr srcinfo, + j_compress_ptr dstinfo, + JCOPY_OPTION option); diff --git a/3rdparty/libjpeg-turbo/src/turbojpeg-jni.c b/3rdparty/libjpeg-turbo/src/turbojpeg-jni.c new file mode 100644 index 000000000000..32186f3fa0ad --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/turbojpeg-jni.c @@ -0,0 +1,1400 @@ +/* + * Copyright (C)2011-2023 D. R. Commander. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "turbojpeg.h" +#include "jinclude.h" +#include +#include "java/org_libjpegturbo_turbojpeg_TJCompressor.h" +#include "java/org_libjpegturbo_turbojpeg_TJDecompressor.h" +#include "java/org_libjpegturbo_turbojpeg_TJTransformer.h" +#include "java/org_libjpegturbo_turbojpeg_TJ.h" + +#define BAILIF0(f) { \ + if (!(f) || (*env)->ExceptionCheck(env)) { \ + goto bailout; \ + } \ +} + +#define BAILIF0NOEC(f) { \ + if (!(f)) { \ + goto bailout; \ + } \ +} + +#define THROW(msg, exceptionClass) { \ + jclass _exccls = (*env)->FindClass(env, exceptionClass); \ + \ + BAILIF0(_exccls); \ + (*env)->ThrowNew(env, _exccls, msg); \ + goto bailout; \ +} + +#define THROW_TJ() { \ + jclass _exccls; \ + jmethodID _excid; \ + jobject _excobj; \ + jstring _errstr; \ + \ + BAILIF0(_errstr = (*env)->NewStringUTF(env, tj3GetErrorStr(handle))); \ + BAILIF0(_exccls = (*env)->FindClass(env, \ + "org/libjpegturbo/turbojpeg/TJException")); \ + BAILIF0(_excid = (*env)->GetMethodID(env, _exccls, "", \ + "(Ljava/lang/String;I)V")); \ + BAILIF0(_excobj = (*env)->NewObject(env, _exccls, _excid, _errstr, \ + tj3GetErrorCode(handle))); \ + (*env)->Throw(env, _excobj); \ + goto bailout; \ +} + +#define THROW_ARG(msg) THROW(msg, "java/lang/IllegalArgumentException") + +#define THROW_MEM() \ + THROW("Memory allocation failure", "java/lang/OutOfMemoryError"); + +#define GET_HANDLE() \ + jclass _cls = (*env)->GetObjectClass(env, obj); \ + jfieldID _fid; \ + \ + BAILIF0(_cls); \ + BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "handle", "J")); \ + handle = (tjhandle)(size_t)(*env)->GetLongField(env, obj, _fid); + +#define SAFE_RELEASE(javaArray, cArray) { \ + if (javaArray && cArray) \ + (*env)->ReleasePrimitiveArrayCritical(env, javaArray, (void *)cArray, 0); \ + cArray = NULL; \ +} + +/* TurboJPEG 1.2.x: TJ::bufSize() */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize + (JNIEnv *env, jclass cls, jint width, jint height, jint jpegSubsamp) +{ + size_t retval = tj3JPEGBufSize(width, height, jpegSubsamp); + + if (retval == 0) THROW_ARG(tj3GetErrorStr(NULL)); + if (retval > (size_t)INT_MAX) + THROW_ARG("Image is too large"); + +bailout: + return (jint)retval; +} + +/* TurboJPEG 1.4.x: TJ::bufSizeYUV() */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII + (JNIEnv *env, jclass cls, jint width, jint align, jint height, jint subsamp) +{ + size_t retval = tj3YUVBufSize(width, align, height, subsamp); + + if (retval == 0) THROW_ARG(tj3GetErrorStr(NULL)); + if (retval > (size_t)INT_MAX) + THROW_ARG("Image is too large"); + +bailout: + return (jint)retval; +} + +/* TurboJPEG 1.4.x: TJ::planeSizeYUV() */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII + (JNIEnv *env, jclass cls, jint componentID, jint width, jint stride, + jint height, jint subsamp) +{ + size_t retval = tj3YUVPlaneSize(componentID, width, stride, height, subsamp); + + if (retval == 0) THROW_ARG(tj3GetErrorStr(NULL)); + if (retval > (size_t)INT_MAX) + THROW_ARG("Image is too large"); + +bailout: + return (jint)retval; +} + +/* TurboJPEG 1.4.x: TJ::planeWidth() */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeWidth__III + (JNIEnv *env, jclass cls, jint componentID, jint width, jint subsamp) +{ + jint retval = (jint)tj3YUVPlaneWidth(componentID, width, subsamp); + + if (retval == 0) THROW_ARG(tj3GetErrorStr(NULL)); + +bailout: + return retval; +} + +/* TurboJPEG 1.4.x: TJ::planeHeight() */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III + (JNIEnv *env, jclass cls, jint componentID, jint height, jint subsamp) +{ + jint retval = (jint)tj3YUVPlaneHeight(componentID, height, subsamp); + + if (retval == 0) THROW_ARG(tj3GetErrorStr(NULL)); + +bailout: + return retval; +} + +/* TurboJPEG 1.2.x: TJCompressor::init() */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init + (JNIEnv *env, jobject obj) +{ + jclass cls; + jfieldID fid; + tjhandle handle; + + if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL) + THROW(tj3GetErrorStr(NULL), "org/libjpegturbo/turbojpeg/TJException"); + + BAILIF0(cls = (*env)->GetObjectClass(env, obj)); + BAILIF0(fid = (*env)->GetFieldID(env, cls, "handle", "J")); + (*env)->SetLongField(env, obj, fid, (size_t)handle); + +bailout: + return; +} + +/* TurboJPEG 3: TJCompressor::set() */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_set + (JNIEnv *env, jobject obj, jint param, jint value) +{ + tjhandle handle = 0; + + GET_HANDLE(); + + if (tj3Set(handle, param, value) == -1) + THROW_TJ(); + +bailout: + return; +} + +/* TurboJPEG 3: TJCompressor::get() */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_get + (JNIEnv *env, jobject obj, jint param) +{ + tjhandle handle = 0; + + GET_HANDLE(); + + return tj3Get(handle, param); + +bailout: + return -1; +} + +static jint TJCompressor_compress + (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint precision, + jint x, jint y, jint width, jint pitch, jint height, jint pf, + jbyteArray dst) +{ + tjhandle handle = 0; + size_t jpegSize = 0; + jsize arraySize = 0, actualPitch; + void *srcBuf = NULL; + unsigned char *jpegBuf = NULL; + int jpegSubsamp; + + GET_HANDLE(); + + if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF || width < 1 || + height < 1 || pitch < 0) + THROW_ARG("Invalid argument in compress*()"); + if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF) + THROW_ARG("Mismatch between Java and C API"); + + actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch; + arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf]; + if ((*env)->GetArrayLength(env, src) * srcElementSize < arraySize) + THROW_ARG("Source buffer is not large enough"); + jpegSubsamp = tj3Get(handle, TJPARAM_SUBSAMP); + if (tj3Get(handle, TJPARAM_LOSSLESS) && jpegSubsamp != TJSAMP_GRAY) + jpegSubsamp = TJSAMP_444; + else if (jpegSubsamp == TJSAMP_UNKNOWN) + THROW_ARG("TJPARAM_SUBSAMP must be specified"); + jpegSize = tj3JPEGBufSize(width, height, jpegSubsamp); + if ((*env)->GetArrayLength(env, dst) < (jsize)jpegSize) + THROW_ARG("Destination buffer is not large enough"); + + if (tj3Set(handle, TJPARAM_NOREALLOC, 1) == -1) + THROW_TJ(); + + BAILIF0NOEC(srcBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0)); + BAILIF0NOEC(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0)); + + if (precision == 8) { + if (tj3Compress8(handle, &((unsigned char *)srcBuf)[y * actualPitch + + x * tjPixelSize[pf]], + width, pitch, height, pf, &jpegBuf, &jpegSize) == -1) { + SAFE_RELEASE(dst, jpegBuf); + SAFE_RELEASE(src, srcBuf); + THROW_TJ(); + } + } else if (precision == 12) { + if (tj3Compress12(handle, &((short *)srcBuf)[y * actualPitch + + x * tjPixelSize[pf]], + width, pitch, height, pf, &jpegBuf, &jpegSize) == -1) { + SAFE_RELEASE(dst, jpegBuf); + SAFE_RELEASE(src, srcBuf); + THROW_TJ(); + } + } else { + if (tj3Compress16(handle, &((unsigned short *)srcBuf)[y * actualPitch + + x * tjPixelSize[pf]], + width, pitch, height, pf, &jpegBuf, &jpegSize) == -1) { + SAFE_RELEASE(dst, jpegBuf); + SAFE_RELEASE(src, srcBuf); + THROW_TJ(); + } + } + +bailout: + SAFE_RELEASE(dst, jpegBuf); + SAFE_RELEASE(src, srcBuf); + return (jint)jpegSize; +} + +/* TurboJPEG 3: TJCompressor::compress8() byte source */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress8___3BIIIIII_3B + (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width, + jint pitch, jint height, jint pf, jbyteArray dst) +{ + return TJCompressor_compress(env, obj, src, 1, 8, x, y, width, pitch, height, + pf, dst); +} + +/* TurboJPEG 3: TJCompressor::compress12() */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress12 + (JNIEnv *env, jobject obj, jshortArray src, jint x, jint y, jint width, + jint pitch, jint height, jint pf, jbyteArray dst) +{ + return TJCompressor_compress(env, obj, src, 1, 12, x, y, width, pitch, + height, pf, dst); +} + +/* TurboJPEG 3: TJCompressor::compress16() */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress16 + (JNIEnv *env, jobject obj, jshortArray src, jint x, jint y, jint width, + jint pitch, jint height, jint pf, jbyteArray dst) +{ + return TJCompressor_compress(env, obj, src, 1, 16, x, y, width, pitch, + height, pf, dst); +} + +/* TurboJPEG 3: TJCompressor::compress8() int source */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress8___3IIIIIII_3B + (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width, + jint stride, jint height, jint pf, jbyteArray dst) +{ + if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF) + THROW_ARG("Invalid argument in compress8()"); + if (tjPixelSize[pf] != sizeof(jint)) + THROW_ARG("Pixel format must be 32-bit when compressing from an integer buffer."); + + return TJCompressor_compress(env, obj, src, sizeof(jint), 8, x, y, width, + stride * sizeof(jint), height, pf, dst); + +bailout: + return 0; +} + +/* TurboJPEG 3: TJCompressor::compressFromYUV8() */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV8 + (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets, + jint width, jintArray jSrcStrides, jint height, jbyteArray dst) +{ + tjhandle handle = 0; + size_t jpegSize = 0; + jbyteArray jSrcPlanes[3] = { NULL, NULL, NULL }; + const unsigned char *srcPlanesTmp[3] = { NULL, NULL, NULL }; + const unsigned char *srcPlanes[3] = { NULL, NULL, NULL }; + jint srcOffsetsTmp[3] = { 0, 0, 0 }, srcStridesTmp[3] = { 0, 0, 0 }; + int srcOffsets[3] = { 0, 0, 0 }, srcStrides[3] = { 0, 0, 0 }; + unsigned char *jpegBuf = NULL; + int nc = 0, i, subsamp; + + GET_HANDLE(); + + if (org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP) + THROW_ARG("Mismatch between Java and C API"); + + if ((subsamp = tj3Get(handle, TJPARAM_SUBSAMP)) == TJSAMP_UNKNOWN) + THROW_ARG("TJPARAM_SUBSAMP must be specified"); + nc = subsamp == TJSAMP_GRAY ? 1 : 3; + if ((*env)->GetArrayLength(env, srcobjs) < nc) + THROW_ARG("Planes array is too small for the subsampling type"); + if ((*env)->GetArrayLength(env, jSrcOffsets) < nc) + THROW_ARG("Offsets array is too small for the subsampling type"); + if ((*env)->GetArrayLength(env, jSrcStrides) < nc) + THROW_ARG("Strides array is too small for the subsampling type"); + + jpegSize = tj3JPEGBufSize(width, height, subsamp); + if ((*env)->GetArrayLength(env, dst) < (jsize)jpegSize) + THROW_ARG("Destination buffer is not large enough"); + + if (tj3Set(handle, TJPARAM_NOREALLOC, 1) == -1) + THROW_TJ(); + + (*env)->GetIntArrayRegion(env, jSrcOffsets, 0, nc, srcOffsetsTmp); + if ((*env)->ExceptionCheck(env)) goto bailout; + for (i = 0; i < 3; i++) + srcOffsets[i] = srcOffsetsTmp[i]; + + (*env)->GetIntArrayRegion(env, jSrcStrides, 0, nc, srcStridesTmp); + if ((*env)->ExceptionCheck(env)) goto bailout; + for (i = 0; i < 3; i++) + srcStrides[i] = srcStridesTmp[i]; + + for (i = 0; i < nc; i++) { + size_t planeSize = tj3YUVPlaneSize(i, width, srcStrides[i], height, + subsamp); + int pw = tj3YUVPlaneWidth(i, width, subsamp); + + if (planeSize == 0 || pw == 0) + THROW_ARG(tj3GetErrorStr(NULL)); + + if (planeSize > (size_t)INT_MAX) + THROW_ARG("Source plane is too large"); + if (srcOffsets[i] < 0) + THROW_ARG("Invalid argument in compressFromYUV8()"); + if (srcStrides[i] < 0 && srcOffsets[i] - (int)planeSize + pw < 0) + THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary"); + + BAILIF0(jSrcPlanes[i] = (*env)->GetObjectArrayElement(env, srcobjs, i)); + if ((*env)->GetArrayLength(env, jSrcPlanes[i]) < + srcOffsets[i] + (int)planeSize) + THROW_ARG("Source plane is not large enough"); + } + for (i = 0; i < nc; i++) { + BAILIF0NOEC(srcPlanesTmp[i] = + (*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i], 0)); + srcPlanes[i] = &srcPlanesTmp[i][srcOffsets[i]]; + } + BAILIF0NOEC(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0)); + + if (tj3CompressFromYUVPlanes8(handle, srcPlanes, width, srcStrides, height, + &jpegBuf, &jpegSize) == -1) { + SAFE_RELEASE(dst, jpegBuf); + for (i = 0; i < nc; i++) + SAFE_RELEASE(jSrcPlanes[i], srcPlanesTmp[i]); + THROW_TJ(); + } + +bailout: + SAFE_RELEASE(dst, jpegBuf); + for (i = 0; i < nc; i++) + SAFE_RELEASE(jSrcPlanes[i], srcPlanesTmp[i]); + return (jint)jpegSize; +} + +static void TJCompressor_encodeYUV8 + (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y, + jint width, jint pitch, jint height, jint pf, jobjectArray dstobjs, + jintArray jDstOffsets, jintArray jDstStrides) +{ + tjhandle handle = 0; + jsize arraySize = 0, actualPitch; + unsigned char *srcBuf = NULL; + jbyteArray jDstPlanes[3] = { NULL, NULL, NULL }; + unsigned char *dstPlanesTmp[3] = { NULL, NULL, NULL }; + unsigned char *dstPlanes[3] = { NULL, NULL, NULL }; + jint dstOffsetsTmp[3] = { 0, 0, 0 }, dstStridesTmp[3] = { 0, 0, 0 }; + int dstOffsets[3] = { 0, 0, 0 }, dstStrides[3] = { 0, 0, 0 }; + int nc = 0, i, subsamp; + + GET_HANDLE(); + + if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF || width < 1 || + height < 1 || pitch < 0) + THROW_ARG("Invalid argument in encodeYUV8()"); + if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF || + org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP) + THROW_ARG("Mismatch between Java and C API"); + + if ((subsamp = tj3Get(handle, TJPARAM_SUBSAMP)) == TJSAMP_UNKNOWN) + THROW_ARG("TJPARAM_SUBSAMP must be specified"); + nc = subsamp == TJSAMP_GRAY ? 1 : 3; + if ((*env)->GetArrayLength(env, dstobjs) < nc) + THROW_ARG("Planes array is too small for the subsampling type"); + if ((*env)->GetArrayLength(env, jDstOffsets) < nc) + THROW_ARG("Offsets array is too small for the subsampling type"); + if ((*env)->GetArrayLength(env, jDstStrides) < nc) + THROW_ARG("Strides array is too small for the subsampling type"); + + actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch; + arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf]; + if ((*env)->GetArrayLength(env, src) * srcElementSize < arraySize) + THROW_ARG("Source buffer is not large enough"); + + (*env)->GetIntArrayRegion(env, jDstOffsets, 0, nc, dstOffsetsTmp); + if ((*env)->ExceptionCheck(env)) goto bailout; + for (i = 0; i < 3; i++) + dstOffsets[i] = dstOffsetsTmp[i]; + + (*env)->GetIntArrayRegion(env, jDstStrides, 0, nc, dstStridesTmp); + if ((*env)->ExceptionCheck(env)) goto bailout; + for (i = 0; i < 3; i++) + dstStrides[i] = dstStridesTmp[i]; + + for (i = 0; i < nc; i++) { + size_t planeSize = tj3YUVPlaneSize(i, width, dstStrides[i], height, + subsamp); + int pw = tj3YUVPlaneWidth(i, width, subsamp); + + if (planeSize == 0 || pw == 0) + THROW_ARG(tj3GetErrorStr(NULL)); + + if (planeSize > (size_t)INT_MAX) + THROW_ARG("Destination plane is too large"); + if (dstOffsets[i] < 0) + THROW_ARG("Invalid argument in encodeYUV8()"); + if (dstStrides[i] < 0 && dstOffsets[i] - (int)planeSize + pw < 0) + THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary"); + + BAILIF0(jDstPlanes[i] = (*env)->GetObjectArrayElement(env, dstobjs, i)); + if ((*env)->GetArrayLength(env, jDstPlanes[i]) < + dstOffsets[i] + (int)planeSize) + THROW_ARG("Destination plane is not large enough"); + } + for (i = 0; i < nc; i++) { + BAILIF0NOEC(dstPlanesTmp[i] = + (*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i], 0)); + dstPlanes[i] = &dstPlanesTmp[i][dstOffsets[i]]; + } + BAILIF0NOEC(srcBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0)); + + if (tj3EncodeYUVPlanes8(handle, + &srcBuf[y * actualPitch + x * tjPixelSize[pf]], + width, pitch, height, pf, dstPlanes, + dstStrides) == -1) { + SAFE_RELEASE(src, srcBuf); + for (i = 0; i < nc; i++) + SAFE_RELEASE(jDstPlanes[i], dstPlanesTmp[i]); + THROW_TJ(); + } + +bailout: + SAFE_RELEASE(src, srcBuf); + for (i = 0; i < nc; i++) + SAFE_RELEASE(jDstPlanes[i], dstPlanesTmp[i]); +} + +/* TurboJPEG 3: TJCompressor::encodeYUV8() byte source */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV8___3BIIIIII_3_3B_3I_3I + (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width, + jint pitch, jint height, jint pf, jobjectArray dstobjs, + jintArray jDstOffsets, jintArray jDstStrides) +{ + TJCompressor_encodeYUV8(env, obj, src, 1, x, y, width, pitch, height, pf, + dstobjs, jDstOffsets, jDstStrides); +} + +/* TurboJPEG 3: TJCompressor::encodeYUV8() int source */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV8___3IIIIIII_3_3B_3I_3I + (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width, + jint stride, jint height, jint pf, jobjectArray dstobjs, + jintArray jDstOffsets, jintArray jDstStrides) +{ + if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF) + THROW_ARG("Invalid argument in encodeYUV8()"); + if (tjPixelSize[pf] != sizeof(jint)) + THROW_ARG("Pixel format must be 32-bit when encoding from an integer buffer."); + + TJCompressor_encodeYUV8(env, obj, src, sizeof(jint), x, y, width, + stride * sizeof(jint), height, pf, dstobjs, + jDstOffsets, jDstStrides); + +bailout: + return; +} + +/* TurboJPEG 1.2.x: TJCompressor::destroy() */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy + (JNIEnv *env, jobject obj) +{ + tjhandle handle = 0; + + GET_HANDLE(); + + tj3Destroy(handle); + (*env)->SetLongField(env, obj, _fid, 0); + +bailout: + return; +} + +/* TurboJPEG 1.2.x: TJDecompressor::init() */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init + (JNIEnv *env, jobject obj) +{ + jclass cls; + jfieldID fid; + tjhandle handle; + + if ((handle = tj3Init(TJINIT_DECOMPRESS)) == NULL) + THROW(tj3GetErrorStr(NULL), "org/libjpegturbo/turbojpeg/TJException"); + + BAILIF0(cls = (*env)->GetObjectClass(env, obj)); + BAILIF0(fid = (*env)->GetFieldID(env, cls, "handle", "J")); + (*env)->SetLongField(env, obj, fid, (size_t)handle); + +bailout: + return; +} + +/* TurboJPEG 3: TJDecompressor::set() */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_set + (JNIEnv *env, jobject obj, jint param, jint value) +{ + Java_org_libjpegturbo_turbojpeg_TJCompressor_set(env, obj, param, value); +} + +/* TurboJPEG 3: TJDecompressor::get() */ +JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_get + (JNIEnv *env, jobject obj, jint param) +{ + return Java_org_libjpegturbo_turbojpeg_TJCompressor_get(env, obj, param); +} + +/* TurboJPEG 1.2.x: TJDecompressor::getScalingFactors() */ +JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors + (JNIEnv *env, jclass cls) +{ + jclass sfcls = NULL; + jfieldID fid = 0; + tjscalingfactor *sf = NULL; + int n = 0, i; + jobject sfobj = NULL; + jobjectArray sfjava = NULL; + + if ((sf = tj3GetScalingFactors(&n)) == NULL || n == 0) + THROW_ARG(tj3GetErrorStr(NULL)); + + BAILIF0(sfcls = (*env)->FindClass(env, + "org/libjpegturbo/turbojpeg/TJScalingFactor")); + BAILIF0(sfjava = (jobjectArray)(*env)->NewObjectArray(env, n, sfcls, 0)); + + for (i = 0; i < n; i++) { + BAILIF0(sfobj = (*env)->AllocObject(env, sfcls)); + BAILIF0(fid = (*env)->GetFieldID(env, sfcls, "num", "I")); + (*env)->SetIntField(env, sfobj, fid, sf[i].num); + BAILIF0(fid = (*env)->GetFieldID(env, sfcls, "denom", "I")); + (*env)->SetIntField(env, sfobj, fid, sf[i].denom); + (*env)->SetObjectArrayElement(env, sfjava, i, sfobj); + } + +bailout: + return sfjava; +} + +/* TurboJPEG 1.2.x: TJDecompressor::decompressHeader() */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader + (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize) +{ + tjhandle handle = 0; + unsigned char *jpegBuf = NULL; + + GET_HANDLE(); + + if ((*env)->GetArrayLength(env, src) < jpegSize) + THROW_ARG("Source buffer is not large enough"); + + BAILIF0NOEC(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0)); + + if (tj3DecompressHeader(handle, jpegBuf, (size_t)jpegSize) == -1) { + SAFE_RELEASE(src, jpegBuf); + THROW_TJ(); + } + +bailout: + SAFE_RELEASE(src, jpegBuf); +} + +/* TurboJPEG 3: TJDecompressor::setCroppingRegion() */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_setCroppingRegion + (JNIEnv *env, jobject obj) +{ + tjhandle handle = 0; + jclass sfcls, crcls; + jobject sfobj, crobj; + tjregion croppingRegion; + tjscalingfactor scalingFactor; + + GET_HANDLE(); + + BAILIF0(sfcls = (*env)->FindClass(env, + "org/libjpegturbo/turbojpeg/TJScalingFactor")); + BAILIF0(_fid = + (*env)->GetFieldID(env, _cls, "scalingFactor", + "Lorg/libjpegturbo/turbojpeg/TJScalingFactor;")); + BAILIF0(sfobj = (*env)->GetObjectField(env, obj, _fid)); + BAILIF0(_fid = (*env)->GetFieldID(env, sfcls, "num", "I")); + scalingFactor.num = (*env)->GetIntField(env, sfobj, _fid); + BAILIF0(_fid = (*env)->GetFieldID(env, sfcls, "denom", "I")); + scalingFactor.denom = (*env)->GetIntField(env, sfobj, _fid); + + if (tj3SetScalingFactor(handle, scalingFactor) == -1) + THROW_TJ(); + + BAILIF0(crcls = (*env)->FindClass(env, "java/awt/Rectangle")); + BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "croppingRegion", + "Ljava/awt/Rectangle;")); + BAILIF0(crobj = (*env)->GetObjectField(env, obj, _fid)); + BAILIF0(_fid = (*env)->GetFieldID(env, crcls, "x", "I")); + croppingRegion.x = (*env)->GetIntField(env, crobj, _fid); + BAILIF0(_fid = (*env)->GetFieldID(env, crcls, "y", "I")); + croppingRegion.y = (*env)->GetIntField(env, crobj, _fid); + BAILIF0(_fid = (*env)->GetFieldID(env, crcls, "width", "I")); + croppingRegion.w = (*env)->GetIntField(env, crobj, _fid); + BAILIF0(_fid = (*env)->GetFieldID(env, crcls, "height", "I")); + croppingRegion.h = (*env)->GetIntField(env, crobj, _fid); + + if (tj3SetCroppingRegion(handle, croppingRegion) == -1) + THROW_TJ(); + +bailout: + return; +} + +static void TJDecompressor_decompress + (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jarray dst, + jint dstElementSize, int precision, jint x, jint y, jint pitch, jint pf) +{ + tjhandle handle = 0; + jsize arraySize = 0, actualPitch; + unsigned char *jpegBuf = NULL; + void *dstBuf = NULL; + jclass sfcls, crcls; + jobject sfobj, crobj; + tjscalingfactor scalingFactor; + tjregion cr; + int jpegWidth, jpegHeight, scaledWidth, scaledHeight; + + GET_HANDLE(); + + if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF) + THROW_ARG("Invalid argument in decompress*()"); + if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF) + THROW_ARG("Mismatch between Java and C API"); + + if ((*env)->GetArrayLength(env, src) < jpegSize) + THROW_ARG("Source buffer is not large enough"); + if ((jpegWidth = tj3Get(handle, TJPARAM_JPEGWIDTH)) == -1) + THROW_ARG("JPEG header has not yet been read"); + if ((jpegHeight = tj3Get(handle, TJPARAM_JPEGHEIGHT)) == -1) + THROW_ARG("JPEG header has not yet been read"); + + BAILIF0(sfcls = (*env)->FindClass(env, + "org/libjpegturbo/turbojpeg/TJScalingFactor")); + BAILIF0(_fid = + (*env)->GetFieldID(env, _cls, "scalingFactor", + "Lorg/libjpegturbo/turbojpeg/TJScalingFactor;")); + BAILIF0(sfobj = (*env)->GetObjectField(env, obj, _fid)); + BAILIF0(_fid = (*env)->GetFieldID(env, sfcls, "num", "I")); + scalingFactor.num = (*env)->GetIntField(env, sfobj, _fid); + BAILIF0(_fid = (*env)->GetFieldID(env, sfcls, "denom", "I")); + scalingFactor.denom = (*env)->GetIntField(env, sfobj, _fid); + + if (tj3SetScalingFactor(handle, scalingFactor) == -1) + THROW_TJ(); + scaledWidth = TJSCALED(jpegWidth, scalingFactor); + scaledHeight = TJSCALED(jpegHeight, scalingFactor); + + BAILIF0(crcls = (*env)->FindClass(env, "java/awt/Rectangle")); + BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "croppingRegion", + "Ljava/awt/Rectangle;")); + BAILIF0(crobj = (*env)->GetObjectField(env, obj, _fid)); + BAILIF0(_fid = (*env)->GetFieldID(env, crcls, "x", "I")); + cr.x = (*env)->GetIntField(env, crobj, _fid); + BAILIF0(_fid = (*env)->GetFieldID(env, crcls, "y", "I")); + cr.y = (*env)->GetIntField(env, crobj, _fid); + BAILIF0(_fid = (*env)->GetFieldID(env, crcls, "width", "I")); + cr.w = (*env)->GetIntField(env, crobj, _fid); + BAILIF0(_fid = (*env)->GetFieldID(env, crcls, "height", "I")); + cr.h = (*env)->GetIntField(env, crobj, _fid); + if (cr.x != 0 || cr.y != 0 || cr.w != 0 || cr.h != 0) { + scaledWidth = cr.w ? cr.w : scaledWidth - cr.x; + scaledHeight = cr.h ? cr.h : scaledHeight - cr.y; + } + + actualPitch = (pitch == 0) ? scaledWidth * tjPixelSize[pf] : pitch; + arraySize = (y + scaledHeight - 1) * actualPitch + + (x + scaledWidth) * tjPixelSize[pf]; + if ((*env)->GetArrayLength(env, dst) * dstElementSize < arraySize) + THROW_ARG("Destination buffer is not large enough"); + + BAILIF0NOEC(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0)); + BAILIF0NOEC(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0)); + + if (precision == 8) { + if (tj3Decompress8(handle, jpegBuf, (size_t)jpegSize, + &((unsigned char *)dstBuf)[y * actualPitch + + x * tjPixelSize[pf]], + pitch, pf) == -1) { + SAFE_RELEASE(dst, dstBuf); + SAFE_RELEASE(src, jpegBuf); + THROW_TJ(); + } + } else if (precision == 12) { + if (tj3Decompress12(handle, jpegBuf, (size_t)jpegSize, + &((short *)dstBuf)[y * actualPitch + + x * tjPixelSize[pf]], + pitch, pf) == -1) { + SAFE_RELEASE(dst, dstBuf); + SAFE_RELEASE(src, jpegBuf); + THROW_TJ(); + } + } else { + if (tj3Decompress16(handle, jpegBuf, (size_t)jpegSize, + &((unsigned short *)dstBuf)[y * actualPitch + + x * tjPixelSize[pf]], + pitch, pf) == -1) { + SAFE_RELEASE(dst, dstBuf); + SAFE_RELEASE(src, jpegBuf); + THROW_TJ(); + } + } + +bailout: + SAFE_RELEASE(dst, dstBuf); + SAFE_RELEASE(src, jpegBuf); +} + +/* TurboJPEG 3: TJDecompressor::decompress8() byte destination */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress8___3BI_3BIIII + (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst, + jint x, jint y, jint pitch, jint pf) +{ + TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, 8, x, y, pitch, + pf); +} + +/* TurboJPEG 3: TJDecompressor::decompress12() */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress12 + (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jshortArray dst, + jint x, jint y, jint pitch, jint pf) +{ + TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, 12, x, y, pitch, + pf); +} + +/* TurboJPEG 3: TJDecompressor::decompress16() */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress16 + (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jshortArray dst, + jint x, jint y, jint pitch, jint pf) +{ + TJDecompressor_decompress(env, obj, src, jpegSize, dst, 1, 16, x, y, pitch, + pf); +} + +/* TurboJPEG 3: TJDecompressor::decompress8() int destination */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress8___3BI_3IIIII + (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst, + jint x, jint y, jint stride, jint pf) +{ + if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF) + THROW_ARG("Invalid argument in decompress8()"); + if (tjPixelSize[pf] != sizeof(jint)) + THROW_ARG("Pixel format must be 32-bit when decompressing to an integer buffer."); + + TJDecompressor_decompress(env, obj, src, jpegSize, dst, sizeof(jint), 8, x, + y, stride * sizeof(jint), pf); + +bailout: + return; +} + +/* TurboJPEG 3: TJDecompressor::decompressToYUV8() */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV8 + (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, + jobjectArray dstobjs, jintArray jDstOffsets, jintArray jDstStrides) +{ + tjhandle handle = 0; + unsigned char *jpegBuf = NULL; + jbyteArray jDstPlanes[3] = { NULL, NULL, NULL }; + unsigned char *dstPlanesTmp[3] = { NULL, NULL, NULL }; + unsigned char *dstPlanes[3] = { NULL, NULL, NULL }; + jint dstOffsetsTmp[3] = { 0, 0, 0 }, dstStridesTmp[3] = { 0, 0, 0 }; + int dstOffsets[3] = { 0, 0, 0 }, dstStrides[3] = { 0, 0, 0 }; + jclass sfcls; + jobject sfobj; + int jpegSubsamp, jpegWidth = 0, jpegHeight = 0; + int nc = 0, i, scaledWidth, scaledHeight; + tjscalingfactor scalingFactor; + + GET_HANDLE(); + + if ((*env)->GetArrayLength(env, src) < jpegSize) + THROW_ARG("Source buffer is not large enough"); + if ((jpegWidth = tj3Get(handle, TJPARAM_JPEGWIDTH)) == -1) + THROW_ARG("JPEG header has not yet been read"); + if ((jpegHeight = tj3Get(handle, TJPARAM_JPEGHEIGHT)) == -1) + THROW_ARG("JPEG header has not yet been read"); + + BAILIF0(sfcls = (*env)->FindClass(env, + "org/libjpegturbo/turbojpeg/TJScalingFactor")); + BAILIF0(_fid = + (*env)->GetFieldID(env, _cls, "scalingFactor", + "Lorg/libjpegturbo/turbojpeg/TJScalingFactor;")); + BAILIF0(sfobj = (*env)->GetObjectField(env, obj, _fid)); + BAILIF0(_fid = (*env)->GetFieldID(env, sfcls, "num", "I")); + scalingFactor.num = (*env)->GetIntField(env, sfobj, _fid); + BAILIF0(_fid = (*env)->GetFieldID(env, sfcls, "denom", "I")); + scalingFactor.denom = (*env)->GetIntField(env, sfobj, _fid); + + if (tj3SetScalingFactor(handle, scalingFactor) == -1) + THROW_TJ(); + scaledWidth = TJSCALED(jpegWidth, scalingFactor); + scaledHeight = TJSCALED(jpegHeight, scalingFactor); + + if ((jpegSubsamp = tj3Get(handle, TJPARAM_SUBSAMP)) == TJSAMP_UNKNOWN) + THROW_ARG("TJPARAM_SUBSAMP must be specified"); + nc = jpegSubsamp == TJSAMP_GRAY ? 1 : 3; + + (*env)->GetIntArrayRegion(env, jDstOffsets, 0, nc, dstOffsetsTmp); + if ((*env)->ExceptionCheck(env)) goto bailout; + for (i = 0; i < 3; i++) + dstOffsets[i] = dstOffsetsTmp[i]; + + (*env)->GetIntArrayRegion(env, jDstStrides, 0, nc, dstStridesTmp); + if ((*env)->ExceptionCheck(env)) goto bailout; + for (i = 0; i < 3; i++) + dstStrides[i] = dstStridesTmp[i]; + + for (i = 0; i < nc; i++) { + size_t planeSize = tj3YUVPlaneSize(i, scaledWidth, dstStrides[i], + scaledHeight, jpegSubsamp); + int pw = tj3YUVPlaneWidth(i, scaledWidth, jpegSubsamp); + + if (planeSize == 0 || pw == 0) + THROW_ARG(tj3GetErrorStr(NULL)); + + if (planeSize > (size_t)INT_MAX) + THROW_ARG("Destination plane is too large"); + if (dstOffsets[i] < 0) + THROW_ARG("Invalid argument in decompressToYUV8()"); + if (dstStrides[i] < 0 && dstOffsets[i] - (int)planeSize + pw < 0) + THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary"); + + BAILIF0(jDstPlanes[i] = (*env)->GetObjectArrayElement(env, dstobjs, i)); + if ((*env)->GetArrayLength(env, jDstPlanes[i]) < + dstOffsets[i] + (int)planeSize) + THROW_ARG("Destination plane is not large enough"); + } + for (i = 0; i < nc; i++) { + BAILIF0NOEC(dstPlanesTmp[i] = + (*env)->GetPrimitiveArrayCritical(env, jDstPlanes[i], 0)); + dstPlanes[i] = &dstPlanesTmp[i][dstOffsets[i]]; + } + BAILIF0NOEC(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, src, 0)); + + if (tj3DecompressToYUVPlanes8(handle, jpegBuf, (size_t)jpegSize, dstPlanes, + dstStrides) == -1) { + SAFE_RELEASE(src, jpegBuf); + for (i = 0; i < nc; i++) + SAFE_RELEASE(jDstPlanes[i], dstPlanesTmp[i]); + THROW_TJ(); + } + +bailout: + SAFE_RELEASE(src, jpegBuf); + for (i = 0; i < nc; i++) + SAFE_RELEASE(jDstPlanes[i], dstPlanesTmp[i]); +} + +static void TJDecompressor_decodeYUV8 + (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets, + jintArray jSrcStrides, jarray dst, jint dstElementSize, jint x, jint y, + jint width, jint pitch, jint height, jint pf) +{ + tjhandle handle = 0; + jsize arraySize = 0, actualPitch; + jbyteArray jSrcPlanes[3] = { NULL, NULL, NULL }; + const unsigned char *srcPlanesTmp[3] = { NULL, NULL, NULL }; + const unsigned char *srcPlanes[3] = { NULL, NULL, NULL }; + jint srcOffsetsTmp[3] = { 0, 0, 0 }, srcStridesTmp[3] = { 0, 0, 0 }; + int srcOffsets[3] = { 0, 0, 0 }, srcStrides[3] = { 0, 0, 0 }; + unsigned char *dstBuf = NULL; + int nc = 0, i, subsamp; + + GET_HANDLE(); + + if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF) + THROW_ARG("Invalid argument in decodeYUV8()"); + if (org_libjpegturbo_turbojpeg_TJ_NUMPF != TJ_NUMPF || + org_libjpegturbo_turbojpeg_TJ_NUMSAMP != TJ_NUMSAMP) + THROW_ARG("Mismatch between Java and C API"); + + if ((subsamp = tj3Get(handle, TJPARAM_SUBSAMP)) == TJSAMP_UNKNOWN) + THROW_ARG("TJPARAM_SUBSAMP must be specified"); + nc = subsamp == TJSAMP_GRAY ? 1 : 3; + if ((*env)->GetArrayLength(env, srcobjs) < nc) + THROW_ARG("Planes array is too small for the subsampling type"); + if ((*env)->GetArrayLength(env, jSrcOffsets) < nc) + THROW_ARG("Offsets array is too small for the subsampling type"); + if ((*env)->GetArrayLength(env, jSrcStrides) < nc) + THROW_ARG("Strides array is too small for the subsampling type"); + + actualPitch = (pitch == 0) ? width * tjPixelSize[pf] : pitch; + arraySize = (y + height - 1) * actualPitch + (x + width) * tjPixelSize[pf]; + if ((*env)->GetArrayLength(env, dst) * dstElementSize < arraySize) + THROW_ARG("Destination buffer is not large enough"); + + (*env)->GetIntArrayRegion(env, jSrcOffsets, 0, nc, srcOffsetsTmp); + if ((*env)->ExceptionCheck(env)) goto bailout; + for (i = 0; i < 3; i++) + srcOffsets[i] = srcOffsetsTmp[i]; + + (*env)->GetIntArrayRegion(env, jSrcStrides, 0, nc, srcStridesTmp); + if ((*env)->ExceptionCheck(env)) goto bailout; + for (i = 0; i < 3; i++) + srcStrides[i] = srcStridesTmp[i]; + + for (i = 0; i < nc; i++) { + size_t planeSize = tj3YUVPlaneSize(i, width, srcStrides[i], height, + subsamp); + int pw = tj3YUVPlaneWidth(i, width, subsamp); + + if (planeSize == 0 || pw == 0) + THROW_ARG(tj3GetErrorStr(NULL)); + + if (planeSize > (size_t)INT_MAX) + THROW_ARG("Source plane is too large"); + if (srcOffsets[i] < 0) + THROW_ARG("Invalid argument in decodeYUV8()"); + if (srcStrides[i] < 0 && srcOffsets[i] - (int)planeSize + pw < 0) + THROW_ARG("Negative plane stride would cause memory to be accessed below plane boundary"); + + BAILIF0(jSrcPlanes[i] = (*env)->GetObjectArrayElement(env, srcobjs, i)); + if ((*env)->GetArrayLength(env, jSrcPlanes[i]) < + srcOffsets[i] + (int)planeSize) + THROW_ARG("Source plane is not large enough"); + } + for (i = 0; i < nc; i++) { + BAILIF0NOEC(srcPlanesTmp[i] = + (*env)->GetPrimitiveArrayCritical(env, jSrcPlanes[i], 0)); + srcPlanes[i] = &srcPlanesTmp[i][srcOffsets[i]]; + } + BAILIF0NOEC(dstBuf = (*env)->GetPrimitiveArrayCritical(env, dst, 0)); + + if (tj3DecodeYUVPlanes8(handle, srcPlanes, srcStrides, + &dstBuf[y * actualPitch + x * tjPixelSize[pf]], + width, pitch, height, pf) == -1) { + SAFE_RELEASE(dst, dstBuf); + for (i = 0; i < nc; i++) + SAFE_RELEASE(jSrcPlanes[i], srcPlanesTmp[i]); + THROW_TJ(); + } + +bailout: + SAFE_RELEASE(dst, dstBuf); + for (i = 0; i < nc; i++) + SAFE_RELEASE(jSrcPlanes[i], srcPlanesTmp[i]); +} + +/* TurboJPEG 3: TJDecompressor::decodeYUV8() byte destination */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV8___3_3B_3I_3I_3BIIIIII + (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets, + jintArray jSrcStrides, jbyteArray dst, jint x, jint y, jint width, + jint pitch, jint height, jint pf) +{ + TJDecompressor_decodeYUV8(env, obj, srcobjs, jSrcOffsets, jSrcStrides, dst, + 1, x, y, width, pitch, height, pf); +} + +/* TurboJPEG 3: TJDecompressor::decodeYUV8() int destination */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV8___3_3B_3I_3I_3IIIIIII + (JNIEnv *env, jobject obj, jobjectArray srcobjs, jintArray jSrcOffsets, + jintArray jSrcStrides, jintArray dst, jint x, jint y, jint width, + jint stride, jint height, jint pf) +{ + if (pf < 0 || pf >= org_libjpegturbo_turbojpeg_TJ_NUMPF) + THROW_ARG("Invalid argument in decodeYUV8()"); + if (tjPixelSize[pf] != sizeof(jint)) + THROW_ARG("Pixel format must be 32-bit when decoding to an integer buffer."); + + TJDecompressor_decodeYUV8(env, obj, srcobjs, jSrcOffsets, jSrcStrides, dst, + sizeof(jint), x, y, width, stride * sizeof(jint), + height, pf); + +bailout: + return; +} + +/* TurboJPEG 1.2.x: TJTransformer::init() */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init + (JNIEnv *env, jobject obj) +{ + jclass cls; + jfieldID fid; + tjhandle handle; + + if ((handle = tj3Init(TJINIT_TRANSFORM)) == NULL) + THROW(tj3GetErrorStr(NULL), "org/libjpegturbo/turbojpeg/TJException"); + + BAILIF0(cls = (*env)->GetObjectClass(env, obj)); + BAILIF0(fid = (*env)->GetFieldID(env, cls, "handle", "J")); + (*env)->SetLongField(env, obj, fid, (size_t)handle); + +bailout: + return; +} + +typedef struct _JNICustomFilterParams { + JNIEnv *env; + jobject tobj; + jobject cfobj; +} JNICustomFilterParams; + +static int JNICustomFilter(short *coeffs, tjregion arrayRegion, + tjregion planeRegion, int componentIndex, + int transformIndex, tjtransform *transform) +{ + JNICustomFilterParams *params = (JNICustomFilterParams *)transform->data; + JNIEnv *env = params->env; + jobject tobj = params->tobj, cfobj = params->cfobj; + jobject arrayRegionObj, planeRegionObj, bufobj, borobj; + jclass cls; + jmethodID mid; + jfieldID fid; + + BAILIF0(bufobj = (*env)->NewDirectByteBuffer(env, coeffs, + sizeof(short) * arrayRegion.w * arrayRegion.h)); + BAILIF0(cls = (*env)->FindClass(env, "java/nio/ByteOrder")); + BAILIF0(mid = (*env)->GetStaticMethodID(env, cls, "nativeOrder", + "()Ljava/nio/ByteOrder;")); + BAILIF0(borobj = (*env)->CallStaticObjectMethod(env, cls, mid)); + BAILIF0(cls = (*env)->GetObjectClass(env, bufobj)); + BAILIF0(mid = (*env)->GetMethodID(env, cls, "order", + "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;")); + (*env)->CallObjectMethod(env, bufobj, mid, borobj); + BAILIF0(mid = (*env)->GetMethodID(env, cls, "asShortBuffer", + "()Ljava/nio/ShortBuffer;")); + BAILIF0(bufobj = (*env)->CallObjectMethod(env, bufobj, mid)); + + BAILIF0(cls = (*env)->FindClass(env, "java/awt/Rectangle")); + BAILIF0(arrayRegionObj = (*env)->AllocObject(env, cls)); + BAILIF0(fid = (*env)->GetFieldID(env, cls, "x", "I")); + (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.x); + BAILIF0(fid = (*env)->GetFieldID(env, cls, "y", "I")); + (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.y); + BAILIF0(fid = (*env)->GetFieldID(env, cls, "width", "I")); + (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.w); + BAILIF0(fid = (*env)->GetFieldID(env, cls, "height", "I")); + (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.h); + + BAILIF0(planeRegionObj = (*env)->AllocObject(env, cls)); + BAILIF0(fid = (*env)->GetFieldID(env, cls, "x", "I")); + (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.x); + BAILIF0(fid = (*env)->GetFieldID(env, cls, "y", "I")); + (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.y); + BAILIF0(fid = (*env)->GetFieldID(env, cls, "width", "I")); + (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.w); + BAILIF0(fid = (*env)->GetFieldID(env, cls, "height", "I")); + (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.h); + + BAILIF0(cls = (*env)->GetObjectClass(env, cfobj)); + BAILIF0(mid = (*env)->GetMethodID(env, cls, "customFilter", + "(Ljava/nio/ShortBuffer;Ljava/awt/Rectangle;Ljava/awt/Rectangle;IILorg/libjpegturbo/turbojpeg/TJTransform;)V")); + (*env)->CallVoidMethod(env, cfobj, mid, bufobj, arrayRegionObj, + planeRegionObj, componentIndex, transformIndex, tobj); + + return 0; + +bailout: + return -1; +} + +/* TurboJPEG 1.2.x: TJTransformer::transform() */ +JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transform + (JNIEnv *env, jobject obj, jbyteArray jsrcBuf, jint jpegSize, + jobjectArray dstobjs, jobjectArray tobjs) +{ + tjhandle handle = 0; + unsigned char *jpegBuf = NULL, **dstBufs = NULL; + jsize n = 0; + size_t *dstSizes = NULL; + tjtransform *t = NULL; + jbyteArray *jdstBufs = NULL; + int i, jpegWidth = 0, jpegHeight = 0, jpegSubsamp; + jintArray jdstSizes = 0; + jint *dstSizesi = NULL; + JNICustomFilterParams *params = NULL; + + GET_HANDLE(); + + if ((*env)->GetArrayLength(env, jsrcBuf) < jpegSize) + THROW_ARG("Source buffer is not large enough"); + if ((jpegWidth = tj3Get(handle, TJPARAM_JPEGWIDTH)) == -1) + THROW_ARG("JPEG header has not yet been read"); + if ((jpegHeight = tj3Get(handle, TJPARAM_JPEGHEIGHT)) == -1) + THROW_ARG("JPEG header has not yet been read"); + if ((jpegSubsamp = tj3Get(handle, TJPARAM_SUBSAMP)) == TJSAMP_UNKNOWN) + THROW_ARG("TJPARAM_SUBSAMP must be specified"); + + n = (*env)->GetArrayLength(env, dstobjs); + if (n != (*env)->GetArrayLength(env, tobjs)) + THROW_ARG("Mismatch between size of transforms array and destination buffers array"); + + if ((dstBufs = + (unsigned char **)malloc(sizeof(unsigned char *) * n)) == NULL) + THROW_MEM(); + if ((jdstBufs = (jbyteArray *)malloc(sizeof(jbyteArray) * n)) == NULL) + THROW_MEM(); + if ((dstSizes = (size_t *)malloc(sizeof(size_t) * n)) == NULL) + THROW_MEM(); + if ((t = (tjtransform *)malloc(sizeof(tjtransform) * n)) == NULL) + THROW_MEM(); + if ((params = (JNICustomFilterParams *)malloc(sizeof(JNICustomFilterParams) * + n)) == NULL) + THROW_MEM(); + for (i = 0; i < n; i++) { + dstBufs[i] = NULL; jdstBufs[i] = NULL; dstSizes[i] = 0; + memset(&t[i], 0, sizeof(tjtransform)); + memset(¶ms[i], 0, sizeof(JNICustomFilterParams)); + } + + for (i = 0; i < n; i++) { + jobject tobj, cfobj; + + BAILIF0(tobj = (*env)->GetObjectArrayElement(env, tobjs, i)); + BAILIF0(_cls = (*env)->GetObjectClass(env, tobj)); + BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "op", "I")); + t[i].op = (*env)->GetIntField(env, tobj, _fid); + BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "options", "I")); + t[i].options = (*env)->GetIntField(env, tobj, _fid); + BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "x", "I")); + t[i].r.x = (*env)->GetIntField(env, tobj, _fid); + BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "y", "I")); + t[i].r.y = (*env)->GetIntField(env, tobj, _fid); + BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "width", "I")); + t[i].r.w = (*env)->GetIntField(env, tobj, _fid); + BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "height", "I")); + t[i].r.h = (*env)->GetIntField(env, tobj, _fid); + + BAILIF0(_fid = (*env)->GetFieldID(env, _cls, "cf", + "Lorg/libjpegturbo/turbojpeg/TJCustomFilter;")); + cfobj = (*env)->GetObjectField(env, tobj, _fid); + if (cfobj) { + params[i].env = env; + params[i].tobj = tobj; + params[i].cfobj = cfobj; + t[i].customFilter = JNICustomFilter; + t[i].data = (void *)¶ms[i]; + } + } + + if (tj3Set(handle, TJPARAM_NOREALLOC, 1) == -1) + THROW_TJ(); + + for (i = 0; i < n; i++) { + int w = jpegWidth, h = jpegHeight; + + if (t[i].op == TJXOP_TRANSPOSE || t[i].op == TJXOP_TRANSVERSE || + t[i].op == TJXOP_ROT90 || t[i].op == TJXOP_ROT270) { + w = jpegHeight; h = jpegWidth; + } + if (t[i].r.w != 0) w = t[i].r.w; + if (t[i].r.h != 0) h = t[i].r.h; + BAILIF0(jdstBufs[i] = (*env)->GetObjectArrayElement(env, dstobjs, i)); + if ((size_t)(*env)->GetArrayLength(env, jdstBufs[i]) < + tj3JPEGBufSize(w, h, jpegSubsamp)) + THROW_ARG("Destination buffer is not large enough"); + } + BAILIF0NOEC(jpegBuf = (*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0)); + for (i = 0; i < n; i++) + BAILIF0NOEC(dstBufs[i] = + (*env)->GetPrimitiveArrayCritical(env, jdstBufs[i], 0)); + + if (tj3Transform(handle, jpegBuf, jpegSize, n, dstBufs, dstSizes, t) == -1) { + for (i = 0; i < n; i++) + SAFE_RELEASE(jdstBufs[i], dstBufs[i]); + SAFE_RELEASE(jsrcBuf, jpegBuf); + THROW_TJ(); + } + + for (i = 0; i < n; i++) + SAFE_RELEASE(jdstBufs[i], dstBufs[i]); + SAFE_RELEASE(jsrcBuf, jpegBuf); + + jdstSizes = (*env)->NewIntArray(env, n); + BAILIF0(dstSizesi = (*env)->GetIntArrayElements(env, jdstSizes, 0)); + for (i = 0; i < n; i++) dstSizesi[i] = (int)dstSizes[i]; + +bailout: + if (dstSizesi) (*env)->ReleaseIntArrayElements(env, jdstSizes, dstSizesi, 0); + if (dstBufs) { + for (i = 0; i < n; i++) { + if (dstBufs[i] && jdstBufs && jdstBufs[i]) + (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0); + } + free(dstBufs); + } + SAFE_RELEASE(jsrcBuf, jpegBuf); + free(jdstBufs); + free(dstSizes); + free(t); + return jdstSizes; +} + +/* TurboJPEG 1.2.x: TJDecompressor::destroy() */ +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy + (JNIEnv *env, jobject obj) +{ + Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy(env, obj); +} + +/* Private image I/O routines (used only by TJBench) */ +JNIEXPORT jobject JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_loadImage + (JNIEnv *env, jobject obj, jint precision, jstring jfilename, + jintArray jwidth, jint align, jintArray jheight, jintArray jpixelFormat) +{ + tjhandle handle = NULL; + void *dstBuf = NULL, *jdstPtr; + int width, *warr, height, *harr, pixelFormat, *pfarr, n; + const char *filename = NULL; + jboolean isCopy; + jobject jdstBuf = NULL; + + GET_HANDLE(); + + if ((precision != 8 && precision != 12 && precision != 16) || + jfilename == NULL || jwidth == NULL || + (*env)->GetArrayLength(env, jwidth) < 1 || jheight == NULL || + (*env)->GetArrayLength(env, jheight) < 1 || jpixelFormat == NULL || + (*env)->GetArrayLength(env, jpixelFormat) < 1) + THROW_ARG("Invalid argument in loadImage()"); + + BAILIF0NOEC(warr = (*env)->GetPrimitiveArrayCritical(env, jwidth, 0)); + width = warr[0]; + (*env)->ReleasePrimitiveArrayCritical(env, jwidth, warr, 0); + BAILIF0NOEC(harr = (*env)->GetPrimitiveArrayCritical(env, jheight, 0)); + height = harr[0]; + (*env)->ReleasePrimitiveArrayCritical(env, jheight, harr, 0); + BAILIF0NOEC(pfarr = (*env)->GetPrimitiveArrayCritical(env, jpixelFormat, 0)); + pixelFormat = pfarr[0]; + (*env)->ReleasePrimitiveArrayCritical(env, jpixelFormat, pfarr, 0); + BAILIF0(filename = (*env)->GetStringUTFChars(env, jfilename, &isCopy)); + + if (precision == 8) { + if ((dstBuf = tj3LoadImage8(handle, filename, &width, align, &height, + &pixelFormat)) == NULL) + THROW_TJ(); + } else if (precision == 12) { + if ((dstBuf = tj3LoadImage12(handle, filename, &width, align, &height, + &pixelFormat)) == NULL) + THROW_TJ(); + } else { + if ((dstBuf = tj3LoadImage16(handle, filename, &width, align, &height, + &pixelFormat)) == NULL) + THROW_TJ(); + } + + (*env)->ReleaseStringUTFChars(env, jfilename, filename); + filename = NULL; + + if ((unsigned long long)width * (unsigned long long)height * + (unsigned long long)tjPixelSize[pixelFormat] > + (unsigned long long)((unsigned int)-1)) + THROW_ARG("Image is too large"); + + BAILIF0NOEC(warr = (*env)->GetPrimitiveArrayCritical(env, jwidth, 0)); + warr[0] = width; + (*env)->ReleasePrimitiveArrayCritical(env, jwidth, warr, 0); + BAILIF0NOEC(harr = (*env)->GetPrimitiveArrayCritical(env, jheight, 0)); + harr[0] = height; + (*env)->ReleasePrimitiveArrayCritical(env, jheight, harr, 0); + BAILIF0NOEC(pfarr = (*env)->GetPrimitiveArrayCritical(env, jpixelFormat, 0)); + pfarr[0] = pixelFormat; + (*env)->ReleasePrimitiveArrayCritical(env, jpixelFormat, pfarr, 0); + + n = width * height * tjPixelSize[pixelFormat]; + if (precision == 8) + jdstBuf = (*env)->NewByteArray(env, n); + else + jdstBuf = (*env)->NewShortArray(env, n); + BAILIF0NOEC(jdstPtr = (*env)->GetPrimitiveArrayCritical(env, jdstBuf, 0)); + memcpy(jdstPtr, dstBuf, n * (precision > 8 ? 2 : 1)); + (*env)->ReleasePrimitiveArrayCritical(env, jdstBuf, jdstPtr, 0); + +bailout: + if (filename) (*env)->ReleaseStringUTFChars(env, jfilename, filename); + tj3Free(dstBuf); + return jdstBuf; +} + + +JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_saveImage + (JNIEnv *env, jobject obj, jint precision, jstring jfilename, + jobject jsrcBuf, jint width, jint pitch, jint height, jint pixelFormat) +{ + tjhandle handle = NULL; + void *srcBuf = NULL, *jsrcPtr; + const char *filename = NULL; + int n; + jboolean isCopy; + + GET_HANDLE(); + + if ((precision != 8 && precision != 12 && precision != 16) || + jfilename == NULL || jsrcBuf == NULL || width < 1 || height < 1 || + pixelFormat < 0 || pixelFormat >= TJ_NUMPF) + THROW_ARG("Invalid argument in saveImage()"); + + if ((unsigned long long)width * (unsigned long long)height * + (unsigned long long)tjPixelSize[pixelFormat] > + (unsigned long long)((unsigned int)-1)) + THROW_ARG("Image is too large"); + n = width * height * tjPixelSize[pixelFormat]; + if ((*env)->GetArrayLength(env, jsrcBuf) < n) + THROW_ARG("Source buffer is not large enough"); + + if ((srcBuf = malloc(n * (precision > 8 ? 2 : 1))) == NULL) + THROW_MEM(); + + BAILIF0NOEC(jsrcPtr = (*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0)); + memcpy(srcBuf, jsrcPtr, n * (precision > 8 ? 2 : 1)); + (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jsrcPtr, 0); + BAILIF0(filename = (*env)->GetStringUTFChars(env, jfilename, &isCopy)); + + if (precision == 8) { + if (tj3SaveImage8(handle, filename, srcBuf, width, pitch, height, + pixelFormat) == -1) + THROW_TJ(); + } else if (precision == 12) { + if (tj3SaveImage12(handle, filename, srcBuf, width, pitch, height, + pixelFormat) == -1) + THROW_TJ(); + } else { + if (tj3SaveImage16(handle, filename, srcBuf, width, pitch, height, + pixelFormat) == -1) + THROW_TJ(); + } + +bailout: + if (filename) (*env)->ReleaseStringUTFChars(env, jfilename, filename); + free(srcBuf); +} diff --git a/3rdparty/libjpeg-turbo/src/turbojpeg-mapfile b/3rdparty/libjpeg-turbo/src/turbojpeg-mapfile new file mode 100644 index 000000000000..6aab87132adc --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/turbojpeg-mapfile @@ -0,0 +1,108 @@ +TURBOJPEG_1.0 +{ + global: + TJBUFSIZE; + tjCompress; + tjDecompress; + tjDecompressHeader; + tjDestroy; + tjGetErrorStr; + tjInitCompress; + tjInitDecompress; + local: + *; +}; + +TURBOJPEG_1.1 +{ + global: + TJBUFSIZEYUV; + tjDecompressHeader2; + tjDecompressToYUV; + tjEncodeYUV; +} TURBOJPEG_1.0; + +TURBOJPEG_1.2 +{ + global: + tjAlloc; + tjBufSize; + tjBufSizeYUV; + tjCompress2; + tjDecompress2; + tjEncodeYUV2; + tjFree; + tjGetScalingFactors; + tjInitTransform; + tjTransform; +} TURBOJPEG_1.1; + +TURBOJPEG_1.4 +{ + global: + tjBufSizeYUV2; + tjCompressFromYUV; + tjCompressFromYUVPlanes; + tjDecodeYUV; + tjDecodeYUVPlanes; + tjDecompressHeader3; + tjDecompressToYUV2; + tjDecompressToYUVPlanes; + tjEncodeYUV3; + tjEncodeYUVPlanes; + tjPlaneHeight; + tjPlaneSizeYUV; + tjPlaneWidth; +} TURBOJPEG_1.2; + +TURBOJPEG_2.0 +{ + global: + tjGetErrorCode; + tjGetErrorStr2; + tjLoadImage; + tjSaveImage; +} TURBOJPEG_1.4; + +TURBOJPEG_3 +{ + global: + tj3Alloc; + tj3Compress8; + tj3Compress12; + tj3Compress16; + tj3CompressFromYUV8; + tj3CompressFromYUVPlanes8; + tj3DecodeYUV8; + tj3DecodeYUVPlanes8; + tj3Decompress8; + tj3Decompress12; + tj3Decompress16; + tj3DecompressHeader; + tj3DecompressToYUV8; + tj3DecompressToYUVPlanes8; + tj3Destroy; + tj3EncodeYUV8; + tj3EncodeYUVPlanes8; + tj3Free; + tj3Get; + tj3GetErrorCode; + tj3GetErrorStr; + tj3GetScalingFactors; + tj3Init; + tj3JPEGBufSize; + tj3LoadImage8; + tj3LoadImage12; + tj3LoadImage16; + tj3SaveImage8; + tj3SaveImage12; + tj3SaveImage16; + tj3Set; + tj3SetCroppingRegion; + tj3SetScalingFactor; + tj3Transform; + tj3YUVBufSize; + tj3YUVPlaneHeight; + tj3YUVPlaneSize; + tj3YUVPlaneWidth; +} TURBOJPEG_2.0; diff --git a/3rdparty/libjpeg-turbo/src/turbojpeg-mapfile.jni b/3rdparty/libjpeg-turbo/src/turbojpeg-mapfile.jni new file mode 100644 index 000000000000..31be75085876 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/turbojpeg-mapfile.jni @@ -0,0 +1,142 @@ +TURBOJPEG_1.0 +{ + global: + TJBUFSIZE; + tjCompress; + tjDecompress; + tjDecompressHeader; + tjDestroy; + tjGetErrorStr; + tjInitCompress; + tjInitDecompress; + local: + *; +}; + +TURBOJPEG_1.1 +{ + global: + TJBUFSIZEYUV; + tjDecompressHeader2; + tjDecompressToYUV; + tjEncodeYUV; +} TURBOJPEG_1.0; + +TURBOJPEG_1.2 +{ + global: + tjAlloc; + tjBufSize; + tjBufSizeYUV; + tjCompress2; + tjDecompress2; + tjEncodeYUV2; + tjFree; + tjGetScalingFactors; + tjInitTransform; + tjTransform; + Java_org_libjpegturbo_turbojpeg_TJ_bufSize; + Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors; + Java_org_libjpegturbo_turbojpeg_TJCompressor_init; + Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_init; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy; + Java_org_libjpegturbo_turbojpeg_TJTransformer_init; + Java_org_libjpegturbo_turbojpeg_TJTransformer_transform; +} TURBOJPEG_1.1; + +TURBOJPEG_1.4 +{ + global: + tjBufSizeYUV2; + tjCompressFromYUV; + tjCompressFromYUVPlanes; + tjDecodeYUV; + tjDecodeYUVPlanes; + tjDecompressHeader3; + tjDecompressToYUV2; + tjDecompressToYUVPlanes; + tjEncodeYUV3; + tjEncodeYUVPlanes; + tjPlaneHeight; + tjPlaneSizeYUV; + tjPlaneWidth; + Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII; + Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III; + Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII; + Java_org_libjpegturbo_turbojpeg_TJ_planeWidth__III; +} TURBOJPEG_1.2; + +TURBOJPEG_2.0 +{ + global: + tjGetErrorCode; + tjGetErrorStr2; + tjLoadImage; + tjSaveImage; +} TURBOJPEG_1.4; + +TURBOJPEG_3 +{ + global: + tj3Alloc; + tj3Compress8; + tj3Compress12; + tj3Compress16; + tj3CompressFromYUV8; + tj3CompressFromYUVPlanes8; + tj3DecodeYUV8; + tj3DecodeYUVPlanes8; + tj3Decompress8; + tj3Decompress12; + tj3Decompress16; + tj3DecompressHeader; + tj3DecompressToYUV8; + tj3DecompressToYUVPlanes8; + tj3Destroy; + tj3EncodeYUV8; + tj3EncodeYUVPlanes8; + tj3Free; + tj3Get; + tj3GetErrorCode; + tj3GetErrorStr; + tj3GetScalingFactors; + tj3Init; + tj3JPEGBufSize; + tj3LoadImage8; + tj3LoadImage12; + tj3LoadImage16; + tj3SaveImage8; + tj3SaveImage12; + tj3SaveImage16; + tj3Set; + tj3SetCroppingRegion; + tj3SetScalingFactor; + tj3Transform; + tj3YUVBufSize; + tj3YUVPlaneHeight; + tj3YUVPlaneSize; + tj3YUVPlaneWidth; + Java_org_libjpegturbo_turbojpeg_TJCompressor_compress8___3BIIIIII_3B; + Java_org_libjpegturbo_turbojpeg_TJCompressor_compress8___3IIIIIII_3B; + Java_org_libjpegturbo_turbojpeg_TJCompressor_compress12; + Java_org_libjpegturbo_turbojpeg_TJCompressor_compress16; + Java_org_libjpegturbo_turbojpeg_TJCompressor_compressFromYUV8; + Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV8___3BIIIIII_3_3B_3I_3I; + Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV8___3IIIIIII_3_3B_3I_3I; + Java_org_libjpegturbo_turbojpeg_TJCompressor_get; + Java_org_libjpegturbo_turbojpeg_TJCompressor_loadImage; + Java_org_libjpegturbo_turbojpeg_TJCompressor_set; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV8___3_3B_3I_3I_3BIIIIII; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_decodeYUV8___3_3B_3I_3I_3IIIIIII; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress8___3BI_3BIIII; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress8___3BI_3IIIII; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress12; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress16; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV8; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_get; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_saveImage; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_set; + Java_org_libjpegturbo_turbojpeg_TJDecompressor_setCroppingRegion; +} TURBOJPEG_2.0; diff --git a/3rdparty/libjpeg-turbo/src/turbojpeg-mp.c b/3rdparty/libjpeg-turbo/src/turbojpeg-mp.c new file mode 100644 index 000000000000..d4b3c74c3976 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/turbojpeg-mp.c @@ -0,0 +1,541 @@ +/* + * Copyright (C)2009-2024 D. R. Commander. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* TurboJPEG API functions that must be compiled for multiple data + precisions */ + +#if BITS_IN_JSAMPLE == 8 +#define _JSAMPLE JSAMPLE +#define _JSAMPROW JSAMPROW +#define _buffer buffer +#define _jinit_read_ppm jinit_read_ppm +#define _jinit_write_ppm jinit_write_ppm +#define _jpeg_crop_scanline jpeg_crop_scanline +#define _jpeg_read_scanlines jpeg_read_scanlines +#define _jpeg_skip_scanlines jpeg_skip_scanlines +#define _jpeg_write_scanlines jpeg_write_scanlines +#elif BITS_IN_JSAMPLE == 12 +#define _JSAMPLE J12SAMPLE +#define _JSAMPROW J12SAMPROW +#define _buffer buffer12 +#define _jinit_read_ppm j12init_read_ppm +#define _jinit_write_ppm j12init_write_ppm +#define _jpeg_crop_scanline jpeg12_crop_scanline +#define _jpeg_read_scanlines jpeg12_read_scanlines +#define _jpeg_skip_scanlines jpeg12_skip_scanlines +#define _jpeg_write_scanlines jpeg12_write_scanlines +#elif BITS_IN_JSAMPLE == 16 +#define _JSAMPLE J16SAMPLE +#define _JSAMPROW J16SAMPROW +#define _buffer buffer16 +#define _jinit_read_ppm j16init_read_ppm +#define _jinit_write_ppm j16init_write_ppm +#define _jpeg_read_scanlines jpeg16_read_scanlines +#define _jpeg_write_scanlines jpeg16_write_scanlines +#endif + +#define _GET_NAME(name, suffix) name##suffix +#define GET_NAME(name, suffix) _GET_NAME(name, suffix) +#define _GET_STRING(name, suffix) #name #suffix +#define GET_STRING(name, suffix) _GET_STRING(name, suffix) + + +/******************************** Compressor *********************************/ + +/* TurboJPEG 3+ */ +DLLEXPORT int GET_NAME(tj3Compress, BITS_IN_JSAMPLE) + (tjhandle handle, const _JSAMPLE *srcBuf, int width, int pitch, int height, + int pixelFormat, unsigned char **jpegBuf, size_t *jpegSize) +{ + static const char FUNCTION_NAME[] = GET_STRING(tj3Compress, BITS_IN_JSAMPLE); + int i, retval = 0; + boolean alloc = TRUE; + _JSAMPROW *row_pointer = NULL; + + GET_CINSTANCE(handle) + if ((this->init & COMPRESS) == 0) + THROW("Instance has not been initialized for compression"); + + if (srcBuf == NULL || width <= 0 || pitch < 0 || height <= 0 || + pixelFormat < 0 || pixelFormat >= TJ_NUMPF || jpegBuf == NULL || + jpegSize == NULL) + THROW("Invalid argument"); + + if (!this->lossless && this->quality == -1) + THROW("TJPARAM_QUALITY must be specified"); + if (!this->lossless && this->subsamp == TJSAMP_UNKNOWN) + THROW("TJPARAM_SUBSAMP must be specified"); + + if (pitch == 0) pitch = width * tjPixelSize[pixelFormat]; + + if ((row_pointer = (_JSAMPROW *)malloc(sizeof(_JSAMPROW) * height)) == NULL) + THROW("Memory allocation failure"); + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + cinfo->image_width = width; + cinfo->image_height = height; + cinfo->data_precision = BITS_IN_JSAMPLE; + + setCompDefaults(this, pixelFormat); + if (this->noRealloc) { + alloc = FALSE; + *jpegSize = tj3JPEGBufSize(width, height, this->subsamp); + } + jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc); + + jpeg_start_compress(cinfo, TRUE); + for (i = 0; i < height; i++) { + if (this->bottomUp) + row_pointer[i] = (_JSAMPROW)&srcBuf[(height - i - 1) * (size_t)pitch]; + else + row_pointer[i] = (_JSAMPROW)&srcBuf[i * (size_t)pitch]; + } + while (cinfo->next_scanline < cinfo->image_height) + _jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline], + cinfo->image_height - cinfo->next_scanline); + jpeg_finish_compress(cinfo); + +bailout: + if (cinfo->global_state > CSTATE_START && alloc) + (*cinfo->dest->term_destination) (cinfo); + if (cinfo->global_state > CSTATE_START || retval == -1) + jpeg_abort_compress(cinfo); + free(row_pointer); + if (this->jerr.warning) retval = -1; + return retval; +} + + +/******************************* Decompressor ********************************/ + +/* TurboJPEG 3+ */ +DLLEXPORT int GET_NAME(tj3Decompress, BITS_IN_JSAMPLE) + (tjhandle handle, const unsigned char *jpegBuf, size_t jpegSize, + _JSAMPLE *dstBuf, int pitch, int pixelFormat) +{ + static const char FUNCTION_NAME[] = + GET_STRING(tj3Decompress, BITS_IN_JSAMPLE); + _JSAMPROW *row_pointer = NULL; + int croppedHeight, i, retval = 0; +#if BITS_IN_JSAMPLE != 16 + int scaledWidth; +#endif + struct my_progress_mgr progress; + + GET_DINSTANCE(handle); + if ((this->init & DECOMPRESS) == 0) + THROW("Instance has not been initialized for decompression"); + + if (jpegBuf == NULL || jpegSize <= 0 || dstBuf == NULL || pitch < 0 || + pixelFormat < 0 || pixelFormat >= TJ_NUMPF) + THROW("Invalid argument"); + + if (this->scanLimit) { + memset(&progress, 0, sizeof(struct my_progress_mgr)); + progress.pub.progress_monitor = my_progress_monitor; + progress.this = this; + dinfo->progress = &progress.pub; + } else + dinfo->progress = NULL; + + dinfo->mem->max_memory_to_use = (long)this->maxMemory * 1048576L; + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + if (dinfo->global_state <= DSTATE_INHEADER) { + jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); + jpeg_read_header(dinfo, TRUE); + } + setDecompParameters(this); + if (this->maxPixels && + (unsigned long long)this->jpegWidth * this->jpegHeight > + (unsigned long long)this->maxPixels) + THROW("Image is too large"); + this->dinfo.out_color_space = pf2cs[pixelFormat]; +#if BITS_IN_JSAMPLE != 16 + scaledWidth = TJSCALED(dinfo->image_width, this->scalingFactor); +#endif + dinfo->do_fancy_upsampling = !this->fastUpsample; + this->dinfo.dct_method = this->fastDCT ? JDCT_FASTEST : JDCT_ISLOW; + + dinfo->scale_num = this->scalingFactor.num; + dinfo->scale_denom = this->scalingFactor.denom; + + jpeg_start_decompress(dinfo); + +#if BITS_IN_JSAMPLE != 16 + if (this->croppingRegion.x != 0 || + (this->croppingRegion.w != 0 && this->croppingRegion.w != scaledWidth)) { + JDIMENSION crop_x = this->croppingRegion.x; + JDIMENSION crop_w = this->croppingRegion.w; + + _jpeg_crop_scanline(dinfo, &crop_x, &crop_w); + if ((int)crop_x != this->croppingRegion.x) + THROWI("Unexplained mismatch between specified (%d) and\n" + "actual (%d) cropping region left boundary", + this->croppingRegion.x, (int)crop_x); + if ((int)crop_w != this->croppingRegion.w) + THROWI("Unexplained mismatch between specified (%d) and\n" + "actual (%d) cropping region width", + this->croppingRegion.w, (int)crop_w); + } +#endif + + if (pitch == 0) pitch = dinfo->output_width * tjPixelSize[pixelFormat]; + + croppedHeight = dinfo->output_height; +#if BITS_IN_JSAMPLE != 16 + if (this->croppingRegion.y != 0 || this->croppingRegion.h != 0) + croppedHeight = this->croppingRegion.h; +#endif + if ((row_pointer = + (_JSAMPROW *)malloc(sizeof(_JSAMPROW) * croppedHeight)) == NULL) + THROW("Memory allocation failure"); + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + for (i = 0; i < (int)croppedHeight; i++) { + if (this->bottomUp) + row_pointer[i] = &dstBuf[(croppedHeight - i - 1) * (size_t)pitch]; + else + row_pointer[i] = &dstBuf[i * (size_t)pitch]; + } + +#if BITS_IN_JSAMPLE != 16 + if (this->croppingRegion.y != 0 || this->croppingRegion.h != 0) { + if (this->croppingRegion.y != 0) { + JDIMENSION lines = _jpeg_skip_scanlines(dinfo, this->croppingRegion.y); + + if ((int)lines != this->croppingRegion.y) + THROWI("Unexplained mismatch between specified (%d) and\n" + "actual (%d) cropping region upper boundary", + this->croppingRegion.y, (int)lines); + } + while ((int)dinfo->output_scanline < + this->croppingRegion.y + this->croppingRegion.h) + _jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline - + this->croppingRegion.y], + this->croppingRegion.y + this->croppingRegion.h - + dinfo->output_scanline); + if (this->croppingRegion.y + this->croppingRegion.h != + (int)dinfo->output_height) { + JDIMENSION lines = _jpeg_skip_scanlines(dinfo, dinfo->output_height - + this->croppingRegion.y - + this->croppingRegion.h); + + if (lines != dinfo->output_height - this->croppingRegion.y - + this->croppingRegion.h) + THROWI("Unexplained mismatch between specified (%d) and\n" + "actual (%d) cropping region lower boundary", + this->croppingRegion.y + this->croppingRegion.h, + (int)(dinfo->output_height - lines)); + } + } else +#endif + { + while (dinfo->output_scanline < dinfo->output_height) + _jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline], + dinfo->output_height - dinfo->output_scanline); + } + jpeg_finish_decompress(dinfo); + +bailout: + if (dinfo->global_state > DSTATE_START) jpeg_abort_decompress(dinfo); + free(row_pointer); + if (this->jerr.warning) retval = -1; + return retval; +} + + +/*************************** Packed-Pixel Image I/O **************************/ + +/* TurboJPEG 3+ */ +DLLEXPORT _JSAMPLE *GET_NAME(tj3LoadImage, BITS_IN_JSAMPLE) + (tjhandle handle, const char *filename, int *width, int align, int *height, + int *pixelFormat) +{ + static const char FUNCTION_NAME[] = + GET_STRING(tj3LoadImage, BITS_IN_JSAMPLE); + +#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) + + int retval = 0, tempc; + size_t pitch; + tjhandle handle2 = NULL; + tjinstance *this2; + j_compress_ptr cinfo = NULL; + cjpeg_source_ptr src; + _JSAMPLE *dstBuf = NULL; + FILE *file = NULL; + boolean invert; + + GET_TJINSTANCE(handle, NULL) + + if (!filename || !width || align < 1 || !height || !pixelFormat || + *pixelFormat < TJPF_UNKNOWN || *pixelFormat >= TJ_NUMPF) + THROW("Invalid argument"); + if ((align & (align - 1)) != 0) + THROW("Alignment must be a power of 2"); + + /* The instance handle passed to this function is used only for parameter + retrieval. Create a new temporary instance to avoid interfering with the + libjpeg state of the primary instance. */ + if ((handle2 = tj3Init(TJINIT_COMPRESS)) == NULL) return NULL; + this2 = (tjinstance *)handle2; + cinfo = &this2->cinfo; + +#ifdef _MSC_VER + if (fopen_s(&file, filename, "rb") || file == NULL) +#else + if ((file = fopen(filename, "rb")) == NULL) +#endif + THROW_UNIX("Cannot open input file"); + + if ((tempc = getc(file)) < 0 || ungetc(tempc, file) == EOF) + THROW_UNIX("Could not read input file") + else if (tempc == EOF) + THROW("Input file contains no data"); + + if (setjmp(this2->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + cinfo->data_precision = BITS_IN_JSAMPLE; + if (*pixelFormat == TJPF_UNKNOWN) cinfo->in_color_space = JCS_UNKNOWN; + else cinfo->in_color_space = pf2cs[*pixelFormat]; + if (tempc == 'B') { + if ((src = jinit_read_bmp(cinfo, FALSE)) == NULL) + THROW("Could not initialize bitmap loader"); + invert = !this->bottomUp; + } else if (tempc == 'P') { + if ((src = _jinit_read_ppm(cinfo)) == NULL) + THROW("Could not initialize PPM loader"); + invert = this->bottomUp; + } else + THROW("Unsupported file type"); + + cinfo->mem->max_memory_to_use = (long)this->maxMemory * 1048576L; + + src->input_file = file; + /* Refuse to load images larger than the specified size. */ + src->max_pixels = this->maxPixels; + (*src->start_input) (cinfo, src); + if (tempc == 'B') { + if (cinfo->X_density && cinfo->Y_density) { + this->xDensity = cinfo->X_density; + this->yDensity = cinfo->Y_density; + this->densityUnits = cinfo->density_unit; + } + } + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo); + + *width = cinfo->image_width; *height = cinfo->image_height; + *pixelFormat = cs2pf[cinfo->in_color_space]; + + pitch = PAD((*width) * tjPixelSize[*pixelFormat], align); + if ( +#if ULLONG_MAX > SIZE_MAX + (unsigned long long)pitch * (unsigned long long)(*height) > + (unsigned long long)((size_t)-1) || +#endif + (dstBuf = (_JSAMPLE *)malloc(pitch * (*height) * + sizeof(_JSAMPLE))) == NULL) + THROW("Memory allocation failure"); + + if (setjmp(this2->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + while (cinfo->next_scanline < cinfo->image_height) { + int i, nlines = (*src->get_pixel_rows) (cinfo, src); + + for (i = 0; i < nlines; i++) { + _JSAMPLE *dstptr; + int row; + + row = cinfo->next_scanline + i; + if (invert) dstptr = &dstBuf[((*height) - row - 1) * pitch]; + else dstptr = &dstBuf[row * pitch]; + memcpy(dstptr, src->_buffer[i], + (*width) * tjPixelSize[*pixelFormat] * sizeof(_JSAMPLE)); + } + cinfo->next_scanline += nlines; + } + + (*src->finish_input) (cinfo, src); + +bailout: + tj3Destroy(handle2); + if (file) fclose(file); + if (retval < 0) { free(dstBuf); dstBuf = NULL; } + return dstBuf; + +#else /* BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) */ + + static const char ERROR_MSG[] = + "16-bit data precision requires lossless JPEG,\n" + "which was disabled at build time."; + _JSAMPLE *retval = NULL; + + GET_TJINSTANCE(handle, NULL) + SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "%s(): %s", FUNCTION_NAME, + ERROR_MSG); + this->isInstanceError = TRUE; THROWG(ERROR_MSG, NULL) + +bailout: + return retval; + +#endif +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int GET_NAME(tj3SaveImage, BITS_IN_JSAMPLE) + (tjhandle handle, const char *filename, const _JSAMPLE *buffer, int width, + int pitch, int height, int pixelFormat) +{ + static const char FUNCTION_NAME[] = + GET_STRING(tj3SaveImage, BITS_IN_JSAMPLE); + int retval = 0; + +#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) + + tjhandle handle2 = NULL; + tjinstance *this2; + j_decompress_ptr dinfo = NULL; + djpeg_dest_ptr dst; + FILE *file = NULL; + char *ptr = NULL; + boolean invert; + + GET_TJINSTANCE(handle, -1) + + if (!filename || !buffer || width < 1 || pitch < 0 || height < 1 || + pixelFormat < 0 || pixelFormat >= TJ_NUMPF) + THROW("Invalid argument"); + + /* The instance handle passed to this function is used only for parameter + retrieval. Create a new temporary instance to avoid interfering with the + libjpeg state of the primary instance. */ + if ((handle2 = tj3Init(TJINIT_DECOMPRESS)) == NULL) + return -1; + this2 = (tjinstance *)handle2; + dinfo = &this2->dinfo; + +#ifdef _MSC_VER + if (fopen_s(&file, filename, "wb") || file == NULL) +#else + if ((file = fopen(filename, "wb")) == NULL) +#endif + THROW_UNIX("Cannot open output file"); + + if (setjmp(this2->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + this2->dinfo.out_color_space = pf2cs[pixelFormat]; + dinfo->image_width = width; dinfo->image_height = height; + dinfo->global_state = DSTATE_READY; + dinfo->scale_num = dinfo->scale_denom = 1; + dinfo->data_precision = BITS_IN_JSAMPLE; + + ptr = strrchr(filename, '.'); + if (ptr && !strcasecmp(ptr, ".bmp")) { + if ((dst = jinit_write_bmp(dinfo, FALSE, FALSE)) == NULL) + THROW("Could not initialize bitmap writer"); + invert = !this->bottomUp; + dinfo->X_density = (UINT16)this->xDensity; + dinfo->Y_density = (UINT16)this->yDensity; + dinfo->density_unit = (UINT8)this->densityUnits; + } else { + if ((dst = _jinit_write_ppm(dinfo)) == NULL) + THROW("Could not initialize PPM writer"); + invert = this->bottomUp; + } + + dinfo->mem->max_memory_to_use = (long)this->maxMemory * 1048576L; + + dst->output_file = file; + (*dst->start_output) (dinfo, dst); + (*dinfo->mem->realize_virt_arrays) ((j_common_ptr)dinfo); + + if (pitch == 0) pitch = width * tjPixelSize[pixelFormat]; + + while (dinfo->output_scanline < dinfo->output_height) { + _JSAMPLE *rowptr; + + if (invert) + rowptr = + (_JSAMPLE *)&buffer[(height - dinfo->output_scanline - 1) * pitch]; + else + rowptr = (_JSAMPLE *)&buffer[dinfo->output_scanline * pitch]; + memcpy(dst->_buffer[0], rowptr, + width * tjPixelSize[pixelFormat] * sizeof(_JSAMPLE)); + (*dst->put_pixel_rows) (dinfo, dst, 1); + dinfo->output_scanline++; + } + + (*dst->finish_output) (dinfo, dst); + +bailout: + tj3Destroy(handle2); + if (file) fclose(file); + return retval; + +#else /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */ + + GET_TJINSTANCE(handle, -1) + THROW("16-bit data precision requires lossless JPEG,\n" + "which was disabled at build time.") +bailout: + return retval; + +#endif +} + + +#undef _JSAMPLE +#undef _JSAMPROW +#undef _buffer +#undef _jinit_read_ppm +#undef _jinit_write_ppm +#undef _jpeg_crop_scanline +#undef _jpeg_read_scanlines +#undef _jpeg_skip_scanlines +#undef _jpeg_write_scanlines diff --git a/3rdparty/libjpeg-turbo/src/turbojpeg.c b/3rdparty/libjpeg-turbo/src/turbojpeg.c new file mode 100644 index 000000000000..3c936160dfbe --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/turbojpeg.c @@ -0,0 +1,2921 @@ +/* + * Copyright (C)2009-2024 D. R. Commander. All Rights Reserved. + * Copyright (C)2021 Alex Richardson. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* TurboJPEG/LJT: this implements the TurboJPEG API using libjpeg or + libjpeg-turbo */ + +#include +#include +#if !defined(_MSC_VER) || _MSC_VER > 1600 +#include +#endif +#include +#define JPEG_INTERNALS +#include +#include +#include +#include +#include "./turbojpeg.h" +#include "./tjutil.h" +#include "transupp.h" +#include "./jpegapicomp.h" +#include "./cdjpeg.h" + +extern void jpeg_mem_dest_tj(j_compress_ptr, unsigned char **, size_t *, + boolean); +extern void jpeg_mem_src_tj(j_decompress_ptr, const unsigned char *, size_t); + +#define PAD(v, p) ((v + (p) - 1) & (~((p) - 1))) +#define IS_POW2(x) (((x) & (x - 1)) == 0) + + +/* Error handling (based on example in example.c) */ + +static THREAD_LOCAL char errStr[JMSG_LENGTH_MAX] = "No error"; + +struct my_error_mgr { + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; + void (*emit_message) (j_common_ptr, int); + boolean warning, stopOnWarning; +}; +typedef struct my_error_mgr *my_error_ptr; + +#define JMESSAGE(code, string) string, +static const char *turbojpeg_message_table[] = { +#include "cderror.h" + NULL +}; + +static void my_error_exit(j_common_ptr cinfo) +{ + my_error_ptr myerr = (my_error_ptr)cinfo->err; + + (*cinfo->err->output_message) (cinfo); + longjmp(myerr->setjmp_buffer, 1); +} + +/* Based on output_message() in jerror.c */ + +static void my_output_message(j_common_ptr cinfo) +{ + (*cinfo->err->format_message) (cinfo, errStr); +} + +static void my_emit_message(j_common_ptr cinfo, int msg_level) +{ + my_error_ptr myerr = (my_error_ptr)cinfo->err; + + myerr->emit_message(cinfo, msg_level); + if (msg_level < 0) { + myerr->warning = TRUE; + if (myerr->stopOnWarning) longjmp(myerr->setjmp_buffer, 1); + } +} + + +/********************** Global structures, macros, etc. **********************/ + +enum { COMPRESS = 1, DECOMPRESS = 2 }; + +typedef struct _tjinstance { + struct jpeg_compress_struct cinfo; + struct jpeg_decompress_struct dinfo; + struct my_error_mgr jerr; + int init; + char errStr[JMSG_LENGTH_MAX]; + boolean isInstanceError; + /* Parameters */ + boolean bottomUp; + boolean noRealloc; + int quality; + int subsamp; + int jpegWidth; + int jpegHeight; + int precision; + int colorspace; + boolean fastUpsample; + boolean fastDCT; + boolean optimize; + boolean progressive; + int scanLimit; + boolean arithmetic; + boolean lossless; + int losslessPSV; + int losslessPt; + int restartIntervalBlocks; + int restartIntervalRows; + int xDensity; + int yDensity; + int densityUnits; + tjscalingfactor scalingFactor; + tjregion croppingRegion; + int maxMemory; + int maxPixels; +} tjinstance; + +static tjhandle _tjInitCompress(tjinstance *this); +static tjhandle _tjInitDecompress(tjinstance *this); + +struct my_progress_mgr { + struct jpeg_progress_mgr pub; + tjinstance *this; +}; +typedef struct my_progress_mgr *my_progress_ptr; + +static void my_progress_monitor(j_common_ptr dinfo) +{ + my_error_ptr myerr = (my_error_ptr)dinfo->err; + my_progress_ptr myprog = (my_progress_ptr)dinfo->progress; + + if (dinfo->is_decompressor) { + int scan_no = ((j_decompress_ptr)dinfo)->input_scan_number; + + if (scan_no > myprog->this->scanLimit) { + SNPRINTF(myprog->this->errStr, JMSG_LENGTH_MAX, + "Progressive JPEG image has more than %d scans", + myprog->this->scanLimit); + SNPRINTF(errStr, JMSG_LENGTH_MAX, + "Progressive JPEG image has more than %d scans", + myprog->this->scanLimit); + myprog->this->isInstanceError = TRUE; + myerr->warning = FALSE; + longjmp(myerr->setjmp_buffer, 1); + } + } +} + +static const JXFORM_CODE xformtypes[TJ_NUMXOP] = { + JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE, + JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270 +}; + +#define NUMSF 16 +static const tjscalingfactor sf[NUMSF] = { + { 2, 1 }, + { 15, 8 }, + { 7, 4 }, + { 13, 8 }, + { 3, 2 }, + { 11, 8 }, + { 5, 4 }, + { 9, 8 }, + { 1, 1 }, + { 7, 8 }, + { 3, 4 }, + { 5, 8 }, + { 1, 2 }, + { 3, 8 }, + { 1, 4 }, + { 1, 8 } +}; + +static J_COLOR_SPACE pf2cs[TJ_NUMPF] = { + JCS_EXT_RGB, JCS_EXT_BGR, JCS_EXT_RGBX, JCS_EXT_BGRX, JCS_EXT_XBGR, + JCS_EXT_XRGB, JCS_GRAYSCALE, JCS_EXT_RGBA, JCS_EXT_BGRA, JCS_EXT_ABGR, + JCS_EXT_ARGB, JCS_CMYK +}; + +static int cs2pf[JPEG_NUMCS] = { + TJPF_UNKNOWN, TJPF_GRAY, +#if RGB_RED == 0 && RGB_GREEN == 1 && RGB_BLUE == 2 && RGB_PIXELSIZE == 3 + TJPF_RGB, +#elif RGB_RED == 2 && RGB_GREEN == 1 && RGB_BLUE == 0 && RGB_PIXELSIZE == 3 + TJPF_BGR, +#elif RGB_RED == 0 && RGB_GREEN == 1 && RGB_BLUE == 2 && RGB_PIXELSIZE == 4 + TJPF_RGBX, +#elif RGB_RED == 2 && RGB_GREEN == 1 && RGB_BLUE == 0 && RGB_PIXELSIZE == 4 + TJPF_BGRX, +#elif RGB_RED == 3 && RGB_GREEN == 2 && RGB_BLUE == 1 && RGB_PIXELSIZE == 4 + TJPF_XBGR, +#elif RGB_RED == 1 && RGB_GREEN == 2 && RGB_BLUE == 3 && RGB_PIXELSIZE == 4 + TJPF_XRGB, +#endif + TJPF_UNKNOWN, TJPF_CMYK, TJPF_UNKNOWN, TJPF_RGB, TJPF_RGBX, TJPF_BGR, + TJPF_BGRX, TJPF_XBGR, TJPF_XRGB, TJPF_RGBA, TJPF_BGRA, TJPF_ABGR, TJPF_ARGB, + TJPF_UNKNOWN +}; + +#define THROWG(m, rv) { \ + SNPRINTF(errStr, JMSG_LENGTH_MAX, "%s(): %s", FUNCTION_NAME, m); \ + retval = rv; goto bailout; \ +} +#ifdef _MSC_VER +#define THROW_UNIX(m) { \ + char strerrorBuf[80] = { 0 }; \ + strerror_s(strerrorBuf, 80, errno); \ + SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "%s(): %s\n%s", FUNCTION_NAME, m, \ + strerrorBuf); \ + this->isInstanceError = TRUE; \ + SNPRINTF(errStr, JMSG_LENGTH_MAX, "%s(): %s\n%s", FUNCTION_NAME, m, \ + strerrorBuf); \ + retval = -1; goto bailout; \ +} +#else +#define THROW_UNIX(m) { \ + SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "%s(): %s\n%s", FUNCTION_NAME, m, \ + strerror(errno)); \ + this->isInstanceError = TRUE; \ + SNPRINTF(errStr, JMSG_LENGTH_MAX, "%s(): %s\n%s", FUNCTION_NAME, m, \ + strerror(errno)); \ + retval = -1; goto bailout; \ +} +#endif +#define THROW(m) { \ + SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "%s(): %s", FUNCTION_NAME, m); \ + this->isInstanceError = TRUE; THROWG(m, -1) \ +} +#define THROWI(format, val1, val2) { \ + SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "%s(): " format, FUNCTION_NAME, \ + val1, val2); \ + this->isInstanceError = TRUE; \ + SNPRINTF(errStr, JMSG_LENGTH_MAX, "%s(): " format, FUNCTION_NAME, val1, \ + val2); \ + retval = -1; goto bailout; \ +} + +#define GET_INSTANCE(handle) \ + tjinstance *this = (tjinstance *)handle; \ + j_compress_ptr cinfo = NULL; \ + j_decompress_ptr dinfo = NULL; \ + \ + if (!this) { \ + SNPRINTF(errStr, JMSG_LENGTH_MAX, "%s(): Invalid handle", FUNCTION_NAME); \ + return -1; \ + } \ + cinfo = &this->cinfo; dinfo = &this->dinfo; \ + this->jerr.warning = FALSE; \ + this->isInstanceError = FALSE; + +#define GET_CINSTANCE(handle) \ + tjinstance *this = (tjinstance *)handle; \ + j_compress_ptr cinfo = NULL; \ + \ + if (!this) { \ + SNPRINTF(errStr, JMSG_LENGTH_MAX, "%s(): Invalid handle", FUNCTION_NAME); \ + return -1; \ + } \ + cinfo = &this->cinfo; \ + this->jerr.warning = FALSE; \ + this->isInstanceError = FALSE; + +#define GET_DINSTANCE(handle) \ + tjinstance *this = (tjinstance *)handle; \ + j_decompress_ptr dinfo = NULL; \ + \ + if (!this) { \ + SNPRINTF(errStr, JMSG_LENGTH_MAX, "%s(): Invalid handle", FUNCTION_NAME); \ + return -1; \ + } \ + dinfo = &this->dinfo; \ + this->jerr.warning = FALSE; \ + this->isInstanceError = FALSE; + +#define GET_TJINSTANCE(handle, errorReturn) \ + tjinstance *this = (tjinstance *)handle; \ + \ + if (!this) { \ + SNPRINTF(errStr, JMSG_LENGTH_MAX, "%s(): Invalid handle", FUNCTION_NAME); \ + return errorReturn; \ + } \ + this->jerr.warning = FALSE; \ + this->isInstanceError = FALSE; + +static int getPixelFormat(int pixelSize, int flags) +{ + if (pixelSize == 1) return TJPF_GRAY; + if (pixelSize == 3) { + if (flags & TJ_BGR) return TJPF_BGR; + else return TJPF_RGB; + } + if (pixelSize == 4) { + if (flags & TJ_ALPHAFIRST) { + if (flags & TJ_BGR) return TJPF_XBGR; + else return TJPF_XRGB; + } else { + if (flags & TJ_BGR) return TJPF_BGRX; + else return TJPF_RGBX; + } + } + return -1; +} + +static void setCompDefaults(tjinstance *this, int pixelFormat) +{ + this->cinfo.in_color_space = pf2cs[pixelFormat]; + this->cinfo.input_components = tjPixelSize[pixelFormat]; + jpeg_set_defaults(&this->cinfo); + + this->cinfo.restart_interval = this->restartIntervalBlocks; + this->cinfo.restart_in_rows = this->restartIntervalRows; + this->cinfo.X_density = (UINT16)this->xDensity; + this->cinfo.Y_density = (UINT16)this->yDensity; + this->cinfo.density_unit = (UINT8)this->densityUnits; + this->cinfo.mem->max_memory_to_use = (long)this->maxMemory * 1048576L; + + if (this->lossless) { +#ifdef C_LOSSLESS_SUPPORTED + jpeg_enable_lossless(&this->cinfo, this->losslessPSV, this->losslessPt); +#endif + if (pixelFormat == TJPF_GRAY) + this->subsamp = TJSAMP_GRAY; + else if (this->subsamp != TJSAMP_GRAY) + this->subsamp = TJSAMP_444; + return; + } + + jpeg_set_quality(&this->cinfo, this->quality, TRUE); + this->cinfo.dct_method = this->fastDCT ? JDCT_FASTEST : JDCT_ISLOW; + + switch (this->colorspace) { + case TJCS_RGB: + jpeg_set_colorspace(&this->cinfo, JCS_RGB); break; + case TJCS_YCbCr: + jpeg_set_colorspace(&this->cinfo, JCS_YCbCr); break; + case TJCS_GRAY: + jpeg_set_colorspace(&this->cinfo, JCS_GRAYSCALE); break; + case TJCS_CMYK: + jpeg_set_colorspace(&this->cinfo, JCS_CMYK); break; + case TJCS_YCCK: + jpeg_set_colorspace(&this->cinfo, JCS_YCCK); break; + default: + if (this->subsamp == TJSAMP_GRAY) + jpeg_set_colorspace(&this->cinfo, JCS_GRAYSCALE); + else if (pixelFormat == TJPF_CMYK) + jpeg_set_colorspace(&this->cinfo, JCS_YCCK); + else + jpeg_set_colorspace(&this->cinfo, JCS_YCbCr); + } + + if (this->cinfo.data_precision == 8) + this->cinfo.optimize_coding = this->optimize; +#ifdef C_PROGRESSIVE_SUPPORTED + if (this->progressive) jpeg_simple_progression(&this->cinfo); +#endif + this->cinfo.arith_code = this->arithmetic; + + this->cinfo.comp_info[0].h_samp_factor = tjMCUWidth[this->subsamp] / 8; + this->cinfo.comp_info[1].h_samp_factor = 1; + this->cinfo.comp_info[2].h_samp_factor = 1; + if (this->cinfo.num_components > 3) + this->cinfo.comp_info[3].h_samp_factor = tjMCUWidth[this->subsamp] / 8; + this->cinfo.comp_info[0].v_samp_factor = tjMCUHeight[this->subsamp] / 8; + this->cinfo.comp_info[1].v_samp_factor = 1; + this->cinfo.comp_info[2].v_samp_factor = 1; + if (this->cinfo.num_components > 3) + this->cinfo.comp_info[3].v_samp_factor = tjMCUHeight[this->subsamp] / 8; +} + + +static int getSubsamp(j_decompress_ptr dinfo) +{ + int retval = TJSAMP_UNKNOWN, i, k; + + /* The sampling factors actually have no meaning with grayscale JPEG files, + and in fact it's possible to generate grayscale JPEGs with sampling + factors > 1 (even though those sampling factors are ignored by the + decompressor.) Thus, we need to treat grayscale as a special case. */ + if (dinfo->num_components == 1 && dinfo->jpeg_color_space == JCS_GRAYSCALE) + return TJSAMP_GRAY; + + for (i = 0; i < TJ_NUMSAMP; i++) { + if (i == TJSAMP_GRAY) continue; + + if (dinfo->num_components == 3 || + ((dinfo->jpeg_color_space == JCS_YCCK || + dinfo->jpeg_color_space == JCS_CMYK) && + dinfo->num_components == 4)) { + if (dinfo->comp_info[0].h_samp_factor == tjMCUWidth[i] / 8 && + dinfo->comp_info[0].v_samp_factor == tjMCUHeight[i] / 8) { + int match = 0; + + for (k = 1; k < dinfo->num_components; k++) { + int href = 1, vref = 1; + + if ((dinfo->jpeg_color_space == JCS_YCCK || + dinfo->jpeg_color_space == JCS_CMYK) && k == 3) { + href = tjMCUWidth[i] / 8; vref = tjMCUHeight[i] / 8; + } + if (dinfo->comp_info[k].h_samp_factor == href && + dinfo->comp_info[k].v_samp_factor == vref) + match++; + } + if (match == dinfo->num_components - 1) { + retval = i; break; + } + } + /* Handle 4:2:2 and 4:4:0 images whose sampling factors are specified + in non-standard ways. */ + if (dinfo->comp_info[0].h_samp_factor == 2 && + dinfo->comp_info[0].v_samp_factor == 2 && + (i == TJSAMP_422 || i == TJSAMP_440)) { + int match = 0; + + for (k = 1; k < dinfo->num_components; k++) { + int href = tjMCUHeight[i] / 8, vref = tjMCUWidth[i] / 8; + + if ((dinfo->jpeg_color_space == JCS_YCCK || + dinfo->jpeg_color_space == JCS_CMYK) && k == 3) { + href = vref = 2; + } + if (dinfo->comp_info[k].h_samp_factor == href && + dinfo->comp_info[k].v_samp_factor == vref) + match++; + } + if (match == dinfo->num_components - 1) { + retval = i; break; + } + } + /* Handle 4:4:4 images whose sampling factors are specified in + non-standard ways. */ + if (dinfo->comp_info[0].h_samp_factor * + dinfo->comp_info[0].v_samp_factor <= + D_MAX_BLOCKS_IN_MCU / 3 && i == TJSAMP_444) { + int match = 0; + for (k = 1; k < dinfo->num_components; k++) { + if (dinfo->comp_info[k].h_samp_factor == + dinfo->comp_info[0].h_samp_factor && + dinfo->comp_info[k].v_samp_factor == + dinfo->comp_info[0].v_samp_factor) + match++; + if (match == dinfo->num_components - 1) { + retval = i; break; + } + } + } + } + } + return retval; +} + + +static void setDecompParameters(tjinstance *this) +{ + this->subsamp = getSubsamp(&this->dinfo); + this->jpegWidth = this->dinfo.image_width; + this->jpegHeight = this->dinfo.image_height; + this->precision = this->dinfo.data_precision; + switch (this->dinfo.jpeg_color_space) { + case JCS_GRAYSCALE: this->colorspace = TJCS_GRAY; break; + case JCS_RGB: this->colorspace = TJCS_RGB; break; + case JCS_YCbCr: this->colorspace = TJCS_YCbCr; break; + case JCS_CMYK: this->colorspace = TJCS_CMYK; break; + case JCS_YCCK: this->colorspace = TJCS_YCCK; break; + default: this->colorspace = -1; break; + } + this->progressive = this->dinfo.progressive_mode; + this->arithmetic = this->dinfo.arith_code; + this->lossless = this->dinfo.master->lossless; + this->losslessPSV = this->dinfo.Ss; + this->losslessPt = this->dinfo.Al; + this->xDensity = this->dinfo.X_density; + this->yDensity = this->dinfo.Y_density; + this->densityUnits = this->dinfo.density_unit; +} + + +static void processFlags(tjhandle handle, int flags, int operation) +{ + tjinstance *this = (tjinstance *)handle; + + this->bottomUp = !!(flags & TJFLAG_BOTTOMUP); + +#ifndef NO_PUTENV + if (flags & TJFLAG_FORCEMMX) PUTENV_S("JSIMD_FORCEMMX", "1"); + else if (flags & TJFLAG_FORCESSE) PUTENV_S("JSIMD_FORCESSE", "1"); + else if (flags & TJFLAG_FORCESSE2) PUTENV_S("JSIMD_FORCESSE2", "1"); +#endif + + this->fastUpsample = !!(flags & TJFLAG_FASTUPSAMPLE); + this->noRealloc = !!(flags & TJFLAG_NOREALLOC); + + if (operation == COMPRESS) { + if (this->quality >= 96 || flags & TJFLAG_ACCURATEDCT) + this->fastDCT = FALSE; + else + this->fastDCT = TRUE; + } else + this->fastDCT = !!(flags & TJFLAG_FASTDCT); + + this->jerr.stopOnWarning = !!(flags & TJFLAG_STOPONWARNING); + this->progressive = !!(flags & TJFLAG_PROGRESSIVE); + + if (flags & TJFLAG_LIMITSCANS) this->scanLimit = 500; +} + + +/*************************** General API functions ***************************/ + +/* TurboJPEG 3+ */ +DLLEXPORT tjhandle tj3Init(int initType) +{ + static const char FUNCTION_NAME[] = "tj3Init"; + tjinstance *this = NULL; + tjhandle retval = NULL; + + if (initType < 0 || initType >= TJ_NUMINIT) + THROWG("Invalid argument", NULL); + + if ((this = (tjinstance *)malloc(sizeof(tjinstance))) == NULL) + THROWG("Memory allocation failure", NULL); + memset(this, 0, sizeof(tjinstance)); + SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "No error"); + + this->quality = -1; + this->subsamp = TJSAMP_UNKNOWN; + this->jpegWidth = -1; + this->jpegHeight = -1; + this->precision = 8; + this->colorspace = -1; + this->losslessPSV = 1; + this->xDensity = 1; + this->yDensity = 1; + this->scalingFactor = TJUNSCALED; + + switch (initType) { + case TJINIT_COMPRESS: return _tjInitCompress(this); + case TJINIT_DECOMPRESS: return _tjInitDecompress(this); + case TJINIT_TRANSFORM: + retval = _tjInitCompress(this); + if (!retval) return NULL; + retval = _tjInitDecompress(this); + return retval; + } + +bailout: + return retval; +} + + +#define SET_PARAM(field, minValue, maxValue) { \ + if (value < minValue || (maxValue > 0 && value > maxValue)) \ + THROW("Parameter value out of range"); \ + this->field = value; \ +} + +#define SET_BOOL_PARAM(field) { \ + if (value < 0 || value > 1) \ + THROW("Parameter value out of range"); \ + this->field = (boolean)value; \ +} + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3Set(tjhandle handle, int param, int value) +{ + static const char FUNCTION_NAME[] = "tj3Set"; + int retval = 0; + + GET_TJINSTANCE(handle, -1); + + switch (param) { + case TJPARAM_STOPONWARNING: + SET_BOOL_PARAM(jerr.stopOnWarning); + break; + case TJPARAM_BOTTOMUP: + SET_BOOL_PARAM(bottomUp); + break; + case TJPARAM_NOREALLOC: + if (!(this->init & COMPRESS)) + THROW("TJPARAM_NOREALLOC is not applicable to decompression instances."); + SET_BOOL_PARAM(noRealloc); + break; + case TJPARAM_QUALITY: + if (!(this->init & COMPRESS)) + THROW("TJPARAM_QUALITY is not applicable to decompression instances."); + SET_PARAM(quality, 1, 100); + break; + case TJPARAM_SUBSAMP: + SET_PARAM(subsamp, 0, TJ_NUMSAMP - 1); + break; + case TJPARAM_JPEGWIDTH: + if (!(this->init & DECOMPRESS)) + THROW("TJPARAM_JPEGWIDTH is not applicable to compression instances."); + THROW("TJPARAM_JPEGWIDTH is read-only in decompression instances."); + break; + case TJPARAM_JPEGHEIGHT: + if (!(this->init & DECOMPRESS)) + THROW("TJPARAM_JPEGHEIGHT is not applicable to compression instances."); + THROW("TJPARAM_JPEGHEIGHT is read-only in decompression instances."); + break; + case TJPARAM_PRECISION: + if (!(this->init & DECOMPRESS)) + THROW("TJPARAM_PRECISION is not applicable to compression instances."); + THROW("TJPARAM_PRECISION is read-only in decompression instances."); + break; + case TJPARAM_COLORSPACE: + if (!(this->init & COMPRESS)) + THROW("TJPARAM_COLORSPACE is read-only in decompression instances."); + SET_PARAM(colorspace, 0, TJ_NUMCS - 1); + break; + case TJPARAM_FASTUPSAMPLE: + if (!(this->init & DECOMPRESS)) + THROW("TJPARAM_FASTUPSAMPLE is not applicable to compression instances."); + SET_BOOL_PARAM(fastUpsample); + break; + case TJPARAM_FASTDCT: + SET_BOOL_PARAM(fastDCT); + break; + case TJPARAM_OPTIMIZE: + if (!(this->init & COMPRESS)) + THROW("TJPARAM_OPTIMIZE is not applicable to decompression instances."); + SET_BOOL_PARAM(optimize); + break; + case TJPARAM_PROGRESSIVE: + if (!(this->init & COMPRESS)) + THROW("TJPARAM_PROGRESSIVE is read-only in decompression instances."); + SET_BOOL_PARAM(progressive); + break; + case TJPARAM_SCANLIMIT: + if (!(this->init & DECOMPRESS)) + THROW("TJPARAM_SCANLIMIT is not applicable to compression instances."); + SET_PARAM(scanLimit, 0, -1); + break; + case TJPARAM_ARITHMETIC: + if (!(this->init & COMPRESS)) + THROW("TJPARAM_ARITHMETIC is read-only in decompression instances."); + SET_BOOL_PARAM(arithmetic); + break; + case TJPARAM_LOSSLESS: + if (!(this->init & COMPRESS)) + THROW("TJPARAM_LOSSLESS is read-only in decompression instances."); + SET_BOOL_PARAM(lossless); + break; + case TJPARAM_LOSSLESSPSV: + if (!(this->init & COMPRESS)) + THROW("TJPARAM_LOSSLESSPSV is read-only in decompression instances."); + SET_PARAM(losslessPSV, 1, 7); + break; + case TJPARAM_LOSSLESSPT: + if (!(this->init & COMPRESS)) + THROW("TJPARAM_LOSSLESSPT is read-only in decompression instances."); + SET_PARAM(losslessPt, 0, this->precision - 1); + break; + case TJPARAM_RESTARTBLOCKS: + if (!(this->init & COMPRESS)) + THROW("TJPARAM_RESTARTBLOCKS is not applicable to decompression instances."); + SET_PARAM(restartIntervalBlocks, 0, 65535); + if (value != 0) this->restartIntervalRows = 0; + break; + case TJPARAM_RESTARTROWS: + if (!(this->init & COMPRESS)) + THROW("TJPARAM_RESTARTROWS is not applicable to decompression instances."); + SET_PARAM(restartIntervalRows, 0, 65535); + if (value != 0) this->restartIntervalBlocks = 0; + break; + case TJPARAM_XDENSITY: + if (!(this->init & COMPRESS)) + THROW("TJPARAM_XDENSITY is read-only in decompression instances."); + SET_PARAM(xDensity, 1, 65535); + break; + case TJPARAM_YDENSITY: + if (!(this->init & COMPRESS)) + THROW("TJPARAM_YDENSITY is read-only in decompression instances."); + SET_PARAM(yDensity, 1, 65535); + break; + case TJPARAM_DENSITYUNITS: + if (!(this->init & COMPRESS)) + THROW("TJPARAM_DENSITYUNITS is read-only in decompression instances."); + SET_PARAM(densityUnits, 0, 2); + break; + case TJPARAM_MAXMEMORY: + SET_PARAM(maxMemory, 0, (int)(min(LONG_MAX / 1048576L, (long)INT_MAX))); + break; + case TJPARAM_MAXPIXELS: + SET_PARAM(maxPixels, 0, -1); + break; + default: + THROW("Invalid parameter"); + } + +bailout: + return retval; +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3Get(tjhandle handle, int param) +{ + tjinstance *this = (tjinstance *)handle; + if (!this) return -1; + + switch (param) { + case TJPARAM_STOPONWARNING: + return this->jerr.stopOnWarning; + case TJPARAM_BOTTOMUP: + return this->bottomUp; + case TJPARAM_NOREALLOC: + return this->noRealloc; + case TJPARAM_QUALITY: + return this->quality; + case TJPARAM_SUBSAMP: + return this->subsamp; + case TJPARAM_JPEGWIDTH: + return this->jpegWidth; + case TJPARAM_JPEGHEIGHT: + return this->jpegHeight; + case TJPARAM_PRECISION: + return this->precision; + case TJPARAM_COLORSPACE: + return this->colorspace; + case TJPARAM_FASTUPSAMPLE: + return this->fastUpsample; + case TJPARAM_FASTDCT: + return this->fastDCT; + case TJPARAM_OPTIMIZE: + return this->optimize; + case TJPARAM_PROGRESSIVE: + return this->progressive; + case TJPARAM_SCANLIMIT: + return this->scanLimit; + case TJPARAM_ARITHMETIC: + return this->arithmetic; + case TJPARAM_LOSSLESS: + return this->lossless; + case TJPARAM_LOSSLESSPSV: + return this->losslessPSV; + case TJPARAM_LOSSLESSPT: + return this->losslessPt; + case TJPARAM_RESTARTBLOCKS: + return this->restartIntervalBlocks; + case TJPARAM_RESTARTROWS: + return this->restartIntervalRows; + case TJPARAM_XDENSITY: + return this->xDensity; + case TJPARAM_YDENSITY: + return this->yDensity; + case TJPARAM_DENSITYUNITS: + return this->densityUnits; + case TJPARAM_MAXMEMORY: + return this->maxMemory; + case TJPARAM_MAXPIXELS: + return this->maxPixels; + } + + return -1; +} + + +/* TurboJPEG 3+ */ +DLLEXPORT char *tj3GetErrorStr(tjhandle handle) +{ + tjinstance *this = (tjinstance *)handle; + + if (this && this->isInstanceError) { + this->isInstanceError = FALSE; + return this->errStr; + } else + return errStr; +} + +/* TurboJPEG 2.0+ */ +DLLEXPORT char *tjGetErrorStr2(tjhandle handle) +{ + return tj3GetErrorStr(handle); +} + +/* TurboJPEG 1.0+ */ +DLLEXPORT char *tjGetErrorStr(void) +{ + return errStr; +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3GetErrorCode(tjhandle handle) +{ + tjinstance *this = (tjinstance *)handle; + + if (this && this->jerr.warning) return TJERR_WARNING; + else return TJERR_FATAL; +} + +/* TurboJPEG 2.0+ */ +DLLEXPORT int tjGetErrorCode(tjhandle handle) +{ + return tj3GetErrorCode(handle); +} + + +/* TurboJPEG 3+ */ +DLLEXPORT void tj3Destroy(tjhandle handle) +{ + tjinstance *this = (tjinstance *)handle; + j_compress_ptr cinfo = NULL; + j_decompress_ptr dinfo = NULL; + + if (!this) return; + + cinfo = &this->cinfo; dinfo = &this->dinfo; + this->jerr.warning = FALSE; + this->isInstanceError = FALSE; + + if (setjmp(this->jerr.setjmp_buffer)) return; + if (this->init & COMPRESS) jpeg_destroy_compress(cinfo); + if (this->init & DECOMPRESS) jpeg_destroy_decompress(dinfo); + free(this); +} + +/* TurboJPEG 1.0+ */ +DLLEXPORT int tjDestroy(tjhandle handle) +{ + static const char FUNCTION_NAME[] = "tjDestroy"; + int retval = 0; + + if (!handle) THROWG("Invalid handle", -1); + + SNPRINTF(errStr, JMSG_LENGTH_MAX, "No error"); + tj3Destroy(handle); + if (strcmp(errStr, "No error")) retval = -1; + +bailout: + return retval; +} + + +/* These are exposed mainly because Windows can't malloc() and free() across + DLL boundaries except when the CRT DLL is used, and we don't use the CRT DLL + with turbojpeg.dll for compatibility reasons. However, these functions + can potentially be used for other purposes by different implementations. */ + +/* TurboJPEG 3+ */ +DLLEXPORT void tj3Free(void *buf) +{ + free(buf); +} + +/* TurboJPEG 1.2+ */ +DLLEXPORT void tjFree(unsigned char *buf) +{ + tj3Free(buf); +} + + +/* TurboJPEG 3+ */ +DLLEXPORT void *tj3Alloc(size_t bytes) +{ + return malloc(bytes); +} + +/* TurboJPEG 1.2+ */ +DLLEXPORT unsigned char *tjAlloc(int bytes) +{ + return (unsigned char *)tj3Alloc((size_t)bytes); +} + + +/******************************** Compressor *********************************/ + +static tjhandle _tjInitCompress(tjinstance *this) +{ + static unsigned char buffer[1]; + unsigned char *buf = buffer; + size_t size = 1; + + /* This is also straight out of example.c */ + this->cinfo.err = jpeg_std_error(&this->jerr.pub); + this->jerr.pub.error_exit = my_error_exit; + this->jerr.pub.output_message = my_output_message; + this->jerr.emit_message = this->jerr.pub.emit_message; + this->jerr.pub.emit_message = my_emit_message; + this->jerr.pub.addon_message_table = turbojpeg_message_table; + this->jerr.pub.first_addon_message = JMSG_FIRSTADDONCODE; + this->jerr.pub.last_addon_message = JMSG_LASTADDONCODE; + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + free(this); + return NULL; + } + + jpeg_create_compress(&this->cinfo); + /* Make an initial call so it will create the destination manager */ + jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0); + + this->init |= COMPRESS; + return (tjhandle)this; +} + +/* TurboJPEG 1.0+ */ +DLLEXPORT tjhandle tjInitCompress(void) +{ + return tj3Init(TJINIT_COMPRESS); +} + + +/* TurboJPEG 3+ */ +DLLEXPORT size_t tj3JPEGBufSize(int width, int height, int jpegSubsamp) +{ + static const char FUNCTION_NAME[] = "tj3JPEGBufSize"; + unsigned long long retval = 0; + int mcuw, mcuh, chromasf; + + if (width < 1 || height < 1 || jpegSubsamp < TJSAMP_UNKNOWN || + jpegSubsamp >= TJ_NUMSAMP) + THROWG("Invalid argument", 0); + + if (jpegSubsamp == TJSAMP_UNKNOWN) + jpegSubsamp = TJSAMP_444; + + /* This allows for rare corner cases in which a JPEG image can actually be + larger than the uncompressed input (we wouldn't mention it if it hadn't + happened before.) */ + mcuw = tjMCUWidth[jpegSubsamp]; + mcuh = tjMCUHeight[jpegSubsamp]; + chromasf = jpegSubsamp == TJSAMP_GRAY ? 0 : 4 * 64 / (mcuw * mcuh); + retval = PAD(width, mcuw) * PAD(height, mcuh) * (2ULL + chromasf) + 2048ULL; +#if ULLONG_MAX > ULONG_MAX + if (retval > (unsigned long long)((unsigned long)-1)) + THROWG("Image is too large", 0); +#endif + +bailout: + return (size_t)retval; +} + +/* TurboJPEG 1.2+ */ +DLLEXPORT unsigned long tjBufSize(int width, int height, int jpegSubsamp) +{ + static const char FUNCTION_NAME[] = "tjBufSize"; + size_t retval; + + if (jpegSubsamp < 0) + THROWG("Invalid argument", 0); + + retval = tj3JPEGBufSize(width, height, jpegSubsamp); + +bailout: + return (retval == 0) ? (unsigned long)-1 : (unsigned long)retval; +} + +/* TurboJPEG 1.0+ */ +DLLEXPORT unsigned long TJBUFSIZE(int width, int height) +{ + static const char FUNCTION_NAME[] = "TJBUFSIZE"; + unsigned long long retval = 0; + + if (width < 1 || height < 1) + THROWG("Invalid argument", (unsigned long)-1); + + /* This allows for rare corner cases in which a JPEG image can actually be + larger than the uncompressed input (we wouldn't mention it if it hadn't + happened before.) */ + retval = PAD(width, 16) * PAD(height, 16) * 6ULL + 2048ULL; +#if ULLONG_MAX > ULONG_MAX + if (retval > (unsigned long long)((unsigned long)-1)) + THROWG("Image is too large", (unsigned long)-1); +#endif + +bailout: + return (unsigned long)retval; +} + + +/* TurboJPEG 3+ */ +DLLEXPORT size_t tj3YUVBufSize(int width, int align, int height, int subsamp) +{ + static const char FUNCTION_NAME[] = "tj3YUVBufSize"; + unsigned long long retval = 0; + int nc, i; + + if (align < 1 || !IS_POW2(align) || subsamp < 0 || subsamp >= TJ_NUMSAMP) + THROWG("Invalid argument", 0); + + nc = (subsamp == TJSAMP_GRAY ? 1 : 3); + for (i = 0; i < nc; i++) { + int pw = tj3YUVPlaneWidth(i, width, subsamp); + int stride = PAD(pw, align); + int ph = tj3YUVPlaneHeight(i, height, subsamp); + + if (pw == 0 || ph == 0) return 0; + else retval += (unsigned long long)stride * ph; + } +#if ULLONG_MAX > ULONG_MAX + if (retval > (unsigned long long)((unsigned long)-1)) + THROWG("Image is too large", 0); +#endif + +bailout: + return (size_t)retval; +} + +/* TurboJPEG 1.4+ */ +DLLEXPORT unsigned long tjBufSizeYUV2(int width, int align, int height, + int subsamp) +{ + size_t retval = tj3YUVBufSize(width, align, height, subsamp); + return (retval == 0) ? (unsigned long)-1 : (unsigned long)retval; +} + +/* TurboJPEG 1.2+ */ +DLLEXPORT unsigned long tjBufSizeYUV(int width, int height, int subsamp) +{ + return tjBufSizeYUV2(width, 4, height, subsamp); +} + +/* TurboJPEG 1.1+ */ +DLLEXPORT unsigned long TJBUFSIZEYUV(int width, int height, int subsamp) +{ + return tjBufSizeYUV(width, height, subsamp); +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3YUVPlaneWidth(int componentID, int width, int subsamp) +{ + static const char FUNCTION_NAME[] = "tj3YUVPlaneWidth"; + unsigned long long pw, retval = 0; + int nc; + + if (width < 1 || subsamp < 0 || subsamp >= TJ_NUMSAMP) + THROWG("Invalid argument", 0); + nc = (subsamp == TJSAMP_GRAY ? 1 : 3); + if (componentID < 0 || componentID >= nc) + THROWG("Invalid argument", 0); + + pw = PAD((unsigned long long)width, tjMCUWidth[subsamp] / 8); + if (componentID == 0) + retval = pw; + else + retval = pw * 8 / tjMCUWidth[subsamp]; + + if (retval > (unsigned long long)INT_MAX) + THROWG("Width is too large", 0); + +bailout: + return (int)retval; +} + +/* TurboJPEG 1.4+ */ +DLLEXPORT int tjPlaneWidth(int componentID, int width, int subsamp) +{ + int retval = tj3YUVPlaneWidth(componentID, width, subsamp); + return (retval == 0) ? -1 : retval; +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3YUVPlaneHeight(int componentID, int height, int subsamp) +{ + static const char FUNCTION_NAME[] = "tj3YUVPlaneHeight"; + unsigned long long ph, retval = 0; + int nc; + + if (height < 1 || subsamp < 0 || subsamp >= TJ_NUMSAMP) + THROWG("Invalid argument", 0); + nc = (subsamp == TJSAMP_GRAY ? 1 : 3); + if (componentID < 0 || componentID >= nc) + THROWG("Invalid argument", 0); + + ph = PAD((unsigned long long)height, tjMCUHeight[subsamp] / 8); + if (componentID == 0) + retval = ph; + else + retval = ph * 8 / tjMCUHeight[subsamp]; + + if (retval > (unsigned long long)INT_MAX) + THROWG("Height is too large", 0); + +bailout: + return (int)retval; +} + +/* TurboJPEG 1.4+ */ +DLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp) +{ + int retval = tj3YUVPlaneHeight(componentID, height, subsamp); + return (retval == 0) ? -1 : retval; +} + + +/* TurboJPEG 3+ */ +DLLEXPORT size_t tj3YUVPlaneSize(int componentID, int width, int stride, + int height, int subsamp) +{ + static const char FUNCTION_NAME[] = "tj3YUVPlaneSize"; + unsigned long long retval = 0; + int pw, ph; + + if (width < 1 || height < 1 || subsamp < 0 || subsamp >= TJ_NUMSAMP) + THROWG("Invalid argument", 0); + + pw = tj3YUVPlaneWidth(componentID, width, subsamp); + ph = tj3YUVPlaneHeight(componentID, height, subsamp); + if (pw == 0 || ph == 0) return 0; + + if (stride == 0) stride = pw; + else stride = abs(stride); + + retval = (unsigned long long)stride * (ph - 1) + pw; +#if ULLONG_MAX > ULONG_MAX + if (retval > (unsigned long long)((unsigned long)-1)) + THROWG("Image is too large", 0); +#endif + +bailout: + return (size_t)retval; +} + +/* TurboJPEG 1.4+ */ +DLLEXPORT unsigned long tjPlaneSizeYUV(int componentID, int width, int stride, + int height, int subsamp) +{ + size_t retval = tj3YUVPlaneSize(componentID, width, stride, height, subsamp); + return (retval == 0) ? -1 : (unsigned long)retval; +} + + +/* tj3Compress*() is implemented in turbojpeg-mp.c */ +#define BITS_IN_JSAMPLE 8 +#include "turbojpeg-mp.c" +#undef BITS_IN_JSAMPLE +#define BITS_IN_JSAMPLE 12 +#include "turbojpeg-mp.c" +#undef BITS_IN_JSAMPLE +#define BITS_IN_JSAMPLE 16 +#include "turbojpeg-mp.c" +#undef BITS_IN_JSAMPLE + +/* TurboJPEG 1.2+ */ +DLLEXPORT int tjCompress2(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, unsigned long *jpegSize, + int jpegSubsamp, int jpegQual, int flags) +{ + static const char FUNCTION_NAME[] = "tjCompress2"; + int retval = 0; + size_t size; + + GET_TJINSTANCE(handle, -1); + + if (jpegSize == NULL || jpegSubsamp < 0 || jpegSubsamp >= TJ_NUMSAMP || + jpegQual < 0 || jpegQual > 100) + THROW("Invalid argument"); + + this->quality = jpegQual; + this->subsamp = jpegSubsamp; + processFlags(handle, flags, COMPRESS); + + size = (size_t)(*jpegSize); + retval = tj3Compress8(handle, srcBuf, width, pitch, height, pixelFormat, + jpegBuf, &size); + *jpegSize = (unsigned long)size; + +bailout: + return retval; +} + +/* TurboJPEG 1.0+ */ +DLLEXPORT int tjCompress(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelSize, + unsigned char *jpegBuf, unsigned long *jpegSize, + int jpegSubsamp, int jpegQual, int flags) +{ + int retval = 0; + unsigned long size = jpegSize ? *jpegSize : 0; + + if (flags & TJ_YUV) { + size = tjBufSizeYUV(width, height, jpegSubsamp); + retval = tjEncodeYUV2(handle, srcBuf, width, pitch, height, + getPixelFormat(pixelSize, flags), jpegBuf, + jpegSubsamp, flags); + } else { + retval = tjCompress2(handle, srcBuf, width, pitch, height, + getPixelFormat(pixelSize, flags), &jpegBuf, &size, + jpegSubsamp, jpegQual, flags | TJFLAG_NOREALLOC); + } + *jpegSize = size; + return retval; +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3EncodeYUVPlanes8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, + int pixelFormat, unsigned char **dstPlanes, + int *strides) +{ + static const char FUNCTION_NAME[] = "tj3EncodeYUVPlanes8"; + JSAMPROW *row_pointer = NULL; + JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS]; + JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS]; + JSAMPROW *outbuf[MAX_COMPONENTS]; + int i, retval = 0, row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS]; + JSAMPLE *ptr; + jpeg_component_info *compptr; + + GET_CINSTANCE(handle) + + for (i = 0; i < MAX_COMPONENTS; i++) { + tmpbuf[i] = NULL; _tmpbuf[i] = NULL; + tmpbuf2[i] = NULL; _tmpbuf2[i] = NULL; outbuf[i] = NULL; + } + + if ((this->init & COMPRESS) == 0) + THROW("Instance has not been initialized for compression"); + + if (srcBuf == NULL || width <= 0 || pitch < 0 || height <= 0 || + pixelFormat < 0 || pixelFormat >= TJ_NUMPF || !dstPlanes || + !dstPlanes[0]) + THROW("Invalid argument"); + if (this->subsamp != TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2])) + THROW("Invalid argument"); + + if (this->subsamp == TJSAMP_UNKNOWN) + THROW("TJPARAM_SUBSAMP must be specified"); + if (pixelFormat == TJPF_CMYK) + THROW("Cannot generate YUV images from packed-pixel CMYK images"); + + if (pitch == 0) pitch = width * tjPixelSize[pixelFormat]; + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + cinfo->image_width = width; + cinfo->image_height = height; + cinfo->data_precision = 8; + + setCompDefaults(this, pixelFormat); + + /* Execute only the parts of jpeg_start_compress() that we need. If we + were to call the whole jpeg_start_compress() function, then it would try + to write the file headers, which could overflow the output buffer if the + YUV image were very small. */ + if (cinfo->global_state != CSTATE_START) + THROW("libjpeg API is in the wrong state"); + (*cinfo->err->reset_error_mgr) ((j_common_ptr)cinfo); + jinit_c_master_control(cinfo, FALSE); + jinit_color_converter(cinfo); + jinit_downsampler(cinfo); + (*cinfo->cconvert->start_pass) (cinfo); + + pw0 = PAD(width, cinfo->max_h_samp_factor); + ph0 = PAD(height, cinfo->max_v_samp_factor); + + if ((row_pointer = (JSAMPROW *)malloc(sizeof(JSAMPROW) * ph0)) == NULL) + THROW("Memory allocation failure"); + for (i = 0; i < height; i++) { + if (this->bottomUp) + row_pointer[i] = (JSAMPROW)&srcBuf[(height - i - 1) * (size_t)pitch]; + else + row_pointer[i] = (JSAMPROW)&srcBuf[i * (size_t)pitch]; + } + if (height < ph0) + for (i = height; i < ph0; i++) row_pointer[i] = row_pointer[height - 1]; + + for (i = 0; i < cinfo->num_components; i++) { + compptr = &cinfo->comp_info[i]; + _tmpbuf[i] = (JSAMPLE *)malloc( + PAD((compptr->width_in_blocks * cinfo->max_h_samp_factor * DCTSIZE) / + compptr->h_samp_factor, 32) * + cinfo->max_v_samp_factor + 32); + if (!_tmpbuf[i]) + THROW("Memory allocation failure"); + tmpbuf[i] = + (JSAMPROW *)malloc(sizeof(JSAMPROW) * cinfo->max_v_samp_factor); + if (!tmpbuf[i]) + THROW("Memory allocation failure"); + for (row = 0; row < cinfo->max_v_samp_factor; row++) { + unsigned char *_tmpbuf_aligned = + (unsigned char *)PAD((JUINTPTR)_tmpbuf[i], 32); + + tmpbuf[i][row] = &_tmpbuf_aligned[ + PAD((compptr->width_in_blocks * cinfo->max_h_samp_factor * DCTSIZE) / + compptr->h_samp_factor, 32) * row]; + } + _tmpbuf2[i] = + (JSAMPLE *)malloc(PAD(compptr->width_in_blocks * DCTSIZE, 32) * + compptr->v_samp_factor + 32); + if (!_tmpbuf2[i]) + THROW("Memory allocation failure"); + tmpbuf2[i] = (JSAMPROW *)malloc(sizeof(JSAMPROW) * compptr->v_samp_factor); + if (!tmpbuf2[i]) + THROW("Memory allocation failure"); + for (row = 0; row < compptr->v_samp_factor; row++) { + unsigned char *_tmpbuf2_aligned = + (unsigned char *)PAD((JUINTPTR)_tmpbuf2[i], 32); + + tmpbuf2[i][row] = + &_tmpbuf2_aligned[PAD(compptr->width_in_blocks * DCTSIZE, 32) * row]; + } + pw[i] = pw0 * compptr->h_samp_factor / cinfo->max_h_samp_factor; + ph[i] = ph0 * compptr->v_samp_factor / cinfo->max_v_samp_factor; + outbuf[i] = (JSAMPROW *)malloc(sizeof(JSAMPROW) * ph[i]); + if (!outbuf[i]) + THROW("Memory allocation failure"); + ptr = dstPlanes[i]; + for (row = 0; row < ph[i]; row++) { + outbuf[i][row] = ptr; + ptr += (strides && strides[i] != 0) ? strides[i] : pw[i]; + } + } + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + for (row = 0; row < ph0; row += cinfo->max_v_samp_factor) { + (*cinfo->cconvert->color_convert) (cinfo, &row_pointer[row], tmpbuf, 0, + cinfo->max_v_samp_factor); + (cinfo->downsample->downsample) (cinfo, tmpbuf, 0, tmpbuf2, 0); + for (i = 0, compptr = cinfo->comp_info; i < cinfo->num_components; + i++, compptr++) + jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i], + row * compptr->v_samp_factor / cinfo->max_v_samp_factor, + compptr->v_samp_factor, pw[i]); + } + cinfo->next_scanline += height; + jpeg_abort_compress(cinfo); + +bailout: + if (cinfo->global_state > CSTATE_START) jpeg_abort_compress(cinfo); + free(row_pointer); + for (i = 0; i < MAX_COMPONENTS; i++) { + free(tmpbuf[i]); + free(_tmpbuf[i]); + free(tmpbuf2[i]); + free(_tmpbuf2[i]); + free(outbuf[i]); + } + if (this->jerr.warning) retval = -1; + return retval; +} + +/* TurboJPEG 1.4+ */ +DLLEXPORT int tjEncodeYUVPlanes(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, + int pixelFormat, unsigned char **dstPlanes, + int *strides, int subsamp, int flags) +{ + static const char FUNCTION_NAME[] = "tjEncodeYUVPlanes"; + int retval = 0; + + GET_TJINSTANCE(handle, -1); + + if (subsamp < 0 || subsamp >= TJ_NUMSAMP) + THROW("Invalid argument"); + + this->subsamp = subsamp; + processFlags(handle, flags, COMPRESS); + + return tj3EncodeYUVPlanes8(handle, srcBuf, width, pitch, height, pixelFormat, + dstPlanes, strides); + +bailout: + return retval; +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3EncodeYUV8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int align) +{ + static const char FUNCTION_NAME[] = "tj3EncodeYUV8"; + unsigned char *dstPlanes[3]; + int pw0, ph0, strides[3], retval = -1; + + GET_TJINSTANCE(handle, -1); + + if (width <= 0 || height <= 0 || dstBuf == NULL || align < 1 || + !IS_POW2(align)) + THROW("Invalid argument"); + + if (this->subsamp == TJSAMP_UNKNOWN) + THROW("TJPARAM_SUBSAMP must be specified"); + + pw0 = tj3YUVPlaneWidth(0, width, this->subsamp); + ph0 = tj3YUVPlaneHeight(0, height, this->subsamp); + dstPlanes[0] = dstBuf; + strides[0] = PAD(pw0, align); + if (this->subsamp == TJSAMP_GRAY) { + strides[1] = strides[2] = 0; + dstPlanes[1] = dstPlanes[2] = NULL; + } else { + int pw1 = tj3YUVPlaneWidth(1, width, this->subsamp); + int ph1 = tj3YUVPlaneHeight(1, height, this->subsamp); + + strides[1] = strides[2] = PAD(pw1, align); + if ((unsigned long long)strides[0] * (unsigned long long)ph0 > + (unsigned long long)INT_MAX || + (unsigned long long)strides[1] * (unsigned long long)ph1 > + (unsigned long long)INT_MAX) + THROW("Image or row alignment is too large"); + dstPlanes[1] = dstPlanes[0] + strides[0] * ph0; + dstPlanes[2] = dstPlanes[1] + strides[1] * ph1; + } + + return tj3EncodeYUVPlanes8(handle, srcBuf, width, pitch, height, pixelFormat, + dstPlanes, strides); + +bailout: + return retval; +} + +/* TurboJPEG 1.4+ */ +DLLEXPORT int tjEncodeYUV3(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int align, int subsamp, + int flags) +{ + static const char FUNCTION_NAME[] = "tjEncodeYUV3"; + int retval = 0; + + GET_TJINSTANCE(handle, -1); + + if (subsamp < 0 || subsamp >= TJ_NUMSAMP) + THROW("Invalid argument"); + + this->subsamp = subsamp; + processFlags(handle, flags, COMPRESS); + + return tj3EncodeYUV8(handle, srcBuf, width, pitch, height, pixelFormat, + dstBuf, align); + +bailout: + return retval; +} + +/* TurboJPEG 1.2+ */ +DLLEXPORT int tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int subsamp, int flags) +{ + return tjEncodeYUV3(handle, srcBuf, width, pitch, height, pixelFormat, + dstBuf, 4, subsamp, flags); +} + +/* TurboJPEG 1.1+ */ +DLLEXPORT int tjEncodeYUV(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelSize, + unsigned char *dstBuf, int subsamp, int flags) +{ + return tjEncodeYUV2(handle, srcBuf, width, pitch, height, + getPixelFormat(pixelSize, flags), dstBuf, subsamp, + flags); +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3CompressFromYUVPlanes8(tjhandle handle, + const unsigned char * const *srcPlanes, + int width, const int *strides, + int height, unsigned char **jpegBuf, + size_t *jpegSize) +{ + static const char FUNCTION_NAME[] = "tj3CompressFromYUVPlanes8"; + int i, row, retval = 0; + boolean alloc = TRUE; + int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS], + tmpbufsize = 0, usetmpbuf = 0, th[MAX_COMPONENTS]; + JSAMPLE *_tmpbuf = NULL, *ptr; + JSAMPROW *inbuf[MAX_COMPONENTS], *tmpbuf[MAX_COMPONENTS]; + + GET_CINSTANCE(handle) + + for (i = 0; i < MAX_COMPONENTS; i++) { + tmpbuf[i] = NULL; inbuf[i] = NULL; + } + + if ((this->init & COMPRESS) == 0) + THROW("Instance has not been initialized for compression"); + + if (!srcPlanes || !srcPlanes[0] || width <= 0 || height <= 0 || + jpegBuf == NULL || jpegSize == NULL) + THROW("Invalid argument"); + if (this->subsamp != TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2])) + THROW("Invalid argument"); + + if (this->quality == -1) + THROW("TJPARAM_QUALITY must be specified"); + if (this->subsamp == TJSAMP_UNKNOWN) + THROW("TJPARAM_SUBSAMP must be specified"); + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + cinfo->image_width = width; + cinfo->image_height = height; + cinfo->data_precision = 8; + + if (this->noRealloc) { + alloc = FALSE; *jpegSize = tj3JPEGBufSize(width, height, this->subsamp); + } + jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc); + setCompDefaults(this, TJPF_RGB); + cinfo->raw_data_in = TRUE; + + jpeg_start_compress(cinfo, TRUE); + for (i = 0; i < cinfo->num_components; i++) { + jpeg_component_info *compptr = &cinfo->comp_info[i]; + int ih; + + iw[i] = compptr->width_in_blocks * DCTSIZE; + ih = compptr->height_in_blocks * DCTSIZE; + pw[i] = PAD(cinfo->image_width, cinfo->max_h_samp_factor) * + compptr->h_samp_factor / cinfo->max_h_samp_factor; + ph[i] = PAD(cinfo->image_height, cinfo->max_v_samp_factor) * + compptr->v_samp_factor / cinfo->max_v_samp_factor; + if (iw[i] != pw[i] || ih != ph[i]) usetmpbuf = 1; + th[i] = compptr->v_samp_factor * DCTSIZE; + tmpbufsize += iw[i] * th[i]; + if ((inbuf[i] = (JSAMPROW *)malloc(sizeof(JSAMPROW) * ph[i])) == NULL) + THROW("Memory allocation failure"); + ptr = (JSAMPLE *)srcPlanes[i]; + for (row = 0; row < ph[i]; row++) { + inbuf[i][row] = ptr; + ptr += (strides && strides[i] != 0) ? strides[i] : pw[i]; + } + } + if (usetmpbuf) { + if ((_tmpbuf = (JSAMPLE *)malloc(sizeof(JSAMPLE) * tmpbufsize)) == NULL) + THROW("Memory allocation failure"); + ptr = _tmpbuf; + for (i = 0; i < cinfo->num_components; i++) { + if ((tmpbuf[i] = (JSAMPROW *)malloc(sizeof(JSAMPROW) * th[i])) == NULL) + THROW("Memory allocation failure"); + for (row = 0; row < th[i]; row++) { + tmpbuf[i][row] = ptr; + ptr += iw[i]; + } + } + } + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + for (row = 0; row < (int)cinfo->image_height; + row += cinfo->max_v_samp_factor * DCTSIZE) { + JSAMPARRAY yuvptr[MAX_COMPONENTS]; + int crow[MAX_COMPONENTS]; + + for (i = 0; i < cinfo->num_components; i++) { + jpeg_component_info *compptr = &cinfo->comp_info[i]; + + crow[i] = row * compptr->v_samp_factor / cinfo->max_v_samp_factor; + if (usetmpbuf) { + int j, k; + + for (j = 0; j < MIN(th[i], ph[i] - crow[i]); j++) { + memcpy(tmpbuf[i][j], inbuf[i][crow[i] + j], pw[i]); + /* Duplicate last sample in row to fill out MCU */ + for (k = pw[i]; k < iw[i]; k++) + tmpbuf[i][j][k] = tmpbuf[i][j][pw[i] - 1]; + } + /* Duplicate last row to fill out MCU */ + for (j = ph[i] - crow[i]; j < th[i]; j++) + memcpy(tmpbuf[i][j], tmpbuf[i][ph[i] - crow[i] - 1], iw[i]); + yuvptr[i] = tmpbuf[i]; + } else + yuvptr[i] = &inbuf[i][crow[i]]; + } + jpeg_write_raw_data(cinfo, yuvptr, cinfo->max_v_samp_factor * DCTSIZE); + } + jpeg_finish_compress(cinfo); + +bailout: + if (cinfo->global_state > CSTATE_START && alloc) + (*cinfo->dest->term_destination) (cinfo); + if (cinfo->global_state > CSTATE_START || retval == -1) + jpeg_abort_compress(cinfo); + for (i = 0; i < MAX_COMPONENTS; i++) { + free(tmpbuf[i]); + free(inbuf[i]); + } + free(_tmpbuf); + if (this->jerr.warning) retval = -1; + return retval; +} + +/* TurboJPEG 1.4+ */ +DLLEXPORT int tjCompressFromYUVPlanes(tjhandle handle, + const unsigned char **srcPlanes, + int width, const int *strides, + int height, int subsamp, + unsigned char **jpegBuf, + unsigned long *jpegSize, int jpegQual, + int flags) +{ + static const char FUNCTION_NAME[] = "tjCompressFromYUVPlanes"; + int retval = 0; + size_t size; + + GET_TJINSTANCE(handle, -1); + + if (subsamp < 0 || subsamp >= TJ_NUMSAMP || jpegSize == NULL || + jpegQual < 0 || jpegQual > 100) + THROW("Invalid argument"); + + this->quality = jpegQual; + this->subsamp = subsamp; + processFlags(handle, flags, COMPRESS); + + size = (size_t)(*jpegSize); + retval = tj3CompressFromYUVPlanes8(handle, srcPlanes, width, strides, height, + jpegBuf, &size); + *jpegSize = (unsigned long)size; + +bailout: + return retval; +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3CompressFromYUV8(tjhandle handle, + const unsigned char *srcBuf, int width, + int align, int height, + unsigned char **jpegBuf, size_t *jpegSize) +{ + static const char FUNCTION_NAME[] = "tj3CompressFromYUV8"; + const unsigned char *srcPlanes[3]; + int pw0, ph0, strides[3], retval = -1; + + GET_TJINSTANCE(handle, -1); + + if (srcBuf == NULL || width <= 0 || align < 1 || !IS_POW2(align) || + height <= 0) + THROW("Invalid argument"); + + if (this->subsamp == TJSAMP_UNKNOWN) + THROW("TJPARAM_SUBSAMP must be specified"); + + pw0 = tj3YUVPlaneWidth(0, width, this->subsamp); + ph0 = tj3YUVPlaneHeight(0, height, this->subsamp); + srcPlanes[0] = srcBuf; + strides[0] = PAD(pw0, align); + if (this->subsamp == TJSAMP_GRAY) { + strides[1] = strides[2] = 0; + srcPlanes[1] = srcPlanes[2] = NULL; + } else { + int pw1 = tjPlaneWidth(1, width, this->subsamp); + int ph1 = tjPlaneHeight(1, height, this->subsamp); + + strides[1] = strides[2] = PAD(pw1, align); + if ((unsigned long long)strides[0] * (unsigned long long)ph0 > + (unsigned long long)INT_MAX || + (unsigned long long)strides[1] * (unsigned long long)ph1 > + (unsigned long long)INT_MAX) + THROW("Image or row alignment is too large"); + srcPlanes[1] = srcPlanes[0] + strides[0] * ph0; + srcPlanes[2] = srcPlanes[1] + strides[1] * ph1; + } + + return tj3CompressFromYUVPlanes8(handle, srcPlanes, width, strides, height, + jpegBuf, jpegSize); + +bailout: + return retval; +} + +/* TurboJPEG 1.4+ */ +DLLEXPORT int tjCompressFromYUV(tjhandle handle, const unsigned char *srcBuf, + int width, int align, int height, int subsamp, + unsigned char **jpegBuf, + unsigned long *jpegSize, int jpegQual, + int flags) +{ + static const char FUNCTION_NAME[] = "tjCompressFromYUV"; + int retval = -1; + size_t size; + + GET_TJINSTANCE(handle, -1); + + if (subsamp < 0 || subsamp >= TJ_NUMSAMP) + THROW("Invalid argument"); + + this->quality = jpegQual; + this->subsamp = subsamp; + processFlags(handle, flags, COMPRESS); + + size = (size_t)(*jpegSize); + retval = tj3CompressFromYUV8(handle, srcBuf, width, align, height, jpegBuf, + &size); + *jpegSize = (unsigned long)size; + +bailout: + return retval; +} + + +/******************************* Decompressor ********************************/ + +static tjhandle _tjInitDecompress(tjinstance *this) +{ + static unsigned char buffer[1]; + + /* This is also straight out of example.c */ + this->dinfo.err = jpeg_std_error(&this->jerr.pub); + this->jerr.pub.error_exit = my_error_exit; + this->jerr.pub.output_message = my_output_message; + this->jerr.emit_message = this->jerr.pub.emit_message; + this->jerr.pub.emit_message = my_emit_message; + this->jerr.pub.addon_message_table = turbojpeg_message_table; + this->jerr.pub.first_addon_message = JMSG_FIRSTADDONCODE; + this->jerr.pub.last_addon_message = JMSG_LASTADDONCODE; + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + free(this); + return NULL; + } + + jpeg_create_decompress(&this->dinfo); + /* Make an initial call so it will create the source manager */ + jpeg_mem_src_tj(&this->dinfo, buffer, 1); + + this->init |= DECOMPRESS; + return (tjhandle)this; +} + +/* TurboJPEG 1.0+ */ +DLLEXPORT tjhandle tjInitDecompress(void) +{ + return tj3Init(TJINIT_DECOMPRESS); +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3DecompressHeader(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize) +{ + static const char FUNCTION_NAME[] = "tj3DecompressHeader"; + int retval = 0; + + GET_DINSTANCE(handle); + if ((this->init & DECOMPRESS) == 0) + THROW("Instance has not been initialized for decompression"); + + if (jpegBuf == NULL || jpegSize <= 0) + THROW("Invalid argument"); + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + return -1; + } + + jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); + + /* jpeg_read_header() calls jpeg_abort() and returns JPEG_HEADER_TABLES_ONLY + if the datastream is a tables-only datastream. Since we aren't using a + suspending data source, the only other value it can return is + JPEG_HEADER_OK. */ + if (jpeg_read_header(dinfo, FALSE) == JPEG_HEADER_TABLES_ONLY) + return 0; + + setDecompParameters(this); + + jpeg_abort_decompress(dinfo); + + if (this->colorspace < 0) + THROW("Could not determine colorspace of JPEG image"); + if (this->jpegWidth < 1 || this->jpegHeight < 1) + THROW("Invalid data returned in header"); + +bailout: + if (this->jerr.warning) retval = -1; + return retval; +} + +/* TurboJPEG 1.4+ */ +DLLEXPORT int tjDecompressHeader3(tjhandle handle, + const unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height, int *jpegSubsamp, + int *jpegColorspace) +{ + static const char FUNCTION_NAME[] = "tjDecompressHeader3"; + int retval = 0; + + GET_TJINSTANCE(handle, -1); + + if (width == NULL || height == NULL || jpegSubsamp == NULL || + jpegColorspace == NULL) + THROW("Invalid argument"); + + retval = tj3DecompressHeader(handle, jpegBuf, jpegSize); + + *width = tj3Get(handle, TJPARAM_JPEGWIDTH); + *height = tj3Get(handle, TJPARAM_JPEGHEIGHT); + *jpegSubsamp = tj3Get(handle, TJPARAM_SUBSAMP); + if (*jpegSubsamp == TJSAMP_UNKNOWN) + THROW("Could not determine subsampling level of JPEG image"); + *jpegColorspace = tj3Get(handle, TJPARAM_COLORSPACE); + +bailout: + return retval; +} + +/* TurboJPEG 1.1+ */ +DLLEXPORT int tjDecompressHeader2(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height, int *jpegSubsamp) +{ + int jpegColorspace; + + return tjDecompressHeader3(handle, jpegBuf, jpegSize, width, height, + jpegSubsamp, &jpegColorspace); +} + +/* TurboJPEG 1.0+ */ +DLLEXPORT int tjDecompressHeader(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height) +{ + int jpegSubsamp; + + return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height, + &jpegSubsamp); +} + + +/* TurboJPEG 3+ */ +DLLEXPORT tjscalingfactor *tj3GetScalingFactors(int *numScalingFactors) +{ + static const char FUNCTION_NAME[] = "tj3GetScalingFactors"; + tjscalingfactor *retval = (tjscalingfactor *)sf; + + if (numScalingFactors == NULL) + THROWG("Invalid argument", NULL); + + *numScalingFactors = NUMSF; + +bailout: + return retval; +} + +/* TurboJPEG 1.2+ */ +DLLEXPORT tjscalingfactor *tjGetScalingFactors(int *numScalingFactors) +{ + return tj3GetScalingFactors(numScalingFactors); +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3SetScalingFactor(tjhandle handle, + tjscalingfactor scalingFactor) +{ + static const char FUNCTION_NAME[] = "tj3SetScalingFactor"; + int i, retval = 0; + + GET_TJINSTANCE(handle, -1); + if ((this->init & DECOMPRESS) == 0) + THROW("Instance has not been initialized for decompression"); + + for (i = 0; i < NUMSF; i++) { + if (scalingFactor.num == sf[i].num && scalingFactor.denom == sf[i].denom) + break; + } + if (i >= NUMSF) + THROW("Unsupported scaling factor"); + + this->scalingFactor = scalingFactor; + +bailout: + return retval; +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3SetCroppingRegion(tjhandle handle, tjregion croppingRegion) +{ + static const char FUNCTION_NAME[] = "tj3SetCroppingRegion"; + int retval = 0, scaledWidth, scaledHeight; + + GET_TJINSTANCE(handle, -1); + if ((this->init & DECOMPRESS) == 0) + THROW("Instance has not been initialized for decompression"); + + if (croppingRegion.x == 0 && croppingRegion.y == 0 && + croppingRegion.w == 0 && croppingRegion.h == 0) { + this->croppingRegion = croppingRegion; + return 0; + } + + if (croppingRegion.x < 0 || croppingRegion.y < 0 || croppingRegion.w < 0 || + croppingRegion.h < 0) + THROW("Invalid cropping region"); + if (this->jpegWidth < 0 || this->jpegHeight < 0) + THROW("JPEG header has not yet been read"); + if (this->precision == 16 || this->lossless) + THROW("Cannot partially decompress lossless JPEG images"); + if (this->subsamp == TJSAMP_UNKNOWN) + THROW("Could not determine subsampling level of JPEG image"); + + scaledWidth = TJSCALED(this->jpegWidth, this->scalingFactor); + scaledHeight = TJSCALED(this->jpegHeight, this->scalingFactor); + + if (croppingRegion.x % + TJSCALED(tjMCUWidth[this->subsamp], this->scalingFactor) != 0) + THROWI("The left boundary of the cropping region (%d) is not\n" + "divisible by the scaled MCU width (%d)", + croppingRegion.x, + TJSCALED(tjMCUWidth[this->subsamp], this->scalingFactor)); + if (croppingRegion.w == 0) + croppingRegion.w = scaledWidth - croppingRegion.x; + if (croppingRegion.h == 0) + croppingRegion.h = scaledHeight - croppingRegion.y; + if (croppingRegion.w < 0 || croppingRegion.h < 0 || + croppingRegion.x + croppingRegion.w > scaledWidth || + croppingRegion.y + croppingRegion.h > scaledHeight) + THROW("The cropping region exceeds the scaled image dimensions"); + + this->croppingRegion = croppingRegion; + +bailout: + return retval; +} + + +/* tj3Decompress*() is implemented in turbojpeg-mp.c */ + +/* TurboJPEG 1.2+ */ +DLLEXPORT int tjDecompress2(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int pitch, int height, int pixelFormat, + int flags) +{ + static const char FUNCTION_NAME[] = "tjDecompress2"; + int i, retval = 0, jpegwidth, jpegheight, scaledw, scaledh; + + GET_DINSTANCE(handle); + if ((this->init & DECOMPRESS) == 0) + THROW("Instance has not been initialized for decompression"); + + if (jpegBuf == NULL || jpegSize <= 0 || width < 0 || height < 0) + THROW("Invalid argument"); + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); + jpeg_read_header(dinfo, TRUE); + jpegwidth = dinfo->image_width; jpegheight = dinfo->image_height; + if (width == 0) width = jpegwidth; + if (height == 0) height = jpegheight; + for (i = 0; i < NUMSF; i++) { + scaledw = TJSCALED(jpegwidth, sf[i]); + scaledh = TJSCALED(jpegheight, sf[i]); + if (scaledw <= width && scaledh <= height) + break; + } + if (i >= NUMSF) + THROW("Could not scale down to desired image dimensions"); + + processFlags(handle, flags, DECOMPRESS); + + if (tj3SetScalingFactor(handle, sf[i]) == -1) + return -1; + if (tj3SetCroppingRegion(handle, TJUNCROPPED) == -1) + return -1; + return tj3Decompress8(handle, jpegBuf, jpegSize, dstBuf, pitch, pixelFormat); + +bailout: + if (dinfo->global_state > DSTATE_START) jpeg_abort_decompress(dinfo); + if (this->jerr.warning) retval = -1; + return retval; +} + +/* TurboJPEG 1.0+ */ +DLLEXPORT int tjDecompress(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int pitch, int height, int pixelSize, + int flags) +{ + if (flags & TJ_YUV) + return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags); + else + return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch, + height, getPixelFormat(pixelSize, flags), flags); +} + + +static void setDecodeDefaults(tjinstance *this, int pixelFormat) +{ + int i; + + this->dinfo.scale_num = this->dinfo.scale_denom = 1; + + if (this->subsamp == TJSAMP_GRAY) { + this->dinfo.num_components = this->dinfo.comps_in_scan = 1; + this->dinfo.jpeg_color_space = JCS_GRAYSCALE; + } else { + this->dinfo.num_components = this->dinfo.comps_in_scan = 3; + this->dinfo.jpeg_color_space = JCS_YCbCr; + } + + this->dinfo.comp_info = (jpeg_component_info *) + (*this->dinfo.mem->alloc_small) ((j_common_ptr)&this->dinfo, JPOOL_IMAGE, + this->dinfo.num_components * + sizeof(jpeg_component_info)); + + for (i = 0; i < this->dinfo.num_components; i++) { + jpeg_component_info *compptr = &this->dinfo.comp_info[i]; + + compptr->h_samp_factor = (i == 0) ? tjMCUWidth[this->subsamp] / 8 : 1; + compptr->v_samp_factor = (i == 0) ? tjMCUHeight[this->subsamp] / 8 : 1; + compptr->component_index = i; + compptr->component_id = i + 1; + compptr->quant_tbl_no = compptr->dc_tbl_no = + compptr->ac_tbl_no = (i == 0) ? 0 : 1; + this->dinfo.cur_comp_info[i] = compptr; + } + this->dinfo.data_precision = 8; + for (i = 0; i < 2; i++) { + if (this->dinfo.quant_tbl_ptrs[i] == NULL) + this->dinfo.quant_tbl_ptrs[i] = + jpeg_alloc_quant_table((j_common_ptr)&this->dinfo); + } + + this->dinfo.mem->max_memory_to_use = (long)this->maxMemory * 1048576L; +} + + +static int my_read_markers(j_decompress_ptr dinfo) +{ + return JPEG_REACHED_SOS; +} + +static void my_reset_marker_reader(j_decompress_ptr dinfo) +{ +} + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3DecodeYUVPlanes8(tjhandle handle, + const unsigned char * const *srcPlanes, + const int *strides, unsigned char *dstBuf, + int width, int pitch, int height, + int pixelFormat) +{ + static const char FUNCTION_NAME[] = "tj3DecodeYUVPlanes8"; + JSAMPROW *row_pointer = NULL; + JSAMPLE *_tmpbuf[MAX_COMPONENTS]; + JSAMPROW *tmpbuf[MAX_COMPONENTS], *inbuf[MAX_COMPONENTS]; + int i, retval = 0, row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS]; + JSAMPLE *ptr; + jpeg_component_info *compptr; + int (*old_read_markers) (j_decompress_ptr); + void (*old_reset_marker_reader) (j_decompress_ptr); + + GET_DINSTANCE(handle); + + for (i = 0; i < MAX_COMPONENTS; i++) { + tmpbuf[i] = NULL; _tmpbuf[i] = NULL; inbuf[i] = NULL; + } + + if ((this->init & DECOMPRESS) == 0) + THROW("Instance has not been initialized for decompression"); + + if (!srcPlanes || !srcPlanes[0] || dstBuf == NULL || width <= 0 || + pitch < 0 || height <= 0 || pixelFormat < 0 || pixelFormat >= TJ_NUMPF) + THROW("Invalid argument"); + if (this->subsamp != TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2])) + THROW("Invalid argument"); + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + if (this->subsamp == TJSAMP_UNKNOWN) + THROW("TJPARAM_SUBSAMP must be specified"); + if (pixelFormat == TJPF_CMYK) + THROW("Cannot decode YUV images into packed-pixel CMYK images."); + + if (pitch == 0) pitch = width * tjPixelSize[pixelFormat]; + dinfo->image_width = width; + dinfo->image_height = height; + + dinfo->progressive_mode = dinfo->inputctl->has_multiple_scans = FALSE; + dinfo->Ss = dinfo->Ah = dinfo->Al = 0; + dinfo->Se = DCTSIZE2 - 1; + setDecodeDefaults(this, pixelFormat); + old_read_markers = dinfo->marker->read_markers; + dinfo->marker->read_markers = my_read_markers; + old_reset_marker_reader = dinfo->marker->reset_marker_reader; + dinfo->marker->reset_marker_reader = my_reset_marker_reader; + jpeg_read_header(dinfo, TRUE); + dinfo->marker->read_markers = old_read_markers; + dinfo->marker->reset_marker_reader = old_reset_marker_reader; + + this->dinfo.out_color_space = pf2cs[pixelFormat]; + this->dinfo.dct_method = this->fastDCT ? JDCT_FASTEST : JDCT_ISLOW; + dinfo->do_fancy_upsampling = FALSE; + dinfo->Se = DCTSIZE2 - 1; + jinit_master_decompress(dinfo); + (*dinfo->upsample->start_pass) (dinfo); + + pw0 = PAD(width, dinfo->max_h_samp_factor); + ph0 = PAD(height, dinfo->max_v_samp_factor); + + if (pitch == 0) pitch = dinfo->output_width * tjPixelSize[pixelFormat]; + + if ((row_pointer = (JSAMPROW *)malloc(sizeof(JSAMPROW) * ph0)) == NULL) + THROW("Memory allocation failure"); + for (i = 0; i < height; i++) { + if (this->bottomUp) + row_pointer[i] = &dstBuf[(height - i - 1) * (size_t)pitch]; + else + row_pointer[i] = &dstBuf[i * (size_t)pitch]; + } + if (height < ph0) + for (i = height; i < ph0; i++) row_pointer[i] = row_pointer[height - 1]; + + for (i = 0; i < dinfo->num_components; i++) { + compptr = &dinfo->comp_info[i]; + _tmpbuf[i] = + (JSAMPLE *)malloc(PAD(compptr->width_in_blocks * DCTSIZE, 32) * + compptr->v_samp_factor + 32); + if (!_tmpbuf[i]) + THROW("Memory allocation failure"); + tmpbuf[i] = (JSAMPROW *)malloc(sizeof(JSAMPROW) * compptr->v_samp_factor); + if (!tmpbuf[i]) + THROW("Memory allocation failure"); + for (row = 0; row < compptr->v_samp_factor; row++) { + unsigned char *_tmpbuf_aligned = + (unsigned char *)PAD((JUINTPTR)_tmpbuf[i], 32); + + tmpbuf[i][row] = + &_tmpbuf_aligned[PAD(compptr->width_in_blocks * DCTSIZE, 32) * row]; + } + pw[i] = pw0 * compptr->h_samp_factor / dinfo->max_h_samp_factor; + ph[i] = ph0 * compptr->v_samp_factor / dinfo->max_v_samp_factor; + inbuf[i] = (JSAMPROW *)malloc(sizeof(JSAMPROW) * ph[i]); + if (!inbuf[i]) + THROW("Memory allocation failure"); + ptr = (JSAMPLE *)srcPlanes[i]; + for (row = 0; row < ph[i]; row++) { + inbuf[i][row] = ptr; + ptr += (strides && strides[i] != 0) ? strides[i] : pw[i]; + } + } + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + for (row = 0; row < ph0; row += dinfo->max_v_samp_factor) { + JDIMENSION inrow = 0, outrow = 0; + + for (i = 0, compptr = dinfo->comp_info; i < dinfo->num_components; + i++, compptr++) + jcopy_sample_rows(inbuf[i], + row * compptr->v_samp_factor / dinfo->max_v_samp_factor, tmpbuf[i], 0, + compptr->v_samp_factor, pw[i]); + (dinfo->upsample->upsample) (dinfo, tmpbuf, &inrow, + dinfo->max_v_samp_factor, &row_pointer[row], + &outrow, dinfo->max_v_samp_factor); + } + jpeg_abort_decompress(dinfo); + +bailout: + if (dinfo->global_state > DSTATE_START) jpeg_abort_decompress(dinfo); + free(row_pointer); + for (i = 0; i < MAX_COMPONENTS; i++) { + free(tmpbuf[i]); + free(_tmpbuf[i]); + free(inbuf[i]); + } + if (this->jerr.warning) retval = -1; + return retval; +} + +/* TurboJPEG 1.4+ */ +DLLEXPORT int tjDecodeYUVPlanes(tjhandle handle, + const unsigned char **srcPlanes, + const int *strides, int subsamp, + unsigned char *dstBuf, int width, int pitch, + int height, int pixelFormat, int flags) +{ + static const char FUNCTION_NAME[] = "tjDecodeYUVPlanes"; + int retval = 0; + + GET_TJINSTANCE(handle, -1); + + if (subsamp < 0 || subsamp >= TJ_NUMSAMP) + THROW("Invalid argument"); + + this->subsamp = subsamp; + processFlags(handle, flags, DECOMPRESS); + + return tj3DecodeYUVPlanes8(handle, srcPlanes, strides, dstBuf, width, pitch, + height, pixelFormat); + +bailout: + return retval; +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3DecodeYUV8(tjhandle handle, const unsigned char *srcBuf, + int align, unsigned char *dstBuf, int width, + int pitch, int height, int pixelFormat) +{ + static const char FUNCTION_NAME[] = "tj3DecodeYUV8"; + const unsigned char *srcPlanes[3]; + int pw0, ph0, strides[3], retval = -1; + + GET_TJINSTANCE(handle, -1); + + if (srcBuf == NULL || align < 1 || !IS_POW2(align) || width <= 0 || + height <= 0) + THROW("Invalid argument"); + + if (this->subsamp == TJSAMP_UNKNOWN) + THROW("TJPARAM_SUBSAMP must be specified"); + + pw0 = tj3YUVPlaneWidth(0, width, this->subsamp); + ph0 = tj3YUVPlaneHeight(0, height, this->subsamp); + srcPlanes[0] = srcBuf; + strides[0] = PAD(pw0, align); + if (this->subsamp == TJSAMP_GRAY) { + strides[1] = strides[2] = 0; + srcPlanes[1] = srcPlanes[2] = NULL; + } else { + int pw1 = tj3YUVPlaneWidth(1, width, this->subsamp); + int ph1 = tj3YUVPlaneHeight(1, height, this->subsamp); + + strides[1] = strides[2] = PAD(pw1, align); + if ((unsigned long long)strides[0] * (unsigned long long)ph0 > + (unsigned long long)INT_MAX || + (unsigned long long)strides[1] * (unsigned long long)ph1 > + (unsigned long long)INT_MAX) + THROW("Image or row alignment is too large"); + srcPlanes[1] = srcPlanes[0] + strides[0] * ph0; + srcPlanes[2] = srcPlanes[1] + strides[1] * ph1; + } + + return tj3DecodeYUVPlanes8(handle, srcPlanes, strides, dstBuf, width, pitch, + height, pixelFormat); + +bailout: + return retval; +} + +/* TurboJPEG 1.4+ */ +DLLEXPORT int tjDecodeYUV(tjhandle handle, const unsigned char *srcBuf, + int align, int subsamp, unsigned char *dstBuf, + int width, int pitch, int height, int pixelFormat, + int flags) +{ + static const char FUNCTION_NAME[] = "tjDecodeYUV"; + int retval = -1; + + GET_TJINSTANCE(handle, -1); + + if (subsamp < 0 || subsamp >= TJ_NUMSAMP) + THROW("Invalid argument"); + + this->subsamp = subsamp; + processFlags(handle, flags, DECOMPRESS); + + return tj3DecodeYUV8(handle, srcBuf, align, dstBuf, width, pitch, height, + pixelFormat); + +bailout: + return retval; +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3DecompressToYUVPlanes8(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize, + unsigned char **dstPlanes, + int *strides) +{ + static const char FUNCTION_NAME[] = "tj3DecompressToYUVPlanes8"; + int i, row, retval = 0; + int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS], + tmpbufsize = 0, usetmpbuf = 0, th[MAX_COMPONENTS]; + JSAMPLE *_tmpbuf = NULL, *ptr; + JSAMPROW *outbuf[MAX_COMPONENTS], *tmpbuf[MAX_COMPONENTS]; + int dctsize; + struct my_progress_mgr progress; + + GET_DINSTANCE(handle); + + for (i = 0; i < MAX_COMPONENTS; i++) { + tmpbuf[i] = NULL; outbuf[i] = NULL; + } + + if ((this->init & DECOMPRESS) == 0) + THROW("Instance has not been initialized for decompression"); + + if (jpegBuf == NULL || jpegSize <= 0 || !dstPlanes || !dstPlanes[0]) + THROW("Invalid argument"); + + if (this->scanLimit) { + memset(&progress, 0, sizeof(struct my_progress_mgr)); + progress.pub.progress_monitor = my_progress_monitor; + progress.this = this; + dinfo->progress = &progress.pub; + } else + dinfo->progress = NULL; + + dinfo->mem->max_memory_to_use = (long)this->maxMemory * 1048576L; + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + if (dinfo->global_state <= DSTATE_INHEADER) { + jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); + jpeg_read_header(dinfo, TRUE); + } + setDecompParameters(this); + if (this->maxPixels && + (unsigned long long)this->jpegWidth * this->jpegHeight > + (unsigned long long)this->maxPixels) + THROW("Image is too large"); + if (this->subsamp == TJSAMP_UNKNOWN) + THROW("Could not determine subsampling level of JPEG image"); + + if (this->subsamp != TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2])) + THROW("Invalid argument"); + + if (dinfo->num_components > 3) + THROW("JPEG image must have 3 or fewer components"); + + dinfo->scale_num = this->scalingFactor.num; + dinfo->scale_denom = this->scalingFactor.denom; + jpeg_calc_output_dimensions(dinfo); + + dctsize = DCTSIZE * this->scalingFactor.num / this->scalingFactor.denom; + + for (i = 0; i < dinfo->num_components; i++) { + jpeg_component_info *compptr = &dinfo->comp_info[i]; + int ih; + + iw[i] = compptr->width_in_blocks * dctsize; + ih = compptr->height_in_blocks * dctsize; + pw[i] = tj3YUVPlaneWidth(i, dinfo->output_width, this->subsamp); + ph[i] = tj3YUVPlaneHeight(i, dinfo->output_height, this->subsamp); + if (iw[i] != pw[i] || ih != ph[i]) usetmpbuf = 1; + th[i] = compptr->v_samp_factor * dctsize; + tmpbufsize += iw[i] * th[i]; + if ((outbuf[i] = (JSAMPROW *)malloc(sizeof(JSAMPROW) * ph[i])) == NULL) + THROW("Memory allocation failure"); + ptr = dstPlanes[i]; + for (row = 0; row < ph[i]; row++) { + outbuf[i][row] = ptr; + ptr += (strides && strides[i] != 0) ? strides[i] : pw[i]; + } + } + if (usetmpbuf) { + if ((_tmpbuf = (JSAMPLE *)malloc(sizeof(JSAMPLE) * tmpbufsize)) == NULL) + THROW("Memory allocation failure"); + ptr = _tmpbuf; + for (i = 0; i < dinfo->num_components; i++) { + if ((tmpbuf[i] = (JSAMPROW *)malloc(sizeof(JSAMPROW) * th[i])) == NULL) + THROW("Memory allocation failure"); + for (row = 0; row < th[i]; row++) { + tmpbuf[i][row] = ptr; + ptr += iw[i]; + } + } + } + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + dinfo->do_fancy_upsampling = !this->fastUpsample; + dinfo->dct_method = this->fastDCT ? JDCT_FASTEST : JDCT_ISLOW; + dinfo->raw_data_out = TRUE; + + dinfo->mem->max_memory_to_use = (long)this->maxMemory * 1048576L; + + jpeg_start_decompress(dinfo); + for (row = 0; row < (int)dinfo->output_height; + row += dinfo->max_v_samp_factor * dinfo->_min_DCT_scaled_size) { + JSAMPARRAY yuvptr[MAX_COMPONENTS]; + int crow[MAX_COMPONENTS]; + + for (i = 0; i < dinfo->num_components; i++) { + jpeg_component_info *compptr = &dinfo->comp_info[i]; + + if (this->subsamp == TJSAMP_420) { + /* When 4:2:0 subsampling is used with IDCT scaling, libjpeg will try + to be clever and use the IDCT to perform upsampling on the U and V + planes. For instance, if the output image is to be scaled by 1/2 + relative to the JPEG image, then the scaling factor and upsampling + effectively cancel each other, so a normal 8x8 IDCT can be used. + However, this is not desirable when using the decompress-to-YUV + functionality in TurboJPEG, since we want to output the U and V + planes in their subsampled form. Thus, we have to override some + internal libjpeg parameters to force it to use the "scaled" IDCT + functions on the U and V planes. */ + compptr->_DCT_scaled_size = dctsize; + compptr->MCU_sample_width = tjMCUWidth[this->subsamp] * + this->scalingFactor.num / this->scalingFactor.denom * + compptr->v_samp_factor / dinfo->max_v_samp_factor; + dinfo->idct->inverse_DCT[i] = dinfo->idct->inverse_DCT[0]; + } + crow[i] = row * compptr->v_samp_factor / dinfo->max_v_samp_factor; + if (usetmpbuf) yuvptr[i] = tmpbuf[i]; + else yuvptr[i] = &outbuf[i][crow[i]]; + } + jpeg_read_raw_data(dinfo, yuvptr, + dinfo->max_v_samp_factor * dinfo->_min_DCT_scaled_size); + if (usetmpbuf) { + int j; + + for (i = 0; i < dinfo->num_components; i++) { + for (j = 0; j < MIN(th[i], ph[i] - crow[i]); j++) { + memcpy(outbuf[i][crow[i] + j], tmpbuf[i][j], pw[i]); + } + } + } + } + jpeg_finish_decompress(dinfo); + +bailout: + if (dinfo->global_state > DSTATE_START) jpeg_abort_decompress(dinfo); + for (i = 0; i < MAX_COMPONENTS; i++) { + free(tmpbuf[i]); + free(outbuf[i]); + } + free(_tmpbuf); + if (this->jerr.warning) retval = -1; + return retval; +} + +/* TurboJPEG 1.4+ */ +DLLEXPORT int tjDecompressToYUVPlanes(tjhandle handle, + const unsigned char *jpegBuf, + unsigned long jpegSize, + unsigned char **dstPlanes, int width, + int *strides, int height, int flags) +{ + static const char FUNCTION_NAME[] = "tjDecompressToYUVPlanes"; + int i, retval = 0, jpegwidth, jpegheight, scaledw, scaledh; + + GET_DINSTANCE(handle); + if ((this->init & DECOMPRESS) == 0) + THROW("Instance has not been initialized for decompression"); + + if (jpegBuf == NULL || jpegSize <= 0 || width < 0 || height < 0) + THROW("Invalid argument"); + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); + jpeg_read_header(dinfo, TRUE); + jpegwidth = dinfo->image_width; jpegheight = dinfo->image_height; + if (width == 0) width = jpegwidth; + if (height == 0) height = jpegheight; + for (i = 0; i < NUMSF; i++) { + scaledw = TJSCALED(jpegwidth, sf[i]); + scaledh = TJSCALED(jpegheight, sf[i]); + if (scaledw <= width && scaledh <= height) + break; + } + if (i >= NUMSF) + THROW("Could not scale down to desired image dimensions"); + + processFlags(handle, flags, DECOMPRESS); + + if (tj3SetScalingFactor(handle, sf[i]) == -1) + return -1; + return tj3DecompressToYUVPlanes8(handle, jpegBuf, jpegSize, dstPlanes, + strides); + +bailout: + if (dinfo->global_state > DSTATE_START) jpeg_abort_decompress(dinfo); + if (this->jerr.warning) retval = -1; + return retval; +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3DecompressToYUV8(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize, + unsigned char *dstBuf, int align) +{ + static const char FUNCTION_NAME[] = "tj3DecompressToYUV8"; + unsigned char *dstPlanes[3]; + int pw0, ph0, strides[3], retval = -1; + int width, height; + + GET_DINSTANCE(handle); + + if (jpegBuf == NULL || jpegSize <= 0 || dstBuf == NULL || align < 1 || + !IS_POW2(align)) + THROW("Invalid argument"); + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + if (dinfo->global_state <= DSTATE_INHEADER) { + jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); + jpeg_read_header(dinfo, TRUE); + } + setDecompParameters(this); + if (this->subsamp == TJSAMP_UNKNOWN) + THROW("Could not determine subsampling level of JPEG image"); + + width = TJSCALED(dinfo->image_width, this->scalingFactor); + height = TJSCALED(dinfo->image_height, this->scalingFactor); + + pw0 = tj3YUVPlaneWidth(0, width, this->subsamp); + ph0 = tj3YUVPlaneHeight(0, height, this->subsamp); + dstPlanes[0] = dstBuf; + strides[0] = PAD(pw0, align); + if (this->subsamp == TJSAMP_GRAY) { + strides[1] = strides[2] = 0; + dstPlanes[1] = dstPlanes[2] = NULL; + } else { + int pw1 = tj3YUVPlaneWidth(1, width, this->subsamp); + int ph1 = tj3YUVPlaneHeight(1, height, this->subsamp); + + strides[1] = strides[2] = PAD(pw1, align); + if ((unsigned long long)strides[0] * (unsigned long long)ph0 > + (unsigned long long)INT_MAX || + (unsigned long long)strides[1] * (unsigned long long)ph1 > + (unsigned long long)INT_MAX) + THROW("Image or row alignment is too large"); + dstPlanes[1] = dstPlanes[0] + strides[0] * ph0; + dstPlanes[2] = dstPlanes[1] + strides[1] * ph1; + } + + return tj3DecompressToYUVPlanes8(handle, jpegBuf, jpegSize, dstPlanes, + strides); + +bailout: + if (dinfo->global_state > DSTATE_START) jpeg_abort_decompress(dinfo); + if (this->jerr.warning) retval = -1; + return retval; +} + +/* TurboJPEG 1.4+ */ +DLLEXPORT int tjDecompressToYUV2(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int align, int height, int flags) +{ + static const char FUNCTION_NAME[] = "tjDecompressToYUV2"; + int i, retval = 0, jpegwidth, jpegheight, scaledw, scaledh; + + GET_DINSTANCE(handle); + if ((this->init & DECOMPRESS) == 0) + THROW("Instance has not been initialized for decompression"); + + if (jpegBuf == NULL || jpegSize <= 0 || width < 0 || height < 0) + THROW("Invalid argument"); + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); + jpeg_read_header(dinfo, TRUE); + jpegwidth = dinfo->image_width; jpegheight = dinfo->image_height; + if (width == 0) width = jpegwidth; + if (height == 0) height = jpegheight; + for (i = 0; i < NUMSF; i++) { + scaledw = TJSCALED(jpegwidth, sf[i]); + scaledh = TJSCALED(jpegheight, sf[i]); + if (scaledw <= width && scaledh <= height) + break; + } + if (i >= NUMSF) + THROW("Could not scale down to desired image dimensions"); + + width = scaledw; height = scaledh; + + processFlags(handle, flags, DECOMPRESS); + + if (tj3SetScalingFactor(handle, sf[i]) == -1) + return -1; + return tj3DecompressToYUV8(handle, jpegBuf, (size_t)jpegSize, dstBuf, align); + +bailout: + if (dinfo->global_state > DSTATE_START) jpeg_abort_decompress(dinfo); + if (this->jerr.warning) retval = -1; + return retval; +} + +/* TurboJPEG 1.1+ */ +DLLEXPORT int tjDecompressToYUV(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int flags) +{ + return tjDecompressToYUV2(handle, jpegBuf, jpegSize, dstBuf, 0, 4, 0, flags); +} + + +/******************************** Transformer ********************************/ + +/* TurboJPEG 1.2+ */ +DLLEXPORT tjhandle tjInitTransform(void) +{ + return tj3Init(TJINIT_TRANSFORM); +} + + +/* TurboJPEG 3+ */ +DLLEXPORT int tj3Transform(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, int n, unsigned char **dstBufs, + size_t *dstSizes, const tjtransform *t) +{ + static const char FUNCTION_NAME[] = "tj3Transform"; + jpeg_transform_info *xinfo = NULL; + jvirt_barray_ptr *srccoefs, *dstcoefs; + int retval = 0, i, saveMarkers = 0; + boolean alloc = TRUE; + struct my_progress_mgr progress; + + GET_INSTANCE(handle); + if ((this->init & COMPRESS) == 0 || (this->init & DECOMPRESS) == 0) + THROW("Instance has not been initialized for transformation"); + + if (jpegBuf == NULL || jpegSize <= 0 || n < 1 || dstBufs == NULL || + dstSizes == NULL || t == NULL) + THROW("Invalid argument"); + + if (this->scanLimit) { + memset(&progress, 0, sizeof(struct my_progress_mgr)); + progress.pub.progress_monitor = my_progress_monitor; + progress.this = this; + dinfo->progress = &progress.pub; + } else + dinfo->progress = NULL; + + dinfo->mem->max_memory_to_use = (long)this->maxMemory * 1048576L; + + if ((xinfo = + (jpeg_transform_info *)malloc(sizeof(jpeg_transform_info) * n)) == NULL) + THROW("Memory allocation failure"); + memset(xinfo, 0, sizeof(jpeg_transform_info) * n); + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + if (dinfo->global_state <= DSTATE_INHEADER) + jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); + + for (i = 0; i < n; i++) { + if (t[i].op < 0 || t[i].op >= TJ_NUMXOP) + THROW("Invalid transform operation"); + xinfo[i].transform = xformtypes[t[i].op]; + xinfo[i].perfect = (t[i].options & TJXOPT_PERFECT) ? 1 : 0; + xinfo[i].trim = (t[i].options & TJXOPT_TRIM) ? 1 : 0; + xinfo[i].force_grayscale = (t[i].options & TJXOPT_GRAY) ? 1 : 0; + xinfo[i].crop = (t[i].options & TJXOPT_CROP) ? 1 : 0; + if (n != 1 && t[i].op == TJXOP_HFLIP) xinfo[i].slow_hflip = 1; + else xinfo[i].slow_hflip = 0; + + if (xinfo[i].crop) { + xinfo[i].crop_xoffset = t[i].r.x; xinfo[i].crop_xoffset_set = JCROP_POS; + xinfo[i].crop_yoffset = t[i].r.y; xinfo[i].crop_yoffset_set = JCROP_POS; + if (t[i].r.w != 0) { + xinfo[i].crop_width = t[i].r.w; xinfo[i].crop_width_set = JCROP_POS; + } else + xinfo[i].crop_width = JCROP_UNSET; + if (t[i].r.h != 0) { + xinfo[i].crop_height = t[i].r.h; xinfo[i].crop_height_set = JCROP_POS; + } else + xinfo[i].crop_height = JCROP_UNSET; + } + if (!(t[i].options & TJXOPT_COPYNONE)) saveMarkers = 1; + } + + jcopy_markers_setup(dinfo, saveMarkers ? JCOPYOPT_ALL : JCOPYOPT_NONE); + if (dinfo->global_state <= DSTATE_INHEADER) + jpeg_read_header(dinfo, TRUE); + if (this->maxPixels && + (unsigned long long)dinfo->image_width * dinfo->image_height > + (unsigned long long)this->maxPixels) + THROW("Image is too large"); + this->subsamp = getSubsamp(&this->dinfo); + + for (i = 0; i < n; i++) { + if (!jtransform_request_workspace(dinfo, &xinfo[i])) + THROW("Transform is not perfect"); + + if (xinfo[i].crop) { + if (this->subsamp == TJSAMP_UNKNOWN) + THROW("Could not determine subsampling level of JPEG image"); + if ((t[i].r.x % tjMCUWidth[this->subsamp]) != 0 || + (t[i].r.y % tjMCUHeight[this->subsamp]) != 0) + THROWI("To crop this JPEG image, x must be a multiple of %d\n" + "and y must be a multiple of %d.", tjMCUWidth[this->subsamp], + tjMCUHeight[this->subsamp]); + } + } + + srccoefs = jpeg_read_coefficients(dinfo); + + for (i = 0; i < n; i++) { + int w, h; + + if (!xinfo[i].crop) { + w = dinfo->image_width; h = dinfo->image_height; + if (t[i].op == TJXOP_TRANSPOSE || t[i].op == TJXOP_TRANSVERSE || + t[i].op == TJXOP_ROT90 || t[i].op == TJXOP_ROT270) { + w = dinfo->image_height; h = dinfo->image_width; + } + } else { + w = xinfo[i].crop_width; h = xinfo[i].crop_height; + } + if (this->noRealloc) { + alloc = FALSE; dstSizes[i] = tj3JPEGBufSize(w, h, this->subsamp); + } + if (!(t[i].options & TJXOPT_NOOUTPUT)) + jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc); + jpeg_copy_critical_parameters(dinfo, cinfo); + dstcoefs = jtransform_adjust_parameters(dinfo, cinfo, srccoefs, &xinfo[i]); + if (this->optimize || t[i].options & TJXOPT_OPTIMIZE) + cinfo->optimize_coding = TRUE; +#ifdef C_PROGRESSIVE_SUPPORTED + if (this->progressive || t[i].options & TJXOPT_PROGRESSIVE) + jpeg_simple_progression(cinfo); +#endif + if (this->arithmetic || t[i].options & TJXOPT_ARITHMETIC) { + cinfo->arith_code = TRUE; + cinfo->optimize_coding = FALSE; + } + if (!(t[i].options & TJXOPT_NOOUTPUT)) { + jpeg_write_coefficients(cinfo, dstcoefs); + jcopy_markers_execute(dinfo, cinfo, t[i].options & TJXOPT_COPYNONE ? + JCOPYOPT_NONE : JCOPYOPT_ALL); + } else + jinit_c_master_control(cinfo, TRUE); + jtransform_execute_transformation(dinfo, cinfo, srccoefs, &xinfo[i]); + if (t[i].customFilter) { + int ci, y; + JDIMENSION by; + + for (ci = 0; ci < cinfo->num_components; ci++) { + jpeg_component_info *compptr = &cinfo->comp_info[ci]; + tjregion arrayRegion = { 0, 0, 0, 0 }; + tjregion planeRegion = { 0, 0, 0, 0 }; + + arrayRegion.w = compptr->width_in_blocks * DCTSIZE; + arrayRegion.h = DCTSIZE; + planeRegion.w = compptr->width_in_blocks * DCTSIZE; + planeRegion.h = compptr->height_in_blocks * DCTSIZE; + + for (by = 0; by < compptr->height_in_blocks; + by += compptr->v_samp_factor) { + JBLOCKARRAY barray = (dinfo->mem->access_virt_barray) + ((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor, + TRUE); + + for (y = 0; y < compptr->v_samp_factor; y++) { + if (t[i].customFilter(barray[y][0], arrayRegion, planeRegion, ci, + i, (tjtransform *)&t[i]) == -1) + THROW("Error in custom filter"); + arrayRegion.y += DCTSIZE; + } + } + } + } + if (!(t[i].options & TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo); + } + + jpeg_finish_decompress(dinfo); + +bailout: + if (cinfo->global_state > CSTATE_START) { + if (alloc) (*cinfo->dest->term_destination) (cinfo); + jpeg_abort_compress(cinfo); + } + if (dinfo->global_state > DSTATE_START) jpeg_abort_decompress(dinfo); + free(xinfo); + if (this->jerr.warning) retval = -1; + return retval; +} + +/* TurboJPEG 1.2+ */ +DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, int n, + unsigned char **dstBufs, unsigned long *dstSizes, + tjtransform *t, int flags) +{ + static const char FUNCTION_NAME[] = "tjTransform"; + int i, retval = 0; + size_t *sizes = NULL; + + GET_DINSTANCE(handle); + if ((this->init & DECOMPRESS) == 0) + THROW("Instance has not been initialized for decompression"); + + if (n < 1 || dstSizes == NULL) + THROW("Invalid argument"); + + if (setjmp(this->jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + retval = -1; goto bailout; + } + + jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); + jpeg_read_header(dinfo, TRUE); + if (getSubsamp(dinfo) == TJSAMP_UNKNOWN) + THROW("Could not determine subsampling level of JPEG image"); + processFlags(handle, flags, COMPRESS); + + if ((sizes = (size_t *)malloc(n * sizeof(size_t))) == NULL) + THROW("Memory allocation failure"); + for (i = 0; i < n; i++) + sizes[i] = (size_t)dstSizes[i]; + retval = tj3Transform(handle, jpegBuf, (size_t)jpegSize, n, dstBufs, sizes, + t); + for (i = 0; i < n; i++) + dstSizes[i] = (unsigned long)sizes[i]; + +bailout: + free(sizes); + return retval; +} + + +/*************************** Packed-Pixel Image I/O **************************/ + +/* tj3LoadImage*() is implemented in turbojpeg-mp.c */ + +/* TurboJPEG 2.0+ */ +DLLEXPORT unsigned char *tjLoadImage(const char *filename, int *width, + int align, int *height, + int *pixelFormat, int flags) +{ + tjhandle handle = NULL; + unsigned char *dstBuf = NULL; + + if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL) return NULL; + + processFlags(handle, flags, COMPRESS); + + dstBuf = tj3LoadImage8(handle, filename, width, align, height, pixelFormat); + + tj3Destroy(handle); + return dstBuf; +} + + +/* tj3SaveImage*() is implemented in turbojpeg-mp.c */ + +/* TurboJPEG 2.0+ */ +DLLEXPORT int tjSaveImage(const char *filename, unsigned char *buffer, + int width, int pitch, int height, int pixelFormat, + int flags) +{ + tjhandle handle = NULL; + int retval = -1; + + if ((handle = tj3Init(TJINIT_DECOMPRESS)) == NULL) return -1; + + processFlags(handle, flags, DECOMPRESS); + + retval = tj3SaveImage8(handle, filename, buffer, width, pitch, height, + pixelFormat); + + tj3Destroy(handle); + return retval; +} diff --git a/3rdparty/libjpeg-turbo/src/turbojpeg.h b/3rdparty/libjpeg-turbo/src/turbojpeg.h new file mode 100644 index 000000000000..68b88a410464 --- /dev/null +++ b/3rdparty/libjpeg-turbo/src/turbojpeg.h @@ -0,0 +1,2328 @@ +/* + * Copyright (C)2009-2015, 2017, 2020-2023 D. R. Commander. + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __TURBOJPEG_H__ +#define __TURBOJPEG_H__ + +#include + +#if defined(_WIN32) && defined(DLLDEFINE) +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT +#endif +#define DLLCALL + + +/** + * @addtogroup TurboJPEG + * TurboJPEG API. This API provides an interface for generating, decoding, and + * transforming planar YUV and JPEG images in memory. + * + * @anchor YUVnotes + * YUV Image Format Notes + * ---------------------- + * Technically, the JPEG format uses the YCbCr colorspace (which is technically + * not a colorspace but a color transform), but per the convention of the + * digital video community, the TurboJPEG API uses "YUV" to refer to an image + * format consisting of Y, Cb, and Cr image planes. + * + * Each plane is simply a 2D array of bytes, each byte representing the value + * of one of the components (Y, Cb, or Cr) at a particular location in the + * image. The width and height of each plane are determined by the image + * width, height, and level of chrominance subsampling. The luminance plane + * width is the image width padded to the nearest multiple of the horizontal + * subsampling factor (1 in the case of 4:4:4, grayscale, 4:4:0, or 4:4:1; 2 in + * the case of 4:2:2 or 4:2:0; 4 in the case of 4:1:1.) Similarly, the + * luminance plane height is the image height padded to the nearest multiple of + * the vertical subsampling factor (1 in the case of 4:4:4, 4:2:2, grayscale, + * or 4:1:1; 2 in the case of 4:2:0 or 4:4:0; 4 in the case of 4:4:1.) This is + * irrespective of any additional padding that may be specified as an argument + * to the various YUV functions. The chrominance plane width is equal to the + * luminance plane width divided by the horizontal subsampling factor, and the + * chrominance plane height is equal to the luminance plane height divided by + * the vertical subsampling factor. + * + * For example, if the source image is 35 x 35 pixels and 4:2:2 subsampling is + * used, then the luminance plane would be 36 x 35 bytes, and each of the + * chrominance planes would be 18 x 35 bytes. If you specify a row alignment + * of 4 bytes on top of this, then the luminance plane would be 36 x 35 bytes, + * and each of the chrominance planes would be 20 x 35 bytes. + * + * @{ + */ + + +/** + * The number of initialization options + */ +#define TJ_NUMINIT 3 + +/** + * Initialization options. + */ +enum TJINIT { + /** + * Initialize the TurboJPEG instance for compression. + */ + TJINIT_COMPRESS, + /** + * Initialize the TurboJPEG instance for decompression. + */ + TJINIT_DECOMPRESS, + /** + * Initialize the TurboJPEG instance for lossless transformation (both + * compression and decompression.) + */ + TJINIT_TRANSFORM +}; + + +/** + * The number of chrominance subsampling options + */ +#define TJ_NUMSAMP 7 + +/** + * Chrominance subsampling options. + * When pixels are converted from RGB to YCbCr (see #TJCS_YCbCr) or from CMYK + * to YCCK (see #TJCS_YCCK) as part of the JPEG compression process, some of + * the Cb and Cr (chrominance) components can be discarded or averaged together + * to produce a smaller image with little perceptible loss of image clarity. + * (The human eye is more sensitive to small changes in brightness than to + * small changes in color.) This is called "chrominance subsampling". + */ +enum TJSAMP { + /** + * 4:4:4 chrominance subsampling (no chrominance subsampling). The JPEG or + * YUV image will contain one chrominance component for every pixel in the + * source image. + */ + TJSAMP_444, + /** + * 4:2:2 chrominance subsampling. The JPEG or YUV image will contain one + * chrominance component for every 2x1 block of pixels in the source image. + */ + TJSAMP_422, + /** + * 4:2:0 chrominance subsampling. The JPEG or YUV image will contain one + * chrominance component for every 2x2 block of pixels in the source image. + */ + TJSAMP_420, + /** + * Grayscale. The JPEG or YUV image will contain no chrominance components. + */ + TJSAMP_GRAY, + /** + * 4:4:0 chrominance subsampling. The JPEG or YUV image will contain one + * chrominance component for every 1x2 block of pixels in the source image. + * + * @note 4:4:0 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_440, + /** + * 4:1:1 chrominance subsampling. The JPEG or YUV image will contain one + * chrominance component for every 4x1 block of pixels in the source image. + * JPEG images compressed with 4:1:1 subsampling will be almost exactly the + * same size as those compressed with 4:2:0 subsampling, and in the + * aggregate, both subsampling methods produce approximately the same + * perceptual quality. However, 4:1:1 is better able to reproduce sharp + * horizontal features. + * + * @note 4:1:1 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_411, + /** + * 4:4:1 chrominance subsampling. The JPEG or YUV image will contain one + * chrominance component for every 1x4 block of pixels in the source image. + * JPEG images compressed with 4:4:1 subsampling will be almost exactly the + * same size as those compressed with 4:2:0 subsampling, and in the + * aggregate, both subsampling methods produce approximately the same + * perceptual quality. However, 4:4:1 is better able to reproduce sharp + * vertical features. + * + * @note 4:4:1 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_441, + /** + * Unknown subsampling. The JPEG image uses an unusual type of chrominance + * subsampling. Such images can be decompressed into packed-pixel images, + * but they cannot be + * - decompressed into planar YUV images, + * - losslessly transformed if #TJXOPT_CROP is specified, or + * - partially decompressed using a cropping region. + */ + TJSAMP_UNKNOWN = -1 +}; + +/** + * MCU block width (in pixels) for a given level of chrominance subsampling. + * MCU block sizes: + * - 8x8 for no subsampling or grayscale + * - 16x8 for 4:2:2 + * - 8x16 for 4:4:0 + * - 16x16 for 4:2:0 + * - 32x8 for 4:1:1 + * - 8x32 for 4:4:1 + */ +static const int tjMCUWidth[TJ_NUMSAMP] = { 8, 16, 16, 8, 8, 32, 8 }; + +/** + * MCU block height (in pixels) for a given level of chrominance subsampling. + * MCU block sizes: + * - 8x8 for no subsampling or grayscale + * - 16x8 for 4:2:2 + * - 8x16 for 4:4:0 + * - 16x16 for 4:2:0 + * - 32x8 for 4:1:1 + * - 8x32 for 4:4:1 + */ +static const int tjMCUHeight[TJ_NUMSAMP] = { 8, 8, 16, 8, 16, 8, 32 }; + + +/** + * The number of pixel formats + */ +#define TJ_NUMPF 12 + +/** + * Pixel formats + */ +enum TJPF { + /** + * RGB pixel format. The red, green, and blue components in the image are + * stored in 3-sample pixels in the order R, G, B from lowest to highest + * memory address within each pixel. + */ + TJPF_RGB, + /** + * BGR pixel format. The red, green, and blue components in the image are + * stored in 3-sample pixels in the order B, G, R from lowest to highest + * memory address within each pixel. + */ + TJPF_BGR, + /** + * RGBX pixel format. The red, green, and blue components in the image are + * stored in 4-sample pixels in the order R, G, B from lowest to highest + * memory address within each pixel. The X component is ignored when + * compressing and undefined when decompressing. + */ + TJPF_RGBX, + /** + * BGRX pixel format. The red, green, and blue components in the image are + * stored in 4-sample pixels in the order B, G, R from lowest to highest + * memory address within each pixel. The X component is ignored when + * compressing and undefined when decompressing. + */ + TJPF_BGRX, + /** + * XBGR pixel format. The red, green, and blue components in the image are + * stored in 4-sample pixels in the order R, G, B from highest to lowest + * memory address within each pixel. The X component is ignored when + * compressing and undefined when decompressing. + */ + TJPF_XBGR, + /** + * XRGB pixel format. The red, green, and blue components in the image are + * stored in 4-sample pixels in the order B, G, R from highest to lowest + * memory address within each pixel. The X component is ignored when + * compressing and undefined when decompressing. + */ + TJPF_XRGB, + /** + * Grayscale pixel format. Each 1-sample pixel represents a luminance + * (brightness) level from 0 to the maximum sample value (255 for 8-bit + * samples, 4095 for 12-bit samples, and 65535 for 16-bit samples.) + */ + TJPF_GRAY, + /** + * RGBA pixel format. This is the same as @ref TJPF_RGBX, except that when + * decompressing, the X component is guaranteed to be equal to the maximum + * sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_RGBA, + /** + * BGRA pixel format. This is the same as @ref TJPF_BGRX, except that when + * decompressing, the X component is guaranteed to be equal to the maximum + * sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_BGRA, + /** + * ABGR pixel format. This is the same as @ref TJPF_XBGR, except that when + * decompressing, the X component is guaranteed to be equal to the maximum + * sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_ABGR, + /** + * ARGB pixel format. This is the same as @ref TJPF_XRGB, except that when + * decompressing, the X component is guaranteed to be equal to the maximum + * sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_ARGB, + /** + * CMYK pixel format. Unlike RGB, which is an additive color model used + * primarily for display, CMYK (Cyan/Magenta/Yellow/Key) is a subtractive + * color model used primarily for printing. In the CMYK color model, the + * value of each color component typically corresponds to an amount of cyan, + * magenta, yellow, or black ink that is applied to a white background. In + * order to convert between CMYK and RGB, it is necessary to use a color + * management system (CMS.) A CMS will attempt to map colors within the + * printer's gamut to perceptually similar colors in the display's gamut and + * vice versa, but the mapping is typically not 1:1 or reversible, nor can it + * be defined with a simple formula. Thus, such a conversion is out of scope + * for a codec library. However, the TurboJPEG API allows for compressing + * packed-pixel CMYK images into YCCK JPEG images (see #TJCS_YCCK) and + * decompressing YCCK JPEG images into packed-pixel CMYK images. + */ + TJPF_CMYK, + /** + * Unknown pixel format. Currently this is only used by #tj3LoadImage8(), + * #tj3LoadImage12(), and #tj3LoadImage16(). + */ + TJPF_UNKNOWN = -1 +}; + +/** + * Red offset (in samples) for a given pixel format. This specifies the number + * of samples that the red component is offset from the start of the pixel. + * For instance, if an 8-bit-per-component pixel of format TJPF_BGRX is stored + * in `unsigned char pixel[]`, then the red component will be + * `pixel[tjRedOffset[TJPF_BGRX]]`. This will be -1 if the pixel format does + * not have a red component. + */ +static const int tjRedOffset[TJ_NUMPF] = { + 0, 2, 0, 2, 3, 1, -1, 0, 2, 3, 1, -1 +}; +/** + * Green offset (in samples) for a given pixel format. This specifies the + * number of samples that the green component is offset from the start of the + * pixel. For instance, if an 8-bit-per-component pixel of format TJPF_BGRX is + * stored in `unsigned char pixel[]`, then the green component will be + * `pixel[tjGreenOffset[TJPF_BGRX]]`. This will be -1 if the pixel format does + * not have a green component. + */ +static const int tjGreenOffset[TJ_NUMPF] = { + 1, 1, 1, 1, 2, 2, -1, 1, 1, 2, 2, -1 +}; +/** + * Blue offset (in samples) for a given pixel format. This specifies the + * number of samples that the blue component is offset from the start of the + * pixel. For instance, if an 8-bit-per-component pixel of format TJPF_BGRX is + * stored in `unsigned char pixel[]`, then the blue component will be + * `pixel[tjBlueOffset[TJPF_BGRX]]`. This will be -1 if the pixel format does + * not have a blue component. + */ +static const int tjBlueOffset[TJ_NUMPF] = { + 2, 0, 2, 0, 1, 3, -1, 2, 0, 1, 3, -1 +}; +/** + * Alpha offset (in samples) for a given pixel format. This specifies the + * number of samples that the alpha component is offset from the start of the + * pixel. For instance, if an 8-bit-per-component pixel of format TJPF_BGRA is + * stored in `unsigned char pixel[]`, then the alpha component will be + * `pixel[tjAlphaOffset[TJPF_BGRA]]`. This will be -1 if the pixel format does + * not have an alpha component. + */ +static const int tjAlphaOffset[TJ_NUMPF] = { + -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1 +}; +/** + * Pixel size (in samples) for a given pixel format + */ +static const int tjPixelSize[TJ_NUMPF] = { + 3, 3, 4, 4, 4, 4, 1, 4, 4, 4, 4, 4 +}; + + +/** + * The number of JPEG colorspaces + */ +#define TJ_NUMCS 5 + +/** + * JPEG colorspaces + */ +enum TJCS { + /** + * RGB colorspace. When compressing the JPEG image, the R, G, and B + * components in the source image are reordered into image planes, but no + * colorspace conversion or subsampling is performed. RGB JPEG images can be + * compressed from and decompressed to packed-pixel images with any of the + * extended RGB or grayscale pixel formats, but they cannot be compressed + * from or decompressed to planar YUV images. + */ + TJCS_RGB, + /** + * YCbCr colorspace. YCbCr is not an absolute colorspace but rather a + * mathematical transformation of RGB designed solely for storage and + * transmission. YCbCr images must be converted to RGB before they can + * actually be displayed. In the YCbCr colorspace, the Y (luminance) + * component represents the black & white portion of the original image, and + * the Cb and Cr (chrominance) components represent the color portion of the + * original image. Originally, the analog equivalent of this transformation + * allowed the same signal to drive both black & white and color televisions, + * but JPEG images use YCbCr primarily because it allows the color data to be + * optionally subsampled for the purposes of reducing network or disk usage. + * YCbCr is the most common JPEG colorspace, and YCbCr JPEG images can be + * compressed from and decompressed to packed-pixel images with any of the + * extended RGB or grayscale pixel formats. YCbCr JPEG images can also be + * compressed from and decompressed to planar YUV images. + */ + TJCS_YCbCr, + /** + * Grayscale colorspace. The JPEG image retains only the luminance data (Y + * component), and any color data from the source image is discarded. + * Grayscale JPEG images can be compressed from and decompressed to + * packed-pixel images with any of the extended RGB or grayscale pixel + * formats, or they can be compressed from and decompressed to planar YUV + * images. + */ + TJCS_GRAY, + /** + * CMYK colorspace. When compressing the JPEG image, the C, M, Y, and K + * components in the source image are reordered into image planes, but no + * colorspace conversion or subsampling is performed. CMYK JPEG images can + * only be compressed from and decompressed to packed-pixel images with the + * CMYK pixel format. + */ + TJCS_CMYK, + /** + * YCCK colorspace. YCCK (AKA "YCbCrK") is not an absolute colorspace but + * rather a mathematical transformation of CMYK designed solely for storage + * and transmission. It is to CMYK as YCbCr is to RGB. CMYK pixels can be + * reversibly transformed into YCCK, and as with YCbCr, the chrominance + * components in the YCCK pixels can be subsampled without incurring major + * perceptual loss. YCCK JPEG images can only be compressed from and + * decompressed to packed-pixel images with the CMYK pixel format. + */ + TJCS_YCCK +}; + + +/** + * Parameters + */ +enum TJPARAM { + /** + * Error handling behavior + * + * **Value** + * - `0` *[default]* Allow the current compression/decompression/transform + * operation to complete unless a fatal error is encountered. + * - `1` Immediately discontinue the current + * compression/decompression/transform operation if a warning (non-fatal + * error) occurs. + */ + TJPARAM_STOPONWARNING, + /** + * Row order in packed-pixel source/destination images + * + * **Value** + * - `0` *[default]* top-down (X11) order + * - `1` bottom-up (Windows, OpenGL) order + */ + TJPARAM_BOTTOMUP, + /** + * JPEG destination buffer (re)allocation [compression, lossless + * transformation] + * + * **Value** + * - `0` *[default]* Attempt to allocate or reallocate the JPEG destination + * buffer as needed. + * - `1` Generate an error if the JPEG destination buffer is invalid or too + * small. + */ + TJPARAM_NOREALLOC, + /** + * Perceptual quality of lossy JPEG images [compression only] + * + * **Value** + * - `1`-`100` (`1` = worst quality but best compression, `100` = best + * quality but worst compression) *[no default; must be explicitly + * specified]* + */ + TJPARAM_QUALITY, + /** + * Chrominance subsampling level + * + * The JPEG or YUV image uses (decompression, decoding) or will use (lossy + * compression, encoding) the specified level of chrominance subsampling. + * + * **Value** + * - One of the @ref TJSAMP "chrominance subsampling options" *[no default; + * must be explicitly specified for lossy compression, encoding, and + * decoding]* + */ + TJPARAM_SUBSAMP, + /** + * JPEG width (in pixels) [decompression only, read-only] + */ + TJPARAM_JPEGWIDTH, + /** + * JPEG height (in pixels) [decompression only, read-only] + */ + TJPARAM_JPEGHEIGHT, + /** + * JPEG data precision (bits per sample) [decompression only, read-only] + * + * The JPEG image uses the specified number of bits per sample. + * + * **Value** + * - `8`, `12`, or `16` + * + * 12-bit data precision implies #TJPARAM_OPTIMIZE unless #TJPARAM_ARITHMETIC + * is set. + */ + TJPARAM_PRECISION, + /** + * JPEG colorspace + * + * The JPEG image uses (decompression) or will use (lossy compression) the + * specified colorspace. + * + * **Value** + * - One of the @ref TJCS "JPEG colorspaces" *[default for lossy compression: + * automatically selected based on the subsampling level and pixel format]* + */ + TJPARAM_COLORSPACE, + /** + * Chrominance upsampling algorithm [lossy decompression only] + * + * **Value** + * - `0` *[default]* Use smooth upsampling when decompressing a JPEG image + * that was compressed using chrominance subsampling. This creates a smooth + * transition between neighboring chrominance components in order to reduce + * upsampling artifacts in the decompressed image. + * - `1` Use the fastest chrominance upsampling algorithm available, which + * may combine upsampling with color conversion. + */ + TJPARAM_FASTUPSAMPLE, + /** + * DCT/IDCT algorithm [lossy compression and decompression] + * + * **Value** + * - `0` *[default]* Use the most accurate DCT/IDCT algorithm available. + * - `1` Use the fastest DCT/IDCT algorithm available. + * + * This parameter is provided mainly for backward compatibility with libjpeg, + * which historically implemented several different DCT/IDCT algorithms + * because of performance limitations with 1990s CPUs. In the libjpeg-turbo + * implementation of the TurboJPEG API: + * - The "fast" and "accurate" DCT/IDCT algorithms perform similarly on + * modern x86/x86-64 CPUs that support AVX2 instructions. + * - The "fast" algorithm is generally only about 5-15% faster than the + * "accurate" algorithm on other types of CPUs. + * - The difference in accuracy between the "fast" and "accurate" algorithms + * is the most pronounced at JPEG quality levels above 90 and tends to be + * more pronounced with decompression than with compression. + * - The "fast" algorithm degrades and is not fully accelerated for JPEG + * quality levels above 97, so it will be slower than the "accurate" + * algorithm. + */ + TJPARAM_FASTDCT, + /** + * Optimized baseline entropy coding [lossy compression only] + * + * **Value** + * - `0` *[default]* The JPEG image will use the default Huffman tables. + * - `1` Optimal Huffman tables will be computed for the JPEG image. For + * lossless transformation, this can also be specified using + * #TJXOPT_OPTIMIZE. + * + * Optimized baseline entropy coding will improve compression slightly + * (generally 5% or less), but it will reduce compression performance + * considerably. + */ + TJPARAM_OPTIMIZE, + /** + * Progressive entropy coding + * + * **Value** + * - `0` *[default for compression, lossless transformation]* The lossy JPEG + * image uses (decompression) or will use (compression, lossless + * transformation) baseline entropy coding. + * - `1` The lossy JPEG image uses (decompression) or will use (compression, + * lossless transformation) progressive entropy coding. For lossless + * transformation, this can also be specified using #TJXOPT_PROGRESSIVE. + * + * Progressive entropy coding will generally improve compression relative to + * baseline entropy coding, but it will reduce compression and decompression + * performance considerably. Can be combined with #TJPARAM_ARITHMETIC. + * Implies #TJPARAM_OPTIMIZE unless #TJPARAM_ARITHMETIC is also set. + */ + TJPARAM_PROGRESSIVE, + /** + * Progressive JPEG scan limit for lossy JPEG images [decompression, lossless + * transformation] + * + * Setting this parameter will cause the decompression and transform + * functions to return an error if the number of scans in a progressive JPEG + * image exceeds the specified limit. The primary purpose of this is to + * allow security-critical applications to guard against an exploit of the + * progressive JPEG format described in + * this report. + * + * **Value** + * - maximum number of progressive JPEG scans that the decompression and + * transform functions will process *[default: `0` (no limit)]* + * + * @see #TJPARAM_PROGRESSIVE + */ + TJPARAM_SCANLIMIT, + /** + * Arithmetic entropy coding + * + * **Value** + * - `0` *[default for compression, lossless transformation]* The lossy JPEG + * image uses (decompression) or will use (compression, lossless + * transformation) Huffman entropy coding. + * - `1` The lossy JPEG image uses (decompression) or will use (compression, + * lossless transformation) arithmetic entropy coding. For lossless + * transformation, this can also be specified using #TJXOPT_ARITHMETIC. + * + * Arithmetic entropy coding will generally improve compression relative to + * Huffman entropy coding, but it will reduce compression and decompression + * performance considerably. Can be combined with #TJPARAM_PROGRESSIVE. + */ + TJPARAM_ARITHMETIC, + /** + * Lossless JPEG + * + * **Value** + * - `0` *[default for compression]* The JPEG image is (decompression) or + * will be (compression) lossy/DCT-based. + * - `1` The JPEG image is (decompression) or will be (compression) + * lossless/predictive. + * + * In most cases, compressing and decompressing lossless JPEG images is + * considerably slower than compressing and decompressing lossy JPEG images, + * and lossless JPEG images are much larger than lossy JPEG images. Thus, + * lossless JPEG images are typically used only for applications that require + * mathematically lossless compression. Also note that the following + * features are not available with lossless JPEG images: + * - Colorspace conversion (lossless JPEG images always use #TJCS_RGB, + * #TJCS_GRAY, or #TJCS_CMYK, depending on the pixel format of the source + * image) + * - Chrominance subsampling (lossless JPEG images always use #TJSAMP_444) + * - JPEG quality selection + * - DCT/IDCT algorithm selection + * - Progressive entropy coding + * - Arithmetic entropy coding + * - Compression from/decompression to planar YUV images + * - Decompression scaling + * - Lossless transformation + * + * @see #TJPARAM_LOSSLESSPSV, #TJPARAM_LOSSLESSPT + */ + TJPARAM_LOSSLESS, + /** + * Lossless JPEG predictor selection value (PSV) + * + * **Value** + * - `1`-`7` *[default for compression: `1`]* + * + * Lossless JPEG compression shares no algorithms with lossy JPEG + * compression. Instead, it uses differential pulse-code modulation (DPCM), + * an algorithm whereby each sample is encoded as the difference between the + * sample's value and a "predictor", which is based on the values of + * neighboring samples. If Ra is the sample immediately to the left of the + * current sample, Rb is the sample immediately above the current sample, and + * Rc is the sample diagonally to the left and above the current sample, then + * the relationship between the predictor selection value and the predictor + * is as follows: + * + * PSV | Predictor + * ----|---------- + * 1 | Ra + * 2 | Rb + * 3 | Rc + * 4 | Ra + Rb – Rc + * 5 | Ra + (Rb – Rc) / 2 + * 6 | Rb + (Ra – Rc) / 2 + * 7 | (Ra + Rb) / 2 + * + * Predictors 1-3 are 1-dimensional predictors, whereas Predictors 4-7 are + * 2-dimensional predictors. The best predictor for a particular image + * depends on the image. + * + * @see #TJPARAM_LOSSLESS + */ + TJPARAM_LOSSLESSPSV, + /** + * Lossless JPEG point transform (Pt) + * + * **Value** + * - `0` through ***precision*** *- 1*, where ***precision*** is the JPEG + * data precision in bits *[default for compression: `0`]* + * + * A point transform value of `0` is necessary in order to generate a fully + * lossless JPEG image. (A non-zero point transform value right-shifts the + * input samples by the specified number of bits, which is effectively a form + * of lossy color quantization.) + * + * @see #TJPARAM_LOSSLESS, #TJPARAM_PRECISION + */ + TJPARAM_LOSSLESSPT, + /** + * JPEG restart marker interval in MCU blocks (lossy) or samples (lossless) + * [compression only] + * + * The nature of entropy coding is such that a corrupt JPEG image cannot + * be decompressed beyond the point of corruption unless it contains restart + * markers. A restart marker stops and restarts the entropy coding algorithm + * so that, if a JPEG image is corrupted, decompression can resume at the + * next marker. Thus, adding more restart markers improves the fault + * tolerance of the JPEG image, but adding too many restart markers can + * adversely affect the compression ratio and performance. + * + * **Value** + * - the number of MCU blocks or samples between each restart marker + * *[default: `0` (no restart markers)]* + * + * Setting this parameter to a non-zero value sets #TJPARAM_RESTARTROWS to 0. + */ + TJPARAM_RESTARTBLOCKS, + /** + * JPEG restart marker interval in MCU rows (lossy) or sample rows (lossless) + * [compression only] + * + * See #TJPARAM_RESTARTBLOCKS for a description of restart markers. + * + * **Value** + * - the number of MCU rows or sample rows between each restart marker + * *[default: `0` (no restart markers)]* + * + * Setting this parameter to a non-zero value sets #TJPARAM_RESTARTBLOCKS to + * 0. + */ + TJPARAM_RESTARTROWS, + /** + * JPEG horizontal pixel density + * + * **Value** + * - The JPEG image has (decompression) or will have (compression) the + * specified horizontal pixel density *[default for compression: `1`]*. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value of #TJPARAM_DENSITYUNITS + * is `2`. + * + * @see TJPARAM_DENSITYUNITS + */ + TJPARAM_XDENSITY, + /** + * JPEG vertical pixel density + * + * **Value** + * - The JPEG image has (decompression) or will have (compression) the + * specified vertical pixel density *[default for compression: `1`]*. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value of #TJPARAM_DENSITYUNITS + * is `2`. + * + * @see TJPARAM_DENSITYUNITS + */ + TJPARAM_YDENSITY, + /** + * JPEG pixel density units + * + * **Value** + * - `0` *[default for compression]* The pixel density of the JPEG image is + * expressed (decompression) or will be expressed (compression) in unknown + * units. + * - `1` The pixel density of the JPEG image is expressed (decompression) or + * will be expressed (compression) in units of pixels/inch. + * - `2` The pixel density of the JPEG image is expressed (decompression) or + * will be expressed (compression) in units of pixels/cm. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value is `2`. + * + * @see TJPARAM_XDENSITY, TJPARAM_YDENSITY + */ + TJPARAM_DENSITYUNITS, + /** + * Memory limit for intermediate buffers + * + * **Value** + * - the maximum amount of memory (in megabytes) that will be allocated for + * intermediate buffers, which are used with progressive JPEG compression and + * decompression, optimized baseline entropy coding, lossless JPEG + * compression, and lossless transformation *[default: `0` (no limit)]* + */ + TJPARAM_MAXMEMORY, + /** + * Image size limit [decompression, lossless transformation, packed-pixel + * image loading] + * + * Setting this parameter will cause the decompression, transform, and image + * loading functions to return an error if the number of pixels in the source + * image exceeds the specified limit. This allows security-critical + * applications to guard against excessive memory consumption. + * + * **Value** + * - maximum number of pixels that the decompression, transform, and image + * loading functions will process *[default: `0` (no limit)]* + */ + TJPARAM_MAXPIXELS +}; + + +/** + * The number of error codes + */ +#define TJ_NUMERR 2 + +/** + * Error codes + */ +enum TJERR { + /** + * The error was non-fatal and recoverable, but the destination image may + * still be corrupt. + */ + TJERR_WARNING, + /** + * The error was fatal and non-recoverable. + */ + TJERR_FATAL +}; + + +/** + * The number of transform operations + */ +#define TJ_NUMXOP 8 + +/** + * Transform operations for #tj3Transform() + */ +enum TJXOP { + /** + * Do not transform the position of the image pixels + */ + TJXOP_NONE, + /** + * Flip (mirror) image horizontally. This transform is imperfect if there + * are any partial MCU blocks on the right edge (see #TJXOPT_PERFECT.) + */ + TJXOP_HFLIP, + /** + * Flip (mirror) image vertically. This transform is imperfect if there are + * any partial MCU blocks on the bottom edge (see #TJXOPT_PERFECT.) + */ + TJXOP_VFLIP, + /** + * Transpose image (flip/mirror along upper left to lower right axis.) This + * transform is always perfect. + */ + TJXOP_TRANSPOSE, + /** + * Transverse transpose image (flip/mirror along upper right to lower left + * axis.) This transform is imperfect if there are any partial MCU blocks in + * the image (see #TJXOPT_PERFECT.) + */ + TJXOP_TRANSVERSE, + /** + * Rotate image clockwise by 90 degrees. This transform is imperfect if + * there are any partial MCU blocks on the bottom edge (see + * #TJXOPT_PERFECT.) + */ + TJXOP_ROT90, + /** + * Rotate image 180 degrees. This transform is imperfect if there are any + * partial MCU blocks in the image (see #TJXOPT_PERFECT.) + */ + TJXOP_ROT180, + /** + * Rotate image counter-clockwise by 90 degrees. This transform is imperfect + * if there are any partial MCU blocks on the right edge (see + * #TJXOPT_PERFECT.) + */ + TJXOP_ROT270 +}; + + +/** + * This option will cause #tj3Transform() to return an error if the transform + * is not perfect. Lossless transforms operate on MCU blocks, whose size + * depends on the level of chrominance subsampling used (see #tjMCUWidth and + * #tjMCUHeight.) If the image's width or height is not evenly divisible by + * the MCU block size, then there will be partial MCU blocks on the right + * and/or bottom edges. It is not possible to move these partial MCU blocks to + * the top or left of the image, so any transform that would require that is + * "imperfect." If this option is not specified, then any partial MCU blocks + * that cannot be transformed will be left in place, which will create + * odd-looking strips on the right or bottom edge of the image. + */ +#define TJXOPT_PERFECT (1 << 0) +/** + * This option will cause #tj3Transform() to discard any partial MCU blocks + * that cannot be transformed. + */ +#define TJXOPT_TRIM (1 << 1) +/** + * This option will enable lossless cropping. See #tj3Transform() for more + * information. + */ +#define TJXOPT_CROP (1 << 2) +/** + * This option will discard the color data in the source image and produce a + * grayscale destination image. + */ +#define TJXOPT_GRAY (1 << 3) +/** + * This option will prevent #tj3Transform() from outputting a JPEG image for + * this particular transform. (This can be used in conjunction with a custom + * filter to capture the transformed DCT coefficients without transcoding + * them.) + */ +#define TJXOPT_NOOUTPUT (1 << 4) +/** + * This option will enable progressive entropy coding in the JPEG image + * generated by this particular transform. Progressive entropy coding will + * generally improve compression relative to baseline entropy coding (the + * default), but it will reduce decompression performance considerably. + * Can be combined with #TJXOPT_ARITHMETIC. Implies #TJXOPT_OPTIMIZE unless + * #TJXOPT_ARITHMETIC is also specified. + */ +#define TJXOPT_PROGRESSIVE (1 << 5) +/** + * This option will prevent #tj3Transform() from copying any extra markers + * (including EXIF and ICC profile data) from the source image to the + * destination image. + */ +#define TJXOPT_COPYNONE (1 << 6) +/** + * This option will enable arithmetic entropy coding in the JPEG image + * generated by this particular transform. Arithmetic entropy coding will + * generally improve compression relative to Huffman entropy coding (the + * default), but it will reduce decompression performance considerably. Can be + * combined with #TJXOPT_PROGRESSIVE. + */ +#define TJXOPT_ARITHMETIC (1 << 7) +/** + * This option will enable optimized baseline entropy coding in the JPEG image + * generated by this particular transform. Optimized baseline entropy coding + * will improve compression slightly (generally 5% or less.) + */ +#define TJXOPT_OPTIMIZE (1 << 8) + + +/** + * Scaling factor + */ +typedef struct { + /** + * Numerator + */ + int num; + /** + * Denominator + */ + int denom; +} tjscalingfactor; + +/** + * Cropping region + */ +typedef struct { + /** + * The left boundary of the cropping region. This must be evenly divisible + * by the MCU block width (see #tjMCUWidth.) + */ + int x; + /** + * The upper boundary of the cropping region. For lossless transformation, + * this must be evenly divisible by the MCU block height (see #tjMCUHeight.) + */ + int y; + /** + * The width of the cropping region. Setting this to 0 is the equivalent of + * setting it to the width of the source JPEG image - x. + */ + int w; + /** + * The height of the cropping region. Setting this to 0 is the equivalent of + * setting it to the height of the source JPEG image - y. + */ + int h; +} tjregion; + +/** + * A #tjregion structure that specifies no cropping + */ +static const tjregion TJUNCROPPED = { 0, 0, 0, 0 }; + +/** + * Lossless transform + */ +typedef struct tjtransform { + /** + * Cropping region + */ + tjregion r; + /** + * One of the @ref TJXOP "transform operations" + */ + int op; + /** + * The bitwise OR of one of more of the @ref TJXOPT_ARITHMETIC + * "transform options" + */ + int options; + /** + * Arbitrary data that can be accessed within the body of the callback + * function + */ + void *data; + /** + * A callback function that can be used to modify the DCT coefficients after + * they are losslessly transformed but before they are transcoded to a new + * JPEG image. This allows for custom filters or other transformations to be + * applied in the frequency domain. + * + * @param coeffs pointer to an array of transformed DCT coefficients. (NOTE: + * this pointer is not guaranteed to be valid once the callback returns, so + * applications wishing to hand off the DCT coefficients to another function + * or library should make a copy of them within the body of the callback.) + * + * @param arrayRegion #tjregion structure containing the width and height of + * the array pointed to by `coeffs` as well as its offset relative to the + * component plane. TurboJPEG implementations may choose to split each + * component plane into multiple DCT coefficient arrays and call the callback + * function once for each array. + * + * @param planeRegion #tjregion structure containing the width and height of + * the component plane to which `coeffs` belongs + * + * @param componentID ID number of the component plane to which `coeffs` + * belongs. (Y, Cb, and Cr have, respectively, ID's of 0, 1, and 2 in + * typical JPEG images.) + * + * @param transformID ID number of the transformed image to which `coeffs` + * belongs. This is the same as the index of the transform in the + * `transforms` array that was passed to #tj3Transform(). + * + * @param transform a pointer to a #tjtransform structure that specifies the + * parameters and/or cropping region for this transform + * + * @return 0 if the callback was successful, or -1 if an error occurred. + */ + int (*customFilter) (short *coeffs, tjregion arrayRegion, + tjregion planeRegion, int componentID, int transformID, + struct tjtransform *transform); +} tjtransform; + +/** + * TurboJPEG instance handle + */ +typedef void *tjhandle; + + +/** + * Compute the scaled value of `dimension` using the given scaling factor. + * This macro performs the integer equivalent of `ceil(dimension * + * scalingFactor)`. + */ +#define TJSCALED(dimension, scalingFactor) \ + (((dimension) * scalingFactor.num + scalingFactor.denom - 1) / \ + scalingFactor.denom) + +/** + * A #tjscalingfactor structure that specifies a scaling factor of 1/1 (no + * scaling) + */ +static const tjscalingfactor TJUNSCALED = { 1, 1 }; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Create a new TurboJPEG instance. + * + * @param initType one of the @ref TJINIT "initialization options" + * + * @return a handle to the newly-created instance, or NULL if an error occurred + * (see #tj3GetErrorStr().) + */ +DLLEXPORT tjhandle tj3Init(int initType); + + +/** + * Set the value of a parameter. + * + * @param handle handle to a TurboJPEG instance + * + * @param param one of the @ref TJPARAM "parameters" + * + * @param value value of the parameter (refer to @ref TJPARAM + * "parameter documentation") + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3Set(tjhandle handle, int param, int value); + + +/** + * Get the value of a parameter. + * + * @param handle handle to a TurboJPEG instance + * + * @param param one of the @ref TJPARAM "parameters" + * + * @return the value of the specified parameter, or -1 if the value is unknown. + */ +DLLEXPORT int tj3Get(tjhandle handle, int param); + + +/** + * Compress an 8-bit-per-sample packed-pixel RGB, grayscale, or CMYK image into + * an 8-bit-per-sample JPEG image. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK source image to be compressed. This buffer should normally be + * `pitch * height` samples in size. However, you can also use this parameter + * to compress from a specific region of a larger buffer. + * + * @param width width (in pixels) of the source image + * + * @param pitch samples per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to compress from a specific region of a larger buffer. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize(). This should ensure that the buffer never has to be + * re-allocated. (Setting #TJPARAM_NOREALLOC guarantees that it won't be.) + * . + * If you choose option 1, then `*jpegSize` should be set to the size of your + * pre-allocated buffer. In any case, unless you have set #TJPARAM_NOREALLOC, + * you should always check `*jpegBuf` upon return from this function, as it may + * have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Upon return, `*jpegSize` will + * contain the size of the JPEG image (in bytes.) If `*jpegBuf` points to a + * JPEG buffer that is being reused from a previous call to one of the JPEG + * compression functions, then `*jpegSize` is ignored. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Compress8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + +/** + * Compress a 12-bit-per-sample packed-pixel RGB, grayscale, or CMYK image into + * a 12-bit-per-sample JPEG image. + * + * \details \copydetails tj3Compress8() + */ +DLLEXPORT int tj3Compress12(tjhandle handle, const short *srcBuf, int width, + int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + +/** + * Compress a 16-bit-per-sample packed-pixel RGB, grayscale, or CMYK image into + * a 16-bit-per-sample lossless JPEG image. + * + * \details \copydetails tj3Compress8() + */ +DLLEXPORT int tj3Compress16(tjhandle handle, const unsigned short *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + + +/** + * Compress an 8-bit-per-sample unified planar YUV image into an + * 8-bit-per-sample JPEG image. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a unified planar YUV source + * image to be compressed. The size of this buffer should match the value + * returned by #tj3YUVBufSize() for the given image width, height, row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes should be stored sequentially in the + * buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param width width (in pixels) of the source image. If the width is not an + * even multiple of the MCU block width (see #tjMCUWidth), then an intermediate + * buffer copy will be performed. + * + * @param align row alignment (in bytes) of the source image (must be a power + * of 2.) Setting this parameter to n indicates that each row in each plane of + * the source image is padded to the nearest multiple of n bytes + * (1 = unpadded.) + * + * @param height height (in pixels) of the source image. If the height is not + * an even multiple of the MCU block height (see #tjMCUHeight), then an + * intermediate buffer copy will be performed. + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize(). This should ensure that the buffer never has to be + * re-allocated. (Setting #TJPARAM_NOREALLOC guarantees that it won't be.) + * . + * If you choose option 1, then `*jpegSize` should be set to the size of your + * pre-allocated buffer. In any case, unless you have set #TJPARAM_NOREALLOC, + * you should always check `*jpegBuf` upon return from this function, as it may + * have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Upon return, `*jpegSize` will + * contain the size of the JPEG image (in bytes.) If `*jpegBuf` points to a + * JPEG buffer that is being reused from a previous call to one of the JPEG + * compression functions, then `*jpegSize` is ignored. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3CompressFromYUV8(tjhandle handle, + const unsigned char *srcBuf, int width, + int align, int height, + unsigned char **jpegBuf, size_t *jpegSize); + + +/** + * Compress a set of 8-bit-per-sample Y, U (Cb), and V (Cr) image planes into + * an 8-bit-per-sample JPEG image. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if compressing a grayscale image) that contain a YUV + * source image to be compressed. These planes can be contiguous or + * non-contiguous in memory. The size of each plane should match the value + * returned by #tj3YUVPlaneSize() for the given image width, height, strides, + * and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) Refer to + * @ref YUVnotes "YUV Image Format Notes" for more details. + * + * @param width width (in pixels) of the source image. If the width is not an + * even multiple of the MCU block width (see #tjMCUWidth), then an intermediate + * buffer copy will be performed. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV source image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective plane widths. You + * can adjust the strides in order to specify an arbitrary amount of row + * padding in each plane or to create a JPEG image from a subregion of a larger + * planar YUV image. + * + * @param height height (in pixels) of the source image. If the height is not + * an even multiple of the MCU block height (see #tjMCUHeight), then an + * intermediate buffer copy will be performed. + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize(). This should ensure that the buffer never has to be + * re-allocated. (Setting #TJPARAM_NOREALLOC guarantees that it won't be.) + * . + * If you choose option 1, then `*jpegSize` should be set to the size of your + * pre-allocated buffer. In any case, unless you have set #TJPARAM_NOREALLOC, + * you should always check `*jpegBuf` upon return from this function, as it may + * have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Upon return, `*jpegSize` will + * contain the size of the JPEG image (in bytes.) If `*jpegBuf` points to a + * JPEG buffer that is being reused from a previous call to one of the JPEG + * compression functions, then `*jpegSize` is ignored. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3CompressFromYUVPlanes8(tjhandle handle, + const unsigned char * const *srcPlanes, + int width, const int *strides, + int height, unsigned char **jpegBuf, + size_t *jpegSize); + + +/** + * The maximum size of the buffer (in bytes) required to hold a JPEG image with + * the given parameters. The number of bytes returned by this function is + * larger than the size of the uncompressed source image. The reason for this + * is that the JPEG format uses 16-bit coefficients, so it is possible for a + * very high-quality source image with very high-frequency content to expand + * rather than compress when converted to the JPEG format. Such images + * represent very rare corner cases, but since there is no way to predict the + * size of a JPEG image prior to compression, the corner cases have to be + * handled. + * + * @param width width (in pixels) of the image + * + * @param height height (in pixels) of the image + * + * @param jpegSubsamp the level of chrominance subsampling to be used when + * generating the JPEG image (see @ref TJSAMP + * "Chrominance subsampling options".) #TJSAMP_UNKNOWN is treated like + * #TJSAMP_444, since a buffer large enough to hold a JPEG image with no + * subsampling should also be large enough to hold a JPEG image with an + * arbitrary level of subsampling. Note that lossless JPEG images always + * use #TJSAMP_444. + * + * @return the maximum size of the buffer (in bytes) required to hold the + * image, or 0 if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3JPEGBufSize(int width, int height, int jpegSubsamp); + + +/** + * The size of the buffer (in bytes) required to hold a unified planar YUV + * image with the given parameters. + * + * @param width width (in pixels) of the image + * + * @param align row alignment (in bytes) of the image (must be a power of 2.) + * Setting this parameter to n specifies that each row in each plane of the + * image will be padded to the nearest multiple of n bytes (1 = unpadded.) + * + * @param height height (in pixels) of the image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the size of the buffer (in bytes) required to hold the image, or 0 + * if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3YUVBufSize(int width, int align, int height, int subsamp); + + +/** + * The size of the buffer (in bytes) required to hold a YUV image plane with + * the given parameters. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param width width (in pixels) of the YUV image. NOTE: this is the width of + * the whole image, not the plane width. + * + * @param stride bytes per row in the image plane. Setting this to 0 is the + * equivalent of setting it to the plane width. + * + * @param height height (in pixels) of the YUV image. NOTE: this is the height + * of the whole image, not the plane height. + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the size of the buffer (in bytes) required to hold the YUV image + * plane, or 0 if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3YUVPlaneSize(int componentID, int width, int stride, + int height, int subsamp); + + +/** + * The plane width of a YUV image plane with the given parameters. Refer to + * @ref YUVnotes "YUV Image Format Notes" for a description of plane width. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param width width (in pixels) of the YUV image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the plane width of a YUV image plane with the given parameters, or 0 + * if the arguments are out of bounds. + */ +DLLEXPORT int tj3YUVPlaneWidth(int componentID, int width, int subsamp); + + +/** + * The plane height of a YUV image plane with the given parameters. Refer to + * @ref YUVnotes "YUV Image Format Notes" for a description of plane height. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param height height (in pixels) of the YUV image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the plane height of a YUV image plane with the given parameters, or + * 0 if the arguments are out of bounds. + */ +DLLEXPORT int tj3YUVPlaneHeight(int componentID, int height, int subsamp); + + +/** + * Encode an 8-bit-per-sample packed-pixel RGB or grayscale image into an + * 8-bit-per-sample unified planar YUV image. This function performs color + * conversion (which is accelerated in the libjpeg-turbo implementation) but + * does not execute any of the other steps in the JPEG compression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB or grayscale + * source image to be encoded. This buffer should normally be `pitch * height` + * bytes in size. However, you can also use this parameter to encode from a + * specific region of a larger buffer. + * + * @param width width (in pixels) of the source image + * + * @param pitch bytes per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to encode from a specific region of a larger packed-pixel image. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param dstBuf pointer to a buffer that will receive the unified planar YUV + * image. Use #tj3YUVBufSize() to determine the appropriate size for this + * buffer based on the image width, height, row alignment, and level of + * chrominance subsampling (see #TJPARAM_SUBSAMP.) The Y, U (Cb), and V (Cr) + * image planes will be stored sequentially in the buffer. (Refer to + * @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV image (must be a power of + * 2.) Setting this parameter to n will cause each row in each plane of the + * YUV image to be padded to the nearest multiple of n bytes (1 = unpadded.) + * To generate images suitable for X Video, `align` should be set to 4. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3EncodeYUV8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int align); + + +/** + * Encode an 8-bit-per-sample packed-pixel RGB or grayscale image into separate + * 8-bit-per-sample Y, U (Cb), and V (Cr) image planes. This function performs + * color conversion (which is accelerated in the libjpeg-turbo implementation) + * but does not execute any of the other steps in the JPEG compression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB or grayscale + * source image to be encoded. This buffer should normally be `pitch * height` + * bytes in size. However, you can also use this parameter to encode from a + * specific region of a larger buffer. + * + * + * @param width width (in pixels) of the source image + * + * @param pitch bytes per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to encode from a specific region of a larger packed-pixel image. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param dstPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if generating a grayscale image) that will receive the + * encoded image. These planes can be contiguous or non-contiguous in memory. + * Use #tj3YUVPlaneSize() to determine the appropriate size for each plane + * based on the image width, height, strides, and level of chrominance + * subsampling (see #TJPARAM_SUBSAMP.) Refer to @ref YUVnotes + * "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV image. Setting the stride for any + * plane to 0 is the same as setting it to the plane width (see @ref YUVnotes + * "YUV Image Format Notes".) If `strides` is NULL, then the strides for all + * planes will be set to their respective plane widths. You can adjust the + * strides in order to add an arbitrary amount of row padding to each plane or + * to encode an RGB or grayscale image into a subregion of a larger planar YUV + * image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3EncodeYUVPlanes8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, + int pixelFormat, unsigned char **dstPlanes, + int *strides); + + +/** + * Retrieve information about a JPEG image without decompressing it, or prime + * the decompressor with quantization and Huffman tables. If a JPEG image is + * passed to this function, then the @ref TJPARAM "parameters" that describe + * the JPEG image will be set when the function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing a JPEG image or an + * "abbreviated table specification" (AKA "tables-only") datastream. Passing a + * tables-only datastream to this function primes the decompressor with + * quantization and Huffman tables that can be used when decompressing + * subsequent "abbreviated image" datastreams. This is useful, for instance, + * when decompressing video streams in which all frames share the same + * quantization and Huffman tables. + * + * @param jpegSize size of the JPEG image or tables-only datastream (in bytes) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressHeader(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize); + + +/** + * Returns a list of fractional scaling factors that the JPEG decompressor + * supports. + * + * @param numScalingFactors pointer to an integer variable that will receive + * the number of elements in the list + * + * @return a pointer to a list of fractional scaling factors, or NULL if an + * error is encountered (see #tj3GetErrorStr().) + */ +DLLEXPORT tjscalingfactor *tj3GetScalingFactors(int *numScalingFactors); + + +/** + * Set the scaling factor for subsequent lossy decompression operations. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param scalingFactor #tjscalingfactor structure that specifies a fractional + * scaling factor that the decompressor supports (see #tj3GetScalingFactors()), + * or #TJUNSCALED for no scaling. Decompression scaling is a function + * of the IDCT algorithm, so scaling factors are generally limited to multiples + * of 1/8. If the entire JPEG image will be decompressed, then the width and + * height of the scaled destination image can be determined by calling + * #TJSCALED() with the JPEG width and height (see #TJPARAM_JPEGWIDTH and + * #TJPARAM_JPEGHEIGHT) and the specified scaling factor. When decompressing + * into a planar YUV image, an intermediate buffer copy will be performed if + * the width or height of the scaled destination image is not an even multiple + * of the MCU block size (see #tjMCUWidth and #tjMCUHeight.) Note that + * decompression scaling is not available (and the specified scaling factor is + * ignored) when decompressing lossless JPEG images (see #TJPARAM_LOSSLESS), + * since the IDCT algorithm is not used with those images. Note also that + * #TJPARAM_FASTDCT is ignored when decompression scaling is enabled. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SetScalingFactor(tjhandle handle, + tjscalingfactor scalingFactor); + + +/** + * Set the cropping region for partially decompressing a lossy JPEG image into + * a packed-pixel image + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param croppingRegion #tjregion structure that specifies a subregion of the + * JPEG image to decompress, or #TJUNCROPPED for no cropping. The + * left boundary of the cropping region must be evenly divisible by the scaled + * MCU block width (#TJSCALED(#tjMCUWidth[subsamp], scalingFactor), + * where `subsamp` is the level of chrominance subsampling in the JPEG image + * (see #TJPARAM_SUBSAMP) and `scalingFactor` is the decompression scaling + * factor (see #tj3SetScalingFactor().) The cropping region should be + * specified relative to the scaled image dimensions. Unless `croppingRegion` + * is #TJUNCROPPED, the JPEG header must be read (see + * #tj3DecompressHeader()) prior to calling this function. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SetCroppingRegion(tjhandle handle, tjregion croppingRegion); + + +/** + * Decompress an 8-bit-per-sample JPEG image into an 8-bit-per-sample + * packed-pixel RGB, grayscale, or CMYK image. The @ref TJPARAM "parameters" + * that describe the JPEG image will be set when this function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel + * decompressed image. This buffer should normally be + * `pitch * destinationHeight` samples in size. However, you can also use this + * parameter to decompress into a specific region of a larger buffer. NOTE: + * If the JPEG image is lossy, then `destinationHeight` is either the scaled + * JPEG height (see #TJSCALED(), #TJPARAM_JPEGHEIGHT, and + * #tj3SetScalingFactor()) or the height of the cropping region (see + * #tj3SetCroppingRegion().) If the JPEG image is lossless, then + * `destinationHeight` is the JPEG height. + * + * @param pitch samples per row in the destination image. Normally this should + * be set to destinationWidth * #tjPixelSize[pixelFormat], if the + * destination image should be unpadded. (Setting this parameter to 0 is the + * equivalent of setting it to + * destinationWidth * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decompress into a specific region of + * a larger buffer. NOTE: If the JPEG image is lossy, then `destinationWidth` + * is either the scaled JPEG width (see #TJSCALED(), #TJPARAM_JPEGWIDTH, and + * #tj3SetScalingFactor()) or the width of the cropping region (see + * #tj3SetCroppingRegion().) If the JPEG image is lossless, then + * `destinationWidth` is the JPEG width. + * + * @param pixelFormat pixel format of the destination image (see @ref + * TJPF "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Decompress8(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, unsigned char *dstBuf, int pitch, + int pixelFormat); + +/** + * Decompress a 12-bit-per-sample JPEG image into a 12-bit-per-sample + * packed-pixel RGB, grayscale, or CMYK image. + * + * \details \copydetails tj3Decompress8() + */ +DLLEXPORT int tj3Decompress12(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, short *dstBuf, int pitch, + int pixelFormat); + +/** + * Decompress a 16-bit-per-sample lossless JPEG image into a 16-bit-per-sample + * packed-pixel RGB, grayscale, or CMYK image. + * + * \details \copydetails tj3Decompress8() + */ +DLLEXPORT int tj3Decompress16(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, unsigned short *dstBuf, + int pitch, int pixelFormat); + + +/** + * Decompress an 8-bit-per-sample JPEG image into an 8-bit-per-sample unified + * planar YUV image. This function performs JPEG decompression but leaves out + * the color conversion step, so a planar YUV image is generated instead of a + * packed-pixel image. The @ref TJPARAM "parameters" that describe the JPEG + * image will be set when this function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstBuf pointer to a buffer that will receive the unified planar YUV + * decompressed image. Use #tj3YUVBufSize() to determine the appropriate size + * for this buffer based on the scaled JPEG width and height (see #TJSCALED(), + * #TJPARAM_JPEGWIDTH, #TJPARAM_JPEGHEIGHT, and #tj3SetScalingFactor()), row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes will be stored sequentially in the + * buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV image (must be a power of + * 2.) Setting this parameter to n will cause each row in each plane of the + * YUV image to be padded to the nearest multiple of n bytes (1 = unpadded.) + * To generate images suitable for X Video, `align` should be set to 4. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressToYUV8(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize, + unsigned char *dstBuf, int align); + + +/** + * Decompress an 8-bit-per-sample JPEG image into separate 8-bit-per-sample Y, + * U (Cb), and V (Cr) image planes. This function performs JPEG decompression + * but leaves out the color conversion step, so a planar YUV image is generated + * instead of a packed-pixel image. The @ref TJPARAM "parameters" that + * describe the JPEG image will be set when this function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if decompressing a grayscale image) that will receive + * the decompressed image. These planes can be contiguous or non-contiguous in + * memory. Use #tj3YUVPlaneSize() to determine the appropriate size for each + * plane based on the scaled JPEG width and height (see #TJSCALED(), + * #TJPARAM_JPEGWIDTH, #TJPARAM_JPEGHEIGHT, and #tj3SetScalingFactor()), + * strides, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) Refer + * to @ref YUVnotes "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV image. Setting the stride for any + * plane to 0 is the same as setting it to the scaled plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective scaled plane widths. + * You can adjust the strides in order to add an arbitrary amount of row + * padding to each plane or to decompress the JPEG image into a subregion of a + * larger planar YUV image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressToYUVPlanes8(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize, + unsigned char **dstPlanes, + int *strides); + + +/** + * Decode an 8-bit-per-sample unified planar YUV image into an 8-bit-per-sample + * packed-pixel RGB or grayscale image. This function performs color + * conversion (which is accelerated in the libjpeg-turbo implementation) but + * does not execute any of the other steps in the JPEG decompression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param srcBuf pointer to a buffer containing a unified planar YUV source + * image to be decoded. The size of this buffer should match the value + * returned by #tj3YUVBufSize() for the given image width, height, row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes should be stored sequentially in the + * source buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV source image (must be a + * power of 2.) Setting this parameter to n indicates that each row in each + * plane of the YUV source image is padded to the nearest multiple of n bytes + * (1 = unpadded.) + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel decoded + * image. This buffer should normally be `pitch * height` bytes in size. + * However, you can also use this parameter to decode into a specific region of + * a larger buffer. + * + * @param width width (in pixels) of the source and destination images + * + * @param pitch bytes per row in the destination image. Normally this should + * be set to width * #tjPixelSize[pixelFormat], if the destination + * image should be unpadded. (Setting this parameter to 0 is the equivalent of + * setting it to width * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decode into a specific region of a + * larger buffer. + * + * @param height height (in pixels) of the source and destination images + * + * @param pixelFormat pixel format of the destination image (see @ref TJPF + * "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecodeYUV8(tjhandle handle, const unsigned char *srcBuf, + int align, unsigned char *dstBuf, int width, + int pitch, int height, int pixelFormat); + + +/** + * Decode a set of 8-bit-per-sample Y, U (Cb), and V (Cr) image planes into an + * 8-bit-per-sample packed-pixel RGB or grayscale image. This function + * performs color conversion (which is accelerated in the libjpeg-turbo + * implementation) but does not execute any of the other steps in the JPEG + * decompression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param srcPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if decoding a grayscale image) that contain a YUV image + * to be decoded. These planes can be contiguous or non-contiguous in memory. + * The size of each plane should match the value returned by #tj3YUVPlaneSize() + * for the given image width, height, strides, and level of chrominance + * subsampling (see #TJPARAM_SUBSAMP.) Refer to @ref YUVnotes + * "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV source image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective plane widths. You + * can adjust the strides in order to specify an arbitrary amount of row + * padding in each plane or to decode a subregion of a larger planar YUV image. + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel decoded + * image. This buffer should normally be `pitch * height` bytes in size. + * However, you can also use this parameter to decode into a specific region of + * a larger buffer. + * + * @param width width (in pixels) of the source and destination images + * + * @param pitch bytes per row in the destination image. Normally this should + * be set to width * #tjPixelSize[pixelFormat], if the destination + * image should be unpadded. (Setting this parameter to 0 is the equivalent of + * setting it to width * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decode into a specific region of a + * larger buffer. + * + * @param height height (in pixels) of the source and destination images + * + * @param pixelFormat pixel format of the destination image (see @ref TJPF + * "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecodeYUVPlanes8(tjhandle handle, + const unsigned char * const *srcPlanes, + const int *strides, unsigned char *dstBuf, + int width, int pitch, int height, + int pixelFormat); + + +/** + * Losslessly transform a JPEG image into another JPEG image. Lossless + * transforms work by moving the raw DCT coefficients from one JPEG image + * structure to another without altering the values of the coefficients. While + * this is typically faster than decompressing the image, transforming it, and + * re-compressing it, lossless transforms are not free. Each lossless + * transform requires reading and performing entropy decoding on all of the + * coefficients in the source image, regardless of the size of the destination + * image. Thus, this function provides a means of generating multiple + * transformed images from the same source or applying multiple transformations + * simultaneously, in order to eliminate the need to read the source + * coefficients multiple times. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * lossless transformation + * + * @param jpegBuf pointer to a byte buffer containing the JPEG source image to + * transform + * + * @param jpegSize size of the JPEG source image (in bytes) + * + * @param n the number of transformed JPEG images to generate + * + * @param dstBufs pointer to an array of n byte buffers. `dstBufs[i]` will + * receive a JPEG image that has been transformed using the parameters in + * `transforms[i]`. TurboJPEG has the ability to reallocate the JPEG + * destination buffer to accommodate the size of the transformed JPEG image. + * Thus, you can choose to: + * -# pre-allocate the JPEG destination buffer with an arbitrary size using + * #tj3Alloc() and let TurboJPEG grow the buffer as needed, + * -# set `dstBufs[i]` to NULL to tell TurboJPEG to allocate the buffer for + * you, or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() with the transformed or cropped width and height and the + * level of subsampling used in the source image. Under normal circumstances, + * this should ensure that the buffer never has to be re-allocated. (Setting + * #TJPARAM_NOREALLOC guarantees that it won't be.) Note, however, that there + * are some rare cases (such as transforming images with a large amount of + * embedded EXIF or ICC profile data) in which the transformed JPEG image will + * be larger than the worst-case size, and #TJPARAM_NOREALLOC cannot be used in + * those cases. + * . + * If you choose option 1, then `dstSizes[i]` should be set to the size of your + * pre-allocated buffer. In any case, unless you have set #TJPARAM_NOREALLOC, + * you should always check `dstBufs[i]` upon return from this function, as it + * may have changed. + * + * @param dstSizes pointer to an array of n size_t variables that will receive + * the actual sizes (in bytes) of each transformed JPEG image. If `dstBufs[i]` + * points to a pre-allocated buffer, then `dstSizes[i]` should be set to the + * size of the buffer. Upon return, `dstSizes[i]` will contain the size of the + * transformed JPEG image (in bytes.) + * + * @param transforms pointer to an array of n #tjtransform structures, each of + * which specifies the transform parameters and/or cropping region for the + * corresponding transformed JPEG image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Transform(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, int n, unsigned char **dstBufs, + size_t *dstSizes, const tjtransform *transforms); + + +/** + * Destroy a TurboJPEG instance. + * + * @param handle handle to a TurboJPEG instance. If the handle is NULL, then + * this function has no effect. + */ +DLLEXPORT void tj3Destroy(tjhandle handle); + + +/** + * Allocate a byte buffer for use with TurboJPEG. You should always use this + * function to allocate the JPEG destination buffer(s) for the compression and + * transform functions unless you are disabling automatic buffer (re)allocation + * (by setting #TJPARAM_NOREALLOC.) + * + * @param bytes the number of bytes to allocate + * + * @return a pointer to a newly-allocated buffer with the specified number of + * bytes. + * + * @see tj3Free() + */ +DLLEXPORT void *tj3Alloc(size_t bytes); + + +/** + * Load an 8-bit-per-sample packed-pixel image from disk into memory. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file containing a packed-pixel image in Windows + * BMP or PBMPLUS (PPM/PGM) format. Windows BMP files require 8-bit-per-sample + * data precision. If the data precision of the PBMPLUS file does not match + * the target data precision, then upconverting or downconverting will be + * performed. + * + * @param width pointer to an integer variable that will receive the width (in + * pixels) of the packed-pixel image + * + * @param align row alignment (in samples) of the packed-pixel buffer to be + * returned (must be a power of 2.) Setting this parameter to n will cause all + * rows in the buffer to be padded to the nearest multiple of n samples + * (1 = unpadded.) + * + * @param height pointer to an integer variable that will receive the height + * (in pixels) of the packed-pixel image + * + * @param pixelFormat pointer to an integer variable that specifies or will + * receive the pixel format of the packed-pixel buffer. The behavior of this + * function will vary depending on the value of `*pixelFormat` passed to the + * function: + * - @ref TJPF_UNKNOWN : The packed-pixel buffer returned by this function will + * use the most optimal pixel format for the file type, and `*pixelFormat` will + * contain the ID of that pixel format upon successful return from this + * function. + * - @ref TJPF_GRAY : Only PGM files and 8-bit-per-pixel BMP files with a + * grayscale colormap can be loaded. + * - @ref TJPF_CMYK : The RGB or grayscale pixels stored in the file will be + * converted using a quick & dirty algorithm that is suitable only for testing + * purposes. (Proper conversion between CMYK and other formats requires a + * color management system.) + * - Other @ref TJPF "pixel formats" : The packed-pixel buffer will use the + * specified pixel format, and pixel format conversion will be performed if + * necessary. + * + * @return a pointer to a newly-allocated buffer containing the packed-pixel + * image, converted to the chosen pixel format and with the chosen row + * alignment, or NULL if an error occurred (see #tj3GetErrorStr().) This + * buffer should be freed using #tj3Free(). + */ +DLLEXPORT unsigned char *tj3LoadImage8(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + +/** + * Load a 12-bit-per-sample packed-pixel image from disk into memory. + * + * \details \copydetails tj3LoadImage8() + */ +DLLEXPORT short *tj3LoadImage12(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + +/** + * Load a 16-bit-per-sample packed-pixel image from disk into memory. + * + * \details \copydetails tj3LoadImage8() + */ +DLLEXPORT unsigned short *tj3LoadImage16(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + + +/** + * Save an 8-bit-per-sample packed-pixel image from memory to disk. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file to which to save the packed-pixel image. The + * image will be stored in Windows BMP or PBMPLUS (PPM/PGM) format, depending + * on the file extension. Windows BMP files require 8-bit-per-sample data + * precision. + * + * @param buffer pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK image to be saved + * + * @param width width (in pixels) of the packed-pixel image + * + * @param pitch samples per row in the packed-pixel image. Setting this + * parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the packed-pixel image + * + * @param pixelFormat pixel format of the packed-pixel image (see @ref TJPF + * "Pixel formats".) If this parameter is set to @ref TJPF_GRAY, then the + * image will be stored in PGM or 8-bit-per-pixel (indexed color) BMP format. + * Otherwise, the image will be stored in PPM or 24-bit-per-pixel BMP format. + * If this parameter is set to @ref TJPF_CMYK, then the CMYK pixels will be + * converted to RGB using a quick & dirty algorithm that is suitable only for + * testing purposes. (Proper conversion between CMYK and other formats + * requires a color management system.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SaveImage8(tjhandle handle, const char *filename, + const unsigned char *buffer, int width, int pitch, + int height, int pixelFormat); + +/** + * Save a 12-bit-per-sample packed-pixel image from memory to disk. + * + * \details \copydetails tj3SaveImage8() + */ +DLLEXPORT int tj3SaveImage12(tjhandle handle, const char *filename, + const short *buffer, int width, int pitch, + int height, int pixelFormat); + +/** + * Save a 16-bit-per-sample packed-pixel image from memory to disk. + * + * \details \copydetails tj3SaveImage8() + */ +DLLEXPORT int tj3SaveImage16(tjhandle handle, const char *filename, + const unsigned short *buffer, int width, + int pitch, int height, int pixelFormat); + + +/** + * Free a byte buffer previously allocated by TurboJPEG. You should always use + * this function to free JPEG destination buffer(s) that were automatically + * (re)allocated by the compression and transform functions or that were + * manually allocated using #tj3Alloc(). + * + * @param buffer address of the buffer to free. If the address is NULL, then + * this function has no effect. + * + * @see tj3Alloc() + */ +DLLEXPORT void tj3Free(void *buffer); + + +/** + * Returns a descriptive error message explaining why the last command failed. + * + * @param handle handle to a TurboJPEG instance, or NULL if the error was + * generated by a global function (but note that retrieving the error message + * for a global function is thread-safe only on platforms that support + * thread-local storage.) + * + * @return a descriptive error message explaining why the last command failed. + */ +DLLEXPORT char *tj3GetErrorStr(tjhandle handle); + + +/** + * Returns a code indicating the severity of the last error. See + * @ref TJERR "Error codes". + * + * @param handle handle to a TurboJPEG instance + * + * @return a code indicating the severity of the last error. See + * @ref TJERR "Error codes". + */ +DLLEXPORT int tj3GetErrorCode(tjhandle handle); + + +/* Backward compatibility functions and macros (nothing to see here) */ + +/* TurboJPEG 1.0+ */ + +#define NUMSUBOPT TJ_NUMSAMP +#define TJ_444 TJSAMP_444 +#define TJ_422 TJSAMP_422 +#define TJ_420 TJSAMP_420 +#define TJ_411 TJSAMP_420 +#define TJ_GRAYSCALE TJSAMP_GRAY + +#define TJ_BGR 1 +#define TJ_BOTTOMUP TJFLAG_BOTTOMUP +#define TJ_FORCEMMX TJFLAG_FORCEMMX +#define TJ_FORCESSE TJFLAG_FORCESSE +#define TJ_FORCESSE2 TJFLAG_FORCESSE2 +#define TJ_ALPHAFIRST 64 +#define TJ_FORCESSE3 TJFLAG_FORCESSE3 +#define TJ_FASTUPSAMPLE TJFLAG_FASTUPSAMPLE + +#define TJPAD(width) (((width) + 3) & (~3)) + +DLLEXPORT unsigned long TJBUFSIZE(int width, int height); + +DLLEXPORT int tjCompress(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelSize, + unsigned char *dstBuf, unsigned long *compressedSize, + int jpegSubsamp, int jpegQual, int flags); + +DLLEXPORT int tjDecompress(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int pitch, int height, int pixelSize, + int flags); + +DLLEXPORT int tjDecompressHeader(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height); + +DLLEXPORT int tjDestroy(tjhandle handle); + +DLLEXPORT char *tjGetErrorStr(void); + +DLLEXPORT tjhandle tjInitCompress(void); + +DLLEXPORT tjhandle tjInitDecompress(void); + +/* TurboJPEG 1.1+ */ + +#define TJ_YUV 512 + +DLLEXPORT unsigned long TJBUFSIZEYUV(int width, int height, int jpegSubsamp); + +DLLEXPORT int tjDecompressHeader2(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height, int *jpegSubsamp); + +DLLEXPORT int tjDecompressToYUV(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int flags); + +DLLEXPORT int tjEncodeYUV(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelSize, + unsigned char *dstBuf, int subsamp, int flags); + +/* TurboJPEG 1.2+ */ + +#define TJFLAG_BOTTOMUP 2 +#define TJFLAG_FORCEMMX 8 +#define TJFLAG_FORCESSE 16 +#define TJFLAG_FORCESSE2 32 +#define TJFLAG_FORCESSE3 128 +#define TJFLAG_FASTUPSAMPLE 256 +#define TJFLAG_NOREALLOC 1024 + +DLLEXPORT unsigned char *tjAlloc(int bytes); + +DLLEXPORT unsigned long tjBufSize(int width, int height, int jpegSubsamp); + +DLLEXPORT unsigned long tjBufSizeYUV(int width, int height, int subsamp); + +DLLEXPORT int tjCompress2(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, unsigned long *jpegSize, + int jpegSubsamp, int jpegQual, int flags); + +DLLEXPORT int tjDecompress2(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int pitch, int height, int pixelFormat, + int flags); + +DLLEXPORT int tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int subsamp, int flags); + +DLLEXPORT void tjFree(unsigned char *buffer); + +DLLEXPORT tjscalingfactor *tjGetScalingFactors(int *numscalingfactors); + +DLLEXPORT tjhandle tjInitTransform(void); + +DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, int n, + unsigned char **dstBufs, unsigned long *dstSizes, + tjtransform *transforms, int flags); + +/* TurboJPEG 1.2.1+ */ + +#define TJFLAG_FASTDCT 2048 +#define TJFLAG_ACCURATEDCT 4096 + +/* TurboJPEG 1.4+ */ + +DLLEXPORT unsigned long tjBufSizeYUV2(int width, int align, int height, + int subsamp); + +DLLEXPORT int tjCompressFromYUV(tjhandle handle, const unsigned char *srcBuf, + int width, int align, int height, int subsamp, + unsigned char **jpegBuf, + unsigned long *jpegSize, int jpegQual, + int flags); + +DLLEXPORT int tjCompressFromYUVPlanes(tjhandle handle, + const unsigned char **srcPlanes, + int width, const int *strides, + int height, int subsamp, + unsigned char **jpegBuf, + unsigned long *jpegSize, int jpegQual, + int flags); + +DLLEXPORT int tjDecodeYUV(tjhandle handle, const unsigned char *srcBuf, + int align, int subsamp, unsigned char *dstBuf, + int width, int pitch, int height, int pixelFormat, + int flags); + +DLLEXPORT int tjDecodeYUVPlanes(tjhandle handle, + const unsigned char **srcPlanes, + const int *strides, int subsamp, + unsigned char *dstBuf, int width, int pitch, + int height, int pixelFormat, int flags); + +DLLEXPORT int tjDecompressHeader3(tjhandle handle, + const unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height, int *jpegSubsamp, + int *jpegColorspace); + +DLLEXPORT int tjDecompressToYUV2(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int align, int height, int flags); + +DLLEXPORT int tjDecompressToYUVPlanes(tjhandle handle, + const unsigned char *jpegBuf, + unsigned long jpegSize, + unsigned char **dstPlanes, int width, + int *strides, int height, int flags); + +DLLEXPORT int tjEncodeYUV3(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int align, int subsamp, + int flags); + +DLLEXPORT int tjEncodeYUVPlanes(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, + int pixelFormat, unsigned char **dstPlanes, + int *strides, int subsamp, int flags); + +DLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp); + +DLLEXPORT unsigned long tjPlaneSizeYUV(int componentID, int width, int stride, + int height, int subsamp); + +DLLEXPORT int tjPlaneWidth(int componentID, int width, int subsamp); + +/* TurboJPEG 2.0+ */ + +#define TJFLAG_STOPONWARNING 8192 +#define TJFLAG_PROGRESSIVE 16384 + +DLLEXPORT int tjGetErrorCode(tjhandle handle); + +DLLEXPORT char *tjGetErrorStr2(tjhandle handle); + +DLLEXPORT unsigned char *tjLoadImage(const char *filename, int *width, + int align, int *height, int *pixelFormat, + int flags); + +DLLEXPORT int tjSaveImage(const char *filename, unsigned char *buffer, + int width, int pitch, int height, int pixelFormat, + int flags); + +/* TurboJPEG 2.1+ */ + +#define TJFLAG_LIMITSCANS 32768 + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif From 1fa96b161ff2525f446d829db06b6eb59850cdc4 Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Sat, 25 May 2024 12:12:03 +0200 Subject: [PATCH 085/119] Merge pull request #25616 from savuor:rv/yuv_docs YUV codes for cvtColor: descriptions added #25616 This PR contains descriptions for various RGB <-> YUV color conversion codes as well as detailed comments in the source code. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/imgproc/doc/colors.markdown | 31 +++ modules/imgproc/include/opencv2/imgproc.hpp | 263 ++++++++++---------- modules/imgproc/src/color_yuv.dispatch.cpp | 46 +++- modules/imgproc/src/color_yuv.simd.hpp | 111 +++++---- modules/imgproc/src/hal_replacement.hpp | 11 +- 5 files changed, 279 insertions(+), 183 deletions(-) diff --git a/modules/imgproc/doc/colors.markdown b/modules/imgproc/doc/colors.markdown index cc780137b300..97d0907a6248 100644 --- a/modules/imgproc/doc/colors.markdown +++ b/modules/imgproc/doc/colors.markdown @@ -50,6 +50,37 @@ where Y, Cr, and Cb cover the whole value range. @see cv::COLOR_BGR2YCrCb, cv::COLOR_RGB2YCrCb, cv::COLOR_YCrCb2BGR, cv::COLOR_YCrCb2RGB +@anchor color_convert_rgb_yuv_42x +RGB <-> YUV with subsampling +------------------------------ +Only 8-bit values are supported. +The coefficients correspond to BT.601 standard with resulting values Y [16, 235], U and V [16, 240] centered at 128. + +Two subsampling schemes are supported: 4:2:0 (Fourcc codes NV12, NV21, YV12, I420 and synonimic) +and 4:2:2 (Fourcc codes UYVY, YUY2, YVYU and synonimic). + +In both subsampling schemes Y values are written for each pixel so that Y plane is in fact a scaled and biased gray version +of a source image. + +In 4:2:0 scheme U and V values are averaged over 2x2 squares, i.e. only 1 U and 1 V value is saved per each 4 pixels. +U and V values are saved interleaved into a separate plane (NV12, NV21) or into two separate semi-planes (YV12, I420). + +In 4:2:2 scheme U and V values are averaged horizontally over each pair of pixels, i.e. only 1 U and 1 V value is saved +per each 2 pixels. U and V values are saved interleaved with Y values for both pixels according to its Fourcc code. + +Note that different conversions are perfomed with different precision for speed or compatibility purposes. For example, +RGB to YUV 4:2:2 is converted using 14-bit fixed-point arithmetics while other conversions use 20 bits. + +\f[R \leftarrow 1.164 \cdot (Y - 16) + 1.596 \cdot (V - 128)\f] +\f[G \leftarrow 1.164 \cdot (Y - 16) - 0.813 \cdot (V - 128) - 0.391 \cdot (U - 128)\f] +\f[B \leftarrow 1.164 \cdot (Y - 16) + 2.018 \cdot (U - 128)\f] + +\f[Y \leftarrow (R \cdot 0.299 + G \cdot 0.587 + B \cdot 0.114) \cdot \frac{236 - 16}{256} + 16 \f] +\f[U \leftarrow -0.148 \cdot R_{avg} - 0.291 \cdot G_{avg} + 0.439 \cdot B_{avg} + 128 \f] +\f[V \leftarrow 0.439 \cdot R_{avg} - 0.368 \cdot G_{avg} - 0.071 \cdot B_{avg} + 128 \f] + +@see cv::COLOR_YUV2RGB_NV12, cv::COLOR_YUV2RGBA_YUY2, cv::COLOR_BGR2YUV_YV12 and similar ones + @anchor color_convert_rgb_hsv RGB <-> HSV ----------- diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 677450f68eb9..471a857f63fc 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -641,112 +641,109 @@ enum ColorConversionCodes { COLOR_YUV2BGR = 84, COLOR_YUV2RGB = 85, - //! YUV 4:2:0 family to RGB - COLOR_YUV2RGB_NV12 = 90, - COLOR_YUV2BGR_NV12 = 91, - COLOR_YUV2RGB_NV21 = 92, - COLOR_YUV2BGR_NV21 = 93, - COLOR_YUV420sp2RGB = COLOR_YUV2RGB_NV21, - COLOR_YUV420sp2BGR = COLOR_YUV2BGR_NV21, - - COLOR_YUV2RGBA_NV12 = 94, - COLOR_YUV2BGRA_NV12 = 95, - COLOR_YUV2RGBA_NV21 = 96, - COLOR_YUV2BGRA_NV21 = 97, - COLOR_YUV420sp2RGBA = COLOR_YUV2RGBA_NV21, - COLOR_YUV420sp2BGRA = COLOR_YUV2BGRA_NV21, - - COLOR_YUV2RGB_YV12 = 98, - COLOR_YUV2BGR_YV12 = 99, - COLOR_YUV2RGB_IYUV = 100, - COLOR_YUV2BGR_IYUV = 101, - COLOR_YUV2RGB_I420 = COLOR_YUV2RGB_IYUV, - COLOR_YUV2BGR_I420 = COLOR_YUV2BGR_IYUV, - COLOR_YUV420p2RGB = COLOR_YUV2RGB_YV12, - COLOR_YUV420p2BGR = COLOR_YUV2BGR_YV12, - - COLOR_YUV2RGBA_YV12 = 102, - COLOR_YUV2BGRA_YV12 = 103, - COLOR_YUV2RGBA_IYUV = 104, - COLOR_YUV2BGRA_IYUV = 105, - COLOR_YUV2RGBA_I420 = COLOR_YUV2RGBA_IYUV, - COLOR_YUV2BGRA_I420 = COLOR_YUV2BGRA_IYUV, - COLOR_YUV420p2RGBA = COLOR_YUV2RGBA_YV12, - COLOR_YUV420p2BGRA = COLOR_YUV2BGRA_YV12, - - COLOR_YUV2GRAY_420 = 106, - COLOR_YUV2GRAY_NV21 = COLOR_YUV2GRAY_420, - COLOR_YUV2GRAY_NV12 = COLOR_YUV2GRAY_420, - COLOR_YUV2GRAY_YV12 = COLOR_YUV2GRAY_420, - COLOR_YUV2GRAY_IYUV = COLOR_YUV2GRAY_420, - COLOR_YUV2GRAY_I420 = COLOR_YUV2GRAY_420, - COLOR_YUV420sp2GRAY = COLOR_YUV2GRAY_420, - COLOR_YUV420p2GRAY = COLOR_YUV2GRAY_420, - - //! YUV 4:2:2 family to RGB - COLOR_YUV2RGB_UYVY = 107, - COLOR_YUV2BGR_UYVY = 108, - //COLOR_YUV2RGB_VYUY = 109, - //COLOR_YUV2BGR_VYUY = 110, - COLOR_YUV2RGB_Y422 = COLOR_YUV2RGB_UYVY, - COLOR_YUV2BGR_Y422 = COLOR_YUV2BGR_UYVY, - COLOR_YUV2RGB_UYNV = COLOR_YUV2RGB_UYVY, - COLOR_YUV2BGR_UYNV = COLOR_YUV2BGR_UYVY, - - COLOR_YUV2RGBA_UYVY = 111, - COLOR_YUV2BGRA_UYVY = 112, - //COLOR_YUV2RGBA_VYUY = 113, - //COLOR_YUV2BGRA_VYUY = 114, - COLOR_YUV2RGBA_Y422 = COLOR_YUV2RGBA_UYVY, - COLOR_YUV2BGRA_Y422 = COLOR_YUV2BGRA_UYVY, - COLOR_YUV2RGBA_UYNV = COLOR_YUV2RGBA_UYVY, - COLOR_YUV2BGRA_UYNV = COLOR_YUV2BGRA_UYVY, - - COLOR_YUV2RGB_YUY2 = 115, - COLOR_YUV2BGR_YUY2 = 116, - COLOR_YUV2RGB_YVYU = 117, - COLOR_YUV2BGR_YVYU = 118, - COLOR_YUV2RGB_YUYV = COLOR_YUV2RGB_YUY2, - COLOR_YUV2BGR_YUYV = COLOR_YUV2BGR_YUY2, - COLOR_YUV2RGB_YUNV = COLOR_YUV2RGB_YUY2, - COLOR_YUV2BGR_YUNV = COLOR_YUV2BGR_YUY2, - - COLOR_YUV2RGBA_YUY2 = 119, - COLOR_YUV2BGRA_YUY2 = 120, - COLOR_YUV2RGBA_YVYU = 121, - COLOR_YUV2BGRA_YVYU = 122, - COLOR_YUV2RGBA_YUYV = COLOR_YUV2RGBA_YUY2, - COLOR_YUV2BGRA_YUYV = COLOR_YUV2BGRA_YUY2, - COLOR_YUV2RGBA_YUNV = COLOR_YUV2RGBA_YUY2, - COLOR_YUV2BGRA_YUNV = COLOR_YUV2BGRA_YUY2, - - COLOR_YUV2GRAY_UYVY = 123, - COLOR_YUV2GRAY_YUY2 = 124, - //CV_YUV2GRAY_VYUY = CV_YUV2GRAY_UYVY, - COLOR_YUV2GRAY_Y422 = COLOR_YUV2GRAY_UYVY, - COLOR_YUV2GRAY_UYNV = COLOR_YUV2GRAY_UYVY, - COLOR_YUV2GRAY_YVYU = COLOR_YUV2GRAY_YUY2, - COLOR_YUV2GRAY_YUYV = COLOR_YUV2GRAY_YUY2, - COLOR_YUV2GRAY_YUNV = COLOR_YUV2GRAY_YUY2, + COLOR_YUV2RGB_NV12 = 90, //!< convert between 4:2:0-subsampled YUV NV12 and RGB, two planes (in one or separate arrays): Y and U/V interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGR_NV12 = 91, //!< convert between 4:2:0-subsampled YUV NV12 and BGR, two planes (in one or separate arrays): Y and U/V interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGB_NV21 = 92, //!< convert between 4:2:0-subsampled YUV NV21 and RGB, two planes (in one or separate arrays): Y and V/U interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGR_NV21 = 93, //!< convert between 4:2:0-subsampled YUV NV21 and BGR, two planes (in one or separate arrays): Y and V/U interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV420sp2RGB = COLOR_YUV2RGB_NV21, //!< synonym to NV21 + COLOR_YUV420sp2BGR = COLOR_YUV2BGR_NV21, //!< synonym to NV21 + + COLOR_YUV2RGBA_NV12 = 94, //!< convert between 4:2:0-subsampled YUV NV12 and RGBA, two planes (in one or separate arrays): Y and U/V interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGRA_NV12 = 95, //!< convert between 4:2:0-subsampled YUV NV12 and BGRA, two planes (in one or separate arrays): Y and U/V interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGBA_NV21 = 96, //!< convert between 4:2:0-subsampled YUV NV21 and RGBA, two planes (in one or separate arrays): Y and V/U interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGRA_NV21 = 97, //!< convert between 4:2:0-subsampled YUV NV21 and BGRA, two planes (in one or separate arrays): Y and V/U interleaved, see @ref color_convert_rgb_yuv_42x + COLOR_YUV420sp2RGBA = COLOR_YUV2RGBA_NV21, //!< synonym to NV21 + COLOR_YUV420sp2BGRA = COLOR_YUV2BGRA_NV21, //!< synonym to NV21 + + COLOR_YUV2RGB_YV12 = 98, //!< convert between 4:2:0-subsampled YUV YV12 and RGB, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGR_YV12 = 99, //!< convert between 4:2:0-subsampled YUV YV12 and BGR, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGB_IYUV = 100, //!< convert between 4:2:0-subsampled YUV IYUV and RGB, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGR_IYUV = 101, //!< convert between 4:2:0-subsampled YUV IYUV and BGR, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGB_I420 = COLOR_YUV2RGB_IYUV, //!< synonym to IYUV + COLOR_YUV2BGR_I420 = COLOR_YUV2BGR_IYUV, //!< synonym to IYUV + COLOR_YUV420p2RGB = COLOR_YUV2RGB_YV12, //!< synonym to YV12 + COLOR_YUV420p2BGR = COLOR_YUV2BGR_YV12, //!< synonym to YV12 + + COLOR_YUV2RGBA_YV12 = 102, //!< convert between 4:2:0-subsampled YUV YV12 and RGBA, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGRA_YV12 = 103, //!< convert between 4:2:0-subsampled YUV YV12 and BGRA, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGBA_IYUV = 104, //!< convert between 4:2:0-subsampled YUV YV12 and RGBA, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGRA_IYUV = 105, //!< convert between 4:2:0-subsampled YUV YV12 and BGRA, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGBA_I420 = COLOR_YUV2RGBA_IYUV, //!< synonym to IYUV + COLOR_YUV2BGRA_I420 = COLOR_YUV2BGRA_IYUV, //!< synonym to IYUV + COLOR_YUV420p2RGBA = COLOR_YUV2RGBA_YV12, //!< synonym to YV12 + COLOR_YUV420p2BGRA = COLOR_YUV2BGRA_YV12, //!< synonym to YV12 + + COLOR_YUV2GRAY_420 = 106, //!< extract Y channel from YUV 4:2:0 image + COLOR_YUV2GRAY_NV21 = COLOR_YUV2GRAY_420, //!< synonym to COLOR_YUV2GRAY_420 + COLOR_YUV2GRAY_NV12 = COLOR_YUV2GRAY_420, //!< synonym to COLOR_YUV2GRAY_420 + COLOR_YUV2GRAY_YV12 = COLOR_YUV2GRAY_420, //!< synonym to COLOR_YUV2GRAY_420 + COLOR_YUV2GRAY_IYUV = COLOR_YUV2GRAY_420, //!< synonym to COLOR_YUV2GRAY_420 + COLOR_YUV2GRAY_I420 = COLOR_YUV2GRAY_420, //!< synonym to COLOR_YUV2GRAY_420 + COLOR_YUV420sp2GRAY = COLOR_YUV2GRAY_420, //!< synonym to COLOR_YUV2GRAY_420 + COLOR_YUV420p2GRAY = COLOR_YUV2GRAY_420, //!< synonym to COLOR_YUV2GRAY_420 + + COLOR_YUV2RGB_UYVY = 107, //!< convert between YUV UYVY and RGB, YUV is 4:2:2-subsampled and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGR_UYVY = 108, //!< convert between YUV UYVY and BGR, YUV is 4:2:2-subsampled and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + //COLOR_YUV2RGB_VYUY = 109, //!< convert between YUV VYUY and RGB, YUV is 4:2:2-subsampled and interleaved as V/Y1/U/Y2, see @ref color_convert_rgb_yuv_42x + //COLOR_YUV2BGR_VYUY = 110, //!< convert between YUV VYUY and BGR, YUV is 4:2:2-subsampled and interleaved as V/Y1/U/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGB_Y422 = COLOR_YUV2RGB_UYVY, //!< synonym to UYVY + COLOR_YUV2BGR_Y422 = COLOR_YUV2BGR_UYVY, //!< synonym to UYVY + COLOR_YUV2RGB_UYNV = COLOR_YUV2RGB_UYVY, //!< synonym to UYVY + COLOR_YUV2BGR_UYNV = COLOR_YUV2BGR_UYVY, //!< synonym to UYVY + + COLOR_YUV2RGBA_UYVY = 111, //!< convert between YUV UYVY and RGBA, YUV is 4:2:2-subsampled and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGRA_UYVY = 112, //!< convert between YUV UYVY and BGRA, YUV is 4:2:2-subsampled and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + //COLOR_YUV2RGBA_VYUY = 113, //!< convert between YUV VYUY and RGBA, YUV is 4:2:2-subsampled and interleaved as V/Y1/U/Y2, see @ref color_convert_rgb_yuv_42x + //COLOR_YUV2BGRA_VYUY = 114, //!< convert between YUV VYUY and BGRA, YUV is 4:2:2-subsampled and interleaved as V/Y1/U/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGBA_Y422 = COLOR_YUV2RGBA_UYVY, //!< synonym to UYVY + COLOR_YUV2BGRA_Y422 = COLOR_YUV2BGRA_UYVY, //!< synonym to UYVY + COLOR_YUV2RGBA_UYNV = COLOR_YUV2RGBA_UYVY, //!< synonym to UYVY + COLOR_YUV2BGRA_UYNV = COLOR_YUV2BGRA_UYVY, //!< synonym to UYVY + + COLOR_YUV2RGB_YUY2 = 115, //!< convert between YUV YUY2 and RGB, YUV is 4:2:2-subsampled and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGR_YUY2 = 116, //!< convert between YUV YUY2 and BGR, YUV is 4:2:2-subsampled and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGB_YVYU = 117, //!< convert between YUV YVYU and RGB, YUV is 4:2:2-subsampled and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGR_YVYU = 118, //!< convert between YUV YVYU and BGR, YUV is 4:2:2-subsampled and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGB_YUYV = COLOR_YUV2RGB_YUY2, //!< synonym to YUY2 + COLOR_YUV2BGR_YUYV = COLOR_YUV2BGR_YUY2, //!< synonym to YUY2 + COLOR_YUV2RGB_YUNV = COLOR_YUV2RGB_YUY2, //!< synonym to YUY2 + COLOR_YUV2BGR_YUNV = COLOR_YUV2BGR_YUY2, //!< synonym to YUY2 + + COLOR_YUV2RGBA_YUY2 = 119, //!< convert between YUV YUY2 and RGBA, YUV is 4:2:2-subsampled and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGRA_YUY2 = 120, //!< convert between YUV YUY2 and BGRA, YUV is 4:2:2-subsampled and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGBA_YVYU = 121, //!< convert between YUV YVYU and RGBA, YUV is 4:2:2-subsampled and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2BGRA_YVYU = 122, //!< convert between YUV YVYU and BGRA, YUV is 4:2:2-subsampled and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_YUV2RGBA_YUYV = COLOR_YUV2RGBA_YUY2, //!< synonym to YUY2 + COLOR_YUV2BGRA_YUYV = COLOR_YUV2BGRA_YUY2, //!< synonym to YUY2 + COLOR_YUV2RGBA_YUNV = COLOR_YUV2RGBA_YUY2, //!< synonym to YUY2 + COLOR_YUV2BGRA_YUNV = COLOR_YUV2BGRA_YUY2, //!< synonym to YUY2 + + COLOR_YUV2GRAY_UYVY = 123, //!< extract Y channel from YUV 4:2:2 image + COLOR_YUV2GRAY_YUY2 = 124, //!< extract Y channel from YUV 4:2:2 image + //CV_YUV2GRAY_VYUY = CV_YUV2GRAY_UYVY, //!< synonym to COLOR_YUV2GRAY_UYVY + COLOR_YUV2GRAY_Y422 = COLOR_YUV2GRAY_UYVY, //!< synonym to COLOR_YUV2GRAY_UYVY + COLOR_YUV2GRAY_UYNV = COLOR_YUV2GRAY_UYVY, //!< synonym to COLOR_YUV2GRAY_UYVY + COLOR_YUV2GRAY_YVYU = COLOR_YUV2GRAY_YUY2, //!< synonym to COLOR_YUV2GRAY_YUY2 + COLOR_YUV2GRAY_YUYV = COLOR_YUV2GRAY_YUY2, //!< synonym to COLOR_YUV2GRAY_YUY2 + COLOR_YUV2GRAY_YUNV = COLOR_YUV2GRAY_YUY2, //!< synonym to COLOR_YUV2GRAY_YUY2 //! alpha premultiplication COLOR_RGBA2mRGBA = 125, COLOR_mRGBA2RGBA = 126, - //! RGB to YUV 4:2:0 family - COLOR_RGB2YUV_I420 = 127, - COLOR_BGR2YUV_I420 = 128, - COLOR_RGB2YUV_IYUV = COLOR_RGB2YUV_I420, - COLOR_BGR2YUV_IYUV = COLOR_BGR2YUV_I420, - - COLOR_RGBA2YUV_I420 = 129, - COLOR_BGRA2YUV_I420 = 130, - COLOR_RGBA2YUV_IYUV = COLOR_RGBA2YUV_I420, - COLOR_BGRA2YUV_IYUV = COLOR_BGRA2YUV_I420, - COLOR_RGB2YUV_YV12 = 131, - COLOR_BGR2YUV_YV12 = 132, - COLOR_RGBA2YUV_YV12 = 133, - COLOR_BGRA2YUV_YV12 = 134, + COLOR_RGB2YUV_I420 = 127, //!< convert between RGB and 4:2:0-subsampled YUV I420, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_BGR2YUV_I420 = 128, //!< convert between BGR and 4:2:0-subsampled YUV I420, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_RGB2YUV_IYUV = COLOR_RGB2YUV_I420, //!< synonym to I420 + COLOR_BGR2YUV_IYUV = COLOR_BGR2YUV_I420, //!< synonym to I420 + + COLOR_RGBA2YUV_I420 = 129, //!< convert between RGBA and 4:2:0-subsampled YUV I420, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_BGRA2YUV_I420 = 130, //!< convert between BGRA and 4:2:0-subsampled YUV I420, three planes in one array: Y, U and V, see @ref color_convert_rgb_yuv_42x + COLOR_RGBA2YUV_IYUV = COLOR_RGBA2YUV_I420, //!< synonym to I420 + COLOR_BGRA2YUV_IYUV = COLOR_BGRA2YUV_I420, //!< synonym to I420 + COLOR_RGB2YUV_YV12 = 131, //!< convert between RGB and 4:2:0-subsampled YUV YV12, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_BGR2YUV_YV12 = 132, //!< convert between BGR and 4:2:0-subsampled YUV YV12, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_RGBA2YUV_YV12 = 133, //!< convert between RGBA and 4:2:0-subsampled YUV YV12, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x + COLOR_BGRA2YUV_YV12 = 134, //!< convert between BGRA and 4:2:0-subsampled YUV YV12, three planes in one array: Y, V and U, see @ref color_convert_rgb_yuv_42x //! Demosaicing, see @ref color_convert_bayer "color conversions" for additional information COLOR_BayerBG2BGR = 46, //!< equivalent to RGGB Bayer pattern @@ -842,39 +839,37 @@ enum ColorConversionCodes { COLOR_BayerRG2RGBA = COLOR_BayerBG2BGRA, //!< equivalent to BGGR Bayer pattern COLOR_BayerGR2RGBA = COLOR_BayerGB2BGRA, //!< equivalent to GBRG Bayer pattern - //! RGB to YUV 4:2:2 family - - COLOR_RGB2YUV_UYVY = 143, - COLOR_BGR2YUV_UYVY = 144, - COLOR_RGB2YUV_Y422 = COLOR_RGB2YUV_UYVY, - COLOR_BGR2YUV_Y422 = COLOR_BGR2YUV_UYVY, - COLOR_RGB2YUV_UYNV = COLOR_RGB2YUV_UYVY, - COLOR_BGR2YUV_UYNV = COLOR_BGR2YUV_UYVY, - - COLOR_RGBA2YUV_UYVY = 145, - COLOR_BGRA2YUV_UYVY = 146, - COLOR_RGBA2YUV_Y422 = COLOR_RGBA2YUV_UYVY, - COLOR_BGRA2YUV_Y422 = COLOR_BGRA2YUV_UYVY, - COLOR_RGBA2YUV_UYNV = COLOR_RGBA2YUV_UYVY, - COLOR_BGRA2YUV_UYNV = COLOR_BGRA2YUV_UYVY, - - COLOR_RGB2YUV_YUY2 = 147, - COLOR_BGR2YUV_YUY2 = 148, - COLOR_RGB2YUV_YVYU = 149, - COLOR_BGR2YUV_YVYU = 150, - COLOR_RGB2YUV_YUYV = COLOR_RGB2YUV_YUY2, - COLOR_BGR2YUV_YUYV = COLOR_BGR2YUV_YUY2, - COLOR_RGB2YUV_YUNV = COLOR_RGB2YUV_YUY2, - COLOR_BGR2YUV_YUNV = COLOR_BGR2YUV_YUY2, - - COLOR_RGBA2YUV_YUY2 = 151, - COLOR_BGRA2YUV_YUY2 = 152, - COLOR_RGBA2YUV_YVYU = 153, - COLOR_BGRA2YUV_YVYU = 154, - COLOR_RGBA2YUV_YUYV = COLOR_RGBA2YUV_YUY2, - COLOR_BGRA2YUV_YUYV = COLOR_BGRA2YUV_YUY2, - COLOR_RGBA2YUV_YUNV = COLOR_RGBA2YUV_YUY2, - COLOR_BGRA2YUV_YUNV = COLOR_BGRA2YUV_YUY2, + COLOR_RGB2YUV_UYVY = 143, //!< convert between RGB and YUV UYVU, YUV is 4:2:2 and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_BGR2YUV_UYVY = 144, //!< convert between BGR and YUV UYVU, YUV is 4:2:2 and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_RGB2YUV_Y422 = COLOR_RGB2YUV_UYVY, //!< synonym to UYVY + COLOR_BGR2YUV_Y422 = COLOR_BGR2YUV_UYVY, //!< synonym to UYVY + COLOR_RGB2YUV_UYNV = COLOR_RGB2YUV_UYVY, //!< synonym to UYVY + COLOR_BGR2YUV_UYNV = COLOR_BGR2YUV_UYVY, //!< synonym to UYVY + + COLOR_RGBA2YUV_UYVY = 145, //!< convert between RGBA and YUV UYVU, YUV is 4:2:2 and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_BGRA2YUV_UYVY = 146, //!< convert between BGRA and YUV UYVU, YUV is 4:2:2 and interleaved as U/Y1/V/Y2, see @ref color_convert_rgb_yuv_42x + COLOR_RGBA2YUV_Y422 = COLOR_RGBA2YUV_UYVY, //!< synonym to UYVY + COLOR_BGRA2YUV_Y422 = COLOR_BGRA2YUV_UYVY, //!< synonym to UYVY + COLOR_RGBA2YUV_UYNV = COLOR_RGBA2YUV_UYVY, //!< synonym to UYVY + COLOR_BGRA2YUV_UYNV = COLOR_BGRA2YUV_UYVY, //!< synonym to UYVY + + COLOR_RGB2YUV_YUY2 = 147, //!< convert between RGB and YUV YUY2, YUV is 4:2:2 and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_BGR2YUV_YUY2 = 148, //!< convert between BGR and YUV YUY2, YUV is 4:2:2 and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_RGB2YUV_YVYU = 149, //!< convert between RGB and YUV YVYU, YUV is 4:2:2 and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_BGR2YUV_YVYU = 150, //!< convert between BGR and YUV YVYU, YUV is 4:2:2 and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_RGB2YUV_YUYV = COLOR_RGB2YUV_YUY2, //!< synonym to YUY2 + COLOR_BGR2YUV_YUYV = COLOR_BGR2YUV_YUY2, //!< synonym to YUY2 + COLOR_RGB2YUV_YUNV = COLOR_RGB2YUV_YUY2, //!< synonym to YUY2 + COLOR_BGR2YUV_YUNV = COLOR_BGR2YUV_YUY2, //!< synonym to YUY2 + + COLOR_RGBA2YUV_YUY2 = 151, //!< convert between RGBA and YUV YUY2, YUV is 4:2:2 and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_BGRA2YUV_YUY2 = 152, //!< convert between BGRA and YUV YUY2, YUV is 4:2:2 and interleaved as Y1/U/Y2/V, see @ref color_convert_rgb_yuv_42x + COLOR_RGBA2YUV_YVYU = 153, //!< convert between RGBA and YUV YVYU, YUV is 4:2:2 and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_BGRA2YUV_YVYU = 154, //!< convert between BGRA and YUV YVYU, YUV is 4:2:2 and interleaved as Y1/V/Y2/U, see @ref color_convert_rgb_yuv_42x + COLOR_RGBA2YUV_YUYV = COLOR_RGBA2YUV_YUY2, //!< synonym to YUY2 + COLOR_BGRA2YUV_YUYV = COLOR_BGRA2YUV_YUY2, //!< synonym to YUY2 + COLOR_RGBA2YUV_YUNV = COLOR_RGBA2YUV_YUY2, //!< synonym to YUY2 + COLOR_BGRA2YUV_YUNV = COLOR_BGRA2YUV_YUY2, //!< synonym to YUY2 COLOR_COLORCVT_MAX = 155 }; diff --git a/modules/imgproc/src/color_yuv.dispatch.cpp b/modules/imgproc/src/color_yuv.dispatch.cpp index 73e1aea32d0b..71d840d85767 100644 --- a/modules/imgproc/src/color_yuv.dispatch.cpp +++ b/modules/imgproc/src/color_yuv.dispatch.cpp @@ -115,6 +115,9 @@ void cvtYUVtoBGR(const uchar * src_data, size_t src_step, CV_CPU_DISPATCH_MODES_ALL); } +// 4:2:0, two planes in one array: Y, UV interleaved +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics void cvtTwoPlaneYUVtoBGR(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int dst_width, int dst_height, @@ -129,6 +132,9 @@ void cvtTwoPlaneYUVtoBGR(const uchar * src_data, size_t src_step, dst_width, dst_height, dcn, swapBlue, uIdx); } +// 4:2:0, two planes: Y, UV interleaved +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics void cvtTwoPlaneYUVtoBGR(const uchar * y_data, const uchar * uv_data, size_t src_step, uchar * dst_data, size_t dst_step, int dst_width, int dst_height, @@ -139,6 +145,9 @@ void cvtTwoPlaneYUVtoBGR(const uchar * y_data, const uchar * uv_data, size_t src cvtTwoPlaneYUVtoBGR(y_data, src_step, uv_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx); } +// 4:2:0, two planes: Y, UV interleaved +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics void cvtTwoPlaneYUVtoBGR(const uchar * y_data, size_t y_step, const uchar * uv_data, size_t uv_step, uchar * dst_data, size_t dst_step, int dst_width, int dst_height, @@ -153,6 +162,9 @@ void cvtTwoPlaneYUVtoBGR(const uchar * y_data, size_t y_step, const uchar * uv_d CV_CPU_DISPATCH_MODES_ALL); } +// 4:2:0, three planes in one array: Y, U, V +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics void cvtThreePlaneYUVtoBGR(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int dst_width, int dst_height, @@ -166,6 +178,9 @@ void cvtThreePlaneYUVtoBGR(const uchar * src_data, size_t src_step, CV_CPU_DISPATCH_MODES_ALL); } +// 4:2:0, three planes in one array: Y, U, V +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics void cvtBGRtoThreePlaneYUV(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, @@ -179,6 +194,9 @@ void cvtBGRtoThreePlaneYUV(const uchar * src_data, size_t src_step, CV_CPU_DISPATCH_MODES_ALL); } +// 4:2:0, two planes: Y, UV interleaved +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics void cvtBGRtoTwoPlaneYUV(const uchar * src_data, size_t src_step, uchar * y_data, uchar * uv_data, size_t dst_step, int width, int height, @@ -193,6 +211,9 @@ void cvtBGRtoTwoPlaneYUV(const uchar * src_data, size_t src_step, CV_CPU_DISPATCH_MODES_ALL); } +// 4:2:2 interleaved +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, @@ -206,6 +227,9 @@ void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, CV_CPU_DISPATCH_MODES_ALL); } +// 4:2:2 interleaved +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 14-bit fixed-point arithmetics is used void cvtOnePlaneBGRtoYUV(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, @@ -379,6 +403,9 @@ void cvtColorYUV2BGR(InputArray _src, OutputArray _dst, int dcn, bool swapb, boo h.depth, dcn, swapb, crcb); } +// 4:2:2 interleaved +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics void cvtColorOnePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx, int ycn) { CvtHelper< Set<2>, Set<3, 4>, Set, FROM_UYVY > h(_src, _dst, dcn); @@ -387,6 +414,9 @@ void cvtColorOnePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool s dcn, swapb, uidx, ycn); } +// 4:2:2 interleaved +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 14-bit fixed-point arithmetics is used void cvtColorOnePlaneBGR2YUV( InputArray _src, OutputArray _dst, bool swapb, int uidx, int ycn) { CvtHelper< Set<3, 4>, Set<2>, Set, TO_UYVY > h(_src, _dst, 2); @@ -402,6 +432,9 @@ void cvtColorYUV2Gray_ch( InputArray _src, OutputArray _dst, int coi ) extractChannel(_src, _dst, coi); } +// 4:2:0, three planes in one array: Y, U, V +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics void cvtColorBGR2ThreePlaneYUV( InputArray _src, OutputArray _dst, bool swapb, int uidx) { CvtHelper< Set<3, 4>, Set<1>, Set, TO_YUV > h(_src, _dst, 1); @@ -424,6 +457,9 @@ void cvtColorYUV2Gray_420( InputArray _src, OutputArray _dst ) h.src(Range(0, h.dstSz.height), Range::all()).copyTo(h.dst); } +// 4:2:0, three planes in one array: Y, U, V +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics void cvtColorThreePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx) { if(dcn <= 0) dcn = 3; @@ -433,9 +469,10 @@ void cvtColorThreePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool dcn, swapb, uidx); } -// http://www.fourcc.org/yuv.php#NV21 == yuv420sp -> a plane of 8 bit Y samples followed by an interleaved V/U plane containing 8 bit 2x2 subsampled chroma samples -// http://www.fourcc.org/yuv.php#NV12 -> a plane of 8 bit Y samples followed by an interleaved U/V plane containing 8 bit 2x2 subsampled colour difference samples - +// 4:2:0, two planes in one array: Y, UV interleaved +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics +// see also: http://www.fourcc.org/yuv.php#NV21, http://www.fourcc.org/yuv.php#NV12 void cvtColorTwoPlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx ) { if(dcn <= 0) dcn = 3; @@ -445,6 +482,9 @@ void cvtColorTwoPlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool s dcn, swapb, uidx); } +// 4:2:0, two planes: Y, UV interleaved +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics void cvtColorTwoPlaneYUV2BGRpair( InputArray _ysrc, InputArray _uvsrc, OutputArray _dst, int dcn, bool swapb, int uidx ) { int stype = _ysrc.type(); diff --git a/modules/imgproc/src/color_yuv.simd.hpp b/modules/imgproc/src/color_yuv.simd.hpp index f80b3d931c49..44f38a3418e0 100644 --- a/modules/imgproc/src/color_yuv.simd.hpp +++ b/modules/imgproc/src/color_yuv.simd.hpp @@ -1015,7 +1015,7 @@ struct YCrCb2RGB_i ///////////////////////////////////// YUV420 -> RGB ///////////////////////////////////// -static const int ITUR_BT_601_CY = 1220542; +static const int ITUR_BT_601_CY = 1220542; static const int ITUR_BT_601_CUB = 2116026; static const int ITUR_BT_601_CUG = -409993; static const int ITUR_BT_601_CVG = -852492; @@ -1023,14 +1023,14 @@ static const int ITUR_BT_601_CVR = 1673527; static const int ITUR_BT_601_SHIFT = 20; // Coefficients for RGB to YUV420p conversion -static const int ITUR_BT_601_CRY = 269484; -static const int ITUR_BT_601_CGY = 528482; -static const int ITUR_BT_601_CBY = 102760; -static const int ITUR_BT_601_CRU = -155188; -static const int ITUR_BT_601_CGU = -305135; -static const int ITUR_BT_601_CBU = 460324; -static const int ITUR_BT_601_CGV = -385875; -static const int ITUR_BT_601_CBV = -74448; +static const int ITUR_BT_601_CRY = 269484; // 0.299055 * (236-16)/256 * (1 << ITUR_BT_601_SHIFT) +static const int ITUR_BT_601_CGY = 528482; // 0.586472 * (236-16)/256 * (1 << ITUR_BT_601_SHIFT) +static const int ITUR_BT_601_CBY = 102760; // 0.114035 * (236-16)/256 * (1 << ITUR_BT_601_SHIFT) +static const int ITUR_BT_601_CRU = -155188; // -0.148 * (1 << (ITUR_BT_601_SHIFT-1)) +static const int ITUR_BT_601_CGU = -305135; // -0.291 * (1 << (ITUR_BT_601_SHIFT-1)) +static const int ITUR_BT_601_CBU = 460324; // 0.439 * (1 << (ITUR_BT_601_SHIFT-1)) +static const int ITUR_BT_601_CGV = -385875; // -0.368 * (1 << (ITUR_BT_601_SHIFT-1)) +static const int ITUR_BT_601_CBV = -74448; // -0.071 * (1 << (ITUR_BT_601_SHIFT-1)) //R = 1.164(Y - 16) + 1.596(V - 128) //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) @@ -1867,15 +1867,22 @@ static const int RGB2YUV422_SHIFT = 14; // separately. For U and V, they are reduced by half to account for two RGB pixels contributing // to the same U and V values. In other words, the U and V contributions from the two RGB pixels // are averaged. The integer versions are obtained by multiplying the float versions by 16384 -// and rounding to the nearest integer. +// and rounding to the nearest integer so that resulting values are in these bounds: +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 -int c_RGB2YUV422Coeffs_i[10] = {1024, 8192, 4211, 8258, 1606, - -1212, -2384, 3596, -3015, -582}; +static const int R2Y422 = 4211; // 0.299077 * (236 - 16) / 256 * 16384 +static const int G2Y422 = 8258; // 0.586506 * (236 - 16) / 256 * 16384 +static const int B2Y422 = 1606; // 0.114062 * (236 - 16) / 256 * 16384 + +static const int R2U422 = -1212; // -0.148 * 8192 +static const int G2U422 = -2384; // -0.291 * 8192 +static const int B2U422 = 3596; // 0.439 * 8192 +static const int G2V422 = -3015; // -0.368 * 8192 +static const int B2V422 = -582; // -0.071 * 8192 static inline void RGB2Y(const uchar r, const uchar g, const uchar b, uchar& y) { - int y_ = r * c_RGB2YUV422Coeffs_i[2] + g * c_RGB2YUV422Coeffs_i[3] + - b * c_RGB2YUV422Coeffs_i[4] + c_RGB2YUV422Coeffs_i[0]*256; + int y_ = r * R2Y422 + g * G2Y422 + b * B2Y422 + (1 << RGB2YUV422_SHIFT) * 16; y = saturate_cast(((1 << (RGB2YUV422_SHIFT-1)) + y_) >> RGB2YUV422_SHIFT); } @@ -1885,12 +1892,10 @@ static inline void RGB2UV(const uchar r1, const uchar g1, const uchar b1, { int sr = r1 + r2, sg = g1 + g2, sb = b1 + b2; - int u_ = sr * c_RGB2YUV422Coeffs_i[5] + sg * c_RGB2YUV422Coeffs_i[6] + - sb * c_RGB2YUV422Coeffs_i[7] + c_RGB2YUV422Coeffs_i[1]*256; + int u_ = sr * R2U422 + sg * G2U422 + sb * B2U422 + (1 << (RGB2YUV422_SHIFT-1)) * 256; u = saturate_cast(((1 << (RGB2YUV422_SHIFT-1)) + u_) >> RGB2YUV422_SHIFT); - int v_ = sr * c_RGB2YUV422Coeffs_i[7] + sg * c_RGB2YUV422Coeffs_i[8] + - sb * c_RGB2YUV422Coeffs_i[9] + c_RGB2YUV422Coeffs_i[1]*256; + int v_ = sr * B2U422 + sg * G2V422 + sb * B2V422 + (1 << (RGB2YUV422_SHIFT-1)) * 256; v = saturate_cast(((1 << (RGB2YUV422_SHIFT-1)) + v_) >> RGB2YUV422_SHIFT); } @@ -2000,14 +2005,17 @@ void cvtYUVtoBGR(const uchar * src_data, size_t src_step, CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, YCrCb2RGB_f(dcn, blueIdx, isCbCr)); } -typedef void (*cvt_2plane_yuv_ptr_t)(uchar * /* dst_data*/, - size_t /* dst_step */, - int /* dst_width */, - int /* dst_height */, - const uchar* /* _y1 */, - size_t /* _y1_step */, - const uchar* /* _uv */, - size_t /* _uv_step */); +// 4:2:0, two planes: Y, UV interleaved +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics +typedef void (*cvt_2plane_yuv_ptr_t)(uchar * /* dst_data */, + size_t /* dst_step */, + int /* dst_width */, + int /* dst_height */, + const uchar* /* _y1 */, + size_t /* _y1_step */, + const uchar* /* _uv */, + size_t /* _uv_step */); void cvtTwoPlaneYUVtoBGR(const uchar * y_data, size_t y_step, const uchar * uv_data, size_t uv_step, uchar * dst_data, size_t dst_step, @@ -2035,21 +2043,24 @@ void cvtTwoPlaneYUVtoBGR(const uchar * y_data, size_t y_step, const uchar * uv_d cvtPtr(dst_data, dst_step, dst_width, dst_height, y_data, y_step, uv_data, uv_step); } -typedef void (*cvt_3plane_yuv_ptr_t)(uchar * /* dst_data */, - size_t /* dst_step */, - int /* dst_width */, - int /* dst_height */, - size_t /* _stride */, - const uchar* /* _y1 */, - const uchar* /* _u */, - const uchar* /* _v */, - int /* ustepIdx */, - int /* vstepIdx */); +// 4:2:0, three planes in one array: Y, U, V +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics +typedef void (*cvt_3plane_yuv_ptr_t)(uchar * /* dst_data */, + size_t /* dst_step */, + int /* dst_width */, + int /* dst_height */, + size_t /* _stride */, + const uchar* /* _y1 */, + const uchar* /* _u */, + const uchar* /* _v */, + int /* ustepIdx */, + int /* vstepIdx */); void cvtThreePlaneYUVtoBGR(const uchar * src_data, size_t src_step, - uchar * dst_data, size_t dst_step, - int dst_width, int dst_height, - int dcn, bool swapBlue, int uIdx) + uchar * dst_data, size_t dst_step, + int dst_width, int dst_height, + int dcn, bool swapBlue, int uIdx) { CV_INSTRUMENT_REGION(); @@ -2075,6 +2086,9 @@ void cvtThreePlaneYUVtoBGR(const uchar * src_data, size_t src_step, cvtPtr(dst_data, dst_step, dst_width, dst_height, src_step, src_data, u, v, ustepIdx, vstepIdx); } +// 4:2:0, three planes in one array: Y, U, V +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics void cvtBGRtoThreePlaneYUV(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, @@ -2093,6 +2107,9 @@ void cvtBGRtoThreePlaneYUV(const uchar * src_data, size_t src_step, cvt(Range(0, height/2)); } +// 4:2:0, two planes: Y, UV interleaved +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics void cvtBGRtoTwoPlaneYUV(const uchar * src_data, size_t src_step, uchar * y_data, uchar * uv_data, size_t dst_step, int width, int height, @@ -2109,12 +2126,15 @@ void cvtBGRtoTwoPlaneYUV(const uchar * src_data, size_t src_step, cvt(Range(0, height/2)); } -typedef void (*cvt_1plane_yuv_ptr_t)(uchar * /* dst_data */, - size_t /* dst_step */, +// 4:2:2 interleaved +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 20-bit fixed-point arithmetics +typedef void (*cvt_1plane_yuv_ptr_t)(uchar * /* dst_data */, + size_t /* dst_step */, const uchar * /* src_data */, - size_t /* src_step */, - int /* width */, - int /* height */); + size_t /* src_step */, + int /* width */, + int /* height */); void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, @@ -2145,6 +2165,9 @@ void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, cvtPtr(dst_data, dst_step, src_data, src_step, width, height); } +// 4:2:2 interleaved +// Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 +// 14-bit fixed-point arithmetics is used void cvtOnePlaneBGRtoYUV(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index 304877cb8bdc..773fed9b482f 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -576,6 +576,7 @@ inline int hal_ni_cvtLabtoBGR(const uchar * src_data, size_t src_step, uchar * d @param uIdx U-channel index in the interleaved U/V plane (0 or 1) Convert from YUV (YUV420sp (or NV12/NV21) - Y plane followed by interleaved U/V plane) to BGR, RGB, BGRA or RGBA. Only for CV_8U. + Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 */ inline int hal_ni_cvtTwoPlaneYUVtoBGR(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int dst_width, int dst_height, int dcn, bool swapBlue, int uIdx) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } @@ -594,6 +595,7 @@ inline int hal_ni_cvtTwoPlaneYUVtoBGR(const uchar * src_data, size_t src_step, u @param uIdx U-channel index in the interleaved U/V plane (0 or 1) Convert from YUV (YUV420sp (or NV12/NV21) - Y plane followed by interleaved U/V plane) to BGR, RGB, BGRA or RGBA. Only for CV_8U. + Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 */ inline int hal_ni_cvtTwoPlaneYUVtoBGREx(const uchar * y_data, size_t y_step, const uchar * uv_data, size_t uv_step, uchar * dst_data, size_t dst_step, int dst_width, int dst_height, @@ -614,6 +616,7 @@ inline int hal_ni_cvtTwoPlaneYUVtoBGREx(const uchar * y_data, size_t y_step, con @param uIdx U-channel plane index (0 or 1) Convert from BGR, RGB, BGRA or RGBA to YUV (YUV420sp (or NV12/NV21) - Y plane followed by interleaved U/V plane). Only for CV_8U. + Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 */ inline int hal_ni_cvtBGRtoTwoPlaneYUV(const uchar * src_data, size_t src_step, uchar * y_data, size_t y_step, uchar * uv_data, size_t uv_step, @@ -633,6 +636,7 @@ inline int hal_ni_cvtBGRtoTwoPlaneYUV(const uchar * src_data, size_t src_step, @param uIdx U-channel plane index (0 or 1) Convert from YUV (YUV420p (or YV12/YV21) - Y plane followed by U and V planes) to BGR, RGB, BGRA or RGBA. Only for CV_8U. + Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 */ inline int hal_ni_cvtThreePlaneYUVtoBGR(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int dst_width, int dst_height, int dcn, bool swapBlue, int uIdx) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } @@ -649,6 +653,7 @@ inline int hal_ni_cvtThreePlaneYUVtoBGR(const uchar * src_data, size_t src_step, @param uIdx U-channel plane index (0 or 1) Convert from BGR, RGB, BGRA or RGBA to YUV (YUV420p (or YV12/YV21) - Y plane followed by U and V planes). Only for CV_8U. + Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 */ inline int hal_ni_cvtBGRtoThreePlaneYUV(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, int scn, bool swapBlue, int uIdx) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } @@ -664,8 +669,9 @@ inline int hal_ni_cvtBGRtoThreePlaneYUV(const uchar * src_data, size_t src_step, @param swapBlue if set to true B and R destination channels will be swapped (write RGB) @param uIdx U-channel index (0 or 1) @param ycn Y-channel index (0 or 1) - Convert from UYVY, YUY2 or YVYU to BGR, RGB, BGRA or RGBA. + Convert from interleaved YUV 4:2:2 (UYVY, YUY2 or YVYU) to BGR, RGB, BGRA or RGBA. Only for CV_8U. + Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 */ inline int hal_ni_cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, int dcn, bool swapBlue, int uIdx, int ycn) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } @@ -678,8 +684,9 @@ inline int hal_ni_cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, u @param swapBlue if set to true B and R destination channels will be swapped (write RGB) @param uIdx U-channel index (0 or 1) @param ycn Y-channel index (0 or 1) - Convert from BGR, RGB, BGRA or RGBA to UYVY, YUY2 or YVYU. + Convert from BGR, RGB, BGRA or RGBA to interleaved YUV 4:2:2 (UYVY, YUY2 or YVYU). Only for CV_8U. + Y : [16, 235]; Cb, Cr: [16, 240] centered at 128 */ inline int hal_ni_cvtOnePlaneBGRtoYUV(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, int scn, bool swapBlue, int uIdx, int ycn) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } From 8955a2757783a5f08bc8539b143f6b91af459351 Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Sun, 26 May 2024 22:50:47 +0300 Subject: [PATCH 086/119] minor cosmetic changes --- 3rdparty/libjpeg-turbo/CMakeLists.txt | 4 +++- 3rdparty/libjpeg-turbo/src/simd/CMakeLists.txt | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/3rdparty/libjpeg-turbo/CMakeLists.txt b/3rdparty/libjpeg-turbo/CMakeLists.txt index 79ffab9cd3f8..5ab3ee11e4d9 100644 --- a/3rdparty/libjpeg-turbo/CMakeLists.txt +++ b/3rdparty/libjpeg-turbo/CMakeLists.txt @@ -249,7 +249,9 @@ set_target_properties(${JPEG_LIBRARY} ) if(ENABLE_SOLUTION_FOLDERS) - set_target_properties(${JPEG_LIBRARY} PROPERTIES FOLDER "3rdparty") + set_target_properties(${JPEG_LIBRARY} PROPERTIES FOLDER "3rdparty/jpeg") + set_target_properties(jpeg12-static PROPERTIES FOLDER "3rdparty/jpeg") + set_target_properties(jpeg16-static PROPERTIES FOLDER "3rdparty/jpeg") endif() if(NOT BUILD_SHARED_LIBS) diff --git a/3rdparty/libjpeg-turbo/src/simd/CMakeLists.txt b/3rdparty/libjpeg-turbo/src/simd/CMakeLists.txt index 023795598a19..48944c6bfe95 100644 --- a/3rdparty/libjpeg-turbo/src/simd/CMakeLists.txt +++ b/3rdparty/libjpeg-turbo/src/simd/CMakeLists.txt @@ -2,7 +2,7 @@ macro(simd_fail message) if(REQUIRE_SIMD) message(FATAL_ERROR "${message}.") else() - message(WARNING "${message}. Performance will suffer.") + message(STATUS "${message}. Performance will suffer.") set(WITH_SIMD 0 PARENT_SCOPE) endif() endmacro() @@ -211,6 +211,9 @@ if(MSVC_IDE OR XCODE) add_library(simd OBJECT ${CPU_TYPE}/jsimd.c) add_custom_target(simd-objs DEPENDS ${SIMD_OBJS}) add_dependencies(simd simd-objs) + set_target_properties(simd PROPERTIES FOLDER "3rdparty/jpeg") + set_target_properties(simd-objs PROPERTIES FOLDER "3rdparty/jpeg") + set_target_properties(jsimdcfg PROPERTIES FOLDER "3rdparty/jpeg") else() add_library(simd OBJECT ${SIMD_SOURCES} ${CPU_TYPE}/jsimd.c) endif() From b6593517c4d2cd9f3d9e176e82ce43e6d0085e3e Mon Sep 17 00:00:00 2001 From: Kumataro Date: Mon, 27 May 2024 23:33:43 +0900 Subject: [PATCH 087/119] Merge pull request #25647 from Kumataro:fix25646 imgcodecs: support IMWRITE_JPEG_LUMA/CHROMA_QUALITY with internal libjpeg-turbo #25647 Close #25646 - increase JPEG_LIB_VERSION for internal libjpeg-turbo from 62 to 70 - add log when using IMWRITE_JPEG_LUMA/CHROMA_QUALITY with JPEG_LIB_VERSION<70 - add document IMWRITE_JPEG_LUMA/CHROMA_QUALITY requests JPEG_LIB_VERSION >= 70 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- 3rdparty/libjpeg-turbo/CMakeLists.txt | 2 +- .../imgcodecs/include/opencv2/imgcodecs.hpp | 4 +- modules/imgcodecs/src/grfmt_jpeg.cpp | 7 ++- modules/imgcodecs/test/test_jpeg.cpp | 62 +++++++++++++++++++ 4 files changed, 70 insertions(+), 5 deletions(-) diff --git a/3rdparty/libjpeg-turbo/CMakeLists.txt b/3rdparty/libjpeg-turbo/CMakeLists.txt index 5ab3ee11e4d9..f41665f329e5 100644 --- a/3rdparty/libjpeg-turbo/CMakeLists.txt +++ b/3rdparty/libjpeg-turbo/CMakeLists.txt @@ -134,7 +134,7 @@ if(WITH_ARITH_DEC) set(D_ARITH_CODING_SUPPORTED 1) endif() -set(JPEG_LIB_VERSION 62) +set(JPEG_LIB_VERSION 70) # OpenCV set(JPEG_LIB_VERSION "${VERSION}-${JPEG_LIB_VERSION}" PARENT_SCOPE) diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index 0ca202722d31..eba25ce1cfb8 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -87,8 +87,8 @@ enum ImwriteFlags { IMWRITE_JPEG_PROGRESSIVE = 2, //!< Enable JPEG features, 0 or 1, default is False. IMWRITE_JPEG_OPTIMIZE = 3, //!< Enable JPEG features, 0 or 1, default is False. IMWRITE_JPEG_RST_INTERVAL = 4, //!< JPEG restart interval, 0 - 65535, default is 0 - no restart. - IMWRITE_JPEG_LUMA_QUALITY = 5, //!< Separate luma quality level, 0 - 100, default is -1 - don't use. - IMWRITE_JPEG_CHROMA_QUALITY = 6, //!< Separate chroma quality level, 0 - 100, default is -1 - don't use. + IMWRITE_JPEG_LUMA_QUALITY = 5, //!< Separate luma quality level, 0 - 100, default is -1 - don't use. If JPEG_LIB_VERSION < 70, Not supported. + IMWRITE_JPEG_CHROMA_QUALITY = 6, //!< Separate chroma quality level, 0 - 100, default is -1 - don't use. If JPEG_LIB_VERSION < 70, Not supported. IMWRITE_JPEG_SAMPLING_FACTOR = 7, //!< For JPEG, set sampling factor. See cv::ImwriteJPEGSamplingFactorParams. IMWRITE_PNG_COMPRESSION = 16, //!< For PNG, it can be the compression level from 0 to 9. A higher value means a smaller size and longer compression time. If specified, strategy is changed to IMWRITE_PNG_STRATEGY_DEFAULT (Z_DEFAULT_STRATEGY). Default value is 1 (best speed setting). IMWRITE_PNG_STRATEGY = 17, //!< One of cv::ImwritePNGFlags, default is IMWRITE_PNG_STRATEGY_RLE. diff --git a/modules/imgcodecs/src/grfmt_jpeg.cpp b/modules/imgcodecs/src/grfmt_jpeg.cpp index 4a2aee12b01f..4e3b1df48d98 100644 --- a/modules/imgcodecs/src/grfmt_jpeg.cpp +++ b/modules/imgcodecs/src/grfmt_jpeg.cpp @@ -783,9 +783,9 @@ bool JpegEncoder::write( const Mat& img, const std::vector& params ) cinfo.comp_info[1].h_samp_factor = 1; } -#if JPEG_LIB_VERSION >= 70 if (luma_quality >= 0 && chroma_quality >= 0) { +#if JPEG_LIB_VERSION >= 70 cinfo.q_scale_factor[0] = jpeg_quality_scaling(luma_quality); cinfo.q_scale_factor[1] = jpeg_quality_scaling(chroma_quality); if ( luma_quality != chroma_quality ) @@ -797,8 +797,11 @@ bool JpegEncoder::write( const Mat& img, const std::vector& params ) cinfo.comp_info[1].h_samp_factor = 1; } jpeg_default_qtables( &cinfo, TRUE ); - } +#else + // See https://github.com/opencv/opencv/issues/25646 + CV_LOG_ONCE_WARNING(NULL, cv::format("IMWRITE_JPEG_LUMA/CHROMA_QUALITY are not supported bacause JPEG_LIB_VERSION < 70.")); #endif // #if JPEG_LIB_VERSION >= 70 + } jpeg_start_compress( &cinfo, TRUE ); diff --git a/modules/imgcodecs/test/test_jpeg.cpp b/modules/imgcodecs/test/test_jpeg.cpp index 12abc0a8e3ed..ee9da01aa79e 100644 --- a/modules/imgcodecs/test/test_jpeg.cpp +++ b/modules/imgcodecs/test/test_jpeg.cpp @@ -7,6 +7,10 @@ namespace opencv_test { namespace { #ifdef HAVE_JPEG +extern "C" { +#include "jpeglib.h" +} + /** * Test for check whether reading exif orientation tag was processed successfully or not * The test info is the set of 8 images named testExifRotate_{1 to 8}.jpg @@ -308,6 +312,64 @@ TEST(Imgcodecs_Jpeg, encode_subsamplingfactor_usersetting_invalid) } } +//================================================================================================== +// See https://github.com/opencv/opencv/issues/25646 +typedef testing::TestWithParam> Imgcodecs_Jpeg_encode_withLumaChromaQuality; + +TEST_P(Imgcodecs_Jpeg_encode_withLumaChromaQuality, basic) +{ + const int luma = get<0>(GetParam()); + const int chroma = get<1>(GetParam()); + + cvtest::TS& ts = *cvtest::TS::ptr(); + string fname = string(ts.get_data_path()) + "../cv/shared/lena.png"; + + cv::Mat src = imread(fname, cv::IMREAD_COLOR); + ASSERT_FALSE(src.empty()); + + std::vector jpegNormal; + ASSERT_NO_THROW(cv::imencode(".jpg", src, jpegNormal)); + + std::vector param; + param.push_back(IMWRITE_JPEG_LUMA_QUALITY); + param.push_back(luma); + param.push_back(IMWRITE_JPEG_CHROMA_QUALITY); + param.push_back(chroma); + + std::vector jpegCustom; + ASSERT_NO_THROW(cv::imencode(".jpg", src, jpegCustom, param)); + +#if JPEG_LIB_VERSION >= 70 + // For jpeg7+, we can support IMWRITE_JPEG_LUMA_QUALITY and IMWRITE_JPEG_CHROMA_QUALITY. + if( (luma == 95 /* Default Luma Quality */ ) && ( chroma == 95 /* Default Chroma Quality */)) + { + EXPECT_EQ(jpegNormal, jpegCustom); + } + else + { + EXPECT_NE(jpegNormal, jpegCustom); + } +#else + // For jpeg6-, we cannot support IMWRITE_JPEG_LUMA/CHROMA_QUALITY because jpeg_default_qtables() is missing. + // - IMWRITE_JPEG_LUMA_QUALITY updates internal parameter of IMWRITE_JPEG_QUALITY. + // - IMWRITE_JPEG_CHROMA_QUALITY updates nothing. + if( luma == 95 /* Default Jpeg Quality */ ) + { + EXPECT_EQ(jpegNormal, jpegCustom); + } + else + { + EXPECT_NE(jpegNormal, jpegCustom); + } +#endif +} + +INSTANTIATE_TEST_CASE_P( /* nothing */, + Imgcodecs_Jpeg_encode_withLumaChromaQuality, + testing::Combine( + testing::Values(70, 95, 100), // IMWRITE_JPEG_LUMA_QUALITY + testing::Values(70, 95, 100) )); // IMWRITE_JPEG_CHROMA_QUALITY + #endif // HAVE_JPEG }} // namespace From 05e48605a0aea00d3a89b9ab5e25cdf89568aa28 Mon Sep 17 00:00:00 2001 From: Danial Javady <122740063+ZelboK@users.noreply.github.com> Date: Tue, 28 May 2024 02:54:08 -0400 Subject: [PATCH 088/119] Merge pull request #25412 from ZelboK:update-cudnn-to-9 Refactor DNN module to build with cudnn 9 #25412 A lot of APIs that are currently being used in the dnn module have been removed in cudnn 9. They were deprecated in 8. This PR updates said code accordingly to the newer API. Some key notes: 1) This is my first PR. I am new to openCV. 2) `opencv_test_core` tests pass 3) On a 3080, cuda 12.4(should be irrelevant since I didn't build the `opencv_modules`, gcc 11.4, WSL 2. 4) For brevity I will avoid including macro code that will allow for older versions of cudnn to build. I was unable to get the tests working for `opencv_test_dnn` and `opencv_perf_dnn`. The errors I get are of the following: ``` OpenCV tests: Can't find required data file: dnn/onnx/conformance/node/test_reduce_prod_default_axes_keepdims_example/model.onnx in function 'findData' " thrown in the test body. ``` So before I spend more time investigating I was hoping to get a maintainer to point me in the right direction here. I would like to run these tests and confirm things are working as intended. I may have missed some details. ### Pull Request Readiness Checklist relevant issue (https://github.com/opencv/opencv/issues/24983 - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ ] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- .../dnn/src/cuda4dnn/csl/cudnn/recurrent.hpp | 70 ++++++++++++---- modules/dnn/src/cuda4dnn/csl/tensor_ops.hpp | 81 +++++++++++++++++-- .../cuda4dnn/primitives/recurrent_cells.hpp | 8 +- 3 files changed, 134 insertions(+), 25 deletions(-) diff --git a/modules/dnn/src/cuda4dnn/csl/cudnn/recurrent.hpp b/modules/dnn/src/cuda4dnn/csl/cudnn/recurrent.hpp index 7ba6acdf173c..8006dca62b96 100644 --- a/modules/dnn/src/cuda4dnn/csl/cudnn/recurrent.hpp +++ b/modules/dnn/src/cuda4dnn/csl/cudnn/recurrent.hpp @@ -97,7 +97,7 @@ class RNNDescriptor /** */ - RNNDescriptor(const Handle &handle, RNNMode mode, int hidden_size, int num_layers, + RNNDescriptor(const Handle &handle, RNNMode mode, int input_size, int hidden_size, int num_layers, bool bidirectional, const DropoutDescriptor &dropoutDesc) { CUDA4DNN_CHECK_CUDNN(cudnnCreateRNNDescriptor(&descriptor)); @@ -119,12 +119,35 @@ class RNNDescriptor try { +#if CUDNN_MAJOR >= 9 + CUDA4DNN_CHECK_CUDNN(cudnnSetRNNDescriptor_v8( + descriptor, + algo, + rnn_mode, + CUDNN_RNN_DOUBLE_BIAS, + bidirectional ? CUDNN_BIDIRECTIONAL : CUDNN_UNIDIRECTIONAL, + CUDNN_LINEAR_INPUT, detail::get_data_type(), + detail::get_data_type(), + detail::get_data_type() == CUDNN_DATA_HALF ? CUDNN_TENSOR_OP_MATH : CUDNN_DEFAULT_MATH, + input_size, + hidden_size, + hidden_size, + num_layers, + dropoutDesc.get(), + 0)); // What other flags do we might want here? +#else CUDA4DNN_CHECK_CUDNN(cudnnSetRNNDescriptor_v6( - handle.get(), descriptor, hidden_size, num_layers, dropoutDesc.get(), - CUDNN_LINEAR_INPUT, bidirectional ? CUDNN_BIDIRECTIONAL : CUDNN_UNIDIRECTIONAL, - rnn_mode, - algo, //CUDNN_RNN_ALGO_STANDARD, - detail::get_data_type())); + handle.get(), + descriptor, + hidden_size, + num_layers, + dropoutDesc.get(), + CUDNN_LINEAR_INPUT, + bidirectional ? CUDNN_BIDIRECTIONAL : CUDNN_UNIDIRECTIONAL, + rnn_mode, + algo, + detail::get_data_type())); +#endif } catch (...) { @@ -158,16 +181,34 @@ class RNNDescriptor cudnnRNNAlgo_t algo{CUDNN_RNN_ALGO_STANDARD}; }; -template -size_t getRNNWorkspaceSize(const Handle &handle, const RNNDescriptor &rnnDesc, - const int seqLength, const TensorDescriptorsArray &inputDesc) +#if CUDNN_MAJOR >= 9 +template +void LSTMForward(const Handle &handle, const RNNDescriptor &rnnDesc, + cudnnRNNDataDescriptor_t xDesc, DevicePtr x, + cudnnRNNDataDescriptor_t yDesc, DevicePtr y, + cudnnTensorDescriptor_t hDesc, DevicePtr hx, DevicePtr hy, + cudnnTensorDescriptor_t cDesc, DevicePtr cx, DevicePtr cy, + size_t weightSpaceSize, DevicePtr weightSpace, + size_t cudnn_WorkspaceSize, DevicePtr cudnn_Workspace, + size_t reserveSpaceSize, DevicePtr reserveSpace) { - size_t workSize; - CUDA4DNN_CHECK_CUDNN(cudnnGetRNNWorkspaceSize(handle.get(), rnnDesc.get(), seqLength, - inputDesc.get().data(), &workSize)); - return workSize; + CV_Assert(handle); + + std::cout << "cudnn_WorkspaceSize: " << cudnn_WorkspaceSize << std::endl; + std::cout << "reserveSpaceSize: " << reserveSpaceSize << std::endl; + + CUDA4DNN_CHECK_CUDNN(cudnnRNNForward( + handle.get(), rnnDesc.get(), CUDNN_FWD_MODE_INFERENCE, + nullptr, // docs say use this as null on >= 8.9.1 + xDesc, x.get(), yDesc, y.get(), + hDesc, hx.get(), hy.get(), + cDesc, cx.get(), cy.get(), + weightSpaceSize, weightSpace.get(), + cudnn_WorkspaceSize, cudnn_Workspace.get(), + reserveSpaceSize, reserveSpace.get())); } +#else template void LSTMForward(const Handle &handle, const RNNDescriptor &rnnDesc, const FilterDescriptor &filterDesc, DevicePtr filterPtr, @@ -189,7 +230,8 @@ void LSTMForward(const Handle &handle, const RNNDescriptor &rnnDesc, initialCDesc.get(), ycOutputPtr.get(), static_cast(workspace.get()), workspace.size_in_bytes())); } +#endif }}}}} /* namespace cv::dnn::cuda4dnn::csl::cudnn */ -#endif //OPENCV_DNN_CUDA4DNN_CSL_CUDNN_RECURRENT_HPP \ No newline at end of file +#endif //OPENCV_DNN_CUDA4DNN_CSL_CUDNN_RECURRENT_HPP diff --git a/modules/dnn/src/cuda4dnn/csl/tensor_ops.hpp b/modules/dnn/src/cuda4dnn/csl/tensor_ops.hpp index 868b0c928463..1c439fb3d6ad 100644 --- a/modules/dnn/src/cuda4dnn/csl/tensor_ops.hpp +++ b/modules/dnn/src/cuda4dnn/csl/tensor_ops.hpp @@ -528,6 +528,46 @@ namespace cv { namespace dnn { namespace cuda4dnn { namespace csl { LSTM() = default; LSTM(const LSTM&) = delete; LSTM(LSTM&&) = default; + +#if CUDNN_MAJOR >= 9 + LSTM(cudnn::Handle handle, const params_type ¶ms) + : cudnnHandle(std::move(handle)), seqLength(params.seqLength) + { + std::vector seqLenArr(params.miniBatch, seqLength); + cudnnCreateRNNDataDescriptor(&xDesc); + cudnnSetRNNDataDescriptor(xDesc, cudnn::detail::get_data_type(), + CUDNN_RNN_DATA_LAYOUT_SEQ_MAJOR_PACKED, seqLength, + params.miniBatch, params.inputSize, seqLenArr.data(), + nullptr); + cudnnCreateRNNDataDescriptor(&cyDesc); + cudnnSetRNNDataDescriptor( + cyDesc, cudnn::detail::get_data_type(), + CUDNN_RNN_DATA_LAYOUT_SEQ_MAJOR_PACKED, + seqLength, params.miniBatch, + params.bidirectional ? params.hiddenSize * 2 : params.hiddenSize, + seqLenArr.data(), + nullptr); + + dropoutDesc = DropoutDescriptor(cudnnHandle, params.dropout); + rnnDesc = RNNDescriptor(cudnnHandle, params.type, params.inputSize, params.hiddenSize, + params.numLayers, params.bidirectional, dropoutDesc); + + int num_direction = params.bidirectional ? 2 : 1; + h0TensorDesc = TensorDescriptor(num_direction, params.miniBatch, params.hiddenSize); + c0TensorDesc = TensorDescriptor(num_direction, params.miniBatch, params.hiddenSize); + + // Get amount of work space required to execute the RNN described by rnnDesc + // with input dimensions defined by inputDesc + CUDA4DNN_CHECK_CUDNN(cudnnGetRNNTempSpaceSizes( + cudnnHandle.get(), rnnDesc.get(), CUDNN_FWD_MODE_INFERENCE, + xDesc, &workSpaceSize, &reserveSpaceSize)); + + csl::WorkspaceBuilder builder; + builder.require(workSpaceSize); + builder.require(reserveSpaceSize); + scratch_mem_in_bytes = builder.required_workspace_size(); + } +#else LSTM(cudnn::Handle handle, const params_type& params) : cudnnHandle(std::move(handle)), seqLength{params.seqLength}, inputDesc(seqLength, {params.miniBatch, params.inputSize, 1}), @@ -538,7 +578,7 @@ namespace cv { namespace dnn { namespace cuda4dnn { namespace csl { { dropoutDesc = DropoutDescriptor(cudnnHandle, params.dropout); filterDesc = FilterDescriptor(params.weights_shape); - rnnDesc = RNNDescriptor(cudnnHandle, params.type, params.hiddenSize, + rnnDesc = RNNDescriptor(cudnnHandle, params.type, params.inputSize, params.hiddenSize, params.numLayers, params.bidirectional, dropoutDesc); int num_direction = params.bidirectional ? 2 : 1; @@ -550,19 +590,44 @@ namespace cv { namespace dnn { namespace cuda4dnn { namespace csl { // Get amount of work space required to execute the RNN described by rnnDesc // with input dimensions defined by inputDesc csl::WorkspaceBuilder builder; - builder.require(cudnn::getRNNWorkspaceSize(cudnnHandle, rnnDesc, seqLength, inputDesc)); + size_t workSize; + CUDA4DNN_CHECK_CUDNN(cudnnGetRNNWorkspaceSize(cudnnHandle.get(), rnnDesc.get(), seqLength, + inputDesc.get().data(), &workSize)); + builder.require(workSize); scratch_mem_in_bytes = builder.required_workspace_size(); } +#endif LSTM& operator=(const LSTM&) = delete; LSTM& operator=(LSTM&&) = default; void inference(TensorView input, TensorSpan y_output, TensorSpan yc_output, TensorView filters, - TensorView h0, TensorView c0, WorkspaceInstance workspace) + TensorView h0, TensorView c0, csl::Workspace& workspace) { + auto ws_allocator = csl::WorkspaceAllocator(workspace); + +#if CUDNN_MAJOR >= 9 + size_t weightSpaceSize = sizeof(typename TensorView::value_type) * filters.size(); + auto workspaceData = ws_allocator.get_span(workSpaceSize); + auto reserveSpaceData = ws_allocator.get_span(reserveSpaceSize); + cudnn::LSTMForward(cudnnHandle, rnnDesc, xDesc, input.get(), cyDesc, + y_output.get(), h0TensorDesc.get(), h0.get(), + DevicePtr(nullptr), // hy, final state + c0TensorDesc.get(), // maps to cxDesc + c0.get(), // maps to cx + yc_output.get(), // maps to cy + weightSpaceSize, + filters.get(), // maps to weightSpace + workSpaceSize, + workspaceData.data(), // workSpaceSize and workSpace + reserveSpaceSize, // reserveSpaceSize + reserveSpaceData.data() + ); +#else cudnn::LSTMForward(cudnnHandle, rnnDesc, filterDesc, filters.get(), inputDesc, input.get(), h0TensorDesc, h0.get(), c0TensorDesc, c0.get(), - seqLength, outputDesc, y_output.get(), yc_output.get(), workspace); + seqLength, outputDesc, y_output.get(), yc_output.get(), ws_allocator.get_instance()); +#endif } std::size_t get_workspace_memory_in_bytes() const noexcept { return scratch_mem_in_bytes; } @@ -575,11 +640,17 @@ namespace cv { namespace dnn { namespace cuda4dnn { namespace csl { RNNDescriptor rnnDesc; DropoutDescriptor dropoutDesc; - FilterDescriptor filterDesc; TensorDescriptor h0TensorDesc, c0TensorDesc; +#if CUDNN_MAJOR >= 9 + size_t weightSpaceSize, workSpaceSize, reserveSpaceSize; + cudnnRNNDataDescriptor_t xDesc; + cudnnRNNDataDescriptor_t cyDesc; // represents cyDesc or cDesc(now reps both final and beginning) +#else + FilterDescriptor filterDesc; TensorDescriptorsArray inputDesc; TensorDescriptorsArray outputDesc; +#endif }; }}}} /* namespace cv::dnn::cuda4dnn::csl */ diff --git a/modules/dnn/src/cuda4dnn/primitives/recurrent_cells.hpp b/modules/dnn/src/cuda4dnn/primitives/recurrent_cells.hpp index 5cba78800812..67f1aff28546 100644 --- a/modules/dnn/src/cuda4dnn/primitives/recurrent_cells.hpp +++ b/modules/dnn/src/cuda4dnn/primitives/recurrent_cells.hpp @@ -55,9 +55,6 @@ class LSTMOp final : public CUDABackendNode c0Tensor = csl::makeTensorHeader(c0); csl::copyMatToTensor(c0, c0Tensor, stream); - - csl::WorkspaceBuilder builder; - builder.require(lstm.get_workspace_memory_in_bytes()); } void forward(const std::vector>& inputs, @@ -75,8 +72,7 @@ class LSTMOp final : public CUDABackendNode Ptr yc_output_wrapper = outputs.size() == 2 ? outputs[1].dynamicCast() : Ptr(); csl::TensorSpan yc_output = yc_output_wrapper.empty() ? csl::TensorSpan() : yc_output_wrapper->getSpan(); - csl::WorkspaceAllocator allocator(workspace); - lstm.inference(input, y_output, yc_output, filtersTensor, h0Tensor, c0Tensor, allocator.get_instance()); + lstm.inference(input, y_output, yc_output, filtersTensor, h0Tensor, c0Tensor, workspace); } std::size_t get_workspace_memory_in_bytes() const noexcept override @@ -94,4 +90,4 @@ class LSTMOp final : public CUDABackendNode }}} /* namespace cv::dnn::cuda4dnn */ -#endif //OPENCV_DNN_SRC_CUDA4DNN_PRIMITIVES_RECURRENT_CELLS_HPP \ No newline at end of file +#endif //OPENCV_DNN_SRC_CUDA4DNN_PRIMITIVES_RECURRENT_CELLS_HPP From 1668203a1c6474b8368e27c55abc10ae7f17c841 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Tue, 28 May 2024 09:55:22 +0300 Subject: [PATCH 089/119] Added branch with variadic version of Trust tuple --- .../opencv2/core/cuda/detail/reduce.hpp | 53 +++++++-- .../core/cuda/detail/reduce_key_val.hpp | 107 ++++++++++++++---- .../core/include/opencv2/core/cuda/reduce.hpp | 31 ++++- 3 files changed, 153 insertions(+), 38 deletions(-) diff --git a/modules/core/include/opencv2/core/cuda/detail/reduce.hpp b/modules/core/include/opencv2/core/cuda/detail/reduce.hpp index 8af20b0dc86d..05a672c3dc36 100644 --- a/modules/core/include/opencv2/core/cuda/detail/reduce.hpp +++ b/modules/core/include/opencv2/core/cuda/detail/reduce.hpp @@ -134,6 +134,22 @@ namespace cv { namespace cuda { namespace device { val = smem[tid]; } + + template + __device__ __forceinline__ void merge(volatile T* smem, T& val, unsigned int tid, unsigned int delta, const Op& op) + { + T reg = smem[tid + delta]; + smem[tid] = val = op(val, reg); + } + + template + __device__ __forceinline__ void mergeShfl(T& val, unsigned int delta, unsigned int width, const Op& op) + { + T reg = shfl_down(val, delta, width); + val = op(val, reg); + } + +#if (CUDART_VERSION < 12040) // details: https://github.com/opencv/opencv_contrib/issues/3690 template __device__ __forceinline__ void loadToSmem(const thrust::tuple& smem, @@ -142,6 +158,7 @@ namespace cv { namespace cuda { namespace device { For<0, thrust::tuple_size >::value>::loadToSmem(smem, val, tid); } + template __device__ __forceinline__ void loadFromSmem(const thrust::tuple& smem, @@ -151,18 +168,6 @@ namespace cv { namespace cuda { namespace device For<0, thrust::tuple_size >::value>::loadFromSmem(smem, val, tid); } - template - __device__ __forceinline__ void merge(volatile T* smem, T& val, unsigned int tid, unsigned int delta, const Op& op) - { - T reg = smem[tid + delta]; - smem[tid] = val = op(val, reg); - } - template - __device__ __forceinline__ void mergeShfl(T& val, unsigned int delta, unsigned int width, const Op& op) - { - T reg = shfl_down(val, delta, width); - val = op(val, reg); - } template @@ -183,7 +188,31 @@ namespace cv { namespace cuda { namespace device { For<0, thrust::tuple_size >::value>::mergeShfl(val, delta, width, op); } +#else + template + __device__ __forceinline__ void loadToSmem(const thrust::tuple& smem, const thrust::tuple& val, unsigned int tid) + { + For<0, thrust::tuple_size >::value>::loadToSmem(smem, val, tid); + } + template + __device__ __forceinline__ void loadFromSmem(const thrust::tuple& smem, const thrust::tuple& val, unsigned int tid) + { + For<0, thrust::tuple_size >::value>::loadFromSmem(smem, val, tid); + } + + template + __device__ __forceinline__ void merge(const thrust::tuple& smem, const thrust::tuple& val, unsigned int tid, unsigned int delta, const thrust::tuple& op) + { + For<0, thrust::tuple_size >::value>::merge(smem, val, tid, delta, op); + } + + template + __device__ __forceinline__ void mergeShfl(const thrust::tuple& val, unsigned int delta, unsigned int width, const thrust::tuple& op) + { + For<0, thrust::tuple_size >::value>::mergeShfl(val, delta, width, op); + } +#endif template struct Generic { template diff --git a/modules/core/include/opencv2/core/cuda/detail/reduce_key_val.hpp b/modules/core/include/opencv2/core/cuda/detail/reduce_key_val.hpp index df37c173be64..4a248c83657e 100644 --- a/modules/core/include/opencv2/core/cuda/detail/reduce_key_val.hpp +++ b/modules/core/include/opencv2/core/cuda/detail/reduce_key_val.hpp @@ -177,6 +177,8 @@ namespace cv { namespace cuda { namespace device { data = smem[tid]; } + +#if (CUDART_VERSION < 12040) template __device__ __forceinline__ void loadToSmem(const thrust::tuple& smem, @@ -193,9 +195,18 @@ namespace cv { namespace cuda { namespace device { For<0, thrust::tuple_size >::value>::loadFromSmem(smem, data, tid); } - - ////////////////////////////////////////////////////// - // copyVals +#else + template + __device__ __forceinline__ void loadToSmem(const thrust::tuple& smem, const thrust::tuple& data, unsigned int tid) + { + For<0, thrust::tuple_size >::value>::loadToSmem(smem, data, tid); + } + template + __device__ __forceinline__ void loadFromSmem(const thrust::tuple& smem, const thrust::tuple& data, unsigned int tid) + { + For<0, thrust::tuple_size >::value>::loadFromSmem(smem, data, tid); + } +#endif template __device__ __forceinline__ void copyValsShfl(V& val, unsigned int delta, int width) @@ -207,24 +218,6 @@ namespace cv { namespace cuda { namespace device { svals[tid] = val = svals[tid + delta]; } - template - __device__ __forceinline__ void copyValsShfl(const thrust::tuple& val, - unsigned int delta, - int width) - { - For<0, thrust::tuple_size >::value>::copyShfl(val, delta, width); - } - template - __device__ __forceinline__ void copyVals(const thrust::tuple& svals, - const thrust::tuple& val, - unsigned int tid, unsigned int delta) - { - For<0, thrust::tuple_size >::value>::copy(svals, val, tid, delta); - } - - ////////////////////////////////////////////////////// - // merge template __device__ __forceinline__ void mergeShfl(K& key, V& val, const Cmp& cmp, unsigned int delta, int width) @@ -248,6 +241,24 @@ namespace cv { namespace cuda { namespace device copyVals(svals, val, tid, delta); } } + +#if (CUDART_VERSION < 12040) // details: https://github.com/opencv/opencv_contrib/issues/3690 + template + __device__ __forceinline__ void copyValsShfl(const thrust::tuple& val, + unsigned int delta, + int width) + { + For<0, thrust::tuple_size >::value>::copyShfl(val, delta, width); + } + template + __device__ __forceinline__ void copyVals(const thrust::tuple& svals, + const thrust::tuple& val, + unsigned int tid, unsigned int delta) + { + For<0, thrust::tuple_size >::value>::copy(svals, val, tid, delta); + } + template @@ -305,7 +316,61 @@ namespace cv { namespace cuda { namespace device { For<0, thrust::tuple_size >::value>::merge(skeys, key, svals, val, cmp, tid, delta); } +#else + template + __device__ __forceinline__ void copyValsShfl(const thrust::tuple& val, unsigned int delta, int width) + { + For<0, thrust::tuple_size >::value>::copyShfl(val, delta, width); + } + template + __device__ __forceinline__ void copyVals(const thrust::tuple& svals, const thrust::tuple& val, unsigned int tid, unsigned int delta) + { + For<0, thrust::tuple_size >::value>::copy(svals, val, tid, delta); + } + + template + __device__ __forceinline__ void mergeShfl(K& key, const thrust::tuple& val, const Cmp& cmp, unsigned int delta, int width) + { + K reg = shfl_down(key, delta, width); + + if (cmp(reg, key)) + { + key = reg; + copyValsShfl(val, delta, width); + } + } + template + __device__ __forceinline__ void merge(volatile K* skeys, K& key, const thrust::tuple& svals, + const thrust::tuple& val, const Cmp& cmp, unsigned int tid, unsigned int delta) + { + K reg = skeys[tid + delta]; + + if (cmp(reg, key)) + { + skeys[tid] = key = reg; + copyVals(svals, val, tid, delta); + } + } + template + __device__ __forceinline__ void mergeShfl(const thrust::tuple& key, + const thrust::tuple& val, + const thrust::tuple& cmp, + unsigned int delta, int width) + { + For<0, thrust::tuple_size >::value>::mergeShfl(key, val, cmp, delta, width); + } + template + __device__ __forceinline__ void merge(const thrust::tuple& skeys, + const thrust::tuple& key, + const thrust::tuple& svals, + const thrust::tuple& val, + const thrust::tuple& cmp, + unsigned int tid, unsigned int delta) + { + For<0, thrust::tuple_size >::value>::merge(skeys, key, svals, val, cmp, tid, delta); + } +#endif ////////////////////////////////////////////////////// // Generic diff --git a/modules/core/include/opencv2/core/cuda/reduce.hpp b/modules/core/include/opencv2/core/cuda/reduce.hpp index 5de365081789..fb74de95a8ab 100644 --- a/modules/core/include/opencv2/core/cuda/reduce.hpp +++ b/modules/core/include/opencv2/core/cuda/reduce.hpp @@ -64,6 +64,12 @@ namespace cv { namespace cuda { namespace device { reduce_detail::Dispatcher::reductor::template reduce(smem, val, tid, op); } + template + __device__ __forceinline__ void reduceKeyVal(volatile K* skeys, K& key, volatile V* svals, V& val, unsigned int tid, const Cmp& cmp) + { + reduce_key_val_detail::Dispatcher::reductor::template reduce(skeys, key, svals, val, tid, cmp); + } +#if (CUDART_VERSION < 12040) // details: https://github.com/opencv/opencv_contrib/issues/3690 template &>(smem, val, tid, op); } - template - __device__ __forceinline__ void reduceKeyVal(volatile K* skeys, K& key, volatile V* svals, V& val, unsigned int tid, const Cmp& cmp) - { - reduce_key_val_detail::Dispatcher::reductor::template reduce(skeys, key, svals, val, tid, cmp); - } template &, const Cmp&>(skeys, key, svals, val, tid, cmp); } + template & >(skeys, key, svals, val, tid, cmp); } +#else + template + __device__ __forceinline__ void reduce(const thrust::tuple& smem, const thrust::tuple& val, unsigned int tid, const thrust::tuple& op) + { + reduce_detail::Dispatcher::reductor::template reduce&, const thrust::tuple&, const thrust::tuple&>(smem, val, tid, op); + } + + template + __device__ __forceinline__ void reduceKeyVal(volatile K* skeys, K& key, const thrust::tuple& svals, const thrust::tuple& val, unsigned int tid, const Cmp& cmp) + { + reduce_key_val_detail::Dispatcher::reductor::template reduce&, const thrust::tuple&, const Cmp&>(skeys, key, svals, val, tid, cmp); + } + + template + __device__ __forceinline__ void reduceKeyVal(const thrust::tuple& skeys, const thrust::tuple& key, const thrust::tuple& svals, const thrust::tuple& val, unsigned int tid, const thrust::tuple& cmp) + { + reduce_key_val_detail::Dispatcher::reductor::template reduce&, const thrust::tuple&, const thrust::tuple&, const thrust::tuple&, const thrust::tuple&>(skeys, key, svals, val, tid, cmp); + } +#endif // smem_tuple From d9421ac148f3ad4878b3a75c58da58c24f19ed01 Mon Sep 17 00:00:00 2001 From: Junyan721113 Date: Tue, 28 May 2024 19:25:53 +0800 Subject: [PATCH 090/119] Merge pull request #25167 from plctlab:rvp_3rdparty 3rdparty: NDSRVP - A New 3rdparty Library with Optimizations Based on RISC-V P Extension v0.5.2 - Part 1: Basic Functions #25167 # Summary ### Previous context From PR #24556: >> * As you wrote, the P-extension differs from RVV thus can not be easily implemented via Universal Intrinsics mechanism, but there is another HAL mechanism for lower-level CPU optimizations which is used by the [Carotene](https://github.com/opencv/opencv/tree/4.x/3rdparty/carotene) library on ARM platforms. I suggest moving all non-dnn code to similar third-party component. For example, FAST algorithm should allow such optimization-shortcut: see https://github.com/opencv/opencv/blob/4.x/modules/features2d/src/hal_replacement.hpp >> Reference documentation is here: >> >> * https://docs.opencv.org/4.x/d1/d1b/group__core__hal__interface.html >> * https://docs.opencv.org/4.x/dd/d8b/group__imgproc__hal__interface.html >> * https://docs.opencv.org/4.x/db/d47/group__features2d__hal__interface.html >> * Carotene library is turned on here: https://github.com/opencv/opencv/blob/8bbf08f0de9c387c12afefdb05af7780d989e4c3/CMakeLists.txt#L906-L911 > As a test outside of this PR, A 3rdparty component called ndsrvp is created, containing one of the non-dnn code (integral_SIMD), and it works very well. > All the non-dnn code in this PR have been removed, currently this PR can be focused on dnn optinizations. > This HAL mechanism is quite suitable for rvp optimizations, all the non-dnn code is expected to be moved into ndsrvp soon. ### Progress #### Part 1 (This PR) - [Core](https://docs.opencv.org/4.x/d1/d1b/group__core__hal__interface.html) - [x] Element-wise add and subtract - [x] Element-wise minimum or maximum - [x] Element-wise absolute difference - [x] Bitwise logical operations - [x] Element-wise compare - [ImgProc](https://docs.opencv.org/4.x/dd/d8b/group__imgproc__hal__interface.html) - [x] Integral - [x] Threshold - [x] WarpAffine - [x] WarpPerspective - [Features2D](https://docs.opencv.org/4.x/db/d47/group__features2d__hal__interface.html) #### Part 2 (Next PR) **Rough Estimate. Todo List May Change.** - [Core](https://docs.opencv.org/4.x/d1/d1b/group__core__hal__interface.html) - [ImgProc](https://docs.opencv.org/4.x/dd/d8b/group__imgproc__hal__interface.html) - smaller remap HAL interface - AdaptiveThreshold - BoxFilter - Canny - Convert - Filter - GaussianBlur - MedianBlur - Morph - Pyrdown - Resize - Scharr - SepFilter - Sobel - [Features2D](https://docs.opencv.org/4.x/db/d47/group__features2d__hal__interface.html) - FAST ### Performance Tests The optimization does not contain floating point opreations. **Absolute Difference** Geometric mean (ms) |Name of Test|opencv perf core Absdiff|opencv perf core Absdiff|opencv perf core Absdiff vs opencv perf core Absdiff (x-factor)| |---|:-:|:-:|:-:| |Absdiff::OCL_AbsDiffFixture::(640x480, 8UC1)|23.104|5.972|3.87| |Absdiff::OCL_AbsDiffFixture::(640x480, 32FC1)|39.500|40.830|0.97| |Absdiff::OCL_AbsDiffFixture::(640x480, 8UC3)|69.155|15.051|4.59| |Absdiff::OCL_AbsDiffFixture::(640x480, 32FC3)|118.715|120.509|0.99| |Absdiff::OCL_AbsDiffFixture::(640x480, 8UC4)|93.001|19.770|4.70| |Absdiff::OCL_AbsDiffFixture::(640x480, 32FC4)|161.136|160.791|1.00| |Absdiff::OCL_AbsDiffFixture::(1280x720, 8UC1)|69.211|15.140|4.57| |Absdiff::OCL_AbsDiffFixture::(1280x720, 32FC1)|118.762|119.263|1.00| |Absdiff::OCL_AbsDiffFixture::(1280x720, 8UC3)|212.414|44.692|4.75| |Absdiff::OCL_AbsDiffFixture::(1280x720, 32FC3)|367.512|366.569|1.00| |Absdiff::OCL_AbsDiffFixture::(1280x720, 8UC4)|285.337|59.708|4.78| |Absdiff::OCL_AbsDiffFixture::(1280x720, 32FC4)|490.395|491.118|1.00| |Absdiff::OCL_AbsDiffFixture::(1920x1080, 8UC1)|158.827|33.462|4.75| |Absdiff::OCL_AbsDiffFixture::(1920x1080, 32FC1)|273.503|273.668|1.00| |Absdiff::OCL_AbsDiffFixture::(1920x1080, 8UC3)|484.175|100.520|4.82| |Absdiff::OCL_AbsDiffFixture::(1920x1080, 32FC3)|828.758|829.689|1.00| |Absdiff::OCL_AbsDiffFixture::(1920x1080, 8UC4)|648.592|137.195|4.73| |Absdiff::OCL_AbsDiffFixture::(1920x1080, 32FC4)|1116.755|1109.587|1.01| |Absdiff::OCL_AbsDiffFixture::(3840x2160, 8UC1)|648.715|134.875|4.81| |Absdiff::OCL_AbsDiffFixture::(3840x2160, 32FC1)|1115.939|1113.818|1.00| |Absdiff::OCL_AbsDiffFixture::(3840x2160, 8UC3)|1944.791|413.420|4.70| |Absdiff::OCL_AbsDiffFixture::(3840x2160, 32FC3)|3354.193|3324.672|1.01| |Absdiff::OCL_AbsDiffFixture::(3840x2160, 8UC4)|2594.585|553.486|4.69| |Absdiff::OCL_AbsDiffFixture::(3840x2160, 32FC4)|4473.543|4438.453|1.01| **Bitwise Operation** Geometric mean (ms) |Name of Test|opencv perf core Bit|opencv perf core Bit|opencv perf core Bit vs opencv perf core Bit (x-factor)| |---|:-:|:-:|:-:| |Bitwise_and::OCL_BitwiseAndFixture::(640x480, 8UC1)|22.542|4.971|4.53| |Bitwise_and::OCL_BitwiseAndFixture::(640x480, 32FC1)|90.210|19.917|4.53| |Bitwise_and::OCL_BitwiseAndFixture::(640x480, 8UC3)|68.429|15.037|4.55| |Bitwise_and::OCL_BitwiseAndFixture::(640x480, 32FC3)|280.168|59.239|4.73| |Bitwise_and::OCL_BitwiseAndFixture::(640x480, 8UC4)|90.565|19.735|4.59| |Bitwise_and::OCL_BitwiseAndFixture::(640x480, 32FC4)|374.695|79.257|4.73| |Bitwise_and::OCL_BitwiseAndFixture::(1280x720, 8UC1)|67.824|14.873|4.56| |Bitwise_and::OCL_BitwiseAndFixture::(1280x720, 32FC1)|279.514|59.232|4.72| |Bitwise_and::OCL_BitwiseAndFixture::(1280x720, 8UC3)|208.337|44.234|4.71| |Bitwise_and::OCL_BitwiseAndFixture::(1280x720, 32FC3)|851.211|182.522|4.66| |Bitwise_and::OCL_BitwiseAndFixture::(1280x720, 8UC4)|279.529|59.095|4.73| |Bitwise_and::OCL_BitwiseAndFixture::(1280x720, 32FC4)|1132.065|244.877|4.62| |Bitwise_and::OCL_BitwiseAndFixture::(1920x1080, 8UC1)|155.685|33.078|4.71| |Bitwise_and::OCL_BitwiseAndFixture::(1920x1080, 32FC1)|635.253|137.482|4.62| |Bitwise_and::OCL_BitwiseAndFixture::(1920x1080, 8UC3)|474.494|100.166|4.74| |Bitwise_and::OCL_BitwiseAndFixture::(1920x1080, 32FC3)|1907.340|412.841|4.62| |Bitwise_and::OCL_BitwiseAndFixture::(1920x1080, 8UC4)|635.538|134.544|4.72| |Bitwise_and::OCL_BitwiseAndFixture::(1920x1080, 32FC4)|2552.666|556.397|4.59| |Bitwise_and::OCL_BitwiseAndFixture::(3840x2160, 8UC1)|634.736|136.355|4.66| |Bitwise_and::OCL_BitwiseAndFixture::(3840x2160, 32FC1)|2548.283|561.827|4.54| |Bitwise_and::OCL_BitwiseAndFixture::(3840x2160, 8UC3)|1911.454|421.571|4.53| |Bitwise_and::OCL_BitwiseAndFixture::(3840x2160, 32FC3)|7663.803|1677.289|4.57| |Bitwise_and::OCL_BitwiseAndFixture::(3840x2160, 8UC4)|2543.983|562.780|4.52| |Bitwise_and::OCL_BitwiseAndFixture::(3840x2160, 32FC4)|10211.693|2237.393|4.56| |Bitwise_not::OCL_BitwiseNotFixture::(640x480, 8UC1)|22.341|4.811|4.64| |Bitwise_not::OCL_BitwiseNotFixture::(640x480, 32FC1)|89.975|19.288|4.66| |Bitwise_not::OCL_BitwiseNotFixture::(640x480, 8UC3)|67.237|14.643|4.59| |Bitwise_not::OCL_BitwiseNotFixture::(640x480, 32FC3)|276.324|58.609|4.71| |Bitwise_not::OCL_BitwiseNotFixture::(640x480, 8UC4)|89.587|19.554|4.58| |Bitwise_not::OCL_BitwiseNotFixture::(640x480, 32FC4)|370.986|77.136|4.81| |Bitwise_not::OCL_BitwiseNotFixture::(1280x720, 8UC1)|67.227|14.541|4.62| |Bitwise_not::OCL_BitwiseNotFixture::(1280x720, 32FC1)|276.357|58.076|4.76| |Bitwise_not::OCL_BitwiseNotFixture::(1280x720, 8UC3)|206.752|43.376|4.77| |Bitwise_not::OCL_BitwiseNotFixture::(1280x720, 32FC3)|841.638|177.787|4.73| |Bitwise_not::OCL_BitwiseNotFixture::(1280x720, 8UC4)|276.773|57.784|4.79| |Bitwise_not::OCL_BitwiseNotFixture::(1280x720, 32FC4)|1127.740|237.472|4.75| |Bitwise_not::OCL_BitwiseNotFixture::(1920x1080, 8UC1)|153.808|32.531|4.73| |Bitwise_not::OCL_BitwiseNotFixture::(1920x1080, 32FC1)|627.765|129.990|4.83| |Bitwise_not::OCL_BitwiseNotFixture::(1920x1080, 8UC3)|469.799|98.249|4.78| |Bitwise_not::OCL_BitwiseNotFixture::(1920x1080, 32FC3)|1893.591|403.694|4.69| |Bitwise_not::OCL_BitwiseNotFixture::(1920x1080, 8UC4)|627.724|129.962|4.83| |Bitwise_not::OCL_BitwiseNotFixture::(1920x1080, 32FC4)|2529.967|540.744|4.68| |Bitwise_not::OCL_BitwiseNotFixture::(3840x2160, 8UC1)|628.089|130.277|4.82| |Bitwise_not::OCL_BitwiseNotFixture::(3840x2160, 32FC1)|2521.817|540.146|4.67| |Bitwise_not::OCL_BitwiseNotFixture::(3840x2160, 8UC3)|1905.004|404.704|4.71| |Bitwise_not::OCL_BitwiseNotFixture::(3840x2160, 32FC3)|7567.971|1627.898|4.65| |Bitwise_not::OCL_BitwiseNotFixture::(3840x2160, 8UC4)|2531.476|540.181|4.69| |Bitwise_not::OCL_BitwiseNotFixture::(3840x2160, 32FC4)|10075.594|2181.654|4.62| |Bitwise_or::OCL_BitwiseOrFixture::(640x480, 8UC1)|22.566|5.076|4.45| |Bitwise_or::OCL_BitwiseOrFixture::(640x480, 32FC1)|90.391|19.928|4.54| |Bitwise_or::OCL_BitwiseOrFixture::(640x480, 8UC3)|67.758|14.740|4.60| |Bitwise_or::OCL_BitwiseOrFixture::(640x480, 32FC3)|279.253|59.844|4.67| |Bitwise_or::OCL_BitwiseOrFixture::(640x480, 8UC4)|90.296|19.802|4.56| |Bitwise_or::OCL_BitwiseOrFixture::(640x480, 32FC4)|373.972|79.815|4.69| |Bitwise_or::OCL_BitwiseOrFixture::(1280x720, 8UC1)|67.815|14.865|4.56| |Bitwise_or::OCL_BitwiseOrFixture::(1280x720, 32FC1)|279.398|60.054|4.65| |Bitwise_or::OCL_BitwiseOrFixture::(1280x720, 8UC3)|208.643|45.043|4.63| |Bitwise_or::OCL_BitwiseOrFixture::(1280x720, 32FC3)|850.042|180.985|4.70| |Bitwise_or::OCL_BitwiseOrFixture::(1280x720, 8UC4)|279.363|60.385|4.63| |Bitwise_or::OCL_BitwiseOrFixture::(1280x720, 32FC4)|1134.858|243.062|4.67| |Bitwise_or::OCL_BitwiseOrFixture::(1920x1080, 8UC1)|155.212|33.155|4.68| |Bitwise_or::OCL_BitwiseOrFixture::(1920x1080, 32FC1)|634.985|134.911|4.71| |Bitwise_or::OCL_BitwiseOrFixture::(1920x1080, 8UC3)|474.648|100.407|4.73| |Bitwise_or::OCL_BitwiseOrFixture::(1920x1080, 32FC3)|1912.049|414.184|4.62| |Bitwise_or::OCL_BitwiseOrFixture::(1920x1080, 8UC4)|635.252|132.587|4.79| |Bitwise_or::OCL_BitwiseOrFixture::(1920x1080, 32FC4)|2544.471|560.737|4.54| |Bitwise_or::OCL_BitwiseOrFixture::(3840x2160, 8UC1)|634.574|134.966|4.70| |Bitwise_or::OCL_BitwiseOrFixture::(3840x2160, 32FC1)|2545.129|561.498|4.53| |Bitwise_or::OCL_BitwiseOrFixture::(3840x2160, 8UC3)|1910.900|419.365|4.56| |Bitwise_or::OCL_BitwiseOrFixture::(3840x2160, 32FC3)|7662.603|1685.812|4.55| |Bitwise_or::OCL_BitwiseOrFixture::(3840x2160, 8UC4)|2548.971|560.787|4.55| |Bitwise_or::OCL_BitwiseOrFixture::(3840x2160, 32FC4)|10201.407|2237.552|4.56| |Bitwise_xor::OCL_BitwiseXorFixture::(640x480, 8UC1)|22.718|4.961|4.58| |Bitwise_xor::OCL_BitwiseXorFixture::(640x480, 32FC1)|91.496|19.831|4.61| |Bitwise_xor::OCL_BitwiseXorFixture::(640x480, 8UC3)|67.910|15.151|4.48| |Bitwise_xor::OCL_BitwiseXorFixture::(640x480, 32FC3)|279.612|59.792|4.68| |Bitwise_xor::OCL_BitwiseXorFixture::(640x480, 8UC4)|91.073|19.853|4.59| |Bitwise_xor::OCL_BitwiseXorFixture::(640x480, 32FC4)|374.641|79.155|4.73| |Bitwise_xor::OCL_BitwiseXorFixture::(1280x720, 8UC1)|67.704|15.008|4.51| |Bitwise_xor::OCL_BitwiseXorFixture::(1280x720, 32FC1)|279.229|60.088|4.65| |Bitwise_xor::OCL_BitwiseXorFixture::(1280x720, 8UC3)|208.156|44.426|4.69| |Bitwise_xor::OCL_BitwiseXorFixture::(1280x720, 32FC3)|849.501|180.848|4.70| |Bitwise_xor::OCL_BitwiseXorFixture::(1280x720, 8UC4)|279.642|59.728|4.68| |Bitwise_xor::OCL_BitwiseXorFixture::(1280x720, 32FC4)|1129.826|242.880|4.65| |Bitwise_xor::OCL_BitwiseXorFixture::(1920x1080, 8UC1)|155.585|33.354|4.66| |Bitwise_xor::OCL_BitwiseXorFixture::(1920x1080, 32FC1)|634.090|134.995|4.70| |Bitwise_xor::OCL_BitwiseXorFixture::(1920x1080, 8UC3)|474.931|99.598|4.77| |Bitwise_xor::OCL_BitwiseXorFixture::(1920x1080, 32FC3)|1910.519|413.138|4.62| |Bitwise_xor::OCL_BitwiseXorFixture::(1920x1080, 8UC4)|635.026|135.155|4.70| |Bitwise_xor::OCL_BitwiseXorFixture::(1920x1080, 32FC4)|2560.167|560.838|4.56| |Bitwise_xor::OCL_BitwiseXorFixture::(3840x2160, 8UC1)|634.893|134.883|4.71| |Bitwise_xor::OCL_BitwiseXorFixture::(3840x2160, 32FC1)|2548.166|560.831|4.54| |Bitwise_xor::OCL_BitwiseXorFixture::(3840x2160, 8UC3)|1911.392|419.816|4.55| |Bitwise_xor::OCL_BitwiseXorFixture::(3840x2160, 32FC3)|7646.634|1677.988|4.56| |Bitwise_xor::OCL_BitwiseXorFixture::(3840x2160, 8UC4)|2560.637|560.805|4.57| |Bitwise_xor::OCL_BitwiseXorFixture::(3840x2160, 32FC4)|10227.044|2249.458|4.55| ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- 3rdparty/ndsrvp/CMakeLists.txt | 34 ++ 3rdparty/ndsrvp/include/core.hpp | 532 ++++++++++++++++++ 3rdparty/ndsrvp/include/features2d.hpp | 8 + 3rdparty/ndsrvp/include/imgproc.hpp | 71 +++ 3rdparty/ndsrvp/ndsrvp_hal.hpp | 15 + 3rdparty/ndsrvp/src/integral.cpp | 210 +++++++ 3rdparty/ndsrvp/src/threshold.cpp | 177 ++++++ 3rdparty/ndsrvp/src/warpAffine.cpp | 153 +++++ 3rdparty/ndsrvp/src/warpPerspective.cpp | 159 ++++++ CMakeLists.txt | 17 + .../linux/riscv64-andes-gcc.toolchain.cmake | 15 + 11 files changed, 1391 insertions(+) create mode 100644 3rdparty/ndsrvp/CMakeLists.txt create mode 100644 3rdparty/ndsrvp/include/core.hpp create mode 100644 3rdparty/ndsrvp/include/features2d.hpp create mode 100644 3rdparty/ndsrvp/include/imgproc.hpp create mode 100644 3rdparty/ndsrvp/ndsrvp_hal.hpp create mode 100644 3rdparty/ndsrvp/src/integral.cpp create mode 100644 3rdparty/ndsrvp/src/threshold.cpp create mode 100644 3rdparty/ndsrvp/src/warpAffine.cpp create mode 100644 3rdparty/ndsrvp/src/warpPerspective.cpp diff --git a/3rdparty/ndsrvp/CMakeLists.txt b/3rdparty/ndsrvp/CMakeLists.txt new file mode 100644 index 000000000000..bc9a3a26dc8e --- /dev/null +++ b/3rdparty/ndsrvp/CMakeLists.txt @@ -0,0 +1,34 @@ +message(STATUS "##########") +message(STATUS "# NDSRVP #") +message(STATUS "##########") + +cmake_minimum_required(VERSION ${MIN_VER_CMAKE} FATAL_ERROR) + +# project setup + +set(NDSRVP_INCLUDE_DIR include) +set(NDSRVP_SOURCE_DIR src) + +file(GLOB ndsrvp_headers RELATIVE "${CMAKE_CURRENT_LIST_DIR}" "${NDSRVP_INCLUDE_DIR}/*.hpp") +file(GLOB ndsrvp_sources RELATIVE "${CMAKE_CURRENT_LIST_DIR}" "${NDSRVP_SOURCE_DIR}/*.cpp") + +add_library(ndsrvp_hal STATIC) +target_sources(ndsrvp_hal PRIVATE ${ndsrvp_headers} ${ndsrvp_sources}) + +set_target_properties(ndsrvp_hal PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH}) +if(NOT BUILD_SHARED_LIBS) + ocv_install_target(ndsrvp_hal EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) +endif() +target_include_directories(ndsrvp_hal PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/modules/core/include + ${CMAKE_SOURCE_DIR}/modules/imgproc/include + ${CMAKE_SOURCE_DIR}/modules/features2d/include) + +# project info + +set(NDSRVP_HAL_FOUND TRUE CACHE INTERNAL "") +set(NDSRVP_HAL_VERSION "0.0.1" CACHE INTERNAL "") +set(NDSRVP_HAL_LIBRARIES "ndsrvp_hal" CACHE INTERNAL "") +set(NDSRVP_HAL_HEADERS "ndsrvp_hal.hpp" CACHE INTERNAL "") +set(NDSRVP_HAL_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "") diff --git a/3rdparty/ndsrvp/include/core.hpp b/3rdparty/ndsrvp/include/core.hpp new file mode 100644 index 000000000000..190a1b926b60 --- /dev/null +++ b/3rdparty/ndsrvp/include/core.hpp @@ -0,0 +1,532 @@ +// 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. + +#ifndef OPENCV_NDSRVP_CORE_HPP +#define OPENCV_NDSRVP_CORE_HPP + +namespace cv { + +namespace ndsrvp { + +template typename operators_t, + typename... params_t> +int elemwise_binop(const srctype* src1_data, size_t src1_step, + const srctype* src2_data, size_t src2_step, + dsttype* dst_data, size_t dst_step, + int width, int height, params_t... params) +{ + src1_step /= sizeof(srctype); + src2_step /= sizeof(srctype); + dst_step /= sizeof(dsttype); + + operators_t operators; + + int i, j; + for (i = 0; i < height; ++i) { + const srctype* src1_row = src1_data + (src1_step * i); + const srctype* src2_row = src2_data + (src2_step * i); + dsttype* dst_row = dst_data + (dst_step * i); + + j = 0; + for (; j + nlane <= width; j += nlane) { + register vsrctype vs1 = *(vsrctype*)(src1_row + j); + register vsrctype vs2 = *(vsrctype*)(src2_row + j); + + *(vdsttype*)(dst_row + j) = operators.vector(vs1, vs2, params...); + } + for (; j < width; j++) + dst_row[j] = operators.scalar(src1_row[j], src2_row[j], params...); + } + + return CV_HAL_ERROR_OK; +} + +template typename operators_t, + typename... params_t> +int elemwise_unop(const srctype* src_data, size_t src_step, + dsttype* dst_data, size_t dst_step, + int width, int height, params_t... params) +{ + src_step /= sizeof(srctype); + dst_step /= sizeof(dsttype); + + operators_t operators; + + int i, j; + for (i = 0; i < height; ++i) { + const srctype* src_row = src_data + (src_step * i); + dsttype* dst_row = dst_data + (dst_step * i); + + j = 0; + for (; j + nlane <= width; j += nlane) { + register vsrctype vs = *(vsrctype*)(src_row + j); + + *(vdsttype*)(dst_row + j) = operators.vector(vs, params...); + } + for (; j < width; j++) + dst_row[j] = operators.scalar(src_row[j], params...); + } + + return CV_HAL_ERROR_OK; +} + +// ################ add ################ + +template +struct operators_add_t { + inline uint8x8_t vector(uint8x8_t a, uint8x8_t b) { return __nds__v_ukadd8(a, b); } + inline uchar scalar(uchar a, uchar b) { return __nds__ukadd8(a, b); } + + inline int8x8_t vector(int8x8_t a, int8x8_t b) { return __nds__v_kadd8(a, b); } + inline schar scalar(schar a, schar b) { return __nds__kadd8(a, b); } + + inline uint16x4_t vector(uint16x4_t a, uint16x4_t b) { return __nds__v_ukadd16(a, b); } + inline ushort scalar(ushort a, ushort b) { return __nds__ukadd16(a, b); } + + inline int16x4_t vector(int16x4_t a, int16x4_t b) { return __nds__v_kadd16(a, b); } + inline short scalar(short a, short b) { return __nds__kadd16(a, b); } + + inline int32x2_t vector(int32x2_t a, int32x2_t b) { return __nds__v_kadd32(a, b); } + inline int scalar(int a, int b) { return __nds__kadd32(a, b); } +}; + +#undef cv_hal_add8u +#define cv_hal_add8u (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_add8s +#define cv_hal_add8s (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_add16u +#define cv_hal_add16u (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_add16s +#define cv_hal_add16s (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_add32s +#define cv_hal_add32s (cv::ndsrvp::elemwise_binop) + +// ################ sub ################ + +template +struct operators_sub_t { + inline uint8x8_t vector(uint8x8_t a, uint8x8_t b) { return __nds__v_uksub8(a, b); } + inline uchar scalar(uchar a, uchar b) { return __nds__uksub8(a, b); } + + inline int8x8_t vector(int8x8_t a, int8x8_t b) { return __nds__v_ksub8(a, b); } + inline schar scalar(schar a, schar b) { return __nds__ksub8(a, b); } + + inline uint16x4_t vector(uint16x4_t a, uint16x4_t b) { return __nds__v_uksub16(a, b); } + inline ushort scalar(ushort a, ushort b) { return __nds__uksub16(a, b); } + + inline int16x4_t vector(int16x4_t a, int16x4_t b) { return __nds__v_ksub16(a, b); } + inline short scalar(short a, short b) { return __nds__ksub16(a, b); } + + inline int32x2_t vector(int32x2_t a, int32x2_t b) { return __nds__v_ksub32(a, b); } + inline int scalar(int a, int b) { return __nds__ksub32(a, b); } +}; + +#undef cv_hal_sub8u +#define cv_hal_sub8u (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_sub8s +#define cv_hal_sub8s (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_sub16u +#define cv_hal_sub16u (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_sub16s +#define cv_hal_sub16s (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_sub32s +#define cv_hal_sub32s (cv::ndsrvp::elemwise_binop) + +// ################ max ################ + +template +struct operators_max_t { + inline uint8x8_t vector(uint8x8_t a, uint8x8_t b) { return __nds__v_umax8(a, b); } + inline uchar scalar(uchar a, uchar b) { return __nds__umax8(a, b); } + + inline int8x8_t vector(int8x8_t a, int8x8_t b) { return __nds__v_smax8(a, b); } + inline schar scalar(schar a, schar b) { return __nds__smax8(a, b); } + + inline uint16x4_t vector(uint16x4_t a, uint16x4_t b) { return __nds__v_umax16(a, b); } + inline ushort scalar(ushort a, ushort b) { return __nds__umax16(a, b); } + + inline int16x4_t vector(int16x4_t a, int16x4_t b) { return __nds__v_smax16(a, b); } + inline short scalar(short a, short b) { return __nds__smax16(a, b); } + + inline int32x2_t vector(int32x2_t a, int32x2_t b) { return __nds__v_smax32(a, b); } + inline int scalar(int a, int b) { return __nds__smax32(a, b); } +}; + +#undef cv_hal_max8u +#define cv_hal_max8u (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_max8s +#define cv_hal_max8s (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_max16u +#define cv_hal_max16u (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_max16s +#define cv_hal_max16s (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_max32s +#define cv_hal_max32s (cv::ndsrvp::elemwise_binop) + +// ################ min ################ + +template +struct operators_min_t { + inline uint8x8_t vector(uint8x8_t a, uint8x8_t b) { return __nds__v_umin8(a, b); } + inline uchar scalar(uchar a, uchar b) { return __nds__umin8(a, b); } + + inline int8x8_t vector(int8x8_t a, int8x8_t b) { return __nds__v_smin8(a, b); } + inline schar scalar(schar a, schar b) { return __nds__smin8(a, b); } + + inline uint16x4_t vector(uint16x4_t a, uint16x4_t b) { return __nds__v_umin16(a, b); } + inline ushort scalar(ushort a, ushort b) { return __nds__umin16(a, b); } + + inline int16x4_t vector(int16x4_t a, int16x4_t b) { return __nds__v_smin16(a, b); } + inline short scalar(short a, short b) { return __nds__smin16(a, b); } + + inline int32x2_t vector(int32x2_t a, int32x2_t b) { return __nds__v_smin32(a, b); } + inline int scalar(int a, int b) { return __nds__smin32(a, b); } +}; + +#undef cv_hal_min8u +#define cv_hal_min8u (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_min8s +#define cv_hal_min8s (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_min16u +#define cv_hal_min16u (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_min16s +#define cv_hal_min16s (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_min32s +#define cv_hal_min32s (cv::ndsrvp::elemwise_binop) + +// ################ absdiff ################ + +template +struct operators_absdiff_t { + inline uint8x8_t vector(uint8x8_t a, uint8x8_t b) { return __nds__v_uksub8(__nds__v_umax8(a, b), __nds__v_umin8(a, b)); } + inline uchar scalar(uchar a, uchar b) { return __nds__uksub8(__nds__umax8(a, b), __nds__umin8(a, b)); } + + inline int8x8_t vector(int8x8_t a, int8x8_t b) { return __nds__v_ksub8(__nds__v_smax8(a, b), __nds__v_smin8(a, b)); } + inline schar scalar(schar a, schar b) { return __nds__ksub8(__nds__smax8(a, b), __nds__smin8(a, b)); } + + inline uint16x4_t vector(uint16x4_t a, uint16x4_t b) { return __nds__v_uksub16(__nds__v_umax16(a, b), __nds__v_umin16(a, b)); } + inline ushort scalar(ushort a, ushort b) { return __nds__uksub16(__nds__umax16(a, b), __nds__umin16(a, b)); } + + inline int16x4_t vector(int16x4_t a, int16x4_t b) { return __nds__v_ksub16(__nds__v_smax16(a, b), __nds__v_smin16(a, b)); } + inline short scalar(short a, short b) { return __nds__ksub16(__nds__smax16(a, b), __nds__smin16(a, b)); } + + inline int32x2_t vector(int32x2_t a, int32x2_t b) { return __nds__v_ksub32(__nds__v_smax32(a, b), __nds__v_smin32(a, b)); } + inline int scalar(int a, int b) { return __nds__ksub32(__nds__smax32(a, b), __nds__smin32(a, b)); } +}; + +#undef cv_hal_absdiff8u +#define cv_hal_absdiff8u (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_absdiff8s +#define cv_hal_absdiff8s (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_absdiff16u +#define cv_hal_absdiff16u (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_absdiff16s +#define cv_hal_absdiff16s (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_absdiff32s +#define cv_hal_absdiff32s (cv::ndsrvp::elemwise_binop) + +// ################ bitwise ################ + +template +struct operators_and_t { + inline uint8x8_t vector(uint8x8_t a, uint8x8_t b) { return a & b; } + inline uchar scalar(uchar a, uchar b) { return a & b; } +}; + +#undef cv_hal_and8u +#define cv_hal_and8u (cv::ndsrvp::elemwise_binop) + +template +struct operators_or_t { + inline uint8x8_t vector(uint8x8_t a, uint8x8_t b) { return a | b; } + inline uchar scalar(uchar a, uchar b) { return a | b; } +}; + +#undef cv_hal_or8u +#define cv_hal_or8u (cv::ndsrvp::elemwise_binop) + +template +struct operators_xor_t { + inline uint8x8_t vector(uint8x8_t a, uint8x8_t b) { return a ^ b; } + inline uchar scalar(uchar a, uchar b) { return a ^ b; } +}; + +#undef cv_hal_xor8u +#define cv_hal_xor8u (cv::ndsrvp::elemwise_binop) + +template +struct operators_not_t { + inline uint8x8_t vector(uint8x8_t a) { return ~a; } + inline uchar scalar(uchar a) { return ~a; } +}; + +#undef cv_hal_not8u +#define cv_hal_not8u (cv::ndsrvp::elemwise_unop) + +// ################ cmp ################ + +template +struct operators_cmp_t { + inline uint8x8_t vector(uint8x8_t a, uint8x8_t b, int operation) + { + switch (operation) { + case CV_HAL_CMP_EQ: + return __nds__v_ucmpeq8(a, b); + case CV_HAL_CMP_GT: + return __nds__v_ucmplt8(b, a); + case CV_HAL_CMP_GE: + return __nds__v_ucmple8(b, a); + case CV_HAL_CMP_LT: + return __nds__v_ucmplt8(a, b); + case CV_HAL_CMP_LE: + return __nds__v_ucmple8(a, b); + case CV_HAL_CMP_NE: + return ~__nds__v_ucmpeq8(a, b); + default: + return uint8x8_t(); + } + } + inline uchar scalar(uchar a, uchar b, int operation) + { + switch (operation) { + case CV_HAL_CMP_EQ: + return __nds__cmpeq8(a, b); + case CV_HAL_CMP_GT: + return __nds__ucmplt8(b, a); + case CV_HAL_CMP_GE: + return __nds__ucmple8(b, a); + case CV_HAL_CMP_LT: + return __nds__ucmplt8(a, b); + case CV_HAL_CMP_LE: + return __nds__ucmple8(a, b); + case CV_HAL_CMP_NE: + return ~__nds__cmpeq8(a, b); + default: + return 0; + } + } + + inline uint8x8_t vector(int8x8_t a, int8x8_t b, int operation) + { + switch (operation) { + case CV_HAL_CMP_EQ: + return __nds__v_scmpeq8(a, b); + case CV_HAL_CMP_GT: + return __nds__v_scmplt8(b, a); + case CV_HAL_CMP_GE: + return __nds__v_scmple8(b, a); + case CV_HAL_CMP_LT: + return __nds__v_scmplt8(a, b); + case CV_HAL_CMP_LE: + return __nds__v_scmple8(a, b); + case CV_HAL_CMP_NE: + return ~__nds__v_scmpeq8(a, b); + default: + return uint8x8_t(); + } + } + inline uchar scalar(schar a, schar b, int operation) + { + switch (operation) { + case CV_HAL_CMP_EQ: + return __nds__cmpeq8(a, b); + case CV_HAL_CMP_GT: + return __nds__scmplt8(b, a); + case CV_HAL_CMP_GE: + return __nds__scmple8(b, a); + case CV_HAL_CMP_LT: + return __nds__scmplt8(a, b); + case CV_HAL_CMP_LE: + return __nds__scmple8(a, b); + case CV_HAL_CMP_NE: + return ~__nds__cmpeq8(a, b); + default: + return 0; + } + } + + inline uint8x4_t vector(uint16x4_t a, uint16x4_t b, int operation) + { + register unsigned long cmp; + switch (operation) { + case CV_HAL_CMP_EQ: + cmp = (unsigned long)__nds__v_ucmpeq16(a, b) >> 8; + break; + case CV_HAL_CMP_GT: + cmp = (unsigned long)__nds__v_ucmplt16(b, a) >> 8; + break; + case CV_HAL_CMP_GE: + cmp = (unsigned long)__nds__v_ucmple16(b, a) >> 8; + break; + case CV_HAL_CMP_LT: + cmp = (unsigned long)__nds__v_ucmplt16(a, b) >> 8; + break; + case CV_HAL_CMP_LE: + cmp = (unsigned long)__nds__v_ucmple16(a, b) >> 8; + break; + case CV_HAL_CMP_NE: + cmp = ~(unsigned long)__nds__v_ucmpeq16(a, b) >> 8; + break; + default: + return uint8x4_t(); + } + return (uint8x4_t)(unsigned int)__nds__pkbb16(cmp >> 32, cmp); + } + inline uchar scalar(ushort a, ushort b, int operation) + { + switch (operation) { + case CV_HAL_CMP_EQ: + return __nds__cmpeq16(a, b); + case CV_HAL_CMP_GT: + return __nds__ucmplt16(b, a); + case CV_HAL_CMP_GE: + return __nds__ucmple16(b, a); + case CV_HAL_CMP_LT: + return __nds__ucmplt16(a, b); + case CV_HAL_CMP_LE: + return __nds__ucmple16(a, b); + case CV_HAL_CMP_NE: + return ~__nds__cmpeq16(a, b); + default: + return 0; + } + } + + inline uint8x4_t vector(int16x4_t a, int16x4_t b, int operation) + { + register unsigned long cmp; + switch (operation) { + case CV_HAL_CMP_EQ: + cmp = (unsigned long)__nds__v_scmpeq16(a, b) >> 8; + break; + case CV_HAL_CMP_GT: + cmp = (unsigned long)__nds__v_scmplt16(b, a) >> 8; + break; + case CV_HAL_CMP_GE: + cmp = (unsigned long)__nds__v_scmple16(b, a) >> 8; + break; + case CV_HAL_CMP_LT: + cmp = (unsigned long)__nds__v_scmplt16(a, b) >> 8; + break; + case CV_HAL_CMP_LE: + cmp = (unsigned long)__nds__v_scmple16(a, b) >> 8; + break; + case CV_HAL_CMP_NE: + cmp = ~(unsigned long)__nds__v_scmpeq16(a, b) >> 8; + break; + default: + return uint8x4_t(); + } + return (uint8x4_t)(unsigned int)__nds__pkbb16(cmp >> 32, cmp); + } + inline uchar scalar(short a, short b, int operation) + { + switch (operation) { + case CV_HAL_CMP_EQ: + return __nds__cmpeq16(a, b); + case CV_HAL_CMP_GT: + return __nds__scmplt16(b, a); + case CV_HAL_CMP_GE: + return __nds__scmple16(b, a); + case CV_HAL_CMP_LT: + return __nds__scmplt16(a, b); + case CV_HAL_CMP_LE: + return __nds__scmple16(a, b); + case CV_HAL_CMP_NE: + return ~__nds__cmpeq16(a, b); + default: + return 0; + } + } +}; + +#undef cv_hal_cmp8u +#define cv_hal_cmp8u (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_cmp8s +#define cv_hal_cmp8s (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_cmp16u +#define cv_hal_cmp16u (cv::ndsrvp::elemwise_binop) + +#undef cv_hal_cmp16s +#define cv_hal_cmp16s (cv::ndsrvp::elemwise_binop) + +// ################ split ################ + +/*template +int split(const srctype* src_data, srctype** dst_data, int len, int cn) +{ + int i, j; + for (i = 0; i < len; i++) { + for (j = 0; j < cn; j++) { + dst_data[j][i] = src_data[i * cn + j]; + } + } + + return CV_HAL_ERROR_OK; +} + +#undef cv_hal_split8u +#define cv_hal_split8u (cv::ndsrvp::split) + +#undef cv_hal_split16u +#define cv_hal_split16u (cv::ndsrvp::split) + +#undef cv_hal_split32s +#define cv_hal_split32s (cv::ndsrvp::split)*/ + +// ################ merge ################ + +/*template +int merge(const srctype** src_data, srctype* dst_data, int len, int cn) +{ + int i, j; + for (i = 0; i < len; i++) { + for (j = 0; j < cn; j++) { + dst_data[i * cn + j] = src_data[j][i]; + } + } + + return CV_HAL_ERROR_OK; +} + +#undef cv_hal_merge8u +#define cv_hal_merge8u (cv::ndsrvp::merge) + +#undef cv_hal_merge16u +#define cv_hal_merge16u (cv::ndsrvp::merge) + +#undef cv_hal_merge32s +#define cv_hal_merge32s (cv::ndsrvp::merge)*/ + +} // namespace ndsrvp + +} // namespace cv + +#endif diff --git a/3rdparty/ndsrvp/include/features2d.hpp b/3rdparty/ndsrvp/include/features2d.hpp new file mode 100644 index 000000000000..1f6180a7958f --- /dev/null +++ b/3rdparty/ndsrvp/include/features2d.hpp @@ -0,0 +1,8 @@ +// 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. + +#ifndef OPENCV_NDSRVP_FEATURES2D_HPP +#define OPENCV_NDSRVP_FEATURES2D_HPP + +#endif diff --git a/3rdparty/ndsrvp/include/imgproc.hpp b/3rdparty/ndsrvp/include/imgproc.hpp new file mode 100644 index 000000000000..3a572172a831 --- /dev/null +++ b/3rdparty/ndsrvp/include/imgproc.hpp @@ -0,0 +1,71 @@ +// 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. + +#ifndef OPENCV_NDSRVP_IMGPROC_HPP +#define OPENCV_NDSRVP_IMGPROC_HPP + +namespace cv { + +// ################ remap ################ + +void remap(InputArray _src, OutputArray _dst, + InputArray _map1, InputArray _map2, + int interpolation, int borderType, const Scalar& borderValue); + +namespace ndsrvp { + +enum InterpolationMasks { + INTER_BITS = 5, + INTER_BITS2 = INTER_BITS * 2, + INTER_TAB_SIZE = 1 << INTER_BITS, + INTER_TAB_SIZE2 = INTER_TAB_SIZE * INTER_TAB_SIZE +}; + +// ################ integral ################ + +int integral(int depth, int sdepth, int sqdepth, + const uchar* src, size_t _srcstep, + uchar* sum, size_t _sumstep, + uchar* sqsum, size_t, + uchar* tilted, size_t, + int width, int height, int cn); + +#undef cv_hal_integral +#define cv_hal_integral (cv::ndsrvp::integral) + +// ################ warpAffine ################ + +int warpAffine(int src_type, + const uchar* src_data, size_t src_step, int src_width, int src_height, + uchar* dst_data, size_t dst_step, int dst_width, int dst_height, + const double M[6], int interpolation, int borderType, const double borderValue[4]); + +#undef cv_hal_warpAffine +#define cv_hal_warpAffine (cv::ndsrvp::warpAffine) + +// ################ warpPerspective ################ + +int warpPerspective(int src_type, + const uchar* src_data, size_t src_step, int src_width, int src_height, + uchar* dst_data, size_t dst_step, int dst_width, int dst_height, + const double M[9], int interpolation, int borderType, const double borderValue[4]); + +#undef cv_hal_warpPerspective +#define cv_hal_warpPerspective (cv::ndsrvp::warpPerspective) + +// ################ threshold ################ + +int threshold(const uchar* src_data, size_t src_step, + uchar* dst_data, size_t dst_step, + int width, int height, int depth, int cn, + double thresh, double maxValue, int thresholdType); + +#undef cv_hal_threshold +#define cv_hal_threshold (cv::ndsrvp::threshold) + +} // namespace ndsrvp + +} // namespace cv + +#endif diff --git a/3rdparty/ndsrvp/ndsrvp_hal.hpp b/3rdparty/ndsrvp/ndsrvp_hal.hpp new file mode 100644 index 000000000000..7f126365205a --- /dev/null +++ b/3rdparty/ndsrvp/ndsrvp_hal.hpp @@ -0,0 +1,15 @@ +// 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. + +#ifndef OPENCV_NDSRVP_HAL_HPP +#define OPENCV_NDSRVP_HAL_HPP + +#include "opencv2/core/mat.hpp" +#include + +#include "include/core.hpp" +#include "include/imgproc.hpp" +#include "include/features2d.hpp" + +#endif diff --git a/3rdparty/ndsrvp/src/integral.cpp b/3rdparty/ndsrvp/src/integral.cpp new file mode 100644 index 000000000000..37030a8d4c95 --- /dev/null +++ b/3rdparty/ndsrvp/src/integral.cpp @@ -0,0 +1,210 @@ +// 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. + +#include "ndsrvp_hal.hpp" + +namespace cv { + +namespace ndsrvp { + +int integral(int depth, int sdepth, int sqdepth, + const uchar* src, size_t _srcstep, + uchar* _sum, size_t _sumstep, + uchar* _sqsum, size_t, + uchar* _tilted, size_t, + int width, int height, int cn) +{ + // 8-bit unsigned integer, 32-bit signed integer only + if (!(depth == CV_8U && sdepth == CV_32S)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + // too small image + if (!(width >> 8 || height >> 8 || cn == 4)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + int* sum = (int*)_sum; + double* sqsum = (double*)_sqsum; + int* tilted = (int*)_tilted; + + if (sqsum || tilted || cn > 4) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + sqdepth = sqdepth; + width *= cn; + + memset(sum, 0, (width + cn) * sizeof(int)); + + if (cn == 1) { + for (int i = 0; i < height; ++i) { + const uchar* src_row = src + _srcstep * i; + int* prev_sum_row = (int*)((uchar*)sum + _sumstep * i) + cn; + int* sum_row = (int*)((uchar*)sum + _sumstep * (i + 1)) + cn; + + sum_row[-1] = 0; + + int32x2_t prev = { 0, 0 }; + int j = 0; + + for (; j + 8 <= width; j += 8) { + unsigned long vs8x8 = *(unsigned long*)(src_row + j); + + unsigned long vs810 = __nds__zunpkd810(vs8x8); + unsigned long vs832 = __nds__zunpkd832(vs8x8); + + int16x4_t vs16x4 = (int16x4_t)__nds__pkbb32(vs832, vs810); + + vs16x4 += (int16x4_t)((unsigned long)vs16x4 << 16); // gcc vector extension + vs16x4 += (int16x4_t)((unsigned long)vs16x4 << 32); // '+' is add16 + + //*(int32x2_t*)(sum_row + j) = (int32x2_t) { vs16x4[0], vs16x4[1] } + *(int32x2_t*)(prev_sum_row + j) + prev; + //*(int32x2_t*)(sum_row + j + 2) = (int32x2_t) { vs16x4[2], vs16x4[3] } + *(int32x2_t*)(prev_sum_row + j + 2) + prev; + // performance loss for unknown reason, commented out, use the following code instead + + sum_row[j] = prev_sum_row[j] + prev[0] + vs16x4[0]; + sum_row[j + 1] = prev_sum_row[j + 1] + prev[1] + vs16x4[1]; + sum_row[j + 2] = prev_sum_row[j + 2] + prev[0] + vs16x4[2]; + sum_row[j + 3] = prev_sum_row[j + 3] + prev[1] + vs16x4[3]; + + prev += vs16x4[3]; // prev += (int32x2_t){vs16x4[3], vs16x4[3]}; + + vs16x4 = (int16x4_t)__nds__pktt32(vs832, vs810); + + vs16x4 += (int16x4_t)((unsigned long)vs16x4 << 16); + vs16x4 += (int16x4_t)((unsigned long)vs16x4 << 32); + + //*(int32x2_t*)(sum_row + j + 4) = (int32x2_t) { vs16x4[0], vs16x4[1] } + *(int32x2_t*)(prev_sum_row + j + 4) + prev; + //*(int32x2_t*)(sum_row + j + 6) = (int32x2_t) { vs16x4[2], vs16x4[3] } + *(int32x2_t*)(prev_sum_row + j + 6) + prev; + // performance loss for unknown reason, commented out, use the following code instead + + sum_row[j + 4] = prev_sum_row[j + 4] + prev[0] + vs16x4[0]; + sum_row[j + 5] = prev_sum_row[j + 5] + prev[1] + vs16x4[1]; + sum_row[j + 6] = prev_sum_row[j + 6] + prev[0] + vs16x4[2]; + sum_row[j + 7] = prev_sum_row[j + 7] + prev[1] + vs16x4[3]; + + prev += vs16x4[3]; + } + + for (int v = sum_row[j - 1] - prev_sum_row[j - 1]; j < width; ++j) + sum_row[j] = (v += src_row[j]) + prev_sum_row[j]; + } + } else if (cn == 2) { + for (int i = 0; i < height; ++i) { + const uchar* src_row = src + _srcstep * i; + int* prev_sum_row = (int*)((uchar*)sum + _sumstep * i) + cn; + int* sum_row = (int*)((uchar*)sum + _sumstep * (i + 1)) + cn; + + sum_row[-1] = sum_row[-2] = 0; + + int32x2_t prev = { 0, 0 }; + int j = 0; + for (; j + 8 <= width; j += 8) { + uint8x8_t vs8x8 = *(uint8x8_t*)(src_row + j); + + uint16x4_t vs16x4_1 = __nds__v_zunpkd820(vs8x8); + uint16x4_t vs16x4_2 = __nds__v_zunpkd831(vs8x8); + + vs16x4_1 += (int16x4_t)((unsigned long)vs16x4_1 << 16); + vs16x4_1 += (int16x4_t)((unsigned long)vs16x4_1 << 32); + + vs16x4_2 += (int16x4_t)((unsigned long)vs16x4_2 << 16); + vs16x4_2 += (int16x4_t)((unsigned long)vs16x4_2 << 32); + + *(int32x2_t*)(sum_row + j) = (int32x2_t) { vs16x4_1[0], vs16x4_2[0] } + *(int32x2_t*)(prev_sum_row + j) + prev; + *(int32x2_t*)(sum_row + j + 2) = (int32x2_t) { vs16x4_1[1], vs16x4_2[1] } + *(int32x2_t*)(prev_sum_row + j + 2) + prev; + *(int32x2_t*)(sum_row + j + 2 * 2) = (int32x2_t) { vs16x4_1[2], vs16x4_2[2] } + *(int32x2_t*)(prev_sum_row + j + 2 * 2) + prev; + *(int32x2_t*)(sum_row + j + 2 * 3) = (int32x2_t) { vs16x4_1[3], vs16x4_2[3] } + *(int32x2_t*)(prev_sum_row + j + 2 * 3) + prev; + + prev += (int32x2_t) { vs16x4_1[3], vs16x4_2[3] }; + } + + for (int v2 = sum_row[j - 1] - prev_sum_row[j - 1], + v1 = sum_row[j - 2] - prev_sum_row[j - 2]; + j < width; j += 2) { + sum_row[j] = (v1 += src_row[j]) + prev_sum_row[j]; + sum_row[j + 1] = (v2 += src_row[j + 1]) + prev_sum_row[j + 1]; + } + } + } else if (cn == 3) { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + /* disabled because of unaligned memory access, difficulty in vectorization, etc. + for (int i = 0; i < height; ++i) { + const uchar* src_row = src + _srcstep * i; + int* prev_sum_row = (int*)((uchar*)sum + _sumstep * i) + cn; + int* sum_row = (int*)((uchar*)sum + _sumstep * (i + 1)) + cn; + + sum_row[-1] = sum_row[-2] = sum_row[-3] = 0; + + int32x2_t prev_ptr[2] = { { 0, 0 }, { 0, 0 } }; + int j = 0; + for (; j + 3 <= width; j += 3) { + //uint8x4_t vs8x4 = *(uint8x4_t*)(src_row + j); + // performance loss for unknown reason, commented out, use the following code instead + + uint8x4_t vs8x4 = (uint8x4_t){ src_row[j], src_row[j + 1], src_row[j + 2], 0}; + + // [ 0 | 2 | 1 | 3 ] + int16x4_t vs16x4 = (int16x4_t)__nds__pkbb32(__nds__zunpkd831((unsigned int)vs8x4), __nds__zunpkd820((unsigned int)vs8x4)); + + // [ b | t | b | t ] + prev_ptr[0] += (int32x2_t)__nds__pkbb16(0, (unsigned long)vs16x4); + prev_ptr[1] += (int32x2_t)__nds__pktt16(0, (unsigned long)vs16x4); + + //*(int32x4_t*)(sum_row + j) = *(int32x4_t*)(prev_sum_row + j) + *(int32x4_t*)prev_ptr; + // performance loss for unknown reason, commented out, use the following code instead + + sum_row[j] = prev_sum_row[j] + prev_ptr[0][0]; + sum_row[j + 1] = prev_sum_row[j + 1] + prev_ptr[0][1]; + sum_row[j + 2] = prev_sum_row[j + 2] + prev_ptr[1][0]; + } + + for (int v3 = sum_row[j - 1] - prev_sum_row[j - 1], + v2 = sum_row[j - 2] - prev_sum_row[j - 2], + v1 = sum_row[j - 3] - prev_sum_row[j - 3]; + j < width; j += 3) { + sum_row[j] = (v1 += src_row[j]) + prev_sum_row[j]; + sum_row[j + 1] = (v2 += src_row[j + 1]) + prev_sum_row[j + 1]; + sum_row[j + 2] = (v3 += src_row[j + 2]) + prev_sum_row[j + 2]; + } + }*/ + } else if (cn == 4) { + for (int i = 0; i < height; ++i) { + const uchar* src_row = src + _srcstep * i; + int* prev_sum_row = (int*)((uchar*)sum + _sumstep * i) + cn; + int* sum_row = (int*)((uchar*)sum + _sumstep * (i + 1)) + cn; + + sum_row[-1] = sum_row[-2] = sum_row[-3] = sum_row[-4] = 0; + + int32x2_t prev_ptr[2] = { { 0, 0 }, { 0, 0 } }; + int j = 0; + for (; j + 4 <= width; j += 4) { + uint8x4_t vs8x4 = *(uint8x4_t*)(src_row + j); + + // [ 0 | 2 | 1 | 3 ] + int16x4_t vs16x4 = (int16x4_t)__nds__pkbb32(__nds__zunpkd831((unsigned int)vs8x4), __nds__zunpkd820((unsigned int)vs8x4)); + + // [ b | t | b | t ] + prev_ptr[0] += (int32x2_t)__nds__pkbb16(0, (unsigned long)vs16x4); + prev_ptr[1] += (int32x2_t)__nds__pktt16(0, (unsigned long)vs16x4); + + *(int32x4_t*)(sum_row + j) = *(int32x4_t*)(prev_sum_row + j) + *(int32x4_t*)prev_ptr; + } + + for (int v4 = sum_row[j - 1] - prev_sum_row[j - 1], + v3 = sum_row[j - 2] - prev_sum_row[j - 2], + v2 = sum_row[j - 3] - prev_sum_row[j - 3], + v1 = sum_row[j - 4] - prev_sum_row[j - 4]; + j < width; j += 4) { + sum_row[j] = (v1 += src_row[j]) + prev_sum_row[j]; + sum_row[j + 1] = (v2 += src_row[j + 1]) + prev_sum_row[j + 1]; + sum_row[j + 2] = (v3 += src_row[j + 2]) + prev_sum_row[j + 2]; + sum_row[j + 3] = (v4 += src_row[j + 3]) + prev_sum_row[j + 3]; + } + } + } + return CV_HAL_ERROR_OK; +} + +} // namespace ndsrvp + +} // namespace cv diff --git a/3rdparty/ndsrvp/src/threshold.cpp b/3rdparty/ndsrvp/src/threshold.cpp new file mode 100644 index 000000000000..06de591feff8 --- /dev/null +++ b/3rdparty/ndsrvp/src/threshold.cpp @@ -0,0 +1,177 @@ +// 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. + +#include "ndsrvp_hal.hpp" +#include "opencv2/imgproc/hal/interface.h" + +namespace cv { + +namespace ndsrvp { + +template +class operators_threshold_t { +public: + virtual ~operators_threshold_t() {}; + virtual inline vtype vector(const vtype& src, const vtype& thresh, const vtype& maxval) + { + (void)src; + (void)thresh; + (void)maxval; + CV_Error(cv::Error::StsBadArg, ""); + return vtype(); + } + virtual inline type scalar(const type& src, const type& thresh, const type& maxval) + { + (void)src; + (void)thresh; + (void)maxval; + CV_Error(cv::Error::StsBadArg, ""); + return type(); + } +}; + +template +class opThreshBinary : public operators_threshold_t { + inline vtype vector(const vtype& src, const vtype& thresh, const vtype& maxval) override + { + return (vtype)__nds__bpick((long)maxval, (long)0, (long)(src > thresh)); + } + inline type scalar(const type& src, const type& thresh, const type& maxval) override + { + return src > thresh ? maxval : 0; + } +}; + +template +class opThreshBinaryInv : public operators_threshold_t { + inline vtype vector(const vtype& src, const vtype& thresh, const vtype& maxval) override + { + return (vtype)__nds__bpick((long)0, (long)maxval, (long)(src > thresh)); + } + inline type scalar(const type& src, const type& thresh, const type& maxval) override + { + return src > thresh ? 0 : maxval; + } +}; + +template +class opThreshTrunc : public operators_threshold_t { + inline vtype vector(const vtype& src, const vtype& thresh, const vtype& maxval) override + { + (void)maxval; + return (vtype)__nds__bpick((long)thresh, (long)src, (long)(src > thresh)); + } + inline type scalar(const type& src, const type& thresh, const type& maxval) override + { + (void)maxval; + return src > thresh ? thresh : src; + } +}; + +template +class opThreshToZero : public operators_threshold_t { + inline vtype vector(const vtype& src, const vtype& thresh, const vtype& maxval) override + { + (void)maxval; + return (vtype)__nds__bpick((long)src, (long)0, (long)(src > thresh)); + } + inline type scalar(const type& src, const type& thresh, const type& maxval) override + { + (void)maxval; + return src > thresh ? src : 0; + } +}; + +template +class opThreshToZeroInv : public operators_threshold_t { + inline vtype vector(const vtype& src, const vtype& thresh, const vtype& maxval) override + { + (void)maxval; + return (vtype)__nds__bpick((long)0, (long)src, (long)(src > thresh)); + } + inline type scalar(const type& src, const type& thresh, const type& maxval) override + { + (void)maxval; + return src > thresh ? 0 : src; + } +}; + +template +static void threshold_op(const type* src_data, size_t src_step, + type* dst_data, size_t dst_step, + int width, int height, int cn, + type thresh, type maxval, int thtype) +{ + int i, j; + width *= cn; + src_step /= sizeof(type); + dst_step /= sizeof(type); + vtype vthresh; + vtype vmaxval; + for (i = 0; i < nlane; i++) { + vthresh[i] = thresh; + vmaxval[i] = maxval; + } + + operators_threshold_t* op; + switch (thtype) { + case CV_HAL_THRESH_BINARY: + op = new opThreshBinary(); + break; + case CV_HAL_THRESH_BINARY_INV: + op = new opThreshBinaryInv(); + break; + case CV_HAL_THRESH_TRUNC: + op = new opThreshTrunc(); + break; + case CV_HAL_THRESH_TOZERO: + op = new opThreshToZero(); + break; + case CV_HAL_THRESH_TOZERO_INV: + op = new opThreshToZeroInv(); + break; + default: + CV_Error(cv::Error::StsBadArg, ""); + return; + } + + for (i = 0; i < height; i++, src_data += src_step, dst_data += dst_step) { + for (j = 0; j <= width - nlane; j += nlane) { + vtype vs = *(vtype*)(src_data + j); + *(vtype*)(dst_data + j) = op->vector(vs, vthresh, vmaxval); + } + for (; j < width; j++) { + dst_data[j] = op->scalar(src_data[j], thresh, maxval); + } + } + + delete op; + return; +} + +int threshold(const uchar* src_data, size_t src_step, + uchar* dst_data, size_t dst_step, + int width, int height, int depth, int cn, + double thresh, double maxValue, int thresholdType) +{ + if (width <= 255 && height <= 255) // slower at small size + return CV_HAL_ERROR_NOT_IMPLEMENTED; + if (depth == CV_8U) { + threshold_op((uchar*)src_data, src_step, (uchar*)dst_data, dst_step, width, height, cn, (uchar)thresh, (uchar)maxValue, thresholdType); + return CV_HAL_ERROR_OK; + } else if (depth == CV_16S) { + threshold_op((short*)src_data, src_step, (short*)dst_data, dst_step, width, height, cn, (short)thresh, (short)maxValue, thresholdType); + return CV_HAL_ERROR_OK; + } else if (depth == CV_16U) { + threshold_op((ushort*)src_data, src_step, (ushort*)dst_data, dst_step, width, height, cn, (ushort)thresh, (ushort)maxValue, thresholdType); + return CV_HAL_ERROR_OK; + } else { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + return CV_HAL_ERROR_NOT_IMPLEMENTED; +} + +} // namespace ndsrvp + +} // namespace cv diff --git a/3rdparty/ndsrvp/src/warpAffine.cpp b/3rdparty/ndsrvp/src/warpAffine.cpp new file mode 100644 index 000000000000..d54e4dc23700 --- /dev/null +++ b/3rdparty/ndsrvp/src/warpAffine.cpp @@ -0,0 +1,153 @@ +// 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. + +#include "ndsrvp_hal.hpp" +#include "opencv2/core.hpp" +#include "opencv2/imgproc/hal/interface.h" + +namespace cv { + +namespace ndsrvp { + +class WarpAffineInvoker : public ParallelLoopBody { +public: + WarpAffineInvoker(const Mat& _src, Mat& _dst, int _interpolation, int _borderType, + const Scalar& _borderValue, int* _adelta, int* _bdelta, const double* _M) + : ParallelLoopBody() + , src(_src) + , dst(_dst) + , interpolation(_interpolation) + , borderType(_borderType) + , borderValue(_borderValue) + , adelta(_adelta) + , bdelta(_bdelta) + , M(_M) + { + } + + virtual void operator()(const Range& range) const CV_OVERRIDE + { + const int BLOCK_SZ = 64; + AutoBuffer __XY(BLOCK_SZ * BLOCK_SZ * 2), __A(BLOCK_SZ * BLOCK_SZ); + short *XY = __XY.data(), *A = __A.data(); + const int AB_BITS = MAX(10, (int)INTER_BITS); + const int AB_SCALE = 1 << AB_BITS; + int round_delta = interpolation == CV_HAL_INTER_NEAREST ? AB_SCALE / 2 : AB_SCALE / INTER_TAB_SIZE / 2, x, y, x1, y1; + + int bh0 = std::min(BLOCK_SZ / 2, dst.rows); + int bw0 = std::min(BLOCK_SZ * BLOCK_SZ / bh0, dst.cols); + bh0 = std::min(BLOCK_SZ * BLOCK_SZ / bw0, dst.rows); + + for (y = range.start; y < range.end; y += bh0) { + for (x = 0; x < dst.cols; x += bw0) { + int bw = std::min(bw0, dst.cols - x); + int bh = std::min(bh0, range.end - y); + + Mat _XY(bh, bw, CV_16SC2, XY); + Mat dpart(dst, Rect(x, y, bw, bh)); + + for (y1 = 0; y1 < bh; y1++) { + short* xy = XY + y1 * bw * 2; + int X0 = saturate_cast((M[1] * (y + y1) + M[2]) * AB_SCALE) + round_delta; + int Y0 = saturate_cast((M[4] * (y + y1) + M[5]) * AB_SCALE) + round_delta; + + if (interpolation == CV_HAL_INTER_NEAREST) { + x1 = 0; + + for (; x1 < bw; x1 += 2) { + int32x2_t vX = { X0 + adelta[x + x1], X0 + adelta[x + x1 + 1] }; + int32x2_t vY = { Y0 + bdelta[x + x1], Y0 + bdelta[x + x1 + 1] }; + + vX = __nds__v_sclip32(__nds__v_sra32(vX, AB_BITS), 15); + vY = __nds__v_sclip32(__nds__v_sra32(vY, AB_BITS), 15); + + *(uint16x4_t*)(xy + x1 * 2) = (uint16x4_t)__nds__pkbb16((unsigned long)vY, (unsigned long)vX); + } + + for (; x1 < bw; x1++) { + int X = (X0 + adelta[x + x1]) >> AB_BITS; + int Y = (Y0 + bdelta[x + x1]) >> AB_BITS; + xy[x1 * 2] = saturate_cast(X); + xy[x1 * 2 + 1] = saturate_cast(Y); + } + } else { + short* alpha = A + y1 * bw; + x1 = 0; + + const int INTER_MASK = INTER_TAB_SIZE - 1; + const uint32x2_t vmask = { INTER_MASK, INTER_MASK }; + for (; x1 < bw; x1 += 2) { + int32x2_t vX = { X0 + adelta[x + x1], X0 + adelta[x + x1 + 1] }; + int32x2_t vY = { Y0 + bdelta[x + x1], Y0 + bdelta[x + x1 + 1] }; + vX = __nds__v_sra32(vX, (AB_BITS - INTER_BITS)); + vY = __nds__v_sra32(vY, (AB_BITS - INTER_BITS)); + + int32x2_t vx = __nds__v_sclip32(__nds__v_sra32(vX, INTER_BITS), 15); + int32x2_t vy = __nds__v_sclip32(__nds__v_sra32(vY, INTER_BITS), 15); + + *(uint16x4_t*)(xy + x1 * 2) = (uint16x4_t)__nds__pkbb16((unsigned long)vy, (unsigned long)vx); + + uint32x2_t valpha = __nds__v_uadd32(__nds__v_sll32((uint32x2_t)(vY & vmask), INTER_BITS), (uint32x2_t)(vX & vmask)); + *(int16x2_t*)(alpha + x1) = (int16x2_t) { (short)(valpha[0]), (short)(valpha[1]) }; + } + + for (; x1 < bw; x1++) { + int X = (X0 + adelta[x + x1]) >> (AB_BITS - INTER_BITS); + int Y = (Y0 + bdelta[x + x1]) >> (AB_BITS - INTER_BITS); + xy[x1 * 2] = saturate_cast(X >> INTER_BITS); + xy[x1 * 2 + 1] = saturate_cast(Y >> INTER_BITS); + alpha[x1] = (short)((Y & (INTER_TAB_SIZE - 1)) * INTER_TAB_SIZE + (X & (INTER_TAB_SIZE - 1))); + } + } + } + + if (interpolation == CV_HAL_INTER_NEAREST) + remap(src, dpart, _XY, Mat(), interpolation, borderType, borderValue); + else { + Mat _matA(bh, bw, CV_16U, A); + remap(src, dpart, _XY, _matA, interpolation, borderType, borderValue); + } + } + } + } + +private: + Mat src; + Mat dst; + int interpolation, borderType; + Scalar borderValue; + int *adelta, *bdelta; + const double* M; +}; + +int warpAffine(int src_type, + const uchar* src_data, size_t src_step, int src_width, int src_height, + uchar* dst_data, size_t dst_step, int dst_width, int dst_height, + const double M[6], int interpolation, int borderType, const double borderValue[4]) +{ + Mat src(Size(src_width, src_height), src_type, const_cast(src_data), src_step); + Mat dst(Size(dst_width, dst_height), src_type, dst_data, dst_step); + + int x; + AutoBuffer _abdelta(dst.cols * 2); + int *adelta = &_abdelta[0], *bdelta = adelta + dst.cols; + const int AB_BITS = MAX(10, (int)INTER_BITS); + const int AB_SCALE = 1 << AB_BITS; + + for (x = 0; x < dst.cols; x++) { + adelta[x] = saturate_cast(M[0] * x * AB_SCALE); + bdelta[x] = saturate_cast(M[3] * x * AB_SCALE); + } + + Range range(0, dst.rows); + WarpAffineInvoker invoker(src, dst, interpolation, borderType, + Scalar(borderValue[0], borderValue[1], borderValue[2], borderValue[3]), + adelta, bdelta, M); + parallel_for_(range, invoker, dst.total() / (double)(1 << 16)); + return CV_HAL_ERROR_OK; +} + +} // namespace ndsrvp + +} // namespace cv diff --git a/3rdparty/ndsrvp/src/warpPerspective.cpp b/3rdparty/ndsrvp/src/warpPerspective.cpp new file mode 100644 index 000000000000..b4fa423ed7ee --- /dev/null +++ b/3rdparty/ndsrvp/src/warpPerspective.cpp @@ -0,0 +1,159 @@ +// 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. + +#include "ndsrvp_hal.hpp" +#include "opencv2/core.hpp" +#include "opencv2/imgproc/hal/interface.h" + +namespace cv { + +namespace ndsrvp { + +class WarpPerspectiveInvoker : public ParallelLoopBody { +public: + WarpPerspectiveInvoker(const Mat& _src, Mat& _dst, const double* _M, int _interpolation, + int _borderType, const Scalar& _borderValue) + : ParallelLoopBody() + , src(_src) + , dst(_dst) + , M(_M) + , interpolation(_interpolation) + , borderType(_borderType) + , borderValue(_borderValue) + { + } + + virtual void operator()(const Range& range) const CV_OVERRIDE + { + const int BLOCK_SZ = 32; + short XY[BLOCK_SZ * BLOCK_SZ * 2], A[BLOCK_SZ * BLOCK_SZ]; + int x, y, y1, width = dst.cols, height = dst.rows; + + int bh0 = std::min(BLOCK_SZ / 2, height); + int bw0 = std::min(BLOCK_SZ * BLOCK_SZ / bh0, width); + bh0 = std::min(BLOCK_SZ * BLOCK_SZ / bw0, height); + + for (y = range.start; y < range.end; y += bh0) { + for (x = 0; x < width; x += bw0) { + int bw = std::min(bw0, width - x); + int bh = std::min(bh0, range.end - y); // height + + Mat _XY(bh, bw, CV_16SC2, XY); + Mat dpart(dst, Rect(x, y, bw, bh)); + + for (y1 = 0; y1 < bh; y1++) { + short* xy = XY + y1 * bw * 2; + double X0 = M[0] * x + M[1] * (y + y1) + M[2]; + double Y0 = M[3] * x + M[4] * (y + y1) + M[5]; + double W0 = M[6] * x + M[7] * (y + y1) + M[8]; + + if (interpolation == CV_HAL_INTER_NEAREST) { + int x1 = 0; + + for (; x1 < bw; x1 += 2) { + double W1 = W0 + M[6] * x1, W2 = W1 + M[6]; + W1 = W1 ? 1. / W1 : 0; + W2 = W2 ? 1. / W2 : 0; + double fX1 = std::max((double)INT_MIN, std::min((double)INT_MAX, (X0 + M[0] * x1) * W1)); + double fX2 = std::max((double)INT_MIN, std::min((double)INT_MAX, (X0 + M[0] * (x1 + 1)) * W2)); + double fY1 = std::max((double)INT_MIN, std::min((double)INT_MAX, (Y0 + M[3] * x1) * W1)); + double fY2 = std::max((double)INT_MIN, std::min((double)INT_MAX, (Y0 + M[3] * (x1 + 1)) * W2)); + + int32x2_t vX = {saturate_cast(fX1), saturate_cast(fX2)}; + int32x2_t vY = {saturate_cast(fY1), saturate_cast(fY2)}; + + vX = __nds__v_sclip32(vX, 15); + vY = __nds__v_sclip32(vY, 15); + + *(uint16x4_t*)(xy + x1 * 2) = (uint16x4_t)__nds__pkbb16((unsigned long)vY, (unsigned long)vX); + } + + for (; x1 < bw; x1++) { + double W = W0 + M[6] * x1; + W = W ? 1. / W : 0; + double fX = std::max((double)INT_MIN, std::min((double)INT_MAX, (X0 + M[0] * x1) * W)); + double fY = std::max((double)INT_MIN, std::min((double)INT_MAX, (Y0 + M[3] * x1) * W)); + int X = saturate_cast(fX); + int Y = saturate_cast(fY); + + xy[x1 * 2] = saturate_cast(X); + xy[x1 * 2 + 1] = saturate_cast(Y); + } + } else { + short* alpha = A + y1 * bw; + int x1 = 0; + + const int INTER_MASK = INTER_TAB_SIZE - 1; + const uint32x2_t vmask = { INTER_MASK, INTER_MASK }; + for (; x1 < bw; x1 += 2) { + double W1 = W0 + M[6] * x1, W2 = W1 + M[6]; + W1 = W1 ? INTER_TAB_SIZE / W1 : 0; + W2 = W2 ? INTER_TAB_SIZE / W2 : 0; + double fX1 = std::max((double)INT_MIN, std::min((double)INT_MAX, (X0 + M[0] * x1) * W1)); + double fX2 = std::max((double)INT_MIN, std::min((double)INT_MAX, (X0 + M[0] * (x1 + 1)) * W2)); + double fY1 = std::max((double)INT_MIN, std::min((double)INT_MAX, (Y0 + M[3] * x1) * W1)); + double fY2 = std::max((double)INT_MIN, std::min((double)INT_MAX, (Y0 + M[3] * (x1 + 1)) * W2)); + + int32x2_t vX = {saturate_cast(fX1), saturate_cast(fX2)}; + int32x2_t vY = {saturate_cast(fY1), saturate_cast(fY2)}; + + int32x2_t vx = __nds__v_sclip32(__nds__v_sra32(vX, INTER_BITS), 15); + int32x2_t vy = __nds__v_sclip32(__nds__v_sra32(vY, INTER_BITS), 15); + + *(uint16x4_t*)(xy + x1 * 2) = (uint16x4_t)__nds__pkbb16((unsigned long)vy, (unsigned long)vx); + + uint32x2_t valpha = __nds__v_uadd32(__nds__v_sll32((uint32x2_t)(vY & vmask), INTER_BITS), (uint32x2_t)(vX & vmask)); + *(int16x2_t*)(alpha + x1) = (int16x2_t) { (short)(valpha[0]), (short)(valpha[1]) }; + } + + for (; x1 < bw; x1++) { + double W = W0 + M[6] * x1; + W = W ? INTER_TAB_SIZE / W : 0; + double fX = std::max((double)INT_MIN, std::min((double)INT_MAX, (X0 + M[0] * x1) * W)); + double fY = std::max((double)INT_MIN, std::min((double)INT_MAX, (Y0 + M[3] * x1) * W)); + int X = saturate_cast(fX); + int Y = saturate_cast(fY); + + xy[x1 * 2] = saturate_cast(X >> INTER_BITS); + xy[x1 * 2 + 1] = saturate_cast(Y >> INTER_BITS); + alpha[x1] = (short)((Y & (INTER_TAB_SIZE - 1)) * INTER_TAB_SIZE + (X & (INTER_TAB_SIZE - 1))); + } + } + } + + if (interpolation == CV_HAL_INTER_NEAREST) + remap(src, dpart, _XY, Mat(), interpolation, borderType, borderValue); + else { + Mat _matA(bh, bw, CV_16U, A); + remap(src, dpart, _XY, _matA, interpolation, borderType, borderValue); + } + } + } + } + +private: + Mat src; + Mat dst; + const double* M; + int interpolation, borderType; + Scalar borderValue; +}; + +int warpPerspective(int src_type, + const uchar* src_data, size_t src_step, int src_width, int src_height, + uchar* dst_data, size_t dst_step, int dst_width, int dst_height, + const double M[9], int interpolation, int borderType, const double borderValue[4]) +{ + Mat src(Size(src_width, src_height), src_type, const_cast(src_data), src_step); + Mat dst(Size(dst_width, dst_height), src_type, dst_data, dst_step); + + Range range(0, dst.rows); + WarpPerspectiveInvoker invoker(src, dst, M, interpolation, borderType, Scalar(borderValue[0], borderValue[1], borderValue[2], borderValue[3])); + parallel_for_(range, invoker, dst.total() / (double)(1 << 16)); + return CV_HAL_ERROR_OK; +} + +} // namespace ndsrvp + +} // namespace cv diff --git a/CMakeLists.txt b/CMakeLists.txt index 136de5c79f8f..f5e39b4c71be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -263,6 +263,8 @@ OCV_OPTION(WITH_CAROTENE "Use NVidia carotene acceleration library for ARM platf VISIBLE_IF (ARM OR AARCH64) AND NOT IOS AND NOT XROS) OCV_OPTION(WITH_KLEIDICV "Use KleidiCV library for ARM platforms" OFF VISIBLE_IF (AARCH64 AND (ANDROID OR UNIX AND NOT IOS AND NOT XROS))) +OCV_OPTION(WITH_NDSRVP "Use Andes RVP extension" (NOT CV_DISABLE_OPTIMIZATION) + VISIBLE_IF RISCV) OCV_OPTION(WITH_CPUFEATURES "Use cpufeatures Android library" ON VISIBLE_IF ANDROID VERIFY HAVE_CPUFEATURES) @@ -985,6 +987,13 @@ if(WITH_CAROTENE) endif() endif() +if(WITH_NDSRVP) + ocv_debug_message(STATUS "Andes RVP 3rdparty NDSRVP enabled") + if(NOT ";${OpenCV_HAL};" MATCHES ";ndsrvp;") + set(OpenCV_HAL "ndsrvp;${OpenCV_HAL}") + endif() +endif() + foreach(hal ${OpenCV_HAL}) if(hal STREQUAL "carotene") if(";${CPU_BASELINE_FINAL};" MATCHES ";NEON;") @@ -1006,6 +1015,14 @@ foreach(hal ${OpenCV_HAL}) add_subdirectory(3rdparty/kleidicv) ocv_hal_register(KLEIDICV_HAL_LIBRARIES KLEIDICV_HAL_HEADERS KLEIDICV_HAL_INCLUDE_DIRS) list(APPEND OpenCV_USED_HAL "KleidiCV (ver ${KLEIDICV_HAL_VERSION})") + elseif(hal STREQUAL "ndsrvp") + if(CMAKE_C_FLAGS MATCHES "-mext-dsp" AND CMAKE_CXX_FLAGS MATCHES "-mext-dsp" AND NOT ";${CPU_BASELINE_FINAL};" MATCHES ";RVV;") + add_subdirectory(3rdparty/ndsrvp) + ocv_hal_register(NDSRVP_HAL_LIBRARIES NDSRVP_HAL_HEADERS NDSRVP_HAL_INCLUDE_DIRS) + list(APPEND OpenCV_USED_HAL "ndsrvp (ver ${NDSRVP_HAL_VERSION})") + else() + message(STATUS "NDSRVP: Andes GNU Toolchain DSP extension is not open, disabling ndsrvp...") + endif() elseif(hal STREQUAL "openvx") add_subdirectory(3rdparty/openvx) ocv_hal_register(OPENVX_HAL_LIBRARIES OPENVX_HAL_HEADERS OPENVX_HAL_INCLUDE_DIRS) diff --git a/platforms/linux/riscv64-andes-gcc.toolchain.cmake b/platforms/linux/riscv64-andes-gcc.toolchain.cmake index ce733fc79055..9b9c0b524678 100755 --- a/platforms/linux/riscv64-andes-gcc.toolchain.cmake +++ b/platforms/linux/riscv64-andes-gcc.toolchain.cmake @@ -1,10 +1,25 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR riscv64) +message(STATUS "RISCV: $ENV{RISCV}") +message(STATUS "RISCV_GCC_INSTALL_ROOT: $ENV{RISCV_GCC_INSTALL_ROOT}") + set(RISCV_GCC_INSTALL_ROOT $ENV{RISCV} CACHE PATH "Path to GCC for RISC-V cross compiler installation directory") set(CMAKE_C_COMPILER ${RISCV_GCC_INSTALL_ROOT}/bin/riscv64-linux-gcc) set(CMAKE_CXX_COMPILER ${RISCV_GCC_INSTALL_ROOT}/bin/riscv64-linux-g++) +# fix toolchain macro + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__ANDES=1") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__ANDES=1") + +# enable rvp + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=rv64gc -mext-dsp") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=rv64gc -mext-dsp") + +# fix segment address + +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Ttext-segment=0x50000") +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-Ttext-segment=0x50000") From e7bf07786dff7535e6ba2e9c8ecd297de1ae6051 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Wed, 29 May 2024 16:41:32 +0200 Subject: [PATCH 091/119] Have the findContours_legacy overload call findContours_legacy. --- modules/imgproc/src/contours.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/contours.cpp b/modules/imgproc/src/contours.cpp index d88c6cbede08..0577ca16c1a0 100644 --- a/modules/imgproc/src/contours.cpp +++ b/modules/imgproc/src/contours.cpp @@ -1884,7 +1884,7 @@ void cv::findContours_legacy( InputArray _image, OutputArrayOfArrays _contours, { CV_INSTRUMENT_REGION(); - findContours(_image, _contours, noArray(), mode, method, offset); + findContours_legacy(_image, _contours, noArray(), mode, method, offset); } /* End of file. */ From 8709115d9a34912d4ee485442d072113951467f6 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 29 May 2024 12:54:18 +0300 Subject: [PATCH 092/119] imgproc: fix contour approximation, added test --- modules/imgproc/src/contours.cpp | 2 +- modules/imgproc/src/contours_approx.cpp | 7 +++---- modules/imgproc/test/test_contours_new.cpp | 19 +++++++++++++++++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/modules/imgproc/src/contours.cpp b/modules/imgproc/src/contours.cpp index d88c6cbede08..0577ca16c1a0 100644 --- a/modules/imgproc/src/contours.cpp +++ b/modules/imgproc/src/contours.cpp @@ -1884,7 +1884,7 @@ void cv::findContours_legacy( InputArray _image, OutputArrayOfArrays _contours, { CV_INSTRUMENT_REGION(); - findContours(_image, _contours, noArray(), mode, method, offset); + findContours_legacy(_image, _contours, noArray(), mode, method, offset); } /* End of file. */ diff --git a/modules/imgproc/src/contours_approx.cpp b/modules/imgproc/src/contours_approx.cpp index bf194933d6d5..f98ea190f4cd 100644 --- a/modules/imgproc/src/contours_approx.cpp +++ b/modules/imgproc/src/contours_approx.cpp @@ -231,7 +231,7 @@ static void pass_cleanup(vector& ares, size_t start_idx) const size_t len = ares.size(); size_t first = start_idx; - for (size_t i = start_idx, prev = i; i < len; ++i) + for (size_t i = start_idx, prev = start_idx; i < len; ++i) { ApproxItem& item = ares[i]; if (item.removed) @@ -248,10 +248,10 @@ static void pass_cleanup(vector& ares, size_t start_idx) if (s1 > s2 || (s1 == s2 && ares[prev].k <= ares[i].k)) /* remove second */ - clear_until(ares, get_next_idx(ares, prev), get_next_idx(ares, i)); + clear_until(ares, prev, get_next_idx(ares, i)); else /* remove first */ - clear_until(ares, first, i); + clear_until(ares, get_next_idx(ares, first), i); } else { @@ -259,7 +259,6 @@ static void pass_cleanup(vector& ares, size_t start_idx) clear_until(ares, first, i); } } - clear_until(ares, first, i); first = i; count = 1; } diff --git a/modules/imgproc/test/test_contours_new.cpp b/modules/imgproc/test/test_contours_new.cpp index 93afab25442a..ef4ce29155c5 100644 --- a/modules/imgproc/test/test_contours_new.cpp +++ b/modules/imgproc/test/test_contours_new.cpp @@ -602,4 +602,23 @@ TEST(Imgproc_FindContours, link_runs) #endif } +TEST(Imgproc_FindContours, regression_25663) +{ + uint8_t data[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; + Mat1b img(32,32,data); + vector> contours; + vector hierarchy; + findContours(img, contours, RETR_EXTERNAL, CHAIN_APPROX_TC89_L1); +#if CHECK_OLD + vector> contours_o; + findContours_legacy(img, contours_o, RETR_EXTERNAL, CHAIN_APPROX_TC89_L1); + ASSERT_EQ(contours_o.size(), contours.size()); + for (size_t i = 0; i < contours_o.size(); ++i) + { + SCOPED_TRACE(format("contour = %zu", i)); + EXPECT_MAT_NEAR(Mat(contours_o[i]), Mat(contours[i]), 0); + } +#endif +} + }} // namespace opencv_test From 7e9ef4db86cd403a8817832c8e558ef82c17733b Mon Sep 17 00:00:00 2001 From: Yuantao Feng Date: Thu, 30 May 2024 22:03:07 +0800 Subject: [PATCH 093/119] Merge pull request #25625 from fengyuentau:core/deploy_fix_lapack_ilp64 core: deployment compatibility for old mac after Accelerate New LAPACK fix #25625 Attempt to fix https://github.com/opencv/opencv/pull/24804#discussion_r1609957747 We may need to explicitly add build option `-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0` or environment variable (`export MACOSX_DEPLOYMENT_TARGET=12.0`) for mac builds (python package most probably) on builders with new macOS (>= 13.3). ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- cmake/OpenCVFindLAPACK.cmake | 39 ++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/cmake/OpenCVFindLAPACK.cmake b/cmake/OpenCVFindLAPACK.cmake index d559ab88b90f..ba682c1c04aa 100644 --- a/cmake/OpenCVFindLAPACK.cmake +++ b/cmake/OpenCVFindLAPACK.cmake @@ -1,3 +1,26 @@ +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(_apple_device_min_target_os_version "13.3") +elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS") + set(_apple_device_min_target_os_version "16.4") +elseif(CMAKE_SYSTEM_NAME STREQUAL "watchOS") + set(_apple_device_min_target_os_version "9.4") +elseif(CMAKE_SYSTEM_NAME STREQUAL "tvOS") + set(_apple_device_min_target_os_version "16.4") +elseif(CMAKE_SYSTEM_NAME STREQUAL "visionOS") + set(_apple_device_min_target_os_version "1.0") +endif() + +if(DEFINED _apple_device_min_target_os_version AND + ("${CMAKE_OSX_DEPLOYMENT_TARGET}" VERSION_GREATER "${_apple_device_min_target_os_version}" OR + "${CMAKE_OSX_DEPLOYMENT_TARGET}" VERSION_EQUAL "${_apple_device_min_target_os_version}")) + set(_apple_device_has_required_min_os_version ON) +else() + set(_apple_device_has_required_min_os_version OFF) +endif() + +OCV_OPTION(OPENCV_OSX_USE_ACCELERATE_NEW_LAPACK "Use new BLAS/LAPACK interfaces from Accelerate framework on Apple platform" _apple_device_has_required_min_os_version + VISIBLE_IF APPLE) + macro(_find_header_file_in_dirs VAR NAME) unset(${VAR}) unset(${VAR} CACHE) @@ -107,17 +130,11 @@ macro(ocv_lapack_check) endif() set(LAPACK_TRY_COMPILE_DEF "") - if(LAPACK_IMPL STREQUAL "LAPACK/Apple" AND NOT IOS) # https://github.com/opencv/opencv/issues/24660 - # Get macOS version - execute_process(COMMAND sw_vers -productVersion - OUTPUT_VARIABLE MACOS_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE) - # Enable Accelerate New LAPACK if macOS >= 13.3 - if (MACOS_VERSION VERSION_GREATER "13.3" OR MACOS_VERSION VERSION_EQUAL "13.3") - set(LAPACK_TRY_COMPILE_DEF "-DACCELERATE_NEW_LAPACK") - add_compile_definitions(ACCELERATE_NEW_LAPACK) - add_compile_definitions(ACCELERATE_LAPACK_ILP64) - endif() + if(LAPACK_IMPL STREQUAL "LAPACK/Apple" AND OPENCV_OSX_USE_ACCELERATE_NEW_LAPACK) + message(STATUS "LAPACK(${LAPACK_IMPL}): Accelerate New LAPACK is enabled.") + set(LAPACK_TRY_COMPILE_DEF "-DACCELERATE_NEW_LAPACK") + add_compile_definitions(ACCELERATE_NEW_LAPACK) + add_compile_definitions(ACCELERATE_LAPACK_ILP64) endif() try_compile(__VALID_LAPACK From 9ed1d6730f8f742efcee0282f5d4c3e58e36f1e3 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 31 May 2024 10:09:34 +0300 Subject: [PATCH 094/119] Fixed offset computation for ND case in MinMaxIdx HAL. --- modules/core/src/minmax.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/core/src/minmax.cpp b/modules/core/src/minmax.cpp index 859fa9e54c38..8c6d8ad9a9a6 100644 --- a/modules/core/src/minmax.cpp +++ b/modules/core/src/minmax.cpp @@ -1522,10 +1522,11 @@ void cv::minMaxIdx(InputArray _src, double* minVal, if (res == CV_HAL_ERROR_OK) { + // minIdx[0] and minIdx[0] are always 0 for "flatten" version if (minIdx) - ofs2idx(src, minIdx[0], minIdx); + ofs2idx(src, minIdx[1], minIdx); if (maxIdx) - ofs2idx(src, maxIdx[0], maxIdx); + ofs2idx(src, maxIdx[1], maxIdx); return; } else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) From d7f04a9d33d9c7d7c4d829fe6a5e55955d158e3a Mon Sep 17 00:00:00 2001 From: Abduragim Shtanchaev <44877829+Abdurrahheem@users.noreply.github.com> Date: Fri, 31 May 2024 14:13:36 +0400 Subject: [PATCH 095/119] Merge pull request #25660 from Abdurrahheem:ash/fix-slice-empty-input Slice layer parser fix to support empty input case #25660 This PR fixes Slice Layer's parser to handle empty input cases (cases with initializer) It fixed the issue rased in #24838 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/dnn/src/onnx/onnx_importer.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/dnn/src/onnx/onnx_importer.cpp b/modules/dnn/src/onnx/onnx_importer.cpp index b09a9ed36085..7b63e39a3abd 100644 --- a/modules/dnn/src/onnx/onnx_importer.cpp +++ b/modules/dnn/src/onnx/onnx_importer.cpp @@ -1202,7 +1202,12 @@ void ONNXImporter::parseReduce(LayerParams& layerParams, const opencv_onnx::Node void ONNXImporter::parseSlice(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto) { - MatShape inpShape = outShapes[node_proto.input(0)]; + MatShape inpShape; + if (constBlobs.find(node_proto.input(0)) != constBlobs.end()) + inpShape = shape(getBlob(node_proto, 0)); + else { + inpShape = outShapes[node_proto.input(0)]; + } int dims = inpShape.size(); std::vector begin(dims, 0); std::vector end(dims, INT_MAX); From dcce2b8b2412dedb35f1ba238ffe40d68019d3ac Mon Sep 17 00:00:00 2001 From: Ujjayant Kadian <118752727+ujjayant-kadian@users.noreply.github.com> Date: Fri, 31 May 2024 15:01:46 +0100 Subject: [PATCH 096/119] Merge pull request #25662 from ujjayant-kadian:uk/port-gapi-onnxrt-backend-into-v2-api Port G-API ONNXRT backend into V2 API #25662 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [ ] I agree to contribute to the project under Apache 2 License. - [ ] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ ] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- .../gapi/include/opencv2/gapi/infer/onnx.hpp | 31 ++++++++++++++++++- .../gapi/src/backends/onnx/gonnxbackend.cpp | 26 +++++++++++----- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/modules/gapi/include/opencv2/gapi/infer/onnx.hpp b/modules/gapi/include/opencv2/gapi/infer/onnx.hpp index ec5950718e30..f985b41d71bf 100644 --- a/modules/gapi/include/opencv2/gapi/infer/onnx.hpp +++ b/modules/gapi/include/opencv2/gapi/infer/onnx.hpp @@ -11,6 +11,7 @@ #include #include #include // tuple, tuple_size +#include #include #include @@ -156,13 +157,24 @@ struct GAPI_EXPORTS_W_SIMPLE OpenVINO { Constructs OpenVINO parameters based on device type information. - @param dev_type Target device type to use. ("CPU_FP32", "GPU_FP16", etc) + @param dev_type Target device type to use. ("CPU", "GPU", "GPU.0" etc) */ GAPI_WRAP explicit OpenVINO(const std::string &dev_type) : device_type(dev_type) { } + /** @brief Class constructor. + + Constructs OpenVINO parameters based on map of options passed. + + * @param params A map of parameter names and their corresponding string values. + */ + GAPI_WRAP + explicit OpenVINO(const std::map& params) + : params_map(params) { + } + /** @brief Specifies OpenVINO Execution Provider cache dir. This function is used to explicitly specify the path to save and load @@ -173,6 +185,10 @@ struct GAPI_EXPORTS_W_SIMPLE OpenVINO { */ GAPI_WRAP OpenVINO& cfgCacheDir(const std::string &dir) { + if (!params_map.empty()) { + cv::util::throw_error(std::logic_error("ep::OpenVINO cannot be changed if" + "created from the parameters map.")); + } cache_dir = dir; return *this; } @@ -187,6 +203,10 @@ struct GAPI_EXPORTS_W_SIMPLE OpenVINO { */ GAPI_WRAP OpenVINO& cfgNumThreads(size_t nthreads) { + if (!params_map.empty()) { + cv::util::throw_error(std::logic_error("ep::OpenVINO cannot be changed if" + "created from the parameters map.")); + } num_of_threads = nthreads; return *this; } @@ -200,6 +220,10 @@ struct GAPI_EXPORTS_W_SIMPLE OpenVINO { */ GAPI_WRAP OpenVINO& cfgEnableOpenCLThrottling() { + if (!params_map.empty()) { + cv::util::throw_error(std::logic_error("ep::OpenVINO cannot be changed if" + "created from the parameters map.")); + } enable_opencl_throttling = true; return *this; } @@ -216,6 +240,10 @@ struct GAPI_EXPORTS_W_SIMPLE OpenVINO { */ GAPI_WRAP OpenVINO& cfgEnableDynamicShapes() { + if (!params_map.empty()) { + cv::util::throw_error(std::logic_error("ep::OpenVINO cannot be changed if" + "created from the parameters map.")); + } enable_dynamic_shapes = true; return *this; } @@ -225,6 +253,7 @@ struct GAPI_EXPORTS_W_SIMPLE OpenVINO { size_t num_of_threads = 0; bool enable_opencl_throttling = false; bool enable_dynamic_shapes = false; + std::map params_map; }; /** diff --git a/modules/gapi/src/backends/onnx/gonnxbackend.cpp b/modules/gapi/src/backends/onnx/gonnxbackend.cpp index e2ddd3ea59e7..92b908da700d 100644 --- a/modules/gapi/src/backends/onnx/gonnxbackend.cpp +++ b/modules/gapi/src/backends/onnx/gonnxbackend.cpp @@ -178,16 +178,26 @@ static void addTensorRTExecutionProvider(Ort::SessionOptions *session_options, static void addOpenVINOExecutionProvider(Ort::SessionOptions *session_options, const cv::gapi::onnx::ep::OpenVINO &ov_ep) { - OrtOpenVINOProviderOptions options{}; - options.device_type = ov_ep.device_type.c_str(); - options.cache_dir = ov_ep.cache_dir.c_str(); - options.num_of_threads = ov_ep.num_of_threads; - options.enable_opencl_throttling = ov_ep.enable_opencl_throttling; - options.enable_dynamic_shapes = ov_ep.enable_dynamic_shapes; - options.context = nullptr; + std::unordered_map options; try { - session_options->AppendExecutionProvider_OpenVINO(options); + // If the OpenVINO Execution Provider object was initialized with a parameters map, + // those parameters are used directly. + // Otherwise, the function constructs the options map from the individual member + // variables of the OpenVINO object. + if (ov_ep.params_map.empty()) { + options = { + {"device_type", ov_ep.device_type}, + {"cache_dir", ov_ep.cache_dir}, + {"num_of_threads", ov_ep.num_of_threads > 0 ? std::to_string(ov_ep.num_of_threads) : ""}, + {"enable_opencl_throttling", ov_ep.enable_opencl_throttling ? "True" : "False"}, + {"enable_dynamic_shapes", ov_ep.enable_dynamic_shapes ? "True" : "False"}, + }; + } else { + options.insert(ov_ep.params_map.begin(), ov_ep.params_map.end()); + } + // AppendExecutionProvider function expects a const std::unordered_map as its second argument + session_options->AppendExecutionProvider("OpenVINO", options); } catch (const std::exception &e) { std::stringstream ss; ss << "ONNX Backend: Failed to enable OpenVINO" From 472eba324af899e192c30970fe8dda98332a0f63 Mon Sep 17 00:00:00 2001 From: Alexander Panov Date: Fri, 31 May 2024 17:03:24 +0300 Subject: [PATCH 097/119] Merge pull request #25673 from AleksandrPanov:fix_charuco_board_markers fixed marker generation in charuco board #25673 When generating Charuco board markers in `generateImage()`, a problem occurs as in https://github.com/opencv/opencv/issues/24806, https://github.com/opencv/opencv/pull/24873: In low resolution: ![charucoImg_before_fix2](https://github.com/opencv/opencv/assets/22337800/aab7b443-2d2a-4287-b869-708ac5976ea5) In medium resolution: ![charucoImg_before_fix](https://github.com/opencv/opencv/assets/22337800/8c21ae42-d9c8-4cb5-9fcc-7814dfc07b80) This PR fixed this problems: ![charucoImg_after_fix2](https://github.com/opencv/opencv/assets/22337800/93256dbb-8544-46eb-be78-844234e42ca9) ![charucoImg_after_fix](https://github.com/opencv/opencv/assets/22337800/f4d6794e-bee9-4ce4-8f9b-67a40800cbe5) The test checks the inner and outer borders of the Aruco markers. In the outer border of Aruco marker, all pixels should be white. In the inner border of Aruco marker, all pixels should be black. ![image](https://github.com/opencv/opencv/assets/22337800/010a9c64-e03c-4239-9ac9-2cda9170793b) ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/objdetect/src/aruco/aruco_board.cpp | 15 ---- .../objdetect/test/test_charucodetection.cpp | 78 +++++++++++++++++-- 2 files changed, 72 insertions(+), 21 deletions(-) diff --git a/modules/objdetect/src/aruco/aruco_board.cpp b/modules/objdetect/src/aruco/aruco_board.cpp index f8d3d3c1082b..f5f274ec0cf1 100644 --- a/modules/objdetect/src/aruco/aruco_board.cpp +++ b/modules/objdetect/src/aruco/aruco_board.cpp @@ -99,21 +99,6 @@ void Board::Impl::generateImage(Size outSize, OutputArray img, int marginSize, i float sizeX = maxX - minX; float sizeY = maxY - minY; - // proportion transformations - float xReduction = sizeX / float(out.cols); - float yReduction = sizeY / float(out.rows); - - // determine the zone where the markers are placed - if(xReduction > yReduction) { - int nRows = int(sizeY / xReduction); - int rowsMargins = (out.rows - nRows) / 2; - out.adjustROI(-rowsMargins, -rowsMargins, 0, 0); - } else { - int nCols = int(sizeX / yReduction); - int colsMargins = (out.cols - nCols) / 2; - out.adjustROI(0, 0, -colsMargins, -colsMargins); - } - // now paint each marker Mat marker; Point2f outCorners[3]; diff --git a/modules/objdetect/test/test_charucodetection.cpp b/modules/objdetect/test/test_charucodetection.cpp index 47166fa78e82..c0f6c93d506b 100644 --- a/modules/objdetect/test/test_charucodetection.cpp +++ b/modules/objdetect/test/test_charucodetection.cpp @@ -81,6 +81,18 @@ static Mat projectCharucoBoard(aruco::CharucoBoard& board, Mat cameraMatrix, dou return img; } +static bool borderPixelsHaveSameColor(const Mat& image, uint8_t color) { + for (int j = 0; j < image.cols; j++) { + if (image.at(0, j) != color || image.at(image.rows-1, j) != color) + return false; + } + for (int i = 0; i < image.rows; i++) { + if (image.at(i, 0) != color || image.at(i, image.cols-1) != color) + return false; + } + return true; +} + /** * @brief Check Charuco detection */ @@ -769,17 +781,24 @@ TEST_P(CharucoBoard, testWrongSizeDetection) ASSERT_TRUE(detectedCharucoIds.empty()); } -TEST(CharucoBoardGenerate, issue_24806) + +typedef testing::TestWithParam> CharucoBoardGenerate; +INSTANTIATE_TEST_CASE_P(/**/, CharucoBoardGenerate, testing::Values(make_tuple(Size(7, 4), 13.f, Size(400, 300), 24), + make_tuple(Size(12, 2), 13.f, Size(200, 150), 1), + make_tuple(Size(12, 2), 13.1f, Size(400, 300), 1))); +TEST_P(CharucoBoardGenerate, issue_24806) { aruco::Dictionary dict = aruco::getPredefinedDictionary(aruco::DICT_4X4_1000); - const float squareLength = 13.f, markerLength = 10.f; - const Size boardSize(7ull, 4ull); + auto params = GetParam(); + const Size boardSize = std::get<0>(params); + const float squareLength = std::get<1>(params), markerLength = 10.f; + Size imgSize = std::get<2>(params); const aruco::CharucoBoard board(boardSize, squareLength, markerLength, dict); - const int marginSize = 24; + const int marginSize = std::get<3>(params); Mat boardImg; // generate chessboard image - board.generateImage(Size(400, 300), boardImg, marginSize); + board.generateImage(imgSize, boardImg, marginSize); // This condition checks that the width of the image determines the dimensions of the chessboard in this test CV_Assert((float)(boardImg.cols) / (float)boardSize.width <= (float)(boardImg.rows) / (float)boardSize.height); @@ -817,7 +836,54 @@ TEST(CharucoBoardGenerate, issue_24806) bool eq = (cv::countNonZero(goldCorner1 != winCorner) == 0) || (cv::countNonZero(goldCorner2 != winCorner) == 0); ASSERT_TRUE(eq); } - // TODO: fix aruco generateImage and add test aruco corners for generated image + + // marker size in pixels + const float pixInMarker = markerLength/squareLength*pixInSquare; + // the size of the marker margin in pixels + const float pixInMarginMarker = 0.5f*(pixInSquare - pixInMarker); + + // determine the zone where the aruco markers are located + int endArucoX = cvRound(pixInSquare*(boardSize.width-1)+pixInMarginMarker+pixInMarker); + int endArucoY = cvRound(pixInSquare*(boardSize.height-1)+pixInMarginMarker+pixInMarker); + Mat arucoZone = chessboardZoneImg(Range(cvRound(pixInMarginMarker), endArucoY), Range(cvRound(pixInMarginMarker), endArucoX)); + + const auto& markerCorners = board.getObjPoints(); + float minX, maxX, minY, maxY; + minX = maxX = markerCorners[0][0].x; + minY = maxY = markerCorners[0][0].y; + for (const auto& marker : markerCorners) { + for (const Point3f& objCorner : marker) { + minX = min(minX, objCorner.x); + maxX = max(maxX, objCorner.x); + minY = min(minY, objCorner.y); + maxY = max(maxY, objCorner.y); + } + } + + Point2f outCorners[3]; + for (const auto& marker : markerCorners) { + for (int i = 0; i < 3; i++) { + outCorners[i] = Point2f(marker[i].x, marker[i].y) - Point2f(minX, minY); + outCorners[i].x = outCorners[i].x / (maxX - minX) * float(arucoZone.cols); + outCorners[i].y = outCorners[i].y / (maxY - minY) * float(arucoZone.rows); + } + Size dst_sz(outCorners[2] - outCorners[0]); // assuming CCW order + dst_sz.width = dst_sz.height = std::min(dst_sz.width, dst_sz.height); + Rect borderRect = Rect(outCorners[0], dst_sz); + + //The test checks the inner and outer borders of the Aruco markers. + //In the inner border of Aruco marker, all pixels should be black. + //In the outer border of Aruco marker, all pixels should be white. + + Mat markerImg = arucoZone(borderRect); + bool markerBorderIsBlack = borderPixelsHaveSameColor(markerImg, 0); + ASSERT_EQ(markerBorderIsBlack, true); + + Mat markerOuterBorder = markerImg; + markerOuterBorder.adjustROI(1, 1, 1, 1); + bool markerOuterBorderIsWhite = borderPixelsHaveSameColor(markerOuterBorder, 255); + ASSERT_EQ(markerOuterBorderIsWhite, true); + } } TEST(Charuco, testSeveralBoardsWithCustomIds) From ca035e6dae6c55a936928296979421cf7db86adf Mon Sep 17 00:00:00 2001 From: fengyuentau Date: Fri, 31 May 2024 22:40:23 +0800 Subject: [PATCH 098/119] fix type for ilp64 api --- modules/calib3d/src/usac/dls_solver.cpp | 5 +++++ modules/calib3d/src/usac/essential_solver.cpp | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/modules/calib3d/src/usac/dls_solver.cpp b/modules/calib3d/src/usac/dls_solver.cpp index ca6a66450422..2e866b938920 100644 --- a/modules/calib3d/src/usac/dls_solver.cpp +++ b/modules/calib3d/src/usac/dls_solver.cpp @@ -155,7 +155,12 @@ class DLSPnPImpl : public DLSPnP { const auto &eigen_vectors = eigen_solver.eigenvectors(); const auto &eigen_values = eigen_solver.eigenvalues(); #else + +#if defined (ACCELERATE_NEW_LAPACK) && defined (ACCELERATE_LAPACK_ILP64) + long mat_order = 27, info, lda = 27, ldvl = 1, ldvr = 27, lwork = 500; +#else int mat_order = 27, info, lda = 27, ldvl = 1, ldvr = 27, lwork = 500; +#endif double wr[27], wi[27] = {0}; // 27 = mat_order std::vector work(lwork), eig_vecs(729); char jobvl = 'N', jobvr = 'V'; // only left eigen vectors are computed diff --git a/modules/calib3d/src/usac/essential_solver.cpp b/modules/calib3d/src/usac/essential_solver.cpp index 6f0e6b1cfce8..8f9b5b9d330f 100644 --- a/modules/calib3d/src/usac/essential_solver.cpp +++ b/modules/calib3d/src/usac/essential_solver.cpp @@ -259,7 +259,11 @@ class EssentialMinimalSolver5ptsImpl : public EssentialMinimalSolver5pts { action_mat_data[83] = -1.0; // 8 row, 3 col action_mat_data[96] = -1.0; // 9 row, 6 col +#if defined (ACCELERATE_NEW_LAPACK) && defined (ACCELERATE_LAPACK_ILP64) + long mat_order = 10, info, lda = 10, ldvl = 10, ldvr = 1, lwork = 100; +#else int mat_order = 10, info, lda = 10, ldvl = 10, ldvr = 1, lwork = 100; +#endif double wr[10], wi[10] = {0}, eig_vecs[100], work[100]; // 10 = mat_order, 100 = lwork char jobvl = 'V', jobvr = 'N'; // only left eigen vectors are computed OCV_LAPACK_FUNC(dgeev)(&jobvl, &jobvr, &mat_order, action_mat_data, &lda, wr, wi, eig_vecs, &ldvl, From 29f91a08d53cf46c2b9183a879c098695ca42c08 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Fri, 31 May 2024 19:28:03 +0300 Subject: [PATCH 099/119] Merge pull request #25680 from mshabunin:fix-approx-2 Reverted contour approximation behavior #25680 Related issue #25663 - revert new function behavior despite it returning different result than the old one (reverts PR #25672). Also added Coverity issue fix. --- modules/imgproc/src/contours_approx.cpp | 4 ++-- modules/imgproc/src/contours_link.cpp | 2 -- modules/imgproc/test/test_contours_new.cpp | 22 +++------------------- 3 files changed, 5 insertions(+), 23 deletions(-) diff --git a/modules/imgproc/src/contours_approx.cpp b/modules/imgproc/src/contours_approx.cpp index f98ea190f4cd..176c4904681f 100644 --- a/modules/imgproc/src/contours_approx.cpp +++ b/modules/imgproc/src/contours_approx.cpp @@ -248,10 +248,10 @@ static void pass_cleanup(vector& ares, size_t start_idx) if (s1 > s2 || (s1 == s2 && ares[prev].k <= ares[i].k)) /* remove second */ - clear_until(ares, prev, get_next_idx(ares, i)); + ares[i].removed = true; else /* remove first */ - clear_until(ares, get_next_idx(ares, first), i); + ares[prev].removed = true; } else { diff --git a/modules/imgproc/src/contours_link.cpp b/modules/imgproc/src/contours_link.cpp index 532519bc97c9..8df88fc1238c 100644 --- a/modules/imgproc/src/contours_link.cpp +++ b/modules/imgproc/src/contours_link.cpp @@ -252,7 +252,6 @@ void LinkRunner::establishLinks(int& prev_point, lower_run = rns[rns[lower_run].next].next; continue; } - rns[rns[lower_run].next] = rns[rns[lower_run].next]; rns[lower_run].link = rns[lower_run].next; // First point of contour @@ -269,7 +268,6 @@ void LinkRunner::establishLinks(int& prev_point, upper_run = rns[rns[upper_run].next].next; continue; } - rns[rns[upper_run].next] = rns[rns[upper_run].next]; rns[rns[upper_run].next].link = upper_run; upper_run = rns[rns[upper_run].next].next; } diff --git a/modules/imgproc/test/test_contours_new.cpp b/modules/imgproc/test/test_contours_new.cpp index ef4ce29155c5..fbeba0658788 100644 --- a/modules/imgproc/test/test_contours_new.cpp +++ b/modules/imgproc/test/test_contours_new.cpp @@ -531,6 +531,9 @@ TEST_P(Imgproc_FindContours_Modes2, approx) findContours(img, contours, hierarchy, mode, method); #if CHECK_OLD + // NOTE: old and new function results might not match when approximation mode is TC89. + // Currently this test passes, but might fail for other random data. + // See https://github.com/opencv/opencv/issues/25663 for details. vector> contours_o; vector hierarchy_o; findContours_legacy(img, contours_o, hierarchy_o, mode, method); @@ -602,23 +605,4 @@ TEST(Imgproc_FindContours, link_runs) #endif } -TEST(Imgproc_FindContours, regression_25663) -{ - uint8_t data[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; - Mat1b img(32,32,data); - vector> contours; - vector hierarchy; - findContours(img, contours, RETR_EXTERNAL, CHAIN_APPROX_TC89_L1); -#if CHECK_OLD - vector> contours_o; - findContours_legacy(img, contours_o, RETR_EXTERNAL, CHAIN_APPROX_TC89_L1); - ASSERT_EQ(contours_o.size(), contours.size()); - for (size_t i = 0; i < contours_o.size(); ++i) - { - SCOPED_TRACE(format("contour = %zu", i)); - EXPECT_MAT_NEAR(Mat(contours_o[i]), Mat(contours[i]), 0); - } -#endif -} - }} // namespace opencv_test From 98b8825031f19f47b1e33a9b9c062208f8d4acb5 Mon Sep 17 00:00:00 2001 From: CNOCycle <24318472+CNOCycle@users.noreply.github.com> Date: Sat, 1 Jun 2024 00:31:21 +0800 Subject: [PATCH 100/119] Merge pull request #25613 from CNOCycle:tflite/ops Support Global_Pool_2D ops in .tflite model #25613 ### Pull Request Readiness Checklist **Merge with extra**: https://github.com/opencv/opencv_extra/pull/1180 This PR adds support for `GlobalAveragePooling2D` and `GlobalMaxPool2D` on the TFlite backend. When the k`eep_dims` option is enabled, the output is a 2D tensor, necessitating the inclusion of an additional flatten layer. Additionally, the names of these layers have been updated to match the output tensor names generated by `generate.py` from the opencv_extra repository. - [X] I agree to contribute to the project under Apache 2 License. - [X] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [X] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [X] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [X] The feature is well documented and sample code can be built with the project CMake --- modules/dnn/src/tflite/tflite_importer.cpp | 45 ++++++++++++++++++++++ modules/dnn/test/test_tflite_importer.cpp | 8 ++++ 2 files changed, 53 insertions(+) diff --git a/modules/dnn/src/tflite/tflite_importer.cpp b/modules/dnn/src/tflite/tflite_importer.cpp index 1c048ad9d026..92bfeeef65bf 100644 --- a/modules/dnn/src/tflite/tflite_importer.cpp +++ b/modules/dnn/src/tflite/tflite_importer.cpp @@ -71,6 +71,7 @@ class TFLiteImporter { void parseSoftmax(const Operator& op, const std::string& opcode, LayerParams& layerParams); void parseCast(const Operator& op, const std::string& opcode, LayerParams& layerParams); void parseTranspose(const Operator& op, const std::string& opcode, LayerParams& layerParams); + void parseGlobalPooling(const Operator& op, const std::string& opcode, LayerParams& layerParams); void parseFusedActivation(const Operator& op, ActivationFunctionType activ); void parseActivation(const Operator& op, const std::string& opcode, LayerParams& layerParams, bool isFused); @@ -78,6 +79,8 @@ class TFLiteImporter { int addPermuteLayer(const std::vector& order, const std::string& permName, const std::pair& inpId, int dtype); int addReshapeLayer(const std::vector& shape, int axis, int num_axes, const std::string& name, const std::pair& inpId, int dtype); + int addFlattenLayer(int axis, int end_axis, const std::string& name, const std::pair& inpId, int dtype); + inline bool isInt8(const Operator& op); inline void getQuantParams(const Operator& op, float& inpScale, int& inpZero, float& outScale, int& outZero); }; @@ -286,6 +289,7 @@ TFLiteImporter::DispatchMap TFLiteImporter::buildDispatchMap() dispatch["CAST"] = &TFLiteImporter::parseCast; dispatch["TFLite_Detection_PostProcess"] = &TFLiteImporter::parseDetectionPostProcess; dispatch["TRANSPOSE"] = &TFLiteImporter::parseTranspose; + dispatch["MEAN"] = dispatch["REDUCE_MAX"] = &TFLiteImporter::parseGlobalPooling; return dispatch; } @@ -764,6 +768,37 @@ void TFLiteImporter::parseTranspose(const Operator& op, const std::string& opcod addLayer(layerParams, op); } +void TFLiteImporter::parseGlobalPooling(const Operator& op, const std::string& opcode, LayerParams& layerParams) +{ + layerParams.type = "Pooling"; + if(opcode == "MEAN") { + layerParams.set("pool", "ave"); + } + else if (opcode == "REDUCE_MAX") { + layerParams.set("pool", "max"); + } + else { + CV_Error(Error::StsNotImplemented, "Unsupported pooling " + opcode); + } + layerParams.set("global_pooling", true); + auto options = op.builtin_options_as_ReducerOptions(); + bool keep_dims = options->keep_dims(); + + if (!keep_dims) { + const auto name = layerParams.name; + layerParams.name += "/global_pooling"; + addLayer(layerParams, op); + + int out = op.outputs()->Get(0); + auto outId = layerIds[out]; + int flattenId = addFlattenLayer(1, -1, name, outId, isInt8(op) ? CV_8S : CV_32F); + layerIds[out] = std::make_pair(flattenId, 0); + } + else { + addLayer(layerParams, op); + } +} + int TFLiteImporter::addPermuteLayer(const std::vector& order, const std::string& permName, const std::pair& inpId, int dtype) { @@ -786,6 +821,16 @@ int TFLiteImporter::addReshapeLayer(const std::vector& shape, int axis, int return id; } +int TFLiteImporter::addFlattenLayer(int axis, int end_axis, const std::string& name, const std::pair& inpId, int dtype) +{ + LayerParams lp; + lp.set("axis", axis); + lp.set("end_axis", end_axis); + int id = dstNet.addLayer(name, "Flatten", dtype, lp); + dstNet.connect(inpId.first, inpId.second, id, 0); + return id; +} + void TFLiteImporter::parseDeconvolution(const Operator& op, const std::string& opcode, LayerParams& layerParams) { layerParams.type = "Deconvolution"; diff --git a/modules/dnn/test/test_tflite_importer.cpp b/modules/dnn/test/test_tflite_importer.cpp index 7621b44ff53d..8d374dc0505d 100644 --- a/modules/dnn/test/test_tflite_importer.cpp +++ b/modules/dnn/test/test_tflite_importer.cpp @@ -260,6 +260,14 @@ TEST_P(Test_TFLite, permute) { testLayer("permutation_4d_0231"); } +TEST_P(Test_TFLite, global_average_pooling_2d) { + testLayer("global_average_pooling_2d"); +} + +TEST_P(Test_TFLite, global_max_pooling_2d) { + testLayer("global_max_pooling_2d"); +} + INSTANTIATE_TEST_CASE_P(/**/, Test_TFLite, dnnBackendsAndTargets()); }} // namespace From 1db6a8a1f33786880706426313d72725f5f7bf99 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Fri, 31 May 2024 19:51:58 +0200 Subject: [PATCH 101/119] Merge pull request #25665 from vrabaud:jacobian Fix Homography computation. #25665 The bug was introduced in https://github.com/opencv/opencv/pull/25308 I am sorry I do not have a proper test. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/calib3d/src/fundam.cpp | 11 ++++---- modules/calib3d/test/test_homography.cpp | 36 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/modules/calib3d/src/fundam.cpp b/modules/calib3d/src/fundam.cpp index 599250114b86..75d345659516 100644 --- a/modules/calib3d/src/fundam.cpp +++ b/modules/calib3d/src/fundam.cpp @@ -261,11 +261,11 @@ class HomographyRefineCallback CV_FINAL : public LMSolver::Callback if( Jptr ) { Jptr[0] = Mx*ww; Jptr[1] = My*ww; Jptr[2] = ww; - Jptr[6] = -Mx*ww*xi; Jptr[7] = -My*ww*xi; - Jptr[11] = Mx*ww; Jptr[12] = My*ww; Jptr[13] = ww; - Jptr[14] = -Mx*ww*yi; Jptr[15] = -My*ww*yi; + Jptr[6] = -Mx*ww*xi; Jptr[7] = -My*ww*xi; Jptr[8] = -ww*xi; + Jptr[12] = Mx*ww; Jptr[13] = My*ww; Jptr[14] = ww; + Jptr[15] = -Mx*ww*yi; Jptr[16] = -My*ww*yi; Jptr[17] = -ww*yi; - Jptr += 16; + Jptr += 18; } } @@ -274,7 +274,7 @@ class HomographyRefineCallback CV_FINAL : public LMSolver::Callback Mat src, dst; }; -} // end namesapce cv +} // end namespace cv namespace cv{ static bool createAndRunRHORegistrator(double confidence, @@ -426,6 +426,7 @@ cv::Mat cv::findHomography( InputArray _points1, InputArray _points2, cb->runKernel( src, dst, H ); Mat H8(9, 1, CV_64F, H.ptr()); LMSolver::create(makePtr(src, dst), 10)->run(H8); + H.convertTo(H, H.type(), scaleFor(H.at(2,2))); } } diff --git a/modules/calib3d/test/test_homography.cpp b/modules/calib3d/test/test_homography.cpp index 6a9cdcdd725f..d8ab243a840c 100644 --- a/modules/calib3d/test/test_homography.cpp +++ b/modules/calib3d/test/test_homography.cpp @@ -727,4 +727,40 @@ TEST(Calib3d_Homography, not_normalized) } } +TEST(Calib3d_Homography, Refine) +{ + Mat_ p1({10, 2}, {41, -86, -87, 99, 66, -96, -86, -8, -67, 24, + -87, -76, -19, 89, 37, -4, -86, -86, -66, -53}); + Mat_ p2({10, 2}, { + 0.007723226608700208, -1.177541410622515, + -0.1909072353027552, -0.4247610181930323, + -0.134992319993638, -0.6469949816560389, + -0.3570627451405215, 0.1811469436293486, + -0.3005671881038939, -0.02325733734262935, + -0.4404509481789249, 0.4851526464158342, + 0.6343346428859541, -3.396187657072353, + -0.3539383967092603, 0.1469447227353143, + -0.4526924606856586, 0.5296757109061794, + -0.4309974583614644, 0.4522732662733471 + }); + hconcat(p1, Mat::ones(p1.rows, 1, CV_64F), p1); + hconcat(p2, Mat::ones(p2.rows, 1, CV_64F), p2); + + for(int method : std::vector({0, RANSAC, LMEDS})) + { + Mat h = findHomography(p1, p2, method); + EXPECT_NEAR(h.at(2, 2), 1.0, 1e-7); + + Mat proj = p1 * h.t(); + proj.col(0) /= proj.col(2); + proj.col(1) /= proj.col(2); + + Mat error; + cv::pow(p2.colRange(0, 2) - proj.colRange(0, 2), 2, error); + cv::reduce(error, error, 1, REDUCE_SUM); + cv::reduce(error, error, 0, REDUCE_AVG); + EXPECT_LE(sqrt(error.at(0, 0)), method == LMEDS ? 7e-4 : 7e-5); + } +} + }} // namespace From 1bd5ca1ebe3279d5492f95f6c080475ef03fd74d Mon Sep 17 00:00:00 2001 From: Kumataro Date: Sun, 2 Jun 2024 20:14:04 +0900 Subject: [PATCH 102/119] Merge pull request #25686 from Kumataro:fix25674 Suppress build warnings for GCC14 #25686 Close #25674 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/core/test/test_mat.cpp | 2 +- modules/dnn/src/tensorflow/tf_importer.cpp | 2 +- modules/dnn/src/torch/torch_importer.cpp | 2 +- modules/gapi/src/compiler/passes/exec.cpp | 2 +- .../gapi/src/streaming/onevpl/file_data_provider.hpp | 2 +- modules/ts/include/opencv2/ts/ts_gtest.h | 11 +++++++++++ 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index 23a00a7effb6..d13fd96f5776 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -601,7 +601,7 @@ static void setValue(SparseMat& M, const int* idx, double value, RNG& rng) CV_Error(cv::Error::StsUnsupportedFormat, ""); } -#if defined(__GNUC__) && (__GNUC__ == 11 || __GNUC__ == 12 || __GNUC__ == 13) +#if defined(__GNUC__) && (__GNUC__ >= 11) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Warray-bounds" #endif diff --git a/modules/dnn/src/tensorflow/tf_importer.cpp b/modules/dnn/src/tensorflow/tf_importer.cpp index bd7ed3e02c99..3e73037a6017 100644 --- a/modules/dnn/src/tensorflow/tf_importer.cpp +++ b/modules/dnn/src/tensorflow/tf_importer.cpp @@ -260,7 +260,7 @@ const tensorflow::AttrValue& getLayerAttr(const tensorflow::NodeDef &layer, cons return layer.attr().at(name); } -#if defined(__GNUC__) && (__GNUC__ == 13) +#if defined(__GNUC__) && (__GNUC__ >= 13) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdangling-reference" #endif diff --git a/modules/dnn/src/torch/torch_importer.cpp b/modules/dnn/src/torch/torch_importer.cpp index be4f3fe851ba..08822102c7f3 100644 --- a/modules/dnn/src/torch/torch_importer.cpp +++ b/modules/dnn/src/torch/torch_importer.cpp @@ -902,7 +902,7 @@ struct TorchImporter { readTorchTable(scalarParams, tensorParams); - float power; + float power = 1.0f; if (nnName == "Square") power = 2.0f; else if (nnName == "Sqrt") power = 0.5f; else if (nnName == "Power") power = scalarParams.get("pow", 1.0f); diff --git a/modules/gapi/src/compiler/passes/exec.cpp b/modules/gapi/src/compiler/passes/exec.cpp index a978e47b42c6..f5cb48162de1 100644 --- a/modules/gapi/src/compiler/passes/exec.cpp +++ b/modules/gapi/src/compiler/passes/exec.cpp @@ -158,7 +158,7 @@ namespace std::unordered_set cycle_causers; }; -#if defined(__GNUC__) && (__GNUC__ == 13) +#if defined(__GNUC__) && (__GNUC__ >= 13) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdangling-reference" #endif diff --git a/modules/gapi/src/streaming/onevpl/file_data_provider.hpp b/modules/gapi/src/streaming/onevpl/file_data_provider.hpp index 7e5e49b0e888..129c6a9d6845 100644 --- a/modules/gapi/src/streaming/onevpl/file_data_provider.hpp +++ b/modules/gapi/src/streaming/onevpl/file_data_provider.hpp @@ -21,7 +21,7 @@ namespace onevpl { // With gcc13, std::unique_ptr(FILE, decltype(&fclose)> causes ignored-attributes warning. // See https://stackoverflow.com/questions/76849365/can-we-add-attributes-to-standard-function-declarations-without-breaking-standar -#if defined(__GNUC__) && (__GNUC__ == 13) +#if defined(__GNUC__) && (__GNUC__ >= 13) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wignored-attributes" #endif diff --git a/modules/ts/include/opencv2/ts/ts_gtest.h b/modules/ts/include/opencv2/ts/ts_gtest.h index b6a953592f14..49eb3a5ec79b 100644 --- a/modules/ts/include/opencv2/ts/ts_gtest.h +++ b/modules/ts/include/opencv2/ts/ts_gtest.h @@ -21317,6 +21317,13 @@ AssertionResult CmpHelperEQFailure(const char* lhs_expression, false); } +// See https://github.com/opencv/opencv/issues/25674 +// Disable optimization for workaround to mis-branch for GCC14. +#if defined(__GNUC__) && (__GNUC__ == 14) +#pragma GCC push_options +#pragma GCC optimize ("O0") +#endif + // The helper function for {ASSERT|EXPECT}_EQ. template AssertionResult CmpHelperEQ(const char* lhs_expression, @@ -21330,6 +21337,10 @@ AssertionResult CmpHelperEQ(const char* lhs_expression, return CmpHelperEQFailure(lhs_expression, rhs_expression, lhs, rhs); } +#if defined(__GNUC__) && (__GNUC__ == 14) +#pragma GCC pop_options +#endif + // With this overloaded version, we allow anonymous enums to be used // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums // can be implicitly cast to BiggestInt. From a7e53aa1846ada1c4de6986a0d02bd7c740d2eec Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Sun, 2 Jun 2024 13:28:06 +0200 Subject: [PATCH 103/119] Merge pull request #25671 from savuor:rv/arithm_extend_tests Tests added for mixed type arithmetic operations #25671 ### Changes * added accuracy tests for mixed type arithmetic operations _Note: div-by-zero values are removed from checking since the result is implementation-defined in common case_ * added perf tests for the same cases * fixed a typo in `getMulExtTab()` function that lead to dead code ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/core/perf/perf_arithm.cpp | 254 ++++++++++++++++++++++++++++++ modules/core/src/arithm.cpp | 2 +- modules/core/test/test_arithm.cpp | 210 +++++++++++++++++++----- modules/ts/include/opencv2/ts.hpp | 4 +- modules/ts/src/ts_func.cpp | 111 ++++++++----- 5 files changed, 494 insertions(+), 87 deletions(-) diff --git a/modules/core/perf/perf_arithm.cpp b/modules/core/perf/perf_arithm.cpp index f14382059c5e..36f400e34f53 100644 --- a/modules/core/perf/perf_arithm.cpp +++ b/modules/core/perf/perf_arithm.cpp @@ -452,6 +452,260 @@ INSTANTIATE_TEST_CASE_P(/*nothing*/ , BinaryOpTest, ) ); +///////////// Mixed type arithmetics //////// + +typedef perf::TestBaseWithParam>> ArithmMixedTest; + +PERF_TEST_P_(ArithmMixedTest, add) +{ + auto p = GetParam(); + Size sz = get<0>(p); + int srcType = get<0>(get<1>(p)); + int dstType = get<1>(get<1>(p)); + + cv::Mat a = Mat(sz, srcType); + cv::Mat b = Mat(sz, srcType); + cv::Mat c = Mat(sz, dstType); + + declare.in(a, b, WARMUP_RNG).out(c); + declare.time(50); + + if (CV_MAT_DEPTH(dstType) == CV_32S) + { + //see ticket 1529: add can be without saturation on 32S + a /= 2; + b /= 2; + } + + TEST_CYCLE() cv::add(a, b, c, /* mask */ noArray(), dstType); + + SANITY_CHECK_NOTHING(); +} + +PERF_TEST_P_(ArithmMixedTest, addScalarDouble) +{ + auto p = GetParam(); + Size sz = get<0>(p); + int srcType = get<0>(get<1>(p)); + int dstType = get<1>(get<1>(p)); + + cv::Mat a = Mat(sz, srcType); + cv::Scalar b; + cv::Mat c = Mat(sz, dstType); + + declare.in(a, b, WARMUP_RNG).out(c); + + if (CV_MAT_DEPTH(dstType) == CV_32S) + { + //see ticket 1529: add can be without saturation on 32S + a /= 2; + b /= 2; + } + + TEST_CYCLE() cv::add(a, b, c, /* mask */ noArray(), dstType); + + SANITY_CHECK_NOTHING(); +} + +PERF_TEST_P_(ArithmMixedTest, addScalarSameType) +{ + auto p = GetParam(); + Size sz = get<0>(p); + int srcType = get<0>(get<1>(p)); + int dstType = get<1>(get<1>(p)); + + cv::Mat a = Mat(sz, srcType); + cv::Scalar b; + cv::Mat c = Mat(sz, dstType); + + declare.in(a, b, WARMUP_RNG).out(c); + + if (CV_MAT_DEPTH(dstType) < CV_32S) + { + b = Scalar(1, 0, 3, 4); // don't pass non-integer values for 8U/8S/16U/16S processing + } + else if (CV_MAT_DEPTH(dstType) == CV_32S) + { + //see ticket 1529: add can be without saturation on 32S + a /= 2; + b = Scalar(1, 0, -3, 4); // don't pass non-integer values for 32S processing + } + + TEST_CYCLE() cv::add(a, b, c, /* mask */ noArray(), dstType); + + SANITY_CHECK_NOTHING(); +} + +PERF_TEST_P_(ArithmMixedTest, subtract) +{ + auto p = GetParam(); + Size sz = get<0>(p); + int srcType = get<0>(get<1>(p)); + int dstType = get<1>(get<1>(p)); + + cv::Mat a = Mat(sz, srcType); + cv::Mat b = Mat(sz, srcType); + cv::Mat c = Mat(sz, dstType); + + declare.in(a, b, WARMUP_RNG).out(c); + + if (CV_MAT_DEPTH(dstType) == CV_32S) + { + //see ticket 1529: subtract can be without saturation on 32S + a /= 2; + b /= 2; + } + + TEST_CYCLE() cv::subtract(a, b, c, /* mask */ noArray(), dstType); + + SANITY_CHECK_NOTHING(); +} + +PERF_TEST_P_(ArithmMixedTest, subtractScalarDouble) +{ + auto p = GetParam(); + Size sz = get<0>(p); + int srcType = get<0>(get<1>(p)); + int dstType = get<1>(get<1>(p)); + + cv::Mat a = Mat(sz, srcType); + cv::Scalar b; + cv::Mat c = Mat(sz, dstType); + + declare.in(a, b, WARMUP_RNG).out(c); + + if (CV_MAT_DEPTH(dstType) == CV_32S) + { + //see ticket 1529: subtract can be without saturation on 32S + a /= 2; + b /= 2; + } + + TEST_CYCLE() cv::subtract(a, b, c, /* mask */ noArray(), dstType); + + SANITY_CHECK_NOTHING(); +} + +PERF_TEST_P_(ArithmMixedTest, subtractScalarSameType) +{ + auto p = GetParam(); + Size sz = get<0>(p); + int srcType = get<0>(get<1>(p)); + int dstType = get<1>(get<1>(p)); + + cv::Mat a = Mat(sz, srcType); + cv::Scalar b; + cv::Mat c = Mat(sz, dstType); + + declare.in(a, b, WARMUP_RNG).out(c); + + if (CV_MAT_DEPTH(dstType) < CV_32S) + { + b = Scalar(1, 0, 3, 4); // don't pass non-integer values for 8U/8S/16U/16S processing + } + else if (CV_MAT_DEPTH(dstType) == CV_32S) + { + //see ticket 1529: subtract can be without saturation on 32S + a /= 2; + b = Scalar(1, 0, -3, 4); // don't pass non-integer values for 32S processing + } + + TEST_CYCLE() cv::subtract(a, b, c, /* mask */ noArray(), dstType); + + SANITY_CHECK_NOTHING(); +} + +PERF_TEST_P_(ArithmMixedTest, multiply) +{ + auto p = GetParam(); + Size sz = get<0>(p); + int srcType = get<0>(get<1>(p)); + int dstType = get<1>(get<1>(p)); + + cv::Mat a(sz, srcType), b(sz, srcType), c(sz, dstType); + + declare.in(a, b, WARMUP_RNG).out(c); + if (CV_MAT_DEPTH(dstType) == CV_32S) + { + //According to docs, saturation is not applied when result is 32bit integer + a /= (2 << 16); + b /= (2 << 16); + } + + TEST_CYCLE() cv::multiply(a, b, c, /* scale */ 1.0, dstType); + + SANITY_CHECK_NOTHING(); +} + +PERF_TEST_P_(ArithmMixedTest, multiplyScale) +{ + auto p = GetParam(); + Size sz = get<0>(p); + int srcType = get<0>(get<1>(p)); + int dstType = get<1>(get<1>(p)); + + cv::Mat a(sz, srcType), b(sz, srcType), c(sz, dstType); + double scale = 0.5; + + declare.in(a, b, WARMUP_RNG).out(c); + + if (CV_MAT_DEPTH(dstType) == CV_32S) + { + //According to docs, saturation is not applied when result is 32bit integer + a /= (2 << 16); + b /= (2 << 16); + } + + TEST_CYCLE() cv::multiply(a, b, c, scale, dstType); + + SANITY_CHECK_NOTHING(); +} + +PERF_TEST_P_(ArithmMixedTest, divide) +{ + auto p = GetParam(); + Size sz = get<0>(p); + int srcType = get<0>(get<1>(p)); + int dstType = get<1>(get<1>(p)); + + cv::Mat a(sz, srcType), b(sz, srcType), c(sz, dstType); + double scale = 0.5; + + declare.in(a, b, WARMUP_RNG).out(c); + + TEST_CYCLE() cv::divide(a, b, c, scale, dstType); + + SANITY_CHECK_NOTHING(); +} + +PERF_TEST_P_(ArithmMixedTest, reciprocal) +{ + auto p = GetParam(); + Size sz = get<0>(p); + int srcType = get<0>(get<1>(p)); + int dstType = get<1>(get<1>(p)); + + cv::Mat b(sz, srcType), c(sz, dstType); + double scale = 0.5; + + declare.in(b, WARMUP_RNG).out(c); + + TEST_CYCLE() cv::divide(scale, b, c, dstType); + + SANITY_CHECK_NOTHING(); +} + +INSTANTIATE_TEST_CASE_P(/*nothing*/ , ArithmMixedTest, + testing::Combine( + testing::Values(szVGA, sz720p, sz1080p), + testing::Values(std::tuple{CV_8U, CV_16U}, + std::tuple{CV_8S, CV_16S}, + std::tuple{CV_8U, CV_32F}, + std::tuple{CV_8S, CV_32F} + ) + ) +); + ///////////// Rotate //////////////////////// typedef perf::TestBaseWithParam> RotateTest; diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index 1a2eb3d9973e..08e1f613ef7a 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -1081,7 +1081,7 @@ static ExtendedTypeFunc getMulExtFunc(int src1Type, int src2Type, int dstType) { return mul8u16uWrapper; } - else if (src1Type == CV_8U && src2Type == CV_8S && dstType == CV_16S) + else if (src1Type == CV_8S && src2Type == CV_8S && dstType == CV_16S) { return mul8s16sWrapper; } diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index ed15c5dcbac9..6e4151c0cc81 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -15,7 +15,12 @@ const int ARITHM_MAX_SIZE_LOG = 10; struct BaseElemWiseOp { - enum { FIX_ALPHA=1, FIX_BETA=2, FIX_GAMMA=4, REAL_GAMMA=8, SUPPORT_MASK=16, SCALAR_OUTPUT=32, SUPPORT_MULTICHANNELMASK=64 }; + enum + { + FIX_ALPHA=1, FIX_BETA=2, FIX_GAMMA=4, REAL_GAMMA=8, + SUPPORT_MASK=16, SCALAR_OUTPUT=32, SUPPORT_MULTICHANNELMASK=64, + MIXED_TYPE=128 + }; BaseElemWiseOp(int _ninputs, int _flags, double _alpha, double _beta, Scalar _gamma=Scalar::all(0), int _context=1) : ninputs(_ninputs), flags(_flags), alpha(_alpha), beta(_beta), gamma(_gamma), context(_context) {} @@ -101,14 +106,15 @@ struct BaseAddOp : public BaseElemWiseOp void refop(const vector& src, Mat& dst, const Mat& mask) { - Mat temp; + int dstType = (flags & MIXED_TYPE) ? dst.type() : src[0].type(); if( !mask.empty() ) { - cvtest::add(src[0], alpha, src.size() > 1 ? src[1] : Mat(), beta, gamma, temp, src[0].type()); + Mat temp; + cvtest::add(src[0], alpha, src.size() > 1 ? src[1] : Mat(), beta, gamma, temp, dstType); cvtest::copy(temp, dst, mask); } else - cvtest::add(src[0], alpha, src.size() > 1 ? src[1] : Mat(), beta, gamma, dst, src[0].type()); + cvtest::add(src[0], alpha, src.size() > 1 ? src[1] : Mat(), beta, gamma, dst, dstType); } }; @@ -118,10 +124,8 @@ struct AddOp : public BaseAddOp AddOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat& mask) { - if( mask.empty() ) - cv::add(src[0], src[1], dst); - else - cv::add(src[0], src[1], dst, mask); + int dtype = (flags & MIXED_TYPE) ? dst.type() : -1; + cv::add(src[0], src[1], dst, mask, dtype); } }; @@ -131,10 +135,8 @@ struct SubOp : public BaseAddOp SubOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, -1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat& mask) { - if( mask.empty() ) - cv::subtract(src[0], src[1], dst); - else - cv::subtract(src[0], src[1], dst, mask); + int dtype = (flags & MIXED_TYPE) ? dst.type() : -1; + cv::subtract(src[0], src[1], dst, mask, dtype); } }; @@ -144,10 +146,8 @@ struct AddSOp : public BaseAddOp AddSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, 1, 0, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat& mask) { - if( mask.empty() ) - cv::add(src[0], gamma, dst); - else - cv::add(src[0], gamma, dst, mask); + int dtype = (flags & MIXED_TYPE) ? dst.type() : -1; + cv::add(src[0], gamma, dst, mask, dtype); } }; @@ -157,10 +157,8 @@ struct SubRSOp : public BaseAddOp SubRSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, -1, 0, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat& mask) { - if( mask.empty() ) - cv::subtract(gamma, src[0], dst); - else - cv::subtract(gamma, src[0], dst, mask); + int dtype = (flags & MIXED_TYPE) ? dst.type() : -1; + cv::subtract(gamma, src[0], dst, mask, dtype); } }; @@ -174,7 +172,7 @@ struct ScaleAddOp : public BaseAddOp } double getMaxErr(int depth) { - return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-4 : 1e-12; + return depth < CV_32F ? 1 : depth == CV_32F ? 3e-5 : 1e-12; } }; @@ -184,11 +182,8 @@ struct AddWeightedOp : public BaseAddOp AddWeightedOp() : BaseAddOp(2, REAL_GAMMA, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { - cv::addWeighted(src[0], alpha, src[1], beta, gamma[0], dst); - } - double getMaxErr(int depth) - { - return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-10; + int dtype = (flags & MIXED_TYPE) ? dst.type() : -1; + cv::addWeighted(src[0], alpha, src[1], beta, gamma[0], dst, dtype); } }; @@ -204,15 +199,35 @@ struct MulOp : public BaseElemWiseOp } void op(const vector& src, Mat& dst, const Mat&) { - cv::multiply(src[0], src[1], dst, alpha); + int dtype = (flags & MIXED_TYPE) ? dst.type() : -1; + cv::multiply(src[0], src[1], dst, alpha, dtype); } void refop(const vector& src, Mat& dst, const Mat&) { - cvtest::multiply(src[0], src[1], dst, alpha); + int dtype = (flags & MIXED_TYPE) ? dst.type() : -1; + cvtest::multiply(src[0], src[1], dst, alpha, dtype); } - double getMaxErr(int depth) +}; + +struct MulSOp : public BaseElemWiseOp +{ + MulSOp() : BaseElemWiseOp(1, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} + void getValueRange(int depth, double& minval, double& maxval) { - return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-12; + minval = depth < CV_32S ? cvtest::getMinVal(depth) : depth == CV_32S ? -1000000 : -1000.; + maxval = depth < CV_32S ? cvtest::getMaxVal(depth) : depth == CV_32S ? 1000000 : 1000.; + minval = std::max(minval, -30000.); + maxval = std::min(maxval, 30000.); + } + void op(const vector& src, Mat& dst, const Mat&) + { + int dtype = (flags & MIXED_TYPE) ? dst.type() : -1; + cv::multiply(src[0], alpha, dst, /* scale */ 1.0, dtype); + } + void refop(const vector& src, Mat& dst, const Mat&) + { + int dtype = (flags & MIXED_TYPE) ? dst.type() : -1; + cvtest::multiply(Mat(), src[0], dst, alpha, dtype); } }; @@ -221,15 +236,20 @@ struct DivOp : public BaseElemWiseOp DivOp() : BaseElemWiseOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { - cv::divide(src[0], src[1], dst, alpha); + int dtype = (flags & MIXED_TYPE) ? dst.type() : -1; + cv::divide(src[0], src[1], dst, alpha, dtype); + if (flags & MIXED_TYPE) + { + // div by zero result is implementation-defined + // since it may involve conversions to/from intermediate format + Mat zeroMask = src[1] == 0; + dst.setTo(0, zeroMask); + } } void refop(const vector& src, Mat& dst, const Mat&) { - cvtest::divide(src[0], src[1], dst, alpha); - } - double getMaxErr(int depth) - { - return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-12; + int dtype = (flags & MIXED_TYPE) ? dst.type() : -1; + cvtest::divide(src[0], src[1], dst, alpha, dtype); } }; @@ -238,15 +258,20 @@ struct RecipOp : public BaseElemWiseOp RecipOp() : BaseElemWiseOp(1, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { - cv::divide(alpha, src[0], dst); + int dtype = (flags & MIXED_TYPE) ? dst.type() : -1; + cv::divide(alpha, src[0], dst, dtype); + if (flags & MIXED_TYPE) + { + // div by zero result is implementation-defined + // since it may involve conversions to/from intermediate format + Mat zeroMask = src[0] == 0; + dst.setTo(0, zeroMask); + } } void refop(const vector& src, Mat& dst, const Mat&) { - cvtest::divide(Mat(), src[0], dst, alpha); - } - double getMaxErr(int depth) - { - return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-12; + int dtype = (flags & MIXED_TYPE) ? dst.type() : -1; + cvtest::divide(Mat(), src[0], dst, alpha, dtype); } }; @@ -1613,6 +1638,107 @@ INSTANTIATE_TEST_CASE_P(Core_MinMaxLoc, ElemWiseTest, ::testing::Values(ElemWise INSTANTIATE_TEST_CASE_P(Core_reduceArgMinMax, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new reduceArgMinMaxOp))); INSTANTIATE_TEST_CASE_P(Core_CartToPolarToCart, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new CartToPolarToCartOp))); +// Mixed Type Arithmetic Operations + +typedef std::tuple> SomeType; +class ArithmMixedTest : public ::testing::TestWithParam {}; + +TEST_P(ArithmMixedTest, accuracy) +{ + auto p = GetParam(); + ElemWiseOpPtr op = std::get<0>(p); + int srcDepth = std::get<0>(std::get<1>(p)); + int dstDepth = std::get<1>(std::get<1>(p)); + + op->flags |= BaseElemWiseOp::MIXED_TYPE; + int testIdx = 0; + RNG rng((uint64)ARITHM_RNG_SEED); + for( testIdx = 0; testIdx < ARITHM_NTESTS; testIdx++ ) + { + vector size; + op->getRandomSize(rng, size); + bool haveMask = ((op->flags & BaseElemWiseOp::SUPPORT_MASK) != 0) && rng.uniform(0, 4) == 0; + + double minval=0, maxval=0; + op->getValueRange(srcDepth, minval, maxval); + int ninputs = op->ninputs; + vector src(ninputs); + for(int i = 0; i < ninputs; i++ ) + src[i] = cvtest::randomMat(rng, size, srcDepth, minval, maxval, true); + Mat dst0, dst, mask; + if( haveMask ) + { + mask = cvtest::randomMat(rng, size, CV_8UC1, 0, 2, true); + } + + dst0 = cvtest::randomMat(rng, size, dstDepth, minval, maxval, false); + dst = cvtest::randomMat(rng, size, dstDepth, minval, maxval, true); + cvtest::copy(dst, dst0); + + op->generateScalars(dstDepth, rng); + + op->refop(src, dst0, mask); + op->op(src, dst, mask); + + double maxErr = op->getMaxErr(dstDepth); + ASSERT_PRED_FORMAT2(cvtest::MatComparator(maxErr, op->context), dst0, dst) << "\nsrc[0] ~ " << + cvtest::MatInfo(!src.empty() ? src[0] : Mat()) << "\ntestCase #" << testIdx << "\n"; + } +} + + +INSTANTIATE_TEST_CASE_P(Core_AddMixed, ArithmMixedTest, + ::testing::Combine(::testing::Values(ElemWiseOpPtr(new AddOp)), + ::testing::Values(std::tuple{CV_8U, CV_16U}, + std::tuple{CV_8S, CV_16S}, + std::tuple{CV_8U, CV_32F}, + std::tuple{CV_8S, CV_32F}))); +INSTANTIATE_TEST_CASE_P(Core_AddScalarMixed, ArithmMixedTest, + ::testing::Combine(::testing::Values(ElemWiseOpPtr(new AddSOp)), + ::testing::Values(std::tuple{CV_8U, CV_16U}, + std::tuple{CV_8S, CV_16S}, + std::tuple{CV_8U, CV_32F}, + std::tuple{CV_8S, CV_32F}))); +INSTANTIATE_TEST_CASE_P(Core_AddWeightedMixed, ArithmMixedTest, + ::testing::Combine(::testing::Values(ElemWiseOpPtr(new AddWeightedOp)), + ::testing::Values(std::tuple{CV_8U, CV_16U}, + std::tuple{CV_8S, CV_16S}, + std::tuple{CV_8U, CV_32F}, + std::tuple{CV_8S, CV_32F}))); +INSTANTIATE_TEST_CASE_P(Core_SubMixed, ArithmMixedTest, + ::testing::Combine(::testing::Values(ElemWiseOpPtr(new SubOp)), + ::testing::Values(std::tuple{CV_8U, CV_16U}, + std::tuple{CV_8S, CV_16S}, + std::tuple{CV_8U, CV_32F}, + std::tuple{CV_8S, CV_32F}))); +INSTANTIATE_TEST_CASE_P(Core_SubScalarMinusArgMixed, ArithmMixedTest, + ::testing::Combine(::testing::Values(ElemWiseOpPtr(new SubRSOp)), + ::testing::Values(std::tuple{CV_8U, CV_16U}, + std::tuple{CV_8S, CV_16S}, + std::tuple{CV_8U, CV_32F}, + std::tuple{CV_8S, CV_32F}))); +INSTANTIATE_TEST_CASE_P(Core_MulMixed, ArithmMixedTest, + ::testing::Combine(::testing::Values(ElemWiseOpPtr(new MulOp)), + ::testing::Values(std::tuple{CV_8U, CV_16U}, + std::tuple{CV_8S, CV_16S}, + std::tuple{CV_8U, CV_32F}, + std::tuple{CV_8S, CV_32F}))); +INSTANTIATE_TEST_CASE_P(Core_MulScalarMixed, ArithmMixedTest, + ::testing::Combine(::testing::Values(ElemWiseOpPtr(new MulSOp)), + ::testing::Values(std::tuple{CV_8U, CV_16U}, + std::tuple{CV_8S, CV_16S}, + std::tuple{CV_8U, CV_32F}, + std::tuple{CV_8S, CV_32F}))); +INSTANTIATE_TEST_CASE_P(Core_DivMixed, ArithmMixedTest, + ::testing::Combine(::testing::Values(ElemWiseOpPtr(new DivOp)), + ::testing::Values(std::tuple{CV_8U, CV_16U}, + std::tuple{CV_8S, CV_16S}, + std::tuple{CV_8U, CV_32F}, + std::tuple{CV_8S, CV_32F}))); +INSTANTIATE_TEST_CASE_P(Core_RecipMixed, ArithmMixedTest, + ::testing::Combine(::testing::Values(ElemWiseOpPtr(new RecipOp)), + ::testing::Values(std::tuple{CV_8U, CV_32F}, + std::tuple{CV_8S, CV_32F}))); TEST(Core_ArithmMask, uninitialized) { diff --git a/modules/ts/include/opencv2/ts.hpp b/modules/ts/include/opencv2/ts.hpp index a768d0047b48..83ef6fc7da6a 100644 --- a/modules/ts/include/opencv2/ts.hpp +++ b/modules/ts/include/opencv2/ts.hpp @@ -300,8 +300,8 @@ Mat randomMat(RNG& rng, Size size, int type, double minVal, double maxVal, bool Mat randomMat(RNG& rng, const vector& size, int type, double minVal, double maxVal, bool useRoi); void add(const Mat& a, double alpha, const Mat& b, double beta, Scalar gamma, Mat& c, int ctype, bool calcAbs=false); -void multiply(const Mat& a, const Mat& b, Mat& c, double alpha=1); -void divide(const Mat& a, const Mat& b, Mat& c, double alpha=1); +void multiply(const Mat& a, const Mat& b, Mat& c, double alpha=1, int ctype=-1); +void divide(const Mat& a, const Mat& b, Mat& c, double alpha=1, int ctype=-1); void convert(const Mat& src, cv::OutputArray dst, int dtype, double alpha=1, double beta=0); void copy(const Mat& src, Mat& dst, const Mat& mask=Mat(), bool invertMask=false); diff --git a/modules/ts/src/ts_func.cpp b/modules/ts/src/ts_func.cpp index cd027661488a..a4713290b1a8 100644 --- a/modules/ts/src/ts_func.cpp +++ b/modules/ts/src/ts_func.cpp @@ -2551,30 +2551,31 @@ void max(const Mat& src1, double val, Mat& dst) } -template static void -muldiv_(const _Tp* src1, const _Tp* src2, _Tp* dst, size_t total, double scale, char op) +template static void +muldiv_(const SrcType* src1, const SrcType* src2, DstType* dst, size_t total, double scale, char op) { - if( op == '*' ) - for( size_t i = 0; i < total; i++ ) - dst[i] = saturate_cast<_Tp>((scale*src1[i])*src2[i]); - else if( src1 ) - for( size_t i = 0; i < total; i++ ) - dst[i] = src2[i] ? saturate_cast<_Tp>((scale*src1[i])/src2[i]) : 0; - else - for( size_t i = 0; i < total; i++ ) - dst[i] = src2[i] ? saturate_cast<_Tp>(scale/src2[i]) : 0; + for( size_t i = 0; i < total; i++ ) + { + double m1 = src1 ? (double)src1[i] : 1.0; + double m2 = src2 ? (double)src2[i] : 1.0; + if (op == '/') + { + m2 = abs(m2) > FLT_EPSILON ? (1.0 / m2) : 0; + } + dst[i] = saturate_cast(scale * m1 * m2); + } } -static void muldiv(const Mat& src1, const Mat& src2, Mat& dst, double scale, char op) +static void muldiv(const Mat& src1, const Mat& src2, Mat& dst, int ctype, double scale, char op) { - dst.create(src2.dims, src2.size, src2.type()); + dst.create(src2.dims, src2.size, (ctype >= 0 ? ctype : src2.type())); CV_Assert( src1.empty() || (src1.type() == src2.type() && src1.size == src2.size) ); const Mat *arrays[]={&src1, &src2, &dst, 0}; Mat planes[3]; NAryMatIterator it(arrays, planes); size_t total = planes[1].total()*planes[1].channels(); - size_t i, nplanes = it.nplanes, depth = src2.depth(); + size_t i, nplanes = it.nplanes, srcDepth = src2.depth(), dstDepth = dst.depth(); for( i = 0; i < nplanes; i++, ++it ) { @@ -2582,44 +2583,70 @@ static void muldiv(const Mat& src1, const Mat& src2, Mat& dst, double scale, cha const uchar* sptr2 = planes[1].ptr(); uchar* dptr = planes[2].ptr(); - switch( depth ) + if (srcDepth == dstDepth) { - case CV_8U: - muldiv_((const uchar*)sptr1, (const uchar*)sptr2, (uchar*)dptr, total, scale, op); - break; - case CV_8S: - muldiv_((const schar*)sptr1, (const schar*)sptr2, (schar*)dptr, total, scale, op); - break; - case CV_16U: - muldiv_((const ushort*)sptr1, (const ushort*)sptr2, (ushort*)dptr, total, scale, op); - break; - case CV_16S: - muldiv_((const short*)sptr1, (const short*)sptr2, (short*)dptr, total, scale, op); - break; - case CV_32S: - muldiv_((const int*)sptr1, (const int*)sptr2, (int*)dptr, total, scale, op); - break; - case CV_32F: - muldiv_((const float*)sptr1, (const float*)sptr2, (float*)dptr, total, scale, op); - break; - case CV_64F: - muldiv_((const double*)sptr1, (const double*)sptr2, (double*)dptr, total, scale, op); - break; - default: - CV_Error(Error::StsUnsupportedFormat, ""); + switch( srcDepth ) + { + case CV_8U: + muldiv_((const uchar*)sptr1, (const uchar*)sptr2, (uchar*)dptr, total, scale, op); + break; + case CV_8S: + muldiv_((const schar*)sptr1, (const schar*)sptr2, (schar*)dptr, total, scale, op); + break; + case CV_16U: + muldiv_((const ushort*)sptr1, (const ushort*)sptr2, (ushort*)dptr, total, scale, op); + break; + case CV_16S: + muldiv_((const short*)sptr1, (const short*)sptr2, (short*)dptr, total, scale, op); + break; + case CV_32S: + muldiv_((const int*)sptr1, (const int*)sptr2, (int*)dptr, total, scale, op); + break; + case CV_32F: + muldiv_((const float*)sptr1, (const float*)sptr2, (float*)dptr, total, scale, op); + break; + case CV_64F: + muldiv_((const double*)sptr1, (const double*)sptr2, (double*)dptr, total, scale, op); + break; + default: + CV_Error(Error::StsUnsupportedFormat, ""); + } + } + else + { + if (srcDepth == CV_8U && dstDepth == CV_16U) + { + muldiv_((const uchar*)sptr1, (const uchar*)sptr2, (ushort*)dptr, total, scale, op); + } + else if (srcDepth == CV_8S && dstDepth == CV_16S) + { + muldiv_((const schar*)sptr1, (const schar*)sptr2, (short*)dptr, total, scale, op); + } + else if (srcDepth == CV_8U && dstDepth == CV_32F) + { + muldiv_((const uchar*)sptr1, (const uchar*)sptr2, (float*)dptr, total, scale, op); + } + else if (srcDepth == CV_8S && dstDepth == CV_32F) + { + muldiv_((const schar*)sptr1, (const schar*)sptr2, (float*)dptr, total, scale, op); + } + else + { + CV_Error(Error::StsUnsupportedFormat, "This format combination is not supported yet"); + } } } } -void multiply(const Mat& src1, const Mat& src2, Mat& dst, double scale) +void multiply(const Mat& src1, const Mat& src2, Mat& dst, double scale, int ctype) { - muldiv( src1, src2, dst, scale, '*' ); + muldiv( src1, src2, dst, ctype, scale, '*' ); } -void divide(const Mat& src1, const Mat& src2, Mat& dst, double scale) +void divide(const Mat& src1, const Mat& src2, Mat& dst, double scale, int ctype) { - muldiv( src1, src2, dst, scale, '/' ); + muldiv( src1, src2, dst, ctype, scale, '/' ); } From 71d3237a093b60a27601c20e9ee6c3e52154e8b1 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Sun, 2 Jun 2024 14:41:07 +0300 Subject: [PATCH 104/119] Release 4.10.0 --- modules/core/include/opencv2/core/version.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core/version.hpp b/modules/core/include/opencv2/core/version.hpp index 18bea5f3a4a6..80e3dc32bcde 100644 --- a/modules/core/include/opencv2/core/version.hpp +++ b/modules/core/include/opencv2/core/version.hpp @@ -8,7 +8,7 @@ #define CV_VERSION_MAJOR 4 #define CV_VERSION_MINOR 10 #define CV_VERSION_REVISION 0 -#define CV_VERSION_STATUS "-pre" +#define CV_VERSION_STATUS "" #define CVAUX_STR_EXP(__A) #__A #define CVAUX_STR(__A) CVAUX_STR_EXP(__A) From 3f26664e8d5a2c2788bf8b52671d2340de93d489 Mon Sep 17 00:00:00 2001 From: Patrick Keane Date: Mon, 3 Jun 2024 17:29:41 -0400 Subject: [PATCH 105/119] ISSUE-25700 update cv::FaceRecognizerSF class documentation --- modules/objdetect/include/opencv2/objdetect/face.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/objdetect/include/opencv2/objdetect/face.hpp b/modules/objdetect/include/opencv2/objdetect/face.hpp index bfa04cbd16eb..cf09c79d50dd 100644 --- a/modules/objdetect/include/opencv2/objdetect/face.hpp +++ b/modules/objdetect/include/opencv2/objdetect/face.hpp @@ -128,23 +128,23 @@ class CV_EXPORTS_W FaceRecognizerSF */ enum DisType { FR_COSINE=0, FR_NORM_L2=1 }; - /** @brief Aligning image to put face on the standard position + /** @brief Aligns detected face with the source input image and crops it * @param src_img input image - * @param face_box the detection result used for indicate face in input image + * @param face_box the detected face result from the input image * @param aligned_img output aligned image */ CV_WRAP virtual void alignCrop(InputArray src_img, InputArray face_box, OutputArray aligned_img) const = 0; - /** @brief Extracting face feature from aligned image + /** @brief Extracts face feature from aligned image * @param aligned_img input aligned image * @param face_feature output face feature */ CV_WRAP virtual void feature(InputArray aligned_img, OutputArray face_feature) = 0; - /** @brief Calculating the distance between two face features + /** @brief Calculates the distance between two face features * @param face_feature1 the first input feature * @param face_feature2 the second input feature of the same size and the same type as face_feature1 - * @param dis_type defining the similarity with optional values "FR_OSINE" or "FR_NORM_L2" + * @param dis_type defines how to calculate the distance between two face features with optional values "FR_COSINE" or "FR_NORM_L2" */ CV_WRAP virtual double match(InputArray face_feature1, InputArray face_feature2, int dis_type = FaceRecognizerSF::FR_COSINE) const = 0; From 2bb8b2b173774b302a4af7f7978a14be5d26d54c Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Tue, 4 Jun 2024 11:07:22 +0300 Subject: [PATCH 106/119] Disable more G-API streaming test due to unstability. --- modules/gapi/test/infer/gapi_infer_ie_test.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/gapi/test/infer/gapi_infer_ie_test.cpp b/modules/gapi/test/infer/gapi_infer_ie_test.cpp index 3998d68099fd..a7c9637a4f72 100644 --- a/modules/gapi/test/infer/gapi_infer_ie_test.cpp +++ b/modules/gapi/test/infer/gapi_infer_ie_test.cpp @@ -1825,6 +1825,9 @@ TEST(InferList, TestStreamingInfer) TEST(Infer2, TestStreamingInfer) { + if (cvtest::skipUnstableTests) + throw SkipTestException("Skip InferROI.TestStreamingInfer as it hangs sporadically"); + initDLDTDataPath(); std::string filepath = findDataFile("cv/video/768x576.avi"); From 9c05b27ba0619f28ee15b42c309500b6f0958cc1 Mon Sep 17 00:00:00 2001 From: cudawarped <12133430+cudawarped@users.noreply.github.com> Date: Tue, 4 Jun 2024 18:50:06 +0300 Subject: [PATCH 107/119] cuda: Add missing python CUDA dependency when CUDA is a first class language --- modules/python/python_loader.cmake | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/python/python_loader.cmake b/modules/python/python_loader.cmake index 4226b8273658..41dce57c18e6 100644 --- a/modules/python/python_loader.cmake +++ b/modules/python/python_loader.cmake @@ -68,8 +68,14 @@ if(DEFINED OPENCV_PYTHON_INSTALL_PATH) endif() set(CMAKE_PYTHON_BINARIES_PATH "${CMAKE_PYTHON_BINARIES_INSTALL_PATH}") if (WIN32 AND HAVE_CUDA) - 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 (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')") + 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')") + endif() endif() endif() string(REPLACE ";" ",\n " CMAKE_PYTHON_BINARIES_PATH "${CMAKE_PYTHON_BINARIES_PATH}") From b77c74b6fc79f6dca2da0fb5694ba57037310caf Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Tue, 4 Jun 2024 14:44:39 +0300 Subject: [PATCH 108/119] imgproc: fixed imread with output image argument, minor refactoring, fixes in HDR --- modules/imgcodecs/src/grfmt_hdr.cpp | 16 +++- modules/imgcodecs/src/loadsave.cpp | 97 +++++++--------------- modules/imgcodecs/test/test_png.cpp | 13 --- modules/imgcodecs/test/test_read_write.cpp | 29 +++++++ 4 files changed, 72 insertions(+), 83 deletions(-) diff --git a/modules/imgcodecs/src/grfmt_hdr.cpp b/modules/imgcodecs/src/grfmt_hdr.cpp index 6e2f565e3283..3a18b5bbebc4 100644 --- a/modules/imgcodecs/src/grfmt_hdr.cpp +++ b/modules/imgcodecs/src/grfmt_hdr.cpp @@ -93,10 +93,18 @@ bool HdrDecoder::readData(Mat& _img) RGBE_ReadPixels_RLE(file, const_cast(img.ptr()), img.cols, img.rows); fclose(file); file = NULL; - if(_img.depth() == img.depth()) { - img.convertTo(_img, _img.type()); - } else { - img.convertTo(_img, _img.type(), 255); + // NOTE: 'img' has type CV32FC3 + switch (_img.depth()) + { + case CV_8U: img.convertTo(img, _img.depth(), 255); break; + case CV_32F: break; + default: CV_Error(Error::StsError, "Wrong expected image depth, allowed: CV_8U and CV_32F"); + } + switch (_img.channels()) + { + case 1: cvtColor(img, _img, COLOR_BGR2GRAY); break; + case 3: img.copyTo(_img); break; + default: CV_Error(Error::StsError, "Wrong expected image channels, allowed: 1 and 3"); } return true; } diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index 2586fc1fa4b1..ec4760b8796d 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -81,6 +81,22 @@ static Size validateInputImageSize(const Size& size) } +static inline int calcType(int type, int flags) +{ + if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED ) + { + if( (flags & IMREAD_ANYDEPTH) == 0 ) + type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type)); + + if( (flags & IMREAD_COLOR) != 0 || + ((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) ) + type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3); + else + type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1); + } + return type; +} + namespace { class ByteStreamBuffer: public std::streambuf @@ -328,7 +344,7 @@ static ImageEncoder findEncoder( const String& _ext ) } -static void ExifTransform(int orientation, Mat& img) +static void ExifTransform(int orientation, OutputArray img) { switch( orientation ) { @@ -365,7 +381,7 @@ static void ExifTransform(int orientation, Mat& img) } } -static void ApplyExifOrientation(ExifEntry_t orientationTag, Mat& img) +static void ApplyExifOrientation(ExifEntry_t orientationTag, OutputArray img) { int orientation = IMAGE_ORIENTATION_TL; @@ -385,7 +401,7 @@ static void ApplyExifOrientation(ExifEntry_t orientationTag, Mat& img) * */ static bool -imread_( const String& filename, int flags, Mat& mat ) +imread_( const String& filename, int flags, OutputArray mat ) { /// Search for the relevant decoder to handle the imagery ImageDecoder decoder; @@ -444,18 +460,7 @@ imread_( const String& filename, int flags, Mat& mat ) Size size = validateInputImageSize(Size(decoder->width(), decoder->height())); // grab the decoded type - int type = decoder->type(); - if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED ) - { - if( (flags & IMREAD_ANYDEPTH) == 0 ) - type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type)); - - if( (flags & IMREAD_COLOR) != 0 || - ((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) ) - type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3); - else - type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1); - } + const int type = calcType(decoder->type(), flags); if (mat.empty()) { @@ -469,11 +474,16 @@ imread_( const String& filename, int flags, Mat& mat ) } // read the image data + Mat real_mat = mat.getMat(); + const void * original_ptr = real_mat.data; bool success = false; try { - if (decoder->readData(mat)) + if (decoder->readData(real_mat)) + { + CV_CheckTrue(original_ptr == real_mat.data, "Internal imread issue"); success = true; + } } catch (const cv::Exception& e) { @@ -567,18 +577,7 @@ imreadmulti_(const String& filename, int flags, std::vector& mats, int star while (current < count) { // grab the decoded type - int type = decoder->type(); - if ((flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED) - { - if ((flags & IMREAD_ANYDEPTH) == 0) - type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type)); - - if ((flags & IMREAD_COLOR) != 0 || - ((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1)) - type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3); - else - type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1); - } + const int type = calcType(decoder->type(), flags); // established the required input image size Size size = validateInputImageSize(Size(decoder->width(), decoder->height())); @@ -645,10 +644,8 @@ void imread( const String& filename, OutputArray dst, int flags ) { CV_TRACE_FUNCTION(); - Mat img = dst.getMat(); - /// load the data - imread_(filename, flags, img); + imread_(filename, flags, dst); } /** @@ -884,18 +881,7 @@ imdecode_( const Mat& buf, int flags, Mat& mat ) // established the required input image size Size size = validateInputImageSize(Size(decoder->width(), decoder->height())); - int type = decoder->type(); - if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED ) - { - if( (flags & IMREAD_ANYDEPTH) == 0 ) - type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type)); - - if( (flags & IMREAD_COLOR) != 0 || - ((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) ) - type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3); - else - type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1); - } + const int type = calcType(decoder->type(), flags); mat.create( size.height, size.width, type ); @@ -1046,18 +1032,7 @@ imdecodemulti_(const Mat& buf, int flags, std::vector& mats, int start, int while (current < count) { // grab the decoded type - int type = decoder->type(); - if ((flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED) - { - if ((flags & IMREAD_ANYDEPTH) == 0) - type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type)); - - if ((flags & IMREAD_COLOR) != 0 || - ((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1)) - type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3); - else - type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1); - } + const int type = calcType(decoder->type(), flags); // established the required input image size Size size = validateInputImageSize(Size(decoder->width(), decoder->height())); @@ -1316,17 +1291,7 @@ bool ImageCollection::Impl::readHeader() { // readHeader must be called before calling this method Mat ImageCollection::Impl::readData() { - int type = m_decoder->type(); - if ((m_flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && m_flags != IMREAD_UNCHANGED) { - if ((m_flags & IMREAD_ANYDEPTH) == 0) - type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type)); - - if ((m_flags & IMREAD_COLOR) != 0 || - ((m_flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1)) - type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3); - else - type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1); - } + const int type = calcType(m_decoder->type(), m_flags); // established the required input image size Size size = validateInputImageSize(Size(m_width, m_height)); diff --git a/modules/imgcodecs/test/test_png.cpp b/modules/imgcodecs/test/test_png.cpp index 655c59430d4b..cdc7da39b282 100644 --- a/modules/imgcodecs/test/test_png.cpp +++ b/modules/imgcodecs/test/test_png.cpp @@ -7,19 +7,6 @@ namespace opencv_test { namespace { #if defined(HAVE_PNG) || defined(HAVE_SPNG) -TEST(Imgcodecs_Png, imread_passing_mat) -{ - const string root = cvtest::TS::ptr()->get_data_path(); - const string imgName = root + "../cv/shared/lena.png"; - - Mat ref = imread(imgName); - Mat img(ref.size(), ref.type()); - void* ptr = img.data; - imread(imgName, img); - EXPECT_EQ(cv::norm(ref, img, NORM_INF), 0); - EXPECT_EQ(img.data, ptr); -} - TEST(Imgcodecs_Png, write_big) { const string root = cvtest::TS::ptr()->get_data_path(); diff --git a/modules/imgcodecs/test/test_read_write.cpp b/modules/imgcodecs/test/test_read_write.cpp index 39c02ca95cea..824688b366be 100644 --- a/modules/imgcodecs/test/test_read_write.cpp +++ b/modules/imgcodecs/test/test_read_write.cpp @@ -282,6 +282,35 @@ TEST(Imgcodecs_Image, regression_9376) EXPECT_EQ(32, m.rows); } +TEST(Imgcodecs_Image, imread_overload) +{ + const string root = cvtest::TS::ptr()->get_data_path(); + const string imgName = findDataFile("../highgui/readwrite/ordinary.bmp"); + + Mat ref = imread(imgName); + ASSERT_FALSE(ref.empty()); + { + Mat img(ref.size(), ref.type(), Scalar::all(0)); // existing image + void * ptr = img.data; + imread(imgName, img); + ASSERT_FALSE(img.empty()); + EXPECT_EQ(cv::norm(ref, img, NORM_INF), 0); + EXPECT_EQ(img.data, ptr); // no reallocation + } + { + Mat img; // empty image + imread(imgName, img); + ASSERT_FALSE(img.empty()); + EXPECT_EQ(cv::norm(ref, img, NORM_INF), 0); + } + { + UMat img; // empty UMat + imread(imgName, img); + ASSERT_FALSE(img.empty()); + EXPECT_EQ(cv::norm(ref, img, NORM_INF), 0); + } +} + //================================================================================================== TEST(Imgcodecs_Image, write_umat) From 99f32f17b481a7ab387c3f4f177b343dad5d1e64 Mon Sep 17 00:00:00 2001 From: Alexander Lyulkov Date: Wed, 5 Jun 2024 19:17:49 +0300 Subject: [PATCH 109/119] Added potential fix for Android H264 Encoding Bug --- modules/videoio/src/cap_android_mediandk.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/videoio/src/cap_android_mediandk.cpp b/modules/videoio/src/cap_android_mediandk.cpp index 2f8b19340405..87d5114ab411 100644 --- a/modules/videoio/src/cap_android_mediandk.cpp +++ b/modules/videoio/src/cap_android_mediandk.cpp @@ -587,6 +587,7 @@ class AndroidMediaNdkVideoWriter CV_FINAL : LOGE("ERROR: AMediaCodec_createInputSurface (%d)", status); goto error; } + ANativeWindow_setBuffersGeometry(surface, width, height, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM); #endif AMediaCodec_start(encoder); From 5dd7b5f0e5f639c6d477166cd1a8e204a7a91cb4 Mon Sep 17 00:00:00 2001 From: Vadim Levin Date: Thu, 6 Jun 2024 11:51:10 +0300 Subject: [PATCH 110/119] fix: mark floodFill mask as optional in Python typing stubs --- modules/python/src2/typing_stubs_generation/api_refinement.py | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/python/src2/typing_stubs_generation/api_refinement.py b/modules/python/src2/typing_stubs_generation/api_refinement.py index b04bb4a19681..994b80201855 100644 --- a/modules/python/src2/typing_stubs_generation/api_refinement.py +++ b/modules/python/src2/typing_stubs_generation/api_refinement.py @@ -325,6 +325,7 @@ def _find_argument_index(arguments: Sequence[FunctionNode.Arg], NODES_TO_REFINE = { SymbolName(("cv", ), (), "resize"): make_optional_arg("dsize"), SymbolName(("cv", ), (), "calcHist"): make_optional_arg("mask"), + SymbolName(("cv", ), (), "floodFill"): make_optional_arg("mask"), } ERROR_CLASS_PROPERTIES = ( From cbc08514fde2002ea8aaf87145f021d7df20ba26 Mon Sep 17 00:00:00 2001 From: Alexander Panov Date: Thu, 6 Jun 2024 14:22:58 +0300 Subject: [PATCH 111/119] updated testSeveralBoardsWithCustomIds to enable in 5.x --- modules/objdetect/test/test_charucodetection.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/objdetect/test/test_charucodetection.cpp b/modules/objdetect/test/test_charucodetection.cpp index 47166fa78e82..b85558627e03 100644 --- a/modules/objdetect/test/test_charucodetection.cpp +++ b/modules/objdetect/test/test_charucodetection.cpp @@ -866,12 +866,14 @@ TEST(Charuco, testSeveralBoardsWithCustomIds) detector2.detectBoard(gray, c_corners2, c_ids2, corners, ids); ASSERT_EQ(ids.size(), size_t(16)); - ASSERT_EQ(c_corners1.rows, expected_corners.rows); - EXPECT_NEAR(0, cvtest::norm(expected_corners, c_corners1.reshape(1), NORM_INF), 3e-1); + // In 4.x detectBoard() returns the charuco corners in a 2D Mat with shape (N_corners, 1) + // In 5.x, after PR #23473, detectBoard() returns the charuco corners in a 1D Mat with shape (1, N_corners) + ASSERT_EQ(expected_corners.total(), c_corners1.total()*c_corners1.channels()); + EXPECT_NEAR(0., cvtest::norm(expected_corners.reshape(1, 1), c_corners1.reshape(1, 1), NORM_INF), 3e-1); - ASSERT_EQ(c_corners2.rows, expected_corners.rows); + ASSERT_EQ(expected_corners.total(), c_corners2.total()*c_corners2.channels()); expected_corners.col(0) += 500; - EXPECT_NEAR(0, cvtest::norm(expected_corners, c_corners2.reshape(1), NORM_INF), 3e-1); + EXPECT_NEAR(0., cvtest::norm(expected_corners.reshape(1, 1), c_corners2.reshape(1, 1), NORM_INF), 3e-1); } }} // namespace From adcb0703965d2835eb76d040ae0a5e0fa151566b Mon Sep 17 00:00:00 2001 From: Maxim Milashchenko <67949029+MaximMilashchenko@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:31:59 +0300 Subject: [PATCH 112/119] Merge pull request #25307 from MaximMilashchenko:halrvv071 * added hal for cv_hal_cvtBGRtoBGR rvv 0.7.1 --- 3rdparty/hal_rvv/CMakeLists.txt | 9 ++ 3rdparty/hal_rvv/hal_rvv.hpp | 24 +++++ 3rdparty/hal_rvv/version/hal_rvv_071.hpp | 107 +++++++++++++++++++++++ CMakeLists.txt | 13 +++ 4 files changed, 153 insertions(+) create mode 100644 3rdparty/hal_rvv/CMakeLists.txt create mode 100644 3rdparty/hal_rvv/hal_rvv.hpp create mode 100644 3rdparty/hal_rvv/version/hal_rvv_071.hpp diff --git a/3rdparty/hal_rvv/CMakeLists.txt b/3rdparty/hal_rvv/CMakeLists.txt new file mode 100644 index 000000000000..814af987d912 --- /dev/null +++ b/3rdparty/hal_rvv/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION ${MIN_VER_CMAKE} FATAL_ERROR) + +set(HAL_LIB_NAME "") + +set(RVV_HAL_FOUND TRUE CACHE INTERNAL "") +set(RVV_HAL_VERSION "0.0.1" CACHE INTERNAL "") +set(RVV_HAL_LIBRARIES ${HAL_LIB_NAME} CACHE INTERNAL "") +set(RVV_HAL_HEADERS "hal_rvv.hpp" CACHE INTERNAL "") +set(RVV_HAL_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "") diff --git a/3rdparty/hal_rvv/hal_rvv.hpp b/3rdparty/hal_rvv/hal_rvv.hpp new file mode 100644 index 000000000000..8bb3545aabab --- /dev/null +++ b/3rdparty/hal_rvv/hal_rvv.hpp @@ -0,0 +1,24 @@ +// 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. + +#ifndef OPENCV_HAL_RVV_HPP_INCLUDED +#define OPENCV_HAL_RVV_HPP_INCLUDED + +#include + +#include "opencv2/core/hal/interface.h" + +#ifndef CV_HAL_RVV_071_ENABLED +# if defined(__GNUC__) && __GNUC__ == 10 && __GNUC_MINOR__ == 4 && defined(__THEAD_VERSION__) && defined(__riscv_v) && __riscv_v == 7000 +# define CV_HAL_RVV_071_ENABLED 1 +# else +# define CV_HAL_RVV_071_ENABLED 0 +# endif +#endif + +#if CV_HAL_RVV_071_ENABLED +#include "version/hal_rvv_071.hpp" +#endif + +#endif \ No newline at end of file diff --git a/3rdparty/hal_rvv/version/hal_rvv_071.hpp b/3rdparty/hal_rvv/version/hal_rvv_071.hpp new file mode 100644 index 000000000000..f86f8c363a25 --- /dev/null +++ b/3rdparty/hal_rvv/version/hal_rvv_071.hpp @@ -0,0 +1,107 @@ +// 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. + +#ifndef OPENCV_HAL_RVV_071_HPP_INCLUDED +#define OPENCV_HAL_RVV_071_HPP_INCLUDED + +#include + +namespace cv { namespace cv_hal_rvv { + +#undef cv_hal_cvtBGRtoBGR +#define cv_hal_cvtBGRtoBGR cv::cv_hal_rvv::cvtBGRtoBGR + +static const unsigned char index_array_32 [32] + { 2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15, 18, 17, 16, 19, 22, 21, 20, 23, 26, 25, 24, 27, 30, 29, 28, 31 }; + +static const unsigned char index_array_24 [24] + { 2, 1, 0, 5, 4, 3, 8, 7, 6, 11, 10, 9, 14, 13, 12, 17, 16, 15, 20, 19, 18, 23, 22, 21 }; + +static void vBGRtoBGR(const unsigned char* src, unsigned char * dst, const unsigned char * index, int n, int scn, int dcn, int vsize_pixels, const int vsize) +{ + vuint8m2_t vec_index = vle8_v_u8m2(index, vsize); + + int i = 0; + + for ( ; i <= n-vsize; i += vsize_pixels, src += vsize, dst += vsize) + { + vuint8m2_t vec_src = vle8_v_u8m2(src, vsize); + vuint8m2_t vec_dst = vrgather_vv_u8m2(vec_src, vec_index, vsize); + vse8_v_u8m2(dst, vec_dst, vsize); + } + + for ( ; i < n; i++, src += scn, dst += dcn ) + { + unsigned char t0 = src[0], t1 = src[1], t2 = src[2]; + dst[2] = t0; + dst[1] = t1; + dst[0] = t2; + if(dcn == 4) + { + unsigned char d = src[3]; + dst[3] = d; + } + } +} + +static void sBGRtoBGR(const unsigned char* src, unsigned char * dst, int n, int scn, int dcn, int bi) +{ + for (int i = 0; i < n; i++, src += scn, dst += dcn) + { + unsigned char t0 = src[0], t1 = src[1], t2 = src[2]; + dst[bi ] = t0; + dst[1] = t1; + dst[bi^2] = t2; + if(dcn == 4) + { + unsigned char d = scn == 4 ? src[3] : std::numeric_limits::max(); + dst[3] = d; + } + } +} + +static int cvtBGRtoBGR(const unsigned char * src_data, size_t src_step, unsigned char * dst_data, size_t dst_step, int width, int height, int depth, int scn, int dcn, bool swapBlue) +{ + if (depth != CV_8U) + { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + const int blueIdx = swapBlue ? 2 : 0; + if (scn == dcn) + { + if (!swapBlue) + { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + const int vsize_pixels = 8; + + if (scn == 4) + { + for (int i = 0; i < height; i++, src_data += src_step, dst_data += dst_step) + { + vBGRtoBGR(src_data, dst_data, index_array_32, width, scn, dcn, vsize_pixels, 32); + } + } + else + { + for (int i = 0; i < height; i++, src_data += src_step, dst_data += dst_step) + { + vBGRtoBGR(src_data, dst_data, index_array_24, width, scn, dcn, vsize_pixels, 24); + } + } + } + else + { + for (int i = 0; i < height; i++, src_data += src_step, dst_data += dst_step) + sBGRtoBGR(src_data, dst_data, width, scn, dcn, blueIdx); + } + + return CV_HAL_ERROR_OK; +} + +}} + +#endif diff --git a/CMakeLists.txt b/CMakeLists.txt index f5e39b4c71be..a61b43abe457 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -265,6 +265,8 @@ OCV_OPTION(WITH_KLEIDICV "Use KleidiCV library for ARM platforms" OFF VISIBLE_IF (AARCH64 AND (ANDROID OR UNIX AND NOT IOS AND NOT XROS))) OCV_OPTION(WITH_NDSRVP "Use Andes RVP extension" (NOT CV_DISABLE_OPTIMIZATION) VISIBLE_IF RISCV) +OCV_OPTION(WITH_HAL_RVV "Use HAL RVV optimizations" (NOT CV_DISABLE_OPTIMIZATION) + VISIBLE_IF RISCV) OCV_OPTION(WITH_CPUFEATURES "Use cpufeatures Android library" ON VISIBLE_IF ANDROID VERIFY HAVE_CPUFEATURES) @@ -994,6 +996,13 @@ if(WITH_NDSRVP) endif() endif() +if(WITH_HAL_RVV) + ocv_debug_message(STATUS "Enable HAL RVV acceleration") + if(NOT ";${OpenCV_HAL};" MATCHES ";halrvv;") + set(OpenCV_HAL "halrvv;${OpenCV_HAL}") + endif() +endif() + foreach(hal ${OpenCV_HAL}) if(hal STREQUAL "carotene") if(";${CPU_BASELINE_FINAL};" MATCHES ";NEON;") @@ -1023,6 +1032,10 @@ foreach(hal ${OpenCV_HAL}) else() message(STATUS "NDSRVP: Andes GNU Toolchain DSP extension is not open, disabling ndsrvp...") endif() + elseif(hal STREQUAL "halrvv") + add_subdirectory(3rdparty/hal_rvv/) + ocv_hal_register(RVV_HAL_LIBRARIES RVV_HAL_HEADERS RVV_HAL_INCLUDE_DIRS) + list(APPEND OpenCV_USED_HAL "HAL RVV (ver ${RVV_HAL_VERSION})") elseif(hal STREQUAL "openvx") add_subdirectory(3rdparty/openvx) ocv_hal_register(OPENVX_HAL_LIBRARIES OPENVX_HAL_HEADERS OPENVX_HAL_INCLUDE_DIRS) From ef3303716efe65a5cd53368dfcbed7c272d56d31 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Thu, 6 Jun 2024 17:29:34 +0300 Subject: [PATCH 113/119] test: use cv::theRNG instead of own generator --- modules/core/test/test_math.cpp | 2 +- modules/ts/include/opencv2/ts.hpp | 3 +-- modules/ts/src/ts.cpp | 5 ----- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index cffe1bb5378b..024177f1a104 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -135,7 +135,7 @@ double Core_PowTest::get_success_error_level( int test_case_idx, int i, int j ) return power == cvRound(power) && power >= 0 ? 0 : 1; else { - return depth != CV_64F ? Base::get_success_error_level( test_case_idx, i, j ) : DBL_EPSILON*1024*1.1; + return depth != CV_64F ? Base::get_success_error_level( test_case_idx, i, j ) : DBL_EPSILON*1024*1.11; } } diff --git a/modules/ts/include/opencv2/ts.hpp b/modules/ts/include/opencv2/ts.hpp index 83ef6fc7da6a..943da1d06747 100644 --- a/modules/ts/include/opencv2/ts.hpp +++ b/modules/ts/include/opencv2/ts.hpp @@ -611,7 +611,7 @@ class TS }; // get RNG to generate random input data for a test - RNG& get_rng() { return rng; } + RNG& get_rng() { return cv::theRNG(); } // returns the current error code TS::FailureCode get_err_code() { return TS::FailureCode(current_test_info.code); } @@ -629,7 +629,6 @@ class TS protected: // these are allocated within a test to try to keep them valid in case of stack corruption - RNG rng; // information about the current test TestInfo current_test_info; diff --git a/modules/ts/src/ts.cpp b/modules/ts/src/ts.cpp index 2d795cd3a2c1..fb60a18ff1be 100644 --- a/modules/ts/src/ts.cpp +++ b/modules/ts/src/ts.cpp @@ -591,8 +591,6 @@ void TS::init( const string& modulename ) if( params.use_optimized == 0 ) cv::setUseOptimized(false); - - rng = RNG(params.rng_seed); } @@ -635,9 +633,6 @@ void TS::update_context( BaseTest* test, int test_case_idx, bool update_ts_conte { current_test_info.rng_seed = param_seed + test_case_idx; current_test_info.rng_seed0 = current_test_info.rng_seed; - - rng = RNG(current_test_info.rng_seed); - cv::theRNG() = rng; } current_test_info.test = test; From 3700f9e1e932ca1aaa15db70534cb78b6e44ce05 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Fri, 7 Jun 2024 20:39:44 +0300 Subject: [PATCH 114/119] Merge pull request #25709 from dkurt:wrap_addLayer * Wrap dnn addLayer * Add typing stubs --- modules/dnn/include/opencv2/dnn/dnn.hpp | 4 ++-- modules/dnn/misc/python/pyopencv_dnn.hpp | 16 ++++++++++++++++ modules/dnn/misc/python/test/test_dnn.py | 16 ++++++++++++++++ .../typing_stubs_generation/predefined_types.py | 7 +++++++ 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index fd9129010475..b516f80bde7a 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -533,7 +533,7 @@ CV__DNN_INLINE_NS_BEGIN * @param params parameters which will be used to initialize the creating layer. * @returns unique identifier of created layer, or -1 if a failure will happen. */ - int addLayer(const String &name, const String &type, const int &dtype, LayerParams ¶ms); + CV_WRAP int addLayer(const String &name, const String &type, const int &dtype, LayerParams ¶ms); /** @overload Datatype of output blobs set to default CV_32F */ int addLayer(const String &name, const String &type, LayerParams ¶ms); @@ -541,7 +541,7 @@ CV__DNN_INLINE_NS_BEGIN /** @brief Adds new layer and connects its first input to the first output of previously added layer. * @see addLayer() */ - int addLayerToPrev(const String &name, const String &type, const int &dtype, LayerParams ¶ms); + CV_WRAP int addLayerToPrev(const String &name, const String &type, const int &dtype, LayerParams ¶ms); /** @overload */ int addLayerToPrev(const String &name, const String &type, LayerParams ¶ms); diff --git a/modules/dnn/misc/python/pyopencv_dnn.hpp b/modules/dnn/misc/python/pyopencv_dnn.hpp index d729cd8b9779..0fc0c45e821b 100644 --- a/modules/dnn/misc/python/pyopencv_dnn.hpp +++ b/modules/dnn/misc/python/pyopencv_dnn.hpp @@ -71,6 +71,22 @@ PyObject* pyopencv_from(const dnn::LayerParams& lp) return dict; } +template<> +bool pyopencv_to(PyObject *o, dnn::LayerParams &lp, const ArgInfo& info) +{ + CV_Assert(PyDict_Check(o)); + PyObject *key, *value; + Py_ssize_t pos = 0; + std::string keyName; + while (PyDict_Next(o, &pos, &key, &value)) { + getUnicodeString(key, keyName); + dnn::DictValue dv; + pyopencv_to(value, dv, info); + lp.set(keyName, dv); + } + return true; +} + template<> PyObject* pyopencv_from(const std::vector &t) { diff --git a/modules/dnn/misc/python/test/test_dnn.py b/modules/dnn/misc/python/test/test_dnn.py index da3409c3b3db..e3cc376dd269 100644 --- a/modules/dnn/misc/python/test/test_dnn.py +++ b/modules/dnn/misc/python/test/test_dnn.py @@ -480,5 +480,21 @@ def test_scalefactor_assign(self): params.scalefactor = 2.0 self.assertEqual(params.scalefactor, (2.0, 0.0, 0.0, 0.0)) + def test_net_builder(self): + net = cv.dnn.Net() + params = { + "kernel_w": 3, + "kernel_h": 3, + "stride_w": 3, + "stride_h": 3, + "pool": "max", + } + net.addLayerToPrev("pool", "Pooling", cv.CV_32F, params) + + inp = np.random.standard_normal([1, 2, 9, 12]).astype(np.float32) + net.setInput(inp) + out = net.forward() + self.assertEqual(out.shape, (1, 2, 3, 4)) + if __name__ == '__main__': NewOpenCVTests.bootstrap() diff --git a/modules/python/src2/typing_stubs_generation/predefined_types.py b/modules/python/src2/typing_stubs_generation/predefined_types.py index f5ba0bc29ec2..5aed93c8b0d6 100644 --- a/modules/python/src2/typing_stubs_generation/predefined_types.py +++ b/modules/python/src2/typing_stubs_generation/predefined_types.py @@ -194,6 +194,13 @@ export_name="ExtractMetaCallback" ), AliasTypeNode.class_("LayerId", "DictValue"), + AliasTypeNode.dict_("LayerParams", + key_type=PrimitiveTypeNode.str_(), + value_type=UnionTypeNode("DictValue", items=( + PrimitiveTypeNode.int_(), + PrimitiveTypeNode.float_(), + PrimitiveTypeNode.str_()) + )), PrimitiveTypeNode.int_("cvflann_flann_distance_t"), PrimitiveTypeNode.int_("flann_flann_distance_t"), PrimitiveTypeNode.int_("cvflann_flann_algorithm_t"), From cc6f85e1bab6942acf107e4cacf813347f0552c1 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Mon, 10 Jun 2024 09:42:56 +0300 Subject: [PATCH 115/119] Merge pull request #25427 from MaximSmolskiy:make-finding-corner-neighbor-symmetrical-in-ChessBoardDetector-findQuadNeighbors Make finding corner neighbor symmetrical in ChessBoardDetector::findQuadNeighbors #25427 ### Pull Request Readiness Checklist The basic idea of finding pair of corners neighbors is to find best candidate for first corner and check if first corner quite good candidate for its best candidate. And we test first corner for its best candidate less than best candidate for first corner. Idea of changes is to make finding corner neighbor symmetrical - find best candidate for first corner, find best candidate for second corner and match them as pair iff they are both best candidates for each other. Additional advantage - it simplifies code and removes some code duplication. I tested this PR with benchmark ``` python3 objdetect_benchmark.py --configuration=generate_run --board_x=7 --path=res_chessboard --synthetic_object=chessboard ``` There are minor changes in results ``` cell_img_size = 100 (default) before category detected chessboard total detected chessboard total chessboard average detected error chessboard _none_none_blur 1.000000 360 360 0.630345 _none_none_gaussNoise 0.833333 300 360 0.623405 _none_none_none 1.000000 360 360 0.631517 _none_none_strongBlur 1.000000 360 360 0.630316 _none_undistorted_blur 1.000000 360 360 0.671232 _none_undistorted_gaussNoise 1.000000 360 360 0.672619 _none_undistorted_none 1.000000 360 360 0.673669 _none_undistorted_strongBlur 1.000000 360 360 0.671257 _perspective_none_blur 1.000000 1080 1080 0.588694 _perspective_none_gaussNoise 0.805556 870 1080 0.599312 _perspective_none_none 1.000000 1080 1080 0.591063 _perspective_none_strongBlur 1.000000 1080 1080 0.588604 _perspective_undistorted_blur 1.000000 1080 1080 0.622081 _perspective_undistorted_gaussNoise 1.000000 1080 1080 0.625704 _perspective_undistorted_none 1.000000 1080 1080 0.624191 _perspective_undistorted_strongBlur 1.000000 1080 1080 0.621618 _strongPerspective_none_blur 1.000000 360 360 0.482934 _strongPerspective_none_gaussNoise 0.166667 60 360 0.391551 _strongPerspective_none_none 1.000000 360 360 0.480290 _strongPerspective_none_strongBlur 0.333333 120 360 0.469080 _strongPerspective_undistorted_blur 1.000000 360 360 0.503458 _strongPerspective_undistorted_gaussNoise 0.250000 90 360 0.448713 _strongPerspective_undistorted_none 1.000000 360 360 0.504412 _strongPerspective_undistorted_strongBlur 0.166667 60 360 0.473791 all 0.904167 13020 14400 0.600512 Total detected time: 139.65614900000008 sec after category detected chessboard total detected chessboard total chessboard average detected error chessboard _none_none_blur 1.000000 360 360 0.630345 _none_none_gaussNoise 0.750000 270 360 0.636279 _none_none_none 1.000000 360 360 0.631517 _none_none_strongBlur 1.000000 360 360 0.630316 _none_undistorted_blur 1.000000 360 360 0.671232 _none_undistorted_gaussNoise 1.000000 360 360 0.672619 _none_undistorted_none 1.000000 360 360 0.673669 _none_undistorted_strongBlur 1.000000 360 360 0.671257 _perspective_none_blur 1.000000 1080 1080 0.588694 _perspective_none_gaussNoise 0.888889 960 1080 0.594106 _perspective_none_none 1.000000 1080 1080 0.591064 _perspective_none_strongBlur 1.000000 1080 1080 0.588604 _perspective_undistorted_blur 1.000000 1080 1080 0.622081 _perspective_undistorted_gaussNoise 1.000000 1080 1080 0.625703 _perspective_undistorted_none 1.000000 1080 1080 0.624191 _perspective_undistorted_strongBlur 1.000000 1080 1080 0.621618 _strongPerspective_none_blur 1.000000 360 360 0.482934 _strongPerspective_none_gaussNoise 0.166667 60 360 0.391551 _strongPerspective_none_none 1.000000 360 360 0.480290 _strongPerspective_none_strongBlur 0.333333 120 360 0.469080 _strongPerspective_undistorted_blur 1.000000 360 360 0.503458 _strongPerspective_undistorted_gaussNoise 0.333333 120 360 0.422259 _strongPerspective_undistorted_none 1.000000 360 360 0.504412 _strongPerspective_undistorted_strongBlur 0.166667 60 360 0.473791 all 0.910417 13110 14400 0.599746 Total detected time: 142.40333700000005 sec ---------------------------------------------------------------------------------------------------------------------------------------------- cell_img_size = 10 before category detected chessboard total detected chessboard total chessboard average detected error chessboard _none_none_blur 0.991667 357 360 4.905091 _none_none_gaussNoise 0.750000 270 360 5.215633 _none_none_none 1.000000 360 360 4.943304 _none_none_strongBlur 0.916667 330 360 3.806217 _none_undistorted_blur 0.994444 358 360 5.220915 _none_undistorted_gaussNoise 0.997222 359 360 4.542443 _none_undistorted_none 0.997222 359 360 4.340208 _none_undistorted_strongBlur 0.161111 58 360 5.024331 _perspective_none_blur 0.629630 680 1080 4.825401 _perspective_none_gaussNoise 0.966667 1044 1080 3.895425 _perspective_none_none 0.971296 1049 1080 3.920378 _perspective_none_strongBlur 0.000000 0 1080 NaN _perspective_undistorted_blur 0.583333 630 1080 4.594335 _perspective_undistorted_gaussNoise 0.999074 1079 1080 3.553195 _perspective_undistorted_none 0.750000 810 1080 3.604110 _perspective_undistorted_strongBlur 0.000000 0 1080 NaN _strongPerspective_none_blur 0.000000 0 360 NaN _strongPerspective_none_gaussNoise 0.000000 0 360 NaN _strongPerspective_none_none 0.083333 30 360 2.382460 _strongPerspective_none_strongBlur 0.000000 0 360 NaN _strongPerspective_undistorted_blur 0.000000 0 360 NaN _strongPerspective_undistorted_gaussNoise 0.000000 0 360 NaN _strongPerspective_undistorted_none 0.000000 0 360 NaN _strongPerspective_undistorted_strongBlur 0.000000 0 360 NaN all 0.539792 7773 14400 4.209964 Total detected time: 2.6968930000000015 sec after category detected chessboard total detected chessboard total chessboard average detected error chessboard _none_none_blur 0.991667 357 360 4.905091 _none_none_gaussNoise 0.750000 270 360 5.215633 _none_none_none 1.000000 360 360 4.943304 _none_none_strongBlur 0.916667 330 360 3.806217 _none_undistorted_blur 0.994444 358 360 5.220915 _none_undistorted_gaussNoise 0.997222 359 360 4.542443 _none_undistorted_none 0.997222 359 360 4.340208 _none_undistorted_strongBlur 0.161111 58 360 5.024331 _perspective_none_blur 0.629630 680 1080 4.825401 _perspective_none_gaussNoise 0.966667 1044 1080 3.895425 _perspective_none_none 0.999074 1079 1080 3.865684 _perspective_none_strongBlur 0.000000 0 1080 NaN _perspective_undistorted_blur 0.583333 630 1080 4.594335 _perspective_undistorted_gaussNoise 0.999074 1079 1080 3.553195 _perspective_undistorted_none 0.750000 810 1080 3.604110 _perspective_undistorted_strongBlur 0.000000 0 1080 NaN _strongPerspective_none_blur 0.000000 0 360 NaN _strongPerspective_none_gaussNoise 0.000000 0 360 NaN _strongPerspective_none_none 0.000000 0 360 NaN _strongPerspective_none_strongBlur 0.000000 0 360 NaN _strongPerspective_undistorted_blur 0.000000 0 360 NaN _strongPerspective_undistorted_gaussNoise 0.000000 0 360 NaN _strongPerspective_undistorted_none 0.000000 0 360 NaN _strongPerspective_undistorted_strongBlur 0.000000 0 360 NaN all 0.539792 7773 14400 4.208308 Total detected time: 2.7706419999999983 sec ``` See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/calib3d/src/calibinit.cpp | 307 ++++++++++++++++++------------ 1 file changed, 184 insertions(+), 123 deletions(-) diff --git a/modules/calib3d/src/calibinit.cpp b/modules/calib3d/src/calibinit.cpp index 3e6c0bfdba7c..060ee5e15882 100644 --- a/modules/calib3d/src/calibinit.cpp +++ b/modules/calib3d/src/calibinit.cpp @@ -221,6 +221,26 @@ class ChessBoardDetector int all_quads_count; + struct NeighborsFinder { + const float thresh_scale = 1.f; + ChessBoardDetector& detector; + std::vector neighbors_indices; + std::vector neighbors_dists; + std::vector all_quads_pts; + flann::GenericIndex> all_quads_pts_index; + + NeighborsFinder(ChessBoardDetector& detector); + + bool findCornerNeighbor( + const int idx, + const cv::Point2f& pt, + float& min_dist, + const float radius, + int& closest_quad_idx, + int& closest_corner_idx, + cv::Point2f& closest_corner_pt); + }; + ChessBoardDetector(const Size& pattern_size_) : pattern_size(pattern_size_), all_quads_count(0) @@ -471,6 +491,125 @@ static void icvBinarizationHistogramBased(Mat & img) } } +static std::vector getCornersFromQuads(ChessBoardQuad* p_all_quads, const int all_quads_count) +{ + std::vector all_quads_pts; + all_quads_pts.reserve(all_quads_count * 4); + for (int idx = 0; idx < all_quads_count; idx++) + { + const ChessBoardQuad& cur_quad = (const ChessBoardQuad&)p_all_quads[idx]; + for (int i = 0; i < 4; i++) + all_quads_pts.push_back(cur_quad.corners[i]->pt); + } + return all_quads_pts; +} + +ChessBoardDetector::NeighborsFinder::NeighborsFinder(ChessBoardDetector& _detector) : + detector(_detector), + all_quads_pts(getCornersFromQuads(detector.all_quads.data(), detector.all_quads_count)), + all_quads_pts_index(Mat(all_quads_pts).reshape(1, detector.all_quads_count * 4), cvflann::KDTreeSingleIndexParams()) +{ + const int all_corners_count = detector.all_quads_count * 4; + neighbors_indices.resize(all_corners_count); + neighbors_dists.resize(all_corners_count); +} + +bool ChessBoardDetector::NeighborsFinder::findCornerNeighbor( + const int idx, + const cv::Point2f& pt, + float& min_dist, + const float radius, + int& closest_quad_idx, + int& closest_corner_idx, + cv::Point2f& closest_corner_pt) +{ + ChessBoardQuad* p_all_quads = detector.all_quads.data(); + + const ChessBoardQuad& cur_quad = (const ChessBoardQuad&)p_all_quads[idx]; + int closest_neighbor_idx = -1; + ChessBoardQuad *closest_quad = 0; + + // find the closest corner in all other quadrangles + const std::vector query = { pt.x, pt.y }; + const cvflann::SearchParams search_params(-1); + const int neighbors_count = all_quads_pts_index.radiusSearch(query, neighbors_indices, neighbors_dists, radius, search_params); + + for (int neighbor_idx_idx = 0; neighbor_idx_idx < neighbors_count; neighbor_idx_idx++) + { + const int neighbor_idx = neighbors_indices[neighbor_idx_idx]; + const int k = neighbor_idx >> 2; + if (k == idx) + continue; + + ChessBoardQuad& q_k = p_all_quads[k]; + const int j = neighbor_idx & 3; + if (q_k.neighbors[j]) + continue; + + const float dist = normL2Sqr(pt - all_quads_pts[neighbor_idx]); + if (dist <= cur_quad.edge_len * thresh_scale && + dist <= q_k.edge_len * thresh_scale) + { + // check edge lengths, make sure they're compatible + // edges that are different by more than 1:4 are rejected. + // edge_len is squared edge length, so we compare them + // with squared constant 16 = 4^2 + if (q_k.edge_len > 16 * cur_quad.edge_len || + cur_quad.edge_len > 16 * q_k.edge_len) + { + DPRINTF("Incompatible edge lengths"); + continue; + } + closest_neighbor_idx = neighbor_idx; + closest_quad_idx = k; + closest_corner_idx = j; + closest_quad = &q_k; + min_dist = dist; + break; + } + } + + // we found a matching corner point? + if (closest_neighbor_idx >= 0 && closest_quad_idx >= 0 && closest_corner_idx >= 0 && min_dist < FLT_MAX) + { + CV_Assert(closest_quad); + + if (cur_quad.count >= 4 || closest_quad->count >= 4) + return false; + + // If another point from our current quad is closer to the found corner + // than the current one, then we don't count this one after all. + // This is necessary to support small squares where otherwise the wrong + // corner will get matched to closest_quad; + closest_corner_pt = all_quads_pts[closest_neighbor_idx]; + + int j = 0; + for (; j < 4; j++) + { + if (cur_quad.neighbors[j] == closest_quad) + break; + + if (normL2Sqr(closest_corner_pt - all_quads_pts[(idx << 2) + j]) < min_dist) + break; + } + if (j < 4) + return false; + + // Check that each corner is a neighbor of different quads + for(j = 0; j < 4; j++ ) + { + if (closest_quad->neighbors[j] == &cur_quad) + break; + } + if (j < 4) + return false; + + return true; + } + + return false; +} + bool findChessboardCorners(InputArray image_, Size pattern_size, OutputArray corners_, int flags) { @@ -1607,25 +1746,7 @@ int ChessBoardDetector::checkQuadGroup(const std::vector& quad_ void ChessBoardDetector::findQuadNeighbors() { - const float thresh_scale = 1.f; - - const int all_corners_count = all_quads_count * 4; - - std::vector all_quads_pts; - all_quads_pts.reserve(all_corners_count); - for (int idx = 0; idx < all_quads_count; idx++) - { - const ChessBoardQuad& cur_quad = (const ChessBoardQuad&)all_quads[idx]; - for (int i = 0; i < 4; i++) - all_quads_pts.push_back(cur_quad.corners[i]->pt); - } - - const cvflann::KDTreeSingleIndexParams index_params; - flann::GenericIndex> all_quads_pts_index(Mat(all_quads_pts).reshape(1, all_corners_count), index_params); - - // find quad neighbors - std::vector neighbors_indices(all_corners_count); - std::vector neighbors_dists(all_corners_count); + NeighborsFinder neighborsFinder(*this); for (int idx = 0; idx < all_quads_count; idx++) { ChessBoardQuad& cur_quad = (ChessBoardQuad&)all_quads[idx]; @@ -1641,125 +1762,65 @@ void ChessBoardDetector::findQuadNeighbors() if (cur_quad.neighbors[i]) continue; - float min_dist = FLT_MAX; - int closest_neighbor_idx = -1; - int closest_corner_idx = -1; - ChessBoardQuad *closest_quad = 0; + const cv::Point2f pt = neighborsFinder.all_quads_pts[(idx << 2) + i]; - cv::Point2f pt = all_quads_pts[(idx << 2) + i]; - - // find the closest corner in all other quadrangles - std::vector query = Mat(pt); - float radius = cur_quad.edge_len * thresh_scale + 1; - const cvflann::SearchParams search_params(-1); - int neighbors_count = all_quads_pts_index.radiusSearch(query, neighbors_indices, neighbors_dists, radius, search_params); + float min_dist = FLT_MAX; - for (int neighbor_idx_idx = 0; neighbor_idx_idx < neighbors_count; neighbor_idx_idx++) - { - const int neighbor_idx = neighbors_indices[neighbor_idx_idx]; - const int k = neighbor_idx >> 2; - if (k == idx) - continue; - - ChessBoardQuad& q_k = all_quads[k]; - const int j = neighbor_idx & 3; - if (q_k.neighbors[j]) - continue; - - const float dist = normL2Sqr(pt - all_quads_pts[neighbor_idx]); - if (dist <= cur_quad.edge_len * thresh_scale && - dist <= q_k.edge_len * thresh_scale) - { - // check edge lengths, make sure they're compatible - // edges that are different by more than 1:4 are rejected. - // edge_len is squared edge length, so we compare them - // with squared constant 16 = 4^2 - if (q_k.edge_len > 16 * cur_quad.edge_len || - cur_quad.edge_len > 16 * q_k.edge_len) - { - DPRINTF("Incompatible edge lengths"); - continue; - } - closest_neighbor_idx = neighbor_idx; - closest_corner_idx = j; - closest_quad = &q_k; - min_dist = dist; - break; - } - } + int closest_quad_idx = -1; + int closest_corner_idx = -1; - // we found a matching corner point? - if (closest_neighbor_idx >= 0 && closest_corner_idx >= 0 && min_dist < FLT_MAX) - { - CV_Assert(closest_quad); + float radius = cur_quad.edge_len * neighborsFinder.thresh_scale + 1; - if (cur_quad.count >= 4 || closest_quad->count >= 4) - continue; + cv::Point2f closest_corner_pt; - // If another point from our current quad is closer to the found corner - // than the current one, then we don't count this one after all. - // This is necessary to support small squares where otherwise the wrong - // corner will get matched to closest_quad; - ChessBoardCorner& closest_corner = *closest_quad->corners[closest_corner_idx]; - cv::Point2f closest_corner_pt = all_quads_pts[closest_neighbor_idx]; + bool found = neighborsFinder.findCornerNeighbor( + idx, + pt, + min_dist, + radius, + closest_quad_idx, + closest_corner_idx, + closest_corner_pt); - int j = 0; - for (; j < 4; j++) - { - if (cur_quad.neighbors[j] == closest_quad) - break; + if (!found) + continue; - if (normL2Sqr(closest_corner_pt - all_quads_pts[(idx << 2) + j]) < min_dist) - break; - } - if (j < 4) - continue; + radius = min_dist + 1; + min_dist = FLT_MAX; - // Check that each corner is a neighbor of different quads - for(j = 0; j < 4; j++ ) - { - if (closest_quad->neighbors[j] == &cur_quad) - break; - } - if (j < 4) - continue; + int closest_closest_quad_idx = -1; + int closest_closest_corner_idx = -1; - // check whether the closest corner to closest_corner is different from pt - query = Mat(closest_corner_pt); - radius = min_dist + 1; - neighbors_count = all_quads_pts_index.radiusSearch(query, neighbors_indices, neighbors_dists, radius, search_params); + cv::Point2f closest_closest_corner_pt; - int neighbor_idx_idx = 0; - for (; neighbor_idx_idx < neighbors_count; neighbor_idx_idx++) - { - const int neighbor_idx = neighbors_indices[neighbor_idx_idx]; - j = neighbor_idx >> 2; + found = neighborsFinder.findCornerNeighbor( + closest_quad_idx, + closest_corner_pt, + min_dist, + radius, + closest_closest_quad_idx, + closest_closest_corner_idx, + closest_closest_corner_pt); - ChessBoardQuad* q = &const_cast(all_quads[j]); - if (j == idx || q == closest_quad) - continue; + if (!found) + continue; - const int k = neighbor_idx & 3; - CV_DbgAssert(q); - if (!q->neighbors[k]) - { - if (normL2Sqr(closest_corner_pt - all_quads_pts[neighbor_idx]) < min_dist) - break; - } - } - if (neighbor_idx_idx < neighbors_count) - continue; + if (closest_closest_quad_idx != idx || + closest_closest_corner_idx != i || + closest_closest_corner_pt != pt) + continue; - closest_corner.pt = (pt + closest_corner_pt) * 0.5f; + ChessBoardQuad* closest_quad = &all_quads[closest_quad_idx]; + ChessBoardCorner& closest_corner = *closest_quad->corners[closest_corner_idx]; + closest_corner.pt = (pt + closest_corner_pt) * 0.5f; - // We've found one more corner - remember it - cur_quad.count++; - cur_quad.neighbors[i] = closest_quad; - cur_quad.corners[i] = &closest_corner; + // We've found one more corner - remember it + cur_quad.count++; + cur_quad.neighbors[i] = closest_quad; + cur_quad.corners[i] = &closest_corner; - closest_quad->count++; - closest_quad->neighbors[closest_corner_idx] = &cur_quad; - } + closest_quad->count++; + closest_quad->neighbors[closest_corner_idx] = &cur_quad; } } } From bdf986ee519b01b0f451d1a3e71866d5027c0a47 Mon Sep 17 00:00:00 2001 From: Pierre Chatelier Date: Mon, 10 Jun 2024 10:09:25 +0200 Subject: [PATCH 116/119] Merge pull request #25726 from chacha21:remap_relative_doc Relates to #24603 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [X] I agree to contribute to the project under Apache 2 License. - [X] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [X] The PR is proposed to the proper branch - [X] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/imgproc/include/opencv2/imgproc.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 471a857f63fc..f4dad4f002e3 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -2485,7 +2485,10 @@ CV_EXPORTS_W void warpPerspective( InputArray src, OutputArray dst, The function remap transforms the source image using the specified map: \f[\texttt{dst} (x,y) = \texttt{src} (map_x(x,y),map_y(x,y))\f] -\f[\texttt{dst} (x,y) = \texttt{src} (x+map_x(x,y),y+map_y(x,y))\f] with WARP_RELATIVE_MAP + +with the WARP_RELATIVE_MAP flag : + +\f[\texttt{dst} (x,y) = \texttt{src} (x+map_x(x,y),y+map_y(x,y))\f] where values of pixels with non-integer coordinates are computed using one of available interpolation methods. \f$map_x\f$ and \f$map_y\f$ can be encoded as separate floating-point maps @@ -2506,7 +2509,7 @@ representation to fixed-point for speed. if map1 is (x,y) points), respectively. @param interpolation Interpolation method (see #InterpolationFlags). The methods #INTER_AREA #INTER_LINEAR_EXACT and #INTER_NEAREST_EXACT are not supported by this function. -The extra flag WARP_RELATIVE_MAP that can be ORed to the interpolation method +The extra flag WARP_RELATIVE_MAP can be ORed to the interpolation method (e.g. INTER_LINEAR | WARP_RELATIVE_MAP) @param borderMode Pixel extrapolation method (see #BorderTypes). When borderMode=#BORDER_TRANSPARENT, it means that the pixels in the destination image that From e1dba2c6d28c21cf0661005cd961a670e46375c2 Mon Sep 17 00:00:00 2001 From: Robert Lexmann Date: Mon, 10 Jun 2024 15:47:29 +0200 Subject: [PATCH 117/119] Perform arithmetics in CV_32F branch of divSpectrums() with doubles to prevent infs/NaNs (+ corresponding test). --- modules/imgproc/src/phasecorr.cpp | 12 ++++++------ modules/imgproc/test/test_pc.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/modules/imgproc/src/phasecorr.cpp b/modules/imgproc/src/phasecorr.cpp index dadc3a3da7f4..d2f88420be84 100644 --- a/modules/imgproc/src/phasecorr.cpp +++ b/modules/imgproc/src/phasecorr.cpp @@ -252,18 +252,18 @@ void divSpectrums( InputArray _srcA, InputArray _srcB, OutputArray _dst, int fla if( !conjB ) for( j = j0; j < j1; j += 2 ) { - double denom = (double)(dataB[j]*dataB[j] + dataB[j+1]*dataB[j+1] + eps); - double re = (double)(dataA[j]*dataB[j] + dataA[j+1]*dataB[j+1]); - double im = (double)(dataA[j+1]*dataB[j] - dataA[j]*dataB[j+1]); + double denom = (double)dataB[j]*dataB[j] + (double)dataB[j+1]*dataB[j+1] + (double)eps; + double re = (double)dataA[j]*dataB[j] + (double)dataA[j+1]*dataB[j+1]; + double im = (double)dataA[j+1]*dataB[j] - (double)dataA[j]*dataB[j+1]; dataC[j] = (float)(re / denom); dataC[j+1] = (float)(im / denom); } else for( j = j0; j < j1; j += 2 ) { - double denom = (double)(dataB[j]*dataB[j] + dataB[j+1]*dataB[j+1] + eps); - double re = (double)(dataA[j]*dataB[j] - dataA[j+1]*dataB[j+1]); - double im = (double)(dataA[j+1]*dataB[j] + dataA[j]*dataB[j+1]); + double denom = (double)dataB[j]*dataB[j] + (double)dataB[j+1]*dataB[j+1] + (double)eps; + double re = (double)dataA[j]*dataB[j] - (double)dataA[j+1]*dataB[j+1]; + double im = (double)dataA[j+1]*dataB[j] + (double)dataA[j]*dataB[j+1]; dataC[j] = (float)(re / denom); dataC[j+1] = (float)(im / denom); } diff --git a/modules/imgproc/test/test_pc.cpp b/modules/imgproc/test/test_pc.cpp index 87f0d804b2ea..969f5bcfa1a3 100644 --- a/modules/imgproc/test/test_pc.cpp +++ b/modules/imgproc/test/test_pc.cpp @@ -120,6 +120,35 @@ TEST(Imgproc_PhaseCorrelatorTest, accuracy_1d_odd_fft) { ASSERT_NEAR(phaseShift.x, (double)xShift, 1.); } +TEST(Imgproc_PhaseCorrelatorTest, float32_overflow) { + // load + Mat im = imread(cvtest::TS::ptr()->get_data_path() + "shared/baboon.png", IMREAD_GRAYSCALE); + ASSERT_EQ(im.type(), CV_8UC1); + + // convert to 32F, scale values as if original image was 16U + constexpr auto u8Max = std::numeric_limits::max(); + constexpr auto u16Max = std::numeric_limits::max(); + im.convertTo(im, CV_32FC1, double(u16Max) / double(u8Max)); + + // enlarge and create ROIs + const auto w = im.cols * 5; + const auto h = im.rows * 5; + const auto roiW = (w * 2) / 3; // 50% overlap + Mat imLarge; + resize(im, imLarge, { w, h }); + const auto roiLeft = imLarge(Rect(0, 0, roiW, h)); + const auto roiRight = imLarge(Rect(w - roiW, 0, roiW, h)); + + // correlate + double response = 0.0; + Point2d phaseShift = phaseCorrelate(roiLeft, roiRight, cv::noArray(), &response); + ASSERT_TRUE(std::isnormal(phaseShift.x) || 0.0 == phaseShift.x); + ASSERT_TRUE(std::isnormal(phaseShift.y) || 0.0 == phaseShift.y); + ASSERT_TRUE(std::isnormal(response) || 0.0 == response); + EXPECT_NEAR(std::abs(phaseShift.x), w / 3.0, 1.0); + EXPECT_NEAR(std::abs(phaseShift.y), 0.0, 1.0); +} + ////////////////////// DivSpectrums //////////////////////// class CV_DivSpectrumsTest : public cvtest::ArrayTest { From 3ea7ed9ebf926d53e2813ce2bde585b208aae167 Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Tue, 11 Jun 2024 09:12:38 +0200 Subject: [PATCH 118/119] Merge pull request #25718 from savuor:rv/hwasan_flag Android SDK build script: HWAsan support added #25718 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- platforms/android/build_sdk.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platforms/android/build_sdk.py b/platforms/android/build_sdk.py index 6e03698a5eb0..7ba3fb8e0d08 100755 --- a/platforms/android/build_sdk.py +++ b/platforms/android/build_sdk.py @@ -158,6 +158,7 @@ def __init__(self, workdir, opencvdir, config): self.debug = True if config.debug else False self.debug_info = True if config.debug_info else False self.no_samples_build = True if config.no_samples_build else False + self.hwasan = True if config.hwasan else False self.opencl = True if config.opencl else False self.no_kotlin = True if config.no_kotlin else False self.shared = True if config.shared else False @@ -265,6 +266,12 @@ def build_library(self, abi, do_install, no_media_ndk): if no_media_ndk: cmake_vars['WITH_ANDROID_MEDIANDK'] = "OFF" + if self.hwasan and "arm64" in abi.name: + hwasan_flags = "-fno-omit-frame-pointer -fsanitize=hwaddress" + cmake_vars['CMAKE_CXX_FLAGS_DEBUG'] = hwasan_flags + cmake_vars['CMAKE_C_FLAGS_DEBUG'] = hwasan_flags + cmake_vars['CMAKE_LINKER_FLAGS_DEBUG'] = hwasan_flags + cmake_vars.update(abi.cmake_vars) if len(self.disable) > 0: @@ -380,6 +387,7 @@ def get_ndk_dir(): parser.add_argument('--no_kotlin', action="store_true", help="Disable Kotlin extensions") parser.add_argument('--shared', action="store_true", help="Build shared libraries") parser.add_argument('--no_media_ndk', action="store_true", help="Do not link Media NDK (required for video I/O support)") + parser.add_argument('--hwasan', action="store_true", help="Enable Hardware Address Sanitizer on ARM64") parser.add_argument('--disable', metavar='FEATURE', default=[], action='append', help='OpenCV features to disable (add WITH_*=OFF). To disable multiple, specify this flag again, e.g. "--disable TBB --disable OPENMP"') args = parser.parse_args() From a03b81316782ae30038b288fd3568993fa1e3538 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Tue, 11 Jun 2024 12:01:51 +0300 Subject: [PATCH 119/119] Merge pull request #25732 from dkurt:opencv_js_tests_update Fix OpenCV.js tests #25732 ### Pull Request Readiness Checklist * Firefox tests passed See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/js/test/init_cv.js | 14 ++++++++++++++ modules/js/test/test_calib3d.js | 5 ----- modules/js/test/test_core.js | 5 ----- modules/js/test/test_features2d.js | 5 ----- modules/js/test/test_imgproc.js | 5 ----- modules/js/test/test_mat.js | 5 ----- modules/js/test/test_objdetect.js | 10 +++++++--- modules/js/test/test_photo.js | 6 ------ modules/js/test/test_utils.js | 4 ---- modules/js/test/test_video.js | 5 ----- modules/js/test/tests.js | 10 +++++++--- platforms/js/build_js.py | 2 +- 12 files changed, 29 insertions(+), 47 deletions(-) create mode 100644 modules/js/test/init_cv.js diff --git a/modules/js/test/init_cv.js b/modules/js/test/init_cv.js new file mode 100644 index 000000000000..d05370740784 --- /dev/null +++ b/modules/js/test/init_cv.js @@ -0,0 +1,14 @@ +// 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. + +if (cv instanceof Promise) { + QUnit.test("init_cv", (assert) => { + const done = assert.async(); + assert.ok(true); + cv.then((ready_cv) => { + cv = ready_cv; + done(); + }); + }); +} diff --git a/modules/js/test/test_calib3d.js b/modules/js/test/test_calib3d.js index b0001dbc6728..157658df5ee6 100644 --- a/modules/js/test/test_calib3d.js +++ b/modules/js/test/test_calib3d.js @@ -2,11 +2,6 @@ // 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. -if (typeof module !== 'undefined' && module.exports) { - // The environment is Node.js - var cv = require('./opencv.js'); // eslint-disable-line no-var -} - QUnit.module('Camera Calibration and 3D Reconstruction', {}); QUnit.test('constants', function(assert) { diff --git a/modules/js/test/test_core.js b/modules/js/test/test_core.js index 14d4ffe72b4c..bfd9d2cd0dad 100644 --- a/modules/js/test/test_core.js +++ b/modules/js/test/test_core.js @@ -2,11 +2,6 @@ // 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. -if (typeof module !== 'undefined' && module.exports) { - // The environment is Node.js - var cv = require('./opencv.js'); // eslint-disable-line no-var -} - QUnit.module('Core', {}); QUnit.test('test_LUT', function(assert) { diff --git a/modules/js/test/test_features2d.js b/modules/js/test/test_features2d.js index c5eb73a123be..7844da314696 100644 --- a/modules/js/test/test_features2d.js +++ b/modules/js/test/test_features2d.js @@ -2,11 +2,6 @@ // 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. -if (typeof module !== 'undefined' && module.exports) { - // The environment is Node.js - var cv = require('./opencv.js'); // eslint-disable-line no-var -} - function generateTestFrame(width, height) { let w = width || 200; let h = height || 200; diff --git a/modules/js/test/test_imgproc.js b/modules/js/test/test_imgproc.js index a0d2d937cc0a..65b3cb74af8d 100644 --- a/modules/js/test/test_imgproc.js +++ b/modules/js/test/test_imgproc.js @@ -68,11 +68,6 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -if (typeof module !== 'undefined' && module.exports) { - // The environment is Node.js - var cv = require('./opencv.js'); // eslint-disable-line no-var -} - QUnit.module('Image Processing', {}); QUnit.test('test_imgProc', function(assert) { diff --git a/modules/js/test/test_mat.js b/modules/js/test/test_mat.js index fd3611cd2c4e..a1d5c98b1793 100644 --- a/modules/js/test/test_mat.js +++ b/modules/js/test/test_mat.js @@ -68,11 +68,6 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -if (typeof module !== 'undefined' && module.exports) { - // The environment is Node.js - var cv = require('./opencv.js'); // eslint-disable-line no-var -} - QUnit.module('CoreMat', {}); QUnit.test('test_mat_creation', function(assert) { diff --git a/modules/js/test/test_objdetect.js b/modules/js/test/test_objdetect.js index e7190db33752..1339029b655e 100644 --- a/modules/js/test/test_objdetect.js +++ b/modules/js/test/test_objdetect.js @@ -68,11 +68,11 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +var haarcascade_data = undefined; if (typeof module !== 'undefined' && module.exports) { // The environment is Node.js - var cv = require('./opencv.js'); // eslint-disable-line no-var - cv.FS_createLazyFile('/', 'haarcascade_frontalface_default.xml', // eslint-disable-line new-cap - 'haarcascade_frontalface_default.xml', true, false); + let fs = require("fs"); + haarcascade_data = fs.readFileSync("haarcascade_frontalface_default.xml"); } QUnit.module('Object Detection', {}); @@ -99,6 +99,10 @@ QUnit.test('Cascade classification', function(assert) { // CascadeClassifier { + if (haarcascade_data) { + cv.FS_createDataFile("/", "haarcascade_frontalface_default.xml", haarcascade_data, true, false, false); + } + let classifier = new cv.CascadeClassifier(); const modelPath = '/haarcascade_frontalface_default.xml'; diff --git a/modules/js/test/test_photo.js b/modules/js/test/test_photo.js index 62f62173d0d2..f04e5071badd 100644 --- a/modules/js/test/test_photo.js +++ b/modules/js/test/test_photo.js @@ -40,12 +40,6 @@ // Author : Rijubrata Bhaumik, Intel Corporation. rijubrata.bhaumik[at]intel[dot]com -if (typeof module !== 'undefined' && module.exports) { - // The environment is Node.js - var cv = require('./opencv.js'); // eslint-disable-line no-var -} - - QUnit.module('Photo', {}); QUnit.test('test_photo', function(assert) { diff --git a/modules/js/test/test_utils.js b/modules/js/test/test_utils.js index 905ac3191a4e..03096aec749a 100644 --- a/modules/js/test/test_utils.js +++ b/modules/js/test/test_utils.js @@ -67,10 +67,6 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -if (typeof module !== 'undefined' && module.exports) { - // The environment is Node.js - var cv = require('./opencv.js'); // eslint-disable-line no-var -} QUnit.module('Utils', {}); QUnit.test('Test vectors', function(assert) { { diff --git a/modules/js/test/test_video.js b/modules/js/test/test_video.js index 3594c21ede73..13fb3beca63d 100644 --- a/modules/js/test/test_video.js +++ b/modules/js/test/test_video.js @@ -67,11 +67,6 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -if (typeof module !== 'undefined' && module.exports) { - // The environment is Node.js - var cv = require('./opencv.js'); // eslint-disable-line no-var -} - QUnit.module('Video', {}); QUnit.test('Background Segmentation', function(assert) { // BackgroundSubtractorMOG2 diff --git a/modules/js/test/tests.js b/modules/js/test/tests.js index 74a4b87e4599..b099fdb3c810 100644 --- a/modules/js/test/tests.js +++ b/modules/js/test/tests.js @@ -43,8 +43,9 @@ testrunner.options.maxBlockDuration = 20000; // cause opencv_js.js need time to testrunner.run( { - code: 'opencv.js', - tests: ['test_mat.js', + code: {path: "opencv.js", namespace: "cv"}, + tests: ['init_cv.js', + 'test_mat.js', 'test_utils.js', 'test_core.js', 'test_imgproc.js', @@ -57,7 +58,10 @@ testrunner.run( }, function(err, report) { console.log(report.failed + ' failed, ' + report.passed + ' passed'); - if (report.failed) { + if (report.failed || err) { + if (err) { + console.log(err); + } process.on('exit', function() { process.exit(1); }); diff --git a/platforms/js/build_js.py b/platforms/js/build_js.py index f0701212af3c..d1c15a9c76b8 100644 --- a/platforms/js/build_js.py +++ b/platforms/js/build_js.py @@ -192,7 +192,7 @@ def get_build_flags(self): if self.options.simd: flags += "-msimd128 " if self.options.build_flags: - flags += self.options.build_flags + flags += self.options.build_flags + " " if self.options.webnn: flags += "-s USE_WEBNN=1 " flags += "-s EXPORTED_FUNCTIONS=\"['_malloc', '_free']\""