mirror of
https://github.com/opencv/opencv.git
synced 2026-07-23 20:33:04 +04:00
Compare commits
146 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 591708903b | |||
| f9d62fba7a | |||
| 9d039c206b | |||
| 4c3f9b2ef4 | |||
| 0e523618a1 | |||
| 3b26105f68 | |||
| 0f2f966a91 | |||
| d7d491d445 | |||
| 9b0d6862c4 | |||
| 890fcdf842 | |||
| 18dbac203f | |||
| 8d1f254dcc | |||
| 90df3af6cf | |||
| b699fe7a9d | |||
| b2ed5c3070 | |||
| 5b8c10f2f8 | |||
| 24983f62e2 | |||
| f2057ce1ab | |||
| 6797fd65a5 | |||
| 947e06a860 | |||
| 04d5ba266f | |||
| 90be83ae99 | |||
| 5e80bd3cc9 | |||
| db4b1e613c | |||
| 7d842f5bcf | |||
| 828304d587 | |||
| 9d584475f6 | |||
| bb60cb0bf9 | |||
| 55e1dfb778 | |||
| c2263db7bc | |||
| 7bbbda71df | |||
| 8e0baf257c | |||
| c8268e65fd | |||
| 3cf4375387 | |||
| c1adbe3189 | |||
| 7ee1816612 | |||
| 8f4f834ce6 | |||
| 2b84c97a78 | |||
| 3ddf84534b | |||
| bd26104088 | |||
| 5f80f43ff5 | |||
| b221143c0f | |||
| 995841624c | |||
| bbcd06f42f | |||
| 43940f7ffc | |||
| f4a79b0554 | |||
| 411fd2b761 | |||
| 61e30c15a9 | |||
| d332f33346 | |||
| 636db09d73 | |||
| 64c018507b | |||
| c34445a496 | |||
| ff60abb575 | |||
| 7d91dfe339 | |||
| 15af65d4cf | |||
| 81afeda537 | |||
| e10de25e86 | |||
| 746bd47ce5 | |||
| dcb4cabb26 | |||
| 59b4baee0c | |||
| bb3bbd192b | |||
| 1212aef03b | |||
| 814550d2a6 | |||
| fb68fe8930 | |||
| d3be58b6d7 | |||
| 8ecfbdb4ff | |||
| 63256a00ff | |||
| 450dc92452 | |||
| 3d2f4fa164 | |||
| 3d394943e6 | |||
| 3e25f32c9b | |||
| 81567a9d3e | |||
| 4a2adba8f4 | |||
| 84f78059d3 | |||
| 7499a15c92 | |||
| 5f4e55bc68 | |||
| c621384707 | |||
| c0162a64d1 | |||
| 1ae16beb06 | |||
| e53a4ce64d | |||
| 72655a9eea | |||
| 125f890dc3 | |||
| 101d50703c | |||
| 901ed5545f | |||
| 699b4b9fc5 | |||
| 1d7d18afba | |||
| b335fe67b0 | |||
| dde029f105 | |||
| 302c2354a3 | |||
| 158b13e0ba | |||
| b1dc7ed873 | |||
| 1bced43e96 | |||
| 8550f7e04d | |||
| 9f3e83baf6 | |||
| 17ab61a40d | |||
| 1b844f8413 | |||
| baa22fa808 | |||
| f78cebfc98 | |||
| d2a9ca13f1 | |||
| 71bae7c23f | |||
| d4f104f17f | |||
| fd44ba296d | |||
| b04d6a2d9b | |||
| a08eac452e | |||
| 7021ea6748 | |||
| 55aa1d4852 | |||
| 159534313e | |||
| 2f68c43e39 | |||
| e2483aa072 | |||
| c69f37343c | |||
| aec62a7fc5 | |||
| bf26050f7e | |||
| 402bce1a31 | |||
| 8868350888 | |||
| 1b64851fa8 | |||
| 2e143b8799 | |||
| 3930c9a492 | |||
| f0839d2703 | |||
| 405e820fe1 | |||
| 6598e9d506 | |||
| 8c2cf89845 | |||
| aeb8dfc52d | |||
| 0649a2fbdb | |||
| ec32061f5f | |||
| f2da1a0a7a | |||
| fda1e6f148 | |||
| 2a48730166 | |||
| 0bdbc745c4 | |||
| 6f70b0524a | |||
| b9b19185bc | |||
| 63ba9970bd | |||
| a9a6801c6d | |||
| 222af8e7e4 | |||
| ec8b7c933a | |||
| 76860933f0 | |||
| 19a936fc03 | |||
| be17fce657 | |||
| 9a1d7736f8 | |||
| 9f295b2c91 | |||
| 3a8154051f | |||
| f3f46096d6 | |||
| ace37df941 | |||
| ac9182f20d | |||
| 2cf1a13755 | |||
| 6465e393b6 | |||
| 6e6c0f31f7 |
+3
-4
@@ -3,10 +3,10 @@ project(${JPEG_LIBRARY} C)
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter -Wsign-compare -Wshorten-64-to-32 -Wimplicit-fallthrough)
|
||||
|
||||
set(VERSION_MAJOR 2)
|
||||
set(VERSION_MINOR 0)
|
||||
set(VERSION_REVISION 6)
|
||||
set(VERSION_MINOR 1)
|
||||
set(VERSION_REVISION 0)
|
||||
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION})
|
||||
set(LIBJPEG_TURBO_VERSION_NUMBER 2000006)
|
||||
set(LIBJPEG_TURBO_VERSION_NUMBER 2001000)
|
||||
|
||||
string(TIMESTAMP BUILD "opencv-${OPENCV_VERSION}-libjpeg-turbo")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
@@ -46,7 +46,6 @@ if(UNIX)
|
||||
ocv_update(HAVE_UNSIGNED_SHORT 1)
|
||||
# undef INCOMPLETE_TYPES_BROKEN
|
||||
ocv_update(RIGHT_SHIFT_IS_UNSIGNED 0)
|
||||
ocv_update(__CHAR_UNSIGNED__ 0)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -91,7 +91,7 @@ best of our understanding.
|
||||
The Modified (3-clause) BSD License
|
||||
===================================
|
||||
|
||||
Copyright (C)2009-2020 D. R. Commander. All Rights Reserved.
|
||||
Copyright (C)2009-2021 D. R. Commander. All Rights Reserved.<br>
|
||||
Copyright (C)2015 Viktor Szathmáry. All Rights Reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
Vendored
+1
-14
@@ -128,7 +128,7 @@ with respect to this software, its quality, accuracy, merchantability, or
|
||||
fitness for a particular purpose. This software is provided "AS IS", and you,
|
||||
its user, assume the entire risk as to its quality and accuracy.
|
||||
|
||||
This software is copyright (C) 1991-2016, Thomas G. Lane, Guido Vollbeding.
|
||||
This software is copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding.
|
||||
All Rights Reserved except as specified below.
|
||||
|
||||
Permission is hereby granted to use, copy, modify, and distribute this
|
||||
@@ -159,19 +159,6 @@ commercial products, provided that all warranty or liability claims are
|
||||
assumed by the product vendor.
|
||||
|
||||
|
||||
The IJG distribution formerly included code to read and write GIF files.
|
||||
To avoid entanglement with the Unisys LZW patent (now expired), GIF reading
|
||||
support has been removed altogether, and the GIF writer has been simplified
|
||||
to produce "uncompressed GIFs". This technique does not use the LZW
|
||||
algorithm; the resulting GIF files are larger than usual, but are readable
|
||||
by all standard GIF decoders.
|
||||
|
||||
We are required to state that
|
||||
"The Graphics Interchange Format(c) is the Copyright property of
|
||||
CompuServe Incorporated. GIF(sm) is a Service Mark property of
|
||||
CompuServe Incorporated."
|
||||
|
||||
|
||||
REFERENCES
|
||||
==========
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -3,7 +3,7 @@ Background
|
||||
|
||||
libjpeg-turbo is a JPEG image codec that uses SIMD instructions to accelerate
|
||||
baseline JPEG compression and decompression on x86, x86-64, Arm, PowerPC, and
|
||||
MIPS systems, as well as progressive JPEG compression on x86 and x86-64
|
||||
MIPS systems, as well as progressive JPEG compression on x86, x86-64, and Arm
|
||||
systems. On such systems, libjpeg-turbo is generally 2-6x as fast as libjpeg,
|
||||
all else being equal. On other types of systems, libjpeg-turbo can still
|
||||
outperform libjpeg by a significant amount, by virtue of its highly-optimized
|
||||
|
||||
Vendored
-5
@@ -61,11 +61,6 @@
|
||||
unsigned. */
|
||||
#cmakedefine RIGHT_SHIFT_IS_UNSIGNED 1
|
||||
|
||||
/* Define to 1 if type `char' is unsigned and you are not using gcc. */
|
||||
#ifndef __CHAR_UNSIGNED__
|
||||
#cmakedefine __CHAR_UNSIGNED__ 1
|
||||
#endif
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
|
||||
-1
@@ -18,7 +18,6 @@
|
||||
#define HAVE_UNSIGNED_SHORT
|
||||
#undef INCOMPLETE_TYPES_BROKEN
|
||||
#undef RIGHT_SHIFT_IS_UNSIGNED
|
||||
#undef __CHAR_UNSIGNED__
|
||||
|
||||
/* Define "boolean" as unsigned char, not int, per Windows custom */
|
||||
#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
|
||||
|
||||
+9
-9
@@ -48,9 +48,9 @@ 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 = GETJSAMPLE(inptr[RGB_RED]);
|
||||
g = GETJSAMPLE(inptr[RGB_GREEN]);
|
||||
b = GETJSAMPLE(inptr[RGB_BLUE]);
|
||||
r = inptr[RGB_RED];
|
||||
g = inptr[RGB_GREEN];
|
||||
b = inptr[RGB_BLUE];
|
||||
inptr += RGB_PIXELSIZE;
|
||||
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
|
||||
* must be too; we do not need an explicit range-limiting operation.
|
||||
@@ -100,9 +100,9 @@ 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 = GETJSAMPLE(inptr[RGB_RED]);
|
||||
g = GETJSAMPLE(inptr[RGB_GREEN]);
|
||||
b = GETJSAMPLE(inptr[RGB_BLUE]);
|
||||
r = inptr[RGB_RED];
|
||||
g = inptr[RGB_GREEN];
|
||||
b = inptr[RGB_BLUE];
|
||||
inptr += RGB_PIXELSIZE;
|
||||
/* Y */
|
||||
outptr[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] +
|
||||
@@ -135,9 +135,9 @@ rgb_rgb_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf,
|
||||
outptr2 = output_buf[2][output_row];
|
||||
output_row++;
|
||||
for (col = 0; col < num_cols; col++) {
|
||||
outptr0[col] = GETJSAMPLE(inptr[RGB_RED]);
|
||||
outptr1[col] = GETJSAMPLE(inptr[RGB_GREEN]);
|
||||
outptr2[col] = GETJSAMPLE(inptr[RGB_BLUE]);
|
||||
outptr0[col] = inptr[RGB_RED];
|
||||
outptr1[col] = inptr[RGB_GREEN];
|
||||
outptr2[col] = inptr[RGB_BLUE];
|
||||
inptr += RGB_PIXELSIZE;
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+6
-6
@@ -392,11 +392,11 @@ 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 - GETJSAMPLE(inptr[0]);
|
||||
g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
|
||||
b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
|
||||
r = MAXJSAMPLE - inptr[0];
|
||||
g = MAXJSAMPLE - inptr[1];
|
||||
b = MAXJSAMPLE - inptr[2];
|
||||
/* K passes through as-is */
|
||||
outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */
|
||||
outptr3[col] = inptr[3];
|
||||
inptr += 4;
|
||||
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
|
||||
* must be too; we do not need an explicit range-limiting operation.
|
||||
@@ -438,7 +438,7 @@ grayscale_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
|
||||
outptr = output_buf[0][output_row];
|
||||
output_row++;
|
||||
for (col = 0; col < num_cols; col++) {
|
||||
outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */
|
||||
outptr[col] = inptr[0];
|
||||
inptr += instride;
|
||||
}
|
||||
}
|
||||
@@ -497,7 +497,7 @@ null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
|
||||
inptr = *input_buf;
|
||||
outptr = output_buf[ci][output_row];
|
||||
for (col = 0; col < num_cols; col++) {
|
||||
outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
|
||||
outptr[col] = inptr[ci];
|
||||
inptr += nc;
|
||||
}
|
||||
}
|
||||
|
||||
+18
-19
@@ -381,19 +381,19 @@ convsamp(JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace)
|
||||
elemptr = sample_data[elemr] + start_col;
|
||||
|
||||
#if DCTSIZE == 8 /* unroll the inner loop */
|
||||
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*workspaceptr++ = GETJSAMPLE(*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++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
||||
*workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -533,20 +533,19 @@ convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col,
|
||||
for (elemr = 0; elemr < DCTSIZE; elemr++) {
|
||||
elemptr = sample_data[elemr] + start_col;
|
||||
#if DCTSIZE == 8 /* unroll the inner loop */
|
||||
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
|
||||
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
|
||||
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
|
||||
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
|
||||
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
|
||||
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
|
||||
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
|
||||
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*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)
|
||||
(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
|
||||
*workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Vendored
+220
-180
@@ -4,8 +4,10 @@
|
||||
* 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, 2014-2016, 2018-2019, D. R. Commander.
|
||||
* Copyright (C) 2009-2011, 2014-2016, 2018-2021, D. R. Commander.
|
||||
* Copyright (C) 2015, Matthieu Darbois.
|
||||
* Copyright (C) 2018, Matthias Räncker.
|
||||
* Copyright (C) 2020, Arm Limited.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
@@ -42,15 +44,19 @@
|
||||
* flags (this defines __thumb__).
|
||||
*/
|
||||
|
||||
/* NOTE: Both GCC and Clang define __GNUC__ */
|
||||
#if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))
|
||||
#if 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"
|
||||
@@ -65,32 +71,43 @@
|
||||
* but must not be updated permanently until we complete the MCU.
|
||||
*/
|
||||
|
||||
#if defined(__x86_64__) && defined(__ILP32__)
|
||||
typedef unsigned long long bit_buf_type;
|
||||
#else
|
||||
typedef size_t bit_buf_type;
|
||||
#endif
|
||||
|
||||
/* NOTE: The more optimal Huffman encoding algorithm is only used by the
|
||||
* intrinsics implementation of the Arm Neon SIMD extensions, which is why we
|
||||
* retain the old Huffman encoder behavior when using the GAS implementation.
|
||||
*/
|
||||
#if defined(WITH_SIMD) && !(defined(__arm__) || defined(__aarch64__) || \
|
||||
defined(_M_ARM) || defined(_M_ARM64))
|
||||
typedef unsigned long long simd_bit_buf_type;
|
||||
#else
|
||||
typedef bit_buf_type simd_bit_buf_type;
|
||||
#endif
|
||||
|
||||
#if (defined(SIZEOF_SIZE_T) && SIZEOF_SIZE_T == 8) || defined(_WIN64) || \
|
||||
(defined(__x86_64__) && defined(__ILP32__))
|
||||
#define BIT_BUF_SIZE 64
|
||||
#elif (defined(SIZEOF_SIZE_T) && SIZEOF_SIZE_T == 4) || defined(_WIN32)
|
||||
#define BIT_BUF_SIZE 32
|
||||
#else
|
||||
#error Cannot determine word size
|
||||
#endif
|
||||
#define SIMD_BIT_BUF_SIZE (sizeof(simd_bit_buf_type) * 8)
|
||||
|
||||
typedef struct {
|
||||
size_t put_buffer; /* current bit-accumulation buffer */
|
||||
int put_bits; /* # of bits now in it */
|
||||
union {
|
||||
bit_buf_type c;
|
||||
simd_bit_buf_type simd;
|
||||
} put_buffer; /* current bit accumulation buffer */
|
||||
int free_bits; /* # of bits available in it */
|
||||
/* (Neon GAS: # of bits now in it) */
|
||||
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
|
||||
} savable_state;
|
||||
|
||||
/* This macro is to work around compilers with missing or broken
|
||||
* structure assignment. You'll need to fix this code if you have
|
||||
* such a compiler and you change MAX_COMPS_IN_SCAN.
|
||||
*/
|
||||
|
||||
#ifndef NO_STRUCT_ASSIGN
|
||||
#define ASSIGN_STATE(dest, src) ((dest) = (src))
|
||||
#else
|
||||
#if MAX_COMPS_IN_SCAN == 4
|
||||
#define ASSIGN_STATE(dest, src) \
|
||||
((dest).put_buffer = (src).put_buffer, \
|
||||
(dest).put_bits = (src).put_bits, \
|
||||
(dest).last_dc_val[0] = (src).last_dc_val[0], \
|
||||
(dest).last_dc_val[1] = (src).last_dc_val[1], \
|
||||
(dest).last_dc_val[2] = (src).last_dc_val[2], \
|
||||
(dest).last_dc_val[3] = (src).last_dc_val[3])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_entropy_encoder pub; /* public fields */
|
||||
|
||||
@@ -123,6 +140,7 @@ 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 */
|
||||
int simd;
|
||||
} working_state;
|
||||
|
||||
|
||||
@@ -201,8 +219,17 @@ start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics)
|
||||
}
|
||||
|
||||
/* Initialize bit buffer to empty */
|
||||
entropy->saved.put_buffer = 0;
|
||||
entropy->saved.put_bits = 0;
|
||||
if (entropy->simd) {
|
||||
entropy->saved.put_buffer.simd = 0;
|
||||
#if defined(__aarch64__) && !defined(NEON_INTRINSICS)
|
||||
entropy->saved.free_bits = 0;
|
||||
#else
|
||||
entropy->saved.free_bits = SIMD_BIT_BUF_SIZE;
|
||||
#endif
|
||||
} else {
|
||||
entropy->saved.put_buffer.c = 0;
|
||||
entropy->saved.free_bits = BIT_BUF_SIZE;
|
||||
}
|
||||
|
||||
/* Initialize restart stuff */
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
@@ -287,6 +314,7 @@ jpeg_make_c_derived_tbl(j_compress_ptr cinfo, boolean isDC, int tblno,
|
||||
* this lets us detect duplicate VAL entries here, and later
|
||||
* allows emit_bits to detect any attempt to emit such symbols.
|
||||
*/
|
||||
MEMZERO(dtbl->ehufco, sizeof(dtbl->ehufco));
|
||||
MEMZERO(dtbl->ehufsi, sizeof(dtbl->ehufsi));
|
||||
|
||||
/* This is also a convenient place to check for out-of-range
|
||||
@@ -334,94 +362,94 @@ dump_buffer(working_state *state)
|
||||
|
||||
/* Outputting bits to the file */
|
||||
|
||||
/* These macros perform the same task as the emit_bits() function in the
|
||||
* original libjpeg code. In addition to reducing overhead by explicitly
|
||||
* inlining the code, additional performance is achieved by taking into
|
||||
* account the size of the bit buffer and waiting until it is almost full
|
||||
* before emptying it. This mostly benefits 64-bit platforms, since 6
|
||||
* bytes can be stored in a 64-bit bit buffer before it has to be emptied.
|
||||
/* Output byte b and, speculatively, an additional 0 byte. 0xFF must be
|
||||
* encoded as 0xFF 0x00, so the output buffer pointer is advanced by 2 if the
|
||||
* byte is 0xFF. Otherwise, the output buffer pointer is advanced by 1, and
|
||||
* the speculative 0 byte will be overwritten by the next byte.
|
||||
*/
|
||||
|
||||
#define EMIT_BYTE() { \
|
||||
JOCTET c; \
|
||||
put_bits -= 8; \
|
||||
c = (JOCTET)GETJOCTET(put_buffer >> put_bits); \
|
||||
*buffer++ = c; \
|
||||
if (c == 0xFF) /* need to stuff a zero byte? */ \
|
||||
*buffer++ = 0; \
|
||||
#define EMIT_BYTE(b) { \
|
||||
buffer[0] = (JOCTET)(b); \
|
||||
buffer[1] = 0; \
|
||||
buffer -= -2 + ((JOCTET)(b) < 0xFF); \
|
||||
}
|
||||
|
||||
#define PUT_BITS(code, size) { \
|
||||
put_bits += size; \
|
||||
put_buffer = (put_buffer << size) | code; \
|
||||
}
|
||||
/* Output the entire bit buffer. If there are no 0xFF bytes in it, then write
|
||||
* directly to the output buffer. Otherwise, use the EMIT_BYTE() macro to
|
||||
* encode 0xFF as 0xFF 0x00.
|
||||
*/
|
||||
#if BIT_BUF_SIZE == 64
|
||||
|
||||
#if SIZEOF_SIZE_T != 8 && !defined(_WIN64)
|
||||
|
||||
#define CHECKBUF15() { \
|
||||
if (put_bits > 15) { \
|
||||
EMIT_BYTE() \
|
||||
EMIT_BYTE() \
|
||||
#define FLUSH() { \
|
||||
if (put_buffer & 0x8080808080808080 & ~(put_buffer + 0x0101010101010101)) { \
|
||||
EMIT_BYTE(put_buffer >> 56) \
|
||||
EMIT_BYTE(put_buffer >> 48) \
|
||||
EMIT_BYTE(put_buffer >> 40) \
|
||||
EMIT_BYTE(put_buffer >> 32) \
|
||||
EMIT_BYTE(put_buffer >> 24) \
|
||||
EMIT_BYTE(put_buffer >> 16) \
|
||||
EMIT_BYTE(put_buffer >> 8) \
|
||||
EMIT_BYTE(put_buffer ) \
|
||||
} else { \
|
||||
buffer[0] = (JOCTET)(put_buffer >> 56); \
|
||||
buffer[1] = (JOCTET)(put_buffer >> 48); \
|
||||
buffer[2] = (JOCTET)(put_buffer >> 40); \
|
||||
buffer[3] = (JOCTET)(put_buffer >> 32); \
|
||||
buffer[4] = (JOCTET)(put_buffer >> 24); \
|
||||
buffer[5] = (JOCTET)(put_buffer >> 16); \
|
||||
buffer[6] = (JOCTET)(put_buffer >> 8); \
|
||||
buffer[7] = (JOCTET)(put_buffer); \
|
||||
buffer += 8; \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define CHECKBUF31() { \
|
||||
if (put_bits > 31) { \
|
||||
EMIT_BYTE() \
|
||||
EMIT_BYTE() \
|
||||
EMIT_BYTE() \
|
||||
EMIT_BYTE() \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CHECKBUF47() { \
|
||||
if (put_bits > 47) { \
|
||||
EMIT_BYTE() \
|
||||
EMIT_BYTE() \
|
||||
EMIT_BYTE() \
|
||||
EMIT_BYTE() \
|
||||
EMIT_BYTE() \
|
||||
EMIT_BYTE() \
|
||||
} \
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(SIZEOF_SIZE_T)
|
||||
#error Cannot determine word size
|
||||
#endif
|
||||
|
||||
#if SIZEOF_SIZE_T == 8 || defined(_WIN64)
|
||||
|
||||
#define EMIT_BITS(code, size) { \
|
||||
CHECKBUF47() \
|
||||
PUT_BITS(code, size) \
|
||||
}
|
||||
|
||||
#define EMIT_CODE(code, size) { \
|
||||
temp2 &= (((JLONG)1) << nbits) - 1; \
|
||||
CHECKBUF31() \
|
||||
PUT_BITS(code, size) \
|
||||
PUT_BITS(temp2, nbits) \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define EMIT_BITS(code, size) { \
|
||||
PUT_BITS(code, size) \
|
||||
CHECKBUF15() \
|
||||
}
|
||||
|
||||
#define EMIT_CODE(code, size) { \
|
||||
temp2 &= (((JLONG)1) << nbits) - 1; \
|
||||
PUT_BITS(code, size) \
|
||||
CHECKBUF15() \
|
||||
PUT_BITS(temp2, nbits) \
|
||||
CHECKBUF15() \
|
||||
#define FLUSH() { \
|
||||
if (put_buffer & 0x80808080 & ~(put_buffer + 0x01010101)) { \
|
||||
EMIT_BYTE(put_buffer >> 24) \
|
||||
EMIT_BYTE(put_buffer >> 16) \
|
||||
EMIT_BYTE(put_buffer >> 8) \
|
||||
EMIT_BYTE(put_buffer ) \
|
||||
} else { \
|
||||
buffer[0] = (JOCTET)(put_buffer >> 24); \
|
||||
buffer[1] = (JOCTET)(put_buffer >> 16); \
|
||||
buffer[2] = (JOCTET)(put_buffer >> 8); \
|
||||
buffer[3] = (JOCTET)(put_buffer); \
|
||||
buffer += 4; \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Fill the bit buffer to capacity with the leading bits from code, then output
|
||||
* the bit buffer and put the remaining bits from code into the bit buffer.
|
||||
*/
|
||||
#define PUT_AND_FLUSH(code, size) { \
|
||||
put_buffer = (put_buffer << (size + free_bits)) | (code >> -free_bits); \
|
||||
FLUSH() \
|
||||
free_bits += BIT_BUF_SIZE; \
|
||||
put_buffer = code; \
|
||||
}
|
||||
|
||||
/* Insert code into the bit buffer and output the bit buffer if needed.
|
||||
* NOTE: We can't flush with free_bits == 0, since the left shift in
|
||||
* PUT_AND_FLUSH() would have undefined behavior.
|
||||
*/
|
||||
#define PUT_BITS(code, size) { \
|
||||
free_bits -= size; \
|
||||
if (free_bits < 0) \
|
||||
PUT_AND_FLUSH(code, size) \
|
||||
else \
|
||||
put_buffer = (put_buffer << size) | code; \
|
||||
}
|
||||
|
||||
#define PUT_CODE(code, size) { \
|
||||
temp &= (((JLONG)1) << nbits) - 1; \
|
||||
temp |= code << nbits; \
|
||||
nbits += size; \
|
||||
PUT_BITS(temp, nbits) \
|
||||
}
|
||||
|
||||
|
||||
/* Although it is exceedingly rare, it is possible for a Huffman-encoded
|
||||
* coefficient block to be larger than the 128-byte unencoded block. For each
|
||||
@@ -444,6 +472,7 @@ dump_buffer(working_state *state)
|
||||
|
||||
#define STORE_BUFFER() { \
|
||||
if (localbuf) { \
|
||||
size_t bytes, bytestocopy; \
|
||||
bytes = buffer - _buffer; \
|
||||
buffer = _buffer; \
|
||||
while (bytes > 0) { \
|
||||
@@ -466,20 +495,46 @@ dump_buffer(working_state *state)
|
||||
LOCAL(boolean)
|
||||
flush_bits(working_state *state)
|
||||
{
|
||||
JOCTET _buffer[BUFSIZE], *buffer;
|
||||
size_t put_buffer; int put_bits;
|
||||
size_t bytes, bytestocopy; int localbuf = 0;
|
||||
JOCTET _buffer[BUFSIZE], *buffer, temp;
|
||||
simd_bit_buf_type put_buffer; int put_bits;
|
||||
int localbuf = 0;
|
||||
|
||||
if (state->simd) {
|
||||
#if defined(__aarch64__) && !defined(NEON_INTRINSICS)
|
||||
put_bits = state->cur.free_bits;
|
||||
#else
|
||||
put_bits = SIMD_BIT_BUF_SIZE - state->cur.free_bits;
|
||||
#endif
|
||||
put_buffer = state->cur.put_buffer.simd;
|
||||
} else {
|
||||
put_bits = BIT_BUF_SIZE - state->cur.free_bits;
|
||||
put_buffer = state->cur.put_buffer.c;
|
||||
}
|
||||
|
||||
put_buffer = state->cur.put_buffer;
|
||||
put_bits = state->cur.put_bits;
|
||||
LOAD_BUFFER()
|
||||
|
||||
/* fill any partial byte with ones */
|
||||
PUT_BITS(0x7F, 7)
|
||||
while (put_bits >= 8) EMIT_BYTE()
|
||||
while (put_bits >= 8) {
|
||||
put_bits -= 8;
|
||||
temp = (JOCTET)(put_buffer >> put_bits);
|
||||
EMIT_BYTE(temp)
|
||||
}
|
||||
if (put_bits) {
|
||||
/* fill partial byte with ones */
|
||||
temp = (JOCTET)((put_buffer << (8 - put_bits)) | (0xFF >> put_bits));
|
||||
EMIT_BYTE(temp)
|
||||
}
|
||||
|
||||
state->cur.put_buffer = 0; /* and reset bit-buffer to empty */
|
||||
state->cur.put_bits = 0;
|
||||
if (state->simd) { /* and reset bit buffer to empty */
|
||||
state->cur.put_buffer.simd = 0;
|
||||
#if defined(__aarch64__) && !defined(NEON_INTRINSICS)
|
||||
state->cur.free_bits = 0;
|
||||
#else
|
||||
state->cur.free_bits = SIMD_BIT_BUF_SIZE;
|
||||
#endif
|
||||
} else {
|
||||
state->cur.put_buffer.c = 0;
|
||||
state->cur.free_bits = BIT_BUF_SIZE;
|
||||
}
|
||||
STORE_BUFFER()
|
||||
|
||||
return TRUE;
|
||||
@@ -493,7 +548,7 @@ encode_one_block_simd(working_state *state, JCOEFPTR block, int last_dc_val,
|
||||
c_derived_tbl *dctbl, c_derived_tbl *actbl)
|
||||
{
|
||||
JOCTET _buffer[BUFSIZE], *buffer;
|
||||
size_t bytes, bytestocopy; int localbuf = 0;
|
||||
int localbuf = 0;
|
||||
|
||||
LOAD_BUFFER()
|
||||
|
||||
@@ -509,53 +564,41 @@ LOCAL(boolean)
|
||||
encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val,
|
||||
c_derived_tbl *dctbl, c_derived_tbl *actbl)
|
||||
{
|
||||
int temp, temp2, temp3;
|
||||
int nbits;
|
||||
int r, code, size;
|
||||
int temp, nbits, free_bits;
|
||||
bit_buf_type put_buffer;
|
||||
JOCTET _buffer[BUFSIZE], *buffer;
|
||||
size_t put_buffer; int put_bits;
|
||||
int code_0xf0 = actbl->ehufco[0xf0], size_0xf0 = actbl->ehufsi[0xf0];
|
||||
size_t bytes, bytestocopy; int localbuf = 0;
|
||||
int localbuf = 0;
|
||||
|
||||
put_buffer = state->cur.put_buffer;
|
||||
put_bits = state->cur.put_bits;
|
||||
free_bits = state->cur.free_bits;
|
||||
put_buffer = state->cur.put_buffer.c;
|
||||
LOAD_BUFFER()
|
||||
|
||||
/* Encode the DC coefficient difference per section F.1.2.1 */
|
||||
|
||||
temp = temp2 = block[0] - last_dc_val;
|
||||
temp = block[0] - last_dc_val;
|
||||
|
||||
/* This is a well-known technique for obtaining the absolute value without a
|
||||
* branch. It is derived from an assembly language technique presented in
|
||||
* "How to Optimize for the Pentium Processors", Copyright (c) 1996, 1997 by
|
||||
* Agner Fog.
|
||||
* Agner Fog. This code assumes we are on a two's complement machine.
|
||||
*/
|
||||
temp3 = temp >> (CHAR_BIT * sizeof(int) - 1);
|
||||
temp ^= temp3;
|
||||
temp -= temp3;
|
||||
|
||||
/* For a negative input, want temp2 = bitwise complement of abs(input) */
|
||||
/* This code assumes we are on a two's complement machine */
|
||||
temp2 += temp3;
|
||||
nbits = temp >> (CHAR_BIT * sizeof(int) - 1);
|
||||
temp += nbits;
|
||||
nbits ^= temp;
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = JPEG_NBITS(temp);
|
||||
nbits = JPEG_NBITS(nbits);
|
||||
|
||||
/* Emit the Huffman-coded symbol for the number of bits */
|
||||
code = dctbl->ehufco[nbits];
|
||||
size = dctbl->ehufsi[nbits];
|
||||
EMIT_BITS(code, size)
|
||||
|
||||
/* Mask off any extra bits in code */
|
||||
temp2 &= (((JLONG)1) << nbits) - 1;
|
||||
|
||||
/* Emit that number of bits of the value, if positive, */
|
||||
/* or the complement of its magnitude, if negative. */
|
||||
EMIT_BITS(temp2, nbits)
|
||||
/* Emit the Huffman-coded symbol for the number of bits.
|
||||
* Emit that number of bits of the value, if positive,
|
||||
* or the complement of its magnitude, if negative.
|
||||
*/
|
||||
PUT_CODE(dctbl->ehufco[nbits], dctbl->ehufsi[nbits])
|
||||
|
||||
/* Encode the AC coefficients per section F.1.2.2 */
|
||||
|
||||
r = 0; /* r = run length of zeros */
|
||||
{
|
||||
int r = 0; /* r = run length of zeros */
|
||||
|
||||
/* Manually unroll the k loop to eliminate the counter variable. This
|
||||
* improves performance greatly on systems with a limited number of
|
||||
@@ -563,51 +606,46 @@ encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val,
|
||||
*/
|
||||
#define kloop(jpeg_natural_order_of_k) { \
|
||||
if ((temp = block[jpeg_natural_order_of_k]) == 0) { \
|
||||
r++; \
|
||||
r += 16; \
|
||||
} else { \
|
||||
temp2 = temp; \
|
||||
/* Branch-less absolute value, bitwise complement, etc., same as above */ \
|
||||
temp3 = temp >> (CHAR_BIT * sizeof(int) - 1); \
|
||||
temp ^= temp3; \
|
||||
temp -= temp3; \
|
||||
temp2 += temp3; \
|
||||
nbits = JPEG_NBITS_NONZERO(temp); \
|
||||
nbits = temp >> (CHAR_BIT * sizeof(int) - 1); \
|
||||
temp += nbits; \
|
||||
nbits ^= temp; \
|
||||
nbits = JPEG_NBITS_NONZERO(nbits); \
|
||||
/* if run length > 15, must emit special run-length-16 codes (0xF0) */ \
|
||||
while (r > 15) { \
|
||||
EMIT_BITS(code_0xf0, size_0xf0) \
|
||||
r -= 16; \
|
||||
while (r >= 16 * 16) { \
|
||||
r -= 16 * 16; \
|
||||
PUT_BITS(actbl->ehufco[0xf0], actbl->ehufsi[0xf0]) \
|
||||
} \
|
||||
/* Emit Huffman symbol for run length / number of bits */ \
|
||||
temp3 = (r << 4) + nbits; \
|
||||
code = actbl->ehufco[temp3]; \
|
||||
size = actbl->ehufsi[temp3]; \
|
||||
EMIT_CODE(code, size) \
|
||||
r += nbits; \
|
||||
PUT_CODE(actbl->ehufco[r], actbl->ehufsi[r]) \
|
||||
r = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* One iteration for each value in jpeg_natural_order[] */
|
||||
kloop(1); kloop(8); kloop(16); kloop(9); kloop(2); kloop(3);
|
||||
kloop(10); kloop(17); kloop(24); kloop(32); kloop(25); kloop(18);
|
||||
kloop(11); kloop(4); kloop(5); kloop(12); kloop(19); kloop(26);
|
||||
kloop(33); kloop(40); kloop(48); kloop(41); kloop(34); kloop(27);
|
||||
kloop(20); kloop(13); kloop(6); kloop(7); kloop(14); kloop(21);
|
||||
kloop(28); kloop(35); kloop(42); kloop(49); kloop(56); kloop(57);
|
||||
kloop(50); kloop(43); kloop(36); kloop(29); kloop(22); kloop(15);
|
||||
kloop(23); kloop(30); kloop(37); kloop(44); kloop(51); kloop(58);
|
||||
kloop(59); kloop(52); kloop(45); kloop(38); kloop(31); kloop(39);
|
||||
kloop(46); kloop(53); kloop(60); kloop(61); kloop(54); kloop(47);
|
||||
kloop(55); kloop(62); kloop(63);
|
||||
/* One iteration for each value in jpeg_natural_order[] */
|
||||
kloop(1); kloop(8); kloop(16); kloop(9); kloop(2); kloop(3);
|
||||
kloop(10); kloop(17); kloop(24); kloop(32); kloop(25); kloop(18);
|
||||
kloop(11); kloop(4); kloop(5); kloop(12); kloop(19); kloop(26);
|
||||
kloop(33); kloop(40); kloop(48); kloop(41); kloop(34); kloop(27);
|
||||
kloop(20); kloop(13); kloop(6); kloop(7); kloop(14); kloop(21);
|
||||
kloop(28); kloop(35); kloop(42); kloop(49); kloop(56); kloop(57);
|
||||
kloop(50); kloop(43); kloop(36); kloop(29); kloop(22); kloop(15);
|
||||
kloop(23); kloop(30); kloop(37); kloop(44); kloop(51); kloop(58);
|
||||
kloop(59); kloop(52); kloop(45); kloop(38); kloop(31); kloop(39);
|
||||
kloop(46); kloop(53); kloop(60); kloop(61); kloop(54); kloop(47);
|
||||
kloop(55); kloop(62); kloop(63);
|
||||
|
||||
/* If the last coef(s) were zero, emit an end-of-block code */
|
||||
if (r > 0) {
|
||||
code = actbl->ehufco[0];
|
||||
size = actbl->ehufsi[0];
|
||||
EMIT_BITS(code, size)
|
||||
/* If the last coef(s) were zero, emit an end-of-block code */
|
||||
if (r > 0) {
|
||||
PUT_BITS(actbl->ehufco[0], actbl->ehufsi[0])
|
||||
}
|
||||
}
|
||||
|
||||
state->cur.put_buffer = put_buffer;
|
||||
state->cur.put_bits = put_bits;
|
||||
state->cur.put_buffer.c = put_buffer;
|
||||
state->cur.free_bits = free_bits;
|
||||
STORE_BUFFER()
|
||||
|
||||
return TRUE;
|
||||
@@ -654,8 +692,9 @@ encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
/* Load up working state */
|
||||
state.next_output_byte = cinfo->dest->next_output_byte;
|
||||
state.free_in_buffer = cinfo->dest->free_in_buffer;
|
||||
ASSIGN_STATE(state.cur, entropy->saved);
|
||||
state.cur = entropy->saved;
|
||||
state.cinfo = cinfo;
|
||||
state.simd = entropy->simd;
|
||||
|
||||
/* Emit restart marker if needed */
|
||||
if (cinfo->restart_interval) {
|
||||
@@ -694,7 +733,7 @@ encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
/* Completed MCU, so update state */
|
||||
cinfo->dest->next_output_byte = state.next_output_byte;
|
||||
cinfo->dest->free_in_buffer = state.free_in_buffer;
|
||||
ASSIGN_STATE(entropy->saved, state.cur);
|
||||
entropy->saved = state.cur;
|
||||
|
||||
/* Update restart-interval state too */
|
||||
if (cinfo->restart_interval) {
|
||||
@@ -723,8 +762,9 @@ finish_pass_huff(j_compress_ptr cinfo)
|
||||
/* 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;
|
||||
ASSIGN_STATE(state.cur, entropy->saved);
|
||||
state.cur = entropy->saved;
|
||||
state.cinfo = cinfo;
|
||||
state.simd = entropy->simd;
|
||||
|
||||
/* Flush out the last data */
|
||||
if (!flush_bits(&state))
|
||||
@@ -733,7 +773,7 @@ finish_pass_huff(j_compress_ptr cinfo)
|
||||
/* Update state */
|
||||
cinfo->dest->next_output_byte = state.next_output_byte;
|
||||
cinfo->dest->free_in_buffer = state.free_in_buffer;
|
||||
ASSIGN_STATE(entropy->saved, state.cur);
|
||||
entropy->saved = state.cur;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Vendored
+16
-9
@@ -4,8 +4,9 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1995-1997, Thomas G. Lane.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2011, 2015, 2018, D. R. Commander.
|
||||
* Copyright (C) 2011, 2015, 2018, 2021, D. R. Commander.
|
||||
* Copyright (C) 2016, 2018, Matthieu Darbois.
|
||||
* Copyright (C) 2020, Arm Limited.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
@@ -51,15 +52,19 @@
|
||||
* flags (this defines __thumb__).
|
||||
*/
|
||||
|
||||
/* NOTE: Both GCC and Clang define __GNUC__ */
|
||||
#if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))
|
||||
#if 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"
|
||||
@@ -169,24 +174,26 @@ INLINE
|
||||
METHODDEF(int)
|
||||
count_zeroes(size_t *x)
|
||||
{
|
||||
int result;
|
||||
#if defined(HAVE_BUILTIN_CTZL)
|
||||
int result;
|
||||
result = __builtin_ctzl(*x);
|
||||
*x >>= result;
|
||||
#elif defined(HAVE_BITSCANFORWARD64)
|
||||
unsigned long result;
|
||||
_BitScanForward64(&result, *x);
|
||||
*x >>= result;
|
||||
#elif defined(HAVE_BITSCANFORWARD)
|
||||
unsigned long result;
|
||||
_BitScanForward(&result, *x);
|
||||
*x >>= result;
|
||||
#else
|
||||
result = 0;
|
||||
int result = 0;
|
||||
while ((*x & 1) == 0) {
|
||||
++result;
|
||||
*x >>= 1;
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
|
||||
@@ -860,7 +867,7 @@ encode_mcu_AC_refine_prepare(const JCOEF *block,
|
||||
|
||||
#define ENCODE_COEFS_AC_REFINE(label) { \
|
||||
while (zerobits) { \
|
||||
int idx = count_zeroes(&zerobits); \
|
||||
idx = count_zeroes(&zerobits); \
|
||||
r += idx; \
|
||||
cabsvalue += idx; \
|
||||
signbits >>= idx; \
|
||||
@@ -917,7 +924,7 @@ METHODDEF(boolean)
|
||||
encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
|
||||
register int temp, r;
|
||||
register int temp, r, idx;
|
||||
char *BR_buffer;
|
||||
unsigned int BR;
|
||||
int Sl = cinfo->Se - cinfo->Ss + 1;
|
||||
@@ -968,7 +975,7 @@ encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
|
||||
if (zerobits) {
|
||||
int diff = ((absvalues + DCTSIZE2 / 2) - cabsvalue);
|
||||
int idx = count_zeroes(&zerobits);
|
||||
idx = count_zeroes(&zerobits);
|
||||
signbits >>= idx;
|
||||
idx += diff;
|
||||
r += idx;
|
||||
|
||||
+23
-40
@@ -6,7 +6,7 @@
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
||||
* Copyright (C) 2014, MIPS Technologies, Inc., California.
|
||||
* Copyright (C) 2015, D. R. Commander.
|
||||
* Copyright (C) 2015, 2019, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
@@ -103,7 +103,7 @@ expand_right_edge(JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols,
|
||||
if (numcols > 0) {
|
||||
for (row = 0; row < num_rows; row++) {
|
||||
ptr = image_data[row] + input_cols;
|
||||
pixval = ptr[-1]; /* don't need GETJSAMPLE() here */
|
||||
pixval = ptr[-1];
|
||||
for (count = numcols; count > 0; count--)
|
||||
*ptr++ = pixval;
|
||||
}
|
||||
@@ -174,7 +174,7 @@ int_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||
for (v = 0; v < v_expand; v++) {
|
||||
inptr = input_data[inrow + v] + outcol_h;
|
||||
for (h = 0; h < h_expand; h++) {
|
||||
outvalue += (JLONG)GETJSAMPLE(*inptr++);
|
||||
outvalue += (JLONG)(*inptr++);
|
||||
}
|
||||
}
|
||||
*outptr++ = (JSAMPLE)((outvalue + numpix2) / numpix);
|
||||
@@ -237,8 +237,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)((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + bias) >> 1);
|
||||
*outptr++ = (JSAMPLE)((inptr[0] + inptr[1] + bias) >> 1);
|
||||
bias ^= 1; /* 0=>1, 1=>0 */
|
||||
inptr += 2;
|
||||
}
|
||||
@@ -277,8 +276,7 @@ h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||
bias = 1; /* bias = 1,2,1,2,... for successive samples */
|
||||
for (outcol = 0; outcol < output_cols; outcol++) {
|
||||
*outptr++ =
|
||||
(JSAMPLE)((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
|
||||
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + bias) >> 2);
|
||||
(JSAMPLE)((inptr0[0] + inptr0[1] + inptr1[0] + inptr1[1] + bias) >> 2);
|
||||
bias ^= 3; /* 1=>2, 2=>1 */
|
||||
inptr0 += 2; inptr1 += 2;
|
||||
}
|
||||
@@ -337,33 +335,25 @@ h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||
below_ptr = input_data[inrow + 2];
|
||||
|
||||
/* Special case for first column: pretend column -1 is same as column 0 */
|
||||
membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
|
||||
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
|
||||
neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
|
||||
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
|
||||
GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +
|
||||
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);
|
||||
membersum = inptr0[0] + inptr0[1] + inptr1[0] + inptr1[1];
|
||||
neighsum = above_ptr[0] + above_ptr[1] + below_ptr[0] + below_ptr[1] +
|
||||
inptr0[0] + inptr0[2] + inptr1[0] + inptr1[2];
|
||||
neighsum += neighsum;
|
||||
neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
|
||||
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
|
||||
neighsum += above_ptr[0] + above_ptr[2] + below_ptr[0] + below_ptr[2];
|
||||
membersum = membersum * memberscale + neighsum * neighscale;
|
||||
*outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
|
||||
inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
|
||||
|
||||
for (colctr = output_cols - 2; colctr > 0; colctr--) {
|
||||
/* sum of pixels directly mapped to this output element */
|
||||
membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
|
||||
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
|
||||
membersum = inptr0[0] + inptr0[1] + inptr1[0] + inptr1[1];
|
||||
/* sum of edge-neighbor pixels */
|
||||
neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
|
||||
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
|
||||
GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +
|
||||
GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);
|
||||
neighsum = above_ptr[0] + above_ptr[1] + below_ptr[0] + below_ptr[1] +
|
||||
inptr0[-1] + inptr0[2] + inptr1[-1] + inptr1[2];
|
||||
/* The edge-neighbors count twice as much as corner-neighbors */
|
||||
neighsum += neighsum;
|
||||
/* Add in the corner-neighbors */
|
||||
neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +
|
||||
GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);
|
||||
neighsum += above_ptr[-1] + above_ptr[2] + below_ptr[-1] + below_ptr[2];
|
||||
/* form final output scaled up by 2^16 */
|
||||
membersum = membersum * memberscale + neighsum * neighscale;
|
||||
/* round, descale and output it */
|
||||
@@ -372,15 +362,11 @@ h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||
}
|
||||
|
||||
/* Special case for last column */
|
||||
membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
|
||||
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
|
||||
neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
|
||||
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
|
||||
GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +
|
||||
GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);
|
||||
membersum = inptr0[0] + inptr0[1] + inptr1[0] + inptr1[1];
|
||||
neighsum = above_ptr[0] + above_ptr[1] + below_ptr[0] + below_ptr[1] +
|
||||
inptr0[-1] + inptr0[1] + inptr1[-1] + inptr1[1];
|
||||
neighsum += neighsum;
|
||||
neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
|
||||
GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
|
||||
neighsum += above_ptr[-1] + above_ptr[1] + below_ptr[-1] + below_ptr[1];
|
||||
membersum = membersum * memberscale + neighsum * neighscale;
|
||||
*outptr = (JSAMPLE)((membersum + 32768) >> 16);
|
||||
|
||||
@@ -429,21 +415,18 @@ fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||
below_ptr = input_data[outrow + 1];
|
||||
|
||||
/* Special case for first column */
|
||||
colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
|
||||
GETJSAMPLE(*inptr);
|
||||
membersum = GETJSAMPLE(*inptr++);
|
||||
nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
|
||||
GETJSAMPLE(*inptr);
|
||||
colsum = (*above_ptr++) + (*below_ptr++) + inptr[0];
|
||||
membersum = *inptr++;
|
||||
nextcolsum = above_ptr[0] + below_ptr[0] + inptr[0];
|
||||
neighsum = colsum + (colsum - membersum) + nextcolsum;
|
||||
membersum = membersum * memberscale + neighsum * neighscale;
|
||||
*outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
|
||||
lastcolsum = colsum; colsum = nextcolsum;
|
||||
|
||||
for (colctr = output_cols - 2; colctr > 0; colctr--) {
|
||||
membersum = GETJSAMPLE(*inptr++);
|
||||
membersum = *inptr++;
|
||||
above_ptr++; below_ptr++;
|
||||
nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
|
||||
GETJSAMPLE(*inptr);
|
||||
nextcolsum = above_ptr[0] + below_ptr[0] + inptr[0];
|
||||
neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
|
||||
membersum = membersum * memberscale + neighsum * neighscale;
|
||||
*outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
|
||||
@@ -451,7 +434,7 @@ fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
|
||||
}
|
||||
|
||||
/* Special case for last column */
|
||||
membersum = GETJSAMPLE(*inptr);
|
||||
membersum = *inptr;
|
||||
neighsum = lastcolsum + (colsum - membersum) + colsum;
|
||||
membersum = membersum * memberscale + neighsum * neighscale;
|
||||
*outptr = (JSAMPLE)((membersum + 32768) >> 16);
|
||||
|
||||
+9
-1
@@ -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-2018, 2020, D. R. Commander.
|
||||
* Copyright (C) 2010, 2015-2020, D. R. Commander.
|
||||
* Copyright (C) 2015, Google, Inc.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
@@ -319,6 +319,8 @@ read_and_discard_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines)
|
||||
{
|
||||
JDIMENSION n;
|
||||
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,
|
||||
@@ -329,6 +331,10 @@ read_and_discard_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines)
|
||||
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) {
|
||||
@@ -532,6 +538,8 @@ jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines)
|
||||
* decoded coefficients. This is ~5% faster for large subsets, but
|
||||
* it's tough to tell a difference for smaller images.
|
||||
*/
|
||||
if (!cinfo->entropy->insufficient_data)
|
||||
cinfo->master->last_good_iMCU_row = cinfo->input_iMCU_row;
|
||||
(*cinfo->entropy->decode_mcu) (cinfo, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+12
-3
@@ -4,7 +4,7 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Developed 1997-2015 by Guido Vollbeding.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2015-2018, D. R. Commander.
|
||||
* Copyright (C) 2015-2020, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
@@ -80,7 +80,7 @@ get_byte(j_decompress_ptr cinfo)
|
||||
if (!(*src->fill_input_buffer) (cinfo))
|
||||
ERREXIT(cinfo, JERR_CANT_SUSPEND);
|
||||
src->bytes_in_buffer--;
|
||||
return GETJOCTET(*src->next_input_byte++);
|
||||
return *src->next_input_byte++;
|
||||
}
|
||||
|
||||
|
||||
@@ -665,8 +665,16 @@ bad:
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
int coefi, cindex = cinfo->cur_comp_info[ci]->component_index;
|
||||
int *coef_bit_ptr = &cinfo->coef_bits[cindex][0];
|
||||
int *prev_coef_bit_ptr =
|
||||
&cinfo->coef_bits[cindex + cinfo->num_components][0];
|
||||
if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
|
||||
WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
|
||||
for (coefi = MIN(cinfo->Ss, 1); coefi <= MAX(cinfo->Se, 9); coefi++) {
|
||||
if (cinfo->input_scan_number > 1)
|
||||
prev_coef_bit_ptr[coefi] = coef_bit_ptr[coefi];
|
||||
else
|
||||
prev_coef_bit_ptr[coefi] = 0;
|
||||
}
|
||||
for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
|
||||
int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi];
|
||||
if (cinfo->Ah != expected)
|
||||
@@ -727,6 +735,7 @@ bad:
|
||||
entropy->c = 0;
|
||||
entropy->a = 0;
|
||||
entropy->ct = -16; /* force reading 2 initial bytes to fill C */
|
||||
entropy->pub.insufficient_data = FALSE;
|
||||
|
||||
/* Initialize restart counter */
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
@@ -763,7 +772,7 @@ jinit_arith_decoder(j_decompress_ptr cinfo)
|
||||
int *coef_bit_ptr, ci;
|
||||
cinfo->coef_bits = (int (*)[DCTSIZE2])
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
cinfo->num_components * DCTSIZE2 *
|
||||
cinfo->num_components * 2 * DCTSIZE2 *
|
||||
sizeof(int));
|
||||
coef_bit_ptr = &cinfo->coef_bits[0][0];
|
||||
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||
|
||||
+237
-53
@@ -5,7 +5,7 @@
|
||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
||||
* Copyright (C) 2010, 2015-2016, D. R. Commander.
|
||||
* Copyright (C) 2010, 2015-2016, 2019-2020, D. R. Commander.
|
||||
* Copyright (C) 2015, 2020, Google, Inc.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
@@ -102,6 +102,8 @@ decompress_onepass(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
/* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */
|
||||
jzero_far((void *)coef->MCU_buffer[0],
|
||||
(size_t)(cinfo->blocks_in_MCU * sizeof(JBLOCK)));
|
||||
if (!cinfo->entropy->insufficient_data)
|
||||
cinfo->master->last_good_iMCU_row = cinfo->input_iMCU_row;
|
||||
if (!(*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||
/* Suspension forced; update state counters and exit */
|
||||
coef->MCU_vert_offset = yoffset;
|
||||
@@ -227,6 +229,8 @@ consume_data(j_decompress_ptr cinfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!cinfo->entropy->insufficient_data)
|
||||
cinfo->master->last_good_iMCU_row = cinfo->input_iMCU_row;
|
||||
/* Try to fetch the MCU. */
|
||||
if (!(*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||
/* Suspension forced; update state counters and exit */
|
||||
@@ -326,19 +330,22 @@ decompress_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||
|
||||
/*
|
||||
* This code applies interblock smoothing as described by section K.8
|
||||
* of the JPEG standard: the first 5 AC coefficients are estimated from
|
||||
* the DC values of a DCT block and its 8 neighboring blocks.
|
||||
* This code applies interblock smoothing; the first 9 AC coefficients are
|
||||
* estimated from the DC values of a DCT block and its 24 neighboring blocks.
|
||||
* We apply smoothing only for progressive JPEG decoding, and only if
|
||||
* the coefficients it can estimate are not yet known to full precision.
|
||||
*/
|
||||
|
||||
/* Natural-order array positions of the first 5 zigzag-order coefficients */
|
||||
/* Natural-order array positions of the first 9 zigzag-order coefficients */
|
||||
#define Q01_POS 1
|
||||
#define Q10_POS 8
|
||||
#define Q20_POS 16
|
||||
#define Q11_POS 9
|
||||
#define Q02_POS 2
|
||||
#define Q03_POS 3
|
||||
#define Q12_POS 10
|
||||
#define Q21_POS 17
|
||||
#define Q30_POS 24
|
||||
|
||||
/*
|
||||
* Determine whether block smoothing is applicable and safe.
|
||||
@@ -356,8 +363,8 @@ smoothing_ok(j_decompress_ptr cinfo)
|
||||
int ci, coefi;
|
||||
jpeg_component_info *compptr;
|
||||
JQUANT_TBL *qtable;
|
||||
int *coef_bits;
|
||||
int *coef_bits_latch;
|
||||
int *coef_bits, *prev_coef_bits;
|
||||
int *coef_bits_latch, *prev_coef_bits_latch;
|
||||
|
||||
if (!cinfo->progressive_mode || cinfo->coef_bits == NULL)
|
||||
return FALSE;
|
||||
@@ -366,34 +373,47 @@ smoothing_ok(j_decompress_ptr cinfo)
|
||||
if (coef->coef_bits_latch == NULL)
|
||||
coef->coef_bits_latch = (int *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
cinfo->num_components *
|
||||
cinfo->num_components * 2 *
|
||||
(SAVED_COEFS * sizeof(int)));
|
||||
coef_bits_latch = coef->coef_bits_latch;
|
||||
prev_coef_bits_latch =
|
||||
&coef->coef_bits_latch[cinfo->num_components * SAVED_COEFS];
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* All components' quantization values must already be latched. */
|
||||
if ((qtable = compptr->quant_table) == NULL)
|
||||
return FALSE;
|
||||
/* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */
|
||||
/* Verify DC & first 9 AC quantizers are nonzero to avoid zero-divide. */
|
||||
if (qtable->quantval[0] == 0 ||
|
||||
qtable->quantval[Q01_POS] == 0 ||
|
||||
qtable->quantval[Q10_POS] == 0 ||
|
||||
qtable->quantval[Q20_POS] == 0 ||
|
||||
qtable->quantval[Q11_POS] == 0 ||
|
||||
qtable->quantval[Q02_POS] == 0)
|
||||
qtable->quantval[Q02_POS] == 0 ||
|
||||
qtable->quantval[Q03_POS] == 0 ||
|
||||
qtable->quantval[Q12_POS] == 0 ||
|
||||
qtable->quantval[Q21_POS] == 0 ||
|
||||
qtable->quantval[Q30_POS] == 0)
|
||||
return FALSE;
|
||||
/* DC values must be at least partly known for all components. */
|
||||
coef_bits = cinfo->coef_bits[ci];
|
||||
prev_coef_bits = cinfo->coef_bits[ci + cinfo->num_components];
|
||||
if (coef_bits[0] < 0)
|
||||
return FALSE;
|
||||
coef_bits_latch[0] = coef_bits[0];
|
||||
/* Block smoothing is helpful if some AC coefficients remain inaccurate. */
|
||||
for (coefi = 1; coefi <= 5; coefi++) {
|
||||
for (coefi = 1; coefi < SAVED_COEFS; coefi++) {
|
||||
if (cinfo->input_scan_number > 1)
|
||||
prev_coef_bits_latch[coefi] = prev_coef_bits[coefi];
|
||||
else
|
||||
prev_coef_bits_latch[coefi] = -1;
|
||||
coef_bits_latch[coefi] = coef_bits[coefi];
|
||||
if (coef_bits[coefi] != 0)
|
||||
smoothing_useful = TRUE;
|
||||
}
|
||||
coef_bits_latch += SAVED_COEFS;
|
||||
prev_coef_bits_latch += SAVED_COEFS;
|
||||
}
|
||||
|
||||
return smoothing_useful;
|
||||
@@ -412,17 +432,20 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
JDIMENSION block_num, last_block_column;
|
||||
int ci, block_row, block_rows, access_rows;
|
||||
JBLOCKARRAY buffer;
|
||||
JBLOCKROW buffer_ptr, prev_block_row, next_block_row;
|
||||
JBLOCKROW buffer_ptr, prev_prev_block_row, prev_block_row;
|
||||
JBLOCKROW next_block_row, next_next_block_row;
|
||||
JSAMPARRAY output_ptr;
|
||||
JDIMENSION output_col;
|
||||
jpeg_component_info *compptr;
|
||||
inverse_DCT_method_ptr inverse_DCT;
|
||||
boolean first_row, last_row;
|
||||
boolean change_dc;
|
||||
JCOEF *workspace;
|
||||
int *coef_bits;
|
||||
JQUANT_TBL *quanttbl;
|
||||
JLONG Q00, Q01, Q02, Q10, Q11, Q20, num;
|
||||
int DC1, DC2, DC3, DC4, DC5, DC6, DC7, DC8, DC9;
|
||||
JLONG Q00, Q01, Q02, Q03 = 0, Q10, Q11, Q12 = 0, Q20, Q21 = 0, Q30 = 0, num;
|
||||
int DC01, DC02, DC03, DC04, DC05, DC06, DC07, DC08, DC09, DC10, DC11, DC12,
|
||||
DC13, DC14, DC15, DC16, DC17, DC18, DC19, DC20, DC21, DC22, DC23, DC24,
|
||||
DC25;
|
||||
int Al, pred;
|
||||
|
||||
/* Keep a local variable to avoid looking it up more than once */
|
||||
@@ -434,10 +457,10 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
if (cinfo->input_scan_number == cinfo->output_scan_number) {
|
||||
/* If input is working on current scan, we ordinarily want it to
|
||||
* have completed the current row. But if input scan is DC,
|
||||
* we want it to keep one row ahead so that next block row's DC
|
||||
* we want it to keep two rows ahead so that next two block rows' DC
|
||||
* values are up to date.
|
||||
*/
|
||||
JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0;
|
||||
JDIMENSION delta = (cinfo->Ss == 0) ? 2 : 0;
|
||||
if (cinfo->input_iMCU_row > cinfo->output_iMCU_row + delta)
|
||||
break;
|
||||
}
|
||||
@@ -452,34 +475,53 @@ 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) {
|
||||
if (cinfo->output_iMCU_row < last_iMCU_row - 1) {
|
||||
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) {
|
||||
block_rows = compptr->v_samp_factor;
|
||||
access_rows = block_rows * 2; /* this and next iMCU row */
|
||||
last_row = FALSE;
|
||||
} else {
|
||||
/* NB: can't use last_row_height here; it is input-side-dependent! */
|
||||
block_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
|
||||
if (block_rows == 0) block_rows = compptr->v_samp_factor;
|
||||
access_rows = block_rows; /* this iMCU row only */
|
||||
last_row = TRUE;
|
||||
}
|
||||
/* Align the virtual buffer for this component. */
|
||||
if (cinfo->output_iMCU_row > 0) {
|
||||
access_rows += compptr->v_samp_factor; /* prior iMCU row too */
|
||||
if (cinfo->output_iMCU_row > 1) {
|
||||
access_rows += 2 * compptr->v_samp_factor; /* prior two iMCU rows too */
|
||||
buffer = (*cinfo->mem->access_virt_barray)
|
||||
((j_common_ptr)cinfo, coef->whole_image[ci],
|
||||
(cinfo->output_iMCU_row - 2) * compptr->v_samp_factor,
|
||||
(JDIMENSION)access_rows, FALSE);
|
||||
buffer += 2 * compptr->v_samp_factor; /* point to current iMCU row */
|
||||
} else if (cinfo->output_iMCU_row > 0) {
|
||||
buffer = (*cinfo->mem->access_virt_barray)
|
||||
((j_common_ptr)cinfo, coef->whole_image[ci],
|
||||
(cinfo->output_iMCU_row - 1) * compptr->v_samp_factor,
|
||||
(JDIMENSION)access_rows, FALSE);
|
||||
buffer += compptr->v_samp_factor; /* point to current iMCU row */
|
||||
first_row = FALSE;
|
||||
} else {
|
||||
buffer = (*cinfo->mem->access_virt_barray)
|
||||
((j_common_ptr)cinfo, coef->whole_image[ci],
|
||||
(JDIMENSION)0, (JDIMENSION)access_rows, FALSE);
|
||||
first_row = TRUE;
|
||||
}
|
||||
/* Fetch component-dependent info */
|
||||
coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS);
|
||||
/* Fetch component-dependent info.
|
||||
* If the current scan is incomplete, then we use the component-dependent
|
||||
* info from the previous scan.
|
||||
*/
|
||||
if (cinfo->output_iMCU_row > cinfo->master->last_good_iMCU_row)
|
||||
coef_bits =
|
||||
coef->coef_bits_latch + ((ci + cinfo->num_components) * SAVED_COEFS);
|
||||
else
|
||||
coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS);
|
||||
|
||||
/* We only do DC interpolation if no AC coefficient data is available. */
|
||||
change_dc =
|
||||
coef_bits[1] == -1 && coef_bits[2] == -1 && coef_bits[3] == -1 &&
|
||||
coef_bits[4] == -1 && coef_bits[5] == -1 && coef_bits[6] == -1 &&
|
||||
coef_bits[7] == -1 && coef_bits[8] == -1 && coef_bits[9] == -1;
|
||||
|
||||
quanttbl = compptr->quant_table;
|
||||
Q00 = quanttbl->quantval[0];
|
||||
Q01 = quanttbl->quantval[Q01_POS];
|
||||
@@ -487,27 +529,51 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
Q20 = quanttbl->quantval[Q20_POS];
|
||||
Q11 = quanttbl->quantval[Q11_POS];
|
||||
Q02 = quanttbl->quantval[Q02_POS];
|
||||
if (change_dc) {
|
||||
Q03 = quanttbl->quantval[Q03_POS];
|
||||
Q12 = quanttbl->quantval[Q12_POS];
|
||||
Q21 = quanttbl->quantval[Q21_POS];
|
||||
Q30 = quanttbl->quantval[Q30_POS];
|
||||
}
|
||||
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++) {
|
||||
buffer_ptr = buffer[block_row] + cinfo->master->first_MCU_col[ci];
|
||||
if (first_row && block_row == 0)
|
||||
|
||||
if (block_row > 0 || cinfo->output_iMCU_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)
|
||||
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)
|
||||
next_block_row =
|
||||
buffer[block_row + 1] + cinfo->master->first_MCU_col[ci];
|
||||
else
|
||||
prev_block_row = buffer[block_row - 1] +
|
||||
cinfo->master->first_MCU_col[ci];
|
||||
if (last_row && block_row == block_rows - 1)
|
||||
next_block_row = buffer_ptr;
|
||||
|
||||
if (block_row < block_rows - 2 ||
|
||||
cinfo->output_iMCU_row < last_iMCU_row - 1)
|
||||
next_next_block_row =
|
||||
buffer[block_row + 2] + cinfo->master->first_MCU_col[ci];
|
||||
else
|
||||
next_block_row = buffer[block_row + 1] +
|
||||
cinfo->master->first_MCU_col[ci];
|
||||
next_next_block_row = next_block_row;
|
||||
|
||||
/* We fetch the surrounding DC values using a sliding-register approach.
|
||||
* Initialize all nine here so as to do the right thing on narrow pics.
|
||||
* Initialize all 25 here so as to do the right thing on narrow pics.
|
||||
*/
|
||||
DC1 = DC2 = DC3 = (int)prev_block_row[0][0];
|
||||
DC4 = DC5 = DC6 = (int)buffer_ptr[0][0];
|
||||
DC7 = DC8 = DC9 = (int)next_block_row[0][0];
|
||||
DC01 = DC02 = DC03 = DC04 = DC05 = (int)prev_prev_block_row[0][0];
|
||||
DC06 = DC07 = DC08 = DC09 = DC10 = (int)prev_block_row[0][0];
|
||||
DC11 = DC12 = DC13 = DC14 = DC15 = (int)buffer_ptr[0][0];
|
||||
DC16 = DC17 = DC18 = DC19 = DC20 = (int)next_block_row[0][0];
|
||||
DC21 = DC22 = DC23 = DC24 = DC25 = (int)next_next_block_row[0][0];
|
||||
output_col = 0;
|
||||
last_block_column = compptr->width_in_blocks - 1;
|
||||
for (block_num = cinfo->master->first_MCU_col[ci];
|
||||
@@ -515,18 +581,39 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
/* Fetch current DCT block into workspace so we can modify it. */
|
||||
jcopy_block_row(buffer_ptr, (JBLOCKROW)workspace, (JDIMENSION)1);
|
||||
/* Update DC values */
|
||||
if (block_num < last_block_column) {
|
||||
DC3 = (int)prev_block_row[1][0];
|
||||
DC6 = (int)buffer_ptr[1][0];
|
||||
DC9 = (int)next_block_row[1][0];
|
||||
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];
|
||||
}
|
||||
/* Compute coefficient estimates per K.8.
|
||||
* An estimate is applied only if coefficient is still zero,
|
||||
* and is not known to be fully accurate.
|
||||
if (block_num + 1 < last_block_column) {
|
||||
DC05 = (int)prev_prev_block_row[2][0];
|
||||
DC10 = (int)prev_block_row[2][0];
|
||||
DC15 = (int)buffer_ptr[2][0];
|
||||
DC20 = (int)next_block_row[2][0];
|
||||
DC25 = (int)next_next_block_row[2][0];
|
||||
}
|
||||
/* If DC interpolation is enabled, compute coefficient estimates using
|
||||
* a Gaussian-like kernel, keeping the averages of the DC values.
|
||||
*
|
||||
* If DC interpolation is disabled, compute coefficient estimates using
|
||||
* an algorithm similar to the one described in Section K.8 of the JPEG
|
||||
* standard, except applied to a 5x5 window rather than a 3x3 window.
|
||||
*
|
||||
* An estimate is applied only if the coefficient is still zero and is
|
||||
* not known to be fully accurate.
|
||||
*/
|
||||
/* AC01 */
|
||||
if ((Al = coef_bits[1]) != 0 && workspace[1] == 0) {
|
||||
num = 36 * Q00 * (DC4 - DC6);
|
||||
num = Q00 * (change_dc ?
|
||||
(-DC01 - DC02 + DC04 + DC05 - 3 * DC06 + 13 * DC07 -
|
||||
13 * DC09 + 3 * DC10 - 3 * DC11 + 38 * DC12 - 38 * DC14 +
|
||||
3 * DC15 - 3 * DC16 + 13 * DC17 - 13 * DC19 + 3 * DC20 -
|
||||
DC21 - DC22 + DC24 + DC25) :
|
||||
(-7 * DC11 + 50 * DC12 - 50 * DC14 + 7 * DC15));
|
||||
if (num >= 0) {
|
||||
pred = (int)(((Q01 << 7) + num) / (Q01 << 8));
|
||||
if (Al > 0 && pred >= (1 << Al))
|
||||
@@ -541,7 +628,12 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
}
|
||||
/* AC10 */
|
||||
if ((Al = coef_bits[2]) != 0 && workspace[8] == 0) {
|
||||
num = 36 * Q00 * (DC2 - DC8);
|
||||
num = Q00 * (change_dc ?
|
||||
(-DC01 - 3 * DC02 - 3 * DC03 - 3 * DC04 - DC05 - DC06 +
|
||||
13 * DC07 + 38 * DC08 + 13 * DC09 - DC10 + DC16 -
|
||||
13 * DC17 - 38 * DC18 - 13 * DC19 + DC20 + DC21 +
|
||||
3 * DC22 + 3 * DC23 + 3 * DC24 + DC25) :
|
||||
(-7 * DC03 + 50 * DC08 - 50 * DC18 + 7 * DC23));
|
||||
if (num >= 0) {
|
||||
pred = (int)(((Q10 << 7) + num) / (Q10 << 8));
|
||||
if (Al > 0 && pred >= (1 << Al))
|
||||
@@ -556,7 +648,10 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
}
|
||||
/* AC20 */
|
||||
if ((Al = coef_bits[3]) != 0 && workspace[16] == 0) {
|
||||
num = 9 * Q00 * (DC2 + DC8 - 2 * DC5);
|
||||
num = Q00 * (change_dc ?
|
||||
(DC03 + 2 * DC07 + 7 * DC08 + 2 * DC09 - 5 * DC12 - 14 * DC13 -
|
||||
5 * DC14 + 2 * DC17 + 7 * DC18 + 2 * DC19 + DC23) :
|
||||
(-DC03 + 13 * DC08 - 24 * DC13 + 13 * DC18 - DC23));
|
||||
if (num >= 0) {
|
||||
pred = (int)(((Q20 << 7) + num) / (Q20 << 8));
|
||||
if (Al > 0 && pred >= (1 << Al))
|
||||
@@ -571,7 +666,11 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
}
|
||||
/* AC11 */
|
||||
if ((Al = coef_bits[4]) != 0 && workspace[9] == 0) {
|
||||
num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
|
||||
num = Q00 * (change_dc ?
|
||||
(-DC01 + DC05 + 9 * DC07 - 9 * DC09 - 9 * DC17 +
|
||||
9 * DC19 + DC21 - DC25) :
|
||||
(DC10 + DC16 - 10 * DC17 + 10 * DC19 - DC02 - DC20 + DC22 -
|
||||
DC24 + DC04 - DC06 + 10 * DC07 - 10 * DC09));
|
||||
if (num >= 0) {
|
||||
pred = (int)(((Q11 << 7) + num) / (Q11 << 8));
|
||||
if (Al > 0 && pred >= (1 << Al))
|
||||
@@ -586,7 +685,10 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
}
|
||||
/* AC02 */
|
||||
if ((Al = coef_bits[5]) != 0 && workspace[2] == 0) {
|
||||
num = 9 * Q00 * (DC4 + DC6 - 2 * DC5);
|
||||
num = Q00 * (change_dc ?
|
||||
(2 * DC07 - 5 * DC08 + 2 * DC09 + DC11 + 7 * DC12 - 14 * DC13 +
|
||||
7 * DC14 + DC15 + 2 * DC17 - 5 * DC18 + 2 * DC19) :
|
||||
(-DC11 + 13 * DC12 - 24 * DC13 + 13 * DC14 - DC15));
|
||||
if (num >= 0) {
|
||||
pred = (int)(((Q02 << 7) + num) / (Q02 << 8));
|
||||
if (Al > 0 && pred >= (1 << Al))
|
||||
@@ -599,14 +701,96 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
}
|
||||
workspace[2] = (JCOEF)pred;
|
||||
}
|
||||
if (change_dc) {
|
||||
/* AC03 */
|
||||
if ((Al = coef_bits[6]) != 0 && workspace[3] == 0) {
|
||||
num = Q00 * (DC07 - DC09 + 2 * DC12 - 2 * DC14 + DC17 - DC19);
|
||||
if (num >= 0) {
|
||||
pred = (int)(((Q03 << 7) + num) / (Q03 << 8));
|
||||
if (Al > 0 && pred >= (1 << Al))
|
||||
pred = (1 << Al) - 1;
|
||||
} else {
|
||||
pred = (int)(((Q03 << 7) - num) / (Q03 << 8));
|
||||
if (Al > 0 && pred >= (1 << Al))
|
||||
pred = (1 << Al) - 1;
|
||||
pred = -pred;
|
||||
}
|
||||
workspace[3] = (JCOEF)pred;
|
||||
}
|
||||
/* AC12 */
|
||||
if ((Al = coef_bits[7]) != 0 && workspace[10] == 0) {
|
||||
num = Q00 * (DC07 - 3 * DC08 + DC09 - DC17 + 3 * DC18 - DC19);
|
||||
if (num >= 0) {
|
||||
pred = (int)(((Q12 << 7) + num) / (Q12 << 8));
|
||||
if (Al > 0 && pred >= (1 << Al))
|
||||
pred = (1 << Al) - 1;
|
||||
} else {
|
||||
pred = (int)(((Q12 << 7) - num) / (Q12 << 8));
|
||||
if (Al > 0 && pred >= (1 << Al))
|
||||
pred = (1 << Al) - 1;
|
||||
pred = -pred;
|
||||
}
|
||||
workspace[10] = (JCOEF)pred;
|
||||
}
|
||||
/* AC21 */
|
||||
if ((Al = coef_bits[8]) != 0 && workspace[17] == 0) {
|
||||
num = Q00 * (DC07 - DC09 - 3 * DC12 + 3 * DC14 + DC17 - DC19);
|
||||
if (num >= 0) {
|
||||
pred = (int)(((Q21 << 7) + num) / (Q21 << 8));
|
||||
if (Al > 0 && pred >= (1 << Al))
|
||||
pred = (1 << Al) - 1;
|
||||
} else {
|
||||
pred = (int)(((Q21 << 7) - num) / (Q21 << 8));
|
||||
if (Al > 0 && pred >= (1 << Al))
|
||||
pred = (1 << Al) - 1;
|
||||
pred = -pred;
|
||||
}
|
||||
workspace[17] = (JCOEF)pred;
|
||||
}
|
||||
/* AC30 */
|
||||
if ((Al = coef_bits[9]) != 0 && workspace[24] == 0) {
|
||||
num = Q00 * (DC07 + 2 * DC08 + DC09 - DC17 - 2 * DC18 - DC19);
|
||||
if (num >= 0) {
|
||||
pred = (int)(((Q30 << 7) + num) / (Q30 << 8));
|
||||
if (Al > 0 && pred >= (1 << Al))
|
||||
pred = (1 << Al) - 1;
|
||||
} else {
|
||||
pred = (int)(((Q30 << 7) - num) / (Q30 << 8));
|
||||
if (Al > 0 && pred >= (1 << Al))
|
||||
pred = (1 << Al) - 1;
|
||||
pred = -pred;
|
||||
}
|
||||
workspace[24] = (JCOEF)pred;
|
||||
}
|
||||
/* coef_bits[0] is non-negative. Otherwise this function would not
|
||||
* be called.
|
||||
*/
|
||||
num = Q00 *
|
||||
(-2 * DC01 - 6 * DC02 - 8 * DC03 - 6 * DC04 - 2 * DC05 -
|
||||
6 * DC06 + 6 * DC07 + 42 * DC08 + 6 * DC09 - 6 * DC10 -
|
||||
8 * DC11 + 42 * DC12 + 152 * DC13 + 42 * DC14 - 8 * DC15 -
|
||||
6 * DC16 + 6 * DC17 + 42 * DC18 + 6 * DC19 - 6 * DC20 -
|
||||
2 * DC21 - 6 * DC22 - 8 * DC23 - 6 * DC24 - 2 * DC25);
|
||||
if (num >= 0) {
|
||||
pred = (int)(((Q00 << 7) + num) / (Q00 << 8));
|
||||
} else {
|
||||
pred = (int)(((Q00 << 7) - num) / (Q00 << 8));
|
||||
pred = -pred;
|
||||
}
|
||||
workspace[0] = (JCOEF)pred;
|
||||
} /* change_dc */
|
||||
|
||||
/* OK, do the IDCT */
|
||||
(*inverse_DCT) (cinfo, compptr, (JCOEFPTR)workspace, output_ptr,
|
||||
output_col);
|
||||
/* Advance for next column */
|
||||
DC1 = DC2; DC2 = DC3;
|
||||
DC4 = DC5; DC5 = DC6;
|
||||
DC7 = DC8; DC8 = DC9;
|
||||
buffer_ptr++, prev_block_row++, next_block_row++;
|
||||
DC01 = DC02; DC02 = DC03; DC03 = DC04; DC04 = DC05;
|
||||
DC06 = DC07; DC07 = DC08; DC08 = DC09; DC09 = DC10;
|
||||
DC11 = DC12; DC12 = DC13; DC13 = DC14; DC14 = DC15;
|
||||
DC16 = DC17; DC17 = DC18; DC18 = DC19; DC19 = DC20;
|
||||
DC21 = DC22; DC22 = DC23; DC23 = DC24; DC24 = DC25;
|
||||
buffer_ptr++, prev_block_row++, next_block_row++,
|
||||
prev_prev_block_row++, next_next_block_row++;
|
||||
output_col += compptr->_DCT_scaled_size;
|
||||
}
|
||||
output_ptr += compptr->_DCT_scaled_size;
|
||||
@@ -655,7 +839,7 @@ jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||
/* If block smoothing could be used, need a bigger window */
|
||||
if (cinfo->progressive_mode)
|
||||
access_rows *= 3;
|
||||
access_rows *= 5;
|
||||
#endif
|
||||
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
|
||||
((j_common_ptr)cinfo, JPOOL_IMAGE, TRUE,
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
||||
* Copyright (C) 2020, Google, Inc.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*/
|
||||
@@ -51,7 +52,7 @@ typedef struct {
|
||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||
/* When doing block smoothing, we latch coefficient Al values here */
|
||||
int *coef_bits_latch;
|
||||
#define SAVED_COEFS 6 /* we save coef_bits[0..5] */
|
||||
#define SAVED_COEFS 10 /* we save coef_bits[0..9] */
|
||||
#endif
|
||||
} my_coef_controller;
|
||||
|
||||
|
||||
+48
-48
@@ -45,9 +45,9 @@ ycc_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
outptr = *output_buf++;
|
||||
|
||||
if (PACK_NEED_ALIGNMENT(outptr)) {
|
||||
y = GETJSAMPLE(*inptr0++);
|
||||
cb = GETJSAMPLE(*inptr1++);
|
||||
cr = GETJSAMPLE(*inptr2++);
|
||||
y = *inptr0++;
|
||||
cb = *inptr1++;
|
||||
cr = *inptr2++;
|
||||
r = range_limit[y + Crrtab[cr]];
|
||||
g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
|
||||
SCALEBITS))];
|
||||
@@ -58,18 +58,18 @@ ycc_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
num_cols--;
|
||||
}
|
||||
for (col = 0; col < (num_cols >> 1); col++) {
|
||||
y = GETJSAMPLE(*inptr0++);
|
||||
cb = GETJSAMPLE(*inptr1++);
|
||||
cr = GETJSAMPLE(*inptr2++);
|
||||
y = *inptr0++;
|
||||
cb = *inptr1++;
|
||||
cr = *inptr2++;
|
||||
r = range_limit[y + Crrtab[cr]];
|
||||
g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
|
||||
SCALEBITS))];
|
||||
b = range_limit[y + Cbbtab[cb]];
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
|
||||
y = GETJSAMPLE(*inptr0++);
|
||||
cb = GETJSAMPLE(*inptr1++);
|
||||
cr = GETJSAMPLE(*inptr2++);
|
||||
y = *inptr0++;
|
||||
cb = *inptr1++;
|
||||
cr = *inptr2++;
|
||||
r = range_limit[y + Crrtab[cr]];
|
||||
g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
|
||||
SCALEBITS))];
|
||||
@@ -80,9 +80,9 @@ ycc_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
outptr += 4;
|
||||
}
|
||||
if (num_cols & 1) {
|
||||
y = GETJSAMPLE(*inptr0);
|
||||
cb = GETJSAMPLE(*inptr1);
|
||||
cr = GETJSAMPLE(*inptr2);
|
||||
y = *inptr0;
|
||||
cb = *inptr1;
|
||||
cr = *inptr2;
|
||||
r = range_limit[y + Crrtab[cr]];
|
||||
g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
|
||||
SCALEBITS))];
|
||||
@@ -125,9 +125,9 @@ ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
input_row++;
|
||||
outptr = *output_buf++;
|
||||
if (PACK_NEED_ALIGNMENT(outptr)) {
|
||||
y = GETJSAMPLE(*inptr0++);
|
||||
cb = GETJSAMPLE(*inptr1++);
|
||||
cr = GETJSAMPLE(*inptr2++);
|
||||
y = *inptr0++;
|
||||
cb = *inptr1++;
|
||||
cr = *inptr2++;
|
||||
r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
|
||||
g = range_limit[DITHER_565_G(y +
|
||||
((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
|
||||
@@ -139,9 +139,9 @@ ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
num_cols--;
|
||||
}
|
||||
for (col = 0; col < (num_cols >> 1); col++) {
|
||||
y = GETJSAMPLE(*inptr0++);
|
||||
cb = GETJSAMPLE(*inptr1++);
|
||||
cr = GETJSAMPLE(*inptr2++);
|
||||
y = *inptr0++;
|
||||
cb = *inptr1++;
|
||||
cr = *inptr2++;
|
||||
r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
|
||||
g = range_limit[DITHER_565_G(y +
|
||||
((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
|
||||
@@ -150,9 +150,9 @@ ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
d0 = DITHER_ROTATE(d0);
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
|
||||
y = GETJSAMPLE(*inptr0++);
|
||||
cb = GETJSAMPLE(*inptr1++);
|
||||
cr = GETJSAMPLE(*inptr2++);
|
||||
y = *inptr0++;
|
||||
cb = *inptr1++;
|
||||
cr = *inptr2++;
|
||||
r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
|
||||
g = range_limit[DITHER_565_G(y +
|
||||
((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
|
||||
@@ -165,9 +165,9 @@ ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
outptr += 4;
|
||||
}
|
||||
if (num_cols & 1) {
|
||||
y = GETJSAMPLE(*inptr0);
|
||||
cb = GETJSAMPLE(*inptr1);
|
||||
cr = GETJSAMPLE(*inptr2);
|
||||
y = *inptr0;
|
||||
cb = *inptr1;
|
||||
cr = *inptr2;
|
||||
r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
|
||||
g = range_limit[DITHER_565_G(y +
|
||||
((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
|
||||
@@ -202,32 +202,32 @@ rgb_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
input_row++;
|
||||
outptr = *output_buf++;
|
||||
if (PACK_NEED_ALIGNMENT(outptr)) {
|
||||
r = GETJSAMPLE(*inptr0++);
|
||||
g = GETJSAMPLE(*inptr1++);
|
||||
b = GETJSAMPLE(*inptr2++);
|
||||
r = *inptr0++;
|
||||
g = *inptr1++;
|
||||
b = *inptr2++;
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
*(INT16 *)outptr = (INT16)rgb;
|
||||
outptr += 2;
|
||||
num_cols--;
|
||||
}
|
||||
for (col = 0; col < (num_cols >> 1); col++) {
|
||||
r = GETJSAMPLE(*inptr0++);
|
||||
g = GETJSAMPLE(*inptr1++);
|
||||
b = GETJSAMPLE(*inptr2++);
|
||||
r = *inptr0++;
|
||||
g = *inptr1++;
|
||||
b = *inptr2++;
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
|
||||
r = GETJSAMPLE(*inptr0++);
|
||||
g = GETJSAMPLE(*inptr1++);
|
||||
b = GETJSAMPLE(*inptr2++);
|
||||
r = *inptr0++;
|
||||
g = *inptr1++;
|
||||
b = *inptr2++;
|
||||
rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
|
||||
|
||||
WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
|
||||
outptr += 4;
|
||||
}
|
||||
if (num_cols & 1) {
|
||||
r = GETJSAMPLE(*inptr0);
|
||||
g = GETJSAMPLE(*inptr1);
|
||||
b = GETJSAMPLE(*inptr2);
|
||||
r = *inptr0;
|
||||
g = *inptr1;
|
||||
b = *inptr2;
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
*(INT16 *)outptr = (INT16)rgb;
|
||||
}
|
||||
@@ -259,24 +259,24 @@ rgb_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
input_row++;
|
||||
outptr = *output_buf++;
|
||||
if (PACK_NEED_ALIGNMENT(outptr)) {
|
||||
r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
|
||||
g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
|
||||
b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
|
||||
r = range_limit[DITHER_565_R(*inptr0++, d0)];
|
||||
g = range_limit[DITHER_565_G(*inptr1++, d0)];
|
||||
b = range_limit[DITHER_565_B(*inptr2++, d0)];
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
*(INT16 *)outptr = (INT16)rgb;
|
||||
outptr += 2;
|
||||
num_cols--;
|
||||
}
|
||||
for (col = 0; col < (num_cols >> 1); col++) {
|
||||
r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
|
||||
g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
|
||||
b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
|
||||
r = range_limit[DITHER_565_R(*inptr0++, d0)];
|
||||
g = range_limit[DITHER_565_G(*inptr1++, d0)];
|
||||
b = range_limit[DITHER_565_B(*inptr2++, d0)];
|
||||
d0 = DITHER_ROTATE(d0);
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
|
||||
r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
|
||||
g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
|
||||
b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
|
||||
r = range_limit[DITHER_565_R(*inptr0++, d0)];
|
||||
g = range_limit[DITHER_565_G(*inptr1++, d0)];
|
||||
b = range_limit[DITHER_565_B(*inptr2++, d0)];
|
||||
d0 = DITHER_ROTATE(d0);
|
||||
rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
|
||||
|
||||
@@ -284,9 +284,9 @@ rgb_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
outptr += 4;
|
||||
}
|
||||
if (num_cols & 1) {
|
||||
r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0), d0)];
|
||||
g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1), d0)];
|
||||
b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2), d0)];
|
||||
r = range_limit[DITHER_565_R(*inptr0, d0)];
|
||||
g = range_limit[DITHER_565_G(*inptr1, d0)];
|
||||
b = range_limit[DITHER_565_B(*inptr2, d0)];
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
*(INT16 *)outptr = (INT16)rgb;
|
||||
}
|
||||
|
||||
+3
-5
@@ -53,9 +53,9 @@ ycc_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
input_row++;
|
||||
outptr = *output_buf++;
|
||||
for (col = 0; col < num_cols; col++) {
|
||||
y = GETJSAMPLE(inptr0[col]);
|
||||
cb = GETJSAMPLE(inptr1[col]);
|
||||
cr = GETJSAMPLE(inptr2[col]);
|
||||
y = inptr0[col];
|
||||
cb = inptr1[col];
|
||||
cr = inptr2[col];
|
||||
/* Range-limiting is essential due to noise introduced by DCT losses. */
|
||||
outptr[RGB_RED] = range_limit[y + Crrtab[cr]];
|
||||
outptr[RGB_GREEN] = range_limit[y +
|
||||
@@ -93,7 +93,6 @@ gray_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
inptr = input_buf[0][input_row++];
|
||||
outptr = *output_buf++;
|
||||
for (col = 0; col < num_cols; col++) {
|
||||
/* We can dispense with GETJSAMPLE() here */
|
||||
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 */
|
||||
@@ -128,7 +127,6 @@ rgb_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
input_row++;
|
||||
outptr = *output_buf++;
|
||||
for (col = 0; col < num_cols; col++) {
|
||||
/* We can dispense with GETJSAMPLE() here */
|
||||
outptr[RGB_RED] = inptr0[col];
|
||||
outptr[RGB_GREEN] = inptr1[col];
|
||||
outptr[RGB_BLUE] = inptr2[col];
|
||||
|
||||
Vendored
+7
-7
@@ -341,9 +341,9 @@ rgb_gray_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
input_row++;
|
||||
outptr = *output_buf++;
|
||||
for (col = 0; col < num_cols; col++) {
|
||||
r = GETJSAMPLE(inptr0[col]);
|
||||
g = GETJSAMPLE(inptr1[col]);
|
||||
b = GETJSAMPLE(inptr2[col]);
|
||||
r = inptr0[col];
|
||||
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);
|
||||
@@ -550,9 +550,9 @@ ycck_cmyk_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
input_row++;
|
||||
outptr = *output_buf++;
|
||||
for (col = 0; col < num_cols; col++) {
|
||||
y = GETJSAMPLE(inptr0[col]);
|
||||
cb = GETJSAMPLE(inptr1[col]);
|
||||
cr = GETJSAMPLE(inptr2[col]);
|
||||
y = inptr0[col];
|
||||
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 */
|
||||
@@ -560,7 +560,7 @@ ycck_cmyk_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
SCALEBITS)))];
|
||||
outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */
|
||||
/* K passes through unchanged */
|
||||
outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */
|
||||
outptr[3] = inptr3[col];
|
||||
outptr += 4;
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+27
-33
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2009-2011, 2016, 2018-2019, D. R. Commander.
|
||||
* Copyright (C) 2018, Matthias Räncker.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
@@ -39,24 +40,6 @@ typedef struct {
|
||||
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
|
||||
} savable_state;
|
||||
|
||||
/* This macro is to work around compilers with missing or broken
|
||||
* structure assignment. You'll need to fix this code if you have
|
||||
* such a compiler and you change MAX_COMPS_IN_SCAN.
|
||||
*/
|
||||
|
||||
#ifndef NO_STRUCT_ASSIGN
|
||||
#define ASSIGN_STATE(dest, src) ((dest) = (src))
|
||||
#else
|
||||
#if MAX_COMPS_IN_SCAN == 4
|
||||
#define ASSIGN_STATE(dest, src) \
|
||||
((dest).last_dc_val[0] = (src).last_dc_val[0], \
|
||||
(dest).last_dc_val[1] = (src).last_dc_val[1], \
|
||||
(dest).last_dc_val[2] = (src).last_dc_val[2], \
|
||||
(dest).last_dc_val[3] = (src).last_dc_val[3])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_entropy_decoder pub; /* public fields */
|
||||
|
||||
@@ -325,7 +308,7 @@ jpeg_fill_bit_buffer(bitread_working_state *state,
|
||||
bytes_in_buffer = cinfo->src->bytes_in_buffer;
|
||||
}
|
||||
bytes_in_buffer--;
|
||||
c = GETJOCTET(*next_input_byte++);
|
||||
c = *next_input_byte++;
|
||||
|
||||
/* If it's 0xFF, check and discard stuffed zero byte */
|
||||
if (c == 0xFF) {
|
||||
@@ -342,7 +325,7 @@ jpeg_fill_bit_buffer(bitread_working_state *state,
|
||||
bytes_in_buffer = cinfo->src->bytes_in_buffer;
|
||||
}
|
||||
bytes_in_buffer--;
|
||||
c = GETJOCTET(*next_input_byte++);
|
||||
c = *next_input_byte++;
|
||||
} while (c == 0xFF);
|
||||
|
||||
if (c == 0) {
|
||||
@@ -405,8 +388,8 @@ no_more_bytes:
|
||||
|
||||
#define GET_BYTE { \
|
||||
register int c0, c1; \
|
||||
c0 = GETJOCTET(*buffer++); \
|
||||
c1 = GETJOCTET(*buffer); \
|
||||
c0 = *buffer++; \
|
||||
c1 = *buffer; \
|
||||
/* Pre-execute most common case */ \
|
||||
get_buffer = (get_buffer << 8) | c0; \
|
||||
bits_left += 8; \
|
||||
@@ -423,7 +406,7 @@ no_more_bytes:
|
||||
} \
|
||||
}
|
||||
|
||||
#if SIZEOF_SIZE_T == 8 || defined(_WIN64)
|
||||
#if SIZEOF_SIZE_T == 8 || defined(_WIN64) || (defined(__x86_64__) && defined(__ILP32__))
|
||||
|
||||
/* Pre-fetch 48 bytes, because the holding register is 64-bit */
|
||||
#define FILL_BIT_BUFFER_FAST \
|
||||
@@ -557,6 +540,12 @@ process_restart(j_decompress_ptr cinfo)
|
||||
}
|
||||
|
||||
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(undefined_behavior_sanitizer)
|
||||
__attribute__((no_sanitize("signed-integer-overflow"),
|
||||
no_sanitize("unsigned-integer-overflow")))
|
||||
#endif
|
||||
#endif
|
||||
LOCAL(boolean)
|
||||
decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
@@ -568,7 +557,7 @@ decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
|
||||
/* Load up working state */
|
||||
BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
|
||||
ASSIGN_STATE(state, entropy->saved);
|
||||
state = entropy->saved;
|
||||
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
JBLOCKROW block = MCU_data ? MCU_data[blkn] : NULL;
|
||||
@@ -589,11 +578,15 @@ decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
if (entropy->dc_needed[blkn]) {
|
||||
/* Convert DC difference to actual value, update last_dc_val */
|
||||
int ci = cinfo->MCU_membership[blkn];
|
||||
/* This is really just
|
||||
* s += state.last_dc_val[ci];
|
||||
* It is written this way in order to shut up UBSan.
|
||||
/* Certain malformed JPEG images produce repeated DC coefficient
|
||||
* differences of 2047 or -2047, which causes state.last_dc_val[ci] to
|
||||
* grow until it overflows or underflows a 32-bit signed integer. This
|
||||
* behavior is, to the best of our understanding, innocuous, and it is
|
||||
* unclear how to work around it without potentially affecting
|
||||
* performance. Thus, we (hopefully temporarily) suppress UBSan integer
|
||||
* overflow errors for this function.
|
||||
*/
|
||||
s = (int)((unsigned int)s + (unsigned int)state.last_dc_val[ci]);
|
||||
s += state.last_dc_val[ci];
|
||||
state.last_dc_val[ci] = s;
|
||||
if (block) {
|
||||
/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
|
||||
@@ -653,7 +646,7 @@ decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
|
||||
/* Completed MCU, so update state */
|
||||
BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
|
||||
ASSIGN_STATE(entropy->saved, state);
|
||||
entropy->saved = state;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -671,7 +664,7 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
/* Load up working state */
|
||||
BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
|
||||
buffer = (JOCTET *)br_state.next_input_byte;
|
||||
ASSIGN_STATE(state, entropy->saved);
|
||||
state = entropy->saved;
|
||||
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
JBLOCKROW block = MCU_data ? MCU_data[blkn] : NULL;
|
||||
@@ -688,7 +681,7 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
|
||||
if (entropy->dc_needed[blkn]) {
|
||||
int ci = cinfo->MCU_membership[blkn];
|
||||
s = (int)((unsigned int)s + (unsigned int)state.last_dc_val[ci]);
|
||||
s += state.last_dc_val[ci];
|
||||
state.last_dc_val[ci] = s;
|
||||
if (block)
|
||||
(*block)[0] = (JCOEF)s;
|
||||
@@ -740,7 +733,7 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
br_state.bytes_in_buffer -= (buffer - br_state.next_input_byte);
|
||||
br_state.next_input_byte = buffer;
|
||||
BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
|
||||
ASSIGN_STATE(entropy->saved, state);
|
||||
entropy->saved = state;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -795,7 +788,8 @@ use_slow:
|
||||
}
|
||||
|
||||
/* Account for restart interval (no-op if not using restarts) */
|
||||
entropy->restarts_to_go--;
|
||||
if (cinfo->restart_interval)
|
||||
entropy->restarts_to_go--;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Vendored
+11
-2
@@ -4,7 +4,8 @@
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2010-2011, 2015-2016, D. R. Commander.
|
||||
* Copyright (C) 2010-2011, 2015-2016, 2021, D. R. Commander.
|
||||
* Copyright (C) 2018, Matthias Räncker.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
@@ -78,6 +79,11 @@ EXTERN(void) jpeg_make_d_derived_tbl(j_decompress_ptr cinfo, boolean isDC,
|
||||
typedef size_t bit_buf_type; /* type of bit-extraction buffer */
|
||||
#define BIT_BUF_SIZE 64 /* size of buffer in bits */
|
||||
|
||||
#elif defined(__x86_64__) && defined(__ILP32__)
|
||||
|
||||
typedef unsigned long long bit_buf_type; /* type of bit-extraction buffer */
|
||||
#define BIT_BUF_SIZE 64 /* size of buffer in bits */
|
||||
|
||||
#else
|
||||
|
||||
typedef unsigned long bit_buf_type; /* type of bit-extraction buffer */
|
||||
@@ -228,7 +234,10 @@ slowlabel: \
|
||||
s |= GET_BITS(1); \
|
||||
nb++; \
|
||||
} \
|
||||
s = htbl->pub->huffval[(int)(s + htbl->valoffset[nb]) & 0xFF]; \
|
||||
if (nb > 16) \
|
||||
s = 0; \
|
||||
else \
|
||||
s = htbl->pub->huffval[(int)(s + htbl->valoffset[nb]) & 0xFF]; \
|
||||
}
|
||||
|
||||
/* Out-of-line case for Huffman code fetching */
|
||||
|
||||
Vendored
+16
-16
@@ -38,18 +38,18 @@ marker_is_icc(jpeg_saved_marker_ptr marker)
|
||||
marker->marker == ICC_MARKER &&
|
||||
marker->data_length >= ICC_OVERHEAD_LEN &&
|
||||
/* verify the identifying string */
|
||||
GETJOCTET(marker->data[0]) == 0x49 &&
|
||||
GETJOCTET(marker->data[1]) == 0x43 &&
|
||||
GETJOCTET(marker->data[2]) == 0x43 &&
|
||||
GETJOCTET(marker->data[3]) == 0x5F &&
|
||||
GETJOCTET(marker->data[4]) == 0x50 &&
|
||||
GETJOCTET(marker->data[5]) == 0x52 &&
|
||||
GETJOCTET(marker->data[6]) == 0x4F &&
|
||||
GETJOCTET(marker->data[7]) == 0x46 &&
|
||||
GETJOCTET(marker->data[8]) == 0x49 &&
|
||||
GETJOCTET(marker->data[9]) == 0x4C &&
|
||||
GETJOCTET(marker->data[10]) == 0x45 &&
|
||||
GETJOCTET(marker->data[11]) == 0x0;
|
||||
marker->data[0] == 0x49 &&
|
||||
marker->data[1] == 0x43 &&
|
||||
marker->data[2] == 0x43 &&
|
||||
marker->data[3] == 0x5F &&
|
||||
marker->data[4] == 0x50 &&
|
||||
marker->data[5] == 0x52 &&
|
||||
marker->data[6] == 0x4F &&
|
||||
marker->data[7] == 0x46 &&
|
||||
marker->data[8] == 0x49 &&
|
||||
marker->data[9] == 0x4C &&
|
||||
marker->data[10] == 0x45 &&
|
||||
marker->data[11] == 0x0;
|
||||
}
|
||||
|
||||
|
||||
@@ -102,12 +102,12 @@ jpeg_read_icc_profile(j_decompress_ptr cinfo, JOCTET **icc_data_ptr,
|
||||
for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
|
||||
if (marker_is_icc(marker)) {
|
||||
if (num_markers == 0)
|
||||
num_markers = GETJOCTET(marker->data[13]);
|
||||
else if (num_markers != GETJOCTET(marker->data[13])) {
|
||||
num_markers = marker->data[13];
|
||||
else if (num_markers != marker->data[13]) {
|
||||
WARNMS(cinfo, JWRN_BOGUS_ICC); /* inconsistent num_markers fields */
|
||||
return FALSE;
|
||||
}
|
||||
seq_no = GETJOCTET(marker->data[12]);
|
||||
seq_no = marker->data[12];
|
||||
if (seq_no <= 0 || seq_no > num_markers) {
|
||||
WARNMS(cinfo, JWRN_BOGUS_ICC); /* bogus sequence number */
|
||||
return FALSE;
|
||||
@@ -154,7 +154,7 @@ jpeg_read_icc_profile(j_decompress_ptr cinfo, JOCTET **icc_data_ptr,
|
||||
JOCTET FAR *src_ptr;
|
||||
JOCTET *dst_ptr;
|
||||
unsigned int length;
|
||||
seq_no = GETJOCTET(marker->data[12]);
|
||||
seq_no = marker->data[12];
|
||||
dst_ptr = icc_data + data_offset[seq_no];
|
||||
src_ptr = marker->data + ICC_OVERHEAD_LEN;
|
||||
length = data_length[seq_no];
|
||||
|
||||
+32
-35
@@ -151,7 +151,7 @@ typedef my_marker_reader *my_marker_ptr;
|
||||
#define INPUT_BYTE(cinfo, V, action) \
|
||||
MAKESTMT( MAKE_BYTE_AVAIL(cinfo, action); \
|
||||
bytes_in_buffer--; \
|
||||
V = GETJOCTET(*next_input_byte++); )
|
||||
V = *next_input_byte++; )
|
||||
|
||||
/* As above, but read two bytes interpreted as an unsigned 16-bit integer.
|
||||
* V should be declared unsigned int or perhaps JLONG.
|
||||
@@ -159,10 +159,10 @@ typedef my_marker_reader *my_marker_ptr;
|
||||
#define INPUT_2BYTES(cinfo, V, action) \
|
||||
MAKESTMT( MAKE_BYTE_AVAIL(cinfo, action); \
|
||||
bytes_in_buffer--; \
|
||||
V = ((unsigned int)GETJOCTET(*next_input_byte++)) << 8; \
|
||||
V = ((unsigned int)(*next_input_byte++)) << 8; \
|
||||
MAKE_BYTE_AVAIL(cinfo, action); \
|
||||
bytes_in_buffer--; \
|
||||
V += GETJOCTET(*next_input_byte++); )
|
||||
V += *next_input_byte++; )
|
||||
|
||||
|
||||
/*
|
||||
@@ -608,18 +608,18 @@ examine_app0(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,
|
||||
JLONG totallen = (JLONG)datalen + remaining;
|
||||
|
||||
if (datalen >= APP0_DATA_LEN &&
|
||||
GETJOCTET(data[0]) == 0x4A &&
|
||||
GETJOCTET(data[1]) == 0x46 &&
|
||||
GETJOCTET(data[2]) == 0x49 &&
|
||||
GETJOCTET(data[3]) == 0x46 &&
|
||||
GETJOCTET(data[4]) == 0) {
|
||||
data[0] == 0x4A &&
|
||||
data[1] == 0x46 &&
|
||||
data[2] == 0x49 &&
|
||||
data[3] == 0x46 &&
|
||||
data[4] == 0) {
|
||||
/* Found JFIF APP0 marker: save info */
|
||||
cinfo->saw_JFIF_marker = TRUE;
|
||||
cinfo->JFIF_major_version = GETJOCTET(data[5]);
|
||||
cinfo->JFIF_minor_version = GETJOCTET(data[6]);
|
||||
cinfo->density_unit = GETJOCTET(data[7]);
|
||||
cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]);
|
||||
cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]);
|
||||
cinfo->JFIF_major_version = data[5];
|
||||
cinfo->JFIF_minor_version = data[6];
|
||||
cinfo->density_unit = data[7];
|
||||
cinfo->X_density = (data[8] << 8) + data[9];
|
||||
cinfo->Y_density = (data[10] << 8) + data[11];
|
||||
/* Check version.
|
||||
* Major version must be 1, anything else signals an incompatible change.
|
||||
* (We used to treat this as an error, but now it's a nonfatal warning,
|
||||
@@ -634,24 +634,22 @@ examine_app0(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,
|
||||
cinfo->JFIF_major_version, cinfo->JFIF_minor_version,
|
||||
cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
|
||||
/* Validate thumbnail dimensions and issue appropriate messages */
|
||||
if (GETJOCTET(data[12]) | GETJOCTET(data[13]))
|
||||
TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL,
|
||||
GETJOCTET(data[12]), GETJOCTET(data[13]));
|
||||
if (data[12] | data[13])
|
||||
TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, data[12], data[13]);
|
||||
totallen -= APP0_DATA_LEN;
|
||||
if (totallen !=
|
||||
((JLONG)GETJOCTET(data[12]) * (JLONG)GETJOCTET(data[13]) * (JLONG)3))
|
||||
if (totallen != ((JLONG)data[12] * (JLONG)data[13] * (JLONG)3))
|
||||
TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int)totallen);
|
||||
} else if (datalen >= 6 &&
|
||||
GETJOCTET(data[0]) == 0x4A &&
|
||||
GETJOCTET(data[1]) == 0x46 &&
|
||||
GETJOCTET(data[2]) == 0x58 &&
|
||||
GETJOCTET(data[3]) == 0x58 &&
|
||||
GETJOCTET(data[4]) == 0) {
|
||||
data[0] == 0x4A &&
|
||||
data[1] == 0x46 &&
|
||||
data[2] == 0x58 &&
|
||||
data[3] == 0x58 &&
|
||||
data[4] == 0) {
|
||||
/* Found JFIF "JFXX" extension APP0 marker */
|
||||
/* The library doesn't actually do anything with these,
|
||||
* but we try to produce a helpful trace message.
|
||||
*/
|
||||
switch (GETJOCTET(data[5])) {
|
||||
switch (data[5]) {
|
||||
case 0x10:
|
||||
TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int)totallen);
|
||||
break;
|
||||
@@ -662,8 +660,7 @@ examine_app0(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,
|
||||
TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int)totallen);
|
||||
break;
|
||||
default:
|
||||
TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION,
|
||||
GETJOCTET(data[5]), (int)totallen);
|
||||
TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, data[5], (int)totallen);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -684,16 +681,16 @@ examine_app14(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,
|
||||
unsigned int version, flags0, flags1, transform;
|
||||
|
||||
if (datalen >= APP14_DATA_LEN &&
|
||||
GETJOCTET(data[0]) == 0x41 &&
|
||||
GETJOCTET(data[1]) == 0x64 &&
|
||||
GETJOCTET(data[2]) == 0x6F &&
|
||||
GETJOCTET(data[3]) == 0x62 &&
|
||||
GETJOCTET(data[4]) == 0x65) {
|
||||
data[0] == 0x41 &&
|
||||
data[1] == 0x64 &&
|
||||
data[2] == 0x6F &&
|
||||
data[3] == 0x62 &&
|
||||
data[4] == 0x65) {
|
||||
/* Found Adobe APP14 marker */
|
||||
version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]);
|
||||
flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]);
|
||||
flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]);
|
||||
transform = GETJOCTET(data[11]);
|
||||
version = (data[5] << 8) + data[6];
|
||||
flags0 = (data[7] << 8) + data[8];
|
||||
flags1 = (data[9] << 8) + data[10];
|
||||
transform = data[11];
|
||||
TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);
|
||||
cinfo->saw_Adobe_marker = TRUE;
|
||||
cinfo->Adobe_transform = (UINT8)transform;
|
||||
|
||||
+2
-13
@@ -5,7 +5,7 @@
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 2002-2009 by Guido Vollbeding.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2009-2011, 2016, D. R. Commander.
|
||||
* Copyright (C) 2009-2011, 2016, 2019, D. R. Commander.
|
||||
* Copyright (C) 2013, Linaro Limited.
|
||||
* Copyright (C) 2015, Google, Inc.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "jpeglib.h"
|
||||
#include "jpegcomp.h"
|
||||
#include "jdmaster.h"
|
||||
#include "jsimd.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -70,17 +69,6 @@ use_merged_upsample(j_decompress_ptr cinfo)
|
||||
cinfo->comp_info[1]._DCT_scaled_size != cinfo->_min_DCT_scaled_size ||
|
||||
cinfo->comp_info[2]._DCT_scaled_size != cinfo->_min_DCT_scaled_size)
|
||||
return FALSE;
|
||||
#ifdef WITH_SIMD
|
||||
/* If YCbCr-to-RGB color conversion is SIMD-accelerated but merged upsampling
|
||||
isn't, then disabling merged upsampling is likely to be faster when
|
||||
decompressing YCbCr JPEG images. */
|
||||
if (!jsimd_can_h2v2_merged_upsample() && !jsimd_can_h2v1_merged_upsample() &&
|
||||
jsimd_can_ycc_rgb() && cinfo->jpeg_color_space == JCS_YCbCr &&
|
||||
(cinfo->out_color_space == JCS_RGB ||
|
||||
(cinfo->out_color_space >= JCS_EXT_RGB &&
|
||||
cinfo->out_color_space <= JCS_EXT_ARGB)))
|
||||
return FALSE;
|
||||
#endif
|
||||
/* ??? also need to test for upsample-time rescaling, when & if supported */
|
||||
return TRUE; /* by golly, it'll work... */
|
||||
#else
|
||||
@@ -580,6 +568,7 @@ master_selection(j_decompress_ptr cinfo)
|
||||
*/
|
||||
cinfo->master->first_iMCU_col = 0;
|
||||
cinfo->master->last_iMCU_col = cinfo->MCUs_per_row - 1;
|
||||
cinfo->master->last_good_iMCU_row = 0;
|
||||
|
||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||
/* If jpeg_start_decompress will read the whole file, initialize
|
||||
|
||||
+34
-34
@@ -43,20 +43,20 @@ h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
/* Loop for each pair of output pixels */
|
||||
for (col = cinfo->output_width >> 1; col > 0; col--) {
|
||||
/* Do the chroma part of the calculation */
|
||||
cb = GETJSAMPLE(*inptr1++);
|
||||
cr = GETJSAMPLE(*inptr2++);
|
||||
cb = *inptr1++;
|
||||
cr = *inptr2++;
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
|
||||
/* Fetch 2 Y values and emit 2 pixels */
|
||||
y = GETJSAMPLE(*inptr0++);
|
||||
y = *inptr0++;
|
||||
r = range_limit[y + cred];
|
||||
g = range_limit[y + cgreen];
|
||||
b = range_limit[y + cblue];
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
|
||||
y = GETJSAMPLE(*inptr0++);
|
||||
y = *inptr0++;
|
||||
r = range_limit[y + cred];
|
||||
g = range_limit[y + cgreen];
|
||||
b = range_limit[y + cblue];
|
||||
@@ -68,12 +68,12 @@ h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
|
||||
/* If image width is odd, do the last output column separately */
|
||||
if (cinfo->output_width & 1) {
|
||||
cb = GETJSAMPLE(*inptr1);
|
||||
cr = GETJSAMPLE(*inptr2);
|
||||
cb = *inptr1;
|
||||
cr = *inptr2;
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
y = GETJSAMPLE(*inptr0);
|
||||
y = *inptr0;
|
||||
r = range_limit[y + cred];
|
||||
g = range_limit[y + cgreen];
|
||||
b = range_limit[y + cblue];
|
||||
@@ -115,21 +115,21 @@ h2v1_merged_upsample_565D_internal(j_decompress_ptr cinfo,
|
||||
/* Loop for each pair of output pixels */
|
||||
for (col = cinfo->output_width >> 1; col > 0; col--) {
|
||||
/* Do the chroma part of the calculation */
|
||||
cb = GETJSAMPLE(*inptr1++);
|
||||
cr = GETJSAMPLE(*inptr2++);
|
||||
cb = *inptr1++;
|
||||
cr = *inptr2++;
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
|
||||
/* Fetch 2 Y values and emit 2 pixels */
|
||||
y = GETJSAMPLE(*inptr0++);
|
||||
y = *inptr0++;
|
||||
r = range_limit[DITHER_565_R(y + cred, d0)];
|
||||
g = range_limit[DITHER_565_G(y + cgreen, d0)];
|
||||
b = range_limit[DITHER_565_B(y + cblue, d0)];
|
||||
d0 = DITHER_ROTATE(d0);
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
|
||||
y = GETJSAMPLE(*inptr0++);
|
||||
y = *inptr0++;
|
||||
r = range_limit[DITHER_565_R(y + cred, d0)];
|
||||
g = range_limit[DITHER_565_G(y + cgreen, d0)];
|
||||
b = range_limit[DITHER_565_B(y + cblue, d0)];
|
||||
@@ -142,12 +142,12 @@ h2v1_merged_upsample_565D_internal(j_decompress_ptr cinfo,
|
||||
|
||||
/* If image width is odd, do the last output column separately */
|
||||
if (cinfo->output_width & 1) {
|
||||
cb = GETJSAMPLE(*inptr1);
|
||||
cr = GETJSAMPLE(*inptr2);
|
||||
cb = *inptr1;
|
||||
cr = *inptr2;
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
y = GETJSAMPLE(*inptr0);
|
||||
y = *inptr0;
|
||||
r = range_limit[DITHER_565_R(y + cred, d0)];
|
||||
g = range_limit[DITHER_565_G(y + cgreen, d0)];
|
||||
b = range_limit[DITHER_565_B(y + cblue, d0)];
|
||||
@@ -189,20 +189,20 @@ h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
/* Loop for each group of output pixels */
|
||||
for (col = cinfo->output_width >> 1; col > 0; col--) {
|
||||
/* Do the chroma part of the calculation */
|
||||
cb = GETJSAMPLE(*inptr1++);
|
||||
cr = GETJSAMPLE(*inptr2++);
|
||||
cb = *inptr1++;
|
||||
cr = *inptr2++;
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
|
||||
/* Fetch 4 Y values and emit 4 pixels */
|
||||
y = GETJSAMPLE(*inptr00++);
|
||||
y = *inptr00++;
|
||||
r = range_limit[y + cred];
|
||||
g = range_limit[y + cgreen];
|
||||
b = range_limit[y + cblue];
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
|
||||
y = GETJSAMPLE(*inptr00++);
|
||||
y = *inptr00++;
|
||||
r = range_limit[y + cred];
|
||||
g = range_limit[y + cgreen];
|
||||
b = range_limit[y + cblue];
|
||||
@@ -211,13 +211,13 @@ h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
WRITE_TWO_PIXELS(outptr0, rgb);
|
||||
outptr0 += 4;
|
||||
|
||||
y = GETJSAMPLE(*inptr01++);
|
||||
y = *inptr01++;
|
||||
r = range_limit[y + cred];
|
||||
g = range_limit[y + cgreen];
|
||||
b = range_limit[y + cblue];
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
|
||||
y = GETJSAMPLE(*inptr01++);
|
||||
y = *inptr01++;
|
||||
r = range_limit[y + cred];
|
||||
g = range_limit[y + cgreen];
|
||||
b = range_limit[y + cblue];
|
||||
@@ -229,20 +229,20 @@ h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
|
||||
/* If image width is odd, do the last output column separately */
|
||||
if (cinfo->output_width & 1) {
|
||||
cb = GETJSAMPLE(*inptr1);
|
||||
cr = GETJSAMPLE(*inptr2);
|
||||
cb = *inptr1;
|
||||
cr = *inptr2;
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
|
||||
y = GETJSAMPLE(*inptr00);
|
||||
y = *inptr00;
|
||||
r = range_limit[y + cred];
|
||||
g = range_limit[y + cgreen];
|
||||
b = range_limit[y + cblue];
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
*(INT16 *)outptr0 = (INT16)rgb;
|
||||
|
||||
y = GETJSAMPLE(*inptr01);
|
||||
y = *inptr01;
|
||||
r = range_limit[y + cred];
|
||||
g = range_limit[y + cgreen];
|
||||
b = range_limit[y + cblue];
|
||||
@@ -287,21 +287,21 @@ h2v2_merged_upsample_565D_internal(j_decompress_ptr cinfo,
|
||||
/* Loop for each group of output pixels */
|
||||
for (col = cinfo->output_width >> 1; col > 0; col--) {
|
||||
/* Do the chroma part of the calculation */
|
||||
cb = GETJSAMPLE(*inptr1++);
|
||||
cr = GETJSAMPLE(*inptr2++);
|
||||
cb = *inptr1++;
|
||||
cr = *inptr2++;
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
|
||||
/* Fetch 4 Y values and emit 4 pixels */
|
||||
y = GETJSAMPLE(*inptr00++);
|
||||
y = *inptr00++;
|
||||
r = range_limit[DITHER_565_R(y + cred, d0)];
|
||||
g = range_limit[DITHER_565_G(y + cgreen, d0)];
|
||||
b = range_limit[DITHER_565_B(y + cblue, d0)];
|
||||
d0 = DITHER_ROTATE(d0);
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
|
||||
y = GETJSAMPLE(*inptr00++);
|
||||
y = *inptr00++;
|
||||
r = range_limit[DITHER_565_R(y + cred, d0)];
|
||||
g = range_limit[DITHER_565_G(y + cgreen, d0)];
|
||||
b = range_limit[DITHER_565_B(y + cblue, d0)];
|
||||
@@ -311,14 +311,14 @@ h2v2_merged_upsample_565D_internal(j_decompress_ptr cinfo,
|
||||
WRITE_TWO_PIXELS(outptr0, rgb);
|
||||
outptr0 += 4;
|
||||
|
||||
y = GETJSAMPLE(*inptr01++);
|
||||
y = *inptr01++;
|
||||
r = range_limit[DITHER_565_R(y + cred, d1)];
|
||||
g = range_limit[DITHER_565_G(y + cgreen, d1)];
|
||||
b = range_limit[DITHER_565_B(y + cblue, d1)];
|
||||
d1 = DITHER_ROTATE(d1);
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
|
||||
y = GETJSAMPLE(*inptr01++);
|
||||
y = *inptr01++;
|
||||
r = range_limit[DITHER_565_R(y + cred, d1)];
|
||||
g = range_limit[DITHER_565_G(y + cgreen, d1)];
|
||||
b = range_limit[DITHER_565_B(y + cblue, d1)];
|
||||
@@ -331,20 +331,20 @@ h2v2_merged_upsample_565D_internal(j_decompress_ptr cinfo,
|
||||
|
||||
/* If image width is odd, do the last output column separately */
|
||||
if (cinfo->output_width & 1) {
|
||||
cb = GETJSAMPLE(*inptr1);
|
||||
cr = GETJSAMPLE(*inptr2);
|
||||
cb = *inptr1;
|
||||
cr = *inptr2;
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
|
||||
y = GETJSAMPLE(*inptr00);
|
||||
y = *inptr00;
|
||||
r = range_limit[DITHER_565_R(y + cred, d0)];
|
||||
g = range_limit[DITHER_565_G(y + cgreen, d0)];
|
||||
b = range_limit[DITHER_565_B(y + cblue, d0)];
|
||||
rgb = PACK_SHORT_565(r, g, b);
|
||||
*(INT16 *)outptr0 = (INT16)rgb;
|
||||
|
||||
y = GETJSAMPLE(*inptr01);
|
||||
y = *inptr01;
|
||||
r = range_limit[DITHER_565_R(y + cred, d1)];
|
||||
g = range_limit[DITHER_565_G(y + cgreen, d1)];
|
||||
b = range_limit[DITHER_565_B(y + cblue, d1)];
|
||||
|
||||
+17
-17
@@ -46,13 +46,13 @@ h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
/* Loop for each pair of output pixels */
|
||||
for (col = cinfo->output_width >> 1; col > 0; col--) {
|
||||
/* Do the chroma part of the calculation */
|
||||
cb = GETJSAMPLE(*inptr1++);
|
||||
cr = GETJSAMPLE(*inptr2++);
|
||||
cb = *inptr1++;
|
||||
cr = *inptr2++;
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
/* Fetch 2 Y values and emit 2 pixels */
|
||||
y = GETJSAMPLE(*inptr0++);
|
||||
y = *inptr0++;
|
||||
outptr[RGB_RED] = range_limit[y + cred];
|
||||
outptr[RGB_GREEN] = range_limit[y + cgreen];
|
||||
outptr[RGB_BLUE] = range_limit[y + cblue];
|
||||
@@ -60,7 +60,7 @@ h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
outptr[RGB_ALPHA] = 0xFF;
|
||||
#endif
|
||||
outptr += RGB_PIXELSIZE;
|
||||
y = GETJSAMPLE(*inptr0++);
|
||||
y = *inptr0++;
|
||||
outptr[RGB_RED] = range_limit[y + cred];
|
||||
outptr[RGB_GREEN] = range_limit[y + cgreen];
|
||||
outptr[RGB_BLUE] = range_limit[y + cblue];
|
||||
@@ -71,12 +71,12 @@ h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
}
|
||||
/* If image width is odd, do the last output column separately */
|
||||
if (cinfo->output_width & 1) {
|
||||
cb = GETJSAMPLE(*inptr1);
|
||||
cr = GETJSAMPLE(*inptr2);
|
||||
cb = *inptr1;
|
||||
cr = *inptr2;
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
y = GETJSAMPLE(*inptr0);
|
||||
y = *inptr0;
|
||||
outptr[RGB_RED] = range_limit[y + cred];
|
||||
outptr[RGB_GREEN] = range_limit[y + cgreen];
|
||||
outptr[RGB_BLUE] = range_limit[y + cblue];
|
||||
@@ -120,13 +120,13 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
/* Loop for each group of output pixels */
|
||||
for (col = cinfo->output_width >> 1; col > 0; col--) {
|
||||
/* Do the chroma part of the calculation */
|
||||
cb = GETJSAMPLE(*inptr1++);
|
||||
cr = GETJSAMPLE(*inptr2++);
|
||||
cb = *inptr1++;
|
||||
cr = *inptr2++;
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
/* Fetch 4 Y values and emit 4 pixels */
|
||||
y = GETJSAMPLE(*inptr00++);
|
||||
y = *inptr00++;
|
||||
outptr0[RGB_RED] = range_limit[y + cred];
|
||||
outptr0[RGB_GREEN] = range_limit[y + cgreen];
|
||||
outptr0[RGB_BLUE] = range_limit[y + cblue];
|
||||
@@ -134,7 +134,7 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
outptr0[RGB_ALPHA] = 0xFF;
|
||||
#endif
|
||||
outptr0 += RGB_PIXELSIZE;
|
||||
y = GETJSAMPLE(*inptr00++);
|
||||
y = *inptr00++;
|
||||
outptr0[RGB_RED] = range_limit[y + cred];
|
||||
outptr0[RGB_GREEN] = range_limit[y + cgreen];
|
||||
outptr0[RGB_BLUE] = range_limit[y + cblue];
|
||||
@@ -142,7 +142,7 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
outptr0[RGB_ALPHA] = 0xFF;
|
||||
#endif
|
||||
outptr0 += RGB_PIXELSIZE;
|
||||
y = GETJSAMPLE(*inptr01++);
|
||||
y = *inptr01++;
|
||||
outptr1[RGB_RED] = range_limit[y + cred];
|
||||
outptr1[RGB_GREEN] = range_limit[y + cgreen];
|
||||
outptr1[RGB_BLUE] = range_limit[y + cblue];
|
||||
@@ -150,7 +150,7 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
outptr1[RGB_ALPHA] = 0xFF;
|
||||
#endif
|
||||
outptr1 += RGB_PIXELSIZE;
|
||||
y = GETJSAMPLE(*inptr01++);
|
||||
y = *inptr01++;
|
||||
outptr1[RGB_RED] = range_limit[y + cred];
|
||||
outptr1[RGB_GREEN] = range_limit[y + cgreen];
|
||||
outptr1[RGB_BLUE] = range_limit[y + cblue];
|
||||
@@ -161,19 +161,19 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
|
||||
}
|
||||
/* If image width is odd, do the last output column separately */
|
||||
if (cinfo->output_width & 1) {
|
||||
cb = GETJSAMPLE(*inptr1);
|
||||
cr = GETJSAMPLE(*inptr2);
|
||||
cb = *inptr1;
|
||||
cr = *inptr2;
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
y = GETJSAMPLE(*inptr00);
|
||||
y = *inptr00;
|
||||
outptr0[RGB_RED] = range_limit[y + cred];
|
||||
outptr0[RGB_GREEN] = range_limit[y + cgreen];
|
||||
outptr0[RGB_BLUE] = range_limit[y + cblue];
|
||||
#ifdef RGB_ALPHA
|
||||
outptr0[RGB_ALPHA] = 0xFF;
|
||||
#endif
|
||||
y = GETJSAMPLE(*inptr01);
|
||||
y = *inptr01;
|
||||
outptr1[RGB_RED] = range_limit[y + cred];
|
||||
outptr1[RGB_GREEN] = range_limit[y + cgreen];
|
||||
outptr1[RGB_BLUE] = range_limit[y + cblue];
|
||||
|
||||
Vendored
+20
-28
@@ -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) 2015-2016, 2018, D. R. Commander.
|
||||
* Copyright (C) 2015-2016, 2018-2021, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
@@ -41,25 +41,6 @@ typedef struct {
|
||||
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
|
||||
} savable_state;
|
||||
|
||||
/* This macro is to work around compilers with missing or broken
|
||||
* structure assignment. You'll need to fix this code if you have
|
||||
* such a compiler and you change MAX_COMPS_IN_SCAN.
|
||||
*/
|
||||
|
||||
#ifndef NO_STRUCT_ASSIGN
|
||||
#define ASSIGN_STATE(dest, src) ((dest) = (src))
|
||||
#else
|
||||
#if MAX_COMPS_IN_SCAN == 4
|
||||
#define ASSIGN_STATE(dest, src) \
|
||||
((dest).EOBRUN = (src).EOBRUN, \
|
||||
(dest).last_dc_val[0] = (src).last_dc_val[0], \
|
||||
(dest).last_dc_val[1] = (src).last_dc_val[1], \
|
||||
(dest).last_dc_val[2] = (src).last_dc_val[2], \
|
||||
(dest).last_dc_val[3] = (src).last_dc_val[3])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_entropy_decoder pub; /* public fields */
|
||||
|
||||
@@ -102,7 +83,7 @@ start_pass_phuff_decoder(j_decompress_ptr cinfo)
|
||||
boolean is_DC_band, bad;
|
||||
int ci, coefi, tbl;
|
||||
d_derived_tbl **pdtbl;
|
||||
int *coef_bit_ptr;
|
||||
int *coef_bit_ptr, *prev_coef_bit_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
is_DC_band = (cinfo->Ss == 0);
|
||||
@@ -143,8 +124,15 @@ start_pass_phuff_decoder(j_decompress_ptr cinfo)
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
int cindex = cinfo->cur_comp_info[ci]->component_index;
|
||||
coef_bit_ptr = &cinfo->coef_bits[cindex][0];
|
||||
prev_coef_bit_ptr = &cinfo->coef_bits[cindex + cinfo->num_components][0];
|
||||
if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
|
||||
WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
|
||||
for (coefi = MIN(cinfo->Ss, 1); coefi <= MAX(cinfo->Se, 9); coefi++) {
|
||||
if (cinfo->input_scan_number > 1)
|
||||
prev_coef_bit_ptr[coefi] = coef_bit_ptr[coefi];
|
||||
else
|
||||
prev_coef_bit_ptr[coefi] = 0;
|
||||
}
|
||||
for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
|
||||
int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi];
|
||||
if (cinfo->Ah != expected)
|
||||
@@ -323,7 +311,7 @@ decode_mcu_DC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
|
||||
/* Load up working state */
|
||||
BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
|
||||
ASSIGN_STATE(state, entropy->saved);
|
||||
state = entropy->saved;
|
||||
|
||||
/* Outer loop handles each block in the MCU */
|
||||
|
||||
@@ -356,11 +344,12 @@ decode_mcu_DC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
|
||||
/* Completed MCU, so update state */
|
||||
BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
|
||||
ASSIGN_STATE(entropy->saved, state);
|
||||
entropy->saved = state;
|
||||
}
|
||||
|
||||
/* Account for restart interval (no-op if not using restarts) */
|
||||
entropy->restarts_to_go--;
|
||||
if (cinfo->restart_interval)
|
||||
entropy->restarts_to_go--;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -444,7 +433,8 @@ decode_mcu_AC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
}
|
||||
|
||||
/* Account for restart interval (no-op if not using restarts) */
|
||||
entropy->restarts_to_go--;
|
||||
if (cinfo->restart_interval)
|
||||
entropy->restarts_to_go--;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -495,7 +485,8 @@ decode_mcu_DC_refine(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
|
||||
|
||||
/* Account for restart interval (no-op if not using restarts) */
|
||||
entropy->restarts_to_go--;
|
||||
if (cinfo->restart_interval)
|
||||
entropy->restarts_to_go--;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -638,7 +629,8 @@ decode_mcu_AC_refine(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
}
|
||||
|
||||
/* Account for restart interval (no-op if not using restarts) */
|
||||
entropy->restarts_to_go--;
|
||||
if (cinfo->restart_interval)
|
||||
entropy->restarts_to_go--;
|
||||
|
||||
return TRUE;
|
||||
|
||||
@@ -676,7 +668,7 @@ jinit_phuff_decoder(j_decompress_ptr cinfo)
|
||||
/* Create progression status table */
|
||||
cinfo->coef_bits = (int (*)[DCTSIZE2])
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
cinfo->num_components * DCTSIZE2 *
|
||||
cinfo->num_components * 2 * DCTSIZE2 *
|
||||
sizeof(int));
|
||||
coef_bit_ptr = &cinfo->coef_bits[0][0];
|
||||
for (ci = 0; ci < cinfo->num_components; ci++)
|
||||
|
||||
+22
-16
@@ -8,7 +8,7 @@
|
||||
* Copyright (C) 2010, 2015-2016, D. R. Commander.
|
||||
* Copyright (C) 2014, MIPS Technologies, Inc., California.
|
||||
* Copyright (C) 2015, Google, Inc.
|
||||
* Copyright (C) 2019, Arm Limited.
|
||||
* Copyright (C) 2019-2020, Arm Limited.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
@@ -177,7 +177,7 @@ int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
||||
outptr = output_data[outrow];
|
||||
outend = outptr + cinfo->output_width;
|
||||
while (outptr < outend) {
|
||||
invalue = *inptr++; /* don't need GETJSAMPLE() here */
|
||||
invalue = *inptr++;
|
||||
for (h = h_expand; h > 0; h--) {
|
||||
*outptr++ = invalue;
|
||||
}
|
||||
@@ -213,7 +213,7 @@ h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
||||
outptr = output_data[inrow];
|
||||
outend = outptr + cinfo->output_width;
|
||||
while (outptr < outend) {
|
||||
invalue = *inptr++; /* don't need GETJSAMPLE() here */
|
||||
invalue = *inptr++;
|
||||
*outptr++ = invalue;
|
||||
*outptr++ = invalue;
|
||||
}
|
||||
@@ -242,7 +242,7 @@ h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
||||
outptr = output_data[outrow];
|
||||
outend = outptr + cinfo->output_width;
|
||||
while (outptr < outend) {
|
||||
invalue = *inptr++; /* don't need GETJSAMPLE() here */
|
||||
invalue = *inptr++;
|
||||
*outptr++ = invalue;
|
||||
*outptr++ = invalue;
|
||||
}
|
||||
@@ -283,20 +283,20 @@ h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
||||
inptr = input_data[inrow];
|
||||
outptr = output_data[inrow];
|
||||
/* Special case for first column */
|
||||
invalue = GETJSAMPLE(*inptr++);
|
||||
invalue = *inptr++;
|
||||
*outptr++ = (JSAMPLE)invalue;
|
||||
*outptr++ = (JSAMPLE)((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
|
||||
*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 = GETJSAMPLE(*inptr++) * 3;
|
||||
*outptr++ = (JSAMPLE)((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
|
||||
*outptr++ = (JSAMPLE)((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
|
||||
invalue = (*inptr++) * 3;
|
||||
*outptr++ = (JSAMPLE)((invalue + inptr[-2] + 1) >> 2);
|
||||
*outptr++ = (JSAMPLE)((invalue + inptr[0] + 2) >> 2);
|
||||
}
|
||||
|
||||
/* Special case for last column */
|
||||
invalue = GETJSAMPLE(*inptr);
|
||||
*outptr++ = (JSAMPLE)((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
|
||||
invalue = *inptr;
|
||||
*outptr++ = (JSAMPLE)((invalue * 3 + inptr[-1] + 1) >> 2);
|
||||
*outptr++ = (JSAMPLE)invalue;
|
||||
}
|
||||
}
|
||||
@@ -338,7 +338,7 @@ h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
||||
outptr = output_data[outrow++];
|
||||
|
||||
for (colctr = 0; colctr < compptr->downsampled_width; colctr++) {
|
||||
thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
|
||||
thiscolsum = (*inptr0++) * 3 + (*inptr1++);
|
||||
*outptr++ = (JSAMPLE)((thiscolsum + bias) >> 2);
|
||||
}
|
||||
}
|
||||
@@ -381,8 +381,8 @@ h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
||||
outptr = output_data[outrow++];
|
||||
|
||||
/* Special case for first column */
|
||||
thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
|
||||
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
|
||||
thiscolsum = (*inptr0++) * 3 + (*inptr1++);
|
||||
nextcolsum = (*inptr0++) * 3 + (*inptr1++);
|
||||
*outptr++ = (JSAMPLE)((thiscolsum * 4 + 8) >> 4);
|
||||
*outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4);
|
||||
lastcolsum = thiscolsum; thiscolsum = nextcolsum;
|
||||
@@ -390,7 +390,7 @@ h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
||||
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 = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
|
||||
nextcolsum = (*inptr0++) * 3 + (*inptr1++);
|
||||
*outptr++ = (JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4);
|
||||
*outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4);
|
||||
lastcolsum = thiscolsum; thiscolsum = nextcolsum;
|
||||
@@ -477,7 +477,13 @@ jinit_upsampler(j_decompress_ptr cinfo)
|
||||
} 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 */
|
||||
upsample->methods[ci] = h1v2_fancy_upsample;
|
||||
#if defined(__arm__) || defined(__aarch64__) || \
|
||||
defined(_M_ARM) || defined(_M_ARM64)
|
||||
if (jsimd_can_h1v2_fancy_upsample())
|
||||
upsample->methods[ci] = jsimd_h1v2_fancy_upsample;
|
||||
else
|
||||
#endif
|
||||
upsample->methods[ci] = h1v2_fancy_upsample;
|
||||
upsample->pub.need_context_rows = TRUE;
|
||||
} else if (h_in_group * 2 == h_out_group &&
|
||||
v_in_group * 2 == v_out_group) {
|
||||
|
||||
Vendored
+13
@@ -207,6 +207,10 @@ JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
|
||||
#endif
|
||||
#endif
|
||||
JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker")
|
||||
#if JPEG_LIB_VERSION < 70
|
||||
JMESSAGE(JERR_BAD_DROP_SAMPLING,
|
||||
"Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c")
|
||||
#endif
|
||||
|
||||
#ifdef JMAKE_ENUM_LIST
|
||||
|
||||
@@ -252,6 +256,15 @@ JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker")
|
||||
(cinfo)->err->msg_parm.i[2] = (p3), \
|
||||
(cinfo)->err->msg_parm.i[3] = (p4), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
|
||||
#define ERREXIT6(cinfo, code, p1, p2, p3, p4, p5, p6) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(cinfo)->err->msg_parm.i[2] = (p3), \
|
||||
(cinfo)->err->msg_parm.i[3] = (p4), \
|
||||
(cinfo)->err->msg_parm.i[4] = (p5), \
|
||||
(cinfo)->err->msg_parm.i[5] = (p6), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
|
||||
#define ERREXITS(cinfo, code, str) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
|
||||
|
||||
+4
-4
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Modification developed 2002-2009 by Guido Vollbeding.
|
||||
* Modification developed 2002-2018 by Guido Vollbeding.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2015, 2020, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -417,7 +417,7 @@ jpeg_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
||||
|
||||
/*
|
||||
* Perform dequantization and inverse DCT on one block of coefficients,
|
||||
* producing a 7x7 output block.
|
||||
* producing a reduced-size 7x7 output block.
|
||||
*
|
||||
* Optimized algorithm with 12 multiplications in the 1-D kernel.
|
||||
* cK represents sqrt(2) * cos(K*pi/14).
|
||||
@@ -1258,7 +1258,7 @@ jpeg_idct_10x10(j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
||||
|
||||
/*
|
||||
* Perform dequantization and inverse DCT on one block of coefficients,
|
||||
* producing a 11x11 output block.
|
||||
* producing an 11x11 output block.
|
||||
*
|
||||
* Optimized algorithm with 24 multiplications in the 1-D kernel.
|
||||
* cK represents sqrt(2) * cos(K*pi/22).
|
||||
@@ -2398,7 +2398,7 @@ jpeg_idct_16x16(j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
||||
tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
|
||||
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
|
||||
/* Add fudge factor here for final descale. */
|
||||
tmp0 += 1 << (CONST_BITS - PASS1_BITS - 1);
|
||||
tmp0 += ONE << (CONST_BITS - PASS1_BITS - 1);
|
||||
|
||||
z1 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
|
||||
tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */
|
||||
|
||||
-35
@@ -43,25 +43,11 @@
|
||||
|
||||
#if BITS_IN_JSAMPLE == 8
|
||||
/* JSAMPLE should be the smallest type that will hold the values 0..255.
|
||||
* You can use a signed char by having GETJSAMPLE mask it with 0xFF.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_UNSIGNED_CHAR
|
||||
|
||||
typedef unsigned char JSAMPLE;
|
||||
#define GETJSAMPLE(value) ((int)(value))
|
||||
|
||||
#else /* not HAVE_UNSIGNED_CHAR */
|
||||
|
||||
typedef char JSAMPLE;
|
||||
#ifdef __CHAR_UNSIGNED__
|
||||
#define GETJSAMPLE(value) ((int)(value))
|
||||
#else
|
||||
#define GETJSAMPLE(value) ((int)(value) & 0xFF)
|
||||
#endif /* __CHAR_UNSIGNED__ */
|
||||
|
||||
#endif /* HAVE_UNSIGNED_CHAR */
|
||||
|
||||
#define MAXJSAMPLE 255
|
||||
#define CENTERJSAMPLE 128
|
||||
|
||||
@@ -97,22 +83,9 @@ typedef short JCOEF;
|
||||
* managers, this is also the data type passed to fread/fwrite.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_UNSIGNED_CHAR
|
||||
|
||||
typedef unsigned char JOCTET;
|
||||
#define GETJOCTET(value) (value)
|
||||
|
||||
#else /* not HAVE_UNSIGNED_CHAR */
|
||||
|
||||
typedef char JOCTET;
|
||||
#ifdef __CHAR_UNSIGNED__
|
||||
#define GETJOCTET(value) (value)
|
||||
#else
|
||||
#define GETJOCTET(value) ((value) & 0xFF)
|
||||
#endif /* __CHAR_UNSIGNED__ */
|
||||
|
||||
#endif /* HAVE_UNSIGNED_CHAR */
|
||||
|
||||
|
||||
/* These typedefs are used for various table entries and so forth.
|
||||
* They must be at least as wide as specified; but making them too big
|
||||
@@ -123,15 +96,7 @@ typedef char JOCTET;
|
||||
|
||||
/* UINT8 must hold at least the values 0..255. */
|
||||
|
||||
#ifdef HAVE_UNSIGNED_CHAR
|
||||
typedef unsigned char UINT8;
|
||||
#else /* not HAVE_UNSIGNED_CHAR */
|
||||
#ifdef __CHAR_UNSIGNED__
|
||||
typedef char UINT8;
|
||||
#else /* not __CHAR_UNSIGNED__ */
|
||||
typedef short UINT8;
|
||||
#endif /* __CHAR_UNSIGNED__ */
|
||||
#endif /* HAVE_UNSIGNED_CHAR */
|
||||
|
||||
/* UINT16 must hold at least the values 0..65535. */
|
||||
|
||||
|
||||
Vendored
+4
-1
@@ -5,7 +5,7 @@
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 1997-2009 by Guido Vollbeding.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2015-2016, D. R. Commander.
|
||||
* Copyright (C) 2015-2016, 2019, D. R. Commander.
|
||||
* Copyright (C) 2015, Google, Inc.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
@@ -158,6 +158,9 @@ struct jpeg_decomp_master {
|
||||
JDIMENSION first_MCU_col[MAX_COMPONENTS];
|
||||
JDIMENSION last_MCU_col[MAX_COMPONENTS];
|
||||
boolean jinit_upsampler_no_alloc;
|
||||
|
||||
/* Last iMCU row that was successfully decoded */
|
||||
JDIMENSION last_good_iMCU_row;
|
||||
};
|
||||
|
||||
/* Input control module */
|
||||
|
||||
Vendored
+12
-15
@@ -479,7 +479,7 @@ color_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
|
||||
for (col = width; col > 0; col--) {
|
||||
pixcode = 0;
|
||||
for (ci = 0; ci < nc; ci++) {
|
||||
pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]);
|
||||
pixcode += colorindex[ci][*ptrin++];
|
||||
}
|
||||
*ptrout++ = (JSAMPLE)pixcode;
|
||||
}
|
||||
@@ -506,9 +506,9 @@ color_quantize3(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
|
||||
ptrin = input_buf[row];
|
||||
ptrout = output_buf[row];
|
||||
for (col = width; col > 0; col--) {
|
||||
pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]);
|
||||
pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]);
|
||||
pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]);
|
||||
pixcode = colorindex0[*ptrin++];
|
||||
pixcode += colorindex1[*ptrin++];
|
||||
pixcode += colorindex2[*ptrin++];
|
||||
*ptrout++ = (JSAMPLE)pixcode;
|
||||
}
|
||||
}
|
||||
@@ -552,7 +552,7 @@ quantize_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
|
||||
* required amount of padding.
|
||||
*/
|
||||
*output_ptr +=
|
||||
colorindex_ci[GETJSAMPLE(*input_ptr) + dither[col_index]];
|
||||
colorindex_ci[*input_ptr + dither[col_index]];
|
||||
input_ptr += nc;
|
||||
output_ptr++;
|
||||
col_index = (col_index + 1) & ODITHER_MASK;
|
||||
@@ -595,12 +595,9 @@ quantize3_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
|
||||
col_index = 0;
|
||||
|
||||
for (col = width; col > 0; col--) {
|
||||
pixcode =
|
||||
GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + dither0[col_index]]);
|
||||
pixcode +=
|
||||
GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + dither1[col_index]]);
|
||||
pixcode +=
|
||||
GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + dither2[col_index]]);
|
||||
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;
|
||||
col_index = (col_index + 1) & ODITHER_MASK;
|
||||
}
|
||||
@@ -677,15 +674,15 @@ quantize_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
|
||||
* The maximum error is +- MAXJSAMPLE; this sets the required size
|
||||
* of the range_limit array.
|
||||
*/
|
||||
cur += GETJSAMPLE(*input_ptr);
|
||||
cur = GETJSAMPLE(range_limit[cur]);
|
||||
cur += *input_ptr;
|
||||
cur = range_limit[cur];
|
||||
/* Select output value, accumulate into output code for this pixel */
|
||||
pixcode = GETJSAMPLE(colorindex_ci[cur]);
|
||||
pixcode = colorindex_ci[cur];
|
||||
*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. */
|
||||
cur -= GETJSAMPLE(colormap_ci[pixcode]);
|
||||
cur -= colormap_ci[pixcode];
|
||||
/* Compute error fractions to be propagated to adjacent pixels.
|
||||
* Add these into the running sums, and simultaneously shift the
|
||||
* next-line error sums left by 1 column.
|
||||
|
||||
Vendored
+23
-23
@@ -215,9 +215,9 @@ prescan_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
|
||||
ptr = input_buf[row];
|
||||
for (col = width; col > 0; col--) {
|
||||
/* get pixel value and index into the histogram */
|
||||
histp = &histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT]
|
||||
[GETJSAMPLE(ptr[1]) >> C1_SHIFT]
|
||||
[GETJSAMPLE(ptr[2]) >> C2_SHIFT];
|
||||
histp = &histogram[ptr[0] >> C0_SHIFT]
|
||||
[ptr[1] >> C1_SHIFT]
|
||||
[ptr[2] >> C2_SHIFT];
|
||||
/* increment, check for overflow and undo increment if so. */
|
||||
if (++(*histp) <= 0)
|
||||
(*histp)--;
|
||||
@@ -665,7 +665,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 = GETJSAMPLE(cinfo->colormap[0][i]);
|
||||
x = cinfo->colormap[0][i];
|
||||
if (x < minc0) {
|
||||
tdist = (x - minc0) * C0_SCALE;
|
||||
min_dist = tdist * tdist;
|
||||
@@ -688,7 +688,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
|
||||
}
|
||||
}
|
||||
|
||||
x = GETJSAMPLE(cinfo->colormap[1][i]);
|
||||
x = cinfo->colormap[1][i];
|
||||
if (x < minc1) {
|
||||
tdist = (x - minc1) * C1_SCALE;
|
||||
min_dist += tdist * tdist;
|
||||
@@ -710,7 +710,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
|
||||
}
|
||||
}
|
||||
|
||||
x = GETJSAMPLE(cinfo->colormap[2][i]);
|
||||
x = cinfo->colormap[2][i];
|
||||
if (x < minc2) {
|
||||
tdist = (x - minc2) * C2_SCALE;
|
||||
min_dist += tdist * tdist;
|
||||
@@ -788,13 +788,13 @@ find_best_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
|
||||
#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE)
|
||||
|
||||
for (i = 0; i < numcolors; i++) {
|
||||
icolor = GETJSAMPLE(colorlist[i]);
|
||||
icolor = colorlist[i];
|
||||
/* Compute (square of) distance from minc0/c1/c2 to this color */
|
||||
inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE;
|
||||
inc0 = (minc0 - cinfo->colormap[0][icolor]) * C0_SCALE;
|
||||
dist0 = inc0 * inc0;
|
||||
inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE;
|
||||
inc1 = (minc1 - cinfo->colormap[1][icolor]) * C1_SCALE;
|
||||
dist0 += inc1 * inc1;
|
||||
inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE;
|
||||
inc2 = (minc2 - cinfo->colormap[2][icolor]) * C2_SCALE;
|
||||
dist0 += inc2 * inc2;
|
||||
/* Form the initial difference increments */
|
||||
inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;
|
||||
@@ -879,7 +879,7 @@ fill_inverse_cmap(j_decompress_ptr cinfo, int c0, int c1, int c2)
|
||||
for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) {
|
||||
cachep = &histogram[c0 + ic0][c1 + ic1][c2];
|
||||
for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) {
|
||||
*cachep++ = (histcell)(GETJSAMPLE(*cptr++) + 1);
|
||||
*cachep++ = (histcell)((*cptr++) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -909,9 +909,9 @@ pass2_no_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
|
||||
outptr = output_buf[row];
|
||||
for (col = width; col > 0; col--) {
|
||||
/* get pixel value and index into the cache */
|
||||
c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT;
|
||||
c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT;
|
||||
c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT;
|
||||
c0 = (*inptr++) >> C0_SHIFT;
|
||||
c1 = (*inptr++) >> C1_SHIFT;
|
||||
c2 = (*inptr++) >> C2_SHIFT;
|
||||
cachep = &histogram[c0][c1][c2];
|
||||
/* If we have not seen this color before, find nearest colormap entry */
|
||||
/* and update the cache */
|
||||
@@ -996,12 +996,12 @@ pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
|
||||
* The maximum error is +- MAXJSAMPLE (or less with error limiting);
|
||||
* this sets the required size of the range_limit array.
|
||||
*/
|
||||
cur0 += GETJSAMPLE(inptr[0]);
|
||||
cur1 += GETJSAMPLE(inptr[1]);
|
||||
cur2 += GETJSAMPLE(inptr[2]);
|
||||
cur0 = GETJSAMPLE(range_limit[cur0]);
|
||||
cur1 = GETJSAMPLE(range_limit[cur1]);
|
||||
cur2 = GETJSAMPLE(range_limit[cur2]);
|
||||
cur0 += inptr[0];
|
||||
cur1 += inptr[1];
|
||||
cur2 += inptr[2];
|
||||
cur0 = range_limit[cur0];
|
||||
cur1 = range_limit[cur1];
|
||||
cur2 = range_limit[cur2];
|
||||
/* Index into the cache with adjusted pixel value */
|
||||
cachep =
|
||||
&histogram[cur0 >> C0_SHIFT][cur1 >> C1_SHIFT][cur2 >> C2_SHIFT];
|
||||
@@ -1015,9 +1015,9 @@ pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
|
||||
register int pixcode = *cachep - 1;
|
||||
*outptr = (JSAMPLE)pixcode;
|
||||
/* Compute representation error for this pixel */
|
||||
cur0 -= GETJSAMPLE(colormap0[pixcode]);
|
||||
cur1 -= GETJSAMPLE(colormap1[pixcode]);
|
||||
cur2 -= GETJSAMPLE(colormap2[pixcode]);
|
||||
cur0 -= colormap0[pixcode];
|
||||
cur1 -= colormap1[pixcode];
|
||||
cur2 -= colormap2[pixcode];
|
||||
}
|
||||
/* Compute error fractions to be propagated to adjacent pixels.
|
||||
* Add these into the running sums, and simultaneously shift the
|
||||
|
||||
Vendored
+6
@@ -4,6 +4,7 @@
|
||||
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
||||
* Copyright (C) 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.
|
||||
@@ -75,6 +76,7 @@ EXTERN(void) jsimd_int_upsample(j_decompress_ptr cinfo,
|
||||
|
||||
EXTERN(int) jsimd_can_h2v2_fancy_upsample(void);
|
||||
EXTERN(int) jsimd_can_h2v1_fancy_upsample(void);
|
||||
EXTERN(int) jsimd_can_h1v2_fancy_upsample(void);
|
||||
|
||||
EXTERN(void) jsimd_h2v2_fancy_upsample(j_decompress_ptr cinfo,
|
||||
jpeg_component_info *compptr,
|
||||
@@ -84,6 +86,10 @@ EXTERN(void) jsimd_h2v1_fancy_upsample(j_decompress_ptr cinfo,
|
||||
jpeg_component_info *compptr,
|
||||
JSAMPARRAY input_data,
|
||||
JSAMPARRAY *output_data_ptr);
|
||||
EXTERN(void) jsimd_h1v2_fancy_upsample(j_decompress_ptr cinfo,
|
||||
jpeg_component_info *compptr,
|
||||
JSAMPARRAY input_data,
|
||||
JSAMPARRAY *output_data_ptr);
|
||||
|
||||
EXTERN(int) jsimd_can_h2v2_merged_upsample(void);
|
||||
EXTERN(int) jsimd_can_h2v1_merged_upsample(void);
|
||||
|
||||
+13
@@ -4,6 +4,7 @@
|
||||
* Copyright 2009 Pierre Ossman <ossman@cendio.se> 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.
|
||||
@@ -169,6 +170,12 @@ 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)
|
||||
@@ -181,6 +188,12 @@ jsimd_h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
||||
{
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
+6
-6
@@ -2,9 +2,9 @@
|
||||
* jversion.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding.
|
||||
* Copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2010, 2012-2020, D. R. Commander.
|
||||
* Copyright (C) 2010, 2012-2021, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
@@ -37,9 +37,9 @@
|
||||
*/
|
||||
|
||||
#define JCOPYRIGHT \
|
||||
"Copyright (C) 2009-2020 D. R. Commander\n" \
|
||||
"Copyright (C) 2009-2021 D. R. Commander\n" \
|
||||
"Copyright (C) 2015, 2020 Google, Inc.\n" \
|
||||
"Copyright (C) 2019 Arm Limited\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" \
|
||||
@@ -48,7 +48,7 @@
|
||||
"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-2017 Thomas G. Lane, Guido Vollbeding"
|
||||
"Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding"
|
||||
|
||||
#define JCOPYRIGHT_SHORT \
|
||||
"Copyright (C) 1991-2020 The libjpeg-turbo Project and many others"
|
||||
"Copyright (C) 1991-2021 The libjpeg-turbo Project and many others"
|
||||
|
||||
@@ -177,7 +177,13 @@ if(CV_GCC OR CV_CLANG)
|
||||
endif()
|
||||
|
||||
# We need pthread's
|
||||
if(UNIX AND NOT ANDROID AND NOT (APPLE AND CV_CLANG)) # TODO
|
||||
if((UNIX
|
||||
AND NOT ANDROID
|
||||
AND NOT (APPLE AND CV_CLANG)
|
||||
AND NOT EMSCRIPTEN
|
||||
)
|
||||
OR (EMSCRIPTEN AND WITH_PTHREADS_PF) # https://github.com/opencv/opencv/issues/20285
|
||||
)
|
||||
add_extra_compiler_option(-pthread)
|
||||
endif()
|
||||
|
||||
@@ -225,9 +231,11 @@ if(CV_GCC OR CV_CLANG)
|
||||
if(APPLE)
|
||||
set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} -Wl,-dead_strip")
|
||||
set(OPENCV_EXTRA_SHARED_LINKER_FLAGS "${OPENCV_EXTRA_SHARED_LINKER_FLAGS} -Wl,-dead_strip")
|
||||
set(OPENCV_EXTRA_MODULE_LINKER_FLAGS "${OPENCV_EXTRA_MODULE_LINKER_FLAGS} -Wl,-dead_strip")
|
||||
else()
|
||||
set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
set(OPENCV_EXTRA_SHARED_LINKER_FLAGS "${OPENCV_EXTRA_SHARED_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
set(OPENCV_EXTRA_MODULE_LINKER_FLAGS "${OPENCV_EXTRA_MODULE_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -279,6 +287,7 @@ if(MSVC)
|
||||
set(OPENCV_EXTRA_FLAGS_RELEASE "${OPENCV_EXTRA_FLAGS_RELEASE} /Zi")
|
||||
set(OPENCV_EXTRA_EXE_LINKER_FLAGS_RELEASE "${OPENCV_EXTRA_EXE_LINKER_FLAGS_RELEASE} /debug")
|
||||
set(OPENCV_EXTRA_SHARED_LINKER_FLAGS_RELEASE "${OPENCV_EXTRA_SHARED_LINKER_FLAGS_RELEASE} /debug")
|
||||
set(OPENCV_EXTRA_MODULE_LINKER_FLAGS_RELEASE "${OPENCV_EXTRA_MODULE_LINKER_FLAGS_RELEASE} /debug")
|
||||
endif()
|
||||
|
||||
# Remove unreferenced functions: function level linking
|
||||
@@ -346,6 +355,7 @@ if(NOT OPENCV_SKIP_LINK_AS_NEEDED)
|
||||
if(HAVE_LINK_AS_NEEDED)
|
||||
set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} ${_option}")
|
||||
set(OPENCV_EXTRA_SHARED_LINKER_FLAGS "${OPENCV_EXTRA_SHARED_LINKER_FLAGS} ${_option}")
|
||||
set(OPENCV_EXTRA_MODULE_LINKER_FLAGS "${OPENCV_EXTRA_MODULE_LINKER_FLAGS} ${_option}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -364,6 +374,9 @@ if(NOT OPENCV_SKIP_EXTRA_COMPILER_FLAGS)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${OPENCV_EXTRA_SHARED_LINKER_FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${OPENCV_EXTRA_SHARED_LINKER_FLAGS_RELEASE}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${OPENCV_EXTRA_SHARED_LINKER_FLAGS_DEBUG}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${OPENCV_EXTRA_MODULE_LINKER_FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${OPENCV_EXTRA_MODULE_LINKER_FLAGS_RELEASE}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} ${OPENCV_EXTRA_MODULE_LINKER_FLAGS_DEBUG}")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
|
||||
@@ -9,9 +9,14 @@ set(HALIDE_ROOT_DIR "${HALIDE_ROOT_DIR}" CACHE PATH "Halide root directory")
|
||||
if(NOT HAVE_HALIDE)
|
||||
find_package(Halide QUIET) # Try CMake-based config files
|
||||
if(Halide_FOUND)
|
||||
set(HALIDE_INCLUDE_DIRS "${Halide_INCLUDE_DIRS}" CACHE PATH "Halide include directories" FORCE)
|
||||
set(HALIDE_LIBRARIES "${Halide_LIBRARIES}" CACHE PATH "Halide libraries" FORCE)
|
||||
set(HAVE_HALIDE TRUE)
|
||||
if(TARGET Halide::Halide) # modern Halide scripts defines imported target
|
||||
set(HALIDE_INCLUDE_DIRS "")
|
||||
set(HALIDE_LIBRARIES "Halide::Halide")
|
||||
set(HAVE_HALIDE TRUE)
|
||||
else()
|
||||
# using HALIDE_INCLUDE_DIRS / Halide_LIBRARIES
|
||||
set(HAVE_HALIDE TRUE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -28,18 +33,15 @@ if(NOT HAVE_HALIDE AND HALIDE_ROOT_DIR)
|
||||
)
|
||||
if(HALIDE_LIBRARY AND HALIDE_INCLUDE_DIR)
|
||||
# TODO try_compile
|
||||
set(HALIDE_INCLUDE_DIRS "${HALIDE_INCLUDE_DIR}" CACHE PATH "Halide include directories" FORCE)
|
||||
set(HALIDE_LIBRARIES "${HALIDE_LIBRARY}" CACHE PATH "Halide libraries" FORCE)
|
||||
set(HALIDE_INCLUDE_DIRS "${HALIDE_INCLUDE_DIR}")
|
||||
set(HALIDE_LIBRARIES "${HALIDE_LIBRARY}")
|
||||
set(HAVE_HALIDE TRUE)
|
||||
endif()
|
||||
if(NOT HAVE_HALIDE)
|
||||
ocv_clear_vars(HALIDE_LIBRARIES HALIDE_INCLUDE_DIRS CACHE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(HAVE_HALIDE)
|
||||
include_directories(${HALIDE_INCLUDE_DIRS})
|
||||
if(HALIDE_INCLUDE_DIRS)
|
||||
include_directories(${HALIDE_INCLUDE_DIRS})
|
||||
endif()
|
||||
list(APPEND OPENCV_LINKER_LIBS ${HALIDE_LIBRARIES})
|
||||
else()
|
||||
ocv_clear_vars(HALIDE_INCLUDE_DIRS HALIDE_LIBRARIES)
|
||||
endif()
|
||||
|
||||
@@ -140,12 +140,21 @@ endif()
|
||||
# Add more features to the target
|
||||
|
||||
if(INF_ENGINE_TARGET)
|
||||
if(NOT INF_ENGINE_RELEASE)
|
||||
message(WARNING "InferenceEngine version has not been set, 2021.3 will be used by default. Set INF_ENGINE_RELEASE variable if you experience build errors.")
|
||||
if(DEFINED InferenceEngine_VERSION)
|
||||
message(STATUS "InferenceEngine: ${InferenceEngine_VERSION}")
|
||||
if(NOT INF_ENGINE_RELEASE AND NOT (InferenceEngine_VERSION VERSION_LESS "2021.4"))
|
||||
math(EXPR INF_ENGINE_RELEASE_INIT "${InferenceEngine_VERSION_MAJOR} * 1000000 + ${InferenceEngine_VERSION_MINOR} * 10000 + ${InferenceEngine_VERSION_PATCH} * 100")
|
||||
endif()
|
||||
endif()
|
||||
set(INF_ENGINE_RELEASE "2021030000" CACHE STRING "Force IE version, should be in form YYYYAABBCC (e.g. 2020.1.0.2 -> 2020010002)")
|
||||
if(NOT INF_ENGINE_RELEASE AND NOT INF_ENGINE_RELEASE_INIT)
|
||||
message(WARNING "InferenceEngine version has not been set, 2021.4 will be used by default. Set INF_ENGINE_RELEASE variable if you experience build errors.")
|
||||
set(INF_ENGINE_RELEASE_INIT "2021040000")
|
||||
elseif(DEFINED INF_ENGINE_RELEASE)
|
||||
set(INF_ENGINE_RELEASE_INIT "${INF_ENGINE_RELEASE}")
|
||||
endif()
|
||||
set(INF_ENGINE_RELEASE "${INF_ENGINE_RELEASE_INIT}" CACHE STRING "Force IE version, should be in form YYYYAABBCC (e.g. 2020.1.0.2 -> 2020010002)")
|
||||
set_target_properties(${INF_ENGINE_TARGET} PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "HAVE_INF_ENGINE=1;INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}"
|
||||
INTERFACE_COMPILE_DEFINITIONS "HAVE_INF_ENGINE=1;INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ set(OPENCV_DOWNLOAD_LOG "${OpenCV_BINARY_DIR}/CMakeDownloadLog.txt")
|
||||
set(OPENCV_DOWNLOAD_WITH_CURL "${OpenCV_BINARY_DIR}/download_with_curl.sh")
|
||||
set(OPENCV_DOWNLOAD_WITH_WGET "${OpenCV_BINARY_DIR}/download_with_wget.sh")
|
||||
set(OPENCV_DOWNLOAD_TRIES_LIST 1 CACHE STRING "List of download tries") # a list
|
||||
set(OPENCV_DOWNLOAD_PARAMS INACTIVITY_TIMEOUT 60 TIMEOUT 600 CACHE STRING "Download parameters to be passed to file(DOWNLAOD ...)")
|
||||
set(OPENCV_DOWNLOAD_PARAMS INACTIVITY_TIMEOUT 60 TIMEOUT 600 CACHE STRING "Download parameters to be passed to file(DOWNLOAD ...)")
|
||||
mark_as_advanced(OPENCV_DOWNLOAD_TRIES_LIST OPENCV_DOWNLOAD_PARAMS)
|
||||
|
||||
# Init download cache directory and log file and helper scripts
|
||||
|
||||
@@ -151,7 +151,7 @@ macro(ipp_detect_version)
|
||||
if("${name}" STREQUAL "core") # https://github.com/opencv/opencv/pull/19681
|
||||
if(OPENCV_FORCE_IPP_EXCLUDE_LIBS OR OPENCV_FORCE_IPP_EXCLUDE_LIBS_CORE
|
||||
OR (UNIX AND NOT ANDROID AND NOT APPLE
|
||||
AND (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|Intel"
|
||||
)
|
||||
AND NOT OPENCV_SKIP_IPP_EXCLUDE_LIBS_CORE
|
||||
)
|
||||
|
||||
@@ -29,7 +29,7 @@ if(WITH_IPP)
|
||||
if(OPENCV_FORCE_IPP_EXCLUDE_LIBS
|
||||
OR (HAVE_IPP_ICV
|
||||
AND UNIX AND NOT ANDROID AND NOT APPLE
|
||||
AND (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|Intel"
|
||||
)
|
||||
AND NOT OPENCV_SKIP_IPP_EXCLUDE_LIBS
|
||||
)
|
||||
|
||||
@@ -877,7 +877,9 @@ macro(_ocv_create_module)
|
||||
|
||||
ocv_compiler_optimization_process_sources(OPENCV_MODULE_${the_module}_SOURCES OPENCV_MODULE_${the_module}_DEPS_EXT ${the_module})
|
||||
set(__module_headers ${OPENCV_MODULE_${the_module}_HEADERS})
|
||||
list(SORT __module_headers) # fix headers order, useful for bindings
|
||||
if(__module_headers)
|
||||
list(SORT __module_headers) # fix headers order, useful for bindings
|
||||
endif()
|
||||
set(OPENCV_MODULE_${the_module}_HEADERS ${__module_headers} CACHE INTERNAL "List of header files for ${the_module}")
|
||||
set(OPENCV_MODULE_${the_module}_SOURCES ${OPENCV_MODULE_${the_module}_SOURCES} CACHE INTERNAL "List of source files for ${the_module}")
|
||||
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ MULTILINE_CPP_IS_BRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 4
|
||||
ALIASES += add_toggle{1}="@htmlonly[block] <div class='newInnerHTML'>\1</div><div> <script type="text/javascript"> addToggle(); </script>@endhtmlonly"
|
||||
ALIASES += add_toggle{1}="@htmlonly[block] <div class='newInnerHTML'>\1</div><div> <script type='text/javascript'> addToggle(); </script>@endhtmlonly"
|
||||
ALIASES += add_toggle_cpp="@htmlonly[block] <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'>@endhtmlonly"
|
||||
ALIASES += add_toggle_java="@htmlonly[block] <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'>@endhtmlonly"
|
||||
ALIASES += add_toggle_python="@htmlonly[block] <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'>@endhtmlonly"
|
||||
|
||||
+4
-4
@@ -835,12 +835,12 @@
|
||||
journal = {IEEE Transactions on Robotics and Automation},
|
||||
title = {Robot sensor calibration: solving AX=XB on the Euclidean group},
|
||||
year = {1994},
|
||||
month = oct,
|
||||
volume = {10},
|
||||
number = {5},
|
||||
pages = {717-721},
|
||||
doi = {10.1109/70.326576},
|
||||
ISSN = {1042-296X},
|
||||
month = {Oct}
|
||||
issn = {1042-296X}
|
||||
}
|
||||
@inproceedings{PM03,
|
||||
author = {P{\'e}rez, Patrick and Gangnet, Michel and Blake, Andrew},
|
||||
@@ -1028,12 +1028,12 @@
|
||||
journal = {IEEE Transactions on Robotics and Automation},
|
||||
title = {A new technique for fully autonomous and efficient 3D robotics hand/eye calibration},
|
||||
year = {1989},
|
||||
month = jun,
|
||||
volume = {5},
|
||||
number = {3},
|
||||
pages = {345-358},
|
||||
doi = {10.1109/70.34770},
|
||||
ISSN = {1042-296X},
|
||||
month = {June}
|
||||
issn = {1042-296X}
|
||||
}
|
||||
@inproceedings{UES01,
|
||||
author = {Uyttendaele, Matthew and Eden, Ashley and Skeliski, R},
|
||||
|
||||
@@ -40,12 +40,12 @@ using **cv.Sobel()**).
|
||||
Then comes the main part. After this, they created a score, basically an equation, which
|
||||
determines if a window can contain a corner or not.
|
||||
|
||||
\f[R = det(M) - k(trace(M))^2\f]
|
||||
\f[R = \det(M) - k(\operatorname{trace}(M))^2\f]
|
||||
|
||||
where
|
||||
- \f$det(M) = \lambda_1 \lambda_2\f$
|
||||
- \f$trace(M) = \lambda_1 + \lambda_2\f$
|
||||
- \f$\lambda_1\f$ and \f$\lambda_2\f$ are the eigenvalues of M
|
||||
- \f$\det(M) = \lambda_1 \lambda_2\f$
|
||||
- \f$\operatorname{trace}(M) = \lambda_1 + \lambda_2\f$
|
||||
- \f$\lambda_1\f$ and \f$\lambda_2\f$ are the eigenvalues of \f$M\f$
|
||||
|
||||
So the magnitudes of these eigenvalues decide whether a region is a corner, an edge, or flat.
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Harris Corner Detector. The scoring function in Harris Corner Detector was given
|
||||
|
||||
Instead of this, Shi-Tomasi proposed:
|
||||
|
||||
\f[R = min(\lambda_1, \lambda_2)\f]
|
||||
\f[R = \min(\lambda_1, \lambda_2)\f]
|
||||
|
||||
If it is a greater than a threshold value, it is considered as a corner. If we plot it in
|
||||
\f$\lambda_1 - \lambda_2\f$ space as we did in Harris Corner Detector, we get an image as below:
|
||||
@@ -28,7 +28,7 @@ If it is a greater than a threshold value, it is considered as a corner. If we p
|
||||

|
||||
|
||||
From the figure, you can see that only when \f$\lambda_1\f$ and \f$\lambda_2\f$ are above a minimum value,
|
||||
\f$\lambda_{min}\f$, it is considered as a corner(green region).
|
||||
\f$\lambda_{\min}\f$, it is considered as a corner(green region).
|
||||
|
||||
Code
|
||||
----
|
||||
|
||||
@@ -156,7 +156,7 @@ sift = cv.SIFT_create()
|
||||
kp, des = sift.detectAndCompute(gray,None)
|
||||
@endcode
|
||||
Here kp will be a list of keypoints and des is a numpy array of shape
|
||||
\f$Number\_of\_Keypoints \times 128\f$.
|
||||
\f$\text{(Number of Keypoints)} \times 128\f$.
|
||||
|
||||
So we got keypoints, descriptors etc. Now we want to see how to match keypoints in different images.
|
||||
That we will learn in coming chapters.
|
||||
|
||||
@@ -107,17 +107,10 @@ def add_signature_to_table(soup, table, signature, language, type):
|
||||
""" Add a signature to an html table"""
|
||||
row = soup.new_tag('tr')
|
||||
row.append(soup.new_tag('td', style='width: 20px;'))
|
||||
|
||||
if 'ret' in signature:
|
||||
row.append(append(soup.new_tag('td'), signature['ret']))
|
||||
row.append(append(soup.new_tag('td'), '='))
|
||||
else:
|
||||
row.append(soup.new_tag('td')) # return values
|
||||
row.append(soup.new_tag('td')) # '='
|
||||
|
||||
row.append(append(soup.new_tag('td'), signature['name'] + '('))
|
||||
row.append(append(soup.new_tag('td', **{'class': 'paramname'}), signature['arg']))
|
||||
row.append(append(soup.new_tag('td'), ')'))
|
||||
row.append(append(soup.new_tag('td'), ') -> '))
|
||||
row.append(append(soup.new_tag('td'), signature['ret']))
|
||||
table.append(row)
|
||||
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ The tutorial consists of two main programs:
|
||||
|
||||
The application starts up extracting the ORB features and descriptors from the input image and
|
||||
then uses the mesh along with the [Möller–Trumbore intersection
|
||||
algorithm](http://http://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm/)
|
||||
algorithm](http://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm/)
|
||||
to compute the 3D coordinates of the found features. Finally, the 3D points and the descriptors
|
||||
are stored in different lists in a file with YAML format which each row is a different point. The
|
||||
technical background on how to store the files can be found in the @ref tutorial_file_input_output_with_xml_yml
|
||||
|
||||
@@ -39,14 +39,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/3.4.14
|
||||
TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.15
|
||||
@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/3.4.14
|
||||
./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.15
|
||||
@endcode
|
||||
|
||||
Doxygen can now use the information from the tag file to link to the OpenCV
|
||||
|
||||
@@ -1510,8 +1510,8 @@ concatenated together.
|
||||
@param imageSize Size of the image used only to initialize the camera intrinsic matrix.
|
||||
@param cameraMatrix Input/output 3x3 floating-point camera intrinsic matrix
|
||||
\f$\cameramatrix{A}\f$ . If @ref CALIB_USE_INTRINSIC_GUESS
|
||||
and/or @ref CALIB_FIX_ASPECT_RATIO are specified, some or all of fx, fy, cx, cy must be
|
||||
initialized before calling the function.
|
||||
and/or @ref CALIB_FIX_ASPECT_RATIO, @ref CALIB_FIX_PRINCIPAL_POINT or @ref CALIB_FIX_FOCAL_LENGTH
|
||||
are specified, some or all of fx, fy, cx, cy must be initialized before calling the function.
|
||||
@param distCoeffs Input/output vector of distortion coefficients
|
||||
\f$\distcoeffs\f$.
|
||||
@param rvecs Output vector of rotation vectors (@ref Rodrigues ) estimated for each pattern view
|
||||
@@ -1537,7 +1537,7 @@ the number of pattern views. \f$R_i, T_i\f$ are concatenated 1x3 vectors.
|
||||
fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set to the image
|
||||
center ( imageSize is used), and focal distances are computed in a least-squares fashion.
|
||||
Note, that if intrinsic parameters are known, there is no need to use this function just to
|
||||
estimate extrinsic parameters. Use solvePnP instead.
|
||||
estimate extrinsic parameters. Use @ref solvePnP instead.
|
||||
- @ref CALIB_FIX_PRINCIPAL_POINT The principal point is not changed during the global
|
||||
optimization. It stays at the center or at a different location specified when
|
||||
@ref CALIB_USE_INTRINSIC_GUESS is set too.
|
||||
@@ -1547,24 +1547,23 @@ ratio fx/fy stays the same as in the input cameraMatrix . When
|
||||
ignored, only their ratio is computed and used further.
|
||||
- @ref CALIB_ZERO_TANGENT_DIST Tangential distortion coefficients \f$(p_1, p_2)\f$ are set
|
||||
to zeros and stay zero.
|
||||
- @ref CALIB_FIX_FOCAL_LENGTH The focal length is not changed during the global optimization if
|
||||
@ref CALIB_USE_INTRINSIC_GUESS is set.
|
||||
- @ref CALIB_FIX_K1,..., @ref CALIB_FIX_K6 The corresponding radial distortion
|
||||
coefficient is not changed during the optimization. If @ref CALIB_USE_INTRINSIC_GUESS is
|
||||
set, the coefficient from the supplied distCoeffs matrix is used. Otherwise, it is set to 0.
|
||||
- @ref CALIB_RATIONAL_MODEL Coefficients k4, k5, and k6 are enabled. To provide the
|
||||
backward compatibility, this extra flag should be explicitly specified to make the
|
||||
calibration function use the rational model and return 8 coefficients. If the flag is not
|
||||
set, the function computes and returns only 5 distortion coefficients.
|
||||
calibration function use the rational model and return 8 coefficients or more.
|
||||
- @ref CALIB_THIN_PRISM_MODEL Coefficients s1, s2, s3 and s4 are enabled. To provide the
|
||||
backward compatibility, this extra flag should be explicitly specified to make the
|
||||
calibration function use the thin prism model and return 12 coefficients. If the flag is not
|
||||
set, the function computes and returns only 5 distortion coefficients.
|
||||
calibration function use the thin prism model and return 12 coefficients or more.
|
||||
- @ref CALIB_FIX_S1_S2_S3_S4 The thin prism distortion coefficients are not changed during
|
||||
the optimization. If @ref CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the
|
||||
supplied distCoeffs matrix is used. Otherwise, it is set to 0.
|
||||
- @ref CALIB_TILTED_MODEL Coefficients tauX and tauY are enabled. To provide the
|
||||
backward compatibility, this extra flag should be explicitly specified to make the
|
||||
calibration function use the tilted sensor model and return 14 coefficients. If the flag is not
|
||||
set, the function computes and returns only 5 distortion coefficients.
|
||||
calibration function use the tilted sensor model and return 14 coefficients.
|
||||
- @ref CALIB_FIX_TAUX_TAUY The coefficients of the tilted sensor model are not changed during
|
||||
the optimization. If @ref CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the
|
||||
supplied distCoeffs matrix is used. Otherwise, it is set to 0.
|
||||
@@ -1589,12 +1588,12 @@ The algorithm performs the following steps:
|
||||
zeros initially unless some of CALIB_FIX_K? are specified.
|
||||
|
||||
- Estimate the initial camera pose as if the intrinsic parameters have been already known. This is
|
||||
done using solvePnP .
|
||||
done using @ref solvePnP .
|
||||
|
||||
- Run the global Levenberg-Marquardt optimization algorithm to minimize the reprojection error,
|
||||
that is, the total sum of squared distances between the observed feature points imagePoints and
|
||||
the projected (using the current estimates for camera parameters and the poses) object points
|
||||
objectPoints. See projectPoints for details.
|
||||
objectPoints. See @ref projectPoints for details.
|
||||
|
||||
@note
|
||||
If you use a non-square (i.e. non-N-by-N) grid and @ref findChessboardCorners for calibration,
|
||||
@@ -2241,6 +2240,7 @@ final fundamental matrix. It can be set to something like 1-3, depending on the
|
||||
point localization, image resolution, and the image noise.
|
||||
@param mask Output array of N elements, every element of which is set to 0 for outliers and to 1
|
||||
for the other points. The array is computed only in the RANSAC and LMedS methods.
|
||||
@param maxIters The maximum number of robust method iterations.
|
||||
|
||||
This function estimates essential matrix based on the five-point algorithm solver in @cite Nister03 .
|
||||
@cite SteweniusCFS is also a related. The epipolar geometry is described by the following equation:
|
||||
@@ -2251,6 +2251,12 @@ where \f$E\f$ is an essential matrix, \f$p_1\f$ and \f$p_2\f$ are corresponding
|
||||
second images, respectively. The result of this function may be passed further to
|
||||
decomposeEssentialMat or recoverPose to recover the relative pose between cameras.
|
||||
*/
|
||||
CV_EXPORTS_W Mat findEssentialMat( InputArray points1, InputArray points2,
|
||||
InputArray cameraMatrix, int method,
|
||||
double prob, double threshold,
|
||||
int maxIters, OutputArray mask = noArray() );
|
||||
|
||||
/** @overload */
|
||||
CV_EXPORTS_W Mat findEssentialMat( InputArray points1, InputArray points2,
|
||||
InputArray cameraMatrix, int method = RANSAC,
|
||||
double prob = 0.999, double threshold = 1.0,
|
||||
@@ -2274,6 +2280,7 @@ point localization, image resolution, and the image noise.
|
||||
confidence (probability) that the estimated matrix is correct.
|
||||
@param mask Output array of N elements, every element of which is set to 0 for outliers and to 1
|
||||
for the other points. The array is computed only in the RANSAC and LMedS methods.
|
||||
@param maxIters The maximum number of robust method iterations.
|
||||
|
||||
This function differs from the one above that it computes camera intrinsic matrix from focal length and
|
||||
principal point:
|
||||
@@ -2285,6 +2292,13 @@ f & 0 & x_{pp} \\
|
||||
0 & 0 & 1
|
||||
\end{bmatrix}\f]
|
||||
*/
|
||||
CV_EXPORTS_W Mat findEssentialMat( InputArray points1, InputArray points2,
|
||||
double focal, Point2d pp,
|
||||
int method, double prob,
|
||||
double threshold, int maxIters,
|
||||
OutputArray mask = noArray() );
|
||||
|
||||
/** @overload */
|
||||
CV_EXPORTS_W Mat findEssentialMat( InputArray points1, InputArray points2,
|
||||
double focal = 1.0, Point2d pp = Point2d(0, 0),
|
||||
int method = RANSAC, double prob = 0.999,
|
||||
|
||||
@@ -403,7 +403,8 @@ protected:
|
||||
|
||||
// Input should be a vector of n 2D points or a Nx2 matrix
|
||||
cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, InputArray _cameraMatrix,
|
||||
int method, double prob, double threshold, OutputArray _mask)
|
||||
int method, double prob, double threshold,
|
||||
int maxIters, OutputArray _mask)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
@@ -442,20 +443,36 @@ cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, InputArr
|
||||
|
||||
Mat E;
|
||||
if( method == RANSAC )
|
||||
createRANSACPointSetRegistrator(makePtr<EMEstimatorCallback>(), 5, threshold, prob)->run(points1, points2, E, _mask);
|
||||
createRANSACPointSetRegistrator(makePtr<EMEstimatorCallback>(), 5, threshold, prob, maxIters)->run(points1, points2, E, _mask);
|
||||
else
|
||||
createLMeDSPointSetRegistrator(makePtr<EMEstimatorCallback>(), 5, prob)->run(points1, points2, E, _mask);
|
||||
createLMeDSPointSetRegistrator(makePtr<EMEstimatorCallback>(), 5, prob, maxIters)->run(points1, points2, E, _mask);
|
||||
|
||||
return E;
|
||||
}
|
||||
|
||||
cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, InputArray _cameraMatrix,
|
||||
int method, double prob, double threshold,
|
||||
OutputArray _mask)
|
||||
{
|
||||
return cv::findEssentialMat(_points1, _points2, _cameraMatrix, method, prob, threshold, 1000, _mask);
|
||||
}
|
||||
|
||||
cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, double focal, Point2d pp,
|
||||
int method, double prob, double threshold, int maxIters, OutputArray _mask)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat cameraMatrix = (Mat_<double>(3,3) << focal, 0, pp.x, 0, focal, pp.y, 0, 0, 1);
|
||||
return cv::findEssentialMat(_points1, _points2, cameraMatrix, method, prob, threshold, maxIters, _mask);
|
||||
}
|
||||
|
||||
cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, double focal, Point2d pp,
|
||||
int method, double prob, double threshold, OutputArray _mask)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat cameraMatrix = (Mat_<double>(3,3) << focal, 0, pp.x, 0, focal, pp.y, 0, 0, 1);
|
||||
return cv::findEssentialMat(_points1, _points2, cameraMatrix, method, prob, threshold, _mask);
|
||||
return cv::findEssentialMat(_points1, _points2, cameraMatrix, method, prob, threshold, 1000, _mask);
|
||||
}
|
||||
|
||||
int cv::recoverPose( InputArray E, InputArray _points1, InputArray _points2,
|
||||
|
||||
@@ -866,7 +866,7 @@ cv::Mat cv::findFundamentalMat( InputArray _points1, InputArray _points2,
|
||||
if( (method & ~3) == FM_RANSAC && npoints >= 15 )
|
||||
result = createRANSACPointSetRegistrator(cb, 7, ransacReprojThreshold, confidence, maxIters)->run(m1, m2, F, _mask);
|
||||
else
|
||||
result = createLMeDSPointSetRegistrator(cb, 7, confidence)->run(m1, m2, F, _mask);
|
||||
result = createLMeDSPointSetRegistrator(cb, 7, confidence, maxIters)->run(m1, m2, F, _mask);
|
||||
}
|
||||
|
||||
if( result <= 0 )
|
||||
|
||||
@@ -554,7 +554,7 @@ Cv64suf;
|
||||
# define CV_XADD(addr, delta) (int)_InterlockedExchangeAdd((long volatile*)addr, delta)
|
||||
#else
|
||||
#ifdef OPENCV_FORCE_UNSAFE_XADD
|
||||
CV_INLINE CV_XADD(int* addr, int delta) { int tmp = *addr; *addr += delta; return tmp; }
|
||||
CV_INLINE int CV_XADD(int* addr, int delta) { int tmp = *addr; *addr += delta; return tmp; }
|
||||
#else
|
||||
#error "OpenCV: can't define safe CV_XADD macro for current platform (unsupported). Define CV_XADD macro through custom port header (see OPENCV_INCLUDE_PORT_FILE)"
|
||||
#endif
|
||||
|
||||
@@ -538,49 +538,81 @@ inline void v_mul_expand(const v_int8x16& a, const v_int8x16& b,
|
||||
v_int16x8& c, v_int16x8& d)
|
||||
{
|
||||
c.val = vmull_s8(vget_low_s8(a.val), vget_low_s8(b.val));
|
||||
#if CV_NEON_AARCH64
|
||||
d.val = vmull_high_s8(a.val, b.val);
|
||||
#else // #if CV_NEON_AARCH64
|
||||
d.val = vmull_s8(vget_high_s8(a.val), vget_high_s8(b.val));
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
|
||||
inline void v_mul_expand(const v_uint8x16& a, const v_uint8x16& b,
|
||||
v_uint16x8& c, v_uint16x8& d)
|
||||
{
|
||||
c.val = vmull_u8(vget_low_u8(a.val), vget_low_u8(b.val));
|
||||
#if CV_NEON_AARCH64
|
||||
d.val = vmull_high_u8(a.val, b.val);
|
||||
#else // #if CV_NEON_AARCH64
|
||||
d.val = vmull_u8(vget_high_u8(a.val), vget_high_u8(b.val));
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
|
||||
inline void v_mul_expand(const v_int16x8& a, const v_int16x8& b,
|
||||
v_int32x4& c, v_int32x4& d)
|
||||
{
|
||||
c.val = vmull_s16(vget_low_s16(a.val), vget_low_s16(b.val));
|
||||
#if CV_NEON_AARCH64
|
||||
d.val = vmull_high_s16(a.val, b.val);
|
||||
#else // #if CV_NEON_AARCH64
|
||||
d.val = vmull_s16(vget_high_s16(a.val), vget_high_s16(b.val));
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
|
||||
inline void v_mul_expand(const v_uint16x8& a, const v_uint16x8& b,
|
||||
v_uint32x4& c, v_uint32x4& d)
|
||||
{
|
||||
c.val = vmull_u16(vget_low_u16(a.val), vget_low_u16(b.val));
|
||||
#if CV_NEON_AARCH64
|
||||
d.val = vmull_high_u16(a.val, b.val);
|
||||
#else // #if CV_NEON_AARCH64
|
||||
d.val = vmull_u16(vget_high_u16(a.val), vget_high_u16(b.val));
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
|
||||
inline void v_mul_expand(const v_uint32x4& a, const v_uint32x4& b,
|
||||
v_uint64x2& c, v_uint64x2& d)
|
||||
{
|
||||
c.val = vmull_u32(vget_low_u32(a.val), vget_low_u32(b.val));
|
||||
#if CV_NEON_AARCH64
|
||||
d.val = vmull_high_u32(a.val, b.val);
|
||||
#else // #if CV_NEON_AARCH64
|
||||
d.val = vmull_u32(vget_high_u32(a.val), vget_high_u32(b.val));
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
|
||||
inline v_int16x8 v_mul_hi(const v_int16x8& a, const v_int16x8& b)
|
||||
{
|
||||
return v_int16x8(vcombine_s16(
|
||||
vshrn_n_s32(vmull_s16( vget_low_s16(a.val), vget_low_s16(b.val)), 16),
|
||||
vshrn_n_s32(vmull_s16(vget_high_s16(a.val), vget_high_s16(b.val)), 16)
|
||||
vshrn_n_s32(
|
||||
#if CV_NEON_AARCH64
|
||||
vmull_high_s16(a.val, b.val)
|
||||
#else // #if CV_NEON_AARCH64
|
||||
vmull_s16(vget_high_s16(a.val), vget_high_s16(b.val))
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
, 16)
|
||||
));
|
||||
}
|
||||
inline v_uint16x8 v_mul_hi(const v_uint16x8& a, const v_uint16x8& b)
|
||||
{
|
||||
return v_uint16x8(vcombine_u16(
|
||||
vshrn_n_u32(vmull_u16( vget_low_u16(a.val), vget_low_u16(b.val)), 16),
|
||||
vshrn_n_u32(vmull_u16(vget_high_u16(a.val), vget_high_u16(b.val)), 16)
|
||||
vshrn_n_u32(
|
||||
#if CV_NEON_AARCH64
|
||||
vmull_high_u16(a.val, b.val)
|
||||
#else // #if CV_NEON_AARCH64
|
||||
vmull_u16(vget_high_u16(a.val), vget_high_u16(b.val))
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
, 16)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1254,29 +1286,56 @@ OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_float64x2, double, f64)
|
||||
|
||||
inline unsigned v_reduce_sum(const v_uint8x16& a)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
uint16_t t0 = vaddlvq_u8(a.val);
|
||||
return t0;
|
||||
#else // #if CV_NEON_AARCH64
|
||||
uint32x4_t t0 = vpaddlq_u16(vpaddlq_u8(a.val));
|
||||
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
|
||||
return vget_lane_u32(vpadd_u32(t1, t1), 0);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
inline int v_reduce_sum(const v_int8x16& a)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
int16_t t0 = vaddlvq_s8(a.val);
|
||||
return t0;
|
||||
#else // #if CV_NEON_AARCH64
|
||||
int32x4_t t0 = vpaddlq_s16(vpaddlq_s8(a.val));
|
||||
int32x2_t t1 = vpadd_s32(vget_low_s32(t0), vget_high_s32(t0));
|
||||
return vget_lane_s32(vpadd_s32(t1, t1), 0);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
inline unsigned v_reduce_sum(const v_uint16x8& a)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
uint32_t t0 = vaddlvq_u16(a.val);
|
||||
return t0;
|
||||
#else // #if CV_NEON_AARCH64
|
||||
uint32x4_t t0 = vpaddlq_u16(a.val);
|
||||
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
|
||||
return vget_lane_u32(vpadd_u32(t1, t1), 0);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
inline int v_reduce_sum(const v_int16x8& a)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
int32_t t0 = vaddlvq_s16(a.val);
|
||||
return t0;
|
||||
#else // #if CV_NEON_AARCH64
|
||||
int32x4_t t0 = vpaddlq_s16(a.val);
|
||||
int32x2_t t1 = vpadd_s32(vget_low_s32(t0), vget_high_s32(t0));
|
||||
return vget_lane_s32(vpadd_s32(t1, t1), 0);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
|
||||
#if CV_NEON_AARCH64
|
||||
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
|
||||
inline scalartype v_reduce_##func(const _Tpvec& a) \
|
||||
{ \
|
||||
return v##vectorfunc##vq_##suffix(a.val); \
|
||||
}
|
||||
#else // #if CV_NEON_AARCH64
|
||||
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
|
||||
inline scalartype v_reduce_##func(const _Tpvec& a) \
|
||||
{ \
|
||||
@@ -1285,12 +1344,20 @@ inline scalartype v_reduce_##func(const _Tpvec& a) \
|
||||
a0 = vp##vectorfunc##_##suffix(a0, a0); \
|
||||
return (scalartype)vget_lane_##suffix(vp##vectorfunc##_##suffix(a0, a0),0); \
|
||||
}
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
|
||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(v_uint8x16, uint8x8, uchar, max, max, u8)
|
||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(v_uint8x16, uint8x8, uchar, min, min, u8)
|
||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(v_int8x16, int8x8, schar, max, max, s8)
|
||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(v_int8x16, int8x8, schar, min, min, s8)
|
||||
|
||||
#if CV_NEON_AARCH64
|
||||
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
|
||||
inline scalartype v_reduce_##func(const _Tpvec& a) \
|
||||
{ \
|
||||
return v##vectorfunc##vq_##suffix(a.val); \
|
||||
}
|
||||
#else // #if CV_NEON_AARCH64
|
||||
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
|
||||
inline scalartype v_reduce_##func(const _Tpvec& a) \
|
||||
{ \
|
||||
@@ -1298,18 +1365,27 @@ inline scalartype v_reduce_##func(const _Tpvec& a) \
|
||||
a0 = vp##vectorfunc##_##suffix(a0, a0); \
|
||||
return (scalartype)vget_lane_##suffix(vp##vectorfunc##_##suffix(a0, a0),0); \
|
||||
}
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
|
||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_uint16x8, uint16x4, ushort, max, max, u16)
|
||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_uint16x8, uint16x4, ushort, min, min, u16)
|
||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_int16x8, int16x4, short, max, max, s16)
|
||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_int16x8, int16x4, short, min, min, s16)
|
||||
|
||||
#if CV_NEON_AARCH64
|
||||
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
|
||||
inline scalartype v_reduce_##func(const _Tpvec& a) \
|
||||
{ \
|
||||
return v##vectorfunc##vq_##suffix(a.val); \
|
||||
}
|
||||
#else // #if CV_NEON_AARCH64
|
||||
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
|
||||
inline scalartype v_reduce_##func(const _Tpvec& a) \
|
||||
{ \
|
||||
_Tpnvec##_t a0 = vp##vectorfunc##_##suffix(vget_low_##suffix(a.val), vget_high_##suffix(a.val)); \
|
||||
return (scalartype)vget_lane_##suffix(vp##vectorfunc##_##suffix(a0, vget_high_##suffix(a.val)),0); \
|
||||
}
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
|
||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_uint32x4, uint32x2, unsigned, sum, add, u32)
|
||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_uint32x4, uint32x2, unsigned, max, max, u32)
|
||||
@@ -1322,9 +1398,21 @@ OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_float32x4, float32x2, float, max, max, f32)
|
||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_float32x4, float32x2, float, min, min, f32)
|
||||
|
||||
inline uint64 v_reduce_sum(const v_uint64x2& a)
|
||||
{ return vget_lane_u64(vadd_u64(vget_low_u64(a.val), vget_high_u64(a.val)),0); }
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
return vaddvq_u64(a.val);
|
||||
#else // #if CV_NEON_AARCH64
|
||||
return vget_lane_u64(vadd_u64(vget_low_u64(a.val), vget_high_u64(a.val)),0);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
inline int64 v_reduce_sum(const v_int64x2& a)
|
||||
{ return vget_lane_s64(vadd_s64(vget_low_s64(a.val), vget_high_s64(a.val)),0); }
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
return vaddvq_s64(a.val);
|
||||
#else // #if CV_NEON_AARCH64
|
||||
return vget_lane_s64(vadd_s64(vget_low_s64(a.val), vget_high_s64(a.val)),0);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
#if CV_SIMD128_64F
|
||||
inline double v_reduce_sum(const v_float64x2& a)
|
||||
{
|
||||
@@ -1335,6 +1423,11 @@ inline double v_reduce_sum(const v_float64x2& a)
|
||||
inline v_float32x4 v_reduce_sum4(const v_float32x4& a, const v_float32x4& b,
|
||||
const v_float32x4& c, const v_float32x4& d)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
float32x4_t ab = vpaddq_f32(a.val, b.val); // a0+a1 a2+a3 b0+b1 b2+b3
|
||||
float32x4_t cd = vpaddq_f32(c.val, d.val); // c0+c1 d0+d1 c2+c3 d2+d3
|
||||
return v_float32x4(vpaddq_f32(ab, cd)); // sumA sumB sumC sumD
|
||||
#else // #if CV_NEON_AARCH64
|
||||
float32x4x2_t ab = vtrnq_f32(a.val, b.val);
|
||||
float32x4x2_t cd = vtrnq_f32(c.val, d.val);
|
||||
|
||||
@@ -1345,49 +1438,91 @@ inline v_float32x4 v_reduce_sum4(const v_float32x4& a, const v_float32x4& b,
|
||||
float32x4_t v1 = vcombine_f32(vget_high_f32(u0), vget_high_f32(u1));
|
||||
|
||||
return v_float32x4(vaddq_f32(v0, v1));
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
|
||||
inline unsigned v_reduce_sad(const v_uint8x16& a, const v_uint8x16& b)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
uint8x16_t t0 = vabdq_u8(a.val, b.val);
|
||||
uint16_t t1 = vaddlvq_u8(t0);
|
||||
return t1;
|
||||
#else // #if CV_NEON_AARCH64
|
||||
uint32x4_t t0 = vpaddlq_u16(vpaddlq_u8(vabdq_u8(a.val, b.val)));
|
||||
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
|
||||
return vget_lane_u32(vpadd_u32(t1, t1), 0);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
inline unsigned v_reduce_sad(const v_int8x16& a, const v_int8x16& b)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
uint8x16_t t0 = vreinterpretq_u8_s8(vabdq_s8(a.val, b.val));
|
||||
uint16_t t1 = vaddlvq_u8(t0);
|
||||
return t1;
|
||||
#else // #if CV_NEON_AARCH64
|
||||
uint32x4_t t0 = vpaddlq_u16(vpaddlq_u8(vreinterpretq_u8_s8(vabdq_s8(a.val, b.val))));
|
||||
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
|
||||
return vget_lane_u32(vpadd_u32(t1, t1), 0);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
inline unsigned v_reduce_sad(const v_uint16x8& a, const v_uint16x8& b)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
uint16x8_t t0 = vabdq_u16(a.val, b.val);
|
||||
uint32_t t1 = vaddlvq_u16(t0);
|
||||
return t1;
|
||||
#else // #if CV_NEON_AARCH64
|
||||
uint32x4_t t0 = vpaddlq_u16(vabdq_u16(a.val, b.val));
|
||||
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
|
||||
return vget_lane_u32(vpadd_u32(t1, t1), 0);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
inline unsigned v_reduce_sad(const v_int16x8& a, const v_int16x8& b)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
uint16x8_t t0 = vreinterpretq_u16_s16(vabdq_s16(a.val, b.val));
|
||||
uint32_t t1 = vaddlvq_u16(t0);
|
||||
return t1;
|
||||
#else // #if CV_NEON_AARCH64
|
||||
uint32x4_t t0 = vpaddlq_u16(vreinterpretq_u16_s16(vabdq_s16(a.val, b.val)));
|
||||
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
|
||||
return vget_lane_u32(vpadd_u32(t1, t1), 0);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
inline unsigned v_reduce_sad(const v_uint32x4& a, const v_uint32x4& b)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
uint32x4_t t0 = vabdq_u32(a.val, b.val);
|
||||
uint32_t t1 = vaddvq_u32(t0);
|
||||
return t1;
|
||||
#else // #if CV_NEON_AARCH64
|
||||
uint32x4_t t0 = vabdq_u32(a.val, b.val);
|
||||
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
|
||||
return vget_lane_u32(vpadd_u32(t1, t1), 0);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
inline unsigned v_reduce_sad(const v_int32x4& a, const v_int32x4& b)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
uint32x4_t t0 = vreinterpretq_u32_s32(vabdq_s32(a.val, b.val));
|
||||
uint32_t t1 = vaddvq_u32(t0);
|
||||
return t1;
|
||||
#else // #if CV_NEON_AARCH64
|
||||
uint32x4_t t0 = vreinterpretq_u32_s32(vabdq_s32(a.val, b.val));
|
||||
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
|
||||
return vget_lane_u32(vpadd_u32(t1, t1), 0);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
inline float v_reduce_sad(const v_float32x4& a, const v_float32x4& b)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
float32x4_t t0 = vabdq_f32(a.val, b.val);
|
||||
return vaddvq_f32(t0);
|
||||
#else // #if CV_NEON_AARCH64
|
||||
float32x4_t t0 = vabdq_f32(a.val, b.val);
|
||||
float32x2_t t1 = vpadd_f32(vget_low_f32(t0), vget_high_f32(t0));
|
||||
return vget_lane_f32(vpadd_f32(t1, t1), 0);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
|
||||
inline v_uint8x16 v_popcount(const v_uint8x16& a)
|
||||
@@ -1409,30 +1544,54 @@ inline v_uint64x2 v_popcount(const v_int64x2& a)
|
||||
|
||||
inline int v_signmask(const v_uint8x16& a)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
const int8x16_t signPosition = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7};
|
||||
const uint8x16_t byteOrder = {0,8,1,9,2,10,3,11,4,12,5,13,6,14,7,15};
|
||||
uint8x16_t v0 = vshlq_u8(vshrq_n_u8(a.val, 7), signPosition);
|
||||
uint8x16_t v1 = vqtbl1q_u8(v0, byteOrder);
|
||||
uint32_t t0 = vaddlvq_u16(vreinterpretq_u16_u8(v1));
|
||||
return t0;
|
||||
#else // #if CV_NEON_AARCH64
|
||||
int8x8_t m0 = vcreate_s8(CV_BIG_UINT(0x0706050403020100));
|
||||
uint8x16_t v0 = vshlq_u8(vshrq_n_u8(a.val, 7), vcombine_s8(m0, m0));
|
||||
uint64x2_t v1 = vpaddlq_u32(vpaddlq_u16(vpaddlq_u8(v0)));
|
||||
return (int)vgetq_lane_u64(v1, 0) + ((int)vgetq_lane_u64(v1, 1) << 8);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
|
||||
inline int v_signmask(const v_int8x16& a)
|
||||
{ return v_signmask(v_reinterpret_as_u8(a)); }
|
||||
|
||||
inline int v_signmask(const v_uint16x8& a)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
const int16x8_t signPosition = {0,1,2,3,4,5,6,7};
|
||||
uint16x8_t v0 = vshlq_u16(vshrq_n_u16(a.val, 15), signPosition);
|
||||
uint32_t t0 = vaddlvq_u16(v0);
|
||||
return t0;
|
||||
#else // #if CV_NEON_AARCH64
|
||||
int16x4_t m0 = vcreate_s16(CV_BIG_UINT(0x0003000200010000));
|
||||
uint16x8_t v0 = vshlq_u16(vshrq_n_u16(a.val, 15), vcombine_s16(m0, m0));
|
||||
uint64x2_t v1 = vpaddlq_u32(vpaddlq_u16(v0));
|
||||
return (int)vgetq_lane_u64(v1, 0) + ((int)vgetq_lane_u64(v1, 1) << 4);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
inline int v_signmask(const v_int16x8& a)
|
||||
{ return v_signmask(v_reinterpret_as_u16(a)); }
|
||||
|
||||
inline int v_signmask(const v_uint32x4& a)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
const int32x4_t signPosition = {0,1,2,3};
|
||||
uint32x4_t v0 = vshlq_u32(vshrq_n_u32(a.val, 31), signPosition);
|
||||
uint32_t t0 = vaddvq_u32(v0);
|
||||
return t0;
|
||||
#else // #if CV_NEON_AARCH64
|
||||
int32x2_t m0 = vcreate_s32(CV_BIG_UINT(0x0000000100000000));
|
||||
uint32x4_t v0 = vshlq_u32(vshrq_n_u32(a.val, 31), vcombine_s32(m0, m0));
|
||||
uint64x2_t v1 = vpaddlq_u32(v0);
|
||||
return (int)vgetq_lane_u64(v1, 0) + ((int)vgetq_lane_u64(v1, 1) << 2);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
inline int v_signmask(const v_int32x4& a)
|
||||
{ return v_signmask(v_reinterpret_as_u32(a)); }
|
||||
@@ -1440,9 +1599,16 @@ inline int v_signmask(const v_float32x4& a)
|
||||
{ return v_signmask(v_reinterpret_as_u32(a)); }
|
||||
inline int v_signmask(const v_uint64x2& a)
|
||||
{
|
||||
#if CV_NEON_AARCH64
|
||||
const int64x2_t signPosition = {0,1};
|
||||
uint64x2_t v0 = vshlq_u64(vshrq_n_u64(a.val, 63), signPosition);
|
||||
uint64_t t0 = vaddvq_u64(v0);
|
||||
return t0;
|
||||
#else // #if CV_NEON_AARCH64
|
||||
int64x1_t m0 = vdup_n_s64(0);
|
||||
uint64x2_t v0 = vshlq_u64(vshrq_n_u64(a.val, 63), vcombine_s64(m0, m0));
|
||||
return (int)vgetq_lane_u64(v0, 0) + ((int)vgetq_lane_u64(v0, 1) << 1);
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
}
|
||||
inline int v_signmask(const v_int64x2& a)
|
||||
{ return v_signmask(v_reinterpret_as_u64(a)); }
|
||||
@@ -1464,19 +1630,31 @@ inline int v_scan_forward(const v_uint64x2& a) { return trailingZeros32(v_signma
|
||||
inline int v_scan_forward(const v_float64x2& a) { return trailingZeros32(v_signmask(a)); }
|
||||
#endif
|
||||
|
||||
#define OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(_Tpvec, suffix, shift) \
|
||||
inline bool v_check_all(const v_##_Tpvec& a) \
|
||||
{ \
|
||||
_Tpvec##_t v0 = vshrq_n_##suffix(vmvnq_##suffix(a.val), shift); \
|
||||
uint64x2_t v1 = vreinterpretq_u64_##suffix(v0); \
|
||||
return (vgetq_lane_u64(v1, 0) | vgetq_lane_u64(v1, 1)) == 0; \
|
||||
} \
|
||||
inline bool v_check_any(const v_##_Tpvec& a) \
|
||||
{ \
|
||||
_Tpvec##_t v0 = vshrq_n_##suffix(a.val, shift); \
|
||||
uint64x2_t v1 = vreinterpretq_u64_##suffix(v0); \
|
||||
return (vgetq_lane_u64(v1, 0) | vgetq_lane_u64(v1, 1)) != 0; \
|
||||
}
|
||||
#if CV_NEON_AARCH64
|
||||
#define OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(_Tpvec, suffix, shift) \
|
||||
inline bool v_check_all(const v_##_Tpvec& a) \
|
||||
{ \
|
||||
return (vminvq_##suffix(a.val) >> shift) != 0; \
|
||||
} \
|
||||
inline bool v_check_any(const v_##_Tpvec& a) \
|
||||
{ \
|
||||
return (vmaxvq_##suffix(a.val) >> shift) != 0; \
|
||||
}
|
||||
#else // #if CV_NEON_AARCH64
|
||||
#define OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(_Tpvec, suffix, shift) \
|
||||
inline bool v_check_all(const v_##_Tpvec& a) \
|
||||
{ \
|
||||
_Tpvec##_t v0 = vshrq_n_##suffix(vmvnq_##suffix(a.val), shift); \
|
||||
uint64x2_t v1 = vreinterpretq_u64_##suffix(v0); \
|
||||
return (vgetq_lane_u64(v1, 0) | vgetq_lane_u64(v1, 1)) == 0; \
|
||||
} \
|
||||
inline bool v_check_any(const v_##_Tpvec& a) \
|
||||
{ \
|
||||
_Tpvec##_t v0 = vshrq_n_##suffix(a.val, shift); \
|
||||
uint64x2_t v1 = vreinterpretq_u64_##suffix(v0); \
|
||||
return (vgetq_lane_u64(v1, 0) | vgetq_lane_u64(v1, 1)) != 0; \
|
||||
}
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
|
||||
OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint8x16, u8, 7)
|
||||
OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint16x8, u16, 15)
|
||||
@@ -1829,6 +2007,37 @@ inline v_int32x4 v_trunc(const v_float64x2& a)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CV_NEON_AARCH64
|
||||
#define OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(_Tpvec, suffix) \
|
||||
inline void v_transpose4x4(const v_##_Tpvec& a0, const v_##_Tpvec& a1, \
|
||||
const v_##_Tpvec& a2, const v_##_Tpvec& a3, \
|
||||
v_##_Tpvec& b0, v_##_Tpvec& b1, \
|
||||
v_##_Tpvec& b2, v_##_Tpvec& b3) \
|
||||
{ \
|
||||
/* -- Pass 1: 64b transpose */ \
|
||||
_Tpvec##_t t0 = vreinterpretq_##suffix##32_##suffix##64( \
|
||||
vtrn1q_##suffix##64(vreinterpretq_##suffix##64_##suffix##32(a0.val), \
|
||||
vreinterpretq_##suffix##64_##suffix##32(a2.val))); \
|
||||
_Tpvec##_t t1 = vreinterpretq_##suffix##32_##suffix##64( \
|
||||
vtrn1q_##suffix##64(vreinterpretq_##suffix##64_##suffix##32(a1.val), \
|
||||
vreinterpretq_##suffix##64_##suffix##32(a3.val))); \
|
||||
_Tpvec##_t t2 = vreinterpretq_##suffix##32_##suffix##64( \
|
||||
vtrn2q_##suffix##64(vreinterpretq_##suffix##64_##suffix##32(a0.val), \
|
||||
vreinterpretq_##suffix##64_##suffix##32(a2.val))); \
|
||||
_Tpvec##_t t3 = vreinterpretq_##suffix##32_##suffix##64( \
|
||||
vtrn2q_##suffix##64(vreinterpretq_##suffix##64_##suffix##32(a1.val), \
|
||||
vreinterpretq_##suffix##64_##suffix##32(a3.val))); \
|
||||
/* -- Pass 2: 32b transpose */ \
|
||||
b0.val = vtrn1q_##suffix##32(t0, t1); \
|
||||
b1.val = vtrn2q_##suffix##32(t0, t1); \
|
||||
b2.val = vtrn1q_##suffix##32(t2, t3); \
|
||||
b3.val = vtrn2q_##suffix##32(t2, t3); \
|
||||
}
|
||||
|
||||
OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(uint32x4, u)
|
||||
OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(int32x4, s)
|
||||
OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(float32x4, f)
|
||||
#else // #if CV_NEON_AARCH64
|
||||
#define OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(_Tpvec, suffix) \
|
||||
inline void v_transpose4x4(const v_##_Tpvec& a0, const v_##_Tpvec& a1, \
|
||||
const v_##_Tpvec& a2, const v_##_Tpvec& a3, \
|
||||
@@ -1854,6 +2063,7 @@ inline void v_transpose4x4(const v_##_Tpvec& a0, const v_##_Tpvec& a1, \
|
||||
OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(uint32x4, u32)
|
||||
OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(int32x4, s32)
|
||||
OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(float32x4, f32)
|
||||
#endif // #if CV_NEON_AARCH64
|
||||
|
||||
#define OPENCV_HAL_IMPL_NEON_INTERLEAVED(_Tpvec, _Tp, suffix) \
|
||||
inline void v_load_deinterleave(const _Tp* ptr, v_##_Tpvec& a, v_##_Tpvec& b) \
|
||||
|
||||
@@ -898,6 +898,33 @@ const _Tp* Mat::ptr(const int* idx) const
|
||||
return (const _Tp*)p;
|
||||
}
|
||||
|
||||
template<int n> inline
|
||||
uchar* Mat::ptr(const Vec<int, n>& idx)
|
||||
{
|
||||
return Mat::ptr(idx.val);
|
||||
}
|
||||
|
||||
template<int n> inline
|
||||
const uchar* Mat::ptr(const Vec<int, n>& idx) const
|
||||
{
|
||||
return Mat::ptr(idx.val);
|
||||
}
|
||||
|
||||
template<typename _Tp, int n> inline
|
||||
_Tp* Mat::ptr(const Vec<int, n>& idx)
|
||||
{
|
||||
CV_DbgAssert( elemSize() == sizeof(_Tp) );
|
||||
return Mat::ptr<_Tp>(idx.val);
|
||||
}
|
||||
|
||||
template<typename _Tp, int n> inline
|
||||
const _Tp* Mat::ptr(const Vec<int, n>& idx) const
|
||||
{
|
||||
CV_DbgAssert( elemSize() == sizeof(_Tp) );
|
||||
return Mat::ptr<_Tp>(idx.val);
|
||||
}
|
||||
|
||||
|
||||
template<typename _Tp> inline
|
||||
_Tp& Mat::at(int i0, int i1)
|
||||
{
|
||||
|
||||
@@ -702,24 +702,24 @@ public:
|
||||
//! the default constructor
|
||||
CV_WRAP KeyPoint();
|
||||
/**
|
||||
@param _pt x & y coordinates of the keypoint
|
||||
@param _size keypoint diameter
|
||||
@param _angle keypoint orientation
|
||||
@param _response keypoint detector response on the keypoint (that is, strength of the keypoint)
|
||||
@param _octave pyramid octave in which the keypoint has been detected
|
||||
@param _class_id object id
|
||||
@param pt x & y coordinates of the keypoint
|
||||
@param size keypoint diameter
|
||||
@param angle keypoint orientation
|
||||
@param response keypoint detector response on the keypoint (that is, strength of the keypoint)
|
||||
@param octave pyramid octave in which the keypoint has been detected
|
||||
@param class_id object id
|
||||
*/
|
||||
KeyPoint(Point2f _pt, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1);
|
||||
KeyPoint(Point2f pt, float size, float angle=-1, float response=0, int octave=0, int class_id=-1);
|
||||
/**
|
||||
@param x x-coordinate of the keypoint
|
||||
@param y y-coordinate of the keypoint
|
||||
@param _size keypoint diameter
|
||||
@param _angle keypoint orientation
|
||||
@param _response keypoint detector response on the keypoint (that is, strength of the keypoint)
|
||||
@param _octave pyramid octave in which the keypoint has been detected
|
||||
@param _class_id object id
|
||||
@param size keypoint diameter
|
||||
@param angle keypoint orientation
|
||||
@param response keypoint detector response on the keypoint (that is, strength of the keypoint)
|
||||
@param octave pyramid octave in which the keypoint has been detected
|
||||
@param class_id object id
|
||||
*/
|
||||
CV_WRAP KeyPoint(float x, float y, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1);
|
||||
CV_WRAP KeyPoint(float x, float y, float size, float angle=-1, float response=0, int octave=0, int class_id=-1);
|
||||
|
||||
size_t hash() const;
|
||||
|
||||
|
||||
@@ -358,7 +358,11 @@ _IplImage
|
||||
needed for correct deallocation */
|
||||
|
||||
#if defined(CV__ENABLE_C_API_CTORS) && defined(__cplusplus)
|
||||
_IplImage() {}
|
||||
_IplImage()
|
||||
{
|
||||
memset(this, 0, sizeof(*this)); // valid for POD structure
|
||||
nSize = sizeof(IplImage);
|
||||
}
|
||||
_IplImage(const cv::Mat& m) { *this = cvIplImage(m); }
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
# define OPENCV_HAVE_FILESYSTEM_SUPPORT 1
|
||||
# elif defined(__APPLE__)
|
||||
# include <TargetConditionals.h>
|
||||
# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX) || (!defined(TARGET_OS_OSX) && !TARGET_OS_IPHONE)
|
||||
# define OPENCV_HAVE_FILESYSTEM_SUPPORT 1 // OSX only
|
||||
# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS)
|
||||
# define OPENCV_HAVE_FILESYSTEM_SUPPORT 1 // OSX, iOS only
|
||||
# endif
|
||||
# else
|
||||
/* unknown */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#define CV_VERSION_MAJOR 3
|
||||
#define CV_VERSION_MINOR 4
|
||||
#define CV_VERSION_REVISION 14
|
||||
#define CV_VERSION_REVISION 15
|
||||
#define CV_VERSION_STATUS ""
|
||||
|
||||
#define CVAUX_STR_EXP(__A) #__A
|
||||
|
||||
@@ -678,7 +678,12 @@ OCL_PERF_TEST_P(SqrtFixture, Sqrt, ::testing::Combine(
|
||||
|
||||
OCL_TEST_CYCLE() cv::sqrt(src, dst);
|
||||
|
||||
if (CV_MAT_DEPTH(type) >= CV_32F)
|
||||
// To square root 32 bit floats we use native_sqrt, which has implementation
|
||||
// defined accuracy. We know intel devices have accurate native_sqrt, but
|
||||
// otherwise stick to a relaxed sanity check. For types larger than 32 bits
|
||||
// we can do the accuracy check for all devices as normal.
|
||||
if (CV_MAT_DEPTH(type) > CV_32F || !ocl::useOpenCL() ||
|
||||
ocl::Device::getDefault().isIntel())
|
||||
SANITY_CHECK(dst, 1e-5, ERROR_RELATIVE);
|
||||
else
|
||||
SANITY_CHECK(dst, 1);
|
||||
|
||||
@@ -1171,7 +1171,7 @@ double norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask
|
||||
// special case to handle "integer" overflow in accumulator
|
||||
const size_t esz = src1.elemSize();
|
||||
const int total = (int)it.size;
|
||||
const int intSumBlockSize = normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15);
|
||||
const int intSumBlockSize = (normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15))/cn;
|
||||
const int blockSize = std::min(total, intSumBlockSize);
|
||||
int isum = 0;
|
||||
int count = 0;
|
||||
|
||||
@@ -2805,7 +2805,6 @@ struct Kernel::Impl
|
||||
void registerImageArgument(int arg, const Image2D& image)
|
||||
{
|
||||
CV_CheckGE(arg, 0, "");
|
||||
CV_CheckLT(arg, (int)MAX_ARRS, "");
|
||||
if (arg < (int)shadow_images.size() && shadow_images[arg].ptr() != image.ptr()) // TODO future: replace ptr => impl (more strong check)
|
||||
{
|
||||
CV_Check(arg, !isInProgress, "ocl::Kernel: clearing of pending Image2D arguments is not allowed");
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "precomp.hpp"
|
||||
#include "persistence.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
char* icv_itoa( int _val, char* buffer, int /*radix*/ )
|
||||
{
|
||||
const int radix = 10;
|
||||
@@ -519,12 +521,16 @@ static const char symbols[9] = "ucwsifdr";
|
||||
|
||||
char icvTypeSymbol(int depth)
|
||||
{
|
||||
CV_Assert(depth >=0 && depth < 9);
|
||||
CV_StaticAssert(CV_64F == 6, "");
|
||||
CV_Assert(depth >=0 && depth <= CV_64F);
|
||||
CV_CheckDepth(depth, depth >=0 && depth <= CV_64F, "");
|
||||
return symbols[depth];
|
||||
}
|
||||
|
||||
static int icvSymbolToType(char c)
|
||||
{
|
||||
if (c == 'r')
|
||||
return CV_SEQ_ELTYPE_PTR;
|
||||
const char* pos = strchr( symbols, c );
|
||||
if( !pos )
|
||||
CV_Error( CV_StsBadArg, "Invalid data type specification" );
|
||||
@@ -618,8 +624,12 @@ int icvCalcStructSize( const char* dt, int initial_size )
|
||||
{
|
||||
int size = icvCalcElemSize( dt, initial_size );
|
||||
size_t elem_max_size = 0;
|
||||
for ( const char * type = dt; *type != '\0'; type++ ) {
|
||||
switch ( *type )
|
||||
for ( const char * type = dt; *type != '\0'; type++ )
|
||||
{
|
||||
char v = *type;
|
||||
if (v >= '0' && v <= '9')
|
||||
continue; // skip vector size
|
||||
switch (v)
|
||||
{
|
||||
case 'u': { elem_max_size = std::max( elem_max_size, sizeof(uchar ) ); break; }
|
||||
case 'c': { elem_max_size = std::max( elem_max_size, sizeof(schar ) ); break; }
|
||||
@@ -628,7 +638,8 @@ int icvCalcStructSize( const char* dt, int initial_size )
|
||||
case 'i': { elem_max_size = std::max( elem_max_size, sizeof(int ) ); break; }
|
||||
case 'f': { elem_max_size = std::max( elem_max_size, sizeof(float ) ); break; }
|
||||
case 'd': { elem_max_size = std::max( elem_max_size, sizeof(double) ); break; }
|
||||
default: break;
|
||||
default:
|
||||
CV_Error_(Error::StsNotImplemented, ("Unknown type identifier: '%c' in '%s'", (char)(*type), dt));
|
||||
}
|
||||
}
|
||||
size = cvAlign( size, static_cast<int>(elem_max_size) );
|
||||
|
||||
@@ -388,6 +388,8 @@ cv::Mutex& getInitializationMutex();
|
||||
#define CV_SINGLETON_LAZY_INIT(TYPE, INITIALIZER) CV_SINGLETON_LAZY_INIT_(TYPE, INITIALIZER, instance)
|
||||
#define CV_SINGLETON_LAZY_INIT_REF(TYPE, INITIALIZER) CV_SINGLETON_LAZY_INIT_(TYPE, INITIALIZER, *instance)
|
||||
|
||||
CV_EXPORTS void releaseTlsStorageThread();
|
||||
|
||||
int cv_snprintf(char* buf, int len, const char* fmt, ...);
|
||||
int cv_vsnprintf(char* buf, int len, const char* fmt, va_list args);
|
||||
}
|
||||
|
||||
@@ -1583,6 +1583,9 @@ struct ThreadData
|
||||
size_t idx; // Thread index in TLS storage. This is not OS thread ID!
|
||||
};
|
||||
|
||||
|
||||
static bool g_isTlsStorageInitialized = false;
|
||||
|
||||
// Main TLS storage class
|
||||
class TlsStorage
|
||||
{
|
||||
@@ -1592,6 +1595,7 @@ public:
|
||||
{
|
||||
tlsSlots.reserve(32);
|
||||
threads.reserve(32);
|
||||
g_isTlsStorageInitialized = true;
|
||||
}
|
||||
~TlsStorage()
|
||||
{
|
||||
@@ -1796,12 +1800,31 @@ static TlsStorage &getTlsStorage()
|
||||
#ifndef _WIN32 // pthread key destructor
|
||||
static void opencv_tls_destructor(void* pData)
|
||||
{
|
||||
if (!g_isTlsStorageInitialized)
|
||||
return; // nothing to release, so prefer to avoid creation of new global structures
|
||||
getTlsStorage().releaseThread(pData);
|
||||
}
|
||||
#else // _WIN32
|
||||
#ifdef CV_USE_FLS
|
||||
static void WINAPI opencv_fls_destructor(void* pData)
|
||||
{
|
||||
// Empiric detection of ExitProcess call
|
||||
DWORD code = STILL_ACTIVE/*259*/;
|
||||
BOOL res = GetExitCodeProcess(GetCurrentProcess(), &code);
|
||||
if (res && code != STILL_ACTIVE)
|
||||
{
|
||||
// Looks like we are in ExitProcess() call
|
||||
// This is FLS specific only because their callback is called before DllMain.
|
||||
// TLS doesn't have similar problem, DllMain() is called first which mark __termination properly.
|
||||
// Note: this workaround conflicts with ExitProcess() steps order described in documentation, however it works:
|
||||
// 3. ... called with DLL_PROCESS_DETACH
|
||||
// 7. The termination status of the process changes from STILL_ACTIVE to the exit value of the process.
|
||||
// (ref: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-exitprocess)
|
||||
cv::__termination = true;
|
||||
}
|
||||
|
||||
if (!g_isTlsStorageInitialized)
|
||||
return; // nothing to release, so prefer to avoid creation of new global structures
|
||||
getTlsStorage().releaseThread(pData);
|
||||
}
|
||||
#endif // CV_USE_FLS
|
||||
@@ -1810,6 +1833,13 @@ static void WINAPI opencv_fls_destructor(void* pData)
|
||||
} // namespace details
|
||||
using namespace details;
|
||||
|
||||
void releaseTlsStorageThread()
|
||||
{
|
||||
if (!g_isTlsStorageInitialized)
|
||||
return; // nothing to release, so prefer to avoid creation of new global structures
|
||||
getTlsStorage().releaseThread();
|
||||
}
|
||||
|
||||
TLSDataContainer::TLSDataContainer()
|
||||
{
|
||||
key_ = (int)getTlsStorage().reserveSlot(this); // Reserve key from TLS storage
|
||||
@@ -1893,7 +1923,7 @@ BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved)
|
||||
{
|
||||
// Not allowed to free resources if lpReserved is non-null
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583.aspx
|
||||
cv::getTlsStorage().releaseThread();
|
||||
releaseTlsStorageThread();
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
@@ -132,4 +132,69 @@ TEST(OpenCL, support_SPIR_programs)
|
||||
testOpenCLKernel(k);
|
||||
}
|
||||
|
||||
TEST(OpenCL, image2Dcount_regression_19334)
|
||||
{
|
||||
cv::ocl::Context ctx = cv::ocl::Context::getDefault();
|
||||
if (!ctx.ptr())
|
||||
{
|
||||
throw cvtest::SkipTestException("OpenCL is not available");
|
||||
}
|
||||
cv::ocl::Device device = cv::ocl::Device::getDefault();
|
||||
if (!device.compilerAvailable())
|
||||
{
|
||||
throw cvtest::SkipTestException("OpenCL compiler is not available");
|
||||
}
|
||||
|
||||
std::string module_name; // empty to disable OpenCL cache
|
||||
|
||||
static const char* opencl_kernel_src =
|
||||
"__kernel void test_kernel(int a,\n"
|
||||
" __global const uchar* src0, int src0_step, int src0_offset, int src0_rows, int src0_cols,\n"
|
||||
" __global const uchar* src1, int src1_step, int src1_offset, int src1_rows, int src1_cols,\n"
|
||||
" __global const uchar* src2, int src2_step, int src2_offset, int src2_rows, int src2_cols,\n"
|
||||
" __read_only image2d_t image)\n"
|
||||
"{\n"
|
||||
"}";
|
||||
cv::ocl::ProgramSource src(module_name, "test_opencl_image_arg", opencl_kernel_src, "");
|
||||
cv::String errmsg;
|
||||
cv::ocl::Program program(src, "", errmsg);
|
||||
ASSERT_TRUE(program.ptr() != NULL);
|
||||
cv::ocl::Kernel k("test_kernel", program);
|
||||
ASSERT_FALSE(k.empty());
|
||||
|
||||
std::vector<UMat> images(4);
|
||||
for (size_t i = 0; i < images.size(); ++i)
|
||||
images[i] = UMat(10, 10, CV_8UC1);
|
||||
cv::ocl::Image2D image;
|
||||
try
|
||||
{
|
||||
cv::ocl::Image2D image_(images.back());
|
||||
image = image_;
|
||||
}
|
||||
catch (const cv::Exception&)
|
||||
{
|
||||
throw cvtest::SkipTestException("OpenCL images are not supported");
|
||||
}
|
||||
|
||||
int nargs = 0;
|
||||
int a = 0;
|
||||
nargs = k.set(nargs, a);
|
||||
ASSERT_EQ(1, nargs);
|
||||
nargs = k.set(nargs, images[0]);
|
||||
ASSERT_EQ(6, nargs);
|
||||
nargs = k.set(nargs, images[1]);
|
||||
ASSERT_EQ(11, nargs);
|
||||
nargs = k.set(nargs, images[2]);
|
||||
ASSERT_EQ(16, nargs);
|
||||
|
||||
// do not throw (issue of #19334)
|
||||
ASSERT_NO_THROW(nargs = k.set(nargs, image));
|
||||
ASSERT_EQ(17, nargs);
|
||||
|
||||
// allow to replace image argument if kernel is not running
|
||||
UMat image2(10, 10, CV_8UC1);
|
||||
ASSERT_NO_THROW(nargs = k.set(16, cv::ocl::Image2D(image2)));
|
||||
ASSERT_EQ(17, nargs);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -2117,6 +2117,15 @@ TEST(Core_Norm, IPP_regression_NORM_L1_16UC3_small)
|
||||
EXPECT_EQ((double)20*cn, cv::norm(a, b, NORM_L1, mask));
|
||||
}
|
||||
|
||||
TEST(Core_Norm, NORM_L2_8UC4)
|
||||
{
|
||||
// Tests there is no integer overflow in norm computation for multiple channels.
|
||||
const int kSide = 100;
|
||||
cv::Mat4b a(kSide, kSide, cv::Scalar(255, 255, 255, 255));
|
||||
cv::Mat4b b = cv::Mat4b::zeros(kSide, kSide);
|
||||
const double kNorm = 2.*kSide*255.;
|
||||
EXPECT_EQ(kNorm, cv::norm(a, b, NORM_L2));
|
||||
}
|
||||
|
||||
TEST(Core_ConvertTo, regression_12121)
|
||||
{
|
||||
|
||||
@@ -577,6 +577,25 @@ template<typename R> struct TheTest
|
||||
return *this;
|
||||
}
|
||||
|
||||
TheTest & test_mul_hi()
|
||||
{
|
||||
// typedef typename V_RegTraits<R>::w_reg Rx2;
|
||||
Data<R> dataA, dataB(32767);
|
||||
R a = dataA, b = dataB;
|
||||
|
||||
R c = v_mul_hi(a, b);
|
||||
|
||||
Data<R> resC = c;
|
||||
const int n = R::nlanes / 2;
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("i=%d", i));
|
||||
EXPECT_EQ((typename R::lane_type)((dataA[i] * dataB[i]) >> 16), resC[i]);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
TheTest & test_abs()
|
||||
{
|
||||
typedef typename V_RegTraits<R>::u_reg Ru;
|
||||
@@ -1663,6 +1682,7 @@ void test_hal_intrin_uint16()
|
||||
.test_arithm_wrap()
|
||||
.test_mul()
|
||||
.test_mul_expand()
|
||||
.test_mul_hi()
|
||||
.test_cmp()
|
||||
.test_shift<1>()
|
||||
.test_shift<8>()
|
||||
@@ -1697,6 +1717,7 @@ void test_hal_intrin_int16()
|
||||
.test_arithm_wrap()
|
||||
.test_mul()
|
||||
.test_mul_expand()
|
||||
.test_mul_hi()
|
||||
.test_cmp()
|
||||
.test_shift<1>()
|
||||
.test_shift<8>()
|
||||
|
||||
@@ -2365,4 +2365,20 @@ TEST(Mat, regression_18473)
|
||||
}
|
||||
|
||||
|
||||
TEST(Mat, ptrVecni_20044)
|
||||
{
|
||||
Mat_<int> m(3,4); m << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12;
|
||||
Vec2i idx(1,1);
|
||||
|
||||
uchar *u = m.ptr(idx);
|
||||
EXPECT_EQ(int(6), *(int*)(u));
|
||||
const uchar *cu = m.ptr(idx);
|
||||
EXPECT_EQ(int(6), *(int*)(cu));
|
||||
|
||||
int *i = m.ptr<int>(idx);
|
||||
EXPECT_EQ(int(6), *(i));
|
||||
const int *ci = m.ptr<int>(idx);
|
||||
EXPECT_EQ(int(6), *(ci));
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -148,16 +148,20 @@ ocv_add_perf_tests(${INF_ENGINE_TARGET}
|
||||
FILES Include ${perf_hdrs}
|
||||
)
|
||||
|
||||
ocv_option(${the_module}_PERF_CAFFE "Add performance tests of Caffe framework" OFF)
|
||||
ocv_option(${the_module}_PERF_CLCAFFE "Add performance tests of clCaffe framework" OFF)
|
||||
ocv_option(OPENCV_DNN_PERF_CAFFE "Add performance tests of Caffe framework" OFF)
|
||||
ocv_option(OPENCV_DNN_PERF_CLCAFFE "Add performance tests of clCaffe framework" OFF)
|
||||
if(BUILD_PERF_TESTS)
|
||||
if (${the_module}_PERF_CAFFE)
|
||||
if (OPENCV_DNN_PERF_CAFFE
|
||||
OR ${the_module}_PERF_CAFFE # compatibility for deprecated option
|
||||
)
|
||||
find_package(Caffe QUIET)
|
||||
if (Caffe_FOUND)
|
||||
add_definitions(-DHAVE_CAFFE=1)
|
||||
ocv_target_link_libraries(opencv_perf_dnn caffe)
|
||||
endif()
|
||||
elseif(${the_module}_PERF_CLCAFFE)
|
||||
elseif(OPENCV_DNN_PERF_CLCAFFE
|
||||
OR ${the_module}_PERF_CAFFE # compatibility for deprecated option
|
||||
)
|
||||
find_package(Caffe QUIET)
|
||||
if (Caffe_FOUND)
|
||||
add_definitions(-DHAVE_CLCAFFE=1)
|
||||
|
||||
@@ -47,9 +47,9 @@
|
||||
#include "opencv2/core/async.hpp"
|
||||
|
||||
#if !defined CV_DOXYGEN && !defined CV_STATIC_ANALYSIS && !defined CV_DNN_DONT_ADD_EXPERIMENTAL_NS
|
||||
#define CV__DNN_EXPERIMENTAL_NS_BEGIN namespace experimental_dnn_34_v21 {
|
||||
#define CV__DNN_EXPERIMENTAL_NS_BEGIN namespace experimental_dnn_34_v22 {
|
||||
#define CV__DNN_EXPERIMENTAL_NS_END }
|
||||
namespace cv { namespace dnn { namespace experimental_dnn_34_v21 { } using namespace experimental_dnn_34_v21; }}
|
||||
namespace cv { namespace dnn { namespace experimental_dnn_34_v22 { } using namespace experimental_dnn_34_v22; }}
|
||||
#else
|
||||
#define CV__DNN_EXPERIMENTAL_NS_BEGIN
|
||||
#define CV__DNN_EXPERIMENTAL_NS_END
|
||||
@@ -712,9 +712,11 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
|
||||
CV_WRAP void enableFusion(bool fusion);
|
||||
|
||||
/** @brief Returns overall time for inference and timings (in ticks) for layers.
|
||||
*
|
||||
* Indexes in returned vector correspond to layers ids. Some layers can be fused with others,
|
||||
* in this case zero ticks count will be return for that skipped layers.
|
||||
* @param timings vector for tick timings for all layers.
|
||||
* in this case zero ticks count will be return for that skipped layers. Supported by DNN_BACKEND_OPENCV on DNN_TARGET_CPU only.
|
||||
*
|
||||
* @param[out] timings vector for tick timings for all layers.
|
||||
* @return overall ticks for model inference.
|
||||
*/
|
||||
CV_WRAP int64 getPerfProfile(CV_OUT std::vector<double>& timings);
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
]
|
||||
|
||||
],
|
||||
"jni_name": "(*(cv::dnn::DictValue*)%(n)s_nativeObj)",
|
||||
"jni_name": "(*(*(Ptr<cv::dnn::DictValue>*)%(n)s_nativeObj))",
|
||||
"jni_type": "jlong",
|
||||
"suffix": "J",
|
||||
"j_import": "org.opencv.dnn.DictValue"
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
#include <opencv2/core/utils/configuration.private.hpp>
|
||||
#include <opencv2/core/utils/logger.hpp>
|
||||
|
||||
#include "opencv2/core/utils/filesystem.hpp"
|
||||
#include "opencv2/core/utils/filesystem.private.hpp"
|
||||
|
||||
namespace cv { namespace dnn {
|
||||
|
||||
#ifdef HAVE_DNN_NGRAPH
|
||||
@@ -651,7 +654,11 @@ void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net)
|
||||
try
|
||||
{
|
||||
InferenceEngine::IExtensionPtr extension =
|
||||
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2021_4)
|
||||
std::make_shared<InferenceEngine::Extension>(libName);
|
||||
#else
|
||||
InferenceEngine::make_so_pointer<InferenceEngine::IExtension>(libName);
|
||||
#endif
|
||||
|
||||
ie.AddExtension(extension, "CPU");
|
||||
CV_LOG_INFO(NULL, "DNN-IE: Loaded extension plugin: " << libName);
|
||||
@@ -680,6 +687,23 @@ void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net)
|
||||
ie.SetConfig({{
|
||||
InferenceEngine::PluginConfigParams::KEY_CPU_THREADS_NUM, format("%d", getNumThreads()),
|
||||
}}, device_name);
|
||||
#endif
|
||||
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2021_2)
|
||||
if (device_name.find("GPU") == 0)
|
||||
{
|
||||
#if OPENCV_HAVE_FILESYSTEM_SUPPORT
|
||||
std::string cache_path = utils::fs::getCacheDirectory((std::string("dnn_ie_cache_") + device_name).c_str(), "OPENCV_DNN_IE_GPU_CACHE_DIR");
|
||||
#else
|
||||
std::string cache_path = utils::getConfigurationParameterString("OPENCV_DNN_IE_GPU_CACHE_DIR", "");
|
||||
#endif
|
||||
if (!cache_path.empty() && cache_path != "disabled")
|
||||
{
|
||||
CV_LOG_INFO(NULL, "OpenCV/nGraph: using GPU kernels cache: " << cache_path);
|
||||
ie.SetConfig({{
|
||||
InferenceEngine::PluginConfigParams::KEY_CACHE_DIR, cache_path,
|
||||
}}, device_name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
std::map<std::string, std::string> config;
|
||||
@@ -982,35 +1006,54 @@ void InfEngineNgraphNet::forward(const std::vector<Ptr<BackendWrapper> >& outBlo
|
||||
reqWrapper->req.SetInput(inpBlobs);
|
||||
reqWrapper->req.SetOutput(outBlobs);
|
||||
|
||||
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2021_4)
|
||||
InferenceEngine::InferRequest infRequest = reqWrapper->req;
|
||||
NgraphReqWrapper* wrapperPtr = reqWrapper.get();
|
||||
CV_Assert(wrapperPtr && "Internal error");
|
||||
#else
|
||||
InferenceEngine::IInferRequest::Ptr infRequestPtr = reqWrapper->req;
|
||||
infRequestPtr->SetUserData(reqWrapper.get(), 0);
|
||||
CV_Assert(infRequestPtr);
|
||||
InferenceEngine::IInferRequest& infRequest = *infRequestPtr.get();
|
||||
infRequest.SetUserData(reqWrapper.get(), 0);
|
||||
#endif
|
||||
|
||||
infRequestPtr->SetCompletionCallback(
|
||||
[](InferenceEngine::IInferRequest::Ptr request, InferenceEngine::StatusCode status)
|
||||
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2021_4)
|
||||
// do NOT capture 'reqWrapper' (smart ptr) in the lambda callback
|
||||
infRequest.SetCompletionCallback<std::function<void(InferenceEngine::InferRequest, InferenceEngine::StatusCode)>>(
|
||||
[wrapperPtr](InferenceEngine::InferRequest /*request*/, InferenceEngine::StatusCode status)
|
||||
#else
|
||||
infRequest.SetCompletionCallback(
|
||||
[](InferenceEngine::IInferRequest::Ptr requestPtr, InferenceEngine::StatusCode status)
|
||||
#endif
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "DNN(nGraph): completionCallback(" << (int)status << ")");
|
||||
#if !INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2021_4)
|
||||
CV_Assert(requestPtr);
|
||||
InferenceEngine::IInferRequest& request = *requestPtr.get();
|
||||
|
||||
NgraphReqWrapper* wrapper;
|
||||
request->GetUserData((void**)&wrapper, 0);
|
||||
CV_Assert(wrapper && "Internal error");
|
||||
NgraphReqWrapper* wrapperPtr;
|
||||
request.GetUserData((void**)&wrapperPtr, 0);
|
||||
CV_Assert(wrapperPtr && "Internal error");
|
||||
#endif
|
||||
NgraphReqWrapper& wrapper = *wrapperPtr;
|
||||
|
||||
size_t processedOutputs = 0;
|
||||
try
|
||||
{
|
||||
for (; processedOutputs < wrapper->outProms.size(); ++processedOutputs)
|
||||
for (; processedOutputs < wrapper.outProms.size(); ++processedOutputs)
|
||||
{
|
||||
const std::string& name = wrapper->outsNames[processedOutputs];
|
||||
Mat m = ngraphBlobToMat(wrapper->req.GetBlob(name));
|
||||
const std::string& name = wrapper.outsNames[processedOutputs];
|
||||
Mat m = ngraphBlobToMat(wrapper.req.GetBlob(name));
|
||||
|
||||
try
|
||||
{
|
||||
CV_Assert(status == InferenceEngine::StatusCode::OK);
|
||||
wrapper->outProms[processedOutputs].setValue(m.clone());
|
||||
wrapper.outProms[processedOutputs].setValue(m.clone());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
try {
|
||||
wrapper->outProms[processedOutputs].setException(std::current_exception());
|
||||
wrapper.outProms[processedOutputs].setException(std::current_exception());
|
||||
} catch(...) {
|
||||
CV_LOG_ERROR(NULL, "DNN: Exception occurred during async inference exception propagation");
|
||||
}
|
||||
@@ -1020,16 +1063,16 @@ void InfEngineNgraphNet::forward(const std::vector<Ptr<BackendWrapper> >& outBlo
|
||||
catch (...)
|
||||
{
|
||||
std::exception_ptr e = std::current_exception();
|
||||
for (; processedOutputs < wrapper->outProms.size(); ++processedOutputs)
|
||||
for (; processedOutputs < wrapper.outProms.size(); ++processedOutputs)
|
||||
{
|
||||
try {
|
||||
wrapper->outProms[processedOutputs].setException(e);
|
||||
wrapper.outProms[processedOutputs].setException(e);
|
||||
} catch(...) {
|
||||
CV_LOG_ERROR(NULL, "DNN: Exception occurred during async inference exception propagation");
|
||||
}
|
||||
}
|
||||
}
|
||||
wrapper->isReady = true;
|
||||
wrapper.isReady = true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace dnn
|
||||
class BatchNormLayerImpl CV_FINAL : public BatchNormLayer
|
||||
{
|
||||
public:
|
||||
Mat origin_weights, origin_bias;
|
||||
Mat weights_, bias_;
|
||||
UMat umat_weight, umat_bias;
|
||||
mutable int dims;
|
||||
@@ -82,11 +83,11 @@ public:
|
||||
const float* weightsData = hasWeights ? blobs[weightsBlobIndex].ptr<float>() : 0;
|
||||
const float* biasData = hasBias ? blobs[biasBlobIndex].ptr<float>() : 0;
|
||||
|
||||
weights_.create(1, (int)n, CV_32F);
|
||||
bias_.create(1, (int)n, CV_32F);
|
||||
origin_weights.create(1, (int)n, CV_32F);
|
||||
origin_bias.create(1, (int)n, CV_32F);
|
||||
|
||||
float* dstWeightsData = weights_.ptr<float>();
|
||||
float* dstBiasData = bias_.ptr<float>();
|
||||
float* dstWeightsData = origin_weights.ptr<float>();
|
||||
float* dstBiasData = origin_bias.ptr<float>();
|
||||
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
{
|
||||
@@ -94,15 +95,12 @@ public:
|
||||
dstWeightsData[i] = w;
|
||||
dstBiasData[i] = (hasBias ? biasData[i] : 0.0f) - w * meanData[i] * varMeanScale;
|
||||
}
|
||||
// We will use blobs to store origin weights and bias to restore them in case of reinitialization.
|
||||
weights_.copyTo(blobs[0].reshape(1, 1));
|
||||
bias_.copyTo(blobs[1].reshape(1, 1));
|
||||
}
|
||||
|
||||
virtual void finalize(InputArrayOfArrays, OutputArrayOfArrays) CV_OVERRIDE
|
||||
{
|
||||
blobs[0].reshape(1, 1).copyTo(weights_);
|
||||
blobs[1].reshape(1, 1).copyTo(bias_);
|
||||
origin_weights.reshape(1, 1).copyTo(weights_);
|
||||
origin_bias.reshape(1, 1).copyTo(bias_);
|
||||
}
|
||||
|
||||
void getScaleShift(Mat& scale, Mat& shift) const CV_OVERRIDE
|
||||
|
||||
@@ -125,7 +125,8 @@ public:
|
||||
auto input = nodes[0].dynamicCast<InfEngineNgraphNode>()->node;
|
||||
auto rois = nodes[1].dynamicCast<InfEngineNgraphNode>()->node;
|
||||
|
||||
std::vector<size_t> dims = rois->get_shape(), offsets(4, 0);
|
||||
auto rois_shape = rois->get_shape();
|
||||
std::vector<int64_t> dims(rois_shape.begin(), rois_shape.end()), offsets(4, 0);
|
||||
offsets[3] = 2;
|
||||
dims[3] = 7;
|
||||
|
||||
@@ -139,7 +140,7 @@ public:
|
||||
lower_bounds, upper_bounds, strides, std::vector<int64_t>{}, std::vector<int64_t>{});
|
||||
|
||||
// Reshape rois from 4D to 2D
|
||||
std::vector<size_t> shapeData = {dims[2], 5};
|
||||
std::vector<int64_t> shapeData = {dims[2], 5};
|
||||
auto shape = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{2}, shapeData.data());
|
||||
auto reshape = std::make_shared<ngraph::op::v1::Reshape>(slice, shape, true);
|
||||
|
||||
|
||||
@@ -328,7 +328,7 @@ public:
|
||||
std::iota(axes_data.begin(), axes_data.end(), 1);
|
||||
}
|
||||
auto axes = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{axes_data.size()}, axes_data);
|
||||
auto norm = std::make_shared<ngraph::op::NormalizeL2>(ieInpNode, axes, epsilon, ngraph::op::EpsMode::ADD);
|
||||
auto norm = std::make_shared<ngraph::op::v0::NormalizeL2>(ieInpNode, axes, epsilon, ngraph::op::EpsMode::ADD);
|
||||
|
||||
CV_Assert(blobs.empty() || numChannels == blobs[0].total());
|
||||
std::vector<size_t> shape(ieInpNode->get_shape().size(), 1);
|
||||
|
||||
@@ -1792,6 +1792,23 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
addConstant(layerParams.name, concatenated[0]);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < node_proto.input_size(); ++i)
|
||||
{
|
||||
if (constBlobs.find(node_proto.input(i)) != constBlobs.end())
|
||||
{
|
||||
LayerParams constParams;
|
||||
constParams.name = node_proto.input(i);
|
||||
constParams.type = "Const";
|
||||
constParams.blobs.push_back(getBlob(node_proto, i));
|
||||
|
||||
opencv_onnx::NodeProto proto;
|
||||
proto.add_output(constParams.name);
|
||||
addLayer(constParams, proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (layer_type == "Resize")
|
||||
{
|
||||
|
||||
@@ -30,10 +30,11 @@
|
||||
#define INF_ENGINE_RELEASE_2021_1 2021010000
|
||||
#define INF_ENGINE_RELEASE_2021_2 2021020000
|
||||
#define INF_ENGINE_RELEASE_2021_3 2021030000
|
||||
#define INF_ENGINE_RELEASE_2021_4 2021040000
|
||||
|
||||
#ifndef INF_ENGINE_RELEASE
|
||||
#warning("IE version have not been provided via command-line. Using 2021.3 by default")
|
||||
#define INF_ENGINE_RELEASE INF_ENGINE_RELEASE_2021_3
|
||||
#warning("IE version have not been provided via command-line. Using 2021.4 by default")
|
||||
#define INF_ENGINE_RELEASE INF_ENGINE_RELEASE_2021_4
|
||||
#endif
|
||||
|
||||
#define INF_ENGINE_VER_MAJOR_GT(ver) (((INF_ENGINE_RELEASE) / 10000) > ((ver) / 10000))
|
||||
|
||||
+1833
-1610
File diff suppressed because it is too large
Load Diff
@@ -196,7 +196,7 @@ TEST_P(DNNTestNetwork, MobileNet_SSD_Caffe)
|
||||
Mat inp = blobFromImage(sample, 1.0f / 127.5, Size(300, 300), Scalar(127.5, 127.5, 127.5), false);
|
||||
float diffScores = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 1.5e-2 : 0.0;
|
||||
float diffSquares = (target == DNN_TARGET_MYRIAD) ? 0.063 : 0.0;
|
||||
float detectionConfThresh = (target == DNN_TARGET_MYRIAD) ? 0.252 : FLT_MIN;
|
||||
float detectionConfThresh = (target == DNN_TARGET_MYRIAD) ? 0.262 : FLT_MIN;
|
||||
processNet("dnn/MobileNetSSD_deploy.caffemodel", "dnn/MobileNetSSD_deploy.prototxt",
|
||||
inp, "detection_out", "", diffScores, diffSquares, detectionConfThresh);
|
||||
expectNoFallbacksFromIE(net);
|
||||
@@ -301,8 +301,8 @@ TEST_P(DNNTestNetwork, OpenPose_pose_coco)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#endif
|
||||
|
||||
const float l1 = (target == DNN_TARGET_MYRIAD) ? 0.0056 : 0.0;
|
||||
const float lInf = (target == DNN_TARGET_MYRIAD) ? 0.072 : 0.0;
|
||||
const float l1 = (target == DNN_TARGET_MYRIAD) ? 0.009 : 0.0;
|
||||
const float lInf = (target == DNN_TARGET_MYRIAD) ? 0.09 : 0.0;
|
||||
processNet("dnn/openpose_pose_coco.caffemodel", "dnn/openpose_pose_coco.prototxt",
|
||||
Size(46, 46), "", "", l1, lInf);
|
||||
expectNoFallbacksFromIE(net);
|
||||
@@ -321,8 +321,8 @@ TEST_P(DNNTestNetwork, OpenPose_pose_mpi)
|
||||
#endif
|
||||
|
||||
// output range: [-0.001, 0.97]
|
||||
const float l1 = (target == DNN_TARGET_MYRIAD) ? 0.012 : 0.0;
|
||||
const float lInf = (target == DNN_TARGET_MYRIAD || target == DNN_TARGET_OPENCL_FP16) ? 0.16 : 0.0;
|
||||
const float l1 = (target == DNN_TARGET_MYRIAD) ? 0.02 : 0.0;
|
||||
const float lInf = (target == DNN_TARGET_MYRIAD || target == DNN_TARGET_OPENCL_FP16) ? 0.2 : 0.0;
|
||||
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi.prototxt",
|
||||
Size(46, 46), "", "", l1, lInf);
|
||||
expectNoFallbacksFromIE(net);
|
||||
|
||||
@@ -288,6 +288,15 @@ TEST_P(DNNTestOpenVINO, models)
|
||||
ASSERT_FALSE(backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) <<
|
||||
"Inference Engine backend is required";
|
||||
|
||||
#if INF_ENGINE_VER_MAJOR_EQ(2021040000)
|
||||
if (targetId == DNN_TARGET_MYRIAD && (
|
||||
modelName == "person-detection-retail-0013" || // ncDeviceOpen:1013 Failed to find booted device after boot
|
||||
modelName == "age-gender-recognition-retail-0013" // ncDeviceOpen:1013 Failed to find booted device after boot
|
||||
)
|
||||
)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#endif
|
||||
|
||||
#if INF_ENGINE_VER_MAJOR_GE(2020020000)
|
||||
if (targetId == DNN_TARGET_MYRIAD && backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
{
|
||||
|
||||
@@ -327,6 +327,7 @@ TEST_P(Test_ONNX_layers, Concatenation)
|
||||
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||
}
|
||||
testONNXModels("concatenation");
|
||||
testONNXModels("concat_const_blobs");
|
||||
}
|
||||
|
||||
TEST_P(Test_ONNX_layers, Eltwise3D)
|
||||
|
||||
@@ -254,9 +254,14 @@ TEST_P(Test_Torch_layers, net_padding)
|
||||
|
||||
TEST_P(Test_Torch_layers, net_non_spatial)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
#if defined(INF_ENGINE_RELEASE) && ( \
|
||||
INF_ENGINE_VER_MAJOR_EQ(2021030000) || \
|
||||
INF_ENGINE_VER_MAJOR_EQ(2021040000) \
|
||||
)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // crash
|
||||
// 2021.3: crash
|
||||
// 2021.4: [ GENERAL_ERROR ] AssertionFailed: !out.networkInputs.empty()
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
|
||||
|
||||
@@ -61,25 +61,11 @@ easily switch between different algorithms solving the same problem. This sectio
|
||||
matching descriptors that are represented as vectors in a multidimensional space. All objects that
|
||||
implement vector descriptor matchers inherit the DescriptorMatcher interface.
|
||||
|
||||
@note
|
||||
- An example explaining keypoint matching can be found at
|
||||
opencv_source_code/samples/cpp/descriptor_extractor_matcher.cpp
|
||||
- An example on descriptor matching evaluation can be found at
|
||||
opencv_source_code/samples/cpp/detector_descriptor_matcher_evaluation.cpp
|
||||
- An example on one to many image matching can be found at
|
||||
opencv_source_code/samples/cpp/matching_to_many_images.cpp
|
||||
|
||||
@defgroup features2d_draw Drawing Function of Keypoints and Matches
|
||||
@defgroup features2d_category Object Categorization
|
||||
|
||||
This section describes approaches based on local 2D features and used to categorize objects.
|
||||
|
||||
@note
|
||||
- A complete Bag-Of-Words sample can be found at
|
||||
opencv_source_code/samples/cpp/bagofwords_classification.cpp
|
||||
- (Python) An example using the features2D framework to perform object categorization can be
|
||||
found at opencv_source_code/samples/python/find_obj.py
|
||||
|
||||
@defgroup feature2d_hal Hardware Acceleration Layer
|
||||
@{
|
||||
@defgroup features2d_hal_interface Interface
|
||||
@@ -90,7 +76,7 @@ This section describes approaches based on local 2D features and used to categor
|
||||
namespace cv
|
||||
{
|
||||
|
||||
//! @addtogroup features2d
|
||||
//! @addtogroup features2d_main
|
||||
//! @{
|
||||
|
||||
// //! writes vector of keypoints to the file storage
|
||||
@@ -241,9 +227,6 @@ the vector descriptor extractors inherit the DescriptorExtractor interface.
|
||||
*/
|
||||
typedef Feature2D DescriptorExtractor;
|
||||
|
||||
//! @addtogroup features2d_main
|
||||
//! @{
|
||||
|
||||
|
||||
/** @brief Class for implementing the wrapper which makes detectors and extractors to be affine invariant,
|
||||
described as ASIFT in @cite YM11 .
|
||||
@@ -477,20 +460,20 @@ class CV_EXPORTS_W MSER : public Feature2D
|
||||
public:
|
||||
/** @brief Full constructor for %MSER detector
|
||||
|
||||
@param _delta it compares \f$(size_{i}-size_{i-delta})/size_{i-delta}\f$
|
||||
@param _min_area prune the area which smaller than minArea
|
||||
@param _max_area prune the area which bigger than maxArea
|
||||
@param _max_variation prune the area have similar size to its children
|
||||
@param _min_diversity for color image, trace back to cut off mser with diversity less than min_diversity
|
||||
@param _max_evolution for color image, the evolution steps
|
||||
@param _area_threshold for color image, the area threshold to cause re-initialize
|
||||
@param _min_margin for color image, ignore too small margin
|
||||
@param _edge_blur_size for color image, the aperture size for edge blur
|
||||
@param delta it compares \f$(size_{i}-size_{i-delta})/size_{i-delta}\f$
|
||||
@param min_area prune the area which smaller than minArea
|
||||
@param max_area prune the area which bigger than maxArea
|
||||
@param max_variation prune the area have similar size to its children
|
||||
@param min_diversity for color image, trace back to cut off mser with diversity less than min_diversity
|
||||
@param max_evolution for color image, the evolution steps
|
||||
@param area_threshold for color image, the area threshold to cause re-initialize
|
||||
@param min_margin for color image, ignore too small margin
|
||||
@param edge_blur_size for color image, the aperture size for edge blur
|
||||
*/
|
||||
CV_WRAP static Ptr<MSER> create( int _delta=5, int _min_area=60, int _max_area=14400,
|
||||
double _max_variation=0.25, double _min_diversity=.2,
|
||||
int _max_evolution=200, double _area_threshold=1.01,
|
||||
double _min_margin=0.003, int _edge_blur_size=5 );
|
||||
CV_WRAP static Ptr<MSER> create( int delta=5, int min_area=60, int max_area=14400,
|
||||
double max_variation=0.25, double min_diversity=.2,
|
||||
int max_evolution=200, double area_threshold=1.01,
|
||||
double min_margin=0.003, int edge_blur_size=5 );
|
||||
|
||||
/** @brief Detect %MSER regions
|
||||
|
||||
@@ -1331,6 +1314,13 @@ CV_EXPORTS_W void drawMatches( InputArray img1, const std::vector<KeyPoint>& key
|
||||
const std::vector<char>& matchesMask=std::vector<char>(), int flags=DrawMatchesFlags::DEFAULT );
|
||||
|
||||
/** @overload */
|
||||
CV_EXPORTS_W void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
InputArray img2, const std::vector<KeyPoint>& keypoints2,
|
||||
const std::vector<DMatch>& matches1to2, InputOutputArray outImg,
|
||||
const int matchesThickness, const Scalar& matchColor=Scalar::all(-1),
|
||||
const Scalar& singlePointColor=Scalar::all(-1), const std::vector<char>& matchesMask=std::vector<char>(),
|
||||
int flags=DrawMatchesFlags::DEFAULT );
|
||||
|
||||
CV_EXPORTS_AS(drawMatchesKnn) void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
InputArray img2, const std::vector<KeyPoint>& keypoints2,
|
||||
const std::vector<std::vector<DMatch> >& matches1to2, InputOutputArray outImg,
|
||||
|
||||
@@ -325,13 +325,19 @@ void SimpleBlobDetectorImpl::detect(InputArray image, std::vector<cv::KeyPoint>&
|
||||
|
||||
std::vector < Center > curCenters;
|
||||
findBlobs(grayscaleImage, binarizedImage, curCenters);
|
||||
if(params.maxThreshold - params.minThreshold <= params.thresholdStep) {
|
||||
// if the difference between min and max threshold is less than the threshold step
|
||||
// we're only going to enter the loop once, so we need to add curCenters
|
||||
// to ensure we still use minDistBetweenBlobs
|
||||
centers.push_back(curCenters);
|
||||
}
|
||||
std::vector < std::vector<Center> > newCenters;
|
||||
for (size_t i = 0; i < curCenters.size(); i++)
|
||||
{
|
||||
bool isNew = true;
|
||||
for (size_t j = 0; j < centers.size(); j++)
|
||||
{
|
||||
double dist = norm(centers[j][ centers[j].size() / 2 ].location - curCenters[i].location);
|
||||
double dist = norm(centers[j][centers[j].size() / 2 ].location - curCenters[i].location);
|
||||
isNew = dist >= params.minDistBetweenBlobs && dist >= centers[j][ centers[j].size() / 2 ].radius && dist >= curCenters[i].radius;
|
||||
if (!isNew)
|
||||
{
|
||||
|
||||
@@ -183,7 +183,8 @@ static void _prepareImgAndDrawKeypoints( InputArray img1, const std::vector<KeyP
|
||||
}
|
||||
|
||||
static inline void _drawMatch( InputOutputArray outImg, InputOutputArray outImg1, InputOutputArray outImg2 ,
|
||||
const KeyPoint& kp1, const KeyPoint& kp2, const Scalar& matchColor, int flags )
|
||||
const KeyPoint& kp1, const KeyPoint& kp2, const Scalar& matchColor, int flags,
|
||||
const int matchesThickness )
|
||||
{
|
||||
RNG& rng = theRNG();
|
||||
bool isRandMatchColor = matchColor == Scalar::all(-1);
|
||||
@@ -199,7 +200,7 @@ static inline void _drawMatch( InputOutputArray outImg, InputOutputArray outImg1
|
||||
line( outImg,
|
||||
Point(cvRound(pt1.x*draw_multiplier), cvRound(pt1.y*draw_multiplier)),
|
||||
Point(cvRound(dpt2.x*draw_multiplier), cvRound(dpt2.y*draw_multiplier)),
|
||||
color, 1, LINE_AA, draw_shift_bits );
|
||||
color, matchesThickness, LINE_AA, draw_shift_bits );
|
||||
}
|
||||
|
||||
void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
@@ -207,6 +208,21 @@ void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
const std::vector<DMatch>& matches1to2, InputOutputArray outImg,
|
||||
const Scalar& matchColor, const Scalar& singlePointColor,
|
||||
const std::vector<char>& matchesMask, int flags )
|
||||
{
|
||||
drawMatches( img1, keypoints1,
|
||||
img2, keypoints2,
|
||||
matches1to2, outImg,
|
||||
1, matchColor,
|
||||
singlePointColor, matchesMask,
|
||||
flags);
|
||||
}
|
||||
|
||||
void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
InputArray img2, const std::vector<KeyPoint>& keypoints2,
|
||||
const std::vector<DMatch>& matches1to2, InputOutputArray outImg,
|
||||
const int matchesThickness, const Scalar& matchColor,
|
||||
const Scalar& singlePointColor, const std::vector<char>& matchesMask,
|
||||
int flags )
|
||||
{
|
||||
if( !matchesMask.empty() && matchesMask.size() != matches1to2.size() )
|
||||
CV_Error( Error::StsBadSize, "matchesMask must have the same size as matches1to2" );
|
||||
@@ -226,11 +242,12 @@ void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
CV_Assert(i2 >= 0 && i2 < static_cast<int>(keypoints2.size()));
|
||||
|
||||
const KeyPoint &kp1 = keypoints1[i1], &kp2 = keypoints2[i2];
|
||||
_drawMatch( outImg, outImg1, outImg2, kp1, kp2, matchColor, flags );
|
||||
_drawMatch( outImg, outImg1, outImg2, kp1, kp2, matchColor, flags, matchesThickness );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
InputArray img2, const std::vector<KeyPoint>& keypoints2,
|
||||
const std::vector<std::vector<DMatch> >& matches1to2, InputOutputArray outImg,
|
||||
@@ -254,7 +271,7 @@ void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
if( matchesMask.empty() || matchesMask[i][j] )
|
||||
{
|
||||
const KeyPoint &kp1 = keypoints1[i1], &kp2 = keypoints2[i2];
|
||||
_drawMatch( outImg, outImg1, outImg2, kp1, kp2, matchColor, flags );
|
||||
_drawMatch( outImg, outImg1, outImg2, kp1, kp2, matchColor, flags, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
TEST(Features2d_BlobDetector, bug_6667)
|
||||
{
|
||||
cv::Mat image = cv::Mat(cv::Size(100, 100), CV_8UC1, cv::Scalar(255, 255, 255));
|
||||
cv::circle(image, Point(50, 50), 20, cv::Scalar(0), -1);
|
||||
SimpleBlobDetector::Params params;
|
||||
params.minThreshold = 250;
|
||||
params.maxThreshold = 260;
|
||||
std::vector<KeyPoint> keypoints;
|
||||
|
||||
Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);
|
||||
detector->detect(image, keypoints);
|
||||
ASSERT_NE((int) keypoints.size(), 0);
|
||||
}
|
||||
}} // namespace
|
||||
@@ -167,17 +167,15 @@ class SinglePolicy
|
||||
|
||||
public:
|
||||
static base_any_policy* get_policy();
|
||||
|
||||
private:
|
||||
static typename choose_policy<T>::type policy;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
typename choose_policy<T>::type SinglePolicy<T>::policy;
|
||||
|
||||
/// This function will return a different policy for each type.
|
||||
template <typename T>
|
||||
inline base_any_policy* SinglePolicy<T>::get_policy() { return &policy; }
|
||||
inline base_any_policy* SinglePolicy<T>::get_policy()
|
||||
{
|
||||
static typename choose_policy<T>::type policy;
|
||||
return &policy;
|
||||
}
|
||||
|
||||
} // namespace anyimpl
|
||||
|
||||
|
||||
@@ -1219,9 +1219,6 @@ void GuiReceiver::addSlider2(QString bar_name, QString window_name, void* value,
|
||||
if (t) //trackbar exists
|
||||
return;
|
||||
|
||||
if (!value)
|
||||
CV_Error(CV_StsNullPtr, "NULL value pointer" );
|
||||
|
||||
if (count <= 0) //count is the max value of the slider, so must be bigger than 0
|
||||
CV_Error(CV_StsNullPtr, "Max value of the slider must be bigger than 0" );
|
||||
|
||||
@@ -1342,7 +1339,8 @@ void CvTrackbar::create(CvWindow* arg, QString name, int* value, int _count)
|
||||
slider->setMinimum(0);
|
||||
slider->setMaximum(_count);
|
||||
slider->setPageStep(5);
|
||||
slider->setValue(*value);
|
||||
if (dataSlider)
|
||||
slider->setValue(*dataSlider);
|
||||
slider->setTickPosition(QSlider::TicksBelow);
|
||||
|
||||
|
||||
@@ -1409,7 +1407,8 @@ void CvTrackbar::update(int myvalue)
|
||||
{
|
||||
setLabel(myvalue);
|
||||
|
||||
*dataSlider = myvalue;
|
||||
if (dataSlider)
|
||||
*dataSlider = myvalue;
|
||||
if (callback)
|
||||
{
|
||||
callback(myvalue);
|
||||
|
||||
@@ -1771,24 +1771,26 @@ static gboolean icvOnClose( GtkWidget* widget, GdkEvent* /*event*/, gpointer use
|
||||
static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_data )
|
||||
{
|
||||
// TODO move this logic to CvImageWidget
|
||||
// TODO add try-catch wrappers into all callbacks
|
||||
CvWindow* window = (CvWindow*)user_data;
|
||||
if (!window || !widget ||
|
||||
window->signature != CV_WINDOW_MAGIC_VAL ||
|
||||
window->widget != widget ||
|
||||
!window->on_mouse)
|
||||
return FALSE;
|
||||
|
||||
CvPoint2D32f pt32f = {-1., -1.};
|
||||
CvPoint pt = {-1,-1};
|
||||
int cv_event = -1, state = 0, flags = 0;
|
||||
CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
|
||||
|
||||
if( window->signature != CV_WINDOW_MAGIC_VAL ||
|
||||
window->widget != widget || !window->widget ||
|
||||
!window->on_mouse /*|| !image_widget->original_image*/)
|
||||
return FALSE;
|
||||
|
||||
if( event->type == GDK_MOTION_NOTIFY )
|
||||
{
|
||||
GdkEventMotion* event_motion = (GdkEventMotion*)event;
|
||||
|
||||
cv_event = CV_EVENT_MOUSEMOVE;
|
||||
pt32f.x = cvRound(event_motion->x);
|
||||
pt32f.y = cvRound(event_motion->y);
|
||||
pt32f.x = cvFloor(event_motion->x);
|
||||
pt32f.y = cvFloor(event_motion->y);
|
||||
state = event_motion->state;
|
||||
}
|
||||
else if( event->type == GDK_BUTTON_PRESS ||
|
||||
@@ -1796,8 +1798,8 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da
|
||||
event->type == GDK_2BUTTON_PRESS )
|
||||
{
|
||||
GdkEventButton* event_button = (GdkEventButton*)event;
|
||||
pt32f.x = cvRound(event_button->x);
|
||||
pt32f.y = cvRound(event_button->y);
|
||||
pt32f.x = cvFloor(event_button->x);
|
||||
pt32f.y = cvFloor(event_button->y);
|
||||
|
||||
|
||||
if( event_button->type == GDK_BUTTON_PRESS )
|
||||
@@ -1874,9 +1876,12 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da
|
||||
pt = cvPointFrom32f( pt32f );
|
||||
}
|
||||
|
||||
// if((unsigned)pt.x < (unsigned)(image_widget->original_image->width) &&
|
||||
// (unsigned)pt.y < (unsigned)(image_widget->original_image->height) )
|
||||
if (!image_widget->original_image/*OpenGL*/ || (
|
||||
(unsigned)pt.x < (unsigned)(image_widget->original_image->width) &&
|
||||
(unsigned)pt.y < (unsigned)(image_widget->original_image->height)
|
||||
))
|
||||
{
|
||||
state &= gtk_accelerator_get_default_mod_mask();
|
||||
flags |= BIT_MAP(state, GDK_SHIFT_MASK, CV_EVENT_FLAG_SHIFTKEY) |
|
||||
BIT_MAP(state, GDK_CONTROL_MASK, CV_EVENT_FLAG_CTRLKEY) |
|
||||
BIT_MAP(state, GDK_MOD1_MASK, CV_EVENT_FLAG_ALTKEY) |
|
||||
|
||||
@@ -271,7 +271,7 @@ void CvWindow::createSlider(cv::String name, int* val, int count, CvTrackbarCall
|
||||
// Image control is loaded. See callback implementation in CvWindow ctor.
|
||||
slider->Width = sliderDefaultWidth;
|
||||
}
|
||||
slider->Value = *val;
|
||||
slider->Value = val ? *val : 0;
|
||||
slider->Maximum = count;
|
||||
slider->Visibility = Windows::UI::Xaml::Visibility::Visible;
|
||||
slider->Margin = Windows::UI::Xaml::ThicknessHelper::FromLengths(10, 10, 10, 0);
|
||||
|
||||
@@ -212,6 +212,8 @@ can be saved using this function, with these exceptions:
|
||||
should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535 (see the code sample below).
|
||||
- Multiple images (vector of Mat) can be saved in TIFF format (see the code sample below).
|
||||
|
||||
If the image format is not supported, the image will be converted to 8-bit unsigned (CV_8U) and saved that way.
|
||||
|
||||
If the format, depth or channel order is different, use
|
||||
Mat::convertTo and cv::cvtColor to convert it before saving. Or, use the universal FileStorage I/O
|
||||
functions to save the image to XML or YAML format.
|
||||
|
||||
@@ -156,6 +156,10 @@ bool ExrDecoder::readHeader()
|
||||
else
|
||||
{
|
||||
m_green = channels.findChannel( "Y" );
|
||||
if( !m_green )
|
||||
{
|
||||
m_green = channels.findChannel( "Z" ); // Distance of the front of a sample from the viewer
|
||||
}
|
||||
if( m_green )
|
||||
{
|
||||
m_ischroma = true;
|
||||
|
||||
@@ -1181,7 +1181,7 @@ protected:
|
||||
struct CV_EXPORTS Vertex
|
||||
{
|
||||
Vertex();
|
||||
Vertex(Point2f pt, bool _isvirtual, int _firstEdge=0);
|
||||
Vertex(Point2f pt, bool isvirtual, int firstEdge=0);
|
||||
bool isvirtual() const;
|
||||
bool isfree() const;
|
||||
|
||||
@@ -1237,9 +1237,9 @@ public:
|
||||
|
||||

|
||||
|
||||
@param _image A grayscale (CV_8UC1) input image. If only a roi needs to be selected, use:
|
||||
@param image A grayscale (CV_8UC1) input image. If only a roi needs to be selected, use:
|
||||
`lsd_ptr-\>detect(image(roi), lines, ...); lines += Scalar(roi.x, roi.y, roi.x, roi.y);`
|
||||
@param _lines A vector of Vec4i or Vec4f elements specifying the beginning and ending point of a line. Where
|
||||
@param lines A vector of Vec4i or Vec4f elements specifying the beginning and ending point of a line. Where
|
||||
Vec4i/Vec4f is (x1, y1, x2, y2), point 1 is the start, point 2 - end. Returned lines are strictly
|
||||
oriented depending on the gradient.
|
||||
@param width Vector of widths of the regions, where the lines are found. E.g. Width of line.
|
||||
@@ -1251,26 +1251,26 @@ public:
|
||||
- 1 corresponds to 0.1 mean false alarms
|
||||
This vector will be calculated only when the objects type is #LSD_REFINE_ADV.
|
||||
*/
|
||||
CV_WRAP virtual void detect(InputArray _image, OutputArray _lines,
|
||||
CV_WRAP virtual void detect(InputArray image, OutputArray lines,
|
||||
OutputArray width = noArray(), OutputArray prec = noArray(),
|
||||
OutputArray nfa = noArray()) = 0;
|
||||
|
||||
/** @brief Draws the line segments on a given image.
|
||||
@param _image The image, where the lines will be drawn. Should be bigger or equal to the image,
|
||||
@param image The image, where the lines will be drawn. Should be bigger or equal to the image,
|
||||
where the lines were found.
|
||||
@param lines A vector of the lines that needed to be drawn.
|
||||
*/
|
||||
CV_WRAP virtual void drawSegments(InputOutputArray _image, InputArray lines) = 0;
|
||||
CV_WRAP virtual void drawSegments(InputOutputArray image, InputArray lines) = 0;
|
||||
|
||||
/** @brief Draws two groups of lines in blue and red, counting the non overlapping (mismatching) pixels.
|
||||
|
||||
@param size The size of the image, where lines1 and lines2 were found.
|
||||
@param lines1 The first group of lines that needs to be drawn. It is visualized in blue color.
|
||||
@param lines2 The second group of lines. They visualized in red color.
|
||||
@param _image Optional image, where the lines will be drawn. The image should be color(3-channel)
|
||||
@param image Optional image, where the lines will be drawn. The image should be color(3-channel)
|
||||
in order for lines1 and lines2 to be drawn in the above mentioned colors.
|
||||
*/
|
||||
CV_WRAP virtual int compareSegments(const Size& size, InputArray lines1, InputArray lines2, InputOutputArray _image = noArray()) = 0;
|
||||
CV_WRAP virtual int compareSegments(const Size& size, InputArray lines1, InputArray lines2, InputOutputArray image = noArray()) = 0;
|
||||
|
||||
virtual ~LineSegmentDetector() { }
|
||||
};
|
||||
@@ -1280,22 +1280,21 @@ public:
|
||||
The LineSegmentDetector algorithm is defined using the standard values. Only advanced users may want
|
||||
to edit those, as to tailor it for their own application.
|
||||
|
||||
@param _refine The way found lines will be refined, see #LineSegmentDetectorModes
|
||||
@param _scale The scale of the image that will be used to find the lines. Range (0..1].
|
||||
@param _sigma_scale Sigma for Gaussian filter. It is computed as sigma = _sigma_scale/_scale.
|
||||
@param _quant Bound to the quantization error on the gradient norm.
|
||||
@param _ang_th Gradient angle tolerance in degrees.
|
||||
@param _log_eps Detection threshold: -log10(NFA) \> log_eps. Used only when advance refinement
|
||||
is chosen.
|
||||
@param _density_th Minimal density of aligned region points in the enclosing rectangle.
|
||||
@param _n_bins Number of bins in pseudo-ordering of gradient modulus.
|
||||
@param refine The way found lines will be refined, see #LineSegmentDetectorModes
|
||||
@param scale The scale of the image that will be used to find the lines. Range (0..1].
|
||||
@param sigma_scale Sigma for Gaussian filter. It is computed as sigma = sigma_scale/scale.
|
||||
@param quant Bound to the quantization error on the gradient norm.
|
||||
@param ang_th Gradient angle tolerance in degrees.
|
||||
@param log_eps Detection threshold: -log10(NFA) \> log_eps. Used only when advance refinement is chosen.
|
||||
@param density_th Minimal density of aligned region points in the enclosing rectangle.
|
||||
@param n_bins Number of bins in pseudo-ordering of gradient modulus.
|
||||
|
||||
@note Implementation has been removed due original code license conflict
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<LineSegmentDetector> createLineSegmentDetector(
|
||||
int _refine = LSD_REFINE_STD, double _scale = 0.8,
|
||||
double _sigma_scale = 0.6, double _quant = 2.0, double _ang_th = 22.5,
|
||||
double _log_eps = 0, double _density_th = 0.7, int _n_bins = 1024);
|
||||
int refine = LSD_REFINE_STD, double scale = 0.8,
|
||||
double sigma_scale = 0.6, double quant = 2.0, double ang_th = 22.5,
|
||||
double log_eps = 0, double density_th = 0.7, int n_bins = 1024);
|
||||
|
||||
//! @} imgproc_feature
|
||||
|
||||
@@ -1494,7 +1493,7 @@ The unnormalized square box filter can be useful in computing local image statis
|
||||
variance and standard deviation around the neighborhood of a pixel.
|
||||
|
||||
@param src input image
|
||||
@param dst output image of the same size and type as _src
|
||||
@param dst output image of the same size and type as src
|
||||
@param ddepth the output image depth (-1 to use src.depth())
|
||||
@param ksize kernel size
|
||||
@param anchor kernel anchor point. The default value of Point(-1, -1) denotes that the anchor is at the kernel
|
||||
@@ -2036,8 +2035,8 @@ CV_EXPORTS_W void HoughLinesP( InputArray image, OutputArray lines,
|
||||
|
||||
The function finds lines in a set of points using a modification of the Hough transform.
|
||||
@include snippets/imgproc_HoughLinesPointSet.cpp
|
||||
@param _point Input vector of points. Each vector must be encoded as a Point vector \f$(x,y)\f$. Type must be CV_32FC2 or CV_32SC2.
|
||||
@param _lines Output vector of found lines. Each vector is encoded as a vector<Vec3d> \f$(votes, rho, theta)\f$.
|
||||
@param point Input vector of points. Each vector must be encoded as a Point vector \f$(x,y)\f$. Type must be CV_32FC2 or CV_32SC2.
|
||||
@param lines Output vector of found lines. Each vector is encoded as a vector<Vec3d> \f$(votes, rho, theta)\f$.
|
||||
The larger the value of 'votes', the higher the reliability of the Hough line.
|
||||
@param lines_max Max count of hough lines.
|
||||
@param threshold Accumulator threshold parameter. Only those lines are returned that get enough
|
||||
@@ -2049,7 +2048,7 @@ votes ( \f$>\texttt{threshold}\f$ )
|
||||
@param max_theta Maximum angle value of the accumulator in radians.
|
||||
@param theta_step Angle resolution of the accumulator in radians.
|
||||
*/
|
||||
CV_EXPORTS_W void HoughLinesPointSet( InputArray _point, OutputArray _lines, int lines_max, int threshold,
|
||||
CV_EXPORTS_W void HoughLinesPointSet( InputArray point, OutputArray lines, int lines_max, int threshold,
|
||||
double min_rho, double max_rho, double rho_step,
|
||||
double min_theta, double max_theta, double theta_step );
|
||||
|
||||
@@ -2836,6 +2835,22 @@ An example is shown below:
|
||||
*/
|
||||
CV_EXPORTS_W void createHanningWindow(OutputArray dst, Size winSize, int type);
|
||||
|
||||
/** @brief Performs the per-element division of the first Fourier spectrum by the second Fourier spectrum.
|
||||
|
||||
The function cv::divSpectrums performs the per-element division of the first array by the second array.
|
||||
The arrays are CCS-packed or complex matrices that are results of a real or complex Fourier transform.
|
||||
|
||||
@param a first input array.
|
||||
@param b second input array of the same size and type as src1 .
|
||||
@param c output array of the same size and type as src1 .
|
||||
@param flags operation flags; currently, the only supported flag is cv::DFT_ROWS, which indicates that
|
||||
each row of src1 and src2 is an independent 1D Fourier spectrum. If you do not want to use this flag, then simply add a `0` as value.
|
||||
@param conjB optional flag that conjugates the second input array before the multiplication (true)
|
||||
or not (false).
|
||||
*/
|
||||
CV_EXPORTS_W void divSpectrums(InputArray a, InputArray b, OutputArray c,
|
||||
int flags, bool conjB = false);
|
||||
|
||||
//! @} imgproc_motion
|
||||
|
||||
//! @addtogroup imgproc_misc
|
||||
@@ -4163,9 +4178,9 @@ Examples of how intersectConvexConvex works
|
||||
|
||||
/** @brief Finds intersection of two convex polygons
|
||||
|
||||
@param _p1 First polygon
|
||||
@param _p2 Second polygon
|
||||
@param _p12 Output polygon describing the intersecting area
|
||||
@param p1 First polygon
|
||||
@param p2 Second polygon
|
||||
@param p12 Output polygon describing the intersecting area
|
||||
@param handleNested When true, an intersection is found if one of the polygons is fully enclosed in the other.
|
||||
When false, no intersection is found. If the polygons share a side or the vertex of one polygon lies on an edge
|
||||
of the other, they are not considered nested and an intersection will be found regardless of the value of handleNested.
|
||||
@@ -4174,8 +4189,8 @@ of the other, they are not considered nested and an intersection will be found r
|
||||
|
||||
@note intersectConvexConvex doesn't confirm that both polygons are convex and will return invalid results if they aren't.
|
||||
*/
|
||||
CV_EXPORTS_W float intersectConvexConvex( InputArray _p1, InputArray _p2,
|
||||
OutputArray _p12, bool handleNested = true );
|
||||
CV_EXPORTS_W float intersectConvexConvex( InputArray p1, InputArray p2,
|
||||
OutputArray p12, bool handleNested = true );
|
||||
|
||||
/** @example samples/cpp/fitellipse.cpp
|
||||
An example using the fitEllipse technique
|
||||
|
||||
@@ -166,7 +166,17 @@ OCL_PERF_TEST_P(CornerMinEigenValFixture, CornerMinEigenVal,
|
||||
|
||||
OCL_TEST_CYCLE() cv::cornerMinEigenVal(src, dst, blockSize, apertureSize, borderType);
|
||||
|
||||
SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE);
|
||||
#ifdef HAVE_OPENCL
|
||||
bool strictCheck = !ocl::useOpenCL() || ocl::Device::getDefault().isIntel();
|
||||
#else
|
||||
bool strictCheck = true;
|
||||
#endif
|
||||
|
||||
// using native_* OpenCL functions on non-intel devices may lose accuracy
|
||||
if (strictCheck)
|
||||
SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE);
|
||||
else
|
||||
SANITY_CHECK(dst, 0.1, ERROR_RELATIVE);
|
||||
}
|
||||
|
||||
///////////// CornerHarris ////////////////////////
|
||||
|
||||
@@ -1536,6 +1536,8 @@ static inline void trilinearPackedInterpolate(const v_uint16& inX, const v_uint1
|
||||
#endif // CV_SIMD
|
||||
|
||||
|
||||
|
||||
|
||||
struct RGB2Lab_b
|
||||
{
|
||||
typedef uchar channel_type;
|
||||
@@ -1571,6 +1573,69 @@ struct RGB2Lab_b
|
||||
}
|
||||
}
|
||||
|
||||
#if CV_NEON
|
||||
template <int n>
|
||||
inline void rgb2lab_batch(const ushort* tab,
|
||||
const v_uint8 vRi, const v_uint8 vGi, const v_uint8 vBi,
|
||||
v_int32& vL, v_int32& va, v_int32& vb) const
|
||||
{
|
||||
// Define some scalar constants which we will make use of later
|
||||
const int Lscale = (116*255+50)/100;
|
||||
const int Lshift = -((16*255*(1 << lab_shift2) + 50)/100);
|
||||
const int xyzDescaleShift = (1 << (lab_shift - 1));
|
||||
const int labDescaleShift = (1 << (lab_shift2 - 1));
|
||||
const int abShift = 128*(1 << lab_shift2);
|
||||
|
||||
const int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
|
||||
C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
|
||||
C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
|
||||
|
||||
// int R = tab[src[0]], G = tab[src[1]], B = tab[src[2]];
|
||||
v_int32 vR(tab[v_extract_n<4*n+0>(vRi)], tab[v_extract_n<4*n+1>(vRi)],
|
||||
tab[v_extract_n<4*n+2>(vRi)], tab[v_extract_n<4*n+3>(vRi)]);
|
||||
v_int32 vG(tab[v_extract_n<4*n+0>(vGi)], tab[v_extract_n<4*n+1>(vGi)],
|
||||
tab[v_extract_n<4*n+2>(vGi)], tab[v_extract_n<4*n+3>(vGi)]);
|
||||
v_int32 vB(tab[v_extract_n<4*n+0>(vBi)], tab[v_extract_n<4*n+1>(vBi)],
|
||||
tab[v_extract_n<4*n+2>(vBi)], tab[v_extract_n<4*n+3>(vBi)]);
|
||||
|
||||
/* int fX = LabCbrtTab_b[CV_DESCALE(R*C0 + G*C1 + B*C2, lab_shift)];*/
|
||||
v_int32 vfX = v_fma(vR, v_setall_s32(C0), v_setall_s32(xyzDescaleShift));
|
||||
vfX = v_fma(vG, v_setall_s32(C1), vfX);
|
||||
vfX = v_fma(vB, v_setall_s32(C2), vfX);
|
||||
vfX = v_shr<lab_shift>(vfX);
|
||||
vfX = v_int32(LabCbrtTab_b[v_extract_n<0>(vfX)], LabCbrtTab_b[v_extract_n<1>(vfX)],
|
||||
LabCbrtTab_b[v_extract_n<2>(vfX)], LabCbrtTab_b[v_extract_n<3>(vfX)]);
|
||||
|
||||
/* int fY = LabCbrtTab_b[CV_DESCALE(R*C3 + G*C4 + B*C5, lab_shift)]; */
|
||||
v_int32 vfY = v_fma(vR, v_setall_s32(C3), v_setall_s32(xyzDescaleShift));
|
||||
vfY = v_fma(vG, v_setall_s32(C4), vfY);
|
||||
vfY = v_fma(vB, v_setall_s32(C5), vfY);
|
||||
vfY = v_shr<lab_shift>(vfY);
|
||||
vfY = v_int32(LabCbrtTab_b[v_extract_n<0>(vfY)], LabCbrtTab_b[v_extract_n<1>(vfY)],
|
||||
LabCbrtTab_b[v_extract_n<2>(vfY)], LabCbrtTab_b[v_extract_n<3>(vfY)]);
|
||||
|
||||
/* int fZ = LabCbrtTab_b[CV_DESCALE(R*C6 + G*C7 + B*C8, lab_shift)];*/
|
||||
v_int32 vfZ = v_fma(vR, v_setall_s32(C6), v_setall_s32(xyzDescaleShift));
|
||||
vfZ = v_fma(vG, v_setall_s32(C7), vfZ);
|
||||
vfZ = v_fma(vB, v_setall_s32(C8), vfZ);
|
||||
vfZ = v_shr<lab_shift>(vfZ);
|
||||
vfZ = v_int32(LabCbrtTab_b[v_extract_n<0>(vfZ)], LabCbrtTab_b[v_extract_n<1>(vfZ)],
|
||||
LabCbrtTab_b[v_extract_n<2>(vfZ)], LabCbrtTab_b[v_extract_n<3>(vfZ)]);
|
||||
|
||||
/* int L = CV_DESCALE( Lscale*fY + Lshift, lab_shift2 );*/
|
||||
vL = v_fma(vfY, v_setall_s32(Lscale), v_setall_s32(Lshift+labDescaleShift));
|
||||
vL = v_shr<lab_shift2>(vL);
|
||||
|
||||
/* int a = CV_DESCALE( 500*(fX - fY) + 128*(1 << lab_shift2), lab_shift2 );*/
|
||||
va = v_fma(vfX - vfY, v_setall_s32(500), v_setall_s32(abShift+labDescaleShift));
|
||||
va = v_shr<lab_shift2>(va);
|
||||
|
||||
/* int b = CV_DESCALE( 200*(fY - fZ) + 128*(1 << lab_shift2), lab_shift2 );*/
|
||||
vb = v_fma(vfY - vfZ, v_setall_s32(200), v_setall_s32(abShift+labDescaleShift));
|
||||
vb = v_shr<lab_shift2>(vb);
|
||||
}
|
||||
#endif // CV_NEON
|
||||
|
||||
void operator()(const uchar* src, uchar* dst, int n) const
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
@@ -1585,6 +1650,45 @@ struct RGB2Lab_b
|
||||
|
||||
i = 0;
|
||||
|
||||
#if CV_NEON
|
||||
// On each loop, we load nlanes of RGB/A v_uint8s and store nlanes of
|
||||
// Lab v_uint8s
|
||||
for(; i <= n - v_uint8::nlanes; i += v_uint8::nlanes,
|
||||
src += scn*v_uint8::nlanes, dst += 3*v_uint8::nlanes )
|
||||
{
|
||||
// Load 4 batches of 4 src
|
||||
v_uint8 vRi, vGi, vBi;
|
||||
if(scn == 4)
|
||||
{
|
||||
v_uint8 vAi;
|
||||
v_load_deinterleave(src, vRi, vGi, vBi, vAi);
|
||||
}
|
||||
else // scn == 3
|
||||
{
|
||||
v_load_deinterleave(src, vRi, vGi, vBi);
|
||||
}
|
||||
|
||||
// Do 4 batches of 4 RGB2Labs
|
||||
v_int32 vL0, va0, vb0;
|
||||
rgb2lab_batch<0>(tab, vRi, vGi, vBi, vL0, va0, vb0);
|
||||
v_int32 vL1, va1, vb1;
|
||||
rgb2lab_batch<1>(tab, vRi, vGi, vBi, vL1, va1, vb1);
|
||||
v_int32 vL2, va2, vb2;
|
||||
rgb2lab_batch<2>(tab, vRi, vGi, vBi, vL2, va2, vb2);
|
||||
v_int32 vL3, va3, vb3;
|
||||
rgb2lab_batch<3>(tab, vRi, vGi, vBi, vL3, va3, vb3);
|
||||
|
||||
// Saturate, combine and store all batches
|
||||
// dst[0] = saturate_cast<uchar>(L);
|
||||
// dst[1] = saturate_cast<uchar>(a);
|
||||
// dst[2] = saturate_cast<uchar>(b);
|
||||
v_store_interleave(dst,
|
||||
v_pack(v_pack_u(vL0, vL1), v_pack_u(vL2, vL3)),
|
||||
v_pack(v_pack_u(va0, va1), v_pack_u(va2, va3)),
|
||||
v_pack(v_pack_u(vb0, vb1), v_pack_u(vb2, vb3)));
|
||||
}
|
||||
#endif // CV_NEON
|
||||
|
||||
#if CV_SIMD
|
||||
const int vsize = v_uint8::nlanes;
|
||||
const int xyzDescaleShift = 1 << (lab_shift - 1);
|
||||
|
||||
@@ -625,7 +625,8 @@ icvFetchContour( schar *ptr,
|
||||
|
||||
/*
|
||||
trace contour until certain point is met.
|
||||
returns 1 if met, 0 else.
|
||||
returns 1 if met and this is the last contour
|
||||
encountered by a raster scan reaching the point, 0 else.
|
||||
*/
|
||||
static int
|
||||
icvTraceContour( schar *ptr, int step, schar *stop_ptr, int is_hole )
|
||||
@@ -668,14 +669,39 @@ icvTraceContour( schar *ptr, int step, schar *stop_ptr, int is_hole )
|
||||
break;
|
||||
}
|
||||
|
||||
if( i3 == stop_ptr || (i4 == i0 && i3 == i1) )
|
||||
if (i3 == stop_ptr) {
|
||||
if (!(*i3 & 0x80)) {
|
||||
/* it's the only contour */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* check if this is the last contour */
|
||||
/* encountered during a raster scan */
|
||||
schar *i5;
|
||||
int t = s;
|
||||
while (true)
|
||||
{
|
||||
t = (t - 1) & 7;
|
||||
i5 = i3 + deltas[t];
|
||||
if (*i5 != 0)
|
||||
break;
|
||||
if (t == 0)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( (i4 == i0 && i3 == i1) )
|
||||
break;
|
||||
|
||||
i3 = i4;
|
||||
s = (s + 4) & 7;
|
||||
} /* end of border following loop */
|
||||
}
|
||||
return i3 == stop_ptr;
|
||||
else {
|
||||
return i3 == stop_ptr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user