--- /dev/null
+/**********************************************************************************
+ * Copyright (c) 2008-2009 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ **********************************************************************************/
+
+#ifndef __OPENCL_CL_D3D11_EXT_H
+#define __OPENCL_CL_D3D11_EXT_H
+
+#include <d3d11.h>
+#include <CL/cl.h>
+#include <CL/cl_platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************
+ * cl_nv_d3d11_sharing */
+
+typedef cl_uint cl_d3d11_device_source_nv;
+typedef cl_uint cl_d3d11_device_set_nv;
+
+/******************************************************************************/
+
+// Error Codes
+#define CL_INVALID_D3D11_DEVICE_NV -1006
+#define CL_INVALID_D3D11_RESOURCE_NV -1007
+#define CL_D3D11_RESOURCE_ALREADY_ACQUIRED_NV -1008
+#define CL_D3D11_RESOURCE_NOT_ACQUIRED_NV -1009
+
+// cl_d3d11_device_source_nv
+#define CL_D3D11_DEVICE_NV 0x4019
+#define CL_D3D11_DXGI_ADAPTER_NV 0x401A
+
+// cl_d3d11_device_set_nv
+#define CL_PREFERRED_DEVICES_FOR_D3D11_NV 0x401B
+#define CL_ALL_DEVICES_FOR_D3D11_NV 0x401C
+
+// cl_context_info
+#define CL_CONTEXT_D3D11_DEVICE_NV 0x401D
+
+// cl_mem_info
+#define CL_MEM_D3D11_RESOURCE_NV 0x401E
+
+// cl_image_info
+#define CL_IMAGE_D3D11_SUBRESOURCE_NV 0x401F
+
+// cl_command_type
+#define CL_COMMAND_ACQUIRE_D3D11_OBJECTS_NV 0x4020
+#define CL_COMMAND_RELEASE_D3D11_OBJECTS_NV 0x4021
+
+/******************************************************************************/
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetDeviceIDsFromD3D11NV_fn)(
+ cl_platform_id platform,
+ cl_d3d11_device_source_nv d3d_device_source,
+ void * d3d_object,
+ cl_d3d11_device_set_nv d3d_device_set,
+ cl_uint num_entries,
+ cl_device_id * devices,
+ cl_uint * num_devices) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D11BufferNV_fn)(
+ cl_context context,
+ cl_mem_flags flags,
+ ID3D11Buffer * resource,
+ cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D11Texture2DNV_fn)(
+ cl_context context,
+ cl_mem_flags flags,
+ ID3D11Texture2D * resource,
+ UINT subresource,
+ cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D11Texture3DNV_fn)(
+ cl_context context,
+ cl_mem_flags flags,
+ ID3D11Texture3D * resource,
+ UINT subresource,
+ cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireD3D11ObjectsNV_fn)(
+ cl_command_queue command_queue,
+ cl_uint num_objects,
+ const cl_mem * mem_objects,
+ cl_uint num_events_in_wait_list,
+ const cl_event * event_wait_list,
+ cl_event * event) CL_API_SUFFIX__VERSION_1_0;
+
+typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReleaseD3D11ObjectsNV_fn)(
+ cl_command_queue command_queue,
+ cl_uint num_objects,
+ cl_mem * mem_objects,
+ cl_uint num_events_in_wait_list,
+ const cl_event * event_wait_list,
+ cl_event * event) CL_API_SUFFIX__VERSION_1_0;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __OPENCL_CL_D3D11_H
+
ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter -Wsign-compare -Wshorten-64-to-32 -Wimplicit-fallthrough)
-set(VERSION_MAJOR 1)
-set(VERSION_MINOR 5)
-set(VERSION_REVISION 3)
+set(VERSION_MAJOR 2)
+set(VERSION_MINOR 0)
+set(VERSION_REVISION 2)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION})
-set(LIBJPEG_TURBO_VERSION_NUMBER 1005003)
+set(LIBJPEG_TURBO_VERSION_NUMBER 2000002)
string(TIMESTAMP BUILD "opencv-${OPENCV_VERSION}-libjpeg-turbo")
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
option(WITH_ARITH_ENC "Include arithmetic encoding support when emulating the libjpeg v6b API/ABI" TRUE)
option(WITH_ARITH_DEC "Include arithmetic decoding support when emulating the libjpeg v6b API/ABI" TRUE)
-if(NOT DEFINED SIZEOF_SIZE_T)
- if(IOS) # Workaround iOS issues
- set(SIZEOF_SIZE_T "${CMAKE_SIZEOF_VOID_P}")
- message(STATUS "SIZEOF_SIZE_T = ${SIZEOF_SIZE_T}")
- else()
- include(CheckTypeSize)
- CHECK_TYPE_SIZE("size_t" SIZEOF_SIZE_T)
- endif()
+include(CheckCSourceCompiles)
+include(CheckIncludeFiles)
+include(CheckTypeSize)
+
+check_type_size("size_t" SIZEOF_SIZE_T)
+check_type_size("unsigned long" SIZEOF_UNSIGNED_LONG)
+
+if(SIZEOF_SIZE_T EQUAL SIZEOF_UNSIGNED_LONG)
+ check_c_source_compiles("int main(int argc, char **argv) { unsigned long a = argc; return __builtin_ctzl(a); }"
+ HAVE_BUILTIN_CTZL)
+endif()
+if(MSVC)
+ check_include_files("intrin.h" HAVE_INTRIN_H)
endif()
+if(UNIX)
+ # Check for headers
+ check_include_files(locale.h HAVE_LOCALE_H)
+ check_include_files(stddef.h HAVE_STDDEF_H)
+ check_include_files(stdlib.h HAVE_STDLIB_H)
+ check_include_files(sys/types.h NEED_SYS_TYPES_H)
+
+ # Other predefines
+ # undef NEED_BSD_STRINGS
+ ocv_update(HAVE_UNSIGNED_CHAR 1)
+ ocv_update(HAVE_UNSIGNED_SHORT 1)
+ # undef INCOMPLETE_TYPES_BROKEN
+ ocv_update(RIGHT_SHIFT_IS_UNSIGNED 0)
+ ocv_update(__CHAR_UNSIGNED__ 0)
+endif()
+
+
set(BITS_IN_JSAMPLE 8)
if(WITH_ARITH_ENC)
add_definitions(-W3 -wd4996 -wd4018)
endif()
-configure_file(jconfig.h.in jconfig.h)
+if(WIN32)
+ configure_file(jconfig.h.win.in jconfig.h)
+else()
+ configure_file(jconfig.h.in jconfig.h)
+endif()
configure_file(jconfigint.h.in jconfigint.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src)
- The Modified (3-clause) BSD License, which is listed below
- This license covers the TurboJPEG API library and associated programs.
+ This license covers the TurboJPEG API library and associated programs, as
+ well as the build system.
-- The zlib License, which is listed below
+- The [zlib License](https://opensource.org/licenses/Zlib)
This license is a subset of the other two, and it covers the libjpeg-turbo
SIMD extensions.
2. If your binary distribution includes or uses the TurboJPEG API, then
your product documentation must include the text of the Modified BSD
- License.
+ License (see below.)
**Origin**
- Clause 2 of the Modified BSD License
The Modified (3-clause) BSD License
===================================
-Copyright (C)\<YEAR\> \<AUTHOR\>. All Rights Reserved.
+Copyright (C)2009-2019 D. R. Commander. All Rights Reserved.
+Copyright (C)2015 Viktor Szathmáry. All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
POSSIBILITY OF SUCH DAMAGE.
-The zlib License
-================
+Why Three Licenses?
+===================
-Copyright (C) \<YEAR\>, \<AUTHOR\>.
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
+The zlib License could have been used instead of the Modified (3-clause) BSD
+License, and since the IJG License effectively subsumes the distribution
+conditions of the zlib License, this would have effectively placed
+libjpeg-turbo binary distributions under the IJG License. However, the IJG
+License specifically refers to the Independent JPEG Group and does not extend
+attribution and endorsement protections to other entities. Thus, it was
+desirable to choose a license that granted us the same protections for new code
+that were granted to the IJG for code derived from their software.
change.log Version-to-version change highlights.
Programmer and internal documentation:
libjpeg.txt How to use the JPEG library in your own programs.
- example.c Sample code for calling the JPEG library.
+ example.txt Sample code for calling the JPEG library.
structure.txt Overview of the JPEG library's internal structure.
coderules.txt Coding style rules --- please read if you contribute code.
assumed by the product vendor.
-The Unix configuration script "configure" was produced with GNU Autoconf.
-It is copyright by the Free Software Foundation but is freely distributable.
-The same holds for its supporting scripts (config.guess, config.sub,
-ltmain.sh). Another support script, install-sh, is copyright by X Consortium
-but is also freely distributable.
-
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
understand the innards of the JPEG software.
The best short technical introduction to the JPEG compression algorithm is
- Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
- Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
+ Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
+ Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
(Adjacent articles in that issue discuss MPEG motion picture compression,
applications of JPEG, and related topics.) If you don't have the CACM issue
handy, a PDF file containing a revised version of Wallace's article is
numbers ISO/IEC IS 10918-2, ITU-T T.83.
The JPEG standard does not specify all details of an interchangeable file
-format. For the omitted details we follow the "JFIF" conventions, revision
-1.02. JFIF 1.02 has been adopted as an Ecma International Technical Report
-and thus received a formal publication status. It is available as a free
-download in PDF format from
-http://www.ecma-international.org/publications/techreports/E-TR-098.htm.
-A PostScript version of the JFIF document is available at
-http://www.ijg.org/files/jfif.ps.gz. There is also a plain text version at
-http://www.ijg.org/files/jfif.txt.gz, but it is missing the figures.
+format. For the omitted details, we follow the "JFIF" conventions, revision
+1.02. JFIF version 1 has been adopted as ISO/IEC 10918-5 (05/2013) and
+Recommendation ITU-T T.871 (05/2011): Information technology - Digital
+compression and coding of continuous-tone still images: JPEG File Interchange
+Format (JFIF). It is available as a free download in PDF file format from
+https://www.iso.org/standard/54989.html and http://www.itu.int/rec/T-REC-T.871.
+A PDF file of the older JFIF 1.02 specification is available at
+http://www.w3.org/Graphics/JPEG/jfif3.pdf.
The TIFF 6.0 file format specification can be obtained by FTP from
ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme
archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
with body
- send usenet/news.answers/jpeg-faq/part1
- send usenet/news.answers/jpeg-faq/part2
-
-
-FILE FORMAT WARS
-================
-
-The ISO/IEC JTC1/SC29/WG1 standards committee (also known as JPEG, together
-with ITU-T SG16) currently promotes different formats containing the name
-"JPEG" which are incompatible with original DCT-based JPEG. IJG therefore does
-not support these formats (see REFERENCES). Indeed, one of the original
-reasons for developing this free software was to help force convergence on
-common, interoperable format standards for JPEG files.
-Don't use an incompatible file format!
-(In any case, our decoder will remain capable of reading existing JPEG
-image files indefinitely.)
+ send usenet/news.answers/jpeg-faq/part1
+ send usenet/news.answers/jpeg-faq/part2
+
+
+FILE FORMAT COMPATIBILITY
+=========================
+
+This software implements ITU T.81 | ISO/IEC 10918 with some extensions from
+ITU T.871 | ISO/IEC 10918-5 (JPEG File Interchange Format-- see REFERENCES).
+Informally, the term "JPEG image" or "JPEG file" most often refers to JFIF or
+a subset thereof, but there are other formats containing the name "JPEG" that
+are incompatible with the DCT-based JPEG standard or with JFIF (for instance,
+JPEG 2000 and JPEG XR). This software therefore does not support these
+formats. Indeed, one of the original reasons for developing this free software
+was to help force convergence on a common, interoperable format standard for
+JPEG files.
+
+JFIF is a minimal or "low end" representation. TIFF/JPEG (TIFF revision 6.0 as
+modified by TIFF Technical Note #2) can be used for "high end" applications
+that need to record a lot of additional data about an image.
TO DO
==========
libjpeg-turbo is a JPEG image codec that uses SIMD instructions (MMX, SSE2,
-NEON, AltiVec) to accelerate baseline JPEG compression and decompression on
-x86, x86-64, ARM, and PowerPC systems. On such systems, libjpeg-turbo is
+AVX2, NEON, AltiVec) to accelerate baseline JPEG compression and decompression
+on x86, x86-64, ARM, and PowerPC systems, as well as progressive JPEG
+compression on x86 and x86-64 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 Huffman coding routines. In many cases, the
straightforward to achieve using the underlying libjpeg API, such as
generating planar YUV images and performing multiple simultaneous lossless
transforms on an image. The Java interface for libjpeg-turbo is written on
- top of the TurboJPEG API.
+ top of the TurboJPEG API. The TurboJPEG API is recommended for first-time
+ users of libjpeg-turbo. Refer to [tjexample.c](tjexample.c) and
+ [TJExample.java](java/TJExample.java) for examples of its usage and to
+ <http://libjpeg-turbo.org/Documentation/Documentation> for API documentation.
- **libjpeg API**<br>
This is the de facto industry-standard API for compressing and decompressing
more powerful. The libjpeg API implementation in libjpeg-turbo is both
API/ABI-compatible and mathematically compatible with libjpeg v6b. It can
also optionally be configured to be API/ABI-compatible with libjpeg v7 and v8
- (see below.)
+ (see below.) Refer to [cjpeg.c](cjpeg.c) and [djpeg.c](djpeg.c) for examples
+ of its usage and to [libjpeg.txt](libjpeg.txt) for API documentation.
There is no significant performance advantage to either API when both are used
to perform similar operations.
-/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */
-/* see jconfig.txt for explanations */
+/* Version ID for the JPEG library.
+ * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60".
+ */
+#define JPEG_LIB_VERSION @JPEG_LIB_VERSION@
+
+/* libjpeg-turbo version */
+#define LIBJPEG_TURBO_VERSION @VERSION@
+
+/* libjpeg-turbo version in integer form */
+#define LIBJPEG_TURBO_VERSION_NUMBER @LIBJPEG_TURBO_VERSION_NUMBER@
+
+/* Support arithmetic encoding */
+#cmakedefine C_ARITH_CODING_SUPPORTED 1
-#define JPEG_LIB_VERSION @JPEG_LIB_VERSION@
-#define LIBJPEG_TURBO_VERSION @VERSION@
-#define LIBJPEG_TURBO_VERSION_NUMBER @LIBJPEG_TURBO_VERSION_NUMBER@
-#cmakedefine C_ARITH_CODING_SUPPORTED
-#cmakedefine D_ARITH_CODING_SUPPORTED
-#cmakedefine MEM_SRCDST_SUPPORTED
+/* Support arithmetic decoding */
+#cmakedefine D_ARITH_CODING_SUPPORTED 1
+
+/* Support in-memory source/destination managers */
+#cmakedefine MEM_SRCDST_SUPPORTED 1
+
+/* Use accelerated SIMD routines. */
+#cmakedefine WITH_SIMD 1
/*
* Define BITS_IN_JSAMPLE as either
#define BITS_IN_JSAMPLE @BITS_IN_JSAMPLE@ /* use 8 or 12 */
-#define HAVE_UNSIGNED_CHAR
-#define HAVE_UNSIGNED_SHORT
-/* #define void char */
-/* #define const */
-#undef __CHAR_UNSIGNED__
-#define HAVE_STDDEF_H
-#define HAVE_STDLIB_H
-#undef NEED_BSD_STRINGS
-#undef NEED_SYS_TYPES_H
-#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */
-#undef INCOMPLETE_TYPES_BROKEN
-
-/* Define "boolean" as unsigned char, not int, per Windows custom */
-#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
-typedef unsigned char boolean;
-#endif
-#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
+/* Define to 1 if you have the <locale.h> header file. */
+#cmakedefine HAVE_LOCALE_H 1
-/* Define "INT32" as int, not long, per Windows custom */
-#if !(defined(_BASETSD_H_) || defined(_BASETSD_H)) /* don't conflict if basetsd.h already read */
-typedef short INT16;
-typedef signed int INT32;
-#endif
-#define XMD_H /* prevent jmorecfg.h from redefining it */
+/* Define to 1 if you have the <stddef.h> header file. */
+#cmakedefine HAVE_STDDEF_H 1
-#ifdef JPEG_INTERNALS
+/* Define to 1 if you have the <stdlib.h> header file. */
+#cmakedefine HAVE_STDLIB_H 1
-#undef RIGHT_SHIFT_IS_UNSIGNED
+/* Define if you need to include <sys/types.h> to get size_t. */
+#cmakedefine NEED_SYS_TYPES_H 1
+
+/* Define if you have BSD-like bzero and bcopy in <strings.h> rather than
+ memset/memcpy in <string.h>. */
+#cmakedefine NEED_BSD_STRINGS 1
+
+/* Define to 1 if the system has the type `unsigned char'. */
+#cmakedefine HAVE_UNSIGNED_CHAR 1
+
+/* Define to 1 if the system has the type `unsigned short'. */
+#cmakedefine HAVE_UNSIGNED_SHORT 1
+
+/* Compiler does not support pointers to undefined structures. */
+#cmakedefine INCOMPLETE_TYPES_BROKEN 1
+
+/* Define if your (broken) compiler shifts signed values as if they were
+ 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 SIZEOF_SIZE_T @SIZEOF_SIZE_T@
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
-#endif /* JPEG_INTERNALS */
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
--- /dev/null
+#define JPEG_LIB_VERSION @JPEG_LIB_VERSION@
+#define LIBJPEG_TURBO_VERSION @VERSION@
+#define LIBJPEG_TURBO_VERSION_NUMBER @LIBJPEG_TURBO_VERSION_NUMBER@
+
+#cmakedefine C_ARITH_CODING_SUPPORTED
+#cmakedefine D_ARITH_CODING_SUPPORTED
+#cmakedefine MEM_SRCDST_SUPPORTED
+#cmakedefine WITH_SIMD
+
+#define BITS_IN_JSAMPLE @BITS_IN_JSAMPLE@ /* use 8 or 12 */
+
+#define HAVE_STDDEF_H
+#define HAVE_STDLIB_H
+#undef NEED_SYS_TYPES_H
+#undef NEED_BSD_STRINGS
+
+#define HAVE_UNSIGNED_CHAR
+#define HAVE_UNSIGNED_SHORT
+#undef INCOMPLETE_TYPES_BROKEN
+#undef RIGHT_SHIFT_IS_UNSIGNED
+#undef __CHAR_UNSIGNED__
+
+/* Define "boolean" as unsigned char, not int, per Windows custom */
+#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
+typedef unsigned char boolean;
+#endif
+#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
+
+/* Define "INT32" as int, not long, per Windows custom */
+#if !(defined(_BASETSD_H_) || defined(_BASETSD_H)) /* don't conflict if basetsd.h already read */
+typedef short INT16;
+typedef signed int INT32;
+#endif
+#define XMD_H /* prevent jmorecfg.h from redefining it */
-#define VERSION "@VERSION@"
-#define BUILD "@BUILD@"
-#define PACKAGE_NAME "@CMAKE_PROJECT_NAME@"
+/* libjpeg-turbo build number */
+#define BUILD "@BUILD@"
+/* Compiler's inline keyword */
+#undef inline
+
+/* How to obtain function inlining. */
#ifndef INLINE
#if defined(__GNUC__)
#define INLINE inline __attribute__((always_inline))
#define INLINE
#endif
#endif
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "@CMAKE_PROJECT_NAME@"
+
+/* Version number of package */
+#define VERSION "@VERSION@"
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T @SIZEOF_SIZE_T@
+
+/* Define if your compiler has __builtin_ctzl() and sizeof(unsigned long) == sizeof(size_t). */
+#cmakedefine HAVE_BUILTIN_CTZL
+
+/* Define to 1 if you have the <intrin.h> header file. */
+#cmakedefine HAVE_INTRIN_H
+
+#if defined(_MSC_VER) && defined(HAVE_INTRIN_H)
+#if (SIZEOF_SIZE_T == 8)
+#define HAVE_BITSCANFORWARD64
+#elif (SIZEOF_SIZE_T == 4)
+#define HAVE_BITSCANFORWARD
+#endif
+#endif
* This file was part of the Independent JPEG Group's software:
* Developed 1997-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2015, D. R. Commander.
+ * Copyright (C) 2015, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
* This file contains probability estimation tables for common use in
* arithmetic entropy encoding and decoding routines.
*
- * This data represents Table D.2 in the JPEG spec (ISO/IEC IS 10918-1
- * and CCITT Recommendation ITU-T T.81) and Table 24 in the JBIG spec
- * (ISO/IEC IS 11544 and CCITT Recommendation ITU-T T.82).
+ * This data represents Table D.2 in
+ * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994 and Table 24 in
+ * Recommendation ITU-T T.82 (1993) | ISO/IEC 11544:1993.
*/
#define JPEG_INTERNALS
* implementation (jbig_tab.c).
*/
-#define V(i,a,b,c,d) (((JLONG)a << 16) | ((JLONG)c << 8) | ((JLONG)d << 7) | b)
+#define V(i, a, b, c, d) \
+ (((JLONG)a << 16) | ((JLONG)c << 8) | ((JLONG)d << 7) | b)
-const JLONG jpeg_aritab[113+1] = {
+const JLONG jpeg_aritab[113 + 1] = {
/*
* Index, Qe_Value, Next_Index_LPS, Next_Index_MPS, Switch_MPS
*/
*/
GLOBAL(void)
-jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
+jpeg_CreateCompress(j_compress_ptr cinfo, int version, size_t structsize)
{
int i;
ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
if (structsize != sizeof(struct jpeg_compress_struct))
ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
- (int) sizeof(struct jpeg_compress_struct), (int) structsize);
+ (int)sizeof(struct jpeg_compress_struct), (int)structsize);
/* For debugging purposes, we zero the whole master structure.
* But the application has already set the err pointer, and may have set
cinfo->is_decompressor = FALSE;
/* Initialize a memory manager instance for this object */
- jinit_memory_mgr((j_common_ptr) cinfo);
+ jinit_memory_mgr((j_common_ptr)cinfo);
/* Zero out pointers to permanent structures. */
cinfo->progress = NULL;
/* Must do it here for emit_dqt in case jpeg_write_tables is used */
cinfo->block_size = DCTSIZE;
cinfo->natural_order = jpeg_natural_order;
- cinfo->lim_Se = DCTSIZE2-1;
+ cinfo->lim_Se = DCTSIZE2 - 1;
#endif
cinfo->script_space = NULL;
*/
GLOBAL(void)
-jpeg_destroy_compress (j_compress_ptr cinfo)
+jpeg_destroy_compress(j_compress_ptr cinfo)
{
- jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
+ jpeg_destroy((j_common_ptr)cinfo); /* use common routine */
}
*/
GLOBAL(void)
-jpeg_abort_compress (j_compress_ptr cinfo)
+jpeg_abort_compress(j_compress_ptr cinfo)
{
- jpeg_abort((j_common_ptr) cinfo); /* use common routine */
+ jpeg_abort((j_common_ptr)cinfo); /* use common routine */
}
*/
GLOBAL(void)
-jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress)
+jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress)
{
int i;
JQUANT_TBL *qtbl;
*/
GLOBAL(void)
-jpeg_finish_compress (j_compress_ptr cinfo)
+jpeg_finish_compress(j_compress_ptr cinfo)
{
JDIMENSION iMCU_row;
} else if (cinfo->global_state != CSTATE_WRCOEFS)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Perform any remaining passes */
- while (! cinfo->master->is_last_pass) {
+ while (!cinfo->master->is_last_pass) {
(*cinfo->master->prepare_for_pass) (cinfo);
for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) {
if (cinfo->progress != NULL) {
- cinfo->progress->pass_counter = (long) iMCU_row;
- cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows;
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ cinfo->progress->pass_counter = (long)iMCU_row;
+ cinfo->progress->pass_limit = (long)cinfo->total_iMCU_rows;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
}
/* We bypass the main controller and invoke coef controller directly;
* all work is being done from the coefficient buffer.
*/
- if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL))
+ if (!(*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE)NULL))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
}
(*cinfo->master->finish_pass) (cinfo);
(*cinfo->marker->write_file_trailer) (cinfo);
(*cinfo->dest->term_destination) (cinfo);
/* We can use jpeg_abort to release memory and reset global_state */
- jpeg_abort((j_common_ptr) cinfo);
+ jpeg_abort((j_common_ptr)cinfo);
}
*/
GLOBAL(void)
-jpeg_write_marker (j_compress_ptr cinfo, int marker,
- const JOCTET *dataptr, unsigned int datalen)
+jpeg_write_marker(j_compress_ptr cinfo, int marker, const JOCTET *dataptr,
+ unsigned int datalen)
{
void (*write_marker_byte) (j_compress_ptr info, int val);
/* Same, but piecemeal. */
GLOBAL(void)
-jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
+jpeg_write_m_header(j_compress_ptr cinfo, int marker, unsigned int datalen)
{
if (cinfo->next_scanline != 0 ||
(cinfo->global_state != CSTATE_SCANNING &&
}
GLOBAL(void)
-jpeg_write_m_byte (j_compress_ptr cinfo, int val)
+jpeg_write_m_byte(j_compress_ptr cinfo, int val)
{
(*cinfo->marker->write_marker_byte) (cinfo, val);
}
*/
GLOBAL(void)
-jpeg_write_tables (j_compress_ptr cinfo)
+jpeg_write_tables(j_compress_ptr cinfo)
{
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* (Re)initialize error mgr and destination modules */
- (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr)cinfo);
(*cinfo->dest->init_destination) (cinfo);
/* Initialize the marker writer ... bit of a crock to do it here. */
jinit_marker_writer(cinfo);
*/
GLOBAL(void)
-jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables)
+jpeg_start_compress(j_compress_ptr cinfo, boolean write_all_tables)
{
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */
/* (Re)initialize error mgr and destination modules */
- (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr)cinfo);
(*cinfo->dest->init_destination) (cinfo);
/* Perform master selection of active modules */
jinit_compress_master(cinfo);
*/
GLOBAL(JDIMENSION)
-jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines,
- JDIMENSION num_lines)
+jpeg_write_scanlines(j_compress_ptr cinfo, JSAMPARRAY scanlines,
+ JDIMENSION num_lines)
{
JDIMENSION row_ctr, rows_left;
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
- cinfo->progress->pass_counter = (long) cinfo->next_scanline;
- cinfo->progress->pass_limit = (long) cinfo->image_height;
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ cinfo->progress->pass_counter = (long)cinfo->next_scanline;
+ cinfo->progress->pass_limit = (long)cinfo->image_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
}
/* Give master control module another chance if this is first call to
*/
GLOBAL(JDIMENSION)
-jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
- JDIMENSION num_lines)
+jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data,
+ JDIMENSION num_lines)
{
JDIMENSION lines_per_iMCU_row;
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
- cinfo->progress->pass_counter = (long) cinfo->next_scanline;
- cinfo->progress->pass_limit = (long) cinfo->image_height;
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ cinfo->progress->pass_counter = (long)cinfo->next_scanline;
+ cinfo->progress->pass_limit = (long)cinfo->image_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
}
/* Give master control module another chance if this is first call to
ERREXIT(cinfo, JERR_BUFFER_SIZE);
/* Directly compress the row. */
- if (! (*cinfo->coef->compress_data) (cinfo, data)) {
+ if (!(*cinfo->coef->compress_data) (cinfo, data)) {
/* If compressor did not consume the whole row, suspend processing. */
return 0;
}
* This file was part of the Independent JPEG Group's software:
* Developed 1997-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2015, D. R. Commander.
+ * Copyright (C) 2015, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
* This file contains portable arithmetic entropy encoding routines for JPEG
- * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81).
+ * (implementing Recommendation ITU-T T.81 | ISO/IEC 10918-1).
*
* Both sequential and progressive modes are supported in this single module.
*
* Suspension is not currently supported in this module.
+ *
+ * NOTE: All referenced figures are from
+ * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994.
*/
#define JPEG_INTERNALS
* in the lower bits (mask 0x7F).
*/
-#define DC_STAT_BINS 64
-#define AC_STAT_BINS 256
+#define DC_STAT_BINS 64
+#define AC_STAT_BINS 256
/* NOTE: Uncomment the following #define if you want to use the
* given formula for calculating the AC conditioning parameter Kx
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define ISHIFT_TEMPS int ishift_temp;
-#define IRIGHT_SHIFT(x,shft) \
- ((ishift_temp = (x)) < 0 ? \
- (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
- (ishift_temp >> (shft)))
+#define IRIGHT_SHIFT(x, shft) \
+ ((ishift_temp = (x)) < 0 ? \
+ (ishift_temp >> (shft)) | ((~0) << (16 - (shft))) : \
+ (ishift_temp >> (shft)))
#else
#define ISHIFT_TEMPS
-#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
+#define IRIGHT_SHIFT(x, shft) ((x) >> (shft))
#endif
LOCAL(void)
-emit_byte (int val, j_compress_ptr cinfo)
+emit_byte(int val, j_compress_ptr cinfo)
/* Write next output byte; we do not support suspension in this module. */
{
struct jpeg_destination_mgr *dest = cinfo->dest;
- *dest->next_output_byte++ = (JOCTET) val;
+ *dest->next_output_byte++ = (JOCTET)val;
if (--dest->free_in_buffer == 0)
- if (! (*dest->empty_output_buffer) (cinfo))
+ if (!(*dest->empty_output_buffer) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
}
*/
METHODDEF(void)
-finish_pass (j_compress_ptr cinfo)
+finish_pass(j_compress_ptr cinfo)
{
- arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr e = (arith_entropy_ptr)cinfo->entropy;
JLONG temp;
/* Section D.1.8: Termination of encoding */
/* Find the e->c in the coding interval with the largest
* number of trailing zero bits */
- if ((temp = (e->a - 1 + e->c) & 0xFFFF0000L) < e->c)
+ if ((temp = (e->a - 1 + e->c) & 0xFFFF0000UL) < e->c)
e->c = temp + 0x8000L;
else
e->c = temp;
/* Send remaining bytes to output */
e->c <<= e->ct;
- if (e->c & 0xF8000000L) {
+ if (e->c & 0xF8000000UL) {
/* One final overflow has to be handled */
if (e->buffer >= 0) {
if (e->zc)
*/
LOCAL(void)
-arith_encode (j_compress_ptr cinfo, unsigned char *st, int val)
+arith_encode(j_compress_ptr cinfo, unsigned char *st, int val)
{
- register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy;
+ register arith_entropy_ptr e = (arith_entropy_ptr)cinfo->entropy;
register unsigned char nl, nm;
register JLONG qe, temp;
register int sv;
*/
sv = *st;
qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */
- nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */
- nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */
+ nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */
+ nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */
/* Encode & estimation procedures per sections D.1.4 & D.1.5 */
e->a -= qe;
*/
LOCAL(void)
-emit_restart (j_compress_ptr cinfo, int restart_num)
+emit_restart(j_compress_ptr cinfo, int restart_num)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
int ci;
jpeg_component_info *compptr;
*/
METHODDEF(boolean)
-encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_DC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
JBLOCKROW block;
unsigned char *st;
int blkn, ci, tbl;
/* Compute the DC value after the required point transform by Al.
* This is simply an arithmetic right shift.
*/
- m = IRIGHT_SHIFT((int) ((*block)[0]), cinfo->Al);
+ m = IRIGHT_SHIFT((int)((*block)[0]), cinfo->Al);
/* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */
}
arith_encode(cinfo, st, 0);
/* Section F.1.4.4.1.2: Establish dc_context conditioning category */
- if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1))
+ if (m < (int)((1L << cinfo->arith_dc_L[tbl]) >> 1))
entropy->dc_context[ci] = 0; /* zero diff category */
- else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1))
+ else if (m > (int)((1L << cinfo->arith_dc_U[tbl]) >> 1))
entropy->dc_context[ci] += 8; /* large diff category */
/* Figure F.9: Encoding the magnitude bit pattern of v */
st += 14;
*/
METHODDEF(boolean)
-encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_AC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
JBLOCKROW block;
unsigned char *st;
int tbl, k, ke;
break;
}
}
- arith_encode(cinfo, st + 1, 0); st += 3; k++;
+ arith_encode(cinfo, st + 1, 0); st += 3; k++;
}
st += 2;
/* Figure F.8: Encoding the magnitude category of v */
*/
METHODDEF(boolean)
-encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_DC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
unsigned char *st;
int Al, blkn;
*/
METHODDEF(boolean)
-encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
JBLOCKROW block;
unsigned char *st;
int tbl, k, ke, kex;
break;
}
}
- arith_encode(cinfo, st + 1, 0); st += 3; k++;
+ arith_encode(cinfo, st + 1, 0); st += 3; k++;
}
}
/* Encode EOB decision only if k <= cinfo->Se */
*/
METHODDEF(boolean)
-encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
jpeg_component_info *compptr;
JBLOCKROW block;
unsigned char *st;
}
arith_encode(cinfo, st, 0);
/* Section F.1.4.4.1.2: Establish dc_context conditioning category */
- if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1))
+ if (m < (int)((1L << cinfo->arith_dc_L[tbl]) >> 1))
entropy->dc_context[ci] = 0; /* zero diff category */
- else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1))
+ else if (m > (int)((1L << cinfo->arith_dc_U[tbl]) >> 1))
entropy->dc_context[ci] += 8; /* large diff category */
/* Figure F.9: Encoding the magnitude bit pattern of v */
st += 14;
st = entropy->ac_stats[tbl] + 3 * (k - 1);
arith_encode(cinfo, st, 0); /* EOB decision */
while ((v = (*block)[jpeg_natural_order[k]]) == 0) {
- arith_encode(cinfo, st + 1, 0); st += 3; k++;
+ arith_encode(cinfo, st + 1, 0); st += 3; k++;
}
arith_encode(cinfo, st + 1, 1);
/* Figure F.6: Encoding nonzero value v */
*/
METHODDEF(void)
-start_pass (j_compress_ptr cinfo, boolean gather_statistics)
+start_pass(j_compress_ptr cinfo, boolean gather_statistics)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
int ci, tbl;
jpeg_component_info *compptr;
if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
if (entropy->dc_stats[tbl] == NULL)
- entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS);
+ entropy->dc_stats[tbl] = (unsigned char *)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, DC_STAT_BINS);
MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS);
/* Initialize DC predictions to 0 */
entropy->last_dc_val[ci] = 0;
if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
if (entropy->ac_stats[tbl] == NULL)
- entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS);
+ entropy->ac_stats[tbl] = (unsigned char *)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, AC_STAT_BINS);
MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS);
#ifdef CALCULATE_SPECTRAL_CONDITIONING
if (cinfo->progressive_mode)
/* Section G.1.3.2: Set appropriate arithmetic conditioning value Kx */
- cinfo->arith_ac_K[tbl] = cinfo->Ss + ((8 + cinfo->Se - cinfo->Ss) >> 4);
+ cinfo->arith_ac_K[tbl] = cinfo->Ss +
+ ((8 + cinfo->Se - cinfo->Ss) >> 4);
#endif
}
}
*/
GLOBAL(void)
-jinit_arith_encoder (j_compress_ptr cinfo)
+jinit_arith_encoder(j_compress_ptr cinfo)
{
arith_entropy_ptr entropy;
int i;
entropy = (arith_entropy_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(arith_entropy_encoder));
- cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
+ cinfo->entropy = (struct jpeg_entropy_encoder *)entropy;
entropy->pub.start_pass = start_pass;
entropy->pub.finish_pass = finish_pass;
/* Forward declarations */
-METHODDEF(boolean) compress_data
- (j_compress_ptr cinfo, JSAMPIMAGE input_buf);
+METHODDEF(boolean) compress_data(j_compress_ptr cinfo, JSAMPIMAGE input_buf);
#ifdef FULL_COEF_BUFFER_SUPPORTED
-METHODDEF(boolean) compress_first_pass
- (j_compress_ptr cinfo, JSAMPIMAGE input_buf);
-METHODDEF(boolean) compress_output
- (j_compress_ptr cinfo, JSAMPIMAGE input_buf);
+METHODDEF(boolean) compress_first_pass(j_compress_ptr cinfo,
+ JSAMPIMAGE input_buf);
+METHODDEF(boolean) compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf);
#endif
LOCAL(void)
-start_iMCU_row (j_compress_ptr cinfo)
+start_iMCU_row(j_compress_ptr cinfo)
/* Reset within-iMCU-row counters for a new row */
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
/* In an interleaved scan, an MCU row is the same as an iMCU row.
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
if (cinfo->comps_in_scan > 1) {
coef->MCU_rows_per_iMCU_row = 1;
} else {
- if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
+ if (coef->iMCU_row_num < (cinfo->total_iMCU_rows - 1))
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
else
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
*/
METHODDEF(void)
-start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+start_pass_coef(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
coef->iMCU_row_num = 0;
start_iMCU_row(cinfo);
*/
METHODDEF(boolean)
-compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+compress_data(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
blkn = 0;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
- blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
- : compptr->last_col_width;
+ blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width :
+ compptr->last_col_width;
xpos = MCU_col_num * compptr->MCU_sample_width;
ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
if (coef->iMCU_row_num < last_iMCU_row ||
- yoffset+yindex < compptr->last_row_height) {
+ yoffset + yindex < compptr->last_row_height) {
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
input_buf[compptr->component_index],
coef->MCU_buffer[blkn],
- ypos, xpos, (JDIMENSION) blockcnt);
+ ypos, xpos, (JDIMENSION)blockcnt);
if (blockcnt < compptr->MCU_width) {
/* Create some dummy blocks at the right edge of the image. */
- jzero_far((void *) coef->MCU_buffer[blkn + blockcnt],
+ jzero_far((void *)coef->MCU_buffer[blkn + blockcnt],
(compptr->MCU_width - blockcnt) * sizeof(JBLOCK));
for (bi = blockcnt; bi < compptr->MCU_width; bi++) {
- coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0];
+ coef->MCU_buffer[blkn + bi][0][0] =
+ coef->MCU_buffer[blkn + bi - 1][0][0];
}
}
} else {
/* Create a row of dummy blocks at the bottom of the image. */
- jzero_far((void *) coef->MCU_buffer[blkn],
+ jzero_far((void *)coef->MCU_buffer[blkn],
compptr->MCU_width * sizeof(JBLOCK));
for (bi = 0; bi < compptr->MCU_width; bi++) {
- coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0];
+ coef->MCU_buffer[blkn + bi][0][0] =
+ coef->MCU_buffer[blkn - 1][0][0];
}
}
blkn += compptr->MCU_width;
/* Try to write the MCU. In event of a suspension failure, we will
* re-DCT the MCU on restart (a bit inefficient, could be fixed...)
*/
- if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
+ if (!(*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->mcu_ctr = MCU_col_num;
*/
METHODDEF(boolean)
-compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+compress_first_pass(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
JDIMENSION blocks_across, MCUs_across, MCUindex;
int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
ci++, compptr++) {
/* Align the virtual buffer for this component. */
buffer = (*cinfo->mem->access_virt_barray)
- ((j_common_ptr) cinfo, coef->whole_image[ci],
+ ((j_common_ptr)cinfo, coef->whole_image[ci],
coef->iMCU_row_num * compptr->v_samp_factor,
- (JDIMENSION) compptr->v_samp_factor, TRUE);
+ (JDIMENSION)compptr->v_samp_factor, TRUE);
/* Count non-dummy DCT block rows in this iMCU row. */
if (coef->iMCU_row_num < last_iMCU_row)
block_rows = compptr->v_samp_factor;
else {
/* NB: can't use last_row_height here, since may not be set! */
- block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ block_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
if (block_rows == 0) block_rows = compptr->v_samp_factor;
}
blocks_across = compptr->width_in_blocks;
h_samp_factor = compptr->h_samp_factor;
/* Count number of dummy blocks to be added at the right margin. */
- ndummy = (int) (blocks_across % h_samp_factor);
+ ndummy = (int)(blocks_across % h_samp_factor);
if (ndummy > 0)
ndummy = h_samp_factor - ndummy;
/* Perform DCT for all non-dummy blocks in this iMCU row. Each call
thisblockrow = buffer[block_row];
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
input_buf[ci], thisblockrow,
- (JDIMENSION) (block_row * DCTSIZE),
- (JDIMENSION) 0, blocks_across);
+ (JDIMENSION)(block_row * DCTSIZE),
+ (JDIMENSION)0, blocks_across);
if (ndummy > 0) {
/* Create dummy blocks at the right edge of the image. */
thisblockrow += blocks_across; /* => first dummy block */
- jzero_far((void *) thisblockrow, ndummy * sizeof(JBLOCK));
+ jzero_far((void *)thisblockrow, ndummy * sizeof(JBLOCK));
lastDC = thisblockrow[-1][0];
for (bi = 0; bi < ndummy; bi++) {
thisblockrow[bi][0] = lastDC;
for (block_row = block_rows; block_row < compptr->v_samp_factor;
block_row++) {
thisblockrow = buffer[block_row];
- lastblockrow = buffer[block_row-1];
- jzero_far((void *) thisblockrow,
- (size_t) (blocks_across * sizeof(JBLOCK)));
+ lastblockrow = buffer[block_row - 1];
+ jzero_far((void *)thisblockrow,
+ (size_t)(blocks_across * sizeof(JBLOCK)));
for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
- lastDC = lastblockrow[h_samp_factor-1][0];
+ lastDC = lastblockrow[h_samp_factor - 1][0];
for (bi = 0; bi < h_samp_factor; bi++) {
thisblockrow[bi][0] = lastDC;
}
*/
METHODDEF(boolean)
-compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
int blkn, ci, xindex, yindex, yoffset;
JDIMENSION start_col;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
buffer[ci] = (*cinfo->mem->access_virt_barray)
- ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ ((j_common_ptr)cinfo, coef->whole_image[compptr->component_index],
coef->iMCU_row_num * compptr->v_samp_factor,
- (JDIMENSION) compptr->v_samp_factor, FALSE);
+ (JDIMENSION)compptr->v_samp_factor, FALSE);
}
/* Loop to process one whole iMCU row */
compptr = cinfo->cur_comp_info[ci];
start_col = MCU_col_num * compptr->MCU_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
- buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ buffer_ptr = buffer[ci][yindex + yoffset] + start_col;
for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
coef->MCU_buffer[blkn++] = buffer_ptr++;
}
}
}
/* Try to write the MCU. */
- if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
+ if (!(*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->mcu_ctr = MCU_col_num;
*/
GLOBAL(void)
-jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+jinit_c_coef_controller(j_compress_ptr cinfo, boolean need_full_buffer)
{
my_coef_ptr coef;
coef = (my_coef_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_coef_controller));
- cinfo->coef = (struct jpeg_c_coef_controller *) coef;
+ cinfo->coef = (struct jpeg_c_coef_controller *)coef;
coef->pub.start_pass = start_pass_coef;
/* Create the coefficient buffer. */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
- (JDIMENSION) jround_up((long) compptr->width_in_blocks,
- (long) compptr->h_samp_factor),
- (JDIMENSION) jround_up((long) compptr->height_in_blocks,
- (long) compptr->v_samp_factor),
- (JDIMENSION) compptr->v_samp_factor);
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION)jround_up((long)compptr->width_in_blocks,
+ (long)compptr->h_samp_factor),
+ (JDIMENSION)jround_up((long)compptr->height_in_blocks,
+ (long)compptr->v_samp_factor),
+ (JDIMENSION)compptr->v_samp_factor);
}
#else
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
int i;
buffer = (JBLOCKROW)
- (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE,
C_MAX_BLOCKS_IN_MCU * sizeof(JBLOCK));
for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
coef->MCU_buffer[i] = buffer + i;
INLINE
LOCAL(void)
-rgb_ycc_convert_internal (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+rgb_ycc_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row,
+ int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int r, g, b;
- register JLONG * ctab = cconvert->rgb_ycc_tab;
+ register JLONG *ctab = cconvert->rgb_ycc_tab;
register JSAMPROW inptr;
register JSAMPROW outptr0, outptr1, outptr2;
register JDIMENSION col;
* need the general RIGHT_SHIFT macro.
*/
/* Y */
- outptr0[col] = (JSAMPLE)
- ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
- >> SCALEBITS);
+ outptr0[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] +
+ ctab[b + B_Y_OFF]) >> SCALEBITS);
/* Cb */
- outptr1[col] = (JSAMPLE)
- ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
- >> SCALEBITS);
+ outptr1[col] = (JSAMPLE)((ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] +
+ ctab[b + B_CB_OFF]) >> SCALEBITS);
/* Cr */
- outptr2[col] = (JSAMPLE)
- ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
- >> SCALEBITS);
+ outptr2[col] = (JSAMPLE)((ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] +
+ ctab[b + B_CR_OFF]) >> SCALEBITS);
}
}
}
INLINE
LOCAL(void)
-rgb_gray_convert_internal (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+rgb_gray_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row,
+ int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int r, g, b;
- register JLONG * ctab = cconvert->rgb_ycc_tab;
+ register JLONG *ctab = cconvert->rgb_ycc_tab;
register JSAMPROW inptr;
register JSAMPROW outptr;
register JDIMENSION col;
b = GETJSAMPLE(inptr[RGB_BLUE]);
inptr += RGB_PIXELSIZE;
/* Y */
- outptr[col] = (JSAMPLE)
- ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
- >> SCALEBITS);
+ outptr[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] +
+ ctab[b + B_Y_OFF]) >> SCALEBITS);
}
}
}
INLINE
LOCAL(void)
-rgb_rgb_convert_internal (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+rgb_rgb_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row,
+ int num_rows)
{
register JSAMPROW inptr;
register JSAMPROW outptr0, outptr1, outptr2;
*/
#define SCALEBITS 16 /* speediest right-shift on some machines */
-#define CBCR_OFFSET ((JLONG) CENTERJSAMPLE << SCALEBITS)
-#define ONE_HALF ((JLONG) 1 << (SCALEBITS-1))
-#define FIX(x) ((JLONG) ((x) * (1L<<SCALEBITS) + 0.5))
+#define CBCR_OFFSET ((JLONG)CENTERJSAMPLE << SCALEBITS)
+#define ONE_HALF ((JLONG)1 << (SCALEBITS - 1))
+#define FIX(x) ((JLONG)((x) * (1L << SCALEBITS) + 0.5))
/* We allocate one big table and divide it up into eight parts, instead of
* doing eight alloc_small requests. This lets us use a single table base
*/
#define R_Y_OFF 0 /* offset to R => Y section */
-#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */
-#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */
-#define R_CB_OFF (3*(MAXJSAMPLE+1))
-#define G_CB_OFF (4*(MAXJSAMPLE+1))
-#define B_CB_OFF (5*(MAXJSAMPLE+1))
+#define G_Y_OFF (1 * (MAXJSAMPLE + 1)) /* offset to G => Y section */
+#define B_Y_OFF (2 * (MAXJSAMPLE + 1)) /* etc. */
+#define R_CB_OFF (3 * (MAXJSAMPLE + 1))
+#define G_CB_OFF (4 * (MAXJSAMPLE + 1))
+#define B_CB_OFF (5 * (MAXJSAMPLE + 1))
#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */
-#define G_CR_OFF (6*(MAXJSAMPLE+1))
-#define B_CR_OFF (7*(MAXJSAMPLE+1))
-#define TABLE_SIZE (8*(MAXJSAMPLE+1))
+#define G_CR_OFF (6 * (MAXJSAMPLE + 1))
+#define B_CR_OFF (7 * (MAXJSAMPLE + 1))
+#define TABLE_SIZE (8 * (MAXJSAMPLE + 1))
/* Include inline routines for colorspace extensions */
#undef RGB_BLUE
#undef RGB_PIXELSIZE
-#define RGB_RED EXT_RGB_RED
-#define RGB_GREEN EXT_RGB_GREEN
-#define RGB_BLUE EXT_RGB_BLUE
-#define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
-#define rgb_ycc_convert_internal extrgb_ycc_convert_internal
-#define rgb_gray_convert_internal extrgb_gray_convert_internal
-#define rgb_rgb_convert_internal extrgb_rgb_convert_internal
+#define RGB_RED EXT_RGB_RED
+#define RGB_GREEN EXT_RGB_GREEN
+#define RGB_BLUE EXT_RGB_BLUE
+#define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
+#define rgb_ycc_convert_internal extrgb_ycc_convert_internal
+#define rgb_gray_convert_internal extrgb_gray_convert_internal
+#define rgb_rgb_convert_internal extrgb_rgb_convert_internal
#include "jccolext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef rgb_gray_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_RGBX_RED
-#define RGB_GREEN EXT_RGBX_GREEN
-#define RGB_BLUE EXT_RGBX_BLUE
-#define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
-#define rgb_ycc_convert_internal extrgbx_ycc_convert_internal
-#define rgb_gray_convert_internal extrgbx_gray_convert_internal
-#define rgb_rgb_convert_internal extrgbx_rgb_convert_internal
+#define RGB_RED EXT_RGBX_RED
+#define RGB_GREEN EXT_RGBX_GREEN
+#define RGB_BLUE EXT_RGBX_BLUE
+#define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
+#define rgb_ycc_convert_internal extrgbx_ycc_convert_internal
+#define rgb_gray_convert_internal extrgbx_gray_convert_internal
+#define rgb_rgb_convert_internal extrgbx_rgb_convert_internal
#include "jccolext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef rgb_gray_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_BGR_RED
-#define RGB_GREEN EXT_BGR_GREEN
-#define RGB_BLUE EXT_BGR_BLUE
-#define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
-#define rgb_ycc_convert_internal extbgr_ycc_convert_internal
-#define rgb_gray_convert_internal extbgr_gray_convert_internal
-#define rgb_rgb_convert_internal extbgr_rgb_convert_internal
+#define RGB_RED EXT_BGR_RED
+#define RGB_GREEN EXT_BGR_GREEN
+#define RGB_BLUE EXT_BGR_BLUE
+#define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
+#define rgb_ycc_convert_internal extbgr_ycc_convert_internal
+#define rgb_gray_convert_internal extbgr_gray_convert_internal
+#define rgb_rgb_convert_internal extbgr_rgb_convert_internal
#include "jccolext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef rgb_gray_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_BGRX_RED
-#define RGB_GREEN EXT_BGRX_GREEN
-#define RGB_BLUE EXT_BGRX_BLUE
-#define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
-#define rgb_ycc_convert_internal extbgrx_ycc_convert_internal
-#define rgb_gray_convert_internal extbgrx_gray_convert_internal
-#define rgb_rgb_convert_internal extbgrx_rgb_convert_internal
+#define RGB_RED EXT_BGRX_RED
+#define RGB_GREEN EXT_BGRX_GREEN
+#define RGB_BLUE EXT_BGRX_BLUE
+#define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
+#define rgb_ycc_convert_internal extbgrx_ycc_convert_internal
+#define rgb_gray_convert_internal extbgrx_gray_convert_internal
+#define rgb_rgb_convert_internal extbgrx_rgb_convert_internal
#include "jccolext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef rgb_gray_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_XBGR_RED
-#define RGB_GREEN EXT_XBGR_GREEN
-#define RGB_BLUE EXT_XBGR_BLUE
-#define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
-#define rgb_ycc_convert_internal extxbgr_ycc_convert_internal
-#define rgb_gray_convert_internal extxbgr_gray_convert_internal
-#define rgb_rgb_convert_internal extxbgr_rgb_convert_internal
+#define RGB_RED EXT_XBGR_RED
+#define RGB_GREEN EXT_XBGR_GREEN
+#define RGB_BLUE EXT_XBGR_BLUE
+#define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
+#define rgb_ycc_convert_internal extxbgr_ycc_convert_internal
+#define rgb_gray_convert_internal extxbgr_gray_convert_internal
+#define rgb_rgb_convert_internal extxbgr_rgb_convert_internal
#include "jccolext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef rgb_gray_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_XRGB_RED
-#define RGB_GREEN EXT_XRGB_GREEN
-#define RGB_BLUE EXT_XRGB_BLUE
-#define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
-#define rgb_ycc_convert_internal extxrgb_ycc_convert_internal
-#define rgb_gray_convert_internal extxrgb_gray_convert_internal
-#define rgb_rgb_convert_internal extxrgb_rgb_convert_internal
+#define RGB_RED EXT_XRGB_RED
+#define RGB_GREEN EXT_XRGB_GREEN
+#define RGB_BLUE EXT_XRGB_BLUE
+#define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
+#define rgb_ycc_convert_internal extxrgb_ycc_convert_internal
+#define rgb_gray_convert_internal extxrgb_gray_convert_internal
+#define rgb_rgb_convert_internal extxrgb_rgb_convert_internal
#include "jccolext.c"
#undef RGB_RED
#undef RGB_GREEN
*/
METHODDEF(void)
-rgb_ycc_start (j_compress_ptr cinfo)
+rgb_ycc_start(j_compress_ptr cinfo)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
JLONG *rgb_ycc_tab;
JLONG i;
/* Allocate and fill in the conversion tables. */
cconvert->rgb_ycc_tab = rgb_ycc_tab = (JLONG *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
(TABLE_SIZE * sizeof(JLONG)));
for (i = 0; i <= MAXJSAMPLE; i++) {
- rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i;
- rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i;
- rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
- rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i;
- rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i;
+ rgb_ycc_tab[i + R_Y_OFF] = FIX(0.29900) * i;
+ rgb_ycc_tab[i + G_Y_OFF] = FIX(0.58700) * i;
+ rgb_ycc_tab[i + B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
+ rgb_ycc_tab[i + R_CB_OFF] = (-FIX(0.16874)) * i;
+ rgb_ycc_tab[i + G_CB_OFF] = (-FIX(0.33126)) * i;
/* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
* This ensures that the maximum output will round to MAXJSAMPLE
* not MAXJSAMPLE+1, and thus that we don't have to range-limit.
*/
- rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
+ rgb_ycc_tab[i + B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF - 1;
/* B=>Cb and R=>Cr tables are the same
- rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
+ rgb_ycc_tab[i + R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF - 1;
*/
- rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i;
- rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i;
+ rgb_ycc_tab[i + G_CR_OFF] = (-FIX(0.41869)) * i;
+ rgb_ycc_tab[i + B_CR_OFF] = (-FIX(0.08131)) * i;
}
}
*/
METHODDEF(void)
-rgb_ycc_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
{
switch (cinfo->in_color_space) {
- case JCS_EXT_RGB:
- extrgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- extrgbx_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_BGR:
- extbgr_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- extbgrx_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- extxbgr_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- extxrgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- default:
- rgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
+ case JCS_EXT_RGB:
+ extrgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ extrgbx_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_BGR:
+ extbgr_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ extbgrx_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ extxbgr_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ extxrgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ default:
+ rgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
}
}
*/
METHODDEF(void)
-rgb_gray_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
{
switch (cinfo->in_color_space) {
- case JCS_EXT_RGB:
- extrgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- extrgbx_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_BGR:
- extbgr_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- extbgrx_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- extxbgr_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- extxrgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- default:
- rgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
+ case JCS_EXT_RGB:
+ extrgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ extrgbx_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_BGR:
+ extbgr_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ extbgrx_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ extxbgr_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ extxrgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ default:
+ rgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
}
}
*/
METHODDEF(void)
-rgb_rgb_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+rgb_rgb_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
{
switch (cinfo->in_color_space) {
- case JCS_EXT_RGB:
- extrgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- extrgbx_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_BGR:
- extbgr_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- extbgrx_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- extxbgr_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- extxrgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- default:
- rgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
+ case JCS_EXT_RGB:
+ extrgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ extrgbx_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_BGR:
+ extbgr_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ extbgrx_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ extxbgr_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ extxrgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ default:
+ rgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
}
}
*/
METHODDEF(void)
-cmyk_ycck_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+cmyk_ycck_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int r, g, b;
register JLONG *ctab = cconvert->rgb_ycc_tab;
register JSAMPROW inptr;
* need the general RIGHT_SHIFT macro.
*/
/* Y */
- outptr0[col] = (JSAMPLE)
- ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
- >> SCALEBITS);
+ outptr0[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] +
+ ctab[b + B_Y_OFF]) >> SCALEBITS);
/* Cb */
- outptr1[col] = (JSAMPLE)
- ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
- >> SCALEBITS);
+ outptr1[col] = (JSAMPLE)((ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] +
+ ctab[b + B_CB_OFF]) >> SCALEBITS);
/* Cr */
- outptr2[col] = (JSAMPLE)
- ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
- >> SCALEBITS);
+ outptr2[col] = (JSAMPLE)((ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] +
+ ctab[b + B_CR_OFF]) >> SCALEBITS);
}
}
}
*/
METHODDEF(void)
-grayscale_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+grayscale_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
{
register JSAMPROW inptr;
register JSAMPROW outptr;
*/
METHODDEF(void)
-null_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
{
register JSAMPROW inptr;
register JSAMPROW outptr, outptr0, outptr1, outptr2, outptr3;
*/
METHODDEF(void)
-null_method (j_compress_ptr cinfo)
+null_method(j_compress_ptr cinfo)
{
/* no work needed */
}
*/
GLOBAL(void)
-jinit_color_converter (j_compress_ptr cinfo)
+jinit_color_converter(j_compress_ptr cinfo)
{
my_cconvert_ptr cconvert;
cconvert = (my_cconvert_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_color_converter));
- cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
+ cinfo->cconvert = (struct jpeg_color_converter *)cconvert;
/* set start_pass to null method until we find out differently */
cconvert->pub.start_pass = null_method;
FAST_FLOAT *divisors,
FAST_FLOAT *workspace);
-METHODDEF(void) quantize (JCOEFPTR, DCTELEM *, DCTELEM *);
+METHODDEF(void) quantize(JCOEFPTR, DCTELEM *, DCTELEM *);
typedef struct {
struct jpeg_forward_dct pub; /* public fields */
*/
LOCAL(int)
-flss (UINT16 val)
+flss(UINT16 val)
{
int bit;
*/
LOCAL(int)
-compute_reciprocal (UINT16 divisor, DCTELEM *dtbl)
+compute_reciprocal(UINT16 divisor, DCTELEM *dtbl)
{
UDCTELEM2 fq, fr;
UDCTELEM c;
* identity function. Since only the C quantization algorithm is used in
* these cases, the scale value is irrelevant.
*/
- dtbl[DCTSIZE2 * 0] = (DCTELEM) 1; /* reciprocal */
- dtbl[DCTSIZE2 * 1] = (DCTELEM) 0; /* correction */
- dtbl[DCTSIZE2 * 2] = (DCTELEM) 1; /* scale */
- dtbl[DCTSIZE2 * 3] = -(DCTELEM) (sizeof(DCTELEM) * 8); /* shift */
+ dtbl[DCTSIZE2 * 0] = (DCTELEM)1; /* reciprocal */
+ dtbl[DCTSIZE2 * 1] = (DCTELEM)0; /* correction */
+ dtbl[DCTSIZE2 * 2] = (DCTELEM)1; /* scale */
+ dtbl[DCTSIZE2 * 3] = -(DCTELEM)(sizeof(DCTELEM) * 8); /* shift */
return 0;
}
fq = ((UDCTELEM2)1 << r) / divisor;
fr = ((UDCTELEM2)1 << r) % divisor;
- c = divisor / 2; /* for rounding */
+ c = divisor / 2; /* for rounding */
- if (fr == 0) { /* divisor is power of two */
+ if (fr == 0) { /* divisor is power of two */
/* fq will be one bit too large to fit in DCTELEM, so adjust */
fq >>= 1;
r--;
- } else if (fr <= (divisor / 2U)) { /* fractional part is < 0.5 */
+ } else if (fr <= (divisor / 2U)) { /* fractional part is < 0.5 */
c++;
- } else { /* fractional part is > 0.5 */
+ } else { /* fractional part is > 0.5 */
fq++;
}
- dtbl[DCTSIZE2 * 0] = (DCTELEM) fq; /* reciprocal */
- dtbl[DCTSIZE2 * 1] = (DCTELEM) c; /* correction + roundfactor */
+ dtbl[DCTSIZE2 * 0] = (DCTELEM)fq; /* reciprocal */
+ dtbl[DCTSIZE2 * 1] = (DCTELEM)c; /* correction + roundfactor */
#ifdef WITH_SIMD
- dtbl[DCTSIZE2 * 2] = (DCTELEM) (1 << (sizeof(DCTELEM)*8*2 - r)); /* scale */
+ dtbl[DCTSIZE2 * 2] = (DCTELEM)(1 << (sizeof(DCTELEM) * 8 * 2 - r)); /* scale */
#else
dtbl[DCTSIZE2 * 2] = 1;
#endif
- dtbl[DCTSIZE2 * 3] = (DCTELEM) r - sizeof(DCTELEM)*8; /* shift */
+ dtbl[DCTSIZE2 * 3] = (DCTELEM)r - sizeof(DCTELEM) * 8; /* shift */
if (r <= 16) return 0;
else return 1;
*/
METHODDEF(void)
-start_pass_fdctmgr (j_compress_ptr cinfo)
+start_pass_fdctmgr(j_compress_ptr cinfo)
{
- my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
+ my_fdct_ptr fdct = (my_fdct_ptr)cinfo->fdct;
int ci, qtblno, i;
jpeg_component_info *compptr;
JQUANT_TBL *qtbl;
*/
if (fdct->divisors[qtblno] == NULL) {
fdct->divisors[qtblno] = (DCTELEM *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
(DCTSIZE2 * 4) * sizeof(DCTELEM));
}
dtbl = fdct->divisors[qtblno];
fdct->quantize == jsimd_quantize)
fdct->quantize = quantize;
#else
- dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3;
+ dtbl[i] = ((DCTELEM)qtbl->quantval[i]) << 3;
#endif
}
break;
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
* We apply a further scale factor of 8.
*/
-#define CONST_BITS 14
+#define CONST_BITS 14
static const INT16 aanscales[DCTSIZE2] = {
/* precomputed values scaled up by 14 bits */
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
if (fdct->divisors[qtblno] == NULL) {
fdct->divisors[qtblno] = (DCTELEM *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
(DCTSIZE2 * 4) * sizeof(DCTELEM));
}
dtbl = fdct->divisors[qtblno];
for (i = 0; i < DCTSIZE2; i++) {
#if BITS_IN_JSAMPLE == 8
if (!compute_reciprocal(
- DESCALE(MULTIPLY16V16((JLONG) qtbl->quantval[i],
- (JLONG) aanscales[i]),
- CONST_BITS-3), &dtbl[i]) &&
+ DESCALE(MULTIPLY16V16((JLONG)qtbl->quantval[i],
+ (JLONG)aanscales[i]),
+ CONST_BITS - 3), &dtbl[i]) &&
fdct->quantize == jsimd_quantize)
fdct->quantize = quantize;
#else
- dtbl[i] = (DCTELEM)
- DESCALE(MULTIPLY16V16((JLONG) qtbl->quantval[i],
- (JLONG) aanscales[i]),
- CONST_BITS-3);
+ dtbl[i] = (DCTELEM)
+ DESCALE(MULTIPLY16V16((JLONG)qtbl->quantval[i],
+ (JLONG)aanscales[i]),
+ CONST_BITS - 3);
#endif
}
}
if (fdct->float_divisors[qtblno] == NULL) {
fdct->float_divisors[qtblno] = (FAST_FLOAT *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
DCTSIZE2 * sizeof(FAST_FLOAT));
}
fdtbl = fdct->float_divisors[qtblno];
for (row = 0; row < DCTSIZE; row++) {
for (col = 0; col < DCTSIZE; col++) {
fdtbl[i] = (FAST_FLOAT)
- (1.0 / (((double) qtbl->quantval[i] *
+ (1.0 / (((double)qtbl->quantval[i] *
aanscalefactor[row] * aanscalefactor[col] * 8.0)));
i++;
}
*/
METHODDEF(void)
-convsamp (JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace)
+convsamp(JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace)
{
register DCTELEM *workspaceptr;
register JSAMPROW elemptr;
*/
METHODDEF(void)
-quantize (JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace)
+quantize(JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace)
{
int i;
DCTELEM temp;
if (temp < 0) {
temp = -temp;
product = (UDCTELEM2)(temp + corr) * recip;
- product >>= shift + sizeof(DCTELEM)*8;
+ product >>= shift + sizeof(DCTELEM) * 8;
temp = (DCTELEM)product;
temp = -temp;
} else {
product = (UDCTELEM2)(temp + corr) * recip;
- product >>= shift + sizeof(DCTELEM)*8;
+ product >>= shift + sizeof(DCTELEM) * 8;
temp = (DCTELEM)product;
}
- output_ptr[i] = (JCOEF) temp;
+ output_ptr[i] = (JCOEF)temp;
}
#else
* If your machine's division is fast enough, define FAST_DIVIDE.
*/
#ifdef FAST_DIVIDE
-#define DIVIDE_BY(a,b) a /= b
+#define DIVIDE_BY(a, b) a /= b
#else
-#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0
+#define DIVIDE_BY(a, b) if (a >= b) a /= b; else a = 0
#endif
if (temp < 0) {
temp = -temp;
- temp += qval>>1; /* for rounding */
+ temp += qval >> 1; /* for rounding */
DIVIDE_BY(temp, qval);
temp = -temp;
} else {
- temp += qval>>1; /* for rounding */
+ temp += qval >> 1; /* for rounding */
DIVIDE_BY(temp, qval);
}
- output_ptr[i] = (JCOEF) temp;
+ output_ptr[i] = (JCOEF)temp;
}
#endif
*/
METHODDEF(void)
-forward_DCT (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
- JDIMENSION start_row, JDIMENSION start_col,
- JDIMENSION num_blocks)
+forward_DCT(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+ JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks)
/* This version is used for integer DCT implementations. */
{
/* This routine is heavily used, so it's worth coding it tightly. */
- my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
+ my_fdct_ptr fdct = (my_fdct_ptr)cinfo->fdct;
DCTELEM *divisors = fdct->divisors[compptr->quant_tbl_no];
DCTELEM *workspace;
JDIMENSION bi;
#ifdef DCT_FLOAT_SUPPORTED
-
METHODDEF(void)
-convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT *workspace)
+convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col,
+ FAST_FLOAT *workspace)
{
register FAST_FLOAT *workspaceptr;
register JSAMPROW elemptr;
METHODDEF(void)
-quantize_float (JCOEFPTR coef_block, FAST_FLOAT *divisors, FAST_FLOAT *workspace)
+quantize_float(JCOEFPTR coef_block, FAST_FLOAT *divisors,
+ FAST_FLOAT *workspace)
{
register FAST_FLOAT temp;
register int i;
* The maximum coefficient size is +-16K (for 12-bit data), so this
* code should work for either 16-bit or 32-bit ints.
*/
- output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384);
+ output_ptr[i] = (JCOEF)((int)(temp + (FAST_FLOAT)16384.5) - 16384);
}
}
METHODDEF(void)
-forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
- JDIMENSION start_row, JDIMENSION start_col,
- JDIMENSION num_blocks)
+forward_DCT_float(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+ JDIMENSION start_row, JDIMENSION start_col,
+ JDIMENSION num_blocks)
/* This version is used for floating-point DCT implementations. */
{
/* This routine is heavily used, so it's worth coding it tightly. */
- my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
+ my_fdct_ptr fdct = (my_fdct_ptr)cinfo->fdct;
FAST_FLOAT *divisors = fdct->float_divisors[compptr->quant_tbl_no];
FAST_FLOAT *workspace;
JDIMENSION bi;
*/
GLOBAL(void)
-jinit_forward_dct (j_compress_ptr cinfo)
+jinit_forward_dct(j_compress_ptr cinfo)
{
my_fdct_ptr fdct;
int i;
fdct = (my_fdct_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_fdct_controller));
- cinfo->fdct = (struct jpeg_forward_dct *) fdct;
+ cinfo->fdct = (struct jpeg_forward_dct *)fdct;
fdct->pub.start_pass = start_pass_fdctmgr;
/* First determine the DCT... */
#ifdef DCT_FLOAT_SUPPORTED
if (cinfo->dct_method == JDCT_FLOAT)
fdct->float_workspace = (FAST_FLOAT *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(FAST_FLOAT) * DCTSIZE2);
else
#endif
fdct->workspace = (DCTELEM *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(DCTELEM) * DCTSIZE2);
/* Mark divisor tables unallocated */
* 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, D. R. Commander.
+ * Copyright (C) 2009-2011, 2014-2016, 2018, D. R. Commander.
* Copyright (C) 2015, Matthieu Darbois.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
* back up to the start of the current MCU. To do this, we copy state
* variables into local working storage, and update them back to the
* permanent JPEG objects only upon successful completion of an MCU.
+ *
+ * NOTE: All referenced figures are from
+ * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994.
*/
#define JPEG_INTERNALS
#endif
#ifdef USE_CLZ_INTRINSIC
-#define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x))
-#define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0)
+#define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x))
+#define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0)
#else
#include "jpeg_nbits_table.h"
-#define JPEG_NBITS(x) (jpeg_nbits_table[x])
-#define JPEG_NBITS_NONZERO(x) JPEG_NBITS(x)
-#endif
-
-#ifndef min
- #define min(a,b) ((a)<(b)?(a):(b))
+#define JPEG_NBITS(x) (jpeg_nbits_table[x])
+#define JPEG_NBITS_NONZERO(x) JPEG_NBITS(x)
#endif
*/
typedef struct {
- size_t put_buffer; /* current bit-accumulation buffer */
- int put_bits; /* # of bits now in it */
- int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+ size_t put_buffer; /* current bit-accumulation buffer */
+ int put_bits; /* # 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
*/
#ifndef NO_STRUCT_ASSIGN
-#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#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])
+#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
/* Forward declarations */
-METHODDEF(boolean) encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data);
-METHODDEF(void) finish_pass_huff (j_compress_ptr cinfo);
+METHODDEF(boolean) encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data);
+METHODDEF(void) finish_pass_huff(j_compress_ptr cinfo);
#ifdef ENTROPY_OPT_SUPPORTED
-METHODDEF(boolean) encode_mcu_gather (j_compress_ptr cinfo,
- JBLOCKROW *MCU_data);
-METHODDEF(void) finish_pass_gather (j_compress_ptr cinfo);
+METHODDEF(boolean) encode_mcu_gather(j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data);
+METHODDEF(void) finish_pass_gather(j_compress_ptr cinfo);
#endif
*/
METHODDEF(void)
-start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
+start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int ci, dctbl, actbl;
jpeg_component_info *compptr;
/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
if (entropy->dc_count_ptrs[dctbl] == NULL)
entropy->dc_count_ptrs[dctbl] = (long *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
257 * sizeof(long));
MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * sizeof(long));
if (entropy->ac_count_ptrs[actbl] == NULL)
entropy->ac_count_ptrs[actbl] = (long *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
257 * sizeof(long));
MEMZERO(entropy->ac_count_ptrs[actbl], 257 * sizeof(long));
#endif
/* Compute derived values for Huffman tables */
/* We may do this more than once for a table, but it's not expensive */
jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl,
- & entropy->dc_derived_tbls[dctbl]);
+ &entropy->dc_derived_tbls[dctbl]);
jpeg_make_c_derived_tbl(cinfo, FALSE, actbl,
- & entropy->ac_derived_tbls[actbl]);
+ &entropy->ac_derived_tbls[actbl]);
}
/* Initialize DC predictions to 0 */
entropy->saved.last_dc_val[ci] = 0;
*/
GLOBAL(void)
-jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno,
- c_derived_tbl **pdtbl)
+jpeg_make_c_derived_tbl(j_compress_ptr cinfo, boolean isDC, int tblno,
+ c_derived_tbl **pdtbl)
{
JHUFF_TBL *htbl;
c_derived_tbl *dtbl;
/* Allocate a workspace if we haven't already done so. */
if (*pdtbl == NULL)
*pdtbl = (c_derived_tbl *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(c_derived_tbl));
dtbl = *pdtbl;
p = 0;
for (l = 1; l <= 16; l++) {
- i = (int) htbl->bits[l];
+ i = (int)htbl->bits[l];
if (i < 0 || p + i > 256) /* protect against table overrun */
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
while (i--)
- huffsize[p++] = (char) l;
+ huffsize[p++] = (char)l;
}
huffsize[p] = 0;
lastp = p;
si = huffsize[0];
p = 0;
while (huffsize[p]) {
- while (((int) huffsize[p]) == si) {
+ while (((int)huffsize[p]) == si) {
huffcode[p++] = code;
code++;
}
/* code is now 1 more than the last code used for codelength si; but
* it must still fit in si bits, since no code is allowed to be all ones.
*/
- if (((JLONG) code) >= (((JLONG) 1) << si))
+ if (((JLONG)code) >= (((JLONG)1) << si))
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
code <<= 1;
si++;
/* Outputting bytes to the file */
/* Emit a byte, taking 'action' if must suspend. */
-#define emit_byte(state,val,action) \
- { *(state)->next_output_byte++ = (JOCTET) (val); \
- if (--(state)->free_in_buffer == 0) \
- if (! dump_buffer(state)) \
- { action; } }
+#define emit_byte(state, val, action) { \
+ *(state)->next_output_byte++ = (JOCTET)(val); \
+ if (--(state)->free_in_buffer == 0) \
+ if (!dump_buffer(state)) \
+ { action; } \
+}
LOCAL(boolean)
-dump_buffer (working_state *state)
+dump_buffer(working_state *state)
/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */
{
struct jpeg_destination_mgr *dest = state->cinfo->dest;
- if (! (*dest->empty_output_buffer) (state->cinfo))
+ if (!(*dest->empty_output_buffer) (state->cinfo))
return FALSE;
/* After a successful buffer dump, must reset buffer pointers */
state->next_output_byte = dest->next_output_byte;
*buffer++ = c; \
if (c == 0xFF) /* need to stuff a zero byte? */ \
*buffer++ = 0; \
- }
+}
#define PUT_BITS(code, size) { \
put_bits += size; \
#error Cannot determine word size
#endif
-#if SIZEOF_SIZE_T==8 || defined(_WIN64)
+#if SIZEOF_SIZE_T == 8 || defined(_WIN64)
#define EMIT_BITS(code, size) { \
CHECKBUF47() \
}
#define EMIT_CODE(code, size) { \
- temp2 &= (((JLONG) 1)<<nbits) - 1; \
+ temp2 &= (((JLONG)1) << nbits) - 1; \
CHECKBUF31() \
PUT_BITS(code, size) \
PUT_BITS(temp2, nbits) \
- }
+}
#else
}
#define EMIT_CODE(code, size) { \
- temp2 &= (((JLONG) 1)<<nbits) - 1; \
+ temp2 &= (((JLONG)1) << nbits) - 1; \
PUT_BITS(code, size) \
CHECKBUF15() \
PUT_BITS(temp2, nbits) \
CHECKBUF15() \
- }
+}
#endif
* scanning order-- 1, 8, 16, etc.), then this will produce an encoded block
* larger than 200 bytes.
*/
-#define BUFSIZE (DCTSIZE2 * 4)
+#define BUFSIZE (DCTSIZE2 * 4)
#define LOAD_BUFFER() { \
if (state->free_in_buffer < BUFSIZE) { \
localbuf = 1; \
buffer = _buffer; \
- } \
- else buffer = state->next_output_byte; \
- }
+ } else \
+ buffer = state->next_output_byte; \
+}
#define STORE_BUFFER() { \
if (localbuf) { \
bytes = buffer - _buffer; \
buffer = _buffer; \
while (bytes > 0) { \
- bytestocopy = min(bytes, state->free_in_buffer); \
+ bytestocopy = MIN(bytes, state->free_in_buffer); \
MEMCOPY(state->next_output_byte, buffer, bytestocopy); \
state->next_output_byte += bytestocopy; \
buffer += bytestocopy; \
state->free_in_buffer -= bytestocopy; \
if (state->free_in_buffer == 0) \
- if (! dump_buffer(state)) return FALSE; \
+ if (!dump_buffer(state)) return FALSE; \
bytes -= bytestocopy; \
} \
- } \
- else { \
+ } else { \
state->free_in_buffer -= (buffer - state->next_output_byte); \
state->next_output_byte = buffer; \
} \
- }
+}
LOCAL(boolean)
-flush_bits (working_state *state)
+flush_bits(working_state *state)
{
JOCTET _buffer[BUFSIZE], *buffer;
size_t put_buffer; int put_bits;
/* Encode a single block's worth of coefficients */
LOCAL(boolean)
-encode_one_block_simd (working_state *state, JCOEFPTR block, int last_dc_val,
- c_derived_tbl *dctbl, c_derived_tbl *actbl)
+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;
}
LOCAL(boolean)
-encode_one_block (working_state *state, JCOEFPTR block, int last_dc_val,
- c_derived_tbl *dctbl, c_derived_tbl *actbl)
+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;
temp = temp2 = 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.
- */
+ /* 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.
+ */
temp3 = temp >> (CHAR_BIT * sizeof(int) - 1);
temp ^= temp3;
temp -= temp3;
EMIT_BITS(code, size)
/* Mask off any extra bits in code */
- temp2 &= (((JLONG) 1)<<nbits) - 1;
+ temp2 &= (((JLONG)1) << nbits) - 1;
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
* improves performance greatly on systems with a limited number of
* registers (such as x86.)
*/
-#define kloop(jpeg_natural_order_of_k) { \
+#define kloop(jpeg_natural_order_of_k) { \
if ((temp = block[jpeg_natural_order_of_k]) == 0) { \
r++; \
} else { \
r -= 16; \
} \
/* Emit Huffman symbol for run length / number of bits */ \
- temp3 = (r << 4) + nbits; \
+ temp3 = (r << 4) + nbits; \
code = actbl->ehufco[temp3]; \
size = actbl->ehufsi[temp3]; \
EMIT_CODE(code, size) \
- r = 0; \
+ r = 0; \
} \
}
*/
LOCAL(boolean)
-emit_restart (working_state *state, int restart_num)
+emit_restart(working_state *state, int restart_num)
{
int ci;
- if (! flush_bits(state))
+ if (!flush_bits(state))
return FALSE;
emit_byte(state, 0xFF, return FALSE);
*/
METHODDEF(boolean)
-encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
working_state state;
int blkn, ci;
jpeg_component_info *compptr;
/* Emit restart marker if needed */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
- if (! emit_restart(&state, entropy->next_restart_num))
+ if (!emit_restart(&state, entropy->next_restart_num))
return FALSE;
}
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
ci = cinfo->MCU_membership[blkn];
compptr = cinfo->cur_comp_info[ci];
- if (! encode_one_block_simd(&state,
- MCU_data[blkn][0], state.cur.last_dc_val[ci],
- entropy->dc_derived_tbls[compptr->dc_tbl_no],
- entropy->ac_derived_tbls[compptr->ac_tbl_no]))
+ if (!encode_one_block_simd(&state,
+ MCU_data[blkn][0], state.cur.last_dc_val[ci],
+ entropy->dc_derived_tbls[compptr->dc_tbl_no],
+ entropy->ac_derived_tbls[compptr->ac_tbl_no]))
return FALSE;
/* Update last_dc_val */
state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
ci = cinfo->MCU_membership[blkn];
compptr = cinfo->cur_comp_info[ci];
- if (! encode_one_block(&state,
- MCU_data[blkn][0], state.cur.last_dc_val[ci],
- entropy->dc_derived_tbls[compptr->dc_tbl_no],
- entropy->ac_derived_tbls[compptr->ac_tbl_no]))
+ if (!encode_one_block(&state,
+ MCU_data[blkn][0], state.cur.last_dc_val[ci],
+ entropy->dc_derived_tbls[compptr->dc_tbl_no],
+ entropy->ac_derived_tbls[compptr->ac_tbl_no]))
return FALSE;
/* Update last_dc_val */
state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
*/
METHODDEF(void)
-finish_pass_huff (j_compress_ptr cinfo)
+finish_pass_huff(j_compress_ptr cinfo)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
working_state state;
/* Load up working state ... flush_bits needs it */
state.cinfo = cinfo;
/* Flush out the last data */
- if (! flush_bits(&state))
+ if (!flush_bits(&state))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
/* Update state */
/* Process a single block's worth of coefficients */
LOCAL(void)
-htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
- long dc_counts[], long ac_counts[])
+htest_one_block(j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
+ long dc_counts[], long ac_counts[])
{
register int temp;
register int nbits;
/* Check for out-of-range coefficient values.
* Since we're encoding a difference, the range limit is twice as much.
*/
- if (nbits > MAX_COEF_BITS+1)
+ if (nbits > MAX_COEF_BITS + 1)
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
/* Count the Huffman symbol for the number of bits */
*/
METHODDEF(boolean)
-encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_gather(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int blkn, ci;
jpeg_component_info *compptr;
* one bits (so that padding bits added at the end of a compressed segment
* can't look like a valid code). Because of the canonical ordering of
* codewords, this just means that there must be an unused slot in the
- * longest codeword length category. Section K.2 of the JPEG spec suggests
- * reserving such a slot by pretending that symbol 256 is a valid symbol
- * with count 1. In theory that's not optimal; giving it count zero but
- * including it in the symbol set anyway should give a better Huffman code.
- * But the theoretically better code actually seems to come out worse in
- * practice, because it produces more all-ones bytes (which incur stuffed
- * zero bytes in the final file). In any case the difference is tiny.
+ * longest codeword length category. Annex K (Clause K.2) of
+ * Rec. ITU-T T.81 (1992) | ISO/IEC 10918-1:1994 suggests reserving such a slot
+ * by pretending that symbol 256 is a valid symbol with count 1. In theory
+ * that's not optimal; giving it count zero but including it in the symbol set
+ * anyway should give a better Huffman code. But the theoretically better code
+ * actually seems to come out worse in practice, because it produces more
+ * all-ones bytes (which incur stuffed zero bytes in the final file). In any
+ * case the difference is tiny.
*
* The JPEG standard requires Huffman codes to be no more than 16 bits long.
* If some symbols have a very small but nonzero probability, the Huffman tree
*/
GLOBAL(void)
-jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[])
+jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[])
{
-#define MAX_CLEN 32 /* assumed maximum initial code length */
- UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */
+#define MAX_CLEN 32 /* assumed maximum initial code length */
+ UINT8 bits[MAX_CLEN + 1]; /* bits[k] = # of symbols with code length k */
int codesize[257]; /* codesize[k] = code length of symbol k */
int others[257]; /* next symbol in current branch of tree */
int c1, c2;
/* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
* Huffman procedure assigned any such lengths, we must adjust the coding.
- * Here is what the JPEG spec says about how this next bit works:
- * Since symbols are paired for the longest Huffman code, the symbols are
- * removed from this length category two at a time. The prefix for the pair
- * (which is one bit shorter) is allocated to one of the pair; then,
- * skipping the BITS entry for that prefix length, a code word from the next
- * shortest nonzero BITS entry is converted into a prefix for two code words
- * one bit longer.
+ * Here is what Rec. ITU-T T.81 | ISO/IEC 10918-1 says about how this next
+ * bit works: Since symbols are paired for the longest Huffman code, the
+ * symbols are removed from this length category two at a time. The prefix
+ * for the pair (which is one bit shorter) is allocated to one of the pair;
+ * then, skipping the BITS entry for that prefix length, a code word from the
+ * next shortest nonzero BITS entry is converted into a prefix for two code
+ * words one bit longer.
*/
for (i = MAX_CLEN; i > 16; i--) {
j--;
bits[i] -= 2; /* remove two symbols */
- bits[i-1]++; /* one goes in this length */
- bits[j+1] += 2; /* two new symbols in this length */
+ bits[i - 1]++; /* one goes in this length */
+ bits[j + 1] += 2; /* two new symbols in this length */
bits[j]--; /* symbol of this length is now a prefix */
}
}
/* Return a list of the symbols sorted by code length */
/* It's not real clear to me why we don't need to consider the codelength
- * changes made above, but the JPEG spec seems to think this works.
+ * changes made above, but Rec. ITU-T T.81 | ISO/IEC 10918-1 seems to think
+ * this works.
*/
p = 0;
for (i = 1; i <= MAX_CLEN; i++) {
for (j = 0; j <= 255; j++) {
if (codesize[j] == i) {
- htbl->huffval[p] = (UINT8) j;
+ htbl->huffval[p] = (UINT8)j;
p++;
}
}
*/
METHODDEF(void)
-finish_pass_gather (j_compress_ptr cinfo)
+finish_pass_gather(j_compress_ptr cinfo)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int ci, dctbl, actbl;
jpeg_component_info *compptr;
JHUFF_TBL **htblptr;
compptr = cinfo->cur_comp_info[ci];
dctbl = compptr->dc_tbl_no;
actbl = compptr->ac_tbl_no;
- if (! did_dc[dctbl]) {
- htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl];
+ if (!did_dc[dctbl]) {
+ htblptr = &cinfo->dc_huff_tbl_ptrs[dctbl];
if (*htblptr == NULL)
- *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo);
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]);
did_dc[dctbl] = TRUE;
}
- if (! did_ac[actbl]) {
- htblptr = & cinfo->ac_huff_tbl_ptrs[actbl];
+ if (!did_ac[actbl]) {
+ htblptr = &cinfo->ac_huff_tbl_ptrs[actbl];
if (*htblptr == NULL)
- *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo);
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]);
did_ac[actbl] = TRUE;
}
*/
GLOBAL(void)
-jinit_huff_encoder (j_compress_ptr cinfo)
+jinit_huff_encoder(j_compress_ptr cinfo)
{
huff_entropy_ptr entropy;
int i;
entropy = (huff_entropy_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(huff_entropy_encoder));
- cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
+ cinfo->entropy = (struct jpeg_entropy_encoder *)entropy;
entropy->pub.start_pass = start_pass_huff;
/* Mark tables unallocated */
*/
#if BITS_IN_JSAMPLE == 8
-#define MAX_COEF_BITS 10
+#define MAX_COEF_BITS 10
#else
-#define MAX_COEF_BITS 14
+#define MAX_COEF_BITS 14
#endif
/* Derived data constructed for each Huffman table */
} c_derived_tbl;
/* Expand a Huffman table definition into the derived format */
-EXTERN(void) jpeg_make_c_derived_tbl
- (j_compress_ptr cinfo, boolean isDC, int tblno,
- c_derived_tbl ** pdtbl);
+EXTERN(void) jpeg_make_c_derived_tbl(j_compress_ptr cinfo, boolean isDC,
+ int tblno, c_derived_tbl **pdtbl);
/* Generate an optimal table definition given the specified counts */
-EXTERN(void) jpeg_gen_optimal_table
- (j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]);
+EXTERN(void) jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl,
+ long freq[]);
*/
GLOBAL(void)
-jinit_compress_master (j_compress_ptr cinfo)
+jinit_compress_master(j_compress_ptr cinfo)
{
/* Initialize master control (includes parameter checking/processing) */
jinit_c_master_control(cinfo, FALSE /* full compression */);
/* Preprocessing */
- if (! cinfo->raw_data_in) {
+ if (!cinfo->raw_data_in) {
jinit_color_converter(cinfo);
jinit_downsampler(cinfo);
jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */);
}
/* Need a full-image coefficient buffer in any multi-pass mode. */
- jinit_c_coef_controller(cinfo,
- (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding));
+ jinit_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 ||
+ cinfo->optimize_coding));
jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
jinit_marker_writer(cinfo);
/* We can now tell the memory manager to allocate virtual arrays. */
- (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo);
/* Write the datastream header (SOI) immediately.
* Frame and scan headers are postponed till later.
/* Forward declarations */
-METHODDEF(void) process_data_simple_main
- (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
- JDIMENSION in_rows_avail);
+METHODDEF(void) process_data_simple_main(j_compress_ptr cinfo,
+ JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail);
/*
*/
METHODDEF(void)
-start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+start_pass_main(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
/* Do nothing in raw-data mode. */
if (cinfo->raw_data_in)
*/
METHODDEF(void)
-process_data_simple_main (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
- JDIMENSION in_rows_avail)
+process_data_simple_main(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
while (main_ptr->cur_iMCU_row < cinfo->total_iMCU_rows) {
/* Read input data if we haven't filled the main buffer yet */
if (main_ptr->rowgroup_ctr < DCTSIZE)
- (*cinfo->prep->pre_process_data) (cinfo,
- input_buf, in_row_ctr, in_rows_avail,
- main_ptr->buffer, &main_ptr->rowgroup_ctr,
- (JDIMENSION) DCTSIZE);
+ (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr,
+ in_rows_avail, main_ptr->buffer,
+ &main_ptr->rowgroup_ctr,
+ (JDIMENSION)DCTSIZE);
/* If we don't have a full iMCU row buffered, return to application for
* more data. Note that preprocessor will always pad to fill the iMCU row
return;
/* Send the completed row to the compressor */
- if (! (*cinfo->coef->compress_data) (cinfo, main_ptr->buffer)) {
+ if (!(*cinfo->coef->compress_data) (cinfo, main_ptr->buffer)) {
/* If compressor did not consume the whole row, then we must need to
* suspend processing and return to the application. In this situation
* we pretend we didn't yet consume the last input row; otherwise, if
* it happened to be the last row of the image, the application would
* think we were done.
*/
- if (! main_ptr->suspended) {
+ if (!main_ptr->suspended) {
(*in_row_ctr)--;
main_ptr->suspended = TRUE;
}
*/
GLOBAL(void)
-jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer)
{
my_main_ptr main_ptr;
int ci;
jpeg_component_info *compptr;
main_ptr = (my_main_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_main_controller));
- cinfo->main = (struct jpeg_c_main_controller *) main_ptr;
+ cinfo->main = (struct jpeg_c_main_controller *)main_ptr;
main_ptr->pub.start_pass = start_pass_main;
/* We don't need to create a buffer in raw-data mode. */
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
main_ptr->buffer[ci] = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
compptr->width_in_blocks * DCTSIZE,
- (JDIMENSION) (compptr->v_samp_factor * DCTSIZE));
+ (JDIMENSION)(compptr->v_samp_factor * DCTSIZE));
}
}
}
*/
LOCAL(void)
-emit_byte (j_compress_ptr cinfo, int val)
+emit_byte(j_compress_ptr cinfo, int val)
/* Emit a byte */
{
struct jpeg_destination_mgr *dest = cinfo->dest;
- *(dest->next_output_byte)++ = (JOCTET) val;
+ *(dest->next_output_byte)++ = (JOCTET)val;
if (--dest->free_in_buffer == 0) {
- if (! (*dest->empty_output_buffer) (cinfo))
+ if (!(*dest->empty_output_buffer) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
}
}
LOCAL(void)
-emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark)
+emit_marker(j_compress_ptr cinfo, JPEG_MARKER mark)
/* Emit a marker code */
{
emit_byte(cinfo, 0xFF);
- emit_byte(cinfo, (int) mark);
+ emit_byte(cinfo, (int)mark);
}
LOCAL(void)
-emit_2bytes (j_compress_ptr cinfo, int value)
+emit_2bytes(j_compress_ptr cinfo, int value)
/* Emit a 2-byte integer; these are always MSB first in JPEG files */
{
emit_byte(cinfo, (value >> 8) & 0xFF);
*/
LOCAL(int)
-emit_dqt (j_compress_ptr cinfo, int index)
+emit_dqt(j_compress_ptr cinfo, int index)
/* Emit a DQT marker */
/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
{
prec = 1;
}
- if (! qtbl->sent_table) {
+ if (!qtbl->sent_table) {
emit_marker(cinfo, M_DQT);
- emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
+ emit_2bytes(cinfo, prec ? DCTSIZE2 * 2 + 1 + 2 : DCTSIZE2 + 1 + 2);
- emit_byte(cinfo, index + (prec<<4));
+ emit_byte(cinfo, index + (prec << 4));
for (i = 0; i < DCTSIZE2; i++) {
/* The table entries must be emitted in zigzag order. */
unsigned int qval = qtbl->quantval[jpeg_natural_order[i]];
if (prec)
- emit_byte(cinfo, (int) (qval >> 8));
- emit_byte(cinfo, (int) (qval & 0xFF));
+ emit_byte(cinfo, (int)(qval >> 8));
+ emit_byte(cinfo, (int)(qval & 0xFF));
}
qtbl->sent_table = TRUE;
LOCAL(void)
-emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
+emit_dht(j_compress_ptr cinfo, int index, boolean is_ac)
/* Emit a DHT marker */
{
JHUFF_TBL *htbl;
if (htbl == NULL)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index);
- if (! htbl->sent_table) {
+ if (!htbl->sent_table) {
emit_marker(cinfo, M_DHT);
length = 0;
LOCAL(void)
-emit_dac (j_compress_ptr cinfo)
+emit_dac(j_compress_ptr cinfo)
/* Emit a DAC marker */
/* Since the useful info is so small, we want to emit all the tables in */
/* one DAC marker. Therefore this routine does its own scan of the table. */
if (length) {
emit_marker(cinfo, M_DAC);
- emit_2bytes(cinfo, length*2 + 2);
+ emit_2bytes(cinfo, length * 2 + 2);
for (i = 0; i < NUM_ARITH_TBLS; i++) {
if (dc_in_use[i]) {
emit_byte(cinfo, i);
- emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
+ emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i] << 4));
}
if (ac_in_use[i]) {
emit_byte(cinfo, i + 0x10);
LOCAL(void)
-emit_dri (j_compress_ptr cinfo)
+emit_dri(j_compress_ptr cinfo)
/* Emit a DRI marker */
{
emit_marker(cinfo, M_DRI);
emit_2bytes(cinfo, 4); /* fixed length */
- emit_2bytes(cinfo, (int) cinfo->restart_interval);
+ emit_2bytes(cinfo, (int)cinfo->restart_interval);
}
LOCAL(void)
-emit_sof (j_compress_ptr cinfo, JPEG_MARKER code)
+emit_sof(j_compress_ptr cinfo, JPEG_MARKER code)
/* Emit a SOF marker */
{
int ci;
emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */
/* Make sure image isn't bigger than SOF field can handle */
- if ((long) cinfo->_jpeg_height > 65535L ||
- (long) cinfo->_jpeg_width > 65535L)
- ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535);
+ if ((long)cinfo->_jpeg_height > 65535L || (long)cinfo->_jpeg_width > 65535L)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int)65535);
emit_byte(cinfo, cinfo->data_precision);
- emit_2bytes(cinfo, (int) cinfo->_jpeg_height);
- emit_2bytes(cinfo, (int) cinfo->_jpeg_width);
+ emit_2bytes(cinfo, (int)cinfo->_jpeg_height);
+ emit_2bytes(cinfo, (int)cinfo->_jpeg_width);
emit_byte(cinfo, cinfo->num_components);
LOCAL(void)
-emit_sos (j_compress_ptr cinfo)
+emit_sos(j_compress_ptr cinfo)
/* Emit a SOS marker */
{
int i, td, ta;
LOCAL(void)
-emit_jfif_app0 (j_compress_ptr cinfo)
+emit_jfif_app0(j_compress_ptr cinfo)
/* Emit a JFIF-compliant APP0 marker */
{
/*
emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */
emit_byte(cinfo, cinfo->JFIF_minor_version);
emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
- emit_2bytes(cinfo, (int) cinfo->X_density);
- emit_2bytes(cinfo, (int) cinfo->Y_density);
+ emit_2bytes(cinfo, (int)cinfo->X_density);
+ emit_2bytes(cinfo, (int)cinfo->Y_density);
emit_byte(cinfo, 0); /* No thumbnail image */
emit_byte(cinfo, 0);
}
LOCAL(void)
-emit_adobe_app14 (j_compress_ptr cinfo)
+emit_adobe_app14(j_compress_ptr cinfo)
/* Emit an Adobe APP14 marker */
{
/*
*/
METHODDEF(void)
-write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
+write_marker_header(j_compress_ptr cinfo, int marker, unsigned int datalen)
/* Emit an arbitrary marker header */
{
- if (datalen > (unsigned int) 65533) /* safety check */
+ if (datalen > (unsigned int)65533) /* safety check */
ERREXIT(cinfo, JERR_BAD_LENGTH);
- emit_marker(cinfo, (JPEG_MARKER) marker);
+ emit_marker(cinfo, (JPEG_MARKER)marker);
- emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */
+ emit_2bytes(cinfo, (int)(datalen + 2)); /* total length */
}
METHODDEF(void)
-write_marker_byte (j_compress_ptr cinfo, int val)
+write_marker_byte(j_compress_ptr cinfo, int val)
/* Emit one byte of marker parameters following write_marker_header */
{
emit_byte(cinfo, val);
*/
METHODDEF(void)
-write_file_header (j_compress_ptr cinfo)
+write_file_header(j_compress_ptr cinfo)
{
- my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
emit_marker(cinfo, M_SOI); /* first the SOI */
*/
METHODDEF(void)
-write_frame_header (j_compress_ptr cinfo)
+write_frame_header(j_compress_ptr cinfo)
{
int ci, prec;
boolean is_baseline;
*/
METHODDEF(void)
-write_scan_header (j_compress_ptr cinfo)
+write_scan_header(j_compress_ptr cinfo)
{
- my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
int i;
jpeg_component_info *compptr;
*/
METHODDEF(void)
-write_file_trailer (j_compress_ptr cinfo)
+write_file_trailer(j_compress_ptr cinfo)
{
emit_marker(cinfo, M_EOI);
}
*/
METHODDEF(void)
-write_tables_only (j_compress_ptr cinfo)
+write_tables_only(j_compress_ptr cinfo)
{
int i;
for (i = 0; i < NUM_QUANT_TBLS; i++) {
if (cinfo->quant_tbl_ptrs[i] != NULL)
- (void) emit_dqt(cinfo, i);
+ (void)emit_dqt(cinfo, i);
}
- if (! cinfo->arith_code) {
+ if (!cinfo->arith_code) {
for (i = 0; i < NUM_HUFF_TBLS; i++) {
if (cinfo->dc_huff_tbl_ptrs[i] != NULL)
emit_dht(cinfo, i, FALSE);
*/
GLOBAL(void)
-jinit_marker_writer (j_compress_ptr cinfo)
+jinit_marker_writer(j_compress_ptr cinfo)
{
my_marker_ptr marker;
/* Create the subobject */
marker = (my_marker_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_marker_writer));
- cinfo->marker = (struct jpeg_marker_writer *) marker;
+ cinfo->marker = (struct jpeg_marker_writer *)marker;
/* Initialize method pointers */
marker->pub.write_file_header = write_file_header;
marker->pub.write_frame_header = write_frame_header;
* Copyright (C) 1991-1997, Thomas G. Lane.
* Modified 2003-2010 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2010, 2016, D. R. Commander.
+ * Copyright (C) 2010, 2016, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
/* Private state */
typedef enum {
- main_pass, /* input data, also do first output step */
- huff_opt_pass, /* Huffman code optimization pass */
- output_pass /* data output pass */
+ main_pass, /* input data, also do first output step */
+ huff_opt_pass, /* Huffman code optimization pass */
+ output_pass /* data output pass */
} c_pass_type;
typedef struct {
*/
GLOBAL(void)
-jpeg_calc_jpeg_dimensions (j_compress_ptr cinfo)
+jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo)
/* Do computations that are needed before master selection phase */
{
/* Hardwire it to "no scaling" */
LOCAL(void)
-initial_setup (j_compress_ptr cinfo, boolean transcode_only)
+initial_setup(j_compress_ptr cinfo, boolean transcode_only)
/* Do computations that are needed before master selection phase */
{
int ci;
#endif
/* Sanity check on image dimensions */
- if (cinfo->_jpeg_height <= 0 || cinfo->_jpeg_width <= 0
- || cinfo->num_components <= 0 || cinfo->input_components <= 0)
+ if (cinfo->_jpeg_height <= 0 || cinfo->_jpeg_width <= 0 ||
+ cinfo->num_components <= 0 || cinfo->input_components <= 0)
ERREXIT(cinfo, JERR_EMPTY_IMAGE);
/* Make sure image isn't bigger than I can handle */
- if ((long) cinfo->_jpeg_height > (long) JPEG_MAX_DIMENSION ||
- (long) cinfo->_jpeg_width > (long) JPEG_MAX_DIMENSION)
- ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
+ if ((long)cinfo->_jpeg_height > (long)JPEG_MAX_DIMENSION ||
+ (long)cinfo->_jpeg_width > (long)JPEG_MAX_DIMENSION)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int)JPEG_MAX_DIMENSION);
/* Width of an input scanline must be representable as JDIMENSION. */
- samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components;
- jd_samplesperrow = (JDIMENSION) samplesperrow;
- if ((long) jd_samplesperrow != samplesperrow)
+ samplesperrow = (long)cinfo->image_width * (long)cinfo->input_components;
+ jd_samplesperrow = (JDIMENSION)samplesperrow;
+ if ((long)jd_samplesperrow != samplesperrow)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
/* For now, precision must match compiled-in value... */
cinfo->max_v_samp_factor = 1;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
- if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
- compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
+ if (compptr->h_samp_factor <= 0 ||
+ compptr->h_samp_factor > MAX_SAMP_FACTOR ||
+ compptr->v_samp_factor <= 0 ||
+ compptr->v_samp_factor > MAX_SAMP_FACTOR)
ERREXIT(cinfo, JERR_BAD_SAMPLING);
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
compptr->h_samp_factor);
#endif
/* Size in DCT blocks */
compptr->width_in_blocks = (JDIMENSION)
- jdiv_round_up((long) cinfo->_jpeg_width * (long) compptr->h_samp_factor,
- (long) (cinfo->max_h_samp_factor * DCTSIZE));
+ jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor,
+ (long)(cinfo->max_h_samp_factor * DCTSIZE));
compptr->height_in_blocks = (JDIMENSION)
- jdiv_round_up((long) cinfo->_jpeg_height * (long) compptr->v_samp_factor,
- (long) (cinfo->max_v_samp_factor * DCTSIZE));
+ jdiv_round_up((long)cinfo->_jpeg_height * (long)compptr->v_samp_factor,
+ (long)(cinfo->max_v_samp_factor * DCTSIZE));
/* Size in samples */
compptr->downsampled_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->_jpeg_width * (long) compptr->h_samp_factor,
- (long) cinfo->max_h_samp_factor);
+ jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor,
+ (long)cinfo->max_h_samp_factor);
compptr->downsampled_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->_jpeg_height * (long) compptr->v_samp_factor,
- (long) cinfo->max_v_samp_factor);
+ jdiv_round_up((long)cinfo->_jpeg_height * (long)compptr->v_samp_factor,
+ (long)cinfo->max_v_samp_factor);
/* Mark component needed (this flag isn't actually used for compression) */
compptr->component_needed = TRUE;
}
* main controller will call coefficient controller).
*/
cinfo->total_iMCU_rows = (JDIMENSION)
- jdiv_round_up((long) cinfo->_jpeg_height,
- (long) (cinfo->max_v_samp_factor*DCTSIZE));
+ jdiv_round_up((long)cinfo->_jpeg_height,
+ (long)(cinfo->max_v_samp_factor * DCTSIZE));
}
#ifdef C_MULTISCAN_FILES_SUPPORTED
LOCAL(void)
-validate_script (j_compress_ptr cinfo)
+validate_script(j_compress_ptr cinfo)
/* Verify that the scan script in cinfo->scan_info[] is valid; also
* determine whether it uses progressive JPEG, and set cinfo->progressive_mode.
*/
* for progressive JPEG, no scan can have this.
*/
scanptr = cinfo->scan_info;
- if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) {
+ if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2 - 1) {
#ifdef C_PROGRESSIVE_SUPPORTED
cinfo->progressive_mode = TRUE;
- last_bitpos_ptr = & last_bitpos[0][0];
+ last_bitpos_ptr = &last_bitpos[0][0];
for (ci = 0; ci < cinfo->num_components; ci++)
for (coefi = 0; coefi < DCTSIZE2; coefi++)
*last_bitpos_ptr++ = -1;
if (thisi < 0 || thisi >= cinfo->num_components)
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
/* Components must appear in SOF order within each scan */
- if (ci > 0 && thisi <= scanptr->component_index[ci-1])
+ if (ci > 0 && thisi <= scanptr->component_index[ci - 1])
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
}
/* Validate progression parameters */
Al = scanptr->Al;
if (cinfo->progressive_mode) {
#ifdef C_PROGRESSIVE_SUPPORTED
- /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
- * seems wrong: the upper bound ought to depend on data precision.
- * Perhaps they really meant 0..N+1 for N-bit precision.
+ /* Rec. ITU-T T.81 | ISO/IEC 10918-1 simply gives the ranges 0..13 for Ah
+ * and Al, but that seems wrong: the upper bound ought to depend on data
+ * precision. Perhaps they really meant 0..N+1 for N-bit precision.
* Here we allow 0..10 for 8-bit data; Al larger than 10 results in
* out-of-range reconstructed DC values during the first DC scan,
* which might cause problems for some decoders.
*/
#if BITS_IN_JSAMPLE == 8
-#define MAX_AH_AL 10
+#define MAX_AH_AL 10
#else
-#define MAX_AH_AL 13
+#define MAX_AH_AL 13
#endif
if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
}
for (ci = 0; ci < ncomps; ci++) {
- last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0];
+ last_bitpos_ptr = &last_bitpos[scanptr->component_index[ci]][0];
if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
for (coefi = Ss; coefi <= Se; coefi++) {
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
} else {
/* not first scan */
- if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1)
+ if (Ah != last_bitpos_ptr[coefi] || Al != Ah - 1)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
}
last_bitpos_ptr[coefi] = Al;
#endif
} else {
/* For sequential JPEG, all progression parameters must be these: */
- if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0)
+ if (Ss != 0 || Se != DCTSIZE2 - 1 || Ah != 0 || Al != 0)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
/* Make sure components are not sent twice */
for (ci = 0; ci < ncomps; ci++) {
#endif
} else {
for (ci = 0; ci < cinfo->num_components; ci++) {
- if (! component_sent[ci])
+ if (!component_sent[ci])
ERREXIT(cinfo, JERR_MISSING_DATA);
}
}
LOCAL(void)
-select_scan_parameters (j_compress_ptr cinfo)
+select_scan_parameters(j_compress_ptr cinfo)
/* Set up the scan parameters for the current scan */
{
int ci;
#ifdef C_MULTISCAN_FILES_SUPPORTED
if (cinfo->scan_info != NULL) {
/* Prepare for current scan --- the script is already validated */
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
const jpeg_scan_info *scanptr = cinfo->scan_info + master->scan_number;
cinfo->comps_in_scan = scanptr->comps_in_scan;
cinfo->Se = scanptr->Se;
cinfo->Ah = scanptr->Ah;
cinfo->Al = scanptr->Al;
- }
- else
+ } else
#endif
{
/* Prepare for single sequential-JPEG scan containing all components */
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
}
cinfo->Ss = 0;
- cinfo->Se = DCTSIZE2-1;
+ cinfo->Se = DCTSIZE2 - 1;
cinfo->Ah = 0;
cinfo->Al = 0;
}
LOCAL(void)
-per_scan_setup (j_compress_ptr cinfo)
+per_scan_setup(j_compress_ptr cinfo)
/* Do computations that are needed before processing a JPEG scan */
/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */
{
/* For noninterleaved scans, it is convenient to define last_row_height
* as the number of block rows present in the last iMCU row.
*/
- tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ tmp = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
if (tmp == 0) tmp = compptr->v_samp_factor;
compptr->last_row_height = tmp;
/* Overall image size in MCUs */
cinfo->MCUs_per_row = (JDIMENSION)
- jdiv_round_up((long) cinfo->_jpeg_width,
- (long) (cinfo->max_h_samp_factor*DCTSIZE));
+ jdiv_round_up((long)cinfo->_jpeg_width,
+ (long)(cinfo->max_h_samp_factor * DCTSIZE));
cinfo->MCU_rows_in_scan = (JDIMENSION)
- jdiv_round_up((long) cinfo->_jpeg_height,
- (long) (cinfo->max_v_samp_factor*DCTSIZE));
+ jdiv_round_up((long)cinfo->_jpeg_height,
+ (long)(cinfo->max_v_samp_factor * DCTSIZE));
cinfo->blocks_in_MCU = 0;
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE;
/* Figure number of non-dummy blocks in last MCU column & row */
- tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
+ tmp = (int)(compptr->width_in_blocks % compptr->MCU_width);
if (tmp == 0) tmp = compptr->MCU_width;
compptr->last_col_width = tmp;
- tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
+ tmp = (int)(compptr->height_in_blocks % compptr->MCU_height);
if (tmp == 0) tmp = compptr->MCU_height;
compptr->last_row_height = tmp;
/* Prepare array describing MCU composition */
/* Convert restart specified in rows to actual MCU count. */
/* Note that count must fit in 16 bits, so we provide limiting. */
if (cinfo->restart_in_rows > 0) {
- long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row;
- cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L);
+ long nominal = (long)cinfo->restart_in_rows * (long)cinfo->MCUs_per_row;
+ cinfo->restart_interval = (unsigned int)MIN(nominal, 65535L);
}
}
*/
METHODDEF(void)
-prepare_for_pass (j_compress_ptr cinfo)
+prepare_for_pass(j_compress_ptr cinfo)
{
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
switch (master->pass_type) {
case main_pass:
*/
select_scan_parameters(cinfo);
per_scan_setup(cinfo);
- if (! cinfo->raw_data_in) {
+ if (!cinfo->raw_data_in) {
(*cinfo->cconvert->start_pass) (cinfo);
(*cinfo->downsample->start_pass) (cinfo);
(*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
case output_pass:
/* Do a data-output pass. */
/* We need not repeat per-scan setup if prior optimization pass did it. */
- if (! cinfo->optimize_coding) {
+ if (!cinfo->optimize_coding) {
select_scan_parameters(cinfo);
per_scan_setup(cinfo);
}
ERREXIT(cinfo, JERR_NOT_COMPILED);
}
- master->pub.is_last_pass = (master->pass_number == master->total_passes-1);
+ master->pub.is_last_pass = (master->pass_number == master->total_passes - 1);
/* Set up progress monitor's pass info if present */
if (cinfo->progress != NULL) {
*/
METHODDEF(void)
-pass_startup (j_compress_ptr cinfo)
+pass_startup(j_compress_ptr cinfo)
{
cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */
*/
METHODDEF(void)
-finish_pass_master (j_compress_ptr cinfo)
+finish_pass_master(j_compress_ptr cinfo)
{
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
/* The entropy coder always needs an end-of-pass call,
* either to analyze statistics or to flush its output buffer.
* or output of scan 1 (if no optimization).
*/
master->pass_type = output_pass;
- if (! cinfo->optimize_coding)
+ if (!cinfo->optimize_coding)
master->scan_number++;
break;
case huff_opt_pass:
*/
GLOBAL(void)
-jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
+jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only)
{
my_master_ptr master;
master = (my_master_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- sizeof(my_comp_master));
- cinfo->master = (struct jpeg_comp_master *) master;
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ sizeof(my_comp_master));
+ cinfo->master = (struct jpeg_comp_master *)master;
master->pub.prepare_for_pass = prepare_for_pass;
master->pub.pass_startup = pass_startup;
master->pub.finish_pass = finish_pass_master;
*/
GLOBAL(void)
-jpeg_abort (j_common_ptr cinfo)
+jpeg_abort(j_common_ptr cinfo)
{
int pool;
/* Releasing pools in reverse order might help avoid fragmentation
* with some (brain-damaged) malloc libraries.
*/
- for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) {
+ for (pool = JPOOL_NUMPOOLS - 1; pool > JPOOL_PERMANENT; pool--) {
(*cinfo->mem->free_pool) (cinfo, pool);
}
/* Try to keep application from accessing now-deleted marker list.
* A bit kludgy to do it here, but this is the most central place.
*/
- ((j_decompress_ptr) cinfo)->marker_list = NULL;
+ ((j_decompress_ptr)cinfo)->marker_list = NULL;
} else {
cinfo->global_state = CSTATE_START;
}
*/
GLOBAL(void)
-jpeg_destroy (j_common_ptr cinfo)
+jpeg_destroy(j_common_ptr cinfo)
{
/* We need only tell the memory manager to release everything. */
/* NB: mem pointer is NULL if memory mgr failed to initialize. */
*/
GLOBAL(JQUANT_TBL *)
-jpeg_alloc_quant_table (j_common_ptr cinfo)
+jpeg_alloc_quant_table(j_common_ptr cinfo)
{
JQUANT_TBL *tbl;
GLOBAL(JHUFF_TBL *)
-jpeg_alloc_huff_table (j_common_ptr cinfo)
+jpeg_alloc_huff_table(j_common_ptr cinfo)
{
JHUFF_TBL *tbl;
* Copyright (C) 1991-1998, Thomas G. Lane.
* Modified 2003-2008 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2009-2011, D. R. Commander.
+ * Copyright (C) 2009-2011, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
*/
GLOBAL(void)
-jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
- const unsigned int *basic_table,
- int scale_factor, boolean force_baseline)
+jpeg_add_quant_table(j_compress_ptr cinfo, int which_tbl,
+ const unsigned int *basic_table, int scale_factor,
+ boolean force_baseline)
/* Define a quantization table equal to the basic_table times
* a scale factor (given as a percentage).
* If force_baseline is TRUE, the computed quantization table entries
if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS)
ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl);
- qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
+ qtblptr = &cinfo->quant_tbl_ptrs[which_tbl];
if (*qtblptr == NULL)
- *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo);
+ *qtblptr = jpeg_alloc_quant_table((j_common_ptr)cinfo);
for (i = 0; i < DCTSIZE2; i++) {
- temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
+ temp = ((long)basic_table[i] * scale_factor + 50L) / 100L;
/* limit the values to the valid range */
if (temp <= 0L) temp = 1L;
if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */
if (force_baseline && temp > 255L)
temp = 255L; /* limit to baseline range if requested */
- (*qtblptr)->quantval[i] = (UINT16) temp;
+ (*qtblptr)->quantval[i] = (UINT16)temp;
}
/* Initialize sent_table FALSE so table will be written to JPEG file. */
}
-/* These are the sample quantization tables given in JPEG spec section K.1.
+/* These are the sample quantization tables given in Annex K (Clause K.1) of
+ * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994.
* The spec says that the values given produce "good" quality, and
* when divided by 2, "very good" quality.
*/
#if JPEG_LIB_VERSION >= 70
GLOBAL(void)
-jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline)
+jpeg_default_qtables(j_compress_ptr cinfo, boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables
* and straight percentage-scaling quality scales.
* This entry point allows different scalings for luminance and chrominance.
GLOBAL(void)
-jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
- boolean force_baseline)
+jpeg_set_linear_quality(j_compress_ptr cinfo, int scale_factor,
+ boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables
* and a straight percentage-scaling quality scale. In most cases it's better
* to use jpeg_set_quality (below); this entry point is provided for
GLOBAL(int)
-jpeg_quality_scaling (int quality)
+jpeg_quality_scaling(int quality)
/* Convert a user-specified quality rating to a percentage scaling factor
* for an underlying quantization table, using our recommended scaling curve.
* The input 'quality' factor should be 0 (terrible) to 100 (very good).
if (quality < 50)
quality = 5000 / quality;
else
- quality = 200 - quality*2;
+ quality = 200 - quality * 2;
return quality;
}
GLOBAL(void)
-jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline)
+jpeg_set_quality(j_compress_ptr cinfo, int quality, boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables.
* This is the standard quality-adjusting entry point for typical user
* interfaces; only those who want detailed control over quantization tables
*/
GLOBAL(void)
-jpeg_set_defaults (j_compress_ptr cinfo)
+jpeg_set_defaults(j_compress_ptr cinfo)
{
int i;
*/
if (cinfo->comp_info == NULL)
cinfo->comp_info = (jpeg_component_info *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
MAX_COMPONENTS * sizeof(jpeg_component_info));
/* Initialize everything not dependent on the color space */
/* Set up two quantization tables using default quality of 75 */
jpeg_set_quality(cinfo, 75, TRUE);
/* Set up two Huffman tables */
- std_huff_tables((j_common_ptr) cinfo);
+ std_huff_tables((j_common_ptr)cinfo);
/* Initialize default arithmetic coding conditioning */
for (i = 0; i < NUM_ARITH_TBLS; i++) {
*/
GLOBAL(void)
-jpeg_default_colorspace (j_compress_ptr cinfo)
+jpeg_default_colorspace(j_compress_ptr cinfo)
{
switch (cinfo->in_color_space) {
case JCS_GRAYSCALE:
*/
GLOBAL(void)
-jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
+jpeg_set_colorspace(j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
{
jpeg_component_info *compptr;
int ci;
-#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \
+#define SET_COMP(index, id, hsamp, vsamp, quant, dctbl, actbl) \
(compptr = &cinfo->comp_info[index], \
compptr->component_id = (id), \
compptr->h_samp_factor = (hsamp), \
cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
cinfo->num_components = 1;
/* JFIF specifies component ID 1 */
- SET_COMP(0, 1, 1,1, 0, 0,0);
+ SET_COMP(0, 1, 1, 1, 0, 0, 0);
break;
case JCS_RGB:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */
cinfo->num_components = 3;
- SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0);
- SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0);
- SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0);
+ SET_COMP(0, 0x52 /* 'R' */, 1, 1, 0, 0, 0);
+ SET_COMP(1, 0x47 /* 'G' */, 1, 1, 0, 0, 0);
+ SET_COMP(2, 0x42 /* 'B' */, 1, 1, 0, 0, 0);
break;
case JCS_YCbCr:
cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
cinfo->num_components = 3;
/* JFIF specifies component IDs 1,2,3 */
/* We default to 2x2 subsamples of chrominance */
- SET_COMP(0, 1, 2,2, 0, 0,0);
- SET_COMP(1, 2, 1,1, 1, 1,1);
- SET_COMP(2, 3, 1,1, 1, 1,1);
+ SET_COMP(0, 1, 2, 2, 0, 0, 0);
+ SET_COMP(1, 2, 1, 1, 1, 1, 1);
+ SET_COMP(2, 3, 1, 1, 1, 1, 1);
break;
case JCS_CMYK:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */
cinfo->num_components = 4;
- SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0);
- SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0);
- SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0);
- SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0);
+ SET_COMP(0, 0x43 /* 'C' */, 1, 1, 0, 0, 0);
+ SET_COMP(1, 0x4D /* 'M' */, 1, 1, 0, 0, 0);
+ SET_COMP(2, 0x59 /* 'Y' */, 1, 1, 0, 0, 0);
+ SET_COMP(3, 0x4B /* 'K' */, 1, 1, 0, 0, 0);
break;
case JCS_YCCK:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */
cinfo->num_components = 4;
- SET_COMP(0, 1, 2,2, 0, 0,0);
- SET_COMP(1, 2, 1,1, 1, 1,1);
- SET_COMP(2, 3, 1,1, 1, 1,1);
- SET_COMP(3, 4, 2,2, 0, 0,0);
+ SET_COMP(0, 1, 2, 2, 0, 0, 0);
+ SET_COMP(1, 2, 1, 1, 1, 1, 1);
+ SET_COMP(2, 3, 1, 1, 1, 1, 1);
+ SET_COMP(3, 4, 2, 2, 0, 0, 0);
break;
case JCS_UNKNOWN:
cinfo->num_components = cinfo->input_components;
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
MAX_COMPONENTS);
for (ci = 0; ci < cinfo->num_components; ci++) {
- SET_COMP(ci, ci, 1,1, 0, 0,0);
+ SET_COMP(ci, ci, 1, 1, 0, 0, 0);
}
break;
default:
#ifdef C_PROGRESSIVE_SUPPORTED
LOCAL(jpeg_scan_info *)
-fill_a_scan (jpeg_scan_info *scanptr, int ci,
- int Ss, int Se, int Ah, int Al)
+fill_a_scan(jpeg_scan_info *scanptr, int ci, int Ss, int Se, int Ah, int Al)
/* Support routine: generate one scan for specified component */
{
scanptr->comps_in_scan = 1;
}
LOCAL(jpeg_scan_info *)
-fill_scans (jpeg_scan_info *scanptr, int ncomps,
- int Ss, int Se, int Ah, int Al)
+fill_scans(jpeg_scan_info *scanptr, int ncomps, int Ss, int Se, int Ah, int Al)
/* Support routine: generate one scan for each component */
{
int ci;
}
LOCAL(jpeg_scan_info *)
-fill_dc_scans (jpeg_scan_info *scanptr, int ncomps, int Ah, int Al)
+fill_dc_scans(jpeg_scan_info *scanptr, int ncomps, int Ah, int Al)
/* Support routine: generate interleaved DC scan if possible, else N scans */
{
int ci;
*/
GLOBAL(void)
-jpeg_simple_progression (j_compress_ptr cinfo)
+jpeg_simple_progression(j_compress_ptr cinfo)
{
int ncomps = cinfo->num_components;
int nscans;
if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) {
cinfo->script_space_size = MAX(nscans, 10);
cinfo->script_space = (jpeg_scan_info *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
cinfo->script_space_size * sizeof(jpeg_scan_info));
}
scanptr = cinfo->script_space;
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1995-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
- * Copyright (C) 2015, D. R. Commander.
+ * Copyright (C) 2011, 2015, 2018, D. R. Commander.
+ * Copyright (C) 2016, 2018, Matthieu Darbois.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
-#include "jchuff.h" /* Declarations shared with jchuff.c */
+#include "jsimd.h"
+#include "jconfigint.h"
+#include <limits.h>
+
+#ifdef HAVE_INTRIN_H
+#include <intrin.h>
+#ifdef _MSC_VER
+#ifdef HAVE_BITSCANFORWARD64
+#pragma intrinsic(_BitScanForward64)
+#endif
+#ifdef HAVE_BITSCANFORWARD
+#pragma intrinsic(_BitScanForward)
+#endif
+#endif
+#endif
#ifdef C_PROGRESSIVE_SUPPORTED
+/*
+ * NOTE: If USE_CLZ_INTRINSIC is defined, then clz/bsr instructions will be
+ * used for bit counting rather than the lookup table. This will reduce the
+ * memory footprint by 64k, which is important for some mobile applications
+ * that create many isolated instances of libjpeg-turbo (web browsers, for
+ * instance.) This may improve performance on some mobile platforms as well.
+ * This feature is enabled by default only on ARM processors, because some x86
+ * chips have a slow implementation of bsr, and the use of clz/bsr cannot be
+ * shown to have a significant performance impact even on the x86 chips that
+ * have a fast implementation of it. When building for ARMv6, you can
+ * explicitly disable the use of clz/bsr by adding -mthumb to the compiler
+ * flags (this defines __thumb__).
+ */
+
+/* NOTE: Both GCC and Clang define __GNUC__ */
+#if defined __GNUC__ && (defined __arm__ || defined __aarch64__)
+#if !defined __thumb__ || defined __thumb2__
+#define USE_CLZ_INTRINSIC
+#endif
+#endif
+
+#ifdef USE_CLZ_INTRINSIC
+#define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x))
+#define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0)
+#else
+#include "jpeg_nbits_table.h"
+#define JPEG_NBITS(x) (jpeg_nbits_table[x])
+#define JPEG_NBITS_NONZERO(x) JPEG_NBITS(x)
+#endif
+
+
/* Expanded entropy encoder object for progressive Huffman encoding. */
typedef struct {
struct jpeg_entropy_encoder pub; /* public fields */
+ /* Pointer to routine to prepare data for encode_mcu_AC_first() */
+ void (*AC_first_prepare) (const JCOEF *block,
+ const int *jpeg_natural_order_start, int Sl,
+ int Al, JCOEF *values, size_t *zerobits);
+ /* Pointer to routine to prepare data for encode_mcu_AC_refine() */
+ int (*AC_refine_prepare) (const JCOEF *block,
+ const int *jpeg_natural_order_start, int Sl,
+ int Al, JCOEF *absvalues, size_t *bits);
+
/* Mode flag: TRUE for optimization, FALSE for actual data output */
boolean gather_statistics;
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define ISHIFT_TEMPS int ishift_temp;
-#define IRIGHT_SHIFT(x,shft) \
- ((ishift_temp = (x)) < 0 ? \
- (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
- (ishift_temp >> (shft)))
+#define IRIGHT_SHIFT(x, shft) \
+ ((ishift_temp = (x)) < 0 ? \
+ (ishift_temp >> (shft)) | ((~0) << (16 - (shft))) : \
+ (ishift_temp >> (shft)))
#else
#define ISHIFT_TEMPS
-#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
+#define IRIGHT_SHIFT(x, shft) ((x) >> (shft))
#endif
+#define PAD(v, p) ((v + (p) - 1) & (~((p) - 1)))
+
/* Forward declarations */
-METHODDEF(boolean) encode_mcu_DC_first (j_compress_ptr cinfo,
+METHODDEF(boolean) encode_mcu_DC_first(j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data);
+METHODDEF(void) encode_mcu_AC_first_prepare
+ (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al,
+ JCOEF *values, size_t *zerobits);
+METHODDEF(boolean) encode_mcu_AC_first(j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data);
+METHODDEF(boolean) encode_mcu_DC_refine(j_compress_ptr cinfo,
JBLOCKROW *MCU_data);
-METHODDEF(boolean) encode_mcu_AC_first (j_compress_ptr cinfo,
+METHODDEF(int) encode_mcu_AC_refine_prepare
+ (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al,
+ JCOEF *absvalues, size_t *bits);
+METHODDEF(boolean) encode_mcu_AC_refine(j_compress_ptr cinfo,
JBLOCKROW *MCU_data);
-METHODDEF(boolean) encode_mcu_DC_refine (j_compress_ptr cinfo,
- JBLOCKROW *MCU_data);
-METHODDEF(boolean) encode_mcu_AC_refine (j_compress_ptr cinfo,
- JBLOCKROW *MCU_data);
-METHODDEF(void) finish_pass_phuff (j_compress_ptr cinfo);
-METHODDEF(void) finish_pass_gather_phuff (j_compress_ptr cinfo);
+METHODDEF(void) finish_pass_phuff(j_compress_ptr cinfo);
+METHODDEF(void) finish_pass_gather_phuff(j_compress_ptr cinfo);
+
+
+/* Count bit loop zeroes */
+INLINE
+METHODDEF(int)
+count_zeroes(size_t *x)
+{
+ int result;
+#if defined(HAVE_BUILTIN_CTZL)
+ result = __builtin_ctzl(*x);
+ *x >>= result;
+#elif defined(HAVE_BITSCANFORWARD64)
+ _BitScanForward64(&result, *x);
+ *x >>= result;
+#elif defined(HAVE_BITSCANFORWARD)
+ _BitScanForward(&result, *x);
+ *x >>= result;
+#else
+ result = 0;
+ while ((*x & 1) == 0) {
+ ++result;
+ *x >>= 1;
+ }
+#endif
+ return result;
+}
/*
*/
METHODDEF(void)
-start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
+start_pass_phuff(j_compress_ptr cinfo, boolean gather_statistics)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
boolean is_DC_band;
int ci, tbl;
jpeg_component_info *compptr;
entropy->pub.encode_mcu = encode_mcu_DC_first;
else
entropy->pub.encode_mcu = encode_mcu_AC_first;
+ if (jsimd_can_encode_mcu_AC_first_prepare())
+ entropy->AC_first_prepare = jsimd_encode_mcu_AC_first_prepare;
+ else
+ entropy->AC_first_prepare = encode_mcu_AC_first_prepare;
} else {
if (is_DC_band)
entropy->pub.encode_mcu = encode_mcu_DC_refine;
else {
entropy->pub.encode_mcu = encode_mcu_AC_refine;
+ if (jsimd_can_encode_mcu_AC_refine_prepare())
+ entropy->AC_refine_prepare = jsimd_encode_mcu_AC_refine_prepare;
+ else
+ entropy->AC_refine_prepare = encode_mcu_AC_refine_prepare;
/* AC refinement needs a correction bit buffer */
if (entropy->bit_buffer == NULL)
entropy->bit_buffer = (char *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
MAX_CORR_BITS * sizeof(char));
}
}
/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
if (entropy->count_ptrs[tbl] == NULL)
entropy->count_ptrs[tbl] = (long *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
257 * sizeof(long));
MEMZERO(entropy->count_ptrs[tbl], 257 * sizeof(long));
} else {
/* Compute derived values for Huffman table */
/* We may do this more than once for a table, but it's not expensive */
jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl,
- & entropy->derived_tbls[tbl]);
+ &entropy->derived_tbls[tbl]);
}
}
*/
/* Emit a byte */
-#define emit_byte(entropy,val) \
- { *(entropy)->next_output_byte++ = (JOCTET) (val); \
- if (--(entropy)->free_in_buffer == 0) \
- dump_buffer(entropy); }
+#define emit_byte(entropy, val) { \
+ *(entropy)->next_output_byte++ = (JOCTET)(val); \
+ if (--(entropy)->free_in_buffer == 0) \
+ dump_buffer(entropy); \
+}
LOCAL(void)
-dump_buffer (phuff_entropy_ptr entropy)
+dump_buffer(phuff_entropy_ptr entropy)
/* Empty the output buffer; we do not support suspension in this module. */
{
struct jpeg_destination_mgr *dest = entropy->cinfo->dest;
- if (! (*dest->empty_output_buffer) (entropy->cinfo))
+ if (!(*dest->empty_output_buffer) (entropy->cinfo))
ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND);
/* After a successful buffer dump, must reset buffer pointers */
entropy->next_output_byte = dest->next_output_byte;
*/
LOCAL(void)
-emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
+emit_bits(phuff_entropy_ptr entropy, unsigned int code, int size)
/* Emit some bits, unless we are in gather mode */
{
/* This routine is heavily used, so it's worth coding tightly. */
- register size_t put_buffer = (size_t) code;
+ register size_t put_buffer = (size_t)code;
register int put_bits = entropy->put_bits;
/* if size is 0, caller used an invalid Huffman table entry */
if (entropy->gather_statistics)
return; /* do nothing if we're only getting stats */
- put_buffer &= (((size_t) 1)<<size) - 1; /* mask off any extra bits in code */
+ put_buffer &= (((size_t)1) << size) - 1; /* mask off any extra bits in code */
put_bits += size; /* new number of bits in buffer */
put_buffer |= entropy->put_buffer; /* and merge with old buffer contents */
while (put_bits >= 8) {
- int c = (int) ((put_buffer >> 16) & 0xFF);
+ int c = (int)((put_buffer >> 16) & 0xFF);
emit_byte(entropy, c);
if (c == 0xFF) { /* need to stuff a zero byte? */
LOCAL(void)
-flush_bits (phuff_entropy_ptr entropy)
+flush_bits(phuff_entropy_ptr entropy)
{
emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */
entropy->put_buffer = 0; /* and reset bit-buffer to empty */
*/
LOCAL(void)
-emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol)
+emit_symbol(phuff_entropy_ptr entropy, int tbl_no, int symbol)
{
if (entropy->gather_statistics)
entropy->count_ptrs[tbl_no][symbol]++;
*/
LOCAL(void)
-emit_buffered_bits (phuff_entropy_ptr entropy, char *bufstart,
- unsigned int nbits)
+emit_buffered_bits(phuff_entropy_ptr entropy, char *bufstart,
+ unsigned int nbits)
{
if (entropy->gather_statistics)
return; /* no real work */
while (nbits > 0) {
- emit_bits(entropy, (unsigned int) (*bufstart), 1);
+ emit_bits(entropy, (unsigned int)(*bufstart), 1);
bufstart++;
nbits--;
}
*/
LOCAL(void)
-emit_eobrun (phuff_entropy_ptr entropy)
+emit_eobrun(phuff_entropy_ptr entropy)
{
register int temp, nbits;
if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */
temp = entropy->EOBRUN;
- nbits = 0;
- while ((temp >>= 1))
- nbits++;
+ nbits = JPEG_NBITS_NONZERO(temp) - 1;
/* safety check: shouldn't happen given limited correction-bit buffer */
if (nbits > 14)
ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
*/
LOCAL(void)
-emit_restart (phuff_entropy_ptr entropy, int restart_num)
+emit_restart(phuff_entropy_ptr entropy, int restart_num)
{
int ci;
emit_eobrun(entropy);
- if (! entropy->gather_statistics) {
+ if (!entropy->gather_statistics) {
flush_bits(entropy);
emit_byte(entropy, 0xFF);
emit_byte(entropy, JPEG_RST0 + restart_num);
*/
METHODDEF(boolean)
-encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_DC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
- register int temp, temp2;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
+ register int temp, temp2, temp3;
register int nbits;
int blkn, ci;
int Al = cinfo->Al;
/* Compute the DC value after the required point transform by Al.
* This is simply an arithmetic right shift.
*/
- temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al);
+ temp2 = IRIGHT_SHIFT((int)((*block)[0]), Al);
/* DC differences are figured on the point-transformed values. */
temp = temp2 - entropy->last_dc_val[ci];
entropy->last_dc_val[ci] = temp2;
/* Encode the DC coefficient difference per section G.1.2.1 */
- temp2 = temp;
- if (temp < 0) {
- temp = -temp; /* temp is abs value of input */
- /* For a negative input, want temp2 = bitwise complement of abs(input) */
- /* This code assumes we are on a two's complement machine */
- temp2--;
- }
+
+ /* 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.
+ */
+ temp3 = temp >> (CHAR_BIT * sizeof(int) - 1);
+ temp ^= temp3;
+ temp -= temp3; /* temp is abs value of input */
+ /* For a negative input, want temp2 = bitwise complement of abs(input) */
+ temp2 = temp ^ temp3;
/* Find the number of bits needed for the magnitude of the coefficient */
- nbits = 0;
- while (temp) {
- nbits++;
- temp >>= 1;
- }
+ nbits = JPEG_NBITS(temp);
/* Check for out-of-range coefficient values.
* Since we're encoding a difference, the range limit is twice as much.
*/
- if (nbits > MAX_COEF_BITS+1)
+ if (nbits > MAX_COEF_BITS + 1)
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
/* Count/emit the Huffman-coded symbol for the number of bits */
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
if (nbits) /* emit_bits rejects calls with size 0 */
- emit_bits(entropy, (unsigned int) temp2, nbits);
+ emit_bits(entropy, (unsigned int)temp2, nbits);
}
cinfo->dest->next_output_byte = entropy->next_output_byte;
/*
+ * Data preparation for encode_mcu_AC_first().
+ */
+
+#define COMPUTE_ABSVALUES_AC_FIRST(Sl) { \
+ for (k = 0; k < Sl; k++) { \
+ temp = block[jpeg_natural_order_start[k]]; \
+ if (temp == 0) \
+ continue; \
+ /* We must apply the point transform by Al. For AC coefficients this \
+ * is an integer division with rounding towards 0. To do this portably \
+ * in C, we shift after obtaining the absolute value; so the code is \
+ * interwoven with finding the abs value (temp) and output bits (temp2). \
+ */ \
+ temp2 = temp >> (CHAR_BIT * sizeof(int) - 1); \
+ temp ^= temp2; \
+ temp -= temp2; /* temp is abs value of input */ \
+ temp >>= Al; /* apply the point transform */ \
+ /* Watch out for case that nonzero coef is zero after point transform */ \
+ if (temp == 0) \
+ continue; \
+ /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ \
+ temp2 ^= temp; \
+ values[k] = temp; \
+ values[k + DCTSIZE2] = temp2; \
+ zerobits |= ((size_t)1U) << k; \
+ } \
+}
+
+METHODDEF(void)
+encode_mcu_AC_first_prepare(const JCOEF *block,
+ const int *jpeg_natural_order_start, int Sl,
+ int Al, JCOEF *values, size_t *bits)
+{
+ register int k, temp, temp2;
+ size_t zerobits = 0U;
+ int Sl0 = Sl;
+
+#if SIZEOF_SIZE_T == 4
+ if (Sl0 > 32)
+ Sl0 = 32;
+#endif
+
+ COMPUTE_ABSVALUES_AC_FIRST(Sl0);
+
+ bits[0] = zerobits;
+#if SIZEOF_SIZE_T == 4
+ zerobits = 0U;
+
+ if (Sl > 32) {
+ Sl -= 32;
+ jpeg_natural_order_start += 32;
+ values += 32;
+
+ COMPUTE_ABSVALUES_AC_FIRST(Sl);
+ }
+ bits[1] = zerobits;
+#endif
+}
+
+/*
* MCU encoding for AC initial scan (either spectral selection,
* or first pass of successive approximation).
*/
+#define ENCODE_COEFS_AC_FIRST(label) { \
+ while (zerobits) { \
+ r = count_zeroes(&zerobits); \
+ cvalue += r; \
+label \
+ temp = cvalue[0]; \
+ temp2 = cvalue[DCTSIZE2]; \
+ \
+ /* if run length > 15, must emit special run-length-16 codes (0xF0) */ \
+ while (r > 15) { \
+ emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); \
+ r -= 16; \
+ } \
+ \
+ /* Find the number of bits needed for the magnitude of the coefficient */ \
+ nbits = JPEG_NBITS_NONZERO(temp); /* there must be at least one 1 bit */ \
+ /* Check for out-of-range coefficient values */ \
+ if (nbits > MAX_COEF_BITS) \
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF); \
+ \
+ /* Count/emit Huffman symbol for run length / number of bits */ \
+ emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); \
+ \
+ /* Emit that number of bits of the value, if positive, */ \
+ /* or the complement of its magnitude, if negative. */ \
+ emit_bits(entropy, (unsigned int)temp2, nbits); \
+ \
+ cvalue++; \
+ zerobits >>= 1; \
+ } \
+}
+
METHODDEF(boolean)
-encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_AC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
register int temp, temp2;
- register int nbits;
- register int r, k;
- int Se = cinfo->Se;
+ register int nbits, r;
+ int Sl = cinfo->Se - cinfo->Ss + 1;
int Al = cinfo->Al;
- JBLOCKROW block;
+ JCOEF values_unaligned[2 * DCTSIZE2 + 15];
+ JCOEF *values;
+ const JCOEF *cvalue;
+ size_t zerobits;
+ size_t bits[8 / SIZEOF_SIZE_T];
entropy->next_output_byte = cinfo->dest->next_output_byte;
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
if (entropy->restarts_to_go == 0)
emit_restart(entropy, entropy->next_restart_num);
- /* Encode the MCU data block */
- block = MCU_data[0];
+#ifdef WITH_SIMD
+ cvalue = values = (JCOEF *)PAD((size_t)values_unaligned, 16);
+#else
+ /* Not using SIMD, so alignment is not needed */
+ cvalue = values = values_unaligned;
+#endif
- /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */
+ /* Prepare data */
+ entropy->AC_first_prepare(MCU_data[0][0], jpeg_natural_order + cinfo->Ss,
+ Sl, Al, values, bits);
- r = 0; /* r = run length of zeros */
-
- for (k = cinfo->Ss; k <= Se; k++) {
- if ((temp = (*block)[jpeg_natural_order[k]]) == 0) {
- r++;
- continue;
- }
- /* We must apply the point transform by Al. For AC coefficients this
- * is an integer division with rounding towards 0. To do this portably
- * in C, we shift after obtaining the absolute value; so the code is
- * interwoven with finding the abs value (temp) and output bits (temp2).
- */
- if (temp < 0) {
- temp = -temp; /* temp is abs value of input */
- temp >>= Al; /* apply the point transform */
- /* For a negative coef, want temp2 = bitwise complement of abs(coef) */
- temp2 = ~temp;
- } else {
- temp >>= Al; /* apply the point transform */
- temp2 = temp;
- }
- /* Watch out for case that nonzero coef is zero after point transform */
- if (temp == 0) {
- r++;
- continue;
- }
+ zerobits = bits[0];
+#if SIZEOF_SIZE_T == 4
+ zerobits |= bits[1];
+#endif
- /* Emit any pending EOBRUN */
- if (entropy->EOBRUN > 0)
- emit_eobrun(entropy);
- /* if run length > 15, must emit special run-length-16 codes (0xF0) */
- while (r > 15) {
- emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
- r -= 16;
- }
+ /* Emit any pending EOBRUN */
+ if (zerobits && (entropy->EOBRUN > 0))
+ emit_eobrun(entropy);
- /* Find the number of bits needed for the magnitude of the coefficient */
- nbits = 1; /* there must be at least one 1 bit */
- while ((temp >>= 1))
- nbits++;
- /* Check for out-of-range coefficient values */
- if (nbits > MAX_COEF_BITS)
- ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+#if SIZEOF_SIZE_T == 4
+ zerobits = bits[0];
+#endif
- /* Count/emit Huffman symbol for run length / number of bits */
- emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits);
+ /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */
- /* Emit that number of bits of the value, if positive, */
- /* or the complement of its magnitude, if negative. */
- emit_bits(entropy, (unsigned int) temp2, nbits);
+ ENCODE_COEFS_AC_FIRST((void)0;);
- r = 0; /* reset zero run length */
+#if SIZEOF_SIZE_T == 4
+ zerobits = bits[1];
+ if (zerobits) {
+ int diff = ((values + DCTSIZE2 / 2) - cvalue);
+ r = count_zeroes(&zerobits);
+ r += diff;
+ cvalue += r;
+ goto first_iter_ac_first;
}
- if (r > 0) { /* If there are trailing zeroes, */
+ ENCODE_COEFS_AC_FIRST(first_iter_ac_first:);
+#endif
+
+ if (cvalue < (values + Sl)) { /* If there are trailing zeroes, */
entropy->EOBRUN++; /* count an EOB */
if (entropy->EOBRUN == 0x7FFF)
emit_eobrun(entropy); /* force it out to avoid overflow */
*/
METHODDEF(boolean)
-encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_DC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
register int temp;
int blkn;
int Al = cinfo->Al;
/* We simply emit the Al'th bit of the DC coefficient value. */
temp = (*block)[0];
- emit_bits(entropy, (unsigned int) (temp >> Al), 1);
+ emit_bits(entropy, (unsigned int)(temp >> Al), 1);
}
cinfo->dest->next_output_byte = entropy->next_output_byte;
/*
+ * Data preparation for encode_mcu_AC_refine().
+ */
+
+#define COMPUTE_ABSVALUES_AC_REFINE(Sl, koffset) { \
+ /* It is convenient to make a pre-pass to determine the transformed \
+ * coefficients' absolute values and the EOB position. \
+ */ \
+ for (k = 0; k < Sl; k++) { \
+ temp = block[jpeg_natural_order_start[k]]; \
+ /* We must apply the point transform by Al. For AC coefficients this \
+ * is an integer division with rounding towards 0. To do this portably \
+ * in C, we shift after obtaining the absolute value. \
+ */ \
+ temp2 = temp >> (CHAR_BIT * sizeof(int) - 1); \
+ temp ^= temp2; \
+ temp -= temp2; /* temp is abs value of input */ \
+ temp >>= Al; /* apply the point transform */ \
+ if (temp != 0) { \
+ zerobits |= ((size_t)1U) << k; \
+ signbits |= ((size_t)(temp2 + 1)) << k; \
+ } \
+ absvalues[k] = (JCOEF)temp; /* save abs value for main pass */ \
+ if (temp == 1) \
+ EOB = k + koffset; /* EOB = index of last newly-nonzero coef */ \
+ } \
+}
+
+METHODDEF(int)
+encode_mcu_AC_refine_prepare(const JCOEF *block,
+ const int *jpeg_natural_order_start, int Sl,
+ int Al, JCOEF *absvalues, size_t *bits)
+{
+ register int k, temp, temp2;
+ int EOB = 0;
+ size_t zerobits = 0U, signbits = 0U;
+ int Sl0 = Sl;
+
+#if SIZEOF_SIZE_T == 4
+ if (Sl0 > 32)
+ Sl0 = 32;
+#endif
+
+ COMPUTE_ABSVALUES_AC_REFINE(Sl0, 0);
+
+ bits[0] = zerobits;
+#if SIZEOF_SIZE_T == 8
+ bits[1] = signbits;
+#else
+ bits[2] = signbits;
+
+ zerobits = 0U;
+ signbits = 0U;
+
+ if (Sl > 32) {
+ Sl -= 32;
+ jpeg_natural_order_start += 32;
+ absvalues += 32;
+
+ COMPUTE_ABSVALUES_AC_REFINE(Sl, 32);
+ }
+
+ bits[1] = zerobits;
+ bits[3] = signbits;
+#endif
+
+ return EOB;
+}
+
+
+/*
* MCU encoding for AC successive approximation refinement scan.
*/
+#define ENCODE_COEFS_AC_REFINE(label) { \
+ while (zerobits) { \
+ int idx = count_zeroes(&zerobits); \
+ r += idx; \
+ cabsvalue += idx; \
+ signbits >>= idx; \
+label \
+ /* Emit any required ZRLs, but not if they can be folded into EOB */ \
+ while (r > 15 && (cabsvalue <= EOBPTR)) { \
+ /* emit any pending EOBRUN and the BE correction bits */ \
+ emit_eobrun(entropy); \
+ /* Emit ZRL */ \
+ emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); \
+ r -= 16; \
+ /* Emit buffered correction bits that must be associated with ZRL */ \
+ emit_buffered_bits(entropy, BR_buffer, BR); \
+ BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ \
+ BR = 0; \
+ } \
+ \
+ temp = *cabsvalue++; \
+ \
+ /* If the coef was previously nonzero, it only needs a correction bit. \
+ * NOTE: a straight translation of the spec's figure G.7 would suggest \
+ * that we also need to test r > 15. But if r > 15, we can only get here \
+ * if k > EOB, which implies that this coefficient is not 1. \
+ */ \
+ if (temp > 1) { \
+ /* The correction bit is the next bit of the absolute value. */ \
+ BR_buffer[BR++] = (char)(temp & 1); \
+ signbits >>= 1; \
+ zerobits >>= 1; \
+ continue; \
+ } \
+ \
+ /* Emit any pending EOBRUN and the BE correction bits */ \
+ emit_eobrun(entropy); \
+ \
+ /* Count/emit Huffman symbol for run length / number of bits */ \
+ emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); \
+ \
+ /* Emit output bit for newly-nonzero coef */ \
+ temp = signbits & 1; /* ((*block)[jpeg_natural_order_start[k]] < 0) ? 0 : 1 */ \
+ emit_bits(entropy, (unsigned int)temp, 1); \
+ \
+ /* Emit buffered correction bits that must be associated with this code */ \
+ emit_buffered_bits(entropy, BR_buffer, BR); \
+ BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ \
+ BR = 0; \
+ r = 0; /* reset zero run length */ \
+ signbits >>= 1; \
+ zerobits >>= 1; \
+ } \
+}
+
METHODDEF(boolean)
-encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
- register int temp;
- register int r, k;
- int EOB;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
+ register int temp, r;
char *BR_buffer;
unsigned int BR;
- int Se = cinfo->Se;
+ int Sl = cinfo->Se - cinfo->Ss + 1;
int Al = cinfo->Al;
- JBLOCKROW block;
- int absvalues[DCTSIZE2];
+ JCOEF absvalues_unaligned[DCTSIZE2 + 15];
+ JCOEF *absvalues;
+ const JCOEF *cabsvalue, *EOBPTR;
+ size_t zerobits, signbits;
+ size_t bits[16 / SIZEOF_SIZE_T];
entropy->next_output_byte = cinfo->dest->next_output_byte;
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
if (entropy->restarts_to_go == 0)
emit_restart(entropy, entropy->next_restart_num);
- /* Encode the MCU data block */
- block = MCU_data[0];
+#ifdef WITH_SIMD
+ cabsvalue = absvalues = (JCOEF *)PAD((size_t)absvalues_unaligned, 16);
+#else
+ /* Not using SIMD, so alignment is not needed */
+ cabsvalue = absvalues = absvalues_unaligned;
+#endif
- /* It is convenient to make a pre-pass to determine the transformed
- * coefficients' absolute values and the EOB position.
- */
- EOB = 0;
- for (k = cinfo->Ss; k <= Se; k++) {
- temp = (*block)[jpeg_natural_order[k]];
- /* We must apply the point transform by Al. For AC coefficients this
- * is an integer division with rounding towards 0. To do this portably
- * in C, we shift after obtaining the absolute value.
- */
- if (temp < 0)
- temp = -temp; /* temp is abs value of input */
- temp >>= Al; /* apply the point transform */
- absvalues[k] = temp; /* save abs value for main pass */
- if (temp == 1)
- EOB = k; /* EOB = index of last newly-nonzero coef */
- }
+ /* Prepare data */
+ EOBPTR = absvalues +
+ entropy->AC_refine_prepare(MCU_data[0][0], jpeg_natural_order + cinfo->Ss,
+ Sl, Al, absvalues, bits);
/* Encode the AC coefficients per section G.1.2.3, fig. G.7 */
BR = 0; /* BR = count of buffered bits added now */
BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */
- for (k = cinfo->Ss; k <= Se; k++) {
- if ((temp = absvalues[k]) == 0) {
- r++;
- continue;
- }
-
- /* Emit any required ZRLs, but not if they can be folded into EOB */
- while (r > 15 && k <= EOB) {
- /* emit any pending EOBRUN and the BE correction bits */
- emit_eobrun(entropy);
- /* Emit ZRL */
- emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
- r -= 16;
- /* Emit buffered correction bits that must be associated with ZRL */
- emit_buffered_bits(entropy, BR_buffer, BR);
- BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
- BR = 0;
- }
-
- /* If the coef was previously nonzero, it only needs a correction bit.
- * NOTE: a straight translation of the spec's figure G.7 would suggest
- * that we also need to test r > 15. But if r > 15, we can only get here
- * if k > EOB, which implies that this coefficient is not 1.
- */
- if (temp > 1) {
- /* The correction bit is the next bit of the absolute value. */
- BR_buffer[BR++] = (char) (temp & 1);
- continue;
- }
-
- /* Emit any pending EOBRUN and the BE correction bits */
- emit_eobrun(entropy);
-
- /* Count/emit Huffman symbol for run length / number of bits */
- emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1);
+ zerobits = bits[0];
+#if SIZEOF_SIZE_T == 8
+ signbits = bits[1];
+#else
+ signbits = bits[2];
+#endif
+ ENCODE_COEFS_AC_REFINE((void)0;);
+
+#if SIZEOF_SIZE_T == 4
+ zerobits = bits[1];
+ signbits = bits[3];
+
+ if (zerobits) {
+ int diff = ((absvalues + DCTSIZE2 / 2) - cabsvalue);
+ int idx = count_zeroes(&zerobits);
+ signbits >>= idx;
+ idx += diff;
+ r += idx;
+ cabsvalue += idx;
+ goto first_iter_ac_refine;
+ }
- /* Emit output bit for newly-nonzero coef */
- temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1;
- emit_bits(entropy, (unsigned int) temp, 1);
+ ENCODE_COEFS_AC_REFINE(first_iter_ac_refine:);
+#endif
- /* Emit buffered correction bits that must be associated with this code */
- emit_buffered_bits(entropy, BR_buffer, BR);
- BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
- BR = 0;
- r = 0; /* reset zero run length */
- }
+ r |= (int)((absvalues + Sl) - cabsvalue);
if (r > 0 || BR > 0) { /* If there are trailing zeroes, */
entropy->EOBRUN++; /* count an EOB */
* 1. overflow of the EOB counter;
* 2. overflow of the correction bit buffer during the next MCU.
*/
- if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1))
+ if (entropy->EOBRUN == 0x7FFF ||
+ entropy->BE > (MAX_CORR_BITS - DCTSIZE2 + 1))
emit_eobrun(entropy);
}
*/
METHODDEF(void)
-finish_pass_phuff (j_compress_ptr cinfo)
+finish_pass_phuff(j_compress_ptr cinfo)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
entropy->next_output_byte = cinfo->dest->next_output_byte;
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
*/
METHODDEF(void)
-finish_pass_gather_phuff (j_compress_ptr cinfo)
+finish_pass_gather_phuff(j_compress_ptr cinfo)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
boolean is_DC_band;
int ci, tbl;
jpeg_component_info *compptr;
} else {
tbl = compptr->ac_tbl_no;
}
- if (! did[tbl]) {
+ if (!did[tbl]) {
if (is_DC_band)
- htblptr = & cinfo->dc_huff_tbl_ptrs[tbl];
+ htblptr = &cinfo->dc_huff_tbl_ptrs[tbl];
else
- htblptr = & cinfo->ac_huff_tbl_ptrs[tbl];
+ htblptr = &cinfo->ac_huff_tbl_ptrs[tbl];
if (*htblptr == NULL)
- *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo);
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]);
did[tbl] = TRUE;
}
*/
GLOBAL(void)
-jinit_phuff_encoder (j_compress_ptr cinfo)
+jinit_phuff_encoder(j_compress_ptr cinfo)
{
phuff_entropy_ptr entropy;
int i;
entropy = (phuff_entropy_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(phuff_entropy_encoder));
- cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
+ cinfo->entropy = (struct jpeg_entropy_encoder *)entropy;
entropy->pub.start_pass = start_pass_phuff;
/* Mark tables unallocated */
*/
METHODDEF(void)
-start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+start_pass_prep(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
- my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ my_prep_ptr prep = (my_prep_ptr)cinfo->prep;
if (pass_mode != JBUF_PASS_THRU)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
*/
LOCAL(void)
-expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
- int input_rows, int output_rows)
+expand_bottom_edge(JSAMPARRAY image_data, JDIMENSION num_cols, int input_rows,
+ int output_rows)
{
register int row;
for (row = input_rows; row < output_rows; row++) {
- jcopy_sample_rows(image_data, input_rows-1, image_data, row,
- 1, num_cols);
+ jcopy_sample_rows(image_data, input_rows - 1, image_data, row, 1,
+ num_cols);
}
}
*/
METHODDEF(void)
-pre_process_data (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
- JDIMENSION in_rows_avail,
- JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
- JDIMENSION out_row_groups_avail)
+pre_process_data(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail,
+ JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
+ JDIMENSION out_row_groups_avail)
{
- my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ my_prep_ptr prep = (my_prep_ptr)cinfo->prep;
int numrows, ci;
JDIMENSION inrows;
jpeg_component_info *compptr;
/* Do color conversion to fill the conversion buffer. */
inrows = in_rows_avail - *in_row_ctr;
numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
- numrows = (int) MIN((JDIMENSION) numrows, inrows);
+ numrows = (int)MIN((JDIMENSION)numrows, inrows);
(*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
prep->color_buf,
- (JDIMENSION) prep->next_buf_row,
+ (JDIMENSION)prep->next_buf_row,
numrows);
*in_row_ctr += numrows;
prep->next_buf_row += numrows;
/* If we've filled the conversion buffer, empty it. */
if (prep->next_buf_row == cinfo->max_v_samp_factor) {
(*cinfo->downsample->downsample) (cinfo,
- prep->color_buf, (JDIMENSION) 0,
+ prep->color_buf, (JDIMENSION)0,
output_buf, *out_row_group_ctr);
prep->next_buf_row = 0;
(*out_row_group_ctr)++;
/* If at bottom of image, pad the output to a full iMCU height.
* Note we assume the caller is providing a one-iMCU-height output buffer!
*/
- if (prep->rows_to_go == 0 &&
- *out_row_group_ctr < out_row_groups_avail) {
+ if (prep->rows_to_go == 0 && *out_row_group_ctr < out_row_groups_avail) {
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
- expand_bottom_edge(output_buf[ci],
- compptr->width_in_blocks * DCTSIZE,
- (int) (*out_row_group_ctr * compptr->v_samp_factor),
- (int) (out_row_groups_avail * compptr->v_samp_factor));
+ expand_bottom_edge(output_buf[ci], compptr->width_in_blocks * DCTSIZE,
+ (int)(*out_row_group_ctr * compptr->v_samp_factor),
+ (int)(out_row_groups_avail * compptr->v_samp_factor));
}
*out_row_group_ctr = out_row_groups_avail;
break; /* can exit outer loop without test */
*/
METHODDEF(void)
-pre_process_context (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
- JDIMENSION in_rows_avail,
- JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
- JDIMENSION out_row_groups_avail)
+pre_process_context(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail,
+ JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
+ JDIMENSION out_row_groups_avail)
{
- my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ my_prep_ptr prep = (my_prep_ptr)cinfo->prep;
int numrows, ci;
int buf_height = cinfo->max_v_samp_factor * 3;
JDIMENSION inrows;
/* Do color conversion to fill the conversion buffer. */
inrows = in_rows_avail - *in_row_ctr;
numrows = prep->next_buf_stop - prep->next_buf_row;
- numrows = (int) MIN((JDIMENSION) numrows, inrows);
+ numrows = (int)MIN((JDIMENSION)numrows, inrows);
(*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
prep->color_buf,
- (JDIMENSION) prep->next_buf_row,
+ (JDIMENSION)prep->next_buf_row,
numrows);
/* Pad at top of image, if first time through */
if (prep->rows_to_go == cinfo->image_height) {
for (ci = 0; ci < cinfo->num_components; ci++) {
int row;
for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
- jcopy_sample_rows(prep->color_buf[ci], 0,
- prep->color_buf[ci], -row,
- 1, cinfo->image_width);
+ jcopy_sample_rows(prep->color_buf[ci], 0, prep->color_buf[ci],
+ -row, 1, cinfo->image_width);
}
}
}
}
/* If we've gotten enough data, downsample a row group. */
if (prep->next_buf_row == prep->next_buf_stop) {
- (*cinfo->downsample->downsample) (cinfo,
- prep->color_buf,
- (JDIMENSION) prep->this_row_group,
+ (*cinfo->downsample->downsample) (cinfo, prep->color_buf,
+ (JDIMENSION)prep->this_row_group,
output_buf, *out_row_group_ctr);
(*out_row_group_ctr)++;
/* Advance pointers with wraparound as necessary. */
*/
LOCAL(void)
-create_context_buffer (j_compress_ptr cinfo)
+create_context_buffer(j_compress_ptr cinfo)
{
- my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ my_prep_ptr prep = (my_prep_ptr)cinfo->prep;
int rgroup_height = cinfo->max_v_samp_factor;
int ci, i;
jpeg_component_info *compptr;
* we need five row groups' worth of pointers for each component.
*/
fake_buffer = (JSAMPARRAY)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
(cinfo->num_components * 5 * rgroup_height) *
sizeof(JSAMPROW));
* horizontally within the buffer, if it so chooses.
*/
true_buffer = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
- cinfo->max_h_samp_factor) / compptr->h_samp_factor),
- (JDIMENSION) (3 * rgroup_height));
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (JDIMENSION)(((long)compptr->width_in_blocks * DCTSIZE *
+ cinfo->max_h_samp_factor) / compptr->h_samp_factor),
+ (JDIMENSION)(3 * rgroup_height));
/* Copy true buffer row pointers into the middle of the fake row array */
MEMCOPY(fake_buffer + rgroup_height, true_buffer,
3 * rgroup_height * sizeof(JSAMPROW));
*/
GLOBAL(void)
-jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+jinit_c_prep_controller(j_compress_ptr cinfo, boolean need_full_buffer)
{
my_prep_ptr prep;
int ci;
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
prep = (my_prep_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_prep_controller));
- cinfo->prep = (struct jpeg_c_prep_controller *) prep;
+ cinfo->prep = (struct jpeg_c_prep_controller *)prep;
prep->pub.start_pass = start_pass_prep;
/* Allocate the color conversion buffer.
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
- cinfo->max_h_samp_factor) / compptr->h_samp_factor),
- (JDIMENSION) cinfo->max_v_samp_factor);
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (JDIMENSION)(((long)compptr->width_in_blocks * DCTSIZE *
+ cinfo->max_h_samp_factor) / compptr->h_samp_factor),
+ (JDIMENSION)cinfo->max_v_samp_factor);
}
}
}
*/
METHODDEF(void)
-start_pass_downsample (j_compress_ptr cinfo)
+start_pass_downsample(j_compress_ptr cinfo)
{
/* no work for now */
}
*/
LOCAL(void)
-expand_right_edge (JSAMPARRAY image_data, int num_rows,
- JDIMENSION input_cols, JDIMENSION output_cols)
+expand_right_edge(JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols,
+ JDIMENSION output_cols)
{
register JSAMPROW ptr;
register JSAMPLE pixval;
register int count;
int row;
- int numcols = (int) (output_cols - input_cols);
+ int numcols = (int)(output_cols - input_cols);
if (numcols > 0) {
for (row = 0; row < num_rows; row++) {
*/
METHODDEF(void)
-sep_downsample (j_compress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION in_row_index,
- JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)
+sep_downsample(j_compress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_index, JSAMPIMAGE output_buf,
+ JDIMENSION out_row_group_index)
{
- my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
+ my_downsample_ptr downsample = (my_downsample_ptr)cinfo->downsample;
int ci;
jpeg_component_info *compptr;
JSAMPARRAY in_ptr, out_ptr;
*/
METHODDEF(void)
-int_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+int_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */
h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
numpix = h_expand * v_expand;
- numpix2 = numpix/2;
+ numpix2 = numpix / 2;
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
- expand_right_edge(input_data, cinfo->max_v_samp_factor,
- cinfo->image_width, output_cols * h_expand);
+ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width,
+ output_cols * h_expand);
inrow = 0;
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outcol++, outcol_h += h_expand) {
outvalue = 0;
for (v = 0; v < v_expand; v++) {
- inptr = input_data[inrow+v] + outcol_h;
+ inptr = input_data[inrow + v] + outcol_h;
for (h = 0; h < h_expand; h++) {
- outvalue += (JLONG) GETJSAMPLE(*inptr++);
+ outvalue += (JLONG)GETJSAMPLE(*inptr++);
}
}
- *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);
+ *outptr++ = (JSAMPLE)((outvalue + numpix2) / numpix);
}
inrow += v_expand;
}
*/
METHODDEF(void)
-fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+fullsize_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
/* Copy the data */
- jcopy_sample_rows(input_data, 0, output_data, 0,
- cinfo->max_v_samp_factor, cinfo->image_width);
+ jcopy_sample_rows(input_data, 0, output_data, 0, cinfo->max_v_samp_factor,
+ cinfo->image_width);
/* Edge-expand */
- expand_right_edge(output_data, cinfo->max_v_samp_factor,
- cinfo->image_width, compptr->width_in_blocks * DCTSIZE);
+ expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width,
+ compptr->width_in_blocks * DCTSIZE);
}
*/
METHODDEF(void)
-h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int outrow;
JDIMENSION outcol;
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
- expand_right_edge(input_data, cinfo->max_v_samp_factor,
- cinfo->image_width, output_cols * 2);
+ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width,
+ output_cols * 2);
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
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)((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + bias) >> 1);
bias ^= 1; /* 0=>1, 1=>0 */
inptr += 2;
}
*/
METHODDEF(void)
-h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int inrow, outrow;
JDIMENSION outcol;
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
- expand_right_edge(input_data, cinfo->max_v_samp_factor,
- cinfo->image_width, output_cols * 2);
+ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width,
+ output_cols * 2);
inrow = 0;
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr0 = input_data[inrow];
- inptr1 = input_data[inrow+1];
+ inptr1 = input_data[inrow + 1];
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);
+ *outptr++ =
+ (JSAMPLE)((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + bias) >> 2);
bias ^= 3; /* 1=>2, 2=>1 */
- inptr0 += 2; inptr1 += 2;
+ inptr0 += 2; inptr1 += 2;
}
inrow += 2;
}
*/
METHODDEF(void)
-h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int inrow, outrow;
JDIMENSION colctr;
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr0 = input_data[inrow];
- inptr1 = input_data[inrow+1];
- above_ptr = input_data[inrow-1];
- below_ptr = input_data[inrow+2];
+ inptr1 = input_data[inrow + 1];
+ above_ptr = input_data[inrow - 1];
+ 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]) +
neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
membersum = membersum * memberscale + neighsum * neighscale;
- *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
- inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
+ *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 */
/* form final output scaled up by 2^16 */
membersum = membersum * memberscale + neighsum * neighscale;
/* round, descale and output it */
- *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
- inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
+ *outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
+ inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
}
/* Special case for last column */
neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
membersum = membersum * memberscale + neighsum * neighscale;
- *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
+ *outptr = (JSAMPLE)((membersum + 32768) >> 16);
inrow += 2;
}
*/
METHODDEF(void)
-fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int outrow;
JDIMENSION colctr;
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr = input_data[outrow];
- above_ptr = input_data[outrow-1];
- below_ptr = input_data[outrow+1];
+ above_ptr = input_data[outrow - 1];
+ below_ptr = input_data[outrow + 1];
/* Special case for first column */
colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
GETJSAMPLE(*inptr);
neighsum = colsum + (colsum - membersum) + nextcolsum;
membersum = membersum * memberscale + neighsum * neighscale;
- *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
- lastcolsum = colsum; colsum = nextcolsum;
+ *outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
+ lastcolsum = colsum; colsum = nextcolsum;
for (colctr = output_cols - 2; colctr > 0; colctr--) {
membersum = GETJSAMPLE(*inptr++);
- above_ptr++; below_ptr++;
+ above_ptr++; below_ptr++;
nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
GETJSAMPLE(*inptr);
neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
membersum = membersum * memberscale + neighsum * neighscale;
- *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
- lastcolsum = colsum; colsum = nextcolsum;
+ *outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
+ lastcolsum = colsum; colsum = nextcolsum;
}
/* Special case for last column */
membersum = GETJSAMPLE(*inptr);
neighsum = lastcolsum + (colsum - membersum) + colsum;
membersum = membersum * memberscale + neighsum * neighscale;
- *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
+ *outptr = (JSAMPLE)((membersum + 32768) >> 16);
}
}
*/
GLOBAL(void)
-jinit_downsampler (j_compress_ptr cinfo)
+jinit_downsampler(j_compress_ptr cinfo)
{
my_downsample_ptr downsample;
int ci;
boolean smoothok = TRUE;
downsample = (my_downsample_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_downsampler));
- cinfo->downsample = (struct jpeg_downsampler *) downsample;
+ cinfo->downsample = (struct jpeg_downsampler *)downsample;
downsample->pub.start_pass = start_pass_downsample;
downsample->pub.downsample = sep_downsample;
downsample->pub.need_context_rows = FALSE;
/* Forward declarations */
-LOCAL(void) transencode_master_selection
- (j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays);
-LOCAL(void) transencode_coef_controller
- (j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays);
+LOCAL(void) transencode_master_selection(j_compress_ptr cinfo,
+ jvirt_barray_ptr *coef_arrays);
+LOCAL(void) transencode_coef_controller(j_compress_ptr cinfo,
+ jvirt_barray_ptr *coef_arrays);
/*
*/
GLOBAL(void)
-jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays)
+jpeg_write_coefficients(j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays)
{
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Mark all tables to be written */
jpeg_suppress_tables(cinfo, FALSE);
/* (Re)initialize error mgr and destination modules */
- (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr)cinfo);
(*cinfo->dest->init_destination) (cinfo);
/* Perform master selection of active modules */
transencode_master_selection(cinfo, coef_arrays);
*/
GLOBAL(void)
-jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
- j_compress_ptr dstinfo)
+jpeg_copy_critical_parameters(j_decompress_ptr srcinfo, j_compress_ptr dstinfo)
{
JQUANT_TBL **qtblptr;
jpeg_component_info *incomp, *outcomp;
/* Copy the source's quantization tables. */
for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
if (srcinfo->quant_tbl_ptrs[tblno] != NULL) {
- qtblptr = & dstinfo->quant_tbl_ptrs[tblno];
+ qtblptr = &dstinfo->quant_tbl_ptrs[tblno];
if (*qtblptr == NULL)
- *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo);
- MEMCOPY((*qtblptr)->quantval,
- srcinfo->quant_tbl_ptrs[tblno]->quantval,
+ *qtblptr = jpeg_alloc_quant_table((j_common_ptr)dstinfo);
+ MEMCOPY((*qtblptr)->quantval, srcinfo->quant_tbl_ptrs[tblno]->quantval,
sizeof((*qtblptr)->quantval));
(*qtblptr)->sent_table = FALSE;
}
*/
LOCAL(void)
-transencode_master_selection (j_compress_ptr cinfo,
- jvirt_barray_ptr *coef_arrays)
+transencode_master_selection(j_compress_ptr cinfo,
+ jvirt_barray_ptr *coef_arrays)
{
/* Although we don't actually use input_components for transcoding,
* jcmaster.c's initial_setup will complain if input_components is 0.
jinit_marker_writer(cinfo);
/* We can now tell the memory manager to allocate virtual arrays. */
- (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo);
/* Write the datastream header (SOI, JFIF) immediately.
* Frame and scan headers are postponed till later.
LOCAL(void)
-start_iMCU_row (j_compress_ptr cinfo)
+start_iMCU_row(j_compress_ptr cinfo)
/* Reset within-iMCU-row counters for a new row */
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
/* In an interleaved scan, an MCU row is the same as an iMCU row.
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
if (cinfo->comps_in_scan > 1) {
coef->MCU_rows_per_iMCU_row = 1;
} else {
- if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
+ if (coef->iMCU_row_num < (cinfo->total_iMCU_rows - 1))
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
else
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
*/
METHODDEF(void)
-start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+start_pass_coef(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
if (pass_mode != JBUF_CRANK_DEST)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
*/
METHODDEF(boolean)
-compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
buffer[ci] = (*cinfo->mem->access_virt_barray)
- ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ ((j_common_ptr)cinfo, coef->whole_image[compptr->component_index],
coef->iMCU_row_num * compptr->v_samp_factor,
- (JDIMENSION) compptr->v_samp_factor, FALSE);
+ (JDIMENSION)compptr->v_samp_factor, FALSE);
}
/* Loop to process one whole iMCU row */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
start_col = MCU_col_num * compptr->MCU_width;
- blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
- : compptr->last_col_width;
+ blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width :
+ compptr->last_col_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
if (coef->iMCU_row_num < last_iMCU_row ||
- yindex+yoffset < compptr->last_row_height) {
+ yindex + yoffset < compptr->last_row_height) {
/* Fill in pointers to real blocks in this row */
- buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ buffer_ptr = buffer[ci][yindex + yoffset] + start_col;
for (xindex = 0; xindex < blockcnt; xindex++)
MCU_buffer[blkn++] = buffer_ptr++;
} else {
*/
for (; xindex < compptr->MCU_width; xindex++) {
MCU_buffer[blkn] = coef->dummy_buffer[blkn];
- MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0];
+ MCU_buffer[blkn][0][0] = MCU_buffer[blkn - 1][0][0];
blkn++;
}
}
}
/* Try to write the MCU. */
- if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) {
+ if (!(*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->mcu_ctr = MCU_col_num;
*/
LOCAL(void)
-transencode_coef_controller (j_compress_ptr cinfo,
- jvirt_barray_ptr *coef_arrays)
+transencode_coef_controller(j_compress_ptr cinfo,
+ jvirt_barray_ptr *coef_arrays)
{
my_coef_ptr coef;
JBLOCKROW buffer;
int i;
coef = (my_coef_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_coef_controller));
- cinfo->coef = (struct jpeg_c_coef_controller *) coef;
+ cinfo->coef = (struct jpeg_c_coef_controller *)coef;
coef->pub.start_pass = start_pass_coef;
coef->pub.compress_data = compress_output;
/* Allocate and pre-zero space for dummy DCT blocks. */
buffer = (JBLOCKROW)
- (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE,
C_MAX_BLOCKS_IN_MCU * sizeof(JBLOCK));
- jzero_far((void *) buffer, C_MAX_BLOCKS_IN_MCU * sizeof(JBLOCK));
+ jzero_far((void *)buffer, C_MAX_BLOCKS_IN_MCU * sizeof(JBLOCK));
for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
coef->dummy_buffer[i] = buffer + i;
}
*/
GLOBAL(void)
-jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
+jpeg_CreateDecompress(j_decompress_ptr cinfo, int version, size_t structsize)
{
int i;
ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
if (structsize != sizeof(struct jpeg_decompress_struct))
ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
- (int) sizeof(struct jpeg_decompress_struct), (int) structsize);
+ (int)sizeof(struct jpeg_decompress_struct), (int)structsize);
/* For debugging purposes, we zero the whole master structure.
* But the application has already set the err pointer, and may have set
* complain here.
*/
{
- struct jpeg_error_mgr * err = cinfo->err;
- void * client_data = cinfo->client_data; /* ignore Purify complaint here */
+ struct jpeg_error_mgr *err = cinfo->err;
+ void *client_data = cinfo->client_data; /* ignore Purify complaint here */
MEMZERO(cinfo, sizeof(struct jpeg_decompress_struct));
cinfo->err = err;
cinfo->client_data = client_data;
cinfo->is_decompressor = TRUE;
/* Initialize a memory manager instance for this object */
- jinit_memory_mgr((j_common_ptr) cinfo);
+ jinit_memory_mgr((j_common_ptr)cinfo);
/* Zero out pointers to permanent structures. */
cinfo->progress = NULL;
* here.
*/
cinfo->master = (struct jpeg_decomp_master *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
- sizeof(my_decomp_master));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
+ sizeof(my_decomp_master));
MEMZERO(cinfo->master, sizeof(my_decomp_master));
}
*/
GLOBAL(void)
-jpeg_destroy_decompress (j_decompress_ptr cinfo)
+jpeg_destroy_decompress(j_decompress_ptr cinfo)
{
- jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
+ jpeg_destroy((j_common_ptr)cinfo); /* use common routine */
}
*/
GLOBAL(void)
-jpeg_abort_decompress (j_decompress_ptr cinfo)
+jpeg_abort_decompress(j_decompress_ptr cinfo)
{
- jpeg_abort((j_common_ptr) cinfo); /* use common routine */
+ jpeg_abort((j_common_ptr)cinfo); /* use common routine */
}
*/
LOCAL(void)
-default_decompress_parms (j_decompress_ptr cinfo)
+default_decompress_parms(j_decompress_ptr cinfo)
{
/* Guess the input colorspace, and set output colorspace accordingly. */
/* (Wish JPEG committee had provided a real way to specify this...) */
*/
GLOBAL(int)
-jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
+jpeg_read_header(j_decompress_ptr cinfo, boolean require_image)
{
int retcode;
* call jpeg_abort, but we can't change it now for compatibility reasons.
* A side effect is to free any temporary memory (there shouldn't be any).
*/
- jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */
+ jpeg_abort((j_common_ptr)cinfo); /* sets state = DSTATE_START */
retcode = JPEG_HEADER_TABLES_ONLY;
break;
case JPEG_SUSPENDED:
*/
GLOBAL(int)
-jpeg_consume_input (j_decompress_ptr cinfo)
+jpeg_consume_input(j_decompress_ptr cinfo)
{
int retcode = JPEG_SUSPENDED;
*/
GLOBAL(boolean)
-jpeg_input_complete (j_decompress_ptr cinfo)
+jpeg_input_complete(j_decompress_ptr cinfo)
{
/* Check for valid jpeg object */
if (cinfo->global_state < DSTATE_START ||
*/
GLOBAL(boolean)
-jpeg_has_multiple_scans (j_decompress_ptr cinfo)
+jpeg_has_multiple_scans(j_decompress_ptr cinfo)
{
/* Only valid after jpeg_read_header completes */
if (cinfo->global_state < DSTATE_READY ||
*/
GLOBAL(boolean)
-jpeg_finish_decompress (j_decompress_ptr cinfo)
+jpeg_finish_decompress(j_decompress_ptr cinfo)
{
if ((cinfo->global_state == DSTATE_SCANNING ||
- cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) {
+ cinfo->global_state == DSTATE_RAW_OK) && !cinfo->buffered_image) {
/* Terminate final pass of non-buffered mode */
if (cinfo->output_scanline < cinfo->output_height)
ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
}
/* Read until EOI */
- while (! cinfo->inputctl->eoi_reached) {
+ while (!cinfo->inputctl->eoi_reached) {
if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
return FALSE; /* Suspend, come back later */
}
/* Do final cleanup */
(*cinfo->src->term_source) (cinfo);
/* We can use jpeg_abort to release memory and reset global_state */
- jpeg_abort((j_common_ptr) cinfo);
+ jpeg_abort((j_common_ptr)cinfo);
return TRUE;
}
* 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-2017, D. R. Commander.
+ * Copyright (C) 2010, 2015-2018, D. R. Commander.
* Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
#include "jmemsys.h"
/* Forward declarations */
-LOCAL(boolean) output_pass_setup (j_decompress_ptr cinfo);
+LOCAL(boolean) output_pass_setup(j_decompress_ptr cinfo);
/*
*/
GLOBAL(boolean)
-jpeg_start_decompress (j_decompress_ptr cinfo)
+jpeg_start_decompress(j_decompress_ptr cinfo)
{
if (cinfo->global_state == DSTATE_READY) {
/* First call: initialize master control, select active modules */
int retcode;
/* Call progress monitor hook if present */
if (cinfo->progress != NULL)
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
/* Absorb some more input */
retcode = (*cinfo->inputctl->consume_input) (cinfo);
if (retcode == JPEG_SUSPENDED)
(retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
/* jdmaster underestimated number of scans; ratchet up one scan */
- cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
+ cinfo->progress->pass_limit += (long)cinfo->total_iMCU_rows;
}
}
}
*/
LOCAL(boolean)
-output_pass_setup (j_decompress_ptr cinfo)
+output_pass_setup(j_decompress_ptr cinfo)
{
if (cinfo->global_state != DSTATE_PRESCAN) {
/* First call: do pass setup */
JDIMENSION last_scanline;
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
- cinfo->progress->pass_counter = (long) cinfo->output_scanline;
- cinfo->progress->pass_limit = (long) cinfo->output_height;
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ cinfo->progress->pass_counter = (long)cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long)cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
}
/* Process some data */
last_scanline = cinfo->output_scanline;
- (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL,
- &cinfo->output_scanline, (JDIMENSION) 0);
+ (*cinfo->main->process_data) (cinfo, (JSAMPARRAY)NULL,
+ &cinfo->output_scanline, (JDIMENSION)0);
if (cinfo->output_scanline == last_scanline)
return FALSE; /* No progress made, must suspend */
}
*/
GLOBAL(void)
-jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
- JDIMENSION *width)
+jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset,
+ JDIMENSION *width)
{
int ci, align, orig_downsampled_width;
JDIMENSION input_xoffset;
/* Set the first and last iMCU columns that we must decompress. These values
* will be used in single-scan decompressions.
*/
- cinfo->master->first_iMCU_col =
- (JDIMENSION) (long) (*xoffset) / (long) align;
+ cinfo->master->first_iMCU_col = (JDIMENSION)(long)(*xoffset) / (long)align;
cinfo->master->last_iMCU_col =
- (JDIMENSION) jdiv_round_up((long) (*xoffset + cinfo->output_width),
- (long) align) - 1;
+ (JDIMENSION)jdiv_round_up((long)(*xoffset + cinfo->output_width),
+ (long)align) - 1;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Set downsampled_width to the new output width. */
orig_downsampled_width = compptr->downsampled_width;
compptr->downsampled_width =
- (JDIMENSION) jdiv_round_up((long) (cinfo->output_width *
- compptr->h_samp_factor),
- (long) cinfo->max_h_samp_factor);
+ (JDIMENSION)jdiv_round_up((long)(cinfo->output_width *
+ compptr->h_samp_factor),
+ (long)cinfo->max_h_samp_factor);
if (compptr->downsampled_width < 2 && orig_downsampled_width >= 2)
reinit_upsampler = TRUE;
* values will be used in multi-scan decompressions.
*/
cinfo->master->first_MCU_col[ci] =
- (JDIMENSION) (long) (*xoffset * hsf) / (long) align;
+ (JDIMENSION)(long)(*xoffset * hsf) / (long)align;
cinfo->master->last_MCU_col[ci] =
- (JDIMENSION) jdiv_round_up((long) ((*xoffset + cinfo->output_width) *
- hsf),
- (long) align) - 1;
+ (JDIMENSION)jdiv_round_up((long)((*xoffset + cinfo->output_width) * hsf),
+ (long)align) - 1;
}
if (reinit_upsampler) {
*/
GLOBAL(JDIMENSION)
-jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
- JDIMENSION max_lines)
+jpeg_read_scanlines(j_decompress_ptr cinfo, JSAMPARRAY scanlines,
+ JDIMENSION max_lines)
{
JDIMENSION row_ctr;
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
- cinfo->progress->pass_counter = (long) cinfo->output_scanline;
- cinfo->progress->pass_limit = (long) cinfo->output_height;
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ cinfo->progress->pass_counter = (long)cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long)cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
}
/* Process some data */
/* Dummy color convert function used by jpeg_skip_scanlines() */
LOCAL(void)
-noop_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
- JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
+noop_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
}
/* Dummy quantize function used by jpeg_skip_scanlines() */
LOCAL(void)
-noop_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
- JSAMPARRAY output_buf, int num_rows)
+noop_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
{
}
*/
LOCAL(void)
-read_and_discard_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
+read_and_discard_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines)
{
JDIMENSION n;
void (*color_convert) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
JDIMENSION input_row, JSAMPARRAY output_buf,
- int num_rows);
+ int num_rows) = NULL;
void (*color_quantize) (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
JSAMPARRAY output_buf, int num_rows) = NULL;
- color_convert = cinfo->cconvert->color_convert;
- cinfo->cconvert->color_convert = noop_convert;
+ if (cinfo->cconvert && cinfo->cconvert->color_convert) {
+ color_convert = cinfo->cconvert->color_convert;
+ cinfo->cconvert->color_convert = noop_convert;
+ }
+
if (cinfo->cquantize && cinfo->cquantize->color_quantize) {
color_quantize = cinfo->cquantize->color_quantize;
cinfo->cquantize->color_quantize = noop_quantize;
for (n = 0; n < num_lines; n++)
jpeg_read_scanlines(cinfo, NULL, 1);
- cinfo->cconvert->color_convert = color_convert;
+ if (color_convert)
+ cinfo->cconvert->color_convert = color_convert;
+
if (color_quantize)
cinfo->cquantize->color_quantize = color_quantize;
}
*/
LOCAL(void)
-increment_simple_rowgroup_ctr (j_decompress_ptr cinfo, JDIMENSION rows)
+increment_simple_rowgroup_ctr(j_decompress_ptr cinfo, JDIMENSION rows)
{
JDIMENSION rows_left;
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
/* Increment the counter to the next row group after the skipped rows. */
main_ptr->rowgroup_ctr += rows / cinfo->max_v_samp_factor;
*/
GLOBAL(JDIMENSION)
-jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
+jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines)
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
JDIMENSION i, x;
int y;
JDIMENSION lines_per_iMCU_row, lines_left_in_iMCU_row, lines_after_iMCU_row;
if (cinfo->upsample->need_context_rows) {
cinfo->output_scanline += lines_to_skip;
cinfo->output_iMCU_row += lines_to_skip / lines_per_iMCU_row;
- main_ptr->iMCU_row_ctr += lines_after_iMCU_row / lines_per_iMCU_row;
+ main_ptr->iMCU_row_ctr += lines_to_skip / lines_per_iMCU_row;
/* It is complex to properly move to the middle of a context block, so
* read the remaining lines instead of skipping them.
*/
*/
GLOBAL(JDIMENSION)
-jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
- JDIMENSION max_lines)
+jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data,
+ JDIMENSION max_lines)
{
JDIMENSION lines_per_iMCU_row;
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
- cinfo->progress->pass_counter = (long) cinfo->output_scanline;
- cinfo->progress->pass_limit = (long) cinfo->output_height;
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ cinfo->progress->pass_counter = (long)cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long)cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
}
/* Verify that at least one iMCU row can be returned. */
ERREXIT(cinfo, JERR_BUFFER_SIZE);
/* Decompress directly into user's buffer. */
- if (! (*cinfo->coef->decompress_data) (cinfo, data))
+ if (!(*cinfo->coef->decompress_data) (cinfo, data))
return 0; /* suspension forced, can do nothing more */
/* OK, we processed one iMCU row. */
*/
GLOBAL(boolean)
-jpeg_start_output (j_decompress_ptr cinfo, int scan_number)
+jpeg_start_output(j_decompress_ptr cinfo, int scan_number)
{
if (cinfo->global_state != DSTATE_BUFIMAGE &&
cinfo->global_state != DSTATE_PRESCAN)
/* Limit scan number to valid range */
if (scan_number <= 0)
scan_number = 1;
- if (cinfo->inputctl->eoi_reached &&
- scan_number > cinfo->input_scan_number)
+ if (cinfo->inputctl->eoi_reached && scan_number > cinfo->input_scan_number)
scan_number = cinfo->input_scan_number;
cinfo->output_scan_number = scan_number;
/* Perform any dummy output passes, and set up for the real pass */
*/
GLOBAL(boolean)
-jpeg_finish_output (j_decompress_ptr cinfo)
+jpeg_finish_output(j_decompress_ptr cinfo)
{
if ((cinfo->global_state == DSTATE_SCANNING ||
cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) {
}
/* Read markers looking for SOS or EOI */
while (cinfo->input_scan_number <= cinfo->output_scan_number &&
- ! cinfo->inputctl->eoi_reached) {
+ !cinfo->inputctl->eoi_reached) {
if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
return FALSE; /* Suspend, come back later */
}
* This file was part of the Independent JPEG Group's software:
* Developed 1997-2015 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2015-2016, D. R. Commander.
+ * Copyright (C) 2015-2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
- * This file contains portable arithmetic entropy decoding routines for JPEG
- * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81).
+ * This file contains portable arithmetic entropy encoding routines for JPEG
+ * (implementing Recommendation ITU-T T.81 | ISO/IEC 10918-1).
*
* Both sequential and progressive modes are supported in this single module.
*
* Suspension is not currently supported in this module.
+ *
+ * NOTE: All referenced figures are from
+ * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994.
*/
#define JPEG_INTERNALS
#include "jpeglib.h"
-#define NEG_1 ((unsigned int)-1)
+#define NEG_1 ((unsigned int)-1)
/* Expanded entropy decoder object for arithmetic decoding. */
* in the lower bits (mask 0x7F).
*/
-#define DC_STAT_BINS 64
-#define AC_STAT_BINS 256
+#define DC_STAT_BINS 64
+#define AC_STAT_BINS 256
LOCAL(int)
-get_byte (j_decompress_ptr cinfo)
+get_byte(j_decompress_ptr cinfo)
/* Read next input byte; we do not support suspension in this module. */
{
struct jpeg_source_mgr *src = cinfo->src;
if (src->bytes_in_buffer == 0)
- if (! (*src->fill_input_buffer) (cinfo))
+ if (!(*src->fill_input_buffer) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
src->bytes_in_buffer--;
return GETJOCTET(*src->next_input_byte++);
*/
LOCAL(int)
-arith_decode (j_decompress_ptr cinfo, unsigned char *st)
+arith_decode(j_decompress_ptr cinfo, unsigned char *st)
{
- register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy;
+ register arith_entropy_ptr e = (arith_entropy_ptr)cinfo->entropy;
register unsigned char nl, nm;
register JLONG qe, temp;
register int sv, data;
*/
sv = *st;
qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */
- nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */
- nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */
+ nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */
+ nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */
/* Decode & estimation procedures per sections D.2.4 & D.2.5 */
temp = e->a - qe;
*/
LOCAL(void)
-process_restart (j_decompress_ptr cinfo)
+process_restart(j_decompress_ptr cinfo)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
int ci;
jpeg_component_info *compptr;
/* Advance past the RSTn marker */
- if (! (*cinfo->marker->read_restart_marker) (cinfo))
+ if (!(*cinfo->marker->read_restart_marker) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
/* Re-initialize statistics areas */
*/
METHODDEF(boolean)
-decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_DC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
JBLOCKROW block;
unsigned char *st;
int blkn, ci, tbl, sign;
/* Figure F.21: Decoding nonzero value v */
/* Figure F.22: Decoding the sign of v */
sign = arith_decode(cinfo, st + 1);
- st += 2; st += sign;
+ st += 2; st += sign;
/* Figure F.23: Decoding the magnitude category of v */
if ((m = arith_decode(cinfo, st)) != 0) {
st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */
}
}
/* Section F.1.4.4.1.2: Establish dc_context conditioning category */
- if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1))
+ if (m < (int)((1L << cinfo->arith_dc_L[tbl]) >> 1))
entropy->dc_context[ci] = 0; /* zero diff category */
- else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1))
+ else if (m > (int)((1L << cinfo->arith_dc_U[tbl]) >> 1))
entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */
else
entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */
st += 14;
while (m >>= 1)
if (arith_decode(cinfo, st)) v |= m;
- v += 1; if (sign) v = -v;
- entropy->last_dc_val[ci] += v;
+ v += 1; if (sign) v = -v;
+ entropy->last_dc_val[ci] = (entropy->last_dc_val[ci] + v) & 0xffff;
}
/* Scale and output the DC coefficient (assumes jpeg_natural_order[0]=0) */
- (*block)[0] = (JCOEF) LEFT_SHIFT(entropy->last_dc_val[ci], cinfo->Al);
+ (*block)[0] = (JCOEF)LEFT_SHIFT(entropy->last_dc_val[ci], cinfo->Al);
}
return TRUE;
*/
METHODDEF(boolean)
-decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_AC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
JBLOCKROW block;
unsigned char *st;
int tbl, sign, k;
st = entropy->ac_stats[tbl] + 3 * (k - 1);
if (arith_decode(cinfo, st)) break; /* EOB flag */
while (arith_decode(cinfo, st + 1) == 0) {
- st += 3; k++;
+ st += 3; k++;
if (k > cinfo->Se) {
WARNMS(cinfo, JWRN_ARITH_BAD_CODE);
entropy->ct = -1; /* spectral overflow */
st += 14;
while (m >>= 1)
if (arith_decode(cinfo, st)) v |= m;
- v += 1; if (sign) v = -v;
+ v += 1; if (sign) v = -v;
/* Scale and output coefficient in natural (dezigzagged) order */
- (*block)[jpeg_natural_order[k]] = (JCOEF) ((unsigned)v << cinfo->Al);
+ (*block)[jpeg_natural_order[k]] = (JCOEF)((unsigned)v << cinfo->Al);
}
return TRUE;
*/
METHODDEF(boolean)
-decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_DC_refine(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
unsigned char *st;
int p1, blkn;
*/
METHODDEF(boolean)
-decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_AC_refine(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
JBLOCKROW block;
JCOEFPTR thiscoef;
unsigned char *st;
*thiscoef = p1;
break;
}
- st += 3; k++;
+ st += 3; k++;
if (k > cinfo->Se) {
WARNMS(cinfo, JWRN_ARITH_BAD_CODE);
entropy->ct = -1; /* spectral overflow */
*/
METHODDEF(boolean)
-decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
jpeg_component_info *compptr;
JBLOCKROW block;
unsigned char *st;
/* Figure F.21: Decoding nonzero value v */
/* Figure F.22: Decoding the sign of v */
sign = arith_decode(cinfo, st + 1);
- st += 2; st += sign;
+ st += 2; st += sign;
/* Figure F.23: Decoding the magnitude category of v */
if ((m = arith_decode(cinfo, st)) != 0) {
st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */
}
}
/* Section F.1.4.4.1.2: Establish dc_context conditioning category */
- if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1))
+ if (m < (int)((1L << cinfo->arith_dc_L[tbl]) >> 1))
entropy->dc_context[ci] = 0; /* zero diff category */
- else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1))
+ else if (m > (int)((1L << cinfo->arith_dc_U[tbl]) >> 1))
entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */
else
entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */
st += 14;
while (m >>= 1)
if (arith_decode(cinfo, st)) v |= m;
- v += 1; if (sign) v = -v;
- entropy->last_dc_val[ci] += v;
+ v += 1; if (sign) v = -v;
+ entropy->last_dc_val[ci] = (entropy->last_dc_val[ci] + v) & 0xffff;
}
if (block)
- (*block)[0] = (JCOEF) entropy->last_dc_val[ci];
+ (*block)[0] = (JCOEF)entropy->last_dc_val[ci];
/* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */
st = entropy->ac_stats[tbl] + 3 * (k - 1);
if (arith_decode(cinfo, st)) break; /* EOB flag */
while (arith_decode(cinfo, st + 1) == 0) {
- st += 3; k++;
+ st += 3; k++;
if (k > DCTSIZE2 - 1) {
WARNMS(cinfo, JWRN_ARITH_BAD_CODE);
entropy->ct = -1; /* spectral overflow */
st += 14;
while (m >>= 1)
if (arith_decode(cinfo, st)) v |= m;
- v += 1; if (sign) v = -v;
+ v += 1; if (sign) v = -v;
if (block)
- (*block)[jpeg_natural_order[k]] = (JCOEF) v;
+ (*block)[jpeg_natural_order[k]] = (JCOEF)v;
}
}
*/
METHODDEF(void)
-start_pass (j_decompress_ptr cinfo)
+start_pass(j_decompress_ptr cinfo)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
int ci, tbl;
jpeg_component_info *compptr;
}
if (cinfo->Ah != 0) {
/* Successive approximation refinement scan: must have Al = Ah-1. */
- if (cinfo->Ah-1 != cinfo->Al)
+ if (cinfo->Ah - 1 != cinfo->Al)
goto bad;
}
if (cinfo->Al > 13) { /* need not check for < 0 */
- bad:
+bad:
ERREXIT4(cinfo, JERR_BAD_PROGRESSION,
cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
}
*/
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 *coef_bit_ptr = &cinfo->coef_bits[cindex][0];
if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
if (entropy->dc_stats[tbl] == NULL)
- entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS);
+ entropy->dc_stats[tbl] = (unsigned char *)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, DC_STAT_BINS);
MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS);
/* Initialize DC predictions to 0 */
entropy->last_dc_val[ci] = 0;
if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
if (entropy->ac_stats[tbl] == NULL)
- entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS);
+ entropy->ac_stats[tbl] = (unsigned char *)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, AC_STAT_BINS);
MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS);
}
}
*/
GLOBAL(void)
-jinit_arith_decoder (j_decompress_ptr cinfo)
+jinit_arith_decoder(j_decompress_ptr cinfo)
{
arith_entropy_ptr entropy;
int i;
entropy = (arith_entropy_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(arith_entropy_decoder));
- cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
+ cinfo->entropy = (struct jpeg_entropy_decoder *)entropy;
entropy->pub.start_pass = start_pass;
/* Mark tables unallocated */
/* Create progression status table */
int *coef_bit_ptr, ci;
cinfo->coef_bits = (int (*)[DCTSIZE2])
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- cinfo->num_components*DCTSIZE2*sizeof(int));
- coef_bit_ptr = & cinfo->coef_bits[0][0];
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ cinfo->num_components * DCTSIZE2 *
+ sizeof(int));
+ coef_bit_ptr = &cinfo->coef_bits[0][0];
for (ci = 0; ci < cinfo->num_components; ci++)
for (i = 0; i < DCTSIZE2; i++)
*coef_bit_ptr++ = -1;
#include "jerror.h"
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
-extern void *malloc (size_t size);
-extern void free (void *ptr);
+extern void *malloc(size_t size);
+extern void free(void *ptr);
#endif
*/
METHODDEF(void)
-init_destination (j_compress_ptr cinfo)
+init_destination(j_compress_ptr cinfo)
{
- my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
/* Allocate the output buffer --- it will be released when done with image */
dest->buffer = (JOCTET *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- OUTPUT_BUF_SIZE * sizeof(JOCTET));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ OUTPUT_BUF_SIZE * sizeof(JOCTET));
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
METHODDEF(void)
-init_mem_destination (j_compress_ptr cinfo)
+init_mem_destination(j_compress_ptr cinfo)
{
/* no work necessary here */
}
*/
METHODDEF(boolean)
-empty_output_buffer (j_compress_ptr cinfo)
+empty_output_buffer(j_compress_ptr cinfo)
{
- my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) !=
- (size_t) OUTPUT_BUF_SIZE)
+ (size_t)OUTPUT_BUF_SIZE)
ERREXIT(cinfo, JERR_FILE_WRITE);
dest->pub.next_output_byte = dest->buffer;
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
METHODDEF(boolean)
-empty_mem_output_buffer (j_compress_ptr cinfo)
+empty_mem_output_buffer(j_compress_ptr cinfo)
{
size_t nextsize;
JOCTET *nextbuffer;
- my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest;
+ my_mem_dest_ptr dest = (my_mem_dest_ptr)cinfo->dest;
/* Try to allocate new buffer with double size */
nextsize = dest->bufsize * 2;
- nextbuffer = (JOCTET *) malloc(nextsize);
+ nextbuffer = (JOCTET *)malloc(nextsize);
if (nextbuffer == NULL)
ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10);
*/
METHODDEF(void)
-term_destination (j_compress_ptr cinfo)
+term_destination(j_compress_ptr cinfo)
{
- my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
/* Write any data remaining in the buffer */
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
METHODDEF(void)
-term_mem_destination (j_compress_ptr cinfo)
+term_mem_destination(j_compress_ptr cinfo)
{
- my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest;
+ my_mem_dest_ptr dest = (my_mem_dest_ptr)cinfo->dest;
*dest->outbuffer = dest->buffer;
*dest->outsize = (unsigned long)(dest->bufsize - dest->pub.free_in_buffer);
*/
GLOBAL(void)
-jpeg_stdio_dest (j_compress_ptr cinfo, FILE *outfile)
+jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile)
{
my_dest_ptr dest;
*/
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(my_destination_mgr));
} else if (cinfo->dest->init_destination != init_destination) {
/* It is unsafe to reuse the existing destination manager unless it was
ERREXIT(cinfo, JERR_BUFFER_SIZE);
}
- dest = (my_dest_ptr) cinfo->dest;
+ dest = (my_dest_ptr)cinfo->dest;
dest->pub.init_destination = init_destination;
dest->pub.empty_output_buffer = empty_output_buffer;
dest->pub.term_destination = term_destination;
*/
GLOBAL(void)
-jpeg_mem_dest (j_compress_ptr cinfo,
- unsigned char **outbuffer, unsigned long *outsize)
+jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer,
+ unsigned long *outsize)
{
my_mem_dest_ptr dest;
*/
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(my_mem_destination_mgr));
} else if (cinfo->dest->init_destination != init_mem_destination) {
/* It is unsafe to reuse the existing destination manager unless it was
ERREXIT(cinfo, JERR_BUFFER_SIZE);
}
- dest = (my_mem_dest_ptr) cinfo->dest;
+ dest = (my_mem_dest_ptr)cinfo->dest;
dest->pub.init_destination = init_mem_destination;
dest->pub.empty_output_buffer = empty_mem_output_buffer;
dest->pub.term_destination = term_mem_destination;
if (*outbuffer == NULL || *outsize == 0) {
/* Allocate initial buffer */
- dest->newbuffer = *outbuffer = (unsigned char *) malloc(OUTPUT_BUF_SIZE);
+ dest->newbuffer = *outbuffer = (unsigned char *)malloc(OUTPUT_BUF_SIZE);
if (dest->newbuffer == NULL)
ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10);
*outsize = OUTPUT_BUF_SIZE;
*/
METHODDEF(void)
-init_source (j_decompress_ptr cinfo)
+init_source(j_decompress_ptr cinfo)
{
- my_src_ptr src = (my_src_ptr) cinfo->src;
+ my_src_ptr src = (my_src_ptr)cinfo->src;
/* We reset the empty-input-file flag for each image,
* but we don't clear the input buffer.
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
METHODDEF(void)
-init_mem_source (j_decompress_ptr cinfo)
+init_mem_source(j_decompress_ptr cinfo)
{
/* no work necessary here */
}
*/
METHODDEF(boolean)
-fill_input_buffer (j_decompress_ptr cinfo)
+fill_input_buffer(j_decompress_ptr cinfo)
{
- my_src_ptr src = (my_src_ptr) cinfo->src;
+ my_src_ptr src = (my_src_ptr)cinfo->src;
size_t nbytes;
nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);
ERREXIT(cinfo, JERR_INPUT_EMPTY);
WARNMS(cinfo, JWRN_JPEG_EOF);
/* Insert a fake EOI marker */
- src->buffer[0] = (JOCTET) 0xFF;
- src->buffer[1] = (JOCTET) JPEG_EOI;
+ src->buffer[0] = (JOCTET)0xFF;
+ src->buffer[1] = (JOCTET)JPEG_EOI;
nbytes = 2;
}
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
METHODDEF(boolean)
-fill_mem_input_buffer (j_decompress_ptr cinfo)
+fill_mem_input_buffer(j_decompress_ptr cinfo)
{
static const JOCTET mybuffer[4] = {
- (JOCTET) 0xFF, (JOCTET) JPEG_EOI, 0, 0
+ (JOCTET)0xFF, (JOCTET)JPEG_EOI, 0, 0
};
/* The whole JPEG data is expected to reside in the supplied memory
*/
METHODDEF(void)
-skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+skip_input_data(j_decompress_ptr cinfo, long num_bytes)
{
struct jpeg_source_mgr *src = cinfo->src;
* any trouble anyway --- large skips are infrequent.
*/
if (num_bytes > 0) {
- while (num_bytes > (long) src->bytes_in_buffer) {
- num_bytes -= (long) src->bytes_in_buffer;
- (void) (*src->fill_input_buffer) (cinfo);
+ while (num_bytes > (long)src->bytes_in_buffer) {
+ num_bytes -= (long)src->bytes_in_buffer;
+ (void)(*src->fill_input_buffer) (cinfo);
/* note we assume that fill_input_buffer will never return FALSE,
* so suspension need not be handled.
*/
}
- src->next_input_byte += (size_t) num_bytes;
- src->bytes_in_buffer -= (size_t) num_bytes;
+ src->next_input_byte += (size_t)num_bytes;
+ src->bytes_in_buffer -= (size_t)num_bytes;
}
}
*/
METHODDEF(void)
-term_source (j_decompress_ptr cinfo)
+term_source(j_decompress_ptr cinfo)
{
/* no work necessary here */
}
*/
GLOBAL(void)
-jpeg_stdio_src (j_decompress_ptr cinfo, FILE *infile)
+jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile)
{
my_src_ptr src;
*/
if (cinfo->src == NULL) { /* first time for this JPEG object? */
cinfo->src = (struct jpeg_source_mgr *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(my_source_mgr));
- src = (my_src_ptr) cinfo->src;
+ src = (my_src_ptr)cinfo->src;
src->buffer = (JOCTET *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
INPUT_BUF_SIZE * sizeof(JOCTET));
} else if (cinfo->src->init_source != init_source) {
/* It is unsafe to reuse the existing source manager unless it was created
ERREXIT(cinfo, JERR_BUFFER_SIZE);
}
- src = (my_src_ptr) cinfo->src;
+ src = (my_src_ptr)cinfo->src;
src->pub.init_source = init_source;
src->pub.fill_input_buffer = fill_input_buffer;
src->pub.skip_input_data = skip_input_data;
*/
GLOBAL(void)
-jpeg_mem_src (j_decompress_ptr cinfo,
- const unsigned char *inbuffer, unsigned long insize)
+jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *inbuffer,
+ unsigned long insize)
{
struct jpeg_source_mgr *src;
*/
if (cinfo->src == NULL) { /* first time for this JPEG object? */
cinfo->src = (struct jpeg_source_mgr *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(struct jpeg_source_mgr));
} else if (cinfo->src->init_source != init_mem_source) {
/* It is unsafe to reuse the existing source manager unless it was created
src->skip_input_data = skip_input_data;
src->resync_to_restart = jpeg_resync_to_restart; /* use default method */
src->term_source = term_source;
- src->bytes_in_buffer = (size_t) insize;
- src->next_input_byte = (const JOCTET *) inbuffer;
+ src->bytes_in_buffer = (size_t)insize;
+ src->next_input_byte = (const JOCTET *)inbuffer;
}
#endif
/* Forward declarations */
-METHODDEF(int) decompress_onepass
- (j_decompress_ptr cinfo, JSAMPIMAGE output_buf);
+METHODDEF(int) decompress_onepass(j_decompress_ptr cinfo,
+ JSAMPIMAGE output_buf);
#ifdef D_MULTISCAN_FILES_SUPPORTED
-METHODDEF(int) decompress_data
- (j_decompress_ptr cinfo, JSAMPIMAGE output_buf);
+METHODDEF(int) decompress_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf);
#endif
#ifdef BLOCK_SMOOTHING_SUPPORTED
-LOCAL(boolean) smoothing_ok (j_decompress_ptr cinfo);
-METHODDEF(int) decompress_smooth_data
- (j_decompress_ptr cinfo, JSAMPIMAGE output_buf);
+LOCAL(boolean) smoothing_ok(j_decompress_ptr cinfo);
+METHODDEF(int) decompress_smooth_data(j_decompress_ptr cinfo,
+ JSAMPIMAGE output_buf);
#endif
*/
METHODDEF(void)
-start_input_pass (j_decompress_ptr cinfo)
+start_input_pass(j_decompress_ptr cinfo)
{
cinfo->input_iMCU_row = 0;
start_iMCU_row(cinfo);
*/
METHODDEF(void)
-start_output_pass (j_decompress_ptr cinfo)
+start_output_pass(j_decompress_ptr cinfo)
{
#ifdef BLOCK_SMOOTHING_SUPPORTED
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
/* If multipass, check to see whether to use block smoothing on this pass */
if (coef->pub.coef_arrays != NULL) {
*/
METHODDEF(int)
-decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+decompress_onepass(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col;
MCU_col_num++) {
/* 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->decode_mcu) (cinfo, coef->MCU_buffer)) {
+ jzero_far((void *)coef->MCU_buffer[0],
+ (size_t)(cinfo->blocks_in_MCU * sizeof(JBLOCK)));
+ if (!(*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->MCU_ctr = MCU_col_num;
* incremented past them!). Note the inner loop relies on having
* allocated the MCU_buffer[] blocks sequentially.
*/
- blkn = 0; /* index of current DCT block within MCU */
+ blkn = 0; /* index of current DCT block within MCU */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* Don't bother to IDCT an uninteresting component. */
- if (! compptr->component_needed) {
+ if (!compptr->component_needed) {
blkn += compptr->MCU_blocks;
continue;
}
inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index];
- useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
- : compptr->last_col_width;
+ useful_width = (MCU_col_num < last_MCU_col) ?
+ compptr->MCU_width : compptr->last_col_width;
output_ptr = output_buf[compptr->component_index] +
- yoffset * compptr->_DCT_scaled_size;
+ yoffset * compptr->_DCT_scaled_size;
start_col = (MCU_col_num - cinfo->master->first_iMCU_col) *
- compptr->MCU_sample_width;
+ compptr->MCU_sample_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
if (cinfo->input_iMCU_row < last_iMCU_row ||
- yoffset+yindex < compptr->last_row_height) {
+ yoffset + yindex < compptr->last_row_height) {
output_col = start_col;
for (xindex = 0; xindex < useful_width; xindex++) {
(*inverse_DCT) (cinfo, compptr,
- (JCOEFPTR) coef->MCU_buffer[blkn+xindex],
+ (JCOEFPTR)coef->MCU_buffer[blkn + xindex],
output_ptr, output_col);
output_col += compptr->_DCT_scaled_size;
}
*/
METHODDEF(int)
-dummy_consume_data (j_decompress_ptr cinfo)
+dummy_consume_data(j_decompress_ptr cinfo)
{
return JPEG_SUSPENDED; /* Always indicate nothing was done */
}
*/
METHODDEF(int)
-consume_data (j_decompress_ptr cinfo)
+consume_data(j_decompress_ptr cinfo)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
int blkn, ci, xindex, yindex, yoffset;
JDIMENSION start_col;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
buffer[ci] = (*cinfo->mem->access_virt_barray)
- ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ ((j_common_ptr)cinfo, coef->whole_image[compptr->component_index],
cinfo->input_iMCU_row * compptr->v_samp_factor,
- (JDIMENSION) compptr->v_samp_factor, TRUE);
+ (JDIMENSION)compptr->v_samp_factor, TRUE);
/* Note: entropy decoder expects buffer to be zeroed,
* but this is handled automatically by the memory manager
* because we requested a pre-zeroed array.
compptr = cinfo->cur_comp_info[ci];
start_col = MCU_col_num * compptr->MCU_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
- buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ buffer_ptr = buffer[ci][yindex + yoffset] + start_col;
for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
coef->MCU_buffer[blkn++] = buffer_ptr++;
}
}
}
/* Try to fetch the MCU. */
- if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
+ if (!(*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->MCU_ctr = MCU_col_num;
*/
METHODDEF(int)
-decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+decompress_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
JDIMENSION block_num;
int ci, block_row, block_rows;
while (cinfo->input_scan_number < cinfo->output_scan_number ||
(cinfo->input_scan_number == cinfo->output_scan_number &&
cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) {
- if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
+ if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
return JPEG_SUSPENDED;
}
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Don't bother to IDCT an uninteresting component. */
- if (! compptr->component_needed)
+ if (!compptr->component_needed)
continue;
/* Align the virtual buffer for this component. */
buffer = (*cinfo->mem->access_virt_barray)
- ((j_common_ptr) cinfo, coef->whole_image[ci],
+ ((j_common_ptr)cinfo, coef->whole_image[ci],
cinfo->output_iMCU_row * compptr->v_samp_factor,
- (JDIMENSION) compptr->v_samp_factor, FALSE);
+ (JDIMENSION)compptr->v_samp_factor, FALSE);
/* Count non-dummy DCT block rows in this iMCU row. */
if (cinfo->output_iMCU_row < last_iMCU_row)
block_rows = compptr->v_samp_factor;
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);
+ block_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
if (block_rows == 0) block_rows = compptr->v_samp_factor;
}
inverse_DCT = cinfo->idct->inverse_DCT[ci];
output_col = 0;
for (block_num = cinfo->master->first_MCU_col[ci];
block_num <= cinfo->master->last_MCU_col[ci]; block_num++) {
- (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
- output_ptr, output_col);
+ (*inverse_DCT) (cinfo, compptr, (JCOEFPTR)buffer_ptr, output_ptr,
+ output_col);
buffer_ptr++;
output_col += compptr->_DCT_scaled_size;
}
*/
LOCAL(boolean)
-smoothing_ok (j_decompress_ptr cinfo)
+smoothing_ok(j_decompress_ptr cinfo)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
boolean smoothing_useful = FALSE;
int ci, coefi;
jpeg_component_info *compptr;
int *coef_bits;
int *coef_bits_latch;
- if (! cinfo->progressive_mode || cinfo->coef_bits == NULL)
+ if (!cinfo->progressive_mode || cinfo->coef_bits == NULL)
return FALSE;
/* Allocate latch area if not already done */
if (coef->coef_bits_latch == NULL)
coef->coef_bits_latch = (int *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
cinfo->num_components *
(SAVED_COEFS * sizeof(int)));
coef_bits_latch = coef->coef_bits_latch;
*/
METHODDEF(int)
-decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
JDIMENSION block_num, last_block_column;
int ci, block_row, block_rows, access_rows;
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, Q10, Q11, Q20, num;
+ int DC1, DC2, DC3, DC4, DC5, DC6, DC7, DC8, DC9;
int Al, pred;
/* Keep a local variable to avoid looking it up more than once */
/* Force some input to be done if we are getting ahead of the input. */
while (cinfo->input_scan_number <= cinfo->output_scan_number &&
- ! cinfo->inputctl->eoi_reached) {
+ !cinfo->inputctl->eoi_reached) {
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,
* values are up to date.
*/
JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0;
- if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta)
+ if (cinfo->input_iMCU_row > cinfo->output_iMCU_row + delta)
break;
}
- if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
+ if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
return JPEG_SUSPENDED;
}
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Don't bother to IDCT an uninteresting component. */
- if (! compptr->component_needed)
+ if (!compptr->component_needed)
continue;
/* Count non-dummy DCT block rows in this iMCU row. */
if (cinfo->output_iMCU_row < last_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);
+ 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;
if (cinfo->output_iMCU_row > 0) {
access_rows += compptr->v_samp_factor; /* prior iMCU row too */
buffer = (*cinfo->mem->access_virt_barray)
- ((j_common_ptr) cinfo, coef->whole_image[ci],
+ ((j_common_ptr)cinfo, coef->whole_image[ci],
(cinfo->output_iMCU_row - 1) * compptr->v_samp_factor,
- (JDIMENSION) access_rows, FALSE);
+ (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);
+ ((j_common_ptr)cinfo, coef->whole_image[ci],
+ (JDIMENSION)0, (JDIMENSION)access_rows, FALSE);
first_row = TRUE;
}
/* Fetch component-dependent info */
if (first_row && block_row == 0)
prev_block_row = buffer_ptr;
else
- prev_block_row = buffer[block_row-1];
- if (last_row && block_row == block_rows-1)
+ prev_block_row = buffer[block_row - 1];
+ if (last_row && block_row == block_rows - 1)
next_block_row = buffer_ptr;
else
- next_block_row = buffer[block_row+1];
+ next_block_row = buffer[block_row + 1];
/* 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.
*/
- 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];
+ 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];
output_col = 0;
last_block_column = compptr->width_in_blocks - 1;
for (block_num = cinfo->master->first_MCU_col[ci];
block_num <= cinfo->master->last_MCU_col[ci]; block_num++) {
/* Fetch current DCT block into workspace so we can modify it. */
- jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1);
+ 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];
+ DC3 = (int)prev_block_row[1][0];
+ DC6 = (int)buffer_ptr[1][0];
+ DC9 = (int)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.
*/
/* AC01 */
- if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) {
+ if ((Al = coef_bits[1]) != 0 && workspace[1] == 0) {
num = 36 * Q00 * (DC4 - DC6);
if (num >= 0) {
- pred = (int) (((Q01<<7) + num) / (Q01<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q01 << 7) + num) / (Q01 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
} else {
- pred = (int) (((Q01<<7) - num) / (Q01<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q01 << 7) - num) / (Q01 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
pred = -pred;
}
- workspace[1] = (JCOEF) pred;
+ workspace[1] = (JCOEF)pred;
}
/* AC10 */
- if ((Al=coef_bits[2]) != 0 && workspace[8] == 0) {
+ if ((Al = coef_bits[2]) != 0 && workspace[8] == 0) {
num = 36 * Q00 * (DC2 - DC8);
if (num >= 0) {
- pred = (int) (((Q10<<7) + num) / (Q10<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q10 << 7) + num) / (Q10 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
} else {
- pred = (int) (((Q10<<7) - num) / (Q10<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q10 << 7) - num) / (Q10 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
pred = -pred;
}
- workspace[8] = (JCOEF) pred;
+ workspace[8] = (JCOEF)pred;
}
/* AC20 */
- if ((Al=coef_bits[3]) != 0 && workspace[16] == 0) {
- num = 9 * Q00 * (DC2 + DC8 - 2*DC5);
+ if ((Al = coef_bits[3]) != 0 && workspace[16] == 0) {
+ num = 9 * Q00 * (DC2 + DC8 - 2 * DC5);
if (num >= 0) {
- pred = (int) (((Q20<<7) + num) / (Q20<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q20 << 7) + num) / (Q20 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
} else {
- pred = (int) (((Q20<<7) - num) / (Q20<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q20 << 7) - num) / (Q20 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
pred = -pred;
}
- workspace[16] = (JCOEF) pred;
+ workspace[16] = (JCOEF)pred;
}
/* AC11 */
- if ((Al=coef_bits[4]) != 0 && workspace[9] == 0) {
+ if ((Al = coef_bits[4]) != 0 && workspace[9] == 0) {
num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
if (num >= 0) {
- pred = (int) (((Q11<<7) + num) / (Q11<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q11 << 7) + num) / (Q11 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
} else {
- pred = (int) (((Q11<<7) - num) / (Q11<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q11 << 7) - num) / (Q11 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
pred = -pred;
}
- workspace[9] = (JCOEF) pred;
+ workspace[9] = (JCOEF)pred;
}
/* AC02 */
- if ((Al=coef_bits[5]) != 0 && workspace[2] == 0) {
- num = 9 * Q00 * (DC4 + DC6 - 2*DC5);
+ if ((Al = coef_bits[5]) != 0 && workspace[2] == 0) {
+ num = 9 * Q00 * (DC4 + DC6 - 2 * DC5);
if (num >= 0) {
- pred = (int) (((Q02<<7) + num) / (Q02<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q02 << 7) + num) / (Q02 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
} else {
- pred = (int) (((Q02<<7) - num) / (Q02<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q02 << 7) - num) / (Q02 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
pred = -pred;
}
- workspace[2] = (JCOEF) pred;
+ workspace[2] = (JCOEF)pred;
}
/* OK, do the IDCT */
- (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workspace,
- output_ptr, output_col);
+ (*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;
+ DC1 = DC2; DC2 = DC3;
+ DC4 = DC5; DC5 = DC6;
+ DC7 = DC8; DC8 = DC9;
buffer_ptr++, prev_block_row++, next_block_row++;
output_col += compptr->_DCT_scaled_size;
}
*/
GLOBAL(void)
-jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
{
my_coef_ptr coef;
coef = (my_coef_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_coef_controller));
- cinfo->coef = (struct jpeg_d_coef_controller *) coef;
+ cinfo->coef = (struct jpeg_d_coef_controller *)coef;
coef->pub.start_input_pass = start_input_pass;
coef->pub.start_output_pass = start_output_pass;
#ifdef BLOCK_SMOOTHING_SUPPORTED
access_rows *= 3;
#endif
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE,
- (JDIMENSION) jround_up((long) compptr->width_in_blocks,
- (long) compptr->h_samp_factor),
- (JDIMENSION) jround_up((long) compptr->height_in_blocks,
- (long) compptr->v_samp_factor),
- (JDIMENSION) access_rows);
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, TRUE,
+ (JDIMENSION)jround_up((long)compptr->width_in_blocks,
+ (long)compptr->h_samp_factor),
+ (JDIMENSION)jround_up((long)compptr->height_in_blocks,
+ (long)compptr->v_samp_factor),
+ (JDIMENSION)access_rows);
}
coef->pub.consume_data = consume_data;
coef->pub.decompress_data = decompress_data;
int i;
buffer = (JBLOCKROW)
- (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE,
D_MAX_BLOCKS_IN_MCU * sizeof(JBLOCK));
for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) {
coef->MCU_buffer[i] = buffer + i;
/* Allocate the workspace buffer */
coef->workspace = (JCOEF *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(JCOEF) * DCTSIZE2);
}
LOCAL(void)
-start_iMCU_row (j_decompress_ptr cinfo)
+start_iMCU_row(j_decompress_ptr cinfo)
/* Reset within-iMCU-row counters for a new row (input side) */
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
/* In an interleaved scan, an MCU row is the same as an iMCU row.
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
if (cinfo->comps_in_scan > 1) {
coef->MCU_rows_per_iMCU_row = 1;
} else {
- if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
+ if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows - 1))
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
else
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
INLINE
LOCAL(void)
-ycc_rgb565_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+ycc_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int y, cb, cr;
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->output_width;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- register int * Crrtab = cconvert->Cr_r_tab;
- register int * Cbbtab = cconvert->Cb_b_tab;
- register JLONG * Crgtab = cconvert->Cr_g_tab;
- register JLONG * Cbgtab = cconvert->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ register int *Crrtab = cconvert->Cr_r_tab;
+ register int *Cbbtab = cconvert->Cb_b_tab;
+ register JLONG *Crgtab = cconvert->Cr_g_tab;
+ register JLONG *Cbgtab = cconvert->Cb_g_tab;
SHIFT_TEMPS
while (--num_rows >= 0) {
SCALEBITS))];
b = range_limit[y + Cbbtab[cb]];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
outptr += 2;
num_cols--;
}
SCALEBITS))];
b = range_limit[y + Cbbtab[cb]];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
}
}
}
INLINE
LOCAL(void)
-ycc_rgb565D_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int y, cb, cr;
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->output_width;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- register int * Crrtab = cconvert->Cr_r_tab;
- register int * Cbbtab = cconvert->Cb_b_tab;
- register JLONG * Crgtab = cconvert->Cr_g_tab;
- register JLONG * Cbgtab = cconvert->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ register int *Crrtab = cconvert->Cr_r_tab;
+ register int *Cbbtab = cconvert->Cb_b_tab;
+ register JLONG *Crgtab = cconvert->Cr_g_tab;
+ register JLONG *Cbgtab = cconvert->Cb_g_tab;
JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
SHIFT_TEMPS
SCALEBITS)), d0)];
b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
outptr += 2;
num_cols--;
}
SCALEBITS)), d0)];
b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
}
}
}
INLINE
LOCAL(void)
-rgb_rgb565_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+rgb_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2;
g = GETJSAMPLE(*inptr1++);
b = GETJSAMPLE(*inptr2++);
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
outptr += 2;
num_cols--;
}
g = GETJSAMPLE(*inptr1);
b = GETJSAMPLE(*inptr2);
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
}
}
}
INLINE
LOCAL(void)
-rgb_rgb565D_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+rgb_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2;
register JDIMENSION col;
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
JDIMENSION num_cols = cinfo->output_width;
JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
SHIFT_TEMPS
g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
outptr += 2;
num_cols--;
}
g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1), d0)];
b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2), d0)];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
}
}
}
INLINE
LOCAL(void)
-gray_rgb565_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+gray_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
register JSAMPROW inptr, outptr;
register JDIMENSION col;
if (PACK_NEED_ALIGNMENT(outptr)) {
g = *inptr++;
rgb = PACK_SHORT_565(g, g, g);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
outptr += 2;
num_cols--;
}
if (num_cols & 1) {
g = *inptr;
rgb = PACK_SHORT_565(g, g, g);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
}
}
}
INLINE
LOCAL(void)
-gray_rgb565D_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+gray_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
register JSAMPROW inptr, outptr;
register JDIMENSION col;
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
JDIMENSION num_cols = cinfo->output_width;
JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
g = *inptr++;
g = range_limit[DITHER_565_R(g, d0)];
rgb = PACK_SHORT_565(g, g, g);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
outptr += 2;
num_cols--;
}
g = *inptr;
g = range_limit[DITHER_565_R(g, d0)];
rgb = PACK_SHORT_565(g, g, g);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
}
}
}
INLINE
LOCAL(void)
-ycc_rgb_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+ycc_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int y, cb, cr;
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->output_width;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- register int * Crrtab = cconvert->Cr_r_tab;
- register int * Cbbtab = cconvert->Cb_b_tab;
- register JLONG * Crgtab = cconvert->Cr_g_tab;
- register JLONG * Cbgtab = cconvert->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ register int *Crrtab = cconvert->Cr_r_tab;
+ register int *Cbbtab = cconvert->Cb_b_tab;
+ register JLONG *Crgtab = cconvert->Cr_g_tab;
+ register JLONG *Cbgtab = cconvert->Cb_g_tab;
SHIFT_TEMPS
while (--num_rows >= 0) {
/* 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 +
- ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
- SCALEBITS))];
+ ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
+ SCALEBITS))];
outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]];
/* Set unused byte to 0xFF so it can be interpreted as an opaque */
/* alpha channel value */
INLINE
LOCAL(void)
-gray_rgb_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+gray_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
register JSAMPROW inptr, outptr;
register JDIMENSION col;
INLINE
LOCAL(void)
-rgb_rgb_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+rgb_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
register JSAMPROW inptr0, inptr1, inptr2;
register JSAMPROW outptr;
*/
#define SCALEBITS 16 /* speediest right-shift on some machines */
-#define ONE_HALF ((JLONG) 1 << (SCALEBITS-1))
-#define FIX(x) ((JLONG) ((x) * (1L<<SCALEBITS) + 0.5))
+#define ONE_HALF ((JLONG)1 << (SCALEBITS - 1))
+#define FIX(x) ((JLONG)((x) * (1L << SCALEBITS) + 0.5))
/* We allocate one big table for RGB->Y conversion and divide it up into
* three parts, instead of doing three alloc_small requests. This lets us
*/
#define R_Y_OFF 0 /* offset to R => Y section */
-#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */
-#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */
-#define TABLE_SIZE (3*(MAXJSAMPLE+1))
+#define G_Y_OFF (1 * (MAXJSAMPLE + 1)) /* offset to G => Y section */
+#define B_Y_OFF (2 * (MAXJSAMPLE + 1)) /* etc. */
+#define TABLE_SIZE (3 * (MAXJSAMPLE + 1))
/* Include inline routines for colorspace extensions */
#undef RGB_BLUE
#undef RGB_PIXELSIZE
-#define RGB_RED EXT_RGB_RED
-#define RGB_GREEN EXT_RGB_GREEN
-#define RGB_BLUE EXT_RGB_BLUE
-#define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
-#define ycc_rgb_convert_internal ycc_extrgb_convert_internal
-#define gray_rgb_convert_internal gray_extrgb_convert_internal
-#define rgb_rgb_convert_internal rgb_extrgb_convert_internal
+#define RGB_RED EXT_RGB_RED
+#define RGB_GREEN EXT_RGB_GREEN
+#define RGB_BLUE EXT_RGB_BLUE
+#define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
+#define ycc_rgb_convert_internal ycc_extrgb_convert_internal
+#define gray_rgb_convert_internal gray_extrgb_convert_internal
+#define rgb_rgb_convert_internal rgb_extrgb_convert_internal
#include "jdcolext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef gray_rgb_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_RGBX_RED
-#define RGB_GREEN EXT_RGBX_GREEN
-#define RGB_BLUE EXT_RGBX_BLUE
-#define RGB_ALPHA 3
-#define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
-#define ycc_rgb_convert_internal ycc_extrgbx_convert_internal
-#define gray_rgb_convert_internal gray_extrgbx_convert_internal
-#define rgb_rgb_convert_internal rgb_extrgbx_convert_internal
+#define RGB_RED EXT_RGBX_RED
+#define RGB_GREEN EXT_RGBX_GREEN
+#define RGB_BLUE EXT_RGBX_BLUE
+#define RGB_ALPHA 3
+#define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
+#define ycc_rgb_convert_internal ycc_extrgbx_convert_internal
+#define gray_rgb_convert_internal gray_extrgbx_convert_internal
+#define rgb_rgb_convert_internal rgb_extrgbx_convert_internal
#include "jdcolext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef gray_rgb_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_BGR_RED
-#define RGB_GREEN EXT_BGR_GREEN
-#define RGB_BLUE EXT_BGR_BLUE
-#define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
-#define ycc_rgb_convert_internal ycc_extbgr_convert_internal
-#define gray_rgb_convert_internal gray_extbgr_convert_internal
-#define rgb_rgb_convert_internal rgb_extbgr_convert_internal
+#define RGB_RED EXT_BGR_RED
+#define RGB_GREEN EXT_BGR_GREEN
+#define RGB_BLUE EXT_BGR_BLUE
+#define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
+#define ycc_rgb_convert_internal ycc_extbgr_convert_internal
+#define gray_rgb_convert_internal gray_extbgr_convert_internal
+#define rgb_rgb_convert_internal rgb_extbgr_convert_internal
#include "jdcolext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef gray_rgb_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_BGRX_RED
-#define RGB_GREEN EXT_BGRX_GREEN
-#define RGB_BLUE EXT_BGRX_BLUE
-#define RGB_ALPHA 3
-#define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
-#define ycc_rgb_convert_internal ycc_extbgrx_convert_internal
-#define gray_rgb_convert_internal gray_extbgrx_convert_internal
-#define rgb_rgb_convert_internal rgb_extbgrx_convert_internal
+#define RGB_RED EXT_BGRX_RED
+#define RGB_GREEN EXT_BGRX_GREEN
+#define RGB_BLUE EXT_BGRX_BLUE
+#define RGB_ALPHA 3
+#define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
+#define ycc_rgb_convert_internal ycc_extbgrx_convert_internal
+#define gray_rgb_convert_internal gray_extbgrx_convert_internal
+#define rgb_rgb_convert_internal rgb_extbgrx_convert_internal
#include "jdcolext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef gray_rgb_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_XBGR_RED
-#define RGB_GREEN EXT_XBGR_GREEN
-#define RGB_BLUE EXT_XBGR_BLUE
-#define RGB_ALPHA 0
-#define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
-#define ycc_rgb_convert_internal ycc_extxbgr_convert_internal
-#define gray_rgb_convert_internal gray_extxbgr_convert_internal
-#define rgb_rgb_convert_internal rgb_extxbgr_convert_internal
+#define RGB_RED EXT_XBGR_RED
+#define RGB_GREEN EXT_XBGR_GREEN
+#define RGB_BLUE EXT_XBGR_BLUE
+#define RGB_ALPHA 0
+#define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
+#define ycc_rgb_convert_internal ycc_extxbgr_convert_internal
+#define gray_rgb_convert_internal gray_extxbgr_convert_internal
+#define rgb_rgb_convert_internal rgb_extxbgr_convert_internal
#include "jdcolext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef gray_rgb_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_XRGB_RED
-#define RGB_GREEN EXT_XRGB_GREEN
-#define RGB_BLUE EXT_XRGB_BLUE
-#define RGB_ALPHA 0
-#define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
-#define ycc_rgb_convert_internal ycc_extxrgb_convert_internal
-#define gray_rgb_convert_internal gray_extxrgb_convert_internal
-#define rgb_rgb_convert_internal rgb_extxrgb_convert_internal
+#define RGB_RED EXT_XRGB_RED
+#define RGB_GREEN EXT_XRGB_GREEN
+#define RGB_BLUE EXT_XRGB_BLUE
+#define RGB_ALPHA 0
+#define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
+#define ycc_rgb_convert_internal ycc_extxrgb_convert_internal
+#define gray_rgb_convert_internal gray_extxrgb_convert_internal
+#define rgb_rgb_convert_internal rgb_extxrgb_convert_internal
#include "jdcolext.c"
#undef RGB_RED
#undef RGB_GREEN
*/
LOCAL(void)
-build_ycc_rgb_table (j_decompress_ptr cinfo)
+build_ycc_rgb_table(j_decompress_ptr cinfo)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
int i;
JLONG x;
SHIFT_TEMPS
cconvert->Cr_r_tab = (int *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(int));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(int));
cconvert->Cb_b_tab = (int *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(int));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(int));
cconvert->Cr_g_tab = (JLONG *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(JLONG));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(JLONG));
cconvert->Cb_g_tab = (JLONG *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(JLONG));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(JLONG));
for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
/* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
cconvert->Cb_b_tab[i] = (int)
RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
/* Cr=>G value is scaled-up -0.71414 * x */
- cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
+ cconvert->Cr_g_tab[i] = (-FIX(0.71414)) * x;
/* Cb=>G value is scaled-up -0.34414 * x */
/* We also add in ONE_HALF so that need not do it in inner loop */
- cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
+ cconvert->Cb_g_tab[i] = (-FIX(0.34414)) * x + ONE_HALF;
}
}
*/
METHODDEF(void)
-ycc_rgb_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+ycc_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
switch (cinfo->out_color_space) {
- case JCS_EXT_RGB:
- ycc_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- ycc_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_BGR:
- ycc_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- ycc_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- ycc_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- ycc_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- default:
- ycc_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
+ case JCS_EXT_RGB:
+ ycc_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ ycc_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_BGR:
+ ycc_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ ycc_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ ycc_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ ycc_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ default:
+ ycc_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
}
}
*/
LOCAL(void)
-build_rgb_y_table (j_decompress_ptr cinfo)
+build_rgb_y_table(j_decompress_ptr cinfo)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
JLONG *rgb_y_tab;
JLONG i;
/* Allocate and fill in the conversion tables. */
cconvert->rgb_y_tab = rgb_y_tab = (JLONG *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
(TABLE_SIZE * sizeof(JLONG)));
for (i = 0; i <= MAXJSAMPLE; i++) {
- rgb_y_tab[i+R_Y_OFF] = FIX(0.29900) * i;
- rgb_y_tab[i+G_Y_OFF] = FIX(0.58700) * i;
- rgb_y_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
+ rgb_y_tab[i + R_Y_OFF] = FIX(0.29900) * i;
+ rgb_y_tab[i + G_Y_OFF] = FIX(0.58700) * i;
+ rgb_y_tab[i + B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
}
}
*/
METHODDEF(void)
-rgb_gray_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+rgb_gray_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int r, g, b;
register JLONG *ctab = cconvert->rgb_y_tab;
register JSAMPROW outptr;
g = GETJSAMPLE(inptr1[col]);
b = GETJSAMPLE(inptr2[col]);
/* Y */
- outptr[col] = (JSAMPLE)
- ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
- >> SCALEBITS);
+ outptr[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] +
+ ctab[b + B_Y_OFF]) >> SCALEBITS);
}
}
}
*/
METHODDEF(void)
-null_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+null_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
register JSAMPROW inptr, inptr0, inptr1, inptr2, inptr3, outptr;
register JDIMENSION col;
*/
METHODDEF(void)
-grayscale_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+grayscale_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
- jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
- num_rows, cinfo->output_width);
+ jcopy_sample_rows(input_buf[0], (int)input_row, output_buf, 0, num_rows,
+ cinfo->output_width);
}
*/
METHODDEF(void)
-gray_rgb_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+gray_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
switch (cinfo->out_color_space) {
- case JCS_EXT_RGB:
- gray_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- gray_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_BGR:
- gray_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- gray_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- gray_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- gray_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- default:
- gray_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
+ case JCS_EXT_RGB:
+ gray_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ gray_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_BGR:
+ gray_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ gray_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ gray_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ gray_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ default:
+ gray_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
}
}
*/
METHODDEF(void)
-rgb_rgb_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+rgb_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
switch (cinfo->out_color_space) {
- case JCS_EXT_RGB:
- rgb_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- rgb_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_BGR:
- rgb_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- rgb_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- rgb_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- rgb_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- default:
- rgb_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
+ case JCS_EXT_RGB:
+ rgb_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ rgb_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_BGR:
+ rgb_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ rgb_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ rgb_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ rgb_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ default:
+ rgb_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
}
}
*/
METHODDEF(void)
-ycck_cmyk_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+ycck_cmyk_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int y, cb, cr;
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2, inptr3;
/* 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 */
- ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
+ ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
SCALEBITS)))];
outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */
/* K passes through unchanged */
* RGB565 conversion
*/
-#define PACK_SHORT_565_LE(r, g, b) ((((r) << 8) & 0xF800) | \
- (((g) << 3) & 0x7E0) | ((b) >> 3))
-#define PACK_SHORT_565_BE(r, g, b) (((r) & 0xF8) | ((g) >> 5) | \
- (((g) << 11) & 0xE000) | \
- (((b) << 5) & 0x1F00))
+#define PACK_SHORT_565_LE(r, g, b) ((((r) << 8) & 0xF800) | \
+ (((g) << 3) & 0x7E0) | ((b) >> 3))
+#define PACK_SHORT_565_BE(r, g, b) (((r) & 0xF8) | ((g) >> 5) | \
+ (((g) << 11) & 0xE000) | \
+ (((b) << 5) & 0x1F00))
-#define PACK_TWO_PIXELS_LE(l, r) ((r << 16) | l)
-#define PACK_TWO_PIXELS_BE(l, r) ((l << 16) | r)
+#define PACK_TWO_PIXELS_LE(l, r) ((r << 16) | l)
+#define PACK_TWO_PIXELS_BE(l, r) ((l << 16) | r)
-#define PACK_NEED_ALIGNMENT(ptr) (((size_t)(ptr)) & 3)
+#define PACK_NEED_ALIGNMENT(ptr) (((size_t)(ptr)) & 3)
#define WRITE_TWO_ALIGNED_PIXELS(addr, pixels) ((*(int *)(addr)) = pixels)
/* Declarations for ordered dithering
*
* We use a 4x4 ordered dither array packed into 32 bits. This array is
- * sufficent for dithering RGB888 to RGB565.
+ * sufficient for dithering RGB888 to RGB565.
*/
#define DITHER_MASK 0x3
/* Include inline routines for RGB565 conversion */
-#define PACK_SHORT_565 PACK_SHORT_565_LE
-#define PACK_TWO_PIXELS PACK_TWO_PIXELS_LE
-#define ycc_rgb565_convert_internal ycc_rgb565_convert_le
-#define ycc_rgb565D_convert_internal ycc_rgb565D_convert_le
-#define rgb_rgb565_convert_internal rgb_rgb565_convert_le
-#define rgb_rgb565D_convert_internal rgb_rgb565D_convert_le
-#define gray_rgb565_convert_internal gray_rgb565_convert_le
-#define gray_rgb565D_convert_internal gray_rgb565D_convert_le
+#define PACK_SHORT_565 PACK_SHORT_565_LE
+#define PACK_TWO_PIXELS PACK_TWO_PIXELS_LE
+#define ycc_rgb565_convert_internal ycc_rgb565_convert_le
+#define ycc_rgb565D_convert_internal ycc_rgb565D_convert_le
+#define rgb_rgb565_convert_internal rgb_rgb565_convert_le
+#define rgb_rgb565D_convert_internal rgb_rgb565D_convert_le
+#define gray_rgb565_convert_internal gray_rgb565_convert_le
+#define gray_rgb565D_convert_internal gray_rgb565D_convert_le
#include "jdcol565.c"
#undef PACK_SHORT_565
#undef PACK_TWO_PIXELS
#undef gray_rgb565_convert_internal
#undef gray_rgb565D_convert_internal
-#define PACK_SHORT_565 PACK_SHORT_565_BE
-#define PACK_TWO_PIXELS PACK_TWO_PIXELS_BE
-#define ycc_rgb565_convert_internal ycc_rgb565_convert_be
-#define ycc_rgb565D_convert_internal ycc_rgb565D_convert_be
-#define rgb_rgb565_convert_internal rgb_rgb565_convert_be
-#define rgb_rgb565D_convert_internal rgb_rgb565D_convert_be
-#define gray_rgb565_convert_internal gray_rgb565_convert_be
-#define gray_rgb565D_convert_internal gray_rgb565D_convert_be
+#define PACK_SHORT_565 PACK_SHORT_565_BE
+#define PACK_TWO_PIXELS PACK_TWO_PIXELS_BE
+#define ycc_rgb565_convert_internal ycc_rgb565_convert_be
+#define ycc_rgb565D_convert_internal ycc_rgb565D_convert_be
+#define rgb_rgb565_convert_internal rgb_rgb565_convert_be
+#define rgb_rgb565D_convert_internal rgb_rgb565D_convert_be
+#define gray_rgb565_convert_internal gray_rgb565_convert_be
+#define gray_rgb565D_convert_internal gray_rgb565D_convert_be
#include "jdcol565.c"
#undef PACK_SHORT_565
#undef PACK_TWO_PIXELS
METHODDEF(void)
-ycc_rgb565_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+ycc_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
if (is_big_endian())
ycc_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
METHODDEF(void)
-ycc_rgb565D_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+ycc_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
if (is_big_endian())
ycc_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
METHODDEF(void)
-rgb_rgb565_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+rgb_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
if (is_big_endian())
rgb_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
METHODDEF(void)
-rgb_rgb565D_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+rgb_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
if (is_big_endian())
rgb_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
METHODDEF(void)
-gray_rgb565_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+gray_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
if (is_big_endian())
gray_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
METHODDEF(void)
-gray_rgb565D_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+gray_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
if (is_big_endian())
gray_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
*/
METHODDEF(void)
-start_pass_dcolor (j_decompress_ptr cinfo)
+start_pass_dcolor(j_decompress_ptr cinfo)
{
/* no work needed */
}
*/
GLOBAL(void)
-jinit_color_deconverter (j_decompress_ptr cinfo)
+jinit_color_deconverter(j_decompress_ptr cinfo)
{
my_cconvert_ptr cconvert;
int ci;
cconvert = (my_cconvert_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_color_deconverter));
- cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
+ cinfo->cconvert = (struct jpeg_color_deconverter *)cconvert;
cconvert->pub.start_pass = start_pass_dcolor;
/* Make sure num_components agrees with jpeg_color_space */
cinfo->out_color_components = 3;
if (cinfo->dither_mode == JDITHER_NONE) {
if (cinfo->jpeg_color_space == JCS_YCbCr) {
- if (jsimd_can_ycc_rgb565())
- cconvert->pub.color_convert = jsimd_ycc_rgb565_convert;
- else {
- cconvert->pub.color_convert = ycc_rgb565_convert;
- build_ycc_rgb_table(cinfo);
+ if (jsimd_can_ycc_rgb565())
+ cconvert->pub.color_convert = jsimd_ycc_rgb565_convert;
+ else {
+ cconvert->pub.color_convert = ycc_rgb565_convert;
+ build_ycc_rgb_table(cinfo);
}
} else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
cconvert->pub.color_convert = gray_rgb565_convert;
typedef unsigned int UDCTELEM;
typedef unsigned long long UDCTELEM2;
#else
-typedef short DCTELEM; /* prefer 16 bit with SIMD for parellelism */
+typedef short DCTELEM; /* prefer 16 bit with SIMD for parellelism */
typedef unsigned short UDCTELEM;
typedef unsigned int UDCTELEM2;
#endif
* Each IDCT routine has its own ideas about the best dct_table element type.
*/
-typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */
+typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */
#if BITS_IN_JSAMPLE == 8
-typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */
-#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */
+typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */
+#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */
#else
-typedef JLONG IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */
-#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */
+typedef JLONG IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */
+#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */
#endif
-typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
+typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
/*
/* Extern declarations for the forward and inverse DCT routines. */
-EXTERN(void) jpeg_fdct_islow (DCTELEM *data);
-EXTERN(void) jpeg_fdct_ifast (DCTELEM *data);
-EXTERN(void) jpeg_fdct_float (FAST_FLOAT *data);
-
-EXTERN(void) jpeg_idct_islow
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_ifast
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_float
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_7x7
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_6x6
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_5x5
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_4x4
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_3x3
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_2x2
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_1x1
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_9x9
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_10x10
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_11x11
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_12x12
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_13x13
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_14x14
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_15x15
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_16x16
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_fdct_islow(DCTELEM *data);
+EXTERN(void) jpeg_fdct_ifast(DCTELEM *data);
+EXTERN(void) jpeg_fdct_float(FAST_FLOAT *data);
+
+EXTERN(void) jpeg_idct_islow(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_ifast(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_float(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_7x7(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_6x6(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_5x5(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_4x4(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_3x3(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_2x2(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_1x1(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_9x9(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_10x10(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_11x11(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_12x12(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_13x13(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_14x14(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_15x15(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_16x16(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
/*
* and may differ from one module to the next.
*/
-#define ONE ((JLONG) 1)
-#define CONST_SCALE (ONE << CONST_BITS)
+#define ONE ((JLONG)1)
+#define CONST_SCALE (ONE << CONST_BITS)
/* Convert a positive real constant to an integer scaled by CONST_SCALE.
* Caution: some C compilers fail to reduce "FIX(constant)" at compile time,
* thus causing a lot of useless floating-point operations at run time.
*/
-#define FIX(x) ((JLONG) ((x) * CONST_SCALE + 0.5))
+#define FIX(x) ((JLONG)((x) * CONST_SCALE + 0.5))
/* Descale and correctly round a JLONG value that's scaled by N bits.
* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
* the fudge factor is correct for either sign of X.
*/
-#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
+#define DESCALE(x, n) RIGHT_SHIFT((x) + (ONE << ((n) - 1)), n)
/* Multiply a JLONG variable by a JLONG constant to yield a JLONG result.
* This macro is used only when the two inputs will actually be no more than
*/
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
-#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const)))
+#define MULTIPLY16C16(var, const) (((INT16)(var)) * ((INT16)(const)))
#endif
#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
-#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((JLONG) (const)))
+#define MULTIPLY16C16(var, const) (((INT16)(var)) * ((JLONG)(const)))
#endif
#ifndef MULTIPLY16C16 /* default definition */
-#define MULTIPLY16C16(var,const) ((var) * (const))
+#define MULTIPLY16C16(var, const) ((var) * (const))
#endif
/* Same except both inputs are variables. */
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
-#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2)))
+#define MULTIPLY16V16(var1, var2) (((INT16)(var1)) * ((INT16)(var2)))
#endif
#ifndef MULTIPLY16V16 /* default definition */
-#define MULTIPLY16V16(var1,var2) ((var1) * (var2))
+#define MULTIPLY16V16(var1, var2) ((var1) * (var2))
#endif
*/
METHODDEF(void)
-start_pass (j_decompress_ptr cinfo)
+start_pass(j_decompress_ptr cinfo)
{
- my_idct_ptr idct = (my_idct_ptr) cinfo->idct;
+ my_idct_ptr idct = (my_idct_ptr)cinfo->idct;
int ci, i;
jpeg_component_info *compptr;
int method = 0;
* multiplier table all-zero; we'll be reading zeroes from the
* coefficient controller's buffer anyway.
*/
- if (! compptr->component_needed || idct->cur_method[ci] == method)
+ if (!compptr->component_needed || idct->cur_method[ci] == method)
continue;
qtbl = compptr->quant_table;
if (qtbl == NULL) /* happens if no data yet for component */
/* For LL&M IDCT method, multipliers are equal to raw quantization
* coefficients, but are stored as ints to ensure access efficiency.
*/
- ISLOW_MULT_TYPE *ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ ISLOW_MULT_TYPE *ismtbl = (ISLOW_MULT_TYPE *)compptr->dct_table;
for (i = 0; i < DCTSIZE2; i++) {
- ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i];
+ ismtbl[i] = (ISLOW_MULT_TYPE)qtbl->quantval[i];
}
}
break;
* For integer operation, the multiplier table is to be scaled by
* IFAST_SCALE_BITS.
*/
- IFAST_MULT_TYPE *ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table;
-#define CONST_BITS 14
+ IFAST_MULT_TYPE *ifmtbl = (IFAST_MULT_TYPE *)compptr->dct_table;
+#define CONST_BITS 14
static const INT16 aanscales[DCTSIZE2] = {
/* precomputed values scaled up by 14 bits */
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
for (i = 0; i < DCTSIZE2; i++) {
ifmtbl[i] = (IFAST_MULT_TYPE)
- DESCALE(MULTIPLY16V16((JLONG) qtbl->quantval[i],
- (JLONG) aanscales[i]),
- CONST_BITS-IFAST_SCALE_BITS);
+ DESCALE(MULTIPLY16V16((JLONG)qtbl->quantval[i],
+ (JLONG)aanscales[i]),
+ CONST_BITS - IFAST_SCALE_BITS);
}
}
break;
* scalefactor[0] = 1
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
*/
- FLOAT_MULT_TYPE *fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table;
+ FLOAT_MULT_TYPE *fmtbl = (FLOAT_MULT_TYPE *)compptr->dct_table;
int row, col;
static const double aanscalefactor[DCTSIZE] = {
1.0, 1.387039845, 1.306562965, 1.175875602,
for (row = 0; row < DCTSIZE; row++) {
for (col = 0; col < DCTSIZE; col++) {
fmtbl[i] = (FLOAT_MULT_TYPE)
- ((double) qtbl->quantval[i] *
+ ((double)qtbl->quantval[i] *
aanscalefactor[row] * aanscalefactor[col]);
i++;
}
*/
GLOBAL(void)
-jinit_inverse_dct (j_decompress_ptr cinfo)
+jinit_inverse_dct(j_decompress_ptr cinfo)
{
my_idct_ptr idct;
int ci;
jpeg_component_info *compptr;
idct = (my_idct_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_idct_controller));
- cinfo->idct = (struct jpeg_inverse_dct *) idct;
+ cinfo->idct = (struct jpeg_inverse_dct *)idct;
idct->pub.start_pass = start_pass;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Allocate and pre-zero a multiplier table for each component */
compptr->dct_table =
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(multiplier_table));
MEMZERO(compptr->dct_table, sizeof(multiplier_table));
/* Mark multiplier table not yet set up for any method */
* 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, 2016, D. R. Commander.
+ * Copyright (C) 2009-2011, 2016, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
* up to the start of the current MCU. To do this, we copy state variables
* into local working storage, and update them back to the permanent
* storage only upon successful completion of an MCU.
+ *
+ * NOTE: All referenced figures are from
+ * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994.
*/
#define JPEG_INTERNALS
*/
#ifndef NO_STRUCT_ASSIGN
-#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#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])
+#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
*/
METHODDEF(void)
-start_pass_huff_decoder (j_decompress_ptr cinfo)
+start_pass_huff_decoder(j_decompress_ptr cinfo)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int ci, blkn, dctbl, actbl;
d_derived_tbl **pdtbl;
jpeg_component_info *compptr;
* This ought to be an error condition, but we make it a warning because
* there are some baseline files out there with all zeroes in these bytes.
*/
- if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 ||
+ if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2 - 1 ||
cinfo->Ah != 0 || cinfo->Al != 0)
WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
*/
GLOBAL(void)
-jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
- d_derived_tbl **pdtbl)
+jpeg_make_d_derived_tbl(j_decompress_ptr cinfo, boolean isDC, int tblno,
+ d_derived_tbl **pdtbl)
{
JHUFF_TBL *htbl;
d_derived_tbl *dtbl;
/* Allocate a workspace if we haven't already done so. */
if (*pdtbl == NULL)
*pdtbl = (d_derived_tbl *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(d_derived_tbl));
dtbl = *pdtbl;
dtbl->pub = htbl; /* fill in back link */
p = 0;
for (l = 1; l <= 16; l++) {
- i = (int) htbl->bits[l];
+ i = (int)htbl->bits[l];
if (i < 0 || p + i > 256) /* protect against table overrun */
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
while (i--)
- huffsize[p++] = (char) l;
+ huffsize[p++] = (char)l;
}
huffsize[p] = 0;
numsymbols = p;
si = huffsize[0];
p = 0;
while (huffsize[p]) {
- while (((int) huffsize[p]) == si) {
+ while (((int)huffsize[p]) == si) {
huffcode[p++] = code;
code++;
}
/* code is now 1 more than the last code used for codelength si; but
* it must still fit in si bits, since no code is allowed to be all ones.
*/
- if (((JLONG) code) >= (((JLONG) 1) << si))
+ if (((JLONG)code) >= (((JLONG)1) << si))
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
code <<= 1;
si++;
/* valoffset[l] = huffval[] index of 1st symbol of code length l,
* minus the minimum code of length l
*/
- dtbl->valoffset[l] = (JLONG) p - (JLONG) huffcode[p];
+ dtbl->valoffset[l] = (JLONG)p - (JLONG)huffcode[p];
p += htbl->bits[l];
- dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
+ dtbl->maxcode[l] = huffcode[p - 1]; /* maximum code of length l */
} else {
dtbl->maxcode[l] = -1; /* -1 if no codes of this length */
}
* with that code.
*/
- for (i = 0; i < (1 << HUFF_LOOKAHEAD); i++)
- dtbl->lookup[i] = (HUFF_LOOKAHEAD + 1) << HUFF_LOOKAHEAD;
+ for (i = 0; i < (1 << HUFF_LOOKAHEAD); i++)
+ dtbl->lookup[i] = (HUFF_LOOKAHEAD + 1) << HUFF_LOOKAHEAD;
p = 0;
for (l = 1; l <= HUFF_LOOKAHEAD; l++) {
- for (i = 1; i <= (int) htbl->bits[l]; i++, p++) {
+ for (i = 1; i <= (int)htbl->bits[l]; i++, p++) {
/* l = current code's length, p = its index in huffcode[] & huffval[]. */
/* Generate left-justified code followed by all possible bit sequences */
- lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
- for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) {
+ lookbits = huffcode[p] << (HUFF_LOOKAHEAD - l);
+ for (ctr = 1 << (HUFF_LOOKAHEAD - l); ctr > 0; ctr--) {
dtbl->lookup[lookbits] = (l << HUFF_LOOKAHEAD) | htbl->huffval[p];
lookbits++;
}
#ifdef SLOW_SHIFT_32
#define MIN_GET_BITS 15 /* minimum allowable value */
#else
-#define MIN_GET_BITS (BIT_BUF_SIZE-7)
+#define MIN_GET_BITS (BIT_BUF_SIZE - 7)
#endif
GLOBAL(boolean)
-jpeg_fill_bit_buffer (bitread_working_state *state,
- register bit_buf_type get_buffer, register int bits_left,
- int nbits)
+jpeg_fill_bit_buffer(bitread_working_state *state,
+ register bit_buf_type get_buffer, register int bits_left,
+ int nbits)
/* Load up the bit buffer to a depth of at least nbits */
{
/* Copy heavily used state fields into locals (hopefully registers) */
/* Attempt to read a byte */
if (bytes_in_buffer == 0) {
- if (! (*cinfo->src->fill_input_buffer) (cinfo))
+ if (!(*cinfo->src->fill_input_buffer) (cinfo))
return FALSE;
next_input_byte = cinfo->src->next_input_byte;
bytes_in_buffer = cinfo->src->bytes_in_buffer;
*/
do {
if (bytes_in_buffer == 0) {
- if (! (*cinfo->src->fill_input_buffer) (cinfo))
+ if (!(*cinfo->src->fill_input_buffer) (cinfo))
return FALSE;
next_input_byte = cinfo->src->next_input_byte;
bytes_in_buffer = cinfo->src->bytes_in_buffer;
bits_left += 8;
} /* end while */
} else {
- no_more_bytes:
+no_more_bytes:
/* We get here if we've read the marker that terminates the compressed
* data segment. There should be enough bits in the buffer register
* to satisfy the request; if so, no problem.
* We use a nonvolatile flag to ensure that only one warning message
* appears per data segment.
*/
- if (! cinfo->entropy->insufficient_data) {
+ if (!cinfo->entropy->insufficient_data) {
WARNMS(cinfo, JWRN_HIT_MARKER);
cinfo->entropy->insufficient_data = TRUE;
}
handle markers. We have to hand off any blocks with markers to the
slower routines. */
-#define GET_BYTE \
-{ \
+#define GET_BYTE { \
register int c0, c1; \
c0 = GETJOCTET(*buffer++); \
c1 = GETJOCTET(*buffer); \
} \
}
-#if SIZEOF_SIZE_T==8 || defined(_WIN64)
+#if SIZEOF_SIZE_T == 8 || defined(_WIN64)
/* Pre-fetch 48 bytes, because the holding register is 64-bit */
#define FILL_BIT_BUFFER_FAST \
*/
GLOBAL(int)
-jpeg_huff_decode (bitread_working_state *state,
- register bit_buf_type get_buffer, register int bits_left,
- d_derived_tbl *htbl, int min_bits)
+jpeg_huff_decode(bitread_working_state *state,
+ register bit_buf_type get_buffer, register int bits_left,
+ d_derived_tbl *htbl, int min_bits)
{
register int l = min_bits;
register JLONG code;
code = GET_BITS(l);
/* Collect the rest of the Huffman code one bit at a time. */
- /* This is per Figure F.16 in the JPEG spec. */
+ /* This is per Figure F.16. */
while (code > htbl->maxcode[l]) {
code <<= 1;
return 0; /* fake a zero as the safest result */
}
- return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ];
+ return htbl->pub->huffval[(int)(code + htbl->valoffset[l])];
}
#define AVOID_TABLES
#ifdef AVOID_TABLES
-#define NEG_1 ((unsigned int)-1)
-#define HUFF_EXTEND(x,s) ((x) + ((((x) - (1<<((s)-1))) >> 31) & (((NEG_1)<<(s)) + 1)))
+#define NEG_1 ((unsigned int)-1)
+#define HUFF_EXTEND(x, s) \
+ ((x) + ((((x) - (1 << ((s) - 1))) >> 31) & (((NEG_1) << (s)) + 1)))
#else
-#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
+#define HUFF_EXTEND(x, s) \
+ ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
-static const int extend_test[16] = /* entry n is 2**(n-1) */
- { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
- 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
+static const int extend_test[16] = { /* entry n is 2**(n-1) */
+ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+ 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000
+};
-static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
- { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
- ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
- ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
- ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+static const int extend_offset[16] = { /* entry n is (-1 << n) + 1 */
+ 0, ((-1) << 1) + 1, ((-1) << 2) + 1, ((-1) << 3) + 1, ((-1) << 4) + 1,
+ ((-1) << 5) + 1, ((-1) << 6) + 1, ((-1) << 7) + 1, ((-1) << 8) + 1,
+ ((-1) << 9) + 1, ((-1) << 10) + 1, ((-1) << 11) + 1, ((-1) << 12) + 1,
+ ((-1) << 13) + 1, ((-1) << 14) + 1, ((-1) << 15) + 1
+};
#endif /* AVOID_TABLES */
*/
LOCAL(boolean)
-process_restart (j_decompress_ptr cinfo)
+process_restart(j_decompress_ptr cinfo)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int ci;
/* Throw away any unused bits remaining in bit buffer; */
entropy->bitstate.bits_left = 0;
/* Advance past the RSTn marker */
- if (! (*cinfo->marker->read_restart_marker) (cinfo))
+ if (!(*cinfo->marker->read_restart_marker) (cinfo))
return FALSE;
/* Re-initialize DC predictions to 0 */
LOCAL(boolean)
-decode_mcu_slow (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
BITREAD_STATE_VARS;
int blkn;
savable_state state;
/* Outer loop handles each block in the MCU */
/* Load up working state */
- BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(state, entropy->saved);
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
state.last_dc_val[ci] = s;
if (block) {
/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
- (*block)[0] = (JCOEF) s;
+ (*block)[0] = (JCOEF)s;
}
}
* Note: the extra entries in jpeg_natural_order[] will save us
* if k >= DCTSIZE2, which could happen if the data is corrupted.
*/
- (*block)[jpeg_natural_order[k]] = (JCOEF) s;
+ (*block)[jpeg_natural_order[k]] = (JCOEF)s;
} else {
if (r != 15)
break;
}
/* Completed MCU, so update state */
- BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(entropy->saved, state);
return TRUE;
}
LOCAL(boolean)
-decode_mcu_fast (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
BITREAD_STATE_VARS;
JOCTET *buffer;
int blkn;
/* Outer loop handles each block in the MCU */
/* Load up working state */
- BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
- buffer = (JOCTET *) br_state.next_input_byte;
+ BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
+ buffer = (JOCTET *)br_state.next_input_byte;
ASSIGN_STATE(state, entropy->saved);
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
s += state.last_dc_val[ci];
state.last_dc_val[ci] = s;
if (block)
- (*block)[0] = (JCOEF) s;
+ (*block)[0] = (JCOEF)s;
}
if (entropy->ac_needed[blkn] && block) {
FILL_BIT_BUFFER_FAST
r = GET_BITS(s);
s = HUFF_EXTEND(r, s);
- (*block)[jpeg_natural_order[k]] = (JCOEF) s;
+ (*block)[jpeg_natural_order[k]] = (JCOEF)s;
} else {
if (r != 15) break;
k += 15;
br_state.bytes_in_buffer -= (buffer - br_state.next_input_byte);
br_state.next_input_byte = buffer;
- BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(entropy->saved, state);
return TRUE;
}
* this module, since we'll just re-assign them on the next call.)
*/
-#define BUFSIZE (DCTSIZE2 * 8)
+#define BUFSIZE (DCTSIZE2 * 8)
METHODDEF(boolean)
-decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int usefast = 1;
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
- if (! process_restart(cinfo))
+ if (!process_restart(cinfo))
return FALSE;
usefast = 0;
}
- if (cinfo->src->bytes_in_buffer < BUFSIZE * (size_t)cinfo->blocks_in_MCU
- || cinfo->unread_marker != 0)
+ if (cinfo->src->bytes_in_buffer < BUFSIZE * (size_t)cinfo->blocks_in_MCU ||
+ cinfo->unread_marker != 0)
usefast = 0;
/* If we've run out of data, just leave the MCU set to zeroes.
* This way, we return uniform gray for the remainder of the segment.
*/
- if (! entropy->pub.insufficient_data) {
+ if (!entropy->pub.insufficient_data) {
if (usefast) {
if (!decode_mcu_fast(cinfo, MCU_data)) goto use_slow;
- }
- else {
- use_slow:
+ } else {
+use_slow:
if (!decode_mcu_slow(cinfo, MCU_data)) return FALSE;
}
*/
GLOBAL(void)
-jinit_huff_decoder (j_decompress_ptr cinfo)
+jinit_huff_decoder(j_decompress_ptr cinfo)
{
huff_entropy_ptr entropy;
int i;
are the default tables. Thus, if the tables are not set by the time
the Huffman decoder is initialized (usually within the body of
jpeg_start_decompress()), we set them to default values. */
- std_huff_tables((j_common_ptr) cinfo);
+ std_huff_tables((j_common_ptr)cinfo);
entropy = (huff_entropy_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(huff_entropy_decoder));
- cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
+ cinfo->entropy = (struct jpeg_entropy_decoder *)entropy;
entropy->pub.start_pass = start_pass_huff_decoder;
entropy->pub.decode_mcu = decode_mcu;
* if too long. The next 8 bits of each entry contain the
* symbol.
*/
- int lookup[1<<HUFF_LOOKAHEAD];
+ int lookup[1 << HUFF_LOOKAHEAD];
} d_derived_tbl;
/* Expand a Huffman table definition into the derived format */
-EXTERN(void) jpeg_make_d_derived_tbl
- (j_decompress_ptr cinfo, boolean isDC, int tblno,
- d_derived_tbl ** pdtbl);
+EXTERN(void) jpeg_make_d_derived_tbl(j_decompress_ptr cinfo, boolean isDC,
+ int tblno, d_derived_tbl **pdtbl);
/*
#error Cannot determine word size
#endif
-#if SIZEOF_SIZE_T==8 || defined(_WIN64)
+#if SIZEOF_SIZE_T == 8 || defined(_WIN64)
typedef size_t bit_buf_type; /* type of bit-extraction buffer */
#define BIT_BUF_SIZE 64 /* size of buffer in bits */
} bitread_working_state;
/* Macros to declare and load/save bitread local variables. */
-#define BITREAD_STATE_VARS \
- register bit_buf_type get_buffer; \
- register int bits_left; \
- bitread_working_state br_state
-
-#define BITREAD_LOAD_STATE(cinfop,permstate) \
- br_state.cinfo = cinfop; \
- br_state.next_input_byte = cinfop->src->next_input_byte; \
- br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \
- get_buffer = permstate.get_buffer; \
- bits_left = permstate.bits_left;
-
-#define BITREAD_SAVE_STATE(cinfop,permstate) \
- cinfop->src->next_input_byte = br_state.next_input_byte; \
- cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \
- permstate.get_buffer = get_buffer; \
- permstate.bits_left = bits_left
+#define BITREAD_STATE_VARS \
+ register bit_buf_type get_buffer; \
+ register int bits_left; \
+ bitread_working_state br_state
+
+#define BITREAD_LOAD_STATE(cinfop, permstate) \
+ br_state.cinfo = cinfop; \
+ br_state.next_input_byte = cinfop->src->next_input_byte; \
+ br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \
+ get_buffer = permstate.get_buffer; \
+ bits_left = permstate.bits_left;
+
+#define BITREAD_SAVE_STATE(cinfop, permstate) \
+ cinfop->src->next_input_byte = br_state.next_input_byte; \
+ cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \
+ permstate.get_buffer = get_buffer; \
+ permstate.bits_left = bits_left
/*
* These macros provide the in-line portion of bit fetching.
* before using GET_BITS, PEEK_BITS, or DROP_BITS.
* The variables get_buffer and bits_left are assumed to be locals,
* but the state struct might not be (jpeg_huff_decode needs this).
- * CHECK_BIT_BUFFER(state,n,action);
+ * CHECK_BIT_BUFFER(state, n, action);
* Ensure there are N bits in get_buffer; if suspend, take action.
* val = GET_BITS(n);
* Fetch next N bits.
* is evaluated multiple times.
*/
-#define CHECK_BIT_BUFFER(state,nbits,action) \
- { if (bits_left < (nbits)) { \
- if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \
- { action; } \
- get_buffer = (state).get_buffer; bits_left = (state).bits_left; } }
+#define CHECK_BIT_BUFFER(state, nbits, action) { \
+ if (bits_left < (nbits)) { \
+ if (!jpeg_fill_bit_buffer(&(state), get_buffer, bits_left, nbits)) \
+ { action; } \
+ get_buffer = (state).get_buffer; bits_left = (state).bits_left; \
+ } \
+}
#define GET_BITS(nbits) \
- (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1))
+ (((int)(get_buffer >> (bits_left -= (nbits)))) & ((1 << (nbits)) - 1))
#define PEEK_BITS(nbits) \
- (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1))
+ (((int)(get_buffer >> (bits_left - (nbits)))) & ((1 << (nbits)) - 1))
#define DROP_BITS(nbits) \
- (bits_left -= (nbits))
+ (bits_left -= (nbits))
/* Load up the bit buffer to a depth of at least nbits */
-EXTERN(boolean) jpeg_fill_bit_buffer
- (bitread_working_state *state, register bit_buf_type get_buffer,
- register int bits_left, int nbits);
+EXTERN(boolean) jpeg_fill_bit_buffer(bitread_working_state *state,
+ register bit_buf_type get_buffer,
+ register int bits_left, int nbits);
/*
* 3. jpeg_huff_decode returns -1 if forced to suspend.
*/
-#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \
-{ register int nb, look; \
+#define HUFF_DECODE(result, state, htbl, failaction, slowlabel) { \
+ register int nb, look; \
if (bits_left < HUFF_LOOKAHEAD) { \
- if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \
- get_buffer = state.get_buffer; bits_left = state.bits_left; \
+ if (!jpeg_fill_bit_buffer(&state, get_buffer, bits_left, 0)) \
+ { failaction; } \
+ get_buffer = state.get_buffer; bits_left = state.bits_left; \
if (bits_left < HUFF_LOOKAHEAD) { \
- nb = 1; goto slowlabel; \
+ nb = 1; goto slowlabel; \
} \
} \
look = PEEK_BITS(HUFF_LOOKAHEAD); \
result = htbl->lookup[look] & ((1 << HUFF_LOOKAHEAD) - 1); \
} else { \
slowlabel: \
- if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \
- { failaction; } \
- get_buffer = state.get_buffer; bits_left = state.bits_left; \
+ if ((result = \
+ jpeg_huff_decode(&state, get_buffer, bits_left, htbl, nb)) < 0) \
+ { failaction; } \
+ get_buffer = state.get_buffer; bits_left = state.bits_left; \
} \
}
-#define HUFF_DECODE_FAST(s,nb,htbl) \
+#define HUFF_DECODE_FAST(s, nb, htbl) \
FILL_BIT_BUFFER_FAST; \
s = PEEK_BITS(HUFF_LOOKAHEAD); \
s = htbl->lookup[s]; \
s |= GET_BITS(1); \
nb++; \
} \
- s = htbl->pub->huffval[ (int) (s + htbl->valoffset[nb]) & 0xFF ]; \
+ s = htbl->pub->huffval[(int)(s + htbl->valoffset[nb]) & 0xFF]; \
}
/* Out-of-line case for Huffman code fetching */
-EXTERN(int) jpeg_huff_decode
- (bitread_working_state *state, register bit_buf_type get_buffer,
- register int bits_left, d_derived_tbl *htbl, int min_bits);
+EXTERN(int) jpeg_huff_decode(bitread_working_state *state,
+ register bit_buf_type get_buffer,
+ register int bits_left, d_derived_tbl *htbl,
+ int min_bits);
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
- * Copyright (C) 2010, 2016, D. R. Commander.
+ * Copyright (C) 2010, 2016, 2018, D. R. Commander.
* Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
/* Forward declarations */
-METHODDEF(int) consume_markers (j_decompress_ptr cinfo);
+METHODDEF(int) consume_markers(j_decompress_ptr cinfo);
/*
*/
LOCAL(void)
-initial_setup (j_decompress_ptr cinfo)
+initial_setup(j_decompress_ptr cinfo)
/* Called once, when first SOS marker is reached */
{
int ci;
jpeg_component_info *compptr;
/* Make sure image isn't bigger than I can handle */
- if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
- (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
- ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
+ if ((long)cinfo->image_height > (long)JPEG_MAX_DIMENSION ||
+ (long)cinfo->image_width > (long)JPEG_MAX_DIMENSION)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int)JPEG_MAX_DIMENSION);
/* For now, precision must match compiled-in value... */
if (cinfo->data_precision != BITS_IN_JSAMPLE)
cinfo->max_v_samp_factor = 1;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
- if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
- compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
+ if (compptr->h_samp_factor <= 0 ||
+ compptr->h_samp_factor > MAX_SAMP_FACTOR ||
+ compptr->v_samp_factor <= 0 ||
+ compptr->v_samp_factor > MAX_SAMP_FACTOR)
ERREXIT(cinfo, JERR_BAD_SAMPLING);
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
compptr->h_samp_factor);
compptr->v_samp_factor);
}
-#if JPEG_LIB_VERSION >=80
- cinfo->block_size = DCTSIZE;
- cinfo->natural_order = jpeg_natural_order;
- cinfo->lim_Se = DCTSIZE2-1;
+#if JPEG_LIB_VERSION >= 80
+ cinfo->block_size = DCTSIZE;
+ cinfo->natural_order = jpeg_natural_order;
+ cinfo->lim_Se = DCTSIZE2 - 1;
#endif
/* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE.
#endif
/* Size in DCT blocks */
compptr->width_in_blocks = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
- (long) (cinfo->max_h_samp_factor * DCTSIZE));
+ jdiv_round_up((long)cinfo->image_width * (long)compptr->h_samp_factor,
+ (long)(cinfo->max_h_samp_factor * DCTSIZE));
compptr->height_in_blocks = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
- (long) (cinfo->max_v_samp_factor * DCTSIZE));
+ jdiv_round_up((long)cinfo->image_height * (long)compptr->v_samp_factor,
+ (long)(cinfo->max_v_samp_factor * DCTSIZE));
/* Set the first and last MCU columns to decompress from multi-scan images.
* By default, decompress all of the MCU columns.
*/
*/
/* Size in samples */
compptr->downsampled_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
- (long) cinfo->max_h_samp_factor);
+ jdiv_round_up((long)cinfo->image_width * (long)compptr->h_samp_factor,
+ (long)cinfo->max_h_samp_factor);
compptr->downsampled_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
- (long) cinfo->max_v_samp_factor);
+ jdiv_round_up((long)cinfo->image_height * (long)compptr->v_samp_factor,
+ (long)cinfo->max_v_samp_factor);
/* Mark component needed, until color conversion says otherwise */
compptr->component_needed = TRUE;
/* Mark no quantization table yet saved for component */
/* Compute number of fully interleaved MCU rows. */
cinfo->total_iMCU_rows = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height,
- (long) (cinfo->max_v_samp_factor*DCTSIZE));
+ jdiv_round_up((long)cinfo->image_height,
+ (long)(cinfo->max_v_samp_factor * DCTSIZE));
/* Decide whether file contains multiple scans */
if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode)
LOCAL(void)
-per_scan_setup (j_decompress_ptr cinfo)
+per_scan_setup(j_decompress_ptr cinfo)
/* Do computations that are needed before processing a JPEG scan */
/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */
{
/* For noninterleaved scans, it is convenient to define last_row_height
* as the number of block rows present in the last iMCU row.
*/
- tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ tmp = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
if (tmp == 0) tmp = compptr->v_samp_factor;
compptr->last_row_height = tmp;
/* Overall image size in MCUs */
cinfo->MCUs_per_row = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width,
- (long) (cinfo->max_h_samp_factor*DCTSIZE));
+ jdiv_round_up((long)cinfo->image_width,
+ (long)(cinfo->max_h_samp_factor * DCTSIZE));
cinfo->MCU_rows_in_scan = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height,
- (long) (cinfo->max_v_samp_factor*DCTSIZE));
+ jdiv_round_up((long)cinfo->image_height,
+ (long)(cinfo->max_v_samp_factor * DCTSIZE));
cinfo->blocks_in_MCU = 0;
compptr->MCU_width = compptr->h_samp_factor;
compptr->MCU_height = compptr->v_samp_factor;
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
- compptr->MCU_sample_width = compptr->MCU_width * compptr->_DCT_scaled_size;
+ compptr->MCU_sample_width = compptr->MCU_width *
+ compptr->_DCT_scaled_size;
/* Figure number of non-dummy blocks in last MCU column & row */
- tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
+ tmp = (int)(compptr->width_in_blocks % compptr->MCU_width);
if (tmp == 0) tmp = compptr->MCU_width;
compptr->last_col_width = tmp;
- tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
+ tmp = (int)(compptr->height_in_blocks % compptr->MCU_height);
if (tmp == 0) tmp = compptr->MCU_height;
compptr->last_row_height = tmp;
/* Prepare array describing MCU composition */
* means that we have to save away the table actually used for each component.
* We do this by copying the table at the start of the first scan containing
* the component.
- * The JPEG spec prohibits the encoder from changing the contents of a Q-table
- * slot between scans of a component using that slot. If the encoder does so
- * anyway, this decoder will simply use the Q-table values that were current
- * at the start of the first scan for the component.
+ * Rec. ITU-T T.81 | ISO/IEC 10918-1 prohibits the encoder from changing the
+ * contents of a Q-table slot between scans of a component using that slot. If
+ * the encoder does so anyway, this decoder will simply use the Q-table values
+ * that were current at the start of the first scan for the component.
*
* The decompressor output side looks only at the saved quant tables,
* not at the current Q-table slots.
*/
LOCAL(void)
-latch_quant_tables (j_decompress_ptr cinfo)
+latch_quant_tables(j_decompress_ptr cinfo)
{
int ci, qtblno;
jpeg_component_info *compptr;
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
/* OK, save away the quantization table */
qtbl = (JQUANT_TBL *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(JQUANT_TBL));
MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], sizeof(JQUANT_TBL));
compptr->quant_table = qtbl;
*/
METHODDEF(void)
-start_input_pass (j_decompress_ptr cinfo)
+start_input_pass(j_decompress_ptr cinfo)
{
per_scan_setup(cinfo);
latch_quant_tables(cinfo);
*/
METHODDEF(void)
-finish_input_pass (j_decompress_ptr cinfo)
+finish_input_pass(j_decompress_ptr cinfo)
{
cinfo->inputctl->consume_input = consume_markers;
}
*/
METHODDEF(int)
-consume_markers (j_decompress_ptr cinfo)
+consume_markers(j_decompress_ptr cinfo)
{
- my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
+ my_inputctl_ptr inputctl = (my_inputctl_ptr)cinfo->inputctl;
int val;
if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */
* responsible for enforcing this sequencing.
*/
} else { /* 2nd or later SOS marker */
- if (! inputctl->pub.has_multiple_scans)
+ if (!inputctl->pub.has_multiple_scans)
ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */
start_input_pass(cinfo);
}
*/
METHODDEF(void)
-reset_input_controller (j_decompress_ptr cinfo)
+reset_input_controller(j_decompress_ptr cinfo)
{
- my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
+ my_inputctl_ptr inputctl = (my_inputctl_ptr)cinfo->inputctl;
inputctl->pub.consume_input = consume_markers;
inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
inputctl->pub.eoi_reached = FALSE;
inputctl->inheaders = TRUE;
/* Reset other modules */
- (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr)cinfo);
(*cinfo->marker->reset_marker_reader) (cinfo);
/* Reset progression state -- would be cleaner if entropy decoder did this */
cinfo->coef_bits = NULL;
*/
GLOBAL(void)
-jinit_input_controller (j_decompress_ptr cinfo)
+jinit_input_controller(j_decompress_ptr cinfo)
{
my_inputctl_ptr inputctl;
/* Create subobject in permanent pool */
inputctl = (my_inputctl_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(my_input_controller));
- cinfo->inputctl = (struct jpeg_input_controller *) inputctl;
+ cinfo->inputctl = (struct jpeg_input_controller *)inputctl;
/* Initialize method pointers */
inputctl->pub.consume_input = consume_markers;
inputctl->pub.reset_input_controller = reset_input_controller;
/* Forward declarations */
-METHODDEF(void) process_data_simple_main
- (j_decompress_ptr cinfo, JSAMPARRAY output_buf,
- JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
-METHODDEF(void) process_data_context_main
- (j_decompress_ptr cinfo, JSAMPARRAY output_buf,
- JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
+METHODDEF(void) process_data_simple_main(j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail);
+METHODDEF(void) process_data_context_main(j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail);
#ifdef QUANT_2PASS_SUPPORTED
-METHODDEF(void) process_data_crank_post
- (j_decompress_ptr cinfo, JSAMPARRAY output_buf,
- JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
+METHODDEF(void) process_data_crank_post(j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail);
#endif
LOCAL(void)
-alloc_funny_pointers (j_decompress_ptr cinfo)
+alloc_funny_pointers(j_decompress_ptr cinfo)
/* Allocate space for the funny pointer lists.
* This is done only once, not once per pass.
*/
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
int ci, rgroup;
int M = cinfo->_min_DCT_scaled_size;
jpeg_component_info *compptr;
* We alloc both arrays with one call to save a few cycles.
*/
main_ptr->xbuffer[0] = (JSAMPIMAGE)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
cinfo->num_components * 2 * sizeof(JSAMPARRAY));
main_ptr->xbuffer[1] = main_ptr->xbuffer[0] + cinfo->num_components;
* We alloc both pointer lists with one call to save a few cycles.
*/
xbuf = (JSAMPARRAY)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
2 * (rgroup * (M + 4)) * sizeof(JSAMPROW));
xbuf += rgroup; /* want one row group at negative offsets */
main_ptr->xbuffer[0][ci] = xbuf;
LOCAL(void)
-make_funny_pointers (j_decompress_ptr cinfo)
+make_funny_pointers(j_decompress_ptr cinfo)
/* Create the funny pointer lists discussed in the comments above.
* The actual workspace is already allocated (in main_ptr->buffer),
* and the space for the pointer lists is allocated too.
* This will be repeated at the beginning of each pass.
*/
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
int ci, i, rgroup;
int M = cinfo->_min_DCT_scaled_size;
jpeg_component_info *compptr;
}
/* In the second list, put the last four row groups in swapped order */
for (i = 0; i < rgroup * 2; i++) {
- xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i];
- xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i];
+ xbuf1[rgroup * (M - 2) + i] = buf[rgroup * M + i];
+ xbuf1[rgroup * M + i] = buf[rgroup * (M - 2) + i];
}
/* The wraparound pointers at top and bottom will be filled later
* (see set_wraparound_pointers, below). Initially we want the "above"
LOCAL(void)
-set_bottom_pointers (j_decompress_ptr cinfo)
+set_bottom_pointers(j_decompress_ptr cinfo)
/* Change the pointer lists to duplicate the last sample row at the bottom
* of the image. whichptr indicates which xbuffer holds the final iMCU row.
* Also sets rowgroups_avail to indicate number of nondummy row groups in row.
*/
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
int ci, i, rgroup, iMCUheight, rows_left;
jpeg_component_info *compptr;
JSAMPARRAY xbuf;
iMCUheight = compptr->v_samp_factor * compptr->_DCT_scaled_size;
rgroup = iMCUheight / cinfo->_min_DCT_scaled_size;
/* Count nondummy sample rows remaining for this component */
- rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight);
+ rows_left = (int)(compptr->downsampled_height % (JDIMENSION)iMCUheight);
if (rows_left == 0) rows_left = iMCUheight;
/* Count nondummy row groups. Should get same answer for each component,
* so we need only do it once.
*/
if (ci == 0) {
- main_ptr->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1);
+ main_ptr->rowgroups_avail = (JDIMENSION)((rows_left - 1) / rgroup + 1);
}
/* Duplicate the last real sample row rgroup*2 times; this pads out the
* last partial rowgroup and ensures at least one full rowgroup of context.
*/
xbuf = main_ptr->xbuffer[main_ptr->whichptr][ci];
for (i = 0; i < rgroup * 2; i++) {
- xbuf[rows_left + i] = xbuf[rows_left-1];
+ xbuf[rows_left + i] = xbuf[rows_left - 1];
}
}
}
*/
METHODDEF(void)
-start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
+start_pass_main(j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
switch (pass_mode) {
case JBUF_PASS_THRU:
*/
METHODDEF(void)
-process_data_simple_main (j_decompress_ptr cinfo,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+process_data_simple_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
JDIMENSION rowgroups_avail;
/* Read input data if we haven't filled the main buffer yet */
- if (! main_ptr->buffer_full) {
- if (! (*cinfo->coef->decompress_data) (cinfo, main_ptr->buffer))
+ if (!main_ptr->buffer_full) {
+ if (!(*cinfo->coef->decompress_data) (cinfo, main_ptr->buffer))
return; /* suspension forced, can do nothing more */
main_ptr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
}
/* There are always min_DCT_scaled_size row groups in an iMCU row. */
- rowgroups_avail = (JDIMENSION) cinfo->_min_DCT_scaled_size;
+ rowgroups_avail = (JDIMENSION)cinfo->_min_DCT_scaled_size;
/* Note: at the bottom of the image, we may pass extra garbage row groups
* to the postprocessor. The postprocessor has to check for bottom
* of image anyway (at row resolution), so no point in us doing it too.
*/
METHODDEF(void)
-process_data_context_main (j_decompress_ptr cinfo,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+process_data_context_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
/* Read input data if we haven't filled the main buffer yet */
- if (! main_ptr->buffer_full) {
- if (! (*cinfo->coef->decompress_data) (cinfo,
- main_ptr->xbuffer[main_ptr->whichptr]))
+ if (!main_ptr->buffer_full) {
+ if (!(*cinfo->coef->decompress_data) (cinfo,
+ main_ptr->xbuffer[main_ptr->whichptr]))
return; /* suspension forced, can do nothing more */
main_ptr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
main_ptr->iMCU_row_ctr++; /* count rows received */
switch (main_ptr->context_state) {
case CTX_POSTPONED_ROW:
/* Call postprocessor using previously set pointers for postponed row */
- (*cinfo->post->post_process_data) (cinfo, main_ptr->xbuffer[main_ptr->whichptr],
- &main_ptr->rowgroup_ctr, main_ptr->rowgroups_avail,
- output_buf, out_row_ctr, out_rows_avail);
+ (*cinfo->post->post_process_data) (cinfo,
+ main_ptr->xbuffer[main_ptr->whichptr],
+ &main_ptr->rowgroup_ctr,
+ main_ptr->rowgroups_avail, output_buf,
+ out_row_ctr, out_rows_avail);
if (main_ptr->rowgroup_ctr < main_ptr->rowgroups_avail)
return; /* Need to suspend */
main_ptr->context_state = CTX_PREPARE_FOR_IMCU;
case CTX_PREPARE_FOR_IMCU:
/* Prepare to process first M-1 row groups of this iMCU row */
main_ptr->rowgroup_ctr = 0;
- main_ptr->rowgroups_avail = (JDIMENSION) (cinfo->_min_DCT_scaled_size - 1);
+ main_ptr->rowgroups_avail = (JDIMENSION)(cinfo->_min_DCT_scaled_size - 1);
/* Check for bottom of image: if so, tweak pointers to "duplicate"
* the last sample row, and adjust rowgroups_avail to ignore padding rows.
*/
/*FALLTHROUGH*/
case CTX_PROCESS_IMCU:
/* Call postprocessor using previously set pointers */
- (*cinfo->post->post_process_data) (cinfo, main_ptr->xbuffer[main_ptr->whichptr],
- &main_ptr->rowgroup_ctr, main_ptr->rowgroups_avail,
- output_buf, out_row_ctr, out_rows_avail);
+ (*cinfo->post->post_process_data) (cinfo,
+ main_ptr->xbuffer[main_ptr->whichptr],
+ &main_ptr->rowgroup_ctr,
+ main_ptr->rowgroups_avail, output_buf,
+ out_row_ctr, out_rows_avail);
if (main_ptr->rowgroup_ctr < main_ptr->rowgroups_avail)
return; /* Need to suspend */
/* After the first iMCU, change wraparound pointers to normal state */
main_ptr->buffer_full = FALSE;
/* Still need to process last row group of this iMCU row, */
/* which is saved at index M+1 of the other xbuffer */
- main_ptr->rowgroup_ctr = (JDIMENSION) (cinfo->_min_DCT_scaled_size + 1);
- main_ptr->rowgroups_avail = (JDIMENSION) (cinfo->_min_DCT_scaled_size + 2);
+ main_ptr->rowgroup_ctr = (JDIMENSION)(cinfo->_min_DCT_scaled_size + 1);
+ main_ptr->rowgroups_avail = (JDIMENSION)(cinfo->_min_DCT_scaled_size + 2);
main_ptr->context_state = CTX_POSTPONED_ROW;
}
}
#ifdef QUANT_2PASS_SUPPORTED
METHODDEF(void)
-process_data_crank_post (j_decompress_ptr cinfo,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+process_data_crank_post(j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
{
- (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL,
- (JDIMENSION *) NULL, (JDIMENSION) 0,
+ (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE)NULL,
+ (JDIMENSION *)NULL, (JDIMENSION)0,
output_buf, out_row_ctr, out_rows_avail);
}
*/
GLOBAL(void)
-jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+jinit_d_main_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
{
my_main_ptr main_ptr;
int ci, rgroup, ngroups;
jpeg_component_info *compptr;
main_ptr = (my_main_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_main_controller));
- cinfo->main = (struct jpeg_d_main_controller *) main_ptr;
+ cinfo->main = (struct jpeg_d_main_controller *)main_ptr;
main_ptr->pub.start_pass = start_pass_main;
if (need_full_buffer) /* shouldn't happen */
rgroup = (compptr->v_samp_factor * compptr->_DCT_scaled_size) /
cinfo->_min_DCT_scaled_size; /* height of a row group of component */
main_ptr->buffer[ci] = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
compptr->width_in_blocks * compptr->_DCT_scaled_size,
- (JDIMENSION) (rgroup * ngroups));
+ (JDIMENSION)(rgroup * ngroups));
}
}
LOCAL(void)
-set_wraparound_pointers (j_decompress_ptr cinfo)
+set_wraparound_pointers(j_decompress_ptr cinfo)
/* Set up the "wraparound" pointers at top and bottom of the pointer lists.
* This changes the pointer list state from top-of-image to the normal state.
*/
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
int ci, i, rgroup;
int M = cinfo->_min_DCT_scaled_size;
jpeg_component_info *compptr;
xbuf0 = main_ptr->xbuffer[0][ci];
xbuf1 = main_ptr->xbuffer[1][ci];
for (i = 0; i < rgroup; i++) {
- xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
- xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
- xbuf0[rgroup*(M+2) + i] = xbuf0[i];
- xbuf1[rgroup*(M+2) + i] = xbuf1[i];
+ xbuf0[i - rgroup] = xbuf0[rgroup * (M + 1) + i];
+ xbuf1[i - rgroup] = xbuf1[rgroup * (M + 1) + i];
+ xbuf0[rgroup * (M + 2) + i] = xbuf0[i];
+ xbuf1[rgroup * (M + 2) + i] = xbuf1[i];
}
}
}
*/
/* Declare and initialize local copies of input pointer/count */
-#define INPUT_VARS(cinfo) \
- struct jpeg_source_mgr *datasrc = (cinfo)->src; \
- const JOCTET *next_input_byte = datasrc->next_input_byte; \
- size_t bytes_in_buffer = datasrc->bytes_in_buffer
+#define INPUT_VARS(cinfo) \
+ struct jpeg_source_mgr *datasrc = (cinfo)->src; \
+ const JOCTET *next_input_byte = datasrc->next_input_byte; \
+ size_t bytes_in_buffer = datasrc->bytes_in_buffer
/* Unload the local copies --- do this only at a restart boundary */
-#define INPUT_SYNC(cinfo) \
- ( datasrc->next_input_byte = next_input_byte, \
- datasrc->bytes_in_buffer = bytes_in_buffer )
+#define INPUT_SYNC(cinfo) \
+ ( datasrc->next_input_byte = next_input_byte, \
+ datasrc->bytes_in_buffer = bytes_in_buffer )
/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */
-#define INPUT_RELOAD(cinfo) \
- ( next_input_byte = datasrc->next_input_byte, \
- bytes_in_buffer = datasrc->bytes_in_buffer )
+#define INPUT_RELOAD(cinfo) \
+ ( next_input_byte = datasrc->next_input_byte, \
+ bytes_in_buffer = datasrc->bytes_in_buffer )
/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available.
* Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
* but we must reload the local copies after a successful fill.
*/
-#define MAKE_BYTE_AVAIL(cinfo,action) \
- if (bytes_in_buffer == 0) { \
- if (! (*datasrc->fill_input_buffer) (cinfo)) \
- { action; } \
- INPUT_RELOAD(cinfo); \
- }
+#define MAKE_BYTE_AVAIL(cinfo, action) \
+ if (bytes_in_buffer == 0) { \
+ if (!(*datasrc->fill_input_buffer) (cinfo)) \
+ { action; } \
+ INPUT_RELOAD(cinfo); \
+ }
/* Read a byte into variable V.
* If must suspend, take the specified action (typically "return FALSE").
*/
-#define INPUT_BYTE(cinfo,V,action) \
- MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
- bytes_in_buffer--; \
- V = GETJOCTET(*next_input_byte++); )
+#define INPUT_BYTE(cinfo, V, action) \
+ MAKESTMT( MAKE_BYTE_AVAIL(cinfo, action); \
+ bytes_in_buffer--; \
+ V = GETJOCTET(*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.
*/
-#define INPUT_2BYTES(cinfo,V,action) \
- MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
- bytes_in_buffer--; \
- V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \
- MAKE_BYTE_AVAIL(cinfo,action); \
- bytes_in_buffer--; \
- V += GETJOCTET(*next_input_byte++); )
+#define INPUT_2BYTES(cinfo, V, action) \
+ MAKESTMT( MAKE_BYTE_AVAIL(cinfo, action); \
+ bytes_in_buffer--; \
+ V = ((unsigned int)GETJOCTET(*next_input_byte++)) << 8; \
+ MAKE_BYTE_AVAIL(cinfo, action); \
+ bytes_in_buffer--; \
+ V += GETJOCTET(*next_input_byte++); )
/*
LOCAL(boolean)
-get_soi (j_decompress_ptr cinfo)
+get_soi(j_decompress_ptr cinfo)
/* Process an SOI marker */
{
int i;
LOCAL(boolean)
-get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith)
+get_sof(j_decompress_ptr cinfo, boolean is_prog, boolean is_arith)
/* Process a SOFn marker */
{
JLONG length;
length -= 8;
TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker,
- (int) cinfo->image_width, (int) cinfo->image_height,
+ (int)cinfo->image_width, (int)cinfo->image_height,
cinfo->num_components);
if (cinfo->marker->saw_SOF)
/* We don't support files in which the image height is initially specified */
/* as 0 and is later redefined by DNL. As long as we have to check that, */
/* might as well have a general sanity check. */
- if (cinfo->image_height <= 0 || cinfo->image_width <= 0
- || cinfo->num_components <= 0)
+ if (cinfo->image_height <= 0 || cinfo->image_width <= 0 ||
+ cinfo->num_components <= 0)
ERREXIT(cinfo, JERR_EMPTY_IMAGE);
if (length != (cinfo->num_components * 3))
ERREXIT(cinfo, JERR_BAD_LENGTH);
if (cinfo->comp_info == NULL) /* do only once, even if suspend */
- cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->comp_info = (jpeg_component_info *)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
cinfo->num_components * sizeof(jpeg_component_info));
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
LOCAL(boolean)
-get_sos (j_decompress_ptr cinfo)
+get_sos(j_decompress_ptr cinfo)
/* Process a SOS marker */
{
JLONG length;
jpeg_component_info *compptr;
INPUT_VARS(cinfo);
- if (! cinfo->marker->saw_SOF)
+ if (!cinfo->marker->saw_SOF)
ERREXIT(cinfo, JERR_SOS_NO_SOF);
INPUT_2BYTES(cinfo, length, return FALSE);
ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
- id_found:
+id_found:
cinfo->cur_comp_info[i] = compptr;
compptr->dc_tbl_no = (c >> 4) & 15;
#ifdef D_ARITH_CODING_SUPPORTED
LOCAL(boolean)
-get_dac (j_decompress_ptr cinfo)
+get_dac(j_decompress_ptr cinfo)
/* Process a DAC marker */
{
JLONG length;
TRACEMS2(cinfo, 1, JTRC_DAC, index, val);
- if (index < 0 || index >= (2*NUM_ARITH_TBLS))
+ if (index < 0 || index >= (2 * NUM_ARITH_TBLS))
ERREXIT1(cinfo, JERR_DAC_INDEX, index);
if (index >= NUM_ARITH_TBLS) { /* define AC table */
- cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val;
+ cinfo->arith_ac_K[index - NUM_ARITH_TBLS] = (UINT8)val;
} else { /* define DC table */
- cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F);
- cinfo->arith_dc_U[index] = (UINT8) (val >> 4);
+ cinfo->arith_dc_L[index] = (UINT8)(val & 0x0F);
+ cinfo->arith_dc_U[index] = (UINT8)(val >> 4);
if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
ERREXIT1(cinfo, JERR_DAC_VALUE, val);
}
return TRUE;
}
-#else /* ! D_ARITH_CODING_SUPPORTED */
+#else /* !D_ARITH_CODING_SUPPORTED */
#define get_dac(cinfo) skip_variable(cinfo)
LOCAL(boolean)
-get_dht (j_decompress_ptr cinfo)
+get_dht(j_decompress_ptr cinfo)
/* Process a DHT marker */
{
JLONG length;
/* Here we just do minimal validation of the counts to avoid walking
* off the end of our table space. jdhuff.c will check more carefully.
*/
- if (count > 256 || ((JLONG) count) > length)
+ if (count > 256 || ((JLONG)count) > length)
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
for (i = 0; i < count; i++)
}
if (*htblptr == NULL)
- *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo);
MEMCOPY((*htblptr)->bits, bits, sizeof((*htblptr)->bits));
MEMCOPY((*htblptr)->huffval, huffval, sizeof((*htblptr)->huffval));
LOCAL(boolean)
-get_dqt (j_decompress_ptr cinfo)
+get_dqt(j_decompress_ptr cinfo)
/* Process a DQT marker */
{
JLONG length;
ERREXIT1(cinfo, JERR_DQT_INDEX, n);
if (cinfo->quant_tbl_ptrs[n] == NULL)
- cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo);
+ cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr)cinfo);
quant_ptr = cinfo->quant_tbl_ptrs[n];
for (i = 0; i < DCTSIZE2; i++) {
else
INPUT_BYTE(cinfo, tmp, return FALSE);
/* We convert the zigzag-order table to natural array order. */
- quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp;
+ quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16)tmp;
}
if (cinfo->err->trace_level >= 2) {
for (i = 0; i < DCTSIZE2; i += 8) {
TRACEMS8(cinfo, 2, JTRC_QUANTVALS,
- quant_ptr->quantval[i], quant_ptr->quantval[i+1],
- quant_ptr->quantval[i+2], quant_ptr->quantval[i+3],
- quant_ptr->quantval[i+4], quant_ptr->quantval[i+5],
- quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]);
+ quant_ptr->quantval[i], quant_ptr->quantval[i + 1],
+ quant_ptr->quantval[i + 2], quant_ptr->quantval[i + 3],
+ quant_ptr->quantval[i + 4], quant_ptr->quantval[i + 5],
+ quant_ptr->quantval[i + 6], quant_ptr->quantval[i + 7]);
}
}
- length -= DCTSIZE2+1;
+ length -= DCTSIZE2 + 1;
if (prec) length -= DCTSIZE2;
}
LOCAL(boolean)
-get_dri (j_decompress_ptr cinfo)
+get_dri(j_decompress_ptr cinfo)
/* Process a DRI marker */
{
JLONG length;
LOCAL(void)
-examine_app0 (j_decompress_ptr cinfo, JOCTET *data,
- unsigned int datalen, JLONG remaining)
+examine_app0(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,
+ JLONG remaining)
/* Examine first few bytes from an APP0.
* Take appropriate action if it is a JFIF marker.
* datalen is # of bytes at data[], remaining is length of rest of marker data.
*/
{
- JLONG totallen = (JLONG) datalen + remaining;
+ JLONG totallen = (JLONG)datalen + remaining;
if (datalen >= APP0_DATA_LEN &&
GETJOCTET(data[0]) == 0x4A &&
GETJOCTET(data[12]), GETJOCTET(data[13]));
totallen -= APP0_DATA_LEN;
if (totallen !=
- ((JLONG)GETJOCTET(data[12]) * (JLONG)GETJOCTET(data[13]) * (JLONG) 3))
- TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen);
+ ((JLONG)GETJOCTET(data[12]) * (JLONG)GETJOCTET(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) {
+ GETJOCTET(data[0]) == 0x4A &&
+ GETJOCTET(data[1]) == 0x46 &&
+ GETJOCTET(data[2]) == 0x58 &&
+ GETJOCTET(data[3]) == 0x58 &&
+ GETJOCTET(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])) {
case 0x10:
- TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen);
+ TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int)totallen);
break;
case 0x11:
- TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen);
+ TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int)totallen);
break;
case 0x13:
- TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen);
+ TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int)totallen);
break;
default:
TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION,
- GETJOCTET(data[5]), (int) totallen);
+ GETJOCTET(data[5]), (int)totallen);
break;
}
} else {
/* Start of APP0 does not match "JFIF" or "JFXX", or too short */
- TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen);
+ TRACEMS1(cinfo, 1, JTRC_APP0, (int)totallen);
}
}
LOCAL(void)
-examine_app14 (j_decompress_ptr cinfo, JOCTET *data,
- unsigned int datalen, JLONG remaining)
+examine_app14(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,
+ JLONG remaining)
/* Examine first few bytes from an APP14.
* Take appropriate action if it is an Adobe marker.
* datalen is # of bytes at data[], remaining is length of rest of marker data.
transform = GETJOCTET(data[11]);
TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);
cinfo->saw_Adobe_marker = TRUE;
- cinfo->Adobe_transform = (UINT8) transform;
+ cinfo->Adobe_transform = (UINT8)transform;
} else {
/* Start of APP14 does not match "Adobe", or too short */
- TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining));
+ TRACEMS1(cinfo, 1, JTRC_APP14, (int)(datalen + remaining));
}
}
METHODDEF(boolean)
-get_interesting_appn (j_decompress_ptr cinfo)
+get_interesting_appn(j_decompress_ptr cinfo)
/* Process an APP0 or APP14 marker without saving it */
{
JLONG length;
if (length >= APPN_DATA_LEN)
numtoread = APPN_DATA_LEN;
else if (length > 0)
- numtoread = (unsigned int) length;
+ numtoread = (unsigned int)length;
else
numtoread = 0;
for (i = 0; i < numtoread; i++)
/* process it */
switch (cinfo->unread_marker) {
case M_APP0:
- examine_app0(cinfo, (JOCTET *) b, numtoread, length);
+ examine_app0(cinfo, (JOCTET *)b, numtoread, length);
break;
case M_APP14:
- examine_app14(cinfo, (JOCTET *) b, numtoread, length);
+ examine_app14(cinfo, (JOCTET *)b, numtoread, length);
break;
default:
/* can't get here unless jpeg_save_markers chooses wrong processor */
/* skip any remaining data -- could be lots */
INPUT_SYNC(cinfo);
if (length > 0)
- (*cinfo->src->skip_input_data) (cinfo, (long) length);
+ (*cinfo->src->skip_input_data) (cinfo, (long)length);
return TRUE;
}
#ifdef SAVE_MARKERS_SUPPORTED
METHODDEF(boolean)
-save_marker (j_decompress_ptr cinfo)
+save_marker(j_decompress_ptr cinfo)
/* Save an APPn or COM marker into the marker list */
{
- my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
jpeg_saved_marker_ptr cur_marker = marker->cur_marker;
unsigned int bytes_read, data_length;
JOCTET *data;
if (length >= 0) { /* watch out for bogus length word */
/* figure out how much we want to save */
unsigned int limit;
- if (cinfo->unread_marker == (int) M_COM)
+ if (cinfo->unread_marker == (int)M_COM)
limit = marker->length_limit_COM;
else
- limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0];
- if ((unsigned int) length < limit)
- limit = (unsigned int) length;
+ limit = marker->length_limit_APPn[cinfo->unread_marker - (int)M_APP0];
+ if ((unsigned int)length < limit)
+ limit = (unsigned int)length;
/* allocate and initialize the marker item */
cur_marker = (jpeg_saved_marker_ptr)
- (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(struct jpeg_marker_struct) + limit);
cur_marker->next = NULL;
- cur_marker->marker = (UINT8) cinfo->unread_marker;
- cur_marker->original_length = (unsigned int) length;
+ cur_marker->marker = (UINT8)cinfo->unread_marker;
+ cur_marker->original_length = (unsigned int)length;
cur_marker->data_length = limit;
/* data area is just beyond the jpeg_marker_struct */
- data = cur_marker->data = (JOCTET *) (cur_marker + 1);
+ data = cur_marker->data = (JOCTET *)(cur_marker + 1);
marker->cur_marker = cur_marker;
marker->bytes_read = 0;
bytes_read = 0;
break;
default:
TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker,
- (int) (data_length + length));
+ (int)(data_length + length));
break;
}
/* skip any remaining data -- could be lots */
INPUT_SYNC(cinfo); /* do before skip_input_data */
if (length > 0)
- (*cinfo->src->skip_input_data) (cinfo, (long) length);
+ (*cinfo->src->skip_input_data) (cinfo, (long)length);
return TRUE;
}
METHODDEF(boolean)
-skip_variable (j_decompress_ptr cinfo)
+skip_variable(j_decompress_ptr cinfo)
/* Skip over an unknown or uninteresting variable-length marker */
{
JLONG length;
INPUT_2BYTES(cinfo, length, return FALSE);
length -= 2;
- TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length);
+ TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int)length);
INPUT_SYNC(cinfo); /* do before skip_input_data */
if (length > 0)
- (*cinfo->src->skip_input_data) (cinfo, (long) length);
+ (*cinfo->src->skip_input_data) (cinfo, (long)length);
return TRUE;
}
*/
LOCAL(boolean)
-next_marker (j_decompress_ptr cinfo)
+next_marker(j_decompress_ptr cinfo)
{
int c;
INPUT_VARS(cinfo);
LOCAL(boolean)
-first_marker (j_decompress_ptr cinfo)
+first_marker(j_decompress_ptr cinfo)
/* Like next_marker, but used to obtain the initial SOI marker. */
/* For this marker, we do not allow preceding garbage or fill; otherwise,
* we might well scan an entire input file before realizing it ain't JPEG.
INPUT_BYTE(cinfo, c, return FALSE);
INPUT_BYTE(cinfo, c2, return FALSE);
- if (c != 0xFF || c2 != (int) M_SOI)
+ if (c != 0xFF || c2 != (int)M_SOI)
ERREXIT2(cinfo, JERR_NO_SOI, c, c2);
cinfo->unread_marker = c2;
*/
METHODDEF(int)
-read_markers (j_decompress_ptr cinfo)
+read_markers(j_decompress_ptr cinfo)
{
/* Outer loop repeats once for each marker. */
for (;;) {
/* Collect the marker proper, unless we already did. */
/* NB: first_marker() enforces the requirement that SOI appear first. */
if (cinfo->unread_marker == 0) {
- if (! cinfo->marker->saw_SOI) {
- if (! first_marker(cinfo))
+ if (!cinfo->marker->saw_SOI) {
+ if (!first_marker(cinfo))
return JPEG_SUSPENDED;
} else {
- if (! next_marker(cinfo))
+ if (!next_marker(cinfo))
return JPEG_SUSPENDED;
}
}
*/
switch (cinfo->unread_marker) {
case M_SOI:
- if (! get_soi(cinfo))
+ if (!get_soi(cinfo))
return JPEG_SUSPENDED;
break;
case M_SOF0: /* Baseline */
case M_SOF1: /* Extended sequential, Huffman */
- if (! get_sof(cinfo, FALSE, FALSE))
+ if (!get_sof(cinfo, FALSE, FALSE))
return JPEG_SUSPENDED;
break;
case M_SOF2: /* Progressive, Huffman */
- if (! get_sof(cinfo, TRUE, FALSE))
+ if (!get_sof(cinfo, TRUE, FALSE))
return JPEG_SUSPENDED;
break;
case M_SOF9: /* Extended sequential, arithmetic */
- if (! get_sof(cinfo, FALSE, TRUE))
+ if (!get_sof(cinfo, FALSE, TRUE))
return JPEG_SUSPENDED;
break;
case M_SOF10: /* Progressive, arithmetic */
- if (! get_sof(cinfo, TRUE, TRUE))
+ if (!get_sof(cinfo, TRUE, TRUE))
return JPEG_SUSPENDED;
break;
break;
case M_SOS:
- if (! get_sos(cinfo))
+ if (!get_sos(cinfo))
return JPEG_SUSPENDED;
cinfo->unread_marker = 0; /* processed the marker */
return JPEG_REACHED_SOS;
return JPEG_REACHED_EOI;
case M_DAC:
- if (! get_dac(cinfo))
+ if (!get_dac(cinfo))
return JPEG_SUSPENDED;
break;
case M_DHT:
- if (! get_dht(cinfo))
+ if (!get_dht(cinfo))
return JPEG_SUSPENDED;
break;
case M_DQT:
- if (! get_dqt(cinfo))
+ if (!get_dqt(cinfo))
return JPEG_SUSPENDED;
break;
case M_DRI:
- if (! get_dri(cinfo))
+ if (!get_dri(cinfo))
return JPEG_SUSPENDED;
break;
case M_APP13:
case M_APP14:
case M_APP15:
- if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[
- cinfo->unread_marker - (int) M_APP0]) (cinfo))
+ if (!(*((my_marker_ptr)cinfo->marker)->process_APPn[
+ cinfo->unread_marker - (int)M_APP0]) (cinfo))
return JPEG_SUSPENDED;
break;
case M_COM:
- if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo))
+ if (!(*((my_marker_ptr)cinfo->marker)->process_COM) (cinfo))
return JPEG_SUSPENDED;
break;
break;
case M_DNL: /* Ignore DNL ... perhaps the wrong thing */
- if (! skip_variable(cinfo))
+ if (!skip_variable(cinfo))
return JPEG_SUSPENDED;
break;
*/
METHODDEF(boolean)
-read_restart_marker (j_decompress_ptr cinfo)
+read_restart_marker(j_decompress_ptr cinfo)
{
/* Obtain a marker unless we already did. */
/* Note that next_marker will complain if it skips any data. */
if (cinfo->unread_marker == 0) {
- if (! next_marker(cinfo))
+ if (!next_marker(cinfo))
return FALSE;
}
if (cinfo->unread_marker ==
- ((int) M_RST0 + cinfo->marker->next_restart_num)) {
+ ((int)M_RST0 + cinfo->marker->next_restart_num)) {
/* Normal case --- swallow the marker and let entropy decoder continue */
TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num);
cinfo->unread_marker = 0;
} else {
/* Uh-oh, the restart markers have been messed up. */
/* Let the data source manager determine how to resync. */
- if (! (*cinfo->src->resync_to_restart) (cinfo,
- cinfo->marker->next_restart_num))
+ if (!(*cinfo->src->resync_to_restart) (cinfo,
+ cinfo->marker->next_restart_num))
return FALSE;
}
*/
GLOBAL(boolean)
-jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired)
+jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired)
{
int marker = cinfo->unread_marker;
int action = 1;
/* Outer loop handles repeated decision after scanning forward. */
for (;;) {
- if (marker < (int) M_SOF0)
+ if (marker < (int)M_SOF0)
action = 2; /* invalid marker */
- else if (marker < (int) M_RST0 || marker > (int) M_RST7)
+ else if (marker < (int)M_RST0 || marker > (int)M_RST7)
action = 3; /* valid non-restart marker */
else {
- if (marker == ((int) M_RST0 + ((desired+1) & 7)) ||
- marker == ((int) M_RST0 + ((desired+2) & 7)))
+ if (marker == ((int)M_RST0 + ((desired + 1) & 7)) ||
+ marker == ((int)M_RST0 + ((desired + 2) & 7)))
action = 3; /* one of the next two expected restarts */
- else if (marker == ((int) M_RST0 + ((desired-1) & 7)) ||
- marker == ((int) M_RST0 + ((desired-2) & 7)))
+ else if (marker == ((int)M_RST0 + ((desired - 1) & 7)) ||
+ marker == ((int)M_RST0 + ((desired - 2) & 7)))
action = 2; /* a prior restart, so advance */
else
action = 1; /* desired restart or too far away */
return TRUE;
case 2:
/* Scan to the next marker, and repeat the decision loop. */
- if (! next_marker(cinfo))
+ if (!next_marker(cinfo))
return FALSE;
marker = cinfo->unread_marker;
break;
*/
METHODDEF(void)
-reset_marker_reader (j_decompress_ptr cinfo)
+reset_marker_reader(j_decompress_ptr cinfo)
{
- my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
cinfo->comp_info = NULL; /* until allocated by get_sof */
cinfo->input_scan_number = 0; /* no SOS seen yet */
*/
GLOBAL(void)
-jinit_marker_reader (j_decompress_ptr cinfo)
+jinit_marker_reader(j_decompress_ptr cinfo)
{
my_marker_ptr marker;
int i;
/* Create subobject in permanent pool */
marker = (my_marker_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(my_marker_reader));
- cinfo->marker = (struct jpeg_marker_reader *) marker;
+ cinfo->marker = (struct jpeg_marker_reader *)marker;
/* Initialize public method pointers */
marker->pub.reset_marker_reader = reset_marker_reader;
marker->pub.read_markers = read_markers;
#ifdef SAVE_MARKERS_SUPPORTED
GLOBAL(void)
-jpeg_save_markers (j_decompress_ptr cinfo, int marker_code,
- unsigned int length_limit)
+jpeg_save_markers(j_decompress_ptr cinfo, int marker_code,
+ unsigned int length_limit)
{
- my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
long maxlength;
jpeg_marker_parser_method processor;
* (should only be a concern in a 16-bit environment).
*/
maxlength = cinfo->mem->max_alloc_chunk - sizeof(struct jpeg_marker_struct);
- if (((long) length_limit) > maxlength)
- length_limit = (unsigned int) maxlength;
+ if (((long)length_limit) > maxlength)
+ length_limit = (unsigned int)maxlength;
/* Choose processor routine to use.
* APP0/APP14 have special requirements.
if (length_limit) {
processor = save_marker;
/* If saving APP0/APP14, save at least enough for our internal use. */
- if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN)
+ if (marker_code == (int)M_APP0 && length_limit < APP0_DATA_LEN)
length_limit = APP0_DATA_LEN;
- else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN)
+ else if (marker_code == (int)M_APP14 && length_limit < APP14_DATA_LEN)
length_limit = APP14_DATA_LEN;
} else {
processor = skip_variable;
/* If discarding APP0/APP14, use our regular on-the-fly processor. */
- if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14)
+ if (marker_code == (int)M_APP0 || marker_code == (int)M_APP14)
processor = get_interesting_appn;
}
- if (marker_code == (int) M_COM) {
+ if (marker_code == (int)M_COM) {
marker->process_COM = processor;
marker->length_limit_COM = length_limit;
- } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) {
- marker->process_APPn[marker_code - (int) M_APP0] = processor;
- marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit;
+ } else if (marker_code >= (int)M_APP0 && marker_code <= (int)M_APP15) {
+ marker->process_APPn[marker_code - (int)M_APP0] = processor;
+ marker->length_limit_APPn[marker_code - (int)M_APP0] = length_limit;
} else
ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
}
*/
GLOBAL(void)
-jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code,
- jpeg_marker_parser_method routine)
+jpeg_set_marker_processor(j_decompress_ptr cinfo, int marker_code,
+ jpeg_marker_parser_method routine)
{
- my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
- if (marker_code == (int) M_COM)
+ if (marker_code == (int)M_COM)
marker->process_COM = routine;
- else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15)
- marker->process_APPn[marker_code - (int) M_APP0] = routine;
+ else if (marker_code >= (int)M_APP0 && marker_code <= (int)M_APP15)
+ marker->process_APPn[marker_code - (int)M_APP0] = routine;
else
ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
}
*/
LOCAL(boolean)
-use_merged_upsample (j_decompress_ptr cinfo)
+use_merged_upsample(j_decompress_ptr cinfo)
{
#ifdef UPSAMPLE_MERGING_SUPPORTED
/* Merging is the equivalent of plain box-filter upsampling */
/* jdmerge.c only supports YCC=>RGB and YCC=>RGB565 color conversion */
if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 ||
(cinfo->out_color_space != JCS_RGB &&
- cinfo->out_color_space != JCS_RGB565 &&
- cinfo->out_color_space != JCS_EXT_RGB &&
- cinfo->out_color_space != JCS_EXT_RGBX &&
- cinfo->out_color_space != JCS_EXT_BGR &&
- cinfo->out_color_space != JCS_EXT_BGRX &&
- cinfo->out_color_space != JCS_EXT_XBGR &&
- cinfo->out_color_space != JCS_EXT_XRGB &&
- cinfo->out_color_space != JCS_EXT_RGBA &&
- cinfo->out_color_space != JCS_EXT_BGRA &&
- cinfo->out_color_space != JCS_EXT_ABGR &&
- cinfo->out_color_space != JCS_EXT_ARGB))
+ cinfo->out_color_space != JCS_RGB565 &&
+ cinfo->out_color_space != JCS_EXT_RGB &&
+ cinfo->out_color_space != JCS_EXT_RGBX &&
+ cinfo->out_color_space != JCS_EXT_BGR &&
+ cinfo->out_color_space != JCS_EXT_BGRX &&
+ cinfo->out_color_space != JCS_EXT_XBGR &&
+ cinfo->out_color_space != JCS_EXT_XRGB &&
+ cinfo->out_color_space != JCS_EXT_RGBA &&
+ cinfo->out_color_space != JCS_EXT_BGRA &&
+ cinfo->out_color_space != JCS_EXT_ABGR &&
+ cinfo->out_color_space != JCS_EXT_ARGB))
return FALSE;
if ((cinfo->out_color_space == JCS_RGB565 &&
- cinfo->out_color_components != 3) ||
+ cinfo->out_color_components != 3) ||
(cinfo->out_color_space != JCS_RGB565 &&
- cinfo->out_color_components != rgb_pixelsize[cinfo->out_color_space]))
+ cinfo->out_color_components != rgb_pixelsize[cinfo->out_color_space]))
return FALSE;
/* and it only handles 2h1v or 2h2v sampling ratios */
if (cinfo->comp_info[0].h_samp_factor != 2 ||
#else
LOCAL(void)
#endif
-jpeg_core_output_dimensions (j_decompress_ptr cinfo)
+jpeg_core_output_dimensions(j_decompress_ptr cinfo)
/* Do computations that are needed before master selection phase.
* This function is used for transcoding and full decompression.
*/
if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom) {
/* Provide 1/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 1;
cinfo->_min_DCT_v_scaled_size = 1;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 2) {
/* Provide 2/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 2L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 2L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 2L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 2L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 2;
cinfo->_min_DCT_v_scaled_size = 2;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 3) {
/* Provide 3/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 3L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 3L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 3L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 3L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 3;
cinfo->_min_DCT_v_scaled_size = 3;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 4) {
/* Provide 4/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 4L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 4L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 4L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 4L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 4;
cinfo->_min_DCT_v_scaled_size = 4;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 5) {
/* Provide 5/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 5L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 5L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 5L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 5L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 5;
cinfo->_min_DCT_v_scaled_size = 5;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 6) {
/* Provide 6/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 6L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 6L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 6L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 6L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 6;
cinfo->_min_DCT_v_scaled_size = 6;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 7) {
/* Provide 7/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 7L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 7L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 7L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 7L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 7;
cinfo->_min_DCT_v_scaled_size = 7;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 8) {
/* Provide 8/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 8L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 8L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 8L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 8L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 8;
cinfo->_min_DCT_v_scaled_size = 8;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 9) {
/* Provide 9/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 9L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 9L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 9L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 9L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 9;
cinfo->_min_DCT_v_scaled_size = 9;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 10) {
/* Provide 10/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 10L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 10L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 10L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 10L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 10;
cinfo->_min_DCT_v_scaled_size = 10;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 11) {
/* Provide 11/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 11L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 11L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 11L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 11L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 11;
cinfo->_min_DCT_v_scaled_size = 11;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 12) {
/* Provide 12/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 12L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 12L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 12L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 12L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 12;
cinfo->_min_DCT_v_scaled_size = 12;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 13) {
/* Provide 13/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 13L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 13L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 13L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 13L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 13;
cinfo->_min_DCT_v_scaled_size = 13;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 14) {
/* Provide 14/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 14L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 14L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 14L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 14L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 14;
cinfo->_min_DCT_v_scaled_size = 14;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 15) {
/* Provide 15/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 15L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 15L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 15L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 15L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 15;
cinfo->_min_DCT_v_scaled_size = 15;
} else {
/* Provide 16/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 16L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 16L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 16L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 16L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 16;
cinfo->_min_DCT_v_scaled_size = 16;
}
*/
GLOBAL(void)
-jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
+jpeg_calc_output_dimensions(j_decompress_ptr cinfo)
/* Do computations that are needed before master selection phase */
{
#ifdef IDCT_SCALING_SUPPORTED
ci++, compptr++) {
/* Size in samples, after IDCT scaling */
compptr->downsampled_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width *
- (long) (compptr->h_samp_factor * compptr->_DCT_scaled_size),
- (long) (cinfo->max_h_samp_factor * DCTSIZE));
+ jdiv_round_up((long)cinfo->image_width *
+ (long)(compptr->h_samp_factor * compptr->_DCT_scaled_size),
+ (long)(cinfo->max_h_samp_factor * DCTSIZE));
compptr->downsampled_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height *
- (long) (compptr->v_samp_factor * compptr->_DCT_scaled_size),
- (long) (cinfo->max_v_samp_factor * DCTSIZE));
+ jdiv_round_up((long)cinfo->image_height *
+ (long)(compptr->v_samp_factor * compptr->_DCT_scaled_size),
+ (long)(cinfo->max_v_samp_factor * DCTSIZE));
}
#else /* !IDCT_SCALING_SUPPORTED */
*/
LOCAL(void)
-prepare_range_limit_table (j_decompress_ptr cinfo)
+prepare_range_limit_table(j_decompress_ptr cinfo)
/* Allocate and fill in the sample_range_limit table */
{
JSAMPLE *table;
int i;
table = (JSAMPLE *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * sizeof(JSAMPLE));
- table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (5 * (MAXJSAMPLE + 1) + CENTERJSAMPLE) * sizeof(JSAMPLE));
+ table += (MAXJSAMPLE + 1); /* allow negative subscripts of simple table */
cinfo->sample_range_limit = table;
/* First segment of "simple" table: limit[x] = 0 for x < 0 */
- MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * sizeof(JSAMPLE));
+ MEMZERO(table - (MAXJSAMPLE + 1), (MAXJSAMPLE + 1) * sizeof(JSAMPLE));
/* Main part of "simple" table: limit[x] = x */
for (i = 0; i <= MAXJSAMPLE; i++)
- table[i] = (JSAMPLE) i;
+ table[i] = (JSAMPLE)i;
table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */
/* End of simple table, rest of first half of post-IDCT table */
- for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++)
+ for (i = CENTERJSAMPLE; i < 2 * (MAXJSAMPLE + 1); i++)
table[i] = MAXJSAMPLE;
/* Second half of post-IDCT table */
- MEMZERO(table + (2 * (MAXJSAMPLE+1)),
- (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * sizeof(JSAMPLE));
- MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE),
+ MEMZERO(table + (2 * (MAXJSAMPLE + 1)),
+ (2 * (MAXJSAMPLE + 1) - CENTERJSAMPLE) * sizeof(JSAMPLE));
+ MEMCOPY(table + (4 * (MAXJSAMPLE + 1) - CENTERJSAMPLE),
cinfo->sample_range_limit, CENTERJSAMPLE * sizeof(JSAMPLE));
}
*/
LOCAL(void)
-master_selection (j_decompress_ptr cinfo)
+master_selection(j_decompress_ptr cinfo)
{
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
boolean use_c_buffer;
long samplesperrow;
JDIMENSION jd_samplesperrow;
prepare_range_limit_table(cinfo);
/* Width of an output scanline must be representable as JDIMENSION. */
- samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components;
- jd_samplesperrow = (JDIMENSION) samplesperrow;
- if ((long) jd_samplesperrow != samplesperrow)
+ samplesperrow = (long)cinfo->output_width *
+ (long)cinfo->out_color_components;
+ jd_samplesperrow = (JDIMENSION)samplesperrow;
+ if ((long)jd_samplesperrow != samplesperrow)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
/* Initialize my private state */
master->quantizer_1pass = NULL;
master->quantizer_2pass = NULL;
/* No mode changes if not using buffered-image mode. */
- if (! cinfo->quantize_colors || ! cinfo->buffered_image) {
+ if (!cinfo->quantize_colors || !cinfo->buffered_image) {
cinfo->enable_1pass_quant = FALSE;
cinfo->enable_external_quant = FALSE;
cinfo->enable_2pass_quant = FALSE;
}
/* Post-processing: in particular, color conversion first */
- if (! cinfo->raw_data_out) {
+ if (!cinfo->raw_data_out) {
if (master->using_merged_upsample) {
#ifdef UPSAMPLE_MERGING_SUPPORTED
jinit_merged_upsampler(cinfo); /* does color conversion too */
use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
jinit_d_coef_controller(cinfo, use_c_buffer);
- if (! cinfo->raw_data_out)
+ if (!cinfo->raw_data_out)
jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
/* We can now tell the memory manager to allocate virtual arrays. */
- (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo);
/* Initialize input side of decompressor to consume first scan. */
(*cinfo->inputctl->start_input_pass) (cinfo);
* progress monitoring appropriately. The input step is counted
* as one pass.
*/
- if (cinfo->progress != NULL && ! cinfo->buffered_image &&
+ if (cinfo->progress != NULL && !cinfo->buffered_image &&
cinfo->inputctl->has_multiple_scans) {
int nscans;
/* Estimate number of scans to set pass_limit. */
nscans = cinfo->num_components;
}
cinfo->progress->pass_counter = 0L;
- cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
+ cinfo->progress->pass_limit = (long)cinfo->total_iMCU_rows * nscans;
cinfo->progress->completed_passes = 0;
cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2);
/* Count the input pass as done */
*/
METHODDEF(void)
-prepare_for_output_pass (j_decompress_ptr cinfo)
+prepare_for_output_pass(j_decompress_ptr cinfo)
{
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
if (master->pub.is_dummy_pass) {
#ifdef QUANT_2PASS_SUPPORTED
}
(*cinfo->idct->start_pass) (cinfo);
(*cinfo->coef->start_output_pass) (cinfo);
- if (! cinfo->raw_data_out) {
- if (! master->using_merged_upsample)
+ if (!cinfo->raw_data_out) {
+ if (!master->using_merged_upsample)
(*cinfo->cconvert->start_pass) (cinfo);
(*cinfo->upsample->start_pass) (cinfo);
if (cinfo->quantize_colors)
/* In buffered-image mode, we assume one more output pass if EOI not
* yet reached, but no more passes if EOI has been reached.
*/
- if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) {
+ if (cinfo->buffered_image && !cinfo->inputctl->eoi_reached) {
cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1);
}
}
*/
METHODDEF(void)
-finish_output_pass (j_decompress_ptr cinfo)
+finish_output_pass(j_decompress_ptr cinfo)
{
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
if (cinfo->quantize_colors)
(*cinfo->cquantize->finish_pass) (cinfo);
*/
GLOBAL(void)
-jpeg_new_colormap (j_decompress_ptr cinfo)
+jpeg_new_colormap(j_decompress_ptr cinfo)
{
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
/* Prevent application from calling me at wrong times */
if (cinfo->global_state != DSTATE_BUFIMAGE)
*/
GLOBAL(void)
-jinit_master_decompress (j_decompress_ptr cinfo)
+jinit_master_decompress(j_decompress_ptr cinfo)
{
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
master->pub.prepare_for_output_pass = prepare_for_output_pass;
master->pub.finish_output_pass = finish_output_pass;
typedef my_upsampler *my_upsample_ptr;
#define SCALEBITS 16 /* speediest right-shift on some machines */
-#define ONE_HALF ((JLONG) 1 << (SCALEBITS-1))
-#define FIX(x) ((JLONG) ((x) * (1L<<SCALEBITS) + 0.5))
+#define ONE_HALF ((JLONG)1 << (SCALEBITS - 1))
+#define FIX(x) ((JLONG)((x) * (1L << SCALEBITS) + 0.5))
/* Include inline routines for colorspace extensions */
#undef RGB_BLUE
#undef RGB_PIXELSIZE
-#define RGB_RED EXT_RGB_RED
-#define RGB_GREEN EXT_RGB_GREEN
-#define RGB_BLUE EXT_RGB_BLUE
-#define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
-#define h2v1_merged_upsample_internal extrgb_h2v1_merged_upsample_internal
-#define h2v2_merged_upsample_internal extrgb_h2v2_merged_upsample_internal
+#define RGB_RED EXT_RGB_RED
+#define RGB_GREEN EXT_RGB_GREEN
+#define RGB_BLUE EXT_RGB_BLUE
+#define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
+#define h2v1_merged_upsample_internal extrgb_h2v1_merged_upsample_internal
+#define h2v2_merged_upsample_internal extrgb_h2v2_merged_upsample_internal
#include "jdmrgext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef h2v1_merged_upsample_internal
#undef h2v2_merged_upsample_internal
-#define RGB_RED EXT_RGBX_RED
-#define RGB_GREEN EXT_RGBX_GREEN
-#define RGB_BLUE EXT_RGBX_BLUE
-#define RGB_ALPHA 3
-#define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
-#define h2v1_merged_upsample_internal extrgbx_h2v1_merged_upsample_internal
-#define h2v2_merged_upsample_internal extrgbx_h2v2_merged_upsample_internal
+#define RGB_RED EXT_RGBX_RED
+#define RGB_GREEN EXT_RGBX_GREEN
+#define RGB_BLUE EXT_RGBX_BLUE
+#define RGB_ALPHA 3
+#define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
+#define h2v1_merged_upsample_internal extrgbx_h2v1_merged_upsample_internal
+#define h2v2_merged_upsample_internal extrgbx_h2v2_merged_upsample_internal
#include "jdmrgext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef h2v1_merged_upsample_internal
#undef h2v2_merged_upsample_internal
-#define RGB_RED EXT_BGR_RED
-#define RGB_GREEN EXT_BGR_GREEN
-#define RGB_BLUE EXT_BGR_BLUE
-#define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
-#define h2v1_merged_upsample_internal extbgr_h2v1_merged_upsample_internal
-#define h2v2_merged_upsample_internal extbgr_h2v2_merged_upsample_internal
+#define RGB_RED EXT_BGR_RED
+#define RGB_GREEN EXT_BGR_GREEN
+#define RGB_BLUE EXT_BGR_BLUE
+#define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
+#define h2v1_merged_upsample_internal extbgr_h2v1_merged_upsample_internal
+#define h2v2_merged_upsample_internal extbgr_h2v2_merged_upsample_internal
#include "jdmrgext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef h2v1_merged_upsample_internal
#undef h2v2_merged_upsample_internal
-#define RGB_RED EXT_BGRX_RED
-#define RGB_GREEN EXT_BGRX_GREEN
-#define RGB_BLUE EXT_BGRX_BLUE
-#define RGB_ALPHA 3
-#define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
-#define h2v1_merged_upsample_internal extbgrx_h2v1_merged_upsample_internal
-#define h2v2_merged_upsample_internal extbgrx_h2v2_merged_upsample_internal
+#define RGB_RED EXT_BGRX_RED
+#define RGB_GREEN EXT_BGRX_GREEN
+#define RGB_BLUE EXT_BGRX_BLUE
+#define RGB_ALPHA 3
+#define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
+#define h2v1_merged_upsample_internal extbgrx_h2v1_merged_upsample_internal
+#define h2v2_merged_upsample_internal extbgrx_h2v2_merged_upsample_internal
#include "jdmrgext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef h2v1_merged_upsample_internal
#undef h2v2_merged_upsample_internal
-#define RGB_RED EXT_XBGR_RED
-#define RGB_GREEN EXT_XBGR_GREEN
-#define RGB_BLUE EXT_XBGR_BLUE
-#define RGB_ALPHA 0
-#define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
-#define h2v1_merged_upsample_internal extxbgr_h2v1_merged_upsample_internal
-#define h2v2_merged_upsample_internal extxbgr_h2v2_merged_upsample_internal
+#define RGB_RED EXT_XBGR_RED
+#define RGB_GREEN EXT_XBGR_GREEN
+#define RGB_BLUE EXT_XBGR_BLUE
+#define RGB_ALPHA 0
+#define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
+#define h2v1_merged_upsample_internal extxbgr_h2v1_merged_upsample_internal
+#define h2v2_merged_upsample_internal extxbgr_h2v2_merged_upsample_internal
#include "jdmrgext.c"
#undef RGB_RED
#undef RGB_GREEN
#undef h2v1_merged_upsample_internal
#undef h2v2_merged_upsample_internal
-#define RGB_RED EXT_XRGB_RED
-#define RGB_GREEN EXT_XRGB_GREEN
-#define RGB_BLUE EXT_XRGB_BLUE
-#define RGB_ALPHA 0
-#define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
-#define h2v1_merged_upsample_internal extxrgb_h2v1_merged_upsample_internal
-#define h2v2_merged_upsample_internal extxrgb_h2v2_merged_upsample_internal
+#define RGB_RED EXT_XRGB_RED
+#define RGB_GREEN EXT_XRGB_GREEN
+#define RGB_BLUE EXT_XRGB_BLUE
+#define RGB_ALPHA 0
+#define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
+#define h2v1_merged_upsample_internal extxrgb_h2v1_merged_upsample_internal
+#define h2v2_merged_upsample_internal extxrgb_h2v2_merged_upsample_internal
#include "jdmrgext.c"
#undef RGB_RED
#undef RGB_GREEN
*/
LOCAL(void)
-build_ycc_rgb_table (j_decompress_ptr cinfo)
+build_ycc_rgb_table(j_decompress_ptr cinfo)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
int i;
JLONG x;
SHIFT_TEMPS
upsample->Cr_r_tab = (int *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(int));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(int));
upsample->Cb_b_tab = (int *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(int));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(int));
upsample->Cr_g_tab = (JLONG *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(JLONG));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(JLONG));
upsample->Cb_g_tab = (JLONG *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(JLONG));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(JLONG));
for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
/* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
upsample->Cb_b_tab[i] = (int)
RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
/* Cr=>G value is scaled-up -0.71414 * x */
- upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x;
+ upsample->Cr_g_tab[i] = (-FIX(0.71414)) * x;
/* Cb=>G value is scaled-up -0.34414 * x */
/* We also add in ONE_HALF so that need not do it in inner loop */
- upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
+ upsample->Cb_g_tab[i] = (-FIX(0.34414)) * x + ONE_HALF;
}
}
*/
METHODDEF(void)
-start_pass_merged_upsample (j_decompress_ptr cinfo)
+start_pass_merged_upsample(j_decompress_ptr cinfo)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
/* Mark the spare buffer empty */
upsample->spare_full = FALSE;
*/
METHODDEF(void)
-merged_2v_upsample (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
- JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+merged_2v_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
/* 2:1 vertical sampling case: may need a spare row. */
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
JSAMPROW work_ptrs[2];
JDIMENSION num_rows; /* number of rows returned to caller */
JDIMENSION size = upsample->out_row_width;
if (cinfo->out_color_space == JCS_RGB565)
size = cinfo->output_width * 2;
- jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
- 1, size);
+ jcopy_sample_rows(&upsample->spare_row, 0, output_buf + *out_row_ctr, 0, 1,
+ size);
num_rows = 1;
upsample->spare_full = FALSE;
} else {
*out_row_ctr += num_rows;
upsample->rows_to_go -= num_rows;
/* When the buffer is emptied, declare this input row group consumed */
- if (! upsample->spare_full)
+ if (!upsample->spare_full)
(*in_row_group_ctr)++;
}
METHODDEF(void)
-merged_1v_upsample (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
- JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+merged_1v_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
/* 1:1 vertical sampling case: much easier, never need a spare row. */
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
/* Just do the upsampling. */
(*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr,
*/
METHODDEF(void)
-h2v1_merged_upsample (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v1_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
switch (cinfo->out_color_space) {
- case JCS_EXT_RGB:
- extrgb_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- extrgbx_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_BGR:
- extbgr_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- extbgrx_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- extxbgr_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- extxrgb_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- default:
- h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
+ case JCS_EXT_RGB:
+ extrgb_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ extrgbx_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_BGR:
+ extbgr_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ extbgrx_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ extxbgr_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ extxrgb_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ default:
+ h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
}
}
*/
METHODDEF(void)
-h2v2_merged_upsample (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v2_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
switch (cinfo->out_color_space) {
- case JCS_EXT_RGB:
- extrgb_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- extrgbx_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_BGR:
- extbgr_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- extbgrx_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- extxbgr_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- extxrgb_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- default:
- h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
+ case JCS_EXT_RGB:
+ extrgb_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ extrgbx_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_BGR:
+ extbgr_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ extbgrx_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ extxbgr_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ extxrgb_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ default:
+ h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
}
}
* RGB565 conversion
*/
-#define PACK_SHORT_565_LE(r, g, b) ((((r) << 8) & 0xF800) | \
- (((g) << 3) & 0x7E0) | ((b) >> 3))
-#define PACK_SHORT_565_BE(r, g, b) (((r) & 0xF8) | ((g) >> 5) | \
- (((g) << 11) & 0xE000) | \
- (((b) << 5) & 0x1F00))
+#define PACK_SHORT_565_LE(r, g, b) ((((r) << 8) & 0xF800) | \
+ (((g) << 3) & 0x7E0) | ((b) >> 3))
+#define PACK_SHORT_565_BE(r, g, b) (((r) & 0xF8) | ((g) >> 5) | \
+ (((g) << 11) & 0xE000) | \
+ (((b) << 5) & 0x1F00))
-#define PACK_TWO_PIXELS_LE(l, r) ((r << 16) | l)
-#define PACK_TWO_PIXELS_BE(l, r) ((l << 16) | r)
+#define PACK_TWO_PIXELS_LE(l, r) ((r << 16) | l)
+#define PACK_TWO_PIXELS_BE(l, r) ((l << 16) | r)
-#define PACK_NEED_ALIGNMENT(ptr) (((size_t)(ptr)) & 3)
+#define PACK_NEED_ALIGNMENT(ptr) (((size_t)(ptr)) & 3)
-#define WRITE_TWO_PIXELS_LE(addr, pixels) { \
- ((INT16*)(addr))[0] = (INT16)(pixels); \
- ((INT16*)(addr))[1] = (INT16)((pixels) >> 16); \
+#define WRITE_TWO_PIXELS_LE(addr, pixels) { \
+ ((INT16 *)(addr))[0] = (INT16)(pixels); \
+ ((INT16 *)(addr))[1] = (INT16)((pixels) >> 16); \
}
-#define WRITE_TWO_PIXELS_BE(addr, pixels) { \
- ((INT16*)(addr))[1] = (INT16)(pixels); \
- ((INT16*)(addr))[0] = (INT16)((pixels) >> 16); \
+#define WRITE_TWO_PIXELS_BE(addr, pixels) { \
+ ((INT16 *)(addr))[1] = (INT16)(pixels); \
+ ((INT16 *)(addr))[0] = (INT16)((pixels) >> 16); \
}
#define DITHER_565_R(r, dither) ((r) + ((dither) & 0xFF))
/* Declarations for ordered dithering
*
* We use a 4x4 ordered dither array packed into 32 bits. This array is
- * sufficent for dithering RGB888 to RGB565.
+ * sufficient for dithering RGB888 to RGB565.
*/
#define DITHER_MASK 0x3
/* Include inline routines for RGB565 conversion */
-#define PACK_SHORT_565 PACK_SHORT_565_LE
-#define PACK_TWO_PIXELS PACK_TWO_PIXELS_LE
-#define WRITE_TWO_PIXELS WRITE_TWO_PIXELS_LE
-#define h2v1_merged_upsample_565_internal h2v1_merged_upsample_565_le
-#define h2v1_merged_upsample_565D_internal h2v1_merged_upsample_565D_le
-#define h2v2_merged_upsample_565_internal h2v2_merged_upsample_565_le
-#define h2v2_merged_upsample_565D_internal h2v2_merged_upsample_565D_le
+#define PACK_SHORT_565 PACK_SHORT_565_LE
+#define PACK_TWO_PIXELS PACK_TWO_PIXELS_LE
+#define WRITE_TWO_PIXELS WRITE_TWO_PIXELS_LE
+#define h2v1_merged_upsample_565_internal h2v1_merged_upsample_565_le
+#define h2v1_merged_upsample_565D_internal h2v1_merged_upsample_565D_le
+#define h2v2_merged_upsample_565_internal h2v2_merged_upsample_565_le
+#define h2v2_merged_upsample_565D_internal h2v2_merged_upsample_565D_le
#include "jdmrg565.c"
#undef PACK_SHORT_565
#undef PACK_TWO_PIXELS
#undef h2v2_merged_upsample_565_internal
#undef h2v2_merged_upsample_565D_internal
-#define PACK_SHORT_565 PACK_SHORT_565_BE
-#define PACK_TWO_PIXELS PACK_TWO_PIXELS_BE
-#define WRITE_TWO_PIXELS WRITE_TWO_PIXELS_BE
-#define h2v1_merged_upsample_565_internal h2v1_merged_upsample_565_be
-#define h2v1_merged_upsample_565D_internal h2v1_merged_upsample_565D_be
-#define h2v2_merged_upsample_565_internal h2v2_merged_upsample_565_be
-#define h2v2_merged_upsample_565D_internal h2v2_merged_upsample_565D_be
+#define PACK_SHORT_565 PACK_SHORT_565_BE
+#define PACK_TWO_PIXELS PACK_TWO_PIXELS_BE
+#define WRITE_TWO_PIXELS WRITE_TWO_PIXELS_BE
+#define h2v1_merged_upsample_565_internal h2v1_merged_upsample_565_be
+#define h2v1_merged_upsample_565D_internal h2v1_merged_upsample_565D_be
+#define h2v2_merged_upsample_565_internal h2v2_merged_upsample_565_be
+#define h2v2_merged_upsample_565D_internal h2v2_merged_upsample_565D_be
#include "jdmrg565.c"
#undef PACK_SHORT_565
#undef PACK_TWO_PIXELS
METHODDEF(void)
-h2v1_merged_upsample_565 (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v1_merged_upsample_565(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
if (is_big_endian())
h2v1_merged_upsample_565_be(cinfo, input_buf, in_row_group_ctr,
else
h2v1_merged_upsample_565_le(cinfo, input_buf, in_row_group_ctr,
output_buf);
- }
+}
METHODDEF(void)
-h2v1_merged_upsample_565D (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v1_merged_upsample_565D(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
if (is_big_endian())
h2v1_merged_upsample_565D_be(cinfo, input_buf, in_row_group_ctr,
METHODDEF(void)
-h2v2_merged_upsample_565 (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v2_merged_upsample_565(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
if (is_big_endian())
h2v2_merged_upsample_565_be(cinfo, input_buf, in_row_group_ctr,
METHODDEF(void)
-h2v2_merged_upsample_565D (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v2_merged_upsample_565D(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
if (is_big_endian())
h2v2_merged_upsample_565D_be(cinfo, input_buf, in_row_group_ctr,
*/
GLOBAL(void)
-jinit_merged_upsampler (j_decompress_ptr cinfo)
+jinit_merged_upsampler(j_decompress_ptr cinfo)
{
my_upsample_ptr upsample;
upsample = (my_upsample_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_upsampler));
- cinfo->upsample = (struct jpeg_upsampler *) upsample;
+ cinfo->upsample = (struct jpeg_upsampler *)upsample;
upsample->pub.start_pass = start_pass_merged_upsample;
upsample->pub.need_context_rows = FALSE;
}
/* Allocate a spare row buffer */
upsample->spare_row = (JSAMPROW)
- (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (size_t) (upsample->out_row_width * sizeof(JSAMPLE)));
+ (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (size_t)(upsample->out_row_width * sizeof(JSAMPLE)));
} else {
upsample->pub.upsample = merged_1v_upsample;
if (jsimd_can_h2v1_merged_upsample())
* Copyright (C) 1994-1996, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2013, Linaro Limited.
- * Copyright (C) 2014-2015, D. R. Commander.
+ * Copyright (C) 2014-2015, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
INLINE
LOCAL(void)
-h2v1_merged_upsample_565_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr;
JSAMPROW inptr0, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- int * Crrtab = upsample->Cr_r_tab;
- int * Cbbtab = upsample->Cb_b_tab;
- JLONG * Crgtab = upsample->Cr_g_tab;
- JLONG * Cbgtab = upsample->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *Crrtab = upsample->Cr_r_tab;
+ int *Cbbtab = upsample->Cb_b_tab;
+ JLONG *Crgtab = upsample->Cr_g_tab;
+ JLONG *Cbgtab = upsample->Cb_g_tab;
unsigned int r, g, b;
JLONG rgb;
SHIFT_TEMPS
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 2 Y values and emit 2 pixels */
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr0);
r = range_limit[y + cred];
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
- }
- }
+ *(INT16 *)outptr = (INT16)rgb;
+ }
+}
INLINE
LOCAL(void)
-h2v1_merged_upsample_565D_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v1_merged_upsample_565D_internal(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr;
JSAMPROW inptr0, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- int * Crrtab = upsample->Cr_r_tab;
- int * Cbbtab = upsample->Cb_b_tab;
- JLONG * Crgtab = upsample->Cr_g_tab;
- JLONG * Cbgtab = upsample->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *Crrtab = upsample->Cr_r_tab;
+ int *Cbbtab = upsample->Cb_b_tab;
+ JLONG *Crgtab = upsample->Cr_g_tab;
+ JLONG *Cbgtab = upsample->Cb_g_tab;
JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
unsigned int r, g, b;
JLONG rgb;
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 2 Y values and emit 2 pixels */
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*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)];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
}
}
INLINE
LOCAL(void)
-h2v2_merged_upsample_565_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr0, outptr1;
JSAMPROW inptr00, inptr01, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- int * Crrtab = upsample->Cr_r_tab;
- int * Cbbtab = upsample->Cb_b_tab;
- JLONG * Crgtab = upsample->Cr_g_tab;
- JLONG * Cbgtab = upsample->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *Crrtab = upsample->Cr_r_tab;
+ int *Cbbtab = upsample->Cb_b_tab;
+ JLONG *Crgtab = upsample->Cr_g_tab;
+ JLONG *Cbgtab = upsample->Cb_g_tab;
unsigned int r, g, b;
JLONG rgb;
SHIFT_TEMPS
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 4 Y values and emit 4 pixels */
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr00);
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr0 = (INT16)rgb;
+ *(INT16 *)outptr0 = (INT16)rgb;
y = GETJSAMPLE(*inptr01);
r = range_limit[y + cred];
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr1 = (INT16)rgb;
+ *(INT16 *)outptr1 = (INT16)rgb;
}
}
INLINE
LOCAL(void)
-h2v2_merged_upsample_565D_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v2_merged_upsample_565D_internal(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr0, outptr1;
JSAMPROW inptr00, inptr01, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- int * Crrtab = upsample->Cr_r_tab;
- int * Cbbtab = upsample->Cb_b_tab;
- JLONG * Crgtab = upsample->Cr_g_tab;
- JLONG * Cbgtab = upsample->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *Crrtab = upsample->Cr_r_tab;
+ int *Cbbtab = upsample->Cb_b_tab;
+ JLONG *Crgtab = upsample->Cr_g_tab;
+ JLONG *Cbgtab = upsample->Cb_g_tab;
JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
- JLONG d1 = dither_matrix[(cinfo->output_scanline+1) & DITHER_MASK];
+ JLONG d1 = dither_matrix[(cinfo->output_scanline + 1) & DITHER_MASK];
unsigned int r, g, b;
JLONG rgb;
SHIFT_TEMPS
- inptr00 = input_buf[0][in_row_group_ctr*2];
- inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
+ inptr00 = input_buf[0][in_row_group_ctr * 2];
+ inptr01 = input_buf[0][in_row_group_ctr * 2 + 1];
inptr1 = input_buf[1][in_row_group_ctr];
inptr2 = input_buf[2][in_row_group_ctr];
outptr0 = output_buf[0];
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 4 Y values and emit 4 pixels */
rgb = PACK_SHORT_565(r, g, b);
y = GETJSAMPLE(*inptr00++);
- 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);
+ 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_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
WRITE_TWO_PIXELS(outptr0, rgb);
outptr0 += 4;
y = GETJSAMPLE(*inptr01++);
- 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);
+ 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++);
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr00);
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;
+ *(INT16 *)outptr0 = (INT16)rgb;
y = GETJSAMPLE(*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)];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr1 = (INT16)rgb;
+ *(INT16 *)outptr1 = (INT16)rgb;
}
}
INLINE
LOCAL(void)
-h2v1_merged_upsample_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr;
JSAMPROW inptr0, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- int * Crrtab = upsample->Cr_r_tab;
- int * Cbbtab = upsample->Cb_b_tab;
- JLONG * Crgtab = upsample->Cr_g_tab;
- JLONG * Cbgtab = upsample->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *Crrtab = upsample->Cr_r_tab;
+ int *Cbbtab = upsample->Cb_b_tab;
+ JLONG *Crgtab = upsample->Cr_g_tab;
+ JLONG *Cbgtab = upsample->Cb_g_tab;
SHIFT_TEMPS
inptr0 = input_buf[0][in_row_group_ctr];
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 2 Y values and emit 2 pixels */
y = GETJSAMPLE(*inptr0++);
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr0);
outptr[RGB_RED] = range_limit[y + cred];
INLINE
LOCAL(void)
-h2v2_merged_upsample_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr0, outptr1;
JSAMPROW inptr00, inptr01, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- int * Crrtab = upsample->Cr_r_tab;
- int * Cbbtab = upsample->Cb_b_tab;
- JLONG * Crgtab = upsample->Cr_g_tab;
- JLONG * Cbgtab = upsample->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *Crrtab = upsample->Cr_r_tab;
+ int *Cbbtab = upsample->Cb_b_tab;
+ JLONG *Crgtab = upsample->Cr_g_tab;
+ JLONG *Cbgtab = upsample->Cb_g_tab;
SHIFT_TEMPS
- inptr00 = input_buf[0][in_row_group_ctr*2];
- inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
+ inptr00 = input_buf[0][in_row_group_ctr * 2];
+ inptr01 = input_buf[0][in_row_group_ctr * 2 + 1];
inptr1 = input_buf[1][in_row_group_ctr];
inptr2 = input_buf[2][in_row_group_ctr];
outptr0 = output_buf[0];
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 4 Y values and emit 4 pixels */
y = GETJSAMPLE(*inptr00++);
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr00);
outptr0[RGB_RED] = range_limit[y + cred];
* 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, D. R. Commander.
+ * Copyright (C) 2015-2016, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
* up to the start of the current MCU. To do this, we copy state variables
* into local working storage, and update them back to the permanent
* storage only upon successful completion of an MCU.
+ *
+ * NOTE: All referenced figures are from
+ * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdhuff.h" /* Declarations shared with jdhuff.c */
+#include <limits.h>
#ifdef D_PROGRESSIVE_SUPPORTED
*/
#ifndef NO_STRUCT_ASSIGN
-#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#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])
+#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 phuff_entropy_decoder *phuff_entropy_ptr;
/* Forward declarations */
-METHODDEF(boolean) decode_mcu_DC_first (j_decompress_ptr cinfo,
+METHODDEF(boolean) decode_mcu_DC_first(j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data);
+METHODDEF(boolean) decode_mcu_AC_first(j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data);
+METHODDEF(boolean) decode_mcu_DC_refine(j_decompress_ptr cinfo,
JBLOCKROW *MCU_data);
-METHODDEF(boolean) decode_mcu_AC_first (j_decompress_ptr cinfo,
+METHODDEF(boolean) decode_mcu_AC_refine(j_decompress_ptr cinfo,
JBLOCKROW *MCU_data);
-METHODDEF(boolean) decode_mcu_DC_refine (j_decompress_ptr cinfo,
- JBLOCKROW *MCU_data);
-METHODDEF(boolean) decode_mcu_AC_refine (j_decompress_ptr cinfo,
- JBLOCKROW *MCU_data);
/*
*/
METHODDEF(void)
-start_pass_phuff_decoder (j_decompress_ptr cinfo)
+start_pass_phuff_decoder(j_decompress_ptr cinfo)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
boolean is_DC_band, bad;
int ci, coefi, tbl;
d_derived_tbl **pdtbl;
}
if (cinfo->Ah != 0) {
/* Successive approximation refinement scan: must have Al = Ah-1. */
- if (cinfo->Al != cinfo->Ah-1)
+ if (cinfo->Al != cinfo->Ah - 1)
bad = TRUE;
}
if (cinfo->Al > 13) /* need not check for < 0 */
*/
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];
+ coef_bit_ptr = &cinfo->coef_bits[cindex][0];
if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
#define AVOID_TABLES
#ifdef AVOID_TABLES
-#define NEG_1 ((unsigned)-1)
-#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((NEG_1)<<(s)) + 1) : (x))
+#define NEG_1 ((unsigned)-1)
+#define HUFF_EXTEND(x, s) \
+ ((x) < (1 << ((s) - 1)) ? (x) + (((NEG_1) << (s)) + 1) : (x))
#else
-#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
+#define HUFF_EXTEND(x, s) \
+ ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
-static const int extend_test[16] = /* entry n is 2**(n-1) */
- { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
- 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
+static const int extend_test[16] = { /* entry n is 2**(n-1) */
+ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+ 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000
+};
-static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
- { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
- ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
- ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
- ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+static const int extend_offset[16] = { /* entry n is (-1 << n) + 1 */
+ 0, ((-1) << 1) + 1, ((-1) << 2) + 1, ((-1) << 3) + 1, ((-1) << 4) + 1,
+ ((-1) << 5) + 1, ((-1) << 6) + 1, ((-1) << 7) + 1, ((-1) << 8) + 1,
+ ((-1) << 9) + 1, ((-1) << 10) + 1, ((-1) << 11) + 1, ((-1) << 12) + 1,
+ ((-1) << 13) + 1, ((-1) << 14) + 1, ((-1) << 15) + 1
+};
#endif /* AVOID_TABLES */
*/
LOCAL(boolean)
-process_restart (j_decompress_ptr cinfo)
+process_restart(j_decompress_ptr cinfo)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
int ci;
/* Throw away any unused bits remaining in bit buffer; */
entropy->bitstate.bits_left = 0;
/* Advance past the RSTn marker */
- if (! (*cinfo->marker->read_restart_marker) (cinfo))
+ if (!(*cinfo->marker->read_restart_marker) (cinfo))
return FALSE;
/* Re-initialize DC predictions to 0 */
*/
METHODDEF(boolean)
-decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_DC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
int Al = cinfo->Al;
register int s, r;
int blkn, ci;
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
- if (! process_restart(cinfo))
+ if (!process_restart(cinfo))
return FALSE;
}
/* If we've run out of data, just leave the MCU set to zeroes.
* This way, we return uniform gray for the remainder of the segment.
*/
- if (! entropy->pub.insufficient_data) {
+ if (!entropy->pub.insufficient_data) {
/* Load up working state */
- BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(state, entropy->saved);
/* Outer loop handles each block in the MCU */
}
/* Convert DC difference to actual value, update last_dc_val */
+ if ((state.last_dc_val[ci] >= 0 &&
+ s > INT_MAX - state.last_dc_val[ci]) ||
+ (state.last_dc_val[ci] < 0 && s < INT_MIN - state.last_dc_val[ci]))
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF);
s += state.last_dc_val[ci];
state.last_dc_val[ci] = s;
/* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */
- (*block)[0] = (JCOEF) LEFT_SHIFT(s, Al);
+ (*block)[0] = (JCOEF)LEFT_SHIFT(s, Al);
}
/* Completed MCU, so update state */
- BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(entropy->saved, state);
}
*/
METHODDEF(boolean)
-decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_AC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
int Se = cinfo->Se;
int Al = cinfo->Al;
register int s, k, r;
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
- if (! process_restart(cinfo))
+ if (!process_restart(cinfo))
return FALSE;
}
/* If we've run out of data, just leave the MCU set to zeroes.
* This way, we return uniform gray for the remainder of the segment.
*/
- if (! entropy->pub.insufficient_data) {
+ if (!entropy->pub.insufficient_data) {
/* Load up working state.
* We can avoid loading/saving bitread state if in an EOB run.
if (EOBRUN > 0) /* if it's a band of zeroes... */
EOBRUN--; /* ...process it now (we do nothing) */
else {
- BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
block = MCU_data[0];
tbl = entropy->ac_derived_tbl;
r = GET_BITS(s);
s = HUFF_EXTEND(r, s);
/* Scale and output coefficient in natural (dezigzagged) order */
- (*block)[jpeg_natural_order[k]] = (JCOEF) LEFT_SHIFT(s, Al);
+ (*block)[jpeg_natural_order[k]] = (JCOEF)LEFT_SHIFT(s, Al);
} else {
if (r == 15) { /* ZRL */
k += 15; /* skip 15 zeroes in band */
}
}
- BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
}
/* Completed MCU, so update state */
*/
METHODDEF(boolean)
-decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_DC_refine(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
int blkn;
JBLOCKROW block;
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
- if (! process_restart(cinfo))
+ if (!process_restart(cinfo))
return FALSE;
}
*/
/* Load up working state */
- BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
/* Outer loop handles each block in the MCU */
}
/* Completed MCU, so update state */
- BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
/* Account for restart interval (no-op if not using restarts) */
entropy->restarts_to_go--;
*/
METHODDEF(boolean)
-decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_AC_refine(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
int Se = cinfo->Se;
int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
int m1 = (NEG_1) << cinfo->Al; /* -1 in the bit position being coded */
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
- if (! process_restart(cinfo))
+ if (!process_restart(cinfo))
return FALSE;
}
/* If we've run out of data, don't modify the MCU.
*/
- if (! entropy->pub.insufficient_data) {
+ if (!entropy->pub.insufficient_data) {
/* Load up working state */
- BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */
/* There is always only one block per MCU */
if (s) {
int pos = jpeg_natural_order[k];
/* Output newly nonzero coefficient */
- (*block)[pos] = (JCOEF) s;
+ (*block)[pos] = (JCOEF)s;
/* Remember its position in case we have to suspend */
newnz_pos[num_newnz++] = pos;
}
}
/* Completed MCU, so update state */
- BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */
}
*/
GLOBAL(void)
-jinit_phuff_decoder (j_decompress_ptr cinfo)
+jinit_phuff_decoder(j_decompress_ptr cinfo)
{
phuff_entropy_ptr entropy;
int *coef_bit_ptr;
int ci, i;
entropy = (phuff_entropy_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(phuff_entropy_decoder));
- cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
+ cinfo->entropy = (struct jpeg_entropy_decoder *)entropy;
entropy->pub.start_pass = start_pass_phuff_decoder;
/* Mark derived tables unallocated */
/* Create progression status table */
cinfo->coef_bits = (int (*)[DCTSIZE2])
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- cinfo->num_components*DCTSIZE2*sizeof(int));
- coef_bit_ptr = & cinfo->coef_bits[0][0];
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ cinfo->num_components * DCTSIZE2 *
+ sizeof(int));
+ coef_bit_ptr = &cinfo->coef_bits[0][0];
for (ci = 0; ci < cinfo->num_components; ci++)
for (i = 0; i < DCTSIZE2; i++)
*coef_bit_ptr++ = -1;
/* Forward declarations */
-METHODDEF(void) post_process_1pass
- (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
- JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail);
+METHODDEF(void) post_process_1pass(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail);
#ifdef QUANT_2PASS_SUPPORTED
-METHODDEF(void) post_process_prepass
- (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
- JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail);
-METHODDEF(void) post_process_2pass
- (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
- JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail);
+METHODDEF(void) post_process_prepass(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail);
+METHODDEF(void) post_process_2pass(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail);
#endif
*/
METHODDEF(void)
-start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
+start_pass_dpost(j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
{
- my_post_ptr post = (my_post_ptr) cinfo->post;
+ my_post_ptr post = (my_post_ptr)cinfo->post;
switch (pass_mode) {
case JBUF_PASS_THRU:
*/
if (post->buffer == NULL) {
post->buffer = (*cinfo->mem->access_virt_sarray)
- ((j_common_ptr) cinfo, post->whole_image,
- (JDIMENSION) 0, post->strip_height, TRUE);
+ ((j_common_ptr)cinfo, post->whole_image,
+ (JDIMENSION)0, post->strip_height, TRUE);
}
} else {
/* For single-pass processing without color quantization,
*/
METHODDEF(void)
-post_process_1pass (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
- JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+post_process_1pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
{
- my_post_ptr post = (my_post_ptr) cinfo->post;
+ my_post_ptr post = (my_post_ptr)cinfo->post;
JDIMENSION num_rows, max_rows;
/* Fill the buffer, but not more than what we can dump out in one go. */
if (max_rows > post->strip_height)
max_rows = post->strip_height;
num_rows = 0;
- (*cinfo->upsample->upsample) (cinfo,
- input_buf, in_row_group_ctr, in_row_groups_avail,
- post->buffer, &num_rows, max_rows);
+ (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr,
+ in_row_groups_avail, post->buffer, &num_rows,
+ max_rows);
/* Quantize and emit data. */
- (*cinfo->cquantize->color_quantize) (cinfo,
- post->buffer, output_buf + *out_row_ctr, (int) num_rows);
+ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer,
+ output_buf + *out_row_ctr,
+ (int)num_rows);
*out_row_ctr += num_rows;
}
*/
METHODDEF(void)
-post_process_prepass (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
- JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+post_process_prepass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
{
- my_post_ptr post = (my_post_ptr) cinfo->post;
+ my_post_ptr post = (my_post_ptr)cinfo->post;
JDIMENSION old_next_row, num_rows;
/* Reposition virtual buffer if at start of strip. */
if (post->next_row == 0) {
post->buffer = (*cinfo->mem->access_virt_sarray)
- ((j_common_ptr) cinfo, post->whole_image,
+ ((j_common_ptr)cinfo, post->whole_image,
post->starting_row, post->strip_height, TRUE);
}
/* Upsample some data (up to a strip height's worth). */
old_next_row = post->next_row;
- (*cinfo->upsample->upsample) (cinfo,
- input_buf, in_row_group_ctr, in_row_groups_avail,
- post->buffer, &post->next_row, post->strip_height);
+ (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr,
+ in_row_groups_avail, post->buffer,
+ &post->next_row, post->strip_height);
/* Allow quantizer to scan new data. No data is emitted, */
/* but we advance out_row_ctr so outer loop can tell when we're done. */
if (post->next_row > old_next_row) {
num_rows = post->next_row - old_next_row;
(*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,
- (JSAMPARRAY) NULL, (int) num_rows);
+ (JSAMPARRAY)NULL, (int)num_rows);
*out_row_ctr += num_rows;
}
*/
METHODDEF(void)
-post_process_2pass (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
- JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+post_process_2pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
{
- my_post_ptr post = (my_post_ptr) cinfo->post;
+ my_post_ptr post = (my_post_ptr)cinfo->post;
JDIMENSION num_rows, max_rows;
/* Reposition virtual buffer if at start of strip. */
if (post->next_row == 0) {
post->buffer = (*cinfo->mem->access_virt_sarray)
- ((j_common_ptr) cinfo, post->whole_image,
+ ((j_common_ptr)cinfo, post->whole_image,
post->starting_row, post->strip_height, FALSE);
}
num_rows = max_rows;
/* Quantize and emit data. */
- (*cinfo->cquantize->color_quantize) (cinfo,
- post->buffer + post->next_row, output_buf + *out_row_ctr,
- (int) num_rows);
+ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + post->next_row,
+ output_buf + *out_row_ctr,
+ (int)num_rows);
*out_row_ctr += num_rows;
/* Advance if we filled the strip. */
*/
GLOBAL(void)
-jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
{
my_post_ptr post;
post = (my_post_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_post_controller));
- cinfo->post = (struct jpeg_d_post_controller *) post;
+ cinfo->post = (struct jpeg_d_post_controller *)post;
post->pub.start_pass = start_pass_dpost;
post->whole_image = NULL; /* flag for no virtual arrays */
post->buffer = NULL; /* flag for no strip buffer */
* an efficient number of rows for upsampling to return.
* (In the presence of output rescaling, we might want to be smarter?)
*/
- post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor;
+ post->strip_height = (JDIMENSION)cinfo->max_v_samp_factor;
if (need_full_buffer) {
/* Two-pass color quantization: need full-image storage. */
/* We round up the number of rows to a multiple of the strip height. */
#ifdef QUANT_2PASS_SUPPORTED
post->whole_image = (*cinfo->mem->request_virt_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE,
cinfo->output_width * cinfo->out_color_components,
- (JDIMENSION) jround_up((long) cinfo->output_height,
- (long) post->strip_height),
+ (JDIMENSION)jround_up((long)cinfo->output_height,
+ (long)post->strip_height),
post->strip_height);
#else
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
} else {
/* One-pass color quantization: just make a strip buffer. */
post->buffer = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
cinfo->output_width * cinfo->out_color_components,
post->strip_height);
}
*/
METHODDEF(void)
-start_pass_upsample (j_decompress_ptr cinfo)
+start_pass_upsample(j_decompress_ptr cinfo)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
/* Mark the conversion buffer empty */
upsample->next_row_out = cinfo->max_v_samp_factor;
*/
METHODDEF(void)
-sep_upsample (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
- JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+sep_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
int ci;
jpeg_component_info *compptr;
JDIMENSION num_rows;
/* Color-convert and emit rows */
/* How many we have in the buffer: */
- num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out);
+ num_rows = (JDIMENSION)(cinfo->max_v_samp_factor - upsample->next_row_out);
/* Not more than the distance to the end of the image. Need this test
* in case the image height is not a multiple of max_v_samp_factor:
*/
num_rows = out_rows_avail;
(*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf,
- (JDIMENSION) upsample->next_row_out,
- output_buf + *out_row_ctr,
- (int) num_rows);
+ (JDIMENSION)upsample->next_row_out,
+ output_buf + *out_row_ctr, (int)num_rows);
/* Adjust counts */
*out_row_ctr += num_rows;
*/
METHODDEF(void)
-fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+fullsize_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
*output_data_ptr = input_data;
}
*/
METHODDEF(void)
-noop_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+noop_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
*output_data_ptr = NULL; /* safety check */
}
*/
METHODDEF(void)
-int_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
register JSAMPLE invalue;
}
/* Generate any additional output rows by duplicating the first one */
if (v_expand > 1) {
- jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
- v_expand-1, cinfo->output_width);
+ jcopy_sample_rows(output_data, outrow, output_data, outrow + 1,
+ v_expand - 1, cinfo->output_width);
}
inrow++;
outrow += v_expand;
*/
METHODDEF(void)
-h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
*/
METHODDEF(void)
-h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
*outptr++ = invalue;
*outptr++ = invalue;
}
- jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
- 1, cinfo->output_width);
+ jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, 1,
+ cinfo->output_width);
inrow++;
outrow += 2;
}
*/
METHODDEF(void)
-h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
outptr = output_data[inrow];
/* Special case for first column */
invalue = GETJSAMPLE(*inptr++);
- *outptr++ = (JSAMPLE) invalue;
- *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
+ *outptr++ = (JSAMPLE)invalue;
+ *outptr++ = (JSAMPLE)((invalue * 3 + GETJSAMPLE(*inptr) + 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);
+ *outptr++ = (JSAMPLE)((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
+ *outptr++ = (JSAMPLE)((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
}
/* Special case for last column */
invalue = GETJSAMPLE(*inptr);
- *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
- *outptr++ = (JSAMPLE) invalue;
+ *outptr++ = (JSAMPLE)((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
+ *outptr++ = (JSAMPLE)invalue;
}
}
*/
METHODDEF(void)
-h1v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
JSAMPROW inptr0, inptr1, outptr;
/* inptr0 points to nearest input row, inptr1 points to next nearest */
inptr0 = input_data[inrow];
if (v == 0) /* next nearest is row above */
- inptr1 = input_data[inrow-1];
+ inptr1 = input_data[inrow - 1];
else /* next nearest is row below */
- inptr1 = input_data[inrow+1];
+ inptr1 = input_data[inrow + 1];
outptr = output_data[outrow++];
- for(colctr = 0; colctr < compptr->downsampled_width; colctr++) {
+ for (colctr = 0; colctr < compptr->downsampled_width; colctr++) {
thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
- *outptr++ = (JSAMPLE) ((thiscolsum + 1) >> 2);
+ *outptr++ = (JSAMPLE)((thiscolsum + 1) >> 2);
}
}
inrow++;
*/
METHODDEF(void)
-h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr0, inptr1, outptr;
/* inptr0 points to nearest input row, inptr1 points to next nearest */
inptr0 = input_data[inrow];
if (v == 0) /* next nearest is row above */
- inptr1 = input_data[inrow-1];
+ inptr1 = input_data[inrow - 1];
else /* next nearest is row below */
- inptr1 = input_data[inrow+1];
+ inptr1 = input_data[inrow + 1];
outptr = output_data[outrow++];
/* Special case for first column */
thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
- *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4);
- *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
- lastcolsum = thiscolsum; thiscolsum = nextcolsum;
+ *outptr++ = (JSAMPLE)((thiscolsum * 4 + 8) >> 4);
+ *outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4);
+ lastcolsum = thiscolsum; thiscolsum = nextcolsum;
for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
/* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
/* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
- *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
- *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
- lastcolsum = thiscolsum; thiscolsum = nextcolsum;
+ *outptr++ = (JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4);
+ *outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4);
+ lastcolsum = thiscolsum; thiscolsum = nextcolsum;
}
/* Special case for last column */
- *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
- *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4);
+ *outptr++ = (JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4);
+ *outptr++ = (JSAMPLE)((thiscolsum * 4 + 7) >> 4);
}
inrow++;
}
*/
GLOBAL(void)
-jinit_upsampler (j_decompress_ptr cinfo)
+jinit_upsampler(j_decompress_ptr cinfo)
{
my_upsample_ptr upsample;
int ci;
if (!cinfo->master->jinit_upsampler_no_alloc) {
upsample = (my_upsample_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_upsampler));
- cinfo->upsample = (struct jpeg_upsampler *) upsample;
+ cinfo->upsample = (struct jpeg_upsampler *)upsample;
upsample->pub.start_pass = start_pass_upsample;
upsample->pub.upsample = sep_upsample;
upsample->pub.need_context_rows = FALSE; /* until we find out differently */
} else
- upsample = (my_upsample_ptr) cinfo->upsample;
+ upsample = (my_upsample_ptr)cinfo->upsample;
if (cinfo->CCIR601_sampling) /* this isn't supported */
ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
v_out_group = cinfo->max_v_samp_factor;
upsample->rowgroup_height[ci] = v_in_group; /* save for use later */
need_buffer = TRUE;
- if (! compptr->component_needed) {
+ if (!compptr->component_needed) {
/* Don't bother to upsample an uninteresting component. */
upsample->methods[ci] = noop_upsample;
need_buffer = FALSE;
/* Fullsize components can be processed without any work. */
upsample->methods[ci] = fullsize_upsample;
need_buffer = FALSE;
- } else if (h_in_group * 2 == h_out_group &&
- v_in_group == v_out_group) {
+ } else if (h_in_group * 2 == h_out_group && v_in_group == v_out_group) {
/* Special cases for 2h1v upsampling */
if (do_fancy && compptr->downsampled_width > 2) {
if (jsimd_can_h2v1_fancy_upsample())
else
#endif
upsample->methods[ci] = int_upsample;
- upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group);
- upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group);
+ upsample->h_expand[ci] = (UINT8)(h_out_group / h_in_group);
+ upsample->v_expand[ci] = (UINT8)(v_out_group / v_in_group);
} else
ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
if (need_buffer && !cinfo->master->jinit_upsampler_no_alloc) {
upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (JDIMENSION) jround_up((long) cinfo->output_width,
- (long) cinfo->max_h_samp_factor),
- (JDIMENSION) cinfo->max_v_samp_factor);
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (JDIMENSION)jround_up((long)cinfo->output_width,
+ (long)cinfo->max_h_samp_factor),
+ (JDIMENSION)cinfo->max_v_samp_factor);
}
}
}
/* Forward declarations */
-LOCAL(void) transdecode_master_selection (j_decompress_ptr cinfo);
+LOCAL(void) transdecode_master_selection(j_decompress_ptr cinfo);
/*
*/
GLOBAL(jvirt_barray_ptr *)
-jpeg_read_coefficients (j_decompress_ptr cinfo)
+jpeg_read_coefficients(j_decompress_ptr cinfo)
{
if (cinfo->global_state == DSTATE_READY) {
/* First call: initialize active modules */
int retcode;
/* Call progress monitor hook if present */
if (cinfo->progress != NULL)
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
/* Absorb some more input */
retcode = (*cinfo->inputctl->consume_input) (cinfo);
if (retcode == JPEG_SUSPENDED)
(retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
/* startup underestimated number of scans; ratchet up one scan */
- cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
+ cinfo->progress->pass_limit += (long)cinfo->total_iMCU_rows;
}
}
}
*/
LOCAL(void)
-transdecode_master_selection (j_decompress_ptr cinfo)
+transdecode_master_selection(j_decompress_ptr cinfo)
{
/* This is effectively a buffered-image operation. */
cinfo->buffered_image = TRUE;
jinit_d_coef_controller(cinfo, TRUE);
/* We can now tell the memory manager to allocate virtual arrays. */
- (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo);
/* Initialize input side of decompressor to consume first scan. */
(*cinfo->inputctl->start_input_pass) (cinfo);
nscans = 1;
}
cinfo->progress->pass_counter = 0L;
- cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
+ cinfo->progress->pass_limit = (long)cinfo->total_iMCU_rows * nscans;
cinfo->progress->completed_passes = 0;
cinfo->progress->total_passes = 1;
}
* want to refer to it directly.
*/
-#define JMESSAGE(code,string) string ,
+#define JMESSAGE(code, string) string,
const char * const jpeg_std_message_table[] = {
#include "jerror.h"
*/
METHODDEF(void)
-error_exit (j_common_ptr cinfo)
+error_exit(j_common_ptr cinfo)
{
/* Always display the message */
(*cinfo->err->output_message) (cinfo);
*/
METHODDEF(void)
-output_message (j_common_ptr cinfo)
+output_message(j_common_ptr cinfo)
{
char buffer[JMSG_LENGTH_MAX];
*/
METHODDEF(void)
-emit_message (j_common_ptr cinfo, int msg_level)
+emit_message(j_common_ptr cinfo, int msg_level)
{
struct jpeg_error_mgr *err = cinfo->err;
*/
METHODDEF(void)
-format_message (j_common_ptr cinfo, char *buffer)
+format_message(j_common_ptr cinfo, char *buffer)
{
struct jpeg_error_mgr *err = cinfo->err;
int msg_code = err->msg_code;
*/
METHODDEF(void)
-reset_error_mgr (j_common_ptr cinfo)
+reset_error_mgr(j_common_ptr cinfo)
{
cinfo->err->num_warnings = 0;
/* trace_level is not reset since it is an application-supplied parameter */
*/
GLOBAL(struct jpeg_error_mgr *)
-jpeg_std_error (struct jpeg_error_mgr *err)
+jpeg_std_error(struct jpeg_error_mgr *err)
{
err->error_exit = error_exit;
err->emit_message = emit_message;
/* Initialize message table pointers */
err->jpeg_message_table = jpeg_std_message_table;
- err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1;
+ err->last_jpeg_message = (int)JMSG_LASTMSGCODE - 1;
err->addon_message_table = NULL;
err->first_addon_message = 0; /* for safety */
* Copyright (C) 1994-1997, Thomas G. Lane.
* Modified 1997-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2014, D. R. Commander.
+ * Copyright (C) 2014, 2017, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
#define JMAKE_ENUM_LIST
#else
/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
-#define JMESSAGE(code,string)
+#define JMESSAGE(code, string)
#endif /* JERROR_H */
#endif /* JMESSAGE */
typedef enum {
-#define JMESSAGE(code,string) code ,
+#define JMESSAGE(code, string) code,
#endif /* JMAKE_ENUM_LIST */
/* For maintenance convenience, list is alphabetical by message code name */
#if JPEG_LIB_VERSION < 70
-JMESSAGE(JERR_ARITH_NOTIMPL,
- "Sorry, arithmetic coding is not implemented")
+JMESSAGE(JERR_ARITH_NOTIMPL, "Sorry, arithmetic coding is not implemented")
#endif
JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d")
JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
"Warning: thumbnail image size does not match data length %u")
-JMESSAGE(JTRC_JFIF_EXTENSION,
- "JFIF extension marker: type 0x%02x, length %u")
+JMESSAGE(JTRC_JFIF_EXTENSION, "JFIF extension marker: type 0x%02x, length %u")
JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
#endif
#endif
+JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker")
#ifdef JMAKE_ENUM_LIST
/* The first parameter is either type of cinfo pointer */
/* Fatal errors (print message and exit) */
-#define ERREXIT(cinfo,code) \
+#define ERREXIT(cinfo, code) \
((cinfo)->err->msg_code = (code), \
- (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
-#define ERREXIT1(cinfo,code,p1) \
+ (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
+#define ERREXIT1(cinfo, code, p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
- (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
-#define ERREXIT2(cinfo,code,p1,p2) \
+ (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
+#define ERREXIT2(cinfo, code, p1, p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
- (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
-#define ERREXIT3(cinfo,code,p1,p2,p3) \
+ (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
+#define ERREXIT3(cinfo, code, p1, p2, p3) \
((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->error_exit) ((j_common_ptr) (cinfo)))
-#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
+ (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
+#define ERREXIT4(cinfo, code, p1, p2, p3, p4) \
((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->error_exit) ((j_common_ptr) (cinfo)))
-#define ERREXITS(cinfo,code,str) \
+ (*(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), \
- (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+ (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
#define MAKESTMT(stuff) do { stuff } while (0)
/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
-#define WARNMS(cinfo,code) \
+#define WARNMS(cinfo, code) \
((cinfo)->err->msg_code = (code), \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
-#define WARNMS1(cinfo,code,p1) \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
+#define WARNMS1(cinfo, code, p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
-#define WARNMS2(cinfo,code,p1,p2) \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
+#define WARNMS2(cinfo, code, p1, p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
/* Informational/debugging messages */
-#define TRACEMS(cinfo,lvl,code) \
+#define TRACEMS(cinfo, lvl, code) \
((cinfo)->err->msg_code = (code), \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
-#define TRACEMS1(cinfo,lvl,code,p1) \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
+#define TRACEMS1(cinfo, lvl, code, p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
-#define TRACEMS2(cinfo,lvl,code,p1,p2) \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
+#define TRACEMS2(cinfo, lvl, code, p1, p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
-#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
- MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
- _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
+#define TRACEMS3(cinfo, lvl, code, p1, p2, p3) \
+ MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
(cinfo)->err->msg_code = (code); \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
-#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
- MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
- _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
+#define TRACEMS4(cinfo, lvl, code, p1, p2, p3, p4) \
+ MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
(cinfo)->err->msg_code = (code); \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
-#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \
- MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
- _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
+#define TRACEMS5(cinfo, lvl, code, p1, p2, p3, p4, p5) \
+ MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); \
(cinfo)->err->msg_code = (code); \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
-#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
- MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
- _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
- _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
+#define TRACEMS8(cinfo, lvl, code, p1, p2, p3, p4, p5, p6, p7, p8) \
+ MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
(cinfo)->err->msg_code = (code); \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
-#define TRACEMSS(cinfo,lvl,code,str) \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
+#define TRACEMSS(cinfo, lvl, code, str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
#endif /* JERROR_H */
*/
GLOBAL(void)
-jpeg_fdct_float (FAST_FLOAT *data)
+jpeg_fdct_float(FAST_FLOAT *data)
{
FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
/* Pass 1: process rows. */
dataptr = data;
- for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ for (ctr = DCTSIZE - 1; ctr >= 0; ctr--) {
tmp0 = dataptr[0] + dataptr[7];
tmp7 = dataptr[0] - dataptr[7];
tmp1 = dataptr[1] + dataptr[6];
dataptr[0] = tmp10 + tmp11; /* phase 3 */
dataptr[4] = tmp10 - tmp11;
- z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
+ z1 = (tmp12 + tmp13) * ((FAST_FLOAT)0.707106781); /* c4 */
dataptr[2] = tmp13 + z1; /* phase 5 */
dataptr[6] = tmp13 - z1;
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
- z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
- z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
- z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
- z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
+ z5 = (tmp10 - tmp12) * ((FAST_FLOAT)0.382683433); /* c6 */
+ z2 = ((FAST_FLOAT)0.541196100) * tmp10 + z5; /* c2-c6 */
+ z4 = ((FAST_FLOAT)1.306562965) * tmp12 + z5; /* c2+c6 */
+ z3 = tmp11 * ((FAST_FLOAT)0.707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
/* Pass 2: process columns. */
dataptr = data;
- for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
- tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
- tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
- tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
- tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
- tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
- tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
- tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
- tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+ for (ctr = DCTSIZE - 1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE * 0] + dataptr[DCTSIZE * 7];
+ tmp7 = dataptr[DCTSIZE * 0] - dataptr[DCTSIZE * 7];
+ tmp1 = dataptr[DCTSIZE * 1] + dataptr[DCTSIZE * 6];
+ tmp6 = dataptr[DCTSIZE * 1] - dataptr[DCTSIZE * 6];
+ tmp2 = dataptr[DCTSIZE * 2] + dataptr[DCTSIZE * 5];
+ tmp5 = dataptr[DCTSIZE * 2] - dataptr[DCTSIZE * 5];
+ tmp3 = dataptr[DCTSIZE * 3] + dataptr[DCTSIZE * 4];
+ tmp4 = dataptr[DCTSIZE * 3] - dataptr[DCTSIZE * 4];
/* Even part */
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
- dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
- dataptr[DCTSIZE*4] = tmp10 - tmp11;
+ dataptr[DCTSIZE * 0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[DCTSIZE * 4] = tmp10 - tmp11;
- z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
- dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
- dataptr[DCTSIZE*6] = tmp13 - z1;
+ z1 = (tmp12 + tmp13) * ((FAST_FLOAT)0.707106781); /* c4 */
+ dataptr[DCTSIZE * 2] = tmp13 + z1; /* phase 5 */
+ dataptr[DCTSIZE * 6] = tmp13 - z1;
/* Odd part */
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
- z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
- z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
- z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
- z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
+ z5 = (tmp10 - tmp12) * ((FAST_FLOAT)0.382683433); /* c6 */
+ z2 = ((FAST_FLOAT)0.541196100) * tmp10 + z5; /* c2-c6 */
+ z4 = ((FAST_FLOAT)1.306562965) * tmp12 + z5; /* c2+c6 */
+ z3 = tmp11 * ((FAST_FLOAT)0.707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
- dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
- dataptr[DCTSIZE*3] = z13 - z2;
- dataptr[DCTSIZE*1] = z11 + z4;
- dataptr[DCTSIZE*7] = z11 - z4;
+ dataptr[DCTSIZE * 5] = z13 + z2; /* phase 6 */
+ dataptr[DCTSIZE * 3] = z13 - z2;
+ dataptr[DCTSIZE * 1] = z11 + z4;
+ dataptr[DCTSIZE * 7] = z11 - z4;
dataptr++; /* advance pointer to next column */
}
*/
#if CONST_BITS == 8
-#define FIX_0_382683433 ((JLONG) 98) /* FIX(0.382683433) */
-#define FIX_0_541196100 ((JLONG) 139) /* FIX(0.541196100) */
-#define FIX_0_707106781 ((JLONG) 181) /* FIX(0.707106781) */
-#define FIX_1_306562965 ((JLONG) 334) /* FIX(1.306562965) */
+#define FIX_0_382683433 ((JLONG)98) /* FIX(0.382683433) */
+#define FIX_0_541196100 ((JLONG)139) /* FIX(0.541196100) */
+#define FIX_0_707106781 ((JLONG)181) /* FIX(0.707106781) */
+#define FIX_1_306562965 ((JLONG)334) /* FIX(1.306562965) */
#else
#define FIX_0_382683433 FIX(0.382683433)
#define FIX_0_541196100 FIX(0.541196100)
#ifndef USE_ACCURATE_ROUNDING
#undef DESCALE
-#define DESCALE(x,n) RIGHT_SHIFT(x, n)
+#define DESCALE(x, n) RIGHT_SHIFT(x, n)
#endif
* descale to yield a DCTELEM result.
*/
-#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
+#define MULTIPLY(var, const) ((DCTELEM)DESCALE((var) * (const), CONST_BITS))
/*
*/
GLOBAL(void)
-jpeg_fdct_ifast (DCTELEM *data)
+jpeg_fdct_ifast(DCTELEM *data)
{
DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
DCTELEM tmp10, tmp11, tmp12, tmp13;
/* Pass 1: process rows. */
dataptr = data;
- for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ for (ctr = DCTSIZE - 1; ctr >= 0; ctr--) {
tmp0 = dataptr[0] + dataptr[7];
tmp7 = dataptr[0] - dataptr[7];
tmp1 = dataptr[1] + dataptr[6];
/* Pass 2: process columns. */
dataptr = data;
- for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
- tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
- tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
- tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
- tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
- tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
- tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
- tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
- tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+ for (ctr = DCTSIZE - 1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE * 0] + dataptr[DCTSIZE * 7];
+ tmp7 = dataptr[DCTSIZE * 0] - dataptr[DCTSIZE * 7];
+ tmp1 = dataptr[DCTSIZE * 1] + dataptr[DCTSIZE * 6];
+ tmp6 = dataptr[DCTSIZE * 1] - dataptr[DCTSIZE * 6];
+ tmp2 = dataptr[DCTSIZE * 2] + dataptr[DCTSIZE * 5];
+ tmp5 = dataptr[DCTSIZE * 2] - dataptr[DCTSIZE * 5];
+ tmp3 = dataptr[DCTSIZE * 3] + dataptr[DCTSIZE * 4];
+ tmp4 = dataptr[DCTSIZE * 3] - dataptr[DCTSIZE * 4];
/* Even part */
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
- dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
- dataptr[DCTSIZE*4] = tmp10 - tmp11;
+ dataptr[DCTSIZE * 0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[DCTSIZE * 4] = tmp10 - tmp11;
z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
- dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
- dataptr[DCTSIZE*6] = tmp13 - z1;
+ dataptr[DCTSIZE * 2] = tmp13 + z1; /* phase 5 */
+ dataptr[DCTSIZE * 6] = tmp13 - z1;
/* Odd part */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
- dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
- dataptr[DCTSIZE*3] = z13 - z2;
- dataptr[DCTSIZE*1] = z11 + z4;
- dataptr[DCTSIZE*7] = z11 - z4;
+ dataptr[DCTSIZE * 5] = z13 + z2; /* phase 6 */
+ dataptr[DCTSIZE * 3] = z13 - z2;
+ dataptr[DCTSIZE * 1] = z11 + z4;
+ dataptr[DCTSIZE * 7] = z11 - z4;
dataptr++; /* advance pointer to next column */
}
*/
#if CONST_BITS == 13
-#define FIX_0_298631336 ((JLONG) 2446) /* FIX(0.298631336) */
-#define FIX_0_390180644 ((JLONG) 3196) /* FIX(0.390180644) */
-#define FIX_0_541196100 ((JLONG) 4433) /* FIX(0.541196100) */
-#define FIX_0_765366865 ((JLONG) 6270) /* FIX(0.765366865) */
-#define FIX_0_899976223 ((JLONG) 7373) /* FIX(0.899976223) */
-#define FIX_1_175875602 ((JLONG) 9633) /* FIX(1.175875602) */
-#define FIX_1_501321110 ((JLONG) 12299) /* FIX(1.501321110) */
-#define FIX_1_847759065 ((JLONG) 15137) /* FIX(1.847759065) */
-#define FIX_1_961570560 ((JLONG) 16069) /* FIX(1.961570560) */
-#define FIX_2_053119869 ((JLONG) 16819) /* FIX(2.053119869) */
-#define FIX_2_562915447 ((JLONG) 20995) /* FIX(2.562915447) */
-#define FIX_3_072711026 ((JLONG) 25172) /* FIX(3.072711026) */
+#define FIX_0_298631336 ((JLONG)2446) /* FIX(0.298631336) */
+#define FIX_0_390180644 ((JLONG)3196) /* FIX(0.390180644) */
+#define FIX_0_541196100 ((JLONG)4433) /* FIX(0.541196100) */
+#define FIX_0_765366865 ((JLONG)6270) /* FIX(0.765366865) */
+#define FIX_0_899976223 ((JLONG)7373) /* FIX(0.899976223) */
+#define FIX_1_175875602 ((JLONG)9633) /* FIX(1.175875602) */
+#define FIX_1_501321110 ((JLONG)12299) /* FIX(1.501321110) */
+#define FIX_1_847759065 ((JLONG)15137) /* FIX(1.847759065) */
+#define FIX_1_961570560 ((JLONG)16069) /* FIX(1.961570560) */
+#define FIX_2_053119869 ((JLONG)16819) /* FIX(2.053119869) */
+#define FIX_2_562915447 ((JLONG)20995) /* FIX(2.562915447) */
+#define FIX_3_072711026 ((JLONG)25172) /* FIX(3.072711026) */
#else
#define FIX_0_298631336 FIX(0.298631336)
#define FIX_0_390180644 FIX(0.390180644)
*/
#if BITS_IN_JSAMPLE == 8
-#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
+#define MULTIPLY(var, const) MULTIPLY16C16(var, const)
#else
-#define MULTIPLY(var,const) ((var) * (const))
+#define MULTIPLY(var, const) ((var) * (const))
#endif
*/
GLOBAL(void)
-jpeg_fdct_islow (DCTELEM *data)
+jpeg_fdct_islow(DCTELEM *data)
{
JLONG tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
JLONG tmp10, tmp11, tmp12, tmp13;
/* furthermore, we scale the results by 2**PASS1_BITS. */
dataptr = data;
- for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ for (ctr = DCTSIZE - 1; ctr >= 0; ctr--) {
tmp0 = dataptr[0] + dataptr[7];
tmp7 = dataptr[0] - dataptr[7];
tmp1 = dataptr[1] + dataptr[6];
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
- dataptr[0] = (DCTELEM) LEFT_SHIFT(tmp10 + tmp11, PASS1_BITS);
- dataptr[4] = (DCTELEM) LEFT_SHIFT(tmp10 - tmp11, PASS1_BITS);
+ dataptr[0] = (DCTELEM)LEFT_SHIFT(tmp10 + tmp11, PASS1_BITS);
+ dataptr[4] = (DCTELEM)LEFT_SHIFT(tmp10 - tmp11, PASS1_BITS);
z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
- dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
- CONST_BITS-PASS1_BITS);
- dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
- CONST_BITS-PASS1_BITS);
+ dataptr[2] = (DCTELEM)DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+ CONST_BITS - PASS1_BITS);
+ dataptr[6] = (DCTELEM)DESCALE(z1 + MULTIPLY(tmp12, -FIX_1_847759065),
+ CONST_BITS - PASS1_BITS);
/* Odd part per figure 8 --- note paper omits factor of sqrt(2).
* cK represents cos(K*pi/16).
tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
- z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
- z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
- z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
- z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z1 = MULTIPLY(z1, -FIX_0_899976223); /* sqrt(2) * ( c7-c3) */
+ z2 = MULTIPLY(z2, -FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, -FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, -FIX_0_390180644); /* sqrt(2) * ( c5-c3) */
z3 += z5;
z4 += z5;
- dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS);
- dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS);
- dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS);
- dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (DCTELEM)DESCALE(tmp4 + z1 + z3, CONST_BITS - PASS1_BITS);
+ dataptr[5] = (DCTELEM)DESCALE(tmp5 + z2 + z4, CONST_BITS - PASS1_BITS);
+ dataptr[3] = (DCTELEM)DESCALE(tmp6 + z2 + z3, CONST_BITS - PASS1_BITS);
+ dataptr[1] = (DCTELEM)DESCALE(tmp7 + z1 + z4, CONST_BITS - PASS1_BITS);
dataptr += DCTSIZE; /* advance pointer to next row */
}
*/
dataptr = data;
- for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
- tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
- tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
- tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
- tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
- tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
- tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
- tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
- tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+ for (ctr = DCTSIZE - 1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE * 0] + dataptr[DCTSIZE * 7];
+ tmp7 = dataptr[DCTSIZE * 0] - dataptr[DCTSIZE * 7];
+ tmp1 = dataptr[DCTSIZE * 1] + dataptr[DCTSIZE * 6];
+ tmp6 = dataptr[DCTSIZE * 1] - dataptr[DCTSIZE * 6];
+ tmp2 = dataptr[DCTSIZE * 2] + dataptr[DCTSIZE * 5];
+ tmp5 = dataptr[DCTSIZE * 2] - dataptr[DCTSIZE * 5];
+ tmp3 = dataptr[DCTSIZE * 3] + dataptr[DCTSIZE * 4];
+ tmp4 = dataptr[DCTSIZE * 3] - dataptr[DCTSIZE * 4];
/* Even part per LL&M figure 1 --- note that published figure is faulty;
* rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
- dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS);
- dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS);
+ dataptr[DCTSIZE * 0] = (DCTELEM)DESCALE(tmp10 + tmp11, PASS1_BITS);
+ dataptr[DCTSIZE * 4] = (DCTELEM)DESCALE(tmp10 - tmp11, PASS1_BITS);
z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
- dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
- CONST_BITS+PASS1_BITS);
- dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
- CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE * 2] =
+ (DCTELEM)DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+ CONST_BITS + PASS1_BITS);
+ dataptr[DCTSIZE * 6] =
+ (DCTELEM)DESCALE(z1 + MULTIPLY(tmp12, -FIX_1_847759065),
+ CONST_BITS + PASS1_BITS);
/* Odd part per figure 8 --- note paper omits factor of sqrt(2).
* cK represents cos(K*pi/16).
tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
- z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
- z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
- z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
- z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z1 = MULTIPLY(z1, -FIX_0_899976223); /* sqrt(2) * ( c7-c3) */
+ z2 = MULTIPLY(z2, -FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, -FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, -FIX_0_390180644); /* sqrt(2) * ( c5-c3) */
z3 += z5;
z4 += z5;
- dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3,
- CONST_BITS+PASS1_BITS);
- dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4,
- CONST_BITS+PASS1_BITS);
- dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3,
- CONST_BITS+PASS1_BITS);
- dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4,
- CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE * 7] = (DCTELEM)DESCALE(tmp4 + z1 + z3,
+ CONST_BITS + PASS1_BITS);
+ dataptr[DCTSIZE * 5] = (DCTELEM)DESCALE(tmp5 + z2 + z4,
+ CONST_BITS + PASS1_BITS);
+ dataptr[DCTSIZE * 3] = (DCTELEM)DESCALE(tmp6 + z2 + z3,
+ CONST_BITS + PASS1_BITS);
+ dataptr[DCTSIZE * 1] = (DCTELEM)DESCALE(tmp7 + z1 + z4,
+ CONST_BITS + PASS1_BITS);
dataptr++; /* advance pointer to next column */
}
* entry; produce a float result.
*/
-#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval))
+#define DEQUANTIZE(coef, quantval) (((FAST_FLOAT)(coef)) * (quantval))
/*
*/
GLOBAL(void)
-jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
JSAMPLE *range_limit = cinfo->sample_range_limit;
int ctr;
FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */
- #define _0_125 ((FLOAT_MULT_TYPE)0.125)
+#define _0_125 ((FLOAT_MULT_TYPE)0.125)
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table;
+ quantptr = (FLOAT_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; ctr--) {
/* Due to quantization, we will usually find that many of the input
* column DCT calculations can be simplified this way.
*/
- if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
- inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
- inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
- inptr[DCTSIZE*7] == 0) {
+ if (inptr[DCTSIZE * 1] == 0 && inptr[DCTSIZE * 2] == 0 &&
+ inptr[DCTSIZE * 3] == 0 && inptr[DCTSIZE * 4] == 0 &&
+ inptr[DCTSIZE * 5] == 0 && inptr[DCTSIZE * 6] == 0 &&
+ inptr[DCTSIZE * 7] == 0) {
/* AC terms all zero */
- FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0],
- quantptr[DCTSIZE*0] * _0_125);
-
- wsptr[DCTSIZE*0] = dcval;
- wsptr[DCTSIZE*1] = dcval;
- wsptr[DCTSIZE*2] = dcval;
- wsptr[DCTSIZE*3] = dcval;
- wsptr[DCTSIZE*4] = dcval;
- wsptr[DCTSIZE*5] = dcval;
- wsptr[DCTSIZE*6] = dcval;
- wsptr[DCTSIZE*7] = dcval;
+ FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE * 0],
+ quantptr[DCTSIZE * 0] * _0_125);
+
+ wsptr[DCTSIZE * 0] = dcval;
+ wsptr[DCTSIZE * 1] = dcval;
+ wsptr[DCTSIZE * 2] = dcval;
+ wsptr[DCTSIZE * 3] = dcval;
+ wsptr[DCTSIZE * 4] = dcval;
+ wsptr[DCTSIZE * 5] = dcval;
+ wsptr[DCTSIZE * 6] = dcval;
+ wsptr[DCTSIZE * 7] = dcval;
inptr++; /* advance pointers to next column */
quantptr++;
/* Even part */
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0] * _0_125);
- tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2] * _0_125);
- tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4] * _0_125);
- tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6] * _0_125);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0] * _0_125);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2] * _0_125);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4] * _0_125);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6] * _0_125);
tmp10 = tmp0 + tmp2; /* phase 3 */
tmp11 = tmp0 - tmp2;
tmp13 = tmp1 + tmp3; /* phases 5-3 */
- tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */
+ tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT)1.414213562) - tmp13; /* 2*c4 */
tmp0 = tmp10 + tmp13; /* phase 2 */
tmp3 = tmp10 - tmp13;
/* Odd part */
- tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1] * _0_125);
- tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3] * _0_125);
- tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5] * _0_125);
- tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7] * _0_125);
+ tmp4 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1] * _0_125);
+ tmp5 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3] * _0_125);
+ tmp6 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5] * _0_125);
+ tmp7 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7] * _0_125);
z13 = tmp6 + tmp5; /* phase 6 */
z10 = tmp6 - tmp5;
z12 = tmp4 - tmp7;
tmp7 = z11 + z13; /* phase 5 */
- tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */
+ tmp11 = (z11 - z13) * ((FAST_FLOAT)1.414213562); /* 2*c4 */
- z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
- tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */
- tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */
+ z5 = (z10 + z12) * ((FAST_FLOAT)1.847759065); /* 2*c2 */
+ tmp10 = z5 - z12 * ((FAST_FLOAT)1.082392200); /* 2*(c2-c6) */
+ tmp12 = z5 - z10 * ((FAST_FLOAT)2.613125930); /* 2*(c2+c6) */
tmp6 = tmp12 - tmp7; /* phase 2 */
tmp5 = tmp11 - tmp6;
tmp4 = tmp10 - tmp5;
- wsptr[DCTSIZE*0] = tmp0 + tmp7;
- wsptr[DCTSIZE*7] = tmp0 - tmp7;
- wsptr[DCTSIZE*1] = tmp1 + tmp6;
- wsptr[DCTSIZE*6] = tmp1 - tmp6;
- wsptr[DCTSIZE*2] = tmp2 + tmp5;
- wsptr[DCTSIZE*5] = tmp2 - tmp5;
- wsptr[DCTSIZE*3] = tmp3 + tmp4;
- wsptr[DCTSIZE*4] = tmp3 - tmp4;
+ wsptr[DCTSIZE * 0] = tmp0 + tmp7;
+ wsptr[DCTSIZE * 7] = tmp0 - tmp7;
+ wsptr[DCTSIZE * 1] = tmp1 + tmp6;
+ wsptr[DCTSIZE * 6] = tmp1 - tmp6;
+ wsptr[DCTSIZE * 2] = tmp2 + tmp5;
+ wsptr[DCTSIZE * 5] = tmp2 - tmp5;
+ wsptr[DCTSIZE * 3] = tmp3 + tmp4;
+ wsptr[DCTSIZE * 4] = tmp3 - tmp4;
inptr++; /* advance pointers to next column */
quantptr++;
/* Even part */
/* Apply signed->unsigned and prepare float->int conversion */
- z5 = wsptr[0] + ((FAST_FLOAT) CENTERJSAMPLE + (FAST_FLOAT) 0.5);
+ z5 = wsptr[0] + ((FAST_FLOAT)CENTERJSAMPLE + (FAST_FLOAT)0.5);
tmp10 = z5 + wsptr[4];
tmp11 = z5 - wsptr[4];
tmp13 = wsptr[2] + wsptr[6];
- tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13;
+ tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT)1.414213562) - tmp13;
tmp0 = tmp10 + tmp13;
tmp3 = tmp10 - tmp13;
z12 = wsptr[1] - wsptr[7];
tmp7 = z11 + z13;
- tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562);
+ tmp11 = (z11 - z13) * ((FAST_FLOAT)1.414213562);
- z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
- tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */
- tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */
+ z5 = (z10 + z12) * ((FAST_FLOAT)1.847759065); /* 2*c2 */
+ tmp10 = z5 - z12 * ((FAST_FLOAT)1.082392200); /* 2*(c2-c6) */
+ tmp12 = z5 - z10 * ((FAST_FLOAT)2.613125930); /* 2*(c2+c6) */
tmp6 = tmp12 - tmp7;
tmp5 = tmp11 - tmp6;
/* Final output stage: float->int conversion and range-limit */
- outptr[0] = range_limit[((int) (tmp0 + tmp7)) & RANGE_MASK];
- outptr[7] = range_limit[((int) (tmp0 - tmp7)) & RANGE_MASK];
- outptr[1] = range_limit[((int) (tmp1 + tmp6)) & RANGE_MASK];
- outptr[6] = range_limit[((int) (tmp1 - tmp6)) & RANGE_MASK];
- outptr[2] = range_limit[((int) (tmp2 + tmp5)) & RANGE_MASK];
- outptr[5] = range_limit[((int) (tmp2 - tmp5)) & RANGE_MASK];
- outptr[3] = range_limit[((int) (tmp3 + tmp4)) & RANGE_MASK];
- outptr[4] = range_limit[((int) (tmp3 - tmp4)) & RANGE_MASK];
+ outptr[0] = range_limit[((int)(tmp0 + tmp7)) & RANGE_MASK];
+ outptr[7] = range_limit[((int)(tmp0 - tmp7)) & RANGE_MASK];
+ outptr[1] = range_limit[((int)(tmp1 + tmp6)) & RANGE_MASK];
+ outptr[6] = range_limit[((int)(tmp1 - tmp6)) & RANGE_MASK];
+ outptr[2] = range_limit[((int)(tmp2 + tmp5)) & RANGE_MASK];
+ outptr[5] = range_limit[((int)(tmp2 - tmp5)) & RANGE_MASK];
+ outptr[3] = range_limit[((int)(tmp3 + tmp4)) & RANGE_MASK];
+ outptr[4] = range_limit[((int)(tmp3 - tmp4)) & RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
*/
#if CONST_BITS == 8
-#define FIX_1_082392200 ((JLONG) 277) /* FIX(1.082392200) */
-#define FIX_1_414213562 ((JLONG) 362) /* FIX(1.414213562) */
-#define FIX_1_847759065 ((JLONG) 473) /* FIX(1.847759065) */
-#define FIX_2_613125930 ((JLONG) 669) /* FIX(2.613125930) */
+#define FIX_1_082392200 ((JLONG)277) /* FIX(1.082392200) */
+#define FIX_1_414213562 ((JLONG)362) /* FIX(1.414213562) */
+#define FIX_1_847759065 ((JLONG)473) /* FIX(1.847759065) */
+#define FIX_2_613125930 ((JLONG)669) /* FIX(2.613125930) */
#else
#define FIX_1_082392200 FIX(1.082392200)
#define FIX_1_414213562 FIX(1.414213562)
#ifndef USE_ACCURATE_ROUNDING
#undef DESCALE
-#define DESCALE(x,n) RIGHT_SHIFT(x, n)
+#define DESCALE(x, n) RIGHT_SHIFT(x, n)
#endif
* descale to yield a DCTELEM result.
*/
-#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
+#define MULTIPLY(var, const) ((DCTELEM)DESCALE((var) * (const), CONST_BITS))
/* Dequantize a coefficient by multiplying it by the multiplier-table
*/
#if BITS_IN_JSAMPLE == 8
-#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval))
+#define DEQUANTIZE(coef, quantval) (((IFAST_MULT_TYPE)(coef)) * (quantval))
#else
-#define DEQUANTIZE(coef,quantval) \
- DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS)
+#define DEQUANTIZE(coef, quantval) \
+ DESCALE((coef) * (quantval), IFAST_SCALE_BITS - PASS1_BITS)
#endif
#else
#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */
#endif
-#define IRIGHT_SHIFT(x,shft) \
- ((ishift_temp = (x)) < 0 ? \
- (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \
- (ishift_temp >> (shft)))
+#define IRIGHT_SHIFT(x, shft) \
+ ((ishift_temp = (x)) < 0 ? \
+ (ishift_temp >> (shft)) | ((~((DCTELEM)0)) << (DCTELEMBITS - (shft))) : \
+ (ishift_temp >> (shft)))
#else
#define ISHIFT_TEMPS
-#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
+#define IRIGHT_SHIFT(x, shft) ((x) >> (shft))
#endif
#ifdef USE_ACCURATE_ROUNDING
-#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n))
+#define IDESCALE(x, n) ((int)IRIGHT_SHIFT((x) + (1 << ((n) - 1)), n))
#else
-#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n))
+#define IDESCALE(x, n) ((int)IRIGHT_SHIFT(x, n))
#endif
*/
GLOBAL(void)
-jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
DCTELEM tmp10, tmp11, tmp12, tmp13;
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (IFAST_MULT_TYPE *) compptr->dct_table;
+ quantptr = (IFAST_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; ctr--) {
/* Due to quantization, we will usually find that many of the input
* column DCT calculations can be simplified this way.
*/
- if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
- inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
- inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
- inptr[DCTSIZE*7] == 0) {
+ if (inptr[DCTSIZE * 1] == 0 && inptr[DCTSIZE * 2] == 0 &&
+ inptr[DCTSIZE * 3] == 0 && inptr[DCTSIZE * 4] == 0 &&
+ inptr[DCTSIZE * 5] == 0 && inptr[DCTSIZE * 6] == 0 &&
+ inptr[DCTSIZE * 7] == 0) {
/* AC terms all zero */
- int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ int dcval = (int)DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
- wsptr[DCTSIZE*0] = dcval;
- wsptr[DCTSIZE*1] = dcval;
- wsptr[DCTSIZE*2] = dcval;
- wsptr[DCTSIZE*3] = dcval;
- wsptr[DCTSIZE*4] = dcval;
- wsptr[DCTSIZE*5] = dcval;
- wsptr[DCTSIZE*6] = dcval;
- wsptr[DCTSIZE*7] = dcval;
+ wsptr[DCTSIZE * 0] = dcval;
+ wsptr[DCTSIZE * 1] = dcval;
+ wsptr[DCTSIZE * 2] = dcval;
+ wsptr[DCTSIZE * 3] = dcval;
+ wsptr[DCTSIZE * 4] = dcval;
+ wsptr[DCTSIZE * 5] = dcval;
+ wsptr[DCTSIZE * 6] = dcval;
+ wsptr[DCTSIZE * 7] = dcval;
inptr++; /* advance pointers to next column */
quantptr++;
/* Even part */
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
- tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
- tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
tmp10 = tmp0 + tmp2; /* phase 3 */
tmp11 = tmp0 - tmp2;
/* Odd part */
- tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ tmp4 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ tmp5 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ tmp6 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ tmp7 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
z13 = tmp6 + tmp5; /* phase 6 */
z10 = tmp6 - tmp5;
z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
- tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
+ tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */
tmp6 = tmp12 - tmp7; /* phase 2 */
tmp5 = tmp11 - tmp6;
tmp4 = tmp10 + tmp5;
- wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7);
- wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7);
- wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6);
- wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6);
- wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5);
- wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5);
- wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4);
- wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4);
+ wsptr[DCTSIZE * 0] = (int)(tmp0 + tmp7);
+ wsptr[DCTSIZE * 7] = (int)(tmp0 - tmp7);
+ wsptr[DCTSIZE * 1] = (int)(tmp1 + tmp6);
+ wsptr[DCTSIZE * 6] = (int)(tmp1 - tmp6);
+ wsptr[DCTSIZE * 2] = (int)(tmp2 + tmp5);
+ wsptr[DCTSIZE * 5] = (int)(tmp2 - tmp5);
+ wsptr[DCTSIZE * 4] = (int)(tmp3 + tmp4);
+ wsptr[DCTSIZE * 3] = (int)(tmp3 - tmp4);
inptr++; /* advance pointers to next column */
quantptr++;
if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
/* AC terms all zero */
- JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3)
- & RANGE_MASK];
+ JSAMPLE dcval =
+ range_limit[IDESCALE(wsptr[0], PASS1_BITS + 3) & RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
/* Even part */
- tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]);
- tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]);
+ tmp10 = ((DCTELEM)wsptr[0] + (DCTELEM)wsptr[4]);
+ tmp11 = ((DCTELEM)wsptr[0] - (DCTELEM)wsptr[4]);
- tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]);
- tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562)
- - tmp13;
+ tmp13 = ((DCTELEM)wsptr[2] + (DCTELEM)wsptr[6]);
+ tmp12 =
+ MULTIPLY((DCTELEM)wsptr[2] - (DCTELEM)wsptr[6], FIX_1_414213562) - tmp13;
tmp0 = tmp10 + tmp13;
tmp3 = tmp10 - tmp13;
/* Odd part */
- z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3];
- z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3];
- z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7];
- z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7];
+ z13 = (DCTELEM)wsptr[5] + (DCTELEM)wsptr[3];
+ z10 = (DCTELEM)wsptr[5] - (DCTELEM)wsptr[3];
+ z11 = (DCTELEM)wsptr[1] + (DCTELEM)wsptr[7];
+ z12 = (DCTELEM)wsptr[1] - (DCTELEM)wsptr[7];
tmp7 = z11 + z13; /* phase 5 */
tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
- tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
+ tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */
tmp6 = tmp12 - tmp7; /* phase 2 */
tmp5 = tmp11 - tmp6;
/* Final output stage: scale down by a factor of 8 and range-limit */
- outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] =
+ range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS + 3) & RANGE_MASK];
+ outptr[7] =
+ range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS + 3) & RANGE_MASK];
+ outptr[1] =
+ range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS + 3) & RANGE_MASK];
+ outptr[6] =
+ range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS + 3) & RANGE_MASK];
+ outptr[2] =
+ range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS + 3) & RANGE_MASK];
+ outptr[5] =
+ range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS + 3) & RANGE_MASK];
+ outptr[4] =
+ range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS + 3) & RANGE_MASK];
+ outptr[3] =
+ range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS + 3) & RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
*/
#if CONST_BITS == 13
-#define FIX_0_298631336 ((JLONG) 2446) /* FIX(0.298631336) */
-#define FIX_0_390180644 ((JLONG) 3196) /* FIX(0.390180644) */
-#define FIX_0_541196100 ((JLONG) 4433) /* FIX(0.541196100) */
-#define FIX_0_765366865 ((JLONG) 6270) /* FIX(0.765366865) */
-#define FIX_0_899976223 ((JLONG) 7373) /* FIX(0.899976223) */
-#define FIX_1_175875602 ((JLONG) 9633) /* FIX(1.175875602) */
-#define FIX_1_501321110 ((JLONG) 12299) /* FIX(1.501321110) */
-#define FIX_1_847759065 ((JLONG) 15137) /* FIX(1.847759065) */
-#define FIX_1_961570560 ((JLONG) 16069) /* FIX(1.961570560) */
-#define FIX_2_053119869 ((JLONG) 16819) /* FIX(2.053119869) */
-#define FIX_2_562915447 ((JLONG) 20995) /* FIX(2.562915447) */
-#define FIX_3_072711026 ((JLONG) 25172) /* FIX(3.072711026) */
+#define FIX_0_298631336 ((JLONG)2446) /* FIX(0.298631336) */
+#define FIX_0_390180644 ((JLONG)3196) /* FIX(0.390180644) */
+#define FIX_0_541196100 ((JLONG)4433) /* FIX(0.541196100) */
+#define FIX_0_765366865 ((JLONG)6270) /* FIX(0.765366865) */
+#define FIX_0_899976223 ((JLONG)7373) /* FIX(0.899976223) */
+#define FIX_1_175875602 ((JLONG)9633) /* FIX(1.175875602) */
+#define FIX_1_501321110 ((JLONG)12299) /* FIX(1.501321110) */
+#define FIX_1_847759065 ((JLONG)15137) /* FIX(1.847759065) */
+#define FIX_1_961570560 ((JLONG)16069) /* FIX(1.961570560) */
+#define FIX_2_053119869 ((JLONG)16819) /* FIX(2.053119869) */
+#define FIX_2_562915447 ((JLONG)20995) /* FIX(2.562915447) */
+#define FIX_3_072711026 ((JLONG)25172) /* FIX(3.072711026) */
#else
#define FIX_0_298631336 FIX(0.298631336)
#define FIX_0_390180644 FIX(0.390180644)
*/
#if BITS_IN_JSAMPLE == 8
-#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
+#define MULTIPLY(var, const) MULTIPLY16C16(var, const)
#else
-#define MULTIPLY(var,const) ((var) * (const))
+#define MULTIPLY(var, const) ((var) * (const))
#endif
* are 16 bits or less, so either int or short multiply will work.
*/
-#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval))
+#define DEQUANTIZE(coef, quantval) (((ISLOW_MULT_TYPE)(coef)) * (quantval))
/*
*/
GLOBAL(void)
-jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp1, tmp2, tmp3;
JLONG tmp10, tmp11, tmp12, tmp13;
/* furthermore, we scale the results by 2**PASS1_BITS. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; ctr--) {
/* Due to quantization, we will usually find that many of the input
* column DCT calculations can be simplified this way.
*/
- if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
- inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
- inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
- inptr[DCTSIZE*7] == 0) {
+ if (inptr[DCTSIZE * 1] == 0 && inptr[DCTSIZE * 2] == 0 &&
+ inptr[DCTSIZE * 3] == 0 && inptr[DCTSIZE * 4] == 0 &&
+ inptr[DCTSIZE * 5] == 0 && inptr[DCTSIZE * 6] == 0 &&
+ inptr[DCTSIZE * 7] == 0) {
/* AC terms all zero */
- int dcval = LEFT_SHIFT(DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]),
- PASS1_BITS);
-
- wsptr[DCTSIZE*0] = dcval;
- wsptr[DCTSIZE*1] = dcval;
- wsptr[DCTSIZE*2] = dcval;
- wsptr[DCTSIZE*3] = dcval;
- wsptr[DCTSIZE*4] = dcval;
- wsptr[DCTSIZE*5] = dcval;
- wsptr[DCTSIZE*6] = dcval;
- wsptr[DCTSIZE*7] = dcval;
+ int dcval = LEFT_SHIFT(DEQUANTIZE(inptr[DCTSIZE * 0],
+ quantptr[DCTSIZE * 0]), PASS1_BITS);
+
+ wsptr[DCTSIZE * 0] = dcval;
+ wsptr[DCTSIZE * 1] = dcval;
+ wsptr[DCTSIZE * 2] = dcval;
+ wsptr[DCTSIZE * 3] = dcval;
+ wsptr[DCTSIZE * 4] = dcval;
+ wsptr[DCTSIZE * 5] = dcval;
+ wsptr[DCTSIZE * 6] = dcval;
+ wsptr[DCTSIZE * 7] = dcval;
inptr++; /* advance pointers to next column */
quantptr++;
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
- z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
- tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
+ tmp2 = z1 + MULTIPLY(z3, -FIX_1_847759065);
tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
- z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
tmp0 = LEFT_SHIFT(z2 + z3, CONST_BITS);
tmp1 = LEFT_SHIFT(z2 - z3, CONST_BITS);
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
- tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
- z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
- z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
- z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
- z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z1 = MULTIPLY(z1, -FIX_0_899976223); /* sqrt(2) * ( c7-c3) */
+ z2 = MULTIPLY(z2, -FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, -FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, -FIX_0_390180644); /* sqrt(2) * ( c5-c3) */
z3 += z5;
z4 += z5;
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
- wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
- wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
- wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
- wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
- wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
- wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
- wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
- wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE * 0] = (int)DESCALE(tmp10 + tmp3, CONST_BITS - PASS1_BITS);
+ wsptr[DCTSIZE * 7] = (int)DESCALE(tmp10 - tmp3, CONST_BITS - PASS1_BITS);
+ wsptr[DCTSIZE * 1] = (int)DESCALE(tmp11 + tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[DCTSIZE * 6] = (int)DESCALE(tmp11 - tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[DCTSIZE * 2] = (int)DESCALE(tmp12 + tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[DCTSIZE * 5] = (int)DESCALE(tmp12 - tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[DCTSIZE * 3] = (int)DESCALE(tmp13 + tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[DCTSIZE * 4] = (int)DESCALE(tmp13 - tmp0, CONST_BITS - PASS1_BITS);
inptr++; /* advance pointers to next column */
quantptr++;
if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
/* AC terms all zero */
- JSAMPLE dcval = range_limit[(int) DESCALE((JLONG) wsptr[0], PASS1_BITS+3)
- & RANGE_MASK];
+ JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0],
+ PASS1_BITS + 3) & RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
- z2 = (JLONG) wsptr[2];
- z3 = (JLONG) wsptr[6];
+ z2 = (JLONG)wsptr[2];
+ z3 = (JLONG)wsptr[6];
z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
- tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
+ tmp2 = z1 + MULTIPLY(z3, -FIX_1_847759065);
tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
- tmp0 = LEFT_SHIFT((JLONG) wsptr[0] + (JLONG) wsptr[4], CONST_BITS);
- tmp1 = LEFT_SHIFT((JLONG) wsptr[0] - (JLONG) wsptr[4], CONST_BITS);
+ tmp0 = LEFT_SHIFT((JLONG)wsptr[0] + (JLONG)wsptr[4], CONST_BITS);
+ tmp1 = LEFT_SHIFT((JLONG)wsptr[0] - (JLONG)wsptr[4], CONST_BITS);
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
- tmp0 = (JLONG) wsptr[7];
- tmp1 = (JLONG) wsptr[5];
- tmp2 = (JLONG) wsptr[3];
- tmp3 = (JLONG) wsptr[1];
+ tmp0 = (JLONG)wsptr[7];
+ tmp1 = (JLONG)wsptr[5];
+ tmp2 = (JLONG)wsptr[3];
+ tmp3 = (JLONG)wsptr[1];
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
- z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
- z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
- z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
- z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z1 = MULTIPLY(z1, -FIX_0_899976223); /* sqrt(2) * ( c7-c3) */
+ z2 = MULTIPLY(z2, -FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, -FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, -FIX_0_390180644); /* sqrt(2) * ( c5-c3) */
z3 += z5;
z4 += z5;
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
- outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)DESCALE(tmp10 + tmp3,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)DESCALE(tmp10 - tmp3,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)DESCALE(tmp11 + tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)DESCALE(tmp11 - tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)DESCALE(tmp12 + tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)DESCALE(tmp12 - tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)DESCALE(tmp13 + tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)DESCALE(tmp13 - tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
*/
GLOBAL(void)
-jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_7x7(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp1, tmp2, tmp10, tmp11, tmp12, tmp13;
JLONG z1, z2, z3;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[7*7]; /* buffers data between passes */
+ int workspace[7 * 7]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 7; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- tmp13 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp13 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
tmp13 = LEFT_SHIFT(tmp13, CONST_BITS);
/* Add fudge factor here for final descale. */
- tmp13 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp13 += ONE << (CONST_BITS - PASS1_BITS - 1);
- z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */
tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */
tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */
tmp0 = tmp1 - tmp2;
tmp1 += tmp2;
- tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */
+ tmp2 = MULTIPLY(z2 + z3, -FIX(1.378756276)); /* -c1 */
tmp1 += tmp2;
z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */
tmp0 += z2;
/* Final output stage */
- wsptr[7*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
- wsptr[7*6] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
- wsptr[7*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS);
- wsptr[7*5] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS);
- wsptr[7*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS);
- wsptr[7*4] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS);
- wsptr[7*3] = (int) RIGHT_SHIFT(tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[7 * 0] = (int)RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[7 * 6] = (int)RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[7 * 1] = (int)RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[7 * 5] = (int)RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[7 * 2] = (int)RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[7 * 4] = (int)RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[7 * 3] = (int)RIGHT_SHIFT(tmp13, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 7 rows from work array, store into output array. */
/* Even part */
/* Add fudge factor here for final descale. */
- tmp13 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp13 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
tmp13 = LEFT_SHIFT(tmp13, CONST_BITS);
- z1 = (JLONG) wsptr[2];
- z2 = (JLONG) wsptr[4];
- z3 = (JLONG) wsptr[6];
+ z1 = (JLONG)wsptr[2];
+ z2 = (JLONG)wsptr[4];
+ z3 = (JLONG)wsptr[6];
tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */
tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */
tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */
tmp0 = tmp1 - tmp2;
tmp1 += tmp2;
- tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */
+ tmp2 = MULTIPLY(z2 + z3, -FIX(1.378756276)); /* -c1 */
tmp1 += tmp2;
z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */
tmp0 += z2;
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp11 + tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp11 - tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp12 + tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp12 - tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 7; /* advance pointer to next row */
}
*/
GLOBAL(void)
-jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_6x6(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp1, tmp2, tmp10, tmp11, tmp12;
JLONG z1, z2, z3;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[6*6]; /* buffers data between passes */
+ int workspace[6 * 6]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
/* Add fudge factor here for final descale. */
- tmp0 += ONE << (CONST_BITS-PASS1_BITS-1);
- tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp0 += ONE << (CONST_BITS - PASS1_BITS - 1);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */
tmp1 = tmp0 + tmp10;
- tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS-PASS1_BITS);
- tmp10 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS - PASS1_BITS);
+ tmp10 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */
tmp10 = tmp1 + tmp0;
tmp12 = tmp1 - tmp0;
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */
tmp0 = tmp1 + LEFT_SHIFT(z1 + z2, CONST_BITS);
tmp2 = tmp1 + LEFT_SHIFT(z3 - z2, CONST_BITS);
/* Final output stage */
- wsptr[6*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
- wsptr[6*5] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
- wsptr[6*1] = (int) (tmp11 + tmp1);
- wsptr[6*4] = (int) (tmp11 - tmp1);
- wsptr[6*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS);
- wsptr[6*3] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[6 * 0] = (int)RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[6 * 5] = (int)RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[6 * 1] = (int)(tmp11 + tmp1);
+ wsptr[6 * 4] = (int)(tmp11 - tmp1);
+ wsptr[6 * 2] = (int)RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[6 * 3] = (int)RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 6 rows from work array, store into output array. */
/* Even part */
/* Add fudge factor here for final descale. */
- tmp0 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
- tmp2 = (JLONG) wsptr[4];
+ tmp2 = (JLONG)wsptr[4];
tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */
tmp1 = tmp0 + tmp10;
tmp11 = tmp0 - tmp10 - tmp10;
- tmp10 = (JLONG) wsptr[2];
+ tmp10 = (JLONG)wsptr[2];
tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */
tmp10 = tmp1 + tmp0;
tmp12 = tmp1 - tmp0;
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */
tmp0 = tmp1 + LEFT_SHIFT(z1 + z2, CONST_BITS);
tmp2 = tmp1 + LEFT_SHIFT(z3 - z2, CONST_BITS);
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp11 + tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp11 - tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp12 + tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp12 - tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 6; /* advance pointer to next row */
}
*/
GLOBAL(void)
-jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_5x5(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp1, tmp10, tmp11, tmp12;
JLONG z1, z2, z3;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[5*5]; /* buffers data between passes */
+ int workspace[5 * 5]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 5; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- tmp12 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp12 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
tmp12 = LEFT_SHIFT(tmp12, CONST_BITS);
/* Add fudge factor here for final descale. */
- tmp12 += ONE << (CONST_BITS-PASS1_BITS-1);
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- tmp1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp12 += ONE << (CONST_BITS - PASS1_BITS - 1);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */
z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */
z3 = tmp12 + z2;
/* Odd part */
- z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */
tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */
/* Final output stage */
- wsptr[5*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
- wsptr[5*4] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
- wsptr[5*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS);
- wsptr[5*3] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS);
- wsptr[5*2] = (int) RIGHT_SHIFT(tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[5 * 0] = (int)RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[5 * 4] = (int)RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[5 * 1] = (int)RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[5 * 3] = (int)RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[5 * 2] = (int)RIGHT_SHIFT(tmp12, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 5 rows from work array, store into output array. */
/* Even part */
/* Add fudge factor here for final descale. */
- tmp12 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp12 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
tmp12 = LEFT_SHIFT(tmp12, CONST_BITS);
- tmp0 = (JLONG) wsptr[2];
- tmp1 = (JLONG) wsptr[4];
+ tmp0 = (JLONG)wsptr[2];
+ tmp1 = (JLONG)wsptr[4];
z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */
z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */
z3 = tmp12 + z2;
/* Odd part */
- z2 = (JLONG) wsptr[1];
- z3 = (JLONG) wsptr[3];
+ z2 = (JLONG)wsptr[1];
+ z3 = (JLONG)wsptr[3];
z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */
tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp11 + tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp11 - tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 5; /* advance pointer to next row */
}
*/
GLOBAL(void)
-jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_3x3(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp2, tmp10, tmp12;
JCOEFPTR inptr;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[3*3]; /* buffers data between passes */
+ int workspace[3 * 3]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 3; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
/* Add fudge factor here for final descale. */
- tmp0 += ONE << (CONST_BITS-PASS1_BITS-1);
- tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp0 += ONE << (CONST_BITS - PASS1_BITS - 1);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */
tmp10 = tmp0 + tmp12;
tmp2 = tmp0 - tmp12 - tmp12;
/* Odd part */
- tmp12 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp12 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */
/* Final output stage */
- wsptr[3*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
- wsptr[3*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
- wsptr[3*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[3 * 0] = (int)RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[3 * 2] = (int)RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[3 * 1] = (int)RIGHT_SHIFT(tmp2, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 3 rows from work array, store into output array. */
/* Even part */
/* Add fudge factor here for final descale. */
- tmp0 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
- tmp2 = (JLONG) wsptr[2];
+ tmp2 = (JLONG)wsptr[2];
tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */
tmp10 = tmp0 + tmp12;
tmp2 = tmp0 - tmp12 - tmp12;
/* Odd part */
- tmp12 = (JLONG) wsptr[1];
+ tmp12 = (JLONG)wsptr[1];
tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 3; /* advance pointer to next row */
}
*/
GLOBAL(void)
-jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_9x9(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13, tmp14;
JLONG z1, z2, z3, z4;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*9]; /* buffers data between passes */
+ int workspace[8 * 9]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
/* Add fudge factor here for final descale. */
- tmp0 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp0 += ONE << (CONST_BITS - PASS1_BITS - 1);
- z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */
tmp1 = tmp0 + tmp3;
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
- z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */
+ z2 = MULTIPLY(z2, -FIX(1.224744871)); /* -c3 */
tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */
tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS);
- wsptr[8*7] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS);
- wsptr[8*3] = (int) RIGHT_SHIFT(tmp13 + tmp3, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp13 - tmp3, CONST_BITS-PASS1_BITS);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 7] = (int)RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 3] = (int)RIGHT_SHIFT(tmp13 + tmp3, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp13 - tmp3, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp14, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 9 rows from work array, store into output array. */
/* Even part */
/* Add fudge factor here for final descale. */
- tmp0 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
- z1 = (JLONG) wsptr[2];
- z2 = (JLONG) wsptr[4];
- z3 = (JLONG) wsptr[6];
+ z1 = (JLONG)wsptr[2];
+ z2 = (JLONG)wsptr[4];
+ z3 = (JLONG)wsptr[6];
tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */
tmp1 = tmp0 + tmp3;
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
- z4 = (JLONG) wsptr[7];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
+ z4 = (JLONG)wsptr[7];
- z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */
+ z2 = MULTIPLY(z2, -FIX(1.224744871)); /* -c3 */
tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */
tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp3,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp3,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp11 + tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp11 - tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp12 + tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp12 - tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp13 + tmp3,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp13 - tmp3,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
*/
GLOBAL(void)
-jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_10x10(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp10, tmp11, tmp12, tmp13, tmp14;
JLONG tmp20, tmp21, tmp22, tmp23, tmp24;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*10]; /* buffers data between passes */
+ int workspace[8 * 10]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
z3 = LEFT_SHIFT(z3, CONST_BITS);
/* Add fudge factor here for final descale. */
- z3 += ONE << (CONST_BITS-PASS1_BITS-1);
- z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z3 += ONE << (CONST_BITS - PASS1_BITS - 1);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */
z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */
tmp10 = z3 + z1;
tmp11 = z3 - z2;
tmp22 = RIGHT_SHIFT(z3 - LEFT_SHIFT(z1 - z2, 1),
- CONST_BITS-PASS1_BITS); /* c0 = (c4-c8)*2 */
+ CONST_BITS - PASS1_BITS); /* c0 = (c4-c8)*2 */
- z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */
tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
tmp11 = z2 + z4;
tmp13 = z2 - z4;
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*9] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) (tmp22 + tmp12);
- wsptr[8*7] = (int) (tmp22 - tmp12);
- wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 9] = (int)RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)(tmp22 + tmp12);
+ wsptr[8 * 7] = (int)(tmp22 - tmp12);
+ wsptr[8 * 3] = (int)RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 10 rows from work array, store into output array. */
/* Even part */
/* Add fudge factor here for final descale. */
- z3 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z3 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
z3 = LEFT_SHIFT(z3, CONST_BITS);
- z4 = (JLONG) wsptr[4];
+ z4 = (JLONG)wsptr[4];
z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */
z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */
tmp10 = z3 + z1;
tmp22 = z3 - LEFT_SHIFT(z1 - z2, 1); /* c0 = (c4-c8)*2 */
- z2 = (JLONG) wsptr[2];
- z3 = (JLONG) wsptr[6];
+ z2 = (JLONG)wsptr[2];
+ z3 = (JLONG)wsptr[6];
z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */
tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
z3 = LEFT_SHIFT(z3, CONST_BITS);
- z4 = (JLONG) wsptr[7];
+ z4 = (JLONG)wsptr[7];
tmp11 = z2 + z4;
tmp13 = z2 - z4;
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[9] = range_limit[(int)RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
*/
GLOBAL(void)
-jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_11x11(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp10, tmp11, tmp12, tmp13, tmp14;
JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*11]; /* buffers data between passes */
+ int workspace[8 * 11]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp10 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
tmp10 = LEFT_SHIFT(tmp10, CONST_BITS);
/* Add fudge factor here for final descale. */
- tmp10 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp10 += ONE << (CONST_BITS - PASS1_BITS - 1);
- z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */
tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */
z4 = z1 + z3;
- tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */
+ tmp24 = MULTIPLY(z4, -FIX(1.155664402)); /* -(c2-c10) */
z4 -= z2;
tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */
tmp21 = tmp20 + tmp23 + tmp25 -
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
tmp11 = z1 + z2;
tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */
z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */
tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */
tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */
- z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */
+ z1 = MULTIPLY(z2 + z4, -FIX(1.798248910)); /* -(c1+c9) */
tmp11 += z1;
tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */
- tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */
+ tmp14 += MULTIPLY(z2, -FIX(1.467221301)) + /* -(c5+c9) */
MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */
MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*10] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*9] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*7] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp25, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 10] = (int)RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 9] = (int)RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 3] = (int)RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 7] = (int)RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp25, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 11 rows from work array, store into output array. */
/* Even part */
/* Add fudge factor here for final descale. */
- tmp10 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp10 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
tmp10 = LEFT_SHIFT(tmp10, CONST_BITS);
- z1 = (JLONG) wsptr[2];
- z2 = (JLONG) wsptr[4];
- z3 = (JLONG) wsptr[6];
+ z1 = (JLONG)wsptr[2];
+ z2 = (JLONG)wsptr[4];
+ z3 = (JLONG)wsptr[6];
tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */
tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */
z4 = z1 + z3;
- tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */
+ tmp24 = MULTIPLY(z4, -FIX(1.155664402)); /* -(c2-c10) */
z4 -= z2;
tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */
tmp21 = tmp20 + tmp23 + tmp25 -
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
- z4 = (JLONG) wsptr[7];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
+ z4 = (JLONG)wsptr[7];
tmp11 = z1 + z2;
tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */
z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */
tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */
tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */
- z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */
+ z1 = MULTIPLY(z2 + z4, -FIX(1.798248910)); /* -(c1+c9) */
tmp11 += z1;
tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */
- tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */
+ tmp14 += MULTIPLY(z2, -FIX(1.467221301)) + /* -(c5+c9) */
MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */
MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[10] = range_limit[(int)RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[9] = range_limit[(int)RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp25,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
*/
GLOBAL(void)
-jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_12x12(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15;
JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*12]; /* buffers data between passes */
+ int workspace[8 * 12]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
z3 = LEFT_SHIFT(z3, CONST_BITS);
/* Add fudge factor here for final descale. */
- z3 += ONE << (CONST_BITS-PASS1_BITS-1);
+ z3 += ONE << (CONST_BITS - PASS1_BITS - 1);
- z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */
tmp10 = z3 + z4;
tmp11 = z3 - z4;
- z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */
z1 = LEFT_SHIFT(z1, CONST_BITS);
- z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
z2 = LEFT_SHIFT(z2, CONST_BITS);
tmp12 = z1 - z2;
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */
- tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */
+ tmp14 = MULTIPLY(z2, -FIX_0_541196100); /* -c9 */
tmp10 = z1 + z3;
tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */
tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */
tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */
- tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */
+ tmp13 = MULTIPLY(z3 + z4, -FIX(1.045510580)); /* -(c7+c11) */
tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */
tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */
tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*11] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*10] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*9] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*7] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 11] = (int)RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 10] = (int)RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 9] = (int)RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 3] = (int)RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 7] = (int)RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 12 rows from work array, store into output array. */
/* Even part */
/* Add fudge factor here for final descale. */
- z3 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z3 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
z3 = LEFT_SHIFT(z3, CONST_BITS);
- z4 = (JLONG) wsptr[4];
+ z4 = (JLONG)wsptr[4];
z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */
tmp10 = z3 + z4;
tmp11 = z3 - z4;
- z1 = (JLONG) wsptr[2];
+ z1 = (JLONG)wsptr[2];
z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */
z1 = LEFT_SHIFT(z1, CONST_BITS);
- z2 = (JLONG) wsptr[6];
+ z2 = (JLONG)wsptr[6];
z2 = LEFT_SHIFT(z2, CONST_BITS);
tmp12 = z1 - z2;
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
- z4 = (JLONG) wsptr[7];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
+ z4 = (JLONG)wsptr[7];
tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */
- tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */
+ tmp14 = MULTIPLY(z2, -FIX_0_541196100); /* -c9 */
tmp10 = z1 + z3;
tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */
tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */
tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */
- tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */
+ tmp13 = MULTIPLY(z3 + z4, -FIX(1.045510580)); /* -(c7+c11) */
tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */
tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */
tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[11] = range_limit[(int)RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[10] = range_limit[(int)RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[9] = range_limit[(int)RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp25 + tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp25 - tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
*/
GLOBAL(void)
-jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_13x13(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15;
JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*13]; /* buffers data between passes */
+ int workspace[8 * 13]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
z1 = LEFT_SHIFT(z1, CONST_BITS);
/* Add fudge factor here for final descale. */
- z1 += ONE << (CONST_BITS-PASS1_BITS-1);
+ z1 += ONE << (CONST_BITS - PASS1_BITS - 1);
- z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
tmp10 = z3 + z4;
tmp11 = z3 - z4;
tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */
tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */
- tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */
+ tmp25 = MULTIPLY(z2, -FIX(1.252223920)) + tmp12 + tmp13; /* c4 */
tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */
tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */
- tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */
- tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */
+ tmp23 = MULTIPLY(z2, -FIX(0.170464608)) - tmp12 - tmp13; /* c12 */
+ tmp24 = MULTIPLY(z2, -FIX(0.803364869)) + tmp12 - tmp13; /* c8 */
tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */
tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */
tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */
tmp10 = tmp11 + tmp12 + tmp13 -
MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */
- tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */
+ tmp14 = MULTIPLY(z2 + z3, -FIX(0.338443458)); /* -c11 */
tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */
tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */
- tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */
+ tmp14 = MULTIPLY(z2 + z4, -FIX(1.163874945)); /* -c5 */
tmp11 += tmp14;
tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */
- tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */
+ tmp14 = MULTIPLY(z3 + z4, -FIX(0.657217813)); /* -c9 */
tmp12 += tmp14;
tmp13 += tmp14;
tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*12] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*11] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*10] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*9] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS);
- wsptr[8*7] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp26, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 12] = (int)RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 11] = (int)RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 10] = (int)RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 3] = (int)RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 9] = (int)RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 7] = (int)RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp26, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 13 rows from work array, store into output array. */
/* Even part */
/* Add fudge factor here for final descale. */
- z1 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z1 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
z1 = LEFT_SHIFT(z1, CONST_BITS);
- z2 = (JLONG) wsptr[2];
- z3 = (JLONG) wsptr[4];
- z4 = (JLONG) wsptr[6];
+ z2 = (JLONG)wsptr[2];
+ z3 = (JLONG)wsptr[4];
+ z4 = (JLONG)wsptr[6];
tmp10 = z3 + z4;
tmp11 = z3 - z4;
tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */
tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */
- tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */
+ tmp25 = MULTIPLY(z2, -FIX(1.252223920)) + tmp12 + tmp13; /* c4 */
tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */
tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */
- tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */
- tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */
+ tmp23 = MULTIPLY(z2, -FIX(0.170464608)) - tmp12 - tmp13; /* c12 */
+ tmp24 = MULTIPLY(z2, -FIX(0.803364869)) + tmp12 - tmp13; /* c8 */
tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
- z4 = (JLONG) wsptr[7];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
+ z4 = (JLONG)wsptr[7];
tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */
tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */
tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */
tmp10 = tmp11 + tmp12 + tmp13 -
MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */
- tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */
+ tmp14 = MULTIPLY(z2 + z3, -FIX(0.338443458)); /* -c11 */
tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */
tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */
- tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */
+ tmp14 = MULTIPLY(z2 + z4, -FIX(1.163874945)); /* -c5 */
tmp11 += tmp14;
tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */
- tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */
+ tmp14 = MULTIPLY(z3 + z4, -FIX(0.657217813)); /* -c9 */
tmp12 += tmp14;
tmp13 += tmp14;
tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[12] = range_limit[(int)RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[11] = range_limit[(int)RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[10] = range_limit[(int)RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[9] = range_limit[(int)RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp25 + tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp25 - tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp26,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
*/
GLOBAL(void)
-jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_14x14(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16;
JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*14]; /* buffers data between passes */
+ int workspace[8 * 14]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
z1 = LEFT_SHIFT(z1, CONST_BITS);
/* Add fudge factor here for final descale. */
- z1 += ONE << (CONST_BITS-PASS1_BITS-1);
- z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z1 += ONE << (CONST_BITS - PASS1_BITS - 1);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */
z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */
z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */
tmp12 = z1 - z4;
tmp23 = RIGHT_SHIFT(z1 - LEFT_SHIFT(z2 + z3 - z4, 1),
- CONST_BITS-PASS1_BITS); /* c0 = (c4+c12-c8)*2 */
+ CONST_BITS - PASS1_BITS); /* c0 = (c4+c12-c8)*2 */
- z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
tmp13 = LEFT_SHIFT(z4, CONST_BITS);
tmp14 = z1 + z3;
tmp15 = MULTIPLY(z1, FIX(0.467085129)) - tmp13; /* c11 */
tmp16 += tmp15;
z1 += z4;
- z4 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - tmp13; /* -c13 */
+ z4 = MULTIPLY(z2 + z3, -FIX(0.158341681)) - tmp13; /* -c13 */
tmp11 += z4 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */
tmp12 += z4 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */
z4 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*13] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*12] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*11] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*3] = (int) (tmp23 + tmp13);
- wsptr[8*10] = (int) (tmp23 - tmp13);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*9] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS);
- wsptr[8*7] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 13] = (int)RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 12] = (int)RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 11] = (int)RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 3] = (int)(tmp23 + tmp13);
+ wsptr[8 * 10] = (int)(tmp23 - tmp13);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 9] = (int)RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 7] = (int)RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 14 rows from work array, store into output array. */
/* Even part */
/* Add fudge factor here for final descale. */
- z1 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z1 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
z1 = LEFT_SHIFT(z1, CONST_BITS);
- z4 = (JLONG) wsptr[4];
+ z4 = (JLONG)wsptr[4];
z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */
z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */
z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */
tmp23 = z1 - LEFT_SHIFT(z2 + z3 - z4, 1); /* c0 = (c4+c12-c8)*2 */
- z1 = (JLONG) wsptr[2];
- z2 = (JLONG) wsptr[6];
+ z1 = (JLONG)wsptr[2];
+ z2 = (JLONG)wsptr[6];
z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
- z4 = (JLONG) wsptr[7];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
+ z4 = (JLONG)wsptr[7];
z4 = LEFT_SHIFT(z4, CONST_BITS);
tmp14 = z1 + z3;
z1 -= z2;
tmp15 = MULTIPLY(z1, FIX(0.467085129)) - z4; /* c11 */
tmp16 += tmp15;
- tmp13 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - z4; /* -c13 */
+ tmp13 = MULTIPLY(z2 + z3, -FIX(0.158341681)) - z4; /* -c13 */
tmp11 += tmp13 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */
tmp12 += tmp13 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */
tmp13 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[13] = range_limit[(int)RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[12] = range_limit[(int)RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[11] = range_limit[(int)RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[10] = range_limit[(int)RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[9] = range_limit[(int)RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp25 + tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp25 - tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp26 + tmp16,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp26 - tmp16,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
*/
GLOBAL(void)
-jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_15x15(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16;
JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*15]; /* buffers data between passes */
+ int workspace[8 * 15]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
z1 = LEFT_SHIFT(z1, CONST_BITS);
/* Add fudge factor here for final descale. */
- z1 += ONE << (CONST_BITS-PASS1_BITS-1);
+ z1 += ONE << (CONST_BITS - PASS1_BITS - 1);
- z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */
tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
tmp13 = z2 - z4;
tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */
tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */
tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */
- tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */
- tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */
+ tmp13 = MULTIPLY(z2, -FIX(0.831253876)); /* -c9 */
+ tmp15 = MULTIPLY(z2, -FIX(1.344997024)); /* -c3 */
z2 = z1 - z4;
tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*14] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*13] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*12] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*11] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*10] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS);
- wsptr[8*9] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS);
- wsptr[8*7] = (int) RIGHT_SHIFT(tmp27, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 14] = (int)RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 13] = (int)RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 12] = (int)RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 3] = (int)RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 11] = (int)RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 10] = (int)RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 9] = (int)RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 7] = (int)RIGHT_SHIFT(tmp27, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 15 rows from work array, store into output array. */
/* Even part */
/* Add fudge factor here for final descale. */
- z1 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z1 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
z1 = LEFT_SHIFT(z1, CONST_BITS);
- z2 = (JLONG) wsptr[2];
- z3 = (JLONG) wsptr[4];
- z4 = (JLONG) wsptr[6];
+ z2 = (JLONG)wsptr[2];
+ z3 = (JLONG)wsptr[4];
+ z4 = (JLONG)wsptr[6];
tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */
tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z4 = (JLONG) wsptr[5];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z4 = (JLONG)wsptr[5];
z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */
- z4 = (JLONG) wsptr[7];
+ z4 = (JLONG)wsptr[7];
tmp13 = z2 - z4;
tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */
tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */
tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */
- tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */
- tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */
+ tmp13 = MULTIPLY(z2, -FIX(0.831253876)); /* -c9 */
+ tmp15 = MULTIPLY(z2, -FIX(1.344997024)); /* -c3 */
z2 = z1 - z4;
tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[14] = range_limit[(int)RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[13] = range_limit[(int)RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[12] = range_limit[(int)RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[11] = range_limit[(int)RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[10] = range_limit[(int)RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp25 + tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[9] = range_limit[(int)RIGHT_SHIFT(tmp25 - tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp26 + tmp16,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp26 - tmp16,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp27,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
*/
GLOBAL(void)
-jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_16x16(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13;
JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*16]; /* buffers data between passes */
+ int workspace[8 * 16]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ 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 += 1 << (CONST_BITS - PASS1_BITS - 1);
- z1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */
tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */
tmp12 = tmp0 + tmp2;
tmp13 = tmp0 - tmp2;
- z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
z3 = z1 - z2;
z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */
z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
tmp11 = z1 + z3;
tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */
tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */
z2 += z4;
- z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */
+ z1 = MULTIPLY(z2, -FIX(0.666655658)); /* -c11 */
tmp1 += z1;
tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */
- z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */
+ z2 = MULTIPLY(z2, -FIX(1.247225013)); /* -c5 */
tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */
tmp12 += z2;
- z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */
+ z2 = MULTIPLY(z3 + z4, -FIX(1.353318001)); /* -c3 */
tmp2 += z2;
tmp3 += z2;
z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS);
- wsptr[8*15] = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS);
- wsptr[8*14] = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS);
- wsptr[8*13] = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS);
- wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS);
- wsptr[8*12] = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*11] = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*10] = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*9] = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*7] = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 15] = (int)RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 14] = (int)RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 13] = (int)RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 3] = (int)RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 12] = (int)RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 11] = (int)RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 10] = (int)RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 9] = (int)RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 7] = (int)RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 16 rows from work array, store into output array. */
/* Even part */
/* Add fudge factor here for final descale. */
- tmp0 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
- z1 = (JLONG) wsptr[4];
+ z1 = (JLONG)wsptr[4];
tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */
tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */
tmp12 = tmp0 + tmp2;
tmp13 = tmp0 - tmp2;
- z1 = (JLONG) wsptr[2];
- z2 = (JLONG) wsptr[6];
+ z1 = (JLONG)wsptr[2];
+ z2 = (JLONG)wsptr[6];
z3 = z1 - z2;
z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */
z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
- z4 = (JLONG) wsptr[7];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
+ z4 = (JLONG)wsptr[7];
tmp11 = z1 + z3;
tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */
tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */
z2 += z4;
- z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */
+ z1 = MULTIPLY(z2, -FIX(0.666655658)); /* -c11 */
tmp1 += z1;
tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */
- z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */
+ z2 = MULTIPLY(z2, -FIX(1.247225013)); /* -c5 */
tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */
tmp12 += z2;
- z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */
+ z2 = MULTIPLY(z3 + z4, -FIX(1.353318001)); /* -c3 */
tmp2 += z2;
tmp3 += z2;
z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp20 + tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[15] = range_limit[(int)RIGHT_SHIFT(tmp20 - tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp21 + tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[14] = range_limit[(int)RIGHT_SHIFT(tmp21 - tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp22 + tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[13] = range_limit[(int)RIGHT_SHIFT(tmp22 - tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp23 + tmp3,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[12] = range_limit[(int)RIGHT_SHIFT(tmp23 - tmp3,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp24 + tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[11] = range_limit[(int)RIGHT_SHIFT(tmp24 - tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp25 + tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[10] = range_limit[(int)RIGHT_SHIFT(tmp25 - tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp26 + tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[9] = range_limit[(int)RIGHT_SHIFT(tmp26 - tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp27 + tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp27 - tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
*/
#if CONST_BITS == 13
-#define FIX_0_211164243 ((JLONG) 1730) /* FIX(0.211164243) */
-#define FIX_0_509795579 ((JLONG) 4176) /* FIX(0.509795579) */
-#define FIX_0_601344887 ((JLONG) 4926) /* FIX(0.601344887) */
-#define FIX_0_720959822 ((JLONG) 5906) /* FIX(0.720959822) */
-#define FIX_0_765366865 ((JLONG) 6270) /* FIX(0.765366865) */
-#define FIX_0_850430095 ((JLONG) 6967) /* FIX(0.850430095) */
-#define FIX_0_899976223 ((JLONG) 7373) /* FIX(0.899976223) */
-#define FIX_1_061594337 ((JLONG) 8697) /* FIX(1.061594337) */
-#define FIX_1_272758580 ((JLONG) 10426) /* FIX(1.272758580) */
-#define FIX_1_451774981 ((JLONG) 11893) /* FIX(1.451774981) */
-#define FIX_1_847759065 ((JLONG) 15137) /* FIX(1.847759065) */
-#define FIX_2_172734803 ((JLONG) 17799) /* FIX(2.172734803) */
-#define FIX_2_562915447 ((JLONG) 20995) /* FIX(2.562915447) */
-#define FIX_3_624509785 ((JLONG) 29692) /* FIX(3.624509785) */
+#define FIX_0_211164243 ((JLONG)1730) /* FIX(0.211164243) */
+#define FIX_0_509795579 ((JLONG)4176) /* FIX(0.509795579) */
+#define FIX_0_601344887 ((JLONG)4926) /* FIX(0.601344887) */
+#define FIX_0_720959822 ((JLONG)5906) /* FIX(0.720959822) */
+#define FIX_0_765366865 ((JLONG)6270) /* FIX(0.765366865) */
+#define FIX_0_850430095 ((JLONG)6967) /* FIX(0.850430095) */
+#define FIX_0_899976223 ((JLONG)7373) /* FIX(0.899976223) */
+#define FIX_1_061594337 ((JLONG)8697) /* FIX(1.061594337) */
+#define FIX_1_272758580 ((JLONG)10426) /* FIX(1.272758580) */
+#define FIX_1_451774981 ((JLONG)11893) /* FIX(1.451774981) */
+#define FIX_1_847759065 ((JLONG)15137) /* FIX(1.847759065) */
+#define FIX_2_172734803 ((JLONG)17799) /* FIX(2.172734803) */
+#define FIX_2_562915447 ((JLONG)20995) /* FIX(2.562915447) */
+#define FIX_3_624509785 ((JLONG)29692) /* FIX(3.624509785) */
#else
#define FIX_0_211164243 FIX(0.211164243)
#define FIX_0_509795579 FIX(0.509795579)
*/
#if BITS_IN_JSAMPLE == 8
-#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
+#define MULTIPLY(var, const) MULTIPLY16C16(var, const)
#else
-#define MULTIPLY(var,const) ((var) * (const))
+#define MULTIPLY(var, const) ((var) * (const))
#endif
* are 16 bits or less, so either int or short multiply will work.
*/
-#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval))
+#define DEQUANTIZE(coef, quantval) (((ISLOW_MULT_TYPE)(coef)) * (quantval))
/*
*/
GLOBAL(void)
-jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp2, tmp10, tmp12;
JLONG z1, z2, z3, z4;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[DCTSIZE*4]; /* buffers data between passes */
+ int workspace[DCTSIZE * 4]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
/* Don't bother to process column 4, because second pass won't use it */
- if (ctr == DCTSIZE-4)
+ if (ctr == DCTSIZE - 4)
continue;
- if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
- inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 &&
- inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) {
+ if (inptr[DCTSIZE * 1] == 0 && inptr[DCTSIZE * 2] == 0 &&
+ inptr[DCTSIZE * 3] == 0 && inptr[DCTSIZE * 5] == 0 &&
+ inptr[DCTSIZE * 6] == 0 && inptr[DCTSIZE * 7] == 0) {
/* AC terms all zero; we need not examine term 4 for 4x4 output */
- int dcval = LEFT_SHIFT(DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]),
- PASS1_BITS);
+ int dcval = LEFT_SHIFT(DEQUANTIZE(inptr[DCTSIZE * 0],
+ quantptr[DCTSIZE * 0]), PASS1_BITS);
- wsptr[DCTSIZE*0] = dcval;
- wsptr[DCTSIZE*1] = dcval;
- wsptr[DCTSIZE*2] = dcval;
- wsptr[DCTSIZE*3] = dcval;
+ wsptr[DCTSIZE * 0] = dcval;
+ wsptr[DCTSIZE * 1] = dcval;
+ wsptr[DCTSIZE * 2] = dcval;
+ wsptr[DCTSIZE * 3] = dcval;
continue;
}
/* Even part */
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
- tmp0 = LEFT_SHIFT(tmp0, CONST_BITS+1);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
+ tmp0 = LEFT_SHIFT(tmp0, CONST_BITS + 1);
- z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
- tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865);
+ tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, -FIX_0_765366865);
tmp10 = tmp0 + tmp2;
tmp12 = tmp0 - tmp2;
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
- tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
- + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
- + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
- + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
+ tmp0 = MULTIPLY(z1, -FIX_0_211164243) + /* sqrt(2) * ( c3-c1) */
+ MULTIPLY(z2, FIX_1_451774981) + /* sqrt(2) * ( c3+c7) */
+ MULTIPLY(z3, -FIX_2_172734803) + /* sqrt(2) * (-c1-c5) */
+ MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * ( c5+c7) */
- tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
- + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
- + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
- + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
+ tmp2 = MULTIPLY(z1, -FIX_0_509795579) + /* sqrt(2) * (c7-c5) */
+ MULTIPLY(z2, -FIX_0_601344887) + /* sqrt(2) * (c5-c1) */
+ MULTIPLY(z3, FIX_0_899976223) + /* sqrt(2) * (c3-c7) */
+ MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
/* Final output stage */
- wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1);
- wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1);
- wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1);
- wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1);
+ wsptr[DCTSIZE * 0] =
+ (int)DESCALE(tmp10 + tmp2, CONST_BITS - PASS1_BITS + 1);
+ wsptr[DCTSIZE * 3] =
+ (int)DESCALE(tmp10 - tmp2, CONST_BITS - PASS1_BITS + 1);
+ wsptr[DCTSIZE * 1] =
+ (int)DESCALE(tmp12 + tmp0, CONST_BITS - PASS1_BITS + 1);
+ wsptr[DCTSIZE * 2] =
+ (int)DESCALE(tmp12 - tmp0, CONST_BITS - PASS1_BITS + 1);
}
/* Pass 2: process 4 rows from work array, store into output array. */
if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 &&
wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
/* AC terms all zero */
- JSAMPLE dcval = range_limit[(int) DESCALE((JLONG) wsptr[0], PASS1_BITS+3)
- & RANGE_MASK];
+ JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0],
+ PASS1_BITS + 3) & RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
/* Even part */
- tmp0 = LEFT_SHIFT((JLONG) wsptr[0], CONST_BITS+1);
+ tmp0 = LEFT_SHIFT((JLONG)wsptr[0], CONST_BITS + 1);
- tmp2 = MULTIPLY((JLONG) wsptr[2], FIX_1_847759065)
- + MULTIPLY((JLONG) wsptr[6], - FIX_0_765366865);
+ tmp2 = MULTIPLY((JLONG)wsptr[2], FIX_1_847759065) +
+ MULTIPLY((JLONG)wsptr[6], -FIX_0_765366865);
tmp10 = tmp0 + tmp2;
tmp12 = tmp0 - tmp2;
/* Odd part */
- z1 = (JLONG) wsptr[7];
- z2 = (JLONG) wsptr[5];
- z3 = (JLONG) wsptr[3];
- z4 = (JLONG) wsptr[1];
+ z1 = (JLONG)wsptr[7];
+ z2 = (JLONG)wsptr[5];
+ z3 = (JLONG)wsptr[3];
+ z4 = (JLONG)wsptr[1];
- tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
- + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
- + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
- + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
+ tmp0 = MULTIPLY(z1, -FIX_0_211164243) + /* sqrt(2) * ( c3-c1) */
+ MULTIPLY(z2, FIX_1_451774981) + /* sqrt(2) * ( c3+c7) */
+ MULTIPLY(z3, -FIX_2_172734803) + /* sqrt(2) * (-c1-c5) */
+ MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * ( c5+c7) */
- tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
- + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
- + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
- + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
+ tmp2 = MULTIPLY(z1, -FIX_0_509795579) + /* sqrt(2) * (c7-c5) */
+ MULTIPLY(z2, -FIX_0_601344887) + /* sqrt(2) * (c5-c1) */
+ MULTIPLY(z3, FIX_0_899976223) + /* sqrt(2) * (c3-c7) */
+ MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
/* Final output stage */
- outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2,
- CONST_BITS+PASS1_BITS+3+1)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2,
- CONST_BITS+PASS1_BITS+3+1)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0,
- CONST_BITS+PASS1_BITS+3+1)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0,
- CONST_BITS+PASS1_BITS+3+1)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)DESCALE(tmp10 + tmp2,
+ CONST_BITS + PASS1_BITS + 3 + 1) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)DESCALE(tmp10 - tmp2,
+ CONST_BITS + PASS1_BITS + 3 + 1) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)DESCALE(tmp12 + tmp0,
+ CONST_BITS + PASS1_BITS + 3 + 1) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)DESCALE(tmp12 - tmp0,
+ CONST_BITS + PASS1_BITS + 3 + 1) &
+ RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
*/
GLOBAL(void)
-jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp10, z1;
JCOEFPTR inptr;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[DCTSIZE*2]; /* buffers data between passes */
+ int workspace[DCTSIZE * 2]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
/* Don't bother to process columns 2,4,6 */
- if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6)
+ if (ctr == DCTSIZE - 2 || ctr == DCTSIZE - 4 || ctr == DCTSIZE - 6)
continue;
- if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 &&
- inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) {
+ if (inptr[DCTSIZE * 1] == 0 && inptr[DCTSIZE * 3] == 0 &&
+ inptr[DCTSIZE * 5] == 0 && inptr[DCTSIZE * 7] == 0) {
/* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */
- int dcval = LEFT_SHIFT(DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]),
- PASS1_BITS);
+ int dcval = LEFT_SHIFT(DEQUANTIZE(inptr[DCTSIZE * 0],
+ quantptr[DCTSIZE * 0]), PASS1_BITS);
- wsptr[DCTSIZE*0] = dcval;
- wsptr[DCTSIZE*1] = dcval;
+ wsptr[DCTSIZE * 0] = dcval;
+ wsptr[DCTSIZE * 1] = dcval;
continue;
}
/* Even part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
- tmp10 = LEFT_SHIFT(z1, CONST_BITS+2);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
+ tmp10 = LEFT_SHIFT(z1, CONST_BITS + 2);
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
- tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */
- z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */
- z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
+ tmp0 = MULTIPLY(z1, -FIX_0_720959822); /* sqrt(2) * ( c7-c5+c3-c1) */
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ tmp0 += MULTIPLY(z1, -FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * ( c1+c3+c5+c7) */
/* Final output stage */
- wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2);
- wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2);
+ wsptr[DCTSIZE * 0] =
+ (int)DESCALE(tmp10 + tmp0, CONST_BITS - PASS1_BITS + 2);
+ wsptr[DCTSIZE * 1] =
+ (int)DESCALE(tmp10 - tmp0, CONST_BITS - PASS1_BITS + 2);
}
/* Pass 2: process 2 rows from work array, store into output array. */
#ifndef NO_ZERO_ROW_TEST
if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) {
/* AC terms all zero */
- JSAMPLE dcval = range_limit[(int) DESCALE((JLONG) wsptr[0], PASS1_BITS+3)
- & RANGE_MASK];
+ JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0],
+ PASS1_BITS + 3) & RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
/* Even part */
- tmp10 = LEFT_SHIFT((JLONG) wsptr[0], CONST_BITS+2);
+ tmp10 = LEFT_SHIFT((JLONG)wsptr[0], CONST_BITS + 2);
/* Odd part */
- tmp0 = MULTIPLY((JLONG) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */
- + MULTIPLY((JLONG) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */
- + MULTIPLY((JLONG) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */
- + MULTIPLY((JLONG) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
+ tmp0 = MULTIPLY((JLONG)wsptr[7], -FIX_0_720959822) + /* sqrt(2) * ( c7-c5+c3-c1) */
+ MULTIPLY((JLONG)wsptr[5], FIX_0_850430095) + /* sqrt(2) * (-c1+c3+c5+c7) */
+ MULTIPLY((JLONG)wsptr[3], -FIX_1_272758580) + /* sqrt(2) * (-c1+c3-c5-c7) */
+ MULTIPLY((JLONG)wsptr[1], FIX_3_624509785); /* sqrt(2) * ( c1+c3+c5+c7) */
/* Final output stage */
- outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0,
- CONST_BITS+PASS1_BITS+3+2)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0,
- CONST_BITS+PASS1_BITS+3+2)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)DESCALE(tmp10 + tmp0,
+ CONST_BITS + PASS1_BITS + 3 + 2) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)DESCALE(tmp10 - tmp0,
+ CONST_BITS + PASS1_BITS + 3 + 2) &
+ RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
*/
GLOBAL(void)
-jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_1x1(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
int dcval;
ISLOW_MULT_TYPE *quantptr;
/* We hardly need an inverse DCT routine for this: just take the
* average pixel value, which is one-eighth of the DC coefficient.
*/
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
dcval = DEQUANTIZE(coef_block[0], quantptr[0]);
- dcval = (int) DESCALE((JLONG) dcval, 3);
+ dcval = (int)DESCALE((JLONG)dcval, 3);
output_buf[0][output_col] = range_limit[dcval & RANGE_MASK];
}
#ifdef NEED_BSD_STRINGS
#include <strings.h>
-#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size))
-#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size))
+#define MEMZERO(target, size) \
+ bzero((void *)(target), (size_t)(size))
+#define MEMCOPY(dest, src, size) \
+ bcopy((const void *)(src), (void *)(dest), (size_t)(size))
#else /* not BSD, assume ANSI/SysV string lib */
#include <string.h>
-#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
-#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
+#define MEMZERO(target, size) \
+ memset((void *)(target), 0, (size_t)(size))
+#define MEMCOPY(dest, src, size) \
+ memcpy((void *)(dest), (const void *)(src), (size_t)(size))
#endif
* CAUTION: argument order is different from underlying functions!
*/
-#define JFREAD(file,buf,sizeofbuf) \
- ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
-#define JFWRITE(file,buf,sizeofbuf) \
- ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
+#define JFREAD(file, buf, sizeofbuf) \
+ ((size_t)fread((void *)(buf), (size_t)1, (size_t)(sizeofbuf), (file)))
+#define JFWRITE(file, buf, sizeofbuf) \
+ ((size_t)fwrite((const void *)(buf), (size_t)1, (size_t)(sizeofbuf), (file)))
#include "jinclude.h"
#include "jpeglib.h"
#include "jmemsys.h" /* import the system-dependent declarations */
-#ifndef _WIN32
+#if !defined(_MSC_VER) || _MSC_VER > 1600
#include <stdint.h>
#endif
#include <limits.h>
#ifndef NO_GETENV
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare getenv() */
-extern char *getenv (const char *name);
+extern char *getenv(const char *name);
#endif
#endif
LOCAL(size_t)
-round_up_pow2 (size_t a, size_t b)
+round_up_pow2(size_t a, size_t b)
/* a rounded up to the next multiple of b, i.e. ceil(a/b)*b */
/* Assumes a >= 0, b > 0, and b is a power of 2 */
{
#ifndef WITH_SIMD
#define ALIGN_SIZE sizeof(double)
#else
-#define ALIGN_SIZE 16 /* Most SIMD implementations require this */
+#define ALIGN_SIZE 32 /* Most of the SIMD instructions we support require
+ 16-byte (128-bit) alignment, but AVX2 requires
+ 32-byte alignment. */
#endif
#endif
typedef struct small_pool_struct *small_pool_ptr;
typedef struct small_pool_struct {
- small_pool_ptr next; /* next in list of pools */
+ small_pool_ptr next; /* next in list of pools */
size_t bytes_used; /* how many bytes already used within pool */
size_t bytes_left; /* bytes still available in this pool */
} small_pool_hdr;
typedef struct large_pool_struct *large_pool_ptr;
typedef struct large_pool_struct {
- large_pool_ptr next; /* next in list of pools */
+ large_pool_ptr next; /* next in list of pools */
size_t bytes_used; /* how many bytes already used within pool */
size_t bytes_left; /* bytes still available in this pool */
} large_pool_hdr;
#ifdef MEM_STATS /* optional extra stuff for statistics */
LOCAL(void)
-print_mem_stats (j_common_ptr cinfo, int pool_id)
+print_mem_stats(j_common_ptr cinfo, int pool_id)
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
small_pool_ptr shdr_ptr;
large_pool_ptr lhdr_ptr;
for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL;
lhdr_ptr = lhdr_ptr->next) {
- fprintf(stderr, " Large chunk used %ld\n",
- (long) lhdr_ptr->bytes_used);
+ fprintf(stderr, " Large chunk used %ld\n", (long)lhdr_ptr->bytes_used);
}
for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL;
shdr_ptr = shdr_ptr->next) {
fprintf(stderr, " Small chunk used %ld free %ld\n",
- (long) shdr_ptr->bytes_used,
- (long) shdr_ptr->bytes_left);
+ (long)shdr_ptr->bytes_used, (long)shdr_ptr->bytes_left);
}
}
LOCAL(void)
-out_of_memory (j_common_ptr cinfo, int which)
+out_of_memory(j_common_ptr cinfo, int which)
/* Report an out-of-memory error and stop execution */
/* If we compiled MEM_STATS support, report alloc requests before dying */
{
* adjustment.
*/
-static const size_t first_pool_slop[JPOOL_NUMPOOLS] =
-{
- 1600, /* first PERMANENT pool */
- 16000 /* first IMAGE pool */
+static const size_t first_pool_slop[JPOOL_NUMPOOLS] = {
+ 1600, /* first PERMANENT pool */
+ 16000 /* first IMAGE pool */
};
-static const size_t extra_pool_slop[JPOOL_NUMPOOLS] =
-{
- 0, /* additional PERMANENT pools */
- 5000 /* additional IMAGE pools */
+static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = {
+ 0, /* additional PERMANENT pools */
+ 5000 /* additional IMAGE pools */
};
#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */
METHODDEF(void *)
-alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
+alloc_small(j_common_ptr cinfo, int pool_id, size_t sizeofobject)
/* Allocate a "small" object */
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
small_pool_ptr hdr_ptr, prev_hdr_ptr;
char *data_ptr;
size_t min_request, slop;
else
slop = extra_pool_slop[pool_id];
/* Don't ask for more than MAX_ALLOC_CHUNK */
- if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request))
- slop = (size_t) (MAX_ALLOC_CHUNK-min_request);
+ if (slop > (size_t)(MAX_ALLOC_CHUNK - min_request))
+ slop = (size_t)(MAX_ALLOC_CHUNK - min_request);
/* Try to get space, if fail reduce slop and try again */
for (;;) {
- hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop);
+ hdr_ptr = (small_pool_ptr)jpeg_get_small(cinfo, min_request + slop);
if (hdr_ptr != NULL)
break;
slop /= 2;
}
/* OK, allocate the object from the current pool */
- data_ptr = (char *) hdr_ptr; /* point to first data byte in pool... */
+ data_ptr = (char *)hdr_ptr; /* point to first data byte in pool... */
data_ptr += sizeof(small_pool_hdr); /* ...by skipping the header... */
if ((size_t)data_ptr % ALIGN_SIZE) /* ...and adjust for alignment */
data_ptr += ALIGN_SIZE - (size_t)data_ptr % ALIGN_SIZE;
hdr_ptr->bytes_used += sizeofobject;
hdr_ptr->bytes_left -= sizeofobject;
- return (void *) data_ptr;
+ return (void *)data_ptr;
}
*/
METHODDEF(void *)
-alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
+alloc_large(j_common_ptr cinfo, int pool_id, size_t sizeofobject)
/* Allocate a "large" object */
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
large_pool_ptr hdr_ptr;
char *data_ptr;
if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
- hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject +
- sizeof(large_pool_hdr) +
- ALIGN_SIZE - 1);
+ hdr_ptr = (large_pool_ptr)jpeg_get_large(cinfo, sizeofobject +
+ sizeof(large_pool_hdr) +
+ ALIGN_SIZE - 1);
if (hdr_ptr == NULL)
out_of_memory(cinfo, 4); /* jpeg_get_large failed */
mem->total_space_allocated += sizeofobject + sizeof(large_pool_hdr) +
hdr_ptr->bytes_left = 0;
mem->large_list[pool_id] = hdr_ptr;
- data_ptr = (char *) hdr_ptr; /* point to first data byte in pool... */
+ data_ptr = (char *)hdr_ptr; /* point to first data byte in pool... */
data_ptr += sizeof(small_pool_hdr); /* ...by skipping the header... */
if ((size_t)data_ptr % ALIGN_SIZE) /* ...and adjust for alignment */
data_ptr += ALIGN_SIZE - (size_t)data_ptr % ALIGN_SIZE;
- return (void *) data_ptr;
+ return (void *)data_ptr;
}
*/
METHODDEF(JSAMPARRAY)
-alloc_sarray (j_common_ptr cinfo, int pool_id,
- JDIMENSION samplesperrow, JDIMENSION numrows)
+alloc_sarray(j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow,
+ JDIMENSION numrows)
/* Allocate a 2-D sample array */
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
JSAMPARRAY result;
JSAMPROW workspace;
JDIMENSION rowsperchunk, currow, i;
sizeof(JSAMPLE));
/* Calculate max # of rows allowed in one allocation chunk */
- ltemp = (MAX_ALLOC_CHUNK-sizeof(large_pool_hdr)) /
- ((long) samplesperrow * sizeof(JSAMPLE));
+ ltemp = (MAX_ALLOC_CHUNK - sizeof(large_pool_hdr)) /
+ ((long)samplesperrow * sizeof(JSAMPLE));
if (ltemp <= 0)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
- if (ltemp < (long) numrows)
- rowsperchunk = (JDIMENSION) ltemp;
+ if (ltemp < (long)numrows)
+ rowsperchunk = (JDIMENSION)ltemp;
else
rowsperchunk = numrows;
mem->last_rowsperchunk = rowsperchunk;
/* Get space for row pointers (small object) */
- result = (JSAMPARRAY) alloc_small(cinfo, pool_id,
- (size_t) (numrows * sizeof(JSAMPROW)));
+ result = (JSAMPARRAY)alloc_small(cinfo, pool_id,
+ (size_t)(numrows * sizeof(JSAMPROW)));
/* Get the rows themselves (large objects) */
currow = 0;
while (currow < numrows) {
rowsperchunk = MIN(rowsperchunk, numrows - currow);
- workspace = (JSAMPROW) alloc_large(cinfo, pool_id,
- (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow
- * sizeof(JSAMPLE)));
+ workspace = (JSAMPROW)alloc_large(cinfo, pool_id,
+ (size_t)((size_t)rowsperchunk * (size_t)samplesperrow *
+ sizeof(JSAMPLE)));
for (i = rowsperchunk; i > 0; i--) {
result[currow++] = workspace;
workspace += samplesperrow;
*/
METHODDEF(JBLOCKARRAY)
-alloc_barray (j_common_ptr cinfo, int pool_id,
- JDIMENSION blocksperrow, JDIMENSION numrows)
+alloc_barray(j_common_ptr cinfo, int pool_id, JDIMENSION blocksperrow,
+ JDIMENSION numrows)
/* Allocate a 2-D coefficient-block array */
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
JBLOCKARRAY result;
JBLOCKROW workspace;
JDIMENSION rowsperchunk, currow, i;
out_of_memory(cinfo, 6); /* safety check */
/* Calculate max # of rows allowed in one allocation chunk */
- ltemp = (MAX_ALLOC_CHUNK-sizeof(large_pool_hdr)) /
- ((long) blocksperrow * sizeof(JBLOCK));
+ ltemp = (MAX_ALLOC_CHUNK - sizeof(large_pool_hdr)) /
+ ((long)blocksperrow * sizeof(JBLOCK));
if (ltemp <= 0)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
- if (ltemp < (long) numrows)
- rowsperchunk = (JDIMENSION) ltemp;
+ if (ltemp < (long)numrows)
+ rowsperchunk = (JDIMENSION)ltemp;
else
rowsperchunk = numrows;
mem->last_rowsperchunk = rowsperchunk;
/* Get space for row pointers (small object) */
- result = (JBLOCKARRAY) alloc_small(cinfo, pool_id,
- (size_t) (numrows * sizeof(JBLOCKROW)));
+ result = (JBLOCKARRAY)alloc_small(cinfo, pool_id,
+ (size_t)(numrows * sizeof(JBLOCKROW)));
/* Get the rows themselves (large objects) */
currow = 0;
while (currow < numrows) {
rowsperchunk = MIN(rowsperchunk, numrows - currow);
- workspace = (JBLOCKROW) alloc_large(cinfo, pool_id,
- (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow
- * sizeof(JBLOCK)));
+ workspace = (JBLOCKROW)alloc_large(cinfo, pool_id,
+ (size_t)((size_t)rowsperchunk * (size_t)blocksperrow *
+ sizeof(JBLOCK)));
for (i = rowsperchunk; i > 0; i--) {
result[currow++] = workspace;
workspace += blocksperrow;
METHODDEF(jvirt_sarray_ptr)
-request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
- JDIMENSION samplesperrow, JDIMENSION numrows,
- JDIMENSION maxaccess)
+request_virt_sarray(j_common_ptr cinfo, int pool_id, boolean pre_zero,
+ JDIMENSION samplesperrow, JDIMENSION numrows,
+ JDIMENSION maxaccess)
/* Request a virtual 2-D sample array */
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
jvirt_sarray_ptr result;
/* Only IMAGE-lifetime virtual arrays are currently supported */
ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
/* get control block */
- result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id,
- sizeof(struct jvirt_sarray_control));
+ result = (jvirt_sarray_ptr)alloc_small(cinfo, pool_id,
+ sizeof(struct jvirt_sarray_control));
result->mem_buffer = NULL; /* marks array not yet realized */
result->rows_in_array = numrows;
METHODDEF(jvirt_barray_ptr)
-request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
- JDIMENSION blocksperrow, JDIMENSION numrows,
- JDIMENSION maxaccess)
+request_virt_barray(j_common_ptr cinfo, int pool_id, boolean pre_zero,
+ JDIMENSION blocksperrow, JDIMENSION numrows,
+ JDIMENSION maxaccess)
/* Request a virtual 2-D coefficient-block array */
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
jvirt_barray_ptr result;
/* Only IMAGE-lifetime virtual arrays are currently supported */
ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
/* get control block */
- result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id,
- sizeof(struct jvirt_barray_control));
+ result = (jvirt_barray_ptr)alloc_small(cinfo, pool_id,
+ sizeof(struct jvirt_barray_control));
result->mem_buffer = NULL; /* marks array not yet realized */
result->rows_in_array = numrows;
METHODDEF(void)
-realize_virt_arrays (j_common_ptr cinfo)
+realize_virt_arrays(j_common_ptr cinfo)
/* Allocate the in-memory buffers for any unrealized virtual arrays */
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
size_t space_per_minheight, maximum_space, avail_mem;
size_t minheights, max_minheights;
jvirt_sarray_ptr sptr;
maximum_space = 0;
for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
if (sptr->mem_buffer == NULL) { /* if not realized yet */
- size_t new_space = (long) sptr->rows_in_array *
- (long) sptr->samplesperrow * sizeof(JSAMPLE);
+ size_t new_space = (long)sptr->rows_in_array *
+ (long)sptr->samplesperrow * sizeof(JSAMPLE);
- space_per_minheight += (long) sptr->maxaccess *
- (long) sptr->samplesperrow * sizeof(JSAMPLE);
+ space_per_minheight += (long)sptr->maxaccess *
+ (long)sptr->samplesperrow * sizeof(JSAMPLE);
if (SIZE_MAX - maximum_space < new_space)
out_of_memory(cinfo, 10);
maximum_space += new_space;
}
for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
if (bptr->mem_buffer == NULL) { /* if not realized yet */
- size_t new_space = (long) bptr->rows_in_array *
- (long) bptr->blocksperrow * sizeof(JBLOCK);
+ size_t new_space = (long)bptr->rows_in_array *
+ (long)bptr->blocksperrow * sizeof(JBLOCK);
- space_per_minheight += (long) bptr->maxaccess *
- (long) bptr->blocksperrow * sizeof(JBLOCK);
+ space_per_minheight += (long)bptr->maxaccess *
+ (long)bptr->blocksperrow * sizeof(JBLOCK);
if (SIZE_MAX - maximum_space < new_space)
out_of_memory(cinfo, 11);
maximum_space += new_space;
for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
if (sptr->mem_buffer == NULL) { /* if not realized yet */
- minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L;
+ minheights = ((long)sptr->rows_in_array - 1L) / sptr->maxaccess + 1L;
if (minheights <= max_minheights) {
/* This buffer fits in memory */
sptr->rows_in_mem = sptr->rows_in_array;
} else {
/* It doesn't fit in memory, create backing store. */
- sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess);
- jpeg_open_backing_store(cinfo, & sptr->b_s_info,
- (long) sptr->rows_in_array *
- (long) sptr->samplesperrow *
- (long) sizeof(JSAMPLE));
+ sptr->rows_in_mem = (JDIMENSION)(max_minheights * sptr->maxaccess);
+ jpeg_open_backing_store(cinfo, &sptr->b_s_info,
+ (long)sptr->rows_in_array *
+ (long)sptr->samplesperrow *
+ (long)sizeof(JSAMPLE));
sptr->b_s_open = TRUE;
}
sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE,
for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
if (bptr->mem_buffer == NULL) { /* if not realized yet */
- minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
+ minheights = ((long)bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
if (minheights <= max_minheights) {
/* This buffer fits in memory */
bptr->rows_in_mem = bptr->rows_in_array;
} else {
/* It doesn't fit in memory, create backing store. */
- bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess);
- jpeg_open_backing_store(cinfo, & bptr->b_s_info,
- (long) bptr->rows_in_array *
- (long) bptr->blocksperrow *
- (long) sizeof(JBLOCK));
+ bptr->rows_in_mem = (JDIMENSION)(max_minheights * bptr->maxaccess);
+ jpeg_open_backing_store(cinfo, &bptr->b_s_info,
+ (long)bptr->rows_in_array *
+ (long)bptr->blocksperrow *
+ (long)sizeof(JBLOCK));
bptr->b_s_open = TRUE;
}
bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE,
LOCAL(void)
-do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
+do_sarray_io(j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
/* Do backing store read or write of a virtual sample array */
{
long bytesperrow, file_offset, byte_count, rows, thisrow, i;
- bytesperrow = (long) ptr->samplesperrow * sizeof(JSAMPLE);
+ bytesperrow = (long)ptr->samplesperrow * sizeof(JSAMPLE);
file_offset = ptr->cur_start_row * bytesperrow;
/* Loop to read or write each allocation chunk in mem_buffer */
- for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
+ for (i = 0; i < (long)ptr->rows_in_mem; i += ptr->rowsperchunk) {
/* One chunk, but check for short chunk at end of buffer */
- rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
+ rows = MIN((long)ptr->rowsperchunk, (long)ptr->rows_in_mem - i);
/* Transfer no more than is currently defined */
- thisrow = (long) ptr->cur_start_row + i;
- rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
+ thisrow = (long)ptr->cur_start_row + i;
+ rows = MIN(rows, (long)ptr->first_undef_row - thisrow);
/* Transfer no more than fits in file */
- rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
+ rows = MIN(rows, (long)ptr->rows_in_array - thisrow);
if (rows <= 0) /* this chunk might be past end of file! */
break;
byte_count = rows * bytesperrow;
if (writing)
- (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
- (void *) ptr->mem_buffer[i],
+ (*ptr->b_s_info.write_backing_store) (cinfo, &ptr->b_s_info,
+ (void *)ptr->mem_buffer[i],
file_offset, byte_count);
else
- (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
- (void *) ptr->mem_buffer[i],
+ (*ptr->b_s_info.read_backing_store) (cinfo, &ptr->b_s_info,
+ (void *)ptr->mem_buffer[i],
file_offset, byte_count);
file_offset += byte_count;
}
LOCAL(void)
-do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing)
+do_barray_io(j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing)
/* Do backing store read or write of a virtual coefficient-block array */
{
long bytesperrow, file_offset, byte_count, rows, thisrow, i;
- bytesperrow = (long) ptr->blocksperrow * sizeof(JBLOCK);
+ bytesperrow = (long)ptr->blocksperrow * sizeof(JBLOCK);
file_offset = ptr->cur_start_row * bytesperrow;
/* Loop to read or write each allocation chunk in mem_buffer */
- for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
+ for (i = 0; i < (long)ptr->rows_in_mem; i += ptr->rowsperchunk) {
/* One chunk, but check for short chunk at end of buffer */
- rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
+ rows = MIN((long)ptr->rowsperchunk, (long)ptr->rows_in_mem - i);
/* Transfer no more than is currently defined */
- thisrow = (long) ptr->cur_start_row + i;
- rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
+ thisrow = (long)ptr->cur_start_row + i;
+ rows = MIN(rows, (long)ptr->first_undef_row - thisrow);
/* Transfer no more than fits in file */
- rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
+ rows = MIN(rows, (long)ptr->rows_in_array - thisrow);
if (rows <= 0) /* this chunk might be past end of file! */
break;
byte_count = rows * bytesperrow;
if (writing)
- (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
- (void *) ptr->mem_buffer[i],
+ (*ptr->b_s_info.write_backing_store) (cinfo, &ptr->b_s_info,
+ (void *)ptr->mem_buffer[i],
file_offset, byte_count);
else
- (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
- (void *) ptr->mem_buffer[i],
+ (*ptr->b_s_info.read_backing_store) (cinfo, &ptr->b_s_info,
+ (void *)ptr->mem_buffer[i],
file_offset, byte_count);
file_offset += byte_count;
}
METHODDEF(JSAMPARRAY)
-access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
- JDIMENSION start_row, JDIMENSION num_rows,
- boolean writable)
+access_virt_sarray(j_common_ptr cinfo, jvirt_sarray_ptr ptr,
+ JDIMENSION start_row, JDIMENSION num_rows, boolean writable)
/* Access the part of a virtual sample array starting at start_row */
/* and extending for num_rows rows. writable is true if */
/* caller intends to modify the accessed area. */
/* Make the desired part of the virtual array accessible */
if (start_row < ptr->cur_start_row ||
- end_row > ptr->cur_start_row+ptr->rows_in_mem) {
- if (! ptr->b_s_open)
+ end_row > ptr->cur_start_row + ptr->rows_in_mem) {
+ if (!ptr->b_s_open)
ERREXIT(cinfo, JERR_VIRTUAL_BUG);
/* Flush old buffer contents if necessary */
if (ptr->dirty) {
/* use long arithmetic here to avoid overflow & unsigned problems */
long ltemp;
- ltemp = (long) end_row - (long) ptr->rows_in_mem;
+ ltemp = (long)end_row - (long)ptr->rows_in_mem;
if (ltemp < 0)
ltemp = 0; /* don't fall off front end of file */
- ptr->cur_start_row = (JDIMENSION) ltemp;
+ ptr->cur_start_row = (JDIMENSION)ltemp;
}
/* Read in the selected part of the array.
* During the initial write pass, we will do no actual read
if (writable)
ptr->first_undef_row = end_row;
if (ptr->pre_zero) {
- size_t bytesperrow = (size_t) ptr->samplesperrow * sizeof(JSAMPLE);
+ size_t bytesperrow = (size_t)ptr->samplesperrow * sizeof(JSAMPLE);
undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
end_row -= ptr->cur_start_row;
while (undef_row < end_row) {
- jzero_far((void *) ptr->mem_buffer[undef_row], bytesperrow);
+ jzero_far((void *)ptr->mem_buffer[undef_row], bytesperrow);
undef_row++;
}
} else {
- if (! writable) /* reader looking at undefined data */
+ if (!writable) /* reader looking at undefined data */
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
}
}
METHODDEF(JBLOCKARRAY)
-access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
- JDIMENSION start_row, JDIMENSION num_rows,
- boolean writable)
+access_virt_barray(j_common_ptr cinfo, jvirt_barray_ptr ptr,
+ JDIMENSION start_row, JDIMENSION num_rows, boolean writable)
/* Access the part of a virtual block array starting at start_row */
/* and extending for num_rows rows. writable is true if */
/* caller intends to modify the accessed area. */
/* Make the desired part of the virtual array accessible */
if (start_row < ptr->cur_start_row ||
- end_row > ptr->cur_start_row+ptr->rows_in_mem) {
- if (! ptr->b_s_open)
+ end_row > ptr->cur_start_row + ptr->rows_in_mem) {
+ if (!ptr->b_s_open)
ERREXIT(cinfo, JERR_VIRTUAL_BUG);
/* Flush old buffer contents if necessary */
if (ptr->dirty) {
/* use long arithmetic here to avoid overflow & unsigned problems */
long ltemp;
- ltemp = (long) end_row - (long) ptr->rows_in_mem;
+ ltemp = (long)end_row - (long)ptr->rows_in_mem;
if (ltemp < 0)
ltemp = 0; /* don't fall off front end of file */
- ptr->cur_start_row = (JDIMENSION) ltemp;
+ ptr->cur_start_row = (JDIMENSION)ltemp;
}
/* Read in the selected part of the array.
* During the initial write pass, we will do no actual read
if (writable)
ptr->first_undef_row = end_row;
if (ptr->pre_zero) {
- size_t bytesperrow = (size_t) ptr->blocksperrow * sizeof(JBLOCK);
+ size_t bytesperrow = (size_t)ptr->blocksperrow * sizeof(JBLOCK);
undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
end_row -= ptr->cur_start_row;
while (undef_row < end_row) {
- jzero_far((void *) ptr->mem_buffer[undef_row], bytesperrow);
+ jzero_far((void *)ptr->mem_buffer[undef_row], bytesperrow);
undef_row++;
}
} else {
- if (! writable) /* reader looking at undefined data */
+ if (!writable) /* reader looking at undefined data */
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
}
}
*/
METHODDEF(void)
-free_pool (j_common_ptr cinfo, int pool_id)
+free_pool(j_common_ptr cinfo, int pool_id)
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
small_pool_ptr shdr_ptr;
large_pool_ptr lhdr_ptr;
size_t space_freed;
for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
if (sptr->b_s_open) { /* there may be no backing store */
sptr->b_s_open = FALSE; /* prevent recursive close if error */
- (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info);
+ (*sptr->b_s_info.close_backing_store) (cinfo, &sptr->b_s_info);
}
}
mem->virt_sarray_list = NULL;
for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
if (bptr->b_s_open) { /* there may be no backing store */
bptr->b_s_open = FALSE; /* prevent recursive close if error */
- (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info);
+ (*bptr->b_s_info.close_backing_store) (cinfo, &bptr->b_s_info);
}
}
mem->virt_barray_list = NULL;
space_freed = lhdr_ptr->bytes_used +
lhdr_ptr->bytes_left +
sizeof(large_pool_hdr);
- jpeg_free_large(cinfo, (void *) lhdr_ptr, space_freed);
+ jpeg_free_large(cinfo, (void *)lhdr_ptr, space_freed);
mem->total_space_allocated -= space_freed;
lhdr_ptr = next_lhdr_ptr;
}
while (shdr_ptr != NULL) {
small_pool_ptr next_shdr_ptr = shdr_ptr->next;
- space_freed = shdr_ptr->bytes_used +
- shdr_ptr->bytes_left +
+ space_freed = shdr_ptr->bytes_used + shdr_ptr->bytes_left +
sizeof(small_pool_hdr);
- jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed);
+ jpeg_free_small(cinfo, (void *)shdr_ptr, space_freed);
mem->total_space_allocated -= space_freed;
shdr_ptr = next_shdr_ptr;
}
*/
METHODDEF(void)
-self_destruct (j_common_ptr cinfo)
+self_destruct(j_common_ptr cinfo)
{
int pool;
* Releasing pools in reverse order might help avoid fragmentation
* with some (brain-damaged) malloc libraries.
*/
- for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
+ for (pool = JPOOL_NUMPOOLS - 1; pool >= JPOOL_PERMANENT; pool--) {
free_pool(cinfo, pool);
}
/* Release the memory manager control block too. */
- jpeg_free_small(cinfo, (void *) cinfo->mem, sizeof(my_memory_mgr));
+ jpeg_free_small(cinfo, (void *)cinfo->mem, sizeof(my_memory_mgr));
cinfo->mem = NULL; /* ensures I will be called only once */
jpeg_mem_term(cinfo); /* system-dependent cleanup */
*/
GLOBAL(void)
-jinit_memory_mgr (j_common_ptr cinfo)
+jinit_memory_mgr(j_common_ptr cinfo)
{
my_mem_ptr mem;
long max_to_use;
* in common if and only if X is a power of 2, ie has only one one-bit.
* Some compilers may give an "unreachable code" warning here; ignore it.
*/
- if ((ALIGN_SIZE & (ALIGN_SIZE-1)) != 0)
+ if ((ALIGN_SIZE & (ALIGN_SIZE - 1)) != 0)
ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);
/* MAX_ALLOC_CHUNK must be representable as type size_t, and must be
* a multiple of ALIGN_SIZE.
* Again, an "unreachable code" warning may be ignored here.
* But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK.
*/
- test_mac = (size_t) MAX_ALLOC_CHUNK;
- if ((long) test_mac != MAX_ALLOC_CHUNK ||
+ test_mac = (size_t)MAX_ALLOC_CHUNK;
+ if ((long)test_mac != MAX_ALLOC_CHUNK ||
(MAX_ALLOC_CHUNK % ALIGN_SIZE) != 0)
ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */
/* Attempt to allocate memory manager's control block */
- mem = (my_mem_ptr) jpeg_get_small(cinfo, sizeof(my_memory_mgr));
+ mem = (my_mem_ptr)jpeg_get_small(cinfo, sizeof(my_memory_mgr));
if (mem == NULL) {
jpeg_mem_term(cinfo); /* system-dependent cleanup */
/* Initialize working state */
mem->pub.max_memory_to_use = max_to_use;
- for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
+ for (pool = JPOOL_NUMPOOLS - 1; pool >= JPOOL_PERMANENT; pool--) {
mem->small_list[pool] = NULL;
mem->large_list[pool] = NULL;
}
mem->total_space_allocated = sizeof(my_memory_mgr);
/* Declare ourselves open for business */
- cinfo->mem = & mem->pub;
+ cinfo->mem = &mem->pub;
/* Check for an environment variable JPEGMEM; if found, override the
* default max_memory setting from jpeg_mem_init. Note that the
* this feature.
*/
#ifndef NO_GETENV
- { char *memenv;
+ {
+ char *memenv;
if ((memenv = getenv("JPEGMEM")) != NULL) {
char ch = 'x';
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1992-1996, Thomas G. Lane.
* libjpeg-turbo Modifications:
- * Copyright (C) 2017, D. R. Commander.
+ * Copyright (C) 2017-2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
#include "jmemsys.h" /* import the system-dependent declarations */
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
-extern void *malloc (size_t size);
-extern void free (void *ptr);
+extern void *malloc(size_t size);
+extern void free(void *ptr);
#endif
*/
GLOBAL(void *)
-jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
+jpeg_get_small(j_common_ptr cinfo, size_t sizeofobject)
{
- return (void *) malloc(sizeofobject);
+ return (void *)malloc(sizeofobject);
}
GLOBAL(void)
-jpeg_free_small (j_common_ptr cinfo, void *object, size_t sizeofobject)
+jpeg_free_small(j_common_ptr cinfo, void *object, size_t sizeofobject)
{
free(object);
}
*/
GLOBAL(void *)
-jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
+jpeg_get_large(j_common_ptr cinfo, size_t sizeofobject)
{
- return (void *) malloc(sizeofobject);
+ return (void *)malloc(sizeofobject);
}
GLOBAL(void)
-jpeg_free_large (j_common_ptr cinfo, void *object, size_t sizeofobject)
+jpeg_free_large(j_common_ptr cinfo, void *object, size_t sizeofobject)
{
free(object);
}
*/
GLOBAL(size_t)
-jpeg_mem_available (j_common_ptr cinfo, size_t min_bytes_needed,
- size_t max_bytes_needed, size_t already_allocated)
+jpeg_mem_available(j_common_ptr cinfo, size_t min_bytes_needed,
+ size_t max_bytes_needed, size_t already_allocated)
{
if (cinfo->mem->max_memory_to_use) {
- if (cinfo->mem->max_memory_to_use > already_allocated)
+ if ((size_t)cinfo->mem->max_memory_to_use > already_allocated)
return cinfo->mem->max_memory_to_use - already_allocated;
else
return 0;
*/
GLOBAL(void)
-jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
- long total_bytes_needed)
+jpeg_open_backing_store(j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
{
ERREXIT(cinfo, JERR_NO_BACKING_STORE);
}
*/
GLOBAL(long)
-jpeg_mem_init (j_common_ptr cinfo)
+jpeg_mem_init(j_common_ptr cinfo)
{
return 0; /* just set max_memory_to_use to 0 */
}
GLOBAL(void)
-jpeg_mem_term (j_common_ptr cinfo)
+jpeg_mem_term(j_common_ptr cinfo)
{
/* no work */
}
* size of the object being freed, just in case it's needed.
*/
-EXTERN(void *) jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject);
-EXTERN(void) jpeg_free_small (j_common_ptr cinfo, void *object,
- size_t sizeofobject);
+EXTERN(void *) jpeg_get_small(j_common_ptr cinfo, size_t sizeofobject);
+EXTERN(void) jpeg_free_small(j_common_ptr cinfo, void *object,
+ size_t sizeofobject);
/*
* These two functions are used to allocate and release large chunks of
* large chunks.
*/
-EXTERN(void *) jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject);
-EXTERN(void) jpeg_free_large (j_common_ptr cinfo, void *object,
- size_t sizeofobject);
+EXTERN(void *) jpeg_get_large(j_common_ptr cinfo, size_t sizeofobject);
+EXTERN(void) jpeg_free_large(j_common_ptr cinfo, void *object,
+ size_t sizeofobject);
/*
* The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may
* Conversely, zero may be returned to always use the minimum amount of memory.
*/
-EXTERN(size_t) jpeg_mem_available (j_common_ptr cinfo, size_t min_bytes_needed,
- size_t max_bytes_needed,
- size_t already_allocated);
+EXTERN(size_t) jpeg_mem_available(j_common_ptr cinfo, size_t min_bytes_needed,
+ size_t max_bytes_needed,
+ size_t already_allocated);
/*
* just take an error exit.)
*/
-EXTERN(void) jpeg_open_backing_store (j_common_ptr cinfo,
- backing_store_ptr info,
- long total_bytes_needed);
+EXTERN(void) jpeg_open_backing_store(j_common_ptr cinfo,
+ backing_store_ptr info,
+ long total_bytes_needed);
/*
* all opened backing-store objects have been closed.
*/
-EXTERN(long) jpeg_mem_init (j_common_ptr cinfo);
-EXTERN(void) jpeg_mem_term (j_common_ptr cinfo);
+EXTERN(long) jpeg_mem_init(j_common_ptr cinfo);
+EXTERN(void) jpeg_mem_term(j_common_ptr cinfo);
* Copyright (C) 1991-1997, Thomas G. Lane.
* Modified 1997-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2009, 2011, 2014-2015, D. R. Commander.
+ * Copyright (C) 2009, 2011, 2014-2015, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
/*
* Maximum number of components (color channels) allowed in JPEG image.
- * To meet the letter of the JPEG spec, set this to 255. However, darn
- * few applications need more than 4 channels (maybe 5 for CMYK + alpha
- * mask). We recommend 10 as a reasonable compromise; use 4 if you are
+ * To meet the letter of Rec. ITU-T T.81 | ISO/IEC 10918-1, set this to 255.
+ * However, darn few applications need more than 4 channels (maybe 5 for CMYK +
+ * alpha mask). We recommend 10 as a reasonable compromise; use 4 if you are
* really short on memory. (Each allowed component costs a hundred or so
* bytes of storage, whether actually used in an image or not.)
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JSAMPLE;
-#define GETJSAMPLE(value) ((int) (value))
+#define GETJSAMPLE(value) ((int)(value))
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JSAMPLE;
#ifdef __CHAR_UNSIGNED__
-#define GETJSAMPLE(value) ((int) (value))
+#define GETJSAMPLE(value) ((int)(value))
#else
-#define GETJSAMPLE(value) ((int) (value) & 0xFF)
+#define GETJSAMPLE(value) ((int)(value) & 0xFF)
#endif /* __CHAR_UNSIGNED__ */
#endif /* HAVE_UNSIGNED_CHAR */
*/
typedef short JSAMPLE;
-#define GETJSAMPLE(value) ((int) (value))
+#define GETJSAMPLE(value) ((int)(value))
#define MAXJSAMPLE 4095
#define CENTERJSAMPLE 2048
*/
#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
-#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */
-#ifndef _BASETSD_H /* MinGW is slightly different */
-#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */
+#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */
+#ifndef _BASETSD_H /* MinGW is slightly different */
+#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */
typedef long INT32;
#endif
#endif
* software out there that uses it.
*/
-#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
+#define JMETHOD(type, methodname, arglist) type (*methodname) arglist
/* libjpeg-turbo no longer supports platforms that have far symbols (MS-DOS),
* with it. In reality, few people ever did this, because there were some
* severe restrictions involved (cjpeg and djpeg no longer worked properly,
* compressing/decompressing RGB JPEGs no longer worked properly, and the color
- * quantizer wouldn't work with pixel sizes other than 3.) Further, since all
- * of the O/S-supplied versions of libjpeg were built with the default values
- * of RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE, many applications have
- * come to regard these values as immutable.
+ * quantizer wouldn't work with pixel sizes other than 3.) Furthermore, since
+ * all of the O/S-supplied versions of libjpeg were built with the default
+ * values of RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE, many applications
+ * have come to regard these values as immutable.
*
* The libjpeg-turbo colorspace extensions provide a much cleaner way of
* compressing from/decompressing to buffers with arbitrary component orders
#define RGB_BLUE 2 /* Offset of Blue */
#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
-#define JPEG_NUMCS 17
+#define JPEG_NUMCS 17
-#define EXT_RGB_RED 0
-#define EXT_RGB_GREEN 1
-#define EXT_RGB_BLUE 2
-#define EXT_RGB_PIXELSIZE 3
+#define EXT_RGB_RED 0
+#define EXT_RGB_GREEN 1
+#define EXT_RGB_BLUE 2
+#define EXT_RGB_PIXELSIZE 3
-#define EXT_RGBX_RED 0
-#define EXT_RGBX_GREEN 1
-#define EXT_RGBX_BLUE 2
-#define EXT_RGBX_PIXELSIZE 4
+#define EXT_RGBX_RED 0
+#define EXT_RGBX_GREEN 1
+#define EXT_RGBX_BLUE 2
+#define EXT_RGBX_PIXELSIZE 4
-#define EXT_BGR_RED 2
-#define EXT_BGR_GREEN 1
-#define EXT_BGR_BLUE 0
-#define EXT_BGR_PIXELSIZE 3
+#define EXT_BGR_RED 2
+#define EXT_BGR_GREEN 1
+#define EXT_BGR_BLUE 0
+#define EXT_BGR_PIXELSIZE 3
-#define EXT_BGRX_RED 2
-#define EXT_BGRX_GREEN 1
-#define EXT_BGRX_BLUE 0
-#define EXT_BGRX_PIXELSIZE 4
+#define EXT_BGRX_RED 2
+#define EXT_BGRX_GREEN 1
+#define EXT_BGRX_BLUE 0
+#define EXT_BGRX_PIXELSIZE 4
-#define EXT_XBGR_RED 3
-#define EXT_XBGR_GREEN 2
-#define EXT_XBGR_BLUE 1
-#define EXT_XBGR_PIXELSIZE 4
+#define EXT_XBGR_RED 3
+#define EXT_XBGR_GREEN 2
+#define EXT_XBGR_BLUE 1
+#define EXT_XBGR_PIXELSIZE 4
-#define EXT_XRGB_RED 1
-#define EXT_XRGB_GREEN 2
-#define EXT_XRGB_BLUE 3
-#define EXT_XRGB_PIXELSIZE 4
+#define EXT_XRGB_RED 1
+#define EXT_XRGB_GREEN 2
+#define EXT_XRGB_BLUE 3
+#define EXT_XRGB_PIXELSIZE 4
static const int rgb_red[JPEG_NUMCS] = {
-1, -1, RGB_RED, -1, -1, -1, EXT_RGB_RED, EXT_RGBX_RED,
#ifndef WITH_SIMD
#define MULTIPLIER int /* type for fastest integer multiply */
#else
-#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */
+#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */
#endif
#endif
*/
#if JPEG_LIB_VERSION >= 70
-#define _DCT_scaled_size DCT_h_scaled_size
-#define _DCT_h_scaled_size DCT_h_scaled_size
-#define _DCT_v_scaled_size DCT_v_scaled_size
-#define _min_DCT_scaled_size min_DCT_h_scaled_size
-#define _min_DCT_h_scaled_size min_DCT_h_scaled_size
-#define _min_DCT_v_scaled_size min_DCT_v_scaled_size
-#define _jpeg_width jpeg_width
-#define _jpeg_height jpeg_height
+#define _DCT_scaled_size DCT_h_scaled_size
+#define _DCT_h_scaled_size DCT_h_scaled_size
+#define _DCT_v_scaled_size DCT_v_scaled_size
+#define _min_DCT_scaled_size min_DCT_h_scaled_size
+#define _min_DCT_h_scaled_size min_DCT_h_scaled_size
+#define _min_DCT_v_scaled_size min_DCT_v_scaled_size
+#define _jpeg_width jpeg_width
+#define _jpeg_height jpeg_height
#else
-#define _DCT_scaled_size DCT_scaled_size
-#define _DCT_h_scaled_size DCT_scaled_size
-#define _DCT_v_scaled_size DCT_scaled_size
-#define _min_DCT_scaled_size min_DCT_scaled_size
-#define _min_DCT_h_scaled_size min_DCT_scaled_size
-#define _min_DCT_v_scaled_size min_DCT_scaled_size
-#define _jpeg_width image_width
-#define _jpeg_height image_height
+#define _DCT_scaled_size DCT_scaled_size
+#define _DCT_h_scaled_size DCT_scaled_size
+#define _DCT_v_scaled_size DCT_scaled_size
+#define _min_DCT_scaled_size min_DCT_scaled_size
+#define _min_DCT_h_scaled_size min_DCT_scaled_size
+#define _min_DCT_v_scaled_size min_DCT_scaled_size
+#define _jpeg_width image_width
+#define _jpeg_height image_height
#endif
} J_BUF_MODE;
/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
-#define CSTATE_START 100 /* after create_compress */
-#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */
-#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */
-#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */
-#define DSTATE_START 200 /* after create_decompress */
-#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */
-#define DSTATE_READY 202 /* found SOS, ready for start_decompress */
-#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/
-#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */
-#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */
-#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */
-#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */
-#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */
-#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */
-#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */
+#define CSTATE_START 100 /* after create_compress */
+#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */
+#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */
+#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */
+#define DSTATE_START 200 /* after create_decompress */
+#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */
+#define DSTATE_READY 202 /* found SOS, ready for start_decompress */
+#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/
+#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */
+#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */
+#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */
+#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */
+#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */
+#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */
+#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */
/* JLONG must hold at least signed 32-bit values. */
* sanitizer warnings
*/
-#define LEFT_SHIFT(a, b) ((JLONG)((unsigned long)(a) << (b)))
+#define LEFT_SHIFT(a, b) ((JLONG)((unsigned long)(a) << (b)))
/* Declarations for compression modules */
/* Miscellaneous useful macros */
#undef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
#undef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
/* We assume that right shift corresponds to signed division by 2 with
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define SHIFT_TEMPS JLONG shift_temp;
-#define RIGHT_SHIFT(x,shft) \
- ((shift_temp = (x)) < 0 ? \
- (shift_temp >> (shft)) | ((~((JLONG) 0)) << (32-(shft))) : \
- (shift_temp >> (shft)))
+#define RIGHT_SHIFT(x, shft) \
+ ((shift_temp = (x)) < 0 ? \
+ (shift_temp >> (shft)) | ((~((JLONG)0)) << (32 - (shft))) : \
+ (shift_temp >> (shft)))
#else
#define SHIFT_TEMPS
-#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
+#define RIGHT_SHIFT(x, shft) ((x) >> (shft))
#endif
/* Compression module initialization routines */
-EXTERN(void) jinit_compress_master (j_compress_ptr cinfo);
-EXTERN(void) jinit_c_master_control (j_compress_ptr cinfo,
- boolean transcode_only);
-EXTERN(void) jinit_c_main_controller (j_compress_ptr cinfo,
- boolean need_full_buffer);
-EXTERN(void) jinit_c_prep_controller (j_compress_ptr cinfo,
- boolean need_full_buffer);
-EXTERN(void) jinit_c_coef_controller (j_compress_ptr cinfo,
- boolean need_full_buffer);
-EXTERN(void) jinit_color_converter (j_compress_ptr cinfo);
-EXTERN(void) jinit_downsampler (j_compress_ptr cinfo);
-EXTERN(void) jinit_forward_dct (j_compress_ptr cinfo);
-EXTERN(void) jinit_huff_encoder (j_compress_ptr cinfo);
-EXTERN(void) jinit_phuff_encoder (j_compress_ptr cinfo);
-EXTERN(void) jinit_arith_encoder (j_compress_ptr cinfo);
-EXTERN(void) jinit_marker_writer (j_compress_ptr cinfo);
+EXTERN(void) jinit_compress_master(j_compress_ptr cinfo);
+EXTERN(void) jinit_c_master_control(j_compress_ptr cinfo,
+ boolean transcode_only);
+EXTERN(void) jinit_c_main_controller(j_compress_ptr cinfo,
+ boolean need_full_buffer);
+EXTERN(void) jinit_c_prep_controller(j_compress_ptr cinfo,
+ boolean need_full_buffer);
+EXTERN(void) jinit_c_coef_controller(j_compress_ptr cinfo,
+ boolean need_full_buffer);
+EXTERN(void) jinit_color_converter(j_compress_ptr cinfo);
+EXTERN(void) jinit_downsampler(j_compress_ptr cinfo);
+EXTERN(void) jinit_forward_dct(j_compress_ptr cinfo);
+EXTERN(void) jinit_huff_encoder(j_compress_ptr cinfo);
+EXTERN(void) jinit_phuff_encoder(j_compress_ptr cinfo);
+EXTERN(void) jinit_arith_encoder(j_compress_ptr cinfo);
+EXTERN(void) jinit_marker_writer(j_compress_ptr cinfo);
/* Decompression module initialization routines */
-EXTERN(void) jinit_master_decompress (j_decompress_ptr cinfo);
-EXTERN(void) jinit_d_main_controller (j_decompress_ptr cinfo,
- boolean need_full_buffer);
-EXTERN(void) jinit_d_coef_controller (j_decompress_ptr cinfo,
- boolean need_full_buffer);
-EXTERN(void) jinit_d_post_controller (j_decompress_ptr cinfo,
- boolean need_full_buffer);
-EXTERN(void) jinit_input_controller (j_decompress_ptr cinfo);
-EXTERN(void) jinit_marker_reader (j_decompress_ptr cinfo);
-EXTERN(void) jinit_huff_decoder (j_decompress_ptr cinfo);
-EXTERN(void) jinit_phuff_decoder (j_decompress_ptr cinfo);
-EXTERN(void) jinit_arith_decoder (j_decompress_ptr cinfo);
-EXTERN(void) jinit_inverse_dct (j_decompress_ptr cinfo);
-EXTERN(void) jinit_upsampler (j_decompress_ptr cinfo);
-EXTERN(void) jinit_color_deconverter (j_decompress_ptr cinfo);
-EXTERN(void) jinit_1pass_quantizer (j_decompress_ptr cinfo);
-EXTERN(void) jinit_2pass_quantizer (j_decompress_ptr cinfo);
-EXTERN(void) jinit_merged_upsampler (j_decompress_ptr cinfo);
+EXTERN(void) jinit_master_decompress(j_decompress_ptr cinfo);
+EXTERN(void) jinit_d_main_controller(j_decompress_ptr cinfo,
+ boolean need_full_buffer);
+EXTERN(void) jinit_d_coef_controller(j_decompress_ptr cinfo,
+ boolean need_full_buffer);
+EXTERN(void) jinit_d_post_controller(j_decompress_ptr cinfo,
+ boolean need_full_buffer);
+EXTERN(void) jinit_input_controller(j_decompress_ptr cinfo);
+EXTERN(void) jinit_marker_reader(j_decompress_ptr cinfo);
+EXTERN(void) jinit_huff_decoder(j_decompress_ptr cinfo);
+EXTERN(void) jinit_phuff_decoder(j_decompress_ptr cinfo);
+EXTERN(void) jinit_arith_decoder(j_decompress_ptr cinfo);
+EXTERN(void) jinit_inverse_dct(j_decompress_ptr cinfo);
+EXTERN(void) jinit_upsampler(j_decompress_ptr cinfo);
+EXTERN(void) jinit_color_deconverter(j_decompress_ptr cinfo);
+EXTERN(void) jinit_1pass_quantizer(j_decompress_ptr cinfo);
+EXTERN(void) jinit_2pass_quantizer(j_decompress_ptr cinfo);
+EXTERN(void) jinit_merged_upsampler(j_decompress_ptr cinfo);
/* Memory manager initialization */
-EXTERN(void) jinit_memory_mgr (j_common_ptr cinfo);
+EXTERN(void) jinit_memory_mgr(j_common_ptr cinfo);
/* Utility routines in jutils.c */
-EXTERN(long) jdiv_round_up (long a, long b);
-EXTERN(long) jround_up (long a, long b);
-EXTERN(void) jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
- JSAMPARRAY output_array, int dest_row,
- int num_rows, JDIMENSION num_cols);
-EXTERN(void) jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row,
- JDIMENSION num_blocks);
-EXTERN(void) jzero_far (void *target, size_t bytestozero);
+EXTERN(long) jdiv_round_up(long a, long b);
+EXTERN(long) jround_up(long a, long b);
+EXTERN(void) jcopy_sample_rows(JSAMPARRAY input_array, int source_row,
+ JSAMPARRAY output_array, int dest_row,
+ int num_rows, JDIMENSION num_cols);
+EXTERN(void) jcopy_block_row(JBLOCKROW input_row, JBLOCKROW output_row,
+ JDIMENSION num_blocks);
+EXTERN(void) jzero_far(void *target, size_t bytestozero);
/* Constant tables in jutils.c */
#if 0 /* This table is not actually needed in v6a */
extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */
* Copyright (C) 1991-1998, Thomas G. Lane.
* Modified 2002-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2009-2011, 2013-2014, 2016, D. R. Commander.
+ * Copyright (C) 2009-2011, 2013-2014, 2016-2017, D. R. Commander.
* Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
/* Known color spaces. */
-#define JCS_EXTENSIONS 1
-#define JCS_ALPHA_EXTENSIONS 1
+#define JCS_EXTENSIONS 1
+#define JCS_ALPHA_EXTENSIONS 1
typedef enum {
JCS_UNKNOWN, /* error/unspecified */
/* Common fields between JPEG compression and decompression master structs. */
#define jpeg_common_fields \
- struct jpeg_error_mgr *err; /* Error handler module */\
- struct jpeg_memory_mgr *mem; /* Memory manager module */\
- struct jpeg_progress_mgr *progress; /* Progress monitor, or NULL if none */\
- void *client_data; /* Available for use by application */\
- boolean is_decompressor; /* So common code can tell which is which */\
+ struct jpeg_error_mgr *err; /* Error handler module */ \
+ struct jpeg_memory_mgr *mem; /* Memory manager module */ \
+ struct jpeg_progress_mgr *progress; /* Progress monitor, or NULL if none */ \
+ void *client_data; /* Available for use by application */ \
+ boolean is_decompressor; /* So common code can tell which is which */ \
int global_state /* For checking call sequence validity */
/* Routines that are to be used by both halves of the library are declared
* successful.
*/
-#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */
-#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */
-#define JPOOL_NUMPOOLS 2
+#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */
+#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */
+#define JPOOL_NUMPOOLS 2
typedef struct jvirt_sarray_control *jvirt_sarray_ptr;
typedef struct jvirt_barray_control *jvirt_barray_ptr;
/* Default error-management setup */
-EXTERN(struct jpeg_error_mgr *) jpeg_std_error (struct jpeg_error_mgr *err);
+EXTERN(struct jpeg_error_mgr *) jpeg_std_error(struct jpeg_error_mgr *err);
/* Initialization of JPEG compression objects.
* jpeg_create_compress() and jpeg_create_decompress() are the exported
* NB: you must set up the error-manager BEFORE calling jpeg_create_xxx.
*/
#define jpeg_create_compress(cinfo) \
- jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
- (size_t) sizeof(struct jpeg_compress_struct))
+ jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
+ (size_t)sizeof(struct jpeg_compress_struct))
#define jpeg_create_decompress(cinfo) \
- jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
- (size_t) sizeof(struct jpeg_decompress_struct))
-EXTERN(void) jpeg_CreateCompress (j_compress_ptr cinfo, int version,
- size_t structsize);
-EXTERN(void) jpeg_CreateDecompress (j_decompress_ptr cinfo, int version,
- size_t structsize);
+ jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
+ (size_t)sizeof(struct jpeg_decompress_struct))
+EXTERN(void) jpeg_CreateCompress(j_compress_ptr cinfo, int version,
+ size_t structsize);
+EXTERN(void) jpeg_CreateDecompress(j_decompress_ptr cinfo, int version,
+ size_t structsize);
/* Destruction of JPEG compression objects */
-EXTERN(void) jpeg_destroy_compress (j_compress_ptr cinfo);
-EXTERN(void) jpeg_destroy_decompress (j_decompress_ptr cinfo);
+EXTERN(void) jpeg_destroy_compress(j_compress_ptr cinfo);
+EXTERN(void) jpeg_destroy_decompress(j_decompress_ptr cinfo);
/* Standard data source and destination managers: stdio streams. */
/* Caller is responsible for opening the file before and closing after. */
-EXTERN(void) jpeg_stdio_dest (j_compress_ptr cinfo, FILE *outfile);
-EXTERN(void) jpeg_stdio_src (j_decompress_ptr cinfo, FILE *infile);
+EXTERN(void) jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile);
+EXTERN(void) jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile);
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
/* Data source and destination managers: memory buffers. */
-EXTERN(void) jpeg_mem_dest (j_compress_ptr cinfo, unsigned char **outbuffer,
- unsigned long *outsize);
-EXTERN(void) jpeg_mem_src (j_decompress_ptr cinfo,
- const unsigned char *inbuffer,
- unsigned long insize);
+EXTERN(void) jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer,
+ unsigned long *outsize);
+EXTERN(void) jpeg_mem_src(j_decompress_ptr cinfo,
+ const unsigned char *inbuffer, unsigned long insize);
#endif
/* Default parameter setup for compression */
-EXTERN(void) jpeg_set_defaults (j_compress_ptr cinfo);
+EXTERN(void) jpeg_set_defaults(j_compress_ptr cinfo);
/* Compression parameter setup aids */
-EXTERN(void) jpeg_set_colorspace (j_compress_ptr cinfo,
- J_COLOR_SPACE colorspace);
-EXTERN(void) jpeg_default_colorspace (j_compress_ptr cinfo);
-EXTERN(void) jpeg_set_quality (j_compress_ptr cinfo, int quality,
- boolean force_baseline);
-EXTERN(void) jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
- boolean force_baseline);
+EXTERN(void) jpeg_set_colorspace(j_compress_ptr cinfo,
+ J_COLOR_SPACE colorspace);
+EXTERN(void) jpeg_default_colorspace(j_compress_ptr cinfo);
+EXTERN(void) jpeg_set_quality(j_compress_ptr cinfo, int quality,
+ boolean force_baseline);
+EXTERN(void) jpeg_set_linear_quality(j_compress_ptr cinfo, int scale_factor,
+ boolean force_baseline);
#if JPEG_LIB_VERSION >= 70
-EXTERN(void) jpeg_default_qtables (j_compress_ptr cinfo,
- boolean force_baseline);
+EXTERN(void) jpeg_default_qtables(j_compress_ptr cinfo,
+ boolean force_baseline);
#endif
-EXTERN(void) jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
- const unsigned int *basic_table,
- int scale_factor, boolean force_baseline);
-EXTERN(int) jpeg_quality_scaling (int quality);
-EXTERN(void) jpeg_simple_progression (j_compress_ptr cinfo);
-EXTERN(void) jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress);
-EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table (j_common_ptr cinfo);
-EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table (j_common_ptr cinfo);
+EXTERN(void) jpeg_add_quant_table(j_compress_ptr cinfo, int which_tbl,
+ const unsigned int *basic_table,
+ int scale_factor, boolean force_baseline);
+EXTERN(int) jpeg_quality_scaling(int quality);
+EXTERN(void) jpeg_simple_progression(j_compress_ptr cinfo);
+EXTERN(void) jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress);
+EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table(j_common_ptr cinfo);
+EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table(j_common_ptr cinfo);
/* Main entry points for compression */
-EXTERN(void) jpeg_start_compress (j_compress_ptr cinfo,
- boolean write_all_tables);
-EXTERN(JDIMENSION) jpeg_write_scanlines (j_compress_ptr cinfo,
- JSAMPARRAY scanlines,
- JDIMENSION num_lines);
-EXTERN(void) jpeg_finish_compress (j_compress_ptr cinfo);
+EXTERN(void) jpeg_start_compress(j_compress_ptr cinfo,
+ boolean write_all_tables);
+EXTERN(JDIMENSION) jpeg_write_scanlines(j_compress_ptr cinfo,
+ JSAMPARRAY scanlines,
+ JDIMENSION num_lines);
+EXTERN(void) jpeg_finish_compress(j_compress_ptr cinfo);
#if JPEG_LIB_VERSION >= 70
/* Precalculate JPEG dimensions for current compression parameters. */
-EXTERN(void) jpeg_calc_jpeg_dimensions (j_compress_ptr cinfo);
+EXTERN(void) jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo);
#endif
/* Replaces jpeg_write_scanlines when writing raw downsampled data. */
-EXTERN(JDIMENSION) jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
- JDIMENSION num_lines);
+EXTERN(JDIMENSION) jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data,
+ JDIMENSION num_lines);
/* Write a special marker. See libjpeg.txt concerning safe usage. */
-EXTERN(void) jpeg_write_marker (j_compress_ptr cinfo, int marker,
- const JOCTET *dataptr, unsigned int datalen);
+EXTERN(void) jpeg_write_marker(j_compress_ptr cinfo, int marker,
+ const JOCTET *dataptr, unsigned int datalen);
/* Same, but piecemeal. */
-EXTERN(void) jpeg_write_m_header (j_compress_ptr cinfo, int marker,
- unsigned int datalen);
-EXTERN(void) jpeg_write_m_byte (j_compress_ptr cinfo, int val);
+EXTERN(void) jpeg_write_m_header(j_compress_ptr cinfo, int marker,
+ unsigned int datalen);
+EXTERN(void) jpeg_write_m_byte(j_compress_ptr cinfo, int val);
/* Alternate compression function: just write an abbreviated table file */
-EXTERN(void) jpeg_write_tables (j_compress_ptr cinfo);
+EXTERN(void) jpeg_write_tables(j_compress_ptr cinfo);
+
+/* Write ICC profile. See libjpeg.txt for usage information. */
+EXTERN(void) jpeg_write_icc_profile(j_compress_ptr cinfo,
+ const JOCTET *icc_data_ptr,
+ unsigned int icc_data_len);
+
/* Decompression startup: read start of JPEG datastream to see what's there */
-EXTERN(int) jpeg_read_header (j_decompress_ptr cinfo, boolean require_image);
+EXTERN(int) jpeg_read_header(j_decompress_ptr cinfo, boolean require_image);
/* Return value is one of: */
-#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */
-#define JPEG_HEADER_OK 1 /* Found valid image datastream */
-#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */
+#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */
+#define JPEG_HEADER_OK 1 /* Found valid image datastream */
+#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */
/* If you pass require_image = TRUE (normal case), you need not check for
* a TABLES_ONLY return code; an abbreviated file will cause an error exit.
* JPEG_SUSPENDED is only possible if you use a data source module that can
*/
/* Main entry points for decompression */
-EXTERN(boolean) jpeg_start_decompress (j_decompress_ptr cinfo);
-EXTERN(JDIMENSION) jpeg_read_scanlines (j_decompress_ptr cinfo,
- JSAMPARRAY scanlines,
- JDIMENSION max_lines);
-EXTERN(JDIMENSION) jpeg_skip_scanlines (j_decompress_ptr cinfo,
- JDIMENSION num_lines);
-EXTERN(void) jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
- JDIMENSION *width);
-EXTERN(boolean) jpeg_finish_decompress (j_decompress_ptr cinfo);
+EXTERN(boolean) jpeg_start_decompress(j_decompress_ptr cinfo);
+EXTERN(JDIMENSION) jpeg_read_scanlines(j_decompress_ptr cinfo,
+ JSAMPARRAY scanlines,
+ JDIMENSION max_lines);
+EXTERN(JDIMENSION) jpeg_skip_scanlines(j_decompress_ptr cinfo,
+ JDIMENSION num_lines);
+EXTERN(void) jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset,
+ JDIMENSION *width);
+EXTERN(boolean) jpeg_finish_decompress(j_decompress_ptr cinfo);
/* Replaces jpeg_read_scanlines when reading raw downsampled data. */
-EXTERN(JDIMENSION) jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
- JDIMENSION max_lines);
+EXTERN(JDIMENSION) jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data,
+ JDIMENSION max_lines);
/* Additional entry points for buffered-image mode. */
-EXTERN(boolean) jpeg_has_multiple_scans (j_decompress_ptr cinfo);
-EXTERN(boolean) jpeg_start_output (j_decompress_ptr cinfo, int scan_number);
-EXTERN(boolean) jpeg_finish_output (j_decompress_ptr cinfo);
-EXTERN(boolean) jpeg_input_complete (j_decompress_ptr cinfo);
-EXTERN(void) jpeg_new_colormap (j_decompress_ptr cinfo);
-EXTERN(int) jpeg_consume_input (j_decompress_ptr cinfo);
+EXTERN(boolean) jpeg_has_multiple_scans(j_decompress_ptr cinfo);
+EXTERN(boolean) jpeg_start_output(j_decompress_ptr cinfo, int scan_number);
+EXTERN(boolean) jpeg_finish_output(j_decompress_ptr cinfo);
+EXTERN(boolean) jpeg_input_complete(j_decompress_ptr cinfo);
+EXTERN(void) jpeg_new_colormap(j_decompress_ptr cinfo);
+EXTERN(int) jpeg_consume_input(j_decompress_ptr cinfo);
/* Return value is one of: */
/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */
#define JPEG_REACHED_SOS 1 /* Reached start of new scan */
/* Precalculate output dimensions for current decompression parameters. */
#if JPEG_LIB_VERSION >= 80
-EXTERN(void) jpeg_core_output_dimensions (j_decompress_ptr cinfo);
+EXTERN(void) jpeg_core_output_dimensions(j_decompress_ptr cinfo);
#endif
-EXTERN(void) jpeg_calc_output_dimensions (j_decompress_ptr cinfo);
+EXTERN(void) jpeg_calc_output_dimensions(j_decompress_ptr cinfo);
/* Control saving of COM and APPn markers into marker_list. */
-EXTERN(void) jpeg_save_markers (j_decompress_ptr cinfo, int marker_code,
- unsigned int length_limit);
+EXTERN(void) jpeg_save_markers(j_decompress_ptr cinfo, int marker_code,
+ unsigned int length_limit);
/* Install a special processing method for COM or APPn markers. */
-EXTERN(void) jpeg_set_marker_processor (j_decompress_ptr cinfo,
- int marker_code,
- jpeg_marker_parser_method routine);
+EXTERN(void) jpeg_set_marker_processor(j_decompress_ptr cinfo,
+ int marker_code,
+ jpeg_marker_parser_method routine);
/* Read or write raw DCT coefficients --- useful for lossless transcoding. */
-EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients (j_decompress_ptr cinfo);
-EXTERN(void) jpeg_write_coefficients (j_compress_ptr cinfo,
- jvirt_barray_ptr *coef_arrays);
-EXTERN(void) jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
- j_compress_ptr dstinfo);
+EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients(j_decompress_ptr cinfo);
+EXTERN(void) jpeg_write_coefficients(j_compress_ptr cinfo,
+ jvirt_barray_ptr *coef_arrays);
+EXTERN(void) jpeg_copy_critical_parameters(j_decompress_ptr srcinfo,
+ j_compress_ptr dstinfo);
/* If you choose to abort compression or decompression before completing
* jpeg_finish_(de)compress, then you need to clean up to release memory,
* if you're done with the JPEG object, but if you want to clean it up and
* reuse it, call this:
*/
-EXTERN(void) jpeg_abort_compress (j_compress_ptr cinfo);
-EXTERN(void) jpeg_abort_decompress (j_decompress_ptr cinfo);
+EXTERN(void) jpeg_abort_compress(j_compress_ptr cinfo);
+EXTERN(void) jpeg_abort_decompress(j_decompress_ptr cinfo);
/* Generic versions of jpeg_abort and jpeg_destroy that work on either
* flavor of JPEG object. These may be more convenient in some places.
*/
-EXTERN(void) jpeg_abort (j_common_ptr cinfo);
-EXTERN(void) jpeg_destroy (j_common_ptr cinfo);
+EXTERN(void) jpeg_abort(j_common_ptr cinfo);
+EXTERN(void) jpeg_destroy(j_common_ptr cinfo);
/* Default restart-marker-resync procedure for use by data source modules */
-EXTERN(boolean) jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired);
+EXTERN(boolean) jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired);
+
+/* Read ICC profile. See libjpeg.txt for usage information. */
+EXTERN(boolean) jpeg_read_icc_profile(j_decompress_ptr cinfo,
+ JOCTET **icc_data_ptr,
+ unsigned int *icc_data_len);
/* These marker codes are exported since applications and data source modules
#define ODITHER_SIZE 16 /* dimension of dither matrix */
/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */
-#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */
-#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */
+#define ODITHER_CELLS (ODITHER_SIZE * ODITHER_SIZE) /* # cells in matrix */
+#define ODITHER_MASK (ODITHER_SIZE - 1) /* mask for wrapping around
+ counters */
typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE];
typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE];
typedef JLONG LOCFSERROR; /* be sure calculation temps are big enough */
#endif
-typedef FSERROR *FSERRPTR; /* pointer to error array */
+typedef FSERROR *FSERRPTR; /* pointer to error array */
/* Private subobject */
-#define MAX_Q_COMPS 4 /* max components I can handle */
+#define MAX_Q_COMPS 4 /* max components I can handle */
typedef struct {
struct jpeg_color_quantizer pub; /* public fields */
*/
boolean is_padded; /* is the colorindex padded for odither? */
- int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */
+ int Ncolors[MAX_Q_COMPS]; /* # of values allocated to each component */
/* Variables for ordered dithering */
int row_index; /* cur row's vertical index in dither matrix */
LOCAL(int)
-select_ncolors (j_decompress_ptr cinfo, int Ncolors[])
+select_ncolors(j_decompress_ptr cinfo, int Ncolors[])
/* Determine allocation of desired colors to components, */
/* and fill in Ncolors[] array to indicate choice. */
/* Return value is total number of colors (product of Ncolors[] values). */
temp = iroot; /* set temp = iroot ** nc */
for (i = 1; i < nc; i++)
temp *= iroot;
- } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */
+ } while (temp <= (long)max_colors); /* repeat till iroot exceeds root */
iroot--; /* now iroot = floor(root) */
/* Must have at least 2 color values per component */
if (iroot < 2)
- ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp);
+ ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int)temp);
/* Initialize to iroot color values for each component */
total_colors = 1;
j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i);
/* calculate new total_colors if Ncolors[j] is incremented */
temp = total_colors / Ncolors[j];
- temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */
- if (temp > (long) max_colors)
+ temp *= Ncolors[j] + 1; /* done in long arith to avoid oflo */
+ if (temp > (long)max_colors)
break; /* won't fit, done with this pass */
Ncolors[j]++; /* OK, apply the increment */
- total_colors = (int) temp;
+ total_colors = (int)temp;
changed = TRUE;
}
} while (changed);
LOCAL(int)
-output_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
+output_value(j_decompress_ptr cinfo, int ci, int j, int maxj)
/* Return j'th output value, where j will range from 0 to maxj */
/* The output values must fall in 0..MAXJSAMPLE in increasing order */
{
* (Forcing the upper and lower values to the limits ensures that
* dithering can't produce a color outside the selected gamut.)
*/
- return (int) (((JLONG) j * MAXJSAMPLE + maxj/2) / maxj);
+ return (int)(((JLONG)j * MAXJSAMPLE + maxj / 2) / maxj);
}
LOCAL(int)
-largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
+largest_input_value(j_decompress_ptr cinfo, int ci, int j, int maxj)
/* Return largest input value that should map to j'th output value */
/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */
{
/* Breakpoints are halfway between values returned by output_value */
- return (int) (((JLONG) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj));
+ return (int)(((JLONG)(2 * j + 1) * MAXJSAMPLE + maxj) / (2 * maxj));
}
*/
LOCAL(void)
-create_colormap (j_decompress_ptr cinfo)
+create_colormap(j_decompress_ptr cinfo)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
JSAMPARRAY colormap; /* Created colormap */
int total_colors; /* Number of distinct output colors */
- int i,j,k, nci, blksize, blkdist, ptr, val;
+ int i, j, k, nci, blksize, blkdist, ptr, val;
/* Select number of colors for each component */
total_colors = select_ncolors(cinfo, cquantize->Ncolors);
/* Report selected color counts */
if (cinfo->out_color_components == 3)
- TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS,
- total_colors, cquantize->Ncolors[0],
- cquantize->Ncolors[1], cquantize->Ncolors[2]);
+ TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, total_colors,
+ cquantize->Ncolors[0], cquantize->Ncolors[1],
+ cquantize->Ncolors[2]);
else
TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors);
/* i.e. rightmost (highest-indexed) color changes most rapidly. */
colormap = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components);
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (JDIMENSION)total_colors, (JDIMENSION)cinfo->out_color_components);
/* blksize is number of adjacent repeated entries for a component */
/* blkdist is distance between groups of identical entries for a component */
blksize = blkdist / nci;
for (j = 0; j < nci; j++) {
/* Compute j'th output value (out of nci) for component */
- val = output_value(cinfo, i, j, nci-1);
+ val = output_value(cinfo, i, j, nci - 1);
/* Fill in all colormap entries that have this value of this component */
for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) {
/* fill in blksize entries beginning at ptr */
for (k = 0; k < blksize; k++)
- colormap[i][ptr+k] = (JSAMPLE) val;
+ colormap[i][ptr + k] = (JSAMPLE)val;
}
}
blkdist = blksize; /* blksize of this color is blkdist of next */
*/
LOCAL(void)
-create_colorindex (j_decompress_ptr cinfo)
+create_colorindex(j_decompress_ptr cinfo)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
JSAMPROW indexptr;
- int i,j,k, nci, blksize, val, pad;
+ int i, j, k, nci, blksize, val, pad;
/* For ordered dither, we pad the color index tables by MAXJSAMPLE in
* each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE).
* flag whether it was done in case user changes dithering mode.
*/
if (cinfo->dither_mode == JDITHER_ORDERED) {
- pad = MAXJSAMPLE*2;
+ pad = MAXJSAMPLE * 2;
cquantize->is_padded = TRUE;
} else {
pad = 0;
}
cquantize->colorindex = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (JDIMENSION) (MAXJSAMPLE+1 + pad),
- (JDIMENSION) cinfo->out_color_components);
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (JDIMENSION)(MAXJSAMPLE + 1 + pad),
+ (JDIMENSION)cinfo->out_color_components);
/* blksize is number of adjacent repeated entries for a component */
blksize = cquantize->sv_actual;
/* and k = largest j that maps to current val */
indexptr = cquantize->colorindex[i];
val = 0;
- k = largest_input_value(cinfo, i, 0, nci-1);
+ k = largest_input_value(cinfo, i, 0, nci - 1);
for (j = 0; j <= MAXJSAMPLE; j++) {
while (j > k) /* advance val if past boundary */
- k = largest_input_value(cinfo, i, ++val, nci-1);
+ k = largest_input_value(cinfo, i, ++val, nci - 1);
/* premultiply so that no multiplication needed in main processing */
- indexptr[j] = (JSAMPLE) (val * blksize);
+ indexptr[j] = (JSAMPLE)(val * blksize);
}
/* Pad at both ends if necessary */
if (pad)
for (j = 1; j <= MAXJSAMPLE; j++) {
indexptr[-j] = indexptr[0];
- indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE];
+ indexptr[MAXJSAMPLE + j] = indexptr[MAXJSAMPLE];
}
}
}
*/
LOCAL(ODITHER_MATRIX_PTR)
-make_odither_array (j_decompress_ptr cinfo, int ncolors)
+make_odither_array(j_decompress_ptr cinfo, int ncolors)
{
ODITHER_MATRIX_PTR odither;
- int j,k;
- JLONG num,den;
+ int j, k;
+ JLONG num, den;
odither = (ODITHER_MATRIX_PTR)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(ODITHER_MATRIX));
/* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1).
* Hence the dither value for the matrix cell with fill order f
* (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1).
* On 16-bit-int machine, be careful to avoid overflow.
*/
- den = 2 * ODITHER_CELLS * ((JLONG) (ncolors - 1));
+ den = 2 * ODITHER_CELLS * ((JLONG)(ncolors - 1));
for (j = 0; j < ODITHER_SIZE; j++) {
for (k = 0; k < ODITHER_SIZE; k++) {
- num = ((JLONG) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k])))
- * MAXJSAMPLE;
+ num = ((JLONG)(ODITHER_CELLS - 1 -
+ 2 * ((int)base_dither_matrix[j][k]))) * MAXJSAMPLE;
/* Ensure round towards zero despite C's lack of consistency
* about rounding negative values in integer division...
*/
- odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den);
+ odither[j][k] = (int)(num < 0 ? -((-num) / den) : num / den);
}
}
return odither;
*/
LOCAL(void)
-create_odither_tables (j_decompress_ptr cinfo)
+create_odither_tables(j_decompress_ptr cinfo)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
ODITHER_MATRIX_PTR odither;
int i, j, nci;
*/
METHODDEF(void)
-color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
- JSAMPARRAY output_buf, int num_rows)
+color_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
/* General case, no dithering */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
JSAMPARRAY colorindex = cquantize->colorindex;
register int pixcode, ci;
register JSAMPROW ptrin, ptrout;
for (ci = 0; ci < nc; ci++) {
pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]);
}
- *ptrout++ = (JSAMPLE) pixcode;
+ *ptrout++ = (JSAMPLE)pixcode;
}
}
}
METHODDEF(void)
-color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
- JSAMPARRAY output_buf, int num_rows)
+color_quantize3(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
/* Fast path for out_color_components==3, no dithering */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
register int pixcode;
register JSAMPROW ptrin, ptrout;
JSAMPROW colorindex0 = cquantize->colorindex[0];
pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]);
pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]);
pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]);
- *ptrout++ = (JSAMPLE) pixcode;
+ *ptrout++ = (JSAMPLE)pixcode;
}
}
}
METHODDEF(void)
-quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
- JSAMPARRAY output_buf, int num_rows)
+quantize_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
/* General case, with ordered dithering */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
register JSAMPROW input_ptr;
register JSAMPROW output_ptr;
JSAMPROW colorindex_ci;
for (row = 0; row < num_rows; row++) {
/* Initialize output values to 0 so can process components separately */
- jzero_far((void *) output_buf[row], (size_t) (width * sizeof(JSAMPLE)));
+ jzero_far((void *)output_buf[row], (size_t)(width * sizeof(JSAMPLE)));
row_index = cquantize->row_index;
for (ci = 0; ci < nc; ci++) {
input_ptr = input_buf[row] + ci;
* inputs. The maximum dither is +- MAXJSAMPLE; this sets the
* required amount of padding.
*/
- *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]];
+ *output_ptr +=
+ colorindex_ci[GETJSAMPLE(*input_ptr) + dither[col_index]];
input_ptr += nc;
output_ptr++;
col_index = (col_index + 1) & ODITHER_MASK;
METHODDEF(void)
-quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
- JSAMPARRAY output_buf, int num_rows)
+quantize3_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
/* Fast path for out_color_components==3, with ordered dithering */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
register int pixcode;
register JSAMPROW input_ptr;
register JSAMPROW output_ptr;
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]]);
- *output_ptr++ = (JSAMPLE) pixcode;
+ 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]]);
+ *output_ptr++ = (JSAMPLE)pixcode;
col_index = (col_index + 1) & ODITHER_MASK;
}
row_index = (row_index + 1) & ODITHER_MASK;
METHODDEF(void)
-quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
- JSAMPARRAY output_buf, int num_rows)
+quantize_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
/* General case, with Floyd-Steinberg dithering */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
register LOCFSERROR cur; /* current error or pixel value */
LOCFSERROR belowerr; /* error for pixel below cur */
LOCFSERROR bpreverr; /* error for below/prev col */
for (row = 0; row < num_rows; row++) {
/* Initialize output values to 0 so can process components separately */
- jzero_far((void *) output_buf[row], (size_t) (width * sizeof(JSAMPLE)));
+ jzero_far((void *)output_buf[row], (size_t)(width * sizeof(JSAMPLE)));
for (ci = 0; ci < nc; ci++) {
input_ptr = input_buf[row] + ci;
output_ptr = output_buf[row];
if (cquantize->on_odd_row) {
/* work right to left in this row */
- input_ptr += (width-1) * nc; /* so point to rightmost pixel */
- output_ptr += width-1;
+ input_ptr += (width - 1) * nc; /* so point to rightmost pixel */
+ output_ptr += width - 1;
dir = -1;
dirnc = -nc;
- errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */
+ errorptr = cquantize->fserrors[ci] + (width + 1); /* => entry after last column */
} else {
/* work left to right in this row */
dir = 1;
cur = GETJSAMPLE(range_limit[cur]);
/* Select output value, accumulate into output code for this pixel */
pixcode = GETJSAMPLE(colorindex_ci[cur]);
- *output_ptr += (JSAMPLE) pixcode;
+ *output_ptr += (JSAMPLE)pixcode;
/* Compute actual representation error at this pixel */
/* Note: we can do this even though we don't have the final */
/* pixel code, because the colormap is orthogonal. */
bnexterr = cur;
delta = cur * 2;
cur += delta; /* form error * 3 */
- errorptr[0] = (FSERROR) (bpreverr + cur);
+ errorptr[0] = (FSERROR)(bpreverr + cur);
cur += delta; /* form error * 5 */
bpreverr = belowerr + cur;
belowerr = bnexterr;
* final fserrors[] entry. Note we need not unload belowerr because
* it is for the dummy column before or after the actual array.
*/
- errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */
+ errorptr[0] = (FSERROR)bpreverr; /* unload prev err into array */
}
cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE);
}
*/
LOCAL(void)
-alloc_fs_workspace (j_decompress_ptr cinfo)
+alloc_fs_workspace(j_decompress_ptr cinfo)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
size_t arraysize;
int i;
- arraysize = (size_t) ((cinfo->output_width + 2) * sizeof(FSERROR));
+ arraysize = (size_t)((cinfo->output_width + 2) * sizeof(FSERROR));
for (i = 0; i < cinfo->out_color_components; i++) {
cquantize->fserrors[i] = (FSERRPTR)
- (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
+ (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE, arraysize);
}
}
*/
METHODDEF(void)
-start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
+start_pass_1_quant(j_decompress_ptr cinfo, boolean is_pre_scan)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
size_t arraysize;
int i;
* we must recreate the color index table with padding.
* This will cost extra space, but probably isn't very likely.
*/
- if (! cquantize->is_padded)
+ if (!cquantize->is_padded)
create_colorindex(cinfo);
/* Create ordered-dither tables if we didn't already. */
if (cquantize->odither[0] == NULL)
if (cquantize->fserrors[0] == NULL)
alloc_fs_workspace(cinfo);
/* Initialize the propagated errors to zero. */
- arraysize = (size_t) ((cinfo->output_width + 2) * sizeof(FSERROR));
+ arraysize = (size_t)((cinfo->output_width + 2) * sizeof(FSERROR));
for (i = 0; i < cinfo->out_color_components; i++)
- jzero_far((void *) cquantize->fserrors[i], arraysize);
+ jzero_far((void *)cquantize->fserrors[i], arraysize);
break;
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
*/
METHODDEF(void)
-finish_pass_1_quant (j_decompress_ptr cinfo)
+finish_pass_1_quant(j_decompress_ptr cinfo)
{
/* no work in 1-pass case */
}
*/
METHODDEF(void)
-new_color_map_1_quant (j_decompress_ptr cinfo)
+new_color_map_1_quant(j_decompress_ptr cinfo)
{
ERREXIT(cinfo, JERR_MODE_CHANGE);
}
*/
GLOBAL(void)
-jinit_1pass_quantizer (j_decompress_ptr cinfo)
+jinit_1pass_quantizer(j_decompress_ptr cinfo)
{
my_cquantize_ptr cquantize;
cquantize = (my_cquantize_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_cquantizer));
- cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
+ cinfo->cquantize = (struct jpeg_color_quantizer *)cquantize;
cquantize->pub.start_pass = start_pass_1_quant;
cquantize->pub.finish_pass = finish_pass_1_quant;
cquantize->pub.new_color_map = new_color_map_1_quant;
if (cinfo->out_color_components > MAX_Q_COMPS)
ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS);
/* Make sure colormap indexes can be represented by JSAMPLEs */
- if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1))
- ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1);
+ if (cinfo->desired_number_of_colors > (MAXJSAMPLE + 1))
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE + 1);
/* Create the colormap and color index table. */
create_colormap(cinfo);
* probably need to change these scale factors.
*/
-#define R_SCALE 2 /* scale R distances by this much */
-#define G_SCALE 3 /* scale G distances by this much */
-#define B_SCALE 1 /* and B by this much */
+#define R_SCALE 2 /* scale R distances by this much */
+#define G_SCALE 3 /* scale G distances by this much */
+#define B_SCALE 1 /* and B by this much */
-static const int c_scales[3]={R_SCALE, G_SCALE, B_SCALE};
-#define C0_SCALE c_scales[rgb_red[cinfo->out_color_space]]
-#define C1_SCALE c_scales[rgb_green[cinfo->out_color_space]]
-#define C2_SCALE c_scales[rgb_blue[cinfo->out_color_space]]
+static const int c_scales[3] = { R_SCALE, G_SCALE, B_SCALE };
+#define C0_SCALE c_scales[rgb_red[cinfo->out_color_space]]
+#define C1_SCALE c_scales[rgb_green[cinfo->out_color_space]]
+#define C2_SCALE c_scales[rgb_blue[cinfo->out_color_space]]
/*
* First we have the histogram data structure and routines for creating it.
* each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries.
*/
-#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */
+#define MAXNUMCOLORS (MAXJSAMPLE + 1) /* maximum size of colormap */
/* These will do the right thing for either R,G,B or B,G,R color order,
* but you may not like the results for other color orders.
#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */
/* Number of elements along histogram axes. */
-#define HIST_C0_ELEMS (1<<HIST_C0_BITS)
-#define HIST_C1_ELEMS (1<<HIST_C1_BITS)
-#define HIST_C2_ELEMS (1<<HIST_C2_BITS)
+#define HIST_C0_ELEMS (1 << HIST_C0_BITS)
+#define HIST_C1_ELEMS (1 << HIST_C1_BITS)
+#define HIST_C2_ELEMS (1 << HIST_C2_BITS)
/* These are the amounts to shift an input value to get a histogram index. */
-#define C0_SHIFT (BITS_IN_JSAMPLE-HIST_C0_BITS)
-#define C1_SHIFT (BITS_IN_JSAMPLE-HIST_C1_BITS)
-#define C2_SHIFT (BITS_IN_JSAMPLE-HIST_C2_BITS)
+#define C0_SHIFT (BITS_IN_JSAMPLE - HIST_C0_BITS)
+#define C1_SHIFT (BITS_IN_JSAMPLE - HIST_C1_BITS)
+#define C2_SHIFT (BITS_IN_JSAMPLE - HIST_C2_BITS)
typedef UINT16 histcell; /* histogram cell; prefer an unsigned type */
-typedef histcell *histptr; /* for pointers to histogram cells */
+typedef histcell *histptr; /* for pointers to histogram cells */
typedef histcell hist1d[HIST_C2_ELEMS]; /* typedefs for the array */
typedef hist1d *hist2d; /* type for the 2nd-level pointers */
*/
METHODDEF(void)
-prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
- JSAMPARRAY output_buf, int num_rows)
+prescan_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
register JSAMPROW ptr;
register histptr histp;
register hist3d histogram = cquantize->histogram;
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[GETJSAMPLE(ptr[0]) >> C0_SHIFT]
+ [GETJSAMPLE(ptr[1]) >> C1_SHIFT]
+ [GETJSAMPLE(ptr[2]) >> C2_SHIFT];
/* increment, check for overflow and undo increment if so. */
if (++(*histp) <= 0)
(*histp)--;
LOCAL(boxptr)
-find_biggest_color_pop (boxptr boxlist, int numboxes)
+find_biggest_color_pop(boxptr boxlist, int numboxes)
/* Find the splittable box with the largest color population */
/* Returns NULL if no splittable boxes remain */
{
LOCAL(boxptr)
-find_biggest_volume (boxptr boxlist, int numboxes)
+find_biggest_volume(boxptr boxlist, int numboxes)
/* Find the splittable box with the largest (scaled) volume */
/* Returns NULL if no splittable boxes remain */
{
LOCAL(void)
-update_box (j_decompress_ptr cinfo, boxptr boxp)
+update_box(j_decompress_ptr cinfo, boxptr boxp)
/* Shrink the min/max bounds of a box to enclose only nonzero elements, */
/* and recompute its volume and population */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
hist3d histogram = cquantize->histogram;
histptr histp;
- int c0,c1,c2;
- int c0min,c0max,c1min,c1max,c2min,c2max;
- JLONG dist0,dist1,dist2;
+ int c0, c1, c2;
+ int c0min, c0max, c1min, c1max, c2min, c2max;
+ JLONG dist0, dist1, dist2;
long ccount;
c0min = boxp->c0min; c0max = boxp->c0max;
if (c0max > c0min)
for (c0 = c0min; c0 <= c0max; c0++)
for (c1 = c1min; c1 <= c1max; c1++) {
- histp = & histogram[c0][c1][c2min];
+ histp = &histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++)
if (*histp++ != 0) {
boxp->c0min = c0min = c0;
goto have_c0min;
}
}
- have_c0min:
+have_c0min:
if (c0max > c0min)
for (c0 = c0max; c0 >= c0min; c0--)
for (c1 = c1min; c1 <= c1max; c1++) {
- histp = & histogram[c0][c1][c2min];
+ histp = &histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++)
if (*histp++ != 0) {
boxp->c0max = c0max = c0;
goto have_c0max;
}
}
- have_c0max:
+have_c0max:
if (c1max > c1min)
for (c1 = c1min; c1 <= c1max; c1++)
for (c0 = c0min; c0 <= c0max; c0++) {
- histp = & histogram[c0][c1][c2min];
+ histp = &histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++)
if (*histp++ != 0) {
boxp->c1min = c1min = c1;
goto have_c1min;
}
}
- have_c1min:
+have_c1min:
if (c1max > c1min)
for (c1 = c1max; c1 >= c1min; c1--)
for (c0 = c0min; c0 <= c0max; c0++) {
- histp = & histogram[c0][c1][c2min];
+ histp = &histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++)
if (*histp++ != 0) {
boxp->c1max = c1max = c1;
goto have_c1max;
}
}
- have_c1max:
+have_c1max:
if (c2max > c2min)
for (c2 = c2min; c2 <= c2max; c2++)
for (c0 = c0min; c0 <= c0max; c0++) {
- histp = & histogram[c0][c1min][c2];
+ histp = &histogram[c0][c1min][c2];
for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
if (*histp != 0) {
boxp->c2min = c2min = c2;
goto have_c2min;
}
}
- have_c2min:
+have_c2min:
if (c2max > c2min)
for (c2 = c2max; c2 >= c2min; c2--)
for (c0 = c0min; c0 <= c0max; c0++) {
- histp = & histogram[c0][c1min][c2];
+ histp = &histogram[c0][c1min][c2];
for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
if (*histp != 0) {
boxp->c2max = c2max = c2;
goto have_c2max;
}
}
- have_c2max:
+have_c2max:
/* Update box volume.
* We use 2-norm rather than real volume here; this biases the method
dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE;
dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE;
dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE;
- boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2;
+ boxp->volume = dist0 * dist0 + dist1 * dist1 + dist2 * dist2;
/* Now scan remaining volume of box and compute population */
ccount = 0;
for (c0 = c0min; c0 <= c0max; c0++)
for (c1 = c1min; c1 <= c1max; c1++) {
- histp = & histogram[c0][c1][c2min];
+ histp = &histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++, histp++)
if (*histp != 0) {
ccount++;
LOCAL(int)
-median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
- int desired_colors)
+median_cut(j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
+ int desired_colors)
/* Repeatedly select and split the largest box until we have enough boxes */
{
- int n,lb;
- int c0,c1,c2,cmax;
- register boxptr b1,b2;
+ int n, lb;
+ int c0, c1, c2, cmax;
+ register boxptr b1, b2;
while (numboxes < desired_colors) {
/* Select box to split.
* Current algorithm: by population for first half, then by volume.
*/
- if (numboxes*2 <= desired_colors) {
+ if (numboxes * 2 <= desired_colors) {
b1 = find_biggest_color_pop(boxlist, numboxes);
} else {
b1 = find_biggest_volume(boxlist, numboxes);
break;
b2 = &boxlist[numboxes]; /* where new box will go */
/* Copy the color bounds to the new box. */
- b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max;
- b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min;
+ b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max;
+ b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min;
/* Choose which axis to split the box on.
* Current algorithm: longest scaled axis.
* See notes in update_box about scaling distances.
* This code does the right thing for R,G,B or B,G,R color orders only.
*/
if (rgb_red[cinfo->out_color_space] == 0) {
- cmax = c1; n = 1;
- if (c0 > cmax) { cmax = c0; n = 0; }
+ cmax = c1; n = 1;
+ if (c0 > cmax) { cmax = c0; n = 0; }
if (c2 > cmax) { n = 2; }
- }
- else {
- cmax = c1; n = 1;
- if (c2 > cmax) { cmax = c2; n = 2; }
+ } else {
+ cmax = c1; n = 1;
+ if (c2 > cmax) { cmax = c2; n = 2; }
if (c0 > cmax) { n = 0; }
}
/* Choose split point along selected axis, and update box bounds.
case 0:
lb = (b1->c0max + b1->c0min) / 2;
b1->c0max = lb;
- b2->c0min = lb+1;
+ b2->c0min = lb + 1;
break;
case 1:
lb = (b1->c1max + b1->c1min) / 2;
b1->c1max = lb;
- b2->c1min = lb+1;
+ b2->c1min = lb + 1;
break;
case 2:
lb = (b1->c2max + b1->c2min) / 2;
b1->c2max = lb;
- b2->c2min = lb+1;
+ b2->c2min = lb + 1;
break;
}
/* Update stats for boxes */
LOCAL(void)
-compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor)
+compute_color(j_decompress_ptr cinfo, boxptr boxp, int icolor)
/* Compute representative color for a box, put it in colormap[icolor] */
{
/* Current algorithm: mean weighted by pixels (not colors) */
/* Note it is important to get the rounding correct! */
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
hist3d histogram = cquantize->histogram;
histptr histp;
- int c0,c1,c2;
- int c0min,c0max,c1min,c1max,c2min,c2max;
+ int c0, c1, c2;
+ int c0min, c0max, c1min, c1max, c2min, c2max;
long count;
long total = 0;
long c0total = 0;
for (c0 = c0min; c0 <= c0max; c0++)
for (c1 = c1min; c1 <= c1max; c1++) {
- histp = & histogram[c0][c1][c2min];
+ histp = &histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++) {
if ((count = *histp++) != 0) {
total += count;
- c0total += ((c0 << C0_SHIFT) + ((1<<C0_SHIFT)>>1)) * count;
- c1total += ((c1 << C1_SHIFT) + ((1<<C1_SHIFT)>>1)) * count;
- c2total += ((c2 << C2_SHIFT) + ((1<<C2_SHIFT)>>1)) * count;
+ c0total += ((c0 << C0_SHIFT) + ((1 << C0_SHIFT) >> 1)) * count;
+ c1total += ((c1 << C1_SHIFT) + ((1 << C1_SHIFT) >> 1)) * count;
+ c2total += ((c2 << C2_SHIFT) + ((1 << C2_SHIFT) >> 1)) * count;
}
}
}
- cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total);
- cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total);
- cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total);
+ cinfo->colormap[0][icolor] = (JSAMPLE)((c0total + (total >> 1)) / total);
+ cinfo->colormap[1][icolor] = (JSAMPLE)((c1total + (total >> 1)) / total);
+ cinfo->colormap[2][icolor] = (JSAMPLE)((c2total + (total >> 1)) / total);
}
LOCAL(void)
-select_colors (j_decompress_ptr cinfo, int desired_colors)
+select_colors(j_decompress_ptr cinfo, int desired_colors)
/* Master routine for color selection */
{
boxptr boxlist;
int i;
/* Allocate workspace for box list */
- boxlist = (boxptr) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * sizeof(box));
+ boxlist = (boxptr)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, desired_colors * sizeof(box));
/* Initialize one box containing whole space */
numboxes = 1;
boxlist[0].c0min = 0;
boxlist[0].c2min = 0;
boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT;
/* Shrink it to actually-used volume and set its statistics */
- update_box(cinfo, & boxlist[0]);
+ update_box(cinfo, &boxlist[0]);
/* Perform median-cut to produce final box list */
numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors);
/* Compute the representative color for each box, fill colormap */
for (i = 0; i < numboxes; i++)
- compute_color(cinfo, & boxlist[i], i);
+ compute_color(cinfo, &boxlist[i], i);
cinfo->actual_number_of_colors = numboxes;
TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes);
}
/* log2(histogram cells in update box) for each axis; this can be adjusted */
-#define BOX_C0_LOG (HIST_C0_BITS-3)
-#define BOX_C1_LOG (HIST_C1_BITS-3)
-#define BOX_C2_LOG (HIST_C2_BITS-3)
+#define BOX_C0_LOG (HIST_C0_BITS - 3)
+#define BOX_C1_LOG (HIST_C1_BITS - 3)
+#define BOX_C2_LOG (HIST_C2_BITS - 3)
-#define BOX_C0_ELEMS (1<<BOX_C0_LOG) /* # of hist cells in update box */
-#define BOX_C1_ELEMS (1<<BOX_C1_LOG)
-#define BOX_C2_ELEMS (1<<BOX_C2_LOG)
+#define BOX_C0_ELEMS (1 << BOX_C0_LOG) /* # of hist cells in update box */
+#define BOX_C1_ELEMS (1 << BOX_C1_LOG)
+#define BOX_C2_ELEMS (1 << BOX_C2_LOG)
#define BOX_C0_SHIFT (C0_SHIFT + BOX_C0_LOG)
#define BOX_C1_SHIFT (C1_SHIFT + BOX_C1_LOG)
*/
LOCAL(int)
-find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
- JSAMPLE colorlist[])
+find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
+ JSAMPLE colorlist[])
/* Locate the colormap entries close enough to an update box to be candidates
* for the nearest entry to some cell(s) in the update box. The update box
* is specified by the center coordinates of its first cell. The number of
x = GETJSAMPLE(cinfo->colormap[0][i]);
if (x < minc0) {
tdist = (x - minc0) * C0_SCALE;
- min_dist = tdist*tdist;
+ min_dist = tdist * tdist;
tdist = (x - maxc0) * C0_SCALE;
- max_dist = tdist*tdist;
+ max_dist = tdist * tdist;
} else if (x > maxc0) {
tdist = (x - maxc0) * C0_SCALE;
- min_dist = tdist*tdist;
+ min_dist = tdist * tdist;
tdist = (x - minc0) * C0_SCALE;
- max_dist = tdist*tdist;
+ max_dist = tdist * tdist;
} else {
/* within cell range so no contribution to min_dist */
min_dist = 0;
if (x <= centerc0) {
tdist = (x - maxc0) * C0_SCALE;
- max_dist = tdist*tdist;
+ max_dist = tdist * tdist;
} else {
tdist = (x - minc0) * C0_SCALE;
- max_dist = tdist*tdist;
+ max_dist = tdist * tdist;
}
}
x = GETJSAMPLE(cinfo->colormap[1][i]);
if (x < minc1) {
tdist = (x - minc1) * C1_SCALE;
- min_dist += tdist*tdist;
+ min_dist += tdist * tdist;
tdist = (x - maxc1) * C1_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
} else if (x > maxc1) {
tdist = (x - maxc1) * C1_SCALE;
- min_dist += tdist*tdist;
+ min_dist += tdist * tdist;
tdist = (x - minc1) * C1_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
} else {
/* within cell range so no contribution to min_dist */
if (x <= centerc1) {
tdist = (x - maxc1) * C1_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
} else {
tdist = (x - minc1) * C1_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
}
}
x = GETJSAMPLE(cinfo->colormap[2][i]);
if (x < minc2) {
tdist = (x - minc2) * C2_SCALE;
- min_dist += tdist*tdist;
+ min_dist += tdist * tdist;
tdist = (x - maxc2) * C2_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
} else if (x > maxc2) {
tdist = (x - maxc2) * C2_SCALE;
- min_dist += tdist*tdist;
+ min_dist += tdist * tdist;
tdist = (x - minc2) * C2_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
} else {
/* within cell range so no contribution to min_dist */
if (x <= centerc2) {
tdist = (x - maxc2) * C2_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
} else {
tdist = (x - minc2) * C2_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
}
}
ncolors = 0;
for (i = 0; i < numcolors; i++) {
if (mindist[i] <= minmaxdist)
- colorlist[ncolors++] = (JSAMPLE) i;
+ colorlist[ncolors++] = (JSAMPLE)i;
}
return ncolors;
}
LOCAL(void)
-find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
- int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[])
+find_best_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
+ int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[])
/* Find the closest colormap entry for each cell in the update box,
* given the list of candidate colors prepared by find_nearby_colors.
* Return the indexes of the closest entries in the bestcolor[] array.
/* Initialize best-distance for each cell of the update box */
bptr = bestdist;
- for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--)
+ for (i = BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS - 1; i >= 0; i--)
*bptr++ = 0x7FFFFFFFL;
/* For each color selected by find_nearby_colors,
icolor = GETJSAMPLE(colorlist[i]);
/* Compute (square of) distance from minc0/c1/c2 to this color */
inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE;
- dist0 = inc0*inc0;
+ dist0 = inc0 * inc0;
inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE;
- dist0 += inc1*inc1;
+ dist0 += inc1 * inc1;
inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE;
- dist0 += inc2*inc2;
+ dist0 += inc2 * inc2;
/* Form the initial difference increments */
inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;
inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1;
bptr = bestdist;
cptr = bestcolor;
xx0 = inc0;
- for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) {
+ for (ic0 = BOX_C0_ELEMS - 1; ic0 >= 0; ic0--) {
dist1 = dist0;
xx1 = inc1;
- for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) {
+ for (ic1 = BOX_C1_ELEMS - 1; ic1 >= 0; ic1--) {
dist2 = dist1;
xx2 = inc2;
- for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) {
+ for (ic2 = BOX_C2_ELEMS - 1; ic2 >= 0; ic2--) {
if (dist2 < *bptr) {
*bptr = dist2;
- *cptr = (JSAMPLE) icolor;
+ *cptr = (JSAMPLE)icolor;
}
dist2 += xx2;
xx2 += 2 * STEP_C2 * STEP_C2;
LOCAL(void)
-fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2)
+fill_inverse_cmap(j_decompress_ptr cinfo, int c0, int c1, int c2)
/* Fill the inverse-colormap entries in the update box that contains */
/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */
/* we can fill as many others as we wish.) */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
hist3d histogram = cquantize->histogram;
int minc0, minc1, minc2; /* lower left corner of update box */
int ic0, ic1, ic2;
cptr = bestcolor;
for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) {
for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) {
- cachep = & histogram[c0+ic0][c1+ic1][c2];
+ cachep = &histogram[c0 + ic0][c1 + ic1][c2];
for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) {
- *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1);
+ *cachep++ = (histcell)(GETJSAMPLE(*cptr++) + 1);
}
}
}
*/
METHODDEF(void)
-pass2_no_dither (j_decompress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
+pass2_no_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
/* This version performs no dithering */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
hist3d histogram = cquantize->histogram;
register JSAMPROW inptr, outptr;
register histptr cachep;
c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT;
c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT;
c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT;
- cachep = & histogram[c0][c1][c2];
+ cachep = &histogram[c0][c1][c2];
/* If we have not seen this color before, find nearest colormap entry */
/* and update the cache */
if (*cachep == 0)
- fill_inverse_cmap(cinfo, c0,c1,c2);
+ fill_inverse_cmap(cinfo, c0, c1, c2);
/* Now emit the colormap index for this cell */
- *outptr++ = (JSAMPLE) (*cachep - 1);
+ *outptr++ = (JSAMPLE)(*cachep - 1);
}
}
}
METHODDEF(void)
-pass2_fs_dither (j_decompress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
+pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
/* This version performs Floyd-Steinberg dithering */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
hist3d histogram = cquantize->histogram;
register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */
LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */
outptr = output_buf[row];
if (cquantize->on_odd_row) {
/* work right to left in this row */
- inptr += (width-1) * 3; /* so point to rightmost pixel */
- outptr += width-1;
+ inptr += (width - 1) * 3; /* so point to rightmost pixel */
+ outptr += width - 1;
dir = -1;
dir3 = -3;
- errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */
+ errorptr = cquantize->fserrors + (width + 1) * 3; /* => entry after last column */
cquantize->on_odd_row = FALSE; /* flip for next time */
} else {
/* work left to right in this row */
* for either sign of the error value.
* Note: errorptr points to *previous* column's array entry.
*/
- cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4);
- cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4);
- cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4);
+ cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3 + 0] + 8, 4);
+ cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3 + 1] + 8, 4);
+ cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3 + 2] + 8, 4);
/* Limit the error using transfer function set by init_error_limit.
* See comments with init_error_limit for rationale.
*/
cur1 = GETJSAMPLE(range_limit[cur1]);
cur2 = GETJSAMPLE(range_limit[cur2]);
/* Index into the cache with adjusted pixel value */
- cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT];
+ cachep =
+ &histogram[cur0 >> C0_SHIFT][cur1 >> C1_SHIFT][cur2 >> C2_SHIFT];
/* If we have not seen this color before, find nearest colormap */
/* entry and update the cache */
if (*cachep == 0)
- fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT);
+ fill_inverse_cmap(cinfo, cur0 >> C0_SHIFT, cur1 >> C1_SHIFT,
+ cur2 >> C2_SHIFT);
/* Now emit the colormap index for this cell */
- { register int pixcode = *cachep - 1;
- *outptr = (JSAMPLE) pixcode;
+ {
+ register int pixcode = *cachep - 1;
+ *outptr = (JSAMPLE)pixcode;
/* Compute representation error for this pixel */
cur0 -= GETJSAMPLE(colormap0[pixcode]);
cur1 -= GETJSAMPLE(colormap1[pixcode]);
* Add these into the running sums, and simultaneously shift the
* next-line error sums left by 1 column.
*/
- { register LOCFSERROR bnexterr;
+ {
+ register LOCFSERROR bnexterr;
bnexterr = cur0; /* Process component 0 */
- errorptr[0] = (FSERROR) (bpreverr0 + cur0 * 3);
+ errorptr[0] = (FSERROR)(bpreverr0 + cur0 * 3);
bpreverr0 = belowerr0 + cur0 * 5;
belowerr0 = bnexterr;
cur0 *= 7;
bnexterr = cur1; /* Process component 1 */
- errorptr[1] = (FSERROR) (bpreverr1 + cur1 * 3);
+ errorptr[1] = (FSERROR)(bpreverr1 + cur1 * 3);
bpreverr1 = belowerr1 + cur1 * 5;
belowerr1 = bnexterr;
cur1 *= 7;
bnexterr = cur2; /* Process component 2 */
- errorptr[2] = (FSERROR) (bpreverr2 + cur2 * 3);
+ errorptr[2] = (FSERROR)(bpreverr2 + cur2 * 3);
bpreverr2 = belowerr2 + cur2 * 5;
belowerr2 = bnexterr;
cur2 *= 7;
* final fserrors[] entry. Note we need not unload belowerrN because
* it is for the dummy column before or after the actual array.
*/
- errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */
- errorptr[1] = (FSERROR) bpreverr1;
- errorptr[2] = (FSERROR) bpreverr2;
+ errorptr[0] = (FSERROR)bpreverr0; /* unload prev errs into array */
+ errorptr[1] = (FSERROR)bpreverr1;
+ errorptr[2] = (FSERROR)bpreverr2;
}
}
*/
LOCAL(void)
-init_error_limit (j_decompress_ptr cinfo)
+init_error_limit(j_decompress_ptr cinfo)
/* Allocate and fill in the error_limiter table */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
int *table;
int in, out;
- table = (int *) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * sizeof(int));
+ table = (int *)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, (MAXJSAMPLE * 2 + 1) * sizeof(int));
table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */
cquantize->error_limiter = table;
-#define STEPSIZE ((MAXJSAMPLE+1)/16)
+#define STEPSIZE ((MAXJSAMPLE + 1) / 16)
/* Map errors 1:1 up to +- MAXJSAMPLE/16 */
out = 0;
for (in = 0; in < STEPSIZE; in++, out++) {
- table[in] = out; table[-in] = -out;
+ table[in] = out; table[-in] = -out;
}
/* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */
- for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) {
- table[in] = out; table[-in] = -out;
+ for (; in < STEPSIZE * 3; in++, out += (in & 1) ? 0 : 1) {
+ table[in] = out; table[-in] = -out;
}
/* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */
for (; in <= MAXJSAMPLE; in++) {
- table[in] = out; table[-in] = -out;
+ table[in] = out; table[-in] = -out;
}
#undef STEPSIZE
}
*/
METHODDEF(void)
-finish_pass1 (j_decompress_ptr cinfo)
+finish_pass1(j_decompress_ptr cinfo)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
/* Select the representative colors and fill in cinfo->colormap */
cinfo->colormap = cquantize->sv_colormap;
METHODDEF(void)
-finish_pass2 (j_decompress_ptr cinfo)
+finish_pass2(j_decompress_ptr cinfo)
{
/* no work */
}
*/
METHODDEF(void)
-start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
+start_pass_2_quant(j_decompress_ptr cinfo, boolean is_pre_scan)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
hist3d histogram = cquantize->histogram;
int i;
ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
if (cinfo->dither_mode == JDITHER_FS) {
- size_t arraysize = (size_t) ((cinfo->output_width + 2) *
- (3 * sizeof(FSERROR)));
+ size_t arraysize =
+ (size_t)((cinfo->output_width + 2) * (3 * sizeof(FSERROR)));
/* Allocate Floyd-Steinberg workspace if we didn't already. */
if (cquantize->fserrors == NULL)
- cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
+ cquantize->fserrors = (FSERRPTR)(*cinfo->mem->alloc_large)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, arraysize);
/* Initialize the propagated errors to zero. */
- jzero_far((void *) cquantize->fserrors, arraysize);
+ jzero_far((void *)cquantize->fserrors, arraysize);
/* Make the error-limit table if we didn't already. */
if (cquantize->error_limiter == NULL)
init_error_limit(cinfo);
/* Zero the histogram or inverse color map, if necessary */
if (cquantize->needs_zeroed) {
for (i = 0; i < HIST_C0_ELEMS; i++) {
- jzero_far((void *) histogram[i],
- HIST_C1_ELEMS*HIST_C2_ELEMS * sizeof(histcell));
+ jzero_far((void *)histogram[i],
+ HIST_C1_ELEMS * HIST_C2_ELEMS * sizeof(histcell));
}
cquantize->needs_zeroed = FALSE;
}
*/
METHODDEF(void)
-new_color_map_2_quant (j_decompress_ptr cinfo)
+new_color_map_2_quant(j_decompress_ptr cinfo)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
/* Reset the inverse color map */
cquantize->needs_zeroed = TRUE;
*/
GLOBAL(void)
-jinit_2pass_quantizer (j_decompress_ptr cinfo)
+jinit_2pass_quantizer(j_decompress_ptr cinfo)
{
my_cquantize_ptr cquantize;
int i;
cquantize = (my_cquantize_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_cquantizer));
- cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
+ cinfo->cquantize = (struct jpeg_color_quantizer *)cquantize;
cquantize->pub.start_pass = start_pass_2_quant;
cquantize->pub.new_color_map = new_color_map_2_quant;
cquantize->fserrors = NULL; /* flag optional arrays not allocated */
ERREXIT(cinfo, JERR_NOTIMPL);
/* Allocate the histogram/inverse colormap storage */
- cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * sizeof(hist2d));
+ cquantize->histogram = (hist3d)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * sizeof(hist2d));
for (i = 0; i < HIST_C0_ELEMS; i++) {
- cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- HIST_C1_ELEMS*HIST_C2_ELEMS * sizeof(histcell));
+ cquantize->histogram[i] = (hist2d)(*cinfo->mem->alloc_large)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ HIST_C1_ELEMS * HIST_C2_ELEMS * sizeof(histcell));
}
cquantize->needs_zeroed = TRUE; /* histogram is garbage now */
if (desired > MAXNUMCOLORS)
ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
cquantize->sv_colormap = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3);
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)desired, (JDIMENSION)3);
cquantize->desired = desired;
} else
cquantize->sv_colormap = NULL;
* dither_mode changes.
*/
if (cinfo->dither_mode == JDITHER_FS) {
- cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (size_t) ((cinfo->output_width + 2) * (3 * sizeof(FSERROR))));
+ cquantize->fserrors = (FSERRPTR)(*cinfo->mem->alloc_large)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (size_t)((cinfo->output_width + 2) * (3 * sizeof(FSERROR))));
/* Might as well create the error-limiting table too. */
init_error_limit(cinfo);
}
*
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2011, 2014, D. R. Commander.
- * Copyright (C) 2015, Matthieu Darbois.
+ * Copyright (C) 2015-2016, 2018, Matthieu Darbois.
*
* Based on the x86 SIMD extension for IJG JPEG library,
* Copyright (C) 1999-2006, MIYASAKA Masaru.
#include "jchuff.h" /* Declarations shared with jcphuff.c */
-EXTERN(int) jsimd_can_rgb_ycc (void);
-EXTERN(int) jsimd_can_rgb_gray (void);
-EXTERN(int) jsimd_can_ycc_rgb (void);
-EXTERN(int) jsimd_can_ycc_rgb565 (void);
-EXTERN(int) jsimd_c_can_null_convert (void);
-
-EXTERN(void) jsimd_rgb_ycc_convert
- (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows);
-EXTERN(void) jsimd_rgb_gray_convert
- (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows);
-EXTERN(void) jsimd_ycc_rgb_convert
- (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows);
-EXTERN(void) jsimd_ycc_rgb565_convert
- (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows);
-EXTERN(void) jsimd_c_null_convert
- (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows);
-
-EXTERN(int) jsimd_can_h2v2_downsample (void);
-EXTERN(int) jsimd_can_h2v1_downsample (void);
-
-EXTERN(void) jsimd_h2v2_downsample
- (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data);
-
-EXTERN(int) jsimd_can_h2v2_smooth_downsample (void);
-
-EXTERN(void) jsimd_h2v2_smooth_downsample
- (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data);
-
-EXTERN(void) jsimd_h2v1_downsample
- (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data);
-
-EXTERN(int) jsimd_can_h2v2_upsample (void);
-EXTERN(int) jsimd_can_h2v1_upsample (void);
-EXTERN(int) jsimd_can_int_upsample (void);
-
-EXTERN(void) jsimd_h2v2_upsample
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr);
-EXTERN(void) jsimd_h2v1_upsample
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr);
-EXTERN(void) jsimd_int_upsample
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr);
-
-EXTERN(int) jsimd_can_h2v2_fancy_upsample (void);
-EXTERN(int) jsimd_can_h2v1_fancy_upsample (void);
-
-EXTERN(void) jsimd_h2v2_fancy_upsample
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr);
-EXTERN(void) jsimd_h2v1_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);
-
-EXTERN(void) jsimd_h2v2_merged_upsample
- (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf);
-EXTERN(void) jsimd_h2v1_merged_upsample
- (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf);
-
-EXTERN(int) jsimd_can_huff_encode_one_block (void);
-
-EXTERN(JOCTET*) jsimd_huff_encode_one_block
- (void *state, JOCTET *buffer, JCOEFPTR block, int last_dc_val,
- c_derived_tbl *dctbl, c_derived_tbl *actbl);
+EXTERN(int) jsimd_can_rgb_ycc(void);
+EXTERN(int) jsimd_can_rgb_gray(void);
+EXTERN(int) jsimd_can_ycc_rgb(void);
+EXTERN(int) jsimd_can_ycc_rgb565(void);
+EXTERN(int) jsimd_c_can_null_convert(void);
+
+EXTERN(void) jsimd_rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows);
+EXTERN(void) jsimd_rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows);
+EXTERN(void) jsimd_ycc_rgb_convert(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows);
+EXTERN(void) jsimd_ycc_rgb565_convert(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows);
+EXTERN(void) jsimd_c_null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row,
+ int num_rows);
+
+EXTERN(int) jsimd_can_h2v2_downsample(void);
+EXTERN(int) jsimd_can_h2v1_downsample(void);
+
+EXTERN(void) jsimd_h2v2_downsample(j_compress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY output_data);
+
+EXTERN(int) jsimd_can_h2v2_smooth_downsample(void);
+
+EXTERN(void) jsimd_h2v2_smooth_downsample(j_compress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY output_data);
+
+EXTERN(void) jsimd_h2v1_downsample(j_compress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY output_data);
+
+EXTERN(int) jsimd_can_h2v2_upsample(void);
+EXTERN(int) jsimd_can_h2v1_upsample(void);
+EXTERN(int) jsimd_can_int_upsample(void);
+
+EXTERN(void) jsimd_h2v2_upsample(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY *output_data_ptr);
+EXTERN(void) jsimd_h2v1_upsample(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY *output_data_ptr);
+EXTERN(void) jsimd_int_upsample(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY *output_data_ptr);
+
+EXTERN(int) jsimd_can_h2v2_fancy_upsample(void);
+EXTERN(int) jsimd_can_h2v1_fancy_upsample(void);
+
+EXTERN(void) jsimd_h2v2_fancy_upsample(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY *output_data_ptr);
+EXTERN(void) jsimd_h2v1_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);
+
+EXTERN(void) jsimd_h2v2_merged_upsample(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf);
+EXTERN(void) jsimd_h2v1_merged_upsample(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf);
+
+EXTERN(int) jsimd_can_huff_encode_one_block(void);
+
+EXTERN(JOCTET *) jsimd_huff_encode_one_block(void *state, JOCTET *buffer,
+ JCOEFPTR block, int last_dc_val,
+ c_derived_tbl *dctbl,
+ c_derived_tbl *actbl);
+
+EXTERN(int) jsimd_can_encode_mcu_AC_first_prepare(void);
+
+EXTERN(void) jsimd_encode_mcu_AC_first_prepare
+ (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al,
+ JCOEF *values, size_t *zerobits);
+
+EXTERN(int) jsimd_can_encode_mcu_AC_refine_prepare(void);
+
+EXTERN(int) jsimd_encode_mcu_AC_refine_prepare
+ (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al,
+ JCOEF *absvalues, size_t *bits);
*
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2009-2011, 2014, D. R. Commander.
- * Copyright (C) 2015, Matthieu Darbois.
+ * Copyright (C) 2015-2016, 2018, Matthieu Darbois.
*
* Based on the x86 SIMD extension for IJG JPEG library,
* Copyright (C) 1999-2006, MIYASAKA Masaru.
#include "jsimddct.h"
GLOBAL(int)
-jsimd_can_rgb_ycc (void)
+jsimd_can_rgb_ycc(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_rgb_gray (void)
+jsimd_can_rgb_gray(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_ycc_rgb (void)
+jsimd_can_ycc_rgb(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_ycc_rgb565 (void)
+jsimd_can_ycc_rgb565(void)
{
return 0;
}
GLOBAL(int)
-jsimd_c_can_null_convert (void)
+jsimd_c_can_null_convert(void)
{
return 0;
}
GLOBAL(void)
-jsimd_rgb_ycc_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+jsimd_rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row,
+ int num_rows)
{
}
GLOBAL(void)
-jsimd_rgb_gray_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+jsimd_rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row,
+ int num_rows)
{
}
GLOBAL(void)
-jsimd_ycc_rgb_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+jsimd_ycc_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
}
GLOBAL(void)
-jsimd_ycc_rgb565_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+jsimd_ycc_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
}
GLOBAL(void)
-jsimd_c_null_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+jsimd_c_null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row,
+ int num_rows)
{
}
GLOBAL(int)
-jsimd_can_h2v2_downsample (void)
+jsimd_can_h2v2_downsample(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_h2v1_downsample (void)
+jsimd_can_h2v1_downsample(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_h2v2_smooth_downsample (void)
+jsimd_can_h2v2_smooth_downsample(void)
{
return 0;
}
GLOBAL(void)
-jsimd_h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+jsimd_h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
}
GLOBAL(void)
-jsimd_h2v2_smooth_downsample (j_compress_ptr cinfo,
- jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+jsimd_h2v2_smooth_downsample(j_compress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
}
GLOBAL(void)
-jsimd_h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+jsimd_h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
}
GLOBAL(int)
-jsimd_can_h2v2_upsample (void)
+jsimd_can_h2v2_upsample(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_h2v1_upsample (void)
+jsimd_can_h2v1_upsample(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_int_upsample (void)
+jsimd_can_int_upsample(void)
{
return 0;
}
GLOBAL(void)
-jsimd_int_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+jsimd_int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
}
GLOBAL(void)
-jsimd_h2v2_upsample (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JSAMPARRAY input_data,
- JSAMPARRAY *output_data_ptr)
+jsimd_h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
}
GLOBAL(void)
-jsimd_h2v1_upsample (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JSAMPARRAY input_data,
- JSAMPARRAY *output_data_ptr)
+jsimd_h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
}
GLOBAL(int)
-jsimd_can_h2v2_fancy_upsample (void)
+jsimd_can_h2v2_fancy_upsample(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_h2v1_fancy_upsample (void)
+jsimd_can_h2v1_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)
+jsimd_h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
}
GLOBAL(void)
-jsimd_h2v1_fancy_upsample (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JSAMPARRAY input_data,
- JSAMPARRAY *output_data_ptr)
+jsimd_h2v1_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)
+jsimd_can_h2v2_merged_upsample(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_h2v1_merged_upsample (void)
+jsimd_can_h2v1_merged_upsample(void)
{
return 0;
}
GLOBAL(void)
-jsimd_h2v2_merged_upsample (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+jsimd_h2v2_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
}
GLOBAL(void)
-jsimd_h2v1_merged_upsample (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+jsimd_h2v1_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
}
GLOBAL(int)
-jsimd_can_convsamp (void)
+jsimd_can_convsamp(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_convsamp_float (void)
+jsimd_can_convsamp_float(void)
{
return 0;
}
GLOBAL(void)
-jsimd_convsamp (JSAMPARRAY sample_data, JDIMENSION start_col,
- DCTELEM *workspace)
+jsimd_convsamp(JSAMPARRAY sample_data, JDIMENSION start_col,
+ DCTELEM *workspace)
{
}
GLOBAL(void)
-jsimd_convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col,
- FAST_FLOAT *workspace)
+jsimd_convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col,
+ FAST_FLOAT *workspace)
{
}
GLOBAL(int)
-jsimd_can_fdct_islow (void)
+jsimd_can_fdct_islow(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_fdct_ifast (void)
+jsimd_can_fdct_ifast(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_fdct_float (void)
+jsimd_can_fdct_float(void)
{
return 0;
}
GLOBAL(void)
-jsimd_fdct_islow (DCTELEM *data)
+jsimd_fdct_islow(DCTELEM *data)
{
}
GLOBAL(void)
-jsimd_fdct_ifast (DCTELEM *data)
+jsimd_fdct_ifast(DCTELEM *data)
{
}
GLOBAL(void)
-jsimd_fdct_float (FAST_FLOAT *data)
+jsimd_fdct_float(FAST_FLOAT *data)
{
}
GLOBAL(int)
-jsimd_can_quantize (void)
+jsimd_can_quantize(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_quantize_float (void)
+jsimd_can_quantize_float(void)
{
return 0;
}
GLOBAL(void)
-jsimd_quantize (JCOEFPTR coef_block, DCTELEM *divisors,
- DCTELEM *workspace)
+jsimd_quantize(JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace)
{
}
GLOBAL(void)
-jsimd_quantize_float (JCOEFPTR coef_block, FAST_FLOAT *divisors,
- FAST_FLOAT *workspace)
+jsimd_quantize_float(JCOEFPTR coef_block, FAST_FLOAT *divisors,
+ FAST_FLOAT *workspace)
{
}
GLOBAL(int)
-jsimd_can_idct_2x2 (void)
+jsimd_can_idct_2x2(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_idct_4x4 (void)
+jsimd_can_idct_4x4(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_idct_6x6 (void)
+jsimd_can_idct_6x6(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_idct_12x12 (void)
+jsimd_can_idct_12x12(void)
{
return 0;
}
GLOBAL(void)
-jsimd_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col)
+jsimd_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
}
GLOBAL(void)
-jsimd_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col)
+jsimd_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
}
GLOBAL(void)
-jsimd_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col)
+jsimd_idct_6x6(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
}
GLOBAL(void)
-jsimd_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col)
+jsimd_idct_12x12(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
}
GLOBAL(int)
-jsimd_can_idct_islow (void)
+jsimd_can_idct_islow(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_idct_ifast (void)
+jsimd_can_idct_ifast(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_idct_float (void)
+jsimd_can_idct_float(void)
{
return 0;
}
GLOBAL(void)
-jsimd_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col)
+jsimd_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
}
GLOBAL(void)
-jsimd_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col)
+jsimd_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
}
GLOBAL(void)
-jsimd_idct_float (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col)
+jsimd_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
}
GLOBAL(int)
-jsimd_can_huff_encode_one_block (void)
+jsimd_can_huff_encode_one_block(void)
{
return 0;
}
-GLOBAL(JOCTET*)
-jsimd_huff_encode_one_block (void *state, JOCTET *buffer, JCOEFPTR block,
- int last_dc_val, c_derived_tbl *dctbl,
- c_derived_tbl *actbl)
+GLOBAL(JOCTET *)
+jsimd_huff_encode_one_block(void *state, JOCTET *buffer, JCOEFPTR block,
+ int last_dc_val, c_derived_tbl *dctbl,
+ c_derived_tbl *actbl)
{
return NULL;
}
+
+GLOBAL(int)
+jsimd_can_encode_mcu_AC_first_prepare(void)
+{
+ return 0;
+}
+
+GLOBAL(void)
+jsimd_encode_mcu_AC_first_prepare(const JCOEF *block,
+ const int *jpeg_natural_order_start, int Sl,
+ int Al, JCOEF *values, size_t *zerobits)
+{
+}
+
+GLOBAL(int)
+jsimd_can_encode_mcu_AC_refine_prepare(void)
+{
+ return 0;
+}
+
+GLOBAL(int)
+jsimd_encode_mcu_AC_refine_prepare(const JCOEF *block,
+ const int *jpeg_natural_order_start, int Sl,
+ int Al, JCOEF *absvalues, size_t *bits)
+{
+ return 0;
+}
*
*/
-EXTERN(int) jsimd_can_convsamp (void);
-EXTERN(int) jsimd_can_convsamp_float (void);
+EXTERN(int) jsimd_can_convsamp(void);
+EXTERN(int) jsimd_can_convsamp_float(void);
-EXTERN(void) jsimd_convsamp (JSAMPARRAY sample_data, JDIMENSION start_col,
- DCTELEM *workspace);
-EXTERN(void) jsimd_convsamp_float (JSAMPARRAY sample_data,
- JDIMENSION start_col,
- FAST_FLOAT *workspace);
+EXTERN(void) jsimd_convsamp(JSAMPARRAY sample_data, JDIMENSION start_col,
+ DCTELEM *workspace);
+EXTERN(void) jsimd_convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col,
+ FAST_FLOAT *workspace);
-EXTERN(int) jsimd_can_fdct_islow (void);
-EXTERN(int) jsimd_can_fdct_ifast (void);
-EXTERN(int) jsimd_can_fdct_float (void);
+EXTERN(int) jsimd_can_fdct_islow(void);
+EXTERN(int) jsimd_can_fdct_ifast(void);
+EXTERN(int) jsimd_can_fdct_float(void);
-EXTERN(void) jsimd_fdct_islow (DCTELEM *data);
-EXTERN(void) jsimd_fdct_ifast (DCTELEM *data);
-EXTERN(void) jsimd_fdct_float (FAST_FLOAT *data);
+EXTERN(void) jsimd_fdct_islow(DCTELEM *data);
+EXTERN(void) jsimd_fdct_ifast(DCTELEM *data);
+EXTERN(void) jsimd_fdct_float(FAST_FLOAT *data);
-EXTERN(int) jsimd_can_quantize (void);
-EXTERN(int) jsimd_can_quantize_float (void);
+EXTERN(int) jsimd_can_quantize(void);
+EXTERN(int) jsimd_can_quantize_float(void);
-EXTERN(void) jsimd_quantize (JCOEFPTR coef_block, DCTELEM *divisors,
- DCTELEM *workspace);
-EXTERN(void) jsimd_quantize_float (JCOEFPTR coef_block, FAST_FLOAT *divisors,
- FAST_FLOAT *workspace);
+EXTERN(void) jsimd_quantize(JCOEFPTR coef_block, DCTELEM *divisors,
+ DCTELEM *workspace);
+EXTERN(void) jsimd_quantize_float(JCOEFPTR coef_block, FAST_FLOAT *divisors,
+ FAST_FLOAT *workspace);
-EXTERN(int) jsimd_can_idct_2x2 (void);
-EXTERN(int) jsimd_can_idct_4x4 (void);
-EXTERN(int) jsimd_can_idct_6x6 (void);
-EXTERN(int) jsimd_can_idct_12x12 (void);
+EXTERN(int) jsimd_can_idct_2x2(void);
+EXTERN(int) jsimd_can_idct_4x4(void);
+EXTERN(int) jsimd_can_idct_6x6(void);
+EXTERN(int) jsimd_can_idct_12x12(void);
-EXTERN(void) jsimd_idct_2x2 (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col);
-EXTERN(void) jsimd_idct_4x4 (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col);
-EXTERN(void) jsimd_idct_6x6 (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col);
-EXTERN(void) jsimd_idct_12x12 (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col);
+EXTERN(void) jsimd_idct_2x2(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jsimd_idct_4x4(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jsimd_idct_6x6(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jsimd_idct_12x12(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col);
-EXTERN(int) jsimd_can_idct_islow (void);
-EXTERN(int) jsimd_can_idct_ifast (void);
-EXTERN(int) jsimd_can_idct_float (void);
+EXTERN(int) jsimd_can_idct_islow(void);
+EXTERN(int) jsimd_can_idct_ifast(void);
+EXTERN(int) jsimd_can_idct_float(void);
-EXTERN(void) jsimd_idct_islow (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col);
-EXTERN(void) jsimd_idct_ifast (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col);
-EXTERN(void) jsimd_idct_float (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col);
+EXTERN(void) jsimd_idct_islow(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col);
+EXTERN(void) jsimd_idct_ifast(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col);
+EXTERN(void) jsimd_idct_float(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col);
*/
LOCAL(void)
-add_huff_table (j_common_ptr cinfo,
- JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
+add_huff_table(j_common_ptr cinfo, JHUFF_TBL **htblptr, const UINT8 *bits,
+ const UINT8 *val)
/* Define a Huffman table */
{
int nsymbols, len;
LOCAL(void)
-std_huff_tables (j_common_ptr cinfo)
+std_huff_tables(j_common_ptr cinfo)
/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
/* IMPORTANT: these are only valid for 8-bit data precision! */
{
JHUFF_TBL **dc_huff_tbl_ptrs, **ac_huff_tbl_ptrs;
- static const UINT8 bits_dc_luminance[17] =
- { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
- static const UINT8 val_dc_luminance[] =
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+ static const UINT8 bits_dc_luminance[17] = {
+ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
+ };
+ static const UINT8 val_dc_luminance[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+ };
- static const UINT8 bits_dc_chrominance[17] =
- { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
- static const UINT8 val_dc_chrominance[] =
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+ static const UINT8 bits_dc_chrominance[17] = {
+ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
+ };
+ static const UINT8 val_dc_chrominance[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+ };
- static const UINT8 bits_ac_luminance[17] =
- { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
- static const UINT8 val_ac_luminance[] =
- { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
- 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
- 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
- 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
- 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
- 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
- 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
- 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
- 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
- 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
- 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
- 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
- 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
- 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
- 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
- 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
- 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
- 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
- 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa };
+ static const UINT8 bits_ac_luminance[17] = {
+ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
+ };
+ static const UINT8 val_ac_luminance[] = {
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+ };
- static const UINT8 bits_ac_chrominance[17] =
- { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
- static const UINT8 val_ac_chrominance[] =
- { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
- 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
- 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
- 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
- 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
- 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
- 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
- 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
- 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
- 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
- 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
- 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
- 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
- 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
- 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
- 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
- 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
- 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
- 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
- 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa };
+ static const UINT8 bits_ac_chrominance[17] = {
+ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77
+ };
+ static const UINT8 val_ac_chrominance[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+ 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+ 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+ 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+ };
if (cinfo->is_decompressor) {
dc_huff_tbl_ptrs = ((j_decompress_ptr)cinfo)->dc_huff_tbl_ptrs;
* fake entries.
*/
-const int jpeg_natural_order[DCTSIZE2+16] = {
+const int jpeg_natural_order[DCTSIZE2 + 16] = {
0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34,
*/
GLOBAL(long)
-jdiv_round_up (long a, long b)
+jdiv_round_up(long a, long b)
/* Compute a/b rounded up to next integer, ie, ceil(a/b) */
/* Assumes a >= 0, b > 0 */
{
GLOBAL(long)
-jround_up (long a, long b)
+jround_up(long a, long b)
/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */
/* Assumes a >= 0, b > 0 */
{
GLOBAL(void)
-jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
- JSAMPARRAY output_array, int dest_row,
- int num_rows, JDIMENSION num_cols)
+jcopy_sample_rows(JSAMPARRAY input_array, int source_row,
+ JSAMPARRAY output_array, int dest_row, int num_rows,
+ JDIMENSION num_cols)
/* Copy some rows of samples from one place to another.
* num_rows rows are copied from input_array[source_row++]
* to output_array[dest_row++]; these areas may overlap for duplication.
*/
{
register JSAMPROW inptr, outptr;
- register size_t count = (size_t) (num_cols * sizeof(JSAMPLE));
+ register size_t count = (size_t)(num_cols * sizeof(JSAMPLE));
register int row;
input_array += source_row;
GLOBAL(void)
-jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row,
- JDIMENSION num_blocks)
+jcopy_block_row(JBLOCKROW input_row, JBLOCKROW output_row,
+ JDIMENSION num_blocks)
/* Copy a row of coefficient blocks from one place to another. */
{
MEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * sizeof(JCOEF)));
GLOBAL(void)
-jzero_far (void *target, size_t bytestozero)
+jzero_far(void *target, size_t bytestozero)
/* Zero out a chunk of memory. */
/* This might be sample-array data, block-array data, or alloc_large data. */
{
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2010, 2012-2017, D. R. Commander.
+ * Copyright (C) 2010, 2012-2019, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
* their code
*/
-#define JCOPYRIGHT "Copyright (C) 2009-2017 D. R. Commander\n" \
- "Copyright (C) 2011-2016 Siarhei Siamashka\n" \
- "Copyright (C) 2015-2016 Matthieu Darbois\n" \
- "Copyright (C) 2015 Google, Inc.\n" \
- "Copyright (C) 2013-2014 MIPS Technologies, Inc.\n" \
- "Copyright (C) 2013 Linaro Limited\n" \
- "Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \
- "Copyright (C) 2009 Pierre Ossman for Cendio AB\n" \
- "Copyright (C) 1999-2006 MIYASAKA Masaru\n" \
- "Copyright (C) 1991-2016 Thomas G. Lane, Guido Vollbeding" \
-
-#define JCOPYRIGHT_SHORT "Copyright (C) 1991-2017 The libjpeg-turbo Project and many others"
+#define JCOPYRIGHT \
+ "Copyright (C) 2009-2019 D. R. Commander\n" \
+ "Copyright (C) 2011-2016 Siarhei Siamashka\n" \
+ "Copyright (C) 2015-2016, 2018 Matthieu Darbois\n" \
+ "Copyright (C) 2015 Intel Corporation\n" \
+ "Copyright (C) 2015 Google, Inc.\n" \
+ "Copyright (C) 2013-2014 MIPS Technologies, Inc.\n" \
+ "Copyright (C) 2013 Linaro Limited\n" \
+ "Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \
+ "Copyright (C) 2009 Pierre Ossman for Cendio AB\n" \
+ "Copyright (C) 1999-2006 MIYASAKA Masaru\n" \
+ "Copyright (C) 1991-2016 Thomas G. Lane, Guido Vollbeding"
+
+#define JCOPYRIGHT_SHORT \
+ "Copyright (C) 1991-2019 The libjpeg-turbo Project and many others"
Added missing parentheses to a macro definition
(suggested by "irwir" in GitHub issue #216)
+Version 1.6.36 [December 1, 2018]
+ Optimized png_do_expand_palette for ARM processors.
+ Improved performance by around 10-22% on a recent ARM Chromebook.
+ (Contributed by Richard Townsend, ARM Holdings)
+ Fixed manipulation of machine-specific optimization options.
+ (Contributed by Vicki Pfau)
+ Used memcpy instead of manual pointer arithmetic on Intel SSE2.
+ (Contributed by Samuel Williams)
+ Fixed build errors with MSVC on ARM64.
+ (Contributed by Zhijie Liang)
+ Fixed detection of libm in CMakeLists.
+ (Contributed by Cameron Cawley)
+ Fixed incorrect creation of pkg-config file in CMakeLists.
+ (Contributed by Kyle Bentley)
+ Fixed the CMake build on Windows MSYS by avoiding symlinks.
+ Fixed a build warning on OpenBSD.
+ (Contributed by Theo Buehler)
+ Fixed various typos in comments.
+ (Contributed by "luz.paz")
+ Raised the minimum required CMake version from 3.0.2 to 3.1.
+ Removed yet more of the vestigial support for pre-ANSI C compilers.
+ Removed ancient makefiles for ancient systems that have been broken
+ across all previous libpng-1.6.x versions.
+ Removed the Y2K compliance statement and the export control
+ information.
+ Applied various code style and documentation fixes.
+
Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
to subscribe).
-
-Glenn R-P
if(ARM OR AARCH64)
- if(ENABLE_NEON AND NOT AARCH64)
- list(APPEND lib_srcs arm/arm_init.c arm/filter_neon.S arm/filter_neon_intrinsics.c)
+ if(ENABLE_NEON)
+ if(NOT AARCH64)
+ list(APPEND lib_srcs arm/filter_neon.S)
+ endif()
+ list(APPEND lib_srcs arm/arm_init.c arm/filter_neon_intrinsics.c arm/palette_neon_intrinsics.c)
add_definitions(-DPNG_ARM_NEON_OPT=2)
else()
add_definitions(-DPNG_ARM_NEON_OPT=0) # NEON assembler is not supported
add_library(${PNG_LIBRARY} STATIC ${lib_srcs} ${lib_hdrs})
target_link_libraries(${PNG_LIBRARY} ${ZLIB_LIBRARIES})
-ocv_warnings_disable(CMAKE_C_FLAGS -Wundef -Wcast-align -Wimplicit-fallthrough)
+ocv_warnings_disable(CMAKE_C_FLAGS -Wundef -Wcast-align -Wimplicit-fallthrough -Wunused-parameter -Wsign-compare)
set_target_properties(${PNG_LIBRARY}
PROPERTIES OUTPUT_NAME ${PNG_LIBRARY}
+COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
+=========================================
-This copy of the libpng notices is provided for your convenience. In case of
-any discrepancy between this copy and the notices in the file png.h that is
-included in the libpng distribution, the latter shall prevail.
+PNG Reference Library License version 2
+---------------------------------------
-COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+ * Copyright (c) 1995-2018 The PNG Reference Library Authors.
+ * Copyright (c) 2018 Cosmin Truta.
+ * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
+ * Copyright (c) 1996-1997 Andreas Dilger.
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
-If you modify libpng you may insert additional notices immediately following
-this sentence.
+The software is supplied "as is", without warranty of any kind,
+express or implied, including, without limitation, the warranties
+of merchantability, fitness for a particular purpose, title, and
+non-infringement. In no even shall the Copyright owners, or
+anyone distributing the software, be liable for any damages or
+other liability, whether in contract, tort or otherwise, arising
+from, out of, or in connection with the software, or the use or
+other dealings in the software, even if advised of the possibility
+of such damage.
-This code is released under the libpng license.
+Permission is hereby granted to use, copy, modify, and distribute
+this software, or portions hereof, for any purpose, without fee,
+subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you
+ must not claim that you wrote the original software. If you
+ use this software in a product, an acknowledgment in the product
+ documentation would be appreciated, but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 3. This Copyright notice may not be removed or altered from any
+ source or altered source distribution.
+
+
+PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
+-----------------------------------------------------------------------
libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are
Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
disclaimer and license as libpng-1.0.6 with the following individuals
added to the list of Contributing Authors:
- Simon-Pierre Cadieux
- Eric S. Raymond
- Mans Rullgard
- Cosmin Truta
- Gilles Vollant
- James Yu
- Mandar Sahastrabuddhe
- Google Inc.
- Vadim Barkov
+ Simon-Pierre Cadieux
+ Eric S. Raymond
+ Mans Rullgard
+ Cosmin Truta
+ Gilles Vollant
+ James Yu
+ Mandar Sahastrabuddhe
+ Google Inc.
+ Vadim Barkov
and with the following additions to the disclaimer:
- There is no warranty against interference with your enjoyment of the
- library or against infringement. There is no warranty that our
- efforts or the library will fulfill any of your particular purposes
- or needs. This library is provided with all faults, and the entire
- risk of satisfactory quality, performance, accuracy, and effort is with
- the user.
+ There is no warranty against interference with your enjoyment of
+ the library or against infringement. There is no warranty that our
+ efforts or the library will fulfill any of your particular purposes
+ or needs. This library is provided with all faults, and the entire
+ risk of satisfactory quality, performance, accuracy, and effort is
+ with the user.
Some files in the "contrib" directory and some configure-generated
-files that are distributed with libpng have other copyright owners and
+files that are distributed with libpng have other copyright owners, and
are released under other open source licenses.
libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
libpng-0.96, and are distributed according to the same disclaimer and
-license as libpng-0.96, with the following individuals added to the list
-of Contributing Authors:
+license as libpng-0.96, with the following individuals added to the
+list of Contributing Authors:
- Tom Lane
- Glenn Randers-Pehrson
- Willem van Schaik
+ Tom Lane
+ Glenn Randers-Pehrson
+ Willem van Schaik
libpng versions 0.89, June 1996, through 0.96, May 1997, are
Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
libpng-0.88, with the following individuals added to the list of
Contributing Authors:
- John Bowler
- Kevin Bracey
- Sam Bushell
- Magnus Holmgren
- Greg Roelofs
- Tom Tanner
+ John Bowler
+ Kevin Bracey
+ Sam Bushell
+ Magnus Holmgren
+ Greg Roelofs
+ Tom Tanner
-Some files in the "scripts" directory have other copyright owners
+Some files in the "scripts" directory have other copyright owners,
but are released under this license.
libpng versions 0.5, May 1995, through 0.88, January 1996, are
For the purposes of this copyright and license, "Contributing Authors"
is defined as the following set of individuals:
- Andreas Dilger
- Dave Martindale
- Guy Eric Schalnat
- Paul Schmidt
- Tim Wegner
-
-The PNG Reference Library is supplied "AS IS". The Contributing Authors
-and Group 42, Inc. disclaim all warranties, expressed or implied,
-including, without limitation, the warranties of merchantability and of
-fitness for any purpose. The Contributing Authors and Group 42, Inc.
-assume no liability for direct, indirect, incidental, special, exemplary,
-or consequential damages, which may result from the use of the PNG
-Reference Library, even if advised of the possibility of such damage.
+ Andreas Dilger
+ Dave Martindale
+ Guy Eric Schalnat
+ Paul Schmidt
+ Tim Wegner
+
+The PNG Reference Library is supplied "AS IS". The Contributing
+Authors and Group 42, Inc. disclaim all warranties, expressed or
+implied, including, without limitation, the warranties of
+merchantability and of fitness for any purpose. The Contributing
+Authors and Group 42, Inc. assume no liability for direct, indirect,
+incidental, special, exemplary, or consequential damages, which may
+result from the use of the PNG Reference Library, even if advised of
+the possibility of such damage.
Permission is hereby granted to use, copy, modify, and distribute this
source code, or portions hereof, for any purpose, without fee, subject
to the following restrictions:
- 1. The origin of this source code must not be misrepresented.
-
- 2. Altered versions must be plainly marked as such and must not
- be misrepresented as being the original source.
-
- 3. This Copyright notice may not be removed or altered from any
- source or altered source distribution.
-
-The Contributing Authors and Group 42, Inc. specifically permit, without
-fee, and encourage the use of this source code as a component to
-supporting the PNG file format in commercial products. If you use this
-source code in a product, acknowledgment is not required but would be
-appreciated.
-
-END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
-
-TRADEMARK:
-
-The name "libpng" has not been registered by the Copyright owner
-as a trademark in any jurisdiction. However, because libpng has
-been distributed and maintained world-wide, continually since 1995,
-the Copyright owner claims "common-law trademark protection" in any
-jurisdiction where common-law trademark is recognized.
-
-OSI CERTIFICATION:
-
-Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
-a certification mark of the Open Source Initiative. OSI has not addressed
-the additional disclaimers inserted at version 1.0.7.
+ 1. The origin of this source code must not be misrepresented.
-EXPORT CONTROL:
+ 2. Altered versions must be plainly marked as such and must not
+ be misrepresented as being the original source.
-The Copyright owner believes that the Export Control Classification
-Number (ECCN) for libpng is EAR99, which means not subject to export
-controls or International Traffic in Arms Regulations (ITAR) because
-it is open source, publicly available software, that does not contain
-any encryption software. See the EAR, paragraphs 734.3(b)(3) and
-734.7(b).
+ 3. This Copyright notice may not be removed or altered from any
+ source or altered source distribution.
-Glenn Randers-Pehrson
-glennrp at users.sourceforge.net
-July 15, 2018
+The Contributing Authors and Group 42, Inc. specifically permit,
+without fee, and encourage the use of this source code as a component
+to supporting the PNG file format in commercial products. If you use
+this source code in a product, acknowledgment is not required but would
+be appreciated.
-README for libpng version 1.6.35 - July 15, 2018 (shared library 16.0)
-See the note about version numbers near the top of png.h
+README for libpng version 1.6.36 - December 1, 2018
+===================================================
+See the note about version numbers near the top of png.h.
See INSTALL for instructions on how to install libpng.
Libpng comes in several distribution formats. Get libpng-*.tar.gz or
-libpng-*.tar.xz or if you want UNIX-style line endings in the text files,
-or lpng*.7z or lpng*.zip if you want DOS-style line endings.
+libpng-*.tar.xz or if you want UNIX-style line endings in the text
+files, or lpng*.7z or lpng*.zip if you want DOS-style line endings.
Version 0.89 was the first official release of libpng. Don't let the
-fact that it's the first release fool you. The libpng library has been in
-extensive use and testing since mid-1995. By late 1997 it had
+fact that it's the first release fool you. The libpng library has been
+in extensive use and testing since mid-1995. By late 1997 it had
finally gotten to the stage where there hadn't been significant
changes to the API in some time, and people have a bad feeling about
libraries with versions < 1.0. Version 1.0.0 was released in
to set different actions based on whether the CRC error occurred in a
critical or an ancillary chunk.
-The changes made to the library, and bugs fixed are based on discussions
-on the PNG-implement mailing list and not on material submitted
-privately to Guy, Andreas, or Glenn. They will forward any good
-suggestions to the list.
-
-For a detailed description on using libpng, read libpng-manual.txt. For
-examples of libpng in a program, see example.c and pngtest.c. For usage
-information and restrictions (what little they are) on libpng, see
-png.h. For a description on using zlib (the compression library used by
-libpng) and zlib's restrictions, see zlib.h
+For a detailed description on using libpng, read libpng-manual.txt.
+For examples of libpng in a program, see example.c and pngtest.c. For
+usage information and restrictions (what little they are) on libpng,
+see png.h. For a description on using zlib (the compression library
+used by libpng) and zlib's restrictions, see zlib.h
I have included a general makefile, as well as several machine and
-compiler specific ones, but you may have to modify one for your own needs.
+compiler specific ones, but you may have to modify one for your own
+needs.
You should use zlib 1.0.4 or later to run this, but it MAY work with
versions as old as zlib 0.95. Even so, there are bugs in older zlib
versions which can cause the output of invalid compression streams for
-some images. You will definitely need zlib 1.0.4 or later if you are
-taking advantage of the MS-DOS "far" structure allocation for the small
-and medium memory models. You should also note that zlib is a
-compression library that is useful for more things than just PNG files.
-You can use zlib as a drop-in replacement for fread() and fwrite() if
-you are so inclined.
+some images.
+
+You should also note that zlib is a compression library that is useful
+for more things than just PNG files. You can use zlib as a drop-in
+replacement for fread() and fwrite(), if you are so inclined.
-zlib should be available at the same place that libpng is, or at zlib.net.
+zlib should be available at the same place that libpng is, or at
+https://zlib.net.
You may also want a copy of the PNG specification. It is available
as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find
these at http://www.libpng.org/pub/png/pngdocs.html .
This code is currently being archived at libpng.sourceforge.io in the
-[DOWNLOAD] area, and at http://libpng.download/src . If you
-can't find it in any of those places, e-mail me, and I'll help you find it.
-
-I am not a lawyer, but I believe that the Export Control Classification
-Number (ECCN) for libpng is EAR99, which means not subject to export
-controls or International Traffic in Arms Regulations (ITAR) because it
-is open source, publicly available software, that does not contain any
-encryption software. See the EAR, paragraphs 734.3(b)(3) and 734.7(b).
-
-If you have any code changes, requests, problems, etc., please e-mail
-them to me. Also, I'd appreciate any make files or project files,
-and any modifications you needed to make to get libpng to compile,
-along with a #define variable to tell what compiler/system you are on.
-If you needed to add transformations to libpng, or wish libpng would
-provide the image in a different way, drop me a note (and code, if
-possible), so I can consider supporting the transformation.
-Finally, if you get any warning messages when compiling libpng
-(note: not zlib), and they are easy to fix, I'd appreciate the
-fix. Please mention "libpng" somewhere in the subject line. Thanks.
-
-This release was created and will be supported by myself (of course
-based in a large way on Guy's and Andreas' earlier work), and the PNG
+[DOWNLOAD] area, and at http://libpng.download/src .
+
+This release, based in a large way on Glenn's, Guy's and Andreas'
+earlier work, was created and will be supported by myself and the PNG
development group.
Send comments/corrections/commendations to png-mng-implement at
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
to subscribe).
-You can't reach Guy, the original libpng author, at the addresses
-given in previous versions of this document. He and Andreas will
-read mail addressed to the png-implement list, however.
-
-Please do not send general questions about PNG. Send them to
-png-mng-misc at lists.sf.net (subscription required; visit
+Send general questions about the PNG specification to png-mng-misc
+at lists.sourceforge.net (subscription required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-misc to
-subscribe). If you have a question about something
-in the PNG specification that is related to using libpng, send it
-to me. Send me any questions that start with "I was using libpng,
-and ...". If in doubt, send questions to me. I'll bounce them
-to others, if necessary.
-
-Please do not send suggestions on how to change PNG. We have
-been discussing PNG for twenty years now, and it is official and
-finished. If you have suggestions for libpng, however, I'll
-gladly listen. Even if your suggestion is not used immediately,
-it may be used later.
+subscribe).
Files in this distribution:
ANNOUNCE => Announcement of this version, with recent changes
+ AUTHORS => List of contributing authors
CHANGES => Description of changes between libpng versions
KNOWNBUG => List of known bugs and deficiencies
LICENSE => License to use and redistribute libpng
README => This file
TODO => Things not implemented in the current library
- Y2KINFO => Statement of Y2K compliance
+ TRADEMARK => Trademark information
example.c => Example code for using libpng functions
libpng.3 => manual page for libpng (includes libpng-manual.txt)
libpng-manual.txt => Description of libpng and its functions
scripts => Directory containing scripts for building libpng:
(see scripts/README.txt for the list of scripts)
-Good luck, and happy coding.
-
--Glenn Randers-Pehrson (current maintainer, since 1998)
- Internet: glennrp at users.sourceforge.net
-
--Andreas Eric Dilger (former maintainer, 1996-1997)
- Internet: adilger at enel.ucalgary.ca
- Web: http://www-mddsp.enel.ucalgary.ca/People/adilger/
+Good luck, and happy coding!
--Guy Eric Schalnat (original author and former maintainer, 1995-1996)
- (formerly of Group 42, Inc)
- Internet: gschal at infinet.com
+ * Cosmin Truta (current maintainer, since 2018)
+ * Glenn Randers-Pehrson (former maintainer, 1998-2018)
+ * Andreas Eric Dilger (former maintainer, 1996-1997)
+ * Guy Eric Schalnat (original author and former maintainer, 1995-1996)
+ (formerly of Group 42, Inc.)
/* arm_init.c - NEON optimised filter functions
*
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
* Written by Mans Rullgard, 2011.
- * Last changed in libpng 1.6.22 [May 26, 2016]
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
+
/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
* called.
*/
/* filter_neon.S - NEON optimised filter functions
*
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2014,2017 Glenn Randers-Pehrson
* Written by Mans Rullgard, 2011.
- * Last changed in libpng 1.6.31 [July 27, 2017]
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
/* filter_neon_intrinsics.c - NEON optimised filter functions
*
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
* Written by James Yu <james.yu at linaro.org>, October 2013.
* Based on filter_neon.S, written by Mans Rullgard, 2011.
*
- * Last changed in libpng 1.6.22 [May 26, 2016]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
/* This code requires -mfpu=neon on the command line: */
#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
-#include <arm_neon.h>
+#if defined(_MSC_VER) && defined(_M_ARM64)
+# include <arm64_neon.h>
+#else
+# include <arm_neon.h>
+#endif
/* libpng row pointers are not necessarily aligned to any particular boundary,
* however this code will only work with appropriate alignment. arm/arm_init.c
* 'type'. This is written this way just to hide the GCC strict aliasing
* warning; note that the code is safe because there never is an alias between
* the input and output pointers.
+ *
+ * When compiling with MSVC ARM64, the png_ldr macro can't be passed directly
+ * to vst4_lane_u32, because of an internal compiler error inside MSVC.
+ * To avoid this compiler bug, we use a temporary variable (vdest_val) to store
+ * the result of png_ldr.
*/
#define png_ldr(type,pointer)\
(temp_pointer = png_ptr(type,pointer), *temp_pointer)
uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp);
uint8x8x4_t vrp = *vrpt;
uint32x2x4_t *temp_pointer;
+ uint32x2x4_t vdest_val;
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]);
vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]);
vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]);
- vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
+
+ vdest_val = png_ldr(uint32x2x4_t, &vdest);
+ vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
}
PNG_UNUSED(prev_row)
uint8x8x4_t *vrpt, *vppt;
uint8x8x4_t vrp, vpp;
uint32x2x4_t *temp_pointer;
+ uint32x2x4_t vdest_val;
vtmp = vld4_u32(png_ptr(uint32_t,rp));
vrpt = png_ptr(uint8x8x4_t,&vtmp);
vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]);
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
- vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
+ vdest_val = png_ldr(uint32x2x4_t, &vdest);
+ vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
}
}
uint8x8x4_t *vrpt, *vppt;
uint8x8x4_t vrp, vpp;
uint32x2x4_t *temp_pointer;
+ uint32x2x4_t vdest_val;
vtmp = vld4_u32(png_ptr(uint32_t,rp));
vrpt = png_ptr(uint8x8x4_t,&vtmp);
vlast = vpp.val[3];
- vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
+ vdest_val = png_ldr(uint32x2x4_t, &vdest);
+ vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
}
}
--- /dev/null
+
+/* palette_neon_intrinsics.c - NEON optimised palette expansion functions
+ *
+ * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2017-2018 Arm Holdings. All rights reserved.
+ * Written by Richard Townsend <Richard.Townsend@arm.com>, February 2017.
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+#include "../pngpriv.h"
+
+#if PNG_ARM_NEON_IMPLEMENTATION == 1
+
+#if defined(_MSC_VER) && defined(_M_ARM64)
+# include <arm64_neon.h>
+#else
+# include <arm_neon.h>
+#endif
+
+/* Build an RGBA palette from the RGB and separate alpha palettes. */
+void
+png_riffle_palette_rgba(png_structrp png_ptr, png_row_infop row_info)
+{
+ png_const_colorp palette = png_ptr->palette;
+ png_bytep riffled_palette = png_ptr->riffled_palette;
+ png_const_bytep trans_alpha = png_ptr->trans_alpha;
+ int num_trans = png_ptr->num_trans;
+ int i;
+
+ /* Initially black, opaque. */
+ uint8x16x4_t w = {{
+ vdupq_n_u8(0x00),
+ vdupq_n_u8(0x00),
+ vdupq_n_u8(0x00),
+ vdupq_n_u8(0xff),
+ }};
+
+ if (row_info->bit_depth != 8)
+ {
+ png_error(png_ptr, "bit_depth must be 8 for png_riffle_palette_rgba");
+ return;
+ }
+
+ /* First, riffle the RGB colours into a RGBA palette, the A value is
+ * set to opaque for now.
+ */
+ for (i = 0; i < (1 << row_info->bit_depth); i += 16)
+ {
+ uint8x16x3_t v = vld3q_u8((png_const_bytep)(palette + i));
+ w.val[0] = v.val[0];
+ w.val[1] = v.val[1];
+ w.val[2] = v.val[2];
+ vst4q_u8(riffled_palette + (i << 2), w);
+ }
+
+ /* Fix up the missing transparency values. */
+ for (i = 0; i < num_trans; i++)
+ riffled_palette[(i << 2) + 3] = trans_alpha[i];
+}
+
+/* Expands a palettized row into RGBA. */
+int
+png_do_expand_palette_neon_rgba(png_structrp png_ptr, png_row_infop row_info,
+ png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
+{
+ png_uint_32 row_width = row_info->width;
+ const png_uint_32 *riffled_palette =
+ (const png_uint_32 *)png_ptr->riffled_palette;
+ const png_int_32 pixels_per_chunk = 4;
+ int i;
+
+ if (row_width < pixels_per_chunk)
+ return 0;
+
+ /* This function originally gets the last byte of the output row.
+ * The NEON part writes forward from a given position, so we have
+ * to seek this back by 4 pixels x 4 bytes.
+ */
+ *ddp = *ddp - ((pixels_per_chunk * sizeof(png_uint_32)) - 1);
+
+ for (i = 0; i < row_width; i += pixels_per_chunk)
+ {
+ uint32x4_t cur;
+ png_bytep sp = *ssp - i, dp = *ddp - (i << 2);
+ cur = vld1q_dup_u32 (riffled_palette + *(sp - 3));
+ cur = vld1q_lane_u32(riffled_palette + *(sp - 2), cur, 1);
+ cur = vld1q_lane_u32(riffled_palette + *(sp - 1), cur, 2);
+ cur = vld1q_lane_u32(riffled_palette + *(sp - 0), cur, 3);
+ vst1q_u32((void *)dp, cur);
+ }
+ if (i != row_width)
+ {
+ /* Remove the amount that wasn't processed. */
+ i -= pixels_per_chunk;
+ }
+
+ /* Decrement output pointers. */
+ *ssp = *ssp - i;
+ *ddp = *ddp - (i << 2);
+ return i;
+}
+
+/* Expands a palettized row into RGB format. */
+int
+png_do_expand_palette_neon_rgb(png_structrp png_ptr, png_row_infop row_info,
+ png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
+{
+ png_uint_32 row_width = row_info->width;
+ png_const_bytep palette = (png_const_bytep)png_ptr->palette;
+ const png_uint_32 pixels_per_chunk = 8;
+ int i;
+
+ if (row_width <= pixels_per_chunk)
+ return 0;
+
+ /* Seeking this back by 8 pixels x 3 bytes. */
+ *ddp = *ddp - ((pixels_per_chunk * sizeof(png_color)) - 1);
+
+ for (i = 0; i < row_width; i += pixels_per_chunk)
+ {
+ uint8x8x3_t cur;
+ png_bytep sp = *ssp - i, dp = *ddp - ((i << 1) + i);
+ cur = vld3_dup_u8(palette + sizeof(png_color) * (*(sp - 7)));
+ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 6)), cur, 1);
+ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 5)), cur, 2);
+ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 4)), cur, 3);
+ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 3)), cur, 4);
+ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 2)), cur, 5);
+ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 1)), cur, 6);
+ cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 0)), cur, 7);
+ vst3_u8((void *)dp, cur);
+ }
+
+ if (i != row_width)
+ {
+ /* Remove the amount that wasn't processed. */
+ i -= pixels_per_chunk;
+ }
+
+ /* Decrement output pointers. */
+ *ssp = *ssp - i;
+ *ddp = *ddp - ((i << 1) + i);
+ return i;
+}
+
+#endif /* PNG_ARM_NEON_IMPLEMENTATION */
/* filter_sse2_intrinsics.c - SSE2 optimized filter functions
*
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2016-2017 Glenn Randers-Pehrson
* Written by Mike Klein and Matt Sarett
* Derived from arm/filter_neon_intrinsics.c
*
- * Last changed in libpng 1.6.31 [July 27, 2017]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
static __m128i load4(const void* p) {
- return _mm_cvtsi32_si128(*(const int*)p);
+ int tmp;
+ memcpy(&tmp, p, sizeof(tmp));
+ return _mm_cvtsi32_si128(tmp);
}
static void store4(void* p, __m128i v) {
- *(int*)p = _mm_cvtsi128_si32(v);
+ int tmp = _mm_cvtsi128_si32(v);
+ memcpy(p, &tmp, sizeof(int));
}
static __m128i load3(const void* p) {
- /* We'll load 2 bytes, then 1 byte,
- * then mask them together, and finally load into SSE.
- */
- const png_uint_16* p01 = (png_const_uint_16p)p;
- const png_byte* p2 = (const png_byte*)(p01+1);
-
- png_uint_32 v012 = (png_uint_32)(*p01)
- | (png_uint_32)(*p2) << 16;
- return load4(&v012);
+ png_uint_32 tmp = 0;
+ memcpy(&tmp, p, 3);
+ return _mm_cvtsi32_si128(tmp);
}
static void store3(void* p, __m128i v) {
- /* We'll pull from SSE as a 32-bit int, then write
- * its bottom two bytes, then its third byte.
- */
- png_uint_32 v012;
- png_uint_16* p01;
- png_byte* p2;
-
- store4(&v012, v);
-
- p01 = (png_uint_16p)p;
- p2 = (png_byte*)(p01+1);
- *p01 = (png_uint_16)v012;
- *p2 = (png_byte)(v012 >> 16);
+ int tmp = _mm_cvtsi128_si32(v);
+ memcpy(p, &tmp, 3);
}
void png_read_filter_row_sub3_sse2(png_row_infop row_info, png_bytep row,
/* intel_init.c - SSE2 optimized filter functions
*
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2016-2017 Glenn Randers-Pehrson
* Written by Mike Klein and Matt Sarett, Google, Inc.
* Derived from arm/arm_init.c
*
- * Last changed in libpng 1.6.29 [March 16, 2017]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
/* png.c - location for general purpose libpng functions
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_35 Your_png_h_is_not_version_1_6_35;
+typedef png_libpng_version_1_6_36 Your_png_h_is_not_version_1_6_36;
#ifdef __GNUC__
/* The version tests may need to be added to, but the problem warning has
int PNGAPI
png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)
{
- static PNG_CONST char short_months[12][4] =
+ static const char short_months[12][4] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
#ifdef PNG_STRING_COPYRIGHT
return PNG_STRING_COPYRIGHT
#else
-# ifdef __STDC__
return PNG_STRING_NEWLINE \
- "libpng version 1.6.35 - July 15, 2018" PNG_STRING_NEWLINE \
+ "libpng version 1.6.36" PNG_STRING_NEWLINE \
+ "Copyright (c) 2018 Cosmin Truta" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
PNG_STRING_NEWLINE \
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
"Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
PNG_STRING_NEWLINE;
-# else
- return "libpng version 1.6.35 - July 15, 2018\
- Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson\
- Copyright (c) 1996-1997 Andreas Dilger\
- Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
-# endif
#endif
}
png_colorspacerp colorspace, png_fixed_point gAMA)
{
/* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
- * occur. Since the fixed point representation is asymetrical it is
+ * occur. Since the fixed point representation is asymmetrical it is
* possible for 1/gamma to overflow the limit of 21474 and this means the
* gamma value must be at least 5/100000 and hence at most 20000.0. For
* safety the limits here are a little narrower. The values are 0.00016 to
/* The total output count (max) is now 4+precision */
/* Check for an exponent, if we don't need one we are
- * done and just need to terminate the string. At
- * this point exp_b10==(-1) is effectively a flag - it got
- * to '-1' because of the decrement after outputting
- * the decimal point above (the exponent required is
- * *not* -1!)
+ * done and just need to terminate the string. At this
+ * point, exp_b10==(-1) is effectively a flag: it got
+ * to '-1' because of the decrement, after outputting
+ * the decimal point above. (The exponent required is
+ * *not* -1.)
*/
if (exp_b10 >= (-1) && exp_b10 <= 2)
{
*/
static void
png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
- PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
+ unsigned int shift, png_fixed_point gamma_val)
{
/* Various values derived from 'shift': */
- PNG_CONST unsigned int num = 1U << (8U - shift);
+ unsigned int num = 1U << (8U - shift);
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
/* CSE the division and work round wacky GCC warnings (see the comments
* in png_gamma_8bit_correct for where these come from.)
*/
- PNG_CONST double fmax = 1./(((png_int_32)1 << (16U - shift))-1);
+ double fmax = 1.0 / (((png_int_32)1 << (16U - shift)) - 1);
#endif
- PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
- PNG_CONST unsigned int max_by_2 = 1U << (15U-shift);
+ unsigned int max = (1U << (16U - shift)) - 1U;
+ unsigned int max_by_2 = 1U << (15U - shift);
unsigned int i;
png_uint_16pp table = *ptable =
*/
static void
png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
- PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
+ unsigned int shift, png_fixed_point gamma_val)
{
- PNG_CONST unsigned int num = 1U << (8U - shift);
- PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
+ unsigned int num = 1U << (8U - shift);
+ unsigned int max = (1U << (16U - shift))-1U;
unsigned int i;
png_uint_32 last;
*/
static void
png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable,
- PNG_CONST png_fixed_point gamma_val)
+ png_fixed_point gamma_val)
{
unsigned int i;
png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256);
/* png.h - header file for PNG reference library
*
- * libpng version 1.6.35, July 15, 2018
+ * libpng version 1.6.36 - December 1, 2018
*
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
- * This code is released under the libpng license (See LICENSE, below)
+ * This code is released under the libpng license. (See LICENSE, below.)
*
* Authors and maintainers:
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
* libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
- * libpng versions 0.97, January 1998, through 1.6.35, July 15, 2018:
+ * libpng versions 0.97, January 1998, through 1.6.35, July 2018:
* Glenn Randers-Pehrson.
+ * libpng version 1.6.36, December 1, 2018: Cosmin Truta
* See also "Contributing Authors", below.
*/
/*
- * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+ * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
+ * =========================================
+ *
+ * PNG Reference Library License version 2
+ * ---------------------------------------
+ *
+ * * Copyright (c) 1995-2018 The PNG Reference Library Authors.
+ * * Copyright (c) 2018 Cosmin Truta.
+ * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
+ * * Copyright (c) 1996-1997 Andreas Dilger.
+ * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+ *
+ * The software is supplied "as is", without warranty of any kind,
+ * express or implied, including, without limitation, the warranties
+ * of merchantability, fitness for a particular purpose, title, and
+ * non-infringement. In no even shall the Copyright owners, or
+ * anyone distributing the software, be liable for any damages or
+ * other liability, whether in contract, tort or otherwise, arising
+ * from, out of, or in connection with the software, or the use or
+ * other dealings in the software, even if advised of the possibility
+ * of such damage.
+ *
+ * Permission is hereby granted to use, copy, modify, and distribute
+ * this software, or portions hereof, for any purpose, without fee,
+ * subject to the following restrictions:
*
- * If you modify libpng you may insert additional notices immediately following
- * this sentence.
+ * 1. The origin of this software must not be misrepresented; you
+ * must not claim that you wrote the original software. If you
+ * use this software in a product, an acknowledgment in the product
+ * documentation would be appreciated, but is not required.
*
- * This code is released under the libpng license.
+ * 2. Altered source versions must be plainly marked as such, and must
+ * not be misrepresented as being the original software.
+ *
+ * 3. This Copyright notice may not be removed or altered from any
+ * source or altered source distribution.
+ *
+ *
+ * PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
+ * -----------------------------------------------------------------------
*
* libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are
* Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
* disclaimer and license as libpng-1.0.6 with the following individuals
* added to the list of Contributing Authors:
*
- * Simon-Pierre Cadieux
- * Eric S. Raymond
- * Mans Rullgard
- * Cosmin Truta
- * Gilles Vollant
- * James Yu
- * Mandar Sahastrabuddhe
- * Google Inc.
- * Vadim Barkov
+ * Simon-Pierre Cadieux
+ * Eric S. Raymond
+ * Mans Rullgard
+ * Cosmin Truta
+ * Gilles Vollant
+ * James Yu
+ * Mandar Sahastrabuddhe
+ * Google Inc.
+ * Vadim Barkov
*
* and with the following additions to the disclaimer:
*
- * There is no warranty against interference with your enjoyment of the
- * library or against infringement. There is no warranty that our
- * efforts or the library will fulfill any of your particular purposes
- * or needs. This library is provided with all faults, and the entire
- * risk of satisfactory quality, performance, accuracy, and effort is with
- * the user.
+ * There is no warranty against interference with your enjoyment of
+ * the library or against infringement. There is no warranty that our
+ * efforts or the library will fulfill any of your particular purposes
+ * or needs. This library is provided with all faults, and the entire
+ * risk of satisfactory quality, performance, accuracy, and effort is
+ * with the user.
*
* Some files in the "contrib" directory and some configure-generated
- * files that are distributed with libpng have other copyright owners and
+ * files that are distributed with libpng have other copyright owners, and
* are released under other open source licenses.
*
* libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
* Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
* libpng-0.96, and are distributed according to the same disclaimer and
- * license as libpng-0.96, with the following individuals added to the list
- * of Contributing Authors:
+ * license as libpng-0.96, with the following individuals added to the
+ * list of Contributing Authors:
*
- * Tom Lane
- * Glenn Randers-Pehrson
- * Willem van Schaik
+ * Tom Lane
+ * Glenn Randers-Pehrson
+ * Willem van Schaik
*
* libpng versions 0.89, June 1996, through 0.96, May 1997, are
* Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
* libpng-0.88, with the following individuals added to the list of
* Contributing Authors:
*
- * John Bowler
- * Kevin Bracey
- * Sam Bushell
- * Magnus Holmgren
- * Greg Roelofs
- * Tom Tanner
+ * John Bowler
+ * Kevin Bracey
+ * Sam Bushell
+ * Magnus Holmgren
+ * Greg Roelofs
+ * Tom Tanner
*
- * Some files in the "scripts" directory have other copyright owners
+ * Some files in the "scripts" directory have other copyright owners,
* but are released under this license.
*
* libpng versions 0.5, May 1995, through 0.88, January 1996, are
* For the purposes of this copyright and license, "Contributing Authors"
* is defined as the following set of individuals:
*
- * Andreas Dilger
- * Dave Martindale
- * Guy Eric Schalnat
- * Paul Schmidt
- * Tim Wegner
- *
- * The PNG Reference Library is supplied "AS IS". The Contributing Authors
- * and Group 42, Inc. disclaim all warranties, expressed or implied,
- * including, without limitation, the warranties of merchantability and of
- * fitness for any purpose. The Contributing Authors and Group 42, Inc.
- * assume no liability for direct, indirect, incidental, special, exemplary,
- * or consequential damages, which may result from the use of the PNG
- * Reference Library, even if advised of the possibility of such damage.
+ * Andreas Dilger
+ * Dave Martindale
+ * Guy Eric Schalnat
+ * Paul Schmidt
+ * Tim Wegner
+ *
+ * The PNG Reference Library is supplied "AS IS". The Contributing
+ * Authors and Group 42, Inc. disclaim all warranties, expressed or
+ * implied, including, without limitation, the warranties of
+ * merchantability and of fitness for any purpose. The Contributing
+ * Authors and Group 42, Inc. assume no liability for direct, indirect,
+ * incidental, special, exemplary, or consequential damages, which may
+ * result from the use of the PNG Reference Library, even if advised of
+ * the possibility of such damage.
*
* Permission is hereby granted to use, copy, modify, and distribute this
* source code, or portions hereof, for any purpose, without fee, subject
* to the following restrictions:
*
- * 1. The origin of this source code must not be misrepresented.
+ * 1. The origin of this source code must not be misrepresented.
*
- * 2. Altered versions must be plainly marked as such and must not
- * be misrepresented as being the original source.
+ * 2. Altered versions must be plainly marked as such and must not
+ * be misrepresented as being the original source.
*
- * 3. This Copyright notice may not be removed or altered from any
- * source or altered source distribution.
+ * 3. This Copyright notice may not be removed or altered from any
+ * source or altered source distribution.
*
- * The Contributing Authors and Group 42, Inc. specifically permit, without
- * fee, and encourage the use of this source code as a component to
- * supporting the PNG file format in commercial products. If you use this
- * source code in a product, acknowledgment is not required but would be
- * appreciated.
+ * The Contributing Authors and Group 42, Inc. specifically permit,
+ * without fee, and encourage the use of this source code as a component
+ * to supporting the PNG file format in commercial products. If you use
+ * this source code in a product, acknowledgment is not required but would
+ * be appreciated.
*
* END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
*
- * TRADEMARK:
+ * TRADEMARK
+ * =========
*
- * The name "libpng" has not been registered by the Copyright owner
+ * The name "libpng" has not been registered by the Copyright owners
* as a trademark in any jurisdiction. However, because libpng has
* been distributed and maintained world-wide, continually since 1995,
- * the Copyright owner claims "common-law trademark protection" in any
+ * the Copyright owners claim "common-law trademark protection" in any
* jurisdiction where common-law trademark is recognized.
- *
- * OSI CERTIFICATION:
- *
- * Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
- * a certification mark of the Open Source Initiative. OSI has not addressed
- * the additional disclaimers inserted at version 1.0.7.
- *
- * EXPORT CONTROL:
- *
- * The Copyright owner believes that the Export Control Classification
- * Number (ECCN) for libpng is EAR99, which means not subject to export
- * controls or International Traffic in Arms Regulations (ITAR) because
- * it is open source, publicly available software, that does not contain
- * any encryption software. See the EAR, paragraphs 734.3(b)(3) and
- * 734.7(b).
*/
/*
* 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible)
* 1.0.7 1 10007 (still compatible)
* ...
- * 1.0.19 10 10019 10.so.0.19[.0]
+ * 1.0.69 10 10069 10.so.0.69[.0]
* ...
- * 1.2.59 13 10257 12.so.0.59[.0]
+ * 1.2.59 13 10259 12.so.0.59[.0]
* ...
- * 1.5.30 15 10527 15.so.15.30[.0]
+ * 1.4.20 14 10420 14.so.0.20[.0]
* ...
- * 1.6.35 16 10635 16.so.16.35[.0]
- *
- * Henceforth the source version will match the shared-library major
- * and minor numbers; the shared-library major version number will be
- * used for changes in backward compatibility, as it is intended. The
- * PNG_LIBPNG_VER macro, which is not used within libpng but is available
- * for applications, is an unsigned integer of the form xyyzz corresponding
- * to the source version x.y.z (leading zeros in y and z). Beta versions
- * were given the previous public release number plus a letter, until
- * version 1.0.6j; from then on they were given the upcoming public
- * release number plus "betaNN" or "rcNN".
+ * 1.5.30 15 10530 15.so.15.30[.0]
+ * ...
+ * 1.6.36 16 10636 16.so.16.36[.0]
+ *
+ * Henceforth the source version will match the shared-library major and
+ * minor numbers; the shared-library major version number will be used for
+ * changes in backward compatibility, as it is intended.
+ * The PNG_LIBPNG_VER macro, which is not used within libpng but is
+ * available for applications, is an unsigned integer of the form XYYZZ
+ * corresponding to the source version X.Y.Z (leading zeros in Y and Z).
+ * Beta versions were given the previous public release number plus a
+ * letter, until version 1.0.6j; from then on they were given the upcoming
+ * public release number plus "betaNN" or "rcNN".
*
* Binary incompatibility exists only when applications make direct access
* to the info_ptr or png_ptr members through png.h, and the compiled
* in binary compatibility (e.g., when a new feature is added).
*
* See libpng.txt or libpng.3 for more information. The PNG specification
- * is available as a W3C Recommendation and as an ISO Specification,
- * <https://www.w3.org/TR/2003/REC-PNG-20031110/
- */
-
-/*
- * Y2K compliance in libpng:
- * =========================
- *
- * July 15, 2018
- *
- * Since the PNG Development group is an ad-hoc body, we can't make
- * an official declaration.
- *
- * This is your unofficial assurance that libpng from version 0.71 and
- * upward through 1.6.35 are Y2K compliant. It is my belief that
- * earlier versions were also Y2K compliant.
- *
- * Libpng only has two year fields. One is a 2-byte unsigned integer
- * that will hold years up to 65535. The other, which is deprecated,
- * holds the date in text format, and will hold years up to 9999.
- *
- * The integer is
- * "png_uint_16 year" in png_time_struct.
- *
- * The string is
- * "char time_buffer[29]" in png_struct. This is no longer used
- * in libpng-1.6.x and will be removed from libpng-1.7.0.
- *
- * There are seven time-related functions:
- * png.c: png_convert_to_rfc_1123_buffer() in png.c
- * (formerly png_convert_to_rfc_1123() prior to libpng-1.5.x and
- * png_convert_to_rfc_1152() in error prior to libpng-0.98)
- * png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c
- * png_convert_from_time_t() in pngwrite.c
- * png_get_tIME() in pngget.c
- * png_handle_tIME() in pngrutil.c, called in pngread.c
- * png_set_tIME() in pngset.c
- * png_write_tIME() in pngwutil.c, called in pngwrite.c
- *
- * All handle dates properly in a Y2K environment. The
- * png_convert_from_time_t() function calls gmtime() to convert from system
- * clock time, which returns (year - 1900), which we properly convert to
- * the full 4-digit year. There is a possibility that libpng applications
- * are not passing 4-digit years into the png_convert_to_rfc_1123_buffer()
- * function, or that they are incorrectly passing only a 2-digit year
- * instead of "year - 1900" into the png_convert_from_struct_tm() function,
- * but this is not under our control. The libpng documentation has always
- * stated that it works with 4-digit years, and the APIs have been
- * documented as such.
- *
- * The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned
- * integer to hold the year, and can hold years as large as 65535.
- *
- * zlib, upon which libpng depends, is also Y2K compliant. It contains
- * no date-related code.
- *
- * Glenn Randers-Pehrson
- * libpng maintainer
- * PNG Development Group
+ * is available as a W3C Recommendation and as an ISO/IEC Standard; see
+ * <https://www.w3.org/TR/2003/REC-PNG-20031110/>
*/
#ifndef PNG_H
*/
/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.35"
-#define PNG_HEADER_VERSION_STRING " libpng version 1.6.35 - July 15, 2018\n"
+#define PNG_LIBPNG_VER_STRING "1.6.36"
+#define PNG_HEADER_VERSION_STRING " libpng version 1.6.36 - December 1, 2018\n"
#define PNG_LIBPNG_VER_SONUM 16
#define PNG_LIBPNG_VER_DLLNUM 16
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
#define PNG_LIBPNG_VER_MINOR 6
-#define PNG_LIBPNG_VER_RELEASE 35
+#define PNG_LIBPNG_VER_RELEASE 36
/* This should match the numeric part of the final component of
* PNG_LIBPNG_VER_STRING, omitting any leading zero:
*/
-#define PNG_LIBPNG_VER_BUILD 02
+#define PNG_LIBPNG_VER_BUILD 0
/* Release Status */
#define PNG_LIBPNG_BUILD_ALPHA 1
#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with
PNG_LIBPNG_BUILD_PRIVATE */
-#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_BETA
+#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE
-/* Careful here. At one time, Guy wanted to use 082, but that would be octal.
- * We must not include leading zeros.
- * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
- * version 1.0.0 was mis-numbered 100 instead of 10000). From
- * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release
+/* Careful here. At one time, Guy wanted to use 082, but that
+ * would be octal. We must not include leading zeros.
+ * Versions 0.7 through 1.0.0 were in the range 0 to 100 here
+ * (only version 1.0.0 was mis-numbered 100 instead of 10000).
+ * From version 1.0.1 it is:
+ * XXYYZZ, where XX=major, YY=minor, ZZ=release
*/
-#define PNG_LIBPNG_VER 10635 /* 1.6.35 */
+#define PNG_LIBPNG_VER 10636 /* 1.6.36 */
/* Library configuration: these options cannot be changed after
* the library has been built.
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
-typedef char* png_libpng_version_1_6_35;
+typedef char* png_libpng_version_1_6_36;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
*
PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr,
png_inforp info_ptr, png_bytep *exif));
PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr,
- png_inforp info_ptr, const png_bytep exif));
+ png_inforp info_ptr, png_bytep exif));
PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr,
png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif));
PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr,
- png_inforp info_ptr, const png_uint_32 num_exif, const png_bytep exif));
+ png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif));
#endif
#ifdef PNG_gAMA_SUPPORTED
*
* When the simplified API needs to convert between sRGB and linear colorspaces,
* the actual sRGB transfer curve defined in the sRGB specification (see the
- * article at https://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2
+ * article at <https://en.wikipedia.org/wiki/SRGB>) is used, not the gamma=1/2.2
* approximation used elsewhere in libpng.
*
* When an alpha channel is present it is expected to denote pixel coverage
* 'flags' field of png_image.
*/
#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01
- /* This indicates the the RGB values of the in-memory bitmap do not
+ /* This indicates that the RGB values of the in-memory bitmap do not
* correspond to the red, green and blue end-points defined by sRGB.
*/
/* pngconf.h - machine configurable file for libpng
*
- * libpng version 1.6.35, July 15, 2018
+ * libpng version 1.6.36
*
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
#endif /* PNG_BUILDING_SYMBOL_TABLE */
-/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using
- * PNG_NO_CONST; this is no longer supported except for data declarations which
- * apparently still cause problems in 2011 on some compilers.
+/* Prior to 1.6.0, it was possible to turn off 'const' in declarations,
+ * using PNG_NO_CONST. This is no longer supported.
*/
#define PNG_CONST const /* backward compatibility only */
-/* This controls optimization of the reading of 16-bit and 32-bit values
- * from PNG files. It can be set on a per-app-file basis - it
+/* This controls optimization of the reading of 16-bit and 32-bit
+ * values from PNG files. It can be set on a per-app-file basis: it
* just changes whether a macro is used when the function is called.
* The library builder sets the default; if read functions are not
* built into the library the macro implementation is forced on.
/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
*
- * Last changed in libpng 1.6.8 [December 19, 2013]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
/* pngerror.c - stub functions for i/o and memory allocation
*
- * Last changed in libpng 1.6.31 [July 27, 2017]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* if the character is invalid.
*/
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
-static PNG_CONST char png_digit[16] = {
+static const char png_digit[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'
};
png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
PNG_NORETURN)
{
- const png_const_structrp png_ptr = png_nonconst_ptr;
+ png_const_structrp png_ptr = png_nonconst_ptr;
png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
/* An error is always logged here, overwriting anything (typically a warning)
void /* PRIVATE */ PNGCBAPI
png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
{
- const png_const_structrp png_ptr = png_nonconst_ptr;
+ png_const_structrp png_ptr = png_nonconst_ptr;
png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
/* A warning is only logged if there is no prior warning or error. */
/* pngget.c - retrieval of values from info struct
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
/* pnginfo.h - header file for PNG reference library
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2013,2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
-/* libpng 1.6.34 STANDARD API DEFINITION */
-
/* pnglibconf.h - library build configuration */
-/* Libpng version 1.6.34 - September 29, 2017 */
+/* libpng version 1.6.36 */
-/* Copyright (c) 1998-2017 Glenn Randers-Pehrson */
+/* Copyright (c) 2018 Cosmin Truta */
+/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
/* This code is released under the libpng license. */
/* For conditions of distribution and use, see the disclaimer */
#define PNG_ALIGNED_MEMORY_SUPPORTED
/*#undef PNG_ARM_NEON_API_SUPPORTED*/
/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
-/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/
-/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/
#define PNG_BENIGN_ERRORS_SUPPORTED
#define PNG_BENIGN_READ_ERRORS_SUPPORTED
/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
#define PNG_IO_STATE_SUPPORTED
#define PNG_MNG_FEATURES_SUPPORTED
#define PNG_POINTER_INDEXING_SUPPORTED
+/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/
+/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/
#define PNG_PROGRESSIVE_READ_SUPPORTED
#define PNG_READ_16BIT_SUPPORTED
#define PNG_READ_ALPHA_MODE_SUPPORTED
/* pngmem.c - stub functions for memory allocation
*
- * Last changed in libpng 1.6.26 [October 20, 2016]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
/* pngpread.c - read a png file in push mode
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
+ static const png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
+ static const png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
/* Height of interlace block. This is not currently used - if you need
* it, uncomment it here and in png.h
- static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
*/
#endif
/* pngpriv.h - private declarations for use inside libpng
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
# else /* !defined __ARM_NEON__ */
/* The 'intrinsics' code simply won't compile without this -mfpu=neon:
*/
-# define PNG_ARM_NEON_IMPLEMENTATION 2
+# if !defined(__aarch64__)
+ /* The assembler code currently does not work on ARM64 */
+# define PNG_ARM_NEON_IMPLEMENTATION 2
+# endif /* __aarch64__ */
# endif /* __ARM_NEON__ */
# endif /* !PNG_ARM_NEON_IMPLEMENTATION */
#endif
PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_const_structrp png_ptr,
- const png_uint_32 chunk_name),PNG_EMPTY);
+ png_uint_32 chunk_name),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_check_chunk_length,(png_const_structrp png_ptr,
- const png_uint_32 chunk_length),PNG_EMPTY);
+ png_uint_32 chunk_length),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr,
png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
png_const_charp key, png_bytep new_key), PNG_EMPTY);
+#if PNG_ARM_NEON_IMPLEMENTATION == 1
+PNG_INTERNAL_FUNCTION(void,
+ png_riffle_palette_rgba,
+ (png_structrp, png_row_infop),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int,
+ png_do_expand_palette_neon_rgba,
+ (png_structrp,
+ png_row_infop,
+ png_const_bytep,
+ const png_bytepp,
+ const png_bytepp),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int,
+ png_do_expand_palette_neon_rgb,
+ (png_structrp,
+ png_row_infop,
+ png_const_bytep,
+ const png_bytepp,
+ const png_bytepp),
+ PNG_EMPTY);
+#endif
+
/* Maintainer: Put new private prototypes here ^ */
#include "pngdebug.h"
/* pngread.c - read a PNG file
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* errors (which are unfortunately quite common.)
*/
{
- static PNG_CONST png_byte chunks_to_process[] = {
+ static const png_byte chunks_to_process[] = {
98, 75, 71, 68, '\0', /* bKGD */
99, 72, 82, 77, '\0', /* cHRM */
103, 65, 77, 65, '\0', /* gAMA */
png_uint_32 alpha, int encoding)
{
png_imagep image = display->image;
- const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
+ int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
P_LINEAR : P_sRGB;
- const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
+ int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
(red != green || green != blue);
if (ip > 255)
/* Store the value. */
{
# ifdef PNG_FORMAT_AFIRST_SUPPORTED
- const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
+ int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
(image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
# else
# define afirst 0
# endif
# ifdef PNG_FORMAT_BGR_SUPPORTED
- const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
+ int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
# else
# define bgr 0
# endif
{
png_image_read_control *display =
png_voidcast(png_image_read_control*, argument);
- const png_imagep image = display->image;
+ png_imagep image = display->image;
- const png_structrp png_ptr = image->opaque->png_ptr;
- const png_uint_32 output_format = image->format;
- const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
+ png_structrp png_ptr = image->opaque->png_ptr;
+ png_uint_32 output_format = image->format;
+ int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
P_LINEAR : P_sRGB;
unsigned int cmap_entries;
unsigned int num_trans = png_ptr->num_trans;
png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL;
png_const_colorp colormap = png_ptr->palette;
- const int do_background = trans != NULL &&
+ int do_background = trans != NULL &&
(output_format & PNG_FORMAT_FLAG_ALPHA) == 0;
unsigned int i;
*/
if (linear != 0)
{
- PNG_CONST png_uint_16 le = 0x0001;
+ png_uint_16 le = 0x0001;
if ((*(png_const_bytep) & le) != 0)
png_set_swap(png_ptr);
* original PNG format because it may not occur in the output PNG format
* and libpng deals with the issues of reading the original.
*/
- const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
+ unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
/* The following checks just the 'row_stride' calculation to ensure it
* fits in a signed 32-bit value. Because channels/components can be
if (image->width <= 0x7fffffffU/channels) /* no overflow */
{
png_uint_32 check;
- const png_uint_32 png_row_stride = image->width * channels;
+ png_uint_32 png_row_stride = image->width * channels;
if (row_stride == 0)
row_stride = (png_int_32)/*SAFE*/png_row_stride;
/* pngrio.c - functions for data input
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
/* pngrtran.c - transforms the data in a row for PNG readers
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
#include "pngpriv.h"
+#ifdef PNG_ARM_NEON_IMPLEMENTATION
+# if PNG_ARM_NEON_IMPLEMENTATION == 1
+# define PNG_ARM_NEON_INTRINSICS_AVAILABLE
+# if defined(_MSC_VER) && defined(_M_ARM64)
+# include <arm64_neon.h>
+# else
+# include <arm_neon.h>
+# endif
+# endif
+#endif
+
#ifdef PNG_READ_SUPPORTED
/* Set the action on getting a CRC error for an ancillary or critical chunk. */
*/
static int
png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
-
{
int rgb_error = 0;
if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
(row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
- PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
- PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
- PNG_CONST png_uint_32 bc = 32768 - rc - gc;
- PNG_CONST png_uint_32 row_width = row_info->width;
- PNG_CONST int have_alpha =
- (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
+ png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
+ png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
+ png_uint_32 bc = 32768 - rc - gc;
+ png_uint_32 row_width = row_info->width;
+ int have_alpha = (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
if (row_info->bit_depth == 8)
{
{
if (row_info->bit_depth == 8)
{
- PNG_CONST png_bytep table = png_ptr->gamma_from_1;
+ png_bytep table = png_ptr->gamma_from_1;
if (table != NULL)
{
- PNG_CONST int step =
- (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
+ int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
/* The alpha channel is the last component: */
row += step - 1;
else if (row_info->bit_depth == 16)
{
- PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1;
- PNG_CONST int gamma_shift = png_ptr->gamma_shift;
+ png_uint_16pp table = png_ptr->gamma_16_from_1;
+ int gamma_shift = png_ptr->gamma_shift;
if (table != NULL)
{
- PNG_CONST int step =
- (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
+ int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
/* The alpha channel is the last component: */
row += step - 2;
* upon whether you supply trans and num_trans.
*/
static void
-png_do_expand_palette(png_row_infop row_info, png_bytep row,
- png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
+png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info,
+ png_bytep row, png_const_colorp palette, png_const_bytep trans_alpha,
+ int num_trans)
{
int shift, value;
png_bytep sp, dp;
sp = row + (size_t)row_width - 1;
dp = row + ((size_t)row_width << 2) - 1;
- for (i = 0; i < row_width; i++)
+ i = 0;
+#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
+ if (png_ptr->riffled_palette != NULL)
+ {
+ /* The RGBA optimization works with png_ptr->bit_depth == 8
+ * but sometimes row_info->bit_depth has been changed to 8.
+ * In these cases, the palette hasn't been riffled.
+ */
+ i = png_do_expand_palette_neon_rgba(png_ptr, row_info, row,
+ &sp, &dp);
+ }
+#endif
+
+ for (; i < row_width; i++)
{
if ((int)(*sp) >= num_trans)
*dp-- = 0xff;
-
else
*dp-- = trans_alpha[*sp];
-
*dp-- = palette[*sp].blue;
*dp-- = palette[*sp].green;
*dp-- = palette[*sp].red;
{
sp = row + (size_t)row_width - 1;
dp = row + (size_t)(row_width * 3) - 1;
+ i = 0;
+#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
+ i = png_do_expand_palette_neon_rgb(png_ptr, row_info, row,
+ &sp, &dp);
+#endif
- for (i = 0; i < row_width; i++)
+ for (; i < row_width; i++)
{
*dp-- = palette[*sp].blue;
*dp-- = palette[*sp].green;
{
if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
{
- png_do_expand_palette(row_info, png_ptr->row_buf + 1,
- png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
+#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
+ if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8))
+ {
+ /* Allocate space for the decompressed full palette. */
+ if (png_ptr->riffled_palette == NULL)
+ {
+ png_ptr->riffled_palette = png_malloc(png_ptr, 256*4);
+ if (png_ptr->riffled_palette == NULL)
+ png_error(png_ptr, "NULL row buffer");
+ /* Build the RGBA palette. */
+ png_riffle_palette_rgba(png_ptr, row_info);
+ }
+ }
+#endif
+ png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1,
+ png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
}
else
/* pngrutil.c - utilities to read a PNG file
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
{
/* We have the ICC profile header; do the basic header checks.
*/
- const png_uint_32 profile_length =
- png_get_uint_32(profile_header);
+ png_uint_32 profile_length = png_get_uint_32(profile_header);
if (png_icc_check_length(png_ptr, &png_ptr->colorspace,
keyword, profile_length) != 0)
* profile. The header check has already validated
* that none of this stuff will overflow.
*/
- const png_uint_32 tag_count = png_get_uint_32(
- profile_header+128);
+ png_uint_32 tag_count =
+ png_get_uint_32(profile_header + 128);
png_bytep profile = png_read_buffer(png_ptr,
profile_length, 2/*silent*/);
*/
void /* PRIVATE */
-png_check_chunk_name(png_const_structrp png_ptr, const png_uint_32 chunk_name)
+png_check_chunk_name(png_const_structrp png_ptr, png_uint_32 chunk_name)
{
int i;
png_uint_32 cn=chunk_name;
}
void /* PRIVATE */
-png_check_chunk_length(png_const_structrp png_ptr, const png_uint_32 length)
+png_check_chunk_length(png_const_structrp png_ptr, png_uint_32 length)
{
png_alloc_size_t limit = PNG_UINT_31_MAX;
/* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and
* then pass:
*/
- static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] =
+ static const png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] =
{
/* Little-endian byte masks for PACKSWAP */
{ S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) },
/* display_mask has only three entries for the odd passes, so index by
* pass>>1.
*/
- static PNG_CONST png_uint_32 display_mask[2][3][3] =
+ static const png_uint_32 display_mask[2][3][3] =
{
/* Little-endian byte masks for PACKSWAP */
{ B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) },
{
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Offset to next interlace block */
- static PNG_CONST unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
png_debug(1, "in png_do_read_interlace");
if (row != NULL && row_info != NULL)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+ static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+ static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
png_debug(1, "in png_read_finish_row");
png_ptr->row_number++;
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+ static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+ static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
unsigned int max_pixel_depth;
size_t row_bytes;
/* pngset.c - storage of image information into info struct
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
#ifdef PNG_eXIf_SUPPORTED
void PNGAPI
png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
- const png_bytep eXIf_buf)
+ png_bytep eXIf_buf)
{
png_warning(png_ptr, "png_set_eXIf does not work; use png_set_eXIf_1");
PNG_UNUSED(info_ptr)
void PNGAPI
png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr,
- const png_uint_32 num_exif, const png_bytep eXIf_buf)
+ png_uint_32 num_exif, png_bytep eXIf_buf)
{
int i;
/* Ignore all unknown chunks and all chunks recognized by
* libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
*/
- static PNG_CONST png_byte chunks_to_ignore[] = {
+ static const png_byte chunks_to_ignore[] = {
98, 75, 71, 68, '\0', /* bKGD */
99, 72, 82, 77, '\0', /* cHRM */
101, 88, 73, 102, '\0', /* eXIf */
/* pngstruct.h - header file for PNG reference library
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* big_row_buf; while writing it is separately
* allocated.
*/
+#ifdef PNG_READ_EXPAND_SUPPORTED
+ /* Buffer to accelerate palette transformations. */
+ png_bytep riffled_palette;
+#endif
#ifdef PNG_WRITE_FILTER_SUPPORTED
png_bytep try_row; /* buffer to save trial row when filtering */
png_bytep tst_row; /* buffer to save best trial row when filtering */
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
#endif
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
-static PNG_CONST png_byte onebppswaptable[256] = {
+static const png_byte onebppswaptable[256] = {
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};
-static PNG_CONST png_byte twobppswaptable[256] = {
+static const png_byte twobppswaptable[256] = {
0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
};
-static PNG_CONST png_byte fourbppswaptable[256] = {
+static const png_byte fourbppswaptable[256] = {
0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
/* pngwio.c - functions for data output
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2014,2016,2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
/* pngwrite.c - general routines to write a PNG file
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
#ifdef PNG_CONVERT_tIME_SUPPORTED
void PNGAPI
-png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime)
+png_convert_from_struct_tm(png_timep ptime, const struct tm * ttime)
{
png_debug(1, "in png_convert_from_struct_tm");
png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
png_free(png_ptr, png_ptr->row_buf);
png_ptr->row_buf = NULL;
+#ifdef PNG_READ_EXPANDED_SUPPORTED
+ png_free(png_ptr, png_ptr->riffled_palette);
+ png_ptr->riffled_palette = NULL;
+#endif
#ifdef PNG_WRITE_FILTER_SUPPORTED
png_free(png_ptr, png_ptr->prev_row);
png_free(png_ptr, png_ptr->try_row);
display->first_row);
png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
png_uint_16p row_end;
- const unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
+ unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
3 : 1;
int aindex = 0;
png_uint_32 y = image->height;
while (out_ptr < row_end)
{
- const png_uint_16 alpha = in_ptr[aindex];
+ png_uint_16 alpha = in_ptr[aindex];
png_uint_32 reciprocal = 0;
int c;
display->first_row);
png_bytep output_row = png_voidcast(png_bytep, display->local_row);
png_uint_32 y = image->height;
- const unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
+ unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
3 : 1;
if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
static void
png_image_set_PLTE(png_image_write_control *display)
{
- const png_imagep image = display->image;
+ png_imagep image = display->image;
const void *cmap = display->colormap;
- const int entries = image->colormap_entries > 256 ? 256 :
+ int entries = image->colormap_entries > 256 ? 256 :
(int)image->colormap_entries;
/* NOTE: the caller must check for cmap != NULL and entries != 0 */
- const png_uint_32 format = image->format;
- const unsigned int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
+ png_uint_32 format = image->format;
+ unsigned int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\
defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED)
- const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
+ int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
(format & PNG_FORMAT_FLAG_ALPHA) != 0;
# else
# define afirst 0
# endif
# ifdef PNG_FORMAT_BGR_SUPPORTED
- const int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
+ int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
# else
# define bgr 0
# endif
* and total image size to ensure that they are within the system limits.
*/
{
- const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
+ unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
if (image->width <= 0x7fffffffU/channels) /* no overflow */
{
png_uint_32 check;
- const png_uint_32 png_row_stride = image->width * channels;
+ png_uint_32 png_row_stride = image->width * channels;
if (display->row_stride == 0)
display->row_stride = (png_int_32)/*SAFE*/png_row_stride;
*/
if (write_16bit != 0)
{
- PNG_CONST png_uint_16 le = 0x0001;
+ png_uint_16 le = 0x0001;
if ((*(png_const_bytep) & le) != 0)
png_set_swap(png_ptr);
{
png_image_write_control *display = png_voidcast(png_image_write_control*,
png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/);
- const png_alloc_size_t ob = display->output_bytes;
+ png_alloc_size_t ob = display->output_bytes;
/* Check for overflow; this should never happen: */
if (size <= ((png_alloc_size_t)-1) - ob)
/* pngwtran.c - transforms the data in a row for PNG writers
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
for (i = 0; i < istop; i++, bp++)
{
-
- const unsigned int c = i%channels;
+ unsigned int c = i%channels;
int j;
unsigned int v, out;
for (bp = row, i = 0; i < istop; i++)
{
- const unsigned int c = i%channels;
+ unsigned int c = i%channels;
int j;
unsigned int value, v;
/* pngwutil.c - utilities to write a PNG file
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+ static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+ static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif
png_alloc_size_t buf_size;
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+ static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+ static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif
png_debug(1, "in png_write_finish_row");
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
png_debug(1, "in png_do_write_interlace");
#ifdef PNG_WRITE_FILTER_SUPPORTED
static size_t /* PRIVATE */
-png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp,
+png_setup_sub_row(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes, size_t lmins)
{
png_bytep rp, dp, lp;
}
static void /* PRIVATE */
-png_setup_sub_row_only(png_structrp png_ptr, const png_uint_32 bpp,
+png_setup_sub_row_only(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes)
{
png_bytep rp, dp, lp;
}
static size_t /* PRIVATE */
-png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp,
+png_setup_avg_row(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes, size_t lmins)
{
png_bytep rp, dp, pp, lp;
return (sum);
}
static void /* PRIVATE */
-png_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp,
+png_setup_avg_row_only(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes)
{
png_bytep rp, dp, pp, lp;
}
static size_t /* PRIVATE */
-png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
+png_setup_paeth_row(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes, size_t lmins)
{
png_bytep rp, dp, pp, cp, lp;
return (sum);
}
static void /* PRIVATE */
-png_setup_paeth_row_only(png_structrp png_ptr, const png_uint_32 bpp,
+png_setup_paeth_row_only(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes)
{
png_bytep rp, dp, pp, cp, lp;
/* filter_vsx_intrinsics.c - PowerPC optimised filter functions
*
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2017 Glenn Randers-Pehrson
* Written by Vadim Barkov, 2017.
- * Last changed in libpng 1.6.29 [March 16, 2017]
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
+
#include <stdio.h>
#include <stdint.h>
#include "../pngpriv.h"
void png_read_filter_row_sub4_vsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
- const png_byte bpp = 4;
+ png_byte bpp = 4;
vector unsigned char rp_vec;
vector unsigned char part_vec;
void png_read_filter_row_sub3_vsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
- const png_byte bpp = 3;
+ png_byte bpp = 3;
vector unsigned char rp_vec;
vector unsigned char part_vec;
void png_read_filter_row_avg4_vsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
- const png_byte bpp = 4;
+ png_byte bpp = 4;
vector unsigned char rp_vec;
vector unsigned char pp_vec;
void png_read_filter_row_avg3_vsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
- const png_byte bpp = 3;
+ png_byte bpp = 3;
vector unsigned char rp_vec;
vector unsigned char pp_vec;
void png_read_filter_row_paeth4_vsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
- const png_byte bpp = 4;
+ png_byte bpp = 4;
int a, b, c, pa, pb, pc, p;
vector unsigned char rp_vec;
void png_read_filter_row_paeth3_vsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
- const png_byte bpp = 3;
+ png_byte bpp = 3;
int a, b, c, pa, pb, pc, p;
vector unsigned char rp_vec;
/* powerpc_init.c - POWERPC optimised filter functions
*
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2017 Glenn Randers-Pehrson
* Written by Vadim Barkov, 2017.
- * Last changed in libpng 1.6.29 [March 16, 2017]
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
+
/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
* called.
*/
tif_tile.c
tif_version.c
tif_warning.c
+ tif_webp.c
tif_write.c
tif_zip.c
+ tif_zstd.c
tif_stream.cxx
- snprintf.c
t4.h
tif_dir.h
tif_fax3.h
"${CMAKE_CURRENT_BINARY_DIR}/tiffconf.h"
)
+if(WIN32 AND NOT HAVE_SNPRINTF)
+ list(APPEND lib_srcs snprintf.c libport.h)
+endif()
+
if(WIN32 AND NOT WINRT)
list(APPEND lib_srcs tif_win32.c)
else()
-Wimplicit-fallthrough
)
ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter) # clang
-ocv_warnings_disable(CMAKE_CXX_FLAGS -Wmissing-declarations -Wunused-parameter
+ocv_warnings_disable(CMAKE_CXX_FLAGS -Wmissing-declarations -Wunused-parameter -Wmissing-prototypes
-Wundef # tiffiop.h: #if __clang_major__ >= 4
)
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4018 /wd4100 /wd4127 /wd4311 /wd4701 /wd4706) # vs2005
+2018-11-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * configure.ac: libtiff 4.0.10 released.
+
+ Change COMPRESSION_ZSTD to 50000 and COMPRESSION_WEBP to 50001.
+
+2018-11-04 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ Added preliminary release notes for release 4.0.10.
+
+2018-11-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ tiff2pdf: Eliminate compiler warning about snprintf output truncation when formatting pdf_datetime.
+
+2018-11-03 Olivier Paquet <olivier.paquet@gmail.com>
+
+ Merge branch 'no_tif_platform_console' into 'master'
+ Remove builtin support for GUI warning and error message boxes
+
+ See merge request libtiff/libtiff!24
+
+2018-11-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ tiffcrop.c: Eliminate compiler warning about snprintf output truncation when formatting filenum.
+
+ TWebPVGetField(): Add apparently missing break statement impacting TIFFTAG_WEBP_LOSSLESS.
+
+ Eliminate compiler warnings about duplicate definitions of streq/strneq macros.
+
+ Ignore generated files.
+
+ Remove and ignore files which are a product of autogen.sh.
+
+2018-11-02 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ Fix TIFFErrorExt() formatting of size_t type for 32-bit compiles.
+
+2018-10-30 Even Rouault <even.rouault@spatialys.com>
+
+ tiff2bw: avoid null pointer dereference in case of out of memory situation. Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2819 / CVE-2018-18661
+
+ tiffio.h: fix comment.
+
+2018-10-26 Even Rouault <even.rouault@spatialys.com>
+
+ Merge branch 'header2' into 'master'
+ Fix 725279bd: Standalone tif_predict.h: tiff.h should be tiffiop.h
+
+ See merge request libtiff/libtiff!41
+
+2018-10-26 Kurt Schwehr <schwehr@google.com>
+
+ Fix 725279bd: Standalone tif_predict.h: tiff.h should be tiffiop.h.
+
+2018-10-25 Even Rouault <even.rouault@spatialys.com>
+
+ Merge branch 'headers' into 'master'
+ Add includes to headers to allow them to stand alone.
+
+ See merge request libtiff/libtiff!40
+
+2018-10-24 Kurt Schwehr <schwehr@google.com>
+
+ Add includes to headers to allow them to stand alone.
+ This allows compilers that can do header stand alone header parsing
+ to process libtiff.
+
+2018-10-18 Even Rouault <even.rouault@spatialys.com>
+
+ LZMAPreEncode: emit verbose error if lzma_stream_encoder() fails (typically because not enough memory available)
+
+2018-10-17 Even Rouault <even.rouault@spatialys.com>
+
+ tif_webp.c: fix previous commit that broke scanline decoding.
+
+ tif_webp.c: fix potential read outside libwebp buffer on corrupted images
+
+2018-10-14 Even Rouault <even.rouault@spatialys.com>
+
+ Merge branch 'jbig_decode_overflow' into 'master'
+ JBIG: fix potential out-of-bounds write in JBIGDecode()
+
+ See merge request libtiff/libtiff!38
+
+2018-10-14 Even Rouault <even.rouault@spatialys.com>
+
+ JBIG: fix potential out-of-bounds write in JBIGDecode()
+ JBIGDecode doesn't check if the user provided buffer is large enough
+ to store the JBIG decoded image, which can potentially cause out-of-bounds
+ write in the buffer.
+ This issue was reported and analyzed by Thomas Dullien.
+
+ Also fixes a (harmless) potential use of uninitialized memory when
+ tif->tif_rawsize > tif->tif_rawcc
+
+ And in case libtiff is compiled with CHUNKY_STRIP_READ_SUPPORT, make sure
+ that whole strip data is provided to JBIGDecode()
+
+2018-10-05 Even Rouault <even.rouault@spatialys.com>
+
+ tif_webp.c: fix scanline reading/writing.
+
+ WEBP codec: initialize nSamples in TWebPSetupDecode() and TWebPSetupEncode()
+
+2018-10-05 Even Rouault <even.rouault@spatialys.com>
+
+ Merge branch 'tif_webp' into 'master'
+ webp support
+
+ See merge request libtiff/libtiff!32
+
+2018-10-05 Norman Barker <norman.barker@mapbox.com>
+
+ webp in tiff.
+
+2018-09-17 Even Rouault <even.rouault@spatialys.com>
+
+ Merge branch 'master' into 'master'
+ fix three potential vulnerabilities.
+
+ See merge request libtiff/libtiff!33
+
+2018-09-08 Young_X <YangX92@hotmail.com>
+
+ fix out-of-bound read on some tiled images.
+
+ avoid potential int32 overflows in multiply_ms()
+
+ only read/write TIFFTAG_GROUP3OPTIONS or TIFFTAG_GROUP4OPTIONS if compression is COMPRESSION_CCITTFAX3 or COMPRESSION_CCITTFAX4
+
+2018-08-15 Even Rouault <even.rouault@spatialys.com>
+
+ TIFFSetupStrips(): avoid potential uint32 overflow on 32-bit systems with large number of strips. Probably relates to http://bugzilla.maptools.org/show_bug.cgi?id=2788 / CVE-2018-10779
+
+2018-08-07 Even Rouault <even.rouault@spatialys.com>
+
+ ZSTD: fix flush issue that can cause endless loop in ZSTDEncode()
+ Fixes https://github.com/OSGeo/gdal/issues/833
+
+2018-08-07 Even Rouault <even.rouault@spatialys.com>
+
+ Merge branch 'fix_bug_2800' into 'master'
+ Fix libtiff 4.0.8 regression when reading LZW-compressed strips with scanline API
+
+ See merge request libtiff/libtiff!31
+
+2018-08-07 Even Rouault <even.rouault@spatialys.com>
+
+ Fix libtiff 4.0.8 regression when reading LZW-compressed strips with scanline API
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2800
+
+2018-07-05 Even Rouault <even.rouault@spatialys.com>
+
+ Add tag and pseudo-tag definitions for ESRI LERC codec (out of tree codec whose source is at https://github.com/OSGeo/gdal/blob/master/gdal/frmts/gtiff/tif_lerc.c)
+
+2018-07-02 Even Rouault <even.rouault@spatialys.com>
+
+ Fix TIFFTAG_ZSTD_LEVEL pseudo tag value to be > 65536, and the next one in the series
+
+2018-05-25 Stefan Weil <sw@weilnetz.de>
+
+ Remove builtin support for GUI warning and error message boxes.
+ Now warnings always go to the console by default unless applications
+ define their own warning and error handlers.
+
+ GUI applications (and Windows CE) are required to define such handlers.
+
+2018-05-12 Even Rouault <even.rouault@spatialys.com>
+
+ LZWDecodeCompat(): fix potential index-out-of-bounds write. Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2780 / CVE-2018-8905
+ The fix consists in using the similar code LZWDecode() to validate we
+ don't write outside of the output buffer.
+
+ TIFFFetchNormalTag(): avoid (probably false positive) clang-tidy clang-analyzer-core.NullDereference warnings
+
+ TIFFWriteDirectorySec: avoid assertion. Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2795. CVE-2018-10963
+
+2018-05-04 Even Rouault <even.rouault@spatialys.com>
+
+ tif_color.c: fix code comment.
+
+2018-04-17 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'fuzzer-fix' into 'master'
+ remove a pointless multiplication and a variable that's not necessary
+
+ See merge request libtiff/libtiff!29
+
+2018-04-17 Paul Kehrer <paul.l.kehrer@gmail.com>
+
+ remove a pointless multiplication and a variable that's not necessary.
+
+2018-04-17 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'ossfuzz' into 'master'
+ move oss-fuzz build script and fuzzer into libtiff tree
+
+ See merge request libtiff/libtiff!28
+
+2018-04-17 Paul Kehrer <paul.l.kehrer@gmail.com>
+
+ move oss-fuzz build script and fuzzer into libtiff tree.
+
+2018-04-14 Even Rouault <even.rouault@spatialys.com>
+
+ _TIFFGetMaxColorChannels: update for LOGLUV, ITULAB and ICCLAB that have 3 color channels
+
+2018-04-12 Even Rouault <even.rouault@spatialys.com>
+
+ Fix MSVC warning.
+
+2018-04-12 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'master' into 'master'
+ Fix NULL pointer dereference in TIFFPrintDirectory (bugzilla 2778/CVE-2018-7456)
+
+ See merge request libtiff/libtiff!27
+
+2018-04-11 Hugo Lefeuvre <hle@debian.org>
+
+ Fix NULL pointer dereference in TIFFPrintDirectory.
+ The TIFFPrintDirectory function relies on the following assumptions,
+ supposed to be guaranteed by the specification:
+
+ (a) A Transfer Function field is only present if the TIFF file has
+ photometric type < 3.
+
+ (b) If SamplesPerPixel > Color Channels, then the ExtraSamples field
+ has count SamplesPerPixel - (Color Channels) and contains
+ information about supplementary channels.
+
+ While respect of (a) and (b) are essential for the well functioning of
+ TIFFPrintDirectory, no checks are realized neither by the callee nor
+ by TIFFPrintDirectory itself. Hence, following scenarios might happen
+ and trigger the NULL pointer dereference:
+
+ (1) TIFF File of photometric type 4 or more has illegal Transfer
+ Function field.
+
+ (2) TIFF File has photometric type 3 or less and defines a
+ SamplesPerPixel field such that SamplesPerPixel > Color Channels
+ without defining all extra samples in the ExtraSamples fields.
+
+ In this patch, we address both issues with respect of the following
+ principles:
+
+ (A) In the case of (1), the defined transfer table should be printed
+ safely even if it isn't 'legal'. This allows us to avoid expensive
+ checks in TIFFPrintDirectory. Also, it is quite possible that
+ an alternative photometric type would be developed (not part of the
+ standard) and would allow definition of Transfer Table. We want
+ libtiff to be able to handle this scenario out of the box.
+
+ (B) In the case of (2), the transfer table should be printed at its
+ right size, that is if TIFF file has photometric type Palette
+ then the transfer table should have one row and not three, even
+ if two extra samples are declared.
+
+ In order to fulfill (A) we simply add a new 'i < 3' end condition to
+ the broken TIFFPrintDirectory loop. This makes sure that in any case
+ where (b) would be respected but not (a), everything stays fine.
+
+ (B) is fulfilled by the loop condition
+ 'i < td->td_samplesperpixel - td->td_extrasamples'. This is enough as
+ long as (b) is respected.
+
+ Naturally, we also make sure (b) is respected. This is done in the
+ TIFFReadDirectory function by making sure any non-color channel is
+ counted in ExtraSamples.
+
+ This commit addresses CVE-2018-7456.
+
+2018-03-27 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'tiffset-long8' into 'master'
+ tiffset: Add support for LONG8, SLONG8 and IFD8 field types
+
+ See merge request libtiff/libtiff!25
+
+2018-03-26 Roger Leigh <rleigh@codelibre.net>
+
+ port: Clean up NetBSD sources and headers to build standalone.
+
+2018-03-23 Roger Leigh <rleigh@dundee.ac.uk>
+
+ port: Add strtol, strtoll and strtoull.
+ Also update strtoul. All use the same implementation from NetBSD libc.
+
+ tiffset: Add support for LONG8, SLONG8 and IFD8 field types.
+
+2018-03-17 Even Rouault <even.rouault@spatialys.com>
+
+ ChopUpSingleUncompressedStrip: avoid memory exhaustion (CVE-2017-11613)
+ Rework fix done in 3719385a3fac5cfb20b487619a5f08abbf967cf8 to work in more
+ cases like https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=6979.
+ Credit to OSS Fuzz
+
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2724
+
+2018-03-13 Even Rouault <even.rouault@spatialys.com>
+
+ libtiff/tif_luv.c: rewrite loops in a more readable way (to avoid false positive reports like http://bugzilla.maptools.org/show_bug.cgi?id=2779)
+
+2018-03-13 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'avoid_memory_exhaustion_in_ChopUpSingleUncompressedStrip' into 'master'
+ ChopUpSingleUncompressedStrip: avoid memory exhaustion (CVE-2017-11613)
+
+ See merge request libtiff/libtiff!26
+
+2018-03-11 Even Rouault <even.rouault@spatialys.com>
+
+ ChopUpSingleUncompressedStrip: avoid memory exhaustion (CVE-2017-11613)
+ In ChopUpSingleUncompressedStrip(), if the computed number of strips is big
+ enough and we are in read only mode, validate that the file size is consistent
+ with that number of strips to avoid useless attempts at allocating a lot of
+ memory for the td_stripbytecount and td_stripoffset arrays.
+
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2724
+
+2018-03-10 Even Rouault <even.rouault@spatialys.com>
+
+ Typo fix in comment.
+
+2018-03-03 Even Rouault <even.rouault@spatialys.com>
+
+ Avoid warning with gcc 8 (partially revert 647b0e8c11ee11896f319b92cf110775f538d75c)
+
+2018-02-25 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'typos' into 'master'
+ Fix some typos
+
+ See merge request libtiff/libtiff!23
+
+2018-02-24 Stefan Weil <sw@weilnetz.de>
+
+ Fix some typos.
+ Most of them were found by codespell.
+
+2018-02-14 Even Rouault <even.rouault@spatialys.com>
+
+ Typo fix in comment.
+
+ Merge branch 'zstd'
+
+ Add warning about COMPRESSION_ZSTD not being officialy registered.
+
+2018-02-14 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'bug2772' into 'master'
+ Fix for bug 2772
+
+ See merge request libtiff/libtiff!20
+
+2018-02-12 Nathan Baker <nathanb@lenovo-chrome.com>
+
+ Fix for bug 2772.
+ It is possible to craft a TIFF document where the IFD list is circular,
+ leading to an infinite loop while traversing the chain. The libtiff
+ directory reader has a failsafe that will break out of this loop after
+ reading 65535 directory entries, but it will continue processing,
+ consuming time and resources to process what is essentially a bogus TIFF
+ document.
+
+ This change fixes the above behavior by breaking out of processing when
+ a TIFF document has >= 65535 directories and terminating with an error.
+
+2018-02-09 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'libtiff-as-subdirectory-fixes' into 'master'
+ Prefer target_include_directories
+
+ See merge request libtiff/libtiff!12
+
+2018-02-06 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'cmake-cleanups' into 'master'
+ Cmake cleanups
+
+ See merge request libtiff/libtiff!11
+
+2018-02-06 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'check-right-cxx-variable' into 'master'
+ Check right cxx variable
+
+ See merge request libtiff/libtiff!19
+
+2018-02-06 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'dont-leak-stream-open' into 'master'
+ Fix a memory leak in TIFFStreamOpen
+
+ See merge request libtiff/libtiff!17
+
+2018-02-06 Ben Boeckel <ben.boeckel@kitware.com>
+
+ cmake: check CXX_SUPPORT.
+ This variable is set in response to the `cxx` cache variable; use it
+ instead.
+
+2018-02-04 Olivier Paquet <olivier.paquet@gmail.com>
+
+ Merge branch 'warnings' into 'master'
+ Fix all compiler warnings for default build
+
+ See merge request libtiff/libtiff!16
+
+2018-02-04 Nathan Baker <elitebadger@gmail.com>
+
+ Fix all compiler warnings for default build.
+
+2018-01-30 Paul Kehrer <paul.l.kehrer@gmail.com>
+
+ tabs are hard.
+
+2018-01-29 Paul Kehrer <paul.l.kehrer@gmail.com>
+
+ use hard tabs like the rest of the project.
+
+ Fix a memory leak in TIFFStreamOpen.
+ TIFFStreamOpen allocates a new tiff{o,i}s_data, but if TIFFClientOpen
+ fails then that struct is leaked. Delete it if the returned TIFF * is
+ null.
+
+2018-01-29 Kevin Funk <kfunk@kde.org>
+
+ Bump minimum required CMake version to v2.8.11.
+ Because we use the BUILD_INTERFACE generator expression
+
+2018-01-27 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'patch-1' into 'master'
+ Update CMakeLists.txt for build fix on Windows
+
+ See merge request libtiff/libtiff!14
+
+2018-01-27 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'patch-2' into 'master'
+ Update tiffgt.c for build fix on Windows
+
+ See merge request libtiff/libtiff!13
+
+2018-01-25 Olivier Paquet <olivier.paquet@gmail.com>
+
+ Merge branch 'bug2750' into 'master'
+ Add workaround to pal2rgb buffer overflow.
+
+ See merge request libtiff/libtiff!15
+
+2018-01-25 Nathan Baker <elitebadger@gmail.com>
+
+ Add workaround to pal2rgb buffer overflow.
+
+2018-01-23 Andrea <andrea@andreaplanet.com>
+
+ Update tiffgt.c for build fix on Windows.
+
+ Update CMakeLists.txt for build fix on Windows.
+
+2018-01-15 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'has-attribute-check' into 'master'
+ tiffiop: use __has_attribute to detect the no_sanitize attribute
+
+ See merge request libtiff/libtiff!10
+
+2018-01-15 Ben Boeckel <ben.boeckel@kitware.com>
+
+ cmake: avoid setting hard-coded variables in the cache.
+
+ cmake: avoid an unnecessary intermediate variable.
+
+ cmake: avoid an unnecessary intermediate variable.
+
+ cmake: avoid tautological logic.
+
+ cmake: use check_symbol_exists.
+ This accounts for symbols being provided by macros.
+
+ cmake: remove unused configure checks.
+
+2018-01-12 Kevin Funk <kfunk@kde.org>
+
+ Prefer target_include_directories.
+ When libtiff is included in a super project via a simple
+ `add_subdirectory(libtiff)`, this way the `tiff` library target has all
+ the necessary information to build against it.
+
+ Note: The BUILD_INTERFACE generator expression feature requires at least
+ CMake v2.8.11 if I'm correct.
+
+2018-01-09 Ben Boeckel <ben.boeckel@kitware.com>
+
+ tiffiop: use __has_attribute to detect the no_sanitize attribute.
+
+2017-12-31 Even Rouault <even.rouault@spatialys.com>
+
+ man/TIFFquery.3tiff: remove reference to non-existing TIFFReadStrip() function in TIFFIsByteSwapped() documentation. Patch by Eric Piel. Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2763
+
+ libtiff/tif_dir.c: _TIFFVGetField(): fix heap out-of-bounds access when requesting TIFFTAG_NUMBEROFINKS on a EXIF directory. Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2765. Reported by Google Autofuzz project
+
+ libtiff/tif_print.c: TIFFPrintDirectory(): fix null pointer dereference on corrupted file. Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2770
+
+2017-12-21 Even Rouault <even.rouault@spatialys.com>
+
+ Add libzstd to gitlab-ci.
+
+2017-12-21 Even Rouault <even.rouault@spatialys.com>
+
+ Add ZSTD compression codec.
+ From https://github.com/facebook/zstd
+ "Zstandard, or zstd as short version, is a fast lossless compression
+ algorithm, targeting real-time compression scenarios at zlib-level
+ and better compression ratios. It's backed by a very fast entropy stage,
+ provided by Huff0 and FSE library."
+
+ We require libzstd >= 1.0.0 so as to be able to use streaming compression
+ and decompression methods.
+
+ The default compression level we have selected is 9 (range goes from 1 to 22),
+ which experimentally offers equivalent or better compression ratio than
+ the default deflate/ZIP level of 6, and much faster compression.
+
+ For example on a 6600x4400 16bit image, tiffcp -c zip runs in 10.7 seconds,
+ while tiffcp -c zstd runs in 5.3 seconds. Decompression time for zip is
+ 840 ms, and for zstd 650 ms. File size is 42735936 for zip, and
+ 42586822 for zstd. Similar findings on other images.
+
+ On a 25894x16701 16bit image,
+
+ Compression time Decompression time File size
+
+ ZSTD 35 s 3.2 s 399 700 498
+ ZIP/Deflate 1m 20 s 4.9 s 419 622 336
+
+2017-12-10 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'fix_cve-2017-9935' into 'master'
+ Fix CVE-2017-9935
+
+ See merge request libtiff/libtiff!7
+
+2017-12-10 Brian May <brian@linuxpenguins.xyz>
+
+ tiff2pdf: Fix apparent incorrect type for transfer table.
+ The standard says the transfer table contains unsigned 16 bit values,
+ I have no idea why we refer to them as floats.
+
+2017-12-10 Brian May <brian@linuxpenguins.xyz>
+
+ tiff2pdf: Fix CVE-2017-9935.
+ Fix for http://bugzilla.maptools.org/show_bug.cgi?id=2704
+
+ This vulnerability - at least for the supplied test case - is because we
+ assume that a tiff will only have one transfer function that is the same
+ for all pages. This is not required by the TIFF standards.
+
+ We than read the transfer function for every page. Depending on the
+ transfer function, we allocate either 2 or 4 bytes to the XREF buffer.
+ We allocate this memory after we read in the transfer function for the
+ page.
+
+ For the first exploit - POC1, this file has 3 pages. For the first page
+ we allocate 2 extra extra XREF entries. Then for the next page 2 more
+ entries. Then for the last page the transfer function changes and we
+ allocate 4 more entries.
+
+ When we read the file into memory, we assume we have 4 bytes extra for
+ each and every page (as per the last transfer function we read). Which
+ is not correct, we only have 2 bytes extra for the first 2 pages. As a
+ result, we end up writing past the end of the buffer.
+
+ There are also some related issues that this also fixes. For example,
+ TIFFGetField can return uninitalized pointer values, and the logic to
+ detect a N=3 vs N=1 transfer function seemed rather strange.
+
+ It is also strange that we declare the transfer functions to be of type
+ float, when the standard says they are unsigned 16 bit values. This is
+ fixed in another patch.
+
+ This patch will check to ensure that the N value for every transfer
+ function is the same for every page. If this changes, we abort with an
+ error. In theory, we should perhaps check that the transfer function
+ itself is identical for every page, however we don't do that due to the
+ confusion of the type of the data in the transfer function.
+
+2017-12-10 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'undef-warn-fixes' into 'master'
+ Fix a couple of harmless but annoying -Wundef warnings
+
+ See merge request libtiff/libtiff!8
+
+2017-12-07 Vadim Zeitlin <vadim@zeitlins.org>
+
+ Remove tests for undefined SIZEOF_VOIDP.
+ As configure never uses AC_CHECK_SIZEOF(void*), this symbol is never
+ defined and so it doesn't make sense to test it in the code, this just
+ results in -Wundef warnings if they're enabled.
+
+ Avoid harmless -Wundef warnings for __clang_major__
+ Check that we're using Clang before checking its version.
+
+2017-12-02 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'remove_autogenerated_files' into 'master'
+ Remove autogenerated files
+
+ See merge request libtiff/libtiff!5
+
+2017-12-02 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ Merge branch 'tif_config_h_includes' into 'master'
+ 'tif_config.h' or 'tiffiop.h' must be included before any system header.
+
+ See merge request libtiff/libtiff!6
+
+2017-12-02 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ 'tif_config.h' or 'tiffio.h' must be included before any system header.
+
+2017-12-01 Even Rouault <even.rouault@spatialys.com>
+
+ .gitignore: add patterns for build from root.
+
+ Remove remaining .cvsignore files.
+
+ Remove autoconf/automake generated files, and add them to .gitignore.
+
+2017-12-01 Olivier Paquet <olivier.paquet@gmail.com>
+
+ Merge branch 'makedistcheck' into 'master'
+ build/gitlab-ci and build/travis-ci: add a 'make dist' step in autoconf_build()…
+
+ See merge request libtiff/libtiff!4
+
+2017-12-01 Even Rouault <even.rouault@spatialys.com>
+
+ build/gitlab-ci and build/travis-ci: add a 'make dist' step in autoconf_build() target, to check we are release-ready
+
+2017-12-01 Even Rouault <even.rouault@mines-paris.org>
+
+ Merge branch 'git_updates' into 'master'
+ CVS to Git updates
+
+ See merge request libtiff/libtiff!2
+
+2017-12-01 Even Rouault <even.rouault@spatialys.com>
+
+ HOWTO-RELEASE: update to use signed tags.
+
+ README.md: use markdown syntax for hyperlinks.
+
+2017-11-30 Even Rouault <even.rouault@spatialys.com>
+
+ Add .gitignore.
+
+ Regenerate autoconf files.
+
+ Makefile.am: update to reflect removal of README.vms and README -> README.md
+
+ Remove all $Id and $Headers comments with CVS versions.
+
+ HOWTO-RELEASE: update for git.
+
+ Remove outdated .cvsignore.
+
+ Remove outdated commit script.
+
+ Remove README.vms.
+
+ Rename README as README.md, and update content.
+
+ html/index.html: reflect change from CVS to gitlab.
+
+2017-11-30 Olivier Paquet <olivier.paquet@gmail.com>
+
+ Merge branch 'test-ci' into 'master'
+ Update CI configuration
+
+ See merge request libtiff/libtiff!1
+
+2017-11-23 Roger Leigh <rleigh@codelibre.net>
+
+ appveyor: Correct path for git clone and skip artefact archival.
+
+2017-11-22 Roger Leigh <rleigh@codelibre.net>
+
+ travis-ci: Remove unused matrix exclusion.
+
+ Add gitlab-ci build support.
+
+2017-11-18 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * configure.ac: libtiff 4.0.9 released.
+
+ * html/v4.0.9.html: Add HTML file to document changes in libtiff
+ v4.0.9.
+
+2017-11-17 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_aux.c, tif_getimage.c, tif_read.c: typo fixes in
+ comments.
+
+2017-11-02 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * test/Makefile.am: Add some tests for tiff2bw.
+
+2017-11-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiff2bw.c (main): Free memory allocated in the tiff2bw
+ program. This is in response to the report associated with
+ CVE-2017-16232 but does not solve the extremely high memory usage
+ with the associated POC file.
+
+2017-10-29 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiff2pdf.c (t2p_sample_realize_palette): Fix possible
+ arithmetic overflow in bounds checking code and eliminate
+ comparison between signed and unsigned type.
+
+ * tools/fax2tiff.c (_FAX_Client_Data): Pass FAX_Client_Data as the
+ client data. This client data is not used at all at the moment,
+ but it makes the most sense. Issue that the value of
+ client_data.fd was passed where a pointer is expected was reported
+ via email by Gerald Schade on Sun, 29 Oct 2017.
+
+2017-10-23 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_getimage.c: avoid floating point division by zero in
+ initCIELabConversion()
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3733
+ Credit to OSS Fuzz
+
+2017-10-17 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_jpeg.c: add compatibility with libjpeg-turbo 1.5.2 that
+ honours max_memory_to_use > 0.
+ Cf https://github.com/libjpeg-turbo/libjpeg-turbo/issues/162
+
+2017-10-10 Even Rouault <even.rouault at spatialys.com>
+
+ * nmake.opt: support a DEBUG=1 option, so as to adjust OPTFLAGS and use
+ /MDd runtime in debug mode.
+
+2017-10-01 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffset.c: fix setting a single value for the ExtraSamples tag
+ (and other tags with variable number of values).
+ So 'tiffset -s ExtraSamples 1 X'. This only worked
+ when setting 2 or more values, but not just one.
+
+2017-09-29 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/libtiff.def: add TIFFReadRGBAStripExt and TIFFReadRGBATileExt
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2735
+
+2017-09-09 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: add NULL check to avoid likely false positive
+ null-pointer dereference warning by CLang Static Analyzer.
+
+2017-09-07 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tiffiop.h, tif_aux.c: redirect SeekOK() macro to a _TIFFSeekoK()
+ function that checks if the offset is not bigger than INT64_MAX, so as
+ to avoid a -1 error return code of TIFFSeekFile() to match a required
+ seek to UINT64_MAX/-1.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2726
+ Adapted from proposal by Nicolas Ruff.
+
+2017-08-29 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_jpeg.c: accept reading the last strip of a JPEG compressed
+ file if the codestream height is larger than the truncated height of the
+ strip. Emit a warning in this situation since this is non compliant.
+
+2017-08-28 Even Rouault <even.rouault at spatialys.com>
+
+ * test/Makefile.am: add missing reference to images/quad-lzw-compat.tiff
+ to fix "make distcheck". Patch by Roger Leigh
+
+2017-08-23 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirwrite.c: replace assertion to tag value not fitting
+ on uint32 when selecting the value of SubIFD tag by runtime check
+ (in TIFFWriteDirectoryTagSubifd()).
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2728
+ Reported by team OWL337
+
+2017-08-23 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirwrite.c: replace assertion related to not finding the
+ SubIFD tag by runtime check (in TIFFWriteDirectorySec())
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2727
+ Reported by team OWL337
+
+2017-07-24 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_luv.c: further reduce memory requirements for temporary
+ buffer when RowsPerStrip >= image_length in LogLuvInitState() and
+ LogL16InitState().
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2700
+ Credit to OSS Fuzz
+
+2017-07-24 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_getimage.c: fix fromskew computation when to-be-skipped
+ pixel number is not a multiple of the horizontal subsampling, and
+ also in some other cases. Impact putcontig8bitYCbCr44tile,
+ putcontig8bitYCbCr42tile, putcontig8bitYCbCr41tile,
+ putcontig8bitYCbCr21tile and putcontig8bitYCbCr12tile
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2637 (discovered
+ by Agostino Sarubbo)
+ and https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2691 (credit
+ to OSS Fuzz)
+
+2017-07-24 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_getimage.c: gtTileContig() and gtTileSeparate():
+ properly break from loops on error when stoponerr is set, instead
+ of going on iterating on row based loop.
+
+2017-07-18 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_luv.c: LogLuvInitState(): avoid excessive memory
+ allocation when RowsPerStrip tag is missing.
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2683
+ Credit to OSS-Fuzz
+
+2017-07-15 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c: add protection against excessive memory
+ allocation attempts in TIFFReadDirEntryArray() on short files.
+ Effective for mmap'ed case. And non-mmap'ed case, but restricted
+ to 64bit builds.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2675
+
+2017-07-15 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c: in TIFFFetchStripThing(), only grow the
+ arrays that hold StripOffsets/StripByteCounts, when they are smaller
+ than the expected number of striles, up to 1 million striles, and
+ error out beyond. Can be tweaked by setting the environment variable
+ LIBTIFF_STRILE_ARRAY_MAX_RESIZE_COUNT.
+ This partially goes against a change added on 2002-12-17 to accept
+ those arrays of wrong sizes, but is needed to avoid denial of services.
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2350
+ Credit to OSS Fuzz
+
+2017-07-15 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c: TIFFFillStrip() / TIFFFillTile().
+ Complementary fix for http://bugzilla.maptools.org/show_bug.cgi?id=2708
+ in the isMapped() case, so as to avoid excessive memory allocation
+ when we need a temporary buffer but the file is truncated.
+
+2017-07-15 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiff2pdf.c: prevent heap buffer overflow write in "Raw"
+ mode on PlanarConfig=Contig input images.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2715
+ Reported by team OWL337
+
+2017-07-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dir.c: avoid potential null pointer dereference in
+ _TIFFVGetField() on corrupted TIFFTAG_NUMBEROFINKS tag instance.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2713
+
+2017-07-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_lzw.c: fix potential out-of-buffer read on 1-byte LZW
+ strips. Crashing issue only on memory mapped files, where the strip
+ offset is the last byte of the file, and the file size is a multiple
+ of one page size on the CPU architecture (typically 4096). Credit
+ to myself :-)
+
+2017-07-11 Even Rouault <even.rouault at spatialys.com>
+
+ * test/tiffcp-lzw-compat.sh, test/images/quad-lzw-compat.tiff: new files
+ to test old-style LZW decompression
+ * test/common.sh, Makefile.am, CMakeList.txt: updated with above
+
+2017-07-11 Even Rouault <even.rouault at spatialys.com>
+
+ * refresh autoconf/make stuff with what is on Ubuntu 16.04 (minor changes)
+
+2017-07-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_lzw.c: fix 4.0.8 regression in the decoding of old-style LZW
+ compressed files.
+
+2017-07-10 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_pixarlog.c: avoid excessive memory allocation on decoding
+ when RowsPerStrip tag is not defined (and thus td_rowsperstrip == UINT_MAX)
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2554
+ Credit to OSS Fuzz
+
+2017-07-04 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c, tiffiop.h: add a _TIFFReadEncodedTileAndAllocBuffer()
+ and _TIFFReadTileAndAllocBuffer() variants of TIFFReadEncodedTile() and
+ TIFFReadTile() that allocates the decoded buffer only after a first
+ successful TIFFFillTile(). This avoids excessive memory allocation
+ on corrupted files.
+ * libtiff/tif_getimage.c: use _TIFFReadTileAndAllocBuffer().
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2470
+ Credit to OSS Fuzz.
+
+2017-07-04 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_error.c, tif_warning.c: correctly use va_list when both
+ an old-style and new-style warning/error handlers are installed.
+ Patch by Paavo Helde (sent on the mailing list)
+
+2017-07-02 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c: TIFFStartTile(): set tif_rawcc to
+ tif_rawdataloaded when it is set. Similarly to TIFFStartStrip().
+ This issue was revealed by the change of 2017-06-30 in TIFFFileTile(),
+ limiting the number of bytes read. But it could probably have been hit
+ too in CHUNKY_STRIP_READ_SUPPORT mode previously ?
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2454
+ Credit to OSS Fuzz
+
+2017-06-30 Even Rouault <even.rouault at spatialys.com>
+
+ * man: update documentation regarding SubIFD tag and
+ TIFFSetSubDirectory() data type.
+ Patch by Eric Piel
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2671
+
+2017-06-30 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirwrite.c: in TIFFWriteDirectoryTagCheckedXXXX()
+ functions associated with LONG8/SLONG8 data type, replace assertion that
+ the file is BigTIFF, by a non-fatal error.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2712
+ Reported by team OWL337
+
+2017-06-30 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c, tiffiop.h: add a _TIFFReadEncodedStripAndAllocBuffer()
+ function, variant of TIFFReadEncodedStrip() that allocates the
+ decoded buffer only after a first successful TIFFFillStrip(). This avoids
+ excessive memory allocation on corrupted files.
+ * libtiff/tif_getimage.c: use _TIFFReadEncodedStripAndAllocBuffer().
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2708 and
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2433 .
+ Credit to OSS Fuzz
+
+2017-06-30 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c: TIFFFillTile(): add limitation to the number
+ of bytes read in case td_stripbytecount[strip] is bigger than
+ reasonable, so as to avoid excessive memory allocation (similarly to
+ what was done for TIFFFileStrip() on 2017-05-10)
+
+2017-06-29 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tiffiop.h, libtiff/tif_jpeg.c, libtiff/tif_jpeg_12.c,
+ libtiff/tif_read.c: make TIFFReadScanline() works in
+ CHUNKY_STRIP_READ_SUPPORT mode with JPEG stream with multiple scans.
+ Also make configurable through a LIBTIFF_JPEG_MAX_ALLOWED_SCAN_NUMBER
+ environment variable the maximum number of scans allowed. Defaults to
+ 100.
+
+2017-06-27 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: in TIFFReadDirEntryFloat(), check that a
+ double value can fit in a float before casting. Patch by Nicolas RUFF
+
+2017-06-26 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_jbig.c: fix memory leak in error code path of JBIGDecode()
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2706
+ Reported by team OWL337
+
+2017-06-24 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_jpeg.c: error out at decoding time if anticipated libjpeg
+ memory allocation is above 100 MB. libjpeg in case of multiple scans,
+ which is allowed even in baseline JPEG, if components are spread over several
+ scans and not interleavedin a single one, needs to allocate memory (or
+ backing store) for the whole strip/tile.
+ See http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf
+ This limitation may be overriden by setting the
+ LIBTIFF_ALLOW_LARGE_LIBJPEG_MEM_ALLOC environment variable, or recompiling
+ libtiff with a custom value of TIFF_LIBJPEG_LARGEST_MEM_ALLOC macro.
+
+2017-06-24 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_jpeg.c: add anti-denial of service measure to avoid excessive
+ CPU consumption on progressive JPEGs with a huge number of scans.
+ See http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf
+ Note: only affects libtiff since 2014-12-29 where support of non-baseline JPEG
+ was added.
+
+2017-06-18 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tiffiop.h: add TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW macro to
+ disable CLang warnings raised by -fsanitize=undefined,unsigned-integer-overflow
+ * libtiff/tif_predict.c: decorate legitimate functions where unsigned int
+ overflow occur with TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
+ * libtiff/tif_dirread.c: avoid unsigned int overflow in EstimateStripByteCounts()
+ and BYTECOUNTLOOKSBAD when file is too short.
+ * libtiff/tif_jpeg.c: avoid (harmless) unsigned int overflow on tiled images.
+ * libtiff/tif_fax3.c: avoid unsigned int overflow in Fax3Encode2DRow(). Could
+ potentially be a bug with huge rows.
+ * libtiff/tif_getimage.c: avoid many (harmless) unsigned int overflows.
+
+2017-06-12 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: TIFFFetchStripThing(): limit the number of items
+ read in StripOffsets/StripByteCounts tags to the number of strips to avoid
+ excessive memory allocation.
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2215
+ Credit to OSS Fuzz
+
+2017-06-12 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: fix regression of libtiff 4.0.8 in
+ ChopUpSingleUncompressedStrip() regarding update of newly single-strip
+ uncompressed files whose bytecount is 0. Before the change of 2016-12-03,
+ the condition bytecount==0 used to trigger an early exit/disabling of
+ strip chop. Re-introduce that in update mode. Otherwise this cause
+ later incorrect setting for the value of StripByCounts/StripOffsets.
+ ( https://trac.osgeo.org/gdal/ticket/6924 )
+
+2017-06-10 Even Rouault <even.rouault at spatialys.com>
+
+ * .appveyor.yml, .travis.yml, build/travis-ci: apply patches
+ 0001-ci-Travis-script-improvements.patch and
+ 0002-ci-Invoke-helper-script-via-shell.patch by Roger Leigh
+ (sent to mailing list)
+
+2017-06-08 Even Rouault <even.rouault at spatialys.com>
+
+ * .travis.yml, build/travis-ci: new files from
+ 0001-ci-Add-Travis-support-for-Linux-builds-with-Autoconf.patch by
+ Roger Leigh (sent to mailing list on 2017-06-08)
+ This patch adds support for the Travis-CI service.
+
+ * .appveyor.yml: new file from
+ 0002-ci-Add-AppVeyor-support.patch by Roger Leigh (sent to mailing
+ list on 2017-06-08)
+ This patch adds a .appveyor.yml file to the top-level. This allows
+ one to opt in to having a branch built on Windows with Cygwin,
+ MinGW and MSVC automatically when a branch is pushed to GitHub,
+ GitLab, BitBucket or any other supported git hosting service.
+
+ * CMakeLists.txt, test/CMakeLists.txt, test/TiffTestCommon.cmake: apply
+ patch 0001-cmake-Improve-Cygwin-and-MingGW-test-support.patch from Roger
+ Leigh (sent to mailing list on 2017-06-08)
+ This patch makes the CMake build system support running the tests
+ with MinGW or Cygwin.
+
+2017-06-08 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_swab.c: if DISABLE_CHECK_TIFFSWABMACROS is defined, do not do
+ the #ifdef TIFFSwabXXX checks. Make it easier for GDAL to rename the symbols
+ of its internal libtiff copy.
+
+2017-06-01 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirinfo.c, tif_dirread.c: add _TIFFCheckFieldIsValidForCodec(),
+ and use it in TIFFReadDirectory() so as to ignore fields whose tag is a
+ codec-specified tag but this codec is not enabled. This avoids TIFFGetField()
+ to behave differently depending on whether the codec is enabled or not, and
+ thus can avoid stack based buffer overflows in a number of TIFF utilities
+ such as tiffsplit, tiffcmp, thumbnail, etc.
+ Patch derived from 0063-Handle-properly-CODEC-specific-tags.patch
+ (http://bugzilla.maptools.org/show_bug.cgi?id=2580) by Raphaël Hertzog.
+ Fixes:
+ http://bugzilla.maptools.org/show_bug.cgi?id=2580
+ http://bugzilla.maptools.org/show_bug.cgi?id=2693
+ http://bugzilla.maptools.org/show_bug.cgi?id=2625 (CVE-2016-10095)
+ http://bugzilla.maptools.org/show_bug.cgi?id=2564 (CVE-2015-7554)
+ http://bugzilla.maptools.org/show_bug.cgi?id=2561 (CVE-2016-5318)
+ http://bugzilla.maptools.org/show_bug.cgi?id=2499 (CVE-2014-8128)
+ http://bugzilla.maptools.org/show_bug.cgi?id=2441
+ http://bugzilla.maptools.org/show_bug.cgi?id=2433
+
+2017-05-29 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_getimage.c: initYCbCrConversion(): stricter validation for
+ refBlackWhite coefficients values. To avoid invalid float->int32 conversion
+ (when refBlackWhite[0] == 2147483648.f)
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1907
+ Credit to OSS Fuzz
+
+2017-05-29 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_color.c: TIFFYCbCrToRGBInit(): stricter clamping to avoid
+ int32 overflow in TIFFYCbCrtoRGB().
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1844
+ Credit to OSS Fuzz
+
+2017-05-21 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * configure.ac: libtiff 4.0.8 released.
+
+ * html/v4.0.8.html: Add description of changes targeting the 4.0.8
+ release.
+
+2017-05-20 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_getimage.c: initYCbCrConversion(): stricter validation for
+ refBlackWhite coefficients values. To avoid invalid float->int32 conversion.
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1718
+ Credit to OSS Fuzz
+
+2017-05-18 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_getimage.c: initYCbCrConversion(): check luma[1] is not zero
+ to avoid division by zero.
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1665
+ Credit to OSS Fuzz
+
+2017-05-17 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c: _TIFFVSetField(): fix outside range cast of double to
+ float.
+ Credit to Google Autofuzz project
+
+2017-05-17 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_getimage.c: initYCbCrConversion(): add basic validation of
+ luma and refBlackWhite coefficients (just check they are not NaN for now),
+ to avoid potential float to int overflows.
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1663
+ Credit to OSS Fuzz
+
+2017-05-17 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_pixarlog.c: PixarLogDecode(): resync tif_rawcp with
+ next_in and tif_rawcc with avail_in at beginning and end of function,
+ similarly to what is done in LZWDecode(). Likely needed so that it
+ works properly with latest chnges in tif_read.c in CHUNKY_STRIP_READ_SUPPORT
+ mode. But untested...
+
+2017-05-17 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_lzw.c: update dec_bitsleft at beginning of LZWDecode(),
+ and update tif_rawcc at end of LZWDecode(). This is needed to properly
+ work with the latest chnges in tif_read.c in CHUNKY_STRIP_READ_SUPPORT
+ mode.
+
+2017-05-14 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_luv.c: LogL16InitState(): avoid excessive memory
+ allocation when RowsPerStrip tag is missing.
+ Credit to OSS-Fuzz (locally run, on GDAL)
+
+2017-05-14 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_packbits.c: fix out-of-buffer read in PackBitsDecode()
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1563
+ Credit to OSS-Fuzz
+
+2017-05-13 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_pixarlog.c, tif_luv.c: avoid potential int32
+ overflows in multiply_ms() and add_ms().
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1558
+ Credit to OSS-Fuzz
+
+2017-05-13 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_color.c: avoid potential int32 overflow in
+ TIFFYCbCrToRGBInit()
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1533
+ Credit to OSS-Fuzz
+
+2017-05-13 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c: update tif_rawcc in CHUNKY_STRIP_READ_SUPPORT
+ mode with tif_rawdataloaded when calling TIFFStartStrip() or
+ TIFFFillStripPartial(). This avoids reading beyond tif_rawdata
+ when bytecount > tif_rawdatasize.
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1545.
+ Credit to OSS-Fuzz
+
+2017-05-12 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c: TIFFFillStripPartial():
+ avoid excessive memory allocation in case of shorten files.
+ Only effective on 64 bit builds.
+ Credit to OSS-Fuzz (locally run, on GDAL)
+
+2017-05-12 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c: TIFFFillStripPartial() / TIFFSeek(),
+ avoid potential integer overflows with read_ahead in
+ CHUNKY_STRIP_READ_SUPPORT mode. Should
+ especially occur on 32 bit platforms.
+
+2017-05-10 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c: TIFFFillStrip() and TIFFFillTile():
+ avoid excessive memory allocation in case of shorten files.
+ Only effective on 64 bit builds and non-mapped cases.
+ Credit to OSS-Fuzz (locally run, on GDAL)
+
+2017-05-10 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_zip.c, tif_pixarlog.c, tif_predict.c: fix memory
+ leak when the underlying codec (ZIP, PixarLog) succeeds its
+ setupdecode() method, but PredictorSetup fails.
+ Credit to OSS-Fuzz (locally run, on GDAL)
+
+2017-05-10 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c: TIFFFillStrip(): add limitation to the number
+ of bytes read in case td_stripbytecount[strip] is bigger than
+ reasonable, so as to avoid excessive memory allocation.
+
+2017-04-28 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiff2bw.c: close TIFF handle in error code path.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2677
+
+2017-04-27 Even Rouault <even.rouault at spatialys.com>
+
+ * litiff/tif_fax3.c: avoid crash in Fax3Close() on empty file.
+ Patch by Alan Coopersmith + complement by myself.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2673
+ * tools/fax2tiff.c: emit appropriate message if the input file is
+ empty. Patch by Alan Coopersmith.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2672
+
+2017-04-27 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_ojpeg.c: fix potential memory leak in
+ OJPEGReadHeaderInfoSecTablesQTable, OJPEGReadHeaderInfoSecTablesDcTable
+ and OJPEGReadHeaderInfoSecTablesAcTable
+ Patch by Nicolás Peña.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2670
+
+2017-04-27 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: fix memory leak in non DEFER_STRILE_LOAD
+ mode (ie default) when there is both a StripOffsets and
+ TileOffsets tag, or a StripByteCounts and TileByteCounts
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2689
+ * tools/tiff2ps.c: call TIFFClose() in error code paths.
+
+2017-02-25 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_fax3.c, tif_predict.c, tif_getimage.c: fix GCC 7
+ -Wimplicit-fallthrough warnings.
+
+2017-02-18 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_pixarlog.c: fix memory leak in error code path of
+ PixarLogSetupDecode(). Patch by Nicolás Peña.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2665
+
+2017-02-18 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_lzw.c: in LZWPostEncode(), increase, if necessary, the
+ code bit-width after flushing the remaining code and before emitting
+ the EOI code.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=1982
+
+2017-01-31 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_jpeg.c: only run JPEGFixupTagsSubsampling() if the
+ YCbCrSubsampling tag is not explicitly present. This helps a bit to reduce
+ the I/O amount when te tag is present (especially on cloud hosted files).
+
+2017-01-14 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/raw2tiff.c: avoid integer division by zero.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2631
+
+2017-01-12 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_ojpeg.c: fix leak in OJPEGReadHeaderInfoSecTablesQTable,
+ OJPEGReadHeaderInfoSecTablesDcTable and OJPEGReadHeaderInfoSecTablesAcTable
+ when read fails.
+ Patch by Nicolás Peña.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2659
+
+2017-01-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_luv.c, tif_lzw.c, tif_packbits.c: return 0 in Encode
+ functions instead of -1 when TIFFFlushData1() fails.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2130
+
+2017-01-11 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcp.c: error out cleanly in cpContig2SeparateByRow and
+ cpSeparate2ContigByRow if BitsPerSample != 8 to avoid heap based overflow.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2656 and
+ http://bugzilla.maptools.org/show_bug.cgi?id=2657
+
+2017-01-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tiffio.h, tif_unix.c, tif_win32.c, tif_vms.c: add _TIFFcalloc()
+
+ * libtiff/tif_read.c: TIFFReadBufferSetup(): use _TIFFcalloc() to zero
+ initialize tif_rawdata.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2651
+
+2017-01-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_getimage.c: add explicit uint32 cast in putagreytile to
+ avoid UndefinedBehaviorSanitizer warning.
+ Patch by Nicolás Peña.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2658
+
+2017-01-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c: avoid potential undefined behaviour on signed integer
+ addition in TIFFReadRawStrip1() in isMapped() case.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2650
+
+2017-01-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_jpeg.c: validate BitsPerSample in JPEGSetupEncode() to avoid
+ undefined behaviour caused by invalid shift exponent.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2648
+
+2017-01-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dir.c, tif_dirread.c, tif_dirwrite.c: implement various clampings
+ of double to other data types to avoid undefined behaviour if the output range
+ isn't big enough to hold the input value.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2643
+ http://bugzilla.maptools.org/show_bug.cgi?id=2642
+ http://bugzilla.maptools.org/show_bug.cgi?id=2646
+ http://bugzilla.maptools.org/show_bug.cgi?id=2647
+
+2017-01-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: avoid division by floating point 0 in
+ TIFFReadDirEntryCheckedRational() and TIFFReadDirEntryCheckedSrational(),
+ and return 0 in that case (instead of infinity as before presumably)
+ Apparently some sanitizers do not like those divisions by zero.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2644
+
+2017-01-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirwrite.c: in TIFFWriteDirectoryTagCheckedRational, replace
+ assertion by runtime check to error out if passed value is strictly
+ negative.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2535
+
+ * tools/tiffcrop.c: remove extraneous TIFFClose() in error code path, that
+ caused double free.
+ Related to http://bugzilla.maptools.org/show_bug.cgi?id=2535
+
+2017-01-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_jpeg.c: avoid integer division by zero in
+ JPEGSetupEncode() when horizontal or vertical sampling is set to 0.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2653
+
+2017-01-03 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_jpeg.c: increase libjpeg max memory usable to
+ 10 MB instead of libjpeg 1MB default. This helps when creating files
+ with "big" tile, without using libjpeg temporary files.
+ Related to https://trac.osgeo.org/gdal/ticket/6757
+
+2016-12-20 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiff2pdf.c: avoid potential heap-based overflow in
+ t2p_readwrite_pdf_image_tile().
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2640
+
+2016-12-20 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiff2pdf.c: avoid potential invalid memory read in
+ t2p_writeproc.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2639
+
+2016-12-20 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiff2pdf.c: fix wrong usage of memcpy() that can trigger
+ unspecified behaviour.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2638
+
+2016-12-18 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_getimage.c: fix potential memory leaks in error code
+ path of TIFFRGBAImageBegin().
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2627
+
+2016-12-18 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiff2pdf.c: prevent heap-based buffer overflow in -j mode
+ on a paletted image. Note: this fix errors out before the overflow
+ happens. There could probably be a better fix.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2635
+
+2016-12-17 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tiffio.h, libtiff/tif_getimage.c: add TIFFReadRGBAStripExt()
+ and TIFFReadRGBATileExt() variants of the functions without ext, with
+ an extra argument to control the stop_on_error behaviour.
+
+2016-12-17 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiff2ps.c: fix 2 heap-based buffer overflows (in PSDataBW
+ and PSDataColorContig). Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2633 and
+ http://bugzilla.maptools.org/show_bug.cgi?id=2634.
+
+2016-12-13 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_fax3.h: revert change done on 2016-01-09 that made
+ Param member of TIFFFaxTabEnt structure a uint16 to reduce size of
+ the binary. It happens that the Hylafax software uses the tables that
+ follow this typedef (TIFFFaxMainTable, TIFFFaxWhiteTable,
+ TIFFFaxBlackTable), although they are not in a public libtiff header.
+ Raised by Lee Howard.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2636
+
+2016-12-04 Even Rouault <even.rouault at spatialys.com>
+
+ * html/man/Makefile.am: remove thumbnail.1.html and rgb2ycbcr.1.html
+ from installed pages since the corresponding utilities are no longer
+ installed. Reported by Havard Eidnes
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2606
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_write.c: fix misleading indentation as warned by GCC.
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcp.c: replace assert( (bps % 8) == 0 ) by a non assert check.
+ Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2605
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcp.c: fix uint32 underflow/overflow that can cause heap-based
+ buffer overflow.
+ Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2610
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcp.c: avoid potential division by zero is BitsPerSamples tag is
+ missing.
+ Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2607
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+ * man/Makefile.am: remove thumbnail.1 and rgb2ycbcr.1 from installed man
+ pages since the corresponding utilities are no longer installed.
+ Reported by Havard Eidnes
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2606
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tif_dir.c: when TIFFGetField(, TIFFTAG_NUMBEROFINKS, ) is called,
+ limit the return number of inks to SamplesPerPixel, so that code that parses
+ ink names doesn't go past the end of the buffer.
+ Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2599
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcp.c: avoid potential division by zero is BitsPerSamples tag is
+ missing.
+ Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2597
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffinfo.c: fix null pointer dereference in -r mode when the image has
+ no StripByteCount tag.
+ Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2594
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcrop.c: fix integer division by zero when BitsPerSample is missing.
+ Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2619
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcrop.c: add 3 extra bytes at end of strip buffer in
+ readSeparateStripsIntoBuffer() to avoid read outside of heap allocated buffer.
+ Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2621
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcrop.c: fix readContigStripsIntoBuffer() in -i (ignore) mode so
+ that the output buffer is correctly incremented to avoid write outside bounds.
+ Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2620
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_ojpeg.c: make OJPEGDecode() early exit in case of failure in
+ OJPEGPreDecode(). This will avoid a divide by zero, and potential other issues.
+ Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2611
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: modify ChopUpSingleUncompressedStrip() to
+ instanciate compute ntrips as TIFFhowmany_32(td->td_imagelength, rowsperstrip),
+ instead of a logic based on the total size of data. Which is faulty is
+ the total size of data is not sufficient to fill the whole image, and thus
+ results in reading outside of the StripByCounts/StripOffsets arrays when
+ using TIFFReadScanline().
+ Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2608.
+
+ * libtiff/tif_strip.c: revert the change in TIFFNumberOfStrips() done
+ for http://bugzilla.maptools.org/show_bug.cgi?id=2587 / CVE-2016-9273 since
+ the above change is a better fix that makes it unnecessary.
+
+2016-12-03 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_pixarlog.c, libtiff/tif_luv.c: fix heap-based buffer
+ overflow on generation of PixarLog / LUV compressed files, with
+ ColorMap, TransferFunction attached and nasty plays with bitspersample.
+ The fix for LUV has not been tested, but suffers from the same kind
+ of issue of PixarLog.
+ Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2604
+
+2016-12-02 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcp.c: avoid uint32 underflow in cpDecodedStrips that
+ can cause various issues, such as buffer overflows in the library.
+ Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2598
+
+2016-12-02 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c, libtiff/tiffiop.h: fix uint32 overflow in
+ TIFFReadEncodedStrip() that caused an integer division by zero.
+ Reported by Agostino Sarubbo.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2596
+
+2016-11-20 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_getimage.c, libtiff/tif_open.c: add parenthesis to
+ fix cppcheck clarifyCalculation warnings
+ * libtiff/tif_predict.c, libtiff/tif_print.c: fix printf unsigned
+ vs signed formatting (cppcheck invalidPrintfArgType_uint warnings)
+
+2016-11-20 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/fax2tiff.c (main): Applied patch by Jörg Ahrens to fix
+ passing client data for Win32 builds using tif_win32.c
+ (USE_WIN32_FILEIO defined) for file I/O. Patch was provided via
+ email on November 20, 2016.
+
+2016-11-19 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff 4.0.7 released.
+
+ * configure.ac: Update for 4.0.7 release.
+
+ * tools/tiffdump.c (ReadDirectory): Remove uint32 cast to
+ _TIFFmalloc() argument which resulted in Coverity report. Added
+ more mutiplication overflow checks.
+
+2016-11-18 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcrop.c: Fix memory leak in (recent) error code path.
+ Fixes Coverity 1394415.
+
+2016-11-17 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_getimage.c: Fix some benign warnings which appear in
+ 64-bit compilation under Microsoft Visual Studio of the form
+ "Arithmetic overflow: 32-bit value is shifted, then cast to 64-bit
+ value. Results might not be an expected value.". Problem was
+ reported on November 16, 2016 on the tiff mailing list.
+
+2016-11-16 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: in TIFFFetchNormalTag(), do not dereference
+ NULL pointer when values of tags with TIFF_SETGET_C16_ASCII / TIFF_SETGET_C32_ASCII
+ access are 0-byte arrays.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2593 (regression introduced
+ by previous fix done on 2016-11-11 for CVE-2016-9297).
+ Reported by Henri Salo. Assigned as CVE-2016-9448
+
+2016-11-12 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiffinfo.c (TIFFReadContigTileData): Fix signed/unsigned
+ comparison warning.
+ (TIFFReadSeparateTileData): Fix signed/unsigned comparison
+ warning.
+
+ * tools/tiffcrop.c (readContigTilesIntoBuffer): Fix
+ signed/unsigned comparison warning.
+
+ * html/v4.0.7.html: Add a file to document the pending 4.0.7
+ release.
+
+2016-11-11 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiff2pdf.c: avoid undefined behaviour related to overlapping
+ of source and destination buffer in memcpy() call in
+ t2p_sample_rgbaa_to_rgb()
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2577
+
+2016-11-11 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiff2pdf.c: fix potential integer overflows on 32 bit builds
+ in t2p_read_tiff_size()
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2576
+
+2016-11-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_aux.c: fix crash in TIFFVGetFieldDefaulted()
+ when requesting Predictor tag and that the zip/lzw codec is not
+ configured.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2591
+
+2016-11-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: in TIFFFetchNormalTag(), make sure that
+ values of tags with TIFF_SETGET_C16_ASCII / TIFF_SETGET_C32_ASCII
+ access are null terminated, to avoid potential read outside buffer
+ in _TIFFPrintField().
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2590 (CVE-2016-9297)
+
+2016-11-11 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: reject images with OJPEG compression that
+ have no TileOffsets/StripOffsets tag, when OJPEG compression is
+ disabled. Prevent null pointer dereference in TIFFReadRawStrip1()
+ and other functions that expect td_stripbytecount to be non NULL.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2585
+
+2016-11-11 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcrop.c: fix multiple uint32 overflows in
+ writeBufferToSeparateStrips(), writeBufferToContigTiles() and
+ writeBufferToSeparateTiles() that could cause heap buffer overflows.
+ Reported by Henri Salo from Nixu Corporation.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2592 (CVE-2016-9532)
+
+2016-11-10 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_strip.c: make TIFFNumberOfStrips() return the td->td_nstrips
+ value when it is non-zero, instead of recomputing it. This is needed in
+ TIFF_STRIPCHOP mode where td_nstrips is modified. Fixes a read outsize of
+ array in tiffsplit (or other utilities using TIFFNumberOfStrips()).
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2587 (CVE-2016-9273)
+
+2016-11-04 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_predic.c: fix memory leaks in error code paths added in
+ previous commit (fix for MSVR 35105)
+
+2016-10-31 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_predict.h, libtiff/tif_predict.c:
+ Replace assertions by runtime checks to avoid assertions in debug mode,
+ or buffer overflows in release mode. Can happen when dealing with
+ unusual tile size like YCbCr with subsampling. Reported as MSVR 35105
+ by Axel Souchet & Vishal Chauhan from the MSRC Vulnerabilities & Mitigations
+ team.
+
+2016-10-26 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/fax2tiff.c: fix segfault when specifying -r without
+ argument. Patch by Yuriy M. Kaminskiy.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2572
+
+2016-10-25 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dir.c: discard values of SMinSampleValue and
+ SMaxSampleValue when they have been read and the value of
+ SamplesPerPixel is changed afterwards (like when reading a
+ OJPEG compressed image with a missing SamplesPerPixel tag,
+ and whose photometric is RGB or YCbCr, forcing SamplesPerPixel
+ being 3). Otherwise when rewriting the directory (for example
+ with tiffset, we will expect 3 values whereas the array had been
+ allocated with just one), thus causing a out of bound read access.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2500
+ (CVE-2014-8127, duplicate: CVE-2016-3658)
+
+ * libtiff/tif_dirwrite.c: avoid null pointer dereference on td_stripoffset
+ when writing directory, if FIELD_STRIPOFFSETS was artificially set
+ for a hack case in OJPEG case.
+ Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2500
+ (CVE-2014-8127, duplicate: CVE-2016-3658)
+
+2016-10-25 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffinfo.c: fix out-of-bound read on some tiled images.
+ (http://bugzilla.maptools.org/show_bug.cgi?id=2517)
+
+ * libtiff/tif_compress.c: make TIFFNoDecode() return 0 to indicate an
+ error and make upper level read routines treat it accordingly.
+ (linked to the test case of http://bugzilla.maptools.org/show_bug.cgi?id=2517)
+
+2016-10-14 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcrop.c: fix out-of-bound read of up to 3 bytes in
+ readContigTilesIntoBuffer(). Reported as MSVR 35092 by Axel Souchet
+ & Vishal Chauhan from the MSRC Vulnerabilities & Mitigations team.
+
+2016-10-09 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiff2pdf.c: fix write buffer overflow of 2 bytes on JPEG
+ compressed images. Reported by Tyler Bohan of Cisco Talos as
+ TALOS-CAN-0187 / CVE-2016-5652.
+ Also prevents writing 2 extra uninitialized bytes to the file stream.
+
+2016-10-08 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcp.c: fix out-of-bounds write on tiled images with odd
+ tile width vs image width. Reported as MSVR 35103
+ by Axel Souchet and Vishal Chauhan from the MSRC Vulnerabilities &
+ Mitigations team.
+
+2016-10-08 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiff2pdf.c: fix read -largely- outsize of buffer in
+ t2p_readwrite_pdf_image_tile(), causing crash, when reading a
+ JPEG compressed image with TIFFTAG_JPEGTABLES length being one.
+ Reported as MSVR 35101 by Axel Souchet and Vishal Chauhan from
+ the MSRC Vulnerabilities & Mitigations team. CVE-2016-9453
+
+2016-10-08 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcp.c: fix read of undefined variable in case of missing
+ required tags. Found on test case of MSVR 35100.
+ * tools/tiffcrop.c: fix read of undefined buffer in
+ readContigStripsIntoBuffer() due to uint16 overflow. Probably not a
+ security issue but I can be wrong. Reported as MSVR 35100 by Axel
+ Souchet from the MSRC Vulnerabilities & Mitigations team.
+
+2016-09-25 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * html: Change as many remotesensing.org broken links to a working
+ URL as possible.
+
+2016-09-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_getimage.c (TIFFRGBAImageOK): Reject attempts to
+ read floating point images.
+
+ * libtiff/tif_predict.c (PredictorSetup): Enforce bits-per-sample
+ requirements of floating point predictor (3). Fixes CVE-2016-3622
+ "Divide By Zero in the tiff2rgba tool."
+
+2016-09-23 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcrop.c: fix various out-of-bounds write vulnerabilities
+ in heap or stack allocated buffers. Reported as MSVR 35093,
+ MSVR 35096 and MSVR 35097. Discovered by Axel Souchet and Vishal
+ Chauhan from the MSRC Vulnerabilities & Mitigations team.
+ * tools/tiff2pdf.c: fix out-of-bounds write vulnerabilities in
+ heap allocate buffer in t2p_process_jpeg_strip(). Reported as MSVR
+ 35098. Discovered by Axel Souchet and Vishal Chauhan from the MSRC
+ Vulnerabilities & Mitigations team.
+ * libtiff/tif_pixarlog.c: fix out-of-bounds write vulnerabilities
+ in heap allocated buffers. Reported as MSVR 35094. Discovered by
+ Axel Souchet and Vishal Chauhan from the MSRC Vulnerabilities &
+ Mitigations team.
+ * libtiff/tif_write.c: fix issue in error code path of TIFFFlushData1()
+ that didn't reset the tif_rawcc and tif_rawcp members. I'm not
+ completely sure if that could happen in practice outside of the odd
+ behaviour of t2p_seekproc() of tiff2pdf). The report points that a
+ better fix could be to check the return value of TIFFFlushData1() in
+ places where it isn't done currently, but it seems this patch is enough.
+ Reported as MSVR 35095. Discovered by Axel Souchet & Vishal Chauhan &
+ Suha Can from the MSRC Vulnerabilities & Mitigations team.
+
+2016-09-20 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * html/man/index.html: Comment out links to documentation for
+ abandoned utilities.
+
+2016-09-17 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_lzma.c: typo fix in comment
+
+2016-09-04 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/*.c: fix warnings raised by clang 3.9 -Wcomma
+
+2016-09-03 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirwrite.c, libtiff/tif_color.c: fix warnings raised
+ by GCC 5 / clang -Wfloat-conversion
+
+2016-08-16 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcrop.c: fix C99'ism.
+
+2016-08-15 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiff2bw.c: fix weight computation that could result of color
+ value overflow (no security implication). Fix bugzilla #2550.
+ Patch by Frank Freudenberg.
+
+2016-08-15 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/rgb2ycbcr.c: validate values of -v and -h parameters to
+ avoid potential divide by zero. Fixes CVE-2016-3623 (bugzilla #2569)
+
+2016-08-15 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcrop.c: Fix out-of-bounds write in loadImage().
+ From patch libtiff-CVE-2016-3991.patch from
+ libtiff-4.0.3-25.el7_2.src.rpm by Nikola Forro (bugzilla #2543)
+
+2016-08-15 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_pixarlog.c: Fix write buffer overflow in PixarLogEncode
+ if more input samples are provided than expected by PixarLogSetupEncode.
+ Idea based on libtiff-CVE-2016-3990.patch from
+ libtiff-4.0.3-25.el7_2.src.rpm by Nikola Forro, but with different and
+ simpler check. (bugzilla #2544)
+
+2016-08-15 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiff2rgba.c: Fix integer overflow in size of allocated
+ buffer, when -b mode is enabled, that could result in out-of-bounds
+ write. Based initially on patch tiff-CVE-2016-3945.patch from
+ libtiff-4.0.3-25.el7_2.src.rpm by Nikola Forro, with correction for
+ invalid tests that rejected valid files. (bugzilla #2545)
+
+2016-07-11 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffcrop.c: Avoid access outside of stack allocated array
+ on a tiled separate TIFF with more than 8 samples per pixel.
+ Reported by Kaixiang Zhang of the Cloud Security Team, Qihoo 360
+ (CVE-2016-5321 / CVE-2016-5323 , bugzilla #2558 / #2559)
+
+2016-07-10 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c: Fix out-of-bounds read on
+ memory-mapped files in TIFFReadRawStrip1() and TIFFReadRawTile1()
+ when stripoffset is beyond tmsize_t max value (reported by
+ Mathias Svensson)
+
+2016-07-10 Even Rouault <even.rouault at spatialys.com>
+
+ * tools/tiffdump.c: fix a few misaligned 64-bit reads warned
+ by -fsanitize
+
+2016-07-03 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c: make TIFFReadEncodedStrip() and
+ TIFFReadEncodedTile() directly use user provided buffer when
+ no compression (and other conditions) to save a memcpy().
+
+ * libtiff/tif_write.c: make TIFFWriteEncodedStrip() and
+ TIFFWriteEncodedTile() directly use user provided buffer when
+ no compression to save a memcpy().
+
+2016-07-01 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_luv.c: validate that for COMPRESSION_SGILOG and
+ PHOTOMETRIC_LOGL, there is only one sample per pixel. Avoid
+ potential invalid memory write on corrupted/unexpected images when
+ using the TIFFRGBAImageBegin() interface (reported by
+ Clay Wood)
+
+2016-06-28 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_pixarlog.c: fix potential buffer write overrun in
+ PixarLogDecode() on corrupted/unexpected images (reported by Mathias Svensson)
+ (CVE-2016-5875)
+
+2016-06-15 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/libtiff.def: Added _TIFFMultiply32 and _TIFFMultiply64
+ to libtiff.def
+
+2016-06-05 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/Makefile.am: The libtiff tools bmp2tiff, gif2tiff,
+ ras2tiff, sgi2tiff, sgisv, and ycbcr are completely removed from
+ the distribution. The libtiff tools rgb2ycbcr and thumbnail are
+ only built in the build tree for testing. Old files are put in
+ new 'archive' subdirectory of the source repository, but not in
+ distribution archives. These changes are made in order to lessen
+ the maintenance burden.
+
+2016-05-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_config.vc.h (HAVE_SNPRINTF): Add a '1' to the
+ HAVE_SNPRINTF definition.'
+
+2016-05-09 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_config.vc.h (HAVE_SNPRINTF): Applied patch by Edward
+ Lam to define HAVE_SNPRINTF for Visual Studio 2015.
+
+2016-04-27 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: when compiled with DEFER_STRILE_LOAD,
+ fix regression, introduced on 2014-12-23, when reading a one-strip
+ file without a StripByteCounts tag. GDAL #6490
+
+2016-04-07 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * html/bugs.html: Replace Andrey Kiselev with Bob Friesenhahn for
+ purposes of security issue reporting.
+
+2016-01-23 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/*: upstream typo fixes (mostly contributed by Kurt Schwehr)
+ coming from GDAL internal libtiff
+
+2016-01-09 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_fax3.h: make Param member of TIFFFaxTabEnt structure
+ a uint16 to reduce size of the binary.
+
+2016-01-03 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_read.c, tif_dirread.c: fix indentation issues raised
+ by GCC 6 -Wmisleading-indentation
+
+2015-12-27 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_pixarlog.c: avoid zlib error messages to pass a NULL
+ string to %s formatter, which is undefined behaviour in sprintf().
+
+2015-12-27 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_next.c: fix potential out-of-bound write in NeXTDecode()
+ triggered by http://lcamtuf.coredump.cx/afl/vulns/libtiff5.tif
+ (bugzilla #2508)
+
+2015-12-27 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_luv.c: fix potential out-of-bound writes in decode
+ functions in non debug builds by replacing assert()s by regular if
+ checks (bugzilla #2522).
+ Fix potential out-of-bound reads in case of short input data.
+
+2015-12-26 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_getimage.c: fix out-of-bound reads in TIFFRGBAImage
+ interface in case of unsupported values of SamplesPerPixel/ExtraSamples
+ for LogLUV / CIELab. Add explicit call to TIFFRGBAImageOK() in
+ TIFFRGBAImageBegin(). Fix CVE-2015-8665 reported by limingxing and
+ CVE-2015-8683 reported by zzf of Alibaba.
+
+2015-12-21 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: workaround false positive warning of Clang Static
+ Analyzer about null pointer dereference in TIFFCheckDirOffset().
+
+2015-12-19 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_fax3.c: remove dead assignment in Fax3PutEOLgdal(). Found
+ by Clang Static Analyzer
+
+2015-12-18 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirwrite.c: fix truncation to 32 bit of file offsets in
+ TIFFLinkDirectory() and TIFFWriteDirectorySec() when aligning directory
+ offsets on a even offset (affects BigTIFF). This was a regression of the
+ changeset of 2015-10-19.
+
+2015-12-12 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_write.c: TIFFWriteEncodedStrip() and TIFFWriteEncodedTile()
+ should return -1 in case of failure of tif_encodestrip() as documented
+ * libtiff/tif_dumpmode.c: DumpModeEncode() should return 0 in case of
+ failure so that the above mentionned functions detect the error.
+
+2015-12-06 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/uvcode.h: const'ify uv_code array
+
+2015-12-06 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirinfo.c: const'ify tiffFields, exifFields,
+ tiffFieldArray and exifFieldArray arrays
+
+2015-12-06 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_print.c: constify photoNames and orientNames arrays
+
+2015-12-06 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_close.c, libtiff/tif_extension.c : rename link
+ variable to avoid -Wshadow warnings
+
+2015-11-22 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/*.c: fix typos in comments (patch by Kurt Schwehr)
+
+2015-11-22 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/*.c: fix MSVC warnings related to cast shortening and
+ assignment within conditional expression
+
+2015-11-18 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/*.c: fix clang -Wshorten-64-to-32 warnings
+
+2015-11-18 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: initialize double* data at line 3693 to NULL
+ to please MSVC 2013
+
+2015-11-17 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: prevent reading ColorMap or TransferFunction
+ if BitsPerPixel > 24, so as to avoid huge memory allocation and file
+ read attempts
+
+2015-11-02 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dirread.c: remove duplicated assignment (reported by
+ Clang static analyzer)
+
+2015-10-28 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dir.c, libtiff/tif_dirinfo.c, libtiff/tif_compress.c,
+ libtiff/tif_jpeg_12.c: suppress warnings about 'no previous
+ declaration/prototype'
+
+2015-10-19 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tiffiop.h, libtiff/tif_dirwrite.c: suffix constants by U to fix
+ 'warning: negative integer implicitly converted to unsigned type' warning
+ (part of -Wconversion)
+
+2015-10-17 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_dir.c, libtiff/tif_dirread.c, libtiff/tif_getimage.c,
+ libtiff/tif_print.c: fix -Wshadow warnings (only in libtiff/)
+
+2015-09-12 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff 4.0.6 released.
+
+ * html/v4.0.6.html: Added release notes for 4.0.6.
+
+2015-09-06 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiffgt.c: Silence glut API deprecation warnings on MacOS
+ X. Patch by Roger Leigh.
+
+ * Makefile.am: Added a 'coverity' rule to assist with Coverity
+ submissions.
+
+ * tools/tiff2pdf.c: Fix compiler warning about unused function
+ when JPEG is not available.
+
+ * tools/fax2ps.c (main): Detect failure to write to temporary
+ file.
+
+2015-09-05 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_dirread.c (TIFFReadDirEntryCheckRangeSlongSlong8):
+ Change implementation so that it does not sometimes overflow the
+ range of a 32-bit int and to avoid a signed vs unsigned compare
+ compiler warning.
+ (TIFF_INT64_MAX): Avoid use of platform-specific large constants.
+ (TIFF_UINT32_MAX): Avoid use of platform-specific large constants.
+
+2015-09-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * Makefile.am (distcheck-hook), configure.ac: Applied patches by
+ Roger Leigh (via tiff mailing list on 2015-09-01) to fix issue
+ with BSD make and to make use of cmake in 'distcheck' target
+ conditional on if cmake is available.
+
+ * CMakeLists.txt, Makefile.am, configure.ac: Applied patches by
+ Roger Leigh (via tiff mailing list on 2015-09-01).
+
+ CMake build is now included in 'distcheck' target.
+
+ Builds with CMake 2.8.9 and newer.
+
+ Tar is now resquested to use POSIX PAX format.
+
+2015-08-31 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * CMakeLists.txt, libtiff/test/Makefile.am: Applied patches by
+ Roger Leigh (via tiff mailing list on 2015-08-31.
+
+ CMake reads all version information directly from configure.ac to
+ avoid duplication of values. This basically greps over the file
+ for the LIBTIFF_* variables, then translates them to the form
+ needed for cmake. This includes the release version and libtool
+ shared library version information.
+
+ Make shared/static library building configurable. Currently it
+ always builds shared libraries, with static libs having a _static
+ suffix (copying zlib, but it means it's got a non-standard name).
+ CMake has a -DBUILD_SHARED_LIBS=ON|OFF option to select one or the
+ other, which is now used instead. There's now a single "tiff"
+ target to build either shared or static as required, and all the
+ tests and tools are linked with this. Note: the Windows tests fail
+ when linked with a static libtiff (says: libtiff.dll not found).
+ Not really a regression since this was not tested up to this
+ point, and it's likely the unit tests haven't (ever?) been run on
+ Windows with a static libtiff, so there's some additional
+ portability issue here to address. Works fine on UNIX systems,
+ and fine on Windows with the default to build a DLL.
+
+ Add a missing file which wasn't being distributed, causing unit
+ tests to fail. Note that "find . -name '*.cmake'" lists all the
+ CMake files which need distributing in addition to all the
+ CMakeLists.txt files (which now are distributed).
+
+2015-08-31 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_predict.c: pedantic change to add explicit masking
+ with 0xff before casting to uchar in floating-point horizontal
+ differencing and accumulation routines.
+
+2015-08-31 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_predict.c: fix generation of output with 16 bit
+ or 32 bit integer, when byte swapping is needed, in
+ horizontal predictor (#2521). Also fixes decoding when there is
+ a single pixel to code (unlikely case...) and byte swapping is
+ involved.
+
+2015-08-30 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_lzw.c: make nextdata a unsigned type to avoid
+ undefined behaviour with shifts (gcc -fsanitize=shift)
+
+2015-08-30 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_fax3.c, libtiff/tif_lzw.c, libtiff/tif_predict.c:
+ add explicit masking with 0xff before casting
+ to unsigned char (make icc -check=conversions happy)
+
+ * libtiff/tif_predict.c: operate on unsigned datatypes when
+ computing/applying differences to avoid undefined behaviour of
+ signed types (C standard compliance)
+
+2015-08-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * configure.ac: libtiff 4.0.5 released.
+
+2015-08-29 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * CMakeLists.txt: Applied patch by Roger Leigh (via tiff mailing
+ list on 2015-08-29) to add ld-version-script option to cmake build
+ to match autoconf. Note: defaults to 'on' to be ABI-compatible by
+ default with common Linux distribution builds. Note that the
+ autoconf configure script defaults to 'off'.
+
+ * html/build.html: Applied patch by Roger Leigh (via tiff mailing
+ list on 2015-08-29) to describe how to use CMake to build libtiff.
+
+2015-08-28 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * html/v4.0.5.html: Added HTML file describing the changes which
+ will appear in the 4.0.5 release.
+
+2015-08-23 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tiffiop.h: For MinGW comiles, make sure that build
+ supports necessary __MSVCRT_VERSION__ (at least at least 0x800).
+ Otherwise large files can not be supported for POSIX-style I/O.
+
+ * tools/fax2tiff.c (main): Eliminate a compiler warning in 64-bit
+ builds about cast to thandle_t.
+
+ * test/rewrite_tag.c (main): Does not require any arguments.
+
+2015-08-20 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/CMakeLists.txt, port/snprintf.c: Patch by Roger Leigh to
+ fix build issues when using Cmake due to Windows large file
+ changes.
+
+2015-08-18 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tiffiop.h: First cut at supporting large files under
+ Microsoft Windows using tif_unix.c and the libtiff tools. This
+ only works if the Windows CDK is new enough to support the APIs
+ used (Visual C++ 2005 or later). Support for large files is not
+ actually tested yet.
+
+2015-08-15 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_jpeg.c: Applied patch by Räisä Olli to assure that
+ client_data is initialized to a known value, and to report an
+ error on two memory allocation failures.
+
+2015-08-13 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * CMakeLists.txt: Applied patch by Roger Leigh to fix libtiffxx
+ symbol versioning. Patch was mailed to libtiff list on Thu, 13
+ Aug 2015.
+
+2015-07-04 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * cmake: Add d suffix to debug libraries with MSVC. Patch #3 of 3
+ by Roger Leigh posted to tiff list on Wed, 1 Jul 2015 15:58:20
+ +0100.
+
+ * cmake: Add extra warning flags. Patch #2 of 3 by Roger Leigh
+ posted to tiff list on Wed, 1 Jul 2015 15:58:20 +0100.
+
+ * cmake: Correct snprintf fallback for VS2015. Patch #1 of 3 by
+ Roger Leigh posted to tiff list on Wed, 1 Jul 2015 15:58:20 +0100.
+
+2015-06-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * CMakeLists.txt: Add CMake patchset by Roger Leigh as posted to
+ libtiff mailing list on Mon, 22 Jun 2015 21:21:01 +0100. Several
+ corrections to ensure that the autotools build still works were
+ added by me. I have not yet tested the build using 'cmake' or
+ MSVC with 'nmake'.
+
+2015-06-21 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * test/Makefile.am: tiff2rgba-quad-tile.jpg.sh depends on the JPEG
+ library so only execute if JPEG is available.
+
+ * libtiff 4.0.4 released.
+
+ * configure.ac: Add a HAVE_FOO Automake conditional for each
+ add-on library.
+
+ * test/Makefile.am (JPEG_DEPENDENT_CHECK_PROG): raw_decode
+ requires JPEG support to compile. Use Automake conditional to
+ only include it when JPEG support is available.
+
+ * html/build.html: Try to improve the nmake-based VC++ build
+ description.
+
+ * libtiff/tiffconf.vc.h: Build fixes based on testing.
+
+ * libtiff/tif_config.vc.h: Build fixes based on testing.
+
+ * libtiff/libtiff.def: TIFFRasterScanline does not exist so remove
+ export for it.
+
+2015-06-20 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_config.vc.h: Make adjustments to match the new
+ definitions that configure produces, including for WIN64. Still
+ needs to be tested.
+
+ * configure.ac: For 64-bit MinGW, fix SSIZE_FORMAT formatting
+ specifier. 64-bit MinGW supports 'long long' but support for
+ 'lld' is not assured by the run-time DLLs and so GCC warns.
+ Add TIFF_SIZE_T and TIFF_SIZE_FORMAT to provide a type definition
+ and printf format specifier to deal with printing values of
+ 'size_t' type. In particular, this was necessary for WIN64.
+ Added a configure test for if the system headers provide 'optarg'
+ (normal case) and block out the many explicit 'extern' statements
+ in the utilities. This was found to be necessary under Windows
+ when getopt is in a DLL and the symbols are already imported with
+ dllimport via standard header files.
+
+ * test/raw_decode.c (XMD_H): Avoid conflicting typedefs for INT32
+ and boolean in MinGW build due to including jpeglib.h.
+
+ * test/rewrite_tag.c (main): Fix problem with location of variable
+ declaration.
+
+ * libtiff/libtiff.def: Added exports for TIFFGetConfiguredCODECs,
+ TIFFReadRGBAImageOriented, TIFFSetCompressionScheme,
+ TIFFSwabArrayOfTriples, TIFFVGetFieldDefaulted, _TIFFCheckRealloc,
+ TIFFRasterScanline, TIFFSetErrorHandlerExt,
+ TIFFSetWarningHandlerExt, TIFFNumberOfDirectories,
+ TIFFCreateCustomDirectory, TIFFCreateEXIFDirectory,
+ TIFFWriteCustomDirectory, _TIFFRewriteField as recommended by
+ Roger Leigh and justified by use in libtiff tests, documentation,
+ and changelog notes. Also sorted symbol list and removed
+ duplicate entries.
+
+2015-06-16 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_getimage.c: Fix four Coverity issues related to
+ unintended sign extension.
+
+2015-06-16 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_unix.c: fix compilation with MSVC (fix by Jeff McKenna)
+
+2015-06-14 Lee Howard <faxguy@howardsilvan.com>
+
+ * libtiff/tif_unix.c: contribution from Vadim Zeitlin on
+ Bugzilla Bug #2510 fixes several harmless but still annoying
+ warnings
+
+ * configure: contribution from Ludolf Holzheid on Bugzilla
+ Bug #2498. Adds an option to select the file I/O style on
+ Windows hosts.
+
+ * libtiff/tif_getimage.c: contribution from Gary Cramblitt
+ on Bugzilla Bug #2409. Correct reading of certain tiled TIFFs.
+
+ * configure, configure.ac: contribution from Marcos H. Woehrmann
+ on Bugzilla Bug #2405. Correct shell equality operator.
+
+ * tools/tiffgt.c (raster_draw): contribution from Jay Berkenbilt
+ on Bugzilla Bug #2401. Appropriately call glFlush().
+
+ * tools/tiff2pdf.c: change ColorTransform from "0" to "1"
+ following Bugzilla Bug #2150.
+
+2015-06-13 Lee Howard <faxguy@howardsilvan.com>
+
+ * libtiff/tif_lzw.c: contribution from Andy Cave - decode
+ files that contain consecutive CODE_CLEAR codes.
+
+ * tools/tiff2pdf.c: contribution from Antti S. Lankila on
+ Bugzilla Bug #2078. Suppress initial output of the header.
+
+ * tools/tiff2pdf.c: contribution from Yuriy M. Kaminskiy -
+ Take care in using the return value from snprintf().
+
+ * tools/tiffcrop.c: contribution from Eduardo Robles Elvira -
+ correctly copy the compression tag from the source TIFF.
+
+ * tools/tiff2ps.c: contribution from Eduardo Robles Elvira -
+ correct sizing and scaling problems with output document.
+
+2015-06-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_jpeg.c (JPEGDecode): Split JPEGDecode() into two
+ clean implementations in order to avoid pre-processor hell. Only
+ one of the implementations is used in a given build.
+
+2015-06-08 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tif_jpeg.c: Fix compilation in BITS_IN_JSAMPLE == 12
+ case
+
+2015-06-07 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_write.c (TIFFWriteEncodedStrip): Fix Coverity 715975
+ "Division or modulo by zero".
+ (TIFFWriteEncodedTile): Fix Coverity 715976 and 715977 "Division
+ or modulo by zero".
+ (TIFFWriteRawStrip): Fix Coverity 715978 "Division or modulo by
+ zero".
+ (TIFFWriteScanline): Fix Coverity 715979 "Division or modulo by
+ zero".
+
+ * libtiff/tif_read.c (TIFFStartTile): Fix Coverity 715973 and
+ 715974 "Division or modulo by zero".
+
+2015-05-31 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_dir.c (TIFFNumberOfDirectories): Quiet Coverity
+ 1134470 "Logically dead code" by making the roll-over check
+ explicit.
+
+ * libtiff/tif_luv.c (LogLuvDecodeTile): Fix Coverity 991227
+ "Division or modulo by zero".
+ (LogLuvDecodeStrip): Fix Coverity 991239 "Division or modulo by
+ zero".
+ (LogLuvEncodeStrip): Fix Coverity 991240 "Division or modulo by
+ zero".
+ (LogLuvEncodeTile): Fix Coverity 991241 "Division or modulo by
+ zero".
+
+ * libtiff/tif_dirread.c (TIFFReadDirEntryDoubleArray): Fix
+ Coverity 298626 "Logically dead code".
+ (TIFFReadDirEntryFloatArray): Fix Coverity 298627 "Logically dead
+ code".
+ (TIFFReadDirEntryIfd8Array): Fix Coverity 298628 "Logically dead
+ code".
+ (TIFFReadDirEntrySlong8Array): Fix Coverity 298629 "Logically dead
+ code"
+
+ * libtiff/tif_dir.c (TIFFNumberOfDirectories): Don't depend on ++
+ operator precedenc in evaluation. Might quench Coverity 1134470
+ "Logically dead code".
+
+ * libtiff/tif_jpeg.c (JPEGDecode): Fix Coverity 602597 "Operands
+ don't affect result". This change uses ifdefs to include
+ applicable code based on properties of libjpeg. Still needs to be
+ re-tested with 12-bit "6b" and "MK1".
+
+2015-05-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_dirwrite.c (_TIFFRewriteField): Fix Coverity 1024310
+ "Resource leak".
+
+ * libtiff/tif_ojpeg.c (OJPEGReadHeaderInfoSecStreamDht): Fix
+ Coverity 601720 "Resource leak".
+
+ * libtiff/tif_jpeg.c (JPEGCleanup): Fix Coverity 298624
+ "Dereference before null check".
+
+ * libtiff/tif_ojpeg.c (OJPEGReadBufferFill): Fix Coverity 603400
+ "Missing break in switch".
+
+ * contrib/addtiffo/tif_overview.c (TIFF_DownSample): Check buffer
+ size calculation for overflow.
+
+ * contrib/addtiffo/addtiffo.c (main): Possibly address Coverity
+ 1024226 "Untrusted value as argument".
+
+ * tools/gif2tiff.c (readgifimage): Fix Coverity 1024222 "Untrusted
+ value as argument".
+ (checksignature): Fix Coverity 1024894 "Ignoring number of bytes
+ read".
+ (readextension): Fix Coverity 1024893 "Ignoring number of bytes
+ read".
+ (readgifimage): Fix Coverity 1024890 "Ignoring number of bytes
+ read".
+ (readraster): Fix Coverity 1024891 "Ignoring number of bytes
+ read".
+ (readgifimage): Fix Coverity 1024892 "Ignoring number of bytes
+ read".
+
+ * tools/tiff2pdf.c (t2p_readwrite_pdf_image): Fix Coverity 1024181
+ "Structurally dead code".
+
+ * tools/raw2tiff.c (main): Fix Coverity 1024887 "Unchecked return
+ value from library".
+ (guessSize): Fix Coverity 1024888 "Unchecked return value from
+ library".
+ (guessSize): Fix Coverity 1214162 "Ignoring number of bytes read".
+ (guessSize): Fix Coverity 1024889 "Unchecked return value from
+ library".
+
+ * tools/tiff2pdf.c (t2p_readwrite_pdf_image): Fix Coverity 298621
+ "Resource leak".
+ (t2p_readwrite_pdf_image): Fix Coverity 1024181 "Structurally dead
+ code".
+ (t2p_write_pdf): Fix Coverity 1227690 "Unused value".
+
+2015-05-29 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * contrib/iptcutil/iptcutil.c (formatIPTC): Fix Coverity 1024468
+ "Infinite loop".
+ (formatIPTC): Fix Coverity 1024727 "Truncated stdio return value".
+ (formatIPTC): Fix Coverity 1214240 "Untrusted loop bound".
+
+2015-05-28 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * contrib/addtiffo/tif_ovrcache.c (TIFFCreateOvrCache): Fix
+ Coverity 298615 "Resource leak".
+ (TIFFGetOvrBlock): Fix Coverity 1024649 "Unintended sign
+ extension".
+
+ * tools/bmp2tiff.c (main): Fix Coverity 1024225 "Untrusted value
+ as argument".
+ (main): Fix Coverity 1024678 "Unchecked return value from
+ library".
+ (main): Fix Coverity 1024679 "Unchecked return value from
+ library".
+ (main): Fix Coverity 1214160 "Ignoring number of bytes read".
+
+ * contrib/addtiffo/tif_ovrcache.c (TIFFCreateOvrCache): Fix
+ Coverity 298615 "Resource leak".
+
+ * tools/tiffcp.c: Fix Coverity 1024306, 1024307, 1024308, 1024309
+ "Resource leak".
+
+ * tools/tiffsplit.c (cpTiles): Fix Coverity 1024304 "Resource
+ leak".
+ (cpStrips): Fix Coverity 1024305 "Resource leak".
+
+2015-05-27 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/ras2tiff.c: Fix Sun Raster header definition to be safe
+ for 64-bit systems. Add some header validations. Should fix many
+ Coverity issues.
+ (main): Fix Coverity 1301206: "Integer handling issues (BAD_SHIFT)".
+ (main): Quiet Coverity 1024223 "Untrusted value as argument".
+
+ * tools/tiffmedian.c (GetInputLine): Fix Coverity 1024795 "Nesting
+ level does not match indentation".
+ (get_histogram): Quiet Coverity 1024386 "Out-of-bounds read".
+ This was a benign mis-diagnosis but added code to enforce against
+ buffer overflow.
+
+ * tools/tiffcrop.c (ROTATE_ANY): Fix Coverity 1294542 "Logical
+ vs. bitwise operator".
+ (readContigStripsIntoBuffer): Fix Coverity 1024545 "Division or
+ modulo by zero".
+ (readContigTilesIntoBuffer): Fix Coverity 1024586 "Logically dead
+ code".
+ (writeSingleSection): Fix Coverity 1024796 "Nesting level does not
+ match indentation".
+ (writeCroppedImage): Fix Coverity 1024797 "Nesting level does not
+ match indentation".
+ (loadImage): Fix Coverity 1299741 "Dereference before null check".
+ (loadImage): Fix Coverity 1299740 "Out-of-bounds write".
+
+2015-03-02 Even Rouault <even.rouault@spatialys.com>
+
+ * tools/tiffdither.c: check memory allocations to avoid writing to
+ NULL pointer. Also check multiplication overflow. Fixes #2501,
+ CVE-2014-8128. Derived from patch by Petr Gajdos.
+
+2015-01-26 Even Rouault <even.rouault@spatialys.com>
+
+ * add html/v4.0.4beta.html under version control
+ * HOWTO-RELEASE: write that cvs add html/vX.X.html must be used
+
+2015-01-26 Even Rouault <even.rouault@spatialys.com>
+
+ * libtiff 4.0.4beta released
+
+2015-01-26 Even Rouault <even.rouault@spatialys.com>
+
+ * automake: updated to 1.15
+ * libtool: updated to 2.4.5
+
+2015-01-22 Even Rouault <even.rouault@spatialys.com>
+
+ * tools/tiff2pdf.c: Fix two crashes (oCERT-2014-013)
+
+2015-01-05 Frank Warmerdam <warmerdam@pobox.com>
+
+ * html/bugs.html: remove note about needing to email the tiff mailing
+ list administrator about being approved for membership, this appears
+ not to be true.
+
+2015-01-05 Olivier Paquet <olivier.paquet@gmail.com>
+
+ * tools/tiff2pdf.c: Fixed unsigned integer addition overflow detection.
+
+2015-01-03 Even Rouault <even.rouault@spatialys.com>
+
+ * libtiff/tif_dirread.c: in TIFFCheckDirOffset(), avoid uint16 overflow
+ when reading more than 65535 directories, and effectively error out when
+ reaching that limit.
+
+2014-12-29 Even Rouault <even.rouault@spatialys.com>
+
+ * libtiff/tif_jpeg.c: in JPEGFixupTags(), recognize SOF2, SOF9 and SOF10
+ markers to avoid emitting a warning (even if, according to the TechNote,
+ there are admittedly unusual/not recommended or even forbidden variants, but
+ they do work well with libjpeg for SOF2, and with libjpeg-turbo for SOF2,
+ SOF9 and SOF10).
+ Define in_color_space and input_components to the right values in
+ JPEGSetupEncode(), before calling jpeg_set_defaults(), as specified by
+ libjpeg API documentation, so as to be compatible with mozjpeg library.
+ Note: the default settings of mozjpeg will produce progressive scans, which
+ is forbidden by the TechNote.
+
+2014-12-29 Even Rouault <even.rouault@spatialys.com>
+
+ * libtiff/tif_getimage.c: move test on vertical value of YCbCr subsampling.
+ to avoid buffer leak (fix previous fix, found by Coverity scan)
+
+2014-12-29 Even Rouault <even.rouault@spatialys.com>
+
+ * libtiff/tif_next.c: add new tests to check that we don't read outside of
+ the compressed input stream buffer.
+
+ * libtiff/tif_getimage.c: in OJPEG case, fix checks on strile width/height
+ in the putcontig8bitYCbCr42tile, putcontig8bitYCbCr41tile and
+ putcontig8bitYCbCr21tile cases.
+
+2014-12-27 Even Rouault <even.rouault@spatialys.com>
+
+ * libtiff/tif_dir.c: in TIFFDefaultDirectory(), reset any already existing
+ extented tags installed by user code through the extender mechaninm before
+ calling the extender callback (GDAL #5054)
+
+2014-12-26 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiffcrop.c: Fix warnings about variables set but not used.
+
+ * contrib/iptcutil/iptcutil.c: Fix warnings about variables set
+ but not used.
+
+ * tools/tiffgt.c: Fix warnings about unused parameters.
+
+ * libtiff/tif_stream.cxx: Fix warnings about unused parameters.
+
+2014-12-25 Even Rouault <even.rouault@spatialys.com>
+
+ * libtiff/tif_getimage.c, libtiff/tif_ojpeg.c, libtiff/tif_zip.c: fix
+ various typos found by Debian lintian tool (GDAL #5756)
+
+2014-12-24 Even Rouault <even.rouault@spatialys.com>
+
+ * libtiff/tif_getimage.c: avoid divide by zero on invalid YCbCr subsampling.
+ http://bugzilla.maptools.org/show_bug.cgi?id=2235
+
+2014-12-24 Even Rouault <even.rouault@spatialys.com>
+
+ * tools/tiff2pdf.c: fix buffer overflow on some YCbCr JPEG compressed images.
+ http://bugzilla.maptools.org/show_bug.cgi?id=2445
+
+2014-12-24 Even Rouault <even.rouault@spatialys.com>
+
+ * tools/tiff2pdf.c: fix buffer overflow on YCbCr JPEG compressed image.
+ Derived from patch by Petr Gajdos,
+ http://bugzilla.maptools.org/show_bug.cgi?id=2443
+
+2014-12-23 Even Rouault <even.rouault@spatialys.com>
+
+ * libtiff/tif_dirread.c: In EstimateStripByteCounts(), check return code
+ of _TIFFFillStriles(). This solves crashing bug on corrupted
+ images generated by afl.
+
+2014-12-23 Even Rouault <even.rouault@spatialys.com>
+
+ * libtiff/tif_read.c: fix several invalid comparisons of a uint64 value with
+ <= 0 by casting it to int64 first. This solves crashing bug on corrupted
+ images generated by afl.
+
+2014-12-21 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiffdump.c: Guard against arithmetic overflow when
+ calculating allocation buffer sizes.
+
+2014-12-21 Even Rouault <even.rouault@spatialys.com>
+
+ * tools/tiff2bw.c: when Photometric=RGB, the utility only works if
+ SamplesPerPixel = 3. Enforce that
+ http://bugzilla.maptools.org/show_bug.cgi?id=2485 (CVE-2014-8127)
+
+2014-12-21 Even Rouault <even.rouault@spatialys.com>
+
+ * tools/pal2rgb.c, tools/thumbnail.c: fix crash by disabling TIFFTAG_INKNAMES
+ copying. The right fix would be to properly copy it, but not worth the burden
+ for those esoteric utilities.
+ http://bugzilla.maptools.org/show_bug.cgi?id=2484 (CVE-2014-8127)
+
+2014-12-21 Even Rouault <even.rouault@spatialys.com>
+
+ * tools/thumbnail.c: fix out-of-buffer write
+ http://bugzilla.maptools.org/show_bug.cgi?id=2489 (CVE-2014-8128)
+
+2014-12-21 Even Rouault <even.rouault@spatialys.com>
+
+ * tools/thumbnail.c, tools/tiffcmp.c: only read/write TIFFTAG_GROUP3OPTIONS
+ or TIFFTAG_GROUP4OPTIONS if compression is COMPRESSION_CCITTFAX3 or
+ COMPRESSION_CCITTFAX4
+ http://bugzilla.maptools.org/show_bug.cgi?id=2493 (CVE-2014-8128)
+
+2014-12-21 Even Rouault <even.rouault@spatialys.com>
+
+ * libtiff/tif_next.c: check that BitsPerSample = 2. Fixes
+ http://bugzilla.maptools.org/show_bug.cgi?id=2487 (CVE-2014-8129)
+
+2014-12-21 Even Rouault <even.rouault@spatialys.com>
+
+ * tools/tiff2pdf.c: check return code of TIFFGetField() when reading
+ TIFFTAG_SAMPLESPERPIXEL
+
+2014-12-21 Even Rouault <even.rouault@spatialys.com>
+
+ * tools/tiffcp.c: fix crash when converting YCbCr JPEG-compressed to none.
+ Based on patch by Tomasz Buchert (http://bugzilla.maptools.org/show_bug.cgi?id=2480)
+ Description: fix for Debian bug #741451
+ tiffcp crashes when converting JPEG-encoded TIFF to a different
+ encoding (like none or lzw). For example this will probably fail:
+ tiffcp -c none jpeg_encoded_file.tif output.tif
+ The reason is that when the input file contains JPEG data,
+ the tiffcp code forces conversion to RGB space. However,
+ the output normally inherits YCbCr subsampling parameters
+ from the input, which leads to a smaller working buffer
+ than necessary. The buffer is subsequently overrun inside
+ cpStripToTile() (called from writeBufferToContigTiles).
+ Note that the resulting TIFF file would be scrambled even
+ if tiffcp wouldn't crash, since the output file would contain
+ RGB data intepreted as subsampled YCbCr values.
+ This patch fixes the problem by forcing RGB space on the output
+ TIF if the input is JPEG-encoded and output is *not* JPEG-encoded.
+ Author: Tomasz Buchert <tomasz.buchert@inria.fr>
+
+2014-12-21 Even Rouault <even.rouault@spatialys.com>
+
+ Fix various crasher bugs on fuzzed images.
+ * libtiff/tif_dir.c: TIFFSetField(): refuse to set negative values for
+ TIFFTAG_XRESOLUTION and TIFFTAG_YRESOLUTION that cause asserts when writing
+ the directory
+ * libtiff/tif_dirread.c: TIFFReadDirectory(): refuse to read ColorMap or
+ TransferFunction if BitsPerSample has not yet been read, otherwise reading
+ it later will cause user code to crash if BitsPerSample > 1
+ * libtiff/tif_getimage.c: TIFFRGBAImageOK(): return FALSE if LOGLUV with
+ SamplesPerPixel != 3, or if CIELAB with SamplesPerPixel != 3 or BitsPerSample != 8
+ * libtiff/tif_next.c: in the "run mode", use tilewidth for tiled images
+ instead of imagewidth to avoid crash
+ * tools/bmp2tiff.c: fix crash due to int overflow related to input BMP dimensions
+ * tools/tiff2pdf.c: fix crash due to invalid tile count (should likely be checked by
+ libtiff too). Detect invalid settings of BitsPerSample/SamplesPerPixel for CIELAB / ITULAB
+ * tools/tiffcrop.c: fix crash due to invalid TileWidth/TileHeight
+ * tools/tiffdump.c: fix crash due to overflow of entry count.
+
+2014-12-15 Even Rouault <even.rouault@spatialys.com>
+
+ * libtiff/tif_jpeg.c: Fix regression introduced on 2010-05-07 that caused
+ all tiles/strips to include quantization tables even when the jpegtablesmode
+ had the JPEGTABLESMODE_QUANT bit set.
+ Also add explicit removal of Huffman tables when jpegtablesmode has the
+ JPEGTABLESMODE_HUFF bit set, which avoids Huffman tables to be emitted in the
+ first tile/strip (only useful in update scenarios. create-only was
+ fine)
+
+2014-12-09 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiff2pdf.c: Assure that memory size calculations for
+ _TIFFmalloc() do not overflow the range of tmsize_t.
+
+2014-12-07 Even Rouault <even.rouault@spatialys.com>
+
+ * tools/thumbnail.c, tools/tiffcrop.c: "fix" heap read over-run found with
+ Valgrind and Address Sanitizer on test suite
+
+2014-12-07 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiff2pdf.c (t2p_read_tiff_init): TIFFTAG_TRANSFERFUNCTION
+ tag can return one channel, with the other two channels set to
+ NULL. The tiff2pdf code was expecting that other two channels
+ were duplicate pointers in the case where there is only one
+ channel. Detect this condition in order to avoid a crash, and
+ presumably perform correctly with just one channel.
+
+2014-12-06 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiffdump.c: Fix double-free bug.
+
+2014-11-27 Even Rouault <even.rouault@spatialys.com>
+
+ * libtiff/tif_config.vc.h: no longer use "#define snprintf _snprintf" with
+ Visual Studio 2015 aka VC 14 aka MSVC 1900
+
+2014-11-20 Even Rouault <even.rouault@spatialys.com>
+
+ * libtiff/tif_lzw.c: prevent potential null dereference of
+ sp->dec_codetab in LZWPreDecode (bug #2459)
+
+ * libtiff/tif_read.c: in TIFFReadBufferSetup(), avoid passing -1 size
+ to TIFFmalloc() if passed user buffer size is 0 (bug #2459)
+
+ * libtiff/tif_ojpeg.c: make Coverity happier (not a bug, #2459)
+
+ * libtiff/tif_dir.c: in _TIFFVGetField() and _TIFFVSetField(), make
+ Coverity happier (not a bug, #2459)
+
+ * libtiff/tif_dirread.c: in TIFFFetchNormalTag(), make Coverity happier
+ (not a bug, #2459)
+
+ * tools/tiff2pdf.c: close PDF file (bug #2479)
+
+ * tools/fax2ps.c: check malloc()/realloc() result (bug #2470)
+
+ * tools/tiffdump.c: detect cycle in TIFF directory chaining (bug #2463)
+ and avoid passing a NULL pointer to read() if seek() failed before (bug #2459)
+
+ * tools/tiffcrop.c: fix segfault if bad value passed to -Z option
+ (bug #2459) and add missing va_end in dump_info (#2459)
+
+ * tools/gif2tif.c: apply patch for CVE-2013-4243 (#2451)
+
+2014-11-20 Even Rouault <even.rouault@spatialys.com>
+ * libtiff/tif_jpeg.c: fix segfault in JPEGFixupTagsSubsampling() on
+ corrupted image where tif->tif_dir.td_stripoffset == NULL (bug #2471)
+
+2014-11-20 Even Rouault <even.rouault@spatialys.com>
+ * automake: updated to 1.14.1
+ * libtool: updated to 2.4.3
+ * HOWTO-RELEASE: small update about autotools building order
+
+2014-10-20 Olivier Paquet <olivier.paquet@gmail.com>
+ * tools/tiff2pdf.c: Preserve input file directory order when pages
+ are tagged with the same page number.
+
+2014-08-31 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_dirread.c (TIFFReadDirEntryOutputErr): Incorrect
+ count for tag should be a warning rather than an error since
+ errors terminate processing.
+
+2014-06-07 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiff2rgba.c (]): Fixed tiff2rgba usage message in that zip
+ was wrongly described. Fix suggested by Miguel Medalha.
+
+2014-05-06 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_dirinfo.c (TIFFField) : Fix data type for
+ TIFFTAG_GLOBALPARAMETERSIFD tag. Patch by Steve Underwood.
+ Reviewed and forwarded by Lee Howard.
+
+2013-11-30 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dir.c: fix last fix for TIFFNumberOfDirectories()
+
+2013-10-21 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dir.c: generate error in case of directory count
+ overflow.
+
+2013-10-01 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tiff.h, libtiff/tif_dirinfo.c: add definitions for
+ TIFF/EP CFARepeatPatternDim and CFAPattern tags (bug #2457)
+
+2013-09-12 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_dir.c (TIFFAdvanceDirectory): If nextdir is found to
+ be defective, then set it to zero before returning error in order
+ to terminate processing of truncated TIFF. Issue found and fix
+ suggested by Richard Nolde.
+
+2013-08-14 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/gif2tiff.c: fix possible OOB write (#2452, CVE-2013-4244)
+
+2013-08-13 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/gif2tiff.c: Be more careful about corrupt or
+ hostile input files (#2450, CVE-2013-4231)
+
+ * tools/tiff2pdf.c: terminate after failure of allocating
+ ycbcr buffer (bug #2449, CVE-2013-4232)
+
+2013-07-09 Frank Warmerdam <warmerdam@google.com>
+
+ * tools/tiffinfo.c: Default various values fetched with
+ TIFFGetField() to avoid being uninitialized.
+
+2013-05-02 Tom Lane <tgl@sss.pgh.pa.us>
+
+ * tools/tiff2pdf.c: Rewrite JPEG marker parsing in
+ t2p_process_jpeg_strip to be at least marginally competent. The
+ approach is still fundamentally flawed, but at least now it won't
+ stomp all over memory when given bogus input. Fixes CVE-2013-1960.
+
+2013-05-02 Tom Lane <tgl@sss.pgh.pa.us>
+
+ * contrib/dbs/xtiff/xtiff.c, libtiff/tif_codec.c,
+ libtiff/tif_dirinfo.c, tools/rgb2ycbcr.c, tools/tiff2bw.c,
+ tools/tiff2pdf.c, tools/tiff2ps.c, tools/tiffcrop.c,
+ tools/tiffdither.c: Enlarge some fixed-size buffers that weren't
+ large enough, and eliminate substantially all uses of sprintf(buf,
+ ...) in favor of using snprintf(buf, sizeof(buf), ...), so as to
+ protect against overflow of fixed-size buffers. This responds in
+ particular to CVE-2013-1961 concerning overflow in tiff2pdf.c's
+ t2p_write_pdf_page(), but in general it seems like a good idea to
+ deprecate use of sprintf().
+
+2013-03-29 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * configure.ac: Applied patch by Brad Smith to improve pkg-config
+ static linking by adding -lm to Libs.private when needed.
+
+2013-03-05 Tom Lane <tgl@sss.pgh.pa.us>
+
+ * html/man/tiff2ps.1.html, html/man/tiffcp.1.html,
+ html/man/tiffdither.1.html, man/tiff2ps.1, man/tiffcp.1,
+ man/tiffdither.1, tools/tiff2ps.c, tools/tiffcp.c,
+ tools/tiffdither.c: Sync tool usage printouts and man pages with
+ reality (quite a few options had escaped being documented in one
+ or both places). Per an old report from Miroslav Vadkerti.
+
+2013-01-25 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiff2ps.c:Fix bug in auto rotate option code. Once a
+ rotation angle was set by the auto rotate check, it was retained
+ for all pages that followed instead ofa being retested for each
+ page. Patch by Richard Nolde.
+
+2013-01-18 Frank Warmerdam <warmerdam@google.com>
+
+ * libtiff/tif_write.c: tmsize_t related casting warning fixed for
+ 64bit linux.
+
+ * libtiff/tif_read.c: uint64/tmsize_t change for MSVC warnings.
+ http://bugzilla.maptools.org/show_bug.cgi?id=2427
+
+2012-12-20 Tom Lane <tgl@sss.pgh.pa.us>
+
+ * test/raw_decode.c: Relax raw_decode's pixel-value checks so that
+ it will pass with more versions of libjpeg. (There are at least
+ three in active use now, and JPEG_LIB_VERSION doesn't tell us
+ enough to uniquely identify expected results.)
+
+2012-12-12 Tom Lane <tgl@sss.pgh.pa.us>
+
+ * libtiff/tif_print.c: Fix TIFFPrintDirectory's handling of
+ field_passcount fields: it had the TIFF_VARIABLE and
+ TIFF_VARIABLE2 cases backwards.
+
+2012-12-10 Tom Lane <tgl@sss.pgh.pa.us>
+
+ * tools/ppm2tiff.c: Improve previous patch for CVE-2012-4564:
+ check the linebytes calculation too, get the max() calculation
+ straight, avoid redundant error messages, check for malloc
+ failure.
+
+2012-12-10 Tom Lane <tgl@sss.pgh.pa.us>
+
+ * libtiff/tif_pixarlog.c: Improve previous patch for CVE-2012-4447
+ (to enlarge tbuf for possible partial stride at end) so that
+ overflow in the integer addition is detected. Per gripe from
+ Huzaifa Sidhpurwala.
+
+2012-12-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiffset.c: tiffset now supports a -u option to unset a
+ tag. Patch by Zach Baker. See
+ http://bugzilla.maptools.org/show_bug.cgi?id=2419
+
+2012-11-18 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * automake: Update Automake to 1.12.5 release.
+
+ * libtiff/tif_{unix,vms,win32}.c (_TIFFmalloc): ANSI C does not
+ require malloc() to return NULL pointer if requested allocation
+ size is zero. Assure that _TIFFmalloc does.
+
+2012-11-01 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/ppm2tiff.c: avoid zero size buffer vulnerability.
+ CVE-2012-4564 - Thanks to Huzaifa Sidhpurwala of the
+ Red Hat Security Response team for the fix.
+
+2012-10-18 Frank Warmerdam <warmerdam@google.com>
+
+ * tif_zip.c: Avoid crash on NULL error messages.
+
+2012-09-22 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff 4.0.3 released.
+
+2012-09-20 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * Makefile.am: Update to Automake 1.12.4
+
+2012-08-19 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * Makefile.in: Update to Automake 1.12.3
+
+ * libtiff{tiff.h, tif_print.c, tif_dirinfo.c, tif_dirread.c}: Add
+ some TIFF/FX support in libtiff. Add the tag definitions to
+ tiff.h. Add the related TIFF field definitions to tif_dirinfo.c,
+ and also fixes an error in a comment. Adds the photometric values
+ to tif_print.c, and fixes a bug. These changes are by Steve
+ Underwood.
+
+2012-08-13 Frank Warmerdam <warmerdam@google.com>
+
+ * libtiff/tif_write.c: Fix bug rewriting image tiles in a
+ compressed file: http://trac.osgeo.org/gdal/ticket/4771
+
+2012-08-02 Frank Warmerdam <warmerdam@google.com>
+
+ * libtiff/tif_dirread.c: report error in case of mismatch value
+ counts for tags (ie. DotRange).
+
+2012-07-26 Tom Lane <tgl@sss.pgh.pa.us>
+
+ * libtiff/{tiffio.h, tif_dirinfo.c, libtiff.def}: Add six new
+ functions TIFFFieldTag(), TIFFFieldName(), TIFFFieldDataType(),
+ TIFFFieldPassCount(), TIFFFieldReadCount(), TIFFFieldWriteCount()
+ as external accessors for the opaque type TIFFField.
+
+ * tools/tiffset.c: Make tiffset use the above functions instead of
+ relying on library private headers.
+
+2012-07-19 Tom Lane <tgl@sss.pgh.pa.us>
+
+ * tools/tiff2pdf.c: Fix two places where t2p_error didn't get set
+ after a malloc failure. No crash risk AFAICS, but the program
+ might not report exit code 1 as desired. h/t mancha@mac.hush.com
+
+2012-07-18 Tom Lane <tgl@sss.pgh.pa.us>
+
+ * tools/tiff2pdf.c: Fail when TIFFSetDirectory() fails. This
+ prevents core dumps or perhaps even arbitrary code execution when
+ processing a corrupt input file (CVE-2012-3401).
+
+2012-07-06 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * test/raw_decode.c (main): Test fixes to work with IJG JPEG 7+.
+ IJG JPEG 7+ uses a different upsampling algorithm which produces
+ different numeric results.
+
+ * libtiff/tif_jpeg.c (JPEGPreDecode): Patch from Even Rouault to
+ work with IJG JPEG 7+.
+
+2012-07-04 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * test/raw_decode.c: Add changes so that test can run with build
+ directory outside of source directory.
+
+2012-07-02 Frank Warmerdam <warmerdam@google.com>
+
+ * libtiff/tif_jpeg.c: Fix handling when writing RGBA jpeg compressed
+ imagery (http://trac.osgeo.org/gdal/ticket/4732)
+
+2012-06-20 Frank Warmerdam <warmerdam@google.com>
+
+ * libtiff/tif_fax3.c: fix memory initialization of runs, only
+ partly done.
+
+ * libtiff/tif_pixarlog.c: Make sure tbuf is large enough for one
+ full "stride" past the end.
+
+2012-06-19 Frank Warmerdam <warmerdam@google.com>
+
+ * libtiff/tif_packbits.c: fix read past end of data buffer.
+
2012-06-15 Frank Warmerdam <warmerdam@google.com>
* libtiff 4.0.2 released.
* libtiff/tif_dir.c, tif_print.c : Remove FIELD_CUSTOM handling for
PAGENUMBER, HALFTONEHINTS, and YCBCRSUBSAMPLING. Implement DOTRANGE
- differently. This is to avoid using special TIFFGetField/TIFFSetField
+ differently. This is to avoid using special TIFFGetField/TIFFSetField
rules for these fields in non-image directories (like EXIF).
2012-06-04 Frank Warmerdam <warmerdam@google.com>
2012-05-19 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
* man/TIFFGetField.3tiff: Correct the 'count' field type in the
- example for how to retreive the value of unsupported tags.
+ example for how to retrieve the value of unsupported tags.
2012-03-30 Frank Warmerdam <warmerdam@google.com>
2012-01-31 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_dir.c, libtiff/tif_dirread.c: Extra caution around
- assumption tag fetching is always successful.
+ assumption tag fetching is always successful.
* libtiff/tif_jpeg.c: Extra caution for case where sp is NULL.
* libtiff/tif_dirread.c: fixes to deal with invalid files where
_TIFFFillStriles() fails, and we try to chop up strips (gdal #4372)
- * libtiff/tif_dirread.c: fix error reporting when there is no
+ * libtiff/tif_dirread.c: fix error reporting when there is no
tag information struct and name (gdal #4373)
2011-10-22 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
2011-04-20 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_dirinfo.c,tiffio.h: Remove the obsolete
- TIFFMergeFieldInfo/TIFFFindFieldInfo/TIFFFindFieldInfoByName API.
+ * libtiff/tif_dirinfo.c,tiffio.h: Remove the obsolete
+ TIFFMergeFieldInfo/TIFFFindFieldInfo/TIFFFindFieldInfoByName API.
http://bugzilla.maptools.org/show_bug.cgi?id=2315
- * libtiff/libtiff.def: add some missing (64bit) APIs.
+ * libtiff/libtiff.def: add some missing (64bit) APIs.
http://bugzilla.maptools.org/show_bug.cgi?id=2316
2011-04-09 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
2011-03-21 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_thunder.c: Correct potential buffer overflow with
- thunder encoded files with wrong bitspersample set. The libtiff
+ * libtiff/tif_thunder.c: Correct potential buffer overflow with
+ thunder encoded files with wrong bitspersample set. The libtiff
development team would like to thank Marin Barbella and TippingPoint's
Zero Day Initiative for reporting this vulnerability (ZDI-CAN-1004,
CVE-2011-1167).
2011-03-10 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_fax3.h: Fix to last change allowing zero length
+ * libtiff/tif_fax3.h: Fix to last change allowing zero length
runs at the start of a scanline - needed for legal cases.
2011-03-02 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_fax3.h: Protect against a fax VL(n) codeword commanding
- a move left. Without this, a malicious input file can generate an
- indefinitely large series of runs without a0 ever reaching the right
+ * libtiff/tif_fax3.h: Protect against a fax VL(n) codeword commanding
+ a move left. Without this, a malicious input file can generate an
+ indefinitely large series of runs without a0 ever reaching the right
margin, thus overrunning our buffer of run lengths. Per CVE-2011-0192.
- This is a modified version of a patch proposed by Drew Yao of Apple
- Product Security. It adds an unexpected() report, and disallows the
- equality case, since emitting a run without increasing a0 still allows
+ This is a modified version of a patch proposed by Drew Yao of Apple
+ Product Security. It adds an unexpected() report, and disallows the
+ equality case, since emitting a run without increasing a0 still allows
buffer overrun.
2011-02-23 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_jpeg.c: avoid divide by zero in degenerate case (#2296)
- * tools/tiff2rgba.c: close source file on error to make leak
+ * tools/tiff2rgba.c: close source file on error to make leak
detection easier.
* libtiff/tif_getimage.c: avoid leaks if TIFFRGBAImageBegin() fails.
2011-02-18 Frank Warmerdam <warmerdam@pobox.com>
* configure.ac, configure: Added support for --enable-chunky-strip-read
- configure option to enable the experimental feature from a couple
- months ago for reading big strips in chunks.
+ configure option to enable the experimental feature from a couple
+ months ago for reading big strips in chunks.
- * configure.ac, tif_read.c, tif_readdir.c, tif_dir.h, tiffiop.h,
+ * configure.ac, tif_read.c, tif_readdir.c, tif_dir.h, tiffiop.h,
tif_write.c, tif_print.c, tif_jpeg.c, tif_dirwrite.c, tif_write.c:
- Implement optional support for deferring the load of strip/tile
+ Implement optional support for deferring the load of strip/tile
offset and size tags for optimized scanning of directories. Enabled
with the --enable-defer-strile-load configure option (DEFER_STRILE_LOAD
- #define in tif_config.h).
+ #define in tif_config.h).
2011-02-11 Frank Warmerdam <warmerdam@pobox.com>
2011-02-09 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_win32.c: avoid error/warning buffer overrun problem
- with non-console (popup message) builds on win32.
+ with non-console (popup message) builds on win32.
http://bugzilla.maptools.org/show_bug.cgi?id=2293
2011-01-06 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_pixarlog.c: Note that tif_rawcc/tif_rawcp are not
- maintained.
+ * libtiff/tif_pixarlog.c: Note that tif_rawcc/tif_rawcp are not
+ maintained.
- * libtiff/tif_zip.c: Maintain tif_rawcc/tif_rawcp when decoding
+ * libtiff/tif_zip.c: Maintain tif_rawcc/tif_rawcp when decoding
for CHUNKY_STRIP_READ_SUPPORT.
* libtiff/tif_jpeg.c: ensure that rawcc and rawcp are maintained
- during JPEGPreDecode and JPEGDecode calls.
- * libtiff/tif_read.c: larger read ahead for CHUNKY_STRIP_READ_SUPPORT,
- as compression formats like JPEG keep 16 lines interleaved in a sense
- and might need to touch quite a bit of data.
-
+ during JPEGPreDecode and JPEGDecode calls.
+ * libtiff/tif_read.c: larger read ahead for CHUNKY_STRIP_READ_SUPPORT,
+ as compression formats like JPEG keep 16 lines interleaved in a sense
+ and might need to touch quite a bit of data.
+
http://trac.osgeo.org/gdal/ticket/3894
2011-01-03 Lee Howard <faxguy@howardsilvan.com>
2010-12-12 Lee Howard <faxguy@howardsilvan.com>
- * tools/tiff2pdf.c: fix colors for images with RGBA
+ * tools/tiff2pdf.c: fix colors for images with RGBA
interleaved data
http://bugzilla.maptools.org/show_bug.cgi?id=2250
2010-10-21 Frank Warmerdam <warmerdam@pobox.com>
* tools/tiffinfo.c: avoid direct reference to _TIFFerrorHandler.
-
+
* libtiff/tif_config.vc.h: define snprintf to _snprintf for tiff2pdf.
* libtiff/libtiff.def: export _TIFFCheckMalloc for tools.
* libtiff/tif_dirinfo.c: Fix invocation of tag compare function (#2201)
- * tools/tiff2pdf.c: Fix assorted bugs in tiff2pdf: missing "return"
- in t2p_read_tiff_size() causes t2p->tiff_datasize to be set entirely
- wrong for COMPRESSION_JPEG case, resulting in memory stomp if actual
- size is larger. Also, there are a bunch of places that try to
- memset() a malloc'd buffer before checking for malloc failure, which
+ * tools/tiff2pdf.c: Fix assorted bugs in tiff2pdf: missing "return"
+ in t2p_read_tiff_size() causes t2p->tiff_datasize to be set entirely
+ wrong for COMPRESSION_JPEG case, resulting in memory stomp if actual
+ size is larger. Also, there are a bunch of places that try to
+ memset() a malloc'd buffer before checking for malloc failure, which
would result in core dump if there actually were a failure. (#2211)
2010-06-11 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
2010-05-07 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_jpeg.c: Ensure that quality is always set in
- JPEGPreEncode(), not just when we want to output local tables.
+ * libtiff/tif_jpeg.c: Ensure that quality is always set in
+ JPEGPreEncode(), not just when we want to output local tables.
Otherwise the quality used during compression may not be right and
might not match the tables in the tables tag. This bug only occurs
when seeking between directories in the midst of writing blocks.
http://trac.osgeo.org/gdal/ticket/3539
-
+
2010-05-06 Andrey Kiselev <dron@ak4719.spb.edu>
* html/man/TIFFGetField.3tiff.html, html/man/TIFFSetField.3tiff.html:
2010-04-21 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_jpeg.c: avoid preparing jpeg tables everytime
- JPEGSetupEncode() is called if the tables already seem to be
- established. This prevents spurious updates and rewriting of
+ * libtiff/tif_jpeg.c: avoid preparing jpeg tables every time
+ JPEGSetupEncode() is called if the tables already seem to be
+ established. This prevents spurious updates and rewriting of
directories with jpegtables when doing updates to existing images.
http://trac.osgeo.org/gdal/ticket/3539
2010-04-02 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_read.c (primarily): Add support for
+ * libtiff/tif_read.c (primarily): Add support for
CHUNKY_STRIP_READ_SUPPORT where large strips are
read in chunks for applications using TIFFReadScanline().
This is intended to make it more practical work with very
2010-02-22 Lee Howard <faxguy@howardsilvan.com>
* libtiff/tif_jpeg.c: Do not generate a JPEGTables tag when creating
- the JPEG TIFF as is is not required in order to prevent it from
- being unused and filled with invalid data. (Leave it to be
+ the JPEG TIFF as is is not required in order to prevent it from
+ being unused and filled with invalid data. (Leave it to be
generated by later activity.)
http://bugzilla.maptools.org/show_bug.cgi?id=2135
- * tools/tiff2pdf.c: Write the JPEG SOI headers into the TIFF strip
+ * tools/tiff2pdf.c: Write the JPEG SOI headers into the TIFF strip
data rather than skipping them. This fixes the ability to view in
Acrobat Reader, Evince, and Ghostscript.
http://bugzilla.maptools.org/show_bug.cgi?id=2135
2009-12-03 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_jpeg.c: Made JPEGDecodeRaw() check for buffer overruns.
- Made so that when working with downsampled images a stub function
+ Made so that when working with downsampled images a stub function
reporting an error is used for tif_decoderow. We cannot meaningfully
support reading scanlines in this situation. (#1936)
2009-11-30 Frank Warmerdam <warmerdam@pobox.com>
- * contrib/dbs/tiff-grayscale.c, contrib/tif-palette.c,
+ * contrib/dbs/tiff-grayscale.c, contrib/tif-palette.c,
tools/ras2tiff.c: Fix resource leaks on error.
http://bugzilla.maptools.org/show_bug.cgi?id=2121
- * libtiff/tif_{aux.c,dir.c,dir.h,dirinfo.c}: Return to handling
+ * libtiff/tif_{aux.c,dir.c,dir.h,dirinfo.c}: Return to handling
TIFFTAG_REFERENCEBLACKWHITE as a field in the TIFF directory instead
of as a custom(generic) field to avoid a potential reentrancy problem.
http://bugzilla.maptools.org/show_bug.cgi?id=2125
-
+
* libtiff/tif_color.c, libtiff/tif_getimage.c, libtiff/tiffio.h,
- man/TIFFcolor.3tiff: Make TIFFDisplay argument in TIFFCIELabToRGBInit
+ man/TIFFcolor.3tiff: Make TIFFDisplay argument in TIFFCIELabToRGBInit
const, and display_sRGB static and const.
http://bugzilla.maptools.org/show_bug.cgi?id=2124
2009-09-03 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_getimage.c: Fixed error recognition handling in RGBA
- interface when stoponerror is set.
+ interface when stoponerror is set.
http://bugzilla.maptools.org/show_bug.cgi?id=2071
2009-08-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
* libtiff/tif_dirread.c (TIFFReadCustomDirectory): Apply patch
from Jay Berkenbilt for "Bug 1895 - logic error in tif_dirread.c:
- segfault after setting tdir_tag = IGNORE".
+ segfault after setting tdir_tag = IGNORE".
http://bugzilla.maptools.org/show_bug.cgi?id=1895
2009-08-23 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
tiffcrop.sh into a collection of many specific tests. Re-wrote
all of the existing tests to be based on some simple shell
functions. Make distcheck works again.
-
+
Export certain variables (MAKE, MAKEFLAGS, MEMCHECK) to tests and
added 'memcheck' and 'ptrcheck' targets to make it easy to run the
tests under valgrind.
1 on success instead of zero.
http://bugzilla.maptools.org/show_bug.cgi?id=2069
- * libtiff/tif_lzw.c: back out patch from #2065 and apply patch from
+ * libtiff/tif_lzw.c: back out patch from #2065 and apply patch from
#1085 for a better underflow fix that errors properly.
http://bugzilla.maptools.org/show_bug.cgi?id=2065
http://bugzilla.maptools.org/show_bug.cgi?id=1985
2009-06-22 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_lzw.c: Fix buffer underflow bug.
+ * libtiff/tif_lzw.c: Fix buffer underflow bug.
http://bugzilla.maptools.org/show_bug.cgi?id=2065
2009-06-21 Frank Warmerdam <warmerdam@pobox.com>
* configure.ac, libtiff/tif_jpeg.c, libtiff/tif_jpeg_12.c: add support
- for dual mode 8/12 bit jpeg support.
+ for dual mode 8/12 bit jpeg support.
2009-06-03 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/{tif_jpeg.c,tif_ojpeg.c,tif_getimage.c}: Fixed various
error reports to use "%s" as format string.
http://trac.osgeo.org/gdal/ticket/2976
-
+
2009-03-12 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/{tif_fax3.c,tif_jpeg.c,tif_ojpeg.c}: Fix printdir chaining
2009-02-12 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_luv.c: Fix handling of tiled logluv images.
+ * libtiff/tif_luv.c: Fix handling of tiled logluv images.
http://bugzilla.maptools.org/show_bug.cgi?id=2005
2009-02-09 Frank Warmerdam <warmerdam@pobox.com>
2009-02-05 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_dirread.c: Re-incorporated a sanity check on tag size,
- but at the 2GB boundary to avoid overflow on 32bit systems.
+ but at the 2GB boundary to avoid overflow on 32bit systems.
http://bugzilla.maptools.org/show_bug.cgi?id=1993
* libtiff/tif_dirread.c: Remove some assertions that blow due to
- corrupt files rather than in response to library internal
- inconsistencies.
+ corrupt files rather than in response to library internal
+ inconsistencies.
http://bugzilla.maptools.org/show_bug.cgi?id=1995
http://bugzilla.maptools.org/show_bug.cgi?id=1991
* libtiff/tif_dirread.c: Fixed testing for failed result from
- TIFFReadDirectoryFindFieldInfo().
+ TIFFReadDirectoryFindFieldInfo().
http://bugzilla.maptools.org/show_bug.cgi?id=1992
2009-01-23 Frank Warmerdam <warmerdam@pobox.com>
http://bugzilla.maptools.org/show_bug.cgi?id=1911
* libtiff/tif_dirwrite.c: Fix byte swapping of next directory offset.
-
+
http://bugzilla.maptools.org/show_bug.cgi?id=1924
- * tools/tiffcrop.c: initialize xres/yres values.
+ * tools/tiffcrop.c: initialize xres/yres values.
* test/*.sh - default ${srcdir} to local directory.
- * test/common.sh - start verbose mode after common settings.
+ * test/common.sh - start verbose mode after common settings.
- * libtiff/tif_dirinfo.c: Replace lfind() with local equivelent to
- avoid type mismatches on different platforms.
+ * libtiff/tif_dirinfo.c: Replace lfind() with local equivalent to
+ avoid type mismatches on different platforms.
http://bugzilla.maptools.org/show_bug.cgi?id=1889
2009-01-22 Frank Warmerdam <warmerdam@pobox.com>
tiffsplit.c}: avoid warnings, mostly 32bit/64bit casting issues.
* port,tools: Introduce libport.h, and include in tools if NEED_LIBPORT
- defined, primarily to reduce prototype warnings on windows.
+ defined, primarily to reduce prototype warnings on windows.
* libtiff/tif_dirinfo.c,tif_dirread.c: Avoid warnings
about unused parameters, and uninitialized variables.
for TIFFError(), TIFFErrorExt(), TIFFWarning(), and
TIFFWarningExt() in order to reveal bugs.
- * Many fixes throughout to work better as a 64-bit build.
+ * Many fixes throughout to work better as a 64-bit build.
2008-12-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
2008-10-09 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_jpeg.c: Add #ifdefs for changes needed if using
- IPP enabled version of libjpeg from Intel.
+ IPP enabled version of libjpeg from Intel.
http://bugzilla.maptools.org/show_bug.cgi?id=1951
2008-09-05 Andrey Kiselev <dron@ak4719.spb.edu>
* tools/tiffdump.c: When compiling for Microsoft Windows, apply
consistent (__int64) casting when testing if _lseeki64 has
- successfully seeked as requested. This is necessary for large
+ successfully sought as requested. This is necessary for large
file support to work since off_t is only 32-bit.
2008-07-29 Frank Warmerdam <warmerdam@pobox.com>
- * tif_strip.c: Replace assertions related to samplesperpixel != 3 or
+ * tif_strip.c: Replace assertions related to samplesperpixel != 3 or
the subsampling values not being 1, 2 or 4 (for jpeg compressed images)
with control logic to return runtime errors (c/o Even Rouault) (#1927).
2008-05-24 Frank Warmerdam <warmerdam@pobox.com>
- * tif_codec.c: Avoid NULL pointer dereferencing for exotic
+ * tif_codec.c: Avoid NULL pointer dereferencing for exotic
compression codec codes.
* tif_dirwrite.c: fix potential memory leak.
* tif_dirread.c: Fix unchecked malloc result.
-
+
2008-05-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
* test {tiff2pdf.sh tiff2ps-EPS1.sh tiff2ps-PS1.sh tiff2ps-PS2.sh
* libtiff/tif_dirinfo.c: Use TIFF_SETGET_ASCII for PIXAR_TEXTUREFORMAT
and PIXAR_WRAPMODES instead of TIFF_SETGET_UNDEFINED. Not exactly clear
- why this is needed.
+ why this is needed.
2008-05-09 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
2008-03-14 Frank Warmerdam <warmerdam@pobox.com>
* tif_dirread.c: Removed sanity checks on tags larger than 4MB in
- TIFFReadDirEntryArray() since they are interfering with seemingly
+ TIFFReadDirEntryArray() since they are interfering with seemingly
legitimate files. http://trac.osgeo.org/gdal/ticket/2005
2008-02-09 Joris Van Damme <joris.at.lebbeke@skynet.be>
- * tif_dirread.c: Added handling for the case of number of values for
- PageNumber tag different from 2 (previously resulted in an assert
+ * tif_dirread.c: Added handling for the case of number of values for
+ PageNumber tag different from 2 (previously resulted in an assert
indicating lack of handling and was forgotten about)
2008-02-01 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_jpeg.c: Do not try to fixup subsampling tags based on
+ * libtiff/tif_jpeg.c: Do not try to fixup subsampling tags based on
the actual jpeg data stream if the first strip/tile has zero size.
This is the case when GDAL creates a new file with zero sizes, closes
and reopens it.
2008-01-07 Frank Warmerdam <warmerdam@pobox.com>
- * tools/tiff2ps.c: fix up 64bit issues (from Edward Lam).
+ * tools/tiff2ps.c: fix up 64bit issues (from Edward Lam).
2008-01-01 Frank Warmerdam <warmerdam@pobox.com>
targets.
* tools/tiffinfo.c, tools/tiffcmp.c, tools/gif2tiff.c, tools/bmp2tiff.c
- tools/tiff2pdf.c: Fix 64-bit warnings when compiling under MSVC 2005
- (x64).
+ tools/tiff2pdf.c: Fix 64-bit warnings when compiling under MSVC 2005
+ (x64).
- * tools/tiffset.c: Changes to reflect the fact that TIFFFieldWithTag()
+ * tools/tiffset.c: Changes to reflect the fact that TIFFFieldWithTag()
and TIFFFieldWithName() now return TIFFField pointers instead of
TIFFFieldInfo pointers.
- * tools/tiffdump.c: Added ssize_t typedef on Windows since it doesn't
+ * tools/tiffdump.c: Added ssize_t typedef on Windows since it doesn't
exist. This makes it compile again on Windows
* tif_aux.c, tif_getimage.c, tif_next.c, tif_predict.c, tif_win32.c,
2007-12-31 Frank Warmerdam <warmerdam@pobox.com>
* tif_dirwrite.c: Added TIFFRewriteField(). This new function
- rewrites one field "on disk" updating an existing directory
+ rewrites one field "on disk" updating an existing directory
entry. Lots of limitations still...
- * tiffiop.h, tif_write.c, tif_dirread.c, tif_flush.c: Keep track of
- TIFF_DIRTYSTRIP separately from TIFF_DIRTYDIRECT to indicate that
- the strip offset/size values are dirty but nothing else about the
+ * tiffiop.h, tif_write.c, tif_dirread.c, tif_flush.c: Keep track of
+ TIFF_DIRTYSTRIP separately from TIFF_DIRTYDIRECT to indicate that
+ the strip offset/size values are dirty but nothing else about the
directory is dirty. In flush handle "just stripmaps dirty" as a
- special case that just rewrites these values without otherwise
- modifying the directory on disk using TIFFRewriteField().
+ special case that just rewrites these values without otherwise
+ modifying the directory on disk using TIFFRewriteField().
We also modify logic so that in update mode the directory is not
marked dirty on read, but only when something is changed. This
- means we need to keep track of updates to the stripmap stuff in
+ means we need to keep track of updates to the stripmap stuff in
TIFFAppendToStrip().
2007-12-10 Frank Warmerdam <warmerdam@pobox.com>
2007-11-23 Frank Warmerdam <warmerdam@pobox.com>
* tif_dir.c, tif_dirread.c, tif_dirwrite.c, tif_read.c, tif_write.c,
- tiffiop.h: Added TIFF_BUF4WRITE flag to indicate if contents of the
+ tiffiop.h: Added TIFF_BUF4WRITE flag to indicate if contents of the
rawcp/rawcc buffer are for writing and thus may require flushing.
Necessary to distinguish whether they need to be written to disk when
in mixed read/write mode and doing a mixture of writing followed by
2007-11-02 Frank Warmerdam <warmerdam@pobox.com>
- * tif_write.c: Rip out the fancy logic in TIFFAppendToStrip() for
- establishing if an existing tile can be rewritten to the same location
- by comparing the current size to all the other blocks in the same
- directory. This is dangerous in many situations and can easily
+ * tif_write.c: Rip out the fancy logic in TIFFAppendToStrip() for
+ establishing if an existing tile can be rewritten to the same location
+ by comparing the current size to all the other blocks in the same
+ directory. This is dangerous in many situations and can easily
corrupt a file. (observed in esoteric GDAL situation that's hard to
- document). This change involves leaving the stripbytecount[] values
+ document). This change involves leaving the stripbytecount[] values
unaltered till TIFFAppendToStrip(). Now we only write a block back
to the same location it used to be at if the new data is the same
size or smaller - otherwise we move it to the end of file.
* tif_dirwrite.c: Try to avoid writing out a full readbuffer of tile
data when writing the directory just because we have BEENWRITING at
some point in the past. This was causing odd junk to be written out
- in a tile of data when a single tile had an interleaving of reading
- and writing with reading last. (highlighted by gdal
- autotest/gcore/tif_write.py test 7.
+ in a tile of data when a single tile had an interleaving of reading
+ and writing with reading last. (highlighted by gdal
+ autotest/gcore/tif_write.py test 7.
* tif_predict.c: use working buffer in PredictorEncodeTile to avoid
- modifying callers buffer.
+ modifying callers buffer.
http://trac.osgeo.org/gdal/ticket/1965
- * tif_predict.c/h: more fixes related to last item, keeping a
+ * tif_predict.c/h: more fixes related to last item, keeping a
distinct pfunc for encode and decode cases as these were getting
mixed up sometimes.
http://trac.osgeo.org/gdal/ticket/1948
2007-11-01 Frank Warmerdam <warmerdam@pobox.com>
- * tif_predict.c/h, tif_lzw.c, tif_zip.c: Improvements so that
+ * tif_predict.c/h, tif_lzw.c, tif_zip.c: Improvements so that
predictor based encoding and decoding works in read-write update
- mode properly.
+ mode properly.
http://trac.osgeo.org/gdal/ticket/1948
2007-10-24 Joris Van Damme <joris.at.lebbeke@skynet.be>
- * tif_dirread.c: Fixed problem with bogus file triggering
- assert(td->td_planarconfig == PLANARCONFIG_CONTIG) in
+ * tif_dirread.c: Fixed problem with bogus file triggering
+ assert(td->td_planarconfig == PLANARCONFIG_CONTIG) in
ChopUpSingleUncompressedStrip
2007-10-22 Joris Van Damme <joris.at.lebbeke@skynet.be>
2007-09-29 Joris Van Damme <joris.at.lebbeke@skynet.be>
- * tif_dirread.c: Strip chopping interfered badly with uncompressed
- subsampled images because it tried to divide subsampled rowblocks,
- leading to all sorts of errors throughout the library for these
- images. Fixed by making strip chopping divide in row counts that
+ * tif_dirread.c: Strip chopping interfered badly with uncompressed
+ subsampled images because it tried to divide subsampled rowblocks,
+ leading to all sorts of errors throughout the library for these
+ images. Fixed by making strip chopping divide in row counts that
are a multiple of vertical subsampling value.
2007-09-28 Joris Van Damme <joris.at.lebbeke@skynet.be>
* tif_dirread.c: Made calculation of td_maxsamplevalue more robust
when dealing with large bitspersample values, shutting up purification
- tools that warn about truncation, though it remains incorrect and
+ tools that warn about truncation, though it remains incorrect and
indicates a conceptual problem there.
- * tif_open.c: Moved early exit in case of 'h' flag (to disable reading
- of first IFD) to proper place because it badly interfered with memory
- mapping, resulting in mapping flag even with dummy mapping functions
- that returned 0 whilst at the same time the mapping tif_size wasn't
+ * tif_open.c: Moved early exit in case of 'h' flag (to disable reading
+ of first IFD) to proper place because it badly interfered with memory
+ mapping, resulting in mapping flag even with dummy mapping functions
+ that returned 0 whilst at the same time the mapping tif_size wasn't
set, thus resulting in continuous incorrect beyond-eof errors.
2007-09-24 Joris Van Damme <joris.at.lebbeke@skynet.be>
- * tif_dirinfo.c: Fixed (MSVC) compiler reports about
+ * tif_dirinfo.c: Fixed (MSVC) compiler reports about
inconsistent use of const in tiffFields and exifFields definition
2007-09-20 Frank Warmerdam <warmerdam@pobox.com>
TIFFWriteDirectoryTagLongLong8Array() function was restructured
accordingly.
- * tif_dirread.c: Improvements to error reporting text in
+ * tif_dirread.c: Improvements to error reporting text in
TIFFFetchDirectory().
2007-09-19 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
2007-08-24 Frank Warmerdam <warmerdam@pobox.com>
* tif_dirwrite.c: Write the tif_nextdiroff value instead of a fixed
- zero when writing directory contents to preserve the ability to
+ zero when writing directory contents to preserve the ability to
rewrite directories in place, even in the middle of a directory
chain.
* tif_dirinfo.c: _TIFFMergeFields() now only merges in field
definitions that are missing. Existing definitions are silently
- ignored.
+ ignored.
* tif_dirread.c: Add runtime error for fields for which no definition
- is found (in addition to an assert for developers) in
- TIFFFetchNormalTag(). Not sure if this is needed, but it seems
+ is found (in addition to an assert for developers) in
+ TIFFFetchNormalTag(). Not sure if this is needed, but it seems
prudent.
2007-08-10 Joris Van Damme <joris.at.lebbeke@skynet.be>
- * libtiff/tif_getimage.c: removed SubsamplingHor and SubsamplingVer
+ * libtiff/tif_getimage.c: removed SubsamplingHor and SubsamplingVer
from _TIFFRGBAImage structure to revert unwanted ABI change.
2007-08-10 Joris Van Damme <joris.at.lebbeke@skynet.be>
- * libtiff/tif_win32.c: use SetFilePointer instead of
+ * libtiff/tif_win32.c: use SetFilePointer instead of
SetFilePointerEx, as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1580
* libtiff/tif_dirread.c: Handle the case of MSVC 6 when using 64-bit
integer constants.
- * libtiff/{Makefile.am, Makefile.v}: Do not distribute tiffconf.h,
+ * libtiff/{Makefile.am, Makefile.v}: Do not distribute tiffconf.h,
remove tif_config.h/tiffconf.h during cleaning. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1573
tif_win3.c}: Obsoleted portability stuff removed.
* tools/tiff2ps.c: Added support 16-bit images as per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=1566
Patch from William Bader.
* tools/tiff2pdf.c: Fix for TIFFTAG_JPEGTABLES tag fetching and
significant upgrade of the whole utility as per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=1560
Now we don't need tiffiop.h in tiff2pdf anymore and will open output
2007-06-25 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
* port/strtoull.c: New porting function in case strtoull() is not
- available on the target system.
+ available on the target system.
* configure.ac: Add configure support for determining sized types
in a portable way and performing necessary substitutions in
tif_config.h and tiffconf.h. Updated tiff.h to use the new
* libtiff/{tif_dir.h, tif_dirread.c, tif_dirinfo.c, tif_jpeg.c,
tif_fax3.c, tif_jbig.c, tif_luv.c, tif_ojpeg.c, tif_pixarlog.c,
tif_predict.c, tif_zip.c}: Finally fix bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=1274
by introducing _TIFFMergeFieldInfo() returning integer error status
2007-04-07 Frank Warmerdam <warmerdam@pobox.com>
- * contrib/addtiffo/tif_overview.c: Fix problems with odd sized output
+ * contrib/addtiffo/tif_overview.c: Fix problems with odd sized output
blocks in TIFF_DownSample_Subsampled() (bug 1542).
2007-04-06 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_jpeg.c: Changed JPEGInitializeLibJPEG() so that it
will convert from decompressor to compressor or compress to decompress
if required by the force arguments. This works around a problem in
- where the JPEGFixupTestSubsampling() may cause a decompressor to
+ where the JPEGFixupTestSubsampling() may cause a decompressor to
be setup on a directory when later a compressor is required with the
- force flag set. Occurs with the addtiffo program for instance.
+ force flag set. Occurs with the addtiffo program for instance.
2007-04-06 Andrey Kiselev <dron@ak4719.spb.edu>
* tools/tiffcrop.c, man/tiffcrop.1: Significant update in
functionality from Richard Nolde. As per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=1525
2007-03-28 Frank Warmerdam <warmerdam@pobox.com>
* start of BigTIFF upgrade - CVS HEAD unstable until further notice
2007-03-07 Joris Van Damme <joris.at.lebbeke@skynet.be>
-
+
* libtiff/tif_getimage.c: workaround for 'Fractional scanline' error reading
OJPEG images with rowsperstrip that is not a multiple of vertical subsampling
factor. This bug is mentioned in:
http://bugzilla.remotesensing.org/show_bug.cgi?id=1390
- http://www.asmail.be/msg0054766825.html
+ http://www.asmail.be/msg0054766825.html
2007-03-07 Joris Van Damme <joris.at.lebbeke@skynet.be>
-
+
* libtiff/tif_win32.c: made inclusion of windows.h unconditional
* libtiff/tif_win32.c: replaced preprocessor indication for consiously
larger than 2GB. Fixes bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=890
-
+
Idea submitted by Matt Hancher.
2007-01-31 Andrey Kiselev <dron@ak4719.spb.edu>
* tools/tif2rgba.c: This utility does not work properly on big-endian
architectures. It was fixed including the bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=1149
2007-01-15 Mateusz Loskot <mateusz@loskot.net>
2006-11-19 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_write.c: TIFFAppendToStrip() - clear sorted flag if
- we move a strip.
- http://bugzilla.remotesensing.org/show_bug.cgi?id=1359
+ * libtiff/tif_write.c: TIFFAppendToStrip() - clear sorted flag if
+ we move a strip.
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1359
2006-10-13 Andrey Kiselev <dron@ak4719.spb.edu>
* libtiff/tif_dir.c: More fixes for vulnerabilities, reported
in Gentoo bug ():
-
+
http://bugs.gentoo.org/show_bug.cgi?id=142383
* libtiff/contrib/dbs/xtiff/xtiff.c: Make xtiff utility compilable.
* libtiff/tif_lzw.c, libtiff/tif_zip.c: Fixed problems with mixing
encoding and decoding on the same read-write TIFF handle. The LZW
code can now maintain encode and decode state at the same time. The
- ZIP code will switch back and forth as needed.
+ ZIP code will switch back and forth as needed.
http://bugzilla.remotesensing.org/show_bug.cgi?id=757
2006-09-20 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff: Rename config.h.vc and tif_config.h.vc to config.vc.h and
+ * libtiff: Rename config.h.vc and tif_config.h.vc to config.vc.h and
tif_config.vc.h for easier identification by folks using an IDE.
2006-07-25 Frank Warmerdam <warmerdam@pobox.com>
2006-07-12 Frank Warmerdam <warmerdam@pobox.com>
- * tif_dirwrite.c: make sure to use uint32 for wordcount in
+ * tif_dirwrite.c: make sure to use uint32 for wordcount in
TIFFWriteNormanTag if writecount is VARIABLE2 for ASCII fields.
It already seems to have been done for other field types. Needed
for "tiffset" on files with geotiff ascii text.
2006-06-17 Frank Warmerdam <warmerdam@pobox.com>
* tif_readdir.c: Added case in EstimateStripByteCounts() for tiled
- files. Modified TIFFReadDirectory() to not invoke
+ files. Modified TIFFReadDirectory() to not invoke
EstimateStripByteCounts() for case where entry 0 and 1 are unequal
- but one of them is zero.
+ but one of them is zero.
http://bugzilla.remotesensing.org/show_bug.cgi?id=1204
2006-06-08 Andrey Kiselev <dron@ak4719.spb.edu>
* {configure, configure.ac, libtiff/tif_jbig.c, tools/tiffcp.c}: Added
support for JBIG compression scheme (34661 code) contributed by Lee
Howard. As per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=896
* configure, configure.ac: OJPEG support enabled by default.
2006-04-18 Frank Warmerdam <warmerdam@pobox.com>
* nmake.opt: use /EHsc for VS2005 compatibility. Also define
- _CRT_SECURE_NO_DEPRECATE to avoid noise on VS2005.
+ _CRT_SECURE_NO_DEPRECATE to avoid noise on VS2005.
2006-04-12 Joris Van Damme <joris.at.lebbeke@skynet.be>
non-subsampled YCbCr (i.e. separate YCbCr with subsampling [1,1])
2006-04-11 Joris Van Damme <joris.at.lebbeke@skynet.be>
-
+
* libtiff/tif_getimage.c: Revision of all RGB(A) put routines
- Conversion of unassociated alpha to associated alpha now done with
more performant LUT, and calculation more correct
- Bugfix of handling of 16bit RGB with unassociated alpha
2006-04-11 Joris Van Damme <joris.at.lebbeke@skynet.be>
-
- * libtiff/tif_getimage.c:
- - When there is no alpha, gtTileSeparate and gtStripSeparate allocated
- buffer for alpha strile and filled it, only to never read it back.
+
+ * libtiff/tif_getimage.c:
+ - When there is no alpha, gtTileSeparate and gtStripSeparate allocated
+ buffer for alpha strile and filled it, only to never read it back.
Removed allocation and fill.
- - Minor rename of vars in gtTileSeparate and gtStripSeparate
+ - Minor rename of vars in gtTileSeparate and gtStripSeparate
anticipating planned functionality extension
2006-04-08 Joris Van Damme <joris.at.lebbeke@skynet.be>
- * libtiff/tif_getimage.c: renamed pickTileContigCase to PickContigCase
- and pickTileSeparateCase to PickSeparateCase as both work on strips as
+ * libtiff/tif_getimage.c: renamed pickTileContigCase to PickContigCase
+ and pickTileSeparateCase to PickSeparateCase as both work on strips as
well
- * libtiff/tif_getimage.c: moved img->get selection from
+ * libtiff/tif_getimage.c: moved img->get selection from
TIFFRGBAImageBegin into PickContigCase and PickSeparateCase to create
logical hook for planned functionality extension
2006-04-07 Joris Van Damme <joris.at.lebbeke@skynet.be>
- * libtiff/tif_getimage.c: replaced usage of TIFFScanlineSize in
+ * libtiff/tif_getimage.c: replaced usage of TIFFScanlineSize in
gtStripContig with TIFFNewScanlineSize so as to fix buggy behaviour
- on subsampled images - this ought to get sorted when we feel brave
- enough to replace TIFFScanlineSize alltogether
+ on subsampled images - this ought to get sorted when we feel brave
+ enough to replace TIFFScanlineSize altogether
* libtiff/tif_ojpeg.c: fixed bug in OJPEGReadSkip
* libtiff/tiffio.h: added new type tstrile_t
- * libtiff/tif_dir.h: changed types of td_stripsperimage and td_nstrips
- to new tstrile_t, types of td_stripoffset and td_stripbytecount to
+ * libtiff/tif_dir.h: changed types of td_stripsperimage and td_nstrips
+ to new tstrile_t, types of td_stripoffset and td_stripbytecount to
toff_t*
* libtiff/tif_ojpeg.c: totally new implementation
- * libtiff/tif_dirread.c: added several hacks to suit new support of
+ * libtiff/tif_dirread.c: added several hacks to suit new support of
OJPEG
* libtiff/tif_getimage.c: removed TIFFTAG_JPEGCOLORMODE handling
* libtiff/tif_getimage.c: added putcontig8bitYCbCr12tile
- * libtiff/tif_read.c: added support for new TIFF_NOREADRAW flag to
+ * libtiff/tif_read.c: added support for new TIFF_NOREADRAW flag to
prepare the path for new tif_ojpeg.c
2006-03-23 Andrey Kiselev <dron@ak4719.spb.edu>
* libtiff/tif_write.c: Small code rearrangement in TIFFWriteScanline()
to avoid crash as per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=1081.
2006-02-26 Andrey Kiselev <dron@ak4719.spb.edu>
2006-02-07 Frank Warmerdam <warmerdam@pobox.com>
* tools/tiff2pdf.c: Fixed support for non-YCbCr encoded JPEG
- compressed TIFF files, per submission from Dan Cobra.
+ compressed TIFF files, per submission from Dan Cobra.
2006-02-07 Andrey Kiselev <dron@ak4719.spb.edu>
* libtiff/tif_dirread.c: Use _TIFFGetExifFieldInfo() instead of
_TIFFGetFieldInfo() in TIFFReadEXIFDirectory() call as per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=1026.
2006-01-23 Andrey Kiselev <dron@ak4719.spb.edu>
2005-12-26 Andrey Kiselev <dron@ak4719.spb.edu>
- * libtiff/{tif_dir.c, tif_dir.h, tif_dirread.c, tif_dirinfo.c}:
+ * libtiff/{tif_dir.c, tif_dir.h, tif_dirread.c, tif_dirinfo.c}:
tiffFieldInfo and exifFieldInfo arrays definitions moved back to
tif_dirinfo.c; added _TIFFGetFieldInfo() and _TIFFGetExifFieldInfo()
private functions to retrieve FieldInfo arrays.
2005-12-23 Joris Van Damme <joris.at.lebbeke@skynet.be>
- * libtiff/tiffio.h: fixed typo that potentially resulted in
+ * libtiff/tiffio.h: fixed typo that potentially resulted in
redefininition of USE_WIN32_FILEIO
- * libtiff/*: Added more 'dual-mode' error handling: Done TIFFWarning
+ * libtiff/*: Added more 'dual-mode' error handling: Done TIFFWarning
calls in core LibTiff.
2005-12-21 Andrey Kiselev <dron@ak4719.spb.edu>
2005-12-21 Joris Van Damme <joris.at.lebbeke@skynet.be>
- * libtiff/*, contrib/*: Added 'dual-mode' error handling, enabling
+ * libtiff/*, contrib/*: Added 'dual-mode' error handling, enabling
newer code to get context indicator in error handler and still
- remain compatible with older code: Done TIFFError calls everywhere
- except in tools
+ remain compatible with older code: Done TIFFError calls everywhere
+ except in tools
2005-12-20 Andrey Kiselev <dron@ak4719.spb.edu>
http://bugzilla.remotesensing.org/show_bug.cgi?id=1002
* .cvsignore: many files added, and a few update according
- to suggestion of Brad HArds on tiff mailing list.
+ to suggestion of Brad HArds on tiff mailing list.
2005-11-03 Frank Warmerdam <warmerdam@pobox.com>
http://bugzilla.remotesensing.org/show_bug.cgi?id=946
* tools/bmp2tiff.c: Fixed possible integer overflow error as per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=965
* libtiff/tif_dirinfo.c: Make XResolution, YResolution and
* tools/tiffsplit.c: Copy fax related fields over splitted parts
as per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=983
2005-10-21 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_dir.c: When prefreeing tv->value in TIFFSetFieldV
also set it to NULL to avoid double free when re-setting custom
- string fields as per:
+ string fields as per:
http://bugzilla.remotesensing.org/show_bug.cgi?id=922
http://bugzilla.remotesensing.org/show_bug.cgi?id=831
Remove TIFFFetchExtraSamples() function, use TIFFFetchNormalTag()
- instead.
+ instead.
* libtiff/tiffconf.h.in: One more attempt to fix the AIX bug
2005-06-03 Andrey Kiselev <dron@ak4719.spb.edu>
- * libtiff/tif_open.c: Replace runtime endianess check with the compile
+ * libtiff/tif_open.c: Replace runtime endianness check with the compile
time one.
* libtiff/tif_predict.c: Floating point predictor now works on
2005-05-22 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_dirread.c: Changed the code that computes
+ * libtiff/tif_dirread.c: Changed the code that computes
stripbytecount[0] if it appears bogus to ignore if stripoffset[0] is
zero. This is a common case with GDAL indicating a "null" tile/strip.
2005-05-06 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_dirread.c: Applied similar change to
- TIFFFetchPerSampleLongs and TIFFFetchPerSampleAnys.
+ * libtiff/tif_dirread.c: Applied similar change to
+ TIFFFetchPerSampleLongs and TIFFFetchPerSampleAnys.
http://bugzilla.remotesensing.org/show_bug.cgi?id=843
* man/TIFFSetField.3tiff: Fixed definition of the TIFFTAG_INKNAMES tag
as per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=816
2005-03-30 Andrey Kiselev <dron@ak4719.spb.edu>
* libtiff/tiffio.h: Move TIFFOpenW() function into the extern "C"{}
block as per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=763
2005-02-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
http://bugzilla.remotesensing.org/show_bug.cgi?id=320
* tools/tiff2ps.c: Fixed problem with page sizes as per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=742
2005-01-31 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
TIFFRGBAImageBegin() as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=739
-
+
2005-01-12 Andrey Kiselev <dron@ak4719.spb.edu>
* libtiff/tif_jpeg.c: Added ability to read/write the fax specific
* libtiff/tiff.h: Restore back the workaround for AIX Visual Age C
compiler to avoid double definition of BSD types as per bug
- http://bugzilla.remotesensing.org/show_bug.cgi?id=39
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=39
* libtiff/Makefile.am: Place the C++ stream API in the separate
library called libtiffxx to avoid unneeded dependencies. Probably
* libtiff/tif_getimage.c: More fixes for multiple-alpha-channelled
RGB-images as per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=713
2004-12-15 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_getimage.c: #define A1 bracketing for clean build on
- SunPro compiler.
+ SunPro compiler.
2004-12-11 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
* libtiff/tif_dirwrite.c: Always write TIFFTAG_SUBIFD using LONG type
as per bugs
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=703
and
* libtiff/tif_config.in.vc: Removed unneded definitions for
read/open/close/lseek functions to fix the
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=680
-
+
2004-12-03 Andrey Kiselev <dron@ak4719.spb.edu>
* libtiff/{tif_dir.c, tif_dirread.c}: Remove TIFFReassignTagToIgnore()
2004-11-26 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/makefile.vc: make it easier to rename the libtiff DLL.
+ * libtiff/makefile.vc: make it easier to rename the libtiff DLL.
2004-11-24 Andrey Kiselev <dron@ak4719.spb.edu>
per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=648
-
+
* libtiff/{tif_jpeg.c, tif_ojpeg.c}: TIFFTAG_JPEGTABLES should have
uint32 count. Use this type everywhere.
* tools/tiff2rgba.c: removed extra newlines in usage message.
2004-10-30 Andrey Kiselev <dron@ak4719.spb.edu>
-
+
* libtiff/tif_dirwrite.c: Improvements in tag writing code.
* tools/tiff2ps.c: Fixed wrong variable data type when read Position
* libtiff/tif_fax3.c: Fixed case with the wrong decode routines
choosing when the incorrect Group4Options tag set. As per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=323
* libtiff/tif_dirwrite.c: Fixed problem with passing count variable of
* tools/tiff2pdf.c: added casts to avoid warnings.
* libtiff/libtiff.def: Added several more entry points required
- to link fax2tiff.c against the DLL on windows.
+ to link fax2tiff.c against the DLL on windows.
2004-10-27 Andrey Kiselev <dron@ak4719.spb.edu>
2004-10-08 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_dirinfo.c: Fix bug with tif_foundfield and reallocation
- of tif_fieldinfo.
+ of tif_fieldinfo.
http://bugzilla.remotesensing.org/show_bug.cgi?id=630
2004-09-30 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_dirinfo.c: changed type of XMLPacket (tag 700) to
+ * libtiff/tif_dirinfo.c: changed type of XMLPacket (tag 700) to
TIFFTAG_BYTE instead of TIFFTAG_UNDEFINED to comply with the info
in the Adobe XMP Specification.
2004-09-26 Andrey Kiselev <dron@ak4719.spb.edu>
* libtiff/{tif_dir.h, tif_dir.c, tif_dirread.c, tif_write.c}:
- Optimize checking for the strip bounds.
+ Optimize checking for the strip bounds.
* libtiff/{tif_dirread.c, tif_strip.c}: TIFFScanlineSize() and
TIFFRasterScanlineSize() functions report zero in the case of integer
here
http://www.asmail.be/msg0054799560.html
-
+
for details.
* tools/fax2tiff.c: Use the new functions in the code.
* tools/tiffsplit.c: Fixed problem with unproperly written multibyte
files. Now output files will be written using the same byte order
flag as in the input image. See
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=574
-
+
for details.
-
+
2004-05-19 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_print.c: added (untested) support for printing
* libtiff/tif_fax3.c: Avoid reading CCITT compression options
if compression type mismatches. See
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=565
2004-04-30 Andrey Kiselev <dron@ak4719.spb.edu>
2004-04-04 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_open.c: close clientdata if TIFFClientOpen() fails
- via bad2.
+ via bad2.
2004-03-26 Andrey Kiselev <dron@ak4719.spb.edu>
2004-02-26 Andrey Kiselev <dron@ak4719.spb.edu>
- * tools/tiffsplit.c: Copy JPEGTables tag contents for JPEG compressed
+ * tools/tiffsplit.c: Copy JPEGTables tag contents for JPEG compressed
images. Reported by Artem Mirolubov.
- * libtiff/tif_dirread.c: Fixed problem with handling TIFF_UNDEFINED
+ * libtiff/tif_dirread.c: Fixed problem with handling TIFF_UNDEFINED
tag type in TIFFFetchNormalTag() as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=508
2004-01-30 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/libtiff.def: Added TIFFCurrentDirOffset, TIFFWriteCheck,
- TIFFRGBAImageOK, and TIFFNumberOfDirectories as suggested by
- Scott Reynolds.
+ TIFFRGBAImageOK, and TIFFNumberOfDirectories as suggested by
+ Scott Reynolds.
2004-01-29 Andrey Kiselev <dron@ak4719.spb.edu>
file if TIFFFdOpen() failed as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=468
-
+
* libtiff/tif_open.c: More fixes for
http://bugzilla.remotesensing.org/show_bug.cgi?id=468
* libtiff/tif_dirwrite.c: Fixed handling of writable ASCII tags that
are field_passcount=TRUE properly. Arguably anonymous custom tags
should be declared as passcount=FALSE, but I don't want to change
- that without a careful review.
+ that without a careful review.
2004-01-20 Andrey Kiselev <dron@ak4719.spb.edu>
2003-11-17 Frank Warmerdam <warmerdam@pobox.com>
- * tif_dirread.c: do not mark all anonymously defined tags to be
- IGNOREd.
+ * tif_dirread.c: do not mark all anonymously defined tags to be
+ IGNOREd.
2003-11-17 Andrey Kiselev <dron@ak4719.spb.edu>
2003-11-16 Andrey Kiselev <dron@ak4719.spb.edu>
* libtiff/{tiff.h, tif_dirinfo.c}: Added support for IFD (13)
- datatype, intruduced in "Adobe PageMaker TIFF Tech. Notes".
+ datatype, introduced in "Adobe PageMaker TIFF Tech. Notes".
2003-11-15 Frank Warmerdam <warmerdam@pobox.com>
2003-11-09 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_tile.c: remove spurious use of "s" (sample) in the
+ * libtiff/tif_tile.c: remove spurious use of "s" (sample) in the
planarconfig_contig case in TIFFComputeTile().
http://bugzilla.remotesensing.org/show_bug.cgi?id=387
2003-11-09 Andrey Kiselev <dron@ak4719.spb.edu>
-
+
* libtiff/tiffiop.h: New macros: TIFFmax, TIFFmin and TIFFrint.
-
+
2003-11-07 Andrey Kiselev <dron@ak4719.spb.edu>
* libtiff/{tiffio.h, tif_strip.c}, man/{TIFFstrip.3t, libtiff.3t}:
function TIFFReadRGBAImageOriented() implemented to retrieve raster
array with user-specified origin position as suggested by Jason Frank.
See
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=322
for details.
-
+
* tools/tiff2rgba.c: Switched to use TIFFReadRGBAImageOriented()
instead of TIFFReadRGBAImage().
encoded write functions use tif_postdecode() to apply byte order
swapping (swab) to the application passed data buffer if the same
would be done when reading. This allows us to write pixel data with
- more than 8 bits per sample to existing files of a non-native byte
+ more than 8 bits per sample to existing files of a non-native byte
order. One side effect of this change is the applications buffer
- itself is altered in this case by the act of writing.
+ itself is altered in this case by the act of writing.
http://bugzilla.remotesensing.org/show_bug.cgi?id=171
2003-07-08 Frank Warmerdam <warmerdam@pobox.com>
* tif_aux.c, tif_codec.c, tif_dir.c, tif_dirread.c, tif_extension.c,
- tif_fax3.c, tif_getimage.c, tif_luv.c, tif_lzw.c, tif_next.c,
+ tif_fax3.c, tif_getimage.c, tif_luv.c, tif_lzw.c, tif_next.c,
tif_packbits.c, tif_predict.c, tif_print.c, tif_swab.c, tif_thunder.c:
- avoid casting warning at /W4.
+ avoid casting warning at /W4.
2003-07-03 Andrey Kiselev <dron@ak4719.spb.edu>
* libtiff/tif_dirinfo.c: TIFFDataWidth() returns 0 in case of
unknown data type.
-
+
2003-06-19 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_print.c: fixed some serious bugs when printing
- custom tags ... almost certain to crash.
+ custom tags ... almost certain to crash.
* libtiff/tif_dirread.c: Don't ignore custom fields that are
autodefined. Not sure how this got to be like this.
* tools/tiffcmp.c, man/tiffcmp.1: Fixed problem with unused data
comparing as per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=349
`-z' option now can be used to set the number of reported different
bytes.
-
+
2003-06-09 Andrey Kiselev <dron@ak4719.spb.edu>
* tools/tiffcp.c, man/tiffcp.1: Added possibility to specify value -1
2003-05-25 Andrey Kiselev <dron@ak4719.spb.edu>
* tools/fax2tiff.c: Page numbering fixed, as per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=341
2003-05-20 Andrey Kiselev <dron@ak4719.spb.edu>
* contrib/ojpeg/{Makefile.in, jdhuff.h, jinclude.h, ojpeg.c, README},
configure, Makefile.in: Improved libtiff compilation with OJPEG
- support. Now no need for patching IJG JPEG library, hack requred by
+ support. Now no need for patching IJG JPEG library, hack required by
libtiff will be compiled and used in-place. Implemented with
suggestion and help from Bill Allombert, Debian's libjpeg maintainer.
* tools/tiffcp.c: Fixed problem with colorspace conversion for JPEG
encoded images. See bug entries
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=275
and
* libtiff/tif_jpeg.c: Modified to defer initialization of jpeg
library so that we can check if there is already any tile/strip data
- before deciding between creating a compressor or a decompressor.
+ before deciding between creating a compressor or a decompressor.
2003-01-31 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_write.c: TIFFWriteCheck() now fails if the image is
- a pre-existing compressed image. That is, image writing to
+ a pre-existing compressed image. That is, image writing to
pre-existing compressed images is not allowed.
* libtiff/tif_open.c: Removed error if opening a compressed file
- in update mode.
+ in update mode.
http://bugzilla.remotesensing.org/show_bug.cgi?id=198
* cut 3.6.0 Beta release.
2002-12-20 Andrey Kiselev <dron@ak4719.spb.edu>
-
+
* tools/fax2ps.c, man/fax2ps.1: Page size was determined
in wrong way as per bug
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=239
2002-12-17 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_dirread.c: Allow wrong sized arrays in
- TIFFFetchStripThing().
+ * libtiff/tif_dirread.c: Allow wrong sized arrays in
+ TIFFFetchStripThing().
http://bugzilla.remotesensing.org/show_bug.cgi?id=49
* libtiff/tif_dir.c: fixed bug with resetting an existing custom
field value.
- * libtiff/tif_dir.c: Fixed potential problem with ascii "custom"
+ * libtiff/tif_dir.c: Fixed potential problem with ascii "custom"
tags in TIFFVGetField() ... added missing break.
2002-10-14 Frank Warmerdam <warmerdam@pobox.com>
the eps by redefining the colorimage operator will get messed up.
Patch supplied by William Bader.
- * Makefile.in: added tif_extension.c to file list as per
+ * Makefile.in: added tif_extension.c to file list as per
http://bugzilla.remotesensing.org/show_bug.cgi?id=218.
2002-10-11 Andrey Kiselev <dron@ak4719.spb.edu>
-
+
* configure, config.site, libtiff/{tif_unix.c, Makefile.in}: Fix for
large files (>2GiB) supporting. New option in the config.site:
LARGEFILE="yes". Should be enough for I/O of the large files.
2002-10-06 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_jpeg.c: fixed problem with boolean defined with wrong
- size on windows. Use #define boolean hack.
+ size on windows. Use #define boolean hack.
http://bugzilla.remotesensing.org/show_bug.cgi?id=188
* libtiff/tiff.h: Don't do special type handling in tiff.h unless
USING_VISUALAGE is defined.
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=39
2002-10-03 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_dirread.c: Another fix for the fetching SBYTE arrays
by the TIFFFetchByteArray() function. Should finally resolve
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=52
-
+
* configure: Set -DPIXARLOG_SUPPORT option along with -DZIP_SUPPORT
* html/Makefile.in: New targets added: html and groffhtml for
producing HTML representations of the manual pages automatically.
html target uses man2html tool, groffhtml uses groff tool.
-
+
2002-09-29 Frank Warmerdam <warmerdam@pobox.com>
* configure, libtiff/Makefile.in: Added SCO OpenServer 5.0.6 support
- from John H. DuBois III.
+ from John H. DuBois III.
2002-09-15 Andrey Kiselev <dron@ak4719.spb.edu>
* Makefile.in, /man/{raw2tiff.1, Makefile.in, libtiff.3}: Added
manual page for raw2tiff(1) tool.
-
+
2002-09-12 Andrey Kiselev <dron@ak4719.spb.edu>
* /libtiff/{tiffio.h, tif_dir.h}: TIFFDataWidth() declaration moved to
the tiffio.h header file.
-
+
* Makefile.in, /man/{TIFFDataWidth.3t, Makefile.in, libtiff.3}: Added
manual page for TIFFDataWidth() function
as per http://bugzilla.remotesensing.org/show_bug.cgi?id=196.
* tools/tiff2ps.c: Don't emit BeginData/EndData DSC comments
- since we are unable to properly include the amount to skip.
-
+ since we are unable to properly include the amount to skip.
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=80
2002-09-02 Andrey Kiselev <dron@ak4719.spb.edu>
http://bugzilla.remotesensing.org/show_bug.cgi?id=52
2002-08-22 Andrey Kiselev <dron@ak4719.spb.edu>
-
+
* /libtiff/tif_dirinfo.c: Further additions to free custom fields
in _TIFFSetupFieldInfo() function.
See http://bugzilla.remotesensing.org/show_bug.cgi?id=169 for details.
LZWDecode() and LZWDecodeCompat().
Fixes http://bugzilla.remotesensing.org/show_bug.cgi?id=190
and http://bugzilla.remotesensing.org/show_bug.cgi?id=100
-
+
* /libtiff/tif_lzw.c:
Added check for valid code lengths in LZWDecode() and
LZWDecodeCompat(). Fixes
http://bugzilla.remotesensing.org/show_bug.cgi?id=115
2002-08-16 Andrey Kiselev <dron@ak4719.spb.edu>
-
+
* /libtiff/{Makefile.vc, libtiff.def}:
Missed declarations added.
http://bugzilla.remotesensing.org/show_bug.cgi?id=177
- * tif_dir.h: changed FIELD_CODEC to 66 from 64 to avoid overlap
+ * tif_dir.h: changed FIELD_CODEC to 66 from 64 to avoid overlap
with FIELD_CUSTOM as mentioned in bug 169.
* tif_close.c: added logic to free dynamically created anonymous
http://bugzilla.remotesensing.org/show_bug.cgi?id=169
2002-08-10 Andrey Kiselev <dron@ak4719.spb.edu>
-
+
* /tools/{raw2tiff.c, Makefile.in, Makefile.lcc, Makefile.vc}:
New tool: raw2tiff --- raw images to TIFF converter. No manual page yet.
2002-07-31 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_jpeg.c: Fixed problem with setting of nrows in
+ * libtiff/tif_jpeg.c: Fixed problem with setting of nrows in
JPEGDecode() as per bugzilla bug (issue 1):
http://bugzilla.remotesensing.org/show_bug.cgi?id=129
* libtiff/{tif_jpeg.c,tif_strip.c,tif_print.c}: Hacked tif_jpeg.c to
fetch TIFFTAG_YCBCRSUBSAMPLING from the jpeg data stream if it isn't
- present in the tiff tags.
+ present in the tiff tags.
http://bugzilla.remotesensing.org/show_bug.cgi?id=168
* libtiff/tif_read.c, libtiff/tif_write.c: TIFFReadScanline() and
TIFFWriteScanline() now set tif_row explicitly in case the codec has
- fooled with the value.
+ fooled with the value.
http://bugzilla.remotesensing.org/show_bug.cgi?id=129
2002-06-22 Andrey Kiselev <dron@ak4719.spb.edu>
-
+
* /tools/tiff2ps.c: Added workaround for some software that may crash
when last strip of image contains fewer number of scanlines than
specified by the `/Height' variable. See
2002-06-11 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/contrib/win95: renamed to contrib/win_dib. Added new
- Tiffile.cpp example of converting TIFF files into a DIB on Win32.
+ * libtiff/contrib/win95: renamed to contrib/win_dib. Added new
+ Tiffile.cpp example of converting TIFF files into a DIB on Win32.
This one is described in:
http://bugzilla.remotesensing.org/show_bug.cgi?id=143
http://bugzilla.remotesensing.org/show_bug.cgi?id=131
2002-04-26 Andrey Kiselev <dron@ak4719.spb.edu>
-
+
* libtiff/libtiff.def: Added missed declaration.
-
+
2002-04-22 Andrey Kiselev <dron@ak4719.spb.edu>
-
+
* tools/fax2tiff.c: Updated to reflect latest changes in libtiff.
Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=125
2002-04-20 Andrey Kiselev <dron@ak4719.spb.edu>
-
+
* libtiff/tif_open.c: Pointers to custom procedures
in TIFFClientOpen() are checked to be not NULL-pointers.
-
+
2002-04-18 Andrey Kiselev <dron@ak4719.spb.edu>
-
+
* libtiff/libtiff.def: Added missed declarations.
* libtiff/tif_pixarlog.c: Updated for using tif_tagmethods structure.
* libtiff/tif_lzw.c: Additional checks for data integrity introduced.
Should finally close
http://bugzilla.remotesensing.org/show_bug.cgi?id=100
-
+
2002-04-10 Andrey Kiselev <dron@ak4719.spb.edu>
* tools/tiff2ps: Division by zero fixed.
Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=88
2002-04-09 Andrey Kiselev <dron@ak4719.spb.edu>
-
+
* libtiff/: tif_dirwrite.c, tif_write.c, tiffio.h:
TIFFCheckpointDirectory() routine added.
Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=124
replaced by warnings. Now libtiff should read corrupted LZW-compressed
files by skipping bad strips.
Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=100
-
+
2002-04-03 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_dirwrite.c: Removed some dead code.
http://bugzilla.remotesensing.org/show_bug.cgi?id=111
- * tif_print.c: Fixed so that ASCII FIELD_CUSTOM values with
+ * tif_print.c: Fixed so that ASCII FIELD_CUSTOM values with
passcount set FALSE can be printed (such as TIFFTAG_SOFTWARE).
- * libtiff/tif_dir.c,tif_dirinfo.c,tif_dir.h,tif_ojpeg.c: modified so
+ * libtiff/tif_dir.c,tif_dirinfo.c,tif_dir.h,tif_ojpeg.c: modified so
that TIFFTAG_SOFTWARE uses FIELD_CUSTOM as an example.
2002-03-26 Dwight Kelly <dbmalloc@remotesensing.org>
* libtiff/: tiff.h, tif_dir.c, tif_dir.h, tif_dirinfo.c, tif_dirread.c,
tif_dirwrite.c: Added get/put code for new tag XMLPACKET as defined
- in Adobe XMP Technote. Added missing INKSET tag value from TIFF 6.0 spec
- INKSET_MULTIINK (=2). Added missing tags from Adobe TIFF technotes:
+ in Adobe XMP Technote. Added missing INKSET tag value from TIFF 6.0 spec
+ INKSET_MULTIINK (=2). Added missing tags from Adobe TIFF technotes:
CLIPPATH, XCLIPPATHUNITS, YCLIPPATHUNITS, OPIIMAGEID, OPIPROXY and
INDEXED. Added PHOTOMETRIC tag value from TIFF technote 4 ICCLAB (=9).
http://bugzilla.remotesensing.org/show_bug.cgi?id=94
- * man/Makefile.in: Patch DESTDIR handling
+ * man/Makefile.in: Patch DESTDIR handling
http://bugzilla.remotesensing.org/show_bug.cgi?id=95
2002-01-04 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_jpeg.c: fixed computation of segment_width for
- tiles files to avoid error about it not matching the
- cinfo.d.image_width values ("JPEGPreDecode: Improper JPEG strip/tile
+ * libtiff/tif_jpeg.c: fixed computation of segment_width for
+ tiles files to avoid error about it not matching the
+ cinfo.d.image_width values ("JPEGPreDecode: Improper JPEG strip/tile
size.") for ITIFF files. Apparently the problem was incorporated since
3.5.5, presumably during the OJPEG/JPEG work recently.
http://bugzilla.remotesensing.org/show_bug.cgi?id=94
- * libtiff/tif_getimage.c: If DEFAULT_EXTRASAMPLE_AS_ALPHA is 1
+ * libtiff/tif_getimage.c: If DEFAULT_EXTRASAMPLE_AS_ALPHA is 1
(defined in tiffconf.h - 1 by default) then the RGBA interface
will assume that a fourth extra sample is ASSOCALPHA if the
EXTRASAMPLE value isn't set for it. This changes the behaviour of
2001-12-12 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_jpeg.c: allow jpeg data stream sampling values to
- override those from tiff directory. This makes this work with
- ImageGear generated files.
+ * libtiff/tif_jpeg.c: allow jpeg data stream sampling values to
+ override those from tiff directory. This makes this work with
+ ImageGear generated files.
2001-12-07 Frank Warmerdam <warmerdam@pobox.com>
* Reissue 3.5.7 release.
* libtiff/mkversion.c: Fix output of TIFF_VERSION to be
- YYYYMMDD so that it is increasing over time.
+ YYYYMMDD so that it is increasing over time.
* Makefile.in: Ensure that tiffvers.h is regenerated in the
make release target.
2001-10-10 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tiff.h: I have created COMPRESSION_CCITT_T4,
- COMPRESSION_CCITT_T6, TIFFTAG_T4OPTIONS and TIFFTAG_T6OPTIONS aliases
+ * libtiff/tiff.h: I have created COMPRESSION_CCITT_T4,
+ COMPRESSION_CCITT_T6, TIFFTAG_T4OPTIONS and TIFFTAG_T6OPTIONS aliases
in keeping with TIFF 6.0 standard in tiff.h
http://bugzilla.remotesensing.org/show_bug.cgi?id=83
error about LZW not being available.
* libtiff/tif_dir.c: propagate failure to initialize compression
- back from TIFFSetField() as an error status, so applications can
+ back from TIFFSetField() as an error status, so applications can
detect failure.
- * libtiff/tif_dir.c: removed the auto replacement of
+ * libtiff/tif_dir.c: removed the auto replacement of
COMPRESSION_LZW with COMPRESSION_NONE in _TIFFVSetField().
* Removed Makefile, tools/Makefile, port/install.sh, man/Makefile
2001-09-22 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_ojpeg.c: new update from Scott.
+ * libtiff/tif_ojpeg.c: new update from Scott.
2001-09-09 Frank Warmerdam <warmerdam@pobox.com>
http://bugzilla.remotesensing.org/show_bug.cgi?id=47
- * tools/tiff2ps.c: added OJPEG YCbCr to RGB support.
+ * tools/tiff2ps.c: added OJPEG YCbCr to RGB support.
* libtiff/tif_ojpeg.c: Applied substantial patch from Scott.
* libtiff/tif_packbits.c: fixed memory overrun error.
http://bugzilla.remotesensing.org/show_bug.cgi?id=77
-
+
2001-08-31 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_getimage.c: relax handling of contig case where
there are extra samples that are supposed to be ignored. This
- should now work for 8bit greyscale or palletted images.
+ should now work for 8bit greyscale or palletted images.
- http://bugzilla.remotesensing.org/show_bug.cgi?id=75
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=75
2001-08-28 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_getimage.c: Use memmove() instead of TIFFmemcpy()
in TIFFReadRGBATile() to avoid issues in cases of overlapping
- buffers. See Bug 69 in Bugzilla.
+ buffers. See Bug 69 in Bugzilla.
http://bugzilla.remotesensing.org/show_bug.cgi?id=69
-
+
* tools/tiff2rgba.c: fixed getopt() call so that -b works again.
2001-08-09 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tiff.h, libtiff/tif_fax3.c: added check for __LP64__
+ * libtiff/tiff.h, libtiff/tif_fax3.c: added check for __LP64__
when checking for 64 bit architectures as per bugzilla bug 67.
2001-07-27 Frank Warmerdam <warmerdam@pobox.com>
2001-07-20 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_jpeg.c: Define HAVE_BOOLEAN on windows if RPCNDR.H
+ * libtiff/tif_jpeg.c: Define HAVE_BOOLEAN on windows if RPCNDR.H
has been included.
2001-07-19 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_ojpeg.c: updates from Scott. Handles colors
much better. Now depends on having patched libjpeg as per
- patch in contrib/ojpeg/*.
+ patch in contrib/ojpeg/*.
2001-07-17 Frank Warmerdam <warmerdam@pobox.com>
- * */Makefile.in: added DESTDIR support.
+ * */Makefile.in: added DESTDIR support.
http://bugzilla.remotesensing.org/show_bug.cgi?id=60
* configure, libtiff/Makefile.in: applied OpenBSD patches
as per:
-
+
http://bugzilla.remotesensing.org/show_bug.cgi?id=61
2001-06-28 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/tif_getimage.c: Fixed so that failure is properly
- reported by gtTileContig, gtStripContig, gtTileSeparate and
+ reported by gtTileContig, gtStripContig, gtTileSeparate and
gtStripSeparate.
See http://bugzilla.remotesensing.org/show_bug.cgi?id=51
- * tiffcmp.c: Fixed multi samples per pixel support for ContigCompare.
+ * tiffcmp.c: Fixed multi samples per pixel support for ContigCompare.
Updated bug section of tiffcmp.1 to note tiled file issues.
-
+
See http://bugzilla.remotesensing.org/show_bug.cgi?id=53
2001-06-22 Frank Warmerdam <warmerdam@pobox.com>
2001-05-08 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tif_dirinfo.c: moved pixar and copyright flags to
+ * libtiff/tif_dirinfo.c: moved pixar and copyright flags to
ensure everything is in order.
- * libtiff/libtiff.def: added TIFFCreateDirectory and
+ * libtiff/libtiff.def: added TIFFCreateDirectory and
TIFFDefaultStripSize as per:
http://bugzilla.remotesensing.org/show_bug.cgi?id=46
* libtiff/tif_dirinfo.c: Modified the TIFF_BYTE definition for
TIFFTAG_PHOTOSHOP to use a writecount of TIFF_VARIABLE2 (-3) to
- force use of uint32 counts instead of short counts.
+ force use of uint32 counts instead of short counts.
* libtiff/tif_dirwrite.c: Added support for TIFF_VARIABLE2 in the
- case of writing TIFF_BYTE/TIFF_SBYTE fields.
+ case of writing TIFF_BYTE/TIFF_SBYTE fields.
http://bugzilla.remotesensing.org/show_bug.cgi?id=43
with the inttypes.h include file on AIX.
See http://bugzilla.remotesensing.org/show_bug.cgi?id=39
-
+
* VERSION: update to 3.5.7 beta in preparation for release.
* configure/config.site: modified to check if -lm is needed for
MACHDEPLIBS if not supplied by config.site. Needed for Darwin.
- * config.guess: updated wholesale to an FSF version apparently
- from 1998 (as opposed to 1994). This is mainly inspired by
+ * config.guess: updated wholesale to an FSF version apparently
+ from 1998 (as opposed to 1994). This is mainly inspired by
providing for MacOS X support.
2001-03-29 Frank Warmerdam <warmerdam@pobox.com>
* configure, Makefile.in, etc: added support for OPTIMIZER being
- set from config.site.
+ set from config.site.
2001-03-28 Frank Warmerdam <warmerdam@pobox.com>
sizes. It fixes two problems:
Without scaling (-S) the fax is now centered on the page size specified
- with -H and/or -W. Before, fax2ps was using an obscure and practially
+ with -H and/or -W. Before, fax2ps was using an obscure and practically
useless algorithm to allocate the image relative to Letter sized paper
which sometime sled to useless whitespace on the paper, while at the
same time cutting of the faxes printable area at the opposite border.
(in particular short ones) print properly.
See http://bugzilla.remotesensing.org/show_bug.cgi?id=35
-
+
* tiff2ps.c/tiff2ps.1: Substantial changes to tiff2ps by
Bruce A. Mallett. See check message for detailed information
on all the changes, including a faster encoder, fixes for level
2001-03-27 Frank Warmerdam <warmerdam@pobox.com>
- * libtiff/tiffio.h: Changed "#if LOGLUV_PUBLIC" to
+ * libtiff/tiffio.h: Changed "#if LOGLUV_PUBLIC" to
"#ifdef LOGLUV_PUBLIC" so it will work with VisualAge on AIX.
http://bugzilla.remotesensing.org/show_bug.cgi?id=39
2001-03-13 Frank Warmerdam <warmerdam@pobox.com>
- * tif_getimage.c: Added support for 16bit minisblack/miniswhite
+ * tif_getimage.c: Added support for 16bit minisblack/miniswhite
images in RGBA interface.
2001-03-02 Frank Warmerdam <warmerdam@pobox.com>
* Brent Roman contributed updated tiffcp utility (and tiffcp.1)
with support for extracting subimages with the ,n syntax, and also
- adding the -b bias removal flag.
+ adding the -b bias removal flag.
2001-02-16 Frank Warmerdam <warmerdam@pobox.com>
* libtiff/libtiff.def: Brent Roman submitted new version adding
- serveral missing entry points.
+ serveral missing entry points.
* libtiff/tif_dirinfo.c: don't declare tiffFieldInfo static on VMS.
- Some sort of weird VMS thing.
+ Some sort of weird VMS thing.
http://bugzilla.remotesensing.org/show_bug.cgi?id=31
- * tif_luv.c/tiff.h/tiffio.h:
- New version of TIFF LogLuv (SGILOG) modules contributed by Greg Ward
+ * tif_luv.c/tiff.h/tiffio.h:
+ New version of TIFF LogLuv (SGILOG) modules contributed by Greg Ward
(greg@shutterfly.com). He writes:
1) I improved the gamut-mapping function in tif_luv.c for imaginary
- colors, because some images were being super-saturated on the input
+ colors, because some images were being super-saturated on the input
side and this resulted in some strange color shifts in the output.
2) I added a psuedotag in tiff.h to control random dithering during
- LogLuv encoding. This is turned off by default for 32-bit LogLuv and
- on for 24-bit LogLuv output. Dithering improves the average color
+ LogLuv encoding. This is turned off by default for 32-bit LogLuv and
+ on for 24-bit LogLuv output. Dithering improves the average color
accuracy over the image.
3) I added a #define for LOG_LUV_PUBLIC, which is enabled by default in
2001-01-23 Frank Warmerdam <warmerdam@pobox.com>
* tif_fax3.c: keep rw_mode flag internal to fax3 state to remember
- whether we are encoding or decoding. This is to ensure graceful
+ whether we are encoding or decoding. This is to ensure graceful
recovery if TIFFClientOpen() discovers an attempt to open a compressed
- file for "r+" access, and subsequently close it, as it resets the
+ file for "r+" access, and subsequently close it, as it resets the
tif_mode flag to O_RDONLY in this case to avoid writes, confusing the
compressor's concept of whether it is in encode or decode mode.
-2001-01-08 Mike Welles <mike@bangstate.com>
+2001-01-08 Mike Welles <mike@bangstate.com>
* Makefile.in: Now cleaning up after itself after creating the .tar.gz and .zip
-
+
2001-01-07 Frank Warmerdam <warmerdam@pobox.com>
* html/libtiff.html: Fixed arguments in example for TIFFRGBAImageGet()
- as per bug report by Patrick Connor.
+ as per bug report by Patrick Connor.
2000-12-28 Frank Warmerdam <warmerdam@pobox.com>
* Fixed libtiff/makefile.vc to make tiffvers.h not version.h.
-2000-12-22 Mike Welles <mike@bangstate.com>
+2000-12-22 Mike Welles <mike@bangstate.com>
* added link to CVS mirror from index.html
-
- * updated html/internals.html to note that LZW compression is
- not supported by default.
-
+
+ * updated html/internals.html to note that LZW compression is
+ not supported by default.
+
2000-12-22 Frank Warmerdam <warmerdam@pobox.com>
* updated html/libtiff.html to not point at Niles' old JPL web site
Leonard Rosenthol <leonardr@lazerware.com>. May interfere
with correct building on older systems. If so, please let me know.
-2000-12-19 Mike Welles <mike@bangsate.com>
+2000-12-19 Mike Welles <mike@bangsate.com>
- * Took out LZW Encoding from tif_lzw.c
+ * Took out LZW Encoding from tif_lzw.c
* Created HOWTO-RELEASE
* Created html/v3.5.6.html
* updated index.html
-
+
2000-12-01 Frank Warmerdam <warmerdam@pobox.com>
- * Added patches for EOFB support in tif_fax3.c and tif_fax3.h.
+ * Added patches for EOFB support in tif_fax3.c and tif_fax3.h.
Patches supplied by Frank Cringle <fdc@cliwe.ping.de>
Example file at: ftp://ftp.remotesensing.org/pub/libtiff/eofb_396.tif
targets so libtiff.so will be built with an explicit dependency
on libm.so.
- * libtiff/Makefile.in: Use softlinks to link libtiff.so.3 to
- libtiff.so.3.5.5.
+ * libtiff/Makefile.in: Use softlinks to link libtiff.so.3 to
+ libtiff.so.3.5.5.
- * libtiff/Makefile.in & configure: Remove all references to the ALPHA
- file, or ALPHA version logic. Added stuff about DIST_POINT in
+ * libtiff/Makefile.in & configure: Remove all references to the ALPHA
+ file, or ALPHA version logic. Added stuff about DIST_POINT in
place of DIST_TYPE and the alpha release number stuff.
2000-11-22 Frank Warmerdam <warmerdam@pobox.com>
* I have applied a patch from Steffen Moeller <moeller@ebi.ac.uk> to
- the configure script so that it now accepts the --prefix, and
- --exec-prefix directives.
+ the configure script so that it now accepts the --prefix, and
+ --exec-prefix directives.
2000-11-13 Frank Warmerdam <warmerda@cs46980-c>
- * I have made a variety of modifications in an effort to ensure the
+ * I have made a variety of modifications in an effort to ensure the
TIFFLIB_VERSION macro is automatically generated from the RELEASE-DATE
- file which seems to be updated regularly.
+ file which seems to be updated regularly.
- o mkversion.c now reads RELEASE-DATE and emits TIFFLIB_VERSION in
- version include file.
- o renamed version.h to tiffvers.h because we now have to install it
- with the public libtiff include files.
- o include tiffvers.h in tiffio.h.
+ o mkversion.c now reads RELEASE-DATE and emits TIFFLIB_VERSION in
+ version include file.
+ o renamed version.h to tiffvers.h because we now have to install it
+ with the public libtiff include files.
+ o include tiffvers.h in tiffio.h.
o updated tif_version.c to use tiffvers.h.
o Updated Makefile.in accordingly.
See http://bugzilla.remotesensing.org/show_bug.cgi?id=20
Some patches from Rick LaMont of Dot C Software.
- * Modified tif_packbits.c encoder to avoid compressing more
+ * Modified tif_packbits.c encoder to avoid compressing more
data than provided if rowsize doesn't factor into provided data
(such as occurs for YCbCr).
2000-10-19 Frank Warmerdam <warmerda@cs46980-c>
- * tools/rgb2ycbcr.c: fixed output strip size to account for vertical
+ * tools/rgb2ycbcr.c: fixed output strip size to account for vertical
roundup if rows_per_strip not a multiple of vertical sample size.
2000-10-16 Frank Warmerdam <warmerda@cs46980-c>
2000-10-12 Frank Warmerdam <warmerda@cs46980-c>
* Modified tiff2bw to ensure portions add to 100%, and that
- white is properly recovered.
-
+ white is properly recovered.
+
See bug http://bugzilla.remotesensing.org/show_bug.cgi?id=15
Patch c/o Stanislav Brabec <utx@penguin.cz>
2000-09-27 Frank Warmerdam <warmerda@cs46980-c>
- * Added GNULDdso target an`d switched linux and freebsd to use it.
+ * Added GNULDdso target an`d switched linux and freebsd to use it.
2000-09-26 Frank Warmerdam <warmerda@cs46980-c>
* Applied patch for 0x0000 sequences in tif_fax3.h's definition
- of EXPAND1D() as per bug 11 (from Roman).
+ of EXPAND1D() as per bug 11 (from Roman).
2000-09-25 Frank Warmerdam <warmerda@cs46980-c>
* Fixed tiffcomp.h to avoid win32 stuff if unix #defined, to improve
cygwin compatibility.
* Applied patch from Roman Shpount to tif_fax3.c. This seems to
- be a proper fix to the buffer sizing problem. See
+ be a proper fix to the buffer sizing problem. See
http://bugzilla.remotesensing.org/show_bug.cgi?id=11
* Fixed tif_getimage.c to fix overrun bug with YCbCr images without
downsampling. http://bugzilla.remotesensing.org/show_bug.cgi?id=10
Thanks to Nick Lamb <njl98r@ecs.soton.ac.uk> for reporting the
bug and proving the patch.
-
+
2000-09-18 Frank Warmerdam <warmerda@cs46980-c>
* Fixed tif_jpeg.c so avoid destroying the decompressor before
* Tentatively added support for SAMPLEFORMAT_COMPLEXIEEEFP, and
SAMPLEFORMAT_COMPLEXINT.
-2000-07-13 Mike Welles <mike@onshore.com>
+2000-07-13 Mike Welles <mike@onshore.com>
+
+ * index.html, bugs.html: added bugzilla info.
- * index.html, bugs.html: added bugzilla info.
-
2000-07-12 Frank Warmerdam <warmerda@rommel.atlsci.com>
* tif_read.c: fix subtle bug with determining the number of
rows for strips that are the last strip in a separation but
- not the last strip of all in TIFFReadEncodedStrip().
+ not the last strip of all in TIFFReadEncodedStrip().
* Applied 16/32 bit fix to tif_fax3.c. Fix supplied by
Peter Skarpetis <peters@serendipity-software.com.au>
* libtiff/tif_dirread.c: Don't use estimate strip byte count for
one tile/strip images with an offset, and byte count of zero. These
- could be "unpopulated" images.
+ could be "unpopulated" images.
2000-04-18 Frank Warmerdam <warmerda@rommel.atlsci.com>
2000-04-12 Mike Welles <mike@onshore.com>
* configure: Fixed stupid mistake in libc6 test on Linux
-2000-04-04 Mike Welles <mike@onshore.com>
+2000-04-04 Mike Welles <mike@onshore.com>
* tif_win32.c: Applied patch to fix overreads and ovverwrites
- caught by BoundsChecker. From Arvan Pritchard
- <arvan.pritchard@infomatix.co.uk> (untested).
-
- * tif_getimage.c: Applied patch to silence VC6 warnings. From
+ caught by BoundsChecker. From Arvan Pritchard
+ <arvan.pritchard@infomatix.co.uk> (untested).
+
+ * tif_getimage.c: Applied patch to silence VC6 warnings. From
Arvan Pritchard <arvan.pritchard@informatix.co.uk>
-
- * tif_lzw.c: Applied patch to silence VC6 warnings. From
+
+ * tif_lzw.c: Applied patch to silence VC6 warnings. From
Arvan Pritchard <arvan.pritchard@informatix.co.uk>
-
+
2000-03-28 Frank Warmerdam <warmerda@cs46980-c>
* Added contrib/stream (stream io) code submitted by Avi Bleiweiss.
* fax2ps: Fixed mixup of width and height in bounding box statement
as per submission by Nalin Dahyabhai <nalin@redhat.com>.
-2000-03-27 Mike Welles <mike@onshore.com>
+2000-03-27 Mike Welles <mike@onshore.com>
- * fax2ps: Modified printruns to take uint32 instead of uint16.
- Patch courtesy of Bernt Herd <herd@herdsoft.com>
-
-2000-03-20 Mike Welles <mike@onshore.com>
+ * fax2ps: Modified printruns to take uint32 instead of uint16.
+ Patch courtesy of Bernt Herd <herd@herdsoft.com>
+
+2000-03-20 Mike Welles <mike@onshore.com>
- * configure: added test for libc6 for linux targets. Bug reported by
+ * configure: added test for libc6 for linux targets. Bug reported by
Stanislav Brabec <utx@k332.feld.cvut.cz>
- * Added 3.5 docs to html/Makefile.in.
+ * Added 3.5 docs to html/Makefile.in.
Thanks to Stanislav Brabec <utx@k332.feld.cvut.cz>
- * configure: fixed bugs in sed scripts
- (applied sed script s:/@:s;@:;s:/s;;:;: to configure).
+ * configure: fixed bugs in sed scripts
+ (applied sed script s:/@:s;@:;s:/s;;:;: to configure).
fix submitted to Stanislav Brabec <utx@k332.feld.cvut.cz>
- * tools/iptcutil was not in files list, and wasn't being
+ * tools/iptcutil was not in files list, and wasn't being
added to tar archive. Updated Makefile.in.
2000-03-17 Frank Warmerdam <warmerda@cs46980-c>
* tif_fax3.c: Fixed serious bug introduced during the uint16->uint32
- conversion for the run arrays.
+ conversion for the run arrays.
2000-03-03 Frank Warmerdam <warmerda@cs46980-c.mtnk1.on.wave.home.com>
- * Set td_sampleformat default to SAMPLEFORMAT_UINT instead of
+ * Set td_sampleformat default to SAMPLEFORMAT_UINT instead of
SAMPLEFORMAT_VOID in TIFFDefaultDirectory() in tif_dir.c.
2000-03-02 Frank Warmerdam <warmerda@cs46980-c.mtnk1.on.wave.home.com>
set to 1, and added default (off) setting in tiffconf.h. This
should eventually be set by the configure script somehow.
- The original work on all these 2-4GB changes was done by
+ The original work on all these 2-4GB changes was done by
Peter Smith (psmith@creo.com).
* Modified tif_win32.c to support 2-4GB seeks.
* tentatively changed toff_t to be unsigned instead of signed to
- facilitate support for 2-4GB files.
+ facilitate support for 2-4GB files.
* Updated a variety of files to use toff_t. Fixed some mixups
between toff_t and tsize_t.
Fri Jan 28 10:13:49 2000 Frank Warmerdam <warmerda@gdal.velocet.ca>
- * Largely reimplemented contrib/addtiffo to avoid temp files,
+ * Largely reimplemented contrib/addtiffo to avoid temp files,
updating the TIFF file in place. Fixed a few other bugs to.
* Set tif_rawdatasize to zero when freeing raw data buffer in
* Enabled "REWRITE_HACK" in tif_write.c by default.
* Fix bug in tif_write.c when switching between reading one directory
- and writing to another.
+ and writing to another.
* Made TIFFWriteCheck() public, and added TIFFCreateDirectory()
* Added libtiff/libtiff.def to TIFFILES distribution list.
-Mon Dec 27 12:13:39 EST 1999 Mike Welles <mike@onshore.com>
+Mon Dec 27 12:13:39 EST 1999 Mike Welles <mike@onshore.com>
- * Created lzw compression kit, as a new module (libtiff-lzw-compression-kit).
+ * Created lzw compression kit, as a new module (libtiff-lzw-compression-kit).
* Altered descriptions in tools to reflect "by default" lzw not supported
- * Updated index.html to note lzw compression kit.
-
+ * Updated index.html to note lzw compression kit.
+
Tue Dec 21 14:01:51 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
- * Added fax3sm_winnt.c to distribution list in Makefile.in.
+ * Added fax3sm_winnt.c to distribution list in Makefile.in.
Tue Dec 21 11:04:45 EST 1999 Mike Welles <mike@onshore.com> *** 3.5.4 release ***
-
- * Aadded Pixar tag support. Contributed by Phil Beffery <phil@pixar.com>
- * Made one more change to tif_dir.c for removal of LZW compression. Also added notice
- when LZW compression invoked.
+ * Aadded Pixar tag support. Contributed by Phil Beffery <phil@pixar.com>
+
+ * Made one more change to tif_dir.c for removal of LZW compression. Also added notice
+ when LZW compression invoked.
* Changed default compression in tools to TIFF_PACKBITS, and changed usage descriptions
in tools to reflect removal of LZW compression
-
+
Mon Dec 20 18:39:02 EST 1999 Mike Welles <mike@onshore.com>
- * Fixed bug that caused LZW (non) compression to segfault. Added
- warning about LZW compression removed being removed, and why.
+ * Fixed bug that caused LZW (non) compression to segfault. Added
+ warning about LZW compression removed being removed, and why.
+
+ * Added nostrip to install in tools/Makefile.in so that debugging
+ symbols are kept.
- * Added nostrip to install in tools/Makefile.in so that debugging
- symbols are kept.
-
Tue Dec 7 12:04:47 EST 1999 Mike Welles <mike@onshore.com>
- * Added patch from Ivo Penzar <ivo.penzar@infolink-software.com>,
- supporting Adobe ZIP deflate. Untested.
-
+ * Added patch from Ivo Penzar <ivo.penzar@infolink-software.com>,
+ supporting Adobe ZIP deflate. Untested.
+
Sat Dec 4 15:47:11 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
* Made Packbits the default compression in tools/tiff2rgba.c instead
* Added tif_luv to contrib/djgpp/Makefile.lib.
-Tue Nov 30 14:15:32 EST 1999 Mike Welles <mike@onshore.com>
+Tue Nov 30 14:15:32 EST 1999 Mike Welles <mike@onshore.com>
- * Added zip creation to relase makefile target
+ * Added zip creation to relase makefile target
+
+ * Added html for TIFFWriteTile.3t man page.
- * Added html for TIFFWriteTile.3t man page.
-
Tue Nov 30 09:20:16 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
* Added some changes to tif_write.c to support rewriting existing
Sun Nov 28 20:36:18 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
- * Added notes on use of makefile.vc in build.html, and fixed
+ * Added notes on use of makefile.vc in build.html, and fixed
email subscription address.
-199-11-28 Mike Welles <mike@onshore.com>
+199-11-28 Mike Welles <mike@onshore.com>
- * Fixed apocalypse-inducing y2k bug in contrib/ras/ras2tiff.c
+ * Fixed apocalypse-inducing y2k bug in contrib/ras/ras2tiff.c
* Did some casts cleaning up to reduce compiler warnings in tif_fax3.c,
- from Bruce Carmeron <cameron@petris.com> -- modifications of
- changes made by Frank (sun cc still complained on cast).
+ from Bruce Carmeron <cameron@petris.com> -- modifications of
+ changes made by Frank (sun cc still complained on cast).
* Added tiffconf.h to install target per request from Bill
Radcliffe <billr@corbis.com>: "We need a way for ImageMagick to
know features have been compiled into the TIFF library in order to
- handle things properly".
-
+ handle things properly".
+
Sat Nov 27 16:49:21 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
* fixed various VC++ warnings as suggested by Gilles Vollant
- <info@winimage.com>.
+ <info@winimage.com>.
Wed Nov 24 12:08:16 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
1999-11-22 Mike Welles <mike@onshore.com>
* HTML-ized the man pages, added to html/man
-
- * Removed LZW Compression to comply with Unisys patent extortion.
-
-1999-09-29 Mike Welles <mike@onshore.com>
- * Corrected one remaining 16 -> 32 bit value in tif_fax3.c,
- From Ivo Penzar <ivo.penzar@infolink-software.com.
+
+ * Removed LZW Compression to comply with Unisys patent extortion.
+
+1999-09-29 Mike Welles <mike@onshore.com>
+ * Corrected one remaining 16 -> 32 bit value in tif_fax3.c,
+ From Ivo Penzar <ivo.penzar@infolink-software.com.
* Added patch from Ivo Penzar to have TiffAdvanceDirectory handle
memory mapped files. <ivo.penzar@infolink-software.com>
-
+
1999-09-26 Mike Welles <mike@onshore.com> *** 3.5.2 release ***
- * Corrected alpha versioning.
+ * Corrected alpha versioning.
- * Removed distinction between alpha and release targets in Makefile.in.
+ * Removed distinction between alpha and release targets in Makefile.in.
- * added release.stamp target, which tags cvs tree, and updates
+ * added release.stamp target, which tags cvs tree, and updates
"RELEASE-DATE"
- * added releasediff target, which diffs tree with source as of
+ * added releasediff target, which diffs tree with source as of
date in "RELEASE-DATE"
-
- * Ticked up version to 3.5.2 (alpha 01 -- but I think we'll moving
- away from alpha/non-alpha distinctions).
- * updated html to reflect release
-
+ * Ticked up version to 3.5.2 (alpha 01 -- but I think we'll moving
+ away from alpha/non-alpha distinctions).
+
+ * updated html to reflect release
+
1999-09-23 <warmerda@CS46980-B>
* Set O_BINARY for tif_unix.c open() ... used on cygwin for instance.
* Added CYGWIN case in configure.
-Fri Sep 17 00:13:51 CEST 1999 Mike Welles <mike@onshore.com>
+Fri Sep 17 00:13:51 CEST 1999 Mike Welles <mike@onshore.com>
+
+ * Applied Francois Dagand's patch to handle fax decompression bug.
+ (sizes >= 65536 were failing)
- * Applied Francois Dagand's patch to handle fax decompression bug.
- (sizes >= 65536 were failing)
-
Tue Sep 14 21:31:43 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
- * Applied "a" mode fix to tif_win32.c/TIFFOpen() as suggested
+ * Applied "a" mode fix to tif_win32.c/TIFFOpen() as suggested
by Christopher Lawton <clawton@mathworks.com>
Wed Sep 8 08:19:18 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
- * Added IRIX/gcc, and OSF/1 4.x support on behalf of
+ * Added IRIX/gcc, and OSF/1 4.x support on behalf of
Albert Chin-A-Young <china@thewrittenword.com>
- * Added TIFFReassignTagToIgnore() API on behalf of
+ * Added TIFFReassignTagToIgnore() API on behalf of
Bruce Cameron <cameron@petris.com>. Man page still pending.
Wed Aug 25 11:39:07 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
- * Added test target in Makefile, test_pics.sh script and pics/*.rpt
+ * Added test target in Makefile, test_pics.sh script and pics/*.rpt
files to provide for a rudimentary testsuite.
* Added contrib/tags back from old distribution ... fixed up a bit.
1999-08-16 <warmerda@CS46980-B>
* Added simple makefile.vc makefiles for building with MS VC++
- on Windows NT/98/95 in console mode. Stuff in contrib/win* make give
+ on Windows NT/98/95 in console mode. Stuff in contrib/win* make give
better solutions for some users.
Mon Aug 16 21:52:11 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
1999-08-16 Michael L. Welles <mike@kurtz.fake>
- * Updated html/index.html with anon CVS instructions.
+ * Updated html/index.html with anon CVS instructions.
Mon Aug 16 13:18:41 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
- * pre-remove so link before softlink in LINUXdso action in
+ * pre-remove so link before softlink in LINUXdso action in
libtiff/Makefile.in to avoid failure on LINUXdso builds other than
the first.
* Fixed problem with cvtcmap() in tif_getimage.c modifying the
colormaps owned by the TIFF handle itself when trying to fixup wrong
(eight bit) colormaps. Corrected by maintaining a private copy of
- the colormap.
+ the colormap.
- * Added TIFFReadRGBATile()/TIFFReadRGBAStrip() support in
+ * Added TIFFReadRGBATile()/TIFFReadRGBAStrip() support in
tif_getimage.c.
* CVS Repository placed at remotesensing.org. ChangeLog added.
--- /dev/null
+/*
+ * Copyright (c) 2009 Frank Warmerdam
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBPORT_
+#define _LIBPORT_
+
+int getopt(int argc, char * const argv[], const char *optstring);
+extern char *optarg;
+extern int opterr;
+extern int optind;
+extern int optopt;
+
+int strcasecmp(const char *s1, const char *s2);
+
+#ifndef HAVE_GETOPT
+# define HAVE_GETOPT 1
+#endif
+
+#if HAVE_STRTOL
+long strtol(const char *nptr, char **endptr, int base);
+#endif
+#if HAVE_STRTOLL
+long long strtoll(const char *nptr, char **endptr, int base);
+#endif
+#if HAVE_STRTOUL
+unsigned long strtoul(const char *nptr, char **endptr, int base);
+#endif
+#if HAVE_STRTOULL
+unsigned long long strtoull(const char *nptr, char **endptr, int base);
+#endif
+
+#if 0
+void *
+lfind(const void *key, const void *base, size_t *nmemb, size_t size,
+ int(*compar)(const void *, const void *));
+#endif
+
+#if !defined(HAVE_SNPRINTF)
+#undef vsnprintf
+#define vsnprintf _TIFF_vsnprintf_f
+
+#undef snprintf
+#define snprintf _TIFF_snprintf_f
+int snprintf(char* str, size_t size, const char* format, ...);
+#endif
+
+#endif /* ndef _LIBPORT_ */
#include <stdio.h>
#include <stdarg.h>
+#include "libport.h"
int _TIFF_vsnprintf_f(char* str, size_t size, const char* format, va_list ap)
{
}
#endif // _MSC_VER
-
-/* $Id: t4.h,v 1.3 2010-03-10 18:56:48 bfriesen Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_aux.c,v 1.31 2017-11-17 20:21:00 erouault Exp $ */
-
/*
* Copyright (c) 1991-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_close.c,v 1.21 2016-01-23 21:20:34 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_codec.c,v 1.17 2015-08-19 02:31:04 bfriesen Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
#ifndef LZMA_SUPPORT
#define TIFFInitLZMA NotConfigured
#endif
+#ifndef ZSTD_SUPPORT
+#define TIFFInitZSTD NotConfigured
+#endif
+#ifndef WEBP_SUPPORT
+#define TIFFInitWebP NotConfigured
+#endif
/*
* Compression schemes statically built into the library.
{ "SGILog", COMPRESSION_SGILOG, TIFFInitSGILog },
{ "SGILog24", COMPRESSION_SGILOG24, TIFFInitSGILog },
{ "LZMA", COMPRESSION_LZMA, TIFFInitLZMA },
+ { "ZSTD", COMPRESSION_ZSTD, TIFFInitZSTD },
+ { "WEBP", COMPRESSION_WEBP, TIFFInitWebP },
{ NULL, 0, NULL }
};
-/* $Id: tif_color.c,v 1.24 2017-05-29 10:12:54 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
}
/*
- * Convert color value from the YCbCr space to CIE XYZ.
+ * Convert color value from the YCbCr space to RGB.
* The colorspace conversion algorithm comes from the IJG v5a code;
* see below for more information on how it works.
*/
-/* $Id: tif_compress.c,v 1.25 2016-10-25 20:04:22 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
/* Define to 1 if you have the <fcntl.h> header file. */
#cmakedefine HAVE_FCNTL_H 1
-/* Define to 1 if you have the `floor' function. */
-#cmakedefine HAVE_FLOOR 1
-
/* Define to 1 if you have the `getopt' function. */
#cmakedefine HAVE_GETOPT 1
/* Define to 1 if you have the <io.h> header file. */
#cmakedefine HAVE_IO_H 1
-/* Define to 1 if you have the `isascii' function. */
-#cmakedefine HAVE_ISASCII 1
-
/* Define to 1 if you have the `jbg_newlen' function. */
#cmakedefine HAVE_JBG_NEWLEN 1
/* Define to 1 if you have the `lfind' function. */
#cmakedefine HAVE_LFIND 1
-/* Define to 1 if you have the <limits.h> header file. */
-#cmakedefine HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the <malloc.h> header file. */
-#cmakedefine HAVE_MALLOC_H 1
-
-/* Define to 1 if you have the `memmove' function. */
-#cmakedefine HAVE_MEMMOVE 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#cmakedefine HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `memset' function. */
-#cmakedefine HAVE_MEMSET 1
-
/* Define to 1 if you have the `mmap' function. */
#cmakedefine HAVE_MMAP 1
/* Define to 1 if you have the <OpenGL/gl.h> header file. */
#cmakedefine HAVE_OPENGL_GL_H 1
-/* Define to 1 if you have the `pow' function. */
-#cmakedefine HAVE_POW 1
-
/* Define to 1 if you have the <search.h> header file. */
#cmakedefine HAVE_SEARCH_H 1
/* Define to 1 if you have the `snprintf' function. */
#cmakedefine HAVE_SNPRINTF 1
-/* Define to 1 if you have the `sqrt' function. */
-#cmakedefine HAVE_SQRT 1
-
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
/* Define to 1 if you have the `strcasecmp' function. */
#cmakedefine HAVE_STRCASECMP 1
-/* Define to 1 if you have the `strchr' function. */
-#cmakedefine HAVE_STRCHR 1
-
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H 1
-/* Define to 1 if you have the `strrchr' function. */
-#cmakedefine HAVE_STRRCHR 1
-
-/* Define to 1 if you have the `strstr' function. */
-#cmakedefine HAVE_STRSTR 1
-
/* Define to 1 if you have the `strtol' function. */
#cmakedefine HAVE_STRTOL 1
+/* Define to 1 if you have the `strtoll' function. */
+#cmakedefine HAVE_STRTOLL 1
+
/* Define to 1 if you have the `strtoul' function. */
#cmakedefine HAVE_STRTOUL 1
/* Support LZMA2 compression */
#cmakedefine LZMA_SUPPORT 1
+/* Support ZSTD compression */
+#cmakedefine ZSTD_SUPPORT 1
+
+/* Support WEBP compression */
+#cmakedefine WEBP_SUPPORT 1
+
/* Name of package */
#define PACKAGE "@PACKAGE_NAME@"
/* The size of `signed long long', as computed by sizeof. */
#define SIZEOF_SIGNED_LONG_LONG @SIZEOF_SIGNED_LONG_LONG@
-/* The size of `signed short', as computed by sizeof. */
-#define SIZEOF_SIGNED_SHORT @SIZEOF_SIGNED_SHORT@
-
/* The size of `unsigned char *', as computed by sizeof. */
#define SIZEOF_UNSIGNED_CHAR_P @SIZEOF_UNSIGNED_CHAR_P@
# endif
#endif
+/* Number of bits in a file offset, on hosts where this is settable. */
+//disabled for OpenCV CMakeLists.txt: #define _FILE_OFFSET_BITS @FILE_OFFSET_BITS@
+
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
-/* $Id: tif_dir.c,v 1.131 2017-07-11 21:38:04 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY);
if( fip == NULL ) /* cannot happen since TIFFGetField() already checks it */
return 0;
+
+ /*
+ * We want to force the custom code to be used for custom
+ * fields even if the tag happens to match a well known
+ * one - important for reinterpreted handling of standard
+ * tag values in custom directories (i.e. EXIF)
+ */
+ if (fip->field_bit == FIELD_CUSTOM) {
+ standard_tag = 0;
+ }
- if( tag == TIFFTAG_NUMBEROFINKS )
+ if( standard_tag == TIFFTAG_NUMBEROFINKS )
{
int i;
for (i = 0; i < td->td_customValueCount; i++) {
uint16 val;
TIFFTagValue *tv = td->td_customValues + i;
- if (tv->info->field_tag != tag)
+ if (tv->info->field_tag != standard_tag)
continue;
if( tv->value == NULL )
return 0;
return 0;
}
- /*
- * We want to force the custom code to be used for custom
- * fields even if the tag happens to match a well known
- * one - important for reinterpreted handling of standard
- * tag values in custom directories (i.e. EXIF)
- */
- if (fip->field_bit == FIELD_CUSTOM) {
- standard_tag = 0;
- }
-
switch (standard_tag) {
case TIFFTAG_SUBFILETYPE:
*va_arg(ap, uint32*) = td->td_subfiletype;
if (td->td_samplesperpixel - td->td_extrasamples > 1) {
*va_arg(ap, uint16**) = td->td_transferfunction[1];
*va_arg(ap, uint16**) = td->td_transferfunction[2];
+ } else {
+ *va_arg(ap, uint16**) = NULL;
+ *va_arg(ap, uint16**) = NULL;
}
break;
case TIFFTAG_REFERENCEBLACKWHITE:
-/* $Id: tif_dir.h,v 1.55 2017-06-01 12:44:04 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
#ifndef _TIFFDIR_
#define _TIFFDIR_
+
+#include "tiff.h"
+#include "tiffio.h"
+
/*
* ``Library-private'' Directory-related Definitions.
*/
-/* $Id: tif_dirinfo.c,v 1.127 2017-06-01 12:44:04 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
case TIFFTAG_CONSECUTIVEBADFAXLINES:
case TIFFTAG_GROUP3OPTIONS:
case TIFFTAG_GROUP4OPTIONS:
+ /* LERC */
+ case TIFFTAG_LERC_PARAMETERS:
break;
default:
return 1;
if (tag == TIFFTAG_PREDICTOR)
return 1;
break;
-
+ case COMPRESSION_ZSTD:
+ if (tag == TIFFTAG_PREDICTOR)
+ return 1;
+ break;
+ case COMPRESSION_LERC:
+ if (tag == TIFFTAG_LERC_PARAMETERS)
+ return 1;
+ break;
+ case COMPRESSION_WEBP:
+ if (tag == TIFFTAG_PREDICTOR)
+ return 1;
+ break;
}
return 0;
}
-/* $Id: tif_dirread.c,v 1.218 2017-09-09 21:44:42 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
static int TIFFFetchSubjectDistance(TIFF*, TIFFDirEntry*);
static void ChopUpSingleUncompressedStrip(TIFF*);
static uint64 TIFFReadUInt64(const uint8 *value);
+static int _TIFFGetMaxColorChannels(uint16 photometric);
static int _TIFFFillStrilesInternal( TIFF *tif, int loadStripByteCount );
static enum TIFFReadDirEntryErr TIFFReadDirEntryDataAndRealloc(
TIFF* tif, uint64 offset, tmsize_t size, void** pdest)
{
-#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8
+#if SIZEOF_SIZE_T == 8
tmsize_t threshold = INITIAL_THRESHOLD;
#endif
tmsize_t already_read = 0;
void* new_dest;
tmsize_t bytes_read;
tmsize_t to_read = size - already_read;
-#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8
+#if SIZEOF_SIZE_T == 8
if( to_read >= threshold && threshold < MAX_THRESHOLD )
{
to_read = threshold;
}
/*
+ * Return the maximum number of color channels specified for a given photometric
+ * type. 0 is returned if photometric type isn't supported or no default value
+ * is defined by the specification.
+ */
+static int _TIFFGetMaxColorChannels( uint16 photometric )
+{
+ switch (photometric) {
+ case PHOTOMETRIC_PALETTE:
+ case PHOTOMETRIC_MINISWHITE:
+ case PHOTOMETRIC_MINISBLACK:
+ return 1;
+ case PHOTOMETRIC_YCBCR:
+ case PHOTOMETRIC_RGB:
+ case PHOTOMETRIC_CIELAB:
+ case PHOTOMETRIC_LOGLUV:
+ case PHOTOMETRIC_ITULAB:
+ case PHOTOMETRIC_ICCLAB:
+ return 3;
+ case PHOTOMETRIC_SEPARATED:
+ case PHOTOMETRIC_MASK:
+ return 4;
+ case PHOTOMETRIC_LOGL:
+ case PHOTOMETRIC_CFA:
+ default:
+ return 0;
+ }
+}
+
+/*
* Read the next TIFF directory from a file and convert it to the internal
* format. We read directories sequentially.
*/
uint32 fii=FAILED_FII;
toff_t nextdiroff;
int bitspersample_read = FALSE;
+ int color_channels;
tif->tif_diroff=tif->tif_nextdiroff;
if (!TIFFCheckDirOffset(tif,tif->tif_nextdiroff))
}
}
}
+
+ /*
+ * Make sure all non-color channels are extrasamples.
+ * If it's not the case, define them as such.
+ */
+ color_channels = _TIFFGetMaxColorChannels(tif->tif_dir.td_photometric);
+ if (color_channels && tif->tif_dir.td_samplesperpixel - tif->tif_dir.td_extrasamples > color_channels) {
+ uint16 old_extrasamples;
+ uint16 *new_sampleinfo;
+
+ TIFFWarningExt(tif->tif_clientdata,module, "Sum of Photometric type-related "
+ "color channels and ExtraSamples doesn't match SamplesPerPixel. "
+ "Defining non-color channels as ExtraSamples.");
+
+ old_extrasamples = tif->tif_dir.td_extrasamples;
+ tif->tif_dir.td_extrasamples = (uint16) (tif->tif_dir.td_samplesperpixel - color_channels);
+
+ // sampleinfo should contain information relative to these new extra samples
+ new_sampleinfo = (uint16*) _TIFFcalloc(tif->tif_dir.td_extrasamples, sizeof(uint16));
+ if (!new_sampleinfo) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Failed to allocate memory for "
+ "temporary new sampleinfo array (%d 16 bit elements)",
+ tif->tif_dir.td_extrasamples);
+ goto bad;
+ }
+
+ memcpy(new_sampleinfo, tif->tif_dir.td_sampleinfo, old_extrasamples * sizeof(uint16));
+ _TIFFsetShortArray(&tif->tif_dir.td_sampleinfo, new_sampleinfo, tif->tif_dir.td_extrasamples);
+ _TIFFfree(new_sampleinfo);
+ }
+
/*
* Verify Palette image has a Colormap.
*/
err=TIFFReadDirEntryByteArray(tif,dp,&data);
if (err==TIFFReadDirEntryErrOk)
{
- uint8* ma;
- uint32 mb;
+ uint32 mb = 0;
int n;
- ma=data;
- mb=0;
- while (mb<(uint32)dp->tdir_count)
+ if (data != NULL)
{
- if (*ma==0)
- break;
- ma++;
- mb++;
+ uint8* ma = data;
+ while (mb<(uint32)dp->tdir_count)
+ {
+ if (*ma==0)
+ break;
+ ma++;
+ mb++;
+ }
}
if (mb+1<(uint32)dp->tdir_count)
TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" contains null byte in value; value incorrectly truncated during reading due to implementation limitations",fip->field_name);
if (err==TIFFReadDirEntryErrOk)
{
int m;
- if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' )
- {
- TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name);
- data[dp->tdir_count-1] = '\0';
- }
+ if( data != 0 && dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' )
+ {
+ TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name);
+ data[dp->tdir_count-1] = '\0';
+ }
m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data);
if (data!=0)
_TIFFfree(data);
if (err==TIFFReadDirEntryErrOk)
{
int m;
- if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' )
- {
- TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name);
- data[dp->tdir_count-1] = '\0';
- }
+ if( data != 0 && dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' )
+ {
+ TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name);
+ data[dp->tdir_count-1] = '\0';
+ }
m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data);
if (data!=0)
_TIFFfree(data);
if( nstrips == 0 )
return;
+ /* If we are going to allocate a lot of memory, make sure that the */
+ /* file is as big as needed */
+ if( tif->tif_mode == O_RDONLY &&
+ nstrips > 1000000 &&
+ (offset >= TIFFGetFileSize(tif) ||
+ stripbytes > (TIFFGetFileSize(tif) - offset) / (nstrips - 1)) )
+ {
+ return;
+ }
+
newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64),
"for chopped \"StripByteCounts\" array");
newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64),
-/* $Id: tif_dirwrite.c,v 1.89 2017-08-23 13:33:42 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
}
break;
default:
- assert(0); /* we should never get here */
- break;
+ TIFFErrorExt(tif->tif_clientdata,module,
+ "Cannot write tag %d (%s)",
+ TIFFFieldTag(o),
+ o->field_name ? o->field_name : "unknown");
+ goto bad;
}
}
}
-/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_dumpmode.c,v 1.15 2015-12-12 18:04:26 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_error.c,v 1.6 2017-07-04 12:54:42 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_extension.c,v 1.8 2015-12-06 11:13:43 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_fax3.c,v 1.81 2017-06-18 10:31:50 erouault Exp $ */
-
/*
* Copyright (c) 1990-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_fax3.h,v 1.13 2016-12-14 18:36:27 faxguy Exp $ */
-
/*
* Copyright (c) 1990-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_flush.c,v 1.9 2010-03-31 06:40:10 fwarmerdam Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_getimage.c,v 1.114 2017-11-17 20:21:00 erouault Exp $ */
-
/*
* Copyright (c) 1991-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_jbig.c,v 1.16 2017-06-26 15:20:00 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
struct jbg_dec_state decoder;
int decodeStatus = 0;
unsigned char* pImage = NULL;
- (void) size, (void) s;
+ unsigned long decodedSize;
+ (void) s;
if (isFillOrder(tif, tif->tif_dir.td_fillorder))
{
- TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdatasize);
+ TIFFReverseBits(tif->tif_rawcp, tif->tif_rawcc);
}
jbg_dec_init(&decoder);
#if defined(HAVE_JBG_NEWLEN)
- jbg_newlen(tif->tif_rawdata, (size_t)tif->tif_rawdatasize);
+ jbg_newlen(tif->tif_rawcp, (size_t)tif->tif_rawcc);
/*
* I do not check the return status of jbg_newlen because even if this
* function fails it does not necessarily mean that decoding the image
*/
#endif /* HAVE_JBG_NEWLEN */
- decodeStatus = jbg_dec_in(&decoder, (unsigned char*)tif->tif_rawdata,
- (size_t)tif->tif_rawdatasize, NULL);
+ decodeStatus = jbg_dec_in(&decoder, (unsigned char*)tif->tif_rawcp,
+ (size_t)tif->tif_rawcc, NULL);
if (JBG_EOK != decodeStatus)
{
/*
return 0;
}
+ decodedSize = jbg_dec_getsize(&decoder);
+ if( (tmsize_t)decodedSize < size )
+ {
+ TIFFWarningExt(tif->tif_clientdata, "JBIG",
+ "Only decoded %lu bytes, whereas %lu requested",
+ decodedSize, (unsigned long)size);
+ }
+ else if( (tmsize_t)decodedSize > size )
+ {
+ TIFFErrorExt(tif->tif_clientdata, "JBIG",
+ "Decoded %lu bytes, whereas %lu were requested",
+ decodedSize, (unsigned long)size);
+ jbg_dec_free(&decoder);
+ return 0;
+ }
pImage = jbg_dec_getimage(&decoder, 0);
- _TIFFmemcpy(buffer, pImage, jbg_dec_getsize(&decoder));
+ _TIFFmemcpy(buffer, pImage, decodedSize);
jbg_dec_free(&decoder);
+
+ tif->tif_rawcp += tif->tif_rawcc;
+ tif->tif_rawcc = 0;
+
return 1;
}
-/* $Id: tif_jpeg.c,v 1.134 2017-10-17 19:04:47 erouault Exp $ */
-
/*
* Copyright (c) 1994-1997 Sam Leffler
* Copyright (c) 1994-1997 Silicon Graphics, Inc.
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
+#include "tiffiop.h"
#include <stdlib.h>
-#include "tiffiop.h"
#ifdef JPEG_SUPPORT
/*
"JPEGLib: JPEG parameter struct mismatch: library thinks size is 432,
caller expects 464"
- For such users we wil fix the problem here. See install.doc file from
+ For such users we will fix the problem here. See install.doc file from
the JPEG library distribution for details.
*/
-/* $Id: tif_luv.c,v 1.49 2017-07-24 12:47:30 erouault Exp $ */
-
/*
* Copyright (c) 1997 Greg Ward Larson
* Copyright (c) 1997 Silicon Graphics, Inc.
bp = (unsigned char*) tif->tif_rawcp;
cc = tif->tif_rawcc;
/* get each byte string */
- for (shft = 2*8; (shft -= 8) >= 0; ) {
+ for (shft = 8; shft >= 0; shft -=8) {
for (i = 0; i < npixels && cc > 0; ) {
if (*bp >= 128) { /* run */
if( cc < 2 )
bp = (unsigned char*) tif->tif_rawcp;
cc = tif->tif_rawcc;
/* get each byte string */
- for (shft = 4*8; (shft -= 8) >= 0; ) {
+ for (shft = 24; shft >= 0; shft -=8) {
for (i = 0; i < npixels && cc > 0; ) {
if (*bp >= 128) { /* run */
if( cc < 2 )
/* compress each byte string */
op = tif->tif_rawcp;
occ = tif->tif_rawdatasize - tif->tif_rawcc;
- for (shft = 2*8; (shft -= 8) >= 0; )
+ for (shft = 8; shft >= 0; shft -=8) {
for (i = 0; i < npixels; i += rc) {
if (occ < 4) {
tif->tif_rawcp = op;
} else
rc = 0;
}
+ }
tif->tif_rawcp = op;
tif->tif_rawcc = tif->tif_rawdatasize - occ;
/* compress each byte string */
op = tif->tif_rawcp;
occ = tif->tif_rawdatasize - tif->tif_rawcc;
- for (shft = 4*8; (shft -= 8) >= 0; )
+ for (shft = 24; shft >= 0; shft -=8) {
for (i = 0; i < npixels; i += rc) {
if (occ < 4) {
tif->tif_rawcp = op;
} else
rc = 0;
}
+ }
tif->tif_rawcp = op;
tif->tif_rawcc = tif->tif_rawdatasize - occ;
-/* $Id: tif_lzma.c,v 1.6 2016-09-17 09:18:59 erouault Exp $ */
-
/*
* Copyright (c) 2010, Andrey Kiselev <dron@ak4719.spb.edu>
*
{
static const char module[] = "LZMAPreEncode";
LZMAState *sp = EncoderState(tif);
+ lzma_ret ret;
(void) s;
assert(sp != NULL);
"Liblzma cannot deal with buffers this size");
return 0;
}
- return (lzma_stream_encoder(&sp->stream, sp->filters, sp->check) == LZMA_OK);
+ ret = lzma_stream_encoder(&sp->stream, sp->filters, sp->check);
+ if (ret != LZMA_OK) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error in lzma_stream_encoder(): %s", LZMAStrerror(ret));
+ return 0;
+ }
+ return 1;
}
/*
-/* $Id: tif_lzw.c,v 1.57 2017-07-11 10:54:29 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
long dec_restart; /* restart count */
#ifdef LZW_CHECKEOS
uint64 dec_bitsleft; /* available bits in raw data */
+ tmsize_t old_tif_rawcc; /* value of tif_rawcc at the end of the previous TIFLZWDecode() call */
#endif
decodeFunc dec_decode; /* regular or backwards compatible */
code_t* dec_codep; /* current recognized code */
sp->dec_nbitsmask = MAXCODE(BITS_MIN);
#ifdef LZW_CHECKEOS
sp->dec_bitsleft = 0;
+ sp->old_tif_rawcc = 0;
#endif
sp->dec_free_entp = sp->dec_codetab + CODE_FIRST;
/*
bp = (unsigned char *)tif->tif_rawcp;
#ifdef LZW_CHECKEOS
- sp->dec_bitsleft = (((uint64)tif->tif_rawcc) << 3);
+ sp->dec_bitsleft += (((uint64)tif->tif_rawcc - sp->old_tif_rawcc) << 3);
#endif
nbits = sp->lzw_nbits;
nextdata = sp->lzw_nextdata;
tif->tif_rawcc -= (tmsize_t)( (uint8*) bp - tif->tif_rawcp );
tif->tif_rawcp = (uint8*) bp;
+#ifdef LZW_CHECKEOS
+ sp->old_tif_rawcc = tif->tif_rawcc;
+#endif
sp->lzw_nbits = (unsigned short) nbits;
sp->lzw_nextdata = nextdata;
sp->lzw_nextbits = nextbits;
char *tp;
unsigned char *bp;
int code, nbits;
+ int len;
long nextbits, nextdata, nbitsmask;
code_t *codep, *free_entp, *maxcodep, *oldcodep;
bp = (unsigned char *)tif->tif_rawcp;
#ifdef LZW_CHECKEOS
- sp->dec_bitsleft = (((uint64)tif->tif_rawcc) << 3);
+ sp->dec_bitsleft += (((uint64)tif->tif_rawcc - sp->old_tif_rawcc) << 3);
#endif
nbits = sp->lzw_nbits;
nextdata = sp->lzw_nextdata;
} while (--occ);
break;
}
- assert(occ >= codep->length);
- op += codep->length;
- occ -= codep->length;
- tp = op;
+ len = codep->length;
+ tp = op + len;
do {
- *--tp = codep->value;
- } while( (codep = codep->next) != NULL );
+ int t;
+ --tp;
+ t = codep->value;
+ codep = codep->next;
+ *tp = (char)t;
+ } while (codep && tp > op);
+ assert(occ >= len);
+ op += len;
+ occ -= len;
} else {
*op++ = (char)code;
occ--;
tif->tif_rawcc -= (tmsize_t)( (uint8*) bp - tif->tif_rawcp );
tif->tif_rawcp = (uint8*) bp;
+#ifdef LZW_CHECKEOS
+ sp->old_tif_rawcc = tif->tif_rawcc;
+#endif
sp->lzw_nbits = (unsigned short)nbits;
sp->lzw_nextdata = nextdata;
sp->lzw_nextbits = nextbits;
-/* $Id: tif_next.c,v 1.19 2016-09-04 21:32:56 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_ojpeg.c,v 1.69 2017-04-27 17:29:26 erouault Exp $ */
-
/* WARNING: The type of JPEG encapsulation defined by the TIFF Version 6.0
specification is now totally obsolete and deprecated for new applications and
images. This file was was created solely in order to read unconverted images
-/* $Id: tif_open.c,v 1.48 2016-11-20 22:29:47 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_packbits.c,v 1.26 2017-05-14 02:26:07 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_pixarlog.c,v 1.54 2017-07-10 10:40:28 erouault Exp $ */
-
/*
* Copyright (c) 1996-1997 Sam Leffler
* Copyright (c) 1996 Pixar
-/* $Id: tif_predict.c,v 1.44 2017-06-18 10:31:50 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_predict.h,v 1.9 2016-10-31 17:24:26 erouault Exp $ */
-
/*
* Copyright (c) 1995-1997 Sam Leffler
* Copyright (c) 1995-1997 Silicon Graphics, Inc.
#ifndef _TIFFPREDICT_
#define _TIFFPREDICT_
+
+#include "tiffio.h"
+#include "tiffiop.h"
+
/*
* ``Library-private'' Support for the Predictor Tag
*/
-/* $Id: tif_print.c,v 1.65 2016-11-20 22:31:22 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
uint16 i;
fprintf(fd, " %2ld: %5u",
l, td->td_transferfunction[0][l]);
- for (i = 1; i < td->td_samplesperpixel; i++)
+ for (i = 1; i < td->td_samplesperpixel - td->td_extrasamples && i < 3; i++)
fprintf(fd, " %5u",
td->td_transferfunction[i][l]);
fputc('\n', fd);
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
fprintf(fd, " %3lu: [%8I64u, %8I64u]\n",
(unsigned long) s,
- (unsigned __int64) td->td_stripoffset[s],
- (unsigned __int64) td->td_stripbytecount[s]);
+ td->td_stripoffset ? (unsigned __int64) td->td_stripoffset[s] : 0,
+ td->td_stripbytecount ? (unsigned __int64) td->td_stripbytecount[s] : 0);
#else
fprintf(fd, " %3lu: [%8llu, %8llu]\n",
(unsigned long) s,
- (unsigned long long) td->td_stripoffset[s],
- (unsigned long long) td->td_stripbytecount[s]);
+ td->td_stripoffset ? (unsigned long long) td->td_stripoffset[s] : 0,
+ td->td_stripbytecount ? (unsigned long long) td->td_stripbytecount[s] : 0);
#endif
}
}
-/* $Id: tif_read.c,v 1.66 2017-11-17 20:21:00 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
int is_strip, uint32 strip_or_tile,
const char* module )
{
-#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8
+#if SIZEOF_SIZE_T == 8
tmsize_t threshold = INITIAL_THRESHOLD;
#endif
tmsize_t already_read = 0;
{
tmsize_t bytes_read;
tmsize_t to_read = size - already_read;
-#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8
+#if SIZEOF_SIZE_T == 8
if( to_read >= threshold && threshold < MAX_THRESHOLD &&
already_read + to_read + rawdata_offset > tif->tif_rawdatasize )
{
return 0;
whole_strip = tif->tif_dir.td_stripbytecount[strip] < 10
|| isMapped(tif);
+ if( td->td_compression == COMPRESSION_LERC ||
+ td->td_compression == COMPRESSION_JBIG )
+ {
+ /* Ideally plugins should have a way to declare they don't support
+ * chunk strip */
+ whole_strip = 1;
+ }
#else
whole_strip = 1;
#endif
-/* $Id: tif_stream.cxx,v 1.11 2010-12-11 23:12:29 faxguy Exp $ */
-
/*
* Copyright (c) 1988-1996 Sam Leffler
* Copyright (c) 1991-1996 Silicon Graphics, Inc.
*
- * Permission to use, copy, modify, distribute, and sell this software and
+ * Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that (i) the above copyright notices and this permission notice appear in
* all copies of the software and related documentation, and (ii) the names of
* Sam Leffler and Silicon Graphics may not be used in any advertising or
* publicity relating to the software without the specific, prior written
* permission of Sam Leffler and Silicon Graphics.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
- * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
* TIFF Library UNIX-specific Routines.
*/
#include "tiffiop.h"
-#include "tiffio.hxx"
#include <iostream>
#ifndef __VMS
extern "C" {
- static tmsize_t _tiffosReadProc(thandle_t, void*, tmsize_t);
- static tmsize_t _tiffisReadProc(thandle_t fd, void* buf, tmsize_t size);
- static tmsize_t _tiffosWriteProc(thandle_t fd, void* buf, tmsize_t size);
- static tmsize_t _tiffisWriteProc(thandle_t, void*, tmsize_t);
- static uint64 _tiffosSeekProc(thandle_t fd, uint64 off, int whence);
- static uint64 _tiffisSeekProc(thandle_t fd, uint64 off, int whence);
- static uint64 _tiffosSizeProc(thandle_t fd);
- static uint64 _tiffisSizeProc(thandle_t fd);
- static int _tiffosCloseProc(thandle_t fd);
- static int _tiffisCloseProc(thandle_t fd);
- static int _tiffDummyMapProc(thandle_t , void** base, toff_t* size );
- static void _tiffDummyUnmapProc(thandle_t , void* base, toff_t size );
- static TIFF* _tiffStreamOpen(const char* name, const char* mode, void *fd);
+ static tmsize_t _tiffosReadProc(thandle_t, void*, tmsize_t);
+ static tmsize_t _tiffisReadProc(thandle_t fd, void* buf, tmsize_t size);
+ static tmsize_t _tiffosWriteProc(thandle_t fd, void* buf, tmsize_t size);
+ static tmsize_t _tiffisWriteProc(thandle_t, void*, tmsize_t);
+ static uint64 _tiffosSeekProc(thandle_t fd, uint64 off, int whence);
+ static uint64 _tiffisSeekProc(thandle_t fd, uint64 off, int whence);
+ static uint64 _tiffosSizeProc(thandle_t fd);
+ static uint64 _tiffisSizeProc(thandle_t fd);
+ static int _tiffosCloseProc(thandle_t fd);
+ static int _tiffisCloseProc(thandle_t fd);
+ static int _tiffDummyMapProc(thandle_t , void** base, toff_t* size );
+ static void _tiffDummyUnmapProc(thandle_t , void* base, toff_t size );
+ static TIFF* _tiffStreamOpen(const char* name, const char* mode, void *fd);
struct tiffis_data
{
- istream *stream;
+ istream *stream;
ios::pos_type start_pos;
};
struct tiffos_data
{
- ostream *stream;
- ios::pos_type start_pos;
+ ostream *stream;
+ ios::pos_type start_pos;
};
static tmsize_t
static tmsize_t
_tiffosWriteProc(thandle_t fd, void* buf, tmsize_t size)
{
- tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
- ostream *os = data->stream;
- ios::pos_type pos = os->tellp();
+ tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
+ ostream *os = data->stream;
+ ios::pos_type pos = os->tellp();
// Verify that type does not overflow.
streamsize request_size = size;
if (static_cast<tmsize_t>(request_size) != size)
return static_cast<tmsize_t>(-1);
- os->write(reinterpret_cast<const char *>(buf), request_size);
+ os->write(reinterpret_cast<const char *>(buf), request_size);
- return static_cast<tmsize_t>(os->tellp() - pos);
+ return static_cast<tmsize_t>(os->tellp() - pos);
}
static tmsize_t
_tiffisWriteProc(thandle_t, void*, tmsize_t)
{
- return 0;
+ return 0;
}
static uint64
_tiffosSeekProc(thandle_t fd, uint64 off, int whence)
{
- tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
- ostream *os = data->stream;
-
- // if the stream has already failed, don't do anything
- if( os->fail() )
- return static_cast<uint64>(-1);
-
- switch(whence) {
- case SEEK_SET:
- {
- // Compute 64-bit offset
- uint64 new_offset = static_cast<uint64>(data->start_pos) + off;
-
- // Verify that value does not overflow
- ios::off_type offset = static_cast<ios::off_type>(new_offset);
- if (static_cast<uint64>(offset) != new_offset)
- return static_cast<uint64>(-1);
-
- os->seekp(offset, ios::beg);
- break;
- }
- case SEEK_CUR:
- {
- // Verify that value does not overflow
- ios::off_type offset = static_cast<ios::off_type>(off);
- if (static_cast<uint64>(offset) != off)
- return static_cast<uint64>(-1);
-
- os->seekp(offset, ios::cur);
- break;
- }
- case SEEK_END:
- {
- // Verify that value does not overflow
- ios::off_type offset = static_cast<ios::off_type>(off);
- if (static_cast<uint64>(offset) != off)
- return static_cast<uint64>(-1);
-
- os->seekp(offset, ios::end);
- break;
- }
- }
-
- // Attempt to workaround problems with seeking past the end of the
- // stream. ofstream doesn't have a problem with this but
- // ostrstream/ostringstream does. In that situation, add intermediate
- // '\0' characters.
- if( os->fail() ) {
+ tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
+ ostream *os = data->stream;
+
+ // if the stream has already failed, don't do anything
+ if( os->fail() )
+ return static_cast<uint64>(-1);
+
+ switch(whence) {
+ case SEEK_SET:
+ {
+ // Compute 64-bit offset
+ uint64 new_offset = static_cast<uint64>(data->start_pos) + off;
+
+ // Verify that value does not overflow
+ ios::off_type offset = static_cast<ios::off_type>(new_offset);
+ if (static_cast<uint64>(offset) != new_offset)
+ return static_cast<uint64>(-1);
+
+ os->seekp(offset, ios::beg);
+ break;
+ }
+ case SEEK_CUR:
+ {
+ // Verify that value does not overflow
+ ios::off_type offset = static_cast<ios::off_type>(off);
+ if (static_cast<uint64>(offset) != off)
+ return static_cast<uint64>(-1);
+
+ os->seekp(offset, ios::cur);
+ break;
+ }
+ case SEEK_END:
+ {
+ // Verify that value does not overflow
+ ios::off_type offset = static_cast<ios::off_type>(off);
+ if (static_cast<uint64>(offset) != off)
+ return static_cast<uint64>(-1);
+
+ os->seekp(offset, ios::end);
+ break;
+ }
+ }
+
+ // Attempt to workaround problems with seeking past the end of the
+ // stream. ofstream doesn't have a problem with this but
+ // ostrstream/ostringstream does. In that situation, add intermediate
+ // '\0' characters.
+ if( os->fail() ) {
#ifdef __VMS
- int old_state;
+ int old_state;
#else
- ios::iostate old_state;
+ ios::iostate old_state;
#endif
- ios::pos_type origin;
+ ios::pos_type origin;
- old_state = os->rdstate();
- // reset the fail bit or else tellp() won't work below
- os->clear(os->rdstate() & ~ios::failbit);
- switch( whence ) {
- case SEEK_SET:
+ old_state = os->rdstate();
+ // reset the fail bit or else tellp() won't work below
+ os->clear(os->rdstate() & ~ios::failbit);
+ switch( whence ) {
+ case SEEK_SET:
default:
- origin = data->start_pos;
- break;
- case SEEK_CUR:
- origin = os->tellp();
- break;
- case SEEK_END:
- os->seekp(0, ios::end);
- origin = os->tellp();
- break;
- }
- // restore original stream state
- os->clear(old_state);
-
- // only do something if desired seek position is valid
- if( (static_cast<uint64>(origin) + off) > static_cast<uint64>(data->start_pos) ) {
- uint64 num_fill;
-
- // clear the fail bit
- os->clear(os->rdstate() & ~ios::failbit);
-
- // extend the stream to the expected size
- os->seekp(0, ios::end);
- num_fill = (static_cast<uint64>(origin)) + off - os->tellp();
- for( uint64 i = 0; i < num_fill; i++ )
- os->put('\0');
-
- // retry the seek
- os->seekp(static_cast<ios::off_type>(static_cast<uint64>(origin) + off), ios::beg);
- }
- }
-
- return static_cast<uint64>(os->tellp());
+ origin = data->start_pos;
+ break;
+ case SEEK_CUR:
+ origin = os->tellp();
+ break;
+ case SEEK_END:
+ os->seekp(0, ios::end);
+ origin = os->tellp();
+ break;
+ }
+ // restore original stream state
+ os->clear(old_state);
+
+ // only do something if desired seek position is valid
+ if( (static_cast<uint64>(origin) + off) > static_cast<uint64>(data->start_pos) ) {
+ uint64 num_fill;
+
+ // clear the fail bit
+ os->clear(os->rdstate() & ~ios::failbit);
+
+ // extend the stream to the expected size
+ os->seekp(0, ios::end);
+ num_fill = (static_cast<uint64>(origin)) + off - os->tellp();
+ for( uint64 i = 0; i < num_fill; i++ )
+ os->put('\0');
+
+ // retry the seek
+ os->seekp(static_cast<ios::off_type>(static_cast<uint64>(origin) + off), ios::beg);
+ }
+ }
+
+ return static_cast<uint64>(os->tellp());
}
static uint64
_tiffisSeekProc(thandle_t fd, uint64 off, int whence)
{
- tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
-
- switch(whence) {
- case SEEK_SET:
- {
- // Compute 64-bit offset
- uint64 new_offset = static_cast<uint64>(data->start_pos) + off;
-
- // Verify that value does not overflow
- ios::off_type offset = static_cast<ios::off_type>(new_offset);
- if (static_cast<uint64>(offset) != new_offset)
- return static_cast<uint64>(-1);
-
- data->stream->seekg(offset, ios::beg);
- break;
- }
- case SEEK_CUR:
- {
- // Verify that value does not overflow
- ios::off_type offset = static_cast<ios::off_type>(off);
- if (static_cast<uint64>(offset) != off)
- return static_cast<uint64>(-1);
-
- data->stream->seekg(offset, ios::cur);
- break;
- }
- case SEEK_END:
- {
- // Verify that value does not overflow
- ios::off_type offset = static_cast<ios::off_type>(off);
- if (static_cast<uint64>(offset) != off)
- return static_cast<uint64>(-1);
-
- data->stream->seekg(offset, ios::end);
- break;
- }
- }
-
- return (uint64) (data->stream->tellg() - data->start_pos);
+ tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
+
+ switch(whence) {
+ case SEEK_SET:
+ {
+ // Compute 64-bit offset
+ uint64 new_offset = static_cast<uint64>(data->start_pos) + off;
+
+ // Verify that value does not overflow
+ ios::off_type offset = static_cast<ios::off_type>(new_offset);
+ if (static_cast<uint64>(offset) != new_offset)
+ return static_cast<uint64>(-1);
+
+ data->stream->seekg(offset, ios::beg);
+ break;
+ }
+ case SEEK_CUR:
+ {
+ // Verify that value does not overflow
+ ios::off_type offset = static_cast<ios::off_type>(off);
+ if (static_cast<uint64>(offset) != off)
+ return static_cast<uint64>(-1);
+
+ data->stream->seekg(offset, ios::cur);
+ break;
+ }
+ case SEEK_END:
+ {
+ // Verify that value does not overflow
+ ios::off_type offset = static_cast<ios::off_type>(off);
+ if (static_cast<uint64>(offset) != off)
+ return static_cast<uint64>(-1);
+
+ data->stream->seekg(offset, ios::end);
+ break;
+ }
+ }
+
+ return (uint64) (data->stream->tellg() - data->start_pos);
}
static uint64
_tiffosSizeProc(thandle_t fd)
{
- tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
- ostream *os = data->stream;
- ios::pos_type pos = os->tellp();
- ios::pos_type len;
+ tiffos_data *data = reinterpret_cast<tiffos_data *>(fd);
+ ostream *os = data->stream;
+ ios::pos_type pos = os->tellp();
+ ios::pos_type len;
- os->seekp(0, ios::end);
- len = os->tellp();
- os->seekp(pos);
+ os->seekp(0, ios::end);
+ len = os->tellp();
+ os->seekp(pos);
- return (uint64) len;
+ return (uint64) len;
}
static uint64
_tiffisSizeProc(thandle_t fd)
{
- tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
- ios::pos_type pos = data->stream->tellg();
- ios::pos_type len;
+ tiffis_data *data = reinterpret_cast<tiffis_data *>(fd);
+ ios::pos_type pos = data->stream->tellg();
+ ios::pos_type len;
- data->stream->seekg(0, ios::end);
- len = data->stream->tellg();
- data->stream->seekg(pos);
+ data->stream->seekg(0, ios::end);
+ len = data->stream->tellg();
+ data->stream->seekg(pos);
- return (uint64) len;
+ return (uint64) len;
}
static int
_tiffosCloseProc(thandle_t fd)
{
- // Our stream was not allocated by us, so it shouldn't be closed by us.
- delete reinterpret_cast<tiffos_data *>(fd);
- return 0;
+ // Our stream was not allocated by us, so it shouldn't be closed by us.
+ delete reinterpret_cast<tiffos_data *>(fd);
+ return 0;
}
static int
_tiffisCloseProc(thandle_t fd)
{
- // Our stream was not allocated by us, so it shouldn't be closed by us.
- delete reinterpret_cast<tiffis_data *>(fd);
- return 0;
+ // Our stream was not allocated by us, so it shouldn't be closed by us.
+ delete reinterpret_cast<tiffis_data *>(fd);
+ return 0;
}
static int
_tiffDummyMapProc(thandle_t , void** base, toff_t* size )
{
- return (0);
+ (void) base;
+ (void) size;
+ return (0);
}
static void
_tiffDummyUnmapProc(thandle_t , void* base, toff_t size )
{
+ (void) base;
+ (void) size;
}
/*
static TIFF*
_tiffStreamOpen(const char* name, const char* mode, void *fd)
{
- TIFF* tif;
+ TIFF* tif;
- if( strchr(mode, 'w') ) {
- tiffos_data *data = new tiffos_data;
- data->stream = reinterpret_cast<ostream *>(fd);
- data->start_pos = data->stream->tellp();
+ if( strchr(mode, 'w') ) {
+ tiffos_data *data = new tiffos_data;
+ data->stream = reinterpret_cast<ostream *>(fd);
+ data->start_pos = data->stream->tellp();
- // Open for writing.
- tif = TIFFClientOpen(name, mode,
- reinterpret_cast<thandle_t>(data),
- _tiffosReadProc,
+ // Open for writing.
+ tif = TIFFClientOpen(name, mode,
+ reinterpret_cast<thandle_t>(data),
+ _tiffosReadProc,
_tiffosWriteProc,
- _tiffosSeekProc,
+ _tiffosSeekProc,
_tiffosCloseProc,
- _tiffosSizeProc,
- _tiffDummyMapProc,
+ _tiffosSizeProc,
+ _tiffDummyMapProc,
_tiffDummyUnmapProc);
- } else {
- tiffis_data *data = new tiffis_data;
- data->stream = reinterpret_cast<istream *>(fd);
- data->start_pos = data->stream->tellg();
- // Open for reading.
- tif = TIFFClientOpen(name, mode,
- reinterpret_cast<thandle_t>(data),
- _tiffisReadProc,
+ if (!tif) {
+ delete data;
+ }
+ } else {
+ tiffis_data *data = new tiffis_data;
+ data->stream = reinterpret_cast<istream *>(fd);
+ data->start_pos = data->stream->tellg();
+ // Open for reading.
+ tif = TIFFClientOpen(name, mode,
+ reinterpret_cast<thandle_t>(data),
+ _tiffisReadProc,
_tiffisWriteProc,
- _tiffisSeekProc,
+ _tiffisSeekProc,
_tiffisCloseProc,
- _tiffisSizeProc,
- _tiffDummyMapProc,
+ _tiffisSizeProc,
+ _tiffDummyMapProc,
_tiffDummyUnmapProc);
- }
+ if (!tif) {
+ delete data;
+ }
+ }
- return (tif);
+ return (tif);
}
} /* extern "C" */
TIFF*
TIFFStreamOpen(const char* name, ostream *os)
{
- // If os is either a ostrstream or ostringstream, and has no data
- // written to it yet, then tellp() will return -1 which will break us.
- // We workaround this by writing out a dummy character and
- // then seek back to the beginning.
- if( !os->fail() && static_cast<int>(os->tellp()) < 0 ) {
- *os << '\0';
- os->seekp(0);
- }
-
- // NB: We don't support mapped files with streams so add 'm'
- return _tiffStreamOpen(name, "wm", os);
+ // If os is either a ostrstream or ostringstream, and has no data
+ // written to it yet, then tellp() will return -1 which will break us.
+ // We workaround this by writing out a dummy character and
+ // then seek back to the beginning.
+ if( !os->fail() && static_cast<int>(os->tellp()) < 0 ) {
+ *os << '\0';
+ os->seekp(0);
+ }
+
+ // NB: We don't support mapped files with streams so add 'm'
+ return _tiffStreamOpen(name, "wm", os);
}
TIFF*
TIFFStreamOpen(const char* name, istream *is)
{
- // NB: We don't support mapped files with streams so add 'm'
- return _tiffStreamOpen(name, "rm", is);
+ // NB: We don't support mapped files with streams so add 'm'
+ return _tiffStreamOpen(name, "rm", is);
}
/* vim: set ts=8 sts=8 sw=8 noet: */
/*
- Local Variables:
- mode: c
- indent-tabs-mode: true
- c-basic-offset: 8
- End:
-*/
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 8
+ * fill-column: 78
+ * End:
+ */
+
-/* $Id: tif_strip.c,v 1.38 2016-12-03 11:02:15 erouault Exp $ */
-
/*
* Copyright (c) 1991-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_swab.c,v 1.15 2017-06-08 16:39:50 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_thunder.c,v 1.13 2016-09-04 21:32:56 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_tile.c,v 1.24 2015-06-07 22:35:40 bfriesen Exp $ */
-
/*
* Copyright (c) 1991-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Id: tif_unix.c,v 1.28 2017-01-11 19:02:49 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
-/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_version.c,v 1.3 2010-03-10 18:56:49 bfriesen Exp $ */
/*
* Copyright (c) 1992-1997 Sam Leffler
* Copyright (c) 1992-1997 Silicon Graphics, Inc.
-/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_warning.c,v 1.4 2017-07-04 12:54:42 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
--- /dev/null
+/*
+* Copyright (c) 2018, Mapbox
+* Author: <norman.barker at mapbox.com>
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee, provided
+* that (i) the above copyright notices and this permission notice appear in
+* all copies of the software and related documentation, and (ii) the names of
+* Sam Leffler and Silicon Graphics may not be used in any advertising or
+* publicity relating to the software without the specific, prior written
+* permission of Sam Leffler and Silicon Graphics.
+*
+* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+*
+* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+* OF THIS SOFTWARE.
+*/
+
+#include "tiffiop.h"
+#ifdef WEBP_SUPPORT
+/*
+ * TIFF Library.
+ *
+ * WEBP Compression Support
+ *
+ */
+
+#include "webp/decode.h"
+#include "webp/encode.h"
+
+#include <stdio.h>
+
+#define LSTATE_INIT_DECODE 0x01
+#define LSTATE_INIT_ENCODE 0x02
+/*
+ * State block for each open TIFF
+ * file using WEBP compression/decompression.
+ */
+typedef struct {
+ uint16 nSamples; /* number of samples per pixel */
+
+ int lossless; /* lossy/lossless compression */
+ int quality_level; /* compression level */
+ WebPPicture sPicture; /* WebP Picture */
+ WebPConfig sEncoderConfig; /* WebP encoder config */
+ uint8* pBuffer; /* buffer to hold raw data on encoding */
+ unsigned int buffer_offset; /* current offset into the buffer */
+ unsigned int buffer_size;
+
+ WebPIDecoder* psDecoder; /* WebPIDecoder */
+ WebPDecBuffer sDecBuffer; /* Decoder buffer */
+ int last_y; /* Last row decoded */
+
+ int state; /* state flags */
+
+ TIFFVGetMethod vgetparent; /* super-class method */
+ TIFFVSetMethod vsetparent; /* super-class method */
+} WebPState;
+
+#define LState(tif) ((WebPState*) (tif)->tif_data)
+#define DecoderState(tif) LState(tif)
+#define EncoderState(tif) LState(tif)
+
+static int TWebPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s);
+static int TWebPDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s);
+
+static
+int TWebPDatasetWriter(const uint8_t* data, size_t data_size,
+ const WebPPicture* const picture)
+{
+ static const char module[] = "TWebPDatasetWriter";
+ TIFF* tif = (TIFF*)(picture->custom_ptr);
+
+ if ( (tif->tif_rawcc + (tmsize_t)data_size) > tif->tif_rawdatasize ) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Buffer too small by " TIFF_SIZE_FORMAT " bytes.",
+ (size_t) (tif->tif_rawcc + data_size - tif->tif_rawdatasize));
+ return 0;
+ } else {
+ _TIFFmemcpy(tif->tif_rawcp, data, data_size);
+ tif->tif_rawcc += data_size;
+ tif->tif_rawcp += data_size;
+ return 1;
+ }
+}
+
+/*
+ * Encode a chunk of pixels.
+ */
+static int
+TWebPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
+{
+ static const char module[] = "TWebPEncode";
+ WebPState *sp = EncoderState(tif);
+ (void) s;
+
+ assert(sp != NULL);
+ assert(sp->state == LSTATE_INIT_ENCODE);
+
+ if( (uint64)sp->buffer_offset +
+ (uint64)cc > sp->buffer_size )
+ {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Too many bytes to be written");
+ return 0;
+ }
+
+ memcpy(sp->pBuffer + sp->buffer_offset,
+ bp, cc);
+ sp->buffer_offset += (unsigned)cc;
+
+ return 1;
+
+}
+
+static int
+TWebPDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
+{
+ static const char module[] = "WebPDecode";
+ VP8StatusCode status = VP8_STATUS_OK;
+ WebPState *sp = DecoderState(tif);
+ (void) s;
+
+ assert(sp != NULL);
+ assert(sp->state == LSTATE_INIT_DECODE);
+
+ if (occ % sp->sDecBuffer.u.RGBA.stride)
+ {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Fractional scanlines cannot be read");
+ return 0;
+ }
+
+ status = WebPIAppend(sp->psDecoder, tif->tif_rawcp, tif->tif_rawcc);
+
+ if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) {
+ if (status == VP8_STATUS_INVALID_PARAM) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Invalid parameter used.");
+ } else if (status == VP8_STATUS_OUT_OF_MEMORY) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Out of memory.");
+ } else {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Unrecognized error.");
+ }
+ return 0;
+ } else {
+ int current_y, stride;
+ uint8_t* buf;
+
+ /* Returns the RGB/A image decoded so far */
+ buf = WebPIDecGetRGB(sp->psDecoder, ¤t_y, NULL, NULL, &stride);
+
+ if ((buf != NULL) &&
+ (occ <= stride * (current_y - sp->last_y))) {
+ memcpy(op,
+ buf + (sp->last_y * stride),
+ occ);
+
+ tif->tif_rawcp += tif->tif_rawcc;
+ tif->tif_rawcc = 0;
+ sp->last_y += occ / sp->sDecBuffer.u.RGBA.stride;
+ return 1;
+ } else {
+ TIFFErrorExt(tif->tif_clientdata, module, "Unable to decode WebP data.");
+ return 0;
+ }
+ }
+}
+
+static int
+TWebPFixupTags(TIFF* tif)
+{
+ (void) tif;
+ if (tif->tif_dir.td_planarconfig != PLANARCONFIG_CONTIG) {
+ static const char module[] = "TWebPFixupTags";
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "TIFF WEBP requires data to be stored contiguously in RGB e.g. RGBRGBRGB "
+#if WEBP_ENCODER_ABI_VERSION >= 0x0100
+ "or RGBARGBARGBA"
+#endif
+ );
+ return 0;
+ }
+ return 1;
+}
+
+static int
+TWebPSetupDecode(TIFF* tif)
+{
+ static const char module[] = "WebPSetupDecode";
+ uint16 nBitsPerSample = tif->tif_dir.td_bitspersample;
+ uint16 sampleFormat = tif->tif_dir.td_sampleformat;
+
+ WebPState* sp = DecoderState(tif);
+ assert(sp != NULL);
+
+ sp->nSamples = tif->tif_dir.td_samplesperpixel;
+
+ /* check band count */
+ if ( sp->nSamples != 3
+#if WEBP_ENCODER_ABI_VERSION >= 0x0100
+ && sp->nSamples != 4
+#endif
+ )
+ {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "WEBP driver doesn't support %d bands. Must be 3 (RGB) "
+ #if WEBP_ENCODER_ABI_VERSION >= 0x0100
+ "or 4 (RGBA) "
+ #endif
+ "bands.",
+ sp->nSamples );
+ return 0;
+ }
+
+ /* check bits per sample and data type */
+ if ((nBitsPerSample != 8) && (sampleFormat != 1)) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "WEBP driver requires 8 bit unsigned data");
+ return 0;
+ }
+
+ /* if we were last encoding, terminate this mode */
+ if (sp->state & LSTATE_INIT_ENCODE) {
+ WebPPictureFree(&sp->sPicture);
+ if (sp->pBuffer != NULL) {
+ _TIFFfree(sp->pBuffer);
+ sp->pBuffer = NULL;
+ }
+ sp->buffer_offset = 0;
+ sp->state = 0;
+ }
+
+ sp->state |= LSTATE_INIT_DECODE;
+
+ return 1;
+}
+
+/*
+* Setup state for decoding a strip.
+*/
+static int
+TWebPPreDecode(TIFF* tif, uint16 s)
+{
+ static const char module[] = "TWebPPreDecode";
+ uint32 segment_width, segment_height;
+ WebPState* sp = DecoderState(tif);
+ TIFFDirectory* td = &tif->tif_dir;
+ (void) s;
+ assert(sp != NULL);
+
+ if (isTiled(tif)) {
+ segment_width = td->td_tilewidth;
+ segment_height = td->td_tilelength;
+ } else {
+ segment_width = td->td_imagewidth;
+ segment_height = td->td_imagelength - tif->tif_row;
+ if (segment_height > td->td_rowsperstrip)
+ segment_height = td->td_rowsperstrip;
+ }
+
+ if( (sp->state & LSTATE_INIT_DECODE) == 0 )
+ tif->tif_setupdecode(tif);
+
+ if (sp->psDecoder != NULL) {
+ WebPIDelete(sp->psDecoder);
+ WebPFreeDecBuffer(&sp->sDecBuffer);
+ sp->psDecoder = NULL;
+ }
+
+ sp->last_y = 0;
+
+ WebPInitDecBuffer(&sp->sDecBuffer);
+
+ sp->sDecBuffer.is_external_memory = 0;
+ sp->sDecBuffer.width = segment_width;
+ sp->sDecBuffer.height = segment_height;
+ sp->sDecBuffer.u.RGBA.stride = segment_width * sp->nSamples;
+ sp->sDecBuffer.u.RGBA.size = segment_width * sp->nSamples * segment_height;
+
+ if (sp->nSamples > 3) {
+ sp->sDecBuffer.colorspace = MODE_RGBA;
+ } else {
+ sp->sDecBuffer.colorspace = MODE_RGB;
+ }
+
+ sp->psDecoder = WebPINewDecoder(&sp->sDecBuffer);
+
+ if (sp->psDecoder == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Unable to allocate WebP decoder.");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+TWebPSetupEncode(TIFF* tif)
+{
+ static const char module[] = "WebPSetupEncode";
+ uint16 nBitsPerSample = tif->tif_dir.td_bitspersample;
+ uint16 sampleFormat = tif->tif_dir.td_sampleformat;
+
+ WebPState* sp = EncoderState(tif);
+ assert(sp != NULL);
+
+ sp->nSamples = tif->tif_dir.td_samplesperpixel;
+
+ /* check band count */
+ if ( sp->nSamples != 3
+#if WEBP_ENCODER_ABI_VERSION >= 0x0100
+ && sp->nSamples != 4
+#endif
+ )
+ {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "WEBP driver doesn't support %d bands. Must be 3 (RGB) "
+#if WEBP_ENCODER_ABI_VERSION >= 0x0100
+ "or 4 (RGBA) "
+#endif
+ "bands.",
+ sp->nSamples );
+ return 0;
+ }
+
+ /* check bits per sample and data type */
+ if ((nBitsPerSample != 8) && (sampleFormat != 1)) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "WEBP driver requires 8 bit unsigned data");
+ return 0;
+ }
+
+ if (sp->state & LSTATE_INIT_DECODE) {
+ WebPIDelete(sp->psDecoder);
+ WebPFreeDecBuffer(&sp->sDecBuffer);
+ sp->psDecoder = NULL;
+ sp->last_y = 0;
+ sp->state = 0;
+ }
+
+ sp->state |= LSTATE_INIT_ENCODE;
+
+ if (!WebPConfigInitInternal(&sp->sEncoderConfig, WEBP_PRESET_DEFAULT,
+ sp->quality_level,
+ WEBP_ENCODER_ABI_VERSION)) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error creating WebP encoder configuration.");
+ return 0;
+ }
+
+#if WEBP_ENCODER_ABI_VERSION >= 0x0100
+ sp->sEncoderConfig.lossless = sp->lossless;
+#endif
+
+ if (!WebPValidateConfig(&sp->sEncoderConfig)) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error with WebP encoder configuration.");
+ return 0;
+ }
+
+ if (!WebPPictureInit(&sp->sPicture)) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error initializing WebP picture.");
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+* Reset encoding state at the start of a strip.
+*/
+static int
+TWebPPreEncode(TIFF* tif, uint16 s)
+{
+ static const char module[] = "TWebPPreEncode";
+ uint32 segment_width, segment_height;
+ WebPState *sp = EncoderState(tif);
+ TIFFDirectory* td = &tif->tif_dir;
+
+ (void) s;
+
+ assert(sp != NULL);
+ if( sp->state != LSTATE_INIT_ENCODE )
+ tif->tif_setupencode(tif);
+
+ /*
+ * Set encoding parameters for this strip/tile.
+ */
+ if (isTiled(tif)) {
+ segment_width = td->td_tilewidth;
+ segment_height = td->td_tilelength;
+ } else {
+ segment_width = td->td_imagewidth;
+ segment_height = td->td_imagelength - tif->tif_row;
+ if (segment_height > td->td_rowsperstrip)
+ segment_height = td->td_rowsperstrip;
+ }
+
+ if( segment_width > 16383 || segment_height > 16383 ) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "WEBP maximum image dimensions are 16383 x 16383.");
+ return 0;
+ }
+
+ /* set up buffer for raw data */
+ /* given above check and that nSamples <= 4, buffer_size is <= 1 GB */
+ sp->buffer_size = segment_width * segment_height * sp->nSamples;
+ sp->pBuffer = _TIFFmalloc(sp->buffer_size);
+ if( !sp->pBuffer) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Cannot allocate buffer");
+ return 0;
+ }
+ sp->buffer_offset = 0;
+
+ sp->sPicture.width = segment_width;
+ sp->sPicture.height = segment_height;
+ sp->sPicture.writer = TWebPDatasetWriter;
+ sp->sPicture.custom_ptr = tif;
+
+ return 1;
+}
+
+/*
+* Finish off an encoded strip by flushing it.
+*/
+static int
+TWebPPostEncode(TIFF* tif)
+{
+ static const char module[] = "WebPPostEncode";
+ int64_t stride;
+ WebPState *sp = EncoderState(tif);
+ assert(sp != NULL);
+
+ assert(sp->state == LSTATE_INIT_ENCODE);
+
+ stride = (int64_t)sp->sPicture.width * sp->nSamples;
+
+#if WEBP_ENCODER_ABI_VERSION >= 0x0100
+ if (sp->nSamples == 4) {
+ if (!WebPPictureImportRGBA(&sp->sPicture, sp->pBuffer, (int)stride)) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "WebPPictureImportRGBA() failed" );
+ return 0;
+ }
+ }
+ else
+#endif
+ if (!WebPPictureImportRGB(&sp->sPicture, sp->pBuffer, (int)stride)) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "WebPPictureImportRGB() failed");
+ return 0;
+ }
+
+ if (!WebPEncode(&sp->sEncoderConfig, &sp->sPicture)) {
+
+#if WEBP_ENCODER_ABI_VERSION >= 0x0100
+ const char* pszErrorMsg = NULL;
+ switch(sp->sPicture.error_code) {
+ case VP8_ENC_ERROR_OUT_OF_MEMORY:
+ pszErrorMsg = "Out of memory"; break;
+ case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY:
+ pszErrorMsg = "Out of memory while flushing bits"; break;
+ case VP8_ENC_ERROR_NULL_PARAMETER:
+ pszErrorMsg = "A pointer parameter is NULL"; break;
+ case VP8_ENC_ERROR_INVALID_CONFIGURATION:
+ pszErrorMsg = "Configuration is invalid"; break;
+ case VP8_ENC_ERROR_BAD_DIMENSION:
+ pszErrorMsg = "Picture has invalid width/height"; break;
+ case VP8_ENC_ERROR_PARTITION0_OVERFLOW:
+ pszErrorMsg = "Partition is bigger than 512k. Try using less "
+ "SEGMENTS, or increase PARTITION_LIMIT value";
+ break;
+ case VP8_ENC_ERROR_PARTITION_OVERFLOW:
+ pszErrorMsg = "Partition is bigger than 16M";
+ break;
+ case VP8_ENC_ERROR_BAD_WRITE:
+ pszErrorMsg = "Error while fludshing bytes"; break;
+ case VP8_ENC_ERROR_FILE_TOO_BIG:
+ pszErrorMsg = "File is bigger than 4G"; break;
+ case VP8_ENC_ERROR_USER_ABORT:
+ pszErrorMsg = "User interrupted";
+ break;
+ default:
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "WebPEncode returned an unknown error code: %d",
+ sp->sPicture.error_code);
+ pszErrorMsg = "Unknown WebP error type.";
+ break;
+ }
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "WebPEncode() failed : %s", pszErrorMsg);
+#else
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error in WebPEncode()");
+#endif
+ return 0;
+ }
+
+ sp->sPicture.custom_ptr = NULL;
+
+ if (!TIFFFlushData1(tif))
+ {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error flushing TIFF WebP encoder.");
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+TWebPCleanup(TIFF* tif)
+{
+ WebPState* sp = LState(tif);
+
+ assert(sp != 0);
+
+ tif->tif_tagmethods.vgetfield = sp->vgetparent;
+ tif->tif_tagmethods.vsetfield = sp->vsetparent;
+
+ if (sp->state & LSTATE_INIT_ENCODE) {
+ WebPPictureFree(&sp->sPicture);
+ }
+
+ if (sp->psDecoder != NULL) {
+ WebPIDelete(sp->psDecoder);
+ WebPFreeDecBuffer(&sp->sDecBuffer);
+ sp->psDecoder = NULL;
+ sp->last_y = 0;
+ }
+
+ if (sp->pBuffer != NULL) {
+ _TIFFfree(sp->pBuffer);
+ sp->pBuffer = NULL;
+ }
+
+ if (tif->tif_data) {
+ _TIFFfree(tif->tif_data);
+ tif->tif_data = NULL;
+ }
+
+ _TIFFSetDefaultCompressionState(tif);
+}
+
+static int
+TWebPVSetField(TIFF* tif, uint32 tag, va_list ap)
+{
+ static const char module[] = "WebPVSetField";
+ WebPState* sp = LState(tif);
+
+ switch (tag) {
+ case TIFFTAG_WEBP_LEVEL:
+ sp->quality_level = (int) va_arg(ap, int);
+ if( sp->quality_level <= 0 ||
+ sp->quality_level > 100.0f ) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "WEBP_LEVEL should be between 1 and 100");
+ }
+ return 1;
+ case TIFFTAG_WEBP_LOSSLESS:
+ #if WEBP_ENCODER_ABI_VERSION >= 0x0100
+ sp->lossless = va_arg(ap, int);
+ return 1;
+ #else
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Need to upgrade WEBP driver, this version doesn't support "
+ "lossless compression.");
+ return 0;
+ #endif
+ default:
+ return (*sp->vsetparent)(tif, tag, ap);
+ }
+ /*NOTREACHED*/
+}
+
+static int
+TWebPVGetField(TIFF* tif, uint32 tag, va_list ap)
+{
+ WebPState* sp = LState(tif);
+
+ switch (tag) {
+ case TIFFTAG_WEBP_LEVEL:
+ *va_arg(ap, int*) = sp->quality_level;
+ break;
+ case TIFFTAG_WEBP_LOSSLESS:
+ *va_arg(ap, int*) = sp->lossless;
+ break;
+ default:
+ return (*sp->vgetparent)(tif, tag, ap);
+ }
+ return 1;
+}
+
+static const TIFFField TWebPFields[] = {
+ { TIFFTAG_WEBP_LEVEL, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
+ TIFF_SETGET_UNDEFINED,
+ FIELD_PSEUDO, TRUE, FALSE, "WEBP quality", NULL },
+ { TIFFTAG_WEBP_LOSSLESS, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
+ TIFF_SETGET_UNDEFINED,
+ FIELD_PSEUDO, TRUE, FALSE, "WEBP lossless/lossy", NULL
+ },
+};
+
+int
+TIFFInitWebP(TIFF* tif, int scheme)
+{
+ static const char module[] = "TIFFInitWebP";
+ WebPState* sp;
+
+ assert( scheme == COMPRESSION_WEBP );
+
+ /*
+ * Merge codec-specific tag information.
+ */
+ if ( !_TIFFMergeFields(tif, TWebPFields, TIFFArrayCount(TWebPFields)) ) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Merging WebP codec-specific tags failed");
+ return 0;
+ }
+
+ /*
+ * Allocate state block so tag methods have storage to record values.
+ */
+ tif->tif_data = (uint8*) _TIFFmalloc(sizeof(WebPState));
+ if (tif->tif_data == NULL)
+ goto bad;
+ sp = LState(tif);
+
+ /*
+ * Override parent get/set field methods.
+ */
+ sp->vgetparent = tif->tif_tagmethods.vgetfield;
+ tif->tif_tagmethods.vgetfield = TWebPVGetField; /* hook for codec tags */
+ sp->vsetparent = tif->tif_tagmethods.vsetfield;
+ tif->tif_tagmethods.vsetfield = TWebPVSetField; /* hook for codec tags */
+
+ /* Default values for codec-specific fields */
+ sp->quality_level = 75.0f; /* default comp. level */
+ sp->lossless = 0; /* default to false */
+ sp->state = 0;
+ sp->nSamples = 0;
+ sp->psDecoder = NULL;
+ sp->last_y = 0;
+
+ sp->buffer_offset = 0;
+ sp->pBuffer = NULL;
+
+ /*
+ * Install codec methods.
+ * Notes:
+ * encoderow is not supported
+ */
+ tif->tif_fixuptags = TWebPFixupTags;
+ tif->tif_setupdecode = TWebPSetupDecode;
+ tif->tif_predecode = TWebPPreDecode;
+ tif->tif_decoderow = TWebPDecode;
+ tif->tif_decodestrip = TWebPDecode;
+ tif->tif_decodetile = TWebPDecode;
+ tif->tif_setupencode = TWebPSetupEncode;
+ tif->tif_preencode = TWebPPreEncode;
+ tif->tif_postencode = TWebPPostEncode;
+ tif->tif_encoderow = TWebPEncode;
+ tif->tif_encodestrip = TWebPEncode;
+ tif->tif_encodetile = TWebPEncode;
+ tif->tif_cleanup = TWebPCleanup;
+
+ return 1;
+bad:
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "No space for WebP state block");
+ return 0;
+}
+
+#endif /* WEBP_SUPPORT */
-/* $Id: tif_win32.c,v 1.42 2017-01-11 19:02:49 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
static void
Win32WarningHandler(const char* module, const char* fmt, va_list ap)
{
-#ifndef TIF_PLATFORM_CONSOLE
- LPTSTR szTitle;
- LPTSTR szTmp;
- LPCTSTR szTitleText = "%s Warning";
- LPCTSTR szDefaultModule = "LIBTIFF";
- LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module;
- SIZE_T nBufSize = (strlen(szTmpModule) +
- strlen(szTitleText) + strlen(fmt) + 256)*sizeof(char);
-
- if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, nBufSize)) == NULL)
- return;
- sprintf(szTitle, szTitleText, szTmpModule);
- szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char);
- vsnprintf(szTmp, nBufSize-(strlen(szTitle)+2)*sizeof(char), fmt, ap);
- MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONINFORMATION);
- LocalFree(szTitle);
-
- return;
-#else
if (module != NULL)
fprintf(stderr, "%s: ", module);
fprintf(stderr, "Warning, ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, ".\n");
-#endif
}
TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler;
static void
Win32ErrorHandler(const char* module, const char* fmt, va_list ap)
{
-#ifndef TIF_PLATFORM_CONSOLE
- LPTSTR szTitle;
- LPTSTR szTmp;
- LPCTSTR szTitleText = "%s Error";
- LPCTSTR szDefaultModule = "LIBTIFF";
- LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module;
- SIZE_T nBufSize = (strlen(szTmpModule) +
- strlen(szTitleText) + strlen(fmt) + 256)*sizeof(char);
-
- if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, nBufSize)) == NULL)
- return;
- sprintf(szTitle, szTitleText, szTmpModule);
- szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char);
- vsnprintf(szTmp, nBufSize-(strlen(szTitle)+2)*sizeof(char), fmt, ap);
- MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION);
- LocalFree(szTitle);
- return;
-#else
if (module != NULL)
fprintf(stderr, "%s: ", module);
vfprintf(stderr, fmt, ap);
fprintf(stderr, ".\n");
-#endif
}
TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler;
-/* $Id: tif_write.c,v 1.46 2016-12-03 21:57:44 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
td->td_stripsperimage /= td->td_samplesperpixel;
td->td_stripoffset = (uint64 *)
- _TIFFmalloc(td->td_nstrips * sizeof (uint64));
+ _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64),
+ "for \"StripOffsets\" array");
td->td_stripbytecount = (uint64 *)
- _TIFFmalloc(td->td_nstrips * sizeof (uint64));
+ _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64),
+ "for \"StripByteCounts\" array");
if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
return (0);
/*
-/* $Id: tif_zip.c,v 1.37 2017-05-10 15:21:16 erouault Exp $ */
-
/*
* Copyright (c) 1995-1997 Sam Leffler
* Copyright (c) 1995-1997 Silicon Graphics, Inc.
--- /dev/null
+/*
+* Copyright (c) 2017, Planet Labs
+* Author: <even.rouault at spatialys.com>
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee, provided
+* that (i) the above copyright notices and this permission notice appear in
+* all copies of the software and related documentation, and (ii) the names of
+* Sam Leffler and Silicon Graphics may not be used in any advertising or
+* publicity relating to the software without the specific, prior written
+* permission of Sam Leffler and Silicon Graphics.
+*
+* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+*
+* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+* OF THIS SOFTWARE.
+*/
+
+#include "tiffiop.h"
+#ifdef ZSTD_SUPPORT
+/*
+* TIFF Library.
+*
+* ZSTD Compression Support
+*
+*/
+
+#include "tif_predict.h"
+#include "zstd.h"
+
+#include <stdio.h>
+
+/*
+* State block for each open TIFF file using ZSTD compression/decompression.
+*/
+typedef struct {
+ TIFFPredictorState predict;
+ ZSTD_DStream* dstream;
+ ZSTD_CStream* cstream;
+ int compression_level; /* compression level */
+ ZSTD_outBuffer out_buffer;
+ int state; /* state flags */
+#define LSTATE_INIT_DECODE 0x01
+#define LSTATE_INIT_ENCODE 0x02
+
+ TIFFVGetMethod vgetparent; /* super-class method */
+ TIFFVSetMethod vsetparent; /* super-class method */
+} ZSTDState;
+
+#define LState(tif) ((ZSTDState*) (tif)->tif_data)
+#define DecoderState(tif) LState(tif)
+#define EncoderState(tif) LState(tif)
+
+static int ZSTDEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s);
+static int ZSTDDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s);
+
+static int
+ZSTDFixupTags(TIFF* tif)
+{
+ (void) tif;
+ return 1;
+}
+
+static int
+ZSTDSetupDecode(TIFF* tif)
+{
+ ZSTDState* sp = DecoderState(tif);
+
+ assert(sp != NULL);
+
+ /* if we were last encoding, terminate this mode */
+ if (sp->state & LSTATE_INIT_ENCODE) {
+ ZSTD_freeCStream(sp->cstream);
+ sp->cstream = NULL;
+ sp->state = 0;
+ }
+
+ sp->state |= LSTATE_INIT_DECODE;
+ return 1;
+}
+
+/*
+* Setup state for decoding a strip.
+*/
+static int
+ZSTDPreDecode(TIFF* tif, uint16 s)
+{
+ static const char module[] = "ZSTDPreDecode";
+ ZSTDState* sp = DecoderState(tif);
+ size_t zstd_ret;
+
+ (void) s;
+ assert(sp != NULL);
+
+ if( (sp->state & LSTATE_INIT_DECODE) == 0 )
+ tif->tif_setupdecode(tif);
+
+ if( sp->dstream )
+ {
+ ZSTD_freeDStream(sp->dstream);
+ sp->dstream = NULL;
+ }
+
+ sp->dstream = ZSTD_createDStream();
+ if( sp->dstream == NULL ) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Cannot allocate decompression stream");
+ return 0;
+ }
+ zstd_ret = ZSTD_initDStream(sp->dstream);
+ if( ZSTD_isError(zstd_ret) ) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error in ZSTD_initDStream(): %s",
+ ZSTD_getErrorName(zstd_ret));
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+ZSTDDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
+{
+ static const char module[] = "ZSTDDecode";
+ ZSTDState* sp = DecoderState(tif);
+ ZSTD_inBuffer in_buffer;
+ ZSTD_outBuffer out_buffer;
+ size_t zstd_ret;
+
+ (void) s;
+ assert(sp != NULL);
+ assert(sp->state == LSTATE_INIT_DECODE);
+
+ in_buffer.src = tif->tif_rawcp;
+ in_buffer.size = (size_t) tif->tif_rawcc;
+ in_buffer.pos = 0;
+
+ out_buffer.dst = op;
+ out_buffer.size = (size_t) occ;
+ out_buffer.pos = 0;
+
+ do {
+ zstd_ret = ZSTD_decompressStream(sp->dstream, &out_buffer,
+ &in_buffer);
+ if( ZSTD_isError(zstd_ret) ) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error in ZSTD_decompressStream(): %s",
+ ZSTD_getErrorName(zstd_ret));
+ return 0;
+ }
+ } while( zstd_ret != 0 &&
+ in_buffer.pos < in_buffer.size &&
+ out_buffer.pos < out_buffer.size );
+
+ if (out_buffer.pos < (size_t)occ) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Not enough data at scanline %lu (short %lu bytes)",
+ (unsigned long) tif->tif_row,
+ (unsigned long) (size_t)occ - out_buffer.pos);
+ return 0;
+ }
+
+ tif->tif_rawcp += in_buffer.pos;
+ tif->tif_rawcc -= in_buffer.pos;
+
+ return 1;
+}
+
+static int
+ZSTDSetupEncode(TIFF* tif)
+{
+ ZSTDState* sp = EncoderState(tif);
+
+ assert(sp != NULL);
+ if (sp->state & LSTATE_INIT_DECODE) {
+ ZSTD_freeDStream(sp->dstream);
+ sp->dstream = NULL;
+ sp->state = 0;
+ }
+
+ sp->state |= LSTATE_INIT_ENCODE;
+ return 1;
+}
+
+/*
+* Reset encoding state at the start of a strip.
+*/
+static int
+ZSTDPreEncode(TIFF* tif, uint16 s)
+{
+ static const char module[] = "ZSTDPreEncode";
+ ZSTDState *sp = EncoderState(tif);
+ size_t zstd_ret;
+
+ (void) s;
+ assert(sp != NULL);
+ if( sp->state != LSTATE_INIT_ENCODE )
+ tif->tif_setupencode(tif);
+
+ if (sp->cstream) {
+ ZSTD_freeCStream(sp->cstream);
+ sp->cstream = NULL;
+ }
+ sp->cstream = ZSTD_createCStream();
+ if( sp->cstream == NULL ) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Cannot allocate compression stream");
+ return 0;
+ }
+
+ zstd_ret = ZSTD_initCStream(sp->cstream, sp->compression_level);
+ if( ZSTD_isError(zstd_ret) ) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error in ZSTD_initCStream(): %s",
+ ZSTD_getErrorName(zstd_ret));
+ return 0;
+ }
+
+ sp->out_buffer.dst = tif->tif_rawdata;
+ sp->out_buffer.size = (size_t)tif->tif_rawdatasize;
+ sp->out_buffer.pos = 0;
+
+ return 1;
+}
+
+/*
+* Encode a chunk of pixels.
+*/
+static int
+ZSTDEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
+{
+ static const char module[] = "ZSTDEncode";
+ ZSTDState *sp = EncoderState(tif);
+ ZSTD_inBuffer in_buffer;
+ size_t zstd_ret;
+
+ assert(sp != NULL);
+ assert(sp->state == LSTATE_INIT_ENCODE);
+
+ (void) s;
+
+ in_buffer.src = bp;
+ in_buffer.size = (size_t)cc;
+ in_buffer.pos = 0;
+
+ do {
+ zstd_ret = ZSTD_compressStream(sp->cstream, &sp->out_buffer,
+ &in_buffer);
+ if( ZSTD_isError(zstd_ret) ) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error in ZSTD_compressStream(): %s",
+ ZSTD_getErrorName(zstd_ret));
+ return 0;
+ }
+ if( sp->out_buffer.pos == sp->out_buffer.size ) {
+ tif->tif_rawcc = tif->tif_rawdatasize;
+ TIFFFlushData1(tif);
+ sp->out_buffer.dst = tif->tif_rawcp;
+ sp->out_buffer.pos = 0;
+ }
+ } while( in_buffer.pos < in_buffer.size );
+
+ return 1;
+}
+
+/*
+* Finish off an encoded strip by flushing it.
+*/
+static int
+ZSTDPostEncode(TIFF* tif)
+{
+ static const char module[] = "ZSTDPostEncode";
+ ZSTDState *sp = EncoderState(tif);
+ size_t zstd_ret;
+
+ do {
+ zstd_ret = ZSTD_endStream(sp->cstream, &sp->out_buffer);
+ if( ZSTD_isError(zstd_ret) ) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error in ZSTD_endStream(): %s",
+ ZSTD_getErrorName(zstd_ret));
+ return 0;
+ }
+ if( sp->out_buffer.pos > 0 ) {
+ tif->tif_rawcc = sp->out_buffer.pos;
+ TIFFFlushData1(tif);
+ sp->out_buffer.dst = tif->tif_rawcp;
+ sp->out_buffer.pos = 0;
+ }
+ } while (zstd_ret != 0);
+ return 1;
+}
+
+static void
+ZSTDCleanup(TIFF* tif)
+{
+ ZSTDState* sp = LState(tif);
+
+ assert(sp != 0);
+
+ (void)TIFFPredictorCleanup(tif);
+
+ tif->tif_tagmethods.vgetfield = sp->vgetparent;
+ tif->tif_tagmethods.vsetfield = sp->vsetparent;
+
+ if (sp->dstream) {
+ ZSTD_freeDStream(sp->dstream);
+ sp->dstream = NULL;
+ }
+ if (sp->cstream) {
+ ZSTD_freeCStream(sp->cstream);
+ sp->cstream = NULL;
+ }
+ _TIFFfree(sp);
+ tif->tif_data = NULL;
+
+ _TIFFSetDefaultCompressionState(tif);
+}
+
+static int
+ZSTDVSetField(TIFF* tif, uint32 tag, va_list ap)
+{
+ static const char module[] = "ZSTDVSetField";
+ ZSTDState* sp = LState(tif);
+
+ switch (tag) {
+ case TIFFTAG_ZSTD_LEVEL:
+ sp->compression_level = (int) va_arg(ap, int);
+ if( sp->compression_level <= 0 ||
+ sp->compression_level > ZSTD_maxCLevel() )
+ {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "ZSTD_LEVEL should be between 1 and %d",
+ ZSTD_maxCLevel());
+ }
+ return 1;
+ default:
+ return (*sp->vsetparent)(tif, tag, ap);
+ }
+ /*NOTREACHED*/
+}
+
+static int
+ZSTDVGetField(TIFF* tif, uint32 tag, va_list ap)
+{
+ ZSTDState* sp = LState(tif);
+
+ switch (tag) {
+ case TIFFTAG_ZSTD_LEVEL:
+ *va_arg(ap, int*) = sp->compression_level;
+ break;
+ default:
+ return (*sp->vgetparent)(tif, tag, ap);
+ }
+ return 1;
+}
+
+static const TIFFField ZSTDFields[] = {
+ { TIFFTAG_ZSTD_LEVEL, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
+ TIFF_SETGET_UNDEFINED,
+ FIELD_PSEUDO, TRUE, FALSE, "ZSTD compression_level", NULL },
+};
+
+int
+TIFFInitZSTD(TIFF* tif, int scheme)
+{
+ static const char module[] = "TIFFInitZSTD";
+ ZSTDState* sp;
+
+ assert( scheme == COMPRESSION_ZSTD );
+
+ /*
+ * Merge codec-specific tag information.
+ */
+ if (!_TIFFMergeFields(tif, ZSTDFields, TIFFArrayCount(ZSTDFields))) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Merging ZSTD codec-specific tags failed");
+ return 0;
+ }
+
+ /*
+ * Allocate state block so tag methods have storage to record values.
+ */
+ tif->tif_data = (uint8*) _TIFFmalloc(sizeof(ZSTDState));
+ if (tif->tif_data == NULL)
+ goto bad;
+ sp = LState(tif);
+
+ /*
+ * Override parent get/set field methods.
+ */
+ sp->vgetparent = tif->tif_tagmethods.vgetfield;
+ tif->tif_tagmethods.vgetfield = ZSTDVGetField; /* hook for codec tags */
+ sp->vsetparent = tif->tif_tagmethods.vsetfield;
+ tif->tif_tagmethods.vsetfield = ZSTDVSetField; /* hook for codec tags */
+
+ /* Default values for codec-specific fields */
+ sp->compression_level = 9; /* default comp. level */
+ sp->state = 0;
+ sp->dstream = 0;
+ sp->cstream = 0;
+ sp->out_buffer.dst = NULL;
+ sp->out_buffer.size = 0;
+ sp->out_buffer.pos = 0;
+
+ /*
+ * Install codec methods.
+ */
+ tif->tif_fixuptags = ZSTDFixupTags;
+ tif->tif_setupdecode = ZSTDSetupDecode;
+ tif->tif_predecode = ZSTDPreDecode;
+ tif->tif_decoderow = ZSTDDecode;
+ tif->tif_decodestrip = ZSTDDecode;
+ tif->tif_decodetile = ZSTDDecode;
+ tif->tif_setupencode = ZSTDSetupEncode;
+ tif->tif_preencode = ZSTDPreEncode;
+ tif->tif_postencode = ZSTDPostEncode;
+ tif->tif_encoderow = ZSTDEncode;
+ tif->tif_encodestrip = ZSTDEncode;
+ tif->tif_encodetile = ZSTDEncode;
+ tif->tif_cleanup = ZSTDCleanup;
+ /*
+ * Setup predictor setup.
+ */
+ (void) TIFFPredictorInit(tif);
+ return 1;
+bad:
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "No space for ZSTD state block");
+ return 0;
+}
+#endif /* ZSTD_SUPPORT */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
-/* $Id: tiff.h,v 1.70 2016-01-23 21:20:34 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
#define COMPRESSION_SGILOG 34676 /* SGI Log Luminance RLE */
#define COMPRESSION_SGILOG24 34677 /* SGI Log 24-bit packed */
#define COMPRESSION_JP2000 34712 /* Leadtools JPEG2000 */
+#define COMPRESSION_LERC 34887 /* ESRI Lerc codec: https://github.com/Esri/lerc */
+/* compression codes 34887-34889 are reserved for ESRI */
#define COMPRESSION_LZMA 34925 /* LZMA2 */
+#define COMPRESSION_ZSTD 50000 /* ZSTD: WARNING not registered in Adobe-maintained registry */
+#define COMPRESSION_WEBP 50001 /* WEBP: WARNING not registered in Adobe-maintained registry */
#define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */
#define PHOTOMETRIC_MINISWHITE 0 /* min value is white */
#define PHOTOMETRIC_MINISBLACK 1 /* min value is black */
/* tag 34929 is a private tag registered to FedEx */
#define TIFFTAG_FEDEX_EDR 34929 /* unknown use */
#define TIFFTAG_INTEROPERABILITYIFD 40965 /* Pointer to Interoperability private directory */
+/* tags 50674 to 50677 are reserved for ESRI */
+#define TIFFTAG_LERC_PARAMETERS 50674 /* Stores LERC version and additional compression method */
/* Adobe Digital Negative (DNG) format tags */
#define TIFFTAG_DNGVERSION 50706 /* &DNG version number */
#define TIFFTAG_DNGBACKWARDVERSION 50707 /* &DNG compatibility version */
#define TIFFTAG_PERSAMPLE 65563 /* interface for per sample tags */
#define PERSAMPLE_MERGED 0 /* present as a single value */
#define PERSAMPLE_MULTI 1 /* present as multiple values */
+#define TIFFTAG_ZSTD_LEVEL 65564 /* ZSTD compression level */
+#define TIFFTAG_LERC_VERSION 65565 /* LERC version */
+#define LERC_VERSION_2_4 4
+#define TIFFTAG_LERC_ADD_COMPRESSION 65566 /* LERC additional compression */
+#define LERC_ADD_COMPRESSION_NONE 0
+#define LERC_ADD_COMPRESSION_DEFLATE 1
+#define LERC_ADD_COMPRESSION_ZSTD 2
+#define TIFFTAG_LERC_MAXZERROR 65567 /* LERC maximum error */
+#define TIFFTAG_WEBP_LEVEL 65568 /* WebP compression level: WARNING not registered in Adobe-maintained registry */
+#define TIFFTAG_WEBP_LOSSLESS 65569 /* WebP lossless/lossy : WARNING not registered in Adobe-maintained registry */
/*
* EXIF tags
/* Pointer difference type */
#define TIFF_PTRDIFF_T @TIFF_PTRDIFF_T@
-/* Define to 1 if the system has the type `int16'. */
-#cmakedefine HAVE_INT16 1
-
-/* Define to 1 if the system has the type `int32'. */
-#cmakedefine HAVE_INT32 1
-
-/* Define to 1 if the system has the type `int8'. */
-#cmakedefine HAVE_INT8 1
-
/* Compatibility stuff. */
/* Define as 0 or 1 according to the floating point format suported by the
-/* $Id: tiffio.h,v 1.94 2017-01-11 19:02:49 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
* promoted type (i.e. one of int, unsigned int, pointer,
* or double) and because we defined pseudo-tags that are
* outside the range of legal Aldus-assigned tags.
- * NB: tsize_t is int32 and not uint32 because some functions
+ * NB: tsize_t is signed and not unsigned because some functions
* return -1.
* NB: toff_t is not off_t for many reasons; TIFFs max out at
* 32-bit file offsets, and BigTIFF maxes out at 64-bit
-/* $Id: tiffio.hxx,v 1.3 2010-06-08 18:55:15 bfriesen Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
#include <iostream>
#include "tiff.h"
+#include "tiffio.h"
extern TIFF* TIFFStreamOpen(const char*, std::ostream *);
extern TIFF* TIFFStreamOpen(const char*, std::istream *);
-/* $Id: tiffiop.h,v 1.95 2017-09-07 14:02:52 erouault Exp $ */
-
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
#endif
#define streq(a,b) (strcmp(a,b) == 0)
+#define strneq(a,b,n) (strncmp(a,b,n) == 0)
#ifndef TRUE
#define TRUE 1
#define _TIFF_off_t off_t
#endif
-#if __clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ >= 8)
+#if defined(__has_attribute) && defined(__clang__)
+#if __has_attribute(no_sanitize)
#define TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW __attribute__((no_sanitize("unsigned-integer-overflow")))
#else
#define TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
#endif
+#else
+#define TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
+#endif
#if defined(__cplusplus)
#ifdef LZMA_SUPPORT
extern int TIFFInitLZMA(TIFF*, int);
#endif
+#ifdef ZSTD_SUPPORT
+extern int TIFFInitZSTD(TIFF*, int);
+#endif
+#ifdef WEBP_SUPPORT
+extern int TIFFInitWebP(TIFF*, int);
+#endif
#ifdef VMS
extern const TIFFCodec _TIFFBuiltinCODECS[];
#else
-#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.9\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
+#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.10\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
/*
* This define can be used in code that requires
* compilation-related definitions specific to a
* version checking should be done based on the
* string returned by TIFFGetVersion.
*/
-#define TIFFLIB_VERSION 20171118
+#define TIFFLIB_VERSION 20181110
state->strm = strm;
state->window = Z_NULL;
state->mode = HEAD; /* to pass state test in inflateReset2() */
+ state->check = 1L; /* 1L is the result of adler32() zero length data */
ret = inflateReset2(strm, windowBits);
if (ret != Z_OK) {
ZFREE(strm, state);
--- /dev/null
+diff --git a/3rdparty/zlib/inflate.c b/3rdparty/zlib/inflate.c
+index ac333e8c2e..19a2cf2ed8 100644
+--- a/3rdparty/zlib/inflate.c
++++ b/3rdparty/zlib/inflate.c
+@@ -228,6 +228,7 @@ int stream_size;
+ state->strm = strm;
+ state->window = Z_NULL;
+ state->mode = HEAD; /* to pass state test in inflateReset2() */
++ state->check = 1L; /* 1L is the result of adler32() zero length data */
+ ret = inflateReset2(strm, windowBits);
+ if (ret != Z_OK) {
+ ZFREE(strm, state);
cmake_policy(SET CMP0067 NEW)
endif()
+if(POLICY CMP0068)
+ cmake_policy(SET CMP0068 NEW) # CMake 3.9+: `RPATH` settings on macOS do not affect `install_name`.
+endif()
+
include(cmake/OpenCVUtils.cmake)
ocv_cmake_reset_hooks()
ocv_check_environment_variables(OPENCV_CMAKE_HOOKS_DIR)
OCV_OPTION(WITH_EIGEN "Include Eigen2/Eigen3 support" (NOT CV_DISABLE_OPTIMIZATION)
VISIBLE_IF NOT WINRT AND NOT CMAKE_CROSSCOMPILING
VERIFY HAVE_EIGEN)
-OCV_OPTION(WITH_FFMPEG "Include FFMPEG support" ON
- VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT
+OCV_OPTION(WITH_FFMPEG "Include FFMPEG support" (NOT ANDROID)
+ VISIBLE_IF NOT IOS AND NOT WINRT
VERIFY HAVE_FFMPEG)
OCV_OPTION(WITH_GSTREAMER "Include Gstreamer support" ON
VISIBLE_IF NOT ANDROID AND NOT IOS AND NOT WINRT
OCV_OPTION(WITH_DIRECTX "Include DirectX support" ON
VISIBLE_IF WIN32 AND NOT WINRT
VERIFY HAVE_DIRECTX)
+OCV_OPTION(WITH_OPENCL_D3D11_NV "Include NVIDIA OpenCL D3D11 support" WITH_DIRECTX
+ VISIBLE_IF WIN32 AND NOT WINRT
+ VERIFY HAVE_OPENCL_D3D11_NV)
OCV_OPTION(WITH_LIBREALSENSE "Include Intel librealsense support" OFF
VISIBLE_IF NOT WITH_INTELPERC
VERIFY HAVE_LIBREALSENSE)
OCV_OPTION(WITH_QUIRC "Include library QR-code decoding" ON
VISIBLE_IF TRUE
VERIFY HAVE_QUIRC)
+OCV_OPTION(WITH_ANDROID_MEDIANDK "Use Android Media NDK for Video I/O (Android)" (ANDROID_NATIVE_API_LEVEL GREATER 20)
+ VISIBLE_IF ANDROID
+ VERIFY HAVE_ANDROID_MEDIANDK)
# OpenCV build components
# ===================================================
CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD)
if(ANDROID)
set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} dl m log)
- elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD|NetBSD|DragonFly|OpenBSD|Haiku")
+ elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD|NetBSD|DragonFly|OpenBSD|Haiku")
set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} m pthread)
elseif(EMSCRIPTEN)
# no need to link to system libs with emscripten
# ========================== OpenCV modules ==========================
status("")
status(" OpenCV modules:")
-string(REPLACE "opencv_" "" OPENCV_MODULES_BUILD_ST "${OPENCV_MODULES_BUILD}")
+set(OPENCV_MODULES_BUILD_ST "")
+foreach(the_module ${OPENCV_MODULES_BUILD})
+ if(NOT OPENCV_MODULE_${the_module}_CLASS STREQUAL "INTERNAL" OR the_module STREQUAL "opencv_ts")
+ list(APPEND OPENCV_MODULES_BUILD_ST "${the_module}")
+ endif()
+endforeach()
+string(REPLACE "opencv_" "" OPENCV_MODULES_BUILD_ST "${OPENCV_MODULES_BUILD_ST}")
string(REPLACE "opencv_" "" OPENCV_MODULES_DISABLED_USER_ST "${OPENCV_MODULES_DISABLED_USER}")
string(REPLACE "opencv_" "" OPENCV_MODULES_DISABLED_AUTO_ST "${OPENCV_MODULES_DISABLED_AUTO}")
string(REPLACE "opencv_" "" OPENCV_MODULES_DISABLED_FORCE_ST "${OPENCV_MODULES_DISABLED_FORCE}")
IF HAVE_OPENCL_SVM THEN "SVM"
IF HAVE_CLAMDFFT THEN "AMDFFT"
IF HAVE_CLAMDBLAS THEN "AMDBLAS"
+ IF HAVE_OPENCL_D3D11_NV THEN "NVD3D11"
ELSE "no extra features")
status("")
status(" OpenCL:" HAVE_OPENCL THEN "YES (${opencl_features})" ELSE "NO")
add_extra_compiler_option(-Wcast-align)
add_extra_compiler_option(-Wstrict-aliasing=2)
else()
- add_extra_compiler_option(-Wno-narrowing)
add_extra_compiler_option(-Wno-delete-non-virtual-dtor)
add_extra_compiler_option(-Wno-unnamed-type-template-args)
add_extra_compiler_option(-Wno-comment)
string(REPLACE "-ffunction-sections" "" ${flags} "${${flags}}")
string(REPLACE "-fdata-sections" "" ${flags} "${${flags}}")
endforeach()
- elseif(NOT ((IOS OR ANDROID) AND NOT BUILD_SHARED_LIBS) AND NOT MSVC)
- # Remove unreferenced functions: function level linking
- add_extra_compiler_option(-ffunction-sections)
- add_extra_compiler_option(-fdata-sections)
- if(NOT APPLE AND NOT OPENCV_SKIP_GC_SECTIONS)
- set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} -Wl,--gc-sections")
+ else()
+ if(MSVC)
+ # TODO: Clang/C2 is not supported
+ elseif(((IOS OR ANDROID) AND NOT BUILD_SHARED_LIBS) AND NOT OPENCV_FORCE_FUNCTIONS_SECTIONS)
+ # don't create separate sections for functions/data, reduce package size
+ else()
+ # Remove unreferenced functions: function level linking
+ add_extra_compiler_option(-ffunction-sections)
+ add_extra_compiler_option(-fdata-sections)
+ if(NOT OPENCV_SKIP_GC_SECTIONS)
+ 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")
+ 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")
+ endif()
+ endif()
endif()
endif()
add_extra_compiler_option(-fvisibility-inlines-hidden)
endif()
+# workaround gcc bug for aligned ld/st
+# https://github.com/opencv/opencv/issues/13211
+if((PPC64LE AND NOT CMAKE_CROSSCOMPILING) OR OPENCV_FORCE_COMPILER_CHECK_VSX_ALIGNED)
+ ocv_check_runtime_flag("${CPU_BASELINE_FLAGS}" OPENCV_CHECK_VSX_ALIGNED "${OpenCV_SOURCE_DIR}/cmake/checks/runtime/cpu_vsx_aligned.cpp")
+ if(NOT OPENCV_CHECK_VSX_ALIGNED)
+ add_extra_compiler_option_force(-DCV_COMPILER_VSX_BROKEN_ALIGNED)
+ endif()
+endif()
+# validate inline asm with fixes register number and constraints wa, wd, wf
+if(PPC64LE)
+ ocv_check_compiler_flag(CXX "${CPU_BASELINE_FLAGS}" OPENCV_CHECK_VSX_ASM "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_vsx_asm.cpp")
+ if(NOT OPENCV_CHECK_VSX_ASM)
+ add_extra_compiler_option_force(-DCV_COMPILER_VSX_BROKEN_ASM)
+ endif()
+endif()
+
# combine all "extra" options
if(NOT OPENCV_SKIP_EXTRA_COMPILER_FLAGS)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPENCV_EXTRA_FLAGS} ${OPENCV_EXTRA_C_FLAGS}")
set(OpenCV_RUNTIME vc14)
elseif(MSVC_VERSION MATCHES "^191[0-9]$")
set(OpenCV_RUNTIME vc15)
+ elseif(MSVC_VERSION MATCHES "^192[0-9]$")
+ set(OpenCV_RUNTIME vc16)
else()
message(WARNING "OpenCV does not recognize MSVC_VERSION \"${MSVC_VERSION}\". Cannot set OpenCV_RUNTIME")
endif()
# The script detects Intel(R) Inference Engine installation
#
# Cache variables:
-# INF_ENGINE_OMP_DIR - directory with OpenMP library to link with (needed by some versions of IE)
# INF_ENGINE_RELEASE - a number reflecting IE source interface (linked with OpenVINO release)
#
# Detect parameters:
# - INF_ENGINE_INCLUDE_DIRS - headers search location
# - INF_ENGINE_LIB_DIRS - library search location
# 3. OpenVINO location:
-# - environment variable INTEL_CVSDK_DIR is set to location of OpenVINO installation dir
-# - INF_ENGINE_PLATFORM - part of name of library directory representing its platform (default ubuntu_16.04)
+# - environment variable INTEL_OPENVINO_DIR is set to location of OpenVINO installation dir
+# - INF_ENGINE_PLATFORM - part of name of library directory representing its platform
#
# Result:
# INF_ENGINE_TARGET - set to name of imported library target representing InferenceEngine
IMPORTED_IMPLIB_DEBUG "${_lib_dbg}"
INTERFACE_INCLUDE_DIRECTORIES "${_inc}"
)
- find_library(omp_lib iomp5 PATHS "${INF_ENGINE_OMP_DIR}" NO_DEFAULT_PATH)
- if(NOT omp_lib)
- message(WARNING "OpenMP for IE have not been found. Set INF_ENGINE_OMP_DIR variable if you experience build errors.")
- else()
- set_target_properties(inference_engine PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES "${omp_lib}")
+ if(NOT INF_ENGINE_RELEASE VERSION_GREATER "2018050000")
+ find_library(INF_ENGINE_OMP_LIBRARY iomp5 PATHS "${INF_ENGINE_OMP_DIR}" NO_DEFAULT_PATH)
+ if(NOT INF_ENGINE_OMP_LIBRARY)
+ message(WARNING "OpenMP for IE have not been found. Set INF_ENGINE_OMP_DIR variable if you experience build errors.")
+ else()
+ set_target_properties(inference_engine PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES "${INF_ENGINE_OMP_LIBRARY}")
+ endif()
endif()
set(INF_ENGINE_VERSION "Unknown" CACHE STRING "")
set(INF_ENGINE_TARGET inference_engine PARENT_SCOPE)
add_custom_ie_build("${ie_custom_inc}" "${ie_custom_lib}" "${ie_custom_lib_rel}" "${ie_custom_lib_dbg}" "INF_ENGINE_{INCLUDE,LIB}_DIRS")
endif()
-set(_loc "$ENV{INTEL_CVSDK_DIR}")
+set(_loc "$ENV{INTEL_OPENVINO_DIR}")
+if(NOT _loc AND DEFINED ENV{INTEL_CVSDK_DIR})
+ set(_loc "$ENV{INTEL_CVSDK_DIR}") # OpenVINO 2018.x
+endif()
if(NOT INF_ENGINE_TARGET AND _loc)
- set(INF_ENGINE_PLATFORM "ubuntu_16.04" CACHE STRING "InferenceEngine platform (library dir)")
+ if(NOT INF_ENGINE_RELEASE VERSION_GREATER "2018050000")
+ set(INF_ENGINE_PLATFORM_DEFAULT "ubuntu_16.04")
+ else()
+ set(INF_ENGINE_PLATFORM_DEFAULT "")
+ endif()
+ set(INF_ENGINE_PLATFORM "${INF_ENGINE_PLATFORM_DEFAULT}" CACHE STRING "InferenceEngine platform (library dir)")
find_path(ie_custom_env_inc "inference_engine.hpp" PATHS "${_loc}/deployment_tools/inference_engine/include" NO_DEFAULT_PATH)
find_library(ie_custom_env_lib "inference_engine" PATHS "${_loc}/deployment_tools/inference_engine/lib/${INF_ENGINE_PLATFORM}/intel64" NO_DEFAULT_PATH)
find_library(ie_custom_env_lib_rel "inference_engine" PATHS "${_loc}/deployment_tools/inference_engine/lib/intel64/Release" NO_DEFAULT_PATH)
if(APPLE)
set(OPENCL_LIBRARY "-framework OpenCL" CACHE STRING "OpenCL library")
set(OPENCL_INCLUDE_DIR "" CACHE PATH "OpenCL include directory")
-else(APPLE)
+else()
set(OPENCL_LIBRARY "" CACHE STRING "OpenCL library")
set(OPENCL_INCLUDE_DIR "${OpenCV_SOURCE_DIR}/3rdparty/include/opencl/1.2" CACHE PATH "OpenCL include directory")
ocv_install_3rdparty_licenses(opencl-headers "${OpenCV_SOURCE_DIR}/3rdparty/include/opencl/LICENSE.txt")
-endif(APPLE)
+endif()
mark_as_advanced(OPENCL_INCLUDE_DIR OPENCL_LIBRARY)
if(OPENCL_FOUND)
+
+ if(WITH_OPENCL_D3D11_NV AND EXISTS "${OPENCL_INCLUDE_DIR}/CL/cl_d3d11_ext.h")
+ set(HAVE_OPENCL_D3D11_NV ON)
+ endif()
+
if(OPENCL_LIBRARY)
set(HAVE_OPENCL_STATIC ON)
set(OPENCL_LIBRARIES "${OPENCL_LIBRARY}")
ocv_target_link_libraries(${the_target} LINK_PRIVATE ${perf_deps} ${OPENCV_MODULE_${the_module}_DEPS} ${OPENCV_LINKER_LIBS} ${OPENCV_PERF_${the_module}_DEPS})
add_dependencies(opencv_perf_tests ${the_target})
+ if(TARGET opencv_videoio_plugins)
+ add_dependencies(${the_target} opencv_videoio_plugins)
+ endif()
+
if(HAVE_HPX)
message("Linking HPX to Perf test of module ${name}")
ocv_target_link_libraries(${the_target} LINK_PRIVATE "${HPX_LIBRARIES}")
ocv_target_link_libraries(${the_target} LINK_PRIVATE ${test_deps} ${OPENCV_MODULE_${the_module}_DEPS} ${OPENCV_LINKER_LIBS} ${OPENCV_TEST_${the_module}_DEPS})
add_dependencies(opencv_tests ${the_target})
+ if(TARGET opencv_videoio_plugins)
+ add_dependencies(${the_target} opencv_videoio_plugins)
+ endif()
+
if(HAVE_HPX)
message("Linking HPX to Perf test of module ${name}")
ocv_target_link_libraries(${the_target} LINK_PRIVATE "${HPX_LIBRARIES}")
endif()
add_dependencies(${parent_target} ${the_target})
+ if(TARGET opencv_videoio_plugins)
+ add_dependencies(${the_target} opencv_videoio_plugins)
+ endif()
+
if(WIN32)
install(TARGETS ${the_target} RUNTIME DESTINATION "samples/${module_id}" COMPONENT samples)
endif()
ocv_check_compiler_flag("${_lang}" "${base_options} ${flag}" ${${varname}} ${ARGN})
endmacro()
+macro(ocv_check_runtime_flag flag result)
+ set(_fname "${ARGN}")
+ if(NOT DEFINED ${result})
+ file(RELATIVE_PATH _rname "${CMAKE_SOURCE_DIR}" "${_fname}")
+ message(STATUS "Performing Runtime Test ${result} (check file: ${_rname})")
+ try_run(exec_return compile_result
+ "${CMAKE_BINARY_DIR}"
+ "${_fname}"
+ CMAKE_FLAGS "-DCMAKE_EXE_LINKER_FLAGS=${CMAKE_EXE_LINKER_FLAGS}" # CMP0056 do this on new CMake
+ COMPILE_DEFINITIONS "${flag}"
+ OUTPUT_VARIABLE OUTPUT)
+
+ if(${compile_result})
+ if(exec_return EQUAL 0)
+ set(${result} 1 CACHE INTERNAL "Runtime Test ${result}")
+ message(STATUS "Performing Runtime Test ${result} - Success")
+ else()
+ message(STATUS "Performing Runtime Test ${result} - Failed(${exec_return})")
+ set(${result} 0 CACHE INTERNAL "Runtime Test ${result}")
+ endif()
+ else()
+ set(${result} 0 CACHE INTERNAL "Runtime Test ${result}")
+ message(STATUS "Performing Runtime Test ${result} - Compiling Failed")
+ endif()
+
+ if(NOT ${result})
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Runtime Test failed:\n"
+ " source file: '${_fname}'\n"
+ " check option: '${flag}'\n"
+ " exec return: ${exec_return}\n"
+ "===== BUILD AND RUNTIME LOG =====\n"
+ "${OUTPUT}\n"
+ "===== END =====\n\n")
+ endif()
+ endif()
+endmacro()
+
# turns off warnings
macro(ocv_warnings_disable)
if(NOT ENABLE_NOISY_WARNINGS)
message(STATUS "${msg}")
string(REPLACE "\\" "\\\\" msg "${msg}")
string(REPLACE "\"" "\\\"" msg "${msg}")
+ string(REGEX REPLACE "^\n+|\n+$" "" msg "${msg}")
+ if(msg MATCHES "\n")
+ message(WARNING "String to be inserted to version_string.inc has an unexpected line break: '${msg}'")
+ string(REPLACE "\n" "\\n" msg "${msg}")
+ endif()
set(OPENCV_BUILD_INFO_STR "${OPENCV_BUILD_INFO_STR}\"${msg}\\n\"\n" CACHE INTERNAL "")
endfunction()
--- /dev/null
+#if defined(__VSX__)
+ #if defined(__PPC64__) && defined(__LITTLE_ENDIAN__)
+ #include <altivec.h>
+ #else
+ #error "OpenCV only supports little-endian mode"
+ #endif
+#else
+ #error "VSX is not supported"
+#endif
+
+/*
+ * xlc and wide versions of clang don't support %x<n> in the inline asm template which fixes register number
+ * when using any of the register constraints wa, wd, wf
+*/
+int main()
+{
+ __vector float vf;
+ __vector signed int vi;
+ __asm__ __volatile__ ("xvcvsxwsp %x0,%x1" : "=wf" (vf) : "wa" (vi));
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+// check sanity of vsx aligned ld/st
+// https://github.com/opencv/opencv/issues/13211
+
+#include <altivec.h>
+#undef bool
+
+#define vsx_ld vec_vsx_ld
+#define vsx_st vec_vsx_st
+
+template<typename T>
+static void fill(T& d, int from = 0, int to = 16)
+{
+ for (int i = from; i < to; i++)
+ d[i] = i;
+}
+
+template<typename T, typename Tvec>
+static bool check_data(T& d, Tvec& v, int from = 0, int to = 16)
+{
+ for (int i = from; i < to; i++)
+ {
+ if (d[i] != vec_extract(v, i))
+ return false;
+ }
+ return true;
+}
+
+int main()
+{
+ unsigned char __attribute__ ((aligned (16))) rbuf[16];
+ unsigned char __attribute__ ((aligned (16))) wbuf[16];
+ __vector unsigned char a;
+
+ // 1- check aligned load and store
+ fill(rbuf);
+ a = vec_ld(0, rbuf);
+ if (!check_data(rbuf, a))
+ return 1;
+ vec_st(a, 0, wbuf);
+ if (!check_data(wbuf, a))
+ return 11;
+
+ // 2- check mixing aligned load and unaligned store
+ a = vec_ld(0, rbuf);
+ vsx_st(a, 0, wbuf);
+ if (!check_data(wbuf, a))
+ return 2;
+
+ // 3- check mixing unaligned load and aligned store
+ a = vsx_ld(0, rbuf);
+ vec_st(a, 0, wbuf);
+ if (!check_data(wbuf, a))
+ return 3;
+
+ return 0;
+}
\ No newline at end of file
if(NOT has_VS2017)
set(OpenCV_RUNTIME vc14) # selecting previous compatible runtime version
endif()
+ elseif(MSVC_VERSION MATCHES "^192[0-9]$")
+ set(OpenCV_RUNTIME vc16)
+ check_one_config(has_VS2019)
+ if(NOT has_VS2019)
+ set(OpenCV_RUNTIME vc15) # selecting previous compatible runtime version
+ check_one_config(has_VS2017)
+ if(NOT has_VS2017)
+ set(OpenCV_RUNTIME vc14) # selecting previous compatible runtime version
+ endif()
+ endif()
endif()
elseif(MINGW)
set(OpenCV_RUNTIME mingw)
#cmakedefine HAVE_OPENCL_STATIC
#cmakedefine HAVE_OPENCL_SVM
+/* NVIDIA OpenCL D3D Extensions support */
+#cmakedefine HAVE_OPENCL_D3D11_NV
+
/* OpenEXR codec */
#cmakedefine HAVE_OPENEXR
script.setAttribute('async', '');
script.setAttribute('type', 'text/javascript');
script.addEventListener('load', () => {
- console.log(cv.getBuildInformation());
- onloadCallback();
+ if (cv.getBuildInformation)
+ {
+ console.log(cv.getBuildInformation());
+ onloadCallback();
+ }
+ else
+ {
+ // WASM
+ cv['onRuntimeInitialized']=()=>{
+ console.log(cv.getBuildInformation());
+ onloadCallback();
+ }
+ }
});
script.addEventListener('error', () => {
self.printError('Failed to load ' + OPENCV_URL);
number = {7},
url = {http://www.bmva.org/bmvc/2013/Papers/paper0013/paper0013.pdf}
}
+@inproceedings{Andreff99,
+ author = {Andreff, Nicolas and Horaud, Radu and Espiau, Bernard},
+ title = {On-line Hand-eye Calibration},
+ booktitle = {Proceedings of the 2Nd International Conference on 3-D Digital Imaging and Modeling},
+ series = {3DIM'99},
+ year = {1999},
+ isbn = {0-7695-0062-5},
+ location = {Ottawa, Canada},
+ pages = {430--436},
+ numpages = {7},
+ url = {http://dl.acm.org/citation.cfm?id=1889712.1889775},
+ acmid = {1889775},
+ publisher = {IEEE Computer Society},
+ address = {Washington, DC, USA},
+}
@inproceedings{Arandjelovic:2012:TTE:2354409.2355123,
author = {Arandjelovic, Relja},
title = {Three Things Everyone Should Know to Improve Object Retrieval},
volume = {9},
publisher = {Walter de Gruyter}
}
+@article{Daniilidis98,
+ author = {Konstantinos Daniilidis},
+ title = {Hand-Eye Calibration Using Dual Quaternions},
+ journal = {International Journal of Robotics Research},
+ year = {1998},
+ volume = {18},
+ pages = {286--298}
+}
@inproceedings{DM03,
author = {Drago, Fr{\'e}d{\'e}ric and Myszkowski, Karol and Annen, Thomas and Chiba, Norishige},
title = {Adaptive logarithmic mapping for displaying high contrast scenes},
publisher = {Cambridge university press},
url = {http://cds.cern.ch/record/1598612/files/0521540518_TOC.pdf}
}
+@article{Horaud95,
+ author = {Horaud, Radu and Dornaika, Fadi},
+ title = {Hand-eye Calibration},
+ journal = {Int. J. Rob. Res.},
+ issue_date = {June 1995},
+ volume = {14},
+ number = {3},
+ month = jun,
+ year = {1995},
+ issn = {0278-3649},
+ pages = {195--210},
+ numpages = {16},
+ url = {http://dx.doi.org/10.1177/027836499501400301},
+ doi = {10.1177/027836499501400301},
+ acmid = {208622},
+ publisher = {Sage Publications, Inc.},
+ address = {Thousand Oaks, CA, USA}
+}
@article{Horn81,
author = {Horn, Berthold KP and Schunck, Brian G},
title = {Determining Optical Flow},
number = {2},
publisher = {Elsevier}
}
+@article{Park94,
+ author = {F. C. Park and B. J. Martin},
+ journal = {IEEE Transactions on Robotics and Automation},
+ title = {Robot sensor calibration: solving AX=XB on the Euclidean group},
+ year = {1994},
+ volume = {10},
+ number = {5},
+ pages = {717-721},
+ doi = {10.1109/70.326576},
+ ISSN = {1042-296X},
+ month = {Oct}
+}
@inproceedings{PM03,
author = {P{\'e}rez, Patrick and Gangnet, Michel and Blake, Andrew},
title = {Poisson image editing},
number = {1},
publisher = {Taylor \& Francis}
}
+@article{Tsai89,
+ author = {R. Y. Tsai and R. K. Lenz},
+ journal = {IEEE Transactions on Robotics and Automation},
+ title = {A new technique for fully autonomous and efficient 3D robotics hand/eye calibration},
+ year = {1989},
+ volume = {5},
+ number = {3},
+ pages = {345-358},
+ doi = {10.1109/70.34770},
+ ISSN = {1042-296X},
+ month = {June}
+}
@inproceedings{UES01,
author = {Uyttendaele, Matthew and Eden, Ashley and Skeliski, R},
title = {Eliminating ghosting and exposure artifacts in image mosaics},
import cv2 as cv
cap = cv.VideoCapture(0)
-
-while(True):
+if not cap.isOpened():
+ print("Cannot open camera")
+ exit()
+while True:
# Capture frame-by-frame
ret, frame = cap.read()
+ # if frame is read correctly ret is True
+ if not ret:
+ print("Can't receive frame (stream end?). Exiting ...")
+ break
# Our operations on the frame come here
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
-
# Display the resulting frame
- cv.imshow('frame',gray)
- if cv.waitKey(1) & 0xFF == ord('q'):
+ cv.imshow('frame', gray)
+ if cv.waitKey(1) == ord('q'):
break
# When everything done, release the capture
cap.release()
-cv.destroyAllWindows()
-@endcode
+cv.destroyAllWindows()@endcode
`cap.read()` returns a bool (`True`/`False`). If frame is read correctly, it will be `True`. So you can
check end of the video by checking this return value.
cap = cv.VideoCapture('vtest.avi')
-while(cap.isOpened()):
+while cap.isOpened():
ret, frame = cap.read()
+ # if frame is read correctly ret is True
+ if not ret:
+ print("Can't receive frame (stream end?). Exiting ...")
+ break
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
- cv.imshow('frame',gray)
- if cv.waitKey(1) & 0xFF == ord('q'):
+ cv.imshow('frame', gray)
+ if cv.waitKey(1) == ord('q'):
break
cap.release()
# Define the codec and create VideoWriter object
fourcc = cv.VideoWriter_fourcc(*'XVID')
-out = cv.VideoWriter('output.avi',fourcc, 20.0, (640,480))
+out = cv.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
-while(cap.isOpened()):
+while cap.isOpened():
ret, frame = cap.read()
- if ret==True:
- frame = cv.flip(frame,0)
+ if not ret:
+ print("Can't receive frame (stream end?). Exiting ...")
+ break
+ frame = cv.flip(frame, 0)
- # write the flipped frame
- out.write(frame)
+ # write the flipped frame
+ out.write(frame)
- cv.imshow('frame',frame)
- if cv.waitKey(1) & 0xFF == ord('q'):
- break
- else:
+ cv.imshow('frame', frame)
+ if cv.waitKey(1) == ord('q'):
break
# Release everything if job is finished
--- /dev/null
+Create calibration pattern {#tutorial_camera_calibration_pattern}
+=========================================
+
+The goal of this tutorial is to learn how to create calibration pattern.
+
+You can find a chessboard pattern in https://github.com/opencv/opencv/blob/master/doc/pattern.png
+
+You can find a circleboard pattern in https://github.com/opencv/opencv/blob/master/doc/acircles_pattern.png
+
+Create your own pattern
+---------------
+
+Now, if you want to create your own pattern, you will need python to use https://github.com/opencv/opencv/blob/master/doc/pattern_tools/gen_pattern.py
+
+Example
+
+create a checkerboard pattern in file chessboard.svg with 9 rows, 6 columns and a square size of 20mm:
+
+ python gen_pattern.py -o chessboard.svg --rows 9 --columns 6 --type checkerboard --square_size 20
+
+create a circle board pattern in file circleboard.svg with 7 rows, 5 columns and a radius of 15mm:
+
+ python gen_pattern.py -o circleboard.svg --rows 7 --columns 5 --type circles --square_size 15
+
+create a circle board pattern in file acircleboard.svg with 7 rows, 5 columns and a square size of 10mm and less spacing between circle:
+
+ python gen_pattern.py -o acircleboard.svg --rows 7 --columns 5 --type acircles --square_size 10 --radius_rate 2
+
+If you want to change unit use -u option (mm inches, px, m)
+
+If you want to change page size use -w and -h options
+
+If you want to create a ChArUco board read tutorial Detection of ChArUco Corners in opencv_contrib tutorial(https://docs.opencv.org/3.4/df/d4a/tutorial_charuco_detection.html)
\ No newline at end of file
Although we get most of our images in a 2D format they do come from a 3D world. Here you will learn how to find out 3D world information from 2D images.
+- @subpage tutorial_camera_calibration_pattern
+
+ *Compatibility:* \> OpenCV 2.0
+
+ *Author:* Laurent Berger
+
+ You will learn how to create some calibration pattern.
+
- @subpage tutorial_camera_calibration_square_chess
*Compatibility:* \> OpenCV 2.0
- Download and install Android Studio from https://developer.android.com/studio.
-- Get the latest pre-built OpenCV for Android release from https://github.com/opencv/opencv/releases and unpack it (for example, `opencv-3.4.5-android-sdk.zip`).
+- Get the latest pre-built OpenCV for Android release from https://github.com/opencv/opencv/releases and unpack it (for example, `opencv-4.1.0-android-sdk.zip`).
- Download MobileNet object detection model from https://github.com/chuanqi305/MobileNet-SSD. We need a configuration file `MobileNetSSD_deploy.prototxt` and weights `MobileNetSSD_deploy.caffemodel`.
[bvlc_googlenet.caffemodel](http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel)
Also you need file with names of [ILSVRC2012](http://image-net.org/challenges/LSVRC/2012/browse-synsets) classes:
- [classification_classes_ILSVRC2012.txt](https://github.com/opencv/opencv/tree/master/samples/dnn/classification_classes_ILSVRC2012.txt).
+ [classification_classes_ILSVRC2012.txt](https://github.com/opencv/opencv/blob/master/samples/data/dnn/classification_classes_ILSVRC2012.txt).
Put these files into working dir of this program example.
Note that this code slightly changes from the original one: forming up
the resulting image is also a part of the pipeline (done with
-cv::gapi::addWeighted). Normalization of orientation and coherency
-images is still done by traditional OpenCV (using cv::normalize) as
-G-API doesn't provide such kernel at the moment.
+cv::gapi::addWeighted).
Result of this G-API pipeline bit-exact matches the original one
(given the same input image):
==6117==
Once done, we can inspect the collected profiles with
-[Massif Visualizer](@https://github.com/KDE/massif-visualizer)
+[Massif Visualizer](https://github.com/KDE/massif-visualizer)
(installed in the above step).
Below is the visualized memory profile of the original OpenCV version
Once G-API computation is created and its execution starts, G-API
allocates all required memory at once and then the memory profile
remains flat until the termination of the program. Massif reports us
-peak memory consumption of 10.6 MiB.
+peak memory consumption of 11.4 MiB.
A reader may ask a right question at this point -- is G-API that bad?
What is the reason in using it than?
![Memory profile: G-API/Fluid port of Anisotropic Image Segmentation sample](pics/massif_export_gapi_fluid.png)
-Now the tool reports 3.8MiB -- and we just changed a few lines in our
-code, without modifying the graph itself! It is a ~2.8X improvement of
-the previous G-API result, and 2X improvement of the original OpenCV
+Now the tool reports 4.7MiB -- and we just changed a few lines in our
+code, without modifying the graph itself! It is a ~2.4X improvement of
+the previous G-API result, and ~1.6X improvement of the original OpenCV
version.
Let's also examine how the internal representation of the graph now
Anisotropic image segmentation by a gradient structure tensor {#tutorial_anisotropic_image_segmentation_by_a_gst}
==========================
+@prev_tutorial{tutorial_motion_deblur_filter}
+@next_tutorial{tutorial_periodic_noise_removing_filter}
+
Goal
----
Coherency:
\f[C = \frac{\lambda_1 - \lambda_2}{\lambda_1 + \lambda_2}\f]
-The coherency ranges from 0 to 1. For ideal local orientation (\f$\lambda_2\f$ = 0, \f$\lambda_1\f$ > 0) it is one, for an isotropic gray value structure (\f$\lambda_1\f$ = \f$\lambda_2\f$ > 0) it is zero.
+The coherency ranges from 0 to 1. For ideal local orientation (\f$\lambda_2\f$ = 0, \f$\lambda_1\f$ > 0) it is one, for an isotropic gray value structure (\f$\lambda_1\f$ = \f$\lambda_2\f$ \> 0) it is zero.
Source code
-----------
You can find source code in the `samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp` of the OpenCV source code library.
-@include cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp
+@add_toggle_cpp
+ @include cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp
+@end_toggle
+
+@add_toggle_python
+ @include samples/python/tutorial_code/imgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.py
+@end_toggle
Explanation
-----------
An anisotropic image segmentation algorithm consists of a gradient structure tensor calculation, an orientation calculation, a coherency calculation and an orientation and coherency thresholding:
-@snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp main
+
+@add_toggle_cpp
+ @snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp main
+@end_toggle
+
+@add_toggle_python
+ @snippet samples/python/tutorial_code/imgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.py main
+@end_toggle
A function calcGST() calculates orientation and coherency by using a gradient structure tensor. An input parameter w defines a window size:
-@snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp calcGST
+
+@add_toggle_cpp
+ @snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp calcGST
+@end_toggle
+
+@add_toggle_python
+ @snippet samples/python/tutorial_code/imgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.py calcGST
+@end_toggle
+
The below code applies a thresholds LowThr and HighThr to image orientation and a threshold C_Thr to image coherency calculated by the previous function. LowThr and HighThr define orientation range:
-@snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp thresholding
+
+@add_toggle_cpp
+ @snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp thresholding
+@end_toggle
+
+@add_toggle_python
+ @snippet samples/python/tutorial_code/imgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.py thresholding
+@end_toggle
+
And finally we combine thresholding results:
-@snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp combining
+
+@add_toggle_cpp
+ @snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp combining
+@end_toggle
+
+@add_toggle_python
+ @snippet samples/python/tutorial_code/imgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.py combining
+@end_toggle
+
Result
------
Motion Deblur Filter {#tutorial_motion_deblur_filter}
==========================
+@prev_tutorial{tutorial_out_of_focus_deblur_filter}
+@next_tutorial{tutorial_anisotropic_image_segmentation_by_a_gst}
+
Goal
----
==========================
@prev_tutorial{tutorial_distance_transform}
+@next_tutorial{tutorial_motion_deblur_filter}
Goal
----
Periodic Noise Removing Filter {#tutorial_periodic_noise_removing_filter}
==========================
+@prev_tutorial{tutorial_anisotropic_image_segmentation_by_a_gst}
+
Goal
----
`TAGFILES`. Change it as follows:
@code
-TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/4.0.1
+TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/4.1.0
@endcode
If you had other definitions already, you can append the line using a `\`:
@code
TAGFILES = ./docs/doxygen-tags/libstdc++.tag=https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen \
- ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/4.0.1
+ ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/4.1.0
@endcode
Doxygen can now use the information from the tag file to link to the OpenCV
- Create build directory near the sources folder(s) and go into it
- Run cmake (assuming you put sources to _opencv_ folder):
@code{.sh}
- cmake ../opencv
+ cmake -DBUILD_DOCS=ON ../opencv
@endcode
Or if you get contrib sources too:
@code{.sh}
- cmake -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules ../opencv
+ cmake -DBUILD_DOCS=ON -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules ../opencv
@endcode
- Run make:
@code{.sh}
opencv_source_code/samples/cpp/calibration.cpp
- A calibration sample in order to do 3D reconstruction can be found at
opencv_source_code/samples/cpp/build3dmodel.cpp
- - A calibration sample of an artificially generated camera and chessboard patterns can be
- found at opencv_source_code/samples/cpp/calibration_artificial.cpp
- A calibration example on stereo calibration can be found at
opencv_source_code/samples/cpp/stereo_calib.cpp
- A calibration example on stereo matching can be found at
// for stereo rectification
CALIB_ZERO_DISPARITY = 0x00400,
CALIB_USE_LU = (1 << 17), //!< use LU instead of SVD decomposition for solving. much faster but potentially less precise
- CALIB_USE_EXTRINSIC_GUESS = (1 << 22), //!< for stereoCalibrate
+ CALIB_USE_EXTRINSIC_GUESS = (1 << 22) //!< for stereoCalibrate
};
//! the algorithm for finding fundamental matrix
FM_RANSAC = 8 //!< RANSAC algorithm. It needs at least 15 points. 7-point algorithm is used.
};
+enum HandEyeCalibrationMethod
+{
+ CALIB_HAND_EYE_TSAI = 0, //!< A New Technique for Fully Autonomous and Efficient 3D Robotics Hand/Eye Calibration @cite Tsai89
+ CALIB_HAND_EYE_PARK = 1, //!< Robot Sensor Calibration: Solving AX = XB on the Euclidean Group @cite Park94
+ CALIB_HAND_EYE_HORAUD = 2, //!< Hand-eye Calibration @cite Horaud95
+ CALIB_HAND_EYE_ANDREFF = 3, //!< On-line Hand-Eye Calibration @cite Andreff99
+ CALIB_HAND_EYE_DANIILIDIS = 4 //!< Hand-Eye Calibration Using Dual Quaternions @cite Daniilidis98
+};
/** @brief Converts a rotation matrix to a rotation vector or vice versa.
CV_OUT Rect* validPixROI = 0,
bool centerPrincipalPoint = false);
+/** @brief Computes Hand-Eye calibration: \f$_{}^{g}\textrm{T}_c\f$
+
+@param[in] R_gripper2base Rotation part extracted from the homogeneous matrix that transforms a point
+expressed in the gripper frame to the robot base frame (\f$_{}^{b}\textrm{T}_g\f$).
+This is a vector (`vector<Mat>`) that contains the rotation matrices for all the transformations
+from gripper frame to robot base frame.
+@param[in] t_gripper2base Translation part extracted from the homogeneous matrix that transforms a point
+expressed in the gripper frame to the robot base frame (\f$_{}^{b}\textrm{T}_g\f$).
+This is a vector (`vector<Mat>`) that contains the translation vectors for all the transformations
+from gripper frame to robot base frame.
+@param[in] R_target2cam Rotation part extracted from the homogeneous matrix that transforms a point
+expressed in the target frame to the camera frame (\f$_{}^{c}\textrm{T}_t\f$).
+This is a vector (`vector<Mat>`) that contains the rotation matrices for all the transformations
+from calibration target frame to camera frame.
+@param[in] t_target2cam Rotation part extracted from the homogeneous matrix that transforms a point
+expressed in the target frame to the camera frame (\f$_{}^{c}\textrm{T}_t\f$).
+This is a vector (`vector<Mat>`) that contains the translation vectors for all the transformations
+from calibration target frame to camera frame.
+@param[out] R_cam2gripper Estimated rotation part extracted from the homogeneous matrix that transforms a point
+expressed in the camera frame to the gripper frame (\f$_{}^{g}\textrm{T}_c\f$).
+@param[out] t_cam2gripper Estimated translation part extracted from the homogeneous matrix that transforms a point
+expressed in the camera frame to the gripper frame (\f$_{}^{g}\textrm{T}_c\f$).
+@param[in] method One of the implemented Hand-Eye calibration method, see cv::HandEyeCalibrationMethod
+
+The function performs the Hand-Eye calibration using various methods. One approach consists in estimating the
+rotation then the translation (separable solutions) and the following methods are implemented:
+ - R. Tsai, R. Lenz A New Technique for Fully Autonomous and Efficient 3D Robotics Hand/EyeCalibration \cite Tsai89
+ - F. Park, B. Martin Robot Sensor Calibration: Solving AX = XB on the Euclidean Group \cite Park94
+ - R. Horaud, F. Dornaika Hand-Eye Calibration \cite Horaud95
+
+Another approach consists in estimating simultaneously the rotation and the translation (simultaneous solutions),
+with the following implemented method:
+ - N. Andreff, R. Horaud, B. Espiau On-line Hand-Eye Calibration \cite Andreff99
+ - K. Daniilidis Hand-Eye Calibration Using Dual Quaternions \cite Daniilidis98
+
+The following picture describes the Hand-Eye calibration problem where the transformation between a camera ("eye")
+mounted on a robot gripper ("hand") has to be estimated.
+
+![](pics/hand-eye_figure.png)
+
+The calibration procedure is the following:
+ - a static calibration pattern is used to estimate the transformation between the target frame
+ and the camera frame
+ - the robot gripper is moved in order to acquire several poses
+ - for each pose, the homogeneous transformation between the gripper frame and the robot base frame is recorded using for
+ instance the robot kinematics
+\f[
+ \begin{bmatrix}
+ X_b\\
+ Y_b\\
+ Z_b\\
+ 1
+ \end{bmatrix}
+ =
+ \begin{bmatrix}
+ _{}^{b}\textrm{R}_g & _{}^{b}\textrm{t}_g \\
+ 0_{1 \times 3} & 1
+ \end{bmatrix}
+ \begin{bmatrix}
+ X_g\\
+ Y_g\\
+ Z_g\\
+ 1
+ \end{bmatrix}
+\f]
+ - for each pose, the homogeneous transformation between the calibration target frame and the camera frame is recorded using
+ for instance a pose estimation method (PnP) from 2D-3D point correspondences
+\f[
+ \begin{bmatrix}
+ X_c\\
+ Y_c\\
+ Z_c\\
+ 1
+ \end{bmatrix}
+ =
+ \begin{bmatrix}
+ _{}^{c}\textrm{R}_t & _{}^{c}\textrm{t}_t \\
+ 0_{1 \times 3} & 1
+ \end{bmatrix}
+ \begin{bmatrix}
+ X_t\\
+ Y_t\\
+ Z_t\\
+ 1
+ \end{bmatrix}
+\f]
+
+The Hand-Eye calibration procedure returns the following homogeneous transformation
+\f[
+ \begin{bmatrix}
+ X_g\\
+ Y_g\\
+ Z_g\\
+ 1
+ \end{bmatrix}
+ =
+ \begin{bmatrix}
+ _{}^{g}\textrm{R}_c & _{}^{g}\textrm{t}_c \\
+ 0_{1 \times 3} & 1
+ \end{bmatrix}
+ \begin{bmatrix}
+ X_c\\
+ Y_c\\
+ Z_c\\
+ 1
+ \end{bmatrix}
+\f]
+
+This problem is also known as solving the \f$\mathbf{A}\mathbf{X}=\mathbf{X}\mathbf{B}\f$ equation:
+\f[
+ \begin{align*}
+ ^{b}{\textrm{T}_g}^{(1)} \hspace{0.2em} ^{g}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(1)} &=
+ \hspace{0.1em} ^{b}{\textrm{T}_g}^{(2)} \hspace{0.2em} ^{g}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(2)} \\
+
+ (^{b}{\textrm{T}_g}^{(2)})^{-1} \hspace{0.2em} ^{b}{\textrm{T}_g}^{(1)} \hspace{0.2em} ^{g}\textrm{T}_c &=
+ \hspace{0.1em} ^{g}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(2)} (^{c}{\textrm{T}_t}^{(1)})^{-1} \\
+
+ \textrm{A}_i \textrm{X} &= \textrm{X} \textrm{B}_i \\
+ \end{align*}
+\f]
+
+\note
+Additional information can be found on this [website](http://campar.in.tum.de/Chair/HandEyeCalibration).
+\note
+A minimum of 2 motions with non parallel rotation axes are necessary to determine the hand-eye transformation.
+So at least 3 different poses are required, but it is strongly recommended to use many more poses.
+
+ */
+CV_EXPORTS_W void calibrateHandEye( InputArrayOfArrays R_gripper2base, InputArrayOfArrays t_gripper2base,
+ InputArrayOfArrays R_target2cam, InputArrayOfArrays t_target2cam,
+ OutputArray R_cam2gripper, OutputArray t_cam2gripper,
+ HandEyeCalibrationMethod method=CALIB_HAND_EYE_TSAI );
+
/** @brief Converts points from Euclidean to homogeneous space.
@param src Input vector of N-dimensional points.
nparams = NINTRINSIC + nimages*6;
if( releaseObject )
nparams += maxPoints * 3;
- Mat _Ji( maxPoints*2, NINTRINSIC, CV_64FC1, Scalar(0));
- Mat _Je( maxPoints*2, 6, CV_64FC1 );
- Mat _Jo( maxPoints*2, maxPoints*3, CV_64FC1, Scalar(0) );
- Mat _err( maxPoints*2, 1, CV_64FC1 );
_k = cvMat( distCoeffs->rows, distCoeffs->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(distCoeffs->type)), k);
if( distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) < 8 )
CvLevMarq solver( nparams, 0, termCrit );
+ Mat _Ji( maxPoints*2, NINTRINSIC, CV_64FC1, Scalar(0));
+ Mat _Je( maxPoints*2, 6, CV_64FC1 );
+ Mat _err( maxPoints*2, 1, CV_64FC1 );
+
+ const bool allocJo = (solver.state == CvLevMarq::CALC_J) || stdDevs;
+ Mat _Jo = allocJo ? Mat( maxPoints*2, maxPoints*3, CV_64FC1, Scalar(0) ) : Mat();
+
if(flags & CALIB_USE_LU) {
solver.solveMethod = DECOMP_LU;
}
_Je.resize(ni*2); _Ji.resize(ni*2); _err.resize(ni*2);
_Jo.resize(ni*2);
- CvMat _dpdr = cvMat(_Je.colRange(0, 3));
- CvMat _dpdt = cvMat(_Je.colRange(3, 6));
- CvMat _dpdf = cvMat(_Ji.colRange(0, 2));
- CvMat _dpdc = cvMat(_Ji.colRange(2, 4));
- CvMat _dpdk = cvMat(_Ji.colRange(4, NINTRINSIC));
- CvMat _dpdo = cvMat(_Jo.colRange(0, ni * 3));
+
CvMat _mp = cvMat(_err.reshape(2, 1));
if( calcJ )
{
- cvProjectPoints2Internal( &_Mi, &_ri, &_ti, &matA, &_k, &_mp, &_dpdr, &_dpdt,
- (flags & CALIB_FIX_FOCAL_LENGTH) ? 0 : &_dpdf,
- (flags & CALIB_FIX_PRINCIPAL_POINT) ? 0 : &_dpdc, &_dpdk,
- &_dpdo,
+ CvMat _dpdr = cvMat(_Je.colRange(0, 3));
+ CvMat _dpdt = cvMat(_Je.colRange(3, 6));
+ CvMat _dpdf = cvMat(_Ji.colRange(0, 2));
+ CvMat _dpdc = cvMat(_Ji.colRange(2, 4));
+ CvMat _dpdk = cvMat(_Ji.colRange(4, NINTRINSIC));
+ CvMat _dpdo = _Jo.empty() ? CvMat() : cvMat(_Jo.colRange(0, ni * 3));
+
+ cvProjectPoints2Internal( &_Mi, &_ri, &_ti, &matA, &_k, &_mp, &_dpdr, &_dpdt,
+ (flags & CALIB_FIX_FOCAL_LENGTH) ? nullptr : &_dpdf,
+ (flags & CALIB_FIX_PRINCIPAL_POINT) ? nullptr : &_dpdc, &_dpdk,
+ (_Jo.empty()) ? nullptr: &_dpdo,
(flags & CALIB_FIX_ASPECT_RATIO) ? aspectRatio : 0);
}
else
--- /dev/null
+// 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 "precomp.hpp"
+#include "opencv2/calib3d.hpp"
+
+namespace cv {
+
+static Mat homogeneousInverse(const Mat& T)
+{
+ CV_Assert(T.rows == 4 && T.cols == 4);
+
+ Mat R = T(Rect(0, 0, 3, 3));
+ Mat t = T(Rect(3, 0, 1, 3));
+ Mat Rt = R.t();
+ Mat tinv = -Rt * t;
+ Mat Tinv = Mat::eye(4, 4, T.type());
+ Rt.copyTo(Tinv(Rect(0, 0, 3, 3)));
+ tinv.copyTo(Tinv(Rect(3, 0, 1, 3)));
+
+ return Tinv;
+}
+
+// q = rot2quatMinimal(R)
+//
+// R - 3x3 rotation matrix, or 4x4 homogeneous matrix
+// q - 3x1 unit quaternion <qx, qy, qz>
+// q = sin(theta/2) * v
+// theta - rotation angle
+// v - unit rotation axis, |v| = 1
+static Mat rot2quatMinimal(const Mat& R)
+{
+ CV_Assert(R.type() == CV_64FC1 && R.rows >= 3 && R.cols >= 3);
+
+ double m00 = R.at<double>(0,0), m01 = R.at<double>(0,1), m02 = R.at<double>(0,2);
+ double m10 = R.at<double>(1,0), m11 = R.at<double>(1,1), m12 = R.at<double>(1,2);
+ double m20 = R.at<double>(2,0), m21 = R.at<double>(2,1), m22 = R.at<double>(2,2);
+ double trace = m00 + m11 + m22;
+
+ double qx, qy, qz;
+ if (trace > 0) {
+ double S = sqrt(trace + 1.0) * 2; // S=4*qw
+ qx = (m21 - m12) / S;
+ qy = (m02 - m20) / S;
+ qz = (m10 - m01) / S;
+ } else if ((m00 > m11)&(m00 > m22)) {
+ double S = sqrt(1.0 + m00 - m11 - m22) * 2; // S=4*qx
+ qx = 0.25 * S;
+ qy = (m01 + m10) / S;
+ qz = (m02 + m20) / S;
+ } else if (m11 > m22) {
+ double S = sqrt(1.0 + m11 - m00 - m22) * 2; // S=4*qy
+ qx = (m01 + m10) / S;
+ qy = 0.25 * S;
+ qz = (m12 + m21) / S;
+ } else {
+ double S = sqrt(1.0 + m22 - m00 - m11) * 2; // S=4*qz
+ qx = (m02 + m20) / S;
+ qy = (m12 + m21) / S;
+ qz = 0.25 * S;
+ }
+
+ return (Mat_<double>(3,1) << qx, qy, qz);
+}
+
+static Mat skew(const Mat& v)
+{
+ CV_Assert(v.type() == CV_64FC1 && v.rows == 3 && v.cols == 1);
+
+ double vx = v.at<double>(0,0);
+ double vy = v.at<double>(1,0);
+ double vz = v.at<double>(2,0);
+ return (Mat_<double>(3,3) << 0, -vz, vy,
+ vz, 0, -vx,
+ -vy, vx, 0);
+}
+
+// R = quatMinimal2rot(q)
+//
+// q - 3x1 unit quaternion <qx, qy, qz>
+// R - 3x3 rotation matrix
+// q = sin(theta/2) * v
+// theta - rotation angle
+// v - unit rotation axis, |v| = 1
+static Mat quatMinimal2rot(const Mat& q)
+{
+ CV_Assert(q.type() == CV_64FC1 && q.rows == 3 && q.cols == 1);
+
+ Mat p = q.t()*q;
+ double w = sqrt(1 - p.at<double>(0,0));
+
+ Mat diag_p = Mat::eye(3,3,CV_64FC1)*p.at<double>(0,0);
+ return 2*q*q.t() + 2*w*skew(q) + Mat::eye(3,3,CV_64FC1) - 2*diag_p;
+}
+
+// q = rot2quat(R)
+//
+// q - 4x1 unit quaternion <qw, qx, qy, qz>
+// R - 3x3 rotation matrix
+static Mat rot2quat(const Mat& R)
+{
+ CV_Assert(R.type() == CV_64FC1 && R.rows >= 3 && R.cols >= 3);
+
+ double m00 = R.at<double>(0,0), m01 = R.at<double>(0,1), m02 = R.at<double>(0,2);
+ double m10 = R.at<double>(1,0), m11 = R.at<double>(1,1), m12 = R.at<double>(1,2);
+ double m20 = R.at<double>(2,0), m21 = R.at<double>(2,1), m22 = R.at<double>(2,2);
+ double trace = m00 + m11 + m22;
+
+ double qw, qx, qy, qz;
+ if (trace > 0) {
+ double S = sqrt(trace + 1.0) * 2; // S=4*qw
+ qw = 0.25 * S;
+ qx = (m21 - m12) / S;
+ qy = (m02 - m20) / S;
+ qz = (m10 - m01) / S;
+ } else if ((m00 > m11)&(m00 > m22)) {
+ double S = sqrt(1.0 + m00 - m11 - m22) * 2; // S=4*qx
+ qw = (m21 - m12) / S;
+ qx = 0.25 * S;
+ qy = (m01 + m10) / S;
+ qz = (m02 + m20) / S;
+ } else if (m11 > m22) {
+ double S = sqrt(1.0 + m11 - m00 - m22) * 2; // S=4*qy
+ qw = (m02 - m20) / S;
+ qx = (m01 + m10) / S;
+ qy = 0.25 * S;
+ qz = (m12 + m21) / S;
+ } else {
+ double S = sqrt(1.0 + m22 - m00 - m11) * 2; // S=4*qz
+ qw = (m10 - m01) / S;
+ qx = (m02 + m20) / S;
+ qy = (m12 + m21) / S;
+ qz = 0.25 * S;
+ }
+
+ return (Mat_<double>(4,1) << qw, qx, qy, qz);
+}
+
+// R = quat2rot(q)
+//
+// q - 4x1 unit quaternion <qw, qx, qy, qz>
+// R - 3x3 rotation matrix
+static Mat quat2rot(const Mat& q)
+{
+ CV_Assert(q.type() == CV_64FC1 && q.rows == 4 && q.cols == 1);
+
+ double qw = q.at<double>(0,0);
+ double qx = q.at<double>(1,0);
+ double qy = q.at<double>(2,0);
+ double qz = q.at<double>(3,0);
+
+ Mat R(3, 3, CV_64FC1);
+ R.at<double>(0, 0) = 1 - 2*qy*qy - 2*qz*qz;
+ R.at<double>(0, 1) = 2*qx*qy - 2*qz*qw;
+ R.at<double>(0, 2) = 2*qx*qz + 2*qy*qw;
+
+ R.at<double>(1, 0) = 2*qx*qy + 2*qz*qw;
+ R.at<double>(1, 1) = 1 - 2*qx*qx - 2*qz*qz;
+ R.at<double>(1, 2) = 2*qy*qz - 2*qx*qw;
+
+ R.at<double>(2, 0) = 2*qx*qz - 2*qy*qw;
+ R.at<double>(2, 1) = 2*qy*qz + 2*qx*qw;
+ R.at<double>(2, 2) = 1 - 2*qx*qx - 2*qy*qy;
+
+ return R;
+}
+
+// Kronecker product or tensor product
+// https://stackoverflow.com/a/36552682
+static Mat kron(const Mat& A, const Mat& B)
+{
+ CV_Assert(A.channels() == 1 && B.channels() == 1);
+
+ Mat1d Ad, Bd;
+ A.convertTo(Ad, CV_64F);
+ B.convertTo(Bd, CV_64F);
+
+ Mat1d Kd(Ad.rows * Bd.rows, Ad.cols * Bd.cols, 0.0);
+ for (int ra = 0; ra < Ad.rows; ra++)
+ {
+ for (int ca = 0; ca < Ad.cols; ca++)
+ {
+ Kd(Range(ra*Bd.rows, (ra + 1)*Bd.rows), Range(ca*Bd.cols, (ca + 1)*Bd.cols)) = Bd.mul(Ad(ra, ca));
+ }
+ }
+
+ Mat K;
+ Kd.convertTo(K, A.type());
+ return K;
+}
+
+// quaternion multiplication
+static Mat qmult(const Mat& s, const Mat& t)
+{
+ CV_Assert(s.type() == CV_64FC1 && t.type() == CV_64FC1);
+ CV_Assert(s.rows == 4 && s.cols == 1);
+ CV_Assert(t.rows == 4 && t.cols == 1);
+
+ double s0 = s.at<double>(0,0);
+ double s1 = s.at<double>(1,0);
+ double s2 = s.at<double>(2,0);
+ double s3 = s.at<double>(3,0);
+
+ double t0 = t.at<double>(0,0);
+ double t1 = t.at<double>(1,0);
+ double t2 = t.at<double>(2,0);
+ double t3 = t.at<double>(3,0);
+
+ Mat q(4, 1, CV_64FC1);
+ q.at<double>(0,0) = s0*t0 - s1*t1 - s2*t2 - s3*t3;
+ q.at<double>(1,0) = s0*t1 + s1*t0 + s2*t3 - s3*t2;
+ q.at<double>(2,0) = s0*t2 - s1*t3 + s2*t0 + s3*t1;
+ q.at<double>(3,0) = s0*t3 + s1*t2 - s2*t1 + s3*t0;
+
+ return q;
+}
+
+// dq = homogeneous2dualQuaternion(H)
+//
+// H - 4x4 homogeneous transformation: [R | t; 0 0 0 | 1]
+// dq - 8x1 dual quaternion: <q (rotation part), qprime (translation part)>
+static Mat homogeneous2dualQuaternion(const Mat& H)
+{
+ CV_Assert(H.type() == CV_64FC1 && H.rows == 4 && H.cols == 4);
+
+ Mat dualq(8, 1, CV_64FC1);
+ Mat R = H(Rect(0, 0, 3, 3));
+ Mat t = H(Rect(3, 0, 1, 3));
+
+ Mat q = rot2quat(R);
+ Mat qt = Mat::zeros(4, 1, CV_64FC1);
+ t.copyTo(qt(Rect(0, 1, 1, 3)));
+ Mat qprime = 0.5 * qmult(qt, q);
+
+ q.copyTo(dualq(Rect(0, 0, 1, 4)));
+ qprime.copyTo(dualq(Rect(0, 4, 1, 4)));
+
+ return dualq;
+}
+
+// H = dualQuaternion2homogeneous(dq)
+//
+// H - 4x4 homogeneous transformation: [R | t; 0 0 0 | 1]
+// dq - 8x1 dual quaternion: <q (rotation part), qprime (translation part)>
+static Mat dualQuaternion2homogeneous(const Mat& dualq)
+{
+ CV_Assert(dualq.type() == CV_64FC1 && dualq.rows == 8 && dualq.cols == 1);
+
+ Mat q = dualq(Rect(0, 0, 1, 4));
+ Mat qprime = dualq(Rect(0, 4, 1, 4));
+
+ Mat R = quat2rot(q);
+ q.at<double>(1,0) = -q.at<double>(1,0);
+ q.at<double>(2,0) = -q.at<double>(2,0);
+ q.at<double>(3,0) = -q.at<double>(3,0);
+
+ Mat qt = 2*qmult(qprime, q);
+ Mat t = qt(Rect(0, 1, 1, 3));
+
+ Mat H = Mat::eye(4, 4, CV_64FC1);
+ R.copyTo(H(Rect(0, 0, 3, 3)));
+ t.copyTo(H(Rect(3, 0, 1, 3)));
+
+ return H;
+}
+
+//Reference:
+//R. Y. Tsai and R. K. Lenz, "A new technique for fully autonomous and efficient 3D robotics hand/eye calibration."
+//In IEEE Transactions on Robotics and Automation, vol. 5, no. 3, pp. 345-358, June 1989.
+//C++ code converted from Zoran Lazarevic's Matlab code:
+//http://lazax.com/www.cs.columbia.edu/~laza/html/Stewart/matlab/handEye.m
+static void calibrateHandEyeTsai(const std::vector<Mat>& Hg, const std::vector<Mat>& Hc,
+ Mat& R_cam2gripper, Mat& t_cam2gripper)
+{
+ //Number of unique camera position pairs
+ int K = static_cast<int>((Hg.size()*Hg.size() - Hg.size()) / 2.0);
+ //Will store: skew(Pgij+Pcij)
+ Mat A(3*K, 3, CV_64FC1);
+ //Will store: Pcij - Pgij
+ Mat B(3*K, 1, CV_64FC1);
+
+ std::vector<Mat> vec_Hgij, vec_Hcij;
+ vec_Hgij.reserve(static_cast<size_t>(K));
+ vec_Hcij.reserve(static_cast<size_t>(K));
+
+ int idx = 0;
+ for (size_t i = 0; i < Hg.size(); i++)
+ {
+ for (size_t j = i+1; j < Hg.size(); j++, idx++)
+ {
+ //Defines coordinate transformation from Gi to Gj
+ //Hgi is from Gi (gripper) to RW (robot base)
+ //Hgj is from Gj (gripper) to RW (robot base)
+ Mat Hgij = homogeneousInverse(Hg[j]) * Hg[i]; //eq 6
+ vec_Hgij.push_back(Hgij);
+ //Rotation axis for Rgij which is the 3D rotation from gripper coordinate frame Gi to Gj
+ Mat Pgij = 2*rot2quatMinimal(Hgij);
+
+ //Defines coordinate transformation from Ci to Cj
+ //Hci is from CW (calibration target) to Ci (camera)
+ //Hcj is from CW (calibration target) to Cj (camera)
+ Mat Hcij = Hc[j] * homogeneousInverse(Hc[i]); //eq 7
+ vec_Hcij.push_back(Hcij);
+ //Rotation axis for Rcij
+ Mat Pcij = 2*rot2quatMinimal(Hcij);
+
+ //Left-hand side: skew(Pgij+Pcij)
+ skew(Pgij+Pcij).copyTo(A(Rect(0, idx*3, 3, 3)));
+ //Right-hand side: Pcij - Pgij
+ Mat diff = Pcij - Pgij;
+ diff.copyTo(B(Rect(0, idx*3, 1, 3)));
+ }
+ }
+
+ Mat Pcg_;
+ //Rotation from camera to gripper is obtained from the set of equations:
+ // skew(Pgij+Pcij) * Pcg_ = Pcij - Pgij (eq 12)
+ solve(A, B, Pcg_, DECOMP_SVD);
+
+ Mat Pcg_norm = Pcg_.t() * Pcg_;
+ //Obtained non-unit quaternion is scaled back to unit value that
+ //designates camera-gripper rotation
+ Mat Pcg = 2 * Pcg_ / sqrt(1 + Pcg_norm.at<double>(0,0)); //eq 14
+
+ Mat Rcg = quatMinimal2rot(Pcg/2.0);
+
+ idx = 0;
+ for (size_t i = 0; i < Hg.size(); i++)
+ {
+ for (size_t j = i+1; j < Hg.size(); j++, idx++)
+ {
+ //Defines coordinate transformation from Gi to Gj
+ //Hgi is from Gi (gripper) to RW (robot base)
+ //Hgj is from Gj (gripper) to RW (robot base)
+ Mat Hgij = vec_Hgij[static_cast<size_t>(idx)];
+ //Defines coordinate transformation from Ci to Cj
+ //Hci is from CW (calibration target) to Ci (camera)
+ //Hcj is from CW (calibration target) to Cj (camera)
+ Mat Hcij = vec_Hcij[static_cast<size_t>(idx)];
+
+ //Left-hand side: (Rgij - I)
+ Mat diff = Hgij(Rect(0,0,3,3)) - Mat::eye(3,3,CV_64FC1);
+ diff.copyTo(A(Rect(0, idx*3, 3, 3)));
+
+ //Right-hand side: Rcg*Tcij - Tgij
+ diff = Rcg*Hcij(Rect(3, 0, 1, 3)) - Hgij(Rect(3, 0, 1, 3));
+ diff.copyTo(B(Rect(0, idx*3, 1, 3)));
+ }
+ }
+
+ Mat Tcg;
+ //Translation from camera to gripper is obtained from the set of equations:
+ // (Rgij - I) * Tcg = Rcg*Tcij - Tgij (eq 15)
+ solve(A, B, Tcg, DECOMP_SVD);
+
+ R_cam2gripper = Rcg;
+ t_cam2gripper = Tcg;
+}
+
+//Reference:
+//F. Park, B. Martin, "Robot Sensor Calibration: Solving AX = XB on the Euclidean Group."
+//In IEEE Transactions on Robotics and Automation, 10(5): 717-721, 1994.
+//Matlab code: http://math.loyola.edu/~mili/Calibration/
+static void calibrateHandEyePark(const std::vector<Mat>& Hg, const std::vector<Mat>& Hc,
+ Mat& R_cam2gripper, Mat& t_cam2gripper)
+{
+ Mat M = Mat::zeros(3, 3, CV_64FC1);
+
+ for (size_t i = 0; i < Hg.size(); i++)
+ {
+ for (size_t j = i+1; j < Hg.size(); j++)
+ {
+ Mat Hgij = homogeneousInverse(Hg[j]) * Hg[i];
+ Mat Hcij = Hc[j] * homogeneousInverse(Hc[i]);
+
+ Mat Rgij = Hgij(Rect(0, 0, 3, 3));
+ Mat Rcij = Hcij(Rect(0, 0, 3, 3));
+
+ Mat a, b;
+ Rodrigues(Rgij, a);
+ Rodrigues(Rcij, b);
+
+ M += b * a.t();
+ }
+ }
+
+ Mat eigenvalues, eigenvectors;
+ eigen(M.t()*M, eigenvalues, eigenvectors);
+
+ Mat v = Mat::zeros(3, 3, CV_64FC1);
+ for (int i = 0; i < 3; i++) {
+ v.at<double>(i,i) = 1.0 / sqrt(eigenvalues.at<double>(i,0));
+ }
+
+ Mat R = eigenvectors.t() * v * eigenvectors * M.t();
+ R_cam2gripper = R;
+
+ int K = static_cast<int>((Hg.size()*Hg.size() - Hg.size()) / 2.0);
+ Mat C(3*K, 3, CV_64FC1);
+ Mat d(3*K, 1, CV_64FC1);
+ Mat I3 = Mat::eye(3, 3, CV_64FC1);
+
+ int idx = 0;
+ for (size_t i = 0; i < Hg.size(); i++)
+ {
+ for (size_t j = i+1; j < Hg.size(); j++, idx++)
+ {
+ Mat Hgij = homogeneousInverse(Hg[j]) * Hg[i];
+ Mat Hcij = Hc[j] * homogeneousInverse(Hc[i]);
+
+ Mat Rgij = Hgij(Rect(0, 0, 3, 3));
+
+ Mat tgij = Hgij(Rect(3, 0, 1, 3));
+ Mat tcij = Hcij(Rect(3, 0, 1, 3));
+
+ Mat I_tgij = I3 - Rgij;
+ I_tgij.copyTo(C(Rect(0, 3*idx, 3, 3)));
+
+ Mat A_RB = tgij - R*tcij;
+ A_RB.copyTo(d(Rect(0, 3*idx, 1, 3)));
+ }
+ }
+
+ Mat t;
+ solve(C, d, t, DECOMP_SVD);
+ t_cam2gripper = t;
+}
+
+//Reference:
+//R. Horaud, F. Dornaika, "Hand-Eye Calibration"
+//In International Journal of Robotics Research, 14(3): 195-210, 1995.
+//Matlab code: http://math.loyola.edu/~mili/Calibration/
+static void calibrateHandEyeHoraud(const std::vector<Mat>& Hg, const std::vector<Mat>& Hc,
+ Mat& R_cam2gripper, Mat& t_cam2gripper)
+{
+ Mat A = Mat::zeros(4, 4, CV_64FC1);
+
+ for (size_t i = 0; i < Hg.size(); i++)
+ {
+ for (size_t j = i+1; j < Hg.size(); j++)
+ {
+ Mat Hgij = homogeneousInverse(Hg[j]) * Hg[i];
+ Mat Hcij = Hc[j] * homogeneousInverse(Hc[i]);
+
+ Mat Rgij = Hgij(Rect(0, 0, 3, 3));
+ Mat Rcij = Hcij(Rect(0, 0, 3, 3));
+
+ Mat qgij = rot2quat(Rgij);
+ double r0 = qgij.at<double>(0,0);
+ double rx = qgij.at<double>(1,0);
+ double ry = qgij.at<double>(2,0);
+ double rz = qgij.at<double>(3,0);
+
+ // Q(r) Appendix A
+ Matx44d Qvi(r0, -rx, -ry, -rz,
+ rx, r0, -rz, ry,
+ ry, rz, r0, -rx,
+ rz, -ry, rx, r0);
+
+ Mat qcij = rot2quat(Rcij);
+ r0 = qcij.at<double>(0,0);
+ rx = qcij.at<double>(1,0);
+ ry = qcij.at<double>(2,0);
+ rz = qcij.at<double>(3,0);
+
+ // W(r) Appendix A
+ Matx44d Wvi(r0, -rx, -ry, -rz,
+ rx, r0, rz, -ry,
+ ry, -rz, r0, rx,
+ rz, ry, -rx, r0);
+
+ // Ai = (Q(vi') - W(vi))^T (Q(vi') - W(vi))
+ A += (Qvi - Wvi).t() * (Qvi - Wvi);
+ }
+ }
+
+ Mat eigenvalues, eigenvectors;
+ eigen(A, eigenvalues, eigenvectors);
+
+ Mat R = quat2rot(eigenvectors.row(3).t());
+ R_cam2gripper = R;
+
+ int K = static_cast<int>((Hg.size()*Hg.size() - Hg.size()) / 2.0);
+ Mat C(3*K, 3, CV_64FC1);
+ Mat d(3*K, 1, CV_64FC1);
+ Mat I3 = Mat::eye(3, 3, CV_64FC1);
+
+ int idx = 0;
+ for (size_t i = 0; i < Hg.size(); i++)
+ {
+ for (size_t j = i+1; j < Hg.size(); j++, idx++)
+ {
+ Mat Hgij = homogeneousInverse(Hg[j]) * Hg[i];
+ Mat Hcij = Hc[j] * homogeneousInverse(Hc[i]);
+
+ Mat Rgij = Hgij(Rect(0, 0, 3, 3));
+
+ Mat tgij = Hgij(Rect(3, 0, 1, 3));
+ Mat tcij = Hcij(Rect(3, 0, 1, 3));
+
+ Mat I_tgij = I3 - Rgij;
+ I_tgij.copyTo(C(Rect(0, 3*idx, 3, 3)));
+
+ Mat A_RB = tgij - R*tcij;
+ A_RB.copyTo(d(Rect(0, 3*idx, 1, 3)));
+ }
+ }
+
+ Mat t;
+ solve(C, d, t, DECOMP_SVD);
+ t_cam2gripper = t;
+}
+
+// sign function, return -1 if negative values, +1 otherwise
+static int sign_double(double val)
+{
+ return (0 < val) - (val < 0);
+}
+
+//Reference:
+//N. Andreff, R. Horaud, B. Espiau, "On-line Hand-Eye Calibration."
+//In Second International Conference on 3-D Digital Imaging and Modeling (3DIM'99), pages 430-436, 1999.
+//Matlab code: http://math.loyola.edu/~mili/Calibration/
+static void calibrateHandEyeAndreff(const std::vector<Mat>& Hg, const std::vector<Mat>& Hc,
+ Mat& R_cam2gripper, Mat& t_cam2gripper)
+{
+ int K = static_cast<int>((Hg.size()*Hg.size() - Hg.size()) / 2.0);
+ Mat A(12*K, 12, CV_64FC1);
+ Mat B(12*K, 1, CV_64FC1);
+
+ Mat I9 = Mat::eye(9, 9, CV_64FC1);
+ Mat I3 = Mat::eye(3, 3, CV_64FC1);
+ Mat O9x3 = Mat::zeros(9, 3, CV_64FC1);
+ Mat O9x1 = Mat::zeros(9, 1, CV_64FC1);
+
+ int idx = 0;
+ for (size_t i = 0; i < Hg.size(); i++)
+ {
+ for (size_t j = i+1; j < Hg.size(); j++, idx++)
+ {
+ Mat Hgij = homogeneousInverse(Hg[j]) * Hg[i];
+ Mat Hcij = Hc[j] * homogeneousInverse(Hc[i]);
+
+ Mat Rgij = Hgij(Rect(0, 0, 3, 3));
+ Mat Rcij = Hcij(Rect(0, 0, 3, 3));
+
+ Mat tgij = Hgij(Rect(3, 0, 1, 3));
+ Mat tcij = Hcij(Rect(3, 0, 1, 3));
+
+ //Eq 10
+ Mat a00 = I9 - kron(Rgij, Rcij);
+ Mat a01 = O9x3;
+ Mat a10 = kron(I3, tcij.t());
+ Mat a11 = I3 - Rgij;
+
+ a00.copyTo(A(Rect(0, idx*12, 9, 9)));
+ a01.copyTo(A(Rect(9, idx*12, 3, 9)));
+ a10.copyTo(A(Rect(0, idx*12 + 9, 9, 3)));
+ a11.copyTo(A(Rect(9, idx*12 + 9, 3, 3)));
+
+ O9x1.copyTo(B(Rect(0, idx*12, 1, 9)));
+ tgij.copyTo(B(Rect(0, idx*12 + 9, 1, 3)));
+ }
+ }
+
+ Mat X;
+ solve(A, B, X, DECOMP_SVD);
+
+ Mat R = X(Rect(0, 0, 1, 9));
+ int newSize[] = {3, 3};
+ R = R.reshape(1, 2, newSize);
+ //Eq 15
+ double det = determinant(R);
+ R = pow(sign_double(det) / abs(det), 1.0/3.0) * R;
+
+ Mat w, u, vt;
+ SVDecomp(R, w, u, vt);
+ R = u*vt;
+
+ if (determinant(R) < 0)
+ {
+ Mat diag = (Mat_<double>(3,3) << 1.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, -1.0);
+ R = u*diag*vt;
+ }
+
+ R_cam2gripper = R;
+
+ Mat t = X(Rect(0, 9, 1, 3));
+ t_cam2gripper = t;
+}
+
+//Reference:
+//K. Daniilidis, "Hand-Eye Calibration Using Dual Quaternions."
+//In The International Journal of Robotics Research,18(3): 286-298, 1998.
+//Matlab code: http://math.loyola.edu/~mili/Calibration/
+static void calibrateHandEyeDaniilidis(const std::vector<Mat>& Hg, const std::vector<Mat>& Hc,
+ Mat& R_cam2gripper, Mat& t_cam2gripper)
+{
+ int K = static_cast<int>((Hg.size()*Hg.size() - Hg.size()) / 2.0);
+ Mat T = Mat::zeros(6*K, 8, CV_64FC1);
+
+ int idx = 0;
+ for (size_t i = 0; i < Hg.size(); i++)
+ {
+ for (size_t j = i+1; j < Hg.size(); j++, idx++)
+ {
+ Mat Hgij = homogeneousInverse(Hg[j]) * Hg[i];
+ Mat Hcij = Hc[j] * homogeneousInverse(Hc[i]);
+
+ Mat dualqa = homogeneous2dualQuaternion(Hgij);
+ Mat dualqb = homogeneous2dualQuaternion(Hcij);
+
+ Mat a = dualqa(Rect(0, 1, 1, 3));
+ Mat b = dualqb(Rect(0, 1, 1, 3));
+
+ Mat aprime = dualqa(Rect(0, 5, 1, 3));
+ Mat bprime = dualqb(Rect(0, 5, 1, 3));
+
+ //Eq 31
+ Mat s00 = a - b;
+ Mat s01 = skew(a + b);
+ Mat s10 = aprime - bprime;
+ Mat s11 = skew(aprime + bprime);
+ Mat s12 = a - b;
+ Mat s13 = skew(a + b);
+
+ s00.copyTo(T(Rect(0, idx*6, 1, 3)));
+ s01.copyTo(T(Rect(1, idx*6, 3, 3)));
+ s10.copyTo(T(Rect(0, idx*6 + 3, 1, 3)));
+ s11.copyTo(T(Rect(1, idx*6 + 3, 3, 3)));
+ s12.copyTo(T(Rect(4, idx*6 + 3, 1, 3)));
+ s13.copyTo(T(Rect(5, idx*6 + 3, 3, 3)));
+ }
+ }
+
+ Mat w, u, vt;
+ SVDecomp(T, w, u, vt);
+ Mat v = vt.t();
+
+ Mat u1 = v(Rect(6, 0, 1, 4));
+ Mat v1 = v(Rect(6, 4, 1, 4));
+ Mat u2 = v(Rect(7, 0, 1, 4));
+ Mat v2 = v(Rect(7, 4, 1, 4));
+
+ //Solves Eq 34, Eq 35
+ Mat ma = u1.t()*v1;
+ Mat mb = u1.t()*v2 + u2.t()*v1;
+ Mat mc = u2.t()*v2;
+
+ double a = ma.at<double>(0,0);
+ double b = mb.at<double>(0,0);
+ double c = mc.at<double>(0,0);
+
+ double s1 = (-b + sqrt(b*b - 4*a*c)) / (2*a);
+ double s2 = (-b - sqrt(b*b - 4*a*c)) / (2*a);
+
+ Mat sol1 = s1*s1*u1.t()*u1 + 2*s1*u1.t()*u2 + u2.t()*u2;
+ Mat sol2 = s2*s2*u1.t()*u1 + 2*s2*u1.t()*u2 + u2.t()*u2;
+ double s, val;
+ if (sol1.at<double>(0,0) > sol2.at<double>(0,0))
+ {
+ s = s1;
+ val = sol1.at<double>(0,0);
+ }
+ else
+ {
+ s = s2;
+ val = sol2.at<double>(0,0);
+ }
+
+ double lambda2 = sqrt(1.0 / val);
+ double lambda1 = s * lambda2;
+
+ Mat dualq = lambda1 * v(Rect(6, 0, 1, 8)) + lambda2*v(Rect(7, 0, 1, 8));
+ Mat X = dualQuaternion2homogeneous(dualq);
+
+ Mat R = X(Rect(0, 0, 3, 3));
+ Mat t = X(Rect(3, 0, 1, 3));
+ R_cam2gripper = R;
+ t_cam2gripper = t;
+}
+
+void calibrateHandEye(InputArrayOfArrays R_gripper2base, InputArrayOfArrays t_gripper2base,
+ InputArrayOfArrays R_target2cam, InputArrayOfArrays t_target2cam,
+ OutputArray R_cam2gripper, OutputArray t_cam2gripper,
+ HandEyeCalibrationMethod method)
+{
+ CV_Assert(R_gripper2base.isMatVector() && t_gripper2base.isMatVector() &&
+ R_target2cam.isMatVector() && t_target2cam.isMatVector());
+
+ std::vector<Mat> R_gripper2base_, t_gripper2base_;
+ R_gripper2base.getMatVector(R_gripper2base_);
+ t_gripper2base.getMatVector(t_gripper2base_);
+
+ std::vector<Mat> R_target2cam_, t_target2cam_;
+ R_target2cam.getMatVector(R_target2cam_);
+ t_target2cam.getMatVector(t_target2cam_);
+
+ CV_Assert(R_gripper2base_.size() == t_gripper2base_.size() &&
+ R_target2cam_.size() == t_target2cam_.size() &&
+ R_gripper2base_.size() == R_target2cam_.size());
+ CV_Assert(R_gripper2base_.size() >= 3);
+
+ //Notation used in Tsai paper
+ //Defines coordinate transformation from G (gripper) to RW (robot base)
+ std::vector<Mat> Hg;
+ Hg.reserve(R_gripper2base_.size());
+ for (size_t i = 0; i < R_gripper2base_.size(); i++)
+ {
+ Mat m = Mat::eye(4, 4, CV_64FC1);
+ Mat R = m(Rect(0, 0, 3, 3));
+ R_gripper2base_[i].convertTo(R, CV_64F);
+
+ Mat t = m(Rect(3, 0, 1, 3));
+ t_gripper2base_[i].convertTo(t, CV_64F);
+
+ Hg.push_back(m);
+ }
+
+ //Defines coordinate transformation from CW (calibration target) to C (camera)
+ std::vector<Mat> Hc;
+ Hc.reserve(R_target2cam_.size());
+ for (size_t i = 0; i < R_target2cam_.size(); i++)
+ {
+ Mat m = Mat::eye(4, 4, CV_64FC1);
+ Mat R = m(Rect(0, 0, 3, 3));
+ R_target2cam_[i].convertTo(R, CV_64F);
+
+ Mat t = m(Rect(3, 0, 1, 3));
+ t_target2cam_[i].convertTo(t, CV_64F);
+
+ Hc.push_back(m);
+ }
+
+ Mat Rcg = Mat::eye(3, 3, CV_64FC1);
+ Mat Tcg = Mat::zeros(3, 1, CV_64FC1);
+
+ switch (method)
+ {
+ case CALIB_HAND_EYE_TSAI:
+ calibrateHandEyeTsai(Hg, Hc, Rcg, Tcg);
+ break;
+
+ case CALIB_HAND_EYE_PARK:
+ calibrateHandEyePark(Hg, Hc, Rcg, Tcg);
+ break;
+
+ case CALIB_HAND_EYE_HORAUD:
+ calibrateHandEyeHoraud(Hg, Hc, Rcg, Tcg);
+ break;
+
+ case CALIB_HAND_EYE_ANDREFF:
+ calibrateHandEyeAndreff(Hg, Hc, Rcg, Tcg);
+ break;
+
+ case CALIB_HAND_EYE_DANIILIDIS:
+ calibrateHandEyeDaniilidis(Hg, Hc, Rcg, Tcg);
+ break;
+
+ default:
+ break;
+ }
+
+ Rcg.copyTo(R_cam2gripper);
+ Tcg.copyTo(t_cam2gripper);
+}
+}
Vec4d k = _D.depth() == CV_32F ? (Vec4d)*_D.getMat().ptr<Vec4f>(): *_D.getMat().ptr<Vec4d>();
+ const bool isJacobianNeeded = jacobian.needed();
JacobianRow *Jn = 0;
- if (jacobian.needed())
+ if (isJacobianNeeded)
{
int nvars = 2 + 2 + 1 + 4 + 3 + 3; // f, c, alpha, k, om, T,
jacobian.create(2*(int)n, nvars, CV_64F);
else
xpd[i] = final_point;
- if (jacobian.needed())
+ if (isJacobianNeeded)
{
//Vec3d Xi = pdepth == CV_32F ? (Vec3d)Xf[i] : Xd[i];
//Vec3d Y = aff*Xi;
--- /dev/null
+// 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"
+#include "opencv2/calib3d.hpp"
+
+namespace opencv_test { namespace {
+
+class CV_CalibrateHandEyeTest : public cvtest::BaseTest
+{
+public:
+ CV_CalibrateHandEyeTest() {
+ eps_rvec[CALIB_HAND_EYE_TSAI] = 1.0e-8;
+ eps_rvec[CALIB_HAND_EYE_PARK] = 1.0e-8;
+ eps_rvec[CALIB_HAND_EYE_HORAUD] = 1.0e-8;
+ eps_rvec[CALIB_HAND_EYE_ANDREFF] = 1.0e-8;
+ eps_rvec[CALIB_HAND_EYE_DANIILIDIS] = 1.0e-8;
+
+ eps_tvec[CALIB_HAND_EYE_TSAI] = 1.0e-8;
+ eps_tvec[CALIB_HAND_EYE_PARK] = 1.0e-8;
+ eps_tvec[CALIB_HAND_EYE_HORAUD] = 1.0e-8;
+ eps_tvec[CALIB_HAND_EYE_ANDREFF] = 1.0e-8;
+ eps_tvec[CALIB_HAND_EYE_DANIILIDIS] = 1.0e-8;
+
+ eps_rvec_noise[CALIB_HAND_EYE_TSAI] = 2.0e-2;
+ eps_rvec_noise[CALIB_HAND_EYE_PARK] = 2.0e-2;
+ eps_rvec_noise[CALIB_HAND_EYE_HORAUD] = 2.0e-2;
+ eps_rvec_noise[CALIB_HAND_EYE_ANDREFF] = 1.0e-2;
+ eps_rvec_noise[CALIB_HAND_EYE_DANIILIDIS] = 1.0e-2;
+
+ eps_tvec_noise[CALIB_HAND_EYE_TSAI] = 5.0e-2;
+ eps_tvec_noise[CALIB_HAND_EYE_PARK] = 5.0e-2;
+ eps_tvec_noise[CALIB_HAND_EYE_HORAUD] = 5.0e-2;
+ eps_tvec_noise[CALIB_HAND_EYE_ANDREFF] = 5.0e-2;
+ eps_tvec_noise[CALIB_HAND_EYE_DANIILIDIS] = 5.0e-2;
+ }
+protected:
+ virtual void run(int);
+ void generatePose(RNG& rng, double min_theta, double max_theta,
+ double min_tx, double max_tx,
+ double min_ty, double max_ty,
+ double min_tz, double max_tz,
+ Mat& R, Mat& tvec,
+ bool randSign=false);
+ void simulateData(RNG& rng, int nPoses,
+ std::vector<Mat> &R_gripper2base, std::vector<Mat> &t_gripper2base,
+ std::vector<Mat> &R_target2cam, std::vector<Mat> &t_target2cam,
+ bool noise, Mat& R_cam2gripper, Mat& t_cam2gripper);
+ Mat homogeneousInverse(const Mat& T);
+ std::string getMethodName(HandEyeCalibrationMethod method);
+ double sign_double(double val);
+
+ double eps_rvec[5];
+ double eps_tvec[5];
+ double eps_rvec_noise[5];
+ double eps_tvec_noise[5];
+};
+
+void CV_CalibrateHandEyeTest::run(int)
+{
+ ts->set_failed_test_info(cvtest::TS::OK);
+
+ RNG& rng = ts->get_rng();
+
+ std::vector<std::vector<double> > vec_rvec_diff(5);
+ std::vector<std::vector<double> > vec_tvec_diff(5);
+ std::vector<std::vector<double> > vec_rvec_diff_noise(5);
+ std::vector<std::vector<double> > vec_tvec_diff_noise(5);
+
+ std::vector<HandEyeCalibrationMethod> methods;
+ methods.push_back(CALIB_HAND_EYE_TSAI);
+ methods.push_back(CALIB_HAND_EYE_PARK);
+ methods.push_back(CALIB_HAND_EYE_HORAUD);
+ methods.push_back(CALIB_HAND_EYE_ANDREFF);
+ methods.push_back(CALIB_HAND_EYE_DANIILIDIS);
+
+ const int nTests = 100;
+ for (int i = 0; i < nTests; i++)
+ {
+ const int nPoses = 10;
+ {
+ //No noise
+ std::vector<Mat> R_gripper2base, t_gripper2base;
+ std::vector<Mat> R_target2cam, t_target2cam;
+ Mat R_cam2gripper_true, t_cam2gripper_true;
+
+ const bool noise = false;
+ simulateData(rng, nPoses, R_gripper2base, t_gripper2base, R_target2cam, t_target2cam, noise, R_cam2gripper_true, t_cam2gripper_true);
+
+ for (size_t idx = 0; idx < methods.size(); idx++)
+ {
+ Mat rvec_cam2gripper_true;
+ cv::Rodrigues(R_cam2gripper_true, rvec_cam2gripper_true);
+
+ Mat R_cam2gripper_est, t_cam2gripper_est;
+ calibrateHandEye(R_gripper2base, t_gripper2base, R_target2cam, t_target2cam, R_cam2gripper_est, t_cam2gripper_est, methods[idx]);
+
+ Mat rvec_cam2gripper_est;
+ cv::Rodrigues(R_cam2gripper_est, rvec_cam2gripper_est);
+
+ double rvecDiff = cvtest::norm(rvec_cam2gripper_true, rvec_cam2gripper_est, NORM_L2);
+ double tvecDiff = cvtest::norm(t_cam2gripper_true, t_cam2gripper_est, NORM_L2);
+
+ vec_rvec_diff[idx].push_back(rvecDiff);
+ vec_tvec_diff[idx].push_back(tvecDiff);
+
+ const double epsilon_rvec = eps_rvec[idx];
+ const double epsilon_tvec = eps_tvec[idx];
+
+ //Maybe a better accuracy test would be to compare the mean and std errors with some thresholds?
+ if (rvecDiff > epsilon_rvec || tvecDiff > epsilon_tvec)
+ {
+ ts->printf(cvtest::TS::LOG, "Invalid accuracy (no noise) for method: %s, rvecDiff: %f, epsilon_rvec: %f, tvecDiff: %f, epsilon_tvec: %f\n",
+ getMethodName(methods[idx]).c_str(), rvecDiff, epsilon_rvec, tvecDiff, epsilon_tvec);
+ ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
+ }
+ }
+ }
+
+ {
+ //Gaussian noise on transformations between calibration target frame and camera frame and between gripper and robot base frames
+ std::vector<Mat> R_gripper2base, t_gripper2base;
+ std::vector<Mat> R_target2cam, t_target2cam;
+ Mat R_cam2gripper_true, t_cam2gripper_true;
+
+ const bool noise = true;
+ simulateData(rng, nPoses, R_gripper2base, t_gripper2base, R_target2cam, t_target2cam, noise, R_cam2gripper_true, t_cam2gripper_true);
+
+ for (size_t idx = 0; idx < methods.size(); idx++)
+ {
+ Mat rvec_cam2gripper_true;
+ cv::Rodrigues(R_cam2gripper_true, rvec_cam2gripper_true);
+
+ Mat R_cam2gripper_est, t_cam2gripper_est;
+ calibrateHandEye(R_gripper2base, t_gripper2base, R_target2cam, t_target2cam, R_cam2gripper_est, t_cam2gripper_est, methods[idx]);
+
+ Mat rvec_cam2gripper_est;
+ cv::Rodrigues(R_cam2gripper_est, rvec_cam2gripper_est);
+
+ double rvecDiff = cvtest::norm(rvec_cam2gripper_true, rvec_cam2gripper_est, NORM_L2);
+ double tvecDiff = cvtest::norm(t_cam2gripper_true, t_cam2gripper_est, NORM_L2);
+
+ vec_rvec_diff_noise[idx].push_back(rvecDiff);
+ vec_tvec_diff_noise[idx].push_back(tvecDiff);
+
+ const double epsilon_rvec = eps_rvec_noise[idx];
+ const double epsilon_tvec = eps_tvec_noise[idx];
+
+ //Maybe a better accuracy test would be to compare the mean and std errors with some thresholds?
+ if (rvecDiff > epsilon_rvec || tvecDiff > epsilon_tvec)
+ {
+ ts->printf(cvtest::TS::LOG, "Invalid accuracy (noise) for method: %s, rvecDiff: %f, epsilon_rvec: %f, tvecDiff: %f, epsilon_tvec: %f\n",
+ getMethodName(methods[idx]).c_str(), rvecDiff, epsilon_rvec, tvecDiff, epsilon_tvec);
+ ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
+ }
+ }
+ }
+ }
+
+ for (size_t idx = 0; idx < methods.size(); idx++)
+ {
+ {
+ double max_rvec_diff = *std::max_element(vec_rvec_diff[idx].begin(), vec_rvec_diff[idx].end());
+ double mean_rvec_diff = std::accumulate(vec_rvec_diff[idx].begin(),
+ vec_rvec_diff[idx].end(), 0.0) / vec_rvec_diff[idx].size();
+ double sq_sum_rvec_diff = std::inner_product(vec_rvec_diff[idx].begin(), vec_rvec_diff[idx].end(),
+ vec_rvec_diff[idx].begin(), 0.0);
+ double std_rvec_diff = std::sqrt(sq_sum_rvec_diff / vec_rvec_diff[idx].size() - mean_rvec_diff * mean_rvec_diff);
+
+ double max_tvec_diff = *std::max_element(vec_tvec_diff[idx].begin(), vec_tvec_diff[idx].end());
+ double mean_tvec_diff = std::accumulate(vec_tvec_diff[idx].begin(),
+ vec_tvec_diff[idx].end(), 0.0) / vec_tvec_diff[idx].size();
+ double sq_sum_tvec_diff = std::inner_product(vec_tvec_diff[idx].begin(), vec_tvec_diff[idx].end(),
+ vec_tvec_diff[idx].begin(), 0.0);
+ double std_tvec_diff = std::sqrt(sq_sum_tvec_diff / vec_tvec_diff[idx].size() - mean_tvec_diff * mean_tvec_diff);
+
+ std::cout << "\nMethod " << getMethodName(methods[idx]) << ":\n"
+ << "Max rvec error: " << max_rvec_diff << ", Mean rvec error: " << mean_rvec_diff
+ << ", Std rvec error: " << std_rvec_diff << "\n"
+ << "Max tvec error: " << max_tvec_diff << ", Mean tvec error: " << mean_tvec_diff
+ << ", Std tvec error: " << std_tvec_diff << std::endl;
+ }
+ {
+ double max_rvec_diff = *std::max_element(vec_rvec_diff_noise[idx].begin(), vec_rvec_diff_noise[idx].end());
+ double mean_rvec_diff = std::accumulate(vec_rvec_diff_noise[idx].begin(),
+ vec_rvec_diff_noise[idx].end(), 0.0) / vec_rvec_diff_noise[idx].size();
+ double sq_sum_rvec_diff = std::inner_product(vec_rvec_diff_noise[idx].begin(), vec_rvec_diff_noise[idx].end(),
+ vec_rvec_diff_noise[idx].begin(), 0.0);
+ double std_rvec_diff = std::sqrt(sq_sum_rvec_diff / vec_rvec_diff_noise[idx].size() - mean_rvec_diff * mean_rvec_diff);
+
+ double max_tvec_diff = *std::max_element(vec_tvec_diff_noise[idx].begin(), vec_tvec_diff_noise[idx].end());
+ double mean_tvec_diff = std::accumulate(vec_tvec_diff_noise[idx].begin(),
+ vec_tvec_diff_noise[idx].end(), 0.0) / vec_tvec_diff_noise[idx].size();
+ double sq_sum_tvec_diff = std::inner_product(vec_tvec_diff_noise[idx].begin(), vec_tvec_diff_noise[idx].end(),
+ vec_tvec_diff_noise[idx].begin(), 0.0);
+ double std_tvec_diff = std::sqrt(sq_sum_tvec_diff / vec_tvec_diff_noise[idx].size() - mean_tvec_diff * mean_tvec_diff);
+
+ std::cout << "Method (noise) " << getMethodName(methods[idx]) << ":\n"
+ << "Max rvec error: " << max_rvec_diff << ", Mean rvec error: " << mean_rvec_diff
+ << ", Std rvec error: " << std_rvec_diff << "\n"
+ << "Max tvec error: " << max_tvec_diff << ", Mean tvec error: " << mean_tvec_diff
+ << ", Std tvec error: " << std_tvec_diff << std::endl;
+ }
+ }
+}
+
+void CV_CalibrateHandEyeTest::generatePose(RNG& rng, double min_theta, double max_theta,
+ double min_tx, double max_tx,
+ double min_ty, double max_ty,
+ double min_tz, double max_tz,
+ Mat& R, Mat& tvec,
+ bool random_sign)
+{
+ Mat axis(3, 1, CV_64FC1);
+ for (int i = 0; i < 3; i++)
+ {
+ axis.at<double>(i,0) = rng.uniform(-1.0, 1.0);
+ }
+ double theta = rng.uniform(min_theta, max_theta);
+ if (random_sign)
+ {
+ theta *= sign_double(rng.uniform(-1.0, 1.0));
+ }
+
+ Mat rvec(3, 1, CV_64FC1);
+ rvec.at<double>(0,0) = theta*axis.at<double>(0,0);
+ rvec.at<double>(1,0) = theta*axis.at<double>(1,0);
+ rvec.at<double>(2,0) = theta*axis.at<double>(2,0);
+
+ tvec.create(3, 1, CV_64FC1);
+ tvec.at<double>(0,0) = rng.uniform(min_tx, max_tx);
+ tvec.at<double>(1,0) = rng.uniform(min_ty, max_ty);
+ tvec.at<double>(2,0) = rng.uniform(min_tz, max_tz);
+
+ if (random_sign)
+ {
+ tvec.at<double>(0,0) *= sign_double(rng.uniform(-1.0, 1.0));
+ tvec.at<double>(1,0) *= sign_double(rng.uniform(-1.0, 1.0));
+ tvec.at<double>(2,0) *= sign_double(rng.uniform(-1.0, 1.0));
+ }
+
+ cv::Rodrigues(rvec, R);
+}
+
+void CV_CalibrateHandEyeTest::simulateData(RNG& rng, int nPoses,
+ std::vector<Mat> &R_gripper2base, std::vector<Mat> &t_gripper2base,
+ std::vector<Mat> &R_target2cam, std::vector<Mat> &t_target2cam,
+ bool noise, Mat& R_cam2gripper, Mat& t_cam2gripper)
+{
+ //to avoid generating values close to zero,
+ //we use positive range values and randomize the sign
+ const bool random_sign = true;
+ generatePose(rng, 10.0*CV_PI/180.0, 50.0*CV_PI/180.0,
+ 0.05, 0.5, 0.05, 0.5, 0.05, 0.5,
+ R_cam2gripper, t_cam2gripper, random_sign);
+
+ Mat R_target2base, t_target2base;
+ generatePose(rng, 5.0*CV_PI/180.0, 85.0*CV_PI/180.0,
+ 0.5, 3.5, 0.5, 3.5, 0.5, 3.5,
+ R_target2base, t_target2base, random_sign);
+
+ for (int i = 0; i < nPoses; i++)
+ {
+ Mat R_gripper2base_, t_gripper2base_;
+ generatePose(rng, 5.0*CV_PI/180.0, 45.0*CV_PI/180.0,
+ 0.5, 1.5, 0.5, 1.5, 0.5, 1.5,
+ R_gripper2base_, t_gripper2base_, random_sign);
+
+ R_gripper2base.push_back(R_gripper2base_);
+ t_gripper2base.push_back(t_gripper2base_);
+
+ Mat T_cam2gripper = Mat::eye(4, 4, CV_64FC1);
+ R_cam2gripper.copyTo(T_cam2gripper(Rect(0, 0, 3, 3)));
+ t_cam2gripper.copyTo(T_cam2gripper(Rect(3, 0, 1, 3)));
+
+ Mat T_gripper2base = Mat::eye(4, 4, CV_64FC1);
+ R_gripper2base_.copyTo(T_gripper2base(Rect(0, 0, 3, 3)));
+ t_gripper2base_.copyTo(T_gripper2base(Rect(3, 0, 1, 3)));
+
+ Mat T_base2cam = homogeneousInverse(T_cam2gripper) * homogeneousInverse(T_gripper2base);
+ Mat T_target2base = Mat::eye(4, 4, CV_64FC1);
+ R_target2base.copyTo(T_target2base(Rect(0, 0, 3, 3)));
+ t_target2base.copyTo(T_target2base(Rect(3, 0, 1, 3)));
+ Mat T_target2cam = T_base2cam * T_target2base;
+
+ if (noise)
+ {
+ //Add some noise for the transformation between the target and the camera
+ Mat R_target2cam_noise = T_target2cam(Rect(0, 0, 3, 3));
+ Mat rvec_target2cam_noise;
+ cv::Rodrigues(R_target2cam_noise, rvec_target2cam_noise);
+ rvec_target2cam_noise.at<double>(0,0) += rng.gaussian(0.002);
+ rvec_target2cam_noise.at<double>(1,0) += rng.gaussian(0.002);
+ rvec_target2cam_noise.at<double>(2,0) += rng.gaussian(0.002);
+
+ cv::Rodrigues(rvec_target2cam_noise, R_target2cam_noise);
+
+ Mat t_target2cam_noise = T_target2cam(Rect(3, 0, 1, 3));
+ t_target2cam_noise.at<double>(0,0) += rng.gaussian(0.005);
+ t_target2cam_noise.at<double>(1,0) += rng.gaussian(0.005);
+ t_target2cam_noise.at<double>(2,0) += rng.gaussian(0.005);
+
+ //Add some noise for the transformation between the gripper and the robot base
+ Mat R_gripper2base_noise = T_gripper2base(Rect(0, 0, 3, 3));
+ Mat rvec_gripper2base_noise;
+ cv::Rodrigues(R_gripper2base_noise, rvec_gripper2base_noise);
+ rvec_gripper2base_noise.at<double>(0,0) += rng.gaussian(0.001);
+ rvec_gripper2base_noise.at<double>(1,0) += rng.gaussian(0.001);
+ rvec_gripper2base_noise.at<double>(2,0) += rng.gaussian(0.001);
+
+ cv::Rodrigues(rvec_gripper2base_noise, R_gripper2base_noise);
+
+ Mat t_gripper2base_noise = T_gripper2base(Rect(3, 0, 1, 3));
+ t_gripper2base_noise.at<double>(0,0) += rng.gaussian(0.001);
+ t_gripper2base_noise.at<double>(1,0) += rng.gaussian(0.001);
+ t_gripper2base_noise.at<double>(2,0) += rng.gaussian(0.001);
+ }
+
+ R_target2cam.push_back(T_target2cam(Rect(0, 0, 3, 3)));
+ t_target2cam.push_back(T_target2cam(Rect(3, 0, 1, 3)));
+ }
+}
+
+Mat CV_CalibrateHandEyeTest::homogeneousInverse(const Mat& T)
+{
+ CV_Assert( T.rows == 4 && T.cols == 4 );
+
+ Mat R = T(Rect(0, 0, 3, 3));
+ Mat t = T(Rect(3, 0, 1, 3));
+ Mat Rt = R.t();
+ Mat tinv = -Rt * t;
+ Mat Tinv = Mat::eye(4, 4, T.type());
+ Rt.copyTo(Tinv(Rect(0, 0, 3, 3)));
+ tinv.copyTo(Tinv(Rect(3, 0, 1, 3)));
+
+ return Tinv;
+}
+
+std::string CV_CalibrateHandEyeTest::getMethodName(HandEyeCalibrationMethod method)
+{
+ std::string method_name = "";
+ switch (method)
+ {
+ case CALIB_HAND_EYE_TSAI:
+ method_name = "Tsai";
+ break;
+
+ case CALIB_HAND_EYE_PARK:
+ method_name = "Park";
+ break;
+
+ case CALIB_HAND_EYE_HORAUD:
+ method_name = "Horaud";
+ break;
+
+ case CALIB_HAND_EYE_ANDREFF:
+ method_name = "Andreff";
+ break;
+
+ case CALIB_HAND_EYE_DANIILIDIS:
+ method_name = "Daniilidis";
+ break;
+
+ default:
+ break;
+ }
+
+ return method_name;
+}
+
+double CV_CalibrateHandEyeTest::sign_double(double val)
+{
+ return (0 < val) - (val < 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+TEST(Calib3d_CalibrateHandEye, regression) { CV_CalibrateHandEyeTest test; test.safe_run(); }
+
+}} // namespace
ocv_add_dispatched_file(mathfuncs_core SSE2 AVX AVX2)
ocv_add_dispatched_file(stat SSE4_2 AVX2)
ocv_add_dispatched_file(arithm SSE2 SSE4_1 AVX2 VSX3)
-ocv_add_dispatched_file(convert SSE2 AVX2)
+ocv_add_dispatched_file(convert SSE2 AVX2 VSX3)
ocv_add_dispatched_file(convert_scale SSE2 AVX2)
+ocv_add_dispatched_file(count_non_zero SSE2 AVX2)
+ocv_add_dispatched_file(matmul SSE2 AVX2)
+ocv_add_dispatched_file(mean SSE2 AVX2)
+ocv_add_dispatched_file(merge SSE2 AVX2)
+ocv_add_dispatched_file(split SSE2 AVX2)
+ocv_add_dispatched_file(sum SSE2 AVX2)
# dispatching for accuracy tests
ocv_add_dispatched_file_force_all(test_intrin128 TEST SSE2 SSE3 SSSE3 SSE4_1 SSE4_2 AVX FP16 AVX2)
endif()
if(HAVE_CUDA)
+ if(NOT HAVE_opencv_cudev)
+ message(FATAL_ERROR "CUDA: OpenCV requires enabled 'cudev' module from 'opencv_contrib' repository: https://github.com/opencv/opencv_contrib")
+ endif()
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef -Wenum-compare -Wunused-function -Wshadow)
endif()
@{
@defgroup core_hal_intrin_impl Private implementation helpers
@}
+ @defgroup core_lowlevel_api Low-level API for external libraries / plugins
@}
@}
*/
}
//constants for conversion from/to RGB and Gray, YUV, YCrCb according to BT.601
- const float B2YF = 0.114f;
- const float G2YF = 0.587f;
- const float R2YF = 0.299f;
+ constexpr float B2YF = 0.114f;
+ constexpr float G2YF = 0.587f;
+ constexpr float R2YF = 0.299f;
//to YCbCr
- const float YCBF = 0.564f; // == 1/2/(1-B2YF)
- const float YCRF = 0.713f; // == 1/2/(1-R2YF)
- const int YCBI = 9241; // == YCBF*16384
- const int YCRI = 11682; // == YCRF*16384
+ constexpr float YCBF = 0.564f; // == 1/2/(1-B2YF)
+ constexpr float YCRF = 0.713f; // == 1/2/(1-R2YF)
+ const int YCBI = 9241; // == YCBF*16384
+ const int YCRI = 11682; // == YCRF*16384
//to YUV
- const float B2UF = 0.492f;
- const float R2VF = 0.877f;
- const int B2UI = 8061; // == B2UF*16384
- const int R2VI = 14369; // == R2VF*16384
+ constexpr float B2UF = 0.492f;
+ constexpr float R2VF = 0.877f;
+ const int B2UI = 8061; // == B2UF*16384
+ const int R2VI = 14369; // == R2VF*16384
//from YUV
- const float U2BF = 2.032f;
- const float U2GF = -0.395f;
- const float V2GF = -0.581f;
- const float V2RF = 1.140f;
- const int U2BI = 33292;
- const int U2GI = -6472;
- const int V2GI = -9519;
- const int V2RI = 18678;
+ constexpr float U2BF = 2.032f;
+ constexpr float U2GF = -0.395f;
+ constexpr float V2GF = -0.581f;
+ constexpr float V2RF = 1.140f;
+ const int U2BI = 33292;
+ const int U2GI = -6472;
+ const int V2GI = -9519;
+ const int V2RI = 18678;
//from YCrCb
- const float CB2BF = 1.773f;
- const float CB2GF = -0.344f;
- const float CR2GF = -0.714f;
- const float CR2RF = 1.403f;
- const int CB2BI = 29049;
- const int CB2GI = -5636;
- const int CR2GI = -11698;
- const int CR2RI = 22987;
+ constexpr float CB2BF = 1.773f;
+ constexpr float CB2GF = -0.344f;
+ constexpr float CR2GF = -0.714f;
+ constexpr float CR2RF = 1.403f;
+ const int CB2BI = 29049;
+ const int CB2GI = -5636;
+ const int CR2GI = -11698;
+ const int CR2RI = 22987;
enum
{
#define CV_CPU_OPTIMIZATION_NAMESPACE cpu_baseline
#define CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN namespace cpu_baseline {
#define CV_CPU_OPTIMIZATION_NAMESPACE_END }
+#define CV_CPU_BASELINE_MODE 1
#endif
#ifdef __GNUC__
__attribute__((always_inline))
#endif
+ inline VZeroUpperGuard() { _mm256_zeroupper(); }
+#ifdef __GNUC__
+ __attribute__((always_inline))
+#endif
inline ~VZeroUpperGuard() { _mm256_zeroupper(); }
};
#define __CV_AVX_GUARD VZeroUpperGuard __vzeroupper_guard; CV_UNUSED(__vzeroupper_guard);
# endif
#endif
#ifndef CV_CONSTEXPR
-# define CV_CONSTEXPR const
+# define CV_CONSTEXPR
#endif
// Integer types portatibility
struct has_custom_delete
: public std::false_type {};
+// Force has_custom_delete to std::false_type when NVCC is compiling CUDA source files
+#ifndef __CUDACC__
template <typename T>
struct has_custom_delete<T, typename std::enable_if< sfinae::has_parenthesis_operator<DefaultDeleter<T>, void, T*>::value >::type >
: public std::true_type {};
-
+#endif
template<typename T>
struct Ptr : public std::shared_ptr<T>
inline vtyp vx_##loadsfx##_low(const typ* ptr) { return prefix##_##loadsfx##_low(ptr); } \
inline vtyp vx_##loadsfx##_halves(const typ* ptr0, const typ* ptr1) { return prefix##_##loadsfx##_halves(ptr0, ptr1); } \
inline void vx_store(typ* ptr, const vtyp& v) { return v_store(ptr, v); } \
- inline void vx_store_aligned(typ* ptr, const vtyp& v) { return v_store_aligned(ptr, v); }
+ inline void vx_store_aligned(typ* ptr, const vtyp& v) { return v_store_aligned(ptr, v); } \
+ inline vtyp vx_lut(const typ* ptr, const int* idx) { return prefix##_lut(ptr, idx); } \
+ inline vtyp vx_lut_pairs(const typ* ptr, const int* idx) { return prefix##_lut_pairs(ptr, idx); }
+
+#define CV_INTRIN_DEFINE_WIDE_LUT_QUAD(typ, vtyp, prefix) \
+ inline vtyp vx_lut_quads(const typ* ptr, const int* idx) { return prefix##_lut_quads(ptr, idx); }
#define CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(typ, wtyp, prefix) \
inline wtyp vx_load_expand(const typ* ptr) { return prefix##_load_expand(ptr); }
#define CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(typ, vtyp, short_typ, wtyp, qtyp, prefix, loadsfx) \
CV_INTRIN_DEFINE_WIDE_INTRIN(typ, vtyp, short_typ, prefix, loadsfx) \
+ CV_INTRIN_DEFINE_WIDE_LUT_QUAD(typ, vtyp, prefix) \
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(typ, wtyp, prefix) \
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND_Q(typ, qtyp, prefix)
CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(uchar, v_uint8, u8, v_uint16, v_uint32, prefix, load) \
CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(schar, v_int8, s8, v_int16, v_int32, prefix, load) \
CV_INTRIN_DEFINE_WIDE_INTRIN(ushort, v_uint16, u16, prefix, load) \
+ CV_INTRIN_DEFINE_WIDE_LUT_QUAD(ushort, v_uint16, prefix) \
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(ushort, v_uint32, prefix) \
CV_INTRIN_DEFINE_WIDE_INTRIN(short, v_int16, s16, prefix, load) \
+ CV_INTRIN_DEFINE_WIDE_LUT_QUAD(short, v_int16, prefix) \
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(short, v_int32, prefix) \
CV_INTRIN_DEFINE_WIDE_INTRIN(int, v_int32, s32, prefix, load) \
+ CV_INTRIN_DEFINE_WIDE_LUT_QUAD(int, v_int32, prefix) \
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(int, v_int64, prefix) \
CV_INTRIN_DEFINE_WIDE_INTRIN(unsigned, v_uint32, u32, prefix, load) \
+ CV_INTRIN_DEFINE_WIDE_LUT_QUAD(unsigned, v_uint32, prefix) \
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(unsigned, v_uint64, prefix) \
CV_INTRIN_DEFINE_WIDE_INTRIN(float, v_float32, f32, prefix, load) \
+ CV_INTRIN_DEFINE_WIDE_LUT_QUAD(float, v_float32, prefix) \
CV_INTRIN_DEFINE_WIDE_INTRIN(int64, v_int64, s64, prefix, load) \
CV_INTRIN_DEFINE_WIDE_INTRIN(uint64, v_uint64, u64, prefix, load) \
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(float16_t, v_float32, prefix)
typedef v_uint64x4 v_uint64;
typedef v_int64x4 v_int64;
typedef v_float32x8 v_float32;
+ CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v256)
#if CV_SIMD256_64F
typedef v_float64x4 v_float64;
- #endif
- CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v256)
CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v256, load)
+ #endif
inline void vx_cleanup() { v256_cleanup(); }
} // namespace
using namespace CV__SIMD_NAMESPACE;
typedef v_uint64x2 v_uint64;
typedef v_int64x2 v_int64;
typedef v_float32x4 v_float32;
- #if CV_SIMD128_64F
- typedef v_float64x2 v_float64;
- #endif
CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v)
#if CV_SIMD128_64F
+ typedef v_float64x2 v_float64;
CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v, load)
#endif
inline void vx_cleanup() { v_cleanup(); }
////////////// Lookup table access ////////////////////
+inline v_int8x32 v256_lut(const schar* tab, const int* idx)
+{
+ return v_int8x32(_mm256_setr_epi8(tab[idx[ 0]], tab[idx[ 1]], tab[idx[ 2]], tab[idx[ 3]], tab[idx[ 4]], tab[idx[ 5]], tab[idx[ 6]], tab[idx[ 7]],
+ tab[idx[ 8]], tab[idx[ 9]], tab[idx[10]], tab[idx[11]], tab[idx[12]], tab[idx[13]], tab[idx[14]], tab[idx[15]],
+ tab[idx[16]], tab[idx[17]], tab[idx[18]], tab[idx[19]], tab[idx[20]], tab[idx[21]], tab[idx[22]], tab[idx[23]],
+ tab[idx[24]], tab[idx[25]], tab[idx[26]], tab[idx[27]], tab[idx[28]], tab[idx[29]], tab[idx[30]], tab[idx[31]]));
+}
+inline v_int8x32 v256_lut_pairs(const schar* tab, const int* idx)
+{
+ return v_int8x32(_mm256_setr_epi16(*(const short*)(tab + idx[ 0]), *(const short*)(tab + idx[ 1]), *(const short*)(tab + idx[ 2]), *(const short*)(tab + idx[ 3]),
+ *(const short*)(tab + idx[ 4]), *(const short*)(tab + idx[ 5]), *(const short*)(tab + idx[ 6]), *(const short*)(tab + idx[ 7]),
+ *(const short*)(tab + idx[ 8]), *(const short*)(tab + idx[ 9]), *(const short*)(tab + idx[10]), *(const short*)(tab + idx[11]),
+ *(const short*)(tab + idx[12]), *(const short*)(tab + idx[13]), *(const short*)(tab + idx[14]), *(const short*)(tab + idx[15])));
+}
+inline v_int8x32 v256_lut_quads(const schar* tab, const int* idx)
+{
+ return v_int8x32(_mm256_i32gather_epi32((const int*)tab, _mm256_loadu_si256((const __m256i*)idx), 1));
+}
+inline v_uint8x32 v256_lut(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v256_lut((const schar *)tab, idx)); }
+inline v_uint8x32 v256_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v256_lut_pairs((const schar *)tab, idx)); }
+inline v_uint8x32 v256_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v256_lut_quads((const schar *)tab, idx)); }
+
+inline v_int16x16 v256_lut(const short* tab, const int* idx)
+{
+ return v_int16x16(_mm256_setr_epi16(tab[idx[0]], tab[idx[1]], tab[idx[ 2]], tab[idx[ 3]], tab[idx[ 4]], tab[idx[ 5]], tab[idx[ 6]], tab[idx[ 7]],
+ tab[idx[8]], tab[idx[9]], tab[idx[10]], tab[idx[11]], tab[idx[12]], tab[idx[13]], tab[idx[14]], tab[idx[15]]));
+}
+inline v_int16x16 v256_lut_pairs(const short* tab, const int* idx)
+{
+ return v_int16x16(_mm256_i32gather_epi32((const int*)tab, _mm256_loadu_si256((const __m256i*)idx), 2));
+}
+inline v_int16x16 v256_lut_quads(const short* tab, const int* idx)
+{
+#if defined(__GNUC__)
+ return v_int16x16(_mm256_i32gather_epi64((const long long int*)tab, _mm_loadu_si128((const __m128i*)idx), 2));//Looks like intrinsic has wrong definition
+#else
+ return v_int16x16(_mm256_i32gather_epi64((const int64*)tab, _mm_loadu_si128((const __m128i*)idx), 2));
+#endif
+}
+inline v_uint16x16 v256_lut(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v256_lut((const short *)tab, idx)); }
+inline v_uint16x16 v256_lut_pairs(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v256_lut_pairs((const short *)tab, idx)); }
+inline v_uint16x16 v256_lut_quads(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v256_lut_quads((const short *)tab, idx)); }
+
+inline v_int32x8 v256_lut(const int* tab, const int* idx)
+{
+ return v_int32x8(_mm256_i32gather_epi32(tab, _mm256_loadu_si256((const __m256i*)idx), 4));
+}
+inline v_int32x8 v256_lut_pairs(const int* tab, const int* idx)
+{
+#if defined(__GNUC__)
+ return v_int32x8(_mm256_i32gather_epi64((const long long int*)tab, _mm_loadu_si128((const __m128i*)idx), 4));
+#else
+ return v_int32x8(_mm256_i32gather_epi64((const int64*)tab, _mm_loadu_si128((const __m128i*)idx), 4));
+#endif
+}
+inline v_int32x8 v256_lut_quads(const int* tab, const int* idx)
+{
+ return v_int32x8(_mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((const __m128i*)(tab + idx[0]))), _mm_loadu_si128((const __m128i*)(tab + idx[1])), 0x1));
+}
+inline v_uint32x8 v256_lut(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v256_lut((const int *)tab, idx)); }
+inline v_uint32x8 v256_lut_pairs(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v256_lut_pairs((const int *)tab, idx)); }
+inline v_uint32x8 v256_lut_quads(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v256_lut_quads((const int *)tab, idx)); }
+
+inline v_int64x4 v256_lut(const int64* tab, const int* idx)
+{
+#if defined(__GNUC__)
+ return v_int64x4(_mm256_i32gather_epi64((const long long int*)tab, _mm_loadu_si128((const __m128i*)idx), 8));
+#else
+ return v_int64x4(_mm256_i32gather_epi64(tab, _mm_loadu_si128((const __m128i*)idx), 8));
+#endif
+}
+inline v_int64x4 v256_lut_pairs(const int64* tab, const int* idx)
+{
+ return v_int64x4(_mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((const __m128i*)(tab + idx[0]))), _mm_loadu_si128((const __m128i*)(tab + idx[1])), 0x1));
+}
+inline v_uint64x4 v256_lut(const uint64* tab, const int* idx) { return v_reinterpret_as_u64(v256_lut((const int64 *)tab, idx)); }
+inline v_uint64x4 v256_lut_pairs(const uint64* tab, const int* idx) { return v_reinterpret_as_u64(v256_lut_pairs((const int64 *)tab, idx)); }
+
+inline v_float32x8 v256_lut(const float* tab, const int* idx)
+{
+ return v_float32x8(_mm256_i32gather_ps(tab, _mm256_loadu_si256((const __m256i*)idx), 4));
+}
+inline v_float32x8 v256_lut_pairs(const float* tab, const int* idx) { return v_reinterpret_as_f32(v256_lut_pairs((const int *)tab, idx)); }
+inline v_float32x8 v256_lut_quads(const float* tab, const int* idx) { return v_reinterpret_as_f32(v256_lut_quads((const int *)tab, idx)); }
+
+inline v_float64x4 v256_lut(const double* tab, const int* idx)
+{
+ return v_float64x4(_mm256_i32gather_pd(tab, _mm_loadu_si128((const __m128i*)idx), 8));
+}
+inline v_float64x4 v256_lut_pairs(const double* tab, const int* idx) { return v_float64x4(_mm256_insertf128_pd(_mm256_castpd128_pd256(_mm_loadu_pd(tab + idx[0])), _mm_loadu_pd(tab + idx[1]), 0x1)); }
+
inline v_int32x8 v_lut(const int* tab, const v_int32x8& idxvec)
{
return v_int32x8(_mm256_i32gather_epi32(tab, idxvec.val, 4));
y = v_float64x4(_mm256_unpackhi_pd(xy02, xy13));
}
+inline v_int8x32 v_interleave_pairs(const v_int8x32& vec)
+{
+ return v_int8x32(_mm256_shuffle_epi8(vec.val, _mm256_set_epi64x(0x0f0d0e0c0b090a08, 0x0705060403010200, 0x0f0d0e0c0b090a08, 0x0705060403010200)));
+}
+inline v_uint8x32 v_interleave_pairs(const v_uint8x32& vec) { return v_reinterpret_as_u8(v_interleave_pairs(v_reinterpret_as_s8(vec))); }
+inline v_int8x32 v_interleave_quads(const v_int8x32& vec)
+{
+ return v_int8x32(_mm256_shuffle_epi8(vec.val, _mm256_set_epi64x(0x0f0b0e0a0d090c08, 0x0703060205010400, 0x0f0b0e0a0d090c08, 0x0703060205010400)));
+}
+inline v_uint8x32 v_interleave_quads(const v_uint8x32& vec) { return v_reinterpret_as_u8(v_interleave_quads(v_reinterpret_as_s8(vec))); }
+
+inline v_int16x16 v_interleave_pairs(const v_int16x16& vec)
+{
+ return v_int16x16(_mm256_shuffle_epi8(vec.val, _mm256_set_epi64x(0x0f0e0b0a0d0c0908, 0x0706030205040100, 0x0f0e0b0a0d0c0908, 0x0706030205040100)));
+}
+inline v_uint16x16 v_interleave_pairs(const v_uint16x16& vec) { return v_reinterpret_as_u16(v_interleave_pairs(v_reinterpret_as_s16(vec))); }
+inline v_int16x16 v_interleave_quads(const v_int16x16& vec)
+{
+ return v_int16x16(_mm256_shuffle_epi8(vec.val, _mm256_set_epi64x(0x0f0e07060d0c0504, 0x0b0a030209080100, 0x0f0e07060d0c0504, 0x0b0a030209080100)));
+}
+inline v_uint16x16 v_interleave_quads(const v_uint16x16& vec) { return v_reinterpret_as_u16(v_interleave_quads(v_reinterpret_as_s16(vec))); }
+
+inline v_int32x8 v_interleave_pairs(const v_int32x8& vec)
+{
+ return v_int32x8(_mm256_shuffle_epi32(vec.val, _MM_SHUFFLE(3, 1, 2, 0)));
+}
+inline v_uint32x8 v_interleave_pairs(const v_uint32x8& vec) { return v_reinterpret_as_u32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
+inline v_float32x8 v_interleave_pairs(const v_float32x8& vec) { return v_reinterpret_as_f32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
+
+inline v_int8x32 v_pack_triplets(const v_int8x32& vec)
+{
+ return v_int8x32(_mm256_permutevar8x32_epi32(_mm256_shuffle_epi8(vec.val, _mm256_broadcastsi128_si256(_mm_set_epi64x(0xffffff0f0e0d0c0a, 0x0908060504020100))),
+ _mm256_set_epi64x(0x0000000700000007, 0x0000000600000005, 0x0000000400000002, 0x0000000100000000)));
+}
+inline v_uint8x32 v_pack_triplets(const v_uint8x32& vec) { return v_reinterpret_as_u8(v_pack_triplets(v_reinterpret_as_s8(vec))); }
+
+inline v_int16x16 v_pack_triplets(const v_int16x16& vec)
+{
+ return v_int16x16(_mm256_permutevar8x32_epi32(_mm256_shuffle_epi8(vec.val, _mm256_broadcastsi128_si256(_mm_set_epi64x(0xffff0f0e0d0c0b0a, 0x0908050403020100))),
+ _mm256_set_epi64x(0x0000000700000007, 0x0000000600000005, 0x0000000400000002, 0x0000000100000000)));
+}
+inline v_uint16x16 v_pack_triplets(const v_uint16x16& vec) { return v_reinterpret_as_u16(v_pack_triplets(v_reinterpret_as_s16(vec))); }
+
+inline v_int32x8 v_pack_triplets(const v_int32x8& vec)
+{
+ return v_int32x8(_mm256_permutevar8x32_epi32(vec.val, _mm256_set_epi64x(0x0000000700000007, 0x0000000600000005, 0x0000000400000002, 0x0000000100000000)));
+}
+inline v_uint32x8 v_pack_triplets(const v_uint32x8& vec) { return v_reinterpret_as_u32(v_pack_triplets(v_reinterpret_as_s32(vec))); }
+inline v_float32x8 v_pack_triplets(const v_float32x8& vec)
+{
+ return v_float32x8(_mm256_permutevar8x32_ps(vec.val, _mm256_set_epi64x(0x0000000700000007, 0x0000000600000005, 0x0000000400000002, 0x0000000100000000)));
+}
+
////////// Matrix operations /////////
inline v_int32x8 v_dotprod(const v_int16x16& a, const v_int16x16& b)
b = v_uint64x4(b0);
}
-inline void v_load_deinterleave( const uchar* ptr, v_uint8x32& b, v_uint8x32& g, v_uint8x32& r )
+inline void v_load_deinterleave( const uchar* ptr, v_uint8x32& a, v_uint8x32& b, v_uint8x32& c )
{
__m256i bgr0 = _mm256_loadu_si256((const __m256i*)ptr);
__m256i bgr1 = _mm256_loadu_si256((const __m256i*)(ptr + 32));
g0 = _mm256_shuffle_epi8(g0, sh_g);
r0 = _mm256_shuffle_epi8(r0, sh_r);
- b = v_uint8x32(b0);
- g = v_uint8x32(g0);
- r = v_uint8x32(r0);
+ a = v_uint8x32(b0);
+ b = v_uint8x32(g0);
+ c = v_uint8x32(r0);
}
-inline void v_load_deinterleave( const ushort* ptr, v_uint16x16& b, v_uint16x16& g, v_uint16x16& r )
+inline void v_load_deinterleave( const ushort* ptr, v_uint16x16& a, v_uint16x16& b, v_uint16x16& c )
{
__m256i bgr0 = _mm256_loadu_si256((const __m256i*)ptr);
__m256i bgr1 = _mm256_loadu_si256((const __m256i*)(ptr + 16));
g0 = _mm256_shuffle_epi8(g0, sh_g);
r0 = _mm256_shuffle_epi8(r0, sh_r);
- b = v_uint16x16(b0);
- g = v_uint16x16(g0);
- r = v_uint16x16(r0);
+ a = v_uint16x16(b0);
+ b = v_uint16x16(g0);
+ c = v_uint16x16(r0);
}
-inline void v_load_deinterleave( const unsigned* ptr, v_uint32x8& b, v_uint32x8& g, v_uint32x8& r )
+inline void v_load_deinterleave( const unsigned* ptr, v_uint32x8& a, v_uint32x8& b, v_uint32x8& c )
{
__m256i bgr0 = _mm256_loadu_si256((const __m256i*)ptr);
__m256i bgr1 = _mm256_loadu_si256((const __m256i*)(ptr + 8));
g0 = _mm256_shuffle_epi32(g0, 0xb1);
r0 = _mm256_shuffle_epi32(r0, 0xc6);
- b = v_uint32x8(b0);
- g = v_uint32x8(g0);
- r = v_uint32x8(r0);
+ a = v_uint32x8(b0);
+ b = v_uint32x8(g0);
+ c = v_uint32x8(r0);
}
-inline void v_load_deinterleave( const uint64* ptr, v_uint64x4& b, v_uint64x4& g, v_uint64x4& r )
+inline void v_load_deinterleave( const uint64* ptr, v_uint64x4& a, v_uint64x4& b, v_uint64x4& c )
{
__m256i bgr0 = _mm256_loadu_si256((const __m256i*)ptr);
__m256i bgr1 = _mm256_loadu_si256((const __m256i*)(ptr + 4));
__m256i g0 = _mm256_alignr_epi8(s12, s01, 8);
__m256i r0 = _mm256_unpackhi_epi64(s20r, s12);
- b = v_uint64x4(b0);
- g = v_uint64x4(g0);
- r = v_uint64x4(r0);
+ a = v_uint64x4(b0);
+ b = v_uint64x4(g0);
+ c = v_uint64x4(r0);
}
-inline void v_load_deinterleave( const uchar* ptr, v_uint8x32& b, v_uint8x32& g, v_uint8x32& r, v_uint8x32& a )
+inline void v_load_deinterleave( const uchar* ptr, v_uint8x32& a, v_uint8x32& b, v_uint8x32& c, v_uint8x32& d )
{
__m256i bgr0 = _mm256_loadu_si256((const __m256i*)ptr);
__m256i bgr1 = _mm256_loadu_si256((const __m256i*)(ptr + 32));
__m256i r0 = _mm256_unpacklo_epi32(phl, phh);
__m256i a0 = _mm256_unpackhi_epi32(phl, phh);
- b = v_uint8x32(b0);
- g = v_uint8x32(g0);
- r = v_uint8x32(r0);
- a = v_uint8x32(a0);
+ a = v_uint8x32(b0);
+ b = v_uint8x32(g0);
+ c = v_uint8x32(r0);
+ d = v_uint8x32(a0);
}
-inline void v_load_deinterleave( const ushort* ptr, v_uint16x16& b, v_uint16x16& g, v_uint16x16& r, v_uint16x16& a )
+inline void v_load_deinterleave( const ushort* ptr, v_uint16x16& a, v_uint16x16& b, v_uint16x16& c, v_uint16x16& d )
{
__m256i bgr0 = _mm256_loadu_si256((const __m256i*)ptr);
__m256i bgr1 = _mm256_loadu_si256((const __m256i*)(ptr + 16));
__m256i r0 = _mm256_unpacklo_epi32(phl, phh);
__m256i a0 = _mm256_unpackhi_epi32(phl, phh);
- b = v_uint16x16(b0);
- g = v_uint16x16(g0);
- r = v_uint16x16(r0);
- a = v_uint16x16(a0);
+ a = v_uint16x16(b0);
+ b = v_uint16x16(g0);
+ c = v_uint16x16(r0);
+ d = v_uint16x16(a0);
}
-inline void v_load_deinterleave( const unsigned* ptr, v_uint32x8& b, v_uint32x8& g, v_uint32x8& r, v_uint32x8& a )
+inline void v_load_deinterleave( const unsigned* ptr, v_uint32x8& a, v_uint32x8& b, v_uint32x8& c, v_uint32x8& d )
{
__m256i p0 = _mm256_loadu_si256((const __m256i*)ptr);
__m256i p1 = _mm256_loadu_si256((const __m256i*)(ptr + 8));
__m256i r0 = _mm256_unpacklo_epi32(phl, phh);
__m256i a0 = _mm256_unpackhi_epi32(phl, phh);
- b = v_uint32x8(b0);
- g = v_uint32x8(g0);
- r = v_uint32x8(r0);
- a = v_uint32x8(a0);
+ a = v_uint32x8(b0);
+ b = v_uint32x8(g0);
+ c = v_uint32x8(r0);
+ d = v_uint32x8(a0);
}
-inline void v_load_deinterleave( const uint64* ptr, v_uint64x4& b, v_uint64x4& g, v_uint64x4& r, v_uint64x4& a )
+inline void v_load_deinterleave( const uint64* ptr, v_uint64x4& a, v_uint64x4& b, v_uint64x4& c, v_uint64x4& d )
{
__m256i bgra0 = _mm256_loadu_si256((const __m256i*)ptr);
__m256i bgra1 = _mm256_loadu_si256((const __m256i*)(ptr + 4));
__m256i r0 = _mm256_unpacklo_epi64(h02, h13);
__m256i a0 = _mm256_unpackhi_epi64(h02, h13);
- b = v_uint64x4(b0);
- g = v_uint64x4(g0);
- r = v_uint64x4(r0);
- a = v_uint64x4(a0);
+ a = v_uint64x4(b0);
+ b = v_uint64x4(g0);
+ c = v_uint64x4(r0);
+ d = v_uint64x4(a0);
}
///////////////////////////// store interleave /////////////////////////////////////
}
}
-inline void v_store_interleave( uchar* ptr, const v_uint8x32& b, const v_uint8x32& g, const v_uint8x32& r,
+inline void v_store_interleave( uchar* ptr, const v_uint8x32& a, const v_uint8x32& b, const v_uint8x32& c,
hal::StoreMode mode=hal::STORE_UNALIGNED )
{
const __m256i sh_b = _mm256_setr_epi8(
10, 5, 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15,
10, 5, 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15);
- __m256i b0 = _mm256_shuffle_epi8(b.val, sh_b);
- __m256i g0 = _mm256_shuffle_epi8(g.val, sh_g);
- __m256i r0 = _mm256_shuffle_epi8(r.val, sh_r);
+ __m256i b0 = _mm256_shuffle_epi8(a.val, sh_b);
+ __m256i g0 = _mm256_shuffle_epi8(b.val, sh_g);
+ __m256i r0 = _mm256_shuffle_epi8(c.val, sh_r);
const __m256i m0 = _mm256_setr_epi8(0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,
0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0);
}
}
-inline void v_store_interleave( ushort* ptr, const v_uint16x16& b, const v_uint16x16& g, const v_uint16x16& r,
+inline void v_store_interleave( ushort* ptr, const v_uint16x16& a, const v_uint16x16& b, const v_uint16x16& c,
hal::StoreMode mode=hal::STORE_UNALIGNED )
{
const __m256i sh_b = _mm256_setr_epi8(
4, 5, 10, 11, 0, 1, 6, 7, 12, 13, 2, 3, 8, 9, 14, 15,
4, 5, 10, 11, 0, 1, 6, 7, 12, 13, 2, 3, 8, 9, 14, 15);
- __m256i b0 = _mm256_shuffle_epi8(b.val, sh_b);
- __m256i g0 = _mm256_shuffle_epi8(g.val, sh_g);
- __m256i r0 = _mm256_shuffle_epi8(r.val, sh_r);
+ __m256i b0 = _mm256_shuffle_epi8(a.val, sh_b);
+ __m256i g0 = _mm256_shuffle_epi8(b.val, sh_g);
+ __m256i r0 = _mm256_shuffle_epi8(c.val, sh_r);
const __m256i m0 = _mm256_setr_epi8(0, 0, -1, -1, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, -1, -1,
0, 0, 0, 0, -1, -1, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0);
}
}
-inline void v_store_interleave( unsigned* ptr, const v_uint32x8& b, const v_uint32x8& g, const v_uint32x8& r,
+inline void v_store_interleave( unsigned* ptr, const v_uint32x8& a, const v_uint32x8& b, const v_uint32x8& c,
hal::StoreMode mode=hal::STORE_UNALIGNED )
{
- __m256i b0 = _mm256_shuffle_epi32(b.val, 0x6c);
- __m256i g0 = _mm256_shuffle_epi32(g.val, 0xb1);
- __m256i r0 = _mm256_shuffle_epi32(r.val, 0xc6);
+ __m256i b0 = _mm256_shuffle_epi32(a.val, 0x6c);
+ __m256i g0 = _mm256_shuffle_epi32(b.val, 0xb1);
+ __m256i r0 = _mm256_shuffle_epi32(c.val, 0xc6);
__m256i p0 = _mm256_blend_epi32(_mm256_blend_epi32(b0, g0, 0x92), r0, 0x24);
__m256i p1 = _mm256_blend_epi32(_mm256_blend_epi32(g0, r0, 0x92), b0, 0x24);
}
}
-inline void v_store_interleave( uint64* ptr, const v_uint64x4& b, const v_uint64x4& g, const v_uint64x4& r,
+inline void v_store_interleave( uint64* ptr, const v_uint64x4& a, const v_uint64x4& b, const v_uint64x4& c,
hal::StoreMode mode=hal::STORE_UNALIGNED )
{
- __m256i s01 = _mm256_unpacklo_epi64(b.val, g.val);
- __m256i s12 = _mm256_unpackhi_epi64(g.val, r.val);
- __m256i s20 = _mm256_blend_epi32(r.val, b.val, 0xcc);
+ __m256i s01 = _mm256_unpacklo_epi64(a.val, b.val);
+ __m256i s12 = _mm256_unpackhi_epi64(b.val, c.val);
+ __m256i s20 = _mm256_blend_epi32(c.val, a.val, 0xcc);
__m256i bgr0 = _mm256_permute2x128_si256(s01, s20, 0 + 2*16);
__m256i bgr1 = _mm256_blend_epi32(s01, s12, 0x0f);
}
}
-inline void v_store_interleave( uchar* ptr, const v_uint8x32& b, const v_uint8x32& g,
- const v_uint8x32& r, const v_uint8x32& a,
+inline void v_store_interleave( uchar* ptr, const v_uint8x32& a, const v_uint8x32& b,
+ const v_uint8x32& c, const v_uint8x32& d,
hal::StoreMode mode=hal::STORE_UNALIGNED )
{
- __m256i bg0 = _mm256_unpacklo_epi8(b.val, g.val);
- __m256i bg1 = _mm256_unpackhi_epi8(b.val, g.val);
- __m256i ra0 = _mm256_unpacklo_epi8(r.val, a.val);
- __m256i ra1 = _mm256_unpackhi_epi8(r.val, a.val);
+ __m256i bg0 = _mm256_unpacklo_epi8(a.val, b.val);
+ __m256i bg1 = _mm256_unpackhi_epi8(a.val, b.val);
+ __m256i ra0 = _mm256_unpacklo_epi8(c.val, d.val);
+ __m256i ra1 = _mm256_unpackhi_epi8(c.val, d.val);
__m256i bgra0_ = _mm256_unpacklo_epi16(bg0, ra0);
__m256i bgra1_ = _mm256_unpackhi_epi16(bg0, ra0);
}
}
-inline void v_store_interleave( ushort* ptr, const v_uint16x16& b, const v_uint16x16& g,
- const v_uint16x16& r, const v_uint16x16& a,
+inline void v_store_interleave( ushort* ptr, const v_uint16x16& a, const v_uint16x16& b,
+ const v_uint16x16& c, const v_uint16x16& d,
hal::StoreMode mode=hal::STORE_UNALIGNED )
{
- __m256i bg0 = _mm256_unpacklo_epi16(b.val, g.val);
- __m256i bg1 = _mm256_unpackhi_epi16(b.val, g.val);
- __m256i ra0 = _mm256_unpacklo_epi16(r.val, a.val);
- __m256i ra1 = _mm256_unpackhi_epi16(r.val, a.val);
+ __m256i bg0 = _mm256_unpacklo_epi16(a.val, b.val);
+ __m256i bg1 = _mm256_unpackhi_epi16(a.val, b.val);
+ __m256i ra0 = _mm256_unpacklo_epi16(c.val, d.val);
+ __m256i ra1 = _mm256_unpackhi_epi16(c.val, d.val);
__m256i bgra0_ = _mm256_unpacklo_epi32(bg0, ra0);
__m256i bgra1_ = _mm256_unpackhi_epi32(bg0, ra0);
}
}
-inline void v_store_interleave( unsigned* ptr, const v_uint32x8& b, const v_uint32x8& g,
- const v_uint32x8& r, const v_uint32x8& a,
+inline void v_store_interleave( unsigned* ptr, const v_uint32x8& a, const v_uint32x8& b,
+ const v_uint32x8& c, const v_uint32x8& d,
hal::StoreMode mode=hal::STORE_UNALIGNED )
{
- __m256i bg0 = _mm256_unpacklo_epi32(b.val, g.val);
- __m256i bg1 = _mm256_unpackhi_epi32(b.val, g.val);
- __m256i ra0 = _mm256_unpacklo_epi32(r.val, a.val);
- __m256i ra1 = _mm256_unpackhi_epi32(r.val, a.val);
+ __m256i bg0 = _mm256_unpacklo_epi32(a.val, b.val);
+ __m256i bg1 = _mm256_unpackhi_epi32(a.val, b.val);
+ __m256i ra0 = _mm256_unpacklo_epi32(c.val, d.val);
+ __m256i ra1 = _mm256_unpackhi_epi32(c.val, d.val);
__m256i bgra0_ = _mm256_unpacklo_epi64(bg0, ra0);
__m256i bgra1_ = _mm256_unpackhi_epi64(bg0, ra0);
}
}
-inline void v_store_interleave( uint64* ptr, const v_uint64x4& b, const v_uint64x4& g,
- const v_uint64x4& r, const v_uint64x4& a,
+inline void v_store_interleave( uint64* ptr, const v_uint64x4& a, const v_uint64x4& b,
+ const v_uint64x4& c, const v_uint64x4& d,
hal::StoreMode mode=hal::STORE_UNALIGNED )
{
- __m256i bg0 = _mm256_unpacklo_epi64(b.val, g.val);
- __m256i bg1 = _mm256_unpackhi_epi64(b.val, g.val);
- __m256i ra0 = _mm256_unpacklo_epi64(r.val, a.val);
- __m256i ra1 = _mm256_unpackhi_epi64(r.val, a.val);
+ __m256i bg0 = _mm256_unpacklo_epi64(a.val, b.val);
+ __m256i bg1 = _mm256_unpackhi_epi64(a.val, b.val);
+ __m256i ra0 = _mm256_unpacklo_epi64(c.val, d.val);
+ __m256i ra1 = _mm256_unpackhi_epi64(c.val, d.val);
__m256i bgra0 = _mm256_permute2x128_si256(bg0, ra0, 0 + 2*16);
__m256i bgra1 = _mm256_permute2x128_si256(bg1, ra1, 0 + 2*16);
return c;
}
+template<typename _Tp> inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_lut(const _Tp* tab, const int* idx)
+{
+ v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c;
+ for (int i = 0; i < V_TypeTraits<_Tp>::nlanes128; i++)
+ c.s[i] = tab[idx[i]];
+ return c;
+}
+template<typename _Tp> inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_lut_pairs(const _Tp* tab, const int* idx)
+{
+ v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c;
+ for (int i = 0; i < V_TypeTraits<_Tp>::nlanes128; i++)
+ c.s[i] = tab[idx[i / 2] + i % 2];
+ return c;
+}
+template<typename _Tp> inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_lut_quads(const _Tp* tab, const int* idx)
+{
+ v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c;
+ for (int i = 0; i < V_TypeTraits<_Tp>::nlanes128; i++)
+ c.s[i] = tab[idx[i / 4] + i % 4];
+ return c;
+}
+
template<int n> inline v_reg<int, n> v_lut(const int* tab, const v_reg<int, n>& idx)
{
v_reg<int, n> c;
return c;
}
+template<int n> inline v_reg<unsigned, n> v_lut(const unsigned* tab, const v_reg<int, n>& idx)
+{
+ v_reg<int, n> c;
+ for (int i = 0; i < n; i++)
+ c.s[i] = tab[idx.s[i]];
+ return c;
+}
+
template<int n> inline v_reg<float, n> v_lut(const float* tab, const v_reg<int, n>& idx)
{
v_reg<float, n> c;
}
}
+template<typename _Tp, int n> inline v_reg<_Tp, n> v_interleave_pairs(const v_reg<_Tp, n>& vec)
+{
+ v_reg<float, n> c;
+ for (int i = 0; i < n/4; i++)
+ {
+ c.s[4*i ] = vec.s[4*i ];
+ c.s[4*i+1] = vec.s[4*i+2];
+ c.s[4*i+2] = vec.s[4*i+1];
+ c.s[4*i+3] = vec.s[4*i+3];
+ }
+ return c;
+}
+
+template<typename _Tp, int n> inline v_reg<_Tp, n> v_interleave_quads(const v_reg<_Tp, n>& vec)
+{
+ v_reg<float, n> c;
+ for (int i = 0; i < n/8; i++)
+ {
+ c.s[8*i ] = vec.s[8*i ];
+ c.s[8*i+1] = vec.s[8*i+4];
+ c.s[8*i+2] = vec.s[8*i+1];
+ c.s[8*i+3] = vec.s[8*i+5];
+ c.s[8*i+4] = vec.s[8*i+2];
+ c.s[8*i+5] = vec.s[8*i+6];
+ c.s[8*i+6] = vec.s[8*i+3];
+ c.s[8*i+7] = vec.s[8*i+7];
+ }
+ return c;
+}
+
+template<typename _Tp, int n> inline v_reg<_Tp, n> v_pack_triplets(const v_reg<_Tp, n>& vec)
+{
+ v_reg<float, n> c;
+ for (int i = 0; i < n/4; i++)
+ {
+ c.s[3*i ] = vec.s[4*i ];
+ c.s[3*i+1] = vec.s[4*i+1];
+ c.s[3*i+2] = vec.s[4*i+2];
+ }
+ return c;
+}
+
/** @brief Transpose 4x4 matrix
Scheme:
inline v_uint32x4 v_load_expand_q(const uchar* ptr)
{
- uint8x8_t v0 = vcreate_u8(*(unsigned*)ptr);
+ typedef unsigned int CV_DECL_ALIGNED(1) unaligned_uint;
+ uint8x8_t v0 = vcreate_u8(*(unaligned_uint*)ptr);
uint16x4_t v1 = vget_low_u16(vmovl_u8(v0));
return v_uint32x4(vmovl_u16(v1));
}
inline v_int32x4 v_load_expand_q(const schar* ptr)
{
- int8x8_t v0 = vcreate_s8(*(unsigned*)ptr);
+ typedef unsigned int CV_DECL_ALIGNED(1) unaligned_uint;
+ int8x8_t v0 = vcreate_s8(*(unaligned_uint*)ptr);
int16x4_t v1 = vget_low_s16(vmovl_s8(v0));
return v_int32x4(vmovl_s16(v1));
}
////////////// Lookup table access ////////////////////
+inline v_int8x16 v_lut(const schar* tab, const int* idx)
+{
+ schar CV_DECL_ALIGNED(32) elems[16] =
+ {
+ tab[idx[ 0]],
+ tab[idx[ 1]],
+ tab[idx[ 2]],
+ tab[idx[ 3]],
+ tab[idx[ 4]],
+ tab[idx[ 5]],
+ tab[idx[ 6]],
+ tab[idx[ 7]],
+ tab[idx[ 8]],
+ tab[idx[ 9]],
+ tab[idx[10]],
+ tab[idx[11]],
+ tab[idx[12]],
+ tab[idx[13]],
+ tab[idx[14]],
+ tab[idx[15]]
+ };
+ return v_int8x16(vld1q_s8(elems));
+}
+inline v_int8x16 v_lut_pairs(const schar* tab, const int* idx)
+{
+ schar CV_DECL_ALIGNED(32) elems[16] =
+ {
+ tab[idx[0]],
+ tab[idx[0] + 1],
+ tab[idx[1]],
+ tab[idx[1] + 1],
+ tab[idx[2]],
+ tab[idx[2] + 1],
+ tab[idx[3]],
+ tab[idx[3] + 1],
+ tab[idx[4]],
+ tab[idx[4] + 1],
+ tab[idx[5]],
+ tab[idx[5] + 1],
+ tab[idx[6]],
+ tab[idx[6] + 1],
+ tab[idx[7]],
+ tab[idx[7] + 1]
+ };
+ return v_int8x16(vld1q_s8(elems));
+}
+inline v_int8x16 v_lut_quads(const schar* tab, const int* idx)
+{
+ schar CV_DECL_ALIGNED(32) elems[16] =
+ {
+ tab[idx[0]],
+ tab[idx[0] + 1],
+ tab[idx[0] + 2],
+ tab[idx[0] + 3],
+ tab[idx[1]],
+ tab[idx[1] + 1],
+ tab[idx[1] + 2],
+ tab[idx[1] + 3],
+ tab[idx[2]],
+ tab[idx[2] + 1],
+ tab[idx[2] + 2],
+ tab[idx[2] + 3],
+ tab[idx[3]],
+ tab[idx[3] + 1],
+ tab[idx[3] + 2],
+ tab[idx[3] + 3]
+ };
+ return v_int8x16(vld1q_s8(elems));
+}
+inline v_uint8x16 v_lut(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut((schar*)tab, idx)); }
+inline v_uint8x16 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((schar*)tab, idx)); }
+inline v_uint8x16 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((schar*)tab, idx)); }
+
+inline v_int16x8 v_lut(const short* tab, const int* idx)
+{
+ short CV_DECL_ALIGNED(32) elems[8] =
+ {
+ tab[idx[0]],
+ tab[idx[1]],
+ tab[idx[2]],
+ tab[idx[3]],
+ tab[idx[4]],
+ tab[idx[5]],
+ tab[idx[6]],
+ tab[idx[7]]
+ };
+ return v_int16x8(vld1q_s16(elems));
+}
+inline v_int16x8 v_lut_pairs(const short* tab, const int* idx)
+{
+ short CV_DECL_ALIGNED(32) elems[8] =
+ {
+ tab[idx[0]],
+ tab[idx[0] + 1],
+ tab[idx[1]],
+ tab[idx[1] + 1],
+ tab[idx[2]],
+ tab[idx[2] + 1],
+ tab[idx[3]],
+ tab[idx[3] + 1]
+ };
+ return v_int16x8(vld1q_s16(elems));
+}
+inline v_int16x8 v_lut_quads(const short* tab, const int* idx)
+{
+ return v_int16x8(vcombine_s16(vld1_s16(tab + idx[0]), vld1_s16(tab + idx[1])));
+}
+inline v_uint16x8 v_lut(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut((short*)tab, idx)); }
+inline v_uint16x8 v_lut_pairs(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut_pairs((short*)tab, idx)); }
+inline v_uint16x8 v_lut_quads(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut_quads((short*)tab, idx)); }
+
+inline v_int32x4 v_lut(const int* tab, const int* idx)
+{
+ int CV_DECL_ALIGNED(32) elems[4] =
+ {
+ tab[idx[0]],
+ tab[idx[1]],
+ tab[idx[2]],
+ tab[idx[3]]
+ };
+ return v_int32x4(vld1q_s32(elems));
+}
+inline v_int32x4 v_lut_pairs(const int* tab, const int* idx)
+{
+ return v_int32x4(vcombine_s32(vld1_s32(tab + idx[0]), vld1_s32(tab + idx[1])));
+}
+inline v_int32x4 v_lut_quads(const int* tab, const int* idx)
+{
+ return v_int32x4(vld1q_s32(tab + idx[0]));
+}
+inline v_uint32x4 v_lut(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut((int*)tab, idx)); }
+inline v_uint32x4 v_lut_pairs(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut_pairs((int*)tab, idx)); }
+inline v_uint32x4 v_lut_quads(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut_quads((int*)tab, idx)); }
+
+inline v_int64x2 v_lut(const int64_t* tab, const int* idx)
+{
+ return v_int64x2(vcombine_s64(vcreate_s64(tab[idx[0]]), vcreate_s64(tab[idx[1]])));
+}
+inline v_int64x2 v_lut_pairs(const int64_t* tab, const int* idx)
+{
+ return v_int64x2(vld1q_s64(tab + idx[0]));
+}
+inline v_uint64x2 v_lut(const uint64_t* tab, const int* idx) { return v_reinterpret_as_u64(v_lut((const int64_t *)tab, idx)); }
+inline v_uint64x2 v_lut_pairs(const uint64_t* tab, const int* idx) { return v_reinterpret_as_u64(v_lut_pairs((const int64_t *)tab, idx)); }
+
+inline v_float32x4 v_lut(const float* tab, const int* idx)
+{
+ float CV_DECL_ALIGNED(32) elems[4] =
+ {
+ tab[idx[0]],
+ tab[idx[1]],
+ tab[idx[2]],
+ tab[idx[3]]
+ };
+ return v_float32x4(vld1q_f32(elems));
+}
+inline v_float32x4 v_lut_pairs(const float* tab, const int* idx)
+{
+ uint64 CV_DECL_ALIGNED(32) elems[2] =
+ {
+ *(uint64*)(tab + idx[0]),
+ *(uint64*)(tab + idx[1])
+ };
+ return v_float32x4(vreinterpretq_f32_u64(vld1q_u64(elems)));
+}
+inline v_float32x4 v_lut_quads(const float* tab, const int* idx)
+{
+ return v_float32x4(vld1q_f32(tab + idx[0]));
+}
+
inline v_int32x4 v_lut(const int* tab, const v_int32x4& idxvec)
{
int CV_DECL_ALIGNED(32) elems[4] =
return v_int32x4(vld1q_s32(elems));
}
+inline v_uint32x4 v_lut(const unsigned* tab, const v_int32x4& idxvec)
+{
+ unsigned CV_DECL_ALIGNED(32) elems[4] =
+ {
+ tab[vgetq_lane_s32(idxvec.val, 0)],
+ tab[vgetq_lane_s32(idxvec.val, 1)],
+ tab[vgetq_lane_s32(idxvec.val, 2)],
+ tab[vgetq_lane_s32(idxvec.val, 3)]
+ };
+ return v_uint32x4(vld1q_u32(elems));
+}
+
inline v_float32x4 v_lut(const float* tab, const v_int32x4& idxvec)
{
float CV_DECL_ALIGNED(32) elems[4] =
y = v_float32x4(tab[idx[0]+1], tab[idx[1]+1], tab[idx[2]+1], tab[idx[3]+1]);
}
+inline v_int8x16 v_interleave_pairs(const v_int8x16& vec)
+{
+ return v_int8x16(vcombine_s8(vtbl1_s8(vget_low_s8(vec.val), vcreate_s8(0x0705060403010200)), vtbl1_s8(vget_high_s8(vec.val), vcreate_s8(0x0705060403010200))));
+}
+inline v_uint8x16 v_interleave_pairs(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_interleave_pairs(v_reinterpret_as_s8(vec))); }
+inline v_int8x16 v_interleave_quads(const v_int8x16& vec)
+{
+ return v_int8x16(vcombine_s8(vtbl1_s8(vget_low_s8(vec.val), vcreate_s8(0x0703060205010400)), vtbl1_s8(vget_high_s8(vec.val), vcreate_s8(0x0703060205010400))));
+}
+inline v_uint8x16 v_interleave_quads(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_interleave_quads(v_reinterpret_as_s8(vec))); }
+
+inline v_int16x8 v_interleave_pairs(const v_int16x8& vec)
+{
+ return v_int16x8(vreinterpretq_s16_s8(vcombine_s8(vtbl1_s8(vget_low_s8(vreinterpretq_s8_s16(vec.val)), vcreate_s8(0x0706030205040100)), vtbl1_s8(vget_high_s8(vreinterpretq_s8_s16(vec.val)), vcreate_s8(0x0706030205040100)))));
+}
+inline v_uint16x8 v_interleave_pairs(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_interleave_pairs(v_reinterpret_as_s16(vec))); }
+inline v_int16x8 v_interleave_quads(const v_int16x8& vec)
+{
+ int16x4x2_t res = vzip_s16(vget_low_s16(vec.val), vget_high_s16(vec.val));
+ return v_int16x8(vcombine_s16(res.val[0], res.val[1]));
+}
+inline v_uint16x8 v_interleave_quads(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_interleave_quads(v_reinterpret_as_s16(vec))); }
+
+inline v_int32x4 v_interleave_pairs(const v_int32x4& vec)
+{
+ int32x2x2_t res = vzip_s32(vget_low_s32(vec.val), vget_high_s32(vec.val));
+ return v_int32x4(vcombine_s32(res.val[0], res.val[1]));
+}
+inline v_uint32x4 v_interleave_pairs(const v_uint32x4& vec) { return v_reinterpret_as_u32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
+inline v_float32x4 v_interleave_pairs(const v_float32x4& vec) { return v_reinterpret_as_f32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
+
+inline v_int8x16 v_pack_triplets(const v_int8x16& vec)
+{
+ return v_int8x16(vextq_s8(vcombine_s8(vtbl1_s8(vget_low_s8(vec.val), vcreate_s8(0x0605040201000000)), vtbl1_s8(vget_high_s8(vec.val), vcreate_s8(0x0807060504020100))), vdupq_n_s8(0), 2));
+}
+inline v_uint8x16 v_pack_triplets(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_pack_triplets(v_reinterpret_as_s8(vec))); }
+
+inline v_int16x8 v_pack_triplets(const v_int16x8& vec)
+{
+ return v_int16x8(vreinterpretq_s16_s8(vextq_s8(vcombine_s8(vtbl1_s8(vget_low_s8(vreinterpretq_s8_s16(vec.val)), vcreate_s8(0x0504030201000000)), vget_high_s8(vreinterpretq_s8_s16(vec.val))), vdupq_n_s8(0), 2)));
+}
+inline v_uint16x8 v_pack_triplets(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_pack_triplets(v_reinterpret_as_s16(vec))); }
+
+inline v_int32x4 v_pack_triplets(const v_int32x4& vec) { return vec; }
+inline v_uint32x4 v_pack_triplets(const v_uint32x4& vec) { return vec; }
+inline v_float32x4 v_pack_triplets(const v_float32x4& vec) { return vec; }
+
#if CV_SIMD128_64F
+inline v_float64x2 v_lut(const double* tab, const int* idx)
+{
+ double CV_DECL_ALIGNED(32) elems[2] =
+ {
+ tab[idx[0]],
+ tab[idx[1]]
+ };
+ return v_float64x2(vld1q_f64(elems));
+}
+
+inline v_float64x2 v_lut_pairs(const double* tab, const int* idx)
+{
+ return v_float64x2(vld1q_f64(tab + idx[0]));
+}
+
inline v_float64x2 v_lut(const double* tab, const v_int32x4& idxvec)
{
double CV_DECL_ALIGNED(32) elems[2] =
////////////// Lookup table access ////////////////////
+inline v_int8x16 v_lut(const schar* tab, const int* idx)
+{
+#if defined(_MSC_VER)
+ return v_int8x16(_mm_setr_epi8(tab[idx[0]], tab[idx[1]], tab[idx[ 2]], tab[idx[ 3]], tab[idx[ 4]], tab[idx[ 5]], tab[idx[ 6]], tab[idx[ 7]],
+ tab[idx[8]], tab[idx[9]], tab[idx[10]], tab[idx[11]], tab[idx[12]], tab[idx[13]], tab[idx[14]], tab[idx[15]]));
+#else
+ return v_int8x16(_mm_setr_epi64(
+ _mm_setr_pi8(tab[idx[0]], tab[idx[1]], tab[idx[ 2]], tab[idx[ 3]], tab[idx[ 4]], tab[idx[ 5]], tab[idx[ 6]], tab[idx[ 7]]),
+ _mm_setr_pi8(tab[idx[8]], tab[idx[9]], tab[idx[10]], tab[idx[11]], tab[idx[12]], tab[idx[13]], tab[idx[14]], tab[idx[15]])
+ ));
+#endif
+}
+inline v_int8x16 v_lut_pairs(const schar* tab, const int* idx)
+{
+#if defined(_MSC_VER)
+ return v_int8x16(_mm_setr_epi16(*(const short*)(tab + idx[0]), *(const short*)(tab + idx[1]), *(const short*)(tab + idx[2]), *(const short*)(tab + idx[3]),
+ *(const short*)(tab + idx[4]), *(const short*)(tab + idx[5]), *(const short*)(tab + idx[6]), *(const short*)(tab + idx[7])));
+#else
+ return v_int8x16(_mm_setr_epi64(
+ _mm_setr_pi16(*(const short*)(tab + idx[0]), *(const short*)(tab + idx[1]), *(const short*)(tab + idx[2]), *(const short*)(tab + idx[3])),
+ _mm_setr_pi16(*(const short*)(tab + idx[4]), *(const short*)(tab + idx[5]), *(const short*)(tab + idx[6]), *(const short*)(tab + idx[7]))
+ ));
+#endif
+}
+inline v_int8x16 v_lut_quads(const schar* tab, const int* idx)
+{
+#if defined(_MSC_VER)
+ return v_int8x16(_mm_setr_epi32(*(const int*)(tab + idx[0]), *(const int*)(tab + idx[1]),
+ *(const int*)(tab + idx[2]), *(const int*)(tab + idx[3])));
+#else
+ return v_int8x16(_mm_setr_epi64(
+ _mm_setr_pi32(*(const int*)(tab + idx[0]), *(const int*)(tab + idx[1])),
+ _mm_setr_pi32(*(const int*)(tab + idx[2]), *(const int*)(tab + idx[3]))
+ ));
+#endif
+}
+inline v_uint8x16 v_lut(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut((const schar *)tab, idx)); }
+inline v_uint8x16 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((const schar *)tab, idx)); }
+inline v_uint8x16 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((const schar *)tab, idx)); }
+
+inline v_int16x8 v_lut(const short* tab, const int* idx)
+{
+#if defined(_MSC_VER)
+ return v_int16x8(_mm_setr_epi16(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]],
+ tab[idx[4]], tab[idx[5]], tab[idx[6]], tab[idx[7]]));
+#else
+ return v_int16x8(_mm_setr_epi64(
+ _mm_setr_pi16(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]),
+ _mm_setr_pi16(tab[idx[4]], tab[idx[5]], tab[idx[6]], tab[idx[7]])
+ ));
+#endif
+}
+inline v_int16x8 v_lut_pairs(const short* tab, const int* idx)
+{
+#if defined(_MSC_VER)
+ return v_int16x8(_mm_setr_epi32(*(const int*)(tab + idx[0]), *(const int*)(tab + idx[1]),
+ *(const int*)(tab + idx[2]), *(const int*)(tab + idx[3])));
+#else
+ return v_int16x8(_mm_setr_epi64(
+ _mm_setr_pi32(*(const int*)(tab + idx[0]), *(const int*)(tab + idx[1])),
+ _mm_setr_pi32(*(const int*)(tab + idx[2]), *(const int*)(tab + idx[3]))
+ ));
+#endif
+}
+inline v_int16x8 v_lut_quads(const short* tab, const int* idx)
+{
+ return v_int16x8(_mm_set_epi64x(*(const int64_t*)(tab + idx[1]), *(const int64_t*)(tab + idx[0])));
+}
+inline v_uint16x8 v_lut(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut((const short *)tab, idx)); }
+inline v_uint16x8 v_lut_pairs(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut_pairs((const short *)tab, idx)); }
+inline v_uint16x8 v_lut_quads(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut_quads((const short *)tab, idx)); }
+
+inline v_int32x4 v_lut(const int* tab, const int* idx)
+{
+#if defined(_MSC_VER)
+ return v_int32x4(_mm_setr_epi32(tab[idx[0]], tab[idx[1]],
+ tab[idx[2]], tab[idx[3]]));
+#else
+ return v_int32x4(_mm_setr_epi64(
+ _mm_setr_pi32(tab[idx[0]], tab[idx[1]]),
+ _mm_setr_pi32(tab[idx[2]], tab[idx[3]])
+ ));
+#endif
+}
+inline v_int32x4 v_lut_pairs(const int* tab, const int* idx)
+{
+ return v_int32x4(_mm_set_epi64x(*(const int64_t*)(tab + idx[1]), *(const int64_t*)(tab + idx[0])));
+}
+inline v_int32x4 v_lut_quads(const int* tab, const int* idx)
+{
+ return v_int32x4(_mm_loadu_si128((const __m128i*)(tab + idx[0])));
+}
+inline v_uint32x4 v_lut(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut((const int *)tab, idx)); }
+inline v_uint32x4 v_lut_pairs(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut_pairs((const int *)tab, idx)); }
+inline v_uint32x4 v_lut_quads(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut_quads((const int *)tab, idx)); }
+
+inline v_int64x2 v_lut(const int64_t* tab, const int* idx)
+{
+ return v_int64x2(_mm_set_epi64x(tab[idx[1]], tab[idx[0]]));
+}
+inline v_int64x2 v_lut_pairs(const int64_t* tab, const int* idx)
+{
+ return v_int64x2(_mm_loadu_si128((const __m128i*)(tab + idx[0])));
+}
+inline v_uint64x2 v_lut(const uint64_t* tab, const int* idx) { return v_reinterpret_as_u64(v_lut((const int64_t *)tab, idx)); }
+inline v_uint64x2 v_lut_pairs(const uint64_t* tab, const int* idx) { return v_reinterpret_as_u64(v_lut_pairs((const int64_t *)tab, idx)); }
+
+inline v_float32x4 v_lut(const float* tab, const int* idx)
+{
+ return v_float32x4(_mm_setr_ps(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]));
+}
+inline v_float32x4 v_lut_pairs(const float* tab, const int* idx) { return v_reinterpret_as_f32(v_lut_pairs((const int *)tab, idx)); }
+inline v_float32x4 v_lut_quads(const float* tab, const int* idx) { return v_reinterpret_as_f32(v_lut_quads((const int *)tab, idx)); }
+
+inline v_float64x2 v_lut(const double* tab, const int* idx)
+{
+ return v_float64x2(_mm_setr_pd(tab[idx[0]], tab[idx[1]]));
+}
+inline v_float64x2 v_lut_pairs(const double* tab, const int* idx) { return v_float64x2(_mm_castsi128_pd(_mm_loadu_si128((const __m128i*)(tab + idx[0])))); }
+
inline v_int32x4 v_lut(const int* tab, const v_int32x4& idxvec)
{
int CV_DECL_ALIGNED(32) idx[4];
return v_int32x4(_mm_setr_epi32(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]));
}
+inline v_uint32x4 v_lut(const unsigned* tab, const v_int32x4& idxvec)
+{
+ return v_reinterpret_as_u32(v_lut((const int *)tab, idxvec));
+}
+
inline v_float32x4 v_lut(const float* tab, const v_int32x4& idxvec)
{
int CV_DECL_ALIGNED(32) idx[4];
y = v_float64x2(_mm_unpackhi_pd(xy0, xy1));
}
+inline v_int8x16 v_interleave_pairs(const v_int8x16& vec)
+{
+#if CV_SSSE3
+ return v_int8x16(_mm_shuffle_epi8(vec.val, _mm_set_epi64x(0x0f0d0e0c0b090a08, 0x0705060403010200)));
+#else
+ __m128i a = _mm_shufflelo_epi16(vec.val, _MM_SHUFFLE(3, 1, 2, 0));
+ a = _mm_shufflehi_epi16(a, _MM_SHUFFLE(3, 1, 2, 0));
+ a = _mm_shuffle_epi32(a, _MM_SHUFFLE(3, 1, 2, 0));
+ return v_int8x16(_mm_unpacklo_epi8(a, _mm_unpackhi_epi64(a, a)));
+#endif
+}
+inline v_uint8x16 v_interleave_pairs(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_interleave_pairs(v_reinterpret_as_s8(vec))); }
+inline v_int8x16 v_interleave_quads(const v_int8x16& vec)
+{
+#if CV_SSSE3
+ return v_int8x16(_mm_shuffle_epi8(vec.val, _mm_set_epi64x(0x0f0b0e0a0d090c08, 0x0703060205010400)));
+#else
+ __m128i a = _mm_shuffle_epi32(vec.val, _MM_SHUFFLE(3, 1, 2, 0));
+ return v_int8x16(_mm_unpacklo_epi8(a, _mm_unpackhi_epi64(a, a)));
+#endif
+}
+inline v_uint8x16 v_interleave_quads(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_interleave_quads(v_reinterpret_as_s8(vec))); }
+
+inline v_int16x8 v_interleave_pairs(const v_int16x8& vec)
+{
+#if CV_SSSE3
+ return v_int16x8(_mm_shuffle_epi8(vec.val, _mm_set_epi64x(0x0f0e0b0a0d0c0908, 0x0706030205040100)));
+#else
+ __m128i a = _mm_shufflelo_epi16(vec.val, _MM_SHUFFLE(3, 1, 2, 0));
+ return v_int16x8(_mm_shufflehi_epi16(a, _MM_SHUFFLE(3, 1, 2, 0)));
+#endif
+}
+inline v_uint16x8 v_interleave_pairs(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_interleave_pairs(v_reinterpret_as_s16(vec))); }
+inline v_int16x8 v_interleave_quads(const v_int16x8& vec)
+{
+#if CV_SSSE3
+ return v_int16x8(_mm_shuffle_epi8(vec.val, _mm_set_epi64x(0x0f0e07060d0c0504, 0x0b0a030209080100)));
+#else
+ return v_int16x8(_mm_unpacklo_epi16(vec.val, _mm_unpackhi_epi64(vec.val, vec.val)));
+#endif
+}
+inline v_uint16x8 v_interleave_quads(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_interleave_quads(v_reinterpret_as_s16(vec))); }
+
+inline v_int32x4 v_interleave_pairs(const v_int32x4& vec)
+{
+ return v_int32x4(_mm_shuffle_epi32(vec.val, _MM_SHUFFLE(3, 1, 2, 0)));
+}
+inline v_uint32x4 v_interleave_pairs(const v_uint32x4& vec) { return v_reinterpret_as_u32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
+inline v_float32x4 v_interleave_pairs(const v_float32x4& vec) { return v_reinterpret_as_f32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
+
+inline v_int8x16 v_pack_triplets(const v_int8x16& vec)
+{
+#if CV_SSSE3
+ return v_int8x16(_mm_shuffle_epi8(vec.val, _mm_set_epi64x(0xffffff0f0e0d0c0a, 0x0908060504020100)));
+#else
+ __m128i mask = _mm_set1_epi64x(0x00000000FFFFFFFF);
+ __m128i a = _mm_srli_si128(_mm_or_si128(_mm_andnot_si128(mask, vec.val), _mm_and_si128(mask, _mm_sll_epi32(vec.val, _mm_set_epi64x(0, 8)))), 1);
+ return v_int8x16(_mm_srli_si128(_mm_shufflelo_epi16(a, _MM_SHUFFLE(2, 1, 0, 3)), 2));
+#endif
+}
+inline v_uint8x16 v_pack_triplets(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_pack_triplets(v_reinterpret_as_s8(vec))); }
+
+inline v_int16x8 v_pack_triplets(const v_int16x8& vec)
+{
+#if CV_SSSE3
+ return v_int16x8(_mm_shuffle_epi8(vec.val, _mm_set_epi64x(0xffff0f0e0d0c0b0a, 0x0908050403020100)));
+#else
+ return v_int16x8(_mm_srli_si128(_mm_shufflelo_epi16(vec.val, _MM_SHUFFLE(2, 1, 0, 3)), 2));
+#endif
+}
+inline v_uint16x8 v_pack_triplets(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_pack_triplets(v_reinterpret_as_s16(vec))); }
+
+inline v_int32x4 v_pack_triplets(const v_int32x4& vec) { return vec; }
+inline v_uint32x4 v_pack_triplets(const v_uint32x4& vec) { return vec; }
+inline v_float32x4 v_pack_triplets(const v_float32x4& vec) { return vec; }
////////////// FP16 support ///////////////////////////
#define CV_SIMD128 1
#define CV_SIMD128_64F 1
-/**
- * todo: supporting half precision for power9
- * convert instractions xvcvhpsp, xvcvsphp
-**/
-
namespace cv
{
inline void v_store_high(_Tp* ptr, const _Tpvec& a) \
{ vec_st_h8(a.val, ptr); }
-#define OPENCV_HAL_IMPL_VSX_LOADSTORE(_Tpvec, _Tp) \
-OPENCV_HAL_IMPL_VSX_LOADSTORE_C(_Tpvec, _Tp, vsx_ld, vec_ld, vsx_st, vec_st)
+// working around gcc bug for aligned ld/st
+// if runtime check for vec_ld/st fail we failback to unaligned ld/st
+// https://github.com/opencv/opencv/issues/13211
+#ifdef CV_COMPILER_VSX_BROKEN_ALIGNED
+ #define OPENCV_HAL_IMPL_VSX_LOADSTORE(_Tpvec, _Tp) \
+ OPENCV_HAL_IMPL_VSX_LOADSTORE_C(_Tpvec, _Tp, vsx_ld, vsx_ld, vsx_st, vsx_st)
+#else
+ #define OPENCV_HAL_IMPL_VSX_LOADSTORE(_Tpvec, _Tp) \
+ OPENCV_HAL_IMPL_VSX_LOADSTORE_C(_Tpvec, _Tp, vsx_ld, vec_ld, vsx_st, vec_st)
+#endif
OPENCV_HAL_IMPL_VSX_LOADSTORE(v_uint8x16, uchar)
OPENCV_HAL_IMPL_VSX_LOADSTORE(v_int8x16, schar)
////////////// Lookup table access ////////////////////
+inline v_int8x16 v_lut(const schar* tab, const int* idx)
+{
+ return v_int8x16(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]], tab[idx[4]], tab[idx[5]], tab[idx[6]], tab[idx[7]],
+ tab[idx[8]], tab[idx[9]], tab[idx[10]], tab[idx[11]], tab[idx[12]], tab[idx[13]], tab[idx[14]], tab[idx[15]]);
+}
+inline v_int8x16 v_lut_pairs(const schar* tab, const int* idx)
+{
+ return v_reinterpret_as_s8(v_int16x8(*(const short*)(tab+idx[0]), *(const short*)(tab+idx[1]), *(const short*)(tab+idx[2]), *(const short*)(tab+idx[3]),
+ *(const short*)(tab+idx[4]), *(const short*)(tab+idx[5]), *(const short*)(tab+idx[6]), *(const short*)(tab+idx[7])));
+}
+inline v_int8x16 v_lut_quads(const schar* tab, const int* idx)
+{
+ return v_reinterpret_as_s8(v_int32x4(*(const int*)(tab+idx[0]), *(const int*)(tab+idx[1]), *(const int*)(tab+idx[2]), *(const int*)(tab+idx[3])));
+}
+inline v_uint8x16 v_lut(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut((const schar*)tab, idx)); }
+inline v_uint8x16 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((const schar*)tab, idx)); }
+inline v_uint8x16 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((const schar*)tab, idx)); }
+
+inline v_int16x8 v_lut(const short* tab, const int* idx)
+{
+ return v_int16x8(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]], tab[idx[4]], tab[idx[5]], tab[idx[6]], tab[idx[7]]);
+}
+inline v_int16x8 v_lut_pairs(const short* tab, const int* idx)
+{
+ return v_reinterpret_as_s16(v_int32x4(*(const int*)(tab + idx[0]), *(const int*)(tab + idx[1]), *(const int*)(tab + idx[2]), *(const int*)(tab + idx[3])));
+}
+inline v_int16x8 v_lut_quads(const short* tab, const int* idx)
+{
+ return v_reinterpret_as_s16(v_int64x2(*(const int64*)(tab + idx[0]), *(const int64*)(tab + idx[1])));
+}
+inline v_uint16x8 v_lut(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut((const short*)tab, idx)); }
+inline v_uint16x8 v_lut_pairs(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut_pairs((const short*)tab, idx)); }
+inline v_uint16x8 v_lut_quads(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut_quads((const short*)tab, idx)); }
+
+inline v_int32x4 v_lut(const int* tab, const int* idx)
+{
+ return v_int32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
+}
+inline v_int32x4 v_lut_pairs(const int* tab, const int* idx)
+{
+ return v_reinterpret_as_s32(v_int64x2(*(const int64*)(tab + idx[0]), *(const int64*)(tab + idx[1])));
+}
+inline v_int32x4 v_lut_quads(const int* tab, const int* idx)
+{
+ return v_int32x4(vsx_ld(0, tab + idx[0]));
+}
+inline v_uint32x4 v_lut(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut((const int*)tab, idx)); }
+inline v_uint32x4 v_lut_pairs(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut_pairs((const int*)tab, idx)); }
+inline v_uint32x4 v_lut_quads(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut_quads((const int*)tab, idx)); }
+
+inline v_int64x2 v_lut(const int64_t* tab, const int* idx)
+{
+ return v_int64x2(tab[idx[0]], tab[idx[1]]);
+}
+inline v_int64x2 v_lut_pairs(const int64_t* tab, const int* idx)
+{
+ return v_int64x2(vsx_ld2(0, tab + idx[0]));
+}
+inline v_uint64x2 v_lut(const uint64_t* tab, const int* idx) { return v_reinterpret_as_u64(v_lut((const int64_t *)tab, idx)); }
+inline v_uint64x2 v_lut_pairs(const uint64_t* tab, const int* idx) { return v_reinterpret_as_u64(v_lut_pairs((const int64_t *)tab, idx)); }
+
+inline v_float32x4 v_lut(const float* tab, const int* idx)
+{
+ return v_float32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
+}
+inline v_float32x4 v_lut_pairs(const float* tab, const int* idx) { return v_reinterpret_as_f32(v_lut_pairs((const int*)tab, idx)); }
+inline v_float32x4 v_lut_quads(const float* tab, const int* idx) { return v_load(tab + *idx); }
+
+inline v_float64x2 v_lut(const double* tab, const int* idx)
+{
+ return v_float64x2(tab[idx[0]], tab[idx[1]]);
+}
+inline v_float64x2 v_lut_pairs(const double* tab, const int* idx) { return v_load(tab + *idx); }
+
inline v_int32x4 v_lut(const int* tab, const v_int32x4& idxvec)
{
- int CV_DECL_ALIGNED(32) idx[4];
- v_store_aligned(idx, idxvec);
+ const int idx[4] = {
+ vec_extract(idxvec.val, 0),
+ vec_extract(idxvec.val, 1),
+ vec_extract(idxvec.val, 2),
+ vec_extract(idxvec.val, 3)
+ };
return v_int32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
}
+inline v_uint32x4 v_lut(const unsigned* tab, const v_int32x4& idxvec)
+{
+ const int idx[4] = {
+ vec_extract(idxvec.val, 0),
+ vec_extract(idxvec.val, 1),
+ vec_extract(idxvec.val, 2),
+ vec_extract(idxvec.val, 3)
+ };
+ return v_uint32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
+}
+
inline v_float32x4 v_lut(const float* tab, const v_int32x4& idxvec)
{
- int CV_DECL_ALIGNED(32) idx[4];
- v_store_aligned(idx, idxvec);
+ const int idx[4] = {
+ vec_extract(idxvec.val, 0),
+ vec_extract(idxvec.val, 1),
+ vec_extract(idxvec.val, 2),
+ vec_extract(idxvec.val, 3)
+ };
return v_float32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
}
inline v_float64x2 v_lut(const double* tab, const v_int32x4& idxvec)
{
- int CV_DECL_ALIGNED(32) idx[4];
- v_store_aligned(idx, idxvec);
+ const int idx[2] = {
+ vec_extract(idxvec.val, 0),
+ vec_extract(idxvec.val, 1)
+ };
return v_float64x2(tab[idx[0]], tab[idx[1]]);
}
inline void v_lut_deinterleave(const float* tab, const v_int32x4& idxvec, v_float32x4& x, v_float32x4& y)
{
- int CV_DECL_ALIGNED(32) idx[4];
- v_store_aligned(idx, idxvec);
- x = v_float32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
- y = v_float32x4(tab[idx[0]+1], tab[idx[1]+1], tab[idx[2]+1], tab[idx[3]+1]);
+ vec_float4 xy0 = vec_ld_l8(tab + vec_extract(idxvec.val, 0));
+ vec_float4 xy1 = vec_ld_l8(tab + vec_extract(idxvec.val, 1));
+ vec_float4 xy2 = vec_ld_l8(tab + vec_extract(idxvec.val, 2));
+ vec_float4 xy3 = vec_ld_l8(tab + vec_extract(idxvec.val, 3));
+ vec_float4 xy02 = vec_mergeh(xy0, xy2); // x0, x2, y0, y2
+ vec_float4 xy13 = vec_mergeh(xy1, xy3); // x1, x3, y1, y3
+ x.val = vec_mergeh(xy02, xy13);
+ y.val = vec_mergel(xy02, xy13);
}
-
inline void v_lut_deinterleave(const double* tab, const v_int32x4& idxvec, v_float64x2& x, v_float64x2& y)
{
- int CV_DECL_ALIGNED(32) idx[4];
- v_store_aligned(idx, idxvec);
- x = v_float64x2(tab[idx[0]], tab[idx[1]]);
- y = v_float64x2(tab[idx[0]+1], tab[idx[1]+1]);
+ vec_double2 xy0 = vsx_ld(vec_extract(idxvec.val, 0), tab);
+ vec_double2 xy1 = vsx_ld(vec_extract(idxvec.val, 1), tab);
+ x.val = vec_mergeh(xy0, xy1);
+ y.val = vec_mergel(xy0, xy1);
+}
+
+inline v_int8x16 v_interleave_pairs(const v_int8x16& vec)
+{
+ static const vec_uchar16 perm = {0, 2, 1, 3, 4, 6, 5, 7, 8, 10, 9, 11, 12, 14, 13, 15};
+ return v_int8x16(vec_perm(vec.val, vec.val, perm));
+}
+inline v_uint8x16 v_interleave_pairs(const v_uint8x16& vec)
+{ return v_reinterpret_as_u8(v_interleave_pairs(v_reinterpret_as_s8(vec))); }
+
+inline v_int8x16 v_interleave_quads(const v_int8x16& vec)
+{
+ static const vec_uchar16 perm = {0, 4, 1, 5, 2, 6, 3, 7, 8, 12, 9, 13, 10, 14, 11, 15};
+ return v_int8x16(vec_perm(vec.val, vec.val, perm));
+}
+inline v_uint8x16 v_interleave_quads(const v_uint8x16& vec)
+{ return v_reinterpret_as_u8(v_interleave_quads(v_reinterpret_as_s8(vec))); }
+
+inline v_int16x8 v_interleave_pairs(const v_int16x8& vec)
+{
+ static const vec_uchar16 perm = {0,1, 4,5, 2,3, 6,7, 8,9, 12,13, 10,11, 14,15};
+ return v_int16x8(vec_perm(vec.val, vec.val, perm));
}
+inline v_uint16x8 v_interleave_pairs(const v_uint16x8& vec)
+{ return v_reinterpret_as_u16(v_interleave_pairs(v_reinterpret_as_s16(vec))); }
+
+inline v_int16x8 v_interleave_quads(const v_int16x8& vec)
+{
+ static const vec_uchar16 perm = {0,1, 8,9, 2,3, 10,11, 4,5, 12,13, 6,7, 14,15};
+ return v_int16x8(vec_perm(vec.val, vec.val, perm));
+}
+inline v_uint16x8 v_interleave_quads(const v_uint16x8& vec)
+{ return v_reinterpret_as_u16(v_interleave_quads(v_reinterpret_as_s16(vec))); }
+
+inline v_int32x4 v_interleave_pairs(const v_int32x4& vec)
+{
+ static const vec_uchar16 perm = {0,1,2,3, 8,9,10,11, 4,5,6,7, 12,13,14,15};
+ return v_int32x4(vec_perm(vec.val, vec.val, perm));
+}
+inline v_uint32x4 v_interleave_pairs(const v_uint32x4& vec)
+{ return v_reinterpret_as_u32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
+inline v_float32x4 v_interleave_pairs(const v_float32x4& vec)
+{ return v_reinterpret_as_f32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
+
+inline v_int8x16 v_pack_triplets(const v_int8x16& vec)
+{
+ static const vec_uchar16 perm = {0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 15, 15, 15, 15};
+ return v_int8x16(vec_perm(vec.val, vec.val, perm));
+}
+inline v_uint8x16 v_pack_triplets(const v_uint8x16& vec)
+{ return v_reinterpret_as_u8(v_pack_triplets(v_reinterpret_as_s8(vec))); }
+
+inline v_int16x8 v_pack_triplets(const v_int16x8& vec)
+{
+ static const vec_uchar16 perm = {0,1, 2,3, 4,5, 8,9, 10,11, 12,13, 14,15, 14,15};
+ return v_int16x8(vec_perm(vec.val, vec.val, perm));
+}
+inline v_uint16x8 v_pack_triplets(const v_uint16x8& vec)
+{ return v_reinterpret_as_u16(v_pack_triplets(v_reinterpret_as_s16(vec))); }
+
+inline v_int32x4 v_pack_triplets(const v_int32x4& vec)
+{ return vec; }
+inline v_uint32x4 v_pack_triplets(const v_uint32x4& vec)
+{ return vec; }
+inline v_float32x4 v_pack_triplets(const v_float32x4& vec)
+{ return vec; }
/////// FP16 support ////////
-// [TODO] implement these 2 using VSX or universal intrinsics (copy from intrin_sse.cpp and adopt)
inline v_float32x4 v_load_expand(const float16_t* ptr)
{
- return v_float32x4((float)ptr[0], (float)ptr[1], (float)ptr[2], (float)ptr[3]);
+ vec_ushort8 vf16 = vec_ld_l8((const ushort*)ptr);
+#if CV_VSX3 && defined(vec_extract_fp_from_shorth)
+ return v_float32x4(vec_extract_fp_from_shorth(vf16));
+#elif CV_VSX3 && !defined(CV_COMPILER_VSX_BROKEN_ASM)
+ vec_float4 vf32;
+ __asm__ __volatile__ ("xvcvhpsp %x0,%x1" : "=wf" (vf32) : "wa" (vec_mergeh(vf16, vf16)));
+ return v_float32x4(vf32);
+#else
+ const vec_int4 z = vec_int4_z, delta = vec_int4_sp(0x38000000);
+ const vec_int4 signmask = vec_int4_sp(0x80000000);
+ const vec_int4 maxexp = vec_int4_sp(0x7c000000);
+ const vec_float4 deltaf = vec_float4_c(vec_int4_sp(0x38800000));
+
+ vec_int4 bits = vec_int4_c(vec_mergeh(vec_short8_c(z), vec_short8_c(vf16)));
+ vec_int4 e = vec_and(bits, maxexp), sign = vec_and(bits, signmask);
+ vec_int4 t = vec_add(vec_sr(vec_xor(bits, sign), vec_uint4_sp(3)), delta); // ((h & 0x7fff) << 13) + delta
+ vec_int4 zt = vec_int4_c(vec_sub(vec_float4_c(vec_add(t, vec_int4_sp(1 << 23))), deltaf));
+
+ t = vec_add(t, vec_and(delta, vec_cmpeq(maxexp, e)));
+ vec_bint4 zmask = vec_cmpeq(e, z);
+ vec_int4 ft = vec_sel(t, zt, zmask);
+ return v_float32x4(vec_float4_c(vec_or(ft, sign)));
+#endif
}
inline void v_pack_store(float16_t* ptr, const v_float32x4& v)
{
- float CV_DECL_ALIGNED(32) f[4];
- v_store_aligned(f, v);
- ptr[0] = float16_t(f[0]);
- ptr[1] = float16_t(f[1]);
- ptr[2] = float16_t(f[2]);
- ptr[3] = float16_t(f[3]);
+// fixme: Is there any buitin op or intrinsic that cover "xvcvsphp"?
+#if CV_VSX3 && !defined(CV_COMPILER_VSX_BROKEN_ASM)
+ vec_ushort8 vf16;
+ __asm__ __volatile__ ("xvcvsphp %x0,%x1" : "=wa" (vf16) : "wf" (v.val));
+ vec_st_l8(vec_mergesqe(vf16, vf16), ptr);
+#else
+ const vec_int4 signmask = vec_int4_sp(0x80000000);
+ const vec_int4 rval = vec_int4_sp(0x3f000000);
+
+ vec_int4 t = vec_int4_c(v.val);
+ vec_int4 sign = vec_sra(vec_and(t, signmask), vec_uint4_sp(16));
+ t = vec_and(vec_nor(signmask, signmask), t);
+
+ vec_bint4 finitemask = vec_cmpgt(vec_int4_sp(0x47800000), t);
+ vec_bint4 isnan = vec_cmpgt(t, vec_int4_sp(0x7f800000));
+ vec_int4 naninf = vec_sel(vec_int4_sp(0x7c00), vec_int4_sp(0x7e00), isnan);
+ vec_bint4 tinymask = vec_cmpgt(vec_int4_sp(0x38800000), t);
+ vec_int4 tt = vec_int4_c(vec_add(vec_float4_c(t), vec_float4_c(rval)));
+ tt = vec_sub(tt, rval);
+ vec_int4 odd = vec_and(vec_sr(t, vec_uint4_sp(13)), vec_int4_sp(1));
+ vec_int4 nt = vec_add(t, vec_int4_sp(0xc8000fff));
+ nt = vec_sr(vec_add(nt, odd), vec_uint4_sp(13));
+ t = vec_sel(nt, tt, tinymask);
+ t = vec_sel(naninf, t, finitemask);
+ t = vec_or(t, sign);
+ vec_st_l8(vec_packs(t, t), ptr);
+#endif
}
inline void v_cleanup() {}
--- /dev/null
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+
+
+#ifndef OPENCV_CORE_LLAPI_LLAPI_H
+#define OPENCV_CORE_LLAPI_LLAPI_H
+/**
+@addtogroup core_lowlevel_api
+
+API for OpenCV external plugins:
+- HAL accelerators
+- VideoIO camera backends / decoders / encoders
+- Imgcodecs encoders / decoders
+
+Plugins are usually built separately or before OpenCV (OpenCV can depend on them - like HAL libraries).
+
+Using this approach OpenCV provides some basic low level functionality for external plugins.
+
+@note Preview only (no backward compatibility)
+
+@{
+*/
+
+#ifndef CV_API_CALL
+//! calling convention (including callbacks)
+#define CV_API_CALL
+#endif
+
+typedef enum cvResult
+{
+ CV_ERROR_FAIL = -1, //!< Some error occured (TODO Require to fill exception information)
+ CV_ERROR_OK = 0 //!< No error
+} CvResult;
+
+typedef struct OpenCV_API_Header_t
+{
+ /** @brief valid size of this structure
+ @details `assert(api.header.valid_size >= sizeof(OpenCV_<Name>_API_v<N>));`
+ */
+ size_t valid_size;
+ unsigned min_api_version; //!< backward compatible API version
+ unsigned api_version; //!< provided API version (features)
+ unsigned opencv_version_major; //!< compiled OpenCV version
+ unsigned opencv_version_minor; //!< compiled OpenCV version
+ unsigned opencv_version_patch; //!< compiled OpenCV version
+ const char* opencv_version_status; //!< compiled OpenCV version
+ const char* api_description; //!< API description (debug purposes only)
+} OpenCV_API_Header;
+
+
+
+#if 0
+
+typedef int (CV_API_CALL *cv_example_callback1_cb_t)(unsigned const char* cb_result, void* cb_context);
+
+struct OpenCV_Example_API_v1
+{
+ OpenCV_API_Header header;
+
+ /** @brief Some API call
+
+ @param param1 description1
+ @param param2 description2
+
+ @note API-CALL 1, API-Version >=1
+ */
+ CvResult (CV_API_CALL *Request1)(int param1, const char* param2);
+
+ /** @brief Register callback
+
+ @param callback function to handle callback
+ @param cb_context context data passed to callback function
+ @param[out] cb_handle callback id (used to unregister callback)
+
+ @note API-CALL 2, API-Version >=1
+ */
+ CvResult (CV_API_CALL *RegisterCallback)(cv_example_callback1_cb_t callback, void* cb_context, CV_OUT unsigned* cb_handle);
+
+ /** @brief Unregister callback
+
+ @param cb_handle callback handle
+
+ @note API-CALL 3, API-Version >=1
+ */
+ CvResult (CV_API_CALL *UnegisterCallback)(unsigned cb_handle);
+
+ ...
+};
+#endif // 0
+
+//! @}
+
+#endif // OPENCV_CORE_LLAPI_LLAPI_H
CV_EXPORTS MatExpr operator * (double s, const MatExpr& e);
CV_EXPORTS MatExpr operator * (const MatExpr& e1, const MatExpr& e2);
template<typename _Tp, int m, int n> static inline
-MatExpr operator * (const Mat& a, const Matx<_Tp, m, n>& b) { return a + Mat(b); }
+MatExpr operator * (const Mat& a, const Matx<_Tp, m, n>& b) { return a * Mat(b); }
template<typename _Tp, int m, int n> static inline
-MatExpr operator * (const Matx<_Tp, m, n>& a, const Mat& b) { return Mat(a) + b; }
+MatExpr operator * (const Matx<_Tp, m, n>& a, const Mat& b) { return Mat(a) * b; }
CV_EXPORTS MatExpr operator / (const Mat& a, const Mat& b);
CV_EXPORTS MatExpr operator / (const Mat& a, double s);
template<int m1, int n1> Matx<_Tp, m1, n1> reshape() const;
//! extract part of the matrix
- template<int m1, int n1> Matx<_Tp, m1, n1> get_minor(int i, int j) const;
+ template<int m1, int n1> Matx<_Tp, m1, n1> get_minor(int base_row, int base_col) const;
//! extract the matrix row
Matx<_Tp, 1, n> row(int i) const;
Matx<_Tp, m, n> div(const Matx<_Tp, m, n>& a) const;
//! element access
- const _Tp& operator ()(int i, int j) const;
- _Tp& operator ()(int i, int j);
+ const _Tp& operator ()(int row, int col) const;
+ _Tp& operator ()(int row, int col);
//! 1D element access
const _Tp& operator ()(int i) const;
template<typename _Tp, int m, int n>
template<int m1, int n1> inline
-Matx<_Tp, m1, n1> Matx<_Tp, m, n>::get_minor(int i, int j) const
+Matx<_Tp, m1, n1> Matx<_Tp, m, n>::get_minor(int base_row, int base_col) const
{
- CV_DbgAssert(0 <= i && i+m1 <= m && 0 <= j && j+n1 <= n);
+ CV_DbgAssert(0 <= base_row && base_row+m1 <= m && 0 <= base_col && base_col+n1 <= n);
Matx<_Tp, m1, n1> s;
for( int di = 0; di < m1; di++ )
for( int dj = 0; dj < n1; dj++ )
- s(di, dj) = (*this)(i+di, j+dj);
+ s(di, dj) = (*this)(base_row+di, base_col+dj);
return s;
}
}
template<typename _Tp, int m, int n> inline
-const _Tp& Matx<_Tp, m, n>::operator()(int i, int j) const
+const _Tp& Matx<_Tp, m, n>::operator()(int row_idx, int col_idx) const
{
- CV_DbgAssert( (unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n );
- return this->val[i*n + j];
+ CV_DbgAssert( (unsigned)row_idx < (unsigned)m && (unsigned)col_idx < (unsigned)n );
+ return this->val[row_idx*n + col_idx];
}
template<typename _Tp, int m, int n> inline
-_Tp& Matx<_Tp, m, n>::operator ()(int i, int j)
+_Tp& Matx<_Tp, m, n>::operator ()(int row_idx, int col_idx)
{
- CV_DbgAssert( (unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n );
- return val[i*n + j];
+ CV_DbgAssert( (unsigned)row_idx < (unsigned)m && (unsigned)col_idx < (unsigned)n );
+ return val[row_idx*n + col_idx];
}
template<typename _Tp, int m, int n> inline
#define clWaitForEvents clWaitForEvents_
#if defined __APPLE__
+#define CL_SILENCE_DEPRECATION
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif
#ifdef __CV_AVX_GUARD
-#define CV_INSTRUMENT_REGION(); __CV_AVX_GUARD CV_INSTRUMENT_REGION_();
+#define CV_INSTRUMENT_REGION() __CV_AVX_GUARD CV_INSTRUMENT_REGION_();
#else
-#define CV_INSTRUMENT_REGION(); CV_INSTRUMENT_REGION_();
+#define CV_INSTRUMENT_REGION() CV_INSTRUMENT_REGION_();
#endif
namespace cv {
*/
CV_EXPORTS void addDataSearchSubDirectory(const cv::String& subdir);
+/** @brief Return location of OpenCV libraries or current executable
+ */
+CV_EXPORTS std::string getBinLocation();
+
//! @}
} // namespace utils
/** Join path components */
CV_EXPORTS cv::String join(const cv::String& base, const cv::String& path);
+/** Get parent directory */
+CV_EXPORTS cv::String getParent(const cv::String &path);
+
/**
* Generate a list of all files that match the globbing pattern.
*
#define OPENCV_VERSION_HPP
#define CV_VERSION_MAJOR 4
-#define CV_VERSION_MINOR 0
-#define CV_VERSION_REVISION 1
-#define CV_VERSION_STATUS "-dev"
+#define CV_VERSION_MINOR 1
+#define CV_VERSION_REVISION 0
+#define CV_VERSION_STATUS "-pre"
#define CVAUX_STR_EXP(__A) #__A
#define CVAUX_STR(__A) CVAUX_STR_EXP(__A)
typedef __vector unsigned char vec_uchar16;
#define vec_uchar16_set(...) (vec_uchar16){__VA_ARGS__}
-#define vec_uchar16_sp(c) (__VSX_S16__(vec_uchar16, c))
+#define vec_uchar16_sp(c) (__VSX_S16__(vec_uchar16, (unsigned char)c))
#define vec_uchar16_c(v) ((vec_uchar16)(v))
#define vec_uchar16_z vec_uchar16_sp(0)
typedef __vector signed char vec_char16;
#define vec_char16_set(...) (vec_char16){__VA_ARGS__}
-#define vec_char16_sp(c) (__VSX_S16__(vec_char16, c))
+#define vec_char16_sp(c) (__VSX_S16__(vec_char16, (signed char)c))
#define vec_char16_c(v) ((vec_char16)(v))
#define vec_char16_z vec_char16_sp(0)
typedef __vector unsigned short vec_ushort8;
#define vec_ushort8_set(...) (vec_ushort8){__VA_ARGS__}
-#define vec_ushort8_sp(c) (__VSX_S8__(vec_ushort8, c))
+#define vec_ushort8_sp(c) (__VSX_S8__(vec_ushort8, (unsigned short)c))
#define vec_ushort8_c(v) ((vec_ushort8)(v))
#define vec_ushort8_z vec_ushort8_sp(0)
typedef __vector signed short vec_short8;
#define vec_short8_set(...) (vec_short8){__VA_ARGS__}
-#define vec_short8_sp(c) (__VSX_S8__(vec_short8, c))
+#define vec_short8_sp(c) (__VSX_S8__(vec_short8, (signed short)c))
#define vec_short8_c(v) ((vec_short8)(v))
#define vec_short8_z vec_short8_sp(0)
typedef __vector unsigned int vec_uint4;
#define vec_uint4_set(...) (vec_uint4){__VA_ARGS__}
-#define vec_uint4_sp(c) (__VSX_S4__(vec_uint4, c))
+#define vec_uint4_sp(c) (__VSX_S4__(vec_uint4, (unsigned int)c))
#define vec_uint4_c(v) ((vec_uint4)(v))
#define vec_uint4_z vec_uint4_sp(0)
typedef __vector signed int vec_int4;
#define vec_int4_set(...) (vec_int4){__VA_ARGS__}
-#define vec_int4_sp(c) (__VSX_S4__(vec_int4, c))
+#define vec_int4_sp(c) (__VSX_S4__(vec_int4, (signed int)c))
#define vec_int4_c(v) ((vec_int4)(v))
#define vec_int4_z vec_int4_sp(0)
typedef __vector unsigned long long vec_udword2;
#define vec_udword2_set(...) (vec_udword2){__VA_ARGS__}
-#define vec_udword2_sp(c) (__VSX_S2__(vec_udword2, c))
+#define vec_udword2_sp(c) (__VSX_S2__(vec_udword2, (unsigned long long)c))
#define vec_udword2_c(v) ((vec_udword2)(v))
#define vec_udword2_z vec_udword2_sp(0)
typedef __vector signed long long vec_dword2;
#define vec_dword2_set(...) (vec_dword2){__VA_ARGS__}
-#define vec_dword2_sp(c) (__VSX_S2__(vec_dword2, c))
+#define vec_dword2_sp(c) (__VSX_S2__(vec_dword2, (signed long long)c))
#define vec_dword2_c(v) ((vec_dword2)(v))
#define vec_dword2_z vec_dword2_sp(0)
*
* So we're not able to use inline asm and only use built-in functions that CLANG supports
* and use __builtin_convertvector if clang missng any of vector conversions built-in functions
+ *
+ * todo: clang asm template bug is fixed, need to reconsider the current workarounds.
*/
// convert vector helper
}
//
+ // C++: Mat::Mat(int ndims, const int* sizes, int type)
+ //
+
+ // javadoc: Mat::Mat(sizes, type)
+ public Mat(int[] sizes, int type)
+ {
+
+ nativeObj = n_Mat(sizes.length, sizes, type);
+
+ return;
+ }
+
+ //
// C++: Mat::Mat(int rows, int cols, int type, Scalar s)
//
}
//
+ // C++: Mat::Mat(int ndims, const int* sizes, int type, Scalar s)
+ //
+
+ // javadoc: Mat::Mat(sizes, type, s)
+ public Mat(int[] sizes, int type, Scalar s)
+ {
+
+ nativeObj = n_Mat(sizes.length, sizes, type, s.val[0], s.val[1], s.val[2], s.val[3]);
+
+ return;
+ }
+
+ //
// C++: Mat::Mat(Mat m, Range rowRange, Range colRange = Range::all())
//
}
//
+ // C++: Mat::Mat(const Mat& m, const std::vector<Range>& ranges)
+ //
+
+ // javadoc: Mat::Mat(m, ranges)
+ public Mat(Mat m, Range[] ranges)
+ {
+
+ nativeObj = n_Mat(m.nativeObj, ranges);
+
+ return;
+ }
+
+ //
// C++: Mat::Mat(Mat m, Rect roi)
//
}
//
+ // C++: void Mat::create(int ndims, const int* sizes, int type)
+ //
+
+ // javadoc: Mat::create(sizes, type)
+ public void create(int[] sizes, int type)
+ {
+
+ n_create(nativeObj, sizes.length, sizes, type);
+
+ return;
+ }
+
+ //
+ // C++: void Mat::copySize(const Mat& m);
+ //
+
+ // javadoc: Mat::copySize(m)
+ public void copySize(Mat m)
+ {
+ n_copySize(nativeObj, m.nativeObj);
+
+ return;
+ }
+
+ //
// C++: Mat Mat::cross(Mat m)
//
}
//
+ // C++: static Mat Mat::ones(int ndims, const int* sizes, int type)
+ //
+
+ // javadoc: Mat::ones(sizes, type)
+ public static Mat ones(int[] sizes, int type)
+ {
+
+ Mat retVal = new Mat(n_ones(sizes.length, sizes, type));
+
+ return retVal;
+ }
+
+ //
// C++: void Mat::push_back(Mat m)
//
}
//
+ // C++: Mat Mat::operator()(const std::vector<Range>& ranges)
+ //
+
+ // javadoc: Mat::operator()(ranges[])
+ public Mat submat(Range[] ranges)
+ {
+
+ Mat retVal = new Mat(n_submat_ranges(nativeObj, ranges));
+
+ return retVal;
+ }
+
+ //
// C++: Mat Mat::operator()(Rect roi)
//
return retVal;
}
+ //
+ // C++: static Mat Mat::zeros(int ndims, const int* sizes, int type)
+ //
+
+ // javadoc: Mat::zeros(sizes, type)
+ public static Mat zeros(int[] sizes, int type)
+ {
+
+ Mat retVal = new Mat(n_zeros(sizes.length, sizes, type));
+
+ return retVal;
+ }
+
@Override
protected void finalize() throws Throwable {
n_delete(nativeObj);
return nPutD(nativeObj, row, col, data.length, data);
}
+ // javadoc:Mat::put(idx,data)
+ public int put(int[] idx, double... data) {
+ int t = type();
+ if (data == null || data.length % CvType.channels(t) != 0)
+ throw new java.lang.UnsupportedOperationException(
+ "Provided data element number (" +
+ (data == null ? 0 : data.length) +
+ ") should be multiple of the Mat channels count (" +
+ CvType.channels(t) + ")");
+ if (idx.length != dims())
+ throw new IllegalArgumentException("Incorrect number of indices");
+ return nPutDIdx(nativeObj, idx, data.length, data);
+ }
+
// javadoc:Mat::put(row,col,data)
public int put(int row, int col, float[] data) {
int t = type();
throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
}
+ // javadoc:Mat::put(idx,data)
+ public int put(int[] idx, float[] data) {
+ int t = type();
+ if (data == null || data.length % CvType.channels(t) != 0)
+ throw new java.lang.UnsupportedOperationException(
+ "Provided data element number (" +
+ (data == null ? 0 : data.length) +
+ ") should be multiple of the Mat channels count (" +
+ CvType.channels(t) + ")");
+ if (idx.length != dims())
+ throw new IllegalArgumentException("Incorrect number of indices");
+ if (CvType.depth(t) == CvType.CV_32F) {
+ return nPutFIdx(nativeObj, idx, data.length, data);
+ }
+ throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
+ }
+
// javadoc:Mat::put(row,col,data)
public int put(int row, int col, int[] data) {
int t = type();
throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
}
+ // javadoc:Mat::put(idx,data)
+ public int put(int[] idx, int[] data) {
+ int t = type();
+ if (data == null || data.length % CvType.channels(t) != 0)
+ throw new java.lang.UnsupportedOperationException(
+ "Provided data element number (" +
+ (data == null ? 0 : data.length) +
+ ") should be multiple of the Mat channels count (" +
+ CvType.channels(t) + ")");
+ if (idx.length != dims())
+ throw new IllegalArgumentException("Incorrect number of indices");
+ if (CvType.depth(t) == CvType.CV_32S) {
+ return nPutIIdx(nativeObj, idx, data.length, data);
+ }
+ throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
+ }
+
// javadoc:Mat::put(row,col,data)
public int put(int row, int col, short[] data) {
int t = type();
throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
}
+ // javadoc:Mat::put(idx,data)
+ public int put(int[] idx, short[] data) {
+ int t = type();
+ if (data == null || data.length % CvType.channels(t) != 0)
+ throw new java.lang.UnsupportedOperationException(
+ "Provided data element number (" +
+ (data == null ? 0 : data.length) +
+ ") should be multiple of the Mat channels count (" +
+ CvType.channels(t) + ")");
+ if (idx.length != dims())
+ throw new IllegalArgumentException("Incorrect number of indices");
+ if (CvType.depth(t) == CvType.CV_16U || CvType.depth(t) == CvType.CV_16S) {
+ return nPutSIdx(nativeObj, idx, data.length, data);
+ }
+ throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
+ }
+
// javadoc:Mat::put(row,col,data)
public int put(int row, int col, byte[] data) {
int t = type();
throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
}
+ // javadoc:Mat::put(idx,data)
+ public int put(int[] idx, byte[] data) {
+ int t = type();
+ if (data == null || data.length % CvType.channels(t) != 0)
+ throw new java.lang.UnsupportedOperationException(
+ "Provided data element number (" +
+ (data == null ? 0 : data.length) +
+ ") should be multiple of the Mat channels count (" +
+ CvType.channels(t) + ")");
+ if (idx.length != dims())
+ throw new IllegalArgumentException("Incorrect number of indices");
+ if (CvType.depth(t) == CvType.CV_8U || CvType.depth(t) == CvType.CV_8S) {
+ return nPutBIdx(nativeObj, idx, data.length, data);
+ }
+ throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
+ }
+
// javadoc:Mat::put(row,col,data,offset,length)
public int put(int row, int col, byte[] data, int offset, int length) {
int t = type();
throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
}
+ // javadoc:Mat::put(idx,data,offset,length)
+ public int put(int[] idx, byte[] data, int offset, int length) {
+ int t = type();
+ if (data == null || length % CvType.channels(t) != 0)
+ throw new java.lang.UnsupportedOperationException(
+ "Provided data element number (" +
+ (data == null ? 0 : data.length) +
+ ") should be multiple of the Mat channels count (" +
+ CvType.channels(t) + ")");
+ if (idx.length != dims())
+ throw new IllegalArgumentException("Incorrect number of indices");
+ if (CvType.depth(t) == CvType.CV_8U || CvType.depth(t) == CvType.CV_8S) {
+ return nPutBwIdxOffset(nativeObj, idx, length, offset, data);
+ }
+ throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
+ }
+
// javadoc:Mat::get(row,col,data)
public int get(int row, int col, byte[] data) {
int t = type();
throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
}
+ // javadoc:Mat::get(idx,data)
+ public int get(int[] idx, byte[] data) {
+ int t = type();
+ if (data == null || data.length % CvType.channels(t) != 0)
+ throw new java.lang.UnsupportedOperationException(
+ "Provided data element number (" +
+ (data == null ? 0 : data.length) +
+ ") should be multiple of the Mat channels count (" +
+ CvType.channels(t) + ")");
+ if (idx.length != dims())
+ throw new IllegalArgumentException("Incorrect number of indices");
+ if (CvType.depth(t) == CvType.CV_8U || CvType.depth(t) == CvType.CV_8S) {
+ return nGetBIdx(nativeObj, idx, data.length, data);
+ }
+ throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
+ }
+
// javadoc:Mat::get(row,col,data)
public int get(int row, int col, short[] data) {
int t = type();
throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
}
+ // javadoc:Mat::get(idx,data)
+ public int get(int[] idx, short[] data) {
+ int t = type();
+ if (data == null || data.length % CvType.channels(t) != 0)
+ throw new java.lang.UnsupportedOperationException(
+ "Provided data element number (" +
+ (data == null ? 0 : data.length) +
+ ") should be multiple of the Mat channels count (" +
+ CvType.channels(t) + ")");
+ if (idx.length != dims())
+ throw new IllegalArgumentException("Incorrect number of indices");
+ if (CvType.depth(t) == CvType.CV_16U || CvType.depth(t) == CvType.CV_16S) {
+ return nGetSIdx(nativeObj, idx, data.length, data);
+ }
+ throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
+ }
+
// javadoc:Mat::get(row,col,data)
public int get(int row, int col, int[] data) {
int t = type();
throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
}
+ // javadoc:Mat::get(idx,data)
+ public int get(int[] idx, int[] data) {
+ int t = type();
+ if (data == null || data.length % CvType.channels(t) != 0)
+ throw new java.lang.UnsupportedOperationException(
+ "Provided data element number (" +
+ (data == null ? 0 : data.length) +
+ ") should be multiple of the Mat channels count (" +
+ CvType.channels(t) + ")");
+ if (idx.length != dims())
+ throw new IllegalArgumentException("Incorrect number of indices");
+ if (CvType.depth(t) == CvType.CV_32S) {
+ return nGetIIdx(nativeObj, idx, data.length, data);
+ }
+ throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
+ }
+
// javadoc:Mat::get(row,col,data)
public int get(int row, int col, float[] data) {
int t = type();
throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
}
+ // javadoc:Mat::get(idx,data)
+ public int get(int[] idx, float[] data) {
+ int t = type();
+ if (data == null || data.length % CvType.channels(t) != 0)
+ throw new java.lang.UnsupportedOperationException(
+ "Provided data element number (" +
+ (data == null ? 0 : data.length) +
+ ") should be multiple of the Mat channels count (" +
+ CvType.channels(t) + ")");
+ if (idx.length != dims())
+ throw new IllegalArgumentException("Incorrect number of indices");
+ if (CvType.depth(t) == CvType.CV_32F) {
+ return nGetFIdx(nativeObj, idx, data.length, data);
+ }
+ throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
+ }
+
// javadoc:Mat::get(row,col,data)
public int get(int row, int col, double[] data) {
int t = type();
throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
}
+ // javadoc:Mat::get(idx,data)
+ public int get(int[] idx, double[] data) {
+ int t = type();
+ if (data == null || data.length % CvType.channels(t) != 0)
+ throw new java.lang.UnsupportedOperationException(
+ "Provided data element number (" +
+ (data == null ? 0 : data.length) +
+ ") should be multiple of the Mat channels count (" +
+ CvType.channels(t) + ")");
+ if (idx.length != dims())
+ throw new IllegalArgumentException("Incorrect number of indices");
+ if (CvType.depth(t) == CvType.CV_64F) {
+ return nGetDIdx(nativeObj, idx, data.length, data);
+ }
+ throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
+ }
+
// javadoc:Mat::get(row,col)
public double[] get(int row, int col) {
return nGet(nativeObj, row, col);
}
+ // javadoc:Mat::get(idx)
+ public double[] get(int[] idx) {
+ if (idx.length != dims())
+ throw new IllegalArgumentException("Incorrect number of indices");
+ return nGetIdx(nativeObj, idx);
+ }
+
// javadoc:Mat::height()
public int height() {
return rows();
// C++: Mat::Mat(int rows, int cols, int type)
private static native long n_Mat(int rows, int cols, int type);
+ // C++: Mat::Mat(int ndims, const int* sizes, int type)
+ private static native long n_Mat(int ndims, int[] sizes, int type);
+
// C++: Mat::Mat(int rows, int cols, int type, void* data)
private static native long n_Mat(int rows, int cols, int type, ByteBuffer data);
// C++: Mat::Mat(Size size, int type, Scalar s)
private static native long n_Mat(double size_width, double size_height, int type, double s_val0, double s_val1, double s_val2, double s_val3);
+ // C++: Mat::Mat(int ndims, const int* sizes, int type, Scalar s)
+ private static native long n_Mat(int ndims, int[] sizes, int type, double s_val0, double s_val1, double s_val2, double s_val3);
+
// C++: Mat::Mat(Mat m, Range rowRange, Range colRange = Range::all())
private static native long n_Mat(long m_nativeObj, int rowRange_start, int rowRange_end, int colRange_start, int colRange_end);
private static native long n_Mat(long m_nativeObj, int rowRange_start, int rowRange_end);
+ // C++: Mat::Mat(const Mat& m, const std::vector<Range>& ranges)
+ private static native long n_Mat(long m_nativeObj, Range[] ranges);
+
// C++: Mat Mat::adjustROI(int dtop, int dbottom, int dleft, int dright)
private static native long n_adjustROI(long nativeObj, int dtop, int dbottom, int dleft, int dright);
// C++: void Mat::create(Size size, int type)
private static native void n_create(long nativeObj, double size_width, double size_height, int type);
+ // C++: void Mat::create(int ndims, const int* sizes, int type)
+ private static native void n_create(long nativeObj, int ndims, int[] sizes, int type);
+
+ // C++: void Mat::copySize(const Mat& m)
+ private static native void n_copySize(long nativeObj, long m_nativeObj);
+
// C++: Mat Mat::cross(Mat m)
private static native long n_cross(long nativeObj, long m_nativeObj);
// C++: static Mat Mat::ones(Size size, int type)
private static native long n_ones(double size_width, double size_height, int type);
+ // C++: static Mat Mat::ones(int ndims, const int* sizes, int type)
+ private static native long n_ones(int ndims, int[] sizes, int type);
+
// C++: void Mat::push_back(Mat m)
private static native void n_push_back(long nativeObj, long m_nativeObj);
// C++: Mat Mat::operator()(Range rowRange, Range colRange)
private static native long n_submat_rr(long nativeObj, int rowRange_start, int rowRange_end, int colRange_start, int colRange_end);
+ // C++: Mat Mat::operator()(const std::vector<Range>& ranges)
+ private static native long n_submat_ranges(long nativeObj, Range[] ranges);
+
// C++: Mat Mat::operator()(Rect roi)
private static native long n_submat(long nativeObj, int roi_x, int roi_y, int roi_width, int roi_height);
// C++: static Mat Mat::zeros(Size size, int type)
private static native long n_zeros(double size_width, double size_height, int type);
+ // C++: static Mat Mat::zeros(int ndims, const int* sizes, int type)
+ private static native long n_zeros(int ndims, int[] sizes, int type);
+
// native support for java finalize()
private static native void n_delete(long nativeObj);
private static native int nPutD(long self, int row, int col, int count, double[] data);
+ private static native int nPutDIdx(long self, int[] idx, int count, double[] data);
+
private static native int nPutF(long self, int row, int col, int count, float[] data);
+ private static native int nPutFIdx(long self, int[] idx, int count, float[] data);
+
private static native int nPutI(long self, int row, int col, int count, int[] data);
+ private static native int nPutIIdx(long self, int[] idx, int count, int[] data);
+
private static native int nPutS(long self, int row, int col, int count, short[] data);
+ private static native int nPutSIdx(long self, int[] idx, int count, short[] data);
+
private static native int nPutB(long self, int row, int col, int count, byte[] data);
+ private static native int nPutBIdx(long self, int[] idx, int count, byte[] data);
+
private static native int nPutBwOffset(long self, int row, int col, int count, int offset, byte[] data);
+ private static native int nPutBwIdxOffset(long self, int[] idx, int count, int offset, byte[] data);
+
private static native int nGetB(long self, int row, int col, int count, byte[] vals);
+ private static native int nGetBIdx(long self, int[] idx, int count, byte[] vals);
+
private static native int nGetS(long self, int row, int col, int count, short[] vals);
+ private static native int nGetSIdx(long self, int[] idx, int count, short[] vals);
+
private static native int nGetI(long self, int row, int col, int count, int[] vals);
+ private static native int nGetIIdx(long self, int[] idx, int count, int[] vals);
+
private static native int nGetF(long self, int row, int col, int count, float[] vals);
+ private static native int nGetFIdx(long self, int[] idx, int count, float[] vals);
+
private static native int nGetD(long self, int row, int col, int count, double[] vals);
+ private static native int nGetDIdx(long self, int[] idx, int count, double[] vals);
+
private static native double[] nGet(long self, int row, int col);
+ private static native double[] nGetIdx(long self, int[] idx);
+
private static native String nDump(long self);
}
assertEquals(CvType.CV_16U, dst.type());
}
+ public void testCreateIntArrayInt() {
+ int[] dims = new int[] {5, 6, 7};
+ dst.create(dims, CvType.CV_16U);
+
+ assertEquals(5, dst.size(0));
+ assertEquals(6, dst.size(1));
+ assertEquals(7, dst.size(2));
+ assertEquals(CvType.CV_16U, dst.type());
+ }
+
public void testCross() {
Mat answer = new Mat(1, 3, CvType.CV_32F);
answer.put(0, 0, 7.0, 1.0, -5.0);
assertMatEqual(truth, dst, EPS);
}
+ public void testMatMatRangeArray() {
+ dst = new Mat(gray255_32f_3d, new Range[]{new Range(0, 5), new Range(0, 5), new Range(0, 5)});
+
+ truth = new Mat(new int[] {5, 5, 5}, CvType.CV_32FC1, new Scalar(255));
+
+ assertFalse(dst.empty());
+ assertMatEqual(truth, dst, EPS);
+ }
+
public void testMatMatRect() {
Mat m = new Mat(7, 6, CvType.CV_32SC1);
m.put(0, 0,
assertMatEqual(gray255_32f, dst, EPS);
}
+ public void testMatIntArrayIntScalar() {
+ dst = new Mat(new int[]{10, 10, 10}, CvType.CV_32F, new Scalar(255));
+
+ assertFalse(dst.empty());
+ assertMatEqual(gray255_32f_3d, dst, EPS);
+ }
+
public void testMulMat() {
assertMatEqual(gray0, gray0.mul(gray255));
}
+ public void testMulMat3d() {
+ Mat m1 = new Mat(new int[] {2, 2, 2}, CvType.CV_32F, new Scalar(2));
+ Mat m2 = new Mat(new int[] {2, 2, 2}, CvType.CV_32F, new Scalar(3));
+
+ dst = m1.mul(m2);
+
+ truth = new Mat(new int[] {2, 2, 2}, CvType.CV_32F, new Scalar(6));
+ assertMatEqual(truth, dst, EPS);
+ }
+
public void testMulMatDouble() {
Mat m1 = new Mat(2, 2, CvType.CV_32F, new Scalar(2));
Mat m2 = new Mat(2, 2, CvType.CV_32F, new Scalar(3));
assertMatEqual(truth, dst);
}
+ public void testOnesIntArrayInt() {
+ dst = Mat.ones(new int[]{2, 2, 2}, CvType.CV_16S);
+ truth = new Mat(new int[]{2, 2, 2}, CvType.CV_16S, new Scalar(1));
+ assertMatEqual(truth, dst);
+ }
+
public void testPush_back() {
Mat m1 = new Mat(2, 4, CvType.CV_32F, new Scalar(2));
Mat m2 = new Mat(3, 4, CvType.CV_32F, new Scalar(3));
}
}
+ public void testPutIntArrayByteArray() {
+ Mat m = new Mat(new int[]{5, 5, 5}, CvType.CV_8UC3, new Scalar(1, 2, 3));
+ Mat sm = m.submat(new Range[]{ new Range(0, 2), new Range(1, 3), new Range(2, 4)});
+ byte[] buff = new byte[] { 0, 0, 0, 0, 0, 0 };
+ byte[] buff0 = new byte[] { 10, 20, 30, 40, 50, 60 };
+ byte[] buff1 = new byte[] { -1, -2, -3, -4, -5, -6 };
+
+ int bytesNum = m.put(new int[]{1, 2, 0}, buff0);
+
+ assertEquals(6, bytesNum);
+ bytesNum = m.get(new int[]{1, 2, 0}, buff);
+ assertEquals(6, bytesNum);
+ assertTrue(Arrays.equals(buff, buff0));
+
+ bytesNum = sm.put(new int[]{0, 0, 0}, buff1);
+
+ assertEquals(6, bytesNum);
+ bytesNum = sm.get(new int[]{0, 0, 0}, buff);
+ assertEquals(6, bytesNum);
+ assertTrue(Arrays.equals(buff, buff1));
+
+ bytesNum = m.get(new int[]{0, 1, 2}, buff);
+ assertEquals(6, bytesNum);
+ assertTrue(Arrays.equals(buff, buff1));
+
+ Mat m1 = m.submat(new Range[]{ new Range(1,2), Range.all(), Range.all() });
+ bytesNum = m1.get(new int[]{ 0, 2, 0}, buff);
+ assertEquals(6, bytesNum);
+ assertTrue(Arrays.equals(buff, buff0));
+
+ try {
+ byte[] bytes2 = new byte[] { 10, 20, 30, 40, 50 };
+ m.put(new int[]{ 2, 2, 0 }, bytes2);
+ fail("Expected UnsupportedOperationException (data.length % CvType.channels(t) != 0)");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ }
+
public void testPutIntIntDoubleArray() {
Mat m = new Mat(5, 5, CvType.CV_8UC3, new Scalar(1, 2, 3));
Mat sm = m.submat(2, 4, 3, 5);
assertTrue(Arrays.equals(buff, new byte[]{-1, -2, -3, -4, -5, -6}));
}
+ public void testPutIntArrayDoubleArray() {
+ Mat m = new Mat(new int[]{5, 5, 5}, CvType.CV_8UC3, new Scalar(1, 2, 3));
+ Mat sm = m.submat(new Range[]{ new Range(0, 2), new Range(1, 3), new Range(2, 4)});
+ byte[] buff = new byte[] { 0, 0, 0, 0, 0, 0 };
+
+ int bytesNum = m.put(new int[]{1, 2, 0}, 10, 20, 30, 40, 50, 60);
+
+ assertEquals(6, bytesNum);
+ bytesNum = m.get(new int[]{1, 2, 0}, buff);
+ assertEquals(6, bytesNum);
+ assertTrue(Arrays.equals(buff, new byte[]{10, 20, 30, 40, 50, 60}));
+
+ bytesNum = sm.put(new int[]{0, 0, 0}, 255, 254, 253, 252, 251, 250);
+
+ assertEquals(6, bytesNum);
+ bytesNum = sm.get(new int[]{0, 0, 0}, buff);
+ assertEquals(6, bytesNum);
+ assertTrue(Arrays.equals(buff, new byte[]{-1, -2, -3, -4, -5, -6}));
+ bytesNum = m.get(new int[]{0, 1, 2}, buff);
+ assertEquals(6, bytesNum);
+ assertTrue(Arrays.equals(buff, new byte[]{-1, -2, -3, -4, -5, -6}));
+ }
+
public void testPutIntIntFloatArray() {
Mat m = new Mat(5, 5, CvType.CV_32FC3, new Scalar(1, 2, 3));
float[] elements = new float[] { 10, 20, 30, 40, 50, 60 };
}
}
+ public void testPutIntArrayFloatArray() {
+ Mat m = new Mat(new int[]{5, 5, 5}, CvType.CV_32FC3, new Scalar(1, 2, 3));
+ float[] elements = new float[] { 10, 20, 30, 40, 50, 60 };
+
+ int bytesNum = m.put(new int[]{0, 4, 3}, elements);
+
+ assertEquals(elements.length * 4, bytesNum);
+ Mat m1 = m.submat(new Range[]{ Range.all(), new Range(4, 5), Range.all() });
+ float buff[] = new float[3];
+ bytesNum = m1.get(new int[]{ 0, 0, 4 }, buff);
+ assertEquals(buff.length * 4, bytesNum);
+ assertTrue(Arrays.equals(new float[]{40, 50, 60}, buff));
+ assertArrayEquals(new double[]{10, 20, 30}, m.get(new int[]{ 0, 4, 3 }), EPS);
+
+ try {
+ float[] elements2 = new float[] { 10, 20, 30, 40, 50 };
+ m.put(new int[]{4, 2, 2}, elements2);
+ fail("Expected UnsupportedOperationException (data.length % CvType.channels(t) != 0)");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
public void testPutIntIntIntArray() {
Mat m = new Mat(5, 5, CvType.CV_32SC3, new Scalar(-1, -2, -3));
int[] elements = new int[] { 10, 20, 30, 40, 50, 60 };
}
}
+ public void testPutIntArrayIntArray() {
+ Mat m = new Mat(new int[]{5, 5, 5}, CvType.CV_32SC3, new Scalar(-1, -2, -3));
+ int[] elements = new int[] { 10, 20, 30, 40, 50, 60 };
+
+ int bytesNum = m.put(new int[]{ 0, 0, 4 }, elements);
+
+ assertEquals(elements.length * 4, bytesNum);
+ Mat m1 = m.submat(new Range[]{ Range.all(), Range.all(), new Range(4, 5)});
+ int buff[] = new int[3];
+ bytesNum = m1.get(new int[]{ 0, 0, 0 }, buff);
+ assertEquals(buff.length * 4, bytesNum);
+ assertTrue(Arrays.equals(new int[]{ 10, 20, 30 }, buff));
+ assertArrayEquals(new double[]{ 40, 50, 60 }, m.get(new int[]{ 0, 1, 0 }), EPS);
+
+ try {
+ int[] elements2 = new int[] { 10, 20, 30, 40, 50 };
+ m.put(new int[] { 2, 2, 0 }, elements2);
+ fail("Expected UnsupportedOperationException (data.length % CvType.channels(t) != 0)");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
public void testPutIntIntShortArray() {
Mat m = new Mat(5, 5, CvType.CV_16SC3, new Scalar(-1, -2, -3));
short[] elements = new short[] { 10, 20, 30, 40, 50, 60 };
}
}
+ public void testPutIntArrayShortArray() {
+ Mat m = new Mat(new int[]{ 5, 5, 5}, CvType.CV_16SC3, new Scalar(-1, -2, -3));
+ short[] elements = new short[] { 10, 20, 30, 40, 50, 60 };
+
+ int bytesNum = m.put(new int[]{ 0, 2, 3 }, elements);
+
+ assertEquals(elements.length * 2, bytesNum);
+ Mat m1 = m.submat(new Range[]{ Range.all(), Range.all(), new Range(3, 4)});
+ short buff[] = new short[3];
+ bytesNum = m1.get(new int[]{ 0, 2, 0 }, buff);
+ assertTrue(Arrays.equals(new short[]{10, 20, 30}, buff));
+ assertArrayEquals(new double[]{40, 50, 60}, m.get(new int[]{ 0, 2, 4 }), EPS);
+
+ try {
+ short[] elements2 = new short[] { 10, 20, 30, 40, 50 };
+ m.put(new int[] { 2, 2, 0 }, elements2);
+ fail("Expected UnsupportedOperationException (data.length % CvType.channels(t) != 0)");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
public void testRelease() {
assertFalse(gray0.empty());
assertTrue(gray0.rows() > 0);
}
public void testReshapeIntIntArray() {
+ // 2D -> 4D
Mat src = new Mat(6, 5, CvType.CV_8UC3, new Scalar(0));
assertEquals(2, src.dims());
assertEquals(src.rows(), src.size(0));
assertEquals(newShape.length, dst.dims());
for (int i = 0; i < newShape.length; ++i)
assertEquals(newShape[i], dst.size(i));
+
+ // 3D -> 2D
+ src = new Mat(new int[]{4, 6, 7}, CvType.CV_8UC3, new Scalar(0));
+ assertEquals(3, src.dims());
+ assertEquals(4, src.size(0));
+ assertEquals(6, src.size(1));
+ assertEquals(7, src.size(2));
+
+ int[] newShape2 = {src.channels() * src.size(2), src.size(0) * src.size(1)};
+ dst = src.reshape(1, newShape2);
+ assertEquals(newShape2.length, dst.dims());
+ for (int i = 0; i < newShape2.length; ++i)
+ assertEquals(newShape2[i], dst.size(i));
+ }
+
+ public void testCopySize() {
+ Mat src = new Mat(new int[]{1, 1, 10, 10}, CvType.CV_8UC1, new Scalar(1));
+ assertEquals(4, src.dims());
+ assertEquals(1, src.size(0));
+ assertEquals(1, src.size(1));
+ assertEquals(10, src.size(2));
+ assertEquals(10, src.size(3));
+ Mat other = new Mat(new int[]{10, 10}, src.type());
+
+ src.copySize(other);
+ assertEquals(other.dims(), src.dims());
+ for (int i = 0; i < other.dims(); ++i)
+ assertEquals(other.size(i), src.size(i));
}
public void testRow() {
assertEquals(2, submat.cols());
}
+ public void testSubmatRangeArray() {
+ Mat submat = gray255_32f_3d.submat(new Range[]{ new Range(2, 4), new Range(2, 4), new Range(3, 6) });
+ assertTrue(submat.isSubmatrix());
+ assertFalse(submat.isContinuous());
+
+ assertEquals(2, submat.size(0));
+ assertEquals(2, submat.size(1));
+ assertEquals(3, submat.size(2));
+ }
+
public void testSubmatRect() {
Mat submat = gray255.submat(new Rect(5, 5, gray255.cols() / 2, gray255.rows() / 2));
assertTrue(submat.isSubmatrix());
assertMatEqual(truth, dst);
}
+ public void testZerosIntArray() {
+ dst = Mat.zeros(new int[]{2, 3, 4}, CvType.CV_16S);
+
+ truth = new Mat(new int[]{2, 3, 4}, CvType.CV_16S, new Scalar(0));
+ assertMatEqual(truth, dst);
+ }
+
public void testMatFromByteBuffer() {
ByteBuffer bbuf = ByteBuffer.allocateDirect(64*64);
bbuf.putInt(0x01010101);
#define FILE_EXTENSION String(".xml"), String(".yml"), String(".json")
-PERF_TEST_P(Size_Mat_StrType, fs_text,
+PERF_TEST_P(Size_Mat_StrType, DISABLED_fs_text,
testing::Combine(testing::Values(MAT_SIZES),
testing::Values(MAT_TYPES),
testing::Values(FILE_EXTENSION))
SANITY_CHECK_NOTHING();
}
-PERF_TEST_P(Size_Mat_StrType, fs_base64,
+PERF_TEST_P(Size_Mat_StrType, DISABLED_fs_base64,
testing::Combine(testing::Values(MAT_SIZES),
testing::Values(MAT_TYPES),
testing::Values(FILE_EXTENSION))
{
CV_TRACE_FUNCTION_VERBOSE();
+ CV_DbgAssert(len > 0);
+
+#ifdef CV_STATIC_ANALYSIS
+ if(p >= 0 && p < len)
+#else
if( (unsigned)p < (unsigned)len )
+#endif
;
else if( borderType == BORDER_REPLICATE )
p = p < 0 ? 0 : len - 1;
else
p = len - 1 - (p - len) - delta;
}
+#ifdef CV_STATIC_ANALYSIS
+ while(p < 0 || p >= len);
+#else
while( (unsigned)p >= (unsigned)len );
+#endif
}
else if( borderType == BORDER_WRAP )
{
#include "opencl_kernels_core.hpp"
#include "stat.hpp"
-namespace cv {
-
-template<typename T>
-static int countNonZero_(const T* src, int len )
-{
- int i=0, nz = 0;
- #if CV_ENABLE_UNROLLED
- for(; i <= len - 4; i += 4 )
- nz += (src[i] != 0) + (src[i+1] != 0) + (src[i+2] != 0) + (src[i+3] != 0);
- #endif
- for( ; i < len; i++ )
- nz += src[i] != 0;
- return nz;
-}
-
-static int countNonZero8u( const uchar* src, int len )
-{
- int i=0, nz = 0;
-#if CV_SIMD
- int len0 = len & -v_uint8::nlanes;
- v_uint8 v_zero = vx_setzero_u8();
- v_uint8 v_one = vx_setall_u8(1);
-
- v_uint32 v_sum32 = vx_setzero_u32();
- while (i < len0)
- {
- v_uint16 v_sum16 = vx_setzero_u16();
- int j = i;
- while (j < std::min(len0, i + 65280 * v_uint16::nlanes))
- {
- v_uint8 v_sum8 = vx_setzero_u8();
- int k = j;
- for (; k < std::min(len0, j + 255 * v_uint8::nlanes); k += v_uint8::nlanes)
- v_sum8 += v_one & (vx_load(src + k) == v_zero);
- v_uint16 part1, part2;
- v_expand(v_sum8, part1, part2);
- v_sum16 += part1 + part2;
- j = k;
- }
- v_uint32 part1, part2;
- v_expand(v_sum16, part1, part2);
- v_sum32 += part1 + part2;
- i = j;
- }
- nz = i - v_reduce_sum(v_sum32);
- v_cleanup();
-#endif
- for( ; i < len; i++ )
- nz += src[i] != 0;
- return nz;
-}
-
-static int countNonZero16u( const ushort* src, int len )
-{
- int i = 0, nz = 0;
-#if CV_SIMD
- int len0 = len & -v_int8::nlanes;
- v_uint16 v_zero = vx_setzero_u16();
- v_int8 v_one = vx_setall_s8(1);
-
- v_int32 v_sum32 = vx_setzero_s32();
- while (i < len0)
- {
- v_int16 v_sum16 = vx_setzero_s16();
- int j = i;
- while (j < std::min(len0, i + 32766 * v_int16::nlanes))
- {
- v_int8 v_sum8 = vx_setzero_s8();
- int k = j;
- for (; k < std::min(len0, j + 127 * v_int8::nlanes); k += v_int8::nlanes)
- v_sum8 += v_one & v_pack(v_reinterpret_as_s16(vx_load(src + k) == v_zero), v_reinterpret_as_s16(vx_load(src + k + v_uint16::nlanes) == v_zero));
- v_int16 part1, part2;
- v_expand(v_sum8, part1, part2);
- v_sum16 += part1 + part2;
- j = k;
- }
- v_int32 part1, part2;
- v_expand(v_sum16, part1, part2);
- v_sum32 += part1 + part2;
- i = j;
- }
- nz = i - v_reduce_sum(v_sum32);
- v_cleanup();
-#endif
- return nz + countNonZero_(src + i, len - i);
-}
-
-static int countNonZero32s( const int* src, int len )
-{
- int i = 0, nz = 0;
-#if CV_SIMD
- int len0 = len & -v_int8::nlanes;
- v_int32 v_zero = vx_setzero_s32();
- v_int8 v_one = vx_setall_s8(1);
-
- v_int32 v_sum32 = vx_setzero_s32();
- while (i < len0)
- {
- v_int16 v_sum16 = vx_setzero_s16();
- int j = i;
- while (j < std::min(len0, i + 32766 * v_int16::nlanes))
- {
- v_int8 v_sum8 = vx_setzero_s8();
- int k = j;
- for (; k < std::min(len0, j + 127 * v_int8::nlanes); k += v_int8::nlanes)
- v_sum8 += v_one & v_pack(
- v_pack(vx_load(src + k ) == v_zero, vx_load(src + k + v_int32::nlanes) == v_zero),
- v_pack(vx_load(src + k + 2*v_int32::nlanes) == v_zero, vx_load(src + k + 3*v_int32::nlanes) == v_zero)
- );
- v_int16 part1, part2;
- v_expand(v_sum8, part1, part2);
- v_sum16 += part1 + part2;
- j = k;
- }
- v_int32 part1, part2;
- v_expand(v_sum16, part1, part2);
- v_sum32 += part1 + part2;
- i = j;
- }
- nz = i - v_reduce_sum(v_sum32);
- v_cleanup();
-#endif
- return nz + countNonZero_(src + i, len - i);
-}
-
-static int countNonZero32f( const float* src, int len )
-{
- int i = 0, nz = 0;
-#if CV_SIMD
- int len0 = len & -v_int8::nlanes;
- v_float32 v_zero = vx_setzero_f32();
- v_int8 v_one = vx_setall_s8(1);
-
- v_int32 v_sum32 = vx_setzero_s32();
- while (i < len0)
- {
- v_int16 v_sum16 = vx_setzero_s16();
- int j = i;
- while (j < std::min(len0, i + 32766 * v_int16::nlanes))
- {
- v_int8 v_sum8 = vx_setzero_s8();
- int k = j;
- for (; k < std::min(len0, j + 127 * v_int8::nlanes); k += v_int8::nlanes)
- v_sum8 += v_one & v_pack(
- v_pack(v_reinterpret_as_s32(vx_load(src + k ) == v_zero), v_reinterpret_as_s32(vx_load(src + k + v_float32::nlanes) == v_zero)),
- v_pack(v_reinterpret_as_s32(vx_load(src + k + 2*v_float32::nlanes) == v_zero), v_reinterpret_as_s32(vx_load(src + k + 3*v_float32::nlanes) == v_zero))
- );
- v_int16 part1, part2;
- v_expand(v_sum8, part1, part2);
- v_sum16 += part1 + part2;
- j = k;
- }
- v_int32 part1, part2;
- v_expand(v_sum16, part1, part2);
- v_sum32 += part1 + part2;
- i = j;
- }
- nz = i - v_reduce_sum(v_sum32);
- v_cleanup();
-#endif
- return nz + countNonZero_(src + i, len - i);
-}
+#include "count_non_zero.simd.hpp"
+#include "count_non_zero.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
-static int countNonZero64f( const double* src, int len )
-{
- return countNonZero_(src, len);
-}
-
-typedef int (*CountNonZeroFunc)(const uchar*, int);
+namespace cv {
static CountNonZeroFunc getCountNonZeroTab(int depth)
{
- static CountNonZeroFunc countNonZeroTab[] =
- {
- (CountNonZeroFunc)GET_OPTIMIZED(countNonZero8u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero8u),
- (CountNonZeroFunc)GET_OPTIMIZED(countNonZero16u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero16u),
- (CountNonZeroFunc)GET_OPTIMIZED(countNonZero32s), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero32f),
- (CountNonZeroFunc)GET_OPTIMIZED(countNonZero64f), 0
- };
-
- return countNonZeroTab[depth];
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(getCountNonZeroTab, (depth),
+ CV_CPU_DISPATCH_MODES_ALL);
}
-
#ifdef HAVE_OPENCL
static bool ocl_countNonZero( InputArray _src, int & res )
{
}
#endif
-} // cv::
-
-int cv::countNonZero( InputArray _src )
+int countNonZero(InputArray _src)
{
CV_INSTRUMENT_REGION();
return nz;
}
-void cv::findNonZero( InputArray _src, OutputArray _idx )
+void findNonZero(InputArray _src, OutputArray _idx)
{
- CV_INSTRUMENT_REGION();
-
Mat src = _src.getMat();
CV_Assert( src.channels() == 1 && src.dims == 2 );
if( !idxvec.empty() )
Mat(idxvec).copyTo(_idx);
}
+
+} // namespace
--- /dev/null
+// 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 "precomp.hpp"
+
+namespace cv {
+
+typedef int (*CountNonZeroFunc)(const uchar*, int);
+
+
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+
+CountNonZeroFunc getCountNonZeroTab(int depth);
+
+
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
+
+template<typename T>
+static int countNonZero_(const T* src, int len )
+{
+ int i=0, nz = 0;
+ #if CV_ENABLE_UNROLLED
+ for(; i <= len - 4; i += 4 )
+ nz += (src[i] != 0) + (src[i+1] != 0) + (src[i+2] != 0) + (src[i+3] != 0);
+ #endif
+ for( ; i < len; i++ )
+ nz += src[i] != 0;
+ return nz;
+}
+
+static int countNonZero8u( const uchar* src, int len )
+{
+ int i=0, nz = 0;
+#if CV_SIMD
+ int len0 = len & -v_uint8::nlanes;
+ v_uint8 v_zero = vx_setzero_u8();
+ v_uint8 v_one = vx_setall_u8(1);
+
+ v_uint32 v_sum32 = vx_setzero_u32();
+ while (i < len0)
+ {
+ v_uint16 v_sum16 = vx_setzero_u16();
+ int j = i;
+ while (j < std::min(len0, i + 65280 * v_uint16::nlanes))
+ {
+ v_uint8 v_sum8 = vx_setzero_u8();
+ int k = j;
+ for (; k < std::min(len0, j + 255 * v_uint8::nlanes); k += v_uint8::nlanes)
+ v_sum8 += v_one & (vx_load(src + k) == v_zero);
+ v_uint16 part1, part2;
+ v_expand(v_sum8, part1, part2);
+ v_sum16 += part1 + part2;
+ j = k;
+ }
+ v_uint32 part1, part2;
+ v_expand(v_sum16, part1, part2);
+ v_sum32 += part1 + part2;
+ i = j;
+ }
+ nz = i - v_reduce_sum(v_sum32);
+ v_cleanup();
+#endif
+ for( ; i < len; i++ )
+ nz += src[i] != 0;
+ return nz;
+}
+
+static int countNonZero16u( const ushort* src, int len )
+{
+ int i = 0, nz = 0;
+#if CV_SIMD
+ int len0 = len & -v_int8::nlanes;
+ v_uint16 v_zero = vx_setzero_u16();
+ v_int8 v_one = vx_setall_s8(1);
+
+ v_int32 v_sum32 = vx_setzero_s32();
+ while (i < len0)
+ {
+ v_int16 v_sum16 = vx_setzero_s16();
+ int j = i;
+ while (j < std::min(len0, i + 32766 * v_int16::nlanes))
+ {
+ v_int8 v_sum8 = vx_setzero_s8();
+ int k = j;
+ for (; k < std::min(len0, j + 127 * v_int8::nlanes); k += v_int8::nlanes)
+ v_sum8 += v_one & v_pack(v_reinterpret_as_s16(vx_load(src + k) == v_zero), v_reinterpret_as_s16(vx_load(src + k + v_uint16::nlanes) == v_zero));
+ v_int16 part1, part2;
+ v_expand(v_sum8, part1, part2);
+ v_sum16 += part1 + part2;
+ j = k;
+ }
+ v_int32 part1, part2;
+ v_expand(v_sum16, part1, part2);
+ v_sum32 += part1 + part2;
+ i = j;
+ }
+ nz = i - v_reduce_sum(v_sum32);
+ v_cleanup();
+#endif
+ return nz + countNonZero_(src + i, len - i);
+}
+
+static int countNonZero32s( const int* src, int len )
+{
+ int i = 0, nz = 0;
+#if CV_SIMD
+ int len0 = len & -v_int8::nlanes;
+ v_int32 v_zero = vx_setzero_s32();
+ v_int8 v_one = vx_setall_s8(1);
+
+ v_int32 v_sum32 = vx_setzero_s32();
+ while (i < len0)
+ {
+ v_int16 v_sum16 = vx_setzero_s16();
+ int j = i;
+ while (j < std::min(len0, i + 32766 * v_int16::nlanes))
+ {
+ v_int8 v_sum8 = vx_setzero_s8();
+ int k = j;
+ for (; k < std::min(len0, j + 127 * v_int8::nlanes); k += v_int8::nlanes)
+ v_sum8 += v_one & v_pack(
+ v_pack(vx_load(src + k ) == v_zero, vx_load(src + k + v_int32::nlanes) == v_zero),
+ v_pack(vx_load(src + k + 2*v_int32::nlanes) == v_zero, vx_load(src + k + 3*v_int32::nlanes) == v_zero)
+ );
+ v_int16 part1, part2;
+ v_expand(v_sum8, part1, part2);
+ v_sum16 += part1 + part2;
+ j = k;
+ }
+ v_int32 part1, part2;
+ v_expand(v_sum16, part1, part2);
+ v_sum32 += part1 + part2;
+ i = j;
+ }
+ nz = i - v_reduce_sum(v_sum32);
+ v_cleanup();
+#endif
+ return nz + countNonZero_(src + i, len - i);
+}
+
+static int countNonZero32f( const float* src, int len )
+{
+ int i = 0, nz = 0;
+#if CV_SIMD
+ int len0 = len & -v_int8::nlanes;
+ v_float32 v_zero = vx_setzero_f32();
+ v_int8 v_one = vx_setall_s8(1);
+
+ v_int32 v_sum32 = vx_setzero_s32();
+ while (i < len0)
+ {
+ v_int16 v_sum16 = vx_setzero_s16();
+ int j = i;
+ while (j < std::min(len0, i + 32766 * v_int16::nlanes))
+ {
+ v_int8 v_sum8 = vx_setzero_s8();
+ int k = j;
+ for (; k < std::min(len0, j + 127 * v_int8::nlanes); k += v_int8::nlanes)
+ v_sum8 += v_one & v_pack(
+ v_pack(v_reinterpret_as_s32(vx_load(src + k ) == v_zero), v_reinterpret_as_s32(vx_load(src + k + v_float32::nlanes) == v_zero)),
+ v_pack(v_reinterpret_as_s32(vx_load(src + k + 2*v_float32::nlanes) == v_zero), v_reinterpret_as_s32(vx_load(src + k + 3*v_float32::nlanes) == v_zero))
+ );
+ v_int16 part1, part2;
+ v_expand(v_sum8, part1, part2);
+ v_sum16 += part1 + part2;
+ j = k;
+ }
+ v_int32 part1, part2;
+ v_expand(v_sum16, part1, part2);
+ v_sum32 += part1 + part2;
+ i = j;
+ }
+ nz = i - v_reduce_sum(v_sum32);
+ v_cleanup();
+#endif
+ return nz + countNonZero_(src + i, len - i);
+}
+
+static int countNonZero64f( const double* src, int len )
+{
+ return countNonZero_(src, len);
+}
+
+CountNonZeroFunc getCountNonZeroTab(int depth)
+{
+ static CountNonZeroFunc countNonZeroTab[] =
+ {
+ (CountNonZeroFunc)GET_OPTIMIZED(countNonZero8u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero8u),
+ (CountNonZeroFunc)GET_OPTIMIZED(countNonZero16u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero16u),
+ (CountNonZeroFunc)GET_OPTIMIZED(countNonZero32s), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero32f),
+ (CountNonZeroFunc)GET_OPTIMIZED(countNonZero64f), 0
+ };
+
+ return countNonZeroTab[depth];
+}
+
+#endif
+
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+} // namespace
cols = cols_;
step = elemSize() * cols;
int sz[] = { rows, cols };
- size_t steps[] = { step, CV_ELEM_SIZE(type_) };
+ size_t steps[] = { step, (size_t)CV_ELEM_SIZE(type_) };
flags = updateContinuityFlag(flags, 2, sz, steps);
if (alloc_type == SHARED)
#ifdef HAVE_DIRECTX
#include <vector>
-# include "directx.inc.hpp"
+#include "directx.inc.hpp"
#else // HAVE_DIRECTX
#define NO_DIRECTX_SUPPORT_ERROR CV_Error(cv::Error::StsBadFunc, "OpenCV was build without DirectX support")
#endif
#ifndef HAVE_OPENCL
-# define NO_OPENCL_SUPPORT_ERROR CV_Error(cv::Error::StsBadFunc, "OpenCV was build without OpenCL support")
+#define NO_OPENCL_SUPPORT_ERROR CV_Error(cv::Error::StsBadFunc, "OpenCV was build without OpenCL support")
#endif // HAVE_OPENCL
namespace cv { namespace directx {
//case DXGI_FORMAT_BC7_TYPELESS:
//case DXGI_FORMAT_BC7_UNORM:
//case DXGI_FORMAT_BC7_UNORM_SRGB:
-#ifdef HAVE_DIRECTX_NV12
+#ifdef HAVE_DIRECTX_NV12 //D3DX11 should support DXGI_FORMAT_NV12.
case DXGI_FORMAT_NV12: return CV_8UC3;
#endif
default: break;
CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");
std::vector<cl_platform_id> platforms(numPlatforms);
- status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
- if (status != CL_SUCCESS)
- CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
-
- // TODO Filter platforms by name from OPENCV_OPENCL_DEVICE
+ size_t exts_len;
+ cv::AutoBuffer<char> extensions;
+ bool is_support_cl_khr_d3d11_sharing = false;
+#ifdef HAVE_OPENCL_D3D11_NV
+ bool is_support_cl_nv_d3d11_sharing = false;
+#endif
+ for (int i = 0; i < (int)numPlatforms; i++)
+ {
+ status = clGetPlatformIDs(numPlatforms, &platforms[i], NULL);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
+ status = clGetPlatformInfo(platforms[i], CL_PLATFORM_EXTENSIONS, 0, NULL, &exts_len);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get length of CL_PLATFORM_EXTENSIONS");
+ extensions.resize(exts_len);
+ status = clGetPlatformInfo(platforms[i], CL_PLATFORM_EXTENSIONS, exts_len, static_cast<void*>(extensions.data()), NULL);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available CL_PLATFORM_EXTENSIONS");
+ if (strstr(extensions.data(), "cl_khr_d3d11_sharing"))
+ is_support_cl_khr_d3d11_sharing = true;
+#ifdef HAVE_OPENCL_D3D11_NV
+ if (strstr(extensions.data(), "cl_nv_d3d11_sharing"))
+ is_support_cl_nv_d3d11_sharing = true;
+#endif
+ }
+#ifdef HAVE_OPENCL_D3D11_NV
+ if (!is_support_cl_nv_d3d11_sharing && !is_support_cl_khr_d3d11_sharing)
+ CV_Error(cv::Error::OpenCLInitError, "OpenCL: No supported extensions");
+#else
+ if (!is_support_cl_khr_d3d11_sharing)
+ CV_Error(cv::Error::OpenCLInitError, "OpenCL: No supported extensions");
+#endif
int found = -1;
cl_device_id device = NULL;
cl_uint numDevices = 0;
cl_context context = NULL;
- // try with CL_PREFERRED_DEVICES_FOR_D3D11_KHR
- for (int i = 0; i < (int)numPlatforms; i++)
- {
- clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR = (clGetDeviceIDsFromD3D11KHR_fn)
- clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11KHR");
- if (!clGetDeviceIDsFromD3D11KHR)
- continue;
-
- device = NULL;
- numDevices = 0;
- status = clGetDeviceIDsFromD3D11KHR(platforms[i], CL_D3D11_DEVICE_KHR, pD3D11Device,
- CL_PREFERRED_DEVICES_FOR_D3D11_KHR, 1, &device, &numDevices);
- if (status != CL_SUCCESS)
- continue;
- if (numDevices > 0)
- {
- cl_context_properties properties[] = {
- CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
- CL_CONTEXT_D3D11_DEVICE_KHR, (cl_context_properties)(pD3D11Device),
- CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
- NULL, NULL
- };
- context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
- if (status != CL_SUCCESS)
- {
- clReleaseDevice(device);
- }
- else
- {
- found = i;
- break;
- }
- }
- }
- if (found < 0)
+#ifdef HAVE_OPENCL_D3D11_NV
+ if (is_support_cl_nv_d3d11_sharing)
{
- // try with CL_ALL_DEVICES_FOR_D3D11_KHR
+ // try with CL_PREFERRED_DEVICES_FOR_D3D11_NV
for (int i = 0; i < (int)numPlatforms; i++)
{
- clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR = (clGetDeviceIDsFromD3D11KHR_fn)
- clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11KHR");
- if (!clGetDeviceIDsFromD3D11KHR)
+ clGetDeviceIDsFromD3D11NV_fn clGetDeviceIDsFromD3D11NV = (clGetDeviceIDsFromD3D11NV_fn)
+ clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11NV");
+ if (!clGetDeviceIDsFromD3D11NV)
continue;
device = NULL;
numDevices = 0;
- status = clGetDeviceIDsFromD3D11KHR(platforms[i], CL_D3D11_DEVICE_KHR, pD3D11Device,
- CL_ALL_DEVICES_FOR_D3D11_KHR, 1, &device, &numDevices);
+ status = clGetDeviceIDsFromD3D11NV(platforms[i], CL_D3D11_DEVICE_NV, pD3D11Device,
+ CL_PREFERRED_DEVICES_FOR_D3D11_NV, 1, &device, &numDevices);
if (status != CL_SUCCESS)
continue;
if (numDevices > 0)
{
cl_context_properties properties[] = {
CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
- CL_CONTEXT_D3D11_DEVICE_KHR, (cl_context_properties)(pD3D11Device),
- CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
- NULL, NULL
+ CL_CONTEXT_D3D11_DEVICE_NV, (cl_context_properties)(pD3D11Device),
+ //CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+ 0
};
+
context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
if (status != CL_SUCCESS)
{
}
}
if (found < 0)
- CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
+ {
+ // try with CL_ALL_DEVICES_FOR_D3D11_NV
+ for (int i = 0; i < (int)numPlatforms; i++)
+ {
+ clGetDeviceIDsFromD3D11NV_fn clGetDeviceIDsFromD3D11NV = (clGetDeviceIDsFromD3D11NV_fn)
+ clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11NV");
+ if (!clGetDeviceIDsFromD3D11NV)
+ continue;
+
+ device = NULL;
+ numDevices = 0;
+ status = clGetDeviceIDsFromD3D11NV(platforms[i], CL_D3D11_DEVICE_NV, pD3D11Device,
+ CL_ALL_DEVICES_FOR_D3D11_NV, 1, &device, &numDevices);
+ if (status != CL_SUCCESS)
+ continue;
+ if (numDevices > 0)
+ {
+ cl_context_properties properties[] = {
+ CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+ CL_CONTEXT_D3D11_DEVICE_NV, (cl_context_properties)(pD3D11Device),
+ //CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+ 0
+ };
+ context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+ if (status != CL_SUCCESS)
+ {
+ clReleaseDevice(device);
+ }
+ else
+ {
+ found = i;
+ break;
+ }
+ }
+ }
+ }
}
+#endif
+ if (is_support_cl_khr_d3d11_sharing)
+ {
+ if (found < 0)
+ {
+ // try with CL_PREFERRED_DEVICES_FOR_D3D11_KHR
+ for (int i = 0; i < (int)numPlatforms; i++)
+ {
+ clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR = (clGetDeviceIDsFromD3D11KHR_fn)
+ clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11KHR");
+ if (!clGetDeviceIDsFromD3D11KHR)
+ continue;
+
+ device = NULL;
+ numDevices = 0;
+ status = clGetDeviceIDsFromD3D11KHR(platforms[i], CL_D3D11_DEVICE_KHR, pD3D11Device,
+ CL_PREFERRED_DEVICES_FOR_D3D11_KHR, 1, &device, &numDevices);
+
+ if (status != CL_SUCCESS)
+ continue;
+ if (numDevices > 0)
+ {
+ cl_context_properties properties[] = {
+ CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+ CL_CONTEXT_D3D11_DEVICE_KHR, (cl_context_properties)(pD3D11Device),
+ CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+ NULL, NULL
+ };
+ context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+ if (status != CL_SUCCESS)
+ {
+ clReleaseDevice(device);
+ }
+ else
+ {
+ found = i;
+ break;
+ }
+ }
+ }
+ }
+ if (found < 0)
+ {
+ // try with CL_ALL_DEVICES_FOR_D3D11_KHR
+ for (int i = 0; i < (int)numPlatforms; i++)
+ {
+ clGetDeviceIDsFromD3D11KHR_fn clGetDeviceIDsFromD3D11KHR = (clGetDeviceIDsFromD3D11KHR_fn)
+ clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11KHR");
+ if (!clGetDeviceIDsFromD3D11KHR)
+ continue;
+
+ device = NULL;
+ numDevices = 0;
+ status = clGetDeviceIDsFromD3D11KHR(platforms[i], CL_D3D11_DEVICE_KHR, pD3D11Device,
+ CL_ALL_DEVICES_FOR_D3D11_KHR, 1, &device, &numDevices);
+ if (status != CL_SUCCESS)
+ continue;
+ if (numDevices > 0)
+ {
+ cl_context_properties properties[] = {
+ CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],
+ CL_CONTEXT_D3D11_DEVICE_KHR, (cl_context_properties)(pD3D11Device),
+ CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
+ NULL, NULL
+ };
+ context = clCreateContext(properties, 1, &device, NULL, NULL, &status);
+ if (status != CL_SUCCESS)
+ {
+ clReleaseDevice(device);
+ }
+ else
+ {
+ found = i;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (found < 0)
+ {
+ CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
+ }
Context& ctx = Context::getDefault(false);
initializeContextFromHandle(ctx, platforms[found], context, device);
} // namespace cv::ocl
#if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+
+#ifdef HAVE_OPENCL_D3D11_NV
+clCreateFromD3D11Texture2DNV_fn clCreateFromD3D11Texture2DNV = NULL;
+clEnqueueAcquireD3D11ObjectsNV_fn clEnqueueAcquireD3D11ObjectsNV = NULL;
+clEnqueueReleaseD3D11ObjectsNV_fn clEnqueueReleaseD3D11ObjectsNV = NULL;
+#endif
clCreateFromD3D11Texture2DKHR_fn clCreateFromD3D11Texture2DKHR = NULL;
clEnqueueAcquireD3D11ObjectsKHR_fn clEnqueueAcquireD3D11ObjectsKHR = NULL;
clEnqueueReleaseD3D11ObjectsKHR_fn clEnqueueReleaseD3D11ObjectsKHR = NULL;
-static void __OpenCLinitializeD3D11()
+static bool __OpenCLinitializeD3D11()
{
using namespace cv::ocl;
static cl_platform_id initializedPlatform = NULL;
cl_platform_id platform = (cl_platform_id)Platform::getDefault().ptr();
- if (initializedPlatform != platform)
+
+ bool useCLNVEXT = false;
+ size_t exts_len;
+ cl_int status = clGetPlatformInfo(platform, CL_PLATFORM_EXTENSIONS, 0, NULL, &exts_len);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get length of CL_PLATFORM_EXTENSIONS");
+ cv::AutoBuffer<char> extensions(exts_len);
+ status = clGetPlatformInfo(platform, CL_PLATFORM_EXTENSIONS, exts_len, static_cast<void*>(extensions.data()), NULL);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available CL_PLATFORM_EXTENSIONS");
+ bool is_support_cl_khr_d3d11_sharing = false;
+ if (strstr(extensions.data(), "cl_khr_d3d11_sharing"))
+ is_support_cl_khr_d3d11_sharing = true;
+#ifdef HAVE_OPENCL_D3D11_NV
+ bool is_support_cl_nv_d3d11_sharing = false;
+ if (strstr(extensions.data(), "cl_nv_d3d11_sharing"))
+ is_support_cl_nv_d3d11_sharing = true;
+ if (!is_support_cl_nv_d3d11_sharing && !is_support_cl_khr_d3d11_sharing)
+ CV_Error(cv::Error::OpenCLInitError, "OpenCL: No supported extensions");
+#else
+ if (!is_support_cl_khr_d3d11_sharing)
+ CV_Error(cv::Error::OpenCLInitError, "OpenCL: No supported extensions");
+#endif
+
+#ifdef HAVE_OPENCL_D3D11_NV
+ if (is_support_cl_nv_d3d11_sharing)
{
- clCreateFromD3D11Texture2DKHR = (clCreateFromD3D11Texture2DKHR_fn)
- clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromD3D11Texture2DKHR");
- clEnqueueAcquireD3D11ObjectsKHR = (clEnqueueAcquireD3D11ObjectsKHR_fn)
- clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireD3D11ObjectsKHR");
- clEnqueueReleaseD3D11ObjectsKHR = (clEnqueueReleaseD3D11ObjectsKHR_fn)
- clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseD3D11ObjectsKHR");
- initializedPlatform = platform;
+ if (initializedPlatform != platform)
+ {
+ clCreateFromD3D11Texture2DNV = (clCreateFromD3D11Texture2DNV_fn)
+ clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromD3D11Texture2DNV");
+ clEnqueueAcquireD3D11ObjectsNV = (clEnqueueAcquireD3D11ObjectsNV_fn)
+ clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireD3D11ObjectsNV");
+ clEnqueueReleaseD3D11ObjectsNV = (clEnqueueReleaseD3D11ObjectsNV_fn)
+ clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseD3D11ObjectsNV");
+ initializedPlatform = platform;
+ }
+ if (clCreateFromD3D11Texture2DNV && clEnqueueAcquireD3D11ObjectsNV && clEnqueueReleaseD3D11ObjectsNV)
+ {
+ useCLNVEXT = true;
+ }
}
- if (!clCreateFromD3D11Texture2DKHR || !clEnqueueAcquireD3D11ObjectsKHR || !clEnqueueReleaseD3D11ObjectsKHR)
+ else
+#endif
{
- CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't find functions for D3D11");
+ if (is_support_cl_khr_d3d11_sharing)
+ {
+ if (initializedPlatform != platform)
+ {
+ clCreateFromD3D11Texture2DKHR = (clCreateFromD3D11Texture2DKHR_fn)
+ clGetExtensionFunctionAddressForPlatform(platform, "clCreateFromD3D11Texture2DKHR");
+ clEnqueueAcquireD3D11ObjectsKHR = (clEnqueueAcquireD3D11ObjectsKHR_fn)
+ clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueAcquireD3D11ObjectsKHR");
+ clEnqueueReleaseD3D11ObjectsKHR = (clEnqueueReleaseD3D11ObjectsKHR_fn)
+ clGetExtensionFunctionAddressForPlatform(platform, "clEnqueueReleaseD3D11ObjectsKHR");
+ initializedPlatform = platform;
+ }
+ if (!clCreateFromD3D11Texture2DKHR || !clEnqueueAcquireD3D11ObjectsKHR || !clEnqueueReleaseD3D11ObjectsKHR)
+ {
+ CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't find functions for D3D11");
+ }
+ }
}
+ return useCLNVEXT;
}
#endif // defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
namespace directx {
-void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D)
+#if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+static void __convertToD3D11Texture2DKHR(InputArray src, ID3D11Texture2D* pD3D11Texture2D)
{
- CV_UNUSED(src); CV_UNUSED(pD3D11Texture2D);
-#if !defined(HAVE_DIRECTX)
- NO_DIRECTX_SUPPORT_ERROR;
-#elif defined(HAVE_OPENCL)
- __OpenCLinitializeD3D11();
-
D3D11_TEXTURE2D_DESC desc = { 0 };
pD3D11Texture2D->GetDesc(&desc);
#ifdef HAVE_DIRECTX_NV12
cl_mem clImageUV = 0;
#endif
-
clImage = clCreateFromD3D11Texture2DKHR(context, CL_MEM_WRITE_ONLY, pD3D11Texture2D, 0, &status);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DKHR failed");
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
}
#endif
+}
+#endif
-#else
- // TODO memcpy
- NO_OPENCL_SUPPORT_ERROR;
+#if defined(HAVE_OPENCL_D3D11_NV)
+static void __convertToD3D11Texture2DNV(InputArray src, ID3D11Texture2D* pD3D11Texture2D)
+{
+ D3D11_TEXTURE2D_DESC desc = { 0 };
+ pD3D11Texture2D->GetDesc(&desc);
+
+ int srcType = src.type();
+ int textureType = getTypeFromDXGI_FORMAT(desc.Format);
+ CV_Assert(textureType == srcType);
+
+ Size srcSize = src.size();
+ CV_Assert(srcSize.width == (int)desc.Width && srcSize.height == (int)desc.Height);
+
+ UMat u = src.getUMat();
+
+ // TODO Add support for roi
+ CV_Assert(u.offset == 0);
+ CV_Assert(u.isContinuous());
+
+ cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
+
+ using namespace cv::ocl;
+ Context& ctx = Context::getDefault();
+ cl_context context = (cl_context)ctx.ptr();
+
+ cl_int status = 0;
+ cl_mem clImage = 0;
+#ifdef HAVE_DIRECTX_NV12
+ cl_mem clImageUV = 0;
#endif
-}
+ clImage = clCreateFromD3D11Texture2DNV(context, CL_MEM_WRITE_ONLY, pD3D11Texture2D, 0, &status);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DNV failed");
+#ifdef HAVE_DIRECTX_NV12
+ if (DXGI_FORMAT_NV12 == desc.Format)
+ {
+ clImageUV = clCreateFromD3D11Texture2DNV(context, CL_MEM_WRITE_ONLY, pD3D11Texture2D, 1, &status);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DNV failed");
+ }
+#endif
+ cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
+ status = clEnqueueAcquireD3D11ObjectsNV(q, 1, &clImage, 0, NULL, NULL);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsNV failed");
-void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst)
-{
- CV_UNUSED(pD3D11Texture2D); CV_UNUSED(dst);
-#if !defined(HAVE_DIRECTX)
- NO_DIRECTX_SUPPORT_ERROR;
-#elif defined(HAVE_OPENCL)
- __OpenCLinitializeD3D11();
+#ifdef HAVE_DIRECTX_NV12
+ if(DXGI_FORMAT_NV12 == desc.Format)
+ {
+ status = clEnqueueAcquireD3D11ObjectsNV(q, 1, &clImageUV, 0, NULL, NULL);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsNV failed");
+
+ if(!ocl::ocl_convert_bgr_to_nv12(clBuffer, (int)u.step[0], u.cols, u.rows, clImage, clImageUV))
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: ocl_convert_bgr_to_nv12 failed");
+
+ status = clEnqueueReleaseD3D11ObjectsNV(q, 1, &clImageUV, 0, NULL, NULL);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsNV failed");
+ }
+ else
+#endif
+ {
+ size_t offset = 0; // TODO
+ size_t origin[3] = { 0, 0, 0 };
+ size_t region[3] = { (size_t)u.cols, (size_t)u.rows, 1 };
+
+ status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, origin, region, 0, NULL, NULL);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed");
+ }
+
+ status = clEnqueueReleaseD3D11ObjectsNV(q, 1, &clImage, 0, NULL, NULL);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsNV failed");
+
+ status = clFinish(q); // TODO Use events
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
+
+ status = clReleaseMemObject(clImage); // TODO RAII
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+
+#ifdef HAVE_DIRECTX_NV12
+ if(DXGI_FORMAT_NV12 == desc.Format)
+ {
+ status = clReleaseMemObject(clImageUV);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+ }
+#endif
+}
+#endif
+#if defined(HAVE_DIRECTX) && defined(HAVE_OPENCL)
+static void __convertFromD3D11Texture2DKHR(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst)
+{
D3D11_TEXTURE2D_DESC desc = { 0 };
pD3D11Texture2D->GetDesc(&desc);
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
}
#endif
+}
+#endif
+
+#if defined(HAVE_OPENCL_D3D11_NV)
+static void __convertFromD3D11Texture2DNV(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst)
+{
+ D3D11_TEXTURE2D_DESC desc = { 0 };
+ pD3D11Texture2D->GetDesc(&desc);
+
+ int textureType = getTypeFromDXGI_FORMAT(desc.Format);
+ CV_Assert(textureType >= 0);
+ // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying!
+ dst.create(Size(desc.Width, desc.Height), textureType);
+ UMat u = dst.getUMat();
+
+ // TODO Add support for roi
+ CV_Assert(u.offset == 0);
+ CV_Assert(u.isContinuous());
+
+ cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ);
+
+ using namespace cv::ocl;
+ Context& ctx = Context::getDefault();
+ cl_context context = (cl_context)ctx.ptr();
+
+ cl_int status = 0;
+ cl_mem clImage = 0;
+
+ clImage = clCreateFromD3D11Texture2DNV(context, CL_MEM_READ_ONLY, pD3D11Texture2D, 0, &status);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DNV failed");
+
+#ifdef HAVE_DIRECTX_NV12
+ cl_mem clImageUV = 0;
+ if(DXGI_FORMAT_NV12 == desc.Format)
+ {
+ clImageUV = clCreateFromD3D11Texture2DNV(context, CL_MEM_READ_ONLY, pD3D11Texture2D, 1, &status);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromD3D11Texture2DNV failed");
+ }
+#endif
+
+ cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr();
+ status = clEnqueueAcquireD3D11ObjectsNV(q, 1, &clImage, 0, NULL, NULL);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsNV failed");
+
+#ifdef HAVE_DIRECTX_NV12
+ if (DXGI_FORMAT::DXGI_FORMAT_NV12 == desc.Format)
+ {
+ status = clEnqueueAcquireD3D11ObjectsNV(q, 1, &clImageUV, 0, NULL, NULL);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D11ObjectsNV failed");
+
+ if (!ocl::ocl_convert_nv12_to_bgr(clImage, clImageUV, clBuffer, (int)u.step[0], u.cols, u.rows))
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: ocl_convert_nv12_to_bgr failed");
+
+ status = clEnqueueReleaseD3D11ObjectsNV(q, 1, &clImageUV, 0, NULL, NULL);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsNV failed");
+ }
+ else
+#endif
+ {
+ size_t offset = 0; // TODO
+ size_t origin[3] = { 0, 0, 0 };
+ size_t region[3] = { (size_t)u.cols, (size_t)u.rows, 1 };
+
+ status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, origin, region, offset, 0, NULL, NULL);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed");
+ }
+
+ status = clEnqueueReleaseD3D11ObjectsNV(q, 1, &clImage, 0, NULL, NULL);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseD3D11ObjectsNV failed");
+
+ status = clFinish(q); // TODO Use events
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed");
+
+ status = clReleaseMemObject(clImage); // TODO RAII
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+
+#ifdef HAVE_DIRECTX_NV12
+ if(DXGI_FORMAT_NV12 == desc.Format)
+ {
+ status = clReleaseMemObject(clImageUV);
+ if (status != CL_SUCCESS)
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed");
+ }
+#endif
+}
+#endif
+
+void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D)
+{
+ CV_UNUSED(src); CV_UNUSED(pD3D11Texture2D);
+#if !defined(HAVE_DIRECTX)
+ NO_DIRECTX_SUPPORT_ERROR;
+#elif !defined(HAVE_OPENCL)
+ NO_OPENCL_SUPPORT_ERROR;
#else
- // TODO memcpy
+
+ bool useCLNVEXT = __OpenCLinitializeD3D11();
+ if(!useCLNVEXT){
+ __convertToD3D11Texture2DKHR(src,pD3D11Texture2D);
+ }
+#ifdef HAVE_OPENCL_D3D11_NV
+ else
+ {
+ __convertToD3D11Texture2DNV(src,pD3D11Texture2D);
+ }
+#endif
+#endif
+}
+
+void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst)
+{
+ CV_UNUSED(pD3D11Texture2D); CV_UNUSED(dst);
+#if !defined(HAVE_DIRECTX)
+ NO_DIRECTX_SUPPORT_ERROR;
+#elif !defined(HAVE_OPENCL)
NO_OPENCL_SUPPORT_ERROR;
+#else
+
+ bool useCLNVEXT = __OpenCLinitializeD3D11();
+ if(!useCLNVEXT){
+ __convertFromD3D11Texture2DKHR(pD3D11Texture2D,dst);
+ }
+#ifdef HAVE_OPENCL_D3D11_NV
+ else
+ {
+ __convertFromD3D11Texture2DNV(pD3D11Texture2D,dst);
+ }
+#endif
#endif
}
#include "opencv2/core/opencl/runtime/opencl_core.hpp"
#include <CL/cl_d3d11.h>
+#ifdef HAVE_OPENCL_D3D11_NV
+#include <CL/cl_d3d11_ext.h>
+#endif
#include <CL/cl_d3d10.h>
#include <CL/cl_dx9_media_sharing.h>
#endif // HAVE_OPENCL
// Holds the data dimension.
int n;
- // Stores real/imag part of a complex division.
- double cdivr, cdivi;
-
// Pointer to internal memory.
double *d, *e, *ort;
double **V, **H;
return arr;
}
- void cdiv(double xr, double xi, double yr, double yi) {
+ static void complex_div(double xr, double xi, double yr, double yi, double& cdivr, double& cdivi) {
double r, dv;
+ CV_DbgAssert(std::abs(yr) + std::abs(yi) > 0.0);
if (std::abs(yr) > std::abs(yi)) {
r = yi / yr;
dv = yr + r * yi;
// Fortran subroutine in EISPACK.
// Initialize
- int nn = this->n;
+ const int max_iters_count = 1000 * this->n;
+
+ const int nn = this->n; CV_Assert(nn > 0);
int n1 = nn - 1;
- int low = 0;
- int high = nn - 1;
- double eps = std::pow(2.0, -52.0);
+ const int low = 0;
+ const int high = nn - 1;
+ const double eps = std::numeric_limits<double>::epsilon();
double exshift = 0.0;
- double p = 0, q = 0, r = 0, s = 0, z = 0, t, w, x, y;
// Store roots isolated by balanc and compute matrix norm
double norm = 0.0;
for (int i = 0; i < nn; i++) {
+#if 0 // 'if' condition is always false
if (i < low || i > high) {
d[i] = H[i][i];
e[i] = 0.0;
}
+#endif
for (int j = std::max(i - 1, 0); j < nn; j++) {
- norm = norm + std::abs(H[i][j]);
+ norm += std::abs(H[i][j]);
}
}
if (norm < FLT_EPSILON) {
break;
}
- s = std::abs(H[l - 1][l - 1]) + std::abs(H[l][l]);
+ double s = std::abs(H[l - 1][l - 1]) + std::abs(H[l][l]);
if (s == 0.0) {
s = norm;
}
}
// Check for convergence
- // One root found
-
if (l == n1) {
+ // One root found
H[n1][n1] = H[n1][n1] + exshift;
d[n1] = H[n1][n1];
e[n1] = 0.0;
n1--;
iter = 0;
- // Two roots found
-
} else if (l == n1 - 1) {
- w = H[n1][n1 - 1] * H[n1 - 1][n1];
- p = (H[n1 - 1][n1 - 1] - H[n1][n1]) / 2.0;
- q = p * p + w;
- z = std::sqrt(std::abs(q));
+ // Two roots found
+ double w = H[n1][n1 - 1] * H[n1 - 1][n1];
+ double p = (H[n1 - 1][n1 - 1] - H[n1][n1]) * 0.5;
+ double q = p * p + w;
+ double z = std::sqrt(std::abs(q));
H[n1][n1] = H[n1][n1] + exshift;
H[n1 - 1][n1 - 1] = H[n1 - 1][n1 - 1] + exshift;
- x = H[n1][n1];
-
- // Real pair
+ double x = H[n1][n1];
if (q >= 0) {
+ // Real pair
if (p >= 0) {
z = p + z;
} else {
e[n1 - 1] = 0.0;
e[n1] = 0.0;
x = H[n1][n1 - 1];
- s = std::abs(x) + std::abs(z);
+ double s = std::abs(x) + std::abs(z);
p = x / s;
q = z / s;
- r = std::sqrt(p * p + q * q);
+ double r = std::sqrt(p * p + q * q);
p = p / r;
q = q / r;
V[i][n1] = q * V[i][n1] - p * z;
}
- // Complex pair
-
} else {
+ // Complex pair
d[n1 - 1] = x + p;
d[n1] = x + p;
e[n1 - 1] = z;
n1 = n1 - 2;
iter = 0;
- // No convergence yet
-
} else {
+ // No convergence yet
// Form shift
-
- x = H[n1][n1];
- y = 0.0;
- w = 0.0;
+ double x = H[n1][n1];
+ double y = 0.0;
+ double w = 0.0;
if (l < n1) {
y = H[n1 - 1][n1 - 1];
w = H[n1][n1 - 1] * H[n1 - 1][n1];
}
// Wilkinson's original ad hoc shift
-
if (iter == 10) {
exshift += x;
for (int i = low; i <= n1; i++) {
H[i][i] -= x;
}
- s = std::abs(H[n1][n1 - 1]) + std::abs(H[n1 - 1][n1 - 2]);
+ double s = std::abs(H[n1][n1 - 1]) + std::abs(H[n1 - 1][n1 - 2]);
x = y = 0.75 * s;
w = -0.4375 * s * s;
}
// MATLAB's new ad hoc shift
if (iter == 30) {
- s = (y - x) / 2.0;
+ double s = (y - x) * 0.5;
s = s * s + w;
if (s > 0) {
s = std::sqrt(s);
if (y < x) {
s = -s;
}
- s = x - w / ((y - x) / 2.0 + s);
+ s = x - w / ((y - x) * 0.5 + s);
for (int i = low; i <= n1; i++) {
H[i][i] -= s;
}
}
}
- iter = iter + 1; // (Could check iteration count here.)
+ iter = iter + 1;
+ if (iter > max_iters_count)
+ CV_Error(Error::StsNoConv, "Algorithm doesn't converge (complex eigen values?)");
+
+ double p = std::numeric_limits<double>::quiet_NaN();
+ double q = std::numeric_limits<double>::quiet_NaN();
+ double r = std::numeric_limits<double>::quiet_NaN();
// Look for two consecutive small sub-diagonal elements
int m = n1 - 2;
while (m >= l) {
- z = H[m][m];
+ double z = H[m][m];
r = x - z;
- s = y - z;
+ double s = y - z;
p = (r * s - w) / H[m + 1][m] + H[m][m + 1];
q = H[m + 1][m + 1] - z - r - s;
r = H[m + 2][m + 1];
// Double QR step involving rows l:n and columns m:n
for (int k = m; k < n1; k++) {
+
bool notlast = (k != n1 - 1);
if (k != m) {
p = H[k][k - 1];
if (x == 0.0) {
break;
}
- s = std::sqrt(p * p + q * q + r * r);
+ double s = std::sqrt(p * p + q * q + r * r);
if (p < 0) {
s = -s;
}
p = p + s;
x = p / s;
y = q / s;
- z = r / s;
+ double z = r / s;
q = q / p;
r = r / p;
p = p + r * H[k + 2][j];
H[k + 2][j] = H[k + 2][j] - p * z;
}
- H[k][j] = H[k][j] - p * x;
- H[k + 1][j] = H[k + 1][j] - p * y;
+ H[k][j] -= p * x;
+ H[k + 1][j] -= p * y;
}
// Column modification
p = p + z * H[i][k + 2];
H[i][k + 2] = H[i][k + 2] - p * r;
}
- H[i][k] = H[i][k] - p;
- H[i][k + 1] = H[i][k + 1] - p * q;
+ H[i][k] -= p;
+ H[i][k + 1] -= p * q;
}
// Accumulate transformations
}
for (n1 = nn - 1; n1 >= 0; n1--) {
- p = d[n1];
- q = e[n1];
-
- // Real vector
+ double p = d[n1];
+ double q = e[n1];
if (q == 0) {
+ // Real vector
+ double z = std::numeric_limits<double>::quiet_NaN();
+ double s = std::numeric_limits<double>::quiet_NaN();
+
int l = n1;
H[n1][n1] = 1.0;
for (int i = n1 - 1; i >= 0; i--) {
- w = H[i][i] - p;
- r = 0.0;
+ double w = H[i][i] - p;
+ double r = 0.0;
for (int j = l; j <= n1; j++) {
r = r + H[i][j] * H[j][n1];
}
} else {
H[i][n1] = -r / (eps * norm);
}
-
- // Solve real equations
-
} else {
- x = H[i][i + 1];
- y = H[i + 1][i];
+ // Solve real equations
+ CV_DbgAssert(!cvIsNaN(z));
+ double x = H[i][i + 1];
+ double y = H[i + 1][i];
q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
- t = (x * s - z * r) / q;
+ double t = (x * s - z * r) / q;
H[i][n1] = t;
if (std::abs(x) > std::abs(z)) {
H[i + 1][n1] = (-r - w * t) / x;
} else {
+ CV_DbgAssert(z != 0.0);
H[i + 1][n1] = (-s - y * t) / z;
}
}
// Overflow control
-
- t = std::abs(H[i][n1]);
+ double t = std::abs(H[i][n1]);
if ((eps * t) * t > 1) {
+ double inv_t = 1.0 / t;
for (int j = i; j <= n1; j++) {
- H[j][n1] = H[j][n1] / t;
+ H[j][n1] *= inv_t;
}
}
}
}
- // Complex vector
} else if (q < 0) {
+ // Complex vector
+ double z = std::numeric_limits<double>::quiet_NaN();
+ double r = std::numeric_limits<double>::quiet_NaN();
+ double s = std::numeric_limits<double>::quiet_NaN();
+
int l = n1 - 1;
// Last vector component imaginary so matrix is triangular
H[n1 - 1][n1 - 1] = q / H[n1][n1 - 1];
H[n1 - 1][n1] = -(H[n1][n1] - p) / H[n1][n1 - 1];
} else {
- cdiv(0.0, -H[n1 - 1][n1], H[n1 - 1][n1 - 1] - p, q);
- H[n1 - 1][n1 - 1] = cdivr;
- H[n1 - 1][n1] = cdivi;
+ complex_div(
+ 0.0, -H[n1 - 1][n1],
+ H[n1 - 1][n1 - 1] - p, q,
+ H[n1 - 1][n1 - 1], H[n1 - 1][n1]
+ );
}
H[n1][n1 - 1] = 0.0;
H[n1][n1] = 1.0;
ra = ra + H[i][j] * H[j][n1 - 1];
sa = sa + H[i][j] * H[j][n1];
}
- w = H[i][i] - p;
+ double w = H[i][i] - p;
if (e[i] < 0.0) {
z = w;
} else {
l = i;
if (e[i] == 0) {
- cdiv(-ra, -sa, w, q);
- H[i][n1 - 1] = cdivr;
- H[i][n1] = cdivi;
+ complex_div(
+ -ra, -sa,
+ w, q,
+ H[i][n1 - 1], H[i][n1]
+ );
} else {
-
// Solve complex equations
- x = H[i][i + 1];
- y = H[i + 1][i];
+ double x = H[i][i + 1];
+ double y = H[i + 1][i];
vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
vi = (d[i] - p) * 2.0 * q;
if (vr == 0.0 && vi == 0.0) {
vr = eps * norm * (std::abs(w) + std::abs(q) + std::abs(x)
+ std::abs(y) + std::abs(z));
}
- cdiv(x * r - z * ra + q * sa,
- x * s - z * sa - q * ra, vr, vi);
- H[i][n1 - 1] = cdivr;
- H[i][n1] = cdivi;
+ complex_div(
+ x * r - z * ra + q * sa, x * s - z * sa - q * ra,
+ vr, vi,
+ H[i][n1 - 1], H[i][n1]);
if (std::abs(x) > (std::abs(z) + std::abs(q))) {
H[i + 1][n1 - 1] = (-ra - w * H[i][n1 - 1] + q
* H[i][n1]) / x;
H[i + 1][n1] = (-sa - w * H[i][n1] - q * H[i][n1
- 1]) / x;
} else {
- cdiv(-r - y * H[i][n1 - 1], -s - y * H[i][n1], z,
- q);
- H[i + 1][n1 - 1] = cdivr;
- H[i + 1][n1] = cdivi;
+ complex_div(
+ -r - y * H[i][n1 - 1], -s - y * H[i][n1],
+ z, q,
+ H[i + 1][n1 - 1], H[i + 1][n1]);
}
}
// Overflow control
- t = std::max(std::abs(H[i][n1 - 1]), std::abs(H[i][n1]));
+ double t = std::max(std::abs(H[i][n1 - 1]), std::abs(H[i][n1]));
if ((eps * t) * t > 1) {
for (int j = i; j <= n1; j++) {
H[j][n1 - 1] = H[j][n1 - 1] / t;
// Vectors of isolated roots
+#if 0 // 'if' condition is always false
for (int i = 0; i < nn; i++) {
if (i < low || i > high) {
for (int j = i; j < nn; j++) {
}
}
}
+#endif
// Back transformation to get eigenvectors of original matrix
for (int j = nn - 1; j >= low; j--) {
for (int i = low; i <= high; i++) {
- z = 0.0;
+ double z = 0.0;
for (int k = low; k <= std::min(j, high); k++) {
- z = z + V[i][k] * H[k][j];
+ z += V[i][k] * H[k][j];
}
V[i][j] = z;
}
// Releases all internal working memory.
void release() {
// releases the working data
- delete[] d;
- delete[] e;
- delete[] ort;
+ delete[] d; d = NULL;
+ delete[] e; e = NULL;
+ delete[] ort; ort = NULL;
for (int i = 0; i < n; i++) {
- delete[] H[i];
- delete[] V[i];
+ if (H) delete[] H[i];
+ if (V) delete[] V[i];
}
- delete[] H;
- delete[] V;
+ delete[] H; H = NULL;
+ delete[] V; V = NULL;
}
// Computes the Eigenvalue Decomposition for a matrix given in H.
d = alloc_1d<double> (n);
e = alloc_1d<double> (n);
ort = alloc_1d<double> (n);
- try {
+ {
// Reduce to Hessenberg form.
orthes();
// Reduce Hessenberg to real Schur form.
// Deallocate the memory by releasing all internal working data.
release();
}
- catch (...)
- {
- release();
- throw;
- }
}
public:
// given in src. This function is a port of the EigenvalueSolver in JAMA,
// which has been released to public domain by The MathWorks and the
// National Institute of Standards and Technology (NIST).
- EigenvalueDecomposition(InputArray src, bool fallbackSymmetric = true) {
- compute(src, fallbackSymmetric);
+ EigenvalueDecomposition() :
+ n(0),
+ d(NULL), e(NULL), ort(NULL),
+ V(NULL), H(NULL)
+ {
+ // nothing
}
// This function computes the Eigenvalue Decomposition for a general matrix
// given in src. This function is a port of the EigenvalueSolver in JAMA,
// which has been released to public domain by The MathWorks and the
// National Institute of Standards and Technology (NIST).
- void compute(InputArray src, bool fallbackSymmetric)
+ void compute(InputArray src, bool fallbackSymmetric = true)
{
CV_INSTRUMENT_REGION();
}
}
- ~EigenvalueDecomposition() {}
+ ~EigenvalueDecomposition() { release(); }
// Returns the eigenvalues of the Eigenvalue Decomposition.
Mat eigenvalues() const { return _eigenvalues; }
else
src64f = src;
- EigenvalueDecomposition eigensystem(src64f, false);
+ EigenvalueDecomposition eigensystem;
+ eigensystem.compute(src64f, false);
// EigenvalueDecomposition returns transposed and non-sorted eigenvalues
std::vector<double> eigenvalues64f;
// M = inv(Sw)*Sb
Mat M;
gemm(Swi, Sb, 1.0, Mat(), 0.0, M);
- EigenvalueDecomposition es(M);
+ EigenvalueDecomposition es;
+ es.compute(M);
_eigenvalues = es.eigenvalues();
_eigenvectors = es.eigenvectors();
// reshape eigenvalues, so they are stored by column
--- /dev/null
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
+// Copyright (C) 2014-2015, Itseez Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "precomp.hpp"
+#include "opencl_kernels_core.hpp"
+#include "opencv2/core/opencl/runtime/opencl_clamdblas.hpp"
+#include "opencv2/core/opencl/runtime/opencl_core.hpp"
+#include "intel_gpu_gemm.inl.hpp"
+
+#include "matmul.simd.hpp"
+#include "matmul.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
+
+namespace cv
+{
+
+/****************************************************************************************\
+* GEMM *
+\****************************************************************************************/
+
+#ifdef HAVE_CLAMDBLAS
+
+static bool ocl_gemm_amdblas( InputArray matA, InputArray matB, double alpha,
+ InputArray matC, double beta, OutputArray matD, int flags )
+{
+ int type = matA.type(), esz = CV_ELEM_SIZE(type);
+ bool haveC = matC.kind() != cv::_InputArray::NONE;
+ Size sizeA = matA.size(), sizeB = matB.size(), sizeC = haveC ? matC.size() : Size(0, 0);
+ bool atrans = (flags & GEMM_1_T) != 0, btrans = (flags & GEMM_2_T) != 0, ctrans = (flags & GEMM_3_T) != 0;
+
+ if (atrans)
+ sizeA = Size(sizeA.height, sizeA.width);
+ if (btrans)
+ sizeB = Size(sizeB.height, sizeB.width);
+ if (haveC && ctrans)
+ sizeC = Size(sizeC.height, sizeC.width);
+
+ Size sizeD(sizeB.width, sizeA.height);
+
+ CV_Assert( matB.type() == type && (!haveC || matC.type() == type) );
+ CV_Assert( sizeA.width == sizeB.height && (!haveC || sizeC == sizeD) );
+
+ matD.create(sizeD, type);
+ if ( matA.offset() % esz != 0 || matA.step() % esz != 0 ||
+ matB.offset() % esz != 0 || matB.step() % esz != 0 ||
+ (haveC && (matC.offset() % esz != 0 || matC.step() % esz != 0)) )
+ return false;
+
+ UMat A = matA.getUMat(), B = matB.getUMat(), D = matD.getUMat();
+ if (!ocl::internal::isCLBuffer(A) || !ocl::internal::isCLBuffer(B) || !ocl::internal::isCLBuffer(D))
+ {
+ return false;
+ }
+ if (haveC)
+ {
+ UMat C = matC.getUMat();
+ if (!ocl::internal::isCLBuffer(C))
+ return false;
+ }
+ if (haveC)
+ ctrans ? transpose(matC, D) : matC.copyTo(D);
+ else
+ D.setTo(Scalar::all(0));
+
+ int M = sizeD.height, N = sizeD.width, K = sizeA.width;
+ int lda = (int)A.step / esz, ldb = (int)B.step / esz, ldc = (int)D.step / esz;
+ int offa = (int)A.offset / esz, offb = (int)B.offset / esz, offc = (int)D.offset / esz;
+
+ cl_command_queue clq = (cl_command_queue)ocl::Queue::getDefault().ptr();
+ clAmdBlasTranspose transA = atrans ? clAmdBlasTrans : clAmdBlasNoTrans;
+ clAmdBlasTranspose transB = btrans ? clAmdBlasTrans : clAmdBlasNoTrans;
+ clAmdBlasOrder order = clAmdBlasRowMajor;
+ clAmdBlasStatus status = clAmdBlasSuccess;
+
+ if (type == CV_32FC1)
+ status = clAmdBlasSgemmEx(order, transA, transB, M, N, K,
+ (cl_float)alpha, (const cl_mem)A.handle(ACCESS_READ), offa, lda,
+ (const cl_mem)B.handle(ACCESS_READ), offb, ldb,
+ (cl_float)beta, (cl_mem)D.handle(ACCESS_RW), offc, ldc,
+ 1, &clq, 0, NULL, NULL);
+ else if (type == CV_64FC1)
+ status = clAmdBlasDgemmEx(order, transA, transB, M, N, K,
+ alpha, (const cl_mem)A.handle(ACCESS_READ), offa, lda,
+ (const cl_mem)B.handle(ACCESS_READ), offb, ldb,
+ beta, (cl_mem)D.handle(ACCESS_RW), offc, ldc,
+ 1, &clq, 0, NULL, NULL);
+ else if (type == CV_32FC2)
+ {
+ cl_float2 alpha_2 = { { (cl_float)alpha, 0 } };
+ cl_float2 beta_2 = { { (cl_float)beta, 0 } };
+ status = clAmdBlasCgemmEx(order, transA, transB, M, N, K,
+ alpha_2, (const cl_mem)A.handle(ACCESS_READ), offa, lda,
+ (const cl_mem)B.handle(ACCESS_READ), offb, ldb,
+ beta_2, (cl_mem)D.handle(ACCESS_RW), offc, ldc,
+ 1, &clq, 0, NULL, NULL);
+ }
+ else if (type == CV_64FC2)
+ {
+ cl_double2 alpha_2 = { { alpha, 0 } };
+ cl_double2 beta_2 = { { beta, 0 } };
+ status = clAmdBlasZgemmEx(order, transA, transB, M, N, K,
+ alpha_2, (const cl_mem)A.handle(ACCESS_READ), offa, lda,
+ (const cl_mem)B.handle(ACCESS_READ), offb, ldb,
+ beta_2, (cl_mem)D.handle(ACCESS_RW), offc, ldc,
+ 1, &clq, 0, NULL, NULL);
+ }
+ else
+ CV_Error(Error::StsUnsupportedFormat, "");
+
+ return status == clAmdBlasSuccess;
+}
+
+#endif
+
+#ifdef HAVE_OPENCL
+static bool ocl_gemm( InputArray matA, InputArray matB, double alpha,
+ InputArray matC, double beta, OutputArray matD, int flags )
+{
+ int depth = matA.depth(), cn = matA.channels();
+ int type = CV_MAKETYPE(depth, cn);
+
+ CV_Assert_N( type == matB.type(), (type == CV_32FC1 || type == CV_64FC1 || type == CV_32FC2 || type == CV_64FC2) );
+
+ const ocl::Device & dev = ocl::Device::getDefault();
+ bool doubleSupport = dev.doubleFPConfig() > 0;
+
+ if (!doubleSupport && depth == CV_64F)
+ return false;
+
+ bool haveC = matC.kind() != cv::_InputArray::NONE;
+ Size sizeA = matA.size(), sizeB = matB.size(), sizeC = haveC ? matC.size() : Size(0, 0);
+ bool atrans = (flags & GEMM_1_T) != 0, btrans = (flags & GEMM_2_T) != 0, ctrans = (flags & GEMM_3_T) != 0;
+
+ CV_Assert( !haveC || matC.type() == type );
+
+ Size sizeD(((btrans)? sizeB.height : sizeB.width),
+ ((atrans)? sizeA.width : sizeA.height));
+ matD.create(sizeD, type);
+
+ UMat A = matA.getUMat(), B = matB.getUMat(), D = matD.getUMat();
+
+
+ if (!dev.intelSubgroupsSupport() || (depth == CV_64F) || cn != 1)
+ {
+ String opts;
+
+ if (atrans)
+ sizeA = Size(sizeA.height, sizeA.width);
+ if (btrans)
+ sizeB = Size(sizeB.height, sizeB.width);
+ if (haveC && ctrans)
+ sizeC = Size(sizeC.height, sizeC.width);
+
+ CV_Assert( sizeA.width == sizeB.height && (!haveC || sizeC == sizeD) );
+
+ int max_wg_size = (int)dev.maxWorkGroupSize();
+ int block_size = (max_wg_size / (32*cn) < 32) ? (max_wg_size / (16*cn) < 16) ? (max_wg_size / (8*cn) < 8) ? 1 : 8 : 16 : 32;
+
+ if (atrans)
+ A = A.t();
+
+ if (btrans)
+ B = B.t();
+
+ if (haveC)
+ ctrans ? transpose(matC, D) : matC.copyTo(D);
+
+ int vectorWidths[] = { 4, 4, 2, 2, 1, 4, cn, -1 };
+ int kercn = ocl::checkOptimalVectorWidth(vectorWidths, B, D);
+
+ opts += format(" -D T=%s -D T1=%s -D WT=%s -D cn=%d -D kercn=%d -D LOCAL_SIZE=%d%s%s%s",
+ ocl::typeToStr(type), ocl::typeToStr(depth), ocl::typeToStr(CV_MAKETYPE(depth, kercn)),
+ cn, kercn, block_size,
+ (sizeA.width % block_size !=0) ? " -D NO_MULT" : "",
+ haveC ? " -D HAVE_C" : "",
+ doubleSupport ? " -D DOUBLE_SUPPORT" : "");
+
+ ocl::Kernel k("gemm", cv::ocl::core::gemm_oclsrc, opts);
+ if (k.empty())
+ return false;
+
+ if (depth == CV_64F)
+ k.args(ocl::KernelArg::ReadOnlyNoSize(A),
+ ocl::KernelArg::ReadOnlyNoSize(B, cn, kercn),
+ ocl::KernelArg::ReadWrite(D, cn, kercn),
+ sizeA.width, alpha, beta);
+ else
+ k.args(ocl::KernelArg::ReadOnlyNoSize(A),
+ ocl::KernelArg::ReadOnlyNoSize(B, cn, kercn),
+ ocl::KernelArg::ReadWrite(D, cn, kercn),
+ sizeA.width, (float)alpha, (float)beta);
+
+ size_t globalsize[2] = { (size_t)sizeD.width * cn / kercn, (size_t)sizeD.height};
+ size_t localsize[2] = { (size_t)block_size, (size_t)block_size};
+
+ return k.run(2, globalsize, block_size!=1 ? localsize : NULL, false);
+ }
+ else
+ {
+ if (haveC && beta != 0.0)
+ {
+ ctrans ? transpose(matC, D) : matC.copyTo(D);
+ }
+ else
+ {
+ beta = 0.0;
+ }
+
+ return intel_gpu_gemm(A, sizeA,
+ B, sizeB,
+ D, sizeD,
+ alpha,
+ beta,
+ atrans, btrans);
+ }
+}
+#endif
+
+
+namespace hal {
+
+void gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step,
+ float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step,
+ int m_a, int n_a, int n_d, int flags)
+{
+ CV_INSTRUMENT_REGION();
+ CALL_HAL(gemm32f, cv_hal_gemm32f, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags)
+#ifdef CV_GEMM_BASELINE_ONLY
+ CV_CPU_CALL_BASELINE(gemm32f, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags));
+#else
+ CV_CPU_DISPATCH(gemm32f, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags),
+ CV_CPU_DISPATCH_MODES_ALL);
+#endif
+}
+
+void gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step,
+ double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step,
+ int m_a, int n_a, int n_d, int flags)
+{
+ CV_INSTRUMENT_REGION();
+ CALL_HAL(gemm64f, cv_hal_gemm64f, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags)
+#ifdef CV_GEMM_BASELINE_ONLY
+ CV_CPU_CALL_BASELINE(gemm64f, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags));
+#else
+ CV_CPU_DISPATCH(gemm64f, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags),
+ CV_CPU_DISPATCH_MODES_ALL);
+#endif
+}
+
+void gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step,
+ float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step,
+ int m_a, int n_a, int n_d, int flags)
+{
+ CV_INSTRUMENT_REGION();
+ CALL_HAL(gemm32fc, cv_hal_gemm32fc, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags)
+#ifdef CV_GEMM_BASELINE_ONLY
+ CV_CPU_CALL_BASELINE(gemm32fc, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags));
+#else
+ CV_CPU_DISPATCH(gemm32fc, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags),
+ CV_CPU_DISPATCH_MODES_ALL);
+#endif
+}
+
+void gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step,
+ double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step,
+ int m_a, int n_a, int n_d, int flags)
+{
+ CV_INSTRUMENT_REGION();
+ CALL_HAL(gemm64fc, cv_hal_gemm64fc, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags)
+#ifdef CV_GEMM_BASELINE_ONLY
+ CV_CPU_CALL_BASELINE(gemm64fc, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags));
+#else
+ CV_CPU_DISPATCH(gemm64fc, (src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags),
+ CV_CPU_DISPATCH_MODES_ALL);
+#endif
+}
+
+} // namespace hal
+
+void gemm(InputArray matA, InputArray matB, double alpha,
+ InputArray matC, double beta, OutputArray _matD, int flags)
+{
+#ifdef HAVE_CLAMDBLAS
+ CV_OCL_RUN(ocl::haveAmdBlas() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2 && _matD.isUMat() &&
+ matA.cols() > 20 && matA.rows() > 20 && matB.cols() > 20, // since it works incorrect for small sizes
+ ocl_gemm_amdblas(matA, matB, alpha, matC, beta, _matD, flags))
+#endif
+
+#ifdef HAVE_OPENCL
+ CV_OCL_RUN(_matD.isUMat() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2,
+ ocl_gemm(matA, matB, alpha, matC, beta, _matD, flags))
+#endif
+
+ Mat A = matA.getMat(), B = matB.getMat(), C = beta != 0.0 ? matC.getMat() : Mat();
+ Size a_size = A.size(), d_size;
+ int len = 0, type = A.type();
+
+ CV_Assert_N( type == B.type(), (type == CV_32FC1 || type == CV_64FC1 || type == CV_32FC2 || type == CV_64FC2) );
+
+ switch( flags & (GEMM_1_T|GEMM_2_T) )
+ {
+ case 0:
+ d_size = Size( B.cols, a_size.height );
+ len = B.rows;
+ CV_Assert( a_size.width == len );
+ break;
+ case 1:
+ d_size = Size( B.cols, a_size.width );
+ len = B.rows;
+ CV_Assert( a_size.height == len );
+ break;
+ case 2:
+ d_size = Size( B.rows, a_size.height );
+ len = B.cols;
+ CV_Assert( a_size.width == len );
+ break;
+ case 3:
+ d_size = Size( B.rows, a_size.width );
+ len = B.cols;
+ CV_Assert( a_size.height == len );
+ break;
+ }
+
+ if( !C.empty() )
+ {
+ CV_Assert_N( C.type() == type,
+ (((flags&GEMM_3_T) == 0 && C.rows == d_size.height && C.cols == d_size.width) ||
+ ((flags&GEMM_3_T) != 0 && C.rows == d_size.width && C.cols == d_size.height)));
+ }
+
+ _matD.create( d_size.height, d_size.width, type );
+ Mat D = _matD.getMat();
+ if( (flags & GEMM_3_T) != 0 && C.data == D.data )
+ {
+ transpose( C, C );
+ flags &= ~GEMM_3_T;
+ }
+
+ Mat *DProxyPtr = &D, DProxy;
+ if( D.data == A.data || D.data == B.data )
+ {
+ DProxy = Mat(d_size.height, d_size.width, D.type());
+ DProxyPtr = &DProxy;
+ }
+
+ if( type == CV_32FC1 )
+ hal::gemm32f(A.ptr<float>(), A.step, B.ptr<float>(), B.step, static_cast<float>(alpha),
+ C.ptr<float>(), C.step, static_cast<float>(beta),
+ DProxyPtr->ptr<float>(), DProxyPtr->step,
+ a_size.height, a_size.width, DProxyPtr->cols, flags);
+ else if( type == CV_64FC1 )
+ hal::gemm64f(A.ptr<double>(), A.step, B.ptr<double>(), B.step, alpha,
+ C.ptr<double>(), C.step, beta,
+ DProxyPtr->ptr<double>(), DProxyPtr->step,
+ a_size.height, a_size.width, DProxyPtr->cols, flags);
+ else if( type == CV_32FC2 )
+ hal::gemm32fc(A.ptr<float>(), A.step, B.ptr<float>(), B.step, static_cast<float>(alpha),
+ C.ptr<float>(), C.step, static_cast<float>(beta),
+ DProxyPtr->ptr<float>(), DProxyPtr->step,
+ a_size.height, a_size.width, DProxyPtr->cols, flags);
+ else
+ {
+ CV_Assert( type == CV_64FC2 );
+ hal::gemm64fc(A.ptr<double>(), A.step, B.ptr<double>(), B.step, alpha,
+ C.ptr<double>(), C.step, beta,
+ D.ptr<double>(), D.step,
+ a_size.height, a_size.width, DProxyPtr->cols, flags);
+ }
+
+ if(DProxyPtr != &D)
+ DProxyPtr->copyTo(D);
+}
+
+
+
+/****************************************************************************************\
+* Transform *
+\****************************************************************************************/
+
+static TransformFunc getTransformFunc(int depth)
+{
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(getTransformFunc, (depth),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+static TransformFunc getDiagTransformFunc(int depth)
+{
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(getDiagTransformFunc, (depth),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void transform(InputArray _src, OutputArray _dst, InputArray _mtx)
+{
+ CV_INSTRUMENT_REGION();
+
+ Mat src = _src.getMat(), m = _mtx.getMat();
+ int depth = src.depth(), scn = src.channels(), dcn = m.rows;
+ CV_Assert( scn == m.cols || scn + 1 == m.cols );
+ bool isDiag = false;
+
+ _dst.create( src.size(), CV_MAKETYPE(depth, dcn) );
+ Mat dst = _dst.getMat();
+
+ int mtype = depth == CV_32S || depth == CV_64F ? CV_64F : CV_32F;
+ AutoBuffer<double> _mbuf;
+ double* mbuf;
+
+ if( !m.isContinuous() || m.type() != mtype || m.cols != scn + 1 )
+ {
+ _mbuf.allocate(dcn*(scn+1));
+ mbuf = _mbuf.data();
+ Mat tmp(dcn, scn+1, mtype, mbuf);
+ memset(tmp.ptr(), 0, tmp.total()*tmp.elemSize());
+ if( m.cols == scn+1 )
+ m.convertTo(tmp, mtype);
+ else
+ {
+ Mat tmppart = tmp.colRange(0, m.cols);
+ m.convertTo(tmppart, mtype);
+ }
+ m = tmp;
+ }
+ else
+ mbuf = m.ptr<double>();
+
+ if( scn == dcn )
+ {
+ int i, j;
+ double eps = mtype == CV_32F ? FLT_EPSILON : DBL_EPSILON;
+
+ if( scn == 1 )
+ {
+ double alpha, beta;
+ if( mtype == CV_32F )
+ alpha = m.at<float>(0), beta = m.at<float>(1);
+ else
+ alpha = m.at<double>(0), beta = m.at<double>(1);
+ src.convertTo(dst, dst.type(), alpha, beta);
+ return;
+ }
+
+ for( i = 0, isDiag = true; isDiag && i < scn; i++ )
+ {
+ for( j = 0; isDiag && j < scn; j++ )
+ {
+ double v = mtype == CV_32F ? m.at<float>(i, j) : m.at<double>(i, j);
+ if( i != j && fabs(v) > eps )
+ isDiag = false;
+ }
+ }
+ }
+
+ TransformFunc func = isDiag ? getDiagTransformFunc(depth): getTransformFunc(depth);
+ CV_Assert( func != 0 );
+
+ const Mat* arrays[] = {&src, &dst, 0};
+ uchar* ptrs[2] = {};
+ NAryMatIterator it(arrays, ptrs);
+ size_t i, total = it.size;
+
+ for( i = 0; i < it.nplanes; i++, ++it )
+ func( ptrs[0], ptrs[1], (uchar*)mbuf, (int)total, scn, dcn );
+}
+
+
+
+/****************************************************************************************\
+* Perspective Transform *
+\****************************************************************************************/
+
+static TransformFunc getPerspectiveTransform(int depth)
+{
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(getPerspectiveTransform, (depth),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void perspectiveTransform(InputArray _src, OutputArray _dst, InputArray _mtx)
+{
+ CV_INSTRUMENT_REGION();
+
+ Mat src = _src.getMat(), m = _mtx.getMat();
+ int depth = src.depth(), scn = src.channels(), dcn = m.rows-1;
+ CV_Assert( scn + 1 == m.cols );
+ CV_Assert( depth == CV_32F || depth == CV_64F );
+
+ _dst.create( src.size(), CV_MAKETYPE(depth, dcn) );
+ Mat dst = _dst.getMat();
+
+ const int mtype = CV_64F;
+ AutoBuffer<double> _mbuf;
+ double* mbuf = m.ptr<double>();
+
+ if( !m.isContinuous() || m.type() != mtype )
+ {
+ _mbuf.allocate((dcn+1)*(scn+1));
+ mbuf = _mbuf.data();
+ Mat tmp(dcn+1, scn+1, mtype, mbuf);
+ m.convertTo(tmp, mtype);
+ m = tmp;
+ }
+
+ TransformFunc func = getPerspectiveTransform(depth);
+ CV_Assert( func != 0 );
+
+ const Mat* arrays[] = {&src, &dst, 0};
+ uchar* ptrs[2] = {};
+ NAryMatIterator it(arrays, ptrs);
+ size_t i, total = it.size;
+
+ for( i = 0; i < it.nplanes; i++, ++it )
+ func( ptrs[0], ptrs[1], (uchar*)mbuf, (int)total, scn, dcn );
+}
+
+/****************************************************************************************\
+* ScaleAdd *
+\****************************************************************************************/
+
+#ifdef HAVE_OPENCL
+
+static bool ocl_scaleAdd( InputArray _src1, double alpha, InputArray _src2, OutputArray _dst, int type )
+{
+ const ocl::Device & d = ocl::Device::getDefault();
+
+ bool doubleSupport = d.doubleFPConfig() > 0;
+ Size size = _src1.size();
+ int depth = CV_MAT_DEPTH(type);
+ if ( (!doubleSupport && depth == CV_64F) || size != _src2.size() )
+ return false;
+
+ _dst.create(size, type);
+ int cn = CV_MAT_CN(type), wdepth = std::max(depth, CV_32F);
+ int kercn = ocl::predictOptimalVectorWidthMax(_src1, _src2, _dst),
+ rowsPerWI = d.isIntel() ? 4 : 1;
+
+ char cvt[2][50];
+ ocl::Kernel k("KF", ocl::core::arithm_oclsrc,
+ format("-D OP_SCALE_ADD -D BINARY_OP -D dstT=%s -D DEPTH_dst=%d -D workT=%s -D convertToWT1=%s"
+ " -D srcT1=dstT -D srcT2=dstT -D convertToDT=%s -D workT1=%s"
+ " -D wdepth=%d%s -D rowsPerWI=%d",
+ ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)), depth,
+ ocl::typeToStr(CV_MAKE_TYPE(wdepth, kercn)),
+ ocl::convertTypeStr(depth, wdepth, kercn, cvt[0]),
+ ocl::convertTypeStr(wdepth, depth, kercn, cvt[1]),
+ ocl::typeToStr(wdepth), wdepth,
+ doubleSupport ? " -D DOUBLE_SUPPORT" : "", rowsPerWI));
+ if (k.empty())
+ return false;
+
+ UMat src1 = _src1.getUMat(), src2 = _src2.getUMat(), dst = _dst.getUMat();
+
+ ocl::KernelArg src1arg = ocl::KernelArg::ReadOnlyNoSize(src1),
+ src2arg = ocl::KernelArg::ReadOnlyNoSize(src2),
+ dstarg = ocl::KernelArg::WriteOnly(dst, cn, kercn);
+
+ if (wdepth == CV_32F)
+ k.args(src1arg, src2arg, dstarg, (float)alpha);
+ else
+ k.args(src1arg, src2arg, dstarg, alpha);
+
+ size_t globalsize[2] = { (size_t)dst.cols * cn / kercn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI };
+ return k.run(2, globalsize, NULL, false);
+}
+
+#endif
+
+static ScaleAddFunc getScaleAddFunc(int depth)
+{
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(getScaleAddFunc, (depth),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void scaleAdd(InputArray _src1, double alpha, InputArray _src2, OutputArray _dst)
+{
+ CV_INSTRUMENT_REGION();
+
+ int type = _src1.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
+ CV_Assert( type == _src2.type() );
+
+ CV_OCL_RUN(_src1.dims() <= 2 && _src2.dims() <= 2 && _dst.isUMat(),
+ ocl_scaleAdd(_src1, alpha, _src2, _dst, type))
+
+ if( depth < CV_32F )
+ {
+ addWeighted(_src1, alpha, _src2, 1, 0, _dst, depth);
+ return;
+ }
+
+ Mat src1 = _src1.getMat(), src2 = _src2.getMat();
+ CV_Assert(src1.size == src2.size);
+
+ _dst.create(src1.dims, src1.size, type);
+ Mat dst = _dst.getMat();
+
+ float falpha = (float)alpha;
+ void* palpha = depth == CV_32F ? (void*)&falpha : (void*)α
+
+ ScaleAddFunc func = getScaleAddFunc(depth);
+ CV_Assert(func);
+
+ if (src1.isContinuous() && src2.isContinuous() && dst.isContinuous())
+ {
+ size_t len = src1.total()*cn;
+ func(src1.ptr(), src2.ptr(), dst.ptr(), (int)len, palpha);
+ return;
+ }
+
+ const Mat* arrays[] = {&src1, &src2, &dst, 0};
+ uchar* ptrs[3] = {};
+ NAryMatIterator it(arrays, ptrs);
+ size_t i, len = it.size*cn;
+
+ for( i = 0; i < it.nplanes; i++, ++it )
+ func( ptrs[0], ptrs[1], ptrs[2], (int)len, palpha );
+}
+
+/****************************************************************************************\
+* Covariation Matrix *
+\****************************************************************************************/
+
+void calcCovarMatrix( const Mat* data, int nsamples, Mat& covar, Mat& _mean, int flags, int ctype )
+{
+ CV_INSTRUMENT_REGION();
+
+ CV_Assert_N( data, nsamples > 0 );
+ Size size = data[0].size();
+ int sz = size.width * size.height, esz = (int)data[0].elemSize();
+ int type = data[0].type();
+ Mat mean;
+ ctype = std::max(std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), _mean.depth()), CV_32F);
+
+ if( (flags & CV_COVAR_USE_AVG) != 0 )
+ {
+ CV_Assert( _mean.size() == size );
+ if( _mean.isContinuous() && _mean.type() == ctype )
+ mean = _mean.reshape(1, 1);
+ else
+ {
+ _mean.convertTo(mean, ctype);
+ mean = mean.reshape(1, 1);
+ }
+ }
+
+ Mat _data(nsamples, sz, type);
+
+ for( int i = 0; i < nsamples; i++ )
+ {
+ CV_Assert_N( data[i].size() == size, data[i].type() == type );
+ if( data[i].isContinuous() )
+ memcpy( _data.ptr(i), data[i].ptr(), sz*esz );
+ else
+ {
+ Mat dataRow(size.height, size.width, type, _data.ptr(i));
+ data[i].copyTo(dataRow);
+ }
+ }
+
+ calcCovarMatrix( _data, covar, mean, (flags & ~(CV_COVAR_ROWS|CV_COVAR_COLS)) | CV_COVAR_ROWS, ctype );
+ if( (flags & CV_COVAR_USE_AVG) == 0 )
+ _mean = mean.reshape(1, size.height);
+}
+
+void calcCovarMatrix( InputArray _src, OutputArray _covar, InputOutputArray _mean, int flags, int ctype )
+{
+ CV_INSTRUMENT_REGION();
+
+ if(_src.kind() == _InputArray::STD_VECTOR_MAT || _src.kind() == _InputArray::STD_ARRAY_MAT)
+ {
+ std::vector<cv::Mat> src;
+ _src.getMatVector(src);
+
+ CV_Assert( src.size() > 0 );
+
+ Size size = src[0].size();
+ int type = src[0].type();
+
+ ctype = std::max(std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), _mean.depth()), CV_32F);
+
+ Mat _data(static_cast<int>(src.size()), size.area(), type);
+
+ int i = 0;
+ for(std::vector<cv::Mat>::iterator each = src.begin(); each != src.end(); ++each, ++i )
+ {
+ CV_Assert_N( (*each).size() == size, (*each).type() == type );
+ Mat dataRow(size.height, size.width, type, _data.ptr(i));
+ (*each).copyTo(dataRow);
+ }
+
+ Mat mean;
+ if( (flags & CV_COVAR_USE_AVG) != 0 )
+ {
+ CV_Assert( _mean.size() == size );
+
+ if( mean.type() != ctype )
+ {
+ mean = _mean.getMat();
+ _mean.create(mean.size(), ctype);
+ Mat tmp = _mean.getMat();
+ mean.convertTo(tmp, ctype);
+ mean = tmp;
+ }
+
+ mean = _mean.getMat().reshape(1, 1);
+ }
+
+ calcCovarMatrix( _data, _covar, mean, (flags & ~(CV_COVAR_ROWS|CV_COVAR_COLS)) | CV_COVAR_ROWS, ctype );
+
+ if( (flags & CV_COVAR_USE_AVG) == 0 )
+ {
+ mean = mean.reshape(1, size.height);
+ mean.copyTo(_mean);
+ }
+ return;
+ }
+
+ Mat data = _src.getMat(), mean;
+ CV_Assert( ((flags & CV_COVAR_ROWS) != 0) ^ ((flags & CV_COVAR_COLS) != 0) );
+ bool takeRows = (flags & CV_COVAR_ROWS) != 0;
+ int type = data.type();
+ int nsamples = takeRows ? data.rows : data.cols;
+ CV_Assert( nsamples > 0 );
+ Size size = takeRows ? Size(data.cols, 1) : Size(1, data.rows);
+
+ if( (flags & CV_COVAR_USE_AVG) != 0 )
+ {
+ mean = _mean.getMat();
+ ctype = std::max(std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), mean.depth()), CV_32F);
+ CV_Assert( mean.size() == size );
+ if( mean.type() != ctype )
+ {
+ _mean.create(mean.size(), ctype);
+ Mat tmp = _mean.getMat();
+ mean.convertTo(tmp, ctype);
+ mean = tmp;
+ }
+ }
+ else
+ {
+ ctype = std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), CV_32F);
+ reduce( _src, _mean, takeRows ? 0 : 1, CV_REDUCE_AVG, ctype );
+ mean = _mean.getMat();
+ }
+
+ mulTransposed( data, _covar, ((flags & CV_COVAR_NORMAL) == 0) ^ takeRows,
+ mean, (flags & CV_COVAR_SCALE) != 0 ? 1./nsamples : 1, ctype );
+}
+
+
+
+/****************************************************************************************\
+* Mahalanobis *
+\****************************************************************************************/
+
+static MahalanobisImplFunc getMahalanobisImplFunc(int depth)
+{
+#ifdef CV_MAHALANOBIS_BASELINE_ONLY
+ CV_CPU_CALL_BASELINE(getMahalanobisImplFunc, (depth));
+#else
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(getMahalanobisImplFunc, (depth),
+ CV_CPU_DISPATCH_MODES_ALL);
+#endif
+}
+
+
+double Mahalanobis(InputArray _v1, InputArray _v2, InputArray _icovar)
+{
+ CV_INSTRUMENT_REGION();
+
+ Mat v1 = _v1.getMat(), v2 = _v2.getMat(), icovar = _icovar.getMat();
+ int type = v1.type(), depth = v1.depth();
+ Size sz = v1.size();
+ int len = sz.width*sz.height*v1.channels();
+ AutoBuffer<double> buf(len);
+
+ CV_Assert_N( type == v2.type(), type == icovar.type(),
+ sz == v2.size(), len == icovar.rows && len == icovar.cols );
+
+ sz.width *= v1.channels();
+ if( v1.isContinuous() && v2.isContinuous() )
+ {
+ sz.width *= sz.height;
+ sz.height = 1;
+ }
+
+ MahalanobisImplFunc func = getMahalanobisImplFunc(depth);
+ CV_Assert(func);
+
+ double result = func(v1, v2, icovar, buf.data(), len);
+ return std::sqrt(result);
+}
+
+
+
+/****************************************************************************************\
+* MulTransposed *
+\****************************************************************************************/
+
+static MulTransposedFunc getMulTransposedFunc(int stype, int dtype, bool ata)
+{
+#ifdef CV_MULTRANSPOSED_BASELINE_ONLY
+ CV_CPU_CALL_BASELINE(getMulTransposedFunc, (stype, dtype, ata));
+#else
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(getMulTransposedFunc, (stype, dtype, ata),
+ CV_CPU_DISPATCH_MODES_ALL);
+#endif
+}
+
+void mulTransposed(InputArray _src, OutputArray _dst, bool ata,
+ InputArray _delta, double scale, int dtype)
+{
+ CV_INSTRUMENT_REGION();
+
+ Mat src = _src.getMat(), delta = _delta.getMat();
+ const int gemm_level = 100; // boundary above which GEMM is faster.
+ int stype = src.type();
+ dtype = std::max(std::max(CV_MAT_DEPTH(dtype >= 0 ? dtype : stype), delta.depth()), CV_32F);
+ CV_Assert( src.channels() == 1 );
+
+ if( !delta.empty() )
+ {
+ CV_Assert_N( delta.channels() == 1,
+ (delta.rows == src.rows || delta.rows == 1),
+ (delta.cols == src.cols || delta.cols == 1));
+ if( delta.type() != dtype )
+ delta.convertTo(delta, dtype);
+ }
+
+ int dsize = ata ? src.cols : src.rows;
+ _dst.create( dsize, dsize, dtype );
+ Mat dst = _dst.getMat();
+
+ if( src.data == dst.data || (stype == dtype &&
+ (dst.cols >= gemm_level && dst.rows >= gemm_level &&
+ src.cols >= gemm_level && src.rows >= gemm_level)))
+ {
+ Mat src2;
+ const Mat* tsrc = &src;
+ if( !delta.empty() )
+ {
+ if( delta.size() == src.size() )
+ subtract( src, delta, src2 );
+ else
+ {
+ repeat(delta, src.rows/delta.rows, src.cols/delta.cols, src2);
+ subtract( src, src2, src2 );
+ }
+ tsrc = &src2;
+ }
+ gemm( *tsrc, *tsrc, scale, Mat(), 0, dst, ata ? GEMM_1_T : GEMM_2_T );
+ }
+ else
+ {
+ MulTransposedFunc func = getMulTransposedFunc(stype, dtype, ata);
+ if( !func )
+ CV_Error( CV_StsUnsupportedFormat, "" );
+
+ func( src, dst, delta, scale );
+ completeSymm( dst, false );
+ }
+}
+
+/****************************************************************************************\
+* Dot Product *
+\****************************************************************************************/
+
+static double dotProd_8u(const uchar* src1, const uchar* src2, int len)
+{
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(dotProd_8u, (src1, src2, len),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+static double dotProd_8s(const schar* src1, const schar* src2, int len)
+{
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(dotProd_8s, (src1, src2, len),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+static double dotProd_16u(const ushort* src1, const ushort* src2, int len)
+{
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(dotProd_16u, (src1, src2, len),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+static double dotProd_16s(const short* src1, const short* src2, int len)
+{
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(dotProd_16s, (src1, src2, len),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+static double dotProd_32s(const int* src1, const int* src2, int len)
+{
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(dotProd_32s, (src1, src2, len),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+static double dotProd_32f(const float* src1, const float* src2, int len)
+{
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(dotProd_32f, (src1, src2, len),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+static double dotProd_64f(const double* src1, const double* src2, int len)
+{
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(dotProd_64f, (src1, src2, len),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+typedef double (*DotProdFunc)(const uchar* src1, const uchar* src2, int len);
+
+static DotProdFunc getDotProdFunc(int depth)
+{
+ static DotProdFunc dotProdTab[] =
+ {
+ (DotProdFunc)GET_OPTIMIZED(dotProd_8u), (DotProdFunc)GET_OPTIMIZED(dotProd_8s),
+ (DotProdFunc)dotProd_16u, (DotProdFunc)dotProd_16s,
+ (DotProdFunc)dotProd_32s, (DotProdFunc)GET_OPTIMIZED(dotProd_32f),
+ (DotProdFunc)dotProd_64f, 0
+ };
+
+ return dotProdTab[depth];
+}
+
+double Mat::dot(InputArray _mat) const
+{
+ CV_INSTRUMENT_REGION();
+
+ Mat mat = _mat.getMat();
+ int cn = channels();
+ DotProdFunc func = getDotProdFunc(depth());
+ CV_Assert_N( mat.type() == type(), mat.size == size, func != 0 );
+
+ if( isContinuous() && mat.isContinuous() )
+ {
+ size_t len = total()*cn;
+ if( len == (size_t)(int)len )
+ return func(data, mat.data, (int)len);
+ }
+
+ const Mat* arrays[] = {this, &mat, 0};
+ uchar* ptrs[2] = {};
+ NAryMatIterator it(arrays, ptrs);
+ int len = (int)(it.size*cn);
+ double r = 0;
+
+ for( size_t i = 0; i < it.nplanes; i++, ++it )
+ r += func( ptrs[0], ptrs[1], len );
+
+ return r;
+}
+
+} // namespace cv::
+
+/****************************************************************************************\
+* Earlier API *
+\****************************************************************************************/
+
+CV_IMPL void cvGEMM( const CvArr* Aarr, const CvArr* Barr, double alpha,
+ const CvArr* Carr, double beta, CvArr* Darr, int flags )
+{
+ cv::Mat A = cv::cvarrToMat(Aarr), B = cv::cvarrToMat(Barr);
+ cv::Mat C, D = cv::cvarrToMat(Darr);
+
+ if( Carr )
+ C = cv::cvarrToMat(Carr);
+
+ CV_Assert_N( (D.rows == ((flags & CV_GEMM_A_T) == 0 ? A.rows : A.cols)),
+ (D.cols == ((flags & CV_GEMM_B_T) == 0 ? B.cols : B.rows)),
+ D.type() == A.type() );
+
+ gemm( A, B, alpha, C, beta, D, flags );
+}
+
+
+CV_IMPL void
+cvTransform( const CvArr* srcarr, CvArr* dstarr,
+ const CvMat* transmat, const CvMat* shiftvec )
+{
+ cv::Mat m = cv::cvarrToMat(transmat), src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
+
+ if( shiftvec )
+ {
+ cv::Mat v = cv::cvarrToMat(shiftvec).reshape(1,m.rows),
+ _m(m.rows, m.cols + 1, m.type()), m1 = _m.colRange(0,m.cols), v1 = _m.col(m.cols);
+ m.convertTo(m1, m1.type());
+ v.convertTo(v1, v1.type());
+ m = _m;
+ }
+
+ CV_Assert_N( dst.depth() == src.depth(), dst.channels() == m.rows );
+ cv::transform( src, dst, m );
+}
+
+
+CV_IMPL void
+cvPerspectiveTransform( const CvArr* srcarr, CvArr* dstarr, const CvMat* mat )
+{
+ cv::Mat m = cv::cvarrToMat(mat), src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
+
+ CV_Assert_N( dst.type() == src.type(), dst.channels() == m.rows-1 );
+ cv::perspectiveTransform( src, dst, m );
+}
+
+
+CV_IMPL void cvScaleAdd( const CvArr* srcarr1, CvScalar scale,
+ const CvArr* srcarr2, CvArr* dstarr )
+{
+ cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr);
+
+ CV_Assert_N( src1.size == dst.size, src1.type() == dst.type() );
+ cv::scaleAdd( src1, scale.val[0], cv::cvarrToMat(srcarr2), dst );
+}
+
+
+CV_IMPL void
+cvCalcCovarMatrix( const CvArr** vecarr, int count,
+ CvArr* covarr, CvArr* avgarr, int flags )
+{
+ cv::Mat cov0 = cv::cvarrToMat(covarr), cov = cov0, mean0, mean;
+ CV_Assert_N( vecarr != 0, count >= 1 );
+
+ if( avgarr )
+ mean = mean0 = cv::cvarrToMat(avgarr);
+
+ if( (flags & CV_COVAR_COLS) != 0 || (flags & CV_COVAR_ROWS) != 0 )
+ {
+
+ cv::Mat data = cv::cvarrToMat(vecarr[0]);
+ cv::calcCovarMatrix( data, cov, mean, flags, cov.type() );
+ }
+ else
+ {
+ std::vector<cv::Mat> data(count);
+ for( int i = 0; i < count; i++ )
+ data[i] = cv::cvarrToMat(vecarr[i]);
+ cv::calcCovarMatrix( &data[0], count, cov, mean, flags, cov.type() );
+ }
+
+ if( mean.data != mean0.data && mean0.data )
+ mean.convertTo(mean0, mean0.type());
+
+ if( cov.data != cov0.data )
+ cov.convertTo(cov0, cov0.type());
+}
+
+
+CV_IMPL double
+cvMahalanobis( const CvArr* srcAarr, const CvArr* srcBarr, const CvArr* matarr )
+{
+ return cv::Mahalanobis(cv::cvarrToMat(srcAarr),
+ cv::cvarrToMat(srcBarr), cv::cvarrToMat(matarr));
+}
+
+CV_IMPL void
+cvMulTransposed( const CvArr* srcarr, CvArr* dstarr,
+ int order, const CvArr* deltaarr, double scale )
+{
+ cv::Mat src = cv::cvarrToMat(srcarr), dst0 = cv::cvarrToMat(dstarr), dst = dst0, delta;
+ if( deltaarr )
+ delta = cv::cvarrToMat(deltaarr);
+ cv::mulTransposed( src, dst, order != 0, delta, scale, dst.type());
+ if( dst.data != dst0.data )
+ dst.convertTo(dst0, dst0.type());
+}
+
+CV_IMPL double cvDotProduct( const CvArr* srcAarr, const CvArr* srcBarr )
+{
+ return cv::cvarrToMat(srcAarr).dot(cv::cvarrToMat(srcBarr));
+}
+
+
+CV_IMPL void
+cvCalcPCA( const CvArr* data_arr, CvArr* avg_arr, CvArr* eigenvals, CvArr* eigenvects, int flags )
+{
+ cv::Mat data = cv::cvarrToMat(data_arr), mean0 = cv::cvarrToMat(avg_arr);
+ cv::Mat evals0 = cv::cvarrToMat(eigenvals), evects0 = cv::cvarrToMat(eigenvects);
+ cv::Mat mean = mean0, evals = evals0, evects = evects0;
+
+ cv::PCA pca;
+ pca.mean = mean;
+ pca.eigenvalues = evals;
+ pca.eigenvectors = evects;
+
+ pca(data, (flags & CV_PCA_USE_AVG) ? mean : cv::Mat(),
+ flags, !evals.empty() ? evals.rows + evals.cols - 1 : 0);
+
+ if( pca.mean.size() == mean.size() )
+ pca.mean.convertTo( mean, mean.type() );
+ else
+ {
+ cv::Mat temp; pca.mean.convertTo( temp, mean.type() );
+ transpose( temp, mean );
+ }
+
+ evals = pca.eigenvalues;
+ evects = pca.eigenvectors;
+ int ecount0 = evals0.cols + evals0.rows - 1;
+ int ecount = evals.cols + evals.rows - 1;
+
+ CV_Assert_N( (evals0.cols == 1 || evals0.rows == 1),
+ ecount0 <= ecount,
+ evects0.cols == evects.cols,
+ evects0.rows == ecount0 );
+
+ cv::Mat temp = evals0;
+ if( evals.rows == 1 )
+ evals.colRange(0, ecount0).convertTo(temp, evals0.type());
+ else
+ evals.rowRange(0, ecount0).convertTo(temp, evals0.type());
+ if( temp.data != evals0.data )
+ transpose(temp, evals0);
+ evects.rowRange(0, ecount0).convertTo( evects0, evects0.type() );
+
+ // otherwise some datatype's or size's were incorrect, so the output arrays have been reallocated
+ CV_Assert( mean0.data == mean.data );
+}
+
+
+CV_IMPL void
+cvProjectPCA( const CvArr* data_arr, const CvArr* avg_arr,
+ const CvArr* eigenvects, CvArr* result_arr )
+{
+ cv::Mat data = cv::cvarrToMat(data_arr), mean = cv::cvarrToMat(avg_arr);
+ cv::Mat evects = cv::cvarrToMat(eigenvects), dst0 = cv::cvarrToMat(result_arr), dst = dst0;
+
+ cv::PCA pca;
+ pca.mean = mean;
+ int n;
+ if( mean.rows == 1 )
+ {
+ CV_Assert_N(dst.cols <= evects.rows, dst.rows == data.rows);
+ n = dst.cols;
+ }
+ else
+ {
+ CV_Assert_N(dst.rows <= evects.rows, dst.cols == data.cols);
+ n = dst.rows;
+ }
+ pca.eigenvectors = evects.rowRange(0, n);
+
+ cv::Mat result = pca.project(data);
+ if( result.cols != dst.cols )
+ result = result.reshape(1, 1);
+ result.convertTo(dst, dst.type());
+
+ CV_Assert(dst0.data == dst.data);
+}
+
+
+CV_IMPL void
+cvBackProjectPCA( const CvArr* proj_arr, const CvArr* avg_arr,
+ const CvArr* eigenvects, CvArr* result_arr )
+{
+ cv::Mat data = cv::cvarrToMat(proj_arr), mean = cv::cvarrToMat(avg_arr);
+ cv::Mat evects = cv::cvarrToMat(eigenvects), dst0 = cv::cvarrToMat(result_arr), dst = dst0;
+
+ cv::PCA pca;
+ pca.mean = mean;
+ int n;
+ if( mean.rows == 1 )
+ {
+ CV_Assert_N(data.cols <= evects.rows, dst.rows == data.rows);
+ n = data.cols;
+ }
+ else
+ {
+ CV_Assert_N(data.rows <= evects.rows, dst.cols == data.cols);
+ n = data.rows;
+ }
+ pca.eigenvectors = evects.rowRange(0, n);
+
+ cv::Mat result = pca.backProject(data);
+ result.convertTo(dst, dst.type());
+
+ CV_Assert(dst0.data == dst.data);
+}
+
+/* End of file. */
//
//M*/
-#include <sstream>
#include "precomp.hpp"
-#include "opencl_kernels_core.hpp"
-#include "opencv2/core/opencl/runtime/opencl_clamdblas.hpp"
-#include "opencv2/core/opencl/runtime/opencl_core.hpp"
-#include "intel_gpu_gemm.inl.hpp"
-namespace cv
-{
+#ifdef HAVE_LAPACK
+#define CV_GEMM_BASELINE_ONLY
+#endif
+#define CV_MAHALANOBIS_BASELINE_ONLY
+#define CV_MULTRANSPOSED_BASELINE_ONLY
+
+namespace cv {
+
+// forward declarations
+typedef void (*TransformFunc)(const uchar* src, uchar* dst, const uchar* m, int len, int scn, int dcn);
+typedef void (*ScaleAddFunc)(const uchar* src1, const uchar* src2, uchar* dst, int len, const void* alpha);
+typedef void (*MulTransposedFunc)(const Mat& src, const/*preallocated*/ Mat& dst, const Mat& delta, double scale);
+typedef double (*MahalanobisImplFunc)(const Mat& v1, const Mat& v2, const Mat& icovar, double *diff_buffer /*[len]*/, int len /*=v1.total()*/);
+
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+
+// forward declarations
+
+void gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step,
+ float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step,
+ int m_a, int n_a, int n_d, int flags);
+void gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step,
+ double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step,
+ int m_a, int n_a, int n_d, int flags);
+void gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step,
+ float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step,
+ int m_a, int n_a, int n_d, int flags);
+void gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step,
+ double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step,
+ int m_a, int n_a, int n_d, int flags);
+
+TransformFunc getTransformFunc(int depth);
+TransformFunc getDiagTransformFunc(int depth);
+TransformFunc getPerspectiveTransform(int depth);
+
+ScaleAddFunc getScaleAddFunc(int depth);
+
+MahalanobisImplFunc getMahalanobisImplFunc(int depth);
+
+MulTransposedFunc getMulTransposedFunc(int stype, int dtype, bool ata);
+
+double dotProd_8u(const uchar* src1, const uchar* src2, int len);
+double dotProd_8s(const schar* src1, const schar* src2, int len);
+double dotProd_16u(const ushort* src1, const ushort* src2, int len);
+double dotProd_16s(const short* src1, const short* src2, int len);
+double dotProd_32s(const int* src1, const int* src2, int len);
+double dotProd_32f(const float* src1, const float* src2, int len);
+double dotProd_64f(const double* src1, const double* src2, int len);
+
+
+
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
+#if !defined(CV_GEMM_BASELINE_ONLY) || defined(CV_CPU_BASELINE_MODE)
/****************************************************************************************\
* GEMM *
\****************************************************************************************/
GEMMStore(c_data, c_step, d_buf, d_buf_step, d_data, d_step, d_size, alpha, beta, flags);
}
-#ifdef HAVE_CLAMDBLAS
-
-static bool ocl_gemm_amdblas( InputArray matA, InputArray matB, double alpha,
- InputArray matC, double beta, OutputArray matD, int flags )
-{
- int type = matA.type(), esz = CV_ELEM_SIZE(type);
- bool haveC = matC.kind() != cv::_InputArray::NONE;
- Size sizeA = matA.size(), sizeB = matB.size(), sizeC = haveC ? matC.size() : Size(0, 0);
- bool atrans = (flags & GEMM_1_T) != 0, btrans = (flags & GEMM_2_T) != 0, ctrans = (flags & GEMM_3_T) != 0;
-
- if (atrans)
- sizeA = Size(sizeA.height, sizeA.width);
- if (btrans)
- sizeB = Size(sizeB.height, sizeB.width);
- if (haveC && ctrans)
- sizeC = Size(sizeC.height, sizeC.width);
-
- Size sizeD(sizeB.width, sizeA.height);
-
- CV_Assert( matB.type() == type && (!haveC || matC.type() == type) );
- CV_Assert( sizeA.width == sizeB.height && (!haveC || sizeC == sizeD) );
-
- matD.create(sizeD, type);
- if ( matA.offset() % esz != 0 || matA.step() % esz != 0 ||
- matB.offset() % esz != 0 || matB.step() % esz != 0 ||
- (haveC && (matC.offset() % esz != 0 || matC.step() % esz != 0)) )
- return false;
-
- UMat A = matA.getUMat(), B = matB.getUMat(), D = matD.getUMat();
- if (!ocl::internal::isCLBuffer(A) || !ocl::internal::isCLBuffer(B) || !ocl::internal::isCLBuffer(D))
- {
- return false;
- }
- if (haveC)
- {
- UMat C = matC.getUMat();
- if (!ocl::internal::isCLBuffer(C))
- return false;
- }
- if (haveC)
- ctrans ? transpose(matC, D) : matC.copyTo(D);
- else
- D.setTo(Scalar::all(0));
-
- int M = sizeD.height, N = sizeD.width, K = sizeA.width;
- int lda = (int)A.step / esz, ldb = (int)B.step / esz, ldc = (int)D.step / esz;
- int offa = (int)A.offset / esz, offb = (int)B.offset / esz, offc = (int)D.offset / esz;
-
- cl_command_queue clq = (cl_command_queue)ocl::Queue::getDefault().ptr();
- clAmdBlasTranspose transA = atrans ? clAmdBlasTrans : clAmdBlasNoTrans;
- clAmdBlasTranspose transB = btrans ? clAmdBlasTrans : clAmdBlasNoTrans;
- clAmdBlasOrder order = clAmdBlasRowMajor;
- clAmdBlasStatus status = clAmdBlasSuccess;
-
- if (type == CV_32FC1)
- status = clAmdBlasSgemmEx(order, transA, transB, M, N, K,
- (cl_float)alpha, (const cl_mem)A.handle(ACCESS_READ), offa, lda,
- (const cl_mem)B.handle(ACCESS_READ), offb, ldb,
- (cl_float)beta, (cl_mem)D.handle(ACCESS_RW), offc, ldc,
- 1, &clq, 0, NULL, NULL);
- else if (type == CV_64FC1)
- status = clAmdBlasDgemmEx(order, transA, transB, M, N, K,
- alpha, (const cl_mem)A.handle(ACCESS_READ), offa, lda,
- (const cl_mem)B.handle(ACCESS_READ), offb, ldb,
- beta, (cl_mem)D.handle(ACCESS_RW), offc, ldc,
- 1, &clq, 0, NULL, NULL);
- else if (type == CV_32FC2)
- {
- cl_float2 alpha_2 = { { (cl_float)alpha, 0 } };
- cl_float2 beta_2 = { { (cl_float)beta, 0 } };
- status = clAmdBlasCgemmEx(order, transA, transB, M, N, K,
- alpha_2, (const cl_mem)A.handle(ACCESS_READ), offa, lda,
- (const cl_mem)B.handle(ACCESS_READ), offb, ldb,
- beta_2, (cl_mem)D.handle(ACCESS_RW), offc, ldc,
- 1, &clq, 0, NULL, NULL);
- }
- else if (type == CV_64FC2)
- {
- cl_double2 alpha_2 = { { alpha, 0 } };
- cl_double2 beta_2 = { { beta, 0 } };
- status = clAmdBlasZgemmEx(order, transA, transB, M, N, K,
- alpha_2, (const cl_mem)A.handle(ACCESS_READ), offa, lda,
- (const cl_mem)B.handle(ACCESS_READ), offb, ldb,
- beta_2, (cl_mem)D.handle(ACCESS_RW), offc, ldc,
- 1, &clq, 0, NULL, NULL);
- }
- else
- CV_Error(Error::StsUnsupportedFormat, "");
-
- return status == clAmdBlasSuccess;
-}
-
-#endif
-
-#ifdef HAVE_OPENCL
-static bool ocl_gemm( InputArray matA, InputArray matB, double alpha,
- InputArray matC, double beta, OutputArray matD, int flags )
-{
- int depth = matA.depth(), cn = matA.channels();
- int type = CV_MAKETYPE(depth, cn);
-
- CV_Assert_N( type == matB.type(), (type == CV_32FC1 || type == CV_64FC1 || type == CV_32FC2 || type == CV_64FC2) );
-
- const ocl::Device & dev = ocl::Device::getDefault();
- bool doubleSupport = dev.doubleFPConfig() > 0;
-
- if (!doubleSupport && depth == CV_64F)
- return false;
-
- bool haveC = matC.kind() != cv::_InputArray::NONE;
- Size sizeA = matA.size(), sizeB = matB.size(), sizeC = haveC ? matC.size() : Size(0, 0);
- bool atrans = (flags & GEMM_1_T) != 0, btrans = (flags & GEMM_2_T) != 0, ctrans = (flags & GEMM_3_T) != 0;
-
- CV_Assert( !haveC || matC.type() == type );
-
- Size sizeD(((btrans)? sizeB.height : sizeB.width),
- ((atrans)? sizeA.width : sizeA.height));
- matD.create(sizeD, type);
-
- UMat A = matA.getUMat(), B = matB.getUMat(), D = matD.getUMat();
-
-
- if (!dev.intelSubgroupsSupport() || (depth == CV_64F) || cn != 1)
- {
- String opts;
-
- if (atrans)
- sizeA = Size(sizeA.height, sizeA.width);
- if (btrans)
- sizeB = Size(sizeB.height, sizeB.width);
- if (haveC && ctrans)
- sizeC = Size(sizeC.height, sizeC.width);
-
- CV_Assert( sizeA.width == sizeB.height && (!haveC || sizeC == sizeD) );
-
- int max_wg_size = (int)dev.maxWorkGroupSize();
- int block_size = (max_wg_size / (32*cn) < 32) ? (max_wg_size / (16*cn) < 16) ? (max_wg_size / (8*cn) < 8) ? 1 : 8 : 16 : 32;
-
- if (atrans)
- A = A.t();
-
- if (btrans)
- B = B.t();
-
- if (haveC)
- ctrans ? transpose(matC, D) : matC.copyTo(D);
-
- int vectorWidths[] = { 4, 4, 2, 2, 1, 4, cn, -1 };
- int kercn = ocl::checkOptimalVectorWidth(vectorWidths, B, D);
-
- opts += format(" -D T=%s -D T1=%s -D WT=%s -D cn=%d -D kercn=%d -D LOCAL_SIZE=%d%s%s%s",
- ocl::typeToStr(type), ocl::typeToStr(depth), ocl::typeToStr(CV_MAKETYPE(depth, kercn)),
- cn, kercn, block_size,
- (sizeA.width % block_size !=0) ? " -D NO_MULT" : "",
- haveC ? " -D HAVE_C" : "",
- doubleSupport ? " -D DOUBLE_SUPPORT" : "");
-
- ocl::Kernel k("gemm", cv::ocl::core::gemm_oclsrc, opts);
- if (k.empty())
- return false;
-
- if (depth == CV_64F)
- k.args(ocl::KernelArg::ReadOnlyNoSize(A),
- ocl::KernelArg::ReadOnlyNoSize(B, cn, kercn),
- ocl::KernelArg::ReadWrite(D, cn, kercn),
- sizeA.width, alpha, beta);
- else
- k.args(ocl::KernelArg::ReadOnlyNoSize(A),
- ocl::KernelArg::ReadOnlyNoSize(B, cn, kercn),
- ocl::KernelArg::ReadWrite(D, cn, kercn),
- sizeA.width, (float)alpha, (float)beta);
-
- size_t globalsize[2] = { (size_t)sizeD.width * cn / kercn, (size_t)sizeD.height};
- size_t localsize[2] = { (size_t)block_size, (size_t)block_size};
-
- return k.run(2, globalsize, block_size!=1 ? localsize : NULL, false);
- }
- else
- {
- if (haveC && beta != 0.0)
- {
- ctrans ? transpose(matC, D) : matC.copyTo(D);
- }
- else
- {
- beta = 0.0;
- }
-
- return intel_gpu_gemm(A, sizeA,
- B, sizeB,
- D, sizeD,
- alpha,
- beta,
- atrans, btrans);
- }
-}
-#endif
-
static void gemmImpl( Mat A, Mat B, double alpha,
Mat C, double beta, Mat D, int flags )
{
gemmImpl(A, B, alpha, C, beta, D, flags);
}
-}
-
-void cv::hal::gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step,
- float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step,
- int m_a, int n_a, int n_d, int flags)
+void gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step,
+ float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step,
+ int m_a, int n_a, int n_d, int flags)
{
-
- CALL_HAL(gemm32f, cv_hal_gemm32f, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags)
+ CV_INSTRUMENT_REGION();
callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_32F);
}
-void cv::hal::gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step,
- double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step,
- int m_a, int n_a, int n_d, int flags)
+void gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step,
+ double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step,
+ int m_a, int n_a, int n_d, int flags)
{
- CALL_HAL(gemm64f, cv_hal_gemm64f, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags)
+ CV_INSTRUMENT_REGION();
callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_64F);
}
-CV_EXPORTS void cv::hal::gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step,
- float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step,
- int m_a, int n_a, int n_d, int flags)
+void gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step,
+ float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step,
+ int m_a, int n_a, int n_d, int flags)
{
- CALL_HAL(gemm32fc, cv_hal_gemm32fc, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags)
+ CV_INSTRUMENT_REGION();
callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_32FC2);
}
-CV_EXPORTS void cv::hal::gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step,
- double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step,
- int m_a, int n_a, int n_d, int flags)
+void gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step,
+ double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step,
+ int m_a, int n_a, int n_d, int flags)
{
- CALL_HAL(gemm64fc, cv_hal_gemm64fc, src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags)
+ CV_INSTRUMENT_REGION();
callGemmImpl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m_a, n_a, n_d, flags, CV_64FC2);
}
-void cv::gemm( InputArray matA, InputArray matB, double alpha,
- InputArray matC, double beta, OutputArray _matD, int flags )
-{
-#ifdef HAVE_CLAMDBLAS
- CV_OCL_RUN(ocl::haveAmdBlas() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2 && _matD.isUMat() &&
- matA.cols() > 20 && matA.rows() > 20 && matB.cols() > 20, // since it works incorrect for small sizes
- ocl_gemm_amdblas(matA, matB, alpha, matC, beta, _matD, flags))
-#endif
-
-#ifdef HAVE_OPENCL
- CV_OCL_RUN(_matD.isUMat() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2,
- ocl_gemm(matA, matB, alpha, matC, beta, _matD, flags))
-#endif
-
- Mat A = matA.getMat(), B = matB.getMat(), C = beta != 0.0 ? matC.getMat() : Mat();
- Size a_size = A.size(), d_size;
- int len = 0, type = A.type();
-
- CV_Assert_N( type == B.type(), (type == CV_32FC1 || type == CV_64FC1 || type == CV_32FC2 || type == CV_64FC2) );
-
- switch( flags & (GEMM_1_T|GEMM_2_T) )
- {
- case 0:
- d_size = Size( B.cols, a_size.height );
- len = B.rows;
- CV_Assert( a_size.width == len );
- break;
- case 1:
- d_size = Size( B.cols, a_size.width );
- len = B.rows;
- CV_Assert( a_size.height == len );
- break;
- case 2:
- d_size = Size( B.rows, a_size.height );
- len = B.cols;
- CV_Assert( a_size.width == len );
- break;
- case 3:
- d_size = Size( B.rows, a_size.width );
- len = B.cols;
- CV_Assert( a_size.height == len );
- break;
- }
-
- if( !C.empty() )
- {
- CV_Assert_N( C.type() == type,
- (((flags&GEMM_3_T) == 0 && C.rows == d_size.height && C.cols == d_size.width) ||
- ((flags&GEMM_3_T) != 0 && C.rows == d_size.width && C.cols == d_size.height)));
- }
-
- _matD.create( d_size.height, d_size.width, type );
- Mat D = _matD.getMat();
- if( (flags & GEMM_3_T) != 0 && C.data == D.data )
- {
- transpose( C, C );
- flags &= ~GEMM_3_T;
- }
-
- Mat *DProxyPtr = &D, DProxy;
- if( D.data == A.data || D.data == B.data )
- {
- DProxy = Mat(d_size.height, d_size.width, D.type());
- DProxyPtr = &DProxy;
- }
+#endif // !defined(CV_GEMM_BASELINE_ONLY) || defined(CV_CPU_BASELINE_MODE)
- if( type == CV_32FC1 )
- hal::gemm32f(A.ptr<float>(), A.step, B.ptr<float>(), B.step, static_cast<float>(alpha),
- C.ptr<float>(), C.step, static_cast<float>(beta),
- DProxyPtr->ptr<float>(), DProxyPtr->step,
- a_size.height, a_size.width, DProxyPtr->cols, flags);
- else if( type == CV_64FC1 )
- hal::gemm64f(A.ptr<double>(), A.step, B.ptr<double>(), B.step, alpha,
- C.ptr<double>(), C.step, beta,
- DProxyPtr->ptr<double>(), DProxyPtr->step,
- a_size.height, a_size.width, DProxyPtr->cols, flags);
- else if( type == CV_32FC2 )
- hal::gemm32fc(A.ptr<float>(), A.step, B.ptr<float>(), B.step, static_cast<float>(alpha),
- C.ptr<float>(), C.step, static_cast<float>(beta),
- DProxyPtr->ptr<float>(), DProxyPtr->step,
- a_size.height, a_size.width, DProxyPtr->cols, flags);
- else
- {
- CV_Assert( type == CV_64FC2 );
- hal::gemm64fc(A.ptr<double>(), A.step, B.ptr<double>(), B.step, alpha,
- C.ptr<double>(), C.step, beta,
- D.ptr<double>(), D.step,
- a_size.height, a_size.width, DProxyPtr->cols, flags);
- }
- if(DProxyPtr != &D)
- DProxyPtr->copyTo(D);
-}
/****************************************************************************************\
* Transform *
\****************************************************************************************/
-namespace cv
-{
-
template<typename T, typename WT> static void
transform_( const T* src, T* dst, const WT* m, int len, int scn, int dcn )
{
}
}
-#if CV_SIMD128 && !defined(__aarch64__)
-static inline void
-load3x3Matrix(const float* m, v_float32x4& m0, v_float32x4& m1, v_float32x4& m2, v_float32x4& m3)
-{
- m0 = v_float32x4(m[0], m[4], m[8], 0);
- m1 = v_float32x4(m[1], m[5], m[9], 0);
- m2 = v_float32x4(m[2], m[6], m[10], 0);
- m3 = v_float32x4(m[3], m[7], m[11], 0);
-}
-#endif
-
-#if CV_SIMD128
-static inline v_int16x8
-v_matmulvec(const v_int16x8 &v0, const v_int16x8 &m0, const v_int16x8 &m1, const v_int16x8 &m2, const v_int32x4 &m3, const int BITS)
-{
- // v0 : 0 b0 g0 r0 b1 g1 r1 ?
- v_int32x4 t0 = v_dotprod(v0, m0); // a0 b0 a1 b1
- v_int32x4 t1 = v_dotprod(v0, m1); // c0 d0 c1 d1
- v_int32x4 t2 = v_dotprod(v0, m2); // e0 f0 e1 f1
- v_int32x4 t3 = v_setzero_s32();
- v_int32x4 s0, s1, s2, s3;
- v_transpose4x4(t0, t1, t2, t3, s0, s1, s2, s3);
- s0 = s0 + s1 + m3; // B0 G0 R0 ?
- s2 = s2 + s3 + m3; // B1 G1 R1 ?
-
- s0 = s0 >> BITS;
- s2 = s2 >> BITS;
-
- v_int16x8 result = v_pack(s0, v_setzero_s32()); // B0 G0 R0 0 0 0 0 0
- result = v_reinterpret_as_s16(v_reinterpret_as_s64(result) << 16); // 0 B0 G0 R0 0 0 0 0
- result = result | v_pack(v_setzero_s32(), s2); // 0 B0 G0 R0 B1 G1 R1 0
- return result;
-}
-#endif
-
static void
transform_8u( const uchar* src, uchar* dst, const float* m, int len, int scn, int dcn )
{
-#if CV_SIMD128
+#if CV_SIMD
const int BITS = 10, SCALE = 1 << BITS;
const float MAX_M = (float)(1 << (15 - BITS));
- if( hasSIMD128() && scn == 3 && dcn == 3 &&
- std::abs(m[0]) < MAX_M && std::abs(m[1]) < MAX_M && std::abs(m[2]) < MAX_M && std::abs(m[3]) < MAX_M*256 &&
- std::abs(m[4]) < MAX_M && std::abs(m[5]) < MAX_M && std::abs(m[6]) < MAX_M && std::abs(m[7]) < MAX_M*256 &&
- std::abs(m[8]) < MAX_M && std::abs(m[9]) < MAX_M && std::abs(m[10]) < MAX_M && std::abs(m[11]) < MAX_M*256 )
+ if( scn == 3 && dcn == 3 &&
+ std::abs(m[0]) < MAX_M && std::abs(m[1]) < MAX_M && std::abs(m[ 2]) < MAX_M*256 && std::abs(m[ 3]) < MAX_M*256 &&
+ std::abs(m[4]) < MAX_M && std::abs(m[5]) < MAX_M && std::abs(m[ 6]) < MAX_M*256 && std::abs(m[ 7]) < MAX_M*256 &&
+ std::abs(m[8]) < MAX_M && std::abs(m[9]) < MAX_M && std::abs(m[10]) < MAX_M*256 && std::abs(m[11]) < MAX_M*256 )
{
const int nChannels = 3;
- const int cWidth = v_int16x8::nlanes;
- // faster fixed-point transformation
- short m00 = saturate_cast<short>(m[0]*SCALE), m01 = saturate_cast<short>(m[1]*SCALE),
- m02 = saturate_cast<short>(m[2]*SCALE), m10 = saturate_cast<short>(m[4]*SCALE),
- m11 = saturate_cast<short>(m[5]*SCALE), m12 = saturate_cast<short>(m[6]*SCALE),
- m20 = saturate_cast<short>(m[8]*SCALE), m21 = saturate_cast<short>(m[9]*SCALE),
- m22 = saturate_cast<short>(m[10]*SCALE);
- int m03 = saturate_cast<int>((m[3]+0.5f)*SCALE), m13 = saturate_cast<int>((m[7]+0.5f)*SCALE ),
- m23 = saturate_cast<int>((m[11]+0.5f)*SCALE);
-
- v_int16x8 m0 = v_int16x8(0, m00, m01, m02, m00, m01, m02, 0);
- v_int16x8 m1 = v_int16x8(0, m10, m11, m12, m10, m11, m12, 0);
- v_int16x8 m2 = v_int16x8(0, m20, m21, m22, m20, m21, m22, 0);
- v_int32x4 m3 = v_int32x4(m03, m13, m23, 0);
- int x = 0;
-
- for (; x <= (len - cWidth) * nChannels; x += cWidth * nChannels)
- {
- // load 8 pixels
- v_int16x8 v0 = v_reinterpret_as_s16(v_load_expand(src + x));
- v_int16x8 v1 = v_reinterpret_as_s16(v_load_expand(src + x + cWidth));
- v_int16x8 v2 = v_reinterpret_as_s16(v_load_expand(src + x + cWidth * 2));
- v_int16x8 v3;
-
- // rotate and pack
- v3 = v_rotate_right<1>(v2); // 0 b6 g6 r6 b7 g7 r7 0
- v2 = v_rotate_left <5>(v2, v1); // 0 b4 g4 r4 b5 g5 r5 0
- v1 = v_rotate_left <3>(v1, v0); // 0 b2 g2 r2 b3 g3 r3 0
- v0 = v_rotate_left <1>(v0); // 0 b0 g0 r0 b1 g1 r1 0
-
- // multiply with matrix and normalize
- v0 = v_matmulvec(v0, m0, m1, m2, m3, BITS); // 0 B0 G0 R0 B1 G1 R1 0
- v1 = v_matmulvec(v1, m0, m1, m2, m3, BITS); // 0 B2 G2 R2 B3 G3 R3 0
- v2 = v_matmulvec(v2, m0, m1, m2, m3, BITS); // 0 B4 G4 R4 B5 G5 R5 0
- v3 = v_matmulvec(v3, m0, m1, m2, m3, BITS); // 0 B6 G6 R6 B7 G7 R7 0
-
- // narrow down as uint8x16
- v_uint8x16 z0 = v_pack_u(v0, v_setzero_s16()); // 0 B0 G0 R0 B1 G1 R1 0 0 0 0 0 0 0 0 0
- v_uint8x16 z1 = v_pack_u(v1, v_setzero_s16()); // 0 B2 G2 R2 B3 G3 R3 0 0 0 0 0 0 0 0 0
- v_uint8x16 z2 = v_pack_u(v2, v_setzero_s16()); // 0 B4 G4 R4 B5 G5 R5 0 0 0 0 0 0 0 0 0
- v_uint8x16 z3 = v_pack_u(v3, v_setzero_s16()); // 0 B6 G6 R6 B7 G7 R7 0 0 0 0 0 0 0 0 0
-
- // rotate and pack
- z0 = v_reinterpret_as_u8(v_reinterpret_as_u64(z0) >> 8) | v_reinterpret_as_u8(v_reinterpret_as_u64(z1) << 40); // B0 G0 R0 B1 G1 R1 B2 G2 0 0 0 0 0 0 0 0
- z1 = v_reinterpret_as_u8(v_reinterpret_as_u64(z1) >> 24) | v_reinterpret_as_u8(v_reinterpret_as_u64(z2) << 24); // R2 B3 G3 R3 B4 G4 R4 B5 0 0 0 0 0 0 0 0
- z2 = v_reinterpret_as_u8(v_reinterpret_as_u64(z2) >> 40) | v_reinterpret_as_u8(v_reinterpret_as_u64(z3) << 8); // G5 R6 B6 G6 R6 B7 G7 R7 0 0 0 0 0 0 0 0
-
- // store on memory
- v_store_low(dst + x, z0);
- v_store_low(dst + x + cWidth, z1);
- v_store_low(dst + x + cWidth * 2, z2);
- }
+ union {
+ short s[6];
+ int p[3];
+ } m16;
+ m16.s[0] = saturate_cast<short>(m[0] * SCALE); m16.s[1] = saturate_cast<short>(m[1] * SCALE);
+ m16.s[2] = saturate_cast<short>(m[4] * SCALE); m16.s[3] = saturate_cast<short>(m[5] * SCALE);
+ m16.s[4] = saturate_cast<short>(m[8] * SCALE); m16.s[5] = saturate_cast<short>(m[9] * SCALE);
+ int m32[] = {saturate_cast<int>(m[ 2] * SCALE), saturate_cast<int>(m[ 3] * SCALE),
+ saturate_cast<int>(m[ 6] * SCALE), saturate_cast<int>(m[ 7] * SCALE),
+ saturate_cast<int>(m[10] * SCALE), saturate_cast<int>(m[11] * SCALE)};
+ v_int16 m01 = v_reinterpret_as_s16(vx_setall_s32(m16.p[0]));
+ v_int32 m2 = vx_setall_s32(m32[0]);
+ v_int32 m3 = vx_setall_s32(m32[1]);
+ v_int16 m45 = v_reinterpret_as_s16(vx_setall_s32(m16.p[1]));
+ v_int32 m6 = vx_setall_s32(m32[2]);
+ v_int32 m7 = vx_setall_s32(m32[3]);
+ v_int16 m89 = v_reinterpret_as_s16(vx_setall_s32(m16.p[2]));
+ v_int32 m10 = vx_setall_s32(m32[4]);
+ v_int32 m11 = vx_setall_s32(m32[5]);
+ int x = 0;
+ for (; x <= (len - v_uint8::nlanes) * nChannels; x += v_uint8::nlanes * nChannels)
+ {
+ v_uint8 b, g, r;
+ v_load_deinterleave(src + x, b, g, r);
+ v_uint8 bgl, bgh;
+ v_zip(b, g, bgl, bgh);
+ v_uint16 rl, rh;
+ v_expand(r, rl, rh);
+
+ v_int16 dbl, dbh, dgl, dgh, drl, drh;
+ v_uint16 p0, p2;
+ v_int32 p1, p3;
+ v_expand(bgl, p0, p2);
+ v_expand(v_reinterpret_as_s16(rl), p1, p3);
+ dbl = v_rshr_pack<BITS>(v_dotprod(v_reinterpret_as_s16(p0), m01) + p1 * m2 + m3,
+ v_dotprod(v_reinterpret_as_s16(p2), m01) + p3 * m2 + m3);
+ dgl = v_rshr_pack<BITS>(v_dotprod(v_reinterpret_as_s16(p0), m45) + p1 * m6 + m7,
+ v_dotprod(v_reinterpret_as_s16(p2), m45) + p3 * m6 + m7);
+ drl = v_rshr_pack<BITS>(v_dotprod(v_reinterpret_as_s16(p0), m89) + p1 * m10 + m11,
+ v_dotprod(v_reinterpret_as_s16(p2), m89) + p3 * m10 + m11);
+ v_expand(bgh, p0, p2);
+ v_expand(v_reinterpret_as_s16(rh), p1, p3);
+ dbh = v_rshr_pack<BITS>(v_dotprod(v_reinterpret_as_s16(p0), m01) + p1 * m2 + m3,
+ v_dotprod(v_reinterpret_as_s16(p2), m01) + p3 * m2 + m3);
+ dgh = v_rshr_pack<BITS>(v_dotprod(v_reinterpret_as_s16(p0), m45) + p1 * m6 + m7,
+ v_dotprod(v_reinterpret_as_s16(p2), m45) + p3 * m6 + m7);
+ drh = v_rshr_pack<BITS>(v_dotprod(v_reinterpret_as_s16(p0), m89) + p1 * m10 + m11,
+ v_dotprod(v_reinterpret_as_s16(p2), m89) + p3 * m10 + m11);
+ v_store_interleave(dst + x, v_pack_u(dbl, dbh), v_pack_u(dgl, dgh), v_pack_u(drl, drh));
+ }
+ m32[1] = saturate_cast<int>((m[3] + 0.5f)*SCALE);
+ m32[3] = saturate_cast<int>((m[7] + 0.5f)*SCALE);
+ m32[5] = saturate_cast<int>((m[11] + 0.5f)*SCALE);
for( ; x < len * nChannels; x += nChannels )
{
int v0 = src[x], v1 = src[x+1], v2 = src[x+2];
- uchar t0 = saturate_cast<uchar>((m00*v0 + m01*v1 + m02*v2 + m03)>>BITS);
- uchar t1 = saturate_cast<uchar>((m10*v0 + m11*v1 + m12*v2 + m13)>>BITS);
- uchar t2 = saturate_cast<uchar>((m20*v0 + m21*v1 + m22*v2 + m23)>>BITS);
+ uchar t0 = saturate_cast<uchar>((m16.s[0] * v0 + m16.s[1] * v1 + m32[0] * v2 + m32[1]) >> BITS);
+ uchar t1 = saturate_cast<uchar>((m16.s[2] * v0 + m16.s[3] * v1 + m32[2] * v2 + m32[3]) >> BITS);
+ uchar t2 = saturate_cast<uchar>((m16.s[4] * v0 + m16.s[5] * v1 + m32[4] * v2 + m32[5]) >> BITS);
dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2;
}
+ vx_cleanup();
return;
}
#endif
static void
transform_16u( const ushort* src, ushort* dst, const float* m, int len, int scn, int dcn )
{
-#if CV_SIMD128 && !defined(__aarch64__)
- if( hasSIMD128() && scn == 3 && dcn == 3 )
+#if CV_SIMD && !defined(__aarch64__)
+ if( scn == 3 && dcn == 3 )
{
- const int nChannels = 3;
- const int cWidth = v_float32x4::nlanes;
- v_int16x8 delta = v_int16x8(0, -32768, -32768, -32768, -32768, -32768, -32768, 0);
- v_float32x4 m0, m1, m2, m3;
- load3x3Matrix(m, m0, m1, m2, m3);
- m3 -= v_float32x4(32768.f, 32768.f, 32768.f, 0.f);
-
int x = 0;
- for( ; x <= (len - cWidth) * nChannels; x += cWidth * nChannels )
- {
- // load 4 pixels
- v_uint16x8 v0_16 = v_load(src + x); // b0 g0 r0 b1 g1 r1 b2 g2
- v_uint16x8 v2_16 = v_load_low(src + x + cWidth * 2); // r2 b3 g3 r3 ? ? ? ?
-
- // expand to 4 vectors
- v_uint32x4 v0_32, v1_32, v2_32, v3_32, dummy_32;
- v_expand(v_rotate_right<3>(v0_16), v1_32, dummy_32); // b1 g1 r1
- v_expand(v_rotate_right<1>(v2_16), v3_32, dummy_32); // b3 g3 r3
- v_expand(v_rotate_right<6>(v0_16, v2_16), v2_32, dummy_32); // b2 g2 r2
- v_expand(v0_16, v0_32, dummy_32); // b0 g0 r0
-
- // convert to float32x4
- v_float32x4 x0 = v_cvt_f32(v_reinterpret_as_s32(v0_32)); // b0 g0 r0
- v_float32x4 x1 = v_cvt_f32(v_reinterpret_as_s32(v1_32)); // b1 g1 r1
- v_float32x4 x2 = v_cvt_f32(v_reinterpret_as_s32(v2_32)); // b2 g2 r2
- v_float32x4 x3 = v_cvt_f32(v_reinterpret_as_s32(v3_32)); // b3 g3 r3
-
- // multiply and convert back to int32x4
- v_int32x4 y0, y1, y2, y3;
- y0 = v_round(v_matmuladd(x0, m0, m1, m2, m3)); // B0 G0 R0
- y1 = v_round(v_matmuladd(x1, m0, m1, m2, m3)); // B1 G1 R1
- y2 = v_round(v_matmuladd(x2, m0, m1, m2, m3)); // B2 G2 R2
- y3 = v_round(v_matmuladd(x3, m0, m1, m2, m3)); // B3 G3 R3
-
- // narrow down to int16x8
- v_int16x8 v0 = v_add_wrap(v_pack(v_rotate_left<1>(y0), y1), delta); // 0 B0 G0 R0 B1 G1 R1 0
- v_int16x8 v2 = v_add_wrap(v_pack(v_rotate_left<1>(y2), y3), delta); // 0 B2 G2 R2 B3 G3 R3 0
-
- // rotate and pack
- v0 = v_rotate_right<1>(v0) | v_rotate_left<5>(v2); // B0 G0 R0 B1 G1 R1 B2 G2
- v2 = v_rotate_right<3>(v2); // R2 B3 G3 R3 0 0 0 0
-
- // store 4 pixels
- v_store(dst + x, v_reinterpret_as_u16(v0));
- v_store_low(dst + x + cWidth * 2, v_reinterpret_as_u16(v2));
+#if CV_SIMD_WIDTH > 16
+ v_float32 m0 = vx_setall_f32(m[ 0]);
+ v_float32 m1 = vx_setall_f32(m[ 1]);
+ v_float32 m2 = vx_setall_f32(m[ 2]);
+ v_float32 m3 = vx_setall_f32(m[ 3] - 32768.f);
+ v_float32 m4 = vx_setall_f32(m[ 4]);
+ v_float32 m5 = vx_setall_f32(m[ 5]);
+ v_float32 m6 = vx_setall_f32(m[ 6]);
+ v_float32 m7 = vx_setall_f32(m[ 7] - 32768.f);
+ v_float32 m8 = vx_setall_f32(m[ 8]);
+ v_float32 m9 = vx_setall_f32(m[ 9]);
+ v_float32 m10 = vx_setall_f32(m[10]);
+ v_float32 m11 = vx_setall_f32(m[11] - 32768.f);
+ v_int16 delta = vx_setall_s16(-32768);
+ for (; x <= (len - v_uint16::nlanes)*3; x += v_uint16::nlanes*3)
+ {
+ v_uint16 b, g, r;
+ v_load_deinterleave(src + x, b, g, r);
+ v_uint32 bl, bh, gl, gh, rl, rh;
+ v_expand(b, bl, bh);
+ v_expand(g, gl, gh);
+ v_expand(r, rl, rh);
+
+ v_int16 db, dg, dr;
+ db = v_add_wrap(v_pack(v_round(v_muladd(v_cvt_f32(v_reinterpret_as_s32(bl)), m0, v_muladd(v_cvt_f32(v_reinterpret_as_s32(gl)), m1, v_muladd(v_cvt_f32(v_reinterpret_as_s32(rl)), m2, m3)))),
+ v_round(v_muladd(v_cvt_f32(v_reinterpret_as_s32(bh)), m0, v_muladd(v_cvt_f32(v_reinterpret_as_s32(gh)), m1, v_muladd(v_cvt_f32(v_reinterpret_as_s32(rh)), m2, m3))))), delta);
+ dg = v_add_wrap(v_pack(v_round(v_muladd(v_cvt_f32(v_reinterpret_as_s32(bl)), m4, v_muladd(v_cvt_f32(v_reinterpret_as_s32(gl)), m5, v_muladd(v_cvt_f32(v_reinterpret_as_s32(rl)), m6, m7)))),
+ v_round(v_muladd(v_cvt_f32(v_reinterpret_as_s32(bh)), m4, v_muladd(v_cvt_f32(v_reinterpret_as_s32(gh)), m5, v_muladd(v_cvt_f32(v_reinterpret_as_s32(rh)), m6, m7))))), delta);
+ dr = v_add_wrap(v_pack(v_round(v_muladd(v_cvt_f32(v_reinterpret_as_s32(bl)), m8, v_muladd(v_cvt_f32(v_reinterpret_as_s32(gl)), m9, v_muladd(v_cvt_f32(v_reinterpret_as_s32(rl)), m10, m11)))),
+ v_round(v_muladd(v_cvt_f32(v_reinterpret_as_s32(bh)), m8, v_muladd(v_cvt_f32(v_reinterpret_as_s32(gh)), m9, v_muladd(v_cvt_f32(v_reinterpret_as_s32(rh)), m10, m11))))), delta);
+ v_store_interleave(dst + x, v_reinterpret_as_u16(db), v_reinterpret_as_u16(dg), v_reinterpret_as_u16(dr));
}
-
- for( ; x < len * nChannels; x += nChannels )
+#endif
+ v_float32x4 _m0l(m[0], m[4], m[ 8], 0.f);
+ v_float32x4 _m1l(m[1], m[5], m[ 9], 0.f);
+ v_float32x4 _m2l(m[2], m[6], m[10], 0.f);
+ v_float32x4 _m3l(m[3] - 32768.f, m[7] - 32768.f, m[11] - 32768.f, 0.f);
+ v_float32x4 _m0h = v_rotate_left<1>(_m0l);
+ v_float32x4 _m1h = v_rotate_left<1>(_m1l);
+ v_float32x4 _m2h = v_rotate_left<1>(_m2l);
+ v_float32x4 _m3h = v_rotate_left<1>(_m3l);
+ v_int16x8 _delta(0, -32768, -32768, -32768, -32768, -32768, -32768, 0);
+ for( ; x <= len*3 - v_uint16x8::nlanes; x += 3*v_uint16x8::nlanes/4 )
+ v_store(dst + x, v_rotate_right<1>(v_reinterpret_as_u16(v_add_wrap(v_pack(
+ v_round(v_matmuladd(v_cvt_f32(v_reinterpret_as_s32(v_load_expand(src + x ))), _m0h, _m1h, _m2h, _m3h)),
+ v_round(v_matmuladd(v_cvt_f32(v_reinterpret_as_s32(v_load_expand(src + x + 3))), _m0l, _m1l, _m2l, _m3l))), _delta))));
+ for( ; x < len * 3; x += 3 )
{
float v0 = src[x], v1 = src[x + 1], v2 = src[x + 2];
- ushort t0 = saturate_cast<ushort>(m[0] * v0 + m[1] * v1 + m[2] * v2 + m[3]);
- ushort t1 = saturate_cast<ushort>(m[4] * v0 + m[5] * v1 + m[6] * v2 + m[7]);
+ ushort t0 = saturate_cast<ushort>(m[0] * v0 + m[1] * v1 + m[ 2] * v2 + m[ 3]);
+ ushort t1 = saturate_cast<ushort>(m[4] * v0 + m[5] * v1 + m[ 6] * v2 + m[ 7]);
ushort t2 = saturate_cast<ushort>(m[8] * v0 + m[9] * v1 + m[10] * v2 + m[11]);
dst[x] = t0; dst[x + 1] = t1; dst[x + 2] = t2;
}
+ vx_cleanup();
return;
}
#endif
static void
transform_32f( const float* src, float* dst, const float* m, int len, int scn, int dcn )
{
-#if CV_SIMD128 && !defined(__aarch64__)
- if( hasSIMD128() )
+#if CV_SIMD && !defined(__aarch64__)
+ int x = 0;
+ if( scn == 3 && dcn == 3 )
+ {
+ int idx[v_float32::nlanes/2];
+ for( int i = 0; i < v_float32::nlanes/4; i++ )
+ {
+ idx[i] = 3*i;
+ idx[i + v_float32::nlanes/4] = 0;
+ }
+ float _m[] = { m[0], m[4], m[ 8], 0.f,
+ m[1], m[5], m[ 9], 0.f,
+ m[2], m[6], m[10], 0.f,
+ m[3], m[7], m[11], 0.f };
+ v_float32 m0 = vx_lut_quads(_m , idx + v_float32::nlanes/4);
+ v_float32 m1 = vx_lut_quads(_m + 4, idx + v_float32::nlanes/4);
+ v_float32 m2 = vx_lut_quads(_m + 8, idx + v_float32::nlanes/4);
+ v_float32 m3 = vx_lut_quads(_m + 12, idx + v_float32::nlanes/4);
+ for( ; x <= len*3 - v_float32::nlanes; x += 3*v_float32::nlanes/4 )
+ v_store(dst + x, v_pack_triplets(v_matmuladd(vx_lut_quads(src + x, idx), m0, m1, m2, m3)));
+ for( ; x < len*3; x += 3 )
+ {
+ float v0 = src[x], v1 = src[x+1], v2 = src[x+2];
+ float t0 = saturate_cast<float>(m[0]*v0 + m[1]*v1 + m[ 2]*v2 + m[ 3]);
+ float t1 = saturate_cast<float>(m[4]*v0 + m[5]*v1 + m[ 6]*v2 + m[ 7]);
+ float t2 = saturate_cast<float>(m[8]*v0 + m[9]*v1 + m[10]*v2 + m[11]);
+ dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2;
+ }
+ vx_cleanup();
+ return;
+ }
+
+ if( scn == 4 && dcn == 4 )
{
- int x = 0;
- if( scn == 3 && dcn == 3 )
+#if CV_SIMD_WIDTH > 16
+ int idx[v_float32::nlanes/4];
+ for( int i = 0; i < v_float32::nlanes/4; i++ )
+ idx[i] = 0;
+ float _m[] = { m[4], m[9], m[14], m[19] };
+ v_float32 m0 = vx_lut_quads(m , idx);
+ v_float32 m1 = vx_lut_quads(m+ 5, idx);
+ v_float32 m2 = vx_lut_quads(m+10, idx);
+ v_float32 m3 = vx_lut_quads(m+15, idx);
+ v_float32 m4 = vx_lut_quads(_m, idx);
+ for( ; x <= len*4 - v_float32::nlanes; x += v_float32::nlanes )
{
- const int cWidth = 3;
- v_float32x4 m0, m1, m2, m3;
- load3x3Matrix(m, m0, m1, m2, m3);
-
- for( ; x < (len - 1)*cWidth; x += cWidth )
- {
- v_float32x4 x0 = v_load(src + x);
- v_float32x4 y0 = v_matmuladd(x0, m0, m1, m2, m3);
- v_store_low(dst + x, y0);
- dst[x + 2] = v_combine_high(y0, y0).get0();
- }
-
- for( ; x < len*cWidth; x += cWidth )
- {
- float v0 = src[x], v1 = src[x+1], v2 = src[x+2];
- float t0 = saturate_cast<float>(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]);
- float t1 = saturate_cast<float>(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]);
- float t2 = saturate_cast<float>(m[8]*v0 + m[9]*v1 + m[10]*v2 + m[11]);
- dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2;
- }
- return;
+ v_float32 v_src = vx_load(src + x);
+ v_store(dst + x, v_reduce_sum4(v_src * m0, v_src * m1, v_src * m2, v_src * m3) + m4);
}
-
- if( scn == 4 && dcn == 4 )
+#endif
+ v_float32x4 _m0 = v_load(m );
+ v_float32x4 _m1 = v_load(m + 5);
+ v_float32x4 _m2 = v_load(m + 10);
+ v_float32x4 _m3 = v_load(m + 15);
+ v_float32x4 _m4(m[4], m[9], m[14], m[19]);
+ for( ; x < len*4; x += v_float32x4::nlanes )
{
- const int cWidth = 4;
- v_float32x4 m0 = v_float32x4(m[0], m[5], m[10], m[15]);
- v_float32x4 m1 = v_float32x4(m[1], m[6], m[11], m[16]);
- v_float32x4 m2 = v_float32x4(m[2], m[7], m[12], m[17]);
- v_float32x4 m3 = v_float32x4(m[3], m[8], m[13], m[18]);
- v_float32x4 m4 = v_float32x4(m[4], m[9], m[14], m[19]);
-
- for( ; x < len*cWidth; x += cWidth )
- {
- v_float32x4 x0 = v_load(src + x);
- v_float32x4 y0 = v_matmul(x0, m0, m1, m2, m3) + m4;
- v_store(dst + x, y0);
- }
- return;
+ v_float32x4 v_src = v_load(src + x);
+ v_store(dst + x, v_reduce_sum4(v_src * _m0, v_src * _m1, v_src * _m2, v_src * _m3) + _m4);
}
+ vx_cleanup();
+ return;
}
#endif
}
-typedef void (*TransformFunc)( const uchar* src, uchar* dst, const uchar* m, int, int, int );
-
-static TransformFunc getTransformFunc(int depth)
+TransformFunc getTransformFunc(int depth)
{
static TransformFunc transformTab[] =
{
return transformTab[depth];
}
-static TransformFunc getDiagTransformFunc(int depth)
+TransformFunc getDiagTransformFunc(int depth)
{
static TransformFunc diagTransformTab[] =
{
return diagTransformTab[depth];
}
-}
-
-void cv::transform( InputArray _src, OutputArray _dst, InputArray _mtx )
-{
- CV_INSTRUMENT_REGION();
-
- Mat src = _src.getMat(), m = _mtx.getMat();
- int depth = src.depth(), scn = src.channels(), dcn = m.rows;
- CV_Assert( scn == m.cols || scn + 1 == m.cols );
- bool isDiag = false;
-
- _dst.create( src.size(), CV_MAKETYPE(depth, dcn) );
- Mat dst = _dst.getMat();
-
- int mtype = depth == CV_32S || depth == CV_64F ? CV_64F : CV_32F;
- AutoBuffer<double> _mbuf;
- double* mbuf;
-
- if( !m.isContinuous() || m.type() != mtype || m.cols != scn + 1 )
- {
- _mbuf.allocate(dcn*(scn+1));
- mbuf = _mbuf.data();
- Mat tmp(dcn, scn+1, mtype, mbuf);
- memset(tmp.ptr(), 0, tmp.total()*tmp.elemSize());
- if( m.cols == scn+1 )
- m.convertTo(tmp, mtype);
- else
- {
- Mat tmppart = tmp.colRange(0, m.cols);
- m.convertTo(tmppart, mtype);
- }
- m = tmp;
- }
- else
- mbuf = m.ptr<double>();
-
- if( scn == dcn )
- {
- int i, j;
- double eps = mtype == CV_32F ? FLT_EPSILON : DBL_EPSILON;
-
- if( scn == 1 )
- {
- double alpha, beta;
- if( mtype == CV_32F )
- alpha = m.at<float>(0), beta = m.at<float>(1);
- else
- alpha = m.at<double>(0), beta = m.at<double>(1);
- src.convertTo(dst, dst.type(), alpha, beta);
- return;
- }
-
- for( i = 0, isDiag = true; isDiag && i < scn; i++ )
- {
- for( j = 0; isDiag && j < scn; j++ )
- {
- double v = mtype == CV_32F ? m.at<float>(i, j) : m.at<double>(i, j);
- if( i != j && fabs(v) > eps )
- isDiag = false;
- }
- }
- }
-
- TransformFunc func = isDiag ? getDiagTransformFunc(depth): getTransformFunc(depth);
- CV_Assert( func != 0 );
-
- const Mat* arrays[] = {&src, &dst, 0};
- uchar* ptrs[2] = {};
- NAryMatIterator it(arrays, ptrs);
- size_t i, total = it.size;
- for( i = 0; i < it.nplanes; i++, ++it )
- func( ptrs[0], ptrs[1], (uchar*)mbuf, (int)total, scn, dcn );
-}
/****************************************************************************************\
* Perspective Transform *
\****************************************************************************************/
-namespace cv
-{
-
template<typename T> static void
perspectiveTransform_( const T* src, T* dst, const double* m, int len, int scn, int dcn )
{
}
}
-
static void
perspectiveTransform_32f(const float* src, float* dst, const double* m, int len, int scn, int dcn)
{
perspectiveTransform_(src, dst, m, len, scn, dcn);
}
-}
-
-void cv::perspectiveTransform( InputArray _src, OutputArray _dst, InputArray _mtx )
+TransformFunc getPerspectiveTransform(int depth)
{
- CV_INSTRUMENT_REGION();
-
- Mat src = _src.getMat(), m = _mtx.getMat();
- int depth = src.depth(), scn = src.channels(), dcn = m.rows-1;
- CV_Assert( scn + 1 == m.cols );
- CV_Assert( depth == CV_32F || depth == CV_64F );
-
- _dst.create( src.size(), CV_MAKETYPE(depth, dcn) );
- Mat dst = _dst.getMat();
-
- const int mtype = CV_64F;
- AutoBuffer<double> _mbuf;
- double* mbuf = m.ptr<double>();
-
- if( !m.isContinuous() || m.type() != mtype )
- {
- _mbuf.allocate((dcn+1)*(scn+1));
- mbuf = _mbuf.data();
- Mat tmp(dcn+1, scn+1, mtype, mbuf);
- m.convertTo(tmp, mtype);
- m = tmp;
- }
-
- TransformFunc func = depth == CV_32F ?
- (TransformFunc)perspectiveTransform_32f :
- (TransformFunc)perspectiveTransform_64f;
- CV_Assert( func != 0 );
+ if (depth == CV_32F)
+ return (TransformFunc)perspectiveTransform_32f;
+ if (depth == CV_64F)
+ return (TransformFunc)perspectiveTransform_64f;
+ CV_Assert(0 && "Not supported");
+}
- const Mat* arrays[] = {&src, &dst, 0};
- uchar* ptrs[2] = {};
- NAryMatIterator it(arrays, ptrs);
- size_t i, total = it.size;
- for( i = 0; i < it.nplanes; i++, ++it )
- func( ptrs[0], ptrs[1], (uchar*)mbuf, (int)total, scn, dcn );
-}
/****************************************************************************************\
* ScaleAdd *
\****************************************************************************************/
-namespace cv
-{
-
static void scaleAdd_32f(const float* src1, const float* src2, float* dst,
int len, float* _alpha)
{
dst[i] = src1[i] * alpha + src2[i];
}
-typedef void (*ScaleAddFunc)(const uchar* src1, const uchar* src2, uchar* dst, int len, const void* alpha);
-
-#ifdef HAVE_OPENCL
-
-static bool ocl_scaleAdd( InputArray _src1, double alpha, InputArray _src2, OutputArray _dst, int type )
+ScaleAddFunc getScaleAddFunc(int depth)
{
- const ocl::Device & d = ocl::Device::getDefault();
-
- bool doubleSupport = d.doubleFPConfig() > 0;
- Size size = _src1.size();
- int depth = CV_MAT_DEPTH(type);
- if ( (!doubleSupport && depth == CV_64F) || size != _src2.size() )
- return false;
-
- _dst.create(size, type);
- int cn = CV_MAT_CN(type), wdepth = std::max(depth, CV_32F);
- int kercn = ocl::predictOptimalVectorWidthMax(_src1, _src2, _dst),
- rowsPerWI = d.isIntel() ? 4 : 1;
-
- char cvt[2][50];
- ocl::Kernel k("KF", ocl::core::arithm_oclsrc,
- format("-D OP_SCALE_ADD -D BINARY_OP -D dstT=%s -D DEPTH_dst=%d -D workT=%s -D convertToWT1=%s"
- " -D srcT1=dstT -D srcT2=dstT -D convertToDT=%s -D workT1=%s"
- " -D wdepth=%d%s -D rowsPerWI=%d",
- ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)), depth,
- ocl::typeToStr(CV_MAKE_TYPE(wdepth, kercn)),
- ocl::convertTypeStr(depth, wdepth, kercn, cvt[0]),
- ocl::convertTypeStr(wdepth, depth, kercn, cvt[1]),
- ocl::typeToStr(wdepth), wdepth,
- doubleSupport ? " -D DOUBLE_SUPPORT" : "", rowsPerWI));
- if (k.empty())
- return false;
-
- UMat src1 = _src1.getUMat(), src2 = _src2.getUMat(), dst = _dst.getUMat();
-
- ocl::KernelArg src1arg = ocl::KernelArg::ReadOnlyNoSize(src1),
- src2arg = ocl::KernelArg::ReadOnlyNoSize(src2),
- dstarg = ocl::KernelArg::WriteOnly(dst, cn, kercn);
-
- if (wdepth == CV_32F)
- k.args(src1arg, src2arg, dstarg, (float)alpha);
- else
- k.args(src1arg, src2arg, dstarg, alpha);
-
- size_t globalsize[2] = { (size_t)dst.cols * cn / kercn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI };
- return k.run(2, globalsize, NULL, false);
-}
-
-#endif
-
+ if (depth == CV_32F)
+ return (ScaleAddFunc)scaleAdd_32f;
+ if (depth == CV_64F)
+ return (ScaleAddFunc)scaleAdd_64f;
+ CV_Assert(0 && "Not supported");
}
-void cv::scaleAdd( InputArray _src1, double alpha, InputArray _src2, OutputArray _dst )
-{
- CV_INSTRUMENT_REGION();
-
- int type = _src1.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
- CV_Assert( type == _src2.type() );
-
- CV_OCL_RUN(_src1.dims() <= 2 && _src2.dims() <= 2 && _dst.isUMat(),
- ocl_scaleAdd(_src1, alpha, _src2, _dst, type))
-
- if( depth < CV_32F )
- {
- addWeighted(_src1, alpha, _src2, 1, 0, _dst, depth);
- return;
- }
-
- Mat src1 = _src1.getMat(), src2 = _src2.getMat();
- CV_Assert(src1.size == src2.size);
-
- _dst.create(src1.dims, src1.size, type);
- Mat dst = _dst.getMat();
-
- float falpha = (float)alpha;
- void* palpha = depth == CV_32F ? (void*)&falpha : (void*)α
-
- ScaleAddFunc func = depth == CV_32F ? (ScaleAddFunc)scaleAdd_32f : (ScaleAddFunc)scaleAdd_64f;
-
- if (src1.isContinuous() && src2.isContinuous() && dst.isContinuous())
- {
- size_t len = src1.total()*cn;
- func(src1.ptr(), src2.ptr(), dst.ptr(), (int)len, palpha);
- return;
- }
-
- const Mat* arrays[] = {&src1, &src2, &dst, 0};
- uchar* ptrs[3] = {};
- NAryMatIterator it(arrays, ptrs);
- size_t i, len = it.size*cn;
- for( i = 0; i < it.nplanes; i++, ++it )
- func( ptrs[0], ptrs[1], ptrs[2], (int)len, palpha );
-}
/****************************************************************************************\
-* Covariation Matrix *
+* Mahalanobis *
\****************************************************************************************/
-void cv::calcCovarMatrix( const Mat* data, int nsamples, Mat& covar, Mat& _mean, int flags, int ctype )
+template<typename T> static inline
+double MahalanobisImpl(const Mat& v1, const Mat& v2, const Mat& icovar, double *diff_buffer /*[len]*/, int len /*=v1.total()*/)
{
CV_INSTRUMENT_REGION();
- CV_Assert_N( data, nsamples > 0 );
- Size size = data[0].size();
- int sz = size.width * size.height, esz = (int)data[0].elemSize();
- int type = data[0].type();
- Mat mean;
- ctype = std::max(std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), _mean.depth()), CV_32F);
+ Size sz = v1.size();
+ double result = 0;
- if( (flags & CV_COVAR_USE_AVG) != 0 )
+ sz.width *= v1.channels();
+ if (v1.isContinuous() && v2.isContinuous())
{
- CV_Assert( _mean.size() == size );
- if( _mean.isContinuous() && _mean.type() == ctype )
- mean = _mean.reshape(1, 1);
- else
- {
- _mean.convertTo(mean, ctype);
- mean = mean.reshape(1, 1);
- }
+ sz.width *= sz.height;
+ sz.height = 1;
}
- Mat _data(nsamples, sz, type);
-
- for( int i = 0; i < nsamples; i++ )
{
- CV_Assert_N( data[i].size() == size, data[i].type() == type );
- if( data[i].isContinuous() )
- memcpy( _data.ptr(i), data[i].ptr(), sz*esz );
- else
+ const T* src1 = v1.ptr<T>();
+ const T* src2 = v2.ptr<T>();
+ size_t step1 = v1.step/sizeof(src1[0]);
+ size_t step2 = v2.step/sizeof(src2[0]);
+ double* diff = diff_buffer;
+ const T* mat = icovar.ptr<T>();
+ size_t matstep = icovar.step/sizeof(mat[0]);
+
+ for (; sz.height--; src1 += step1, src2 += step2, diff += sz.width)
{
- Mat dataRow(size.height, size.width, type, _data.ptr(i));
- data[i].copyTo(dataRow);
- }
- }
-
- calcCovarMatrix( _data, covar, mean, (flags & ~(CV_COVAR_ROWS|CV_COVAR_COLS)) | CV_COVAR_ROWS, ctype );
- if( (flags & CV_COVAR_USE_AVG) == 0 )
- _mean = mean.reshape(1, size.height);
-}
-
-void cv::calcCovarMatrix( InputArray _src, OutputArray _covar, InputOutputArray _mean, int flags, int ctype )
-{
- CV_INSTRUMENT_REGION();
-
- if(_src.kind() == _InputArray::STD_VECTOR_MAT || _src.kind() == _InputArray::STD_ARRAY_MAT)
- {
- std::vector<cv::Mat> src;
- _src.getMatVector(src);
-
- CV_Assert( src.size() > 0 );
-
- Size size = src[0].size();
- int type = src[0].type();
-
- ctype = std::max(std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), _mean.depth()), CV_32F);
-
- Mat _data(static_cast<int>(src.size()), size.area(), type);
-
- int i = 0;
- for(std::vector<cv::Mat>::iterator each = src.begin(); each != src.end(); ++each, ++i )
- {
- CV_Assert_N( (*each).size() == size, (*each).type() == type );
- Mat dataRow(size.height, size.width, type, _data.ptr(i));
- (*each).copyTo(dataRow);
- }
-
- Mat mean;
- if( (flags & CV_COVAR_USE_AVG) != 0 )
- {
- CV_Assert( _mean.size() == size );
-
- if( mean.type() != ctype )
- {
- mean = _mean.getMat();
- _mean.create(mean.size(), ctype);
- Mat tmp = _mean.getMat();
- mean.convertTo(tmp, ctype);
- mean = tmp;
- }
-
- mean = _mean.getMat().reshape(1, 1);
- }
-
- calcCovarMatrix( _data, _covar, mean, (flags & ~(CV_COVAR_ROWS|CV_COVAR_COLS)) | CV_COVAR_ROWS, ctype );
-
- if( (flags & CV_COVAR_USE_AVG) == 0 )
- {
- mean = mean.reshape(1, size.height);
- mean.copyTo(_mean);
- }
- return;
- }
-
- Mat data = _src.getMat(), mean;
- CV_Assert( ((flags & CV_COVAR_ROWS) != 0) ^ ((flags & CV_COVAR_COLS) != 0) );
- bool takeRows = (flags & CV_COVAR_ROWS) != 0;
- int type = data.type();
- int nsamples = takeRows ? data.rows : data.cols;
- CV_Assert( nsamples > 0 );
- Size size = takeRows ? Size(data.cols, 1) : Size(1, data.rows);
-
- if( (flags & CV_COVAR_USE_AVG) != 0 )
- {
- mean = _mean.getMat();
- ctype = std::max(std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), mean.depth()), CV_32F);
- CV_Assert( mean.size() == size );
- if( mean.type() != ctype )
- {
- _mean.create(mean.size(), ctype);
- Mat tmp = _mean.getMat();
- mean.convertTo(tmp, ctype);
- mean = tmp;
- }
- }
- else
- {
- ctype = std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), CV_32F);
- reduce( _src, _mean, takeRows ? 0 : 1, CV_REDUCE_AVG, ctype );
- mean = _mean.getMat();
- }
-
- mulTransposed( data, _covar, ((flags & CV_COVAR_NORMAL) == 0) ^ takeRows,
- mean, (flags & CV_COVAR_SCALE) != 0 ? 1./nsamples : 1, ctype );
-}
-
-/****************************************************************************************\
-* Mahalanobis *
-\****************************************************************************************/
-
-double cv::Mahalanobis( InputArray _v1, InputArray _v2, InputArray _icovar )
-{
- CV_INSTRUMENT_REGION();
-
- Mat v1 = _v1.getMat(), v2 = _v2.getMat(), icovar = _icovar.getMat();
- int type = v1.type(), depth = v1.depth();
- Size sz = v1.size();
- int i, j, len = sz.width*sz.height*v1.channels();
- AutoBuffer<double> buf(len);
- double result = 0;
-
- CV_Assert_N( type == v2.type(), type == icovar.type(),
- sz == v2.size(), len == icovar.rows && len == icovar.cols );
-
- sz.width *= v1.channels();
- if( v1.isContinuous() && v2.isContinuous() )
- {
- sz.width *= sz.height;
- sz.height = 1;
- }
-
- if( depth == CV_32F )
- {
- const float* src1 = v1.ptr<float>();
- const float* src2 = v2.ptr<float>();
- size_t step1 = v1.step/sizeof(src1[0]);
- size_t step2 = v2.step/sizeof(src2[0]);
- double* diff = buf.data();
- const float* mat = icovar.ptr<float>();
- size_t matstep = icovar.step/sizeof(mat[0]);
-
- for( ; sz.height--; src1 += step1, src2 += step2, diff += sz.width )
- {
- for( i = 0; i < sz.width; i++ )
- diff[i] = src1[i] - src2[i];
- }
-
- diff = buf.data();
- for( i = 0; i < len; i++, mat += matstep )
- {
- double row_sum = 0;
- j = 0;
- #if CV_ENABLE_UNROLLED
- for(; j <= len - 4; j += 4 )
- row_sum += diff[j]*mat[j] + diff[j+1]*mat[j+1] +
- diff[j+2]*mat[j+2] + diff[j+3]*mat[j+3];
- #endif
- for( ; j < len; j++ )
- row_sum += diff[j]*mat[j];
- result += row_sum * diff[i];
- }
- }
- else if( depth == CV_64F )
- {
- const double* src1 = v1.ptr<double>();
- const double* src2 = v2.ptr<double>();
- size_t step1 = v1.step/sizeof(src1[0]);
- size_t step2 = v2.step/sizeof(src2[0]);
- double* diff = buf.data();
- const double* mat = icovar.ptr<double>();
- size_t matstep = icovar.step/sizeof(mat[0]);
-
- for( ; sz.height--; src1 += step1, src2 += step2, diff += sz.width )
- {
- for( i = 0; i < sz.width; i++ )
+ for (int i = 0; i < sz.width; i++)
diff[i] = src1[i] - src2[i];
}
- diff = buf.data();
- for( i = 0; i < len; i++, mat += matstep )
+ diff = diff_buffer;
+ for (int i = 0; i < len; i++, mat += matstep)
{
double row_sum = 0;
- j = 0;
- #if CV_ENABLE_UNROLLED
+ int j = 0;
+#if CV_ENABLE_UNROLLED
for(; j <= len - 4; j += 4 )
row_sum += diff[j]*mat[j] + diff[j+1]*mat[j+1] +
diff[j+2]*mat[j+2] + diff[j+3]*mat[j+3];
- #endif
- for( ; j < len; j++ )
+#endif
+ for (; j < len; j++)
row_sum += diff[j]*mat[j];
result += row_sum * diff[i];
}
}
- else
- CV_Error( CV_StsUnsupportedFormat, "" );
+ return result;
+}
- return std::sqrt(result);
+MahalanobisImplFunc getMahalanobisImplFunc(int depth)
+{
+ if (depth == CV_32F)
+ return (MahalanobisImplFunc)MahalanobisImpl<float>;
+ if (depth == CV_64F)
+ return (MahalanobisImplFunc)MahalanobisImpl<double>;
+ CV_Assert(0 && "Not supported");
}
+
+#if !defined(CV_MULTRANSPOSED_BASELINE_ONLY) || defined(CV_CPU_BASELINE_MODE)
/****************************************************************************************\
* MulTransposed *
\****************************************************************************************/
-namespace cv
-{
-
template<typename sT, typename dT> static void
-MulTransposedR( const Mat& srcmat, Mat& dstmat, const Mat& deltamat, double scale )
+MulTransposedR(const Mat& srcmat, const Mat& dstmat, const Mat& deltamat, double scale)
{
int i, j, k;
const sT* src = srcmat.ptr<sT>();
- dT* dst = dstmat.ptr<dT>();
+ dT* dst = (dT*)dstmat.ptr<dT>();
const dT* delta = deltamat.ptr<dT>();
size_t srcstep = srcmat.step/sizeof(src[0]);
size_t dststep = dstmat.step/sizeof(dst[0]);
template<typename sT, typename dT> static void
-MulTransposedL( const Mat& srcmat, Mat& dstmat, const Mat& deltamat, double scale )
+MulTransposedL(const Mat& srcmat, const Mat& dstmat, const Mat& deltamat, double scale)
{
int i, j, k;
const sT* src = srcmat.ptr<sT>();
- dT* dst = dstmat.ptr<dT>();
+ dT* dst = (dT*)dstmat.ptr<dT>();
const dT* delta = deltamat.ptr<dT>();
size_t srcstep = srcmat.step/sizeof(src[0]);
size_t dststep = dstmat.step/sizeof(dst[0]);
}
}
-typedef void (*MulTransposedFunc)(const Mat& src, Mat& dst, const Mat& delta, double scale);
-
-}
-
-void cv::mulTransposed( InputArray _src, OutputArray _dst, bool ata,
- InputArray _delta, double scale, int dtype )
+MulTransposedFunc getMulTransposedFunc(int stype, int dtype, bool ata)
{
- CV_INSTRUMENT_REGION();
-
- Mat src = _src.getMat(), delta = _delta.getMat();
- const int gemm_level = 100; // boundary above which GEMM is faster.
- int stype = src.type();
- dtype = std::max(std::max(CV_MAT_DEPTH(dtype >= 0 ? dtype : stype), delta.depth()), CV_32F);
- CV_Assert( src.channels() == 1 );
-
- if( !delta.empty() )
+ MulTransposedFunc func = NULL;
+ if (stype == CV_8U && dtype == CV_32F)
{
- CV_Assert_N( delta.channels() == 1,
- (delta.rows == src.rows || delta.rows == 1),
- (delta.cols == src.cols || delta.cols == 1));
- if( delta.type() != dtype )
- delta.convertTo(delta, dtype);
+ func = ata ? MulTransposedR<uchar,float>
+ : MulTransposedL<uchar,float>;
}
-
- int dsize = ata ? src.cols : src.rows;
- _dst.create( dsize, dsize, dtype );
- Mat dst = _dst.getMat();
-
- if( src.data == dst.data || (stype == dtype &&
- (dst.cols >= gemm_level && dst.rows >= gemm_level &&
- src.cols >= gemm_level && src.rows >= gemm_level)))
+ else if (stype == CV_8U && dtype == CV_64F)
{
- Mat src2;
- const Mat* tsrc = &src;
- if( !delta.empty() )
- {
- if( delta.size() == src.size() )
- subtract( src, delta, src2 );
- else
- {
- repeat(delta, src.rows/delta.rows, src.cols/delta.cols, src2);
- subtract( src, src2, src2 );
- }
- tsrc = &src2;
- }
- gemm( *tsrc, *tsrc, scale, Mat(), 0, dst, ata ? GEMM_1_T : GEMM_2_T );
+ func = ata ? MulTransposedR<uchar,double>
+ : MulTransposedL<uchar,double>;
}
- else
+ else if(stype == CV_16U && dtype == CV_32F)
{
- MulTransposedFunc func = 0;
- if(stype == CV_8U && dtype == CV_32F)
- {
- if(ata)
- func = MulTransposedR<uchar,float>;
- else
- func = MulTransposedL<uchar,float>;
- }
- else if(stype == CV_8U && dtype == CV_64F)
- {
- if(ata)
- func = MulTransposedR<uchar,double>;
- else
- func = MulTransposedL<uchar,double>;
- }
- else if(stype == CV_16U && dtype == CV_32F)
- {
- if(ata)
- func = MulTransposedR<ushort,float>;
- else
- func = MulTransposedL<ushort,float>;
- }
- else if(stype == CV_16U && dtype == CV_64F)
- {
- if(ata)
- func = MulTransposedR<ushort,double>;
- else
- func = MulTransposedL<ushort,double>;
- }
- else if(stype == CV_16S && dtype == CV_32F)
- {
- if(ata)
- func = MulTransposedR<short,float>;
- else
- func = MulTransposedL<short,float>;
- }
- else if(stype == CV_16S && dtype == CV_64F)
- {
- if(ata)
- func = MulTransposedR<short,double>;
- else
- func = MulTransposedL<short,double>;
- }
- else if(stype == CV_32F && dtype == CV_32F)
- {
- if(ata)
- func = MulTransposedR<float,float>;
- else
- func = MulTransposedL<float,float>;
- }
- else if(stype == CV_32F && dtype == CV_64F)
- {
- if(ata)
- func = MulTransposedR<float,double>;
- else
- func = MulTransposedL<float,double>;
- }
- else if(stype == CV_64F && dtype == CV_64F)
- {
- if(ata)
- func = MulTransposedR<double,double>;
- else
- func = MulTransposedL<double,double>;
- }
- if( !func )
- CV_Error( CV_StsUnsupportedFormat, "" );
-
- func( src, dst, delta, scale );
- completeSymm( dst, false );
+ func = ata ? MulTransposedR<ushort,float>
+ : MulTransposedL<ushort,float>;
+ }
+ else if(stype == CV_16U && dtype == CV_64F)
+ {
+ func = ata ? MulTransposedR<ushort,double>
+ : MulTransposedL<ushort,double>;
+ }
+ else if(stype == CV_16S && dtype == CV_32F)
+ {
+ func = ata ? MulTransposedR<short,float>
+ : MulTransposedL<short,float>;
+ }
+ else if(stype == CV_16S && dtype == CV_64F)
+ {
+ func = ata ? MulTransposedR<short,double>
+ : MulTransposedL<short,double>;
+ }
+ else if(stype == CV_32F && dtype == CV_32F)
+ {
+ func = ata ? MulTransposedR<float,float>
+ : MulTransposedL<float,float>;
+ }
+ else if(stype == CV_32F && dtype == CV_64F)
+ {
+ func = ata ? MulTransposedR<float,double>
+ : MulTransposedL<float,double>;
}
+ else if(stype == CV_64F && dtype == CV_64F)
+ {
+ func = ata ? MulTransposedR<double,double>
+ : MulTransposedL<double,double>;
+ }
+ CV_Assert(func && "Not supported");
+ return func;
}
+#endif // !defined(CV_MULTRANSPOSED_BASELINE_ONLY) || defined(CV_CPU_BASELINE_MODE)
+
/****************************************************************************************\
* Dot Product *
\****************************************************************************************/
-namespace cv
-{
-
-template<typename T> double
-dotProd_(const T* src1, const T* src2, int len)
+template<typename T> static inline
+double dotProd_(const T* src1, const T* src2, int len)
{
int i = 0;
double result = 0;
- #if CV_ENABLE_UNROLLED
+#if CV_ENABLE_UNROLLED
for( ; i <= len - 4; i += 4 )
result += (double)src1[i]*src2[i] + (double)src1[i+1]*src2[i+1] +
(double)src1[i+2]*src2[i+2] + (double)src1[i+3]*src2[i+3];
- #endif
+#endif
for( ; i < len; i++ )
result += (double)src1[i]*src2[i];
}
-static double dotProd_8u(const uchar* src1, const uchar* src2, int len)
+double dotProd_8u(const uchar* src1, const uchar* src2, int len)
{
double r = 0;
-#if ARITHM_USE_IPP
- CV_IPP_RUN(IPP_VERSION_X100 > 201800 || cv::ipp::getIppTopFeatures() != ippCPUID_SSE42, CV_INSTRUMENT_FUN_IPP(ippiDotProd_8u64f_C1R, src1, len*sizeof(uchar), src2, len*sizeof(uchar), ippiSize(len, 1), &r) >= 0, r);
-#endif
int i = 0;
#if CV_SIMD
}
-static double dotProd_8s(const schar* src1, const schar* src2, int len)
+double dotProd_8s(const schar* src1, const schar* src2, int len)
{
double r = 0.0;
int i = 0;
return r + dotProd_(src1, src2, len - i);
}
-static double dotProd_16u(const ushort* src1, const ushort* src2, int len)
+double dotProd_16u(const ushort* src1, const ushort* src2, int len)
{
-#if ARITHM_USE_IPP
- double r = 0;
- CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiDotProd_16u64f_C1R, src1, len*sizeof(ushort), src2, len*sizeof(ushort), ippiSize(len, 1), &r) >= 0, r);
-#endif
return dotProd_(src1, src2, len);
}
-static double dotProd_16s(const short* src1, const short* src2, int len)
+double dotProd_16s(const short* src1, const short* src2, int len)
{
-#if ARITHM_USE_IPP && (IPP_VERSION_X100 != 900) // bug in IPP 9.0.0
- double r = 0;
- CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiDotProd_16s64f_C1R, src1, len*sizeof(short), src2, len*sizeof(short), ippiSize(len, 1), &r) >= 0, r);
-#endif
return dotProd_(src1, src2, len);
}
-static double dotProd_32s(const int* src1, const int* src2, int len)
+double dotProd_32s(const int* src1, const int* src2, int len)
{
-#if ARITHM_USE_IPP
- double r = 0;
- CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiDotProd_32s64f_C1R, src1, len*sizeof(int), src2, len*sizeof(int), ippiSize(len, 1), &r) >= 0, r);
-#endif
return dotProd_(src1, src2, len);
}
-static double dotProd_32f(const float* src1, const float* src2, int len)
+double dotProd_32f(const float* src1, const float* src2, int len)
{
double r = 0.0;
-
-#if ARITHM_USE_IPP
- CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiDotProd_32f64f_C1R, src1, len*sizeof(float), src2, len*sizeof(float), ippiSize(len, 1), &r, ippAlgHintFast) >= 0, r);
-#endif
int i = 0;
#if CV_SIMD
return r + dotProd_(src1, src2, len - i);
}
-static double dotProd_64f(const double* src1, const double* src2, int len)
+double dotProd_64f(const double* src1, const double* src2, int len)
{
-#if ARITHM_USE_IPP
- double r = 0;
- CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippsDotProd_64f, src1, src2, len, &r) >= 0, r);
-#endif
-
return dotProd_(src1, src2, len);
}
-
-typedef double (*DotProdFunc)(const uchar* src1, const uchar* src2, int len);
-
-static DotProdFunc getDotProdFunc(int depth)
-{
- static DotProdFunc dotProdTab[] =
- {
- (DotProdFunc)GET_OPTIMIZED(dotProd_8u), (DotProdFunc)GET_OPTIMIZED(dotProd_8s),
- (DotProdFunc)dotProd_16u, (DotProdFunc)dotProd_16s,
- (DotProdFunc)dotProd_32s, (DotProdFunc)GET_OPTIMIZED(dotProd_32f),
- (DotProdFunc)dotProd_64f, 0
- };
-
- return dotProdTab[depth];
-}
-
-double Mat::dot(InputArray _mat) const
-{
- CV_INSTRUMENT_REGION();
-
- Mat mat = _mat.getMat();
- int cn = channels();
- DotProdFunc func = getDotProdFunc(depth());
- CV_Assert_N( mat.type() == type(), mat.size == size, func != 0 );
-
- if( isContinuous() && mat.isContinuous() )
- {
- size_t len = total()*cn;
- if( len == (size_t)(int)len )
- return func(data, mat.data, (int)len);
- }
-
- const Mat* arrays[] = {this, &mat, 0};
- uchar* ptrs[2] = {};
- NAryMatIterator it(arrays, ptrs);
- int len = (int)(it.size*cn);
- double r = 0;
-
- for( size_t i = 0; i < it.nplanes; i++, ++it )
- r += func( ptrs[0], ptrs[1], len );
-
- return r;
-}
-
-}
-
-/****************************************************************************************\
-* Earlier API *
-\****************************************************************************************/
-
-CV_IMPL void cvGEMM( const CvArr* Aarr, const CvArr* Barr, double alpha,
- const CvArr* Carr, double beta, CvArr* Darr, int flags )
-{
- cv::Mat A = cv::cvarrToMat(Aarr), B = cv::cvarrToMat(Barr);
- cv::Mat C, D = cv::cvarrToMat(Darr);
-
- if( Carr )
- C = cv::cvarrToMat(Carr);
-
- CV_Assert_N( (D.rows == ((flags & CV_GEMM_A_T) == 0 ? A.rows : A.cols)),
- (D.cols == ((flags & CV_GEMM_B_T) == 0 ? B.cols : B.rows)),
- D.type() == A.type() );
-
- gemm( A, B, alpha, C, beta, D, flags );
-}
-
-
-CV_IMPL void
-cvTransform( const CvArr* srcarr, CvArr* dstarr,
- const CvMat* transmat, const CvMat* shiftvec )
-{
- cv::Mat m = cv::cvarrToMat(transmat), src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
-
- if( shiftvec )
- {
- cv::Mat v = cv::cvarrToMat(shiftvec).reshape(1,m.rows),
- _m(m.rows, m.cols + 1, m.type()), m1 = _m.colRange(0,m.cols), v1 = _m.col(m.cols);
- m.convertTo(m1, m1.type());
- v.convertTo(v1, v1.type());
- m = _m;
- }
-
- CV_Assert_N( dst.depth() == src.depth(), dst.channels() == m.rows );
- cv::transform( src, dst, m );
-}
-
-
-CV_IMPL void
-cvPerspectiveTransform( const CvArr* srcarr, CvArr* dstarr, const CvMat* mat )
-{
- cv::Mat m = cv::cvarrToMat(mat), src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
-
- CV_Assert_N( dst.type() == src.type(), dst.channels() == m.rows-1 );
- cv::perspectiveTransform( src, dst, m );
-}
-
-
-CV_IMPL void cvScaleAdd( const CvArr* srcarr1, CvScalar scale,
- const CvArr* srcarr2, CvArr* dstarr )
-{
- cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr);
-
- CV_Assert_N( src1.size == dst.size, src1.type() == dst.type() );
- cv::scaleAdd( src1, scale.val[0], cv::cvarrToMat(srcarr2), dst );
-}
-
-
-CV_IMPL void
-cvCalcCovarMatrix( const CvArr** vecarr, int count,
- CvArr* covarr, CvArr* avgarr, int flags )
-{
- cv::Mat cov0 = cv::cvarrToMat(covarr), cov = cov0, mean0, mean;
- CV_Assert_N( vecarr != 0, count >= 1 );
-
- if( avgarr )
- mean = mean0 = cv::cvarrToMat(avgarr);
-
- if( (flags & CV_COVAR_COLS) != 0 || (flags & CV_COVAR_ROWS) != 0 )
- {
-
- cv::Mat data = cv::cvarrToMat(vecarr[0]);
- cv::calcCovarMatrix( data, cov, mean, flags, cov.type() );
- }
- else
- {
- std::vector<cv::Mat> data(count);
- for( int i = 0; i < count; i++ )
- data[i] = cv::cvarrToMat(vecarr[i]);
- cv::calcCovarMatrix( &data[0], count, cov, mean, flags, cov.type() );
- }
-
- if( mean.data != mean0.data && mean0.data )
- mean.convertTo(mean0, mean0.type());
-
- if( cov.data != cov0.data )
- cov.convertTo(cov0, cov0.type());
-}
-
-
-CV_IMPL double
-cvMahalanobis( const CvArr* srcAarr, const CvArr* srcBarr, const CvArr* matarr )
-{
- return cv::Mahalanobis(cv::cvarrToMat(srcAarr),
- cv::cvarrToMat(srcBarr), cv::cvarrToMat(matarr));
-}
-
-CV_IMPL void
-cvMulTransposed( const CvArr* srcarr, CvArr* dstarr,
- int order, const CvArr* deltaarr, double scale )
-{
- cv::Mat src = cv::cvarrToMat(srcarr), dst0 = cv::cvarrToMat(dstarr), dst = dst0, delta;
- if( deltaarr )
- delta = cv::cvarrToMat(deltaarr);
- cv::mulTransposed( src, dst, order != 0, delta, scale, dst.type());
- if( dst.data != dst0.data )
- dst.convertTo(dst0, dst0.type());
-}
-
-CV_IMPL double cvDotProduct( const CvArr* srcAarr, const CvArr* srcBarr )
-{
- return cv::cvarrToMat(srcAarr).dot(cv::cvarrToMat(srcBarr));
-}
-
-
-CV_IMPL void
-cvCalcPCA( const CvArr* data_arr, CvArr* avg_arr, CvArr* eigenvals, CvArr* eigenvects, int flags )
-{
- cv::Mat data = cv::cvarrToMat(data_arr), mean0 = cv::cvarrToMat(avg_arr);
- cv::Mat evals0 = cv::cvarrToMat(eigenvals), evects0 = cv::cvarrToMat(eigenvects);
- cv::Mat mean = mean0, evals = evals0, evects = evects0;
-
- cv::PCA pca;
- pca.mean = mean;
- pca.eigenvalues = evals;
- pca.eigenvectors = evects;
-
- pca(data, (flags & CV_PCA_USE_AVG) ? mean : cv::Mat(),
- flags, !evals.empty() ? evals.rows + evals.cols - 1 : 0);
-
- if( pca.mean.size() == mean.size() )
- pca.mean.convertTo( mean, mean.type() );
- else
- {
- cv::Mat temp; pca.mean.convertTo( temp, mean.type() );
- transpose( temp, mean );
- }
-
- evals = pca.eigenvalues;
- evects = pca.eigenvectors;
- int ecount0 = evals0.cols + evals0.rows - 1;
- int ecount = evals.cols + evals.rows - 1;
-
- CV_Assert_N( (evals0.cols == 1 || evals0.rows == 1),
- ecount0 <= ecount,
- evects0.cols == evects.cols,
- evects0.rows == ecount0 );
-
- cv::Mat temp = evals0;
- if( evals.rows == 1 )
- evals.colRange(0, ecount0).convertTo(temp, evals0.type());
- else
- evals.rowRange(0, ecount0).convertTo(temp, evals0.type());
- if( temp.data != evals0.data )
- transpose(temp, evals0);
- evects.rowRange(0, ecount0).convertTo( evects0, evects0.type() );
-
- // otherwise some datatype's or size's were incorrect, so the output arrays have been reallocated
- CV_Assert( mean0.data == mean.data );
-}
-
-
-CV_IMPL void
-cvProjectPCA( const CvArr* data_arr, const CvArr* avg_arr,
- const CvArr* eigenvects, CvArr* result_arr )
-{
- cv::Mat data = cv::cvarrToMat(data_arr), mean = cv::cvarrToMat(avg_arr);
- cv::Mat evects = cv::cvarrToMat(eigenvects), dst0 = cv::cvarrToMat(result_arr), dst = dst0;
-
- cv::PCA pca;
- pca.mean = mean;
- int n;
- if( mean.rows == 1 )
- {
- CV_Assert_N(dst.cols <= evects.rows, dst.rows == data.rows);
- n = dst.cols;
- }
- else
- {
- CV_Assert_N(dst.rows <= evects.rows, dst.cols == data.cols);
- n = dst.rows;
- }
- pca.eigenvectors = evects.rowRange(0, n);
-
- cv::Mat result = pca.project(data);
- if( result.cols != dst.cols )
- result = result.reshape(1, 1);
- result.convertTo(dst, dst.type());
-
- CV_Assert(dst0.data == dst.data);
-}
-
-
-CV_IMPL void
-cvBackProjectPCA( const CvArr* proj_arr, const CvArr* avg_arr,
- const CvArr* eigenvects, CvArr* result_arr )
-{
- cv::Mat data = cv::cvarrToMat(proj_arr), mean = cv::cvarrToMat(avg_arr);
- cv::Mat evects = cv::cvarrToMat(eigenvects), dst0 = cv::cvarrToMat(result_arr), dst = dst0;
-
- cv::PCA pca;
- pca.mean = mean;
- int n;
- if( mean.rows == 1 )
- {
- CV_Assert_N(data.cols <= evects.rows, dst.rows == data.rows);
- n = data.cols;
- }
- else
- {
- CV_Assert_N(data.rows <= evects.rows, dst.cols == data.cols);
- n = data.rows;
- }
- pca.eigenvectors = evects.rowRange(0, n);
-
- cv::Mat result = pca.backProject(data);
- result.convertTo(dst, dst.type());
-
- CV_Assert(dst0.data == dst.data);
-}
-
-/* End of file. */
+#endif
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+} // namespace
\ No newline at end of file
{
CV_Assert( i < 0 );
Mat& m = *(Mat*)obj;
- if( allowTransposed )
+ if (allowTransposed && !m.empty() &&
+ d == 2 && m.dims == 2 &&
+ m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] &&
+ m.isContinuous())
{
- if( !m.isContinuous() )
- {
- CV_Assert(!fixedType() && !fixedSize());
- m.release();
- }
-
- if( d == 2 && m.dims == 2 && m.data &&
- m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] )
- return;
+ return;
}
if(fixedType())
if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
mtype = m.type();
else
- CV_Assert(CV_MAT_TYPE(mtype) == m.type());
+ CV_CheckTypeEQ(m.type(), CV_MAT_TYPE(mtype), "");
}
if(fixedSize())
{
- CV_Assert(m.dims == d);
+ CV_CheckEQ(m.dims, d, "");
for(int j = 0; j < d; ++j)
- CV_Assert(m.size[j] == sizes[j]);
+ CV_CheckEQ(m.size[j], sizes[j], "");
}
m.create(d, sizes, mtype);
return;
{
CV_Assert( i < 0 );
UMat& m = *(UMat*)obj;
- if( allowTransposed )
+ if (allowTransposed && !m.empty() &&
+ d == 2 && m.dims == 2 &&
+ m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] &&
+ m.isContinuous())
{
- if( !m.isContinuous() )
- {
- CV_Assert(!fixedType() && !fixedSize());
- m.release();
- }
-
- if( d == 2 && m.dims == 2 && !m.empty() &&
- m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] )
- return;
+ return;
}
if(fixedType())
if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
mtype = m.type();
else
- CV_Assert(CV_MAT_TYPE(mtype) == m.type());
+ CV_CheckTypeEQ(m.type(), CV_MAT_TYPE(mtype), "");
}
if(fixedSize())
{
- CV_Assert(m.dims == d);
+ CV_CheckEQ(m.dims, d, "");
for(int j = 0; j < d; ++j)
- CV_Assert(m.size[j] == sizes[j]);
+ CV_CheckEQ(m.size[j], sizes[j], "");
}
m.create(d, sizes, mtype);
return;
#undef CV_IPP_RUN
#define CV_IPP_RUN(c, f, ...)
+#include "mean.simd.hpp"
+#include "mean.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
+
+namespace cv {
+
#if defined HAVE_IPP
-namespace cv
-{
static bool ipp_mean( Mat &src, Mat &mask, Scalar &ret )
{
CV_INSTRUMENT_REGION_IPP();
return false;
#endif
}
-}
#endif
-cv::Scalar cv::mean( InputArray _src, InputArray _mask )
+Scalar mean(InputArray _src, InputArray _mask)
{
CV_INSTRUMENT_REGION();
return s*(nz0 ? 1./nz0 : 0);
}
-//==================================================================================================
-
-namespace cv {
-
-template <typename T, typename ST, typename SQT>
-struct SumSqr_SIMD
+static SumSqrFunc getSumSqrFunc(int depth)
{
- int operator () (const T *, const uchar *, ST *, SQT *, int, int) const
- {
- return 0;
- }
-};
-
-#if CV_SIMD
-
-template <>
-struct SumSqr_SIMD<uchar, int, int>
-{
- int operator () (const uchar * src0, const uchar * mask, int * sum, int * sqsum, int len, int cn) const
- {
- if (mask || (cn != 1 && cn != 2 && cn != 4))
- return 0;
- len *= cn;
-
- int x = 0;
- v_int32 v_sum = vx_setzero_s32();
- v_int32 v_sqsum = vx_setzero_s32();
-
- const int len0 = len & -v_uint8::nlanes;
- while(x < len0)
- {
- const int len_tmp = min(x + 256*v_uint16::nlanes, len0);
- v_uint16 v_sum16 = vx_setzero_u16();
- for ( ; x < len_tmp; x += v_uint8::nlanes)
- {
- v_uint16 v_src0 = vx_load_expand(src0 + x);
- v_uint16 v_src1 = vx_load_expand(src0 + x + v_uint16::nlanes);
- v_sum16 += v_src0 + v_src1;
- v_int16 v_tmp0, v_tmp1;
- v_zip(v_reinterpret_as_s16(v_src0), v_reinterpret_as_s16(v_src1), v_tmp0, v_tmp1);
- v_sqsum += v_dotprod(v_tmp0, v_tmp0) + v_dotprod(v_tmp1, v_tmp1);
- }
- v_uint32 v_half0, v_half1;
- v_expand(v_sum16, v_half0, v_half1);
- v_sum += v_reinterpret_as_s32(v_half0 + v_half1);
- }
- if (x <= len - v_uint16::nlanes)
- {
- v_uint16 v_src = vx_load_expand(src0 + x);
- v_uint16 v_half = v_combine_high(v_src, v_src);
-
- v_uint32 v_tmp0, v_tmp1;
- v_expand(v_src + v_half, v_tmp0, v_tmp1);
- v_sum += v_reinterpret_as_s32(v_tmp0);
-
- v_int16 v_tmp2, v_tmp3;
- v_zip(v_reinterpret_as_s16(v_src), v_reinterpret_as_s16(v_half), v_tmp2, v_tmp3);
- v_sqsum += v_dotprod(v_tmp2, v_tmp2);
- x += v_uint16::nlanes;
- }
-
- if (cn == 1)
- {
- *sum += v_reduce_sum(v_sum);
- *sqsum += v_reduce_sum(v_sqsum);
- }
- else
- {
- int CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[2 * v_int32::nlanes];
- v_store(ar, v_sum);
- v_store(ar + v_int32::nlanes, v_sqsum);
- for (int i = 0; i < v_int32::nlanes; ++i)
- {
- sum[i % cn] += ar[i];
- sqsum[i % cn] += ar[v_int32::nlanes + i];
- }
- }
- v_cleanup();
- return x / cn;
- }
-};
-
-template <>
-struct SumSqr_SIMD<schar, int, int>
-{
- int operator () (const schar * src0, const uchar * mask, int * sum, int * sqsum, int len, int cn) const
- {
- if (mask || (cn != 1 && cn != 2 && cn != 4))
- return 0;
- len *= cn;
-
- int x = 0;
- v_int32 v_sum = vx_setzero_s32();
- v_int32 v_sqsum = vx_setzero_s32();
-
- const int len0 = len & -v_int8::nlanes;
- while (x < len0)
- {
- const int len_tmp = min(x + 256 * v_int16::nlanes, len0);
- v_int16 v_sum16 = vx_setzero_s16();
- for (; x < len_tmp; x += v_int8::nlanes)
- {
- v_int16 v_src0 = vx_load_expand(src0 + x);
- v_int16 v_src1 = vx_load_expand(src0 + x + v_int16::nlanes);
- v_sum16 += v_src0 + v_src1;
- v_int16 v_tmp0, v_tmp1;
- v_zip(v_src0, v_src1, v_tmp0, v_tmp1);
- v_sqsum += v_dotprod(v_tmp0, v_tmp0) + v_dotprod(v_tmp1, v_tmp1);
- }
- v_int32 v_half0, v_half1;
- v_expand(v_sum16, v_half0, v_half1);
- v_sum += v_half0 + v_half1;
- }
- if (x <= len - v_int16::nlanes)
- {
- v_int16 v_src = vx_load_expand(src0 + x);
- v_int16 v_half = v_combine_high(v_src, v_src);
-
- v_int32 v_tmp0, v_tmp1;
- v_expand(v_src + v_half, v_tmp0, v_tmp1);
- v_sum += v_tmp0;
-
- v_int16 v_tmp2, v_tmp3;
- v_zip(v_src, v_half, v_tmp2, v_tmp3);
- v_sqsum += v_dotprod(v_tmp2, v_tmp2);
- x += v_int16::nlanes;
- }
-
- if (cn == 1)
- {
- *sum += v_reduce_sum(v_sum);
- *sqsum += v_reduce_sum(v_sqsum);
- }
- else
- {
- int CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[2 * v_int32::nlanes];
- v_store(ar, v_sum);
- v_store(ar + v_int32::nlanes, v_sqsum);
- for (int i = 0; i < v_int32::nlanes; ++i)
- {
- sum[i % cn] += ar[i];
- sqsum[i % cn] += ar[v_int32::nlanes + i];
- }
- }
- v_cleanup();
- return x / cn;
- }
-};
-
-#endif
-
-template<typename T, typename ST, typename SQT>
-static int sumsqr_(const T* src0, const uchar* mask, ST* sum, SQT* sqsum, int len, int cn )
-{
- const T* src = src0;
-
- if( !mask )
- {
- SumSqr_SIMD<T, ST, SQT> vop;
- int x = vop(src0, mask, sum, sqsum, len, cn), k = cn % 4;
- src = src0 + x * cn;
-
- if( k == 1 )
- {
- ST s0 = sum[0];
- SQT sq0 = sqsum[0];
- for(int i = x; i < len; i++, src += cn )
- {
- T v = src[0];
- s0 += v; sq0 += (SQT)v*v;
- }
- sum[0] = s0;
- sqsum[0] = sq0;
- }
- else if( k == 2 )
- {
- ST s0 = sum[0], s1 = sum[1];
- SQT sq0 = sqsum[0], sq1 = sqsum[1];
- for(int i = x; i < len; i++, src += cn )
- {
- T v0 = src[0], v1 = src[1];
- s0 += v0; sq0 += (SQT)v0*v0;
- s1 += v1; sq1 += (SQT)v1*v1;
- }
- sum[0] = s0; sum[1] = s1;
- sqsum[0] = sq0; sqsum[1] = sq1;
- }
- else if( k == 3 )
- {
- ST s0 = sum[0], s1 = sum[1], s2 = sum[2];
- SQT sq0 = sqsum[0], sq1 = sqsum[1], sq2 = sqsum[2];
- for(int i = x; i < len; i++, src += cn )
- {
- T v0 = src[0], v1 = src[1], v2 = src[2];
- s0 += v0; sq0 += (SQT)v0*v0;
- s1 += v1; sq1 += (SQT)v1*v1;
- s2 += v2; sq2 += (SQT)v2*v2;
- }
- sum[0] = s0; sum[1] = s1; sum[2] = s2;
- sqsum[0] = sq0; sqsum[1] = sq1; sqsum[2] = sq2;
- }
-
- for( ; k < cn; k += 4 )
- {
- src = src0 + x * cn + k;
- ST s0 = sum[k], s1 = sum[k+1], s2 = sum[k+2], s3 = sum[k+3];
- SQT sq0 = sqsum[k], sq1 = sqsum[k+1], sq2 = sqsum[k+2], sq3 = sqsum[k+3];
- for(int i = x; i < len; i++, src += cn )
- {
- T v0, v1;
- v0 = src[0], v1 = src[1];
- s0 += v0; sq0 += (SQT)v0*v0;
- s1 += v1; sq1 += (SQT)v1*v1;
- v0 = src[2], v1 = src[3];
- s2 += v0; sq2 += (SQT)v0*v0;
- s3 += v1; sq3 += (SQT)v1*v1;
- }
- sum[k] = s0; sum[k+1] = s1;
- sum[k+2] = s2; sum[k+3] = s3;
- sqsum[k] = sq0; sqsum[k+1] = sq1;
- sqsum[k+2] = sq2; sqsum[k+3] = sq3;
- }
- return len;
- }
-
- int i, nzm = 0;
-
- if( cn == 1 )
- {
- ST s0 = sum[0];
- SQT sq0 = sqsum[0];
- for( i = 0; i < len; i++ )
- if( mask[i] )
- {
- T v = src[i];
- s0 += v; sq0 += (SQT)v*v;
- nzm++;
- }
- sum[0] = s0;
- sqsum[0] = sq0;
- }
- else if( cn == 3 )
- {
- ST s0 = sum[0], s1 = sum[1], s2 = sum[2];
- SQT sq0 = sqsum[0], sq1 = sqsum[1], sq2 = sqsum[2];
- for( i = 0; i < len; i++, src += 3 )
- if( mask[i] )
- {
- T v0 = src[0], v1 = src[1], v2 = src[2];
- s0 += v0; sq0 += (SQT)v0*v0;
- s1 += v1; sq1 += (SQT)v1*v1;
- s2 += v2; sq2 += (SQT)v2*v2;
- nzm++;
- }
- sum[0] = s0; sum[1] = s1; sum[2] = s2;
- sqsum[0] = sq0; sqsum[1] = sq1; sqsum[2] = sq2;
- }
- else
- {
- for( i = 0; i < len; i++, src += cn )
- if( mask[i] )
- {
- for( int k = 0; k < cn; k++ )
- {
- T v = src[k];
- ST s = sum[k] + v;
- SQT sq = sqsum[k] + (SQT)v*v;
- sum[k] = s; sqsum[k] = sq;
- }
- nzm++;
- }
- }
- return nzm;
-}
-
-
-static int sqsum8u( const uchar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn )
-{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
-
-static int sqsum8s( const schar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn )
-{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
-
-static int sqsum16u( const ushort* src, const uchar* mask, int* sum, double* sqsum, int len, int cn )
-{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
-
-static int sqsum16s( const short* src, const uchar* mask, int* sum, double* sqsum, int len, int cn )
-{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
-
-static int sqsum32s( const int* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
-{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
-
-static int sqsum32f( const float* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
-{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
-
-static int sqsum64f( const double* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
-{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
-
-typedef int (*SumSqrFunc)(const uchar*, const uchar* mask, uchar*, uchar*, int, int);
-
-static SumSqrFunc getSumSqrTab(int depth)
-{
- static SumSqrFunc sumSqrTab[] =
- {
- (SumSqrFunc)GET_OPTIMIZED(sqsum8u), (SumSqrFunc)sqsum8s, (SumSqrFunc)sqsum16u, (SumSqrFunc)sqsum16s,
- (SumSqrFunc)sqsum32s, (SumSqrFunc)GET_OPTIMIZED(sqsum32f), (SumSqrFunc)sqsum64f, 0
- };
-
- return sumSqrTab[depth];
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(getSumSqrFunc, (depth),
+ CV_CPU_DISPATCH_MODES_ALL);
}
#ifdef HAVE_OPENCL
}
#endif
-} // cv::
-
-void cv::meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray _mask )
+void meanStdDev(InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray _mask)
{
CV_INSTRUMENT_REGION();
int k, cn = src.channels(), depth = src.depth();
- SumSqrFunc func = getSumSqrTab(depth);
+ SumSqrFunc func = getSumSqrFunc(depth);
CV_Assert( func != 0 );
dptr[k] = 0;
}
}
+
+} // namespace
--- /dev/null
+// 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 "precomp.hpp"
+#include "stat.hpp"
+
+namespace cv {
+typedef int (*SumSqrFunc)(const uchar*, const uchar* mask, uchar*, uchar*, int, int);
+
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+
+SumSqrFunc getSumSqrFunc(int depth);
+
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
+
+template <typename T, typename ST, typename SQT>
+struct SumSqr_SIMD
+{
+ inline int operator () (const T *, const uchar *, ST *, SQT *, int, int) const
+ {
+ return 0;
+ }
+};
+
+#if CV_SIMD
+
+template <>
+struct SumSqr_SIMD<uchar, int, int>
+{
+ int operator () (const uchar * src0, const uchar * mask, int * sum, int * sqsum, int len, int cn) const
+ {
+ if (mask || (cn != 1 && cn != 2 && cn != 4))
+ return 0;
+ len *= cn;
+
+ int x = 0;
+ v_int32 v_sum = vx_setzero_s32();
+ v_int32 v_sqsum = vx_setzero_s32();
+
+ const int len0 = len & -v_uint8::nlanes;
+ while(x < len0)
+ {
+ const int len_tmp = min(x + 256*v_uint16::nlanes, len0);
+ v_uint16 v_sum16 = vx_setzero_u16();
+ for ( ; x < len_tmp; x += v_uint8::nlanes)
+ {
+ v_uint16 v_src0 = vx_load_expand(src0 + x);
+ v_uint16 v_src1 = vx_load_expand(src0 + x + v_uint16::nlanes);
+ v_sum16 += v_src0 + v_src1;
+ v_int16 v_tmp0, v_tmp1;
+ v_zip(v_reinterpret_as_s16(v_src0), v_reinterpret_as_s16(v_src1), v_tmp0, v_tmp1);
+ v_sqsum += v_dotprod(v_tmp0, v_tmp0) + v_dotprod(v_tmp1, v_tmp1);
+ }
+ v_uint32 v_half0, v_half1;
+ v_expand(v_sum16, v_half0, v_half1);
+ v_sum += v_reinterpret_as_s32(v_half0 + v_half1);
+ }
+ if (x <= len - v_uint16::nlanes)
+ {
+ v_uint16 v_src = vx_load_expand(src0 + x);
+ v_uint16 v_half = v_combine_high(v_src, v_src);
+
+ v_uint32 v_tmp0, v_tmp1;
+ v_expand(v_src + v_half, v_tmp0, v_tmp1);
+ v_sum += v_reinterpret_as_s32(v_tmp0);
+
+ v_int16 v_tmp2, v_tmp3;
+ v_zip(v_reinterpret_as_s16(v_src), v_reinterpret_as_s16(v_half), v_tmp2, v_tmp3);
+ v_sqsum += v_dotprod(v_tmp2, v_tmp2);
+ x += v_uint16::nlanes;
+ }
+
+ if (cn == 1)
+ {
+ *sum += v_reduce_sum(v_sum);
+ *sqsum += v_reduce_sum(v_sqsum);
+ }
+ else
+ {
+ int CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[2 * v_int32::nlanes];
+ v_store(ar, v_sum);
+ v_store(ar + v_int32::nlanes, v_sqsum);
+ for (int i = 0; i < v_int32::nlanes; ++i)
+ {
+ sum[i % cn] += ar[i];
+ sqsum[i % cn] += ar[v_int32::nlanes + i];
+ }
+ }
+ v_cleanup();
+ return x / cn;
+ }
+};
+
+template <>
+struct SumSqr_SIMD<schar, int, int>
+{
+ int operator () (const schar * src0, const uchar * mask, int * sum, int * sqsum, int len, int cn) const
+ {
+ if (mask || (cn != 1 && cn != 2 && cn != 4))
+ return 0;
+ len *= cn;
+
+ int x = 0;
+ v_int32 v_sum = vx_setzero_s32();
+ v_int32 v_sqsum = vx_setzero_s32();
+
+ const int len0 = len & -v_int8::nlanes;
+ while (x < len0)
+ {
+ const int len_tmp = min(x + 256 * v_int16::nlanes, len0);
+ v_int16 v_sum16 = vx_setzero_s16();
+ for (; x < len_tmp; x += v_int8::nlanes)
+ {
+ v_int16 v_src0 = vx_load_expand(src0 + x);
+ v_int16 v_src1 = vx_load_expand(src0 + x + v_int16::nlanes);
+ v_sum16 += v_src0 + v_src1;
+ v_int16 v_tmp0, v_tmp1;
+ v_zip(v_src0, v_src1, v_tmp0, v_tmp1);
+ v_sqsum += v_dotprod(v_tmp0, v_tmp0) + v_dotprod(v_tmp1, v_tmp1);
+ }
+ v_int32 v_half0, v_half1;
+ v_expand(v_sum16, v_half0, v_half1);
+ v_sum += v_half0 + v_half1;
+ }
+ if (x <= len - v_int16::nlanes)
+ {
+ v_int16 v_src = vx_load_expand(src0 + x);
+ v_int16 v_half = v_combine_high(v_src, v_src);
+
+ v_int32 v_tmp0, v_tmp1;
+ v_expand(v_src + v_half, v_tmp0, v_tmp1);
+ v_sum += v_tmp0;
+
+ v_int16 v_tmp2, v_tmp3;
+ v_zip(v_src, v_half, v_tmp2, v_tmp3);
+ v_sqsum += v_dotprod(v_tmp2, v_tmp2);
+ x += v_int16::nlanes;
+ }
+
+ if (cn == 1)
+ {
+ *sum += v_reduce_sum(v_sum);
+ *sqsum += v_reduce_sum(v_sqsum);
+ }
+ else
+ {
+ int CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[2 * v_int32::nlanes];
+ v_store(ar, v_sum);
+ v_store(ar + v_int32::nlanes, v_sqsum);
+ for (int i = 0; i < v_int32::nlanes; ++i)
+ {
+ sum[i % cn] += ar[i];
+ sqsum[i % cn] += ar[v_int32::nlanes + i];
+ }
+ }
+ v_cleanup();
+ return x / cn;
+ }
+};
+
+#endif
+
+template<typename T, typename ST, typename SQT>
+static int sumsqr_(const T* src0, const uchar* mask, ST* sum, SQT* sqsum, int len, int cn )
+{
+ const T* src = src0;
+
+ if( !mask )
+ {
+ SumSqr_SIMD<T, ST, SQT> vop;
+ int x = vop(src0, mask, sum, sqsum, len, cn), k = cn % 4;
+ src = src0 + x * cn;
+
+ if( k == 1 )
+ {
+ ST s0 = sum[0];
+ SQT sq0 = sqsum[0];
+ for(int i = x; i < len; i++, src += cn )
+ {
+ T v = src[0];
+ s0 += v; sq0 += (SQT)v*v;
+ }
+ sum[0] = s0;
+ sqsum[0] = sq0;
+ }
+ else if( k == 2 )
+ {
+ ST s0 = sum[0], s1 = sum[1];
+ SQT sq0 = sqsum[0], sq1 = sqsum[1];
+ for(int i = x; i < len; i++, src += cn )
+ {
+ T v0 = src[0], v1 = src[1];
+ s0 += v0; sq0 += (SQT)v0*v0;
+ s1 += v1; sq1 += (SQT)v1*v1;
+ }
+ sum[0] = s0; sum[1] = s1;
+ sqsum[0] = sq0; sqsum[1] = sq1;
+ }
+ else if( k == 3 )
+ {
+ ST s0 = sum[0], s1 = sum[1], s2 = sum[2];
+ SQT sq0 = sqsum[0], sq1 = sqsum[1], sq2 = sqsum[2];
+ for(int i = x; i < len; i++, src += cn )
+ {
+ T v0 = src[0], v1 = src[1], v2 = src[2];
+ s0 += v0; sq0 += (SQT)v0*v0;
+ s1 += v1; sq1 += (SQT)v1*v1;
+ s2 += v2; sq2 += (SQT)v2*v2;
+ }
+ sum[0] = s0; sum[1] = s1; sum[2] = s2;
+ sqsum[0] = sq0; sqsum[1] = sq1; sqsum[2] = sq2;
+ }
+
+ for( ; k < cn; k += 4 )
+ {
+ src = src0 + x * cn + k;
+ ST s0 = sum[k], s1 = sum[k+1], s2 = sum[k+2], s3 = sum[k+3];
+ SQT sq0 = sqsum[k], sq1 = sqsum[k+1], sq2 = sqsum[k+2], sq3 = sqsum[k+3];
+ for(int i = x; i < len; i++, src += cn )
+ {
+ T v0, v1;
+ v0 = src[0], v1 = src[1];
+ s0 += v0; sq0 += (SQT)v0*v0;
+ s1 += v1; sq1 += (SQT)v1*v1;
+ v0 = src[2], v1 = src[3];
+ s2 += v0; sq2 += (SQT)v0*v0;
+ s3 += v1; sq3 += (SQT)v1*v1;
+ }
+ sum[k] = s0; sum[k+1] = s1;
+ sum[k+2] = s2; sum[k+3] = s3;
+ sqsum[k] = sq0; sqsum[k+1] = sq1;
+ sqsum[k+2] = sq2; sqsum[k+3] = sq3;
+ }
+ return len;
+ }
+
+ int i, nzm = 0;
+
+ if( cn == 1 )
+ {
+ ST s0 = sum[0];
+ SQT sq0 = sqsum[0];
+ for( i = 0; i < len; i++ )
+ if( mask[i] )
+ {
+ T v = src[i];
+ s0 += v; sq0 += (SQT)v*v;
+ nzm++;
+ }
+ sum[0] = s0;
+ sqsum[0] = sq0;
+ }
+ else if( cn == 3 )
+ {
+ ST s0 = sum[0], s1 = sum[1], s2 = sum[2];
+ SQT sq0 = sqsum[0], sq1 = sqsum[1], sq2 = sqsum[2];
+ for( i = 0; i < len; i++, src += 3 )
+ if( mask[i] )
+ {
+ T v0 = src[0], v1 = src[1], v2 = src[2];
+ s0 += v0; sq0 += (SQT)v0*v0;
+ s1 += v1; sq1 += (SQT)v1*v1;
+ s2 += v2; sq2 += (SQT)v2*v2;
+ nzm++;
+ }
+ sum[0] = s0; sum[1] = s1; sum[2] = s2;
+ sqsum[0] = sq0; sqsum[1] = sq1; sqsum[2] = sq2;
+ }
+ else
+ {
+ for( i = 0; i < len; i++, src += cn )
+ if( mask[i] )
+ {
+ for( int k = 0; k < cn; k++ )
+ {
+ T v = src[k];
+ ST s = sum[k] + v;
+ SQT sq = sqsum[k] + (SQT)v*v;
+ sum[k] = s; sqsum[k] = sq;
+ }
+ nzm++;
+ }
+ }
+ return nzm;
+}
+
+
+static int sqsum8u( const uchar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn )
+{ CV_INSTRUMENT_REGION(); return sumsqr_(src, mask, sum, sqsum, len, cn); }
+
+static int sqsum8s( const schar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn )
+{ CV_INSTRUMENT_REGION(); return sumsqr_(src, mask, sum, sqsum, len, cn); }
+
+static int sqsum16u( const ushort* src, const uchar* mask, int* sum, double* sqsum, int len, int cn )
+{ CV_INSTRUMENT_REGION(); return sumsqr_(src, mask, sum, sqsum, len, cn); }
+
+static int sqsum16s( const short* src, const uchar* mask, int* sum, double* sqsum, int len, int cn )
+{ CV_INSTRUMENT_REGION(); return sumsqr_(src, mask, sum, sqsum, len, cn); }
+
+static int sqsum32s( const int* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
+{ CV_INSTRUMENT_REGION(); return sumsqr_(src, mask, sum, sqsum, len, cn); }
+
+static int sqsum32f( const float* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
+{ CV_INSTRUMENT_REGION(); return sumsqr_(src, mask, sum, sqsum, len, cn); }
+
+static int sqsum64f( const double* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
+{ CV_INSTRUMENT_REGION(); return sumsqr_(src, mask, sum, sqsum, len, cn); }
+
+SumSqrFunc getSumSqrFunc(int depth)
+{
+ CV_INSTRUMENT_REGION();
+ static SumSqrFunc sumSqrTab[] =
+ {
+ (SumSqrFunc)GET_OPTIMIZED(sqsum8u), (SumSqrFunc)sqsum8s, (SumSqrFunc)sqsum16u, (SumSqrFunc)sqsum16s,
+ (SumSqrFunc)sqsum32s, (SumSqrFunc)GET_OPTIMIZED(sqsum32f), (SumSqrFunc)sqsum64f, 0
+ };
+
+ return sumSqrTab[depth];
+}
+
+#endif
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+} // namespace
#include "precomp.hpp"
#include "opencl_kernels_core.hpp"
-namespace cv { namespace hal {
-
-#if CV_SIMD
-/*
- The trick with STORE_UNALIGNED/STORE_ALIGNED_NOCACHE is the following:
- on IA there are instructions movntps and such to which
- v_store_interleave(...., STORE_ALIGNED_NOCACHE) is mapped.
- Those instructions write directly into memory w/o touching cache
- that results in dramatic speed improvements, especially on
- large arrays (FullHD, 4K etc.).
-
- Those intrinsics require the destination address to be aligned
- by 16/32 bits (with SSE2 and AVX2, respectively).
- So we potentially split the processing into 3 stages:
- 1) the optional prefix part [0:i0), where we use simple unaligned stores.
- 2) the optional main part [i0:len - VECSZ], where we use "nocache" mode.
- But in some cases we have to use unaligned stores in this part.
- 3) the optional suffix part (the tail) (len - VECSZ:len) where we switch back to "unaligned" mode
- to process the remaining len - VECSZ elements.
- In principle there can be very poorly aligned data where there is no main part.
- For that we set i0=0 and use unaligned stores for the whole array.
-*/
-template<typename T, typename VecT> static void
-vecmerge_( const T** src, T* dst, int len, int cn )
-{
- const int VECSZ = VecT::nlanes;
- int i, i0 = 0;
- const T* src0 = src[0];
- const T* src1 = src[1];
-
- const int dstElemSize = cn * sizeof(T);
- int r = (int)((size_t)(void*)dst % (VECSZ*sizeof(T)));
- hal::StoreMode mode = hal::STORE_ALIGNED_NOCACHE;
- if( r != 0 )
- {
- mode = hal::STORE_UNALIGNED;
- if (r % dstElemSize == 0 && len > VECSZ*2)
- i0 = VECSZ - (r / dstElemSize);
- }
+#include "merge.simd.hpp"
+#include "merge.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
- if( cn == 2 )
- {
- for( i = 0; i < len; i += VECSZ )
- {
- if( i > len - VECSZ )
- {
- i = len - VECSZ;
- mode = hal::STORE_UNALIGNED;
- }
- VecT a = vx_load(src0 + i), b = vx_load(src1 + i);
- v_store_interleave(dst + i*cn, a, b, mode);
- if( i < i0 )
- {
- i = i0 - VECSZ;
- mode = hal::STORE_ALIGNED_NOCACHE;
- }
- }
- }
- else if( cn == 3 )
- {
- const T* src2 = src[2];
- for( i = 0; i < len; i += VECSZ )
- {
- if( i > len - VECSZ )
- {
- i = len - VECSZ;
- mode = hal::STORE_UNALIGNED;
- }
- VecT a = vx_load(src0 + i), b = vx_load(src1 + i), c = vx_load(src2 + i);
- v_store_interleave(dst + i*cn, a, b, c, mode);
- if( i < i0 )
- {
- i = i0 - VECSZ;
- mode = hal::STORE_ALIGNED_NOCACHE;
- }
- }
- }
- else
- {
- CV_Assert( cn == 4 );
- const T* src2 = src[2];
- const T* src3 = src[3];
- for( i = 0; i < len; i += VECSZ )
- {
- if( i > len - VECSZ )
- {
- i = len - VECSZ;
- mode = hal::STORE_UNALIGNED;
- }
- VecT a = vx_load(src0 + i), b = vx_load(src1 + i);
- VecT c = vx_load(src2 + i), d = vx_load(src3 + i);
- v_store_interleave(dst + i*cn, a, b, c, d, mode);
- if( i < i0 )
- {
- i = i0 - VECSZ;
- mode = hal::STORE_ALIGNED_NOCACHE;
- }
- }
- }
- vx_cleanup();
-}
-#endif
-
-template<typename T> static void
-merge_( const T** src, T* dst, int len, int cn )
-{
- int k = cn % 4 ? cn % 4 : 4;
- int i, j;
- if( k == 1 )
- {
- const T* src0 = src[0];
- for( i = j = 0; i < len; i++, j += cn )
- dst[j] = src0[i];
- }
- else if( k == 2 )
- {
- const T *src0 = src[0], *src1 = src[1];
- i = j = 0;
- for( ; i < len; i++, j += cn )
- {
- dst[j] = src0[i];
- dst[j+1] = src1[i];
- }
- }
- else if( k == 3 )
- {
- const T *src0 = src[0], *src1 = src[1], *src2 = src[2];
- i = j = 0;
- for( ; i < len; i++, j += cn )
- {
- dst[j] = src0[i];
- dst[j+1] = src1[i];
- dst[j+2] = src2[i];
- }
- }
- else
- {
- const T *src0 = src[0], *src1 = src[1], *src2 = src[2], *src3 = src[3];
- i = j = 0;
- for( ; i < len; i++, j += cn )
- {
- dst[j] = src0[i]; dst[j+1] = src1[i];
- dst[j+2] = src2[i]; dst[j+3] = src3[i];
- }
- }
-
- for( ; k < cn; k += 4 )
- {
- const T *src0 = src[k], *src1 = src[k+1], *src2 = src[k+2], *src3 = src[k+3];
- for( i = 0, j = k; i < len; i++, j += cn )
- {
- dst[j] = src0[i]; dst[j+1] = src1[i];
- dst[j+2] = src2[i]; dst[j+3] = src3[i];
- }
- }
-}
+namespace cv { namespace hal {
void merge8u(const uchar** src, uchar* dst, int len, int cn )
{
+ CV_INSTRUMENT_REGION();
CALL_HAL(merge8u, cv_hal_merge8u, src, dst, len, cn)
-#if CV_SIMD
- if( len >= v_uint8::nlanes && 2 <= cn && cn <= 4 )
- vecmerge_<uchar, v_uint8>(src, dst, len, cn);
- else
-#endif
- merge_(src, dst, len, cn);
+ CV_CPU_DISPATCH(merge8u, (src, dst, len, cn),
+ CV_CPU_DISPATCH_MODES_ALL);
}
void merge16u(const ushort** src, ushort* dst, int len, int cn )
{
+ CV_INSTRUMENT_REGION();
CALL_HAL(merge16u, cv_hal_merge16u, src, dst, len, cn)
-#if CV_SIMD
- if( len >= v_uint16::nlanes && 2 <= cn && cn <= 4 )
- vecmerge_<ushort, v_uint16>(src, dst, len, cn);
- else
-#endif
- merge_(src, dst, len, cn);
+ CV_CPU_DISPATCH(merge16u, (src, dst, len, cn),
+ CV_CPU_DISPATCH_MODES_ALL);
}
void merge32s(const int** src, int* dst, int len, int cn )
{
+ CV_INSTRUMENT_REGION();
CALL_HAL(merge32s, cv_hal_merge32s, src, dst, len, cn)
-#if CV_SIMD
- if( len >= v_int32::nlanes && 2 <= cn && cn <= 4 )
- vecmerge_<int, v_int32>(src, dst, len, cn);
- else
-#endif
- merge_(src, dst, len, cn);
+ CV_CPU_DISPATCH(merge32s, (src, dst, len, cn),
+ CV_CPU_DISPATCH_MODES_ALL);
}
void merge64s(const int64** src, int64* dst, int len, int cn )
{
+ CV_INSTRUMENT_REGION();
CALL_HAL(merge64s, cv_hal_merge64s, src, dst, len, cn)
-#if CV_SIMD
- if( len >= v_int64::nlanes && 2 <= cn && cn <= 4 )
- vecmerge_<int64, v_int64>(src, dst, len, cn);
- else
-#endif
- merge_(src, dst, len, cn);
+ CV_CPU_DISPATCH(merge64s, (src, dst, len, cn),
+ CV_CPU_DISPATCH_MODES_ALL);
}
-}} // cv::hal::
+} // namespace cv::hal::
typedef void (*MergeFunc)(const uchar** src, uchar* dst, int len, int cn);
#ifdef HAVE_IPP
-namespace cv {
static bool ipp_merge(const Mat* mv, Mat& dst, int channels)
{
#ifdef HAVE_IPP_IW_LL
return false;
#endif
}
-}
#endif
-void cv::merge(const Mat* mv, size_t n, OutputArray _dst)
+void merge(const Mat* mv, size_t n, OutputArray _dst)
{
CV_INSTRUMENT_REGION();
#ifdef HAVE_OPENCL
-namespace cv {
-
static bool ocl_merge( InputArrayOfArrays _mv, OutputArray _dst )
{
std::vector<UMat> src, ksrc;
return k.run(2, globalsize, NULL, false);
}
-}
-
#endif
-void cv::merge(InputArrayOfArrays _mv, OutputArray _dst)
+void merge(InputArrayOfArrays _mv, OutputArray _dst)
{
CV_INSTRUMENT_REGION();
_mv.getMatVector(mv);
merge(!mv.empty() ? &mv[0] : 0, mv.size(), _dst);
}
+
+} // namespace
--- /dev/null
+// 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 "precomp.hpp"
+
+namespace cv { namespace hal {
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+
+void merge8u(const uchar** src, uchar* dst, int len, int cn);
+void merge16u(const ushort** src, ushort* dst, int len, int cn);
+void merge32s(const int** src, int* dst, int len, int cn);
+void merge64s(const int64** src, int64* dst, int len, int cn);
+
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
+
+#if CV_SIMD
+/*
+ The trick with STORE_UNALIGNED/STORE_ALIGNED_NOCACHE is the following:
+ on IA there are instructions movntps and such to which
+ v_store_interleave(...., STORE_ALIGNED_NOCACHE) is mapped.
+ Those instructions write directly into memory w/o touching cache
+ that results in dramatic speed improvements, especially on
+ large arrays (FullHD, 4K etc.).
+
+ Those intrinsics require the destination address to be aligned
+ by 16/32 bits (with SSE2 and AVX2, respectively).
+ So we potentially split the processing into 3 stages:
+ 1) the optional prefix part [0:i0), where we use simple unaligned stores.
+ 2) the optional main part [i0:len - VECSZ], where we use "nocache" mode.
+ But in some cases we have to use unaligned stores in this part.
+ 3) the optional suffix part (the tail) (len - VECSZ:len) where we switch back to "unaligned" mode
+ to process the remaining len - VECSZ elements.
+ In principle there can be very poorly aligned data where there is no main part.
+ For that we set i0=0 and use unaligned stores for the whole array.
+*/
+template<typename T, typename VecT> static void
+vecmerge_( const T** src, T* dst, int len, int cn )
+{
+ const int VECSZ = VecT::nlanes;
+ int i, i0 = 0;
+ const T* src0 = src[0];
+ const T* src1 = src[1];
+
+ const int dstElemSize = cn * sizeof(T);
+ int r = (int)((size_t)(void*)dst % (VECSZ*sizeof(T)));
+ hal::StoreMode mode = hal::STORE_ALIGNED_NOCACHE;
+ if( r != 0 )
+ {
+ mode = hal::STORE_UNALIGNED;
+ if (r % dstElemSize == 0 && len > VECSZ*2)
+ i0 = VECSZ - (r / dstElemSize);
+ }
+
+ if( cn == 2 )
+ {
+ for( i = 0; i < len; i += VECSZ )
+ {
+ if( i > len - VECSZ )
+ {
+ i = len - VECSZ;
+ mode = hal::STORE_UNALIGNED;
+ }
+ VecT a = vx_load(src0 + i), b = vx_load(src1 + i);
+ v_store_interleave(dst + i*cn, a, b, mode);
+ if( i < i0 )
+ {
+ i = i0 - VECSZ;
+ mode = hal::STORE_ALIGNED_NOCACHE;
+ }
+ }
+ }
+ else if( cn == 3 )
+ {
+ const T* src2 = src[2];
+ for( i = 0; i < len; i += VECSZ )
+ {
+ if( i > len - VECSZ )
+ {
+ i = len - VECSZ;
+ mode = hal::STORE_UNALIGNED;
+ }
+ VecT a = vx_load(src0 + i), b = vx_load(src1 + i), c = vx_load(src2 + i);
+ v_store_interleave(dst + i*cn, a, b, c, mode);
+ if( i < i0 )
+ {
+ i = i0 - VECSZ;
+ mode = hal::STORE_ALIGNED_NOCACHE;
+ }
+ }
+ }
+ else
+ {
+ CV_Assert( cn == 4 );
+ const T* src2 = src[2];
+ const T* src3 = src[3];
+ for( i = 0; i < len; i += VECSZ )
+ {
+ if( i > len - VECSZ )
+ {
+ i = len - VECSZ;
+ mode = hal::STORE_UNALIGNED;
+ }
+ VecT a = vx_load(src0 + i), b = vx_load(src1 + i);
+ VecT c = vx_load(src2 + i), d = vx_load(src3 + i);
+ v_store_interleave(dst + i*cn, a, b, c, d, mode);
+ if( i < i0 )
+ {
+ i = i0 - VECSZ;
+ mode = hal::STORE_ALIGNED_NOCACHE;
+ }
+ }
+ }
+ vx_cleanup();
+}
+#endif
+
+template<typename T> static void
+merge_( const T** src, T* dst, int len, int cn )
+{
+ int k = cn % 4 ? cn % 4 : 4;
+ int i, j;
+ if( k == 1 )
+ {
+ const T* src0 = src[0];
+ for( i = j = 0; i < len; i++, j += cn )
+ dst[j] = src0[i];
+ }
+ else if( k == 2 )
+ {
+ const T *src0 = src[0], *src1 = src[1];
+ i = j = 0;
+ for( ; i < len; i++, j += cn )
+ {
+ dst[j] = src0[i];
+ dst[j+1] = src1[i];
+ }
+ }
+ else if( k == 3 )
+ {
+ const T *src0 = src[0], *src1 = src[1], *src2 = src[2];
+ i = j = 0;
+ for( ; i < len; i++, j += cn )
+ {
+ dst[j] = src0[i];
+ dst[j+1] = src1[i];
+ dst[j+2] = src2[i];
+ }
+ }
+ else
+ {
+ const T *src0 = src[0], *src1 = src[1], *src2 = src[2], *src3 = src[3];
+ i = j = 0;
+ for( ; i < len; i++, j += cn )
+ {
+ dst[j] = src0[i]; dst[j+1] = src1[i];
+ dst[j+2] = src2[i]; dst[j+3] = src3[i];
+ }
+ }
+
+ for( ; k < cn; k += 4 )
+ {
+ const T *src0 = src[k], *src1 = src[k+1], *src2 = src[k+2], *src3 = src[k+3];
+ for( i = 0, j = k; i < len; i++, j += cn )
+ {
+ dst[j] = src0[i]; dst[j+1] = src1[i];
+ dst[j+2] = src2[i]; dst[j+3] = src3[i];
+ }
+ }
+}
+
+void merge8u(const uchar** src, uchar* dst, int len, int cn )
+{
+ CV_INSTRUMENT_REGION();
+#if CV_SIMD
+ if( len >= v_uint8::nlanes && 2 <= cn && cn <= 4 )
+ vecmerge_<uchar, v_uint8>(src, dst, len, cn);
+ else
+#endif
+ merge_(src, dst, len, cn);
+}
+
+void merge16u(const ushort** src, ushort* dst, int len, int cn )
+{
+ CV_INSTRUMENT_REGION();
+#if CV_SIMD
+ if( len >= v_uint16::nlanes && 2 <= cn && cn <= 4 )
+ vecmerge_<ushort, v_uint16>(src, dst, len, cn);
+ else
+#endif
+ merge_(src, dst, len, cn);
+}
+
+void merge32s(const int** src, int* dst, int len, int cn )
+{
+ CV_INSTRUMENT_REGION();
+#if CV_SIMD
+ if( len >= v_int32::nlanes && 2 <= cn && cn <= 4 )
+ vecmerge_<int, v_int32>(src, dst, len, cn);
+ else
+#endif
+ merge_(src, dst, len, cn);
+}
+
+void merge64s(const int64** src, int64* dst, int len, int cn )
+{
+ CV_INSTRUMENT_REGION();
+#if CV_SIMD
+ if( len >= v_int64::nlanes && 2 <= cn && cn <= 4 )
+ vecmerge_<int64, v_int64>(src, dst, len, cn);
+ else
+#endif
+ merge_(src, dst, len, cn);
+}
+
+#endif
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+}} // namespace
: size_(size), originPtr_(ptr), alignment_(alignment), ptr_(ptr), allocatedPtr_(NULL)
{
CV_DbgAssert((alignment & (alignment - 1)) == 0); // check for 2^n
+ CV_DbgAssert(!readAccess || ptr);
if (((size_t)ptr_ & (alignment - 1)) != 0)
{
allocatedPtr_ = new uchar[size_ + alignment - 1];
: size_(rows*step), originPtr_(ptr), alignment_(alignment), ptr_(ptr), allocatedPtr_(NULL), rows_(rows), cols_(cols), step_(step)
{
CV_DbgAssert((alignment & (alignment - 1)) == 0); // check for 2^n
+ CV_DbgAssert(!readAccess || ptr != NULL);
if (ptr == 0 || ((size_t)ptr_ & (alignment - 1)) != 0)
{
allocatedPtr_ = new uchar[size_ + extrabytes + alignment - 1];
@CL_REMAP_ORIGIN@
#if defined __APPLE__
+#define CL_SILENCE_DEPRECATION
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#if defined(HAVE_OPENCL_STATIC)
#if defined __APPLE__
+#define CL_SILENCE_DEPRECATION
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireGLObjects failed");
size_t offset = 0; // TODO
size_t dst_origin[3] = {0, 0, 0};
- size_t region[3] = {u.cols, u.rows, 1};
+ size_t region[3] = { (size_t)u.cols, (size_t)u.rows, 1};
status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, dst_origin, region, 0, NULL, NULL);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed");
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireGLObjects failed");
size_t offset = 0; // TODO
size_t src_origin[3] = {0, 0, 0};
- size_t region[3] = {u.cols, u.rows, 1};
+ size_t region[3] = { (size_t)u.cols, (size_t)u.rows, 1};
status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, src_origin, region, offset, 0, NULL, NULL);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed");
}
char* ptr = fs->bufferPtr();
- if( ptr > fs->bufferStart() + current_struct.indent && !FileNode::FileNode::isEmptyCollection(struct_flags) )
+ if( ptr > fs->bufferStart() + current_struct.indent && !FileNode::isEmptyCollection(struct_flags) )
*ptr++ = ' ';
*ptr++ = FileNode::isMap(struct_flags) ? '}' : ']';
fs->setBufferPtr(ptr);
{
int new_offset;
ptr = fs->bufferPtr();
- if( !FileNode::FileNode::isEmptyCollection(struct_flags) )
+ if( !FileNode::isEmptyCollection(struct_flags) )
*ptr++ = ',';
new_offset = static_cast<int>(ptr - fs->bufferStart() + key_len + data_len);
if( new_offset > fs->wrapMargin() && new_offset - current_struct.indent > 10 )
}
else
{
- if ( !FileNode::FileNode::isEmptyCollection(struct_flags) )
+ if ( !FileNode::isEmptyCollection(struct_flags) )
{
ptr = fs->bufferPtr();
*ptr++ = ',';
#include "precomp.hpp"
#include "opencl_kernels_core.hpp"
-namespace cv { namespace hal {
-
-#if CV_SIMD
-// see the comments for vecmerge_ in merge.cpp
-template<typename T, typename VecT> static void
-vecsplit_( const T* src, T** dst, int len, int cn )
-{
- const int VECSZ = VecT::nlanes;
- int i, i0 = 0;
- T* dst0 = dst[0];
- T* dst1 = dst[1];
-
- int r0 = (int)((size_t)(void*)dst0 % (VECSZ*sizeof(T)));
- int r1 = (int)((size_t)(void*)dst1 % (VECSZ*sizeof(T)));
- int r2 = cn > 2 ? (int)((size_t)(void*)dst[2] % (VECSZ*sizeof(T))) : r0;
- int r3 = cn > 3 ? (int)((size_t)(void*)dst[3] % (VECSZ*sizeof(T))) : r0;
-
- hal::StoreMode mode = hal::STORE_ALIGNED_NOCACHE;
- if( (r0|r1|r2|r3) != 0 )
- {
- mode = hal::STORE_UNALIGNED;
- if( r0 == r1 && r0 == r2 && r0 == r3 && r0 % sizeof(T) == 0 && len > VECSZ*2 )
- i0 = VECSZ - (r0 / sizeof(T));
- }
-
- if( cn == 2 )
- {
- for( i = 0; i < len; i += VECSZ )
- {
- if( i > len - VECSZ )
- {
- i = len - VECSZ;
- mode = hal::STORE_UNALIGNED;
- }
- VecT a, b;
- v_load_deinterleave(src + i*cn, a, b);
- v_store(dst0 + i, a, mode);
- v_store(dst1 + i, b, mode);
- if( i < i0 )
- {
- i = i0 - VECSZ;
- mode = hal::STORE_ALIGNED_NOCACHE;
- }
- }
- }
- else if( cn == 3 )
- {
- T* dst2 = dst[2];
- for( i = 0; i < len; i += VECSZ )
- {
- if( i > len - VECSZ )
- {
- i = len - VECSZ;
- mode = hal::STORE_UNALIGNED;
- }
- VecT a, b, c;
- v_load_deinterleave(src + i*cn, a, b, c);
- v_store(dst0 + i, a, mode);
- v_store(dst1 + i, b, mode);
- v_store(dst2 + i, c, mode);
- if( i < i0 )
- {
- i = i0 - VECSZ;
- mode = hal::STORE_ALIGNED_NOCACHE;
- }
- }
- }
- else
- {
- CV_Assert( cn == 4 );
- T* dst2 = dst[2];
- T* dst3 = dst[3];
- for( i = 0; i < len; i += VECSZ )
- {
- if( i > len - VECSZ )
- {
- i = len - VECSZ;
- mode = hal::STORE_UNALIGNED;
- }
- VecT a, b, c, d;
- v_load_deinterleave(src + i*cn, a, b, c, d);
- v_store(dst0 + i, a, mode);
- v_store(dst1 + i, b, mode);
- v_store(dst2 + i, c, mode);
- v_store(dst3 + i, d, mode);
- if( i < i0 )
- {
- i = i0 - VECSZ;
- mode = hal::STORE_ALIGNED_NOCACHE;
- }
- }
- }
- vx_cleanup();
-}
-#endif
-
-template<typename T> static void
-split_( const T* src, T** dst, int len, int cn )
-{
- int k = cn % 4 ? cn % 4 : 4;
- int i, j;
- if( k == 1 )
- {
- T* dst0 = dst[0];
-
- if(cn == 1)
- {
- memcpy(dst0, src, len * sizeof(T));
- }
- else
- {
- for( i = 0, j = 0 ; i < len; i++, j += cn )
- dst0[i] = src[j];
- }
- }
- else if( k == 2 )
- {
- T *dst0 = dst[0], *dst1 = dst[1];
- i = j = 0;
+#include "split.simd.hpp"
+#include "split.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
- for( ; i < len; i++, j += cn )
- {
- dst0[i] = src[j];
- dst1[i] = src[j+1];
- }
- }
- else if( k == 3 )
- {
- T *dst0 = dst[0], *dst1 = dst[1], *dst2 = dst[2];
- i = j = 0;
-
- for( ; i < len; i++, j += cn )
- {
- dst0[i] = src[j];
- dst1[i] = src[j+1];
- dst2[i] = src[j+2];
- }
- }
- else
- {
- T *dst0 = dst[0], *dst1 = dst[1], *dst2 = dst[2], *dst3 = dst[3];
- i = j = 0;
-
- for( ; i < len; i++, j += cn )
- {
- dst0[i] = src[j]; dst1[i] = src[j+1];
- dst2[i] = src[j+2]; dst3[i] = src[j+3];
- }
- }
-
- for( ; k < cn; k += 4 )
- {
- T *dst0 = dst[k], *dst1 = dst[k+1], *dst2 = dst[k+2], *dst3 = dst[k+3];
- for( i = 0, j = k; i < len; i++, j += cn )
- {
- dst0[i] = src[j]; dst1[i] = src[j+1];
- dst2[i] = src[j+2]; dst3[i] = src[j+3];
- }
- }
-}
+namespace cv { namespace hal {
void split8u(const uchar* src, uchar** dst, int len, int cn )
{
+ CV_INSTRUMENT_REGION();
CALL_HAL(split8u, cv_hal_split8u, src,dst, len, cn)
-
-#if CV_SIMD
- if( len >= v_uint8::nlanes && 2 <= cn && cn <= 4 )
- vecsplit_<uchar, v_uint8>(src, dst, len, cn);
- else
-#endif
- split_(src, dst, len, cn);
+ CV_CPU_DISPATCH(split8u, (src, dst, len, cn),
+ CV_CPU_DISPATCH_MODES_ALL);
}
void split16u(const ushort* src, ushort** dst, int len, int cn )
{
+ CV_INSTRUMENT_REGION();
CALL_HAL(split16u, cv_hal_split16u, src,dst, len, cn)
-#if CV_SIMD
- if( len >= v_uint16::nlanes && 2 <= cn && cn <= 4 )
- vecsplit_<ushort, v_uint16>(src, dst, len, cn);
- else
-#endif
- split_(src, dst, len, cn);
+ CV_CPU_DISPATCH(split16u, (src, dst, len, cn),
+ CV_CPU_DISPATCH_MODES_ALL);
}
void split32s(const int* src, int** dst, int len, int cn )
{
+ CV_INSTRUMENT_REGION();
CALL_HAL(split32s, cv_hal_split32s, src,dst, len, cn)
-#if CV_SIMD
- if( len >= v_uint32::nlanes && 2 <= cn && cn <= 4 )
- vecsplit_<int, v_int32>(src, dst, len, cn);
- else
-#endif
- split_(src, dst, len, cn);
+ CV_CPU_DISPATCH(split32s, (src, dst, len, cn),
+ CV_CPU_DISPATCH_MODES_ALL);
}
void split64s(const int64* src, int64** dst, int len, int cn )
{
+ CV_INSTRUMENT_REGION();
CALL_HAL(split64s, cv_hal_split64s, src,dst, len, cn)
-#if CV_SIMD
- if( len >= v_int64::nlanes && 2 <= cn && cn <= 4 )
- vecsplit_<int64, v_int64>(src, dst, len, cn);
- else
-#endif
- split_(src, dst, len, cn);
+ CV_CPU_DISPATCH(split64s, (src, dst, len, cn),
+ CV_CPU_DISPATCH_MODES_ALL);
}
-}} // cv::hal::
+} // namespace cv::hal::
/****************************************************************************************\
* split & merge *
#ifdef HAVE_IPP
-namespace cv {
static bool ipp_split(const Mat& src, Mat* mv, int channels)
{
#ifdef HAVE_IPP_IW_LL
return false;
#endif
}
-}
#endif
-void cv::split(const Mat& src, Mat* mv)
+void split(const Mat& src, Mat* mv)
{
CV_INSTRUMENT_REGION();
#ifdef HAVE_OPENCL
-namespace cv {
-
static bool ocl_split( InputArray _m, OutputArrayOfArrays _mv )
{
int type = _m.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
return k.run(2, globalsize, NULL, false);
}
-}
-
#endif
-void cv::split(InputArray _m, OutputArrayOfArrays _mv)
+void split(InputArray _m, OutputArrayOfArrays _mv)
{
CV_INSTRUMENT_REGION();
split(m, &dst[0]);
}
+
+} // namespace
--- /dev/null
+// 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 "precomp.hpp"
+
+namespace cv { namespace hal {
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+
+void split8u(const uchar* src, uchar** dst, int len, int cn);
+void split16u(const ushort* src, ushort** dst, int len, int cn);
+void split32s(const int* src, int** dst, int len, int cn);
+void split64s(const int64* src, int64** dst, int len, int cn);
+
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
+
+#if CV_SIMD
+// see the comments for vecmerge_ in merge.cpp
+template<typename T, typename VecT> static void
+vecsplit_( const T* src, T** dst, int len, int cn )
+{
+ const int VECSZ = VecT::nlanes;
+ int i, i0 = 0;
+ T* dst0 = dst[0];
+ T* dst1 = dst[1];
+
+ int r0 = (int)((size_t)(void*)dst0 % (VECSZ*sizeof(T)));
+ int r1 = (int)((size_t)(void*)dst1 % (VECSZ*sizeof(T)));
+ int r2 = cn > 2 ? (int)((size_t)(void*)dst[2] % (VECSZ*sizeof(T))) : r0;
+ int r3 = cn > 3 ? (int)((size_t)(void*)dst[3] % (VECSZ*sizeof(T))) : r0;
+
+ hal::StoreMode mode = hal::STORE_ALIGNED_NOCACHE;
+ if( (r0|r1|r2|r3) != 0 )
+ {
+ mode = hal::STORE_UNALIGNED;
+ if( r0 == r1 && r0 == r2 && r0 == r3 && r0 % sizeof(T) == 0 && len > VECSZ*2 )
+ i0 = VECSZ - (r0 / sizeof(T));
+ }
+
+ if( cn == 2 )
+ {
+ for( i = 0; i < len; i += VECSZ )
+ {
+ if( i > len - VECSZ )
+ {
+ i = len - VECSZ;
+ mode = hal::STORE_UNALIGNED;
+ }
+ VecT a, b;
+ v_load_deinterleave(src + i*cn, a, b);
+ v_store(dst0 + i, a, mode);
+ v_store(dst1 + i, b, mode);
+ if( i < i0 )
+ {
+ i = i0 - VECSZ;
+ mode = hal::STORE_ALIGNED_NOCACHE;
+ }
+ }
+ }
+ else if( cn == 3 )
+ {
+ T* dst2 = dst[2];
+ for( i = 0; i < len; i += VECSZ )
+ {
+ if( i > len - VECSZ )
+ {
+ i = len - VECSZ;
+ mode = hal::STORE_UNALIGNED;
+ }
+ VecT a, b, c;
+ v_load_deinterleave(src + i*cn, a, b, c);
+ v_store(dst0 + i, a, mode);
+ v_store(dst1 + i, b, mode);
+ v_store(dst2 + i, c, mode);
+ if( i < i0 )
+ {
+ i = i0 - VECSZ;
+ mode = hal::STORE_ALIGNED_NOCACHE;
+ }
+ }
+ }
+ else
+ {
+ CV_Assert( cn == 4 );
+ T* dst2 = dst[2];
+ T* dst3 = dst[3];
+ for( i = 0; i < len; i += VECSZ )
+ {
+ if( i > len - VECSZ )
+ {
+ i = len - VECSZ;
+ mode = hal::STORE_UNALIGNED;
+ }
+ VecT a, b, c, d;
+ v_load_deinterleave(src + i*cn, a, b, c, d);
+ v_store(dst0 + i, a, mode);
+ v_store(dst1 + i, b, mode);
+ v_store(dst2 + i, c, mode);
+ v_store(dst3 + i, d, mode);
+ if( i < i0 )
+ {
+ i = i0 - VECSZ;
+ mode = hal::STORE_ALIGNED_NOCACHE;
+ }
+ }
+ }
+ vx_cleanup();
+}
+#endif
+
+template<typename T> static void
+split_( const T* src, T** dst, int len, int cn )
+{
+ int k = cn % 4 ? cn % 4 : 4;
+ int i, j;
+ if( k == 1 )
+ {
+ T* dst0 = dst[0];
+
+ if(cn == 1)
+ {
+ memcpy(dst0, src, len * sizeof(T));
+ }
+ else
+ {
+ for( i = 0, j = 0 ; i < len; i++, j += cn )
+ dst0[i] = src[j];
+ }
+ }
+ else if( k == 2 )
+ {
+ T *dst0 = dst[0], *dst1 = dst[1];
+ i = j = 0;
+
+ for( ; i < len; i++, j += cn )
+ {
+ dst0[i] = src[j];
+ dst1[i] = src[j+1];
+ }
+ }
+ else if( k == 3 )
+ {
+ T *dst0 = dst[0], *dst1 = dst[1], *dst2 = dst[2];
+ i = j = 0;
+
+ for( ; i < len; i++, j += cn )
+ {
+ dst0[i] = src[j];
+ dst1[i] = src[j+1];
+ dst2[i] = src[j+2];
+ }
+ }
+ else
+ {
+ T *dst0 = dst[0], *dst1 = dst[1], *dst2 = dst[2], *dst3 = dst[3];
+ i = j = 0;
+
+ for( ; i < len; i++, j += cn )
+ {
+ dst0[i] = src[j]; dst1[i] = src[j+1];
+ dst2[i] = src[j+2]; dst3[i] = src[j+3];
+ }
+ }
+
+ for( ; k < cn; k += 4 )
+ {
+ T *dst0 = dst[k], *dst1 = dst[k+1], *dst2 = dst[k+2], *dst3 = dst[k+3];
+ for( i = 0, j = k; i < len; i++, j += cn )
+ {
+ dst0[i] = src[j]; dst1[i] = src[j+1];
+ dst2[i] = src[j+2]; dst3[i] = src[j+3];
+ }
+ }
+}
+
+void split8u(const uchar* src, uchar** dst, int len, int cn )
+{
+ CV_INSTRUMENT_REGION();
+#if CV_SIMD
+ if( len >= v_uint8::nlanes && 2 <= cn && cn <= 4 )
+ vecsplit_<uchar, v_uint8>(src, dst, len, cn);
+ else
+#endif
+ split_(src, dst, len, cn);
+}
+
+void split16u(const ushort* src, ushort** dst, int len, int cn )
+{
+ CV_INSTRUMENT_REGION();
+#if CV_SIMD
+ if( len >= v_uint16::nlanes && 2 <= cn && cn <= 4 )
+ vecsplit_<ushort, v_uint16>(src, dst, len, cn);
+ else
+#endif
+ split_(src, dst, len, cn);
+}
+
+void split32s(const int* src, int** dst, int len, int cn )
+{
+ CV_INSTRUMENT_REGION();
+#if CV_SIMD
+ if( len >= v_uint32::nlanes && 2 <= cn && cn <= 4 )
+ vecsplit_<int, v_int32>(src, dst, len, cn);
+ else
+#endif
+ split_(src, dst, len, cn);
+}
+
+void split64s(const int64* src, int64** dst, int len, int cn )
+{
+ CV_INSTRUMENT_REGION();
+#if CV_SIMD
+ if( len >= v_int64::nlanes && 2 <= cn && cn <= 4 )
+ vecsplit_<int64, v_int64>(src, dst, len, cn);
+ else
+#endif
+ split_(src, dst, len, cn);
+}
+
+#endif
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+}} // namespace
\ No newline at end of file
--- /dev/null
+// 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 "precomp.hpp"
+#include "opencl_kernels_core.hpp"
+#include "stat.hpp"
+
+#include "sum.simd.hpp"
+#include "sum.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
+
+#undef HAVE_IPP
+#undef CV_IPP_RUN_FAST
+#define CV_IPP_RUN_FAST(f, ...)
+#undef CV_IPP_RUN
+#define CV_IPP_RUN(c, f, ...)
+
+namespace cv
+{
+
+SumFunc getSumFunc(int depth)
+{
+ CV_INSTRUMENT_REGION();
+ CV_CPU_DISPATCH(getSumFunc, (depth),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+#ifdef HAVE_OPENCL
+
+bool ocl_sum( InputArray _src, Scalar & res, int sum_op, InputArray _mask,
+ InputArray _src2, bool calc2, const Scalar & res2 )
+{
+ CV_Assert(sum_op == OCL_OP_SUM || sum_op == OCL_OP_SUM_ABS || sum_op == OCL_OP_SUM_SQR);
+
+ const ocl::Device & dev = ocl::Device::getDefault();
+ bool doubleSupport = dev.doubleFPConfig() > 0,
+ haveMask = _mask.kind() != _InputArray::NONE,
+ haveSrc2 = _src2.kind() != _InputArray::NONE;
+ int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
+ kercn = cn == 1 && !haveMask ? ocl::predictOptimalVectorWidth(_src, _src2) : 1,
+ mcn = std::max(cn, kercn);
+ CV_Assert(!haveSrc2 || _src2.type() == type);
+ int convert_cn = haveSrc2 ? mcn : cn;
+
+ if ( (!doubleSupport && depth == CV_64F) || cn > 4 )
+ return false;
+
+ int ngroups = dev.maxComputeUnits(), dbsize = ngroups * (calc2 ? 2 : 1);
+ size_t wgs = dev.maxWorkGroupSize();
+
+ int ddepth = std::max(sum_op == OCL_OP_SUM_SQR ? CV_32F : CV_32S, depth),
+ dtype = CV_MAKE_TYPE(ddepth, cn);
+ CV_Assert(!haveMask || _mask.type() == CV_8UC1);
+
+ int wgs2_aligned = 1;
+ while (wgs2_aligned < (int)wgs)
+ wgs2_aligned <<= 1;
+ wgs2_aligned >>= 1;
+
+ static const char * const opMap[3] = { "OP_SUM", "OP_SUM_ABS", "OP_SUM_SQR" };
+ char cvt[2][40];
+ String opts = format("-D srcT=%s -D srcT1=%s -D dstT=%s -D dstTK=%s -D dstT1=%s -D ddepth=%d -D cn=%d"
+ " -D convertToDT=%s -D %s -D WGS=%d -D WGS2_ALIGNED=%d%s%s%s%s -D kercn=%d%s%s%s -D convertFromU=%s",
+ ocl::typeToStr(CV_MAKE_TYPE(depth, mcn)), ocl::typeToStr(depth),
+ ocl::typeToStr(dtype), ocl::typeToStr(CV_MAKE_TYPE(ddepth, mcn)),
+ ocl::typeToStr(ddepth), ddepth, cn,
+ ocl::convertTypeStr(depth, ddepth, mcn, cvt[0]),
+ opMap[sum_op], (int)wgs, wgs2_aligned,
+ doubleSupport ? " -D DOUBLE_SUPPORT" : "",
+ haveMask ? " -D HAVE_MASK" : "",
+ _src.isContinuous() ? " -D HAVE_SRC_CONT" : "",
+ haveMask && _mask.isContinuous() ? " -D HAVE_MASK_CONT" : "", kercn,
+ haveSrc2 ? " -D HAVE_SRC2" : "", calc2 ? " -D OP_CALC2" : "",
+ haveSrc2 && _src2.isContinuous() ? " -D HAVE_SRC2_CONT" : "",
+ depth <= CV_32S && ddepth == CV_32S ? ocl::convertTypeStr(CV_8U, ddepth, convert_cn, cvt[1]) : "noconvert");
+
+ ocl::Kernel k("reduce", ocl::core::reduce_oclsrc, opts);
+ if (k.empty())
+ return false;
+
+ UMat src = _src.getUMat(), src2 = _src2.getUMat(),
+ db(1, dbsize, dtype), mask = _mask.getUMat();
+
+ ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
+ dbarg = ocl::KernelArg::PtrWriteOnly(db),
+ maskarg = ocl::KernelArg::ReadOnlyNoSize(mask),
+ src2arg = ocl::KernelArg::ReadOnlyNoSize(src2);
+
+ if (haveMask)
+ {
+ if (haveSrc2)
+ k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg, maskarg, src2arg);
+ else
+ k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg, maskarg);
+ }
+ else
+ {
+ if (haveSrc2)
+ k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg, src2arg);
+ else
+ k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg);
+ }
+
+ size_t globalsize = ngroups * wgs;
+ if (k.run(1, &globalsize, &wgs, true))
+ {
+ typedef Scalar (*part_sum)(Mat m);
+ part_sum funcs[3] = { ocl_part_sum<int>, ocl_part_sum<float>, ocl_part_sum<double> },
+ func = funcs[ddepth - CV_32S];
+
+ Mat mres = db.getMat(ACCESS_READ);
+ if (calc2)
+ const_cast<Scalar &>(res2) = func(mres.colRange(ngroups, dbsize));
+
+ res = func(mres.colRange(0, ngroups));
+ return true;
+ }
+ return false;
+}
+
+#endif
+
+#ifdef HAVE_IPP
+static bool ipp_sum(Mat &src, Scalar &_res)
+{
+ CV_INSTRUMENT_REGION_IPP();
+
+#if IPP_VERSION_X100 >= 700
+ int cn = src.channels();
+ if (cn > 4)
+ return false;
+ size_t total_size = src.total();
+ int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0;
+ if( src.dims == 2 || (src.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) )
+ {
+ IppiSize sz = { cols, rows };
+ int type = src.type();
+ typedef IppStatus (CV_STDCALL* ippiSumFuncHint)(const void*, int, IppiSize, double *, IppHintAlgorithm);
+ typedef IppStatus (CV_STDCALL* ippiSumFuncNoHint)(const void*, int, IppiSize, double *);
+ ippiSumFuncHint ippiSumHint =
+ type == CV_32FC1 ? (ippiSumFuncHint)ippiSum_32f_C1R :
+ type == CV_32FC3 ? (ippiSumFuncHint)ippiSum_32f_C3R :
+ type == CV_32FC4 ? (ippiSumFuncHint)ippiSum_32f_C4R :
+ 0;
+ ippiSumFuncNoHint ippiSum =
+ type == CV_8UC1 ? (ippiSumFuncNoHint)ippiSum_8u_C1R :
+ type == CV_8UC3 ? (ippiSumFuncNoHint)ippiSum_8u_C3R :
+ type == CV_8UC4 ? (ippiSumFuncNoHint)ippiSum_8u_C4R :
+ type == CV_16UC1 ? (ippiSumFuncNoHint)ippiSum_16u_C1R :
+ type == CV_16UC3 ? (ippiSumFuncNoHint)ippiSum_16u_C3R :
+ type == CV_16UC4 ? (ippiSumFuncNoHint)ippiSum_16u_C4R :
+ type == CV_16SC1 ? (ippiSumFuncNoHint)ippiSum_16s_C1R :
+ type == CV_16SC3 ? (ippiSumFuncNoHint)ippiSum_16s_C3R :
+ type == CV_16SC4 ? (ippiSumFuncNoHint)ippiSum_16s_C4R :
+ 0;
+ CV_Assert(!ippiSumHint || !ippiSum);
+ if( ippiSumHint || ippiSum )
+ {
+ Ipp64f res[4];
+ IppStatus ret = ippiSumHint ?
+ CV_INSTRUMENT_FUN_IPP(ippiSumHint, src.ptr(), (int)src.step[0], sz, res, ippAlgHintAccurate) :
+ CV_INSTRUMENT_FUN_IPP(ippiSum, src.ptr(), (int)src.step[0], sz, res);
+ if( ret >= 0 )
+ {
+ for( int i = 0; i < cn; i++ )
+ _res[i] = res[i];
+ return true;
+ }
+ }
+ }
+#else
+ CV_UNUSED(src); CV_UNUSED(_res);
+#endif
+ return false;
+}
+#endif
+
+Scalar sum(InputArray _src)
+{
+ CV_INSTRUMENT_REGION();
+
+#if defined HAVE_OPENCL || defined HAVE_IPP
+ Scalar _res;
+#endif
+
+#ifdef HAVE_OPENCL
+ CV_OCL_RUN_(OCL_PERFORMANCE_CHECK(_src.isUMat()) && _src.dims() <= 2,
+ ocl_sum(_src, _res, OCL_OP_SUM),
+ _res)
+#endif
+
+ Mat src = _src.getMat();
+ CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_sum(src, _res), _res);
+
+ int k, cn = src.channels(), depth = src.depth();
+ SumFunc func = getSumFunc(depth);
+ CV_Assert( cn <= 4 && func != 0 );
+
+ const Mat* arrays[] = {&src, 0};
+ uchar* ptrs[1] = {};
+ NAryMatIterator it(arrays, ptrs);
+ Scalar s;
+ int total = (int)it.size, blockSize = total, intSumBlockSize = 0;
+ int j, count = 0;
+ AutoBuffer<int> _buf;
+ int* buf = (int*)&s[0];
+ size_t esz = 0;
+ bool blockSum = depth < CV_32S;
+
+ if( blockSum )
+ {
+ intSumBlockSize = depth <= CV_8S ? (1 << 23) : (1 << 15);
+ blockSize = std::min(blockSize, intSumBlockSize);
+ _buf.allocate(cn);
+ buf = _buf.data();
+
+ for( k = 0; k < cn; k++ )
+ buf[k] = 0;
+ esz = src.elemSize();
+ }
+
+ for( size_t i = 0; i < it.nplanes; i++, ++it )
+ {
+ for( j = 0; j < total; j += blockSize )
+ {
+ int bsz = std::min(total - j, blockSize);
+ func( ptrs[0], 0, (uchar*)buf, bsz, cn );
+ count += bsz;
+ if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) )
+ {
+ for( k = 0; k < cn; k++ )
+ {
+ s[k] += buf[k];
+ buf[k] = 0;
+ }
+ count = 0;
+ }
+ ptrs[0] += bsz*esz;
+ }
+ }
+ return s;
+}
+
+} // namespace
#include "precomp.hpp"
-#include "opencl_kernels_core.hpp"
#include "stat.hpp"
-#undef HAVE_IPP
-#undef CV_IPP_RUN_FAST
-#define CV_IPP_RUN_FAST(f, ...)
-#undef CV_IPP_RUN
-#define CV_IPP_RUN(c, f, ...)
+namespace cv {
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
-namespace cv
-{
+SumFunc getSumFunc(int depth);
+
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
template <typename T, typename ST>
struct Sum_SIMD
static int sum8u( const uchar* src, const uchar* mask, int* dst, int len, int cn )
-{ return sum_(src, mask, dst, len, cn); }
+{ CV_INSTRUMENT_REGION(); return sum_(src, mask, dst, len, cn); }
static int sum8s( const schar* src, const uchar* mask, int* dst, int len, int cn )
-{ return sum_(src, mask, dst, len, cn); }
+{ CV_INSTRUMENT_REGION(); return sum_(src, mask, dst, len, cn); }
static int sum16u( const ushort* src, const uchar* mask, int* dst, int len, int cn )
-{ return sum_(src, mask, dst, len, cn); }
+{ CV_INSTRUMENT_REGION(); return sum_(src, mask, dst, len, cn); }
static int sum16s( const short* src, const uchar* mask, int* dst, int len, int cn )
-{ return sum_(src, mask, dst, len, cn); }
+{ CV_INSTRUMENT_REGION(); return sum_(src, mask, dst, len, cn); }
static int sum32s( const int* src, const uchar* mask, double* dst, int len, int cn )
-{ return sum_(src, mask, dst, len, cn); }
+{ CV_INSTRUMENT_REGION(); return sum_(src, mask, dst, len, cn); }
static int sum32f( const float* src, const uchar* mask, double* dst, int len, int cn )
-{ return sum_(src, mask, dst, len, cn); }
+{ CV_INSTRUMENT_REGION(); return sum_(src, mask, dst, len, cn); }
static int sum64f( const double* src, const uchar* mask, double* dst, int len, int cn )
-{ return sum_(src, mask, dst, len, cn); }
+{ CV_INSTRUMENT_REGION(); return sum_(src, mask, dst, len, cn); }
SumFunc getSumFunc(int depth)
{
return sumTab[depth];
}
-#ifdef HAVE_OPENCL
-
-bool ocl_sum( InputArray _src, Scalar & res, int sum_op, InputArray _mask,
- InputArray _src2, bool calc2, const Scalar & res2 )
-{
- CV_Assert(sum_op == OCL_OP_SUM || sum_op == OCL_OP_SUM_ABS || sum_op == OCL_OP_SUM_SQR);
-
- const ocl::Device & dev = ocl::Device::getDefault();
- bool doubleSupport = dev.doubleFPConfig() > 0,
- haveMask = _mask.kind() != _InputArray::NONE,
- haveSrc2 = _src2.kind() != _InputArray::NONE;
- int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
- kercn = cn == 1 && !haveMask ? ocl::predictOptimalVectorWidth(_src, _src2) : 1,
- mcn = std::max(cn, kercn);
- CV_Assert(!haveSrc2 || _src2.type() == type);
- int convert_cn = haveSrc2 ? mcn : cn;
-
- if ( (!doubleSupport && depth == CV_64F) || cn > 4 )
- return false;
-
- int ngroups = dev.maxComputeUnits(), dbsize = ngroups * (calc2 ? 2 : 1);
- size_t wgs = dev.maxWorkGroupSize();
-
- int ddepth = std::max(sum_op == OCL_OP_SUM_SQR ? CV_32F : CV_32S, depth),
- dtype = CV_MAKE_TYPE(ddepth, cn);
- CV_Assert(!haveMask || _mask.type() == CV_8UC1);
-
- int wgs2_aligned = 1;
- while (wgs2_aligned < (int)wgs)
- wgs2_aligned <<= 1;
- wgs2_aligned >>= 1;
-
- static const char * const opMap[3] = { "OP_SUM", "OP_SUM_ABS", "OP_SUM_SQR" };
- char cvt[2][40];
- String opts = format("-D srcT=%s -D srcT1=%s -D dstT=%s -D dstTK=%s -D dstT1=%s -D ddepth=%d -D cn=%d"
- " -D convertToDT=%s -D %s -D WGS=%d -D WGS2_ALIGNED=%d%s%s%s%s -D kercn=%d%s%s%s -D convertFromU=%s",
- ocl::typeToStr(CV_MAKE_TYPE(depth, mcn)), ocl::typeToStr(depth),
- ocl::typeToStr(dtype), ocl::typeToStr(CV_MAKE_TYPE(ddepth, mcn)),
- ocl::typeToStr(ddepth), ddepth, cn,
- ocl::convertTypeStr(depth, ddepth, mcn, cvt[0]),
- opMap[sum_op], (int)wgs, wgs2_aligned,
- doubleSupport ? " -D DOUBLE_SUPPORT" : "",
- haveMask ? " -D HAVE_MASK" : "",
- _src.isContinuous() ? " -D HAVE_SRC_CONT" : "",
- haveMask && _mask.isContinuous() ? " -D HAVE_MASK_CONT" : "", kercn,
- haveSrc2 ? " -D HAVE_SRC2" : "", calc2 ? " -D OP_CALC2" : "",
- haveSrc2 && _src2.isContinuous() ? " -D HAVE_SRC2_CONT" : "",
- depth <= CV_32S && ddepth == CV_32S ? ocl::convertTypeStr(CV_8U, ddepth, convert_cn, cvt[1]) : "noconvert");
-
- ocl::Kernel k("reduce", ocl::core::reduce_oclsrc, opts);
- if (k.empty())
- return false;
-
- UMat src = _src.getUMat(), src2 = _src2.getUMat(),
- db(1, dbsize, dtype), mask = _mask.getUMat();
-
- ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
- dbarg = ocl::KernelArg::PtrWriteOnly(db),
- maskarg = ocl::KernelArg::ReadOnlyNoSize(mask),
- src2arg = ocl::KernelArg::ReadOnlyNoSize(src2);
-
- if (haveMask)
- {
- if (haveSrc2)
- k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg, maskarg, src2arg);
- else
- k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg, maskarg);
- }
- else
- {
- if (haveSrc2)
- k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg, src2arg);
- else
- k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg);
- }
-
- size_t globalsize = ngroups * wgs;
- if (k.run(1, &globalsize, &wgs, true))
- {
- typedef Scalar (*part_sum)(Mat m);
- part_sum funcs[3] = { ocl_part_sum<int>, ocl_part_sum<float>, ocl_part_sum<double> },
- func = funcs[ddepth - CV_32S];
-
- Mat mres = db.getMat(ACCESS_READ);
- if (calc2)
- const_cast<Scalar &>(res2) = func(mres.colRange(ngroups, dbsize));
-
- res = func(mres.colRange(0, ngroups));
- return true;
- }
- return false;
-}
-
#endif
-#ifdef HAVE_IPP
-static bool ipp_sum(Mat &src, Scalar &_res)
-{
- CV_INSTRUMENT_REGION_IPP();
-
-#if IPP_VERSION_X100 >= 700
- int cn = src.channels();
- if (cn > 4)
- return false;
- size_t total_size = src.total();
- int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0;
- if( src.dims == 2 || (src.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) )
- {
- IppiSize sz = { cols, rows };
- int type = src.type();
- typedef IppStatus (CV_STDCALL* ippiSumFuncHint)(const void*, int, IppiSize, double *, IppHintAlgorithm);
- typedef IppStatus (CV_STDCALL* ippiSumFuncNoHint)(const void*, int, IppiSize, double *);
- ippiSumFuncHint ippiSumHint =
- type == CV_32FC1 ? (ippiSumFuncHint)ippiSum_32f_C1R :
- type == CV_32FC3 ? (ippiSumFuncHint)ippiSum_32f_C3R :
- type == CV_32FC4 ? (ippiSumFuncHint)ippiSum_32f_C4R :
- 0;
- ippiSumFuncNoHint ippiSum =
- type == CV_8UC1 ? (ippiSumFuncNoHint)ippiSum_8u_C1R :
- type == CV_8UC3 ? (ippiSumFuncNoHint)ippiSum_8u_C3R :
- type == CV_8UC4 ? (ippiSumFuncNoHint)ippiSum_8u_C4R :
- type == CV_16UC1 ? (ippiSumFuncNoHint)ippiSum_16u_C1R :
- type == CV_16UC3 ? (ippiSumFuncNoHint)ippiSum_16u_C3R :
- type == CV_16UC4 ? (ippiSumFuncNoHint)ippiSum_16u_C4R :
- type == CV_16SC1 ? (ippiSumFuncNoHint)ippiSum_16s_C1R :
- type == CV_16SC3 ? (ippiSumFuncNoHint)ippiSum_16s_C3R :
- type == CV_16SC4 ? (ippiSumFuncNoHint)ippiSum_16s_C4R :
- 0;
- CV_Assert(!ippiSumHint || !ippiSum);
- if( ippiSumHint || ippiSum )
- {
- Ipp64f res[4];
- IppStatus ret = ippiSumHint ?
- CV_INSTRUMENT_FUN_IPP(ippiSumHint, src.ptr(), (int)src.step[0], sz, res, ippAlgHintAccurate) :
- CV_INSTRUMENT_FUN_IPP(ippiSum, src.ptr(), (int)src.step[0], sz, res);
- if( ret >= 0 )
- {
- for( int i = 0; i < cn; i++ )
- _res[i] = res[i];
- return true;
- }
- }
- }
-#else
- CV_UNUSED(src); CV_UNUSED(_res);
-#endif
- return false;
-}
-#endif
-
-} // cv::
-
-cv::Scalar cv::sum( InputArray _src )
-{
- CV_INSTRUMENT_REGION();
-
-#if defined HAVE_OPENCL || defined HAVE_IPP
- Scalar _res;
-#endif
-
-#ifdef HAVE_OPENCL
- CV_OCL_RUN_(OCL_PERFORMANCE_CHECK(_src.isUMat()) && _src.dims() <= 2,
- ocl_sum(_src, _res, OCL_OP_SUM),
- _res)
-#endif
-
- Mat src = _src.getMat();
- CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_sum(src, _res), _res);
-
- int k, cn = src.channels(), depth = src.depth();
- SumFunc func = getSumFunc(depth);
- CV_Assert( cn <= 4 && func != 0 );
-
- const Mat* arrays[] = {&src, 0};
- uchar* ptrs[1] = {};
- NAryMatIterator it(arrays, ptrs);
- Scalar s;
- int total = (int)it.size, blockSize = total, intSumBlockSize = 0;
- int j, count = 0;
- AutoBuffer<int> _buf;
- int* buf = (int*)&s[0];
- size_t esz = 0;
- bool blockSum = depth < CV_32S;
-
- if( blockSum )
- {
- intSumBlockSize = depth <= CV_8S ? (1 << 23) : (1 << 15);
- blockSize = std::min(blockSize, intSumBlockSize);
- _buf.allocate(cn);
- buf = _buf.data();
-
- for( k = 0; k < cn; k++ )
- buf[k] = 0;
- esz = src.elemSize();
- }
-
- for( size_t i = 0; i < it.nplanes; i++, ++it )
- {
- for( j = 0; j < total; j += blockSize )
- {
- int bsz = std::min(total - j, blockSize);
- func( ptrs[0], 0, (uchar*)buf, bsz, cn );
- count += bsz;
- if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) )
- {
- for( k = 0; k < cn; k++ )
- {
- s[k] += buf[k];
- buf[k] = 0;
- }
- count = 0;
- }
- ptrs[0] += bsz*esz;
- }
- }
- return s;
-}
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+} // namespace
#include <cstdlib> // std::abort
#endif
-#if defined __ANDROID__ || defined __linux__ || defined __FreeBSD__ || defined __HAIKU__ || defined __Fuchsia__
+#if defined __ANDROID__ || defined __linux__ || defined __FreeBSD__ || defined __OpenBSD__ || defined __HAIKU__ || defined __Fuchsia__
# include <unistd.h>
# include <fcntl.h>
# include <elf.h>
return cv::String();
}
+std::string getBinLocation()
+{
+ return getModuleLocation((void*)getModuleLocation); // use code addr, doesn't work with static linkage!
+}
+
cv::String findDataFile(const cv::String& relative_path,
const char* configuration_parameter,
const std::vector<String>* search_paths,
}
}
- cv::String module_path = getModuleLocation((void*)getModuleLocation); // use code addr, doesn't work with static linkage!
+ cv::String module_path = getBinLocation();
CV_LOG_DEBUG(NULL, "Detected module path: '" << module_path << '\'');
if (!has_tested_build_directory &&
return result;
}
+CV_EXPORTS cv::String getParent(const cv::String &path)
+{
+ std::string::size_type loc = path.find_last_of("/\\");
+ if (loc == std::string::npos)
+ return std::string();
+ return std::string(path, 0, loc);
+}
+
#if OPENCV_HAVE_FILESYSTEM_SUPPORT
cv::String canonical(const cv::String& path)
if (utils::fs::isDirectory(default_cache_path))
{
cv::String default_cache_path_base = utils::fs::join(default_cache_path, "opencv");
- default_cache_path = utils::fs::join(default_cache_path_base, "4.0" CV_VERSION_STATUS);
+ default_cache_path = utils::fs::join(default_cache_path_base, CVAUX_STR(CV_VERSION_MAJOR) "." CVAUX_STR(CV_VERSION_MINOR) CV_VERSION_STATUS);
if (utils::getConfigurationParameterBool("OPENCV_CACHE_SHOW_CLEANUP_MESSAGE", true)
&& !utils::fs::isDirectory(default_cache_path))
{
}
INSTANTIATE_TEST_CASE_P(/**/, Core_EigenZero, testing::Values(2, 3, 5));
+TEST(Core_EigenNonSymmetric, convergence)
+{
+ Matx33d m(
+ 0, -1, 0,
+ 1, 0, 1,
+ 0, -1, 0);
+ Mat eigenvalues, eigenvectors;
+ // eigen values are complex, algorithm doesn't converge
+ try
+ {
+ cv::eigenNonSymmetric(m, eigenvalues, eigenvectors);
+ std::cout << Mat(eigenvalues.t()) << std::endl;
+ }
+ catch (const cv::Exception& e)
+ {
+ EXPECT_EQ(Error::StsNoConv, e.code) << e.what();
+ }
+ catch (...)
+ {
+ FAIL() << "Unknown exception has been raised";
+ }
+}
+
}} // namespace
ASSERT_EQ(7, ints[3]);
}
+TEST(Core_MatExpr, issue_13926)
+{
+ Mat M1 = (Mat_<double>(4,4,CV_64FC1) << 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16);
+
+ Matx44d M2(1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16);
+
+ EXPECT_GE(1e-6, cvtest::norm(M1*M2, M1*M1, NORM_INF)) << Mat(M1*M2) << std::endl << Mat(M1*M1);
+ EXPECT_GE(1e-6, cvtest::norm(M2*M1, M2*M2, NORM_INF)) << Mat(M2*M1) << std::endl << Mat(M2*M2);
+}
+
#ifdef HAVE_EIGEN
TEST(Core_Eigen, eigen2cv_check_Mat_type)
int i, j, cols;
int cn, depth, mat_depth;
CvMat astub, bstub, *a, *b;
- double mat[16];
+ double mat[16] = {0.0};
a = cvGetMat( _src, &astub, 0, 0 );
b = cvGetMat( _dst, &bstub, 0, 0 );
EXPECT_EQ(2, num_defaultResult);
}
+TEST(Core_OutputArrayCreate, _13772)
+{
+ cv::Mat1d mat;
+ cv::OutputArray o(mat);
+ ASSERT_NO_THROW(o.create(3, 5, CV_64F, -1, true));
+}
+
TEST(Core_String, find_last_of__with__empty_string)
ocv_create_module(${libs} ${INF_ENGINE_TARGET})
ocv_add_samples()
ocv_add_accuracy_tests(${INF_ENGINE_TARGET})
-ocv_add_perf_tests(${INF_ENGINE_TARGET})
+
+set(perf_path "${CMAKE_CURRENT_LIST_DIR}/perf")
+file(GLOB_RECURSE perf_srcs "${perf_path}/*.cpp")
+file(GLOB_RECURSE perf_hdrs "${perf_path}/*.hpp" "${perf_path}/*.h")
+ocv_add_perf_tests(${INF_ENGINE_TARGET}
+ FILES test_common "${CMAKE_CURRENT_LIST_DIR}/test/test_common.hpp" "${CMAKE_CURRENT_LIST_DIR}/test/test_common.impl.hpp"
+ FILES Src ${perf_srcs}
+ 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)
CV_OUT std::vector<int>& indices,
const float eta = 1.f, const int top_k = 0);
- /** @brief Release a Myriad device is binded by OpenCV.
- *
- * Single Myriad device cannot be shared across multiple processes which uses
- * Inference Engine's Myriad plugin.
- */
- CV_EXPORTS_W void resetMyriadDevice();
-
//! @}
CV__DNN_INLINE_NS_END
}
#include <opencv2/dnn/layer.hpp>
#include <opencv2/dnn/dnn.inl.hpp>
+/// @deprecated Include this header directly from application. Automatic inclusion will be removed
+#include <opencv2/dnn/utils/inference_engine.hpp>
+
#endif /* OPENCV_DNN_DNN_HPP */
--- /dev/null
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2018-2019, Intel Corporation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+
+#ifndef OPENCV_DNN_UTILS_INF_ENGINE_HPP
+#define OPENCV_DNN_UTILS_INF_ENGINE_HPP
+
+#include "../dnn.hpp"
+
+namespace cv { namespace dnn {
+CV__DNN_INLINE_NS_BEGIN
+
+
+/** @brief Release a Myriad device (binded by OpenCV).
+ *
+ * Single Myriad device cannot be shared across multiple processes which uses
+ * Inference Engine's Myriad plugin.
+ */
+CV_EXPORTS_W void resetMyriadDevice();
+
+
+/* Values for 'OPENCV_DNN_IE_VPU_TYPE' parameter */
+#define CV_DNN_INFERENCE_ENGINE_VPU_TYPE_UNSPECIFIED ""
+/// Intel(R) Movidius(TM) Neural Compute Stick, NCS (USB 03e7:2150), Myriad2 (https://software.intel.com/en-us/movidius-ncs)
+#define CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_2 "Myriad2"
+/// Intel(R) Neural Compute Stick 2, NCS2 (USB 03e7:2485), MyriadX (https://software.intel.com/ru-ru/neural-compute-stick)
+#define CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X "MyriadX"
+
+
+/** @brief Returns Inference Engine VPU type.
+ *
+ * See values of `CV_DNN_INFERENCE_ENGINE_VPU_TYPE_*` macros.
+ */
+CV_EXPORTS_W cv::String getInferenceEngineVPUType();
+
+
+CV__DNN_INLINE_NS_END
+}} // namespace
+
+#endif // OPENCV_DNN_UTILS_INF_ENGINE_HPP
#include "dnn_converters.hpp"
+#define LOG_TAG "org.opencv.dnn"
void Mat_to_MatShape(cv::Mat& mat, MatShape& matshape)
{
--- /dev/null
+// 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 "perf_precomp.hpp"
+#include "../test/test_common.impl.hpp" // shared with accuracy tests
PERF_TEST_P_(DNNTestNetwork, OpenFace)
{
if (backend == DNN_BACKEND_HALIDE ||
- (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16) ||
- (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD))
+ (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD))
throw SkipTestException("");
processNet("dnn/openface_nn4.small2.v1.t7", "", "",
Mat(cv::Size(96, 96), CV_32FC3));
Mat(cv::Size(224, 224), CV_32FC3));
}
-PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_coco)
-{
- if (backend == DNN_BACKEND_HALIDE ||
- (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD))
- throw SkipTestException("");
- processNet("dnn/openpose_pose_coco.caffemodel", "dnn/openpose_pose_coco.prototxt", "",
- Mat(cv::Size(368, 368), CV_32FC3));
-}
-
-PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_mpi)
-{
- if (backend == DNN_BACKEND_HALIDE ||
- (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD))
- throw SkipTestException("");
- processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi.prototxt", "",
- Mat(cv::Size(368, 368), CV_32FC3));
-}
-
PERF_TEST_P_(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages)
{
if (backend == DNN_BACKEND_HALIDE ||
{
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
+ throw SkipTestException("Test is disabled for MyriadX");
+#endif
processNet("dnn/ssd_inception_v2_coco_2017_11_17.pb", "ssd_inception_v2_coco_2017_11_17.pbtxt", "",
Mat(cv::Size(300, 300), CV_32FC3));
}
PERF_TEST_P_(DNNTestNetwork, EAST_text_detection)
{
- if (backend == DNN_BACKEND_HALIDE
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE < 2018030000
- || (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
-#endif
- )
+ if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
processNet("dnn/frozen_east_text_detection.pb", "", "", Mat(cv::Size(320, 320), CV_32FC3));
}
fused_layer_names.push_back(last_layer);
}
- void setYolo(int classes, const std::vector<int>& mask, const std::vector<float>& anchors)
+ void setYolo(int classes, const std::vector<int>& mask, const std::vector<float>& anchors, float thresh, float nms_threshold)
{
cv::dnn::LayerParams region_param;
region_param.name = "Region-name";
region_param.set<int>("classes", classes);
region_param.set<int>("anchors", numAnchors);
region_param.set<bool>("logistic", true);
+ region_param.set<float>("thresh", thresh);
+ region_param.set<float>("nms_threshold", nms_threshold);
std::vector<float> usedAnchors(numAnchors * 2);
for (int i = 0; i < numAnchors; ++i)
{
int classes = getParam<int>(layer_params, "classes", -1);
int num_of_anchors = getParam<int>(layer_params, "num", -1);
+ float thresh = getParam<float>(layer_params, "thresh", 0.2);
+ float nms_threshold = getParam<float>(layer_params, "nms_threshold", 0.4);
std::string anchors_values = getParam<std::string>(layer_params, "anchors", std::string());
CV_Assert(!anchors_values.empty());
CV_Assert(classes > 0 && num_of_anchors > 0 && (num_of_anchors * 2) == anchors_vec.size());
setParams.setPermute(false);
- setParams.setYolo(classes, mask_vec, anchors_vec);
+ setParams.setYolo(classes, mask_vec, anchors_vec, thresh, nms_threshold);
}
else {
CV_Error(cv::Error::StsParseError, "Unknown layer type: " + layer_type);
biases->set(biasesVec);
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5)
- InferenceEngine::Builder::ScaleShiftLayer ieLayer(name);
- ieLayer.setWeights(weights);
- ieLayer.setBiases(biases);
+ InferenceEngine::Builder::Layer ieLayer = InferenceEngine::Builder::ScaleShiftLayer(name);
+ addConstantData("weights", weights, ieLayer);
+ addConstantData("biases", biases, ieLayer);
#else
InferenceEngine::LayerParams lp;
lp.name = name;
preferableTarget == DNN_TARGET_FPGA) && !fused)
{
#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R5)
- bool hasWeights = false;
for (const std::string& name : {"weights", "biases"})
{
auto it = ieNode->layer.getParameters().find(name);
if (it != ieNode->layer.getParameters().end())
{
- InferenceEngine::Blob::CPtr bp = it->second.as<InferenceEngine::Blob::CPtr>();
- it->second = (InferenceEngine::Blob::CPtr)convertFp16(std::const_pointer_cast<InferenceEngine::Blob>(bp));
- hasWeights = true;
+ InferenceEngine::Blob::Ptr bp = it->second.as<InferenceEngine::Blob::Ptr>();
+ it->second = convertFp16(std::const_pointer_cast<InferenceEngine::Blob>(bp));
}
}
- if (!hasWeights)
- {
- InferenceEngine::Blob::Ptr blob = InferenceEngine::make_shared_blob<int16_t>(
- InferenceEngine::Precision::FP16,
- InferenceEngine::Layout::C, {1});
- blob->allocate();
- ieNode->layer.getParameters()["weights"] = (InferenceEngine::Blob::CPtr)blob;
- }
#else
auto& blobs = ieNode->layer.getConstantData();
if (blobs.empty())
}
}
}
-
- if (preferableBackend != DNN_BACKEND_OPENCV)
- continue; // Go to the next layer.
-
// the optimization #2. if there is no layer that takes max pooling layer's computed
// max indices (and only some semantical segmentation networks might need this;
// many others only take the maximum values), then we switch the max pooling
}
}
+ if (preferableBackend != DNN_BACKEND_OPENCV)
+ continue; // Go to the next layer.
+
// the optimization #3. if there is concat layer that concatenates channels
// from the inputs together (i.e. axis == 1) then we make the inputs of
// the concat layer to write to the concatenation output buffer
{
#ifdef HAVE_INF_ENGINE
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5)
- InferenceEngine::Builder::ScaleShiftLayer ieLayer(name);
-
+ InferenceEngine::Builder::Layer ieLayer = InferenceEngine::Builder::ScaleShiftLayer(name);
const size_t numChannels = weights_.total();
- ieLayer.setWeights(wrapToInfEngineBlob(weights_, {numChannels}, InferenceEngine::Layout::C));
- ieLayer.setBiases(wrapToInfEngineBlob(bias_, {numChannels}, InferenceEngine::Layout::C));
+ addConstantData("weights", wrapToInfEngineBlob(weights_, {numChannels}, InferenceEngine::Layout::C), ieLayer);
+ addConstantData("biases", wrapToInfEngineBlob(bias_, {numChannels}, InferenceEngine::Layout::C), ieLayer);
return Ptr<BackendNode>(new InfEngineBackendNode(ieLayer));
#else
InferenceEngine::LayerParams lp;
ieLayer.getParameters()["axis"] = input->dims.size() - 1;
ieLayer.getParameters()["out_sizes"] = input->dims[0];
}
- ieLayer.setInputPorts(std::vector<InferenceEngine::Port>(1));
+ std::vector<size_t> shape(input->dims);
+ std::reverse(shape.begin(), shape.end());
+ ieLayer.setInputPorts({InferenceEngine::Port(shape)});
ieLayer.setOutputPorts(std::vector<InferenceEngine::Port>(1));
return Ptr<BackendNode>(new InfEngineBackendNode(ieLayer));
#else
class BaseConvolutionLayerImpl : public ConvolutionLayer
{
public:
+ bool newWeightAndBias;
+ std::vector<double> weightsMultipliers;
BaseConvolutionLayerImpl(const LayerParams ¶ms)
{
setParamsFrom(params);
CV_Assert(numOutput % ngroups == 0);
CV_Assert(adjustPad.width < stride.width &&
adjustPad.height < stride.height);
+
+ newWeightAndBias = false;
}
void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE
(dilation.height == 1 && dilation.width == 1);
}
+ virtual bool tryFuse(Ptr<Layer>& top) CV_OVERRIDE
+ {
+ Mat w, b;
+ top->getScaleShift(w, b);
+ if (!w.empty() || !b.empty())
+ {
+ fuseWeights(w, b);
+ return true;
+ }
+ return false;
+ }
+
+ virtual void fuseWeights(const Mat& w_, const Mat& b_) = 0;
+
virtual void applyHalideScheduler(Ptr<BackendNode>& node,
const std::vector<Mat*> &inputs,
const std::vector<Mat> &outputs,
public:
enum { VEC_ALIGN = 8, DFT_TYPE = CV_32F };
Mat weightsMat;
- std::vector<double> weightsMultipliers;
std::vector<float> biasvec;
std::vector<float> reluslope;
Ptr<ActivationLayer> activ;
- bool newWeightAndBias;
bool fusedBias;
#ifdef HAVE_OPENCL
#endif
ConvolutionLayerImpl(const LayerParams ¶ms) : BaseConvolutionLayerImpl(params)
{
- newWeightAndBias = false;
fusedBias = false;
#ifdef HAVE_OPENCL
newActiv = false;
return !activ.empty();
}
- virtual bool tryFuse(Ptr<Layer>& top) CV_OVERRIDE
- {
- Mat w, b;
- top->getScaleShift(w, b);
- if (!w.empty() || !b.empty())
- {
- fuseWeights(w, b);
- return true;
- }
- return false;
- }
-
- void fuseWeights(const Mat& w_, const Mat& b_)
+ void fuseWeights(const Mat& w_, const Mat& b_) CV_OVERRIDE
{
// Convolution weights have OIHW data layout. Parameters fusion in case of
// (conv(I) + b1 ) * w + b2
ieLayer.setGroup((size_t)group);
ieLayer.setOutDepth((size_t)outCn);
- ieLayer.setWeights(ieWeights);
+ InferenceEngine::Builder::Layer l = ieLayer;
+ addConstantData("weights", ieWeights, l);
if (ieBiases)
- ieLayer.setBiases(ieBiases);
+ addConstantData("biases", ieBiases, l);
- InferenceEngine::Builder::Layer l = ieLayer;
if (!padMode.empty())
l.getParameters()["auto_pad"] = padMode == "VALID" ? std::string("valid") : std::string("same_upper");
const int group = numOutput / outGroupCn;
if (group != 1)
{
-#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R3)
return preferableTarget == DNN_TARGET_CPU;
-#endif
- return false;
}
if (preferableTarget == DNN_TARGET_OPENCL || preferableTarget == DNN_TARGET_OPENCL_FP16)
return dilation.width == 1 && dilation.height == 1;
int dims[] = {inputs[0][0], outCn, outH, outW};
outputs.resize(inputs.size(), shape(dims, 4));
- internals.push_back(MatShape());
if (!is1x1())
- internals[0] = computeColRowShape(inputs[0], outputs[0]);
-
- if (hasBias())
- internals.push_back(shape(1, outH*outW));
+ internals.push_back(computeColRowShape(inputs[0], outputs[0]));
return false;
}
pad.width = pad_l;
pad.height = pad_t;
+
+ weightsMultipliers.assign(numOutput, 1.0);
+ if (weightsMat.empty())
+ {
+ transpose(blobs[0].reshape(1, blobs[0].size[0]), weightsMat);
+ biasesMat = hasBias() ? blobs[1].reshape(1, numOutput)
+ : Mat::zeros(numOutput, 1, CV_32F);
+ }
+ }
+
+ void fuseWeights(const Mat& w_, const Mat& b_) CV_OVERRIDE
+ {
+ Mat w = w_.total() == 1 ? Mat(1, numOutput, CV_32F, Scalar(w_.at<float>(0))) : w_;
+ Mat b = b_.total() == 1 ? Mat(1, numOutput, CV_32F, Scalar(b_.at<float>(0))) : b_;
+
+ CV_Assert_N(!weightsMat.empty(),
+ w.empty() || numOutput == w.total(),
+ b.empty() || numOutput == b.total());
+
+ if (!w.empty())
+ {
+ transpose(blobs[0].reshape(1, blobs[0].size[0]), weightsMat);
+ weightsMat = weightsMat.reshape(1, numOutput);
+ for (int i = 0; i < numOutput; ++i)
+ {
+ double wi = w.at<float>(i);
+ weightsMultipliers[i] *= wi;
+ cv::multiply(weightsMat.row(i), weightsMultipliers[i], weightsMat.row(i));
+ biasesMat.at<float>(i) *= wi;
+ }
+ weightsMat = weightsMat.reshape(1, weightsMat.total() / blobs[0].size[0]);
+ }
+
+ if (!b.empty())
+ {
+ cv::add(biasesMat, b.reshape(1, numOutput), biasesMat);
+ }
+
+ newWeightAndBias = !w.empty() || !b.empty();
}
class MatMulInvoker : public ParallelLoopBody
if (umat_weights.empty())
{
- transpose(blobs[0].reshape(1, inpCn), umat_weights);
- if (hasBias())
- blobs[1].reshape(1, outCn).copyTo(umat_biases);
+ if (newWeightAndBias)
+ {
+ weightsMat.copyTo(umat_weights);
+ biasesMat.copyTo(umat_biases);
+ }
else
- umat_biases = UMat::zeros(outCn, 1, CV_32F);
+ {
+ transpose(blobs[0].reshape(1, inpCn), umat_weights);
+ if (hasBias())
+ blobs[1].reshape(1, outCn).copyTo(umat_biases);
+ else
+ umat_biases = UMat::zeros(outCn, 1, CV_32F);
+ }
}
String buildopt = format("-DT=%s ", ocl::typeToStr(inputs[0].type()));
ieLayer.setGroup((size_t)group);
ieLayer.setOutDepth((size_t)numOutput);
- ieLayer.setWeights(wrapToInfEngineBlob(blobs[0], InferenceEngine::Layout::OIHW));
+ InferenceEngine::Builder::Layer l = ieLayer;
+ addConstantData("weights", wrapToInfEngineBlob(blobs[0], InferenceEngine::Layout::OIHW), l);
if (hasBias())
- {
- ieLayer.setBiases(wrapToInfEngineBlob(blobs[1], {(size_t)numOutput}, InferenceEngine::Layout::C));
- }
- return Ptr<BackendNode>(new InfEngineBackendNode(ieLayer));
+ addConstantData("biases", wrapToInfEngineBlob(blobs[1], {(size_t)numOutput}, InferenceEngine::Layout::C), l);
+ return Ptr<BackendNode>(new InfEngineBackendNode(l));
#else
const int outGroupCn = blobs[0].size[1]; // Weights are in IOHW layout
const int group = numOutput / outGroupCn;
_backgroundLabelId = getParameter<int>(params, "background_label_id");
_varianceEncodedInTarget = getParameter<bool>(params, "variance_encoded_in_target", 0, false, false);
_keepTopK = getParameter<int>(params, "keep_top_k");
- _confidenceThreshold = getParameter<float>(params, "confidence_threshold", 0, false, -FLT_MAX);
+ _confidenceThreshold = getParameter<float>(params, "confidence_threshold", 0, false, 0);
_topK = getParameter<int>(params, "top_k", 0, false, -1);
_locPredTransposed = getParameter<bool>(params, "loc_pred_transposed", 0, false, false);
_bboxesNormalized = getParameter<bool>(params, "normalized_bbox", 0, false, true);
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5)
InferenceEngine::Builder::Layer initInfEngineBuilderAPI()
{
- InferenceEngine::Builder::PReLULayer ieLayer("");
+ InferenceEngine::Builder::Layer l = InferenceEngine::Builder::PReLULayer("");
const size_t numChannels = scale.total();
- ieLayer.setWeights(wrapToInfEngineBlob(scale, {numChannels}, InferenceEngine::Layout::C));
- return ieLayer;
+ addConstantData("weights", wrapToInfEngineBlob(scale, {numChannels}, InferenceEngine::Layout::C), l);
+ return l;
}
#else
InferenceEngine::CNNLayerPtr initInfEngine(InferenceEngine::LayerParams& lp)
const int outNum = blobs[0].size[0];
ieLayer.setOutputNum(outNum);
- ieLayer.setWeights(wrapToInfEngineBlob(blobs[0], {(size_t)blobs[0].size[0], (size_t)blobs[0].size[1], 1, 1}, InferenceEngine::Layout::OIHW));
+ InferenceEngine::Builder::Layer l = ieLayer;
+ addConstantData("weights", wrapToInfEngineBlob(blobs[0], {(size_t)blobs[0].size[0], (size_t)blobs[0].size[1], 1, 1}, InferenceEngine::Layout::OIHW), l);
if (blobs.size() > 1)
- ieLayer.setBiases(wrapToInfEngineBlob(blobs[1], {(size_t)outNum}, InferenceEngine::Layout::C));
+ addConstantData("biases", wrapToInfEngineBlob(blobs[1], {(size_t)outNum}, InferenceEngine::Layout::C), l);
- return Ptr<BackendNode>(new InfEngineBackendNode(ieLayer));
+ return Ptr<BackendNode>(new InfEngineBackendNode(l));
#else
InferenceEngine::LayerParams lp;
lp.name = name;
virtual bool supportBackend(int backendId) CV_OVERRIDE
{
+ if (backendId == DNN_BACKEND_INFERENCE_ENGINE)
+ return bias == 1;
return backendId == DNN_BACKEND_OPENCV ||
backendId == DNN_BACKEND_HALIDE ||
- (backendId == DNN_BACKEND_INFERENCE_ENGINE && (preferableTarget != DNN_TARGET_MYRIAD || type == CHANNEL_NRM)) ||
(backendId == DNN_BACKEND_VKCOM && haveVulkan() && (size % 2 == 1) && (type == CHANNEL_NRM));
}
virtual Ptr<BackendNode> initInfEngine(const std::vector<Ptr<BackendWrapper> >&) CV_OVERRIDE
{
#ifdef HAVE_INF_ENGINE
+ float alphaSize = alpha;
+ if (!normBySize)
+ alphaSize *= (type == SPATIAL_NRM ? size*size : size);
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5)
InferenceEngine::Builder::NormLayer ieLayer(name);
ieLayer.setSize(size);
- ieLayer.setAlpha(alpha);
+ ieLayer.setAlpha(alphaSize);
ieLayer.setBeta(beta);
ieLayer.setAcrossMaps(type == CHANNEL_NRM);
ieLayer->_size = size;
ieLayer->_k = (int)bias;
ieLayer->_beta = beta;
- ieLayer->_alpha = alpha;
+ ieLayer->_alpha = alphaSize;
ieLayer->_isAcrossMaps = (type == CHANNEL_NRM);
return Ptr<BackendNode>(new InfEngineBackendNode(ieLayer));
#endif
{
if (pnorm != 2)
return false;
- if (!blobs.empty())
- return true;
- if (preferableTarget == DNN_TARGET_MYRIAD)
- return !acrossSpatial;
- return startAxis == 1 && (!acrossSpatial || endAxis > 1);
+
+ return preferableTarget == DNN_TARGET_MYRIAD ? !acrossSpatial : startAxis == 1;
}
- else
- return backendId == DNN_BACKEND_OPENCV;
+ return backendId == DNN_BACKEND_OPENCV;
}
bool getMemoryShapes(const std::vector<MatShape> &inputs,
l.getParameters()["channel_shared"] = blobs[0].total() == 1;
}
#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R5)
- l.getParameters()["weights"] = (InferenceEngine::Blob::CPtr)weights;
+ l.getParameters()["weights"] = weights;
#else
l.addConstantData("weights", weights);
#endif
{
if (backendId == DNN_BACKEND_INFERENCE_ENGINE)
{
- if (preferableTarget == DNN_TARGET_MYRIAD)
+#ifdef HAVE_INF_ENGINE
+ if (preferableTarget == DNN_TARGET_MYRIAD) {
+ if (type == MAX && (pad_l == 1 && pad_t == 1) && stride == Size(2, 2) ) {
+ return !isMyriadX();
+ }
return type == MAX || type == AVE;
+ }
else
return type != STOCHASTIC;
+#else
+ return false;
+#endif
}
else
return backendId == DNN_BACKEND_OPENCV ||
if (_stepX == _stepY)
{
l.getParameters()["step"] = _stepX;
- l.getParameters()["step_h"] = 0.0;
- l.getParameters()["step_w"] = 0.0;
+ l.getParameters()["step_h"] = 0.0f;
+ l.getParameters()["step_w"] = 0.0f;
}
else
{
- l.getParameters()["step"] = 0.0;
+ l.getParameters()["step"] = 0.0f;
l.getParameters()["step_h"] = _stepY;
l.getParameters()["step_w"] = _stepX;
}
dstData[box_index + 0] = (x + logistic_activate(srcData[box_index + 0])) / cols;
dstData[box_index + 1] = (y + logistic_activate(srcData[box_index + 1])) / rows;
- dstData[box_index + 2] = exp(srcData[box_index + 2]) * biasData[2 * a] / hNorm;
- dstData[box_index + 3] = exp(srcData[box_index + 3]) * biasData[2 * a + 1] / wNorm;
+ dstData[box_index + 2] = exp(srcData[box_index + 2]) * biasData[2 * a] / wNorm;
+ dstData[box_index + 3] = exp(srcData[box_index + 3]) * biasData[2 * a + 1] / hNorm;
int class_index = index_sample_offset + index * cell_size + 5;
for (int j = 0; j < classes; ++j) {
#ifdef HAVE_INF_ENGINE
if (backendId == DNN_BACKEND_INFERENCE_ENGINE)
{
- return (interpolation == "nearest" && preferableTarget != DNN_TARGET_MYRIAD) ||
+ return (interpolation == "nearest" && scaleWidth == scaleHeight) ||
(interpolation == "bilinear" && INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R4));
}
- else
#endif
- return backendId == DNN_BACKEND_OPENCV;
+ return backendId == DNN_BACKEND_OPENCV;
}
virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE
{
#ifdef HAVE_INF_ENGINE
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5)
- InferenceEngine::Builder::ScaleShiftLayer ieLayer(name);
+ InferenceEngine::Builder::Layer l = InferenceEngine::Builder::ScaleShiftLayer(name);
CV_Assert(!blobs.empty());
const size_t numChannels = blobs[0].total();
if (hasWeights)
{
- ieLayer.setWeights(wrapToInfEngineBlob(blobs[0], {numChannels}, InferenceEngine::Layout::C));
+ addConstantData("weights", wrapToInfEngineBlob(blobs[0], {numChannels}, InferenceEngine::Layout::C), l);
}
else
{
std::vector<float> ones(numChannels, 1);
weights->set(ones);
- ieLayer.setWeights(weights);
+ addConstantData("weights", weights, l);
}
if (hasBias)
- ieLayer.setBiases(wrapToInfEngineBlob(blobs.back(), {numChannels}, InferenceEngine::Layout::C));
- return Ptr<BackendNode>(new InfEngineBackendNode(ieLayer));
+ addConstantData("biases", wrapToInfEngineBlob(blobs.back(), {numChannels}, InferenceEngine::Layout::C), l);
+ return Ptr<BackendNode>(new InfEngineBackendNode(l));
#else
InferenceEngine::LayerParams lp;
lp.name = name;
}
else
{
- CV_LOG_VERBOSE(NULL, "Kernel " << config->kernelName << " pass verification");
+ CV_LOG_VERBOSE(NULL, 0, "Kernel " << config->kernelName << " pass verification");
}
}
catch (...)
layerParams.set("ceil_mode", isCeilMode(layerParams));
layerParams.set("ave_pool_padded_area", framework_name == "pytorch");
}
- else if (layer_type == "GlobalAveragePool")
+ else if (layer_type == "GlobalAveragePool" || layer_type == "GlobalMaxPool")
{
layerParams.type = "Pooling";
- layerParams.set("pool", "AVE");
+ layerParams.set("pool", layer_type == "GlobalAveragePool" ? "AVE" : "MAX");
layerParams.set("global_pooling", true);
}
else if (layer_type == "Add" || layer_type == "Sum")
layerParams.set("bias_term", false);
}
}
+ else if (layer_type == "Neg")
+ {
+ layerParams.type = "Power";
+ layerParams.set("scale", -1);
+ }
else if (layer_type == "Constant")
{
CV_Assert(node_proto.input_size() == 0);
for (int j = 1; j < node_proto.input_size(); j++) {
layerParams.blobs.push_back(getBlob(node_proto, constBlobs, j));
}
- layerParams.set("num_output", layerParams.blobs[0].size[1]);
+ layerParams.set("num_output", layerParams.blobs[0].size[1] * layerParams.get<int>("group", 1));
layerParams.set("bias_term", node_proto.input_size() == 3);
+
+ if (layerParams.has("output_shape"))
+ {
+ const DictValue& outShape = layerParams.get("output_shape");
+
+ if (outShape.size() != 4)
+ CV_Error(Error::StsNotImplemented, "Output shape must have 4 elements.");
+
+ const int strideY = layerParams.get<int>("stride_h", 1);
+ const int strideX = layerParams.get<int>("stride_w", 1);
+ const int outH = outShape.getIntValue(2);
+ const int outW = outShape.getIntValue(3);
+
+ if (layerParams.get<String>("pad_mode") == "SAME")
+ {
+ layerParams.set("adj_w", (outW - 1) % strideX);
+ layerParams.set("adj_h", (outH - 1) % strideY);
+ }
+ else if (layerParams.get<String>("pad_mode") == "VALID")
+ {
+ if (!layerParams.has("kernel_h") || !layerParams.has("kernel_w"))
+ CV_Error(Error::StsNotImplemented,
+ "Required attributes 'kernel_h' and 'kernel_w' are not present.");
+
+ int kernelH = layerParams.get<int>("kernel_h");
+ int kernelW = layerParams.get<int>("kernel_w");
+
+ layerParams.set("adj_w", (outW - kernelW) % strideX);
+ layerParams.set("adj_h", (outH - kernelH) % strideY);
+ }
+ }
}
else if (layer_type == "Transpose")
{
else if (layer_type == "Unsqueeze")
{
CV_Assert(node_proto.input_size() == 1);
- Mat input = getBlob(node_proto, constBlobs, 0);
-
DictValue axes = layerParams.get("axes");
- std::vector<int> dims;
- for (int j = 0; j < input.dims; j++) {
- dims.push_back(input.size[j]);
- }
- CV_Assert(axes.getIntValue(axes.size()-1) <= dims.size());
- for (int j = 0; j < axes.size(); j++) {
- dims.insert(dims.begin() + axes.getIntValue(j), 1);
+ if (constBlobs.find(node_proto.input(0)) != constBlobs.end())
+ {
+ // Constant input.
+ Mat input = getBlob(node_proto, constBlobs, 0);
+
+ std::vector<int> dims;
+ for (int j = 0; j < input.dims; j++) {
+ dims.push_back(input.size[j]);
+ }
+ CV_Assert(axes.getIntValue(axes.size()-1) <= dims.size());
+ for (int j = 0; j < axes.size(); j++) {
+ dims.insert(dims.begin() + axes.getIntValue(j), 1);
+ }
+
+ Mat out = input.reshape(0, dims);
+ constBlobs.insert(std::make_pair(layerParams.name, out));
+ continue;
}
- Mat out = input.reshape(0, dims);
- constBlobs.insert(std::make_pair(layerParams.name, out));
- continue;
+ // Variable input.
+ if (axes.size() != 1)
+ CV_Error(Error::StsNotImplemented, "Multidimensional unsqueeze");
+
+ int dims[] = {1, -1};
+ layerParams.type = "Reshape";
+ layerParams.set("axis", axes.getIntValue(0));
+ layerParams.set("num_axes", 1);
+ layerParams.set("dim", DictValue::arrayInt(&dims[0], 2));
}
else if (layer_type == "Reshape")
{
continue;
}
}
+ else if (layer_type == "Upsample")
+ {
+ layerParams.type = "Resize";
+ if (layerParams.has("scales"))
+ {
+ // Pytorch layer
+ DictValue scales = layerParams.get("scales");
+ CV_Assert(scales.size() == 4);
+ layerParams.set("zoom_factor_y", scales.getIntValue(2));
+ layerParams.set("zoom_factor_x", scales.getIntValue(3));
+ }
+ else
+ {
+ // Caffe2 layer
+ replaceLayerParam(layerParams, "height_scale", "zoom_factor_y");
+ replaceLayerParam(layerParams, "width_scale", "zoom_factor_x");
+ }
+ replaceLayerParam(layerParams, "mode", "interpolation");
+ }
else
{
for (int j = 0; j < node_proto.input_size(); j++) {
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
-// Copyright (C) 2018, Intel Corporation, all rights reserved.
+// Copyright (C) 2018-2019, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
#include "precomp.hpp"
#ifdef HAVE_INF_ENGINE
#include <ie_extension.h>
#include <ie_plugin_dispatcher.hpp>
+#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5)
+#include <vpu/vpu_plugin_config.hpp>
+#endif
#endif // HAVE_INF_ENGINE
+#include <opencv2/core/utils/configuration.private.hpp>
+#include <opencv2/core/utils/logger.hpp>
+
namespace cv { namespace dnn {
#ifdef HAVE_INF_ENGINE
+// For networks with input layer which has an empty name, IE generates a name id[some_number].
+// OpenCV lets users use an empty input name and to prevent unexpected naming,
+// we can use some predefined name.
+static std::string kDefaultInpLayerName = "empty_inp_layer_name";
+
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5)
InfEngineBackendNode::InfEngineBackendNode(const InferenceEngine::Builder::Layer& _layer)
: BackendNode(DNN_BACKEND_INFERENCE_ENGINE), layer(_layer) {}
it = layers.find(inpName);
if (it == layers.end())
{
- InferenceEngine::Builder::InputLayer inpLayer(inpName);
+ InferenceEngine::Builder::InputLayer inpLayer(!inpName.empty() ? inpName : kDefaultInpLayerName);
std::vector<size_t> shape(inp->blob->dims());
std::reverse(shape.begin(), shape.end());
for (int id : unconnectedLayersIds)
{
InferenceEngine::Builder::OutputLayer outLayer("myconv1");
+#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R5)
+ // Inference Engine determines network precision by ports.
+ InferenceEngine::Precision p = (targetId == DNN_TARGET_MYRIAD ||
+ targetId == DNN_TARGET_OPENCL_FP16) ?
+ InferenceEngine::Precision::FP16 :
+ InferenceEngine::Precision::FP32;
+ outLayer.setPort(InferenceEngine::Port({}, p));
+#endif
netBuilder.addLayer({InferenceEngine::PortInfo(id)}, outLayer);
}
cnn = InferenceEngine::CNNNetwork(InferenceEngine::Builder::convertToICNNNetwork(netBuilder.build()));
initPlugin(cnn);
}
-void InfEngineBackendNet::addLayer(const InferenceEngine::Builder::Layer& layer)
+void InfEngineBackendNet::addLayer(InferenceEngine::Builder::Layer& layer)
{
+#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R5)
+ // Add weights to network and connect them after input blobs.
+ std::map<std::string, InferenceEngine::Parameter>& params = layer.getParameters();
+ std::vector<int> blobsIds;
+ std::vector<int> portIds;
+ for (const std::string& name : {"weights", "biases"})
+ {
+ bool asInput = false;
+ int portId = 0;
+ for (int i = 0; i < layer.getInputPorts().size(); ++i)
+ {
+ const auto& port = layer.getInputPorts()[i];
+ auto it = port.getParameters().find("type");
+ if (it != port.getParameters().end() && it->second == name)
+ {
+ portId = i;
+ asInput = true;
+ break;
+ }
+ }
+
+ if (!asInput)
+ continue;
+
+ auto it = params.find(name);
+ if (it != params.end())
+ {
+ InferenceEngine::Blob::Ptr blob = it->second.as<InferenceEngine::Blob::Ptr>();
+ params.erase(it);
+ int blobId = netBuilder.addLayer(InferenceEngine::Builder::ConstLayer(name).setData(blob));
+ blobsIds.push_back(blobId);
+ portIds.push_back(portId);
+ }
+ }
+#endif
+
int id = netBuilder.addLayer(layer);
const std::string& layerName = layer.getName();
CV_Assert(layers.insert({layerName, id}).second);
unconnectedLayersIds.insert(id);
+
+#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R5)
+ // By default, all the weights are connected to last ports ids.
+ for (int i = 0; i < blobsIds.size(); ++i)
+ {
+ netBuilder.connect((size_t)blobsIds[i], {(size_t)id, (size_t)portIds[i]});
+ }
+#endif
}
void InfEngineBackendNet::addOutput(const std::string& name)
return batchSize;
}
-#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R2)
InferenceEngine::StatusCode InfEngineBackendNet::AddExtension(const InferenceEngine::IShapeInferExtensionPtr &extension, InferenceEngine::ResponseDesc *resp) CV_NOEXCEPT
{
CV_Error(Error::StsNotImplemented, "");
CV_Error(Error::StsNotImplemented, "");
return InferenceEngine::StatusCode::OK;
}
-#endif
void InfEngineBackendNet::init(int targetId)
{
return sharedPlugins;
}
+
+#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5) && !defined(OPENCV_DNN_IE_VPU_TYPE_DEFAULT)
+static bool detectMyriadX_()
+{
+ InferenceEngine::Builder::Network builder("");
+ InferenceEngine::idx_t inpId = builder.addLayer(
+ InferenceEngine::Builder::InputLayer().setPort(InferenceEngine::Port({1})));
+
+#if INF_ENGINE_RELEASE <= 2018050000
+ InferenceEngine::idx_t clampId;
+ {
+ InferenceEngine::Builder::Layer l = InferenceEngine::Builder::ClampLayer();
+ auto& blobs = l.getConstantData();
+ auto blob = InferenceEngine::make_shared_blob<int16_t>(
+ InferenceEngine::Precision::FP16,
+ InferenceEngine::Layout::C, {1});
+ blob->allocate();
+ blobs[""] = blob;
+ clampId = builder.addLayer({inpId}, l);
+ }
+ builder.addLayer({InferenceEngine::PortInfo(clampId)}, InferenceEngine::Builder::OutputLayer());
+#else
+ InferenceEngine::idx_t clampId = builder.addLayer({inpId}, InferenceEngine::Builder::ClampLayer());
+ builder.addLayer({InferenceEngine::PortInfo(clampId)},
+ InferenceEngine::Builder::OutputLayer().setPort(InferenceEngine::Port({},
+ InferenceEngine::Precision::FP16)));
+#endif
+
+ InferenceEngine::CNNNetwork cnn = InferenceEngine::CNNNetwork(
+ InferenceEngine::Builder::convertToICNNNetwork(builder.build()));
+
+ InferenceEngine::TargetDevice device = InferenceEngine::TargetDevice::eMYRIAD;
+ InferenceEngine::InferenceEnginePluginPtr enginePtr;
+ {
+ AutoLock lock(getInitializationMutex());
+ auto& sharedPlugins = getSharedPlugins();
+ auto pluginIt = sharedPlugins.find(device);
+ if (pluginIt != sharedPlugins.end()) {
+ enginePtr = pluginIt->second;
+ } else {
+ auto dispatcher = InferenceEngine::PluginDispatcher({""});
+ enginePtr = dispatcher.getSuitablePlugin(device);
+ sharedPlugins[device] = enginePtr;
+ }
+ }
+ auto plugin = InferenceEngine::InferencePlugin(enginePtr);
+ try
+ {
+ auto netExec = plugin.LoadNetwork(cnn, {{InferenceEngine::VPUConfigParams::KEY_VPU_PLATFORM,
+ InferenceEngine::VPUConfigParams::VPU_2480}});
+ auto infRequest = netExec.CreateInferRequest();
+ } catch(...) {
+ return false;
+ }
+ return true;
+}
+#endif // >= 2018R5
+
void InfEngineBackendNet::initPlugin(InferenceEngine::ICNNNetwork& net)
{
CV_Assert(!isInitialized());
{
std::string name = wrapper->dataPtr->name;
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5)
- name = name.empty() ? "id1" : name; // TODO: drop the magic input name.
+ name = name.empty() ? kDefaultInpLayerName : name;
#endif
allBlobs.insert({name, wrapper->blob});
}
std::vector<MatShape> &outputs,
std::vector<MatShape> &internals) const
{
+#if INF_ENGINE_VER_MAJOR_EQ(INF_ENGINE_RELEASE_2018R3)
+ InferenceEngine::ICNNNetwork::InputShapes inShapes = const_cast<InferenceEngine::CNNNetwork&>(t_net).getInputShapes();
+#else
InferenceEngine::ICNNNetwork::InputShapes inShapes = t_net.getInputShapes();
+#endif
InferenceEngine::ICNNNetwork::InputShapes::iterator itr;
bool equal_flag = true;
size_t i = 0;
return halfs;
}
+#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5)
+void addConstantData(const std::string& name, InferenceEngine::Blob::Ptr data,
+ InferenceEngine::Builder::Layer& l)
+{
+#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R5)
+ l.getParameters()[name] = data;
+#else
+ l.addConstantData(name, data);
+#endif
+}
+#endif
+
#endif // HAVE_INF_ENGINE
bool haveInfEngine()
#endif // HAVE_INF_ENGINE
}
+#ifdef HAVE_INF_ENGINE
+bool isMyriadX()
+{
+ static bool myriadX = getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X;
+ return myriadX;
+}
+
+static std::string getInferenceEngineVPUType_()
+{
+ static std::string param_vpu_type = utils::getConfigurationParameterString("OPENCV_DNN_IE_VPU_TYPE", "");
+ if (param_vpu_type == "")
+ {
+#if defined(OPENCV_DNN_IE_VPU_TYPE_DEFAULT)
+ param_vpu_type = OPENCV_DNN_IE_VPU_TYPE_DEFAULT;
+#elif INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5)
+ CV_LOG_INFO(NULL, "OpenCV-DNN: running Inference Engine VPU autodetection: Myriad2/X. In case of other accelerator types specify 'OPENCV_DNN_IE_VPU_TYPE' parameter");
+ try {
+ bool isMyriadX_ = detectMyriadX_();
+ if (isMyriadX_)
+ {
+ param_vpu_type = CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X;
+ }
+ else
+ {
+ param_vpu_type = CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_2;
+ }
+ }
+ catch (...)
+ {
+ CV_LOG_WARNING(NULL, "OpenCV-DNN: Failed Inference Engine VPU autodetection. Specify 'OPENCV_DNN_IE_VPU_TYPE' parameter.");
+ param_vpu_type.clear();
+ }
+#else
+ CV_LOG_WARNING(NULL, "OpenCV-DNN: VPU auto-detection is not implemented. Consider specifying VPU type via 'OPENCV_DNN_IE_VPU_TYPE' parameter");
+ param_vpu_type = CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_2;
+#endif
+ }
+ CV_LOG_INFO(NULL, "OpenCV-DNN: Inference Engine VPU type='" << param_vpu_type << "'");
+ return param_vpu_type;
+}
+
+cv::String getInferenceEngineVPUType()
+{
+ static cv::String vpu_type = getInferenceEngineVPUType_();
+ return vpu_type;
+}
+#else // HAVE_INF_ENGINE
+cv::String getInferenceEngineVPUType()
+{
+ CV_Error(Error::StsNotImplemented, "This OpenCV build doesn't include InferenceEngine support");
+}
+#endif // HAVE_INF_ENGINE
+
+
CV__DNN_INLINE_NS_END
}} // namespace dnn, namespace cv
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
-// Copyright (C) 2018, Intel Corporation, all rights reserved.
+// Copyright (C) 2018-2019, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
#ifndef __OPENCV_DNN_OP_INF_ENGINE_HPP__
#include "opencv2/core/cvstd.hpp"
#include "opencv2/dnn.hpp"
+#include "opencv2/dnn/utils/inference_engine.hpp"
+
#ifdef HAVE_INF_ENGINE
#if defined(__GNUC__) && __GNUC__ >= 5
//#pragma GCC diagnostic push
//#pragma GCC diagnostic pop
#endif
-#define INF_ENGINE_RELEASE_2018R1 2018010000
-#define INF_ENGINE_RELEASE_2018R2 2018020000
#define INF_ENGINE_RELEASE_2018R3 2018030000
#define INF_ENGINE_RELEASE_2018R4 2018040000
#define INF_ENGINE_RELEASE_2018R5 2018050000
virtual size_t getBatchSize() const CV_NOEXCEPT CV_OVERRIDE;
-#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R2)
- virtual InferenceEngine::StatusCode AddExtension(const InferenceEngine::IShapeInferExtensionPtr& extension, InferenceEngine::ResponseDesc* resp) CV_NOEXCEPT;
- virtual InferenceEngine::StatusCode reshape(const InputShapes& inputShapes, InferenceEngine::ResponseDesc* resp) CV_NOEXCEPT;
-#endif
+ virtual InferenceEngine::StatusCode AddExtension(const InferenceEngine::IShapeInferExtensionPtr& extension, InferenceEngine::ResponseDesc* resp) CV_NOEXCEPT CV_OVERRIDE;
+ virtual InferenceEngine::StatusCode reshape(const InputShapes& inputShapes, InferenceEngine::ResponseDesc* resp) CV_NOEXCEPT CV_OVERRIDE;
void init(int targetId);
InfEngineBackendNet(InferenceEngine::CNNNetwork& net);
- void addLayer(const InferenceEngine::Builder::Layer& layer);
+ void addLayer(InferenceEngine::Builder::Layer& layer);
void addOutput(const std::string& name);
// Allocates memory for a new blob.
InferenceEngine::Blob::Ptr convertFp16(const InferenceEngine::Blob::Ptr& blob);
+#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2018R5)
+void addConstantData(const std::string& name, InferenceEngine::Blob::Ptr data, InferenceEngine::Builder::Layer& l);
+#endif
+
// This is a fake class to run networks from Model Optimizer. Objects of that
// class simulate responses of layers are imported by OpenCV and supported by
// Inference Engine. The main difference is that they do not perform forward pass.
InferenceEngine::CNNNetwork t_net;
};
+CV__DNN_INLINE_NS_BEGIN
+
+bool isMyriadX();
+
+CV__DNN_INLINE_NS_END
+
#endif // HAVE_INF_ENGINE
bool haveInfEngine();
}
};
+class SoftMaxSlimSubgraph : public Subgraph
+{
+public:
+ SoftMaxSlimSubgraph()
+ {
+ int input = addNodeToMatch("");
+ int shape = addNodeToMatch("Const");
+ int shapeOp = addNodeToMatch("Shape", input);
+ int reshape = addNodeToMatch("Reshape", input, shape);
+ int softmax = addNodeToMatch("Softmax", reshape);
+ addNodeToMatch("Reshape", softmax, shapeOp);
+ setFusedNode("Softmax", input);
+ }
+};
+
void simplifySubgraphs(tensorflow::GraphDef& net)
{
std::vector<Ptr<Subgraph> > subgraphs;
subgraphs.push_back(Ptr<Subgraph>(new ResizeBilinearSubgraph()));
subgraphs.push_back(Ptr<Subgraph>(new UpsamplingKerasSubgraph()));
subgraphs.push_back(Ptr<Subgraph>(new ReshapeAsShapeSubgraph()));
+ subgraphs.push_back(Ptr<Subgraph>(new SoftMaxSlimSubgraph()));
int numNodes = net.node_size();
std::vector<int> matchedNodesIds;
RemoveIdentityOps(netTxt);
if (!netTxt.ByteSize())
+ {
simplifySubgraphs(netBin);
+ sortByExecutionOrder(netBin);
+ }
std::set<String> layers_to_ignore;
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
-// Copyright (C) 2018, Intel Corporation, all rights reserved.
+// Copyright (C) 2018-2019, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
#include "test_precomp.hpp"
throw SkipTestException("");
Mat sample = imread(findDataFile("dnn/street.png", false));
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) ? 6e-3 : 0.0;
- processNet("dnn/MobileNetSSD_deploy.caffemodel", "dnn/MobileNetSSD_deploy.prototxt",
- inp, "detection_out", "", diffScores);
+ 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 : 0.0;
+ processNet("dnn/MobileNetSSD_deploy.caffemodel", "dnn/MobileNetSSD_deploy.prototxt",
+ inp, "detection_out", "", diffScores, diffSquares, detectionConfThresh);
}
TEST_P(DNNTestNetwork, MobileNet_SSD_Caffe_Different_Width_Height)
{
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
+ throw SkipTestException("Test is disabled for MyriadX");
+#endif
Mat sample = imread(findDataFile("dnn/street.png", false));
Mat inp = blobFromImage(sample, 1.0f / 127.5, Size(300, 560), Scalar(127.5, 127.5, 127.5), false);
float diffScores = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.029 : 0.0;
float diffSquares = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.09 : 0.0;
processNet("dnn/MobileNetSSD_deploy.caffemodel", "dnn/MobileNetSSD_deploy.prototxt",
- inp, "detection_out", "", diffScores, diffSquares);
+ inp, "detection_out", "", diffScores, diffSquares);
+
}
TEST_P(DNNTestNetwork, MobileNet_SSD_v1_TensorFlow)
throw SkipTestException("");
Mat sample = imread(findDataFile("dnn/street.png", false));
Mat inp = blobFromImage(sample, 1.0f, Size(300, 300), Scalar(), false);
- float l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.011 : 0.0;
- float lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.06 : 0.0;
+ float l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.095 : 0.0;
+ float lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.09 : 0.0;
+ float detectionConfThresh = (target == DNN_TARGET_MYRIAD) ? 0.216 : 0.2;
processNet("dnn/ssd_mobilenet_v1_coco_2017_11_17.pb", "dnn/ssd_mobilenet_v1_coco_2017_11_17.pbtxt",
- inp, "detection_out", "", l1, lInf);
+ inp, "detection_out", "", l1, lInf, detectionConfThresh);
}
TEST_P(DNNTestNetwork, MobileNet_SSD_v1_TensorFlow_Different_Width_Height)
{
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
+ throw SkipTestException("Test is disabled for MyriadX");
+#endif
Mat sample = imread(findDataFile("dnn/street.png", false));
Mat inp = blobFromImage(sample, 1.0f, Size(300, 560), Scalar(), false);
float l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.012 : 0.0;
if (backend == DNN_BACKEND_HALIDE && target == DNN_TARGET_CPU)
throw SkipTestException("");
double scoreThreshold = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.0325 : 0.0;
+ const float lInf = (target == DNN_TARGET_MYRIAD) ? 0.032 : 0.0;
Mat sample = imread(findDataFile("dnn/street.png", false));
Mat inp = blobFromImage(sample, 1.0f, Size(300, 300), Scalar(), false);
processNet("dnn/VGG_ILSVRC2016_SSD_300x300_iter_440000.caffemodel",
- "dnn/ssd_vgg16.prototxt", inp, "detection_out", "", scoreThreshold);
+ "dnn/ssd_vgg16.prototxt", inp, "detection_out", "", scoreThreshold, lInf);
}
TEST_P(DNNTestNetwork, OpenPose_pose_coco)
{
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
+ throw SkipTestException("Test is disabled for OpenVINO <= 2018R5 + MyriadX target");
+#endif
+
+ const float l1 = (target == DNN_TARGET_MYRIAD) ? 0.0056 : 0.0;
+ const float lInf = (target == DNN_TARGET_MYRIAD) ? 0.072 : 0.0;
processNet("dnn/openpose_pose_coco.caffemodel", "dnn/openpose_pose_coco.prototxt",
- Size(46, 46));
+ Size(46, 46), "", "", l1, lInf);
}
TEST_P(DNNTestNetwork, OpenPose_pose_mpi)
{
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
+ throw SkipTestException("Test is disabled for OpenVINO <= 2018R5 + MyriadX target");
+#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;
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi.prototxt",
- Size(46, 46));
+ Size(46, 46), "", "", l1, lInf);
}
TEST_P(DNNTestNetwork, OpenPose_pose_mpi_faster_4_stages)
{
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
+ throw SkipTestException("Test is disabled for OpenVINO <= 2018R5 + MyriadX target");
+#endif
// The same .caffemodel but modified .prototxt
// See https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/src/openpose/pose/poseParameters.cpp
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi_faster_4_stages.prototxt",
TEST_P(DNNTestNetwork, OpenFace)
{
#if defined(INF_ENGINE_RELEASE)
-#if (INF_ENGINE_RELEASE < 2018030000 || INF_ENGINE_RELEASE == 2018050000)
+#if INF_ENGINE_VER_MAJOR_EQ(2018050000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
- throw SkipTestException("");
-#elif INF_ENGINE_RELEASE < 2018040000
+ throw SkipTestException("Test is disabled for Myriad targets");
+#elif INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X
+ )
+ throw SkipTestException("Test is disabled for MyriadX target");
+#else
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16)
- throw SkipTestException("Test is enabled starts from OpenVINO 2018R4");
+ throw SkipTestException("Test has been fixed in OpenVINO 2018R4");
#endif
#endif
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
- processNet("dnn/openface_nn4.small2.v1.t7", "", Size(96, 96), "");
+ const float l1 = (target == DNN_TARGET_MYRIAD) ? 0.0024 : 0.0;
+ const float lInf = (target == DNN_TARGET_MYRIAD) ? 0.0071 : 0.0;
+ processNet("dnn/openface_nn4.small2.v1.t7", "", Size(96, 96), "", "", l1, lInf);
}
TEST_P(DNNTestNetwork, opencv_face_detector)
TEST_P(DNNTestNetwork, Inception_v2_SSD_TensorFlow)
{
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
+ throw SkipTestException("Test is disabled for MyriadX");
+#endif
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
Mat sample = imread(findDataFile("dnn/street.png", false));
{
if (backend == DNN_BACKEND_HALIDE)
throw SkipTestException("");
-
+ // Reference output values are in range [-3.807, 4.605]
float l1 = 0.0, lInf = 0.0;
if (target == DNN_TARGET_OPENCL_FP16)
{
}
else if (target == DNN_TARGET_MYRIAD)
{
- l1 = 6e-2; lInf = 0.27;
+ l1 = 0.1; lInf = 0.6;
}
processNet("dnn/DenseNet_121.caffemodel", "dnn/DenseNet_121.prototxt", Size(224, 224), "", "", l1, lInf);
}
TEST_P(DNNTestNetwork, FastNeuralStyle_eccv16)
{
if (backend == DNN_BACKEND_HALIDE ||
- (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) ||
(backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD))
throw SkipTestException("");
+
+#if defined(INF_ENGINE_RELEASE)
+#if INF_ENGINE_RELEASE <= 2018050000
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL)
+ throw SkipTestException("");
+#endif
+#endif
+
Mat img = imread(findDataFile("dnn/googlenet_1.png", false));
Mat inp = blobFromImage(img, 1.0, Size(320, 240), Scalar(103.939, 116.779, 123.68), false, false);
// Output image has values in range [-143.526, 148.539].
TEST_P(Test_Caffe_nets, Colorization)
{
checkBackend();
+
Mat inp = blobFromNPY(_tf("colorization_inp.npy"));
Mat ref = blobFromNPY(_tf("colorization_out.npy"));
Mat kernel = blobFromNPY(_tf("colorization_pts_in_hull.npy"));
Mat out = net.forward();
// Reference output values are in range [-29.1, 69.5]
- const double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.25 : 4e-4;
- const double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 5.3 : 3e-3;
+ double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.25 : 4e-4;
+ double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 5.3 : 3e-3;
+ if (target == DNN_TARGET_MYRIAD && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
+ {
+ l1 = 0.6; lInf = 15;
+ }
normAssert(out, ref, "", l1, lInf);
}
}
else if (target == DNN_TARGET_MYRIAD)
{
- l1 = 0.097; lInf = 0.52;
+ l1 = 0.11; lInf = 0.5;
}
normAssert(out, ref, "", l1, lInf);
}
TEST_P(Test_Caffe_nets, FasterRCNN_vgg16)
{
- if ((backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE > 2018030000
- || (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16)
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
+ throw SkipTestException("Test is disabled for DLIE OpenCL targets"); // very slow
+
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
+ throw SkipTestException("Test is disabled for Myriad targets");
#endif
- )
- throw SkipTestException("");
+
static Mat ref = (Mat_<float>(3, 7) << 0, 2, 0.949398, 99.2454, 210.141, 601.205, 462.849,
0, 7, 0.997022, 481.841, 92.3218, 722.685, 175.953,
0, 12, 0.993028, 133.221, 189.377, 350.994, 563.166);
--- /dev/null
+// 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"
+#include "test_common.impl.hpp" // shared with perf tests
-/*M///////////////////////////////////////////////////////////////////////////////////////
-//
-// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
-//
-// By downloading, copying, installing or using the software you agree to this license.
-// If you do not agree to this license, do not download, install,
-// copy or use the software.
-//
-//
-// License Agreement
-// For Open Source Computer Vision Library
-//
-// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
-// Third party copyrights are property of their respective owners.
-//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-// * Redistribution's of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// * Redistribution's in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// * The name of the copyright holders may not be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// This software is provided by the copyright holders and contributors "as is" and
-// any express or implied warranties, including, but not limited to, the implied
-// warranties of merchantability and fitness for a particular purpose are disclaimed.
-// In no event shall the Intel Corporation or contributors be liable for any direct,
-// indirect, incidental, special, exemplary, or consequential damages
-// (including, but not limited to, procurement of substitute goods or services;
-// loss of use, data, or profits; or business interruption) however caused
-// and on any theory of liability, whether in contract, strict liability,
-// or tort (including negligence or otherwise) arising in any way out of
-// the use of this software, even if advised of the possibility of such damage.
-//
-//M*/
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
#ifndef __OPENCV_TEST_COMMON_HPP__
#define __OPENCV_TEST_COMMON_HPP__
+#include "opencv2/dnn/utils/inference_engine.hpp"
+
#ifdef HAVE_OPENCL
#include "opencv2/core/ocl.hpp"
#endif
+
namespace cv { namespace dnn {
CV__DNN_INLINE_NS_BEGIN
-static inline void PrintTo(const cv::dnn::Backend& v, std::ostream* os)
-{
- switch (v) {
- case DNN_BACKEND_DEFAULT: *os << "DEFAULT"; return;
- case DNN_BACKEND_HALIDE: *os << "HALIDE"; return;
- case DNN_BACKEND_INFERENCE_ENGINE: *os << "DLIE"; return;
- case DNN_BACKEND_OPENCV: *os << "OCV"; return;
- case DNN_BACKEND_VKCOM: *os << "VKCOM"; return;
- } // don't use "default:" to emit compiler warnings
- *os << "DNN_BACKEND_UNKNOWN(" << (int)v << ")";
-}
-
-static inline void PrintTo(const cv::dnn::Target& v, std::ostream* os)
-{
- switch (v) {
- case DNN_TARGET_CPU: *os << "CPU"; return;
- case DNN_TARGET_OPENCL: *os << "OCL"; return;
- case DNN_TARGET_OPENCL_FP16: *os << "OCL_FP16"; return;
- case DNN_TARGET_MYRIAD: *os << "MYRIAD"; return;
- case DNN_TARGET_VULKAN: *os << "VULKAN"; return;
- case DNN_TARGET_FPGA: *os << "FPGA"; return;
- } // don't use "default:" to emit compiler warnings
- *os << "DNN_TARGET_UNKNOWN(" << (int)v << ")";
-}
+void PrintTo(const cv::dnn::Backend& v, std::ostream* os);
+void PrintTo(const cv::dnn::Target& v, std::ostream* os);
using opencv_test::tuple;
using opencv_test::get;
-static inline void PrintTo(const tuple<cv::dnn::Backend, cv::dnn::Target> v, std::ostream* os)
-{
- PrintTo(get<0>(v), os);
- *os << "/";
- PrintTo(get<1>(v), os);
-}
+void PrintTo(const tuple<cv::dnn::Backend, cv::dnn::Target> v, std::ostream* os);
CV__DNN_INLINE_NS_END
-}} // namespace
+}} // namespace cv::dnn
-static inline const std::string &getOpenCVExtraDir()
-{
- return cvtest::TS::ptr()->get_data_path();
-}
-static inline void normAssert(cv::InputArray ref, cv::InputArray test, const char *comment = "",
- double l1 = 0.00001, double lInf = 0.0001)
-{
- double normL1 = cvtest::norm(ref, test, cv::NORM_L1) / ref.getMat().total();
- EXPECT_LE(normL1, l1) << comment;
+namespace opencv_test {
- double normInf = cvtest::norm(ref, test, cv::NORM_INF);
- EXPECT_LE(normInf, lInf) << comment;
-}
+using namespace cv::dnn;
-static std::vector<cv::Rect2d> matToBoxes(const cv::Mat& m)
+static inline const std::string &getOpenCVExtraDir()
{
- EXPECT_EQ(m.type(), CV_32FC1);
- EXPECT_EQ(m.dims, 2);
- EXPECT_EQ(m.cols, 4);
-
- std::vector<cv::Rect2d> boxes(m.rows);
- for (int i = 0; i < m.rows; ++i)
- {
- CV_Assert(m.row(i).isContinuous());
- const float* data = m.ptr<float>(i);
- double l = data[0], t = data[1], r = data[2], b = data[3];
- boxes[i] = cv::Rect2d(l, t, r - l, b - t);
- }
- return boxes;
+ return cvtest::TS::ptr()->get_data_path();
}
-static inline void normAssertDetections(const std::vector<int>& refClassIds,
- const std::vector<float>& refScores,
- const std::vector<cv::Rect2d>& refBoxes,
- const std::vector<int>& testClassIds,
- const std::vector<float>& testScores,
- const std::vector<cv::Rect2d>& testBoxes,
- const char *comment = "", double confThreshold = 0.0,
- double scores_diff = 1e-5, double boxes_iou_diff = 1e-4)
-{
- std::vector<bool> matchedRefBoxes(refBoxes.size(), false);
- for (int i = 0; i < testBoxes.size(); ++i)
- {
- double testScore = testScores[i];
- if (testScore < confThreshold)
- continue;
+void normAssert(
+ cv::InputArray ref, cv::InputArray test, const char *comment = "",
+ double l1 = 0.00001, double lInf = 0.0001);
- int testClassId = testClassIds[i];
- const cv::Rect2d& testBox = testBoxes[i];
- bool matched = false;
- for (int j = 0; j < refBoxes.size() && !matched; ++j)
- {
- if (!matchedRefBoxes[j] && testClassId == refClassIds[j] &&
- std::abs(testScore - refScores[j]) < scores_diff)
- {
- double interArea = (testBox & refBoxes[j]).area();
- double iou = interArea / (testBox.area() + refBoxes[j].area() - interArea);
- if (std::abs(iou - 1.0) < boxes_iou_diff)
- {
- matched = true;
- matchedRefBoxes[j] = true;
- }
- }
- }
- if (!matched)
- std::cout << cv::format("Unmatched prediction: class %d score %f box ",
- testClassId, testScore) << testBox << std::endl;
- EXPECT_TRUE(matched) << comment;
- }
+std::vector<cv::Rect2d> matToBoxes(const cv::Mat& m);
- // Check unmatched reference detections.
- for (int i = 0; i < refBoxes.size(); ++i)
- {
- if (!matchedRefBoxes[i] && refScores[i] > confThreshold)
- {
- std::cout << cv::format("Unmatched reference: class %d score %f box ",
- refClassIds[i], refScores[i]) << refBoxes[i] << std::endl;
- EXPECT_LE(refScores[i], confThreshold) << comment;
- }
- }
-}
+void normAssertDetections(
+ const std::vector<int>& refClassIds,
+ const std::vector<float>& refScores,
+ const std::vector<cv::Rect2d>& refBoxes,
+ const std::vector<int>& testClassIds,
+ const std::vector<float>& testScores,
+ const std::vector<cv::Rect2d>& testBoxes,
+ const char *comment = "", double confThreshold = 0.0,
+ double scores_diff = 1e-5, double boxes_iou_diff = 1e-4);
// For SSD-based object detection networks which produce output of shape 1x1xNx7
// where N is a number of detections and an every detection is represented by
// a vector [batchId, classId, confidence, left, top, right, bottom].
-static inline void normAssertDetections(cv::Mat ref, cv::Mat out, const char *comment = "",
- double confThreshold = 0.0, double scores_diff = 1e-5,
- double boxes_iou_diff = 1e-4)
-{
- CV_Assert(ref.total() % 7 == 0);
- CV_Assert(out.total() % 7 == 0);
- ref = ref.reshape(1, ref.total() / 7);
- out = out.reshape(1, out.total() / 7);
-
- cv::Mat refClassIds, testClassIds;
- ref.col(1).convertTo(refClassIds, CV_32SC1);
- out.col(1).convertTo(testClassIds, CV_32SC1);
- std::vector<float> refScores(ref.col(2)), testScores(out.col(2));
- std::vector<cv::Rect2d> refBoxes = matToBoxes(ref.colRange(3, 7));
- std::vector<cv::Rect2d> testBoxes = matToBoxes(out.colRange(3, 7));
- normAssertDetections(refClassIds, refScores, refBoxes, testClassIds, testScores,
- testBoxes, comment, confThreshold, scores_diff, boxes_iou_diff);
-}
-
-static inline bool readFileInMemory(const std::string& filename, std::string& content)
-{
- std::ios::openmode mode = std::ios::in | std::ios::binary;
- std::ifstream ifs(filename.c_str(), mode);
- if (!ifs.is_open())
- return false;
-
- content.clear();
+void normAssertDetections(
+ cv::Mat ref, cv::Mat out, const char *comment = "",
+ double confThreshold = 0.0, double scores_diff = 1e-5,
+ double boxes_iou_diff = 1e-4);
- ifs.seekg(0, std::ios::end);
- content.reserve(ifs.tellg());
- ifs.seekg(0, std::ios::beg);
+bool readFileInMemory(const std::string& filename, std::string& content);
- content.assign((std::istreambuf_iterator<char>(ifs)),
- std::istreambuf_iterator<char>());
-
- return true;
-}
-
-namespace opencv_test {
-
-using namespace cv::dnn;
+#ifdef HAVE_INF_ENGINE
+bool validateVPUType();
+#endif
-static inline
testing::internal::ParamGenerator< tuple<Backend, Target> > dnnBackendsAndTargets(
bool withInferenceEngine = true,
bool withHalide = false,
bool withCpuOCV = true,
bool withVkCom = true
-)
-{
- std::vector< tuple<Backend, Target> > targets;
- std::vector< Target > available;
- if (withHalide)
- {
- available = getAvailableTargets(DNN_BACKEND_HALIDE);
- for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i)
- targets.push_back(make_tuple(DNN_BACKEND_HALIDE, *i));
- }
- if (withInferenceEngine)
- {
- available = getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE);
- for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i)
- targets.push_back(make_tuple(DNN_BACKEND_INFERENCE_ENGINE, *i));
- }
- if (withVkCom)
- {
- available = getAvailableTargets(DNN_BACKEND_VKCOM);
- for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i)
- targets.push_back(make_tuple(DNN_BACKEND_VKCOM, *i));
- }
- {
- available = getAvailableTargets(DNN_BACKEND_OPENCV);
- for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i)
- {
- if (!withCpuOCV && *i == DNN_TARGET_CPU)
- continue;
- targets.push_back(make_tuple(DNN_BACKEND_OPENCV, *i));
- }
- }
- if (targets.empty()) // validate at least CPU mode
- targets.push_back(make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU));
- return testing::ValuesIn(targets);
-}
+);
-} // namespace
-
-
-namespace opencv_test {
-using namespace cv::dnn;
class DNNTestLayer : public TestWithParam<tuple<Backend, Target> >
{
getDefaultThresholds(backend, target, &default_l1, &default_lInf);
}
- static void getDefaultThresholds(int backend, int target, double* l1, double* lInf)
- {
- if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD)
- {
- *l1 = 4e-3;
- *lInf = 2e-2;
- }
- else
- {
- *l1 = 1e-5;
- *lInf = 1e-4;
- }
- }
+ static void getDefaultThresholds(int backend, int target, double* l1, double* lInf)
+ {
+ if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD)
+ {
+ *l1 = 4e-3;
+ *lInf = 2e-2;
+ }
+ else
+ {
+ *l1 = 1e-5;
+ *lInf = 1e-4;
+ }
+ }
static void checkBackend(int backend, int target, Mat* inp = 0, Mat* ref = 0)
{
- if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
- {
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE < 2018030000
- if (inp && ref && inp->size[0] != 1)
- {
- // Myriad plugin supports only batch size 1. Slice a single sample.
- if (inp->size[0] == ref->size[0])
- {
- std::vector<cv::Range> range(inp->dims, Range::all());
- range[0] = Range(0, 1);
- *inp = inp->operator()(range);
-
- range = std::vector<cv::Range>(ref->dims, Range::all());
- range[0] = Range(0, 1);
- *ref = ref->operator()(range);
- }
- else
- throw SkipTestException("Myriad plugin supports only batch size 1");
- }
-#else
- if (inp && ref && inp->dims == 4 && ref->dims == 4 &&
- inp->size[0] != 1 && inp->size[0] != ref->size[0])
- throw SkipTestException("Inconsistent batch size of input and output blobs for Myriad plugin");
-
-#endif
- }
- }
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
+ {
+ if (inp && ref && inp->dims == 4 && ref->dims == 4 &&
+ inp->size[0] != 1 && inp->size[0] != ref->size[0])
+ throw SkipTestException("Inconsistent batch size of input and output blobs for Myriad plugin");
+ }
+ }
protected:
void checkBackend(Mat* inp = 0, Mat* ref = 0)
} // namespace
+
+// src/op_inf_engine.hpp
+#define INF_ENGINE_VER_MAJOR_GT(ver) (((INF_ENGINE_RELEASE) / 10000) > ((ver) / 10000))
+#define INF_ENGINE_VER_MAJOR_GE(ver) (((INF_ENGINE_RELEASE) / 10000) >= ((ver) / 10000))
+#define INF_ENGINE_VER_MAJOR_LT(ver) (((INF_ENGINE_RELEASE) / 10000) < ((ver) / 10000))
+#define INF_ENGINE_VER_MAJOR_LE(ver) (((INF_ENGINE_RELEASE) / 10000) <= ((ver) / 10000))
+#define INF_ENGINE_VER_MAJOR_EQ(ver) (((INF_ENGINE_RELEASE) / 10000) == ((ver) / 10000))
+
#endif
--- /dev/null
+// 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.
+
+// Used in accuracy and perf tests as a content of .cpp file
+// Note: don't use "precomp.hpp" here
+#include "opencv2/ts.hpp"
+#include "opencv2/ts/ts_perf.hpp"
+#include "opencv2/core/utility.hpp"
+#include "opencv2/core/ocl.hpp"
+
+#include "opencv2/dnn.hpp"
+#include "test_common.hpp"
+
+#include <opencv2/core/utils/configuration.private.hpp>
+#include <opencv2/core/utils/logger.hpp>
+
+namespace cv { namespace dnn {
+CV__DNN_INLINE_NS_BEGIN
+
+void PrintTo(const cv::dnn::Backend& v, std::ostream* os)
+{
+ switch (v) {
+ case DNN_BACKEND_DEFAULT: *os << "DEFAULT"; return;
+ case DNN_BACKEND_HALIDE: *os << "HALIDE"; return;
+ case DNN_BACKEND_INFERENCE_ENGINE: *os << "DLIE"; return;
+ case DNN_BACKEND_VKCOM: *os << "VKCOM"; return;
+ case DNN_BACKEND_OPENCV: *os << "OCV"; return;
+ } // don't use "default:" to emit compiler warnings
+ *os << "DNN_BACKEND_UNKNOWN(" << (int)v << ")";
+}
+
+void PrintTo(const cv::dnn::Target& v, std::ostream* os)
+{
+ switch (v) {
+ case DNN_TARGET_CPU: *os << "CPU"; return;
+ case DNN_TARGET_OPENCL: *os << "OCL"; return;
+ case DNN_TARGET_OPENCL_FP16: *os << "OCL_FP16"; return;
+ case DNN_TARGET_MYRIAD: *os << "MYRIAD"; return;
+ case DNN_TARGET_VULKAN: *os << "VULKAN"; return;
+ case DNN_TARGET_FPGA: *os << "FPGA"; return;
+ } // don't use "default:" to emit compiler warnings
+ *os << "DNN_TARGET_UNKNOWN(" << (int)v << ")";
+}
+
+void PrintTo(const tuple<cv::dnn::Backend, cv::dnn::Target> v, std::ostream* os)
+{
+ PrintTo(get<0>(v), os);
+ *os << "/";
+ PrintTo(get<1>(v), os);
+}
+
+CV__DNN_INLINE_NS_END
+}} // namespace
+
+
+
+namespace opencv_test {
+
+void normAssert(
+ cv::InputArray ref, cv::InputArray test, const char *comment /*= ""*/,
+ double l1 /*= 0.00001*/, double lInf /*= 0.0001*/)
+{
+ double normL1 = cvtest::norm(ref, test, cv::NORM_L1) / ref.getMat().total();
+ EXPECT_LE(normL1, l1) << comment;
+
+ double normInf = cvtest::norm(ref, test, cv::NORM_INF);
+ EXPECT_LE(normInf, lInf) << comment;
+}
+
+std::vector<cv::Rect2d> matToBoxes(const cv::Mat& m)
+{
+ EXPECT_EQ(m.type(), CV_32FC1);
+ EXPECT_EQ(m.dims, 2);
+ EXPECT_EQ(m.cols, 4);
+
+ std::vector<cv::Rect2d> boxes(m.rows);
+ for (int i = 0; i < m.rows; ++i)
+ {
+ CV_Assert(m.row(i).isContinuous());
+ const float* data = m.ptr<float>(i);
+ double l = data[0], t = data[1], r = data[2], b = data[3];
+ boxes[i] = cv::Rect2d(l, t, r - l, b - t);
+ }
+ return boxes;
+}
+
+void normAssertDetections(
+ const std::vector<int>& refClassIds,
+ const std::vector<float>& refScores,
+ const std::vector<cv::Rect2d>& refBoxes,
+ const std::vector<int>& testClassIds,
+ const std::vector<float>& testScores,
+ const std::vector<cv::Rect2d>& testBoxes,
+ const char *comment /*= ""*/, double confThreshold /*= 0.0*/,
+ double scores_diff /*= 1e-5*/, double boxes_iou_diff /*= 1e-4*/)
+{
+ std::vector<bool> matchedRefBoxes(refBoxes.size(), false);
+ for (int i = 0; i < testBoxes.size(); ++i)
+ {
+ double testScore = testScores[i];
+ if (testScore < confThreshold)
+ continue;
+
+ int testClassId = testClassIds[i];
+ const cv::Rect2d& testBox = testBoxes[i];
+ bool matched = false;
+ for (int j = 0; j < refBoxes.size() && !matched; ++j)
+ {
+ if (!matchedRefBoxes[j] && testClassId == refClassIds[j] &&
+ std::abs(testScore - refScores[j]) < scores_diff)
+ {
+ double interArea = (testBox & refBoxes[j]).area();
+ double iou = interArea / (testBox.area() + refBoxes[j].area() - interArea);
+ if (std::abs(iou - 1.0) < boxes_iou_diff)
+ {
+ matched = true;
+ matchedRefBoxes[j] = true;
+ }
+ }
+ }
+ if (!matched)
+ std::cout << cv::format("Unmatched prediction: class %d score %f box ",
+ testClassId, testScore) << testBox << std::endl;
+ EXPECT_TRUE(matched) << comment;
+ }
+
+ // Check unmatched reference detections.
+ for (int i = 0; i < refBoxes.size(); ++i)
+ {
+ if (!matchedRefBoxes[i] && refScores[i] > confThreshold)
+ {
+ std::cout << cv::format("Unmatched reference: class %d score %f box ",
+ refClassIds[i], refScores[i]) << refBoxes[i] << std::endl;
+ EXPECT_LE(refScores[i], confThreshold) << comment;
+ }
+ }
+}
+
+// For SSD-based object detection networks which produce output of shape 1x1xNx7
+// where N is a number of detections and an every detection is represented by
+// a vector [batchId, classId, confidence, left, top, right, bottom].
+void normAssertDetections(
+ cv::Mat ref, cv::Mat out, const char *comment /*= ""*/,
+ double confThreshold /*= 0.0*/, double scores_diff /*= 1e-5*/,
+ double boxes_iou_diff /*= 1e-4*/)
+{
+ CV_Assert(ref.total() % 7 == 0);
+ CV_Assert(out.total() % 7 == 0);
+ ref = ref.reshape(1, ref.total() / 7);
+ out = out.reshape(1, out.total() / 7);
+
+ cv::Mat refClassIds, testClassIds;
+ ref.col(1).convertTo(refClassIds, CV_32SC1);
+ out.col(1).convertTo(testClassIds, CV_32SC1);
+ std::vector<float> refScores(ref.col(2)), testScores(out.col(2));
+ std::vector<cv::Rect2d> refBoxes = matToBoxes(ref.colRange(3, 7));
+ std::vector<cv::Rect2d> testBoxes = matToBoxes(out.colRange(3, 7));
+ normAssertDetections(refClassIds, refScores, refBoxes, testClassIds, testScores,
+ testBoxes, comment, confThreshold, scores_diff, boxes_iou_diff);
+}
+
+bool readFileInMemory(const std::string& filename, std::string& content)
+{
+ std::ios::openmode mode = std::ios::in | std::ios::binary;
+ std::ifstream ifs(filename.c_str(), mode);
+ if (!ifs.is_open())
+ return false;
+
+ content.clear();
+
+ ifs.seekg(0, std::ios::end);
+ content.reserve(ifs.tellg());
+ ifs.seekg(0, std::ios::beg);
+
+ content.assign((std::istreambuf_iterator<char>(ifs)),
+ std::istreambuf_iterator<char>());
+
+ return true;
+}
+
+
+testing::internal::ParamGenerator< tuple<Backend, Target> > dnnBackendsAndTargets(
+ bool withInferenceEngine /*= true*/,
+ bool withHalide /*= false*/,
+ bool withCpuOCV /*= true*/,
+ bool withVkCom /*= true*/
+)
+{
+#ifdef HAVE_INF_ENGINE
+ bool withVPU = validateVPUType();
+#endif
+
+ std::vector< tuple<Backend, Target> > targets;
+ std::vector< Target > available;
+ if (withHalide)
+ {
+ available = getAvailableTargets(DNN_BACKEND_HALIDE);
+ for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i)
+ targets.push_back(make_tuple(DNN_BACKEND_HALIDE, *i));
+ }
+#ifdef HAVE_INF_ENGINE
+ if (withInferenceEngine)
+ {
+ available = getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE);
+ for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i)
+ {
+ if (*i == DNN_TARGET_MYRIAD && !withVPU)
+ continue;
+ targets.push_back(make_tuple(DNN_BACKEND_INFERENCE_ENGINE, *i));
+ }
+ }
+#else
+ CV_UNUSED(withInferenceEngine);
+#endif
+ if (withVkCom)
+ {
+ available = getAvailableTargets(DNN_BACKEND_VKCOM);
+ for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i)
+ targets.push_back(make_tuple(DNN_BACKEND_VKCOM, *i));
+ }
+ {
+ available = getAvailableTargets(DNN_BACKEND_OPENCV);
+ for (std::vector< Target >::const_iterator i = available.begin(); i != available.end(); ++i)
+ {
+ if (!withCpuOCV && *i == DNN_TARGET_CPU)
+ continue;
+ targets.push_back(make_tuple(DNN_BACKEND_OPENCV, *i));
+ }
+ }
+ if (targets.empty()) // validate at least CPU mode
+ targets.push_back(make_tuple(DNN_BACKEND_OPENCV, DNN_TARGET_CPU));
+ return testing::ValuesIn(targets);
+}
+
+
+#ifdef HAVE_INF_ENGINE
+static std::string getTestInferenceEngineVPUType()
+{
+ static std::string param_vpu_type = utils::getConfigurationParameterString("OPENCV_TEST_DNN_IE_VPU_TYPE", "");
+ return param_vpu_type;
+}
+
+static bool validateVPUType_()
+{
+ std::string test_vpu_type = getTestInferenceEngineVPUType();
+ if (test_vpu_type == "DISABLED" || test_vpu_type == "disabled")
+ {
+ return false;
+ }
+
+ std::vector<Target> available = getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE);
+ bool have_vpu_target = false;
+ for (std::vector<Target>::const_iterator i = available.begin(); i != available.end(); ++i)
+ {
+ if (*i == DNN_TARGET_MYRIAD)
+ {
+ have_vpu_target = true;
+ break;
+ }
+ }
+
+ if (test_vpu_type.empty())
+ {
+ if (have_vpu_target)
+ {
+ CV_LOG_INFO(NULL, "OpenCV-DNN-Test: VPU type for testing is not specified via 'OPENCV_TEST_DNN_IE_VPU_TYPE' parameter.")
+ }
+ }
+ else
+ {
+ if (!have_vpu_target)
+ {
+ CV_LOG_FATAL(NULL, "OpenCV-DNN-Test: 'OPENCV_TEST_DNN_IE_VPU_TYPE' parameter requires VPU of type = '" << test_vpu_type << "', but VPU is not detected. STOP.");
+ exit(1);
+ }
+ std::string dnn_vpu_type = getInferenceEngineVPUType();
+ if (dnn_vpu_type != test_vpu_type)
+ {
+ CV_LOG_FATAL(NULL, "OpenCV-DNN-Test: 'testing' and 'detected' VPU types mismatch: '" << test_vpu_type << "' vs '" << dnn_vpu_type << "'. STOP.");
+ exit(1);
+ }
+ }
+ return true;
+}
+
+bool validateVPUType()
+{
+ static bool result = validateVPUType_();
+ return result;
+}
+#endif // HAVE_INF_ENGINE
+
+} // namespace
TEST_P(Test_Darknet_nets, YoloVoc)
{
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16)
+ throw SkipTestException("Test is disabled");
+#endif
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
+ throw SkipTestException("Test is disabled for MyriadX (need to update check function)");
+#endif
+
// batchId, classId, confidence, left, top, right, bottom
Mat ref = (Mat_<float>(6, 7) << 0, 6, 0.750469f, 0.577374f, 0.127391f, 0.902949f, 0.300809f, // a car
0, 1, 0.780879f, 0.270762f, 0.264102f, 0.732475f, 0.745412f, // a bicycle
std::string config_file = "yolo-voc.cfg";
std::string weights_file = "yolo-voc.weights";
- // batch size 1
+ {
+ SCOPED_TRACE("batch size 1");
testDarknetModel(config_file, weights_file, ref.rowRange(0, 3), scoreDiff, iouDiff);
+ }
- // batch size 2
+ {
+ SCOPED_TRACE("batch size 2");
testDarknetModel(config_file, weights_file, ref, scoreDiff, iouDiff, 0.24, nmsThreshold);
+ }
}
TEST_P(Test_Darknet_nets, TinyYoloVoc)
{
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
+ throw SkipTestException("Test is disabled for MyriadX (need to update check function)");
+#endif
// batchId, classId, confidence, left, top, right, bottom
Mat ref = (Mat_<float>(4, 7) << 0, 6, 0.761967f, 0.579042f, 0.159161f, 0.894482f, 0.31994f, // a car
0, 11, 0.780595f, 0.129696f, 0.386467f, 0.445275f, 0.920994f, // a dog
std::string config_file = "tiny-yolo-voc.cfg";
std::string weights_file = "tiny-yolo-voc.weights";
- // batch size 1
+ {
+ SCOPED_TRACE("batch size 1");
testDarknetModel(config_file, weights_file, ref.rowRange(0, 2), scoreDiff, iouDiff);
+ }
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE == 2018040000
- if (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_MYRIAD)
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018040000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
+ throw SkipTestException("Test with 'batch size 2' is disabled for Myriad target (fixed in 2018R5)");
#endif
- // batch size 2
+ {
+ SCOPED_TRACE("batch size 2");
testDarknetModel(config_file, weights_file, ref, scoreDiff, iouDiff);
+ }
}
TEST_P(Test_Darknet_nets, YOLOv3)
{
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
+ throw SkipTestException("Test is disabled for MyriadX");
+#endif
+
// batchId, classId, confidence, left, top, right, bottom
Mat ref = (Mat_<float>(9, 7) << 0, 7, 0.952983f, 0.614622f, 0.150257f, 0.901369f, 0.289251f, // a truck
0, 1, 0.987908f, 0.150913f, 0.221933f, 0.742255f, 0.74626f, // a bicycle
std::string config_file = "yolov3.cfg";
std::string weights_file = "yolov3.weights";
- // batch size 1
+ {
+ SCOPED_TRACE("batch size 1");
testDarknetModel(config_file, weights_file, ref.rowRange(0, 3), scoreDiff, iouDiff);
+ }
+
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL)
+ throw SkipTestException("Test with 'batch size 2' is disabled for DLIE/OpenCL target");
+#endif
- if ((backend != DNN_BACKEND_INFERENCE_ENGINE || target != DNN_TARGET_MYRIAD) &&
- (backend != DNN_BACKEND_INFERENCE_ENGINE || target != DNN_TARGET_OPENCL))
{
- // batch size 2
+ SCOPED_TRACE("batch size 2");
testDarknetModel(config_file, weights_file, ref, scoreDiff, iouDiff);
}
}
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
-// Copyright (C) 2017, Intel Corporation, all rights reserved.
+// Copyright (C) 2017-2019, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
// This tests doesn't require any external data. They just compare outputs of
Backend backendId = get<0>(get<7>(GetParam()));
Target targetId = get<1>(get<7>(GetParam()));
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE < 2018030000
- if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD)
- throw SkipTestException("Test is enabled starts from OpenVINO 2018R3");
-#endif
-
bool skipCheck = false;
int sz[] = {outChannels, inChannels / group, kernel.height, kernel.width};
bool hasBias = get<6>(GetParam());
Backend backendId = get<0>(get<7>(GetParam()));
Target targetId = get<1>(get<7>(GetParam()));
+
if (backendId == DNN_BACKEND_INFERENCE_ENGINE && (targetId == DNN_TARGET_CPU || targetId == DNN_TARGET_MYRIAD) &&
dilation.width == 2 && dilation.height == 2)
throw SkipTestException("");
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE >= 2018040000
- if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_CPU &&
- hasBias && group != 1)
+
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018040000)
+ if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_CPU
+ && hasBias && group != 1)
throw SkipTestException("Test is disabled for OpenVINO 2018R4");
#endif
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X
+ && inChannels == 6 && outChannels == 4 && group == 1
+ && kernel == Size(1, 3) && pad == Size(1, 0)
+ && stride == Size(1, 1) && dilation == Size(1, 1))
+ throw SkipTestException("Test is disabled");
+#endif
+
int sz[] = {inChannels, outChannels / group, kernel.height, kernel.width};
Mat weights(4, &sz[0], CV_32F);
randu(weights, -1.0f, 1.0f);
std::string nrmType = get<4>(GetParam());
Backend backendId = get<0>(get<5>(GetParam()));
Target targetId = get<1>(get<5>(GetParam()));
- if (backendId == DNN_BACKEND_INFERENCE_ENGINE)
- throw SkipTestException("");
+
+ if ((inSize.width == 5 || inSize.height == 5) && targetId == DNN_TARGET_MYRIAD &&
+ nrmType == "ACROSS_CHANNELS")
+ throw SkipTestException("This test case is disabled");
LayerParams lp;
lp.set("norm_region", nrmType);
/*input ch,w,h*/ Values(Vec3i(6, 5, 8), Vec3i(7, 11, 6)),
/*local size*/ Values(3, 5),
Values(Vec3f(0.9f, 1.0f, 1.1f), Vec3f(0.9f, 1.1f, 1.0f),
-/*alpha, beta,*/ Vec3f(1.0f, 0.9f, 1.1f), Vec3f(1.0f, 1.1f, 0.9f),
-/*bias */ Vec3f(1.1f, 0.9f, 1.0f), Vec3f(1.1f, 1.0f, 0.9f)),
+/*alpha, beta, bias*/ Vec3f(1.0f, 0.9f, 1.1f), Vec3f(1.0f, 1.1f, 0.9f),
+ Vec3f(1.1f, 0.9f, 1.0f), Vec3f(1.1f, 1.0f, 0.9f)),
/*norm_by_size*/ Bool(),
/*norm_type*/ Values("ACROSS_CHANNELS", "WITHIN_CHANNEL"),
dnnBackendsAndTargetsWithHalide()
Size stride = get<3>(GetParam());
Backend backendId = get<0>(get<4>(GetParam()));
Target targetId = get<1>(get<4>(GetParam()));
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE < 2018040000
+
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2018050000)
+ if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X
+ && kernel == Size(1, 1) && (stride == Size(1, 1) || stride == Size(2, 2)))
+ throw SkipTestException("Test is disabled for MyriadX target");
+#endif
+
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2018040000)
if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD &&
stride == Size(3, 2) && kernel == Size(3, 3) && outSize != Size(1, 1))
- throw SkipTestException("Test is enabled starts from OpenVINO 2018R4");
+ throw SkipTestException("Test is fixed in OpenVINO 2018R4");
#endif
const int inWidth = (outSize.width - 1) * stride.width + kernel.width;
Backend backendId = get<0>(get<5>(GetParam()));
Target targetId = get<1>(get<5>(GetParam()));
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000)
+ if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD
+ && inSize == Size(7, 6) && kernel == Size(3, 2)
+ && (stride == Size(1, 1) || stride == Size(2, 2))
+ && (pad == Size(0, 1) || pad == Size(1, 1))
+ )
+ throw SkipTestException("Test is disabled in OpenVINO <= 2018R5");
+#endif
+
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000)
+ if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD
+ && (kernel == Size(2, 2) || kernel == Size(3, 2))
+ && stride == Size(1, 1) && (pad == Size(0, 0) || pad == Size(0, 1))
+ )
+ throw SkipTestException("Problems with output dimension in OpenVINO 2018R5");
+#endif
+
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X
+ && (stride == Size(1, 1) || stride == Size(2, 2))
+ && (pad == Size(0, 1) || pad == Size(1, 1))
+ )
+ throw SkipTestException("Test is disabled for MyriadX target");
+#endif
+
LayerParams lp;
lp.set("pool", "max");
lp.set("kernel_w", kernel.width);
float negativeSlope = get<0>(GetParam());
Backend backendId = get<0>(get<1>(GetParam()));
Target targetId = get<1>(get<1>(GetParam()));
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backendId == DNN_BACKEND_INFERENCE_ENGINE
+ && negativeSlope < 0
+ )
+ throw SkipTestException("Test is disabled");
+#endif
LayerParams lp;
lp.set("negative_slope", negativeSlope);
LayerParams lp;
lp.type = get<0>(GetParam());
lp.name = "testLayer";
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backendId == DNN_BACKEND_INFERENCE_ENGINE
+ && lp.type == "AbsVal"
+ )
+ throw SkipTestException("Test is disabled");
+#endif
+
testInPlaceActivation(lp, backendId, targetId);
}
INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, NoParamActivation, Combine(
Backend backendId = get<0>(get<2>(GetParam()));
Target targetId = get<1>(get<2>(GetParam()));
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000)
+ if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD
+ && inSize == Vec3i(1, 4, 5) && numChannels == Vec3i(1, 6, 2)
+ )
+ throw SkipTestException("Test is disabled for Myriad target"); // crash
+#endif
+
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_CPU
+ && inSize == Vec3i(1, 4, 5) && numChannels == Vec3i(1, 6, 2)
+ )
+ throw SkipTestException("Test is disabled for DLIE/CPU target");
+#endif
+
Net net;
std::vector<int> convLayerIds;
Backend backendId = get<0>(get<4>(GetParam()));
Target targetId = get<1>(get<4>(GetParam()));
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE > 2018050000
- if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_OPENCL)
- throw SkipTestException("");
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000)
+ if (backendId == DNN_BACKEND_INFERENCE_ENGINE && targetId == DNN_TARGET_MYRIAD &&
+ inSize == Vec3i(1, 4, 5))
+ throw SkipTestException("Test is disabled for Myriad target");
+#endif
+
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backendId == DNN_BACKEND_INFERENCE_ENGINE && numConv > 1)
+ throw SkipTestException("Test is disabled for DLIE backend");
#endif
Net net;
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
-// Copyright (C) 2018, Intel Corporation, all rights reserved.
+// Copyright (C) 2018-2019, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
#include "test_precomp.hpp"
{
Target target = (dnn::Target)(int)get<0>(GetParam());
std::string modelName = get<1>(GetParam());
+ std::string precision = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? "FP16" : "FP32";
#ifdef INF_ENGINE_RELEASE
-#if INF_ENGINE_RELEASE <= 2018030000
- if (target == DNN_TARGET_MYRIAD && (modelName == "landmarks-regression-retail-0001" ||
- modelName == "semantic-segmentation-adas-0001" ||
- modelName == "face-reidentification-retail-0001"))
- throw SkipTestException("");
-#elif INF_ENGINE_RELEASE == 2018040000
- if (modelName == "single-image-super-resolution-0034" ||
- (target == DNN_TARGET_MYRIAD && (modelName == "license-plate-recognition-barrier-0001" ||
- modelName == "landmarks-regression-retail-0009" ||
- modelName == "semantic-segmentation-adas-0001")))
- throw SkipTestException("");
-#elif INF_ENGINE_RELEASE == 2018050000
- if (modelName == "single-image-super-resolution-0063" ||
- modelName == "single-image-super-resolution-1011" ||
- modelName == "single-image-super-resolution-1021" ||
- (target == DNN_TARGET_OPENCL_FP16 && modelName == "face-reidentification-retail-0095") ||
- (target == DNN_TARGET_MYRIAD && (modelName == "license-plate-recognition-barrier-0001" ||
- modelName == "semantic-segmentation-adas-0001")))
- throw SkipTestException("");
-#endif
-#endif
-
- std::string precision = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? "FP16" : "FP32";
+#if INF_ENGINE_RELEASE <= 2018050000
std::string prefix = utils::fs::join("intel_models",
utils::fs::join(modelName,
utils::fs::join(precision, modelName)));
+#endif
+#endif
+
+ initDLDTDataPath();
std::string xmlPath = findDataFile(prefix + ".xml");
std::string binPath = findDataFile(prefix + ".bin");
}
}
-static testing::internal::ParamGenerator<String> intelModels()
-{
- initDLDTDataPath();
- std::vector<String> modelsNames;
-
- std::string path;
- try
- {
- path = findDataDirectory("intel_models", false);
- }
- catch (...)
- {
- std::cerr << "ERROR: Can't find OpenVINO models. Check INTEL_CVSDK_DIR environment variable (run setup.sh)" << std::endl;
- return ValuesIn(modelsNames); // empty list
- }
-
- cv::utils::fs::glob_relative(path, "", modelsNames, false, true);
-
- modelsNames.erase(
- std::remove_if(modelsNames.begin(), modelsNames.end(),
- [&](const String& dir){ return !utils::fs::isDirectory(utils::fs::join(path, dir)); }),
- modelsNames.end()
- );
- CV_Assert(!modelsNames.empty());
-
- return ValuesIn(modelsNames);
-}
-
INSTANTIATE_TEST_CASE_P(/**/,
DNNTestOpenVINO,
- Combine(testing::ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE)), intelModels())
+ Combine(testing::ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE)),
+ testing::Values(
+ "age-gender-recognition-retail-0013",
+ "face-person-detection-retail-0002",
+ "head-pose-estimation-adas-0001",
+ "person-detection-retail-0002",
+ "vehicle-detection-adas-0002"
+ ))
);
}}
TEST_P(Test_Caffe_layers, BatchNorm)
{
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE < 2018030000
- if (backend == DNN_BACKEND_INFERENCE_ENGINE)
- throw SkipTestException("Test is enabled starts from OpenVINO 2018R3");
-#endif
testLayerUsingCaffeModels("layer_batch_norm", true);
testLayerUsingCaffeModels("layer_batch_norm_local_stats", true, false);
}
TEST_P(Test_Caffe_layers, Concat)
{
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE > 2018050000
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
- throw SkipTestException("");
+ throw SkipTestException("Test is disabled for Myriad targets");
#endif
testLayerUsingCaffeModels("layer_concat");
testLayerUsingCaffeModels("layer_concat_optim", true, false);
TEST_P(Test_Caffe_layers, Fused_Concat)
{
-#if defined(INF_ENGINE_RELEASE)
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE)
- {
- if (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16 ||
- (INF_ENGINE_RELEASE < 2018040000 && target == DNN_TARGET_CPU))
- throw SkipTestException("");
- }
+ throw SkipTestException("Test is disabled for DLIE due negative_slope parameter");
+#endif
+
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE
+ && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16
+ || (INF_ENGINE_RELEASE < 2018040000 && target == DNN_TARGET_CPU))
+ )
+ throw SkipTestException("Test is disabled for DLIE");
#endif
+
checkBackend();
// Test case
{
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
throw SkipTestException("");
- testLayerUsingCaffeModels("layer_prelu_fc", true, false);
+ // Reference output values are in range [-0.0001, 10.3906]
+ double l1 = (target == DNN_TARGET_MYRIAD) ? 0.005 : 0.0;
+ double lInf = (target == DNN_TARGET_MYRIAD) ? 0.021 : 0.0;
+ testLayerUsingCaffeModels("layer_prelu_fc", true, false, l1, lInf);
}
//template<typename XMat>
TEST_P(Test_Caffe_layers, Conv_Elu)
{
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE <= 2018050000
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
+ throw SkipTestException("");
+#endif
+
Net net = readNetFromTensorflow(_tf("layer_elu_model.pb"));
ASSERT_FALSE(net.empty());
// into the normalization area.
TEST_P(Test_Caffe_layers, Average_pooling_kernel_area)
{
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE < 2018030000
- if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
- throw SkipTestException("Test is enabled starts from OpenVINO 2018R3");
-#endif
LayerParams lp;
lp.name = "testAvePool";
lp.type = "Pooling";
Mat out = net.forward();
- double l1 = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 1.4e-3 : 1e-5;
+ double l1 = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 1.5e-3 : 1e-5;
double lInf = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD) ? 1.8e-2 : 1e-4;
normAssert(outDefault, out, "", l1, lInf);
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
-// Copyright (C) 2018, Intel Corporation, all rights reserved.
+// Copyright (C) 2018-2019, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
#include "test_precomp.hpp"
#include "npy_blob.hpp"
#include <opencv2/dnn/shape_utils.hpp>
-
namespace opencv_test { namespace {
template<typename TString>
pb
};
- void testONNXModels(const String& basename, const Extension ext = npy, const double l1 = 0, const float lInf = 0)
+ void testONNXModels(const String& basename, const Extension ext = npy,
+ const double l1 = 0, const float lInf = 0, const bool useSoftmax = false)
{
String onnxmodel = _tf("models/" + basename + ".onnx");
Mat inp, ref;
net.setPreferableTarget(target);
net.setInput(inp);
- Mat out = net.forward();
+ Mat out = net.forward("");
+
+ if (useSoftmax)
+ {
+ LayerParams lp;
+ Net netSoftmax;
+ netSoftmax.addLayerToPrev("softmaxLayer", "SoftMax", lp);
+ netSoftmax.setPreferableBackend(DNN_BACKEND_OPENCV);
+
+ netSoftmax.setInput(out);
+ out = netSoftmax.forward();
+
+ netSoftmax.setInput(ref);
+ ref = netSoftmax.forward();
+ }
normAssert(ref, out, "", l1 ? l1 : default_l1, lInf ? lInf : default_lInf);
}
};
TEST_P(Test_ONNX_layers, Convolution)
{
testONNXModels("convolution");
+}
+
+
+TEST_P(Test_ONNX_layers, Two_convolution)
+{
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X
+ )
+ throw SkipTestException("Test is disabled for MyriadX"); // 2018R5+ is failed
+#endif
+ // Reference output values are in range [-0.855, 0.611]
testONNXModels("two_convolution");
}
{
testONNXModels("deconvolution");
testONNXModels("two_deconvolution");
+ testONNXModels("deconvolution_group");
+ testONNXModels("deconvolution_output_shape");
}
TEST_P(Test_ONNX_layers, Dropout)
TEST_P(Test_ONNX_layers, Constant)
{
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
+ throw SkipTestException("Test is disabled for OpenVINO <= 2018R5 + MyriadX target");
+#endif
testONNXModels("constant");
}
testONNXModels("padding");
}
+TEST_P(Test_ONNX_layers, Resize)
+{
+ testONNXModels("resize_nearest");
+}
+
TEST_P(Test_ONNX_layers, MultyInputs)
{
const String model = _tf("models/multy_inputs.onnx");
testONNXModels("dynamic_reshape");
}
+TEST_P(Test_ONNX_layers, Reshape)
+{
+ testONNXModels("unsqueeze");
+}
+
INSTANTIATE_TEST_CASE_P(/*nothing*/, Test_ONNX_layers, dnnBackendsAndTargets());
class Test_ONNX_nets : public Test_ONNX_layers {};
TEST_P(Test_ONNX_nets, RCNN_ILSVRC13)
{
- testONNXModels("rcnn_ilsvrc13", pb);
+ // Reference output values are in range [-4.992, -1.161]
+ testONNXModels("rcnn_ilsvrc13", pb, 0.0045);
}
#ifdef OPENCV_32BIT_CONFIGURATION
TEST_P(Test_ONNX_nets, VGG16)
#endif
{
- double l1 = default_l1;
- double lInf = default_lInf;
- // output range: [-69; 72]
- if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) {
- l1 = 0.087;
- lInf = 0.585;
- }
- else if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL) {
- lInf = 1.2e-4;
- }
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE >= 2018050000
- if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16)
- l1 = 0.131;
-#endif
- testONNXModels("vgg16", pb, l1, lInf);
+ // output range: [-69; 72], after Softmax [0; 0.96]
+ testONNXModels("vgg16", pb, default_l1, default_lInf, true);
}
#ifdef OPENCV_32BIT_CONFIGURATION
TEST_P(Test_ONNX_nets, VGG16_bn)
#endif
{
- double l1 = default_l1;
- double lInf = default_lInf;
- // output range: [-16; 27]
- if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16) {
- l1 = 0.0086;
- lInf = 0.037;
- }
- else if (backend == DNN_BACKEND_INFERENCE_ENGINE &&
- (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD)) {
- l1 = 0.031;
- lInf = 0.2;
- }
- testONNXModels("vgg16-bn", pb, l1, lInf);
+ // output range: [-16; 27], after Softmax [0; 0.67]
+ const double lInf = (target == DNN_TARGET_MYRIAD) ? 0.038 : default_lInf;
+ testONNXModels("vgg16-bn", pb, default_l1, lInf, true);
}
TEST_P(Test_ONNX_nets, ZFNet)
TEST_P(Test_ONNX_nets, ResNet18v1)
{
- // output range: [-16; 22]
- const double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.022 : default_l1;
- const double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.12 : default_lInf;
- testONNXModels("resnet18v1", pb, l1, lInf);
+ // output range: [-16; 22], after Softmax [0, 0.51]
+ testONNXModels("resnet18v1", pb, default_l1, default_lInf, true);
}
TEST_P(Test_ONNX_nets, ResNet50v1)
{
- // output range: [-67; 75]
- const double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.6 : 1.25e-5;
- const double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.51 : 1.2e-4;
- testONNXModels("resnet50v1", pb, l1, lInf);
+ // output range: [-67; 75], after Softmax [0, 0.98]
+ testONNXModels("resnet50v1", pb, default_l1, default_lInf, true);
}
TEST_P(Test_ONNX_nets, ResNet101_DUC_HDC)
{
- if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_OPENCL
- || target == DNN_TARGET_MYRIAD) {
- throw SkipTestException("");
- }
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE)
+ throw SkipTestException("Test is disabled for DLIE targets");
+#endif
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
+ throw SkipTestException("Test is disabled for Myriad targets");
+#endif
+ if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_OPENCL)
+ throw SkipTestException("Test is disabled for OpenCL targets");
testONNXModels("resnet101_duc_hdc", pb);
}
TEST_P(Test_ONNX_nets, TinyYolov2)
{
- if (cvtest::skipUnstableTests ||
- (backend == DNN_BACKEND_INFERENCE_ENGINE && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))) {
- throw SkipTestException("");
- }
+ if (cvtest::skipUnstableTests)
+ throw SkipTestException("Skip unstable test");
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE
+ && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)
+ )
+ throw SkipTestException("Test is disabled for DLIE OpenCL targets");
+
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X
+ )
+ throw SkipTestException("Test is disabled for MyriadX");
+#endif
// output range: [-11; 8]
- const double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.017 : default_l1;
- const double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.14 : default_lInf;
+ double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.017 : default_l1;
+ double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.14 : default_lInf;
testONNXModels("tiny_yolo2", pb, l1, lInf);
}
TEST_P(Test_ONNX_nets, CNN_MNIST)
{
- // output range: [-1952; 6574]
- const double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 3.82 : 4.4e-4;
- const double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 13.5 : 2e-3;
-
- testONNXModels("cnn_mnist", pb, l1, lInf);
+ // output range: [-1952; 6574], after Softmax [0; 1]
+ testONNXModels("cnn_mnist", pb, default_l1, default_lInf, true);
}
TEST_P(Test_ONNX_nets, MobileNet_v2)
{
- // output range: [-166; 317]
- const double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.4 : 7e-5;
- const double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 2.87 : 5e-4;
- testONNXModels("mobilenetv2", pb, l1, lInf);
+ // output range: [-166; 317], after Softmax [0; 1]
+ testONNXModels("mobilenetv2", pb, default_l1, default_lInf, true);
}
TEST_P(Test_ONNX_nets, LResNet100E_IR)
TEST_P(Test_ONNX_nets, Emotion_ferplus)
{
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X
+ )
+ throw SkipTestException("Test is disabled for MyriadX");
+#endif
+
double l1 = default_l1;
double lInf = default_lInf;
- // Output values are in range [-2.01109, 2.11111]
+
+ // Output values are in range [-2.011, 2.111]
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
l1 = 0.007;
else if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16)
TEST_P(Test_ONNX_nets, Inception_v2)
{
- if (backend == DNN_BACKEND_INFERENCE_ENGINE)
- throw SkipTestException("");
-
- testONNXModels("inception_v2", pb);
+ testONNXModels("inception_v2", pb, default_l1, default_lInf, true);
}
TEST_P(Test_ONNX_nets, DenseNet121)
{
- // output range: [-87; 138]
- const double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.12 : 2.2e-5;
- const double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.74 : 1.23e-4;
- testONNXModels("densenet121", pb, l1, lInf);
+ // output range: [-87; 138], after Softmax [0; 1]
+ testONNXModels("densenet121", pb, default_l1, default_lInf, true);
}
TEST_P(Test_ONNX_nets, Inception_v1)
{
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE >= 2018050000
+#if defined(INF_ENGINE_RELEASE)
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
- throw SkipTestException("Test is disabled for OpenVINO 2018R5");
+ throw SkipTestException("Test is disabled for Myriad targets");
#endif
testONNXModels("inception_v1", pb);
}
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
-// Copyright (C) 2017, Intel Corporation, all rights reserved.
+// Copyright (C) 2017-2019, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
/*
TEST_P(Test_TensorFlow_layers, padding)
{
- runTensorFlowNet("padding_same");
runTensorFlowNet("padding_valid");
runTensorFlowNet("spatial_padding");
runTensorFlowNet("keras_pad_concat");
}
+TEST_P(Test_TensorFlow_layers, padding_same)
+{
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE)
+ throw SkipTestException("Test is disabled for DLIE");
+#endif
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X
+ )
+ throw SkipTestException("Test is disabled for MyriadX");
+#endif
+ // Reference output values are in range [0.0006, 2.798]
+ runTensorFlowNet("padding_same");
+}
+
TEST_P(Test_TensorFlow_layers, eltwise)
{
runTensorFlowNet("eltwise_add_mul");
TEST_P(Test_TensorFlow_layers, pad_and_concat)
{
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE < 2018030000
- if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
- throw SkipTestException("Test is enabled starts from OpenVINO 2018R3");
-#endif
runTensorFlowNet("pad_and_concat");
}
// TODO: fix tests and replace to pooling
TEST_P(Test_TensorFlow_layers, ave_pool_same)
{
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE < 2018030000
- if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
- throw SkipTestException("Test is enabled starts from OpenVINO 2018R3");
+ // Reference output values are in range [-0.519531, 0.112976]
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X
+ )
+ throw SkipTestException("Test is disabled for MyriadX");
#endif
runTensorFlowNet("ave_pool_same");
}
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
throw SkipTestException("");
runTensorFlowNet("matmul");
- runTensorFlowNet("nhwc_reshape_matmul");
runTensorFlowNet("nhwc_transpose_reshape_matmul");
+ // Reference output values are in range [-5.688, 4.484]
+ double l1 = target == DNN_TARGET_MYRIAD ? 6.1e-3 : default_l1;
+ runTensorFlowNet("nhwc_reshape_matmul", false, l1);
+
}
TEST_P(Test_TensorFlow_layers, reshape)
TEST_P(Test_TensorFlow_layers, flatten)
{
- if (backend == DNN_BACKEND_INFERENCE_ENGINE &&
- (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD))
- throw SkipTestException("");
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE)
+ throw SkipTestException("Test is disabled for DLIE");
+#endif
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_2
+ )
+ throw SkipTestException("Test is disabled for Myriad2");
+#endif
+
runTensorFlowNet("flatten", true);
}
TEST_P(Test_TensorFlow_layers, unfused_flatten)
{
- if (backend == DNN_BACKEND_INFERENCE_ENGINE &&
- (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
- throw SkipTestException("");
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE)
+ throw SkipTestException("Test is disabled for DLIE");
+#endif
+
runTensorFlowNet("unfused_flatten");
runTensorFlowNet("unfused_flatten_unknown_batch");
}
TEST_P(Test_TensorFlow_layers, leaky_relu)
{
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE >= 2018050000
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL)
- throw SkipTestException("");
+ throw SkipTestException("Test is disabled for DLIE/OCL target (OpenVINO 2018R5)");
#endif
runTensorFlowNet("leaky_relu_order1");
runTensorFlowNet("leaky_relu_order2");
TEST_P(Test_TensorFlow_layers, l2_normalize)
{
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X
+ )
+ throw SkipTestException("Test is disabled for MyriadX");
+#endif
+
runTensorFlowNet("l2_normalize");
}
// TODO: fix it and add to l2_normalize
TEST_P(Test_TensorFlow_layers, l2_normalize_3d)
{
- if (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU)
- throw SkipTestException("");
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE
+ && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)
+ )
+ throw SkipTestException("Test is disabled for DLIE for OpenCL targets");
+#endif
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
+ throw SkipTestException("Test is disabled for Myriad targets");
+#endif
+
runTensorFlowNet("l2_normalize_3d");
}
TEST_P(Test_TensorFlow_nets, Inception_v2_SSD)
{
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X
+ )
+ throw SkipTestException("Test is disabled for MyriadX");
+#endif
+
checkBackend();
std::string proto = findDataFile("dnn/ssd_inception_v2_coco_2017_11_17.pbtxt", false);
std::string model = findDataFile("dnn/ssd_inception_v2_coco_2017_11_17.pb", false);
0, 3, 0.75838411, 0.44668293, 0.45907149, 0.49459291, 0.52197015,
0, 10, 0.95932811, 0.38349164, 0.32528657, 0.40387636, 0.39165527,
0, 10, 0.93973452, 0.66561931, 0.37841269, 0.68074018, 0.42907384);
+
double scoreDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.0097 : default_l1;
double iouDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.09 : default_lInf;
normAssertDetections(ref, out, "", 0.5, scoreDiff, iouDiff);
{
checkBackend();
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X
+ )
+ throw SkipTestException("Test is disabled for MyriadX");
+#endif
+
std::string model = findDataFile("dnn/ssd_mobilenet_v1_coco_2017_11_17.pb", false);
std::string proto = findDataFile("dnn/ssd_mobilenet_v1_coco_2017_11_17.pbtxt", false);
"faster_rcnn_resnet50_coco_2018_01_28"};
checkBackend();
- if ((backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_CPU) ||
+ if ((backend == DNN_BACKEND_INFERENCE_ENGINE) ||
(backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16))
throw SkipTestException("");
TEST_P(Test_TensorFlow_nets, MobileNet_v1_SSD_PPN)
{
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE >= 2018050000
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
- throw SkipTestException("Unstable test case");
+ throw SkipTestException("Test is disabled for DLIE OpenCL targets in OpenVINO 2018R5");
#endif
+
checkBackend();
std::string proto = findDataFile("dnn/ssd_mobilenet_v1_ppn_coco.pbtxt", false);
std::string model = findDataFile("dnn/ssd_mobilenet_v1_ppn_coco.pb", false);
net.setInput(blob);
Mat out = net.forward();
- double scoreDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.011 : 1.1e-5;
- double iouDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.021 : default_lInf;
- normAssertDetections(ref, out, "", 0.4, scoreDiff, iouDiff);
+ double scoreDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.048 : 1.1e-5;
+ double iouDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.058 : default_lInf;
+ normAssertDetections(ref, out, "", 0.45, scoreDiff, iouDiff);
}
TEST_P(Test_TensorFlow_nets, opencv_face_detector_uint8)
// np.save('east_text_detection.geometry.npy', geometry)
TEST_P(Test_TensorFlow_nets, EAST_text_detection)
{
- checkBackend();
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE < 2018030000
+#if defined(INF_ENGINE_RELEASE)
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
- throw SkipTestException("Test is enabled starts from OpenVINO 2018R3");
+ throw SkipTestException("Test is disabled for Myriad targets");
#endif
+ checkBackend();
+
std::string netPath = findDataFile("dnn/frozen_east_text_detection.pb", false);
std::string imgPath = findDataFile("cv/ximgproc/sources/08.png", false);
std::string refScoresPath = findDataFile("dnn/east_text_detection.scores.npy", false);
}
else if (target == DNN_TARGET_MYRIAD)
{
- lInf_scores = 0.214;
- l1_geometry = 0.47; lInf_geometry = 15.34;
+ lInf_scores = 0.41;
+ l1_geometry = 0.28; lInf_geometry = 5.94;
}
else
{
TEST_P(Test_TensorFlow_layers, fp16_weights)
{
- const float l1 = 0.00071;
- const float lInf = 0.012;
+ float l1 = 0.00078;
+ float lInf = 0.012;
runTensorFlowNet("fp16_single_conv", false, l1, lInf);
- runTensorFlowNet("fp16_deconvolution", false, l1, lInf);
runTensorFlowNet("fp16_max_pool_odd_same", false, l1, lInf);
- runTensorFlowNet("fp16_padding_valid", false, l1, lInf);
runTensorFlowNet("fp16_eltwise_add_mul", false, l1, lInf);
+ runTensorFlowNet("fp16_pad_and_concat", false, l1, lInf);
+ runTensorFlowNet("fp16_padding_valid", false, l1, lInf);
+ // Reference output values are in range [0.0889, 1.651]
+ runTensorFlowNet("fp16_max_pool_even", false, (target == DNN_TARGET_MYRIAD) ? 0.003 : l1, lInf);
+ if (target == DNN_TARGET_MYRIAD) {
+ l1 = 0.0041;
+ lInf = 0.024;
+ }
+ // Reference output values are in range [0, 10.75]
+ runTensorFlowNet("fp16_deconvolution", false, l1, lInf);
+ // Reference output values are in range [0.418, 2.297]
runTensorFlowNet("fp16_max_pool_odd_valid", false, l1, lInf);
- runTensorFlowNet("fp16_max_pool_even", false, l1, lInf);
- runTensorFlowNet("fp16_padding_same", false, l1, lInf);
}
-// TODO: fix pad_and_concat and add this test case to fp16_weights
-TEST_P(Test_TensorFlow_layers, fp16_pad_and_concat)
+TEST_P(Test_TensorFlow_layers, fp16_padding_same)
{
- const float l1 = 0.00071;
- const float lInf = 0.012;
-#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE < 2018030000
- if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
- throw SkipTestException("Test is enabled starts from OpenVINO 2018R3");
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GT(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE)
+ throw SkipTestException("Test is disabled for DLIE");
#endif
- runTensorFlowNet("fp16_pad_and_concat", false, l1, lInf);
+#if defined(INF_ENGINE_RELEASE)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X
+ )
+ throw SkipTestException("Test is disabled for MyriadX");
+#endif
+
+ // Reference output values are in range [-3.504, -0.002]
+ runTensorFlowNet("fp16_padding_same", false, 6e-4, 4e-3);
}
TEST_P(Test_TensorFlow_layers, defun)
TEST_P(Test_TensorFlow_layers, resize_nearest_neighbor)
{
- if (backend == DNN_BACKEND_INFERENCE_ENGINE && target != DNN_TARGET_MYRIAD)
- throw SkipTestException("");
runTensorFlowNet("resize_nearest_neighbor");
runTensorFlowNet("keras_upsampling2d");
}
TEST_P(Test_TensorFlow_layers, softmax)
{
runTensorFlowNet("keras_softmax");
+ runTensorFlowNet("slim_softmax");
}
TEST_P(Test_TensorFlow_layers, relu6)
{
// Reference output values in range [14.4586, 18.4492].
runTorchNet("net_reshape_single_sample", "", false, false, true,
- (target == DNN_TARGET_MYRIAD || target == DNN_TARGET_OPENCL_FP16) ? 0.0073 : default_l1,
- (target == DNN_TARGET_MYRIAD || target == DNN_TARGET_OPENCL_FP16) ? 0.025 : default_lInf);
+ (target == DNN_TARGET_MYRIAD || target == DNN_TARGET_OPENCL_FP16) ? 0.033 : default_l1,
+ (target == DNN_TARGET_MYRIAD || target == DNN_TARGET_OPENCL_FP16) ? 0.05 : default_lInf);
}
TEST_P(Test_Torch_layers, run_linear)
TEST_P(Test_Torch_nets, OpenFace_accuracy)
{
-#if defined(INF_ENGINE_RELEASE) && (INF_ENGINE_RELEASE < 2018030000 || INF_ENGINE_RELEASE == 2018050000)
+#if defined(INF_ENGINE_RELEASE)
if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD)
- throw SkipTestException("");
+ throw SkipTestException("Test is disabled for Myriad targets");
#endif
checkBackend();
- if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL_FP16)
- throw SkipTestException("");
const string model = findDataFile("dnn/openface_nn4.small2.v1.t7", false);
Net net = readNetFromTorch(model);
net.setInput(inputBlob);
Mat out = net.forward();
+ // Reference output values are in range [-0.17212, 0.263492]
+ // on Myriad problem layer: l4_Pooling - does not use pads_begin
+ float l1 = (target == DNN_TARGET_OPENCL_FP16) ? 4e-4 : 1e-5;
+ float lInf = (target == DNN_TARGET_OPENCL_FP16) ? 1.5e-3 : 1e-3;
Mat outRef = readTorchBlob(_tf("net_openface_output.dat"), true);
- normAssert(out, outRef, "", default_l1, default_lInf);
+ normAssert(out, outRef, "", l1, lInf);
}
static Mat getSegmMask(const Mat& scores)
// -model models/instance_norm/feathers.t7
TEST_P(Test_Torch_nets, FastNeuralStyle_accuracy)
{
+#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LE(2018050000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_MYRIAD
+ && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
+ throw SkipTestException("Test is disabled for OpenVINO <= 2018R5 + MyriadX target");
+#endif
+
checkBackend();
+
+#if defined(INF_ENGINE_RELEASE)
+#if INF_ENGINE_RELEASE <= 2018050000
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE && target == DNN_TARGET_OPENCL)
+ throw SkipTestException("");
+#endif
+#endif
+
std::string models[] = {"dnn/fast_neural_style_eccv16_starry_night.t7",
"dnn/fast_neural_style_instance_norm_feathers.t7"};
std::string targets[] = {"dnn/lena_starry_night.png", "dnn/lena_feathers.png"};
# include <Intrin.h>
#endif
-#ifdef __ARM_NEON__
+#if defined(__ARM_NEON__) && !defined(__CUDACC__)
# include "arm_neon.h"
#endif
ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const
{
ResultType result = 0;
-#ifdef __ARM_NEON__
+#if defined(__ARM_NEON__) && !defined(__CUDACC__)
{
uint32x4_t bits = vmovq_n_u32(0);
for (size_t i = 0; i < size; i += 16) {
public:
KMeansDistanceComputer(Distance _distance, const Matrix<ElementType>& _dataset,
const int _branching, const int* _indices, const Matrix<double>& _dcenters, const size_t _veclen,
- int* _count, int* _belongs_to, std::vector<DistanceType>& _radiuses, bool& _converged)
+ std::vector<int> &_new_centroids, std::vector<DistanceType> &_sq_dists)
: distance(_distance)
, dataset(_dataset)
, branching(_branching)
, indices(_indices)
, dcenters(_dcenters)
, veclen(_veclen)
- , count(_count)
- , belongs_to(_belongs_to)
- , radiuses(_radiuses)
- , converged(_converged)
+ , new_centroids(_new_centroids)
+ , sq_dists(_sq_dists)
{
}
for( int i = begin; i<end; ++i)
{
- DistanceType sq_dist = distance(dataset[indices[i]], dcenters[0], veclen);
- int new_centroid = 0;
+ DistanceType sq_dist(distance(dataset[indices[i]], dcenters[0], veclen));
+ int new_centroid(0);
for (int j=1; j<branching; ++j) {
DistanceType new_sq_dist = distance(dataset[indices[i]], dcenters[j], veclen);
if (sq_dist>new_sq_dist) {
sq_dist = new_sq_dist;
}
}
- if (sq_dist > radiuses[new_centroid]) {
- radiuses[new_centroid] = sq_dist;
- }
- if (new_centroid != belongs_to[i]) {
- CV_XADD(&count[belongs_to[i]], -1);
- CV_XADD(&count[new_centroid], 1);
- belongs_to[i] = new_centroid;
- converged = false;
- }
+ sq_dists[i] = sq_dist;
+ new_centroids[i] = new_centroid;
}
}
const int* indices;
const Matrix<double>& dcenters;
const size_t veclen;
- int* count;
- int* belongs_to;
- std::vector<DistanceType>& radiuses;
- bool& converged;
+ std::vector<int> &new_centroids;
+ std::vector<DistanceType> &sq_dists;
KMeansDistanceComputer& operator=( const KMeansDistanceComputer & ) { return *this; }
};
}
}
+ std::vector<int> new_centroids(indices_length);
+ std::vector<DistanceType> sq_dists(indices_length);
+
// reassign points to clusters
- KMeansDistanceComputer invoker(distance_, dataset_, branching, indices, dcenters, veclen_, count, belongs_to, radiuses, converged);
+ KMeansDistanceComputer invoker(distance_, dataset_, branching, indices, dcenters, veclen_, new_centroids, sq_dists);
parallel_for_(cv::Range(0, (int)indices_length), invoker);
+ for (int i=0; i < (int)indices_length; ++i) {
+ DistanceType sq_dist(sq_dists[i]);
+ int new_centroid(new_centroids[i]);
+ if (sq_dist > radiuses[new_centroid]) {
+ radiuses[new_centroid] = sq_dist;
+ }
+ if (new_centroid != belongs_to[i]) {
+ count[belongs_to[i]]--;
+ count[new_centroid]++;
+ belongs_to[i] = new_centroid;
+ converged = false;
+ }
+ }
+
for (int i=0; i<branching; ++i) {
// if one cluster converges to an empty cluster,
// move an element into that cluster
# FIXME: Rework standalone build in more generic maner
# (Restructure directories, add common pass, etc)
if (NOT DEFINED OPENCV_INITIAL_PASS)
+ cmake_minimum_required(VERSION 3.3)
include("cmake/standalone.cmake")
return()
endif()
+if("${CMAKE_BUILD_TYPE}" STREQUAL "")
+ set(CMAKE_BUILD_TYPE "Release")
+endif()
+
if (NOT TARGET ade )
find_package(ade 0.1.0 REQUIRED)
endif()
PUBLIC $<BUILD_INTERFACE:${FLUID_ROOT}/include>
PRIVATE ${FLUID_ROOT}/src)
-target_compile_definitions(${FLUID_TARGET} PUBLIC -DGAPI_STANDALONE
+target_compile_definitions(${FLUID_TARGET} PUBLIC GAPI_STANDALONE
# This preprocessor definition resolves symbol clash when
# standalone fluid meets gapi ocv module in one application
PUBLIC cv=fluidcv)
set_target_properties(${FLUID_TARGET} PROPERTIES POSITION_INDEPENDENT_CODE True)
set_property(TARGET ${FLUID_TARGET} PROPERTY CXX_STANDARD 11)
+if(MSVC)
+ target_compile_options(${FLUID_TARGET} PUBLIC "/wd4251")
+ target_compile_definitions(${FLUID_TARGET} PRIVATE _CRT_SECURE_NO_DEPRECATE)
+endif()
+
target_link_libraries(${FLUID_TARGET} PRIVATE ade)
inline const uint8_t* linePtr(int index) const
{
+ // "out_of_window" check:
+ // user must not request the lines which are outside of specified kernel window
+ GAPI_DbgAssert(index >= -m_border_size
+ && index < -m_border_size + static_cast<int>(m_linePtrs.size()));
return m_linePtrs[index + m_border_size];
}
};
enum class Kind
{
Filter,
- Resize
+ Resize,
+ NV12toRGB
};
// This function is a generic "doWork" callback
}
};
+ G_TYPED_KERNEL(GNV12toRGB, <GMat(GMat, GMat)>, "org.opencv.imgproc.colorconvert.nv12torgb") {
+ static GMatDesc outMeta(GMatDesc in_y, GMatDesc in_uv) {
+ GAPI_Assert(in_y.chan == 1);
+ GAPI_Assert(in_uv.chan == 2);
+ GAPI_Assert(in_y.depth == CV_8U);
+ GAPI_Assert(in_uv.depth == CV_8U);
+ // UV size should be aligned with Y
+ GAPI_Assert(in_y.size.width == 2 * in_uv.size.width);
+ GAPI_Assert(in_y.size.height == 2 * in_uv.size.height);
+ return in_y.withType(CV_8U, 3); // type will be CV_8UC3;
+ }
+ };
+
+ G_TYPED_KERNEL(GNV12toBGR, <GMat(GMat, GMat)>, "org.opencv.imgproc.colorconvert.nv12tobgr") {
+ static GMatDesc outMeta(GMatDesc in_y, GMatDesc in_uv) {
+ GAPI_Assert(in_y.chan == 1);
+ GAPI_Assert(in_uv.chan == 2);
+ GAPI_Assert(in_y.depth == CV_8U);
+ GAPI_Assert(in_uv.depth == CV_8U);
+ // UV size should be aligned with Y
+ GAPI_Assert(in_y.size.width == 2 * in_uv.size.width);
+ GAPI_Assert(in_y.size.height == 2 * in_uv.size.height);
+ return in_y.withType(CV_8U, 3); // type will be CV_8UC3;
+ }
+ };
+
G_TYPED_KERNEL(GRGB2Lab, <GMat(GMat)>, "org.opencv.imgproc.colorconvert.rgb2lab") {
static GMatDesc outMeta(GMatDesc in) {
return in; // type still remains CV_8UC3;
@sa RGB2Lab, RGB2YUV
*/
GAPI_EXPORTS GMat YUV2RGB(const GMat& src);
+
+/** @brief Converts an image from NV12 (YUV420p) color space to RGB.
+The function converts an input image from NV12 color space to RGB.
+The conventional ranges for Y, U, and V channel values are 0 to 255.
+
+Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3.
+
+@note Function textual ID is "org.opencv.imgproc.colorconvert.nv12torgb"
+
+@param src_y input image: 8-bit unsigned 1-channel image @ref CV_8UC1.
+@param src_uv input image: 8-bit unsigned 2-channel image @ref CV_8UC2.
+
+@sa YUV2RGB, NV12toBGR
+*/
+GAPI_EXPORTS GMat NV12toRGB(const GMat& src_y, const GMat& src_uv);
+
+/** @brief Converts an image from NV12 (YUV420p) color space to BGR.
+The function converts an input image from NV12 color space to RGB.
+The conventional ranges for Y, U, and V channel values are 0 to 255.
+
+Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3.
+
+@note Function textual ID is "org.opencv.imgproc.colorconvert.nv12tobgr"
+
+@param src_y input image: 8-bit unsigned 1-channel image @ref CV_8UC1.
+@param src_uv input image: 8-bit unsigned 2-channel image @ref CV_8UC2.
+
+@sa YUV2BGR, NV12toRGB
+*/
+GAPI_EXPORTS GMat NV12toBGR(const GMat& src_y, const GMat& src_uv);
//! @} gapi_colorconvert
} //namespace gapi
} //namespace cv
return imgproc::GYUV2RGB::on(src);
}
+GMat NV12toRGB(const GMat& src_y, const GMat& src_uv)
+{
+ return imgproc::GNV12toRGB::on(src_y, src_uv);
+}
+
+GMat NV12toBGR(const GMat& src_y, const GMat& src_uv)
+{
+ return imgproc::GNV12toBGR::on(src_y, src_uv);
+}
+
GMat RGB2Lab(const GMat& src)
{
return imgproc::GRGB2Lab::on(src);
}
};
+GAPI_OCV_KERNEL(GCPUNV12toRGB, cv::gapi::imgproc::GNV12toRGB)
+{
+ static void run(const cv::Mat& in_y, const cv::Mat& in_uv, cv::Mat &out)
+ {
+ cv::cvtColorTwoPlane(in_y, in_uv, out, cv::COLOR_YUV2RGB_NV12);
+ }
+};
+
+GAPI_OCV_KERNEL(GCPUNV12toBGR, cv::gapi::imgproc::GNV12toBGR)
+{
+ static void run(const cv::Mat& in_y, const cv::Mat& in_uv, cv::Mat &out)
+ {
+ cv::cvtColorTwoPlane(in_y, in_uv, out, cv::COLOR_YUV2BGR_NV12);
+ }
+};
+
GAPI_OCV_KERNEL(GCPURGB2Lab, cv::gapi::imgproc::GRGB2Lab)
{
static void run(const cv::Mat& in, cv::Mat &out)
, GCPUEqualizeHist
, GCPURGB2YUV
, GCPUYUV2RGB
+ , GCPUNV12toRGB
+ , GCPUNV12toBGR
, GCPURGB2Lab
, GCPUBGR2LUV
, GCPUBGR2YUV
{
GFluidModel fm(graph);
auto fluid_impl = cv::util::any_cast<cv::GFluidKernel>(impl.opaque);
- fm.metadata(op_node).set(cv::gimpl::FluidUnit{fluid_impl, {}, 0, 0, 0.0});
+ fm.metadata(op_node).set(cv::gimpl::FluidUnit{fluid_impl, {}, 0, {}, 0.0});
}
virtual EPtr compile(const ade::Graph &graph,
struct FluidFilterAgent : public FluidAgent
{
private:
- virtual int firstWindow() const override;
- virtual std::pair<int,int> linesReadAndnextWindow() const override;
+ virtual int firstWindow(std::size_t inPort) const override;
+ virtual std::pair<int,int> linesReadAndnextWindow(std::size_t inPort) const override;
virtual void setRatio(double) override { /* nothing */ }
public:
using FluidAgent::FluidAgent;
struct FluidResizeAgent : public FluidAgent
{
private:
- virtual int firstWindow() const override;
- virtual std::pair<int,int> linesReadAndnextWindow() const override;
+ virtual int firstWindow(std::size_t inPort) const override;
+ virtual std::pair<int,int> linesReadAndnextWindow(std::size_t inPort) const override;
virtual void setRatio(double ratio) override;
std::unique_ptr<FluidMapper> m_mapper;
public:
using FluidAgent::FluidAgent;
};
+
+struct FluidNV12toRGBAgent : public FluidAgent
+{
+private:
+ virtual int firstWindow(std::size_t inPort) const override;
+ virtual std::pair<int,int> linesReadAndnextWindow(std::size_t inPort) const override;
+ virtual void setRatio(double) override { /* nothing */ }
+public:
+ using FluidAgent::FluidAgent;
+};
}} // namespace cv::gimpl
cv::gimpl::FluidAgent::FluidAgent(const ade::Graph &g, ade::NodeHandle nh)
{
m_producedLines = 0;
- auto lines = firstWindow();
- for (auto &v : in_views)
+ for (const auto& it : ade::util::indexed(in_views))
{
+ auto& v = ade::util::value(it);
if (v)
{
+ auto idx = ade::util::index(it);
+ auto lines = firstWindow(idx);
v.priv().reset(lines);
}
}
}
}
-static int maxLineConsumption(const cv::GFluidKernel& k, int inH, int outH, int lpi)
+static int maxLineConsumption(const cv::GFluidKernel& k, int inH, int outH, int lpi, std::size_t inPort)
{
switch (k.m_kind)
{
return (inH == 1) ? 1 : 2 + lpi - 1;
}
} break;
+ case cv::GFluidKernel::Kind::NV12toRGB: return inPort == 0 ? 2 : 1; break;
default: GAPI_Assert(false); return 0;
}
}
case cv::GFluidKernel::Kind::Filter: return (k.m_window - 1) / 2; break;
// Resize never reads from border pixels
case cv::GFluidKernel::Kind::Resize: return 0; break;
+ case cv::GFluidKernel::Kind::NV12toRGB: return 0; break;
default: GAPI_Assert(false); return 0;
}
}
return std::make_pair(lines_read, next_window);
}
-int cv::gimpl::FluidFilterAgent::firstWindow() const
+int cv::gimpl::FluidFilterAgent::firstWindow(std::size_t) const
{
return k.m_window + k.m_lpi - 1;
}
-std::pair<int,int> cv::gimpl::FluidFilterAgent::linesReadAndnextWindow() const
+std::pair<int,int> cv::gimpl::FluidFilterAgent::linesReadAndnextWindow(std::size_t) const
{
int lpi = std::min(k.m_lpi, m_outputLines - m_producedLines - k.m_lpi);
return std::make_pair(k.m_lpi, k.m_window - 1 + lpi);
}
-int cv::gimpl::FluidResizeAgent::firstWindow() const
+int cv::gimpl::FluidResizeAgent::firstWindow(std::size_t) const
{
auto outIdx = out_buffers[0]->priv().y();
auto lpi = std::min(m_outputLines - m_producedLines, k.m_lpi);
return m_mapper->firstWindow(outIdx, lpi);
}
-std::pair<int,int> cv::gimpl::FluidResizeAgent::linesReadAndnextWindow() const
+std::pair<int,int> cv::gimpl::FluidResizeAgent::linesReadAndnextWindow(std::size_t) const
{
auto outIdx = out_buffers[0]->priv().y();
auto lpi = std::min(m_outputLines - m_producedLines - k.m_lpi, k.m_lpi);
return m_mapper->linesReadAndNextWindow(outIdx, lpi);
}
+int cv::gimpl::FluidNV12toRGBAgent::firstWindow(std::size_t inPort) const
+{
+ // 2 lines for Y, 1 for UV
+ return inPort == 0 ? 2 : 1;
+}
+
+std::pair<int,int> cv::gimpl::FluidNV12toRGBAgent::linesReadAndnextWindow(std::size_t inPort) const
+{
+ // 2 lines for Y, 1 for UV
+ return inPort == 0 ? std::make_pair(2, 2) : std::make_pair(1, 1);
+}
+
void cv::gimpl::FluidResizeAgent::setRatio(double ratio)
{
if (ratio >= 1.0)
k.m_f(in_args, out_buffers);
- for (auto& in_view : in_views)
+ for (const auto& it : ade::util::indexed(in_views))
{
+ auto& in_view = ade::util::value(it);
+
if (in_view)
{
- auto pair = linesReadAndnextWindow();
+ auto idx = ade::util::index(it);
+ auto pair = linesReadAndnextWindow(idx);
in_view.priv().readDone(pair.first, pair.second);
};
}
// only GMats participate in the process so it's valid to obtain GMatDesc
const auto& meta = util::get<GMatDesc>(data.meta);
- for (const auto& inNode : oh->inNodes())
+ for (const auto& in_edge : oh->inEdges())
{
- const auto& in_data = m_gm.metadata(inNode).get<Data>();
+ const auto& in_node = in_edge->srcNode();
+ const auto& in_data = m_gm.metadata(in_node).get<Data>();
- if (in_data.shape == GShape::GMAT && fg.metadata(inNode).contains<FluidData>())
+ if (in_data.shape == GShape::GMAT && fg.metadata(in_node).contains<FluidData>())
{
const auto& in_meta = util::get<GMatDesc>(in_data.meta);
- const auto& fd = fg.metadata(inNode).get<FluidData>();
+ const auto& fd = fg.metadata(in_node).get<FluidData>();
auto adjFilterRoi = [](cv::gapi::own::Rect produced, int b, int max_height) {
// Extend with border roi which should be produced, crop to logical image size
return roi;
};
+ auto adjNV12Roi = [&](cv::gapi::own::Rect produced, std::size_t port) {
+ GAPI_Assert(produced.x % 2 == 0);
+ GAPI_Assert(produced.y % 2 == 0);
+ GAPI_Assert(produced.width % 2 == 0);
+ GAPI_Assert(produced.height % 2 == 0);
+
+ cv::gapi::own::Rect roi;
+ switch (port) {
+ case 0: roi = produced; break;
+ case 1: roi = cv::gapi::own::Rect{ produced.x/2, produced.y/2, produced.width/2, produced.height/2 }; break;
+ default: GAPI_Assert(false);
+ }
+ return roi;
+ };
+
cv::gapi::own::Rect produced = rois[m_id_map.at(data.rc)];
cv::gapi::own::Rect resized;
switch (fg.metadata(oh).get<FluidUnit>().k.m_kind)
{
- case GFluidKernel::Kind::Filter: resized = produced; break;
- case GFluidKernel::Kind::Resize: resized = adjResizeRoi(produced, in_meta.size, meta.size); break;
+ case GFluidKernel::Kind::Filter: resized = produced; break;
+ case GFluidKernel::Kind::Resize: resized = adjResizeRoi(produced, in_meta.size, meta.size); break;
+ case GFluidKernel::Kind::NV12toRGB: resized = adjNV12Roi(produced, m_gm.metadata(in_edge).get<Input>().port); break;
default: GAPI_Assert(false);
}
readStarts[in_id] = readStart;
rois[in_id] = roi;
// Continue traverse on internal (w.r.t Island) data nodes only.
- if (fd.internal) nodesToVisit.push(inNode);
+ if (fd.internal) nodesToVisit.push(in_node);
}
else
{
GAPI_Assert(rois[in_id] == roi);
}
} // if (in_data.shape == GShape::GMAT)
- } // for (const auto& inNode : oh->inNodes())
+ } // for (const auto& in_edge : oh->inEdges())
} // if (!startNode->inNodes().empty())
} // while (!nodesToVisit.empty())
}
const auto& fu = fg.metadata(nh).get<FluidUnit>();
switch (fu.k.m_kind)
{
- case GFluidKernel::Kind::Filter: m_agents.emplace_back(new FluidFilterAgent(m_g, nh)); break;
- case GFluidKernel::Kind::Resize: m_agents.emplace_back(new FluidResizeAgent(m_g, nh)); break;
+ case GFluidKernel::Kind::Filter: m_agents.emplace_back(new FluidFilterAgent(m_g, nh)); break;
+ case GFluidKernel::Kind::Resize: m_agents.emplace_back(new FluidResizeAgent(m_g, nh)); break;
+ case GFluidKernel::Kind::NV12toRGB: m_agents.emplace_back(new FluidNV12toRGBAgent(m_g, nh)); break;
default: GAPI_Assert(false);
}
// NB.: in_buffer_ids size is equal to Arguments size, not Edges size!!!
}
}
- GAPI_Assert(in_hs.size() == 1 && out_ws.size() == 1 && out_hs.size() == 1);
+ auto &fu = fg.metadata(node).get<FluidUnit>();
+
+ GAPI_Assert((out_ws.size() == 1 && out_hs.size() == 1) &&
+ ((in_hs.size() == 1) ||
+ ((in_hs.size() == 2) && fu.k.m_kind == cv::GFluidKernel::Kind::NV12toRGB)));
+
+ const auto &op = g.metadata(node).get<Op>();
+ fu.line_consumption.resize(op.args.size(), 0);
auto in_h = *in_hs .cbegin();
auto out_h = *out_hs.cbegin();
- auto &fu = fg.metadata(node).get<FluidUnit>();
fu.ratio = (double)in_h / out_h;
- int line_consumption = maxLineConsumption(fu.k, in_h, out_h, fu.k.m_lpi);
- int border_size = borderSize(fu.k);
+ // Set line consumption for each image (GMat) input
+ for (const auto& in_edge : node->inEdges())
+ {
+ const auto& d = g.metadata(in_edge->srcNode()).get<Data>();
+ if (d.shape == cv::GShape::GMAT)
+ {
+ auto port = g.metadata(in_edge).get<Input>().port;
+ fu.line_consumption[port] = maxLineConsumption(fu.k, in_h, out_h, fu.k.m_lpi, port);
- fu.border_size = border_size;
- fu.line_consumption = line_consumption;
+ GModel::log(g, node, "Line consumption (port " + std::to_string(port) + "): "
+ + std::to_string(fu.line_consumption[port]));
+ }
+ }
- GModel::log(g, node, "Line consumption: " + std::to_string(fu.line_consumption));
+ fu.border_size = borderSize(fu.k);
GModel::log(g, node, "Border size: " + std::to_string(fu.border_size));
}
}
{
const auto &fu = fg.metadata(node).get<FluidUnit>();
- for (const auto &in_data_node : node->inNodes())
+ for (const auto &in_edge : node->inEdges())
{
+ const auto &in_data_node = in_edge->srcNode();
+ auto port = g.metadata(in_edge).get<Input>().port;
+
auto &fd = fg.metadata(in_data_node).get<FluidData>();
// Update (not Set) fields here since a single data node may be
// accessed by multiple consumers
- fd.max_consumption = std::max(fu.line_consumption, fd.max_consumption);
+ fd.max_consumption = std::max(fu.line_consumption[port], fd.max_consumption);
fd.border_size = std::max(fu.border_size, fd.border_size);
GModel::log(g, in_data_node, "Line consumption: " + std::to_string(fd.max_consumption)
- + " (upd by " + std::to_string(fu.line_consumption) + ")", node);
+ + " (upd by " + std::to_string(fu.line_consumption[port]) + ")", node);
GModel::log(g, in_data_node, "Border size: " + std::to_string(fd.border_size), node);
}
}
{
const auto &fu = fg.metadata(node).get<FluidUnit>();
- const int own_latency = fu.line_consumption - fu.border_size;
GModel::log(g, node, "LPI: " + std::to_string(fu.k.m_lpi));
// Output latency is max(input_latency) + own_latency
- int in_latency = 0;
- for (const auto &in_data_node : node->inNodes())
+ int out_latency = 0;
+ for (const auto &in_edge: node->inEdges())
{
// FIXME: ASSERT(DATA), ASSERT(FLUIDDATA)
- in_latency = std::max(in_latency, fg.metadata(in_data_node).get<FluidData>().latency);
+ const auto port = g.metadata(in_edge).get<Input>().port;
+ const auto own_latency = fu.line_consumption[port] - fu.border_size;
+ const auto in_latency = fg.metadata(in_edge->srcNode()).get<FluidData>().latency;
+ out_latency = std::max(out_latency, in_latency + own_latency);
}
- const int out_latency = in_latency + own_latency;
for (const auto &out_data_node : node->outNodes())
{
if (buf_idx >= 0)
{
- agent->in_views[in_idx].priv().allocate(fu.line_consumption, fu.border);
+ agent->in_views[in_idx].priv().allocate(fu.line_consumption[in_idx], fu.border);
}
}
// will be copied by views on each iteration and base our choice
// on this criteria)
auto readers = node->outNodes();
+
+ // There can be a situation when __internal__ nodes produced as part of some
+ // operation are unused later in the graph:
+ //
+ // in -> OP1
+ // |------> internal_1 // unused node
+ // |------> internal_2 -> OP2
+ // |------> out
+ //
+ // To allow graphs like the one above, skip nodes with empty outNodes()
+ if (readers.empty()) {
+ continue;
+ }
+
const auto &candidate = ade::util::find_if(readers, [&](ade::NodeHandle nh) {
return fg.metadata(nh).contains<FluidUnit>() &&
fg.metadata(nh).get<FluidUnit>().border_size == fd.border_size;
//
// Copyright (C) 2018 Intel Corporation
-
#ifndef OPENCV_GAPI_FLUID_BACKEND_HPP
#define OPENCV_GAPI_FLUID_BACKEND_HPP
+// FIXME? Actually gfluidbackend.hpp is not included anywhere
+// and can be placed in gfluidbackend.cpp
+
#include "opencv2/gapi/garg.hpp"
#include "opencv2/gapi/gproto.hpp"
#include "opencv2/gapi/fluid/gfluidkernel.hpp"
GFluidKernel k;
gapi::fluid::BorderOpt border;
int border_size;
- int line_consumption;
+ std::vector<int> line_consumption;
double ratio;
};
private:
// FIXME!!!
// move to another class
- virtual int firstWindow() const = 0;
- virtual std::pair<int,int> linesReadAndnextWindow() const = 0;
+ virtual int firstWindow(std::size_t inPort) const = 0;
+ virtual std::pair<int,int> linesReadAndnextWindow(std::size_t inPort) const = 0;
};
class GFluidExecutable final: public GIslandExecutable
m_border_size = borderSize;
}
-const uint8_t* fluid::ViewPrivWithoutOwnBorder::InLineB(int index) const
-{
- GAPI_DbgAssert(m_p);
-
- const auto &p_priv = m_p->priv();
-
- GAPI_DbgAssert(index >= -m_border_size
- && index < -m_border_size + m_lines_next_iter);
-
- const int log_idx = m_read_caret + index;
-
- return p_priv.storage().inLineB(log_idx, m_p->meta().size.height);
-}
-
void fluid::ViewPrivWithoutOwnBorder::allocate(int lineConsumption, BorderOpt)
{
initCache(lineConsumption);
return m_own_storage.size();
}
-const uint8_t* fluid::ViewPrivWithOwnBorder::InLineB(int index) const
-{
- GAPI_DbgAssert(m_p);
- GAPI_DbgAssert(index >= -m_border_size
- && index < -m_border_size + m_lines_next_iter);
-
- const int log_idx = m_read_caret + index;
-
- return m_own_storage.inLineB(log_idx, m_p->meta().size.height);
-}
-
bool fluid::View::ready() const
{
return m_priv->ready();
// Init physical buffer
// FIXME? combine line_consumption with skew?
+ // FIXME? This formula serves general case to avoid possible deadlock,
+ // in some cases this value can be smaller:
+ // 2 lines produced, 2 consumed, data_height can be 2, not 3
auto data_height = std::max(line_consumption, skew) + m_writer_lpi - 1;
m_storage = createStorage(data_height,
}
}
-uint8_t* fluid::Buffer::Priv::OutLineB(int index)
-{
- GAPI_DbgAssert(index >= 0 && index < m_writer_lpi);
-
- return m_storage->ptr(m_write_caret + index);
-}
-
int fluid::Buffer::Priv::lpi() const
{
// FIXME:
// Does the view have enough unread lines for next iteration
bool ready() const;
-
- // API used (indirectly) by user code
- virtual const uint8_t* InLineB(int index) const = 0;
};
class ViewPrivWithoutOwnBorder final : public View::Priv
virtual void prepareToRead() override;
inline virtual std::size_t size() const override { return 0; }
-
- // API used (indirectly) by user code
- virtual const uint8_t* InLineB(int index) const override;
};
class ViewPrivWithOwnBorder final : public View::Priv
virtual void allocate(int lineConsumption, BorderOpt border) override;
virtual void prepareToRead() override;
virtual std::size_t size() const override;
-
- // API used (indirectly) by user code
- virtual const uint8_t* InLineB(int index) const override;
};
void debugBufferPriv(const Buffer& buffer, std::ostream &os);
inline int writer_lpi() const { return m_writer_lpi; }
// API used (indirectly) by user code
- uint8_t* OutLineB(int index = 0);
int lpi() const;
inline int readStart() const { return m_readStart; }
struct BGR2GrayTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
struct RGB2YUVTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
struct YUV2RGBTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
+struct NV12toRGBTest : public TestParams<std::tuple<compare_f,cv::Size,cv::GCompileArgs>> {};
+struct NV12toBGRTest : public TestParams<std::tuple<compare_f,cv::Size,cv::GCompileArgs>> {};
struct RGB2LabTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
struct BGR2LUVTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
struct LUV2BGRTest : public TestParams<std::tuple<compare_f,cv::Size,bool,cv::GCompileArgs>> {};
}
}
+TEST_P(NV12toRGBTest, AccuracyTest)
+{
+ compare_f cmpF;
+ cv::Size sz;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, sz, compile_args) = GetParam();
+
+ initMatsRandN(CV_8UC1, sz, CV_8UC3);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in_y;
+ cv::GMat in_uv;
+ auto out = cv::gapi::NV12toRGB(in_y, in_uv);
+
+ // Additional mat for uv
+ cv::Mat in_mat_uv(cv::Size(sz.width / 2, sz.height / 2), CV_8UC2);
+ cv::randn(in_mat_uv, cv::Scalar::all(127), cv::Scalar::all(40.f));
+
+ cv::GComputation c(cv::GIn(in_y, in_uv), cv::GOut(out));
+ c.apply(cv::gin(in_mat1, in_mat_uv), cv::gout(out_mat_gapi), std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColorTwoPlane(in_mat1, in_mat_uv, out_mat_ocv, cv::COLOR_YUV2RGB_NV12);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
+TEST_P(NV12toBGRTest, AccuracyTest)
+{
+ compare_f cmpF;
+ cv::Size sz;
+ cv::GCompileArgs compile_args;
+ std::tie(cmpF, sz, compile_args) = GetParam();
+
+ initMatsRandN(CV_8UC1, sz, CV_8UC3);
+
+ // G-API code //////////////////////////////////////////////////////////////
+ cv::GMat in_y;
+ cv::GMat in_uv;
+ auto out = cv::gapi::NV12toBGR(in_y, in_uv);
+
+ // Additional mat for uv
+ cv::Mat in_mat_uv(cv::Size(sz.width / 2, sz.height / 2), CV_8UC2);
+ cv::randn(in_mat_uv, cv::Scalar::all(127), cv::Scalar::all(40.f));
+
+ cv::GComputation c(cv::GIn(in_y, in_uv), cv::GOut(out));
+ c.apply(cv::gin(in_mat1, in_mat_uv), cv::gout(out_mat_gapi), std::move(compile_args));
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ cv::cvtColorTwoPlane(in_mat1, in_mat_uv, out_mat_ocv, cv::COLOR_YUV2BGR_NV12);
+ }
+ // Comparison //////////////////////////////////////////////////////////////
+ {
+ EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
+ EXPECT_EQ(out_mat_gapi.size(), sz);
+ }
+}
+
TEST_P(RGB2LabTest, AccuracyTest)
{
auto param = GetParam();
/*init output matrices or not*/ testing::Bool(),
Values(cv::compile_args(IMGPROC_CPU))));
+INSTANTIATE_TEST_CASE_P(NV12toRGBTestCPU, NV12toRGBTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
+INSTANTIATE_TEST_CASE_P(NV12toBGRTestCPU, NV12toBGRTest,
+ Combine(Values(AbsExact().to_compare_f()),
+ Values(cv::Size(1280, 720),
+ cv::Size(640, 480)),
+ Values(cv::compile_args(IMGPROC_CPU))));
+
INSTANTIATE_TEST_CASE_P(RGB2LabTestCPU, RGB2LabTest,
Combine(Values(AbsExact().to_compare_f()),
Values(cv::Size(1280, 720),
std::make_tuple(cv::Size{64,64},
cv::Size{49,49}, cv::Rect{0,39,49,10}))));
+struct NV12PlusResizeTest : public TestWithParam <std::tuple<cv::Size, cv::Size, cv::Rect>> {};
+TEST_P(NV12PlusResizeTest, Test)
+{
+ cv::Size y_sz, out_sz;
+ cv::Rect roi;
+ std::tie(y_sz, out_sz, roi) = GetParam();
+ int interp = cv::INTER_LINEAR;
+
+ cv::Size uv_sz(y_sz.width / 2, y_sz.height / 2);
+ cv::Size in_sz(y_sz.width, y_sz.height*3/2);
+
+ cv::Mat in_mat = cv::Mat(in_sz, CV_8UC1);
+
+ cv::Scalar mean = cv::Scalar(127.0f);
+ cv::Scalar stddev = cv::Scalar(40.f);
+ cv::randn(in_mat, mean, stddev);
+
+ cv::Mat y_mat = cv::Mat(y_sz, CV_8UC1, in_mat.data);
+ cv::Mat uv_mat = cv::Mat(uv_sz, CV_8UC2, in_mat.data + in_mat.step1() * y_sz.height);
+ cv::Mat out_mat, out_mat_ocv;
+
+ cv::GMat y, uv;
+ auto rgb = cv::gapi::NV12toRGB(y, uv);
+ auto out = cv::gapi::resize(rgb, out_sz, 0, 0, interp);
+ cv::GComputation c(cv::GIn(y, uv), cv::GOut(out));
+
+ auto pkg = cv::gapi::combine(fluidTestPackage, cv::gapi::core::fluid::kernels(), cv::unite_policy::KEEP);
+
+ c.apply(cv::gin(y_mat, uv_mat), cv::gout(out_mat)
+ ,cv::compile_args(pkg, cv::GFluidOutputRois{{to_own(roi)}}));
+
+ cv::Mat rgb_mat;
+ cv::cvtColor(in_mat, rgb_mat, cv::COLOR_YUV2RGB_NV12);
+ cv::resize(rgb_mat, out_mat_ocv, out_sz, 0, 0, interp);
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat(roi) != out_mat_ocv(roi)));
+}
+
+INSTANTIATE_TEST_CASE_P(Fluid, NV12PlusResizeTest,
+ Values(std::make_tuple(cv::Size{8, 8},
+ cv::Size{4, 4}, cv::Rect{0, 0, 4, 4})
+ ,std::make_tuple(cv::Size{8, 8},
+ cv::Size{4, 4}, cv::Rect{0, 0, 4, 1})
+ ,std::make_tuple(cv::Size{8, 8},
+ cv::Size{4, 4}, cv::Rect{0, 1, 4, 2})
+ ,std::make_tuple(cv::Size{8, 8},
+ cv::Size{4, 4}, cv::Rect{0, 2, 4, 2})
+ ,std::make_tuple(cv::Size{64, 64},
+ cv::Size{49, 49}, cv::Rect{0, 0, 49, 49})
+ ,std::make_tuple(cv::Size{64, 64},
+ cv::Size{49, 49}, cv::Rect{0, 0, 49, 12})
+ ,std::make_tuple(cv::Size{64, 64},
+ cv::Size{49, 49}, cv::Rect{0, 11, 49, 15})
+ ,std::make_tuple(cv::Size{64, 64},
+ cv::Size{49, 49}, cv::Rect{0, 39, 49, 10})
+ ,std::make_tuple(cv::Size{1920, 1080},
+ cv::Size{ 320, 256}, cv::Rect{0, 0, 320, 64})
+ ,std::make_tuple(cv::Size{1920, 1080},
+ cv::Size{ 320, 256}, cv::Rect{0, 64, 320, 64})
+ ,std::make_tuple(cv::Size{1920, 1080},
+ cv::Size{ 320, 256}, cv::Rect{0, 128, 320, 64})
+ ,std::make_tuple(cv::Size{1920, 1080},
+ cv::Size{ 320, 256}, cv::Rect{0, 192, 320, 64})
+ ,std::make_tuple(cv::Size{256, 400},
+ cv::Size{ 32, 64}, cv::Rect{0, 0, 32, 16})
+ ,std::make_tuple(cv::Size{256, 400},
+ cv::Size{ 32, 64}, cv::Rect{0, 16, 32, 16})
+ ,std::make_tuple(cv::Size{256, 400},
+ cv::Size{ 32, 64}, cv::Rect{0, 32, 32, 16})
+ ,std::make_tuple(cv::Size{256, 400},
+ cv::Size{ 32, 64}, cv::Rect{0, 48, 32, 16})
+ ));
+
} // namespace opencv_test
EXPECT_EQ(0, countNonZero(in_mat2 != out_mat2));
}
+struct NV12RoiTest : public TestWithParam <std::pair<cv::Size, cv::Rect>> {};
+TEST_P(NV12RoiTest, Test)
+{
+ cv::Size y_sz;
+ cv::Rect roi;
+ std::tie(y_sz, roi) = GetParam();
+
+ cv::Size uv_sz(y_sz.width / 2, y_sz.height / 2);
+ cv::Size in_sz(y_sz.width, y_sz.height*3/2);
+
+ cv::Mat in_mat = cv::Mat(in_sz, CV_8UC1);
+
+ cv::Scalar mean = cv::Scalar(127.0f);
+ cv::Scalar stddev = cv::Scalar(40.f);
+ cv::randn(in_mat, mean, stddev);
+
+ cv::Mat y_mat = cv::Mat(y_sz, CV_8UC1, in_mat.data);
+ cv::Mat uv_mat = cv::Mat(uv_sz, CV_8UC2, in_mat.data + in_mat.step1() * y_sz.height);
+ cv::Mat out_mat, out_mat_ocv;
+
+ cv::GMat y, uv;
+ auto rgb = cv::gapi::NV12toRGB(y, uv);
+ cv::GComputation c(cv::GIn(y, uv), cv::GOut(rgb));
+
+ c.apply(cv::gin(y_mat, uv_mat), cv::gout(out_mat), cv::compile_args(fluidTestPackage, cv::GFluidOutputRois{{to_own(roi)}}));
+
+ cv::cvtColor(in_mat, out_mat_ocv, cv::COLOR_YUV2RGB_NV12);
+
+ EXPECT_EQ(0, cv::countNonZero(out_mat(roi) != out_mat_ocv(roi)));
+}
+
+INSTANTIATE_TEST_CASE_P(Fluid, NV12RoiTest,
+ Values(std::make_pair(cv::Size{8, 8}, cv::Rect{0, 0, 8, 2})
+ ,std::make_pair(cv::Size{8, 8}, cv::Rect{0, 2, 8, 2})
+ ,std::make_pair(cv::Size{8, 8}, cv::Rect{0, 4, 8, 2})
+ ,std::make_pair(cv::Size{8, 8}, cv::Rect{0, 6, 8, 2})
+ ,std::make_pair(cv::Size{1920, 1080}, cv::Rect{0, 0, 1920, 270})
+ ,std::make_pair(cv::Size{1920, 1080}, cv::Rect{0, 270, 1920, 270})
+ ,std::make_pair(cv::Size{1920, 1080}, cv::Rect{0, 540, 1920, 270})
+ ,std::make_pair(cv::Size{1920, 1080}, cv::Rect{0, 710, 1920, 270})
+ ));
+
+TEST(Fluid, UnusedNodeTest) {
+ cv::GMat in;
+ cv::GMat a, b, c, d;
+ std::tie(a, b, c, d) = cv::gapi::split4(in);
+ cv::GMat out = cv::gapi::merge3(a, b, c);
+
+ cv::Mat in_mat(cv::Size(8, 8), CV_8UC4);
+ cv::Mat out_mat(cv::Size(8, 8), CV_8UC3);
+
+ cv::GComputation comp(cv::GIn(in), cv::GOut(out));
+
+ ASSERT_NO_THROW(comp.apply(cv::gin(in_mat), cv::gout(out_mat),
+ cv::compile_args(cv::gapi::core::fluid::kernels())));
+}
+
} // namespace opencv_test
}
};
+static const int ITUR_BT_601_CY = 1220542;
+static const int ITUR_BT_601_CUB = 2116026;
+static const int ITUR_BT_601_CUG = -409993;
+static const int ITUR_BT_601_CVG = -852492;
+static const int ITUR_BT_601_CVR = 1673527;
+static const int ITUR_BT_601_SHIFT = 20;
+
+static inline void uvToRGBuv(const uchar u, const uchar v, int& ruv, int& guv, int& buv)
+{
+ int uu, vv;
+ uu = int(u) - 128;
+ vv = int(v) - 128;
+
+ ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * vv;
+ guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * vv + ITUR_BT_601_CUG * uu;
+ buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * uu;
+}
+
+static inline void yRGBuvToRGB(const uchar vy, const int ruv, const int guv, const int buv,
+ uchar& r, uchar& g, uchar& b)
+{
+ int y = std::max(0, vy - 16) * ITUR_BT_601_CY;
+ r = saturate_cast<uchar>((y + ruv) >> ITUR_BT_601_SHIFT);
+ g = saturate_cast<uchar>((y + guv) >> ITUR_BT_601_SHIFT);
+ b = saturate_cast<uchar>((y + buv) >> ITUR_BT_601_SHIFT);
+}
+
+GAPI_FLUID_KERNEL(FNV12toRGB, cv::gapi::imgproc::GNV12toRGB, false)
+{
+ static const int Window = 1;
+ static const int LPI = 2;
+ static const auto Kind = GFluidKernel::Kind::NV12toRGB;
+
+ static void run(const cv::gapi::fluid::View &in1,
+ const cv::gapi::fluid::View &in2,
+ cv::gapi::fluid::Buffer &out)
+ {
+ const auto w = out.length();
+
+ GAPI_Assert(w % 2 == 0);
+ GAPI_Assert(out.lpi() == 2);
+
+ const uchar* uv_row = in2.InLineB(0);
+ const uchar* y_rows[] = {in1. InLineB(0), in1. InLineB(1)};
+ uchar* out_rows[] = {out.OutLineB(0), out.OutLineB(1)};
+
+ for (int i = 0; i < w/2; i++)
+ {
+ uchar u = uv_row[2*i];
+ uchar v = uv_row[2*i + 1];
+ int ruv, guv, buv;
+ uvToRGBuv(u, v, ruv, guv, buv);
+
+ for (int y = 0; y < 2; y++)
+ {
+ for (int x = 0; x < 2; x++)
+ {
+ uchar vy = y_rows[y][2*i + x];
+ uchar r, g, b;
+ yRGBuvToRGB(vy, ruv, guv, buv, r, g, b);
+
+ out_rows[y][3*(2*i + x)] = r;
+ out_rows[y][3*(2*i + x) + 1] = g;
+ out_rows[y][3*(2*i + x) + 2] = b;
+ }
+ }
+ }
+ }
+};
+
cv::gapi::GKernelPackage fluidTestPackage = cv::gapi::kernels
<FAddSimple
,FAddCSimple
,FBlur5x5_2lpi
,FIdentity
,FId7x7
+ ,FNV12toRGB
,FPlusRow0
,FSum2MatsAndScalar
,FTestSplit3
float dx;//spacing letter in Qt (0 default) in pixel
int line_type;//<- pointSize in Qt
*/
- CvFont f = {nameFont,color,style,NULL,NULL,NULL,0,0,0,weight,spacing,pointSize};
+ CvFont f = {nameFont,color,style,NULL,NULL,NULL,0,0,0,weight, (float)spacing, pointSize};
return f;
}
CVWindow *window = cvGetWindow(name);
if(window && ![window autosize]) {
height += [window contentView].sliderHeight;
- NSSize size = { width, height };
+ NSSize size = { (CGFloat)width, (CGFloat)height };
[window setContentSize:size];
}
[localpool drain];
if(HAVE_JASPER)
ocv_include_directories(${JASPER_INCLUDE_DIR})
list(APPEND GRFMT_LIBS ${JASPER_LIBRARIES})
+ if(OPENCV_IO_FORCE_JASPER)
+ add_definitions(-DOPENCV_IMGCODECS_FORCE_JASPER=1)
+ endif()
endif()
if(HAVE_OPENEXR)
endif()
ocv_add_accuracy_tests()
+if(TARGET opencv_test_imgcodecs AND HAVE_JASPER AND "$ENV{OPENCV_IO_ENABLE_JASPER}")
+ ocv_target_compile_definitions(opencv_test_imgcodecs PRIVATE OPENCV_IMGCODECS_ENABLE_JASPER_TESTS=1)
+endif()
ocv_add_perf_tests()
IMWRITE_PAM_TUPLETYPE = 128,//!< For PAM, sets the TUPLETYPE field to the corresponding string value that is defined for the format
IMWRITE_TIFF_RESUNIT = 256,//!< For TIFF, use to specify which DPI resolution unit to set; see libtiff documentation for valid values
IMWRITE_TIFF_XDPI = 257,//!< For TIFF, use to specify the X direction DPI
- IMWRITE_TIFF_YDPI = 258 //!< For TIFF, use to specify the Y direction DPI
+ IMWRITE_TIFF_YDPI = 258, //!< For TIFF, use to specify the Y direction DPI
+ IMWRITE_TIFF_COMPRESSION = 259, //!< For TIFF, use to specify the image compression scheme. See libtiff for integer constants corresponding to compression formats. Note, for images whose depth is CV_32F, only libtiff's SGILOG compression scheme is used. For other supported depths, the compression scheme can be specified by this flag; LZW compression is the default.
+ IMWRITE_JPEG2000_COMPRESSION_X1000 = 272 //!< For JPEG2000, use to specify the target compression rate (multiplied by 1000). The value can be from 0 to 1000. Default is 1000.
};
enum ImwriteEXRTypeFlags {
}
int offset = pos % m_block_size;
+ int old_block_pos = m_block_pos;
m_block_pos = pos - offset;
m_current = m_start + offset;
+ if (old_block_pos != m_block_pos)
+ readBlock();
}
int nch = color ? 3 : 1;
int y, width3 = m_width*nch;
+ // FIXIT: use safe pointer arithmetic (avoid 'int'), use size_t, intptr_t, etc
+ CV_Assert(((uint64)m_height * m_width * nch < (CV_BIG_UINT(1) << 30)) && "BMP reader implementation doesn't support large images >= 1Gb");
+
if( m_offset < 0 || !m_strm.isOpened())
return false;
#include "precomp.hpp"
#ifdef HAVE_JASPER
+#include <sstream>
+
+#include <opencv2/core/utils/configuration.private.hpp>
+#include <opencv2/core/utils/logger.hpp>
#include "grfmt_jpeg2000.hpp"
#include "opencv2/imgproc.hpp"
~JasperInitializer() { jas_cleanup(); }
};
-static JasperInitializer initialize_jasper;
+static JasperInitializer& _initJasper()
+{
+ static JasperInitializer initialize_jasper;
+ return initialize_jasper;
+}
+
+static bool isJasperEnabled()
+{
+ static const bool PARAM_ENABLE_JASPER = utils::getConfigurationParameterBool("OPENCV_IO_ENABLE_JASPER",
+#ifdef OPENCV_IMGCODECS_FORCE_JASPER
+ true
+#else
+ false
+#endif
+ );
+ return PARAM_ENABLE_JASPER;
+}
+static JasperInitializer& initJasper()
+{
+ if (isJasperEnabled())
+ {
+ return _initJasper();
+ }
+ else
+ {
+ const char* message = "imgcodecs: Jasper (JPEG-2000) codec is disabled. You can enable it via 'OPENCV_IO_ENABLE_JASPER' option. Refer for details and cautions here: https://github.com/opencv/opencv/issues/14058";
+ CV_LOG_WARNING(NULL, message);
+ CV_Error(Error::StsNotImplemented, message);
+ }
+}
/////////////////////// Jpeg2KDecoder ///////////////////
ImageDecoder Jpeg2KDecoder::newDecoder() const
{
+ initJasper();
return makePtr<Jpeg2KDecoder>();
}
{
if( m_stream )
{
+ CV_Assert(isJasperEnabled());
jas_stream_close( (jas_stream_t*)m_stream );
m_stream = 0;
}
if( m_image )
{
+ CV_Assert(isJasperEnabled());
jas_image_destroy( (jas_image_t*)m_image );
m_image = 0;
}
bool Jpeg2KDecoder::readHeader()
{
+ CV_Assert(isJasperEnabled());
bool result = false;
close();
bool Jpeg2KDecoder::readData( Mat& img )
{
+ CV_Assert(isJasperEnabled());
+
Ptr<Jpeg2KDecoder> close_this(this, Jpeg2KDecoder_close);
bool result = false;
bool color = img.channels() > 1;
int step, int cmpt,
int maxval, int offset, int ncmpts )
{
+ CV_Assert(isJasperEnabled());
+
jas_matrix_t* buffer = (jas_matrix_t*)_buffer;
jas_image_t* image = (jas_image_t*)m_image;
int xstart = jas_image_cmpttlx( image, cmpt );
int step, int cmpt,
int maxval, int offset, int ncmpts )
{
+ CV_Assert(isJasperEnabled());
+
jas_matrix_t* buffer = (jas_matrix_t*)_buffer;
jas_image_t* image = (jas_image_t*)m_image;
int xstart = jas_image_cmpttlx( image, cmpt );
ImageEncoder Jpeg2KEncoder::newEncoder() const
{
+ initJasper();
return makePtr<Jpeg2KEncoder>();
}
}
-bool Jpeg2KEncoder::write( const Mat& _img, const std::vector<int>& )
+bool Jpeg2KEncoder::write( const Mat& _img, const std::vector<int>& params )
{
+ CV_Assert(isJasperEnabled());
int width = _img.cols, height = _img.rows;
int depth = _img.depth(), channels = _img.channels();
depth = depth == CV_8U ? 8 : 16;
if( channels > 3 || channels < 1 )
return false;
+ CV_Assert(params.size() % 2 == 0);
+ double target_compression_rate = 1.0;
+ for( size_t i = 0; i < params.size(); i += 2 )
+ {
+ switch(params[i])
+ {
+ case cv::IMWRITE_JPEG2000_COMPRESSION_X1000:
+ target_compression_rate = std::min(std::max(params[i+1], 0), 1000) / 1000.0;
+ break;
+ }
+ }
+
jas_image_cmptparm_t component_info[3];
for( int i = 0; i < channels; i++ )
{
jas_stream_t *stream = jas_stream_fopen( m_filename.c_str(), "wb" );
if( stream )
{
- result = !jas_image_encode( img, stream, jas_image_strtofmt( (char*)"jp2" ), (char*)"" );
+ std::stringstream options;
+ options << "rate=" << target_compression_rate;
+
+ result = !jas_image_encode( img, stream, jas_image_strtofmt( (char*)"jp2" ), (char*)options.str().c_str() );
jas_stream_close( stream );
}
bool Jpeg2KEncoder::writeComponent8u( void *__img, const Mat& _img )
{
+ CV_Assert(isJasperEnabled());
+
jas_image_t* img = (jas_image_t*)__img;
int w = _img.cols, h = _img.rows, ncmpts = _img.channels();
jas_matrix_t *row = jas_matrix_create( 1, w );
bool Jpeg2KEncoder::writeComponent16u( void *__img, const Mat& _img )
{
+ CV_Assert(isJasperEnabled());
+
jas_image_t* img = (jas_image_t*)__img;
int w = _img.cols, h = _img.rows, ncmpts = _img.channels();
jas_matrix_t *row = jas_matrix_create( 1, w );
m_width = m_strm.getDWord();
m_height = m_strm.getDWord();
m_bpp = m_strm.getDWord();
- int palSize = 3*(1 << m_bpp);
+ int palSize = (m_bpp > 0 && m_bpp <= 8) ? (3*(1 << m_bpp)) : 0;
m_strm.skip( 4 );
m_encoding = (SunRasType)m_strm.getDWord();
&TiffDecoderBufHelper::write, &TiffDecoderBufHelper::seek,
&TiffDecoderBufHelper::close, &TiffDecoderBufHelper::size,
&TiffDecoderBufHelper::map, /*unmap=*/0 );
+ if (!tif)
+ delete buf_helper;
}
else
{
}
//Settings that matter to all images
- // defaults for now, maybe base them on params in the future
int compression = COMPRESSION_LZW;
int predictor = PREDICTOR_HORIZONTAL;
int resUnit = -1, dpiX = -1, dpiY = -1;
- readParam(params, TIFFTAG_COMPRESSION, compression);
+ readParam(params, IMWRITE_TIFF_COMPRESSION, compression);
readParam(params, TIFFTAG_PREDICTOR, predictor);
readParam(params, IMWRITE_TIFF_RESUNIT, resUnit);
readParam(params, IMWRITE_TIFF_XDPI, dpiX);
const string all_images[] =
{
-#ifdef HAVE_JASPER
+#if defined(HAVE_JASPER) && defined(OPENCV_IMGCODECS_ENABLE_JASPER_TESTS)
"readwrite/Rome.jp2",
"readwrite/Bretagne2.jp2",
"readwrite/Bretagne2.jp2",
#ifdef HAVE_JPEG
"jpg",
#endif
-#ifdef HAVE_JASPER
+#if defined(HAVE_JASPER) && defined(OPENCV_IMGCODECS_ENABLE_JASPER_TESTS)
"jp2",
#endif
#if 0 /*defined HAVE_OPENEXR && !defined __APPLE__*/
// Write sample TIFF file
FILE* fp = fopen(filename.c_str(), "wb");
ASSERT_TRUE(fp != NULL);
- ASSERT_EQ((size_t)1, fwrite(tiff_sample_data, 86, 1, fp));
+ ASSERT_EQ((size_t)1, fwrite(tiff_sample_data[i], 86, 1, fp));
fclose(fp);
Mat img = imread(filename, IMREAD_UNCHANGED);
set(the_description "Image Processing")
ocv_add_dispatched_file(accum SSE4_1 AVX AVX2)
+ocv_add_dispatched_file(bilateral_filter SSE2 AVX2)
+ocv_add_dispatched_file(box_filter SSE2 SSE4_1 AVX2)
+ocv_add_dispatched_file(filter SSE2 SSE4_1 AVX2)
+ocv_add_dispatched_file(color_hsv SSE2 SSE4_1 AVX2)
+ocv_add_dispatched_file(color_rgb SSE2 SSE4_1 AVX2)
+ocv_add_dispatched_file(color_yuv SSE2 SSE4_1 AVX2)
+ocv_add_dispatched_file(median_blur SSE2 SSE4_1 AVX2)
+ocv_add_dispatched_file(morph SSE2 SSE4_1 AVX2)
+ocv_add_dispatched_file(smooth SSE2 SSE4_1 AVX2)
ocv_define_module(imgproc opencv_core WRAP java python js)
//! @addtogroup imgproc_feature
//! @{
-/** @example samples/cpp/lsd_lines.cpp
-An example using the LineSegmentDetector
-\image html building_lsd.png "Sample output image" width=434 height=300
-*/
-
/** @brief Line segment detector class
following the algorithm described at @cite Rafael12 .
+
+@note Implementation has been removed due original code license conflict
+
*/
class CV_EXPORTS_W LineSegmentDetector : public Algorithm
{
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,
SANITY_CHECK(dst, 1);
}
-PERF_TEST_P(TestFilter2d, Filter2d_ovx,
+PERF_TEST_P(TestFilter2d, DISABLED_Filter2d_ovx,
Combine(
Values(Size(320, 240), sz1080p),
Values(3, 5),
PERF_TEST_P(Size_MatType_OutMatDepth, integral,
testing::Combine(
testing::Values(TYPICAL_MAT_SIZES),
- testing::Values(CV_8UC1, CV_8UC3, CV_8UC4),
+ testing::Values(CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4),
testing::Values(CV_32S, CV_32F, CV_64F)
)
)
PERF_TEST_P(Size_MatType_OutMatDepth, integral_sqsum,
testing::Combine(
- testing::Values(::perf::szVGA, ::perf::sz1080p),
- testing::Values(CV_8UC1, CV_8UC4),
- testing::Values(CV_32S, CV_32F)
+ testing::Values(TYPICAL_MAT_SIZES),
+ testing::Values(CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4),
+ testing::Values(CV_32S, CV_32F, CV_64F)
)
)
{
PERF_TEST_P( Size_MatType_OutMatDepth, integral_sqsum_tilted,
testing::Combine(
- testing::Values( ::perf::szVGA, ::perf::szODD , ::perf::sz1080p ),
- testing::Values( CV_8UC1, CV_8UC4 ),
- testing::Values( CV_32S, CV_32F )
+ testing::Values(TYPICAL_MAT_SIZES),
+ testing::Values( CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4 ),
+ testing::Values( CV_32S, CV_32F, CV_64F )
)
)
{
SANITY_CHECK(dst, eps, error_type);
}
-PERF_TEST_P(Size_MatType, pyrDown_ovx, testing::Combine(
+PERF_TEST_P(Size_MatType, DISABLED_pyrDown_ovx, testing::Combine(
testing::Values(sz1080p, sz720p, szVGA, szQVGA, szODD),
testing::Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_16SC1, CV_16SC3, CV_16SC4, CV_32FC1, CV_32FC3, CV_32FC4)
)
#endif
}
-PERF_TEST_P(TestWarpAffine, WarpAffine_ovx,
+PERF_TEST_P(TestWarpAffine, DISABLED_WarpAffine_ovx,
Combine(
Values(szVGA, sz720p, sz1080p),
InterType::all(),
#endif
}
-PERF_TEST_P(TestWarpPerspective, WarpPerspective_ovx,
+PERF_TEST_P(TestWarpPerspective, DISABLED_WarpPerspective_ovx,
Combine(
Values(szVGA, sz720p, sz1080p),
InterType::all(),
--- /dev/null
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, 2018, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Copyright (C) 2014-2015, Itseez Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "precomp.hpp"
+
+#include <vector>
+
+#include "opencv2/core/hal/intrin.hpp"
+#include "opencl_kernels_imgproc.hpp"
+
+#include "bilateral_filter.simd.hpp"
+#include "bilateral_filter.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
+
+/****************************************************************************************\
+ Bilateral Filtering
+\****************************************************************************************/
+
+namespace cv {
+
+#ifdef HAVE_OPENCL
+
+static bool ocl_bilateralFilter_8u(InputArray _src, OutputArray _dst, int d,
+ double sigma_color, double sigma_space,
+ int borderType)
+{
+ CV_INSTRUMENT_REGION();
+#ifdef __ANDROID__
+ if (ocl::Device::getDefault().isNVidia())
+ return false;
+#endif
+
+ int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
+ int i, j, maxk, radius;
+
+ if (depth != CV_8U || cn > 4)
+ return false;
+
+ if (sigma_color <= 0)
+ sigma_color = 1;
+ if (sigma_space <= 0)
+ sigma_space = 1;
+
+ double gauss_color_coeff = -0.5 / (sigma_color * sigma_color);
+ double gauss_space_coeff = -0.5 / (sigma_space * sigma_space);
+
+ if ( d <= 0 )
+ radius = cvRound(sigma_space * 1.5);
+ else
+ radius = d / 2;
+ radius = MAX(radius, 1);
+ d = radius * 2 + 1;
+
+ UMat src = _src.getUMat(), dst = _dst.getUMat(), temp;
+ if (src.u == dst.u)
+ return false;
+
+ copyMakeBorder(src, temp, radius, radius, radius, radius, borderType);
+ std::vector<float> _space_weight(d * d);
+ std::vector<int> _space_ofs(d * d);
+ float * const space_weight = &_space_weight[0];
+ int * const space_ofs = &_space_ofs[0];
+
+ // initialize space-related bilateral filter coefficients
+ for( i = -radius, maxk = 0; i <= radius; i++ )
+ for( j = -radius; j <= radius; j++ )
+ {
+ double r = std::sqrt((double)i * i + (double)j * j);
+ if ( r > radius )
+ continue;
+ space_weight[maxk] = (float)std::exp(r * r * gauss_space_coeff);
+ space_ofs[maxk++] = (int)(i * temp.step + j * cn);
+ }
+
+ char cvt[3][40];
+ String cnstr = cn > 1 ? format("%d", cn) : "";
+ String kernelName("bilateral");
+ size_t sizeDiv = 1;
+ if ((ocl::Device::getDefault().isIntel()) &&
+ (ocl::Device::getDefault().type() == ocl::Device::TYPE_GPU))
+ {
+ //Intel GPU
+ if (dst.cols % 4 == 0 && cn == 1) // For single channel x4 sized images.
+ {
+ kernelName = "bilateral_float4";
+ sizeDiv = 4;
+ }
+ }
+ ocl::Kernel k(kernelName.c_str(), ocl::imgproc::bilateral_oclsrc,
+ format("-D radius=%d -D maxk=%d -D cn=%d -D int_t=%s -D uint_t=uint%s -D convert_int_t=%s"
+ " -D uchar_t=%s -D float_t=%s -D convert_float_t=%s -D convert_uchar_t=%s -D gauss_color_coeff=(float)%f",
+ radius, maxk, cn, ocl::typeToStr(CV_32SC(cn)), cnstr.c_str(),
+ ocl::convertTypeStr(CV_8U, CV_32S, cn, cvt[0]),
+ ocl::typeToStr(type), ocl::typeToStr(CV_32FC(cn)),
+ ocl::convertTypeStr(CV_32S, CV_32F, cn, cvt[1]),
+ ocl::convertTypeStr(CV_32F, CV_8U, cn, cvt[2]), gauss_color_coeff));
+ if (k.empty())
+ return false;
+
+ Mat mspace_weight(1, d * d, CV_32FC1, space_weight);
+ Mat mspace_ofs(1, d * d, CV_32SC1, space_ofs);
+ UMat ucolor_weight, uspace_weight, uspace_ofs;
+
+ mspace_weight.copyTo(uspace_weight);
+ mspace_ofs.copyTo(uspace_ofs);
+
+ k.args(ocl::KernelArg::ReadOnlyNoSize(temp), ocl::KernelArg::WriteOnly(dst),
+ ocl::KernelArg::PtrReadOnly(uspace_weight),
+ ocl::KernelArg::PtrReadOnly(uspace_ofs));
+
+ size_t globalsize[2] = { (size_t)dst.cols / sizeDiv, (size_t)dst.rows };
+ return k.run(2, globalsize, NULL, false);
+}
+#endif
+
+
+static void
+bilateralFilter_8u( const Mat& src, Mat& dst, int d,
+ double sigma_color, double sigma_space,
+ int borderType )
+{
+ CV_INSTRUMENT_REGION();
+
+ int cn = src.channels();
+ int i, j, maxk, radius;
+
+ CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_8UC3) && src.data != dst.data );
+
+ if( sigma_color <= 0 )
+ sigma_color = 1;
+ if( sigma_space <= 0 )
+ sigma_space = 1;
+
+ double gauss_color_coeff = -0.5/(sigma_color*sigma_color);
+ double gauss_space_coeff = -0.5/(sigma_space*sigma_space);
+
+ if( d <= 0 )
+ radius = cvRound(sigma_space*1.5);
+ else
+ radius = d/2;
+ radius = MAX(radius, 1);
+ d = radius*2 + 1;
+
+ Mat temp;
+ copyMakeBorder( src, temp, radius, radius, radius, radius, borderType );
+
+ std::vector<float> _color_weight(cn*256);
+ std::vector<float> _space_weight(d*d);
+ std::vector<int> _space_ofs(d*d);
+ float* color_weight = &_color_weight[0];
+ float* space_weight = &_space_weight[0];
+ int* space_ofs = &_space_ofs[0];
+
+ // initialize color-related bilateral filter coefficients
+
+ for( i = 0; i < 256*cn; i++ )
+ color_weight[i] = (float)std::exp(i*i*gauss_color_coeff);
+
+ // initialize space-related bilateral filter coefficients
+ for( i = -radius, maxk = 0; i <= radius; i++ )
+ {
+ j = -radius;
+
+ for( ; j <= radius; j++ )
+ {
+ double r = std::sqrt((double)i*i + (double)j*j);
+ if( r > radius )
+ continue;
+ space_weight[maxk] = (float)std::exp(r*r*gauss_space_coeff);
+ space_ofs[maxk++] = (int)(i*temp.step + j*cn);
+ }
+ }
+
+ CV_CPU_DISPATCH(bilateralFilterInvoker_8u, (dst, temp, radius, maxk, space_ofs, space_weight, color_weight),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+
+static void
+bilateralFilter_32f( const Mat& src, Mat& dst, int d,
+ double sigma_color, double sigma_space,
+ int borderType )
+{
+ CV_INSTRUMENT_REGION();
+
+ int cn = src.channels();
+ int i, j, maxk, radius;
+ double minValSrc=-1, maxValSrc=1;
+ const int kExpNumBinsPerChannel = 1 << 12;
+ int kExpNumBins = 0;
+ float lastExpVal = 1.f;
+ float len, scale_index;
+
+ CV_Assert( (src.type() == CV_32FC1 || src.type() == CV_32FC3) && src.data != dst.data );
+
+ if( sigma_color <= 0 )
+ sigma_color = 1;
+ if( sigma_space <= 0 )
+ sigma_space = 1;
+
+ double gauss_color_coeff = -0.5/(sigma_color*sigma_color);
+ double gauss_space_coeff = -0.5/(sigma_space*sigma_space);
+
+ if( d <= 0 )
+ radius = cvRound(sigma_space*1.5);
+ else
+ radius = d/2;
+ radius = MAX(radius, 1);
+ d = radius*2 + 1;
+ // compute the min/max range for the input image (even if multichannel)
+
+ minMaxLoc( src.reshape(1), &minValSrc, &maxValSrc );
+ if(std::abs(minValSrc - maxValSrc) < FLT_EPSILON)
+ {
+ src.copyTo(dst);
+ return;
+ }
+
+ // temporary copy of the image with borders for easy processing
+ Mat temp;
+ copyMakeBorder( src, temp, radius, radius, radius, radius, borderType );
+
+ // allocate lookup tables
+ std::vector<float> _space_weight(d*d);
+ std::vector<int> _space_ofs(d*d);
+ float* space_weight = &_space_weight[0];
+ int* space_ofs = &_space_ofs[0];
+
+ // assign a length which is slightly more than needed
+ len = (float)(maxValSrc - minValSrc) * cn;
+ kExpNumBins = kExpNumBinsPerChannel * cn;
+ std::vector<float> _expLUT(kExpNumBins+2);
+ float* expLUT = &_expLUT[0];
+
+ scale_index = kExpNumBins/len;
+
+ // initialize the exp LUT
+ for( i = 0; i < kExpNumBins+2; i++ )
+ {
+ if( lastExpVal > 0.f )
+ {
+ double val = i / scale_index;
+ expLUT[i] = (float)std::exp(val * val * gauss_color_coeff);
+ lastExpVal = expLUT[i];
+ }
+ else
+ expLUT[i] = 0.f;
+ }
+
+ // initialize space-related bilateral filter coefficients
+ for( i = -radius, maxk = 0; i <= radius; i++ )
+ for( j = -radius; j <= radius; j++ )
+ {
+ double r = std::sqrt((double)i*i + (double)j*j);
+ if( r > radius || ( i == 0 && j == 0 ) )
+ continue;
+ space_weight[maxk] = (float)std::exp(r*r*gauss_space_coeff);
+ space_ofs[maxk++] = (int)(i*(temp.step/sizeof(float)) + j*cn);
+ }
+
+ // parallel_for usage
+ CV_CPU_DISPATCH(bilateralFilterInvoker_32f, (cn, radius, maxk, space_ofs, temp, dst, scale_index, space_weight, expLUT),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+#ifdef HAVE_IPP
+#define IPP_BILATERAL_PARALLEL 1
+
+#ifdef HAVE_IPP_IW
+class ipp_bilateralFilterParallel: public ParallelLoopBody
+{
+public:
+ ipp_bilateralFilterParallel(::ipp::IwiImage &_src, ::ipp::IwiImage &_dst, int _radius, Ipp32f _valSquareSigma, Ipp32f _posSquareSigma, ::ipp::IwiBorderType _borderType, bool *_ok):
+ src(_src), dst(_dst)
+ {
+ pOk = _ok;
+
+ radius = _radius;
+ valSquareSigma = _valSquareSigma;
+ posSquareSigma = _posSquareSigma;
+ borderType = _borderType;
+
+ *pOk = true;
+ }
+ ~ipp_bilateralFilterParallel() {}
+
+ virtual void operator() (const Range& range) const CV_OVERRIDE
+ {
+ if(*pOk == false)
+ return;
+
+ try
+ {
+ ::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, dst.m_size.width, range.end - range.start);
+ CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBilateral, src, dst, radius, valSquareSigma, posSquareSigma, ::ipp::IwDefault(), borderType, tile);
+ }
+ catch(const ::ipp::IwException &)
+ {
+ *pOk = false;
+ return;
+ }
+ }
+private:
+ ::ipp::IwiImage &src;
+ ::ipp::IwiImage &dst;
+
+ int radius;
+ Ipp32f valSquareSigma;
+ Ipp32f posSquareSigma;
+ ::ipp::IwiBorderType borderType;
+
+ bool *pOk;
+ const ipp_bilateralFilterParallel& operator= (const ipp_bilateralFilterParallel&);
+};
+#endif
+
+static bool ipp_bilateralFilter(Mat &src, Mat &dst, int d, double sigmaColor, double sigmaSpace, int borderType)
+{
+#ifdef HAVE_IPP_IW
+ CV_INSTRUMENT_REGION_IPP();
+
+ int radius = IPP_MAX(((d <= 0)?cvRound(sigmaSpace*1.5):d/2), 1);
+ Ipp32f valSquareSigma = (Ipp32f)((sigmaColor <= 0)?1:sigmaColor*sigmaColor);
+ Ipp32f posSquareSigma = (Ipp32f)((sigmaSpace <= 0)?1:sigmaSpace*sigmaSpace);
+
+ // Acquire data and begin processing
+ try
+ {
+ ::ipp::IwiImage iwSrc = ippiGetImage(src);
+ ::ipp::IwiImage iwDst = ippiGetImage(dst);
+ ::ipp::IwiBorderSize borderSize(radius);
+ ::ipp::IwiBorderType ippBorder(ippiGetBorder(iwSrc, borderType, borderSize));
+ if(!ippBorder)
+ return false;
+
+ const int threads = ippiSuggestThreadsNum(iwDst, 2);
+ if(IPP_BILATERAL_PARALLEL && threads > 1) {
+ bool ok = true;
+ Range range(0, (int)iwDst.m_size.height);
+ ipp_bilateralFilterParallel invoker(iwSrc, iwDst, radius, valSquareSigma, posSquareSigma, ippBorder, &ok);
+ if(!ok)
+ return false;
+
+ parallel_for_(range, invoker, threads*4);
+
+ if(!ok)
+ return false;
+ } else {
+ CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBilateral, iwSrc, iwDst, radius, valSquareSigma, posSquareSigma, ::ipp::IwDefault(), ippBorder);
+ }
+ }
+ catch (const ::ipp::IwException &)
+ {
+ return false;
+ }
+ return true;
+#else
+ CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(d); CV_UNUSED(sigmaColor); CV_UNUSED(sigmaSpace); CV_UNUSED(borderType);
+ return false;
+#endif
+}
+#endif
+
+void bilateralFilter( InputArray _src, OutputArray _dst, int d,
+ double sigmaColor, double sigmaSpace,
+ int borderType )
+{
+ CV_INSTRUMENT_REGION();
+
+ _dst.create( _src.size(), _src.type() );
+
+ CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
+ ocl_bilateralFilter_8u(_src, _dst, d, sigmaColor, sigmaSpace, borderType))
+
+ Mat src = _src.getMat(), dst = _dst.getMat();
+
+ CV_IPP_RUN_FAST(ipp_bilateralFilter(src, dst, d, sigmaColor, sigmaSpace, borderType));
+
+ if( src.depth() == CV_8U )
+ bilateralFilter_8u( src, dst, d, sigmaColor, sigmaSpace, borderType );
+ else if( src.depth() == CV_32F )
+ bilateralFilter_32f( src, dst, d, sigmaColor, sigmaSpace, borderType );
+ else
+ CV_Error( CV_StsUnsupportedFormat,
+ "Bilateral filtering is only implemented for 8u and 32f images" );
+}
+
+} // namespace
#include "precomp.hpp"
-#include <vector>
-
#include "opencv2/core/hal/intrin.hpp"
-#include "opencl_kernels_imgproc.hpp"
/****************************************************************************************\
Bilateral Filtering
\****************************************************************************************/
-namespace cv
-{
+namespace cv {
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+// forward declarations
+void bilateralFilterInvoker_8u(
+ Mat& dst, const Mat& temp, int radius, int maxk,
+ int* space_ofs, float *space_weight, float *color_weight);
+void bilateralFilterInvoker_32f(
+ int cn, int radius, int maxk, int *space_ofs,
+ const Mat& temp, Mat& dst, float scale_index, float *space_weight, float *expLUT);
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
+
+namespace {
class BilateralFilter_8u_Invoker :
public ParallelLoopBody
{
virtual void operator() (const Range& range) const CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
int i, j, cn = dest->channels(), k;
Size size = dest->size();
float *space_weight, *color_weight;
};
-#ifdef HAVE_OPENCL
-
-static bool ocl_bilateralFilter_8u(InputArray _src, OutputArray _dst, int d,
- double sigma_color, double sigma_space,
- int borderType)
-{
-#ifdef __ANDROID__
- if (ocl::Device::getDefault().isNVidia())
- return false;
-#endif
-
- int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
- int i, j, maxk, radius;
-
- if (depth != CV_8U || cn > 4)
- return false;
-
- if (sigma_color <= 0)
- sigma_color = 1;
- if (sigma_space <= 0)
- sigma_space = 1;
-
- double gauss_color_coeff = -0.5 / (sigma_color * sigma_color);
- double gauss_space_coeff = -0.5 / (sigma_space * sigma_space);
-
- if ( d <= 0 )
- radius = cvRound(sigma_space * 1.5);
- else
- radius = d / 2;
- radius = MAX(radius, 1);
- d = radius * 2 + 1;
-
- UMat src = _src.getUMat(), dst = _dst.getUMat(), temp;
- if (src.u == dst.u)
- return false;
+} // namespace anon
- copyMakeBorder(src, temp, radius, radius, radius, radius, borderType);
- std::vector<float> _space_weight(d * d);
- std::vector<int> _space_ofs(d * d);
- float * const space_weight = &_space_weight[0];
- int * const space_ofs = &_space_ofs[0];
-
- // initialize space-related bilateral filter coefficients
- for( i = -radius, maxk = 0; i <= radius; i++ )
- for( j = -radius; j <= radius; j++ )
- {
- double r = std::sqrt((double)i * i + (double)j * j);
- if ( r > radius )
- continue;
- space_weight[maxk] = (float)std::exp(r * r * gauss_space_coeff);
- space_ofs[maxk++] = (int)(i * temp.step + j * cn);
- }
-
- char cvt[3][40];
- String cnstr = cn > 1 ? format("%d", cn) : "";
- String kernelName("bilateral");
- size_t sizeDiv = 1;
- if ((ocl::Device::getDefault().isIntel()) &&
- (ocl::Device::getDefault().type() == ocl::Device::TYPE_GPU))
- {
- //Intel GPU
- if (dst.cols % 4 == 0 && cn == 1) // For single channel x4 sized images.
- {
- kernelName = "bilateral_float4";
- sizeDiv = 4;
- }
- }
- ocl::Kernel k(kernelName.c_str(), ocl::imgproc::bilateral_oclsrc,
- format("-D radius=%d -D maxk=%d -D cn=%d -D int_t=%s -D uint_t=uint%s -D convert_int_t=%s"
- " -D uchar_t=%s -D float_t=%s -D convert_float_t=%s -D convert_uchar_t=%s -D gauss_color_coeff=(float)%f",
- radius, maxk, cn, ocl::typeToStr(CV_32SC(cn)), cnstr.c_str(),
- ocl::convertTypeStr(CV_8U, CV_32S, cn, cvt[0]),
- ocl::typeToStr(type), ocl::typeToStr(CV_32FC(cn)),
- ocl::convertTypeStr(CV_32S, CV_32F, cn, cvt[1]),
- ocl::convertTypeStr(CV_32F, CV_8U, cn, cvt[2]), gauss_color_coeff));
- if (k.empty())
- return false;
-
- Mat mspace_weight(1, d * d, CV_32FC1, space_weight);
- Mat mspace_ofs(1, d * d, CV_32SC1, space_ofs);
- UMat ucolor_weight, uspace_weight, uspace_ofs;
-
- mspace_weight.copyTo(uspace_weight);
- mspace_ofs.copyTo(uspace_ofs);
-
- k.args(ocl::KernelArg::ReadOnlyNoSize(temp), ocl::KernelArg::WriteOnly(dst),
- ocl::KernelArg::PtrReadOnly(uspace_weight),
- ocl::KernelArg::PtrReadOnly(uspace_ofs));
-
- size_t globalsize[2] = { (size_t)dst.cols / sizeDiv, (size_t)dst.rows };
- return k.run(2, globalsize, NULL, false);
-}
-
-#endif
-static void
-bilateralFilter_8u( const Mat& src, Mat& dst, int d,
- double sigma_color, double sigma_space,
- int borderType )
+void bilateralFilterInvoker_8u(
+ Mat& dst, const Mat& temp, int radius, int maxk,
+ int* space_ofs, float *space_weight, float *color_weight)
{
- int cn = src.channels();
- int i, j, maxk, radius;
- Size size = src.size();
-
- CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_8UC3) && src.data != dst.data );
-
- if( sigma_color <= 0 )
- sigma_color = 1;
- if( sigma_space <= 0 )
- sigma_space = 1;
-
- double gauss_color_coeff = -0.5/(sigma_color*sigma_color);
- double gauss_space_coeff = -0.5/(sigma_space*sigma_space);
-
- if( d <= 0 )
- radius = cvRound(sigma_space*1.5);
- else
- radius = d/2;
- radius = MAX(radius, 1);
- d = radius*2 + 1;
-
- Mat temp;
- copyMakeBorder( src, temp, radius, radius, radius, radius, borderType );
-
- std::vector<float> _color_weight(cn*256);
- std::vector<float> _space_weight(d*d);
- std::vector<int> _space_ofs(d*d);
- float* color_weight = &_color_weight[0];
- float* space_weight = &_space_weight[0];
- int* space_ofs = &_space_ofs[0];
-
- // initialize color-related bilateral filter coefficients
-
- for( i = 0; i < 256*cn; i++ )
- color_weight[i] = (float)std::exp(i*i*gauss_color_coeff);
-
- // initialize space-related bilateral filter coefficients
- for( i = -radius, maxk = 0; i <= radius; i++ )
- {
- j = -radius;
-
- for( ; j <= radius; j++ )
- {
- double r = std::sqrt((double)i*i + (double)j*j);
- if( r > radius )
- continue;
- space_weight[maxk] = (float)std::exp(r*r*gauss_space_coeff);
- space_ofs[maxk++] = (int)(i*temp.step + j*cn);
- }
- }
-
+ CV_INSTRUMENT_REGION();
BilateralFilter_8u_Invoker body(dst, temp, radius, maxk, space_ofs, space_weight, color_weight);
- parallel_for_(Range(0, size.height), body, dst.total()/(double)(1<<16));
+ parallel_for_(Range(0, dst.rows), body, dst.total()/(double)(1<<16));
}
+namespace {
+
class BilateralFilter_32f_Invoker :
public ParallelLoopBody
{
virtual void operator() (const Range& range) const CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
int i, j, k;
Size size = dest->size();
float scale_index, *space_weight, *expLUT;
};
+} // namespace anon
-static void
-bilateralFilter_32f( const Mat& src, Mat& dst, int d,
- double sigma_color, double sigma_space,
- int borderType )
+void bilateralFilterInvoker_32f(
+ int cn, int radius, int maxk, int *space_ofs,
+ const Mat& temp, Mat& dst, float scale_index, float *space_weight, float *expLUT)
{
- int cn = src.channels();
- int i, j, maxk, radius;
- double minValSrc=-1, maxValSrc=1;
- const int kExpNumBinsPerChannel = 1 << 12;
- int kExpNumBins = 0;
- float lastExpVal = 1.f;
- float len, scale_index;
- Size size = src.size();
-
- CV_Assert( (src.type() == CV_32FC1 || src.type() == CV_32FC3) && src.data != dst.data );
-
- if( sigma_color <= 0 )
- sigma_color = 1;
- if( sigma_space <= 0 )
- sigma_space = 1;
-
- double gauss_color_coeff = -0.5/(sigma_color*sigma_color);
- double gauss_space_coeff = -0.5/(sigma_space*sigma_space);
-
- if( d <= 0 )
- radius = cvRound(sigma_space*1.5);
- else
- radius = d/2;
- radius = MAX(radius, 1);
- d = radius*2 + 1;
- // compute the min/max range for the input image (even if multichannel)
-
- minMaxLoc( src.reshape(1), &minValSrc, &maxValSrc );
- if(std::abs(minValSrc - maxValSrc) < FLT_EPSILON)
- {
- src.copyTo(dst);
- return;
- }
-
- // temporary copy of the image with borders for easy processing
- Mat temp;
- copyMakeBorder( src, temp, radius, radius, radius, radius, borderType );
-
- // allocate lookup tables
- std::vector<float> _space_weight(d*d);
- std::vector<int> _space_ofs(d*d);
- float* space_weight = &_space_weight[0];
- int* space_ofs = &_space_ofs[0];
-
- // assign a length which is slightly more than needed
- len = (float)(maxValSrc - minValSrc) * cn;
- kExpNumBins = kExpNumBinsPerChannel * cn;
- std::vector<float> _expLUT(kExpNumBins+2);
- float* expLUT = &_expLUT[0];
-
- scale_index = kExpNumBins/len;
-
- // initialize the exp LUT
- for( i = 0; i < kExpNumBins+2; i++ )
- {
- if( lastExpVal > 0.f )
- {
- double val = i / scale_index;
- expLUT[i] = (float)std::exp(val * val * gauss_color_coeff);
- lastExpVal = expLUT[i];
- }
- else
- expLUT[i] = 0.f;
- }
-
- // initialize space-related bilateral filter coefficients
- for( i = -radius, maxk = 0; i <= radius; i++ )
- for( j = -radius; j <= radius; j++ )
- {
- double r = std::sqrt((double)i*i + (double)j*j);
- if( r > radius || ( i == 0 && j == 0 ) )
- continue;
- space_weight[maxk] = (float)std::exp(r*r*gauss_space_coeff);
- space_ofs[maxk++] = (int)(i*(temp.step/sizeof(float)) + j*cn);
- }
-
- // parallel_for usage
+ CV_INSTRUMENT_REGION();
BilateralFilter_32f_Invoker body(cn, radius, maxk, space_ofs, temp, dst, scale_index, space_weight, expLUT);
- parallel_for_(Range(0, size.height), body, dst.total()/(double)(1<<16));
+ parallel_for_(Range(0, dst.rows), body, dst.total()/(double)(1<<16));
}
-#ifdef HAVE_IPP
-#define IPP_BILATERAL_PARALLEL 1
-
-#ifdef HAVE_IPP_IW
-class ipp_bilateralFilterParallel: public ParallelLoopBody
-{
-public:
- ipp_bilateralFilterParallel(::ipp::IwiImage &_src, ::ipp::IwiImage &_dst, int _radius, Ipp32f _valSquareSigma, Ipp32f _posSquareSigma, ::ipp::IwiBorderType _borderType, bool *_ok):
- src(_src), dst(_dst)
- {
- pOk = _ok;
-
- radius = _radius;
- valSquareSigma = _valSquareSigma;
- posSquareSigma = _posSquareSigma;
- borderType = _borderType;
-
- *pOk = true;
- }
- ~ipp_bilateralFilterParallel() {}
-
- virtual void operator() (const Range& range) const CV_OVERRIDE
- {
- if(*pOk == false)
- return;
-
- try
- {
- ::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, dst.m_size.width, range.end - range.start);
- CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBilateral, src, dst, radius, valSquareSigma, posSquareSigma, ::ipp::IwDefault(), borderType, tile);
- }
- catch(const ::ipp::IwException &)
- {
- *pOk = false;
- return;
- }
- }
-private:
- ::ipp::IwiImage &src;
- ::ipp::IwiImage &dst;
-
- int radius;
- Ipp32f valSquareSigma;
- Ipp32f posSquareSigma;
- ::ipp::IwiBorderType borderType;
-
- bool *pOk;
- const ipp_bilateralFilterParallel& operator= (const ipp_bilateralFilterParallel&);
-};
#endif
-
-static bool ipp_bilateralFilter(Mat &src, Mat &dst, int d, double sigmaColor, double sigmaSpace, int borderType)
-{
-#ifdef HAVE_IPP_IW
- CV_INSTRUMENT_REGION_IPP();
-
- int radius = IPP_MAX(((d <= 0)?cvRound(sigmaSpace*1.5):d/2), 1);
- Ipp32f valSquareSigma = (Ipp32f)((sigmaColor <= 0)?1:sigmaColor*sigmaColor);
- Ipp32f posSquareSigma = (Ipp32f)((sigmaSpace <= 0)?1:sigmaSpace*sigmaSpace);
-
- // Acquire data and begin processing
- try
- {
- ::ipp::IwiImage iwSrc = ippiGetImage(src);
- ::ipp::IwiImage iwDst = ippiGetImage(dst);
- ::ipp::IwiBorderSize borderSize(radius);
- ::ipp::IwiBorderType ippBorder(ippiGetBorder(iwSrc, borderType, borderSize));
- if(!ippBorder)
- return false;
-
- const int threads = ippiSuggestThreadsNum(iwDst, 2);
- if(IPP_BILATERAL_PARALLEL && threads > 1) {
- bool ok = true;
- Range range(0, (int)iwDst.m_size.height);
- ipp_bilateralFilterParallel invoker(iwSrc, iwDst, radius, valSquareSigma, posSquareSigma, ippBorder, &ok);
- if(!ok)
- return false;
-
- parallel_for_(range, invoker, threads*4);
-
- if(!ok)
- return false;
- } else {
- CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBilateral, iwSrc, iwDst, radius, valSquareSigma, posSquareSigma, ::ipp::IwDefault(), ippBorder);
- }
- }
- catch (const ::ipp::IwException &)
- {
- return false;
- }
- return true;
-#else
- CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(d); CV_UNUSED(sigmaColor); CV_UNUSED(sigmaSpace); CV_UNUSED(borderType);
- return false;
-#endif
-}
-#endif
-
-}
-
-void cv::bilateralFilter( InputArray _src, OutputArray _dst, int d,
- double sigmaColor, double sigmaSpace,
- int borderType )
-{
- CV_INSTRUMENT_REGION();
-
- _dst.create( _src.size(), _src.type() );
-
- CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
- ocl_bilateralFilter_8u(_src, _dst, d, sigmaColor, sigmaSpace, borderType))
-
- Mat src = _src.getMat(), dst = _dst.getMat();
-
- CV_IPP_RUN_FAST(ipp_bilateralFilter(src, dst, d, sigmaColor, sigmaSpace, borderType));
-
- if( src.depth() == CV_8U )
- bilateralFilter_8u( src, dst, d, sigmaColor, sigmaSpace, borderType );
- else if( src.depth() == CV_32F )
- bilateralFilter_32f( src, dst, d, sigmaColor, sigmaSpace, borderType );
- else
- CV_Error( CV_StsUnsupportedFormat,
- "Bilateral filtering is only implemented for 8u and 32f images" );
-}
-
-/* End of file. */
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+} // namespace
--- /dev/null
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, 2018, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Copyright (C) 2014-2015, Itseez Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "precomp.hpp"
+
+#include <vector>
+
+#include "opencv2/core/hal/intrin.hpp"
+#include "opencl_kernels_imgproc.hpp"
+
+#include "opencv2/core/openvx/ovx_defs.hpp"
+
+#include "box_filter.simd.hpp"
+#include "box_filter.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
+
+
+namespace cv {
+
+#ifdef HAVE_OPENCL
+
+static bool ocl_boxFilter3x3_8UC1( InputArray _src, OutputArray _dst, int ddepth,
+ Size ksize, Point anchor, int borderType, bool normalize )
+{
+ const ocl::Device & dev = ocl::Device::getDefault();
+ int type = _src.type(), sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
+
+ if (ddepth < 0)
+ ddepth = sdepth;
+
+ if (anchor.x < 0)
+ anchor.x = ksize.width / 2;
+ if (anchor.y < 0)
+ anchor.y = ksize.height / 2;
+
+ if ( !(dev.isIntel() && (type == CV_8UC1) &&
+ (_src.offset() == 0) && (_src.step() % 4 == 0) &&
+ (_src.cols() % 16 == 0) && (_src.rows() % 2 == 0) &&
+ (anchor.x == 1) && (anchor.y == 1) &&
+ (ksize.width == 3) && (ksize.height == 3)) )
+ return false;
+
+ float alpha = 1.0f / (ksize.height * ksize.width);
+ Size size = _src.size();
+ size_t globalsize[2] = { 0, 0 };
+ size_t localsize[2] = { 0, 0 };
+ const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", 0, "BORDER_REFLECT_101" };
+
+ globalsize[0] = size.width / 16;
+ globalsize[1] = size.height / 2;
+
+ char build_opts[1024];
+ sprintf(build_opts, "-D %s %s", borderMap[borderType], normalize ? "-D NORMALIZE" : "");
+
+ ocl::Kernel kernel("boxFilter3x3_8UC1_cols16_rows2", cv::ocl::imgproc::boxFilter3x3_oclsrc, build_opts);
+ if (kernel.empty())
+ return false;
+
+ UMat src = _src.getUMat();
+ _dst.create(size, CV_MAKETYPE(ddepth, cn));
+ if (!(_dst.offset() == 0 && _dst.step() % 4 == 0))
+ return false;
+ UMat dst = _dst.getUMat();
+
+ int idxArg = kernel.set(0, ocl::KernelArg::PtrReadOnly(src));
+ idxArg = kernel.set(idxArg, (int)src.step);
+ idxArg = kernel.set(idxArg, ocl::KernelArg::PtrWriteOnly(dst));
+ idxArg = kernel.set(idxArg, (int)dst.step);
+ idxArg = kernel.set(idxArg, (int)dst.rows);
+ idxArg = kernel.set(idxArg, (int)dst.cols);
+ if (normalize)
+ idxArg = kernel.set(idxArg, (float)alpha);
+
+ return kernel.run(2, globalsize, (localsize[0] == 0) ? NULL : localsize, false);
+}
+
+static bool ocl_boxFilter( InputArray _src, OutputArray _dst, int ddepth,
+ Size ksize, Point anchor, int borderType, bool normalize, bool sqr = false )
+{
+ const ocl::Device & dev = ocl::Device::getDefault();
+ int type = _src.type(), sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), esz = CV_ELEM_SIZE(type);
+ bool doubleSupport = dev.doubleFPConfig() > 0;
+
+ if (ddepth < 0)
+ ddepth = sdepth;
+
+ if (cn > 4 || (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F)) ||
+ _src.offset() % esz != 0 || _src.step() % esz != 0)
+ return false;
+
+ if (anchor.x < 0)
+ anchor.x = ksize.width / 2;
+ if (anchor.y < 0)
+ anchor.y = ksize.height / 2;
+
+ int computeUnits = ocl::Device::getDefault().maxComputeUnits();
+ float alpha = 1.0f / (ksize.height * ksize.width);
+ Size size = _src.size(), wholeSize;
+ bool isolated = (borderType & BORDER_ISOLATED) != 0;
+ borderType &= ~BORDER_ISOLATED;
+ int wdepth = std::max(CV_32F, std::max(ddepth, sdepth)),
+ wtype = CV_MAKE_TYPE(wdepth, cn), dtype = CV_MAKE_TYPE(ddepth, cn);
+
+ const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", 0, "BORDER_REFLECT_101" };
+ size_t globalsize[2] = { (size_t)size.width, (size_t)size.height };
+ size_t localsize_general[2] = { 0, 1 }, * localsize = NULL;
+
+ UMat src = _src.getUMat();
+ if (!isolated)
+ {
+ Point ofs;
+ src.locateROI(wholeSize, ofs);
+ }
+
+ int h = isolated ? size.height : wholeSize.height;
+ int w = isolated ? size.width : wholeSize.width;
+
+ size_t maxWorkItemSizes[32];
+ ocl::Device::getDefault().maxWorkItemSizes(maxWorkItemSizes);
+ int tryWorkItems = (int)maxWorkItemSizes[0];
+
+ ocl::Kernel kernel;
+
+ if (dev.isIntel() && !(dev.type() & ocl::Device::TYPE_CPU) &&
+ ((ksize.width < 5 && ksize.height < 5 && esz <= 4) ||
+ (ksize.width == 5 && ksize.height == 5 && cn == 1)))
+ {
+ if (w < ksize.width || h < ksize.height)
+ return false;
+
+ // Figure out what vector size to use for loading the pixels.
+ int pxLoadNumPixels = cn != 1 || size.width % 4 ? 1 : 4;
+ int pxLoadVecSize = cn * pxLoadNumPixels;
+
+ // Figure out how many pixels per work item to compute in X and Y
+ // directions. Too many and we run out of registers.
+ int pxPerWorkItemX = 1, pxPerWorkItemY = 1;
+ if (cn <= 2 && ksize.width <= 4 && ksize.height <= 4)
+ {
+ pxPerWorkItemX = size.width % 8 ? size.width % 4 ? size.width % 2 ? 1 : 2 : 4 : 8;
+ pxPerWorkItemY = size.height % 2 ? 1 : 2;
+ }
+ else if (cn < 4 || (ksize.width <= 4 && ksize.height <= 4))
+ {
+ pxPerWorkItemX = size.width % 2 ? 1 : 2;
+ pxPerWorkItemY = size.height % 2 ? 1 : 2;
+ }
+ globalsize[0] = size.width / pxPerWorkItemX;
+ globalsize[1] = size.height / pxPerWorkItemY;
+
+ // Need some padding in the private array for pixels
+ int privDataWidth = roundUp(pxPerWorkItemX + ksize.width - 1, pxLoadNumPixels);
+
+ // Make the global size a nice round number so the runtime can pick
+ // from reasonable choices for the workgroup size
+ const int wgRound = 256;
+ globalsize[0] = roundUp(globalsize[0], wgRound);
+
+ char build_options[1024], cvt[2][40];
+ sprintf(build_options, "-D cn=%d "
+ "-D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d "
+ "-D PX_LOAD_VEC_SIZE=%d -D PX_LOAD_NUM_PX=%d "
+ "-D PX_PER_WI_X=%d -D PX_PER_WI_Y=%d -D PRIV_DATA_WIDTH=%d -D %s -D %s "
+ "-D PX_LOAD_X_ITERATIONS=%d -D PX_LOAD_Y_ITERATIONS=%d "
+ "-D srcT=%s -D srcT1=%s -D dstT=%s -D dstT1=%s -D WT=%s -D WT1=%s "
+ "-D convertToWT=%s -D convertToDstT=%s%s%s -D PX_LOAD_FLOAT_VEC_CONV=convert_%s -D OP_BOX_FILTER",
+ cn, anchor.x, anchor.y, ksize.width, ksize.height,
+ pxLoadVecSize, pxLoadNumPixels,
+ pxPerWorkItemX, pxPerWorkItemY, privDataWidth, borderMap[borderType],
+ isolated ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED",
+ privDataWidth / pxLoadNumPixels, pxPerWorkItemY + ksize.height - 1,
+ ocl::typeToStr(type), ocl::typeToStr(sdepth), ocl::typeToStr(dtype),
+ ocl::typeToStr(ddepth), ocl::typeToStr(wtype), ocl::typeToStr(wdepth),
+ ocl::convertTypeStr(sdepth, wdepth, cn, cvt[0]),
+ ocl::convertTypeStr(wdepth, ddepth, cn, cvt[1]),
+ normalize ? " -D NORMALIZE" : "", sqr ? " -D SQR" : "",
+ ocl::typeToStr(CV_MAKE_TYPE(wdepth, pxLoadVecSize)) //PX_LOAD_FLOAT_VEC_CONV
+ );
+
+
+ if (!kernel.create("filterSmall", cv::ocl::imgproc::filterSmall_oclsrc, build_options))
+ return false;
+ }
+ else
+ {
+ localsize = localsize_general;
+ for ( ; ; )
+ {
+ int BLOCK_SIZE_X = tryWorkItems, BLOCK_SIZE_Y = std::min(ksize.height * 10, size.height);
+
+ while (BLOCK_SIZE_X > 32 && BLOCK_SIZE_X >= ksize.width * 2 && BLOCK_SIZE_X > size.width * 2)
+ BLOCK_SIZE_X /= 2;
+ while (BLOCK_SIZE_Y < BLOCK_SIZE_X / 8 && BLOCK_SIZE_Y * computeUnits * 32 < size.height)
+ BLOCK_SIZE_Y *= 2;
+
+ if (ksize.width > BLOCK_SIZE_X || w < ksize.width || h < ksize.height)
+ return false;
+
+ char cvt[2][50];
+ String opts = format("-D LOCAL_SIZE_X=%d -D BLOCK_SIZE_Y=%d -D ST=%s -D DT=%s -D WT=%s -D convertToDT=%s -D convertToWT=%s"
+ " -D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d -D %s%s%s%s%s"
+ " -D ST1=%s -D DT1=%s -D cn=%d",
+ BLOCK_SIZE_X, BLOCK_SIZE_Y, ocl::typeToStr(type), ocl::typeToStr(CV_MAKE_TYPE(ddepth, cn)),
+ ocl::typeToStr(CV_MAKE_TYPE(wdepth, cn)),
+ ocl::convertTypeStr(wdepth, ddepth, cn, cvt[0]),
+ ocl::convertTypeStr(sdepth, wdepth, cn, cvt[1]),
+ anchor.x, anchor.y, ksize.width, ksize.height, borderMap[borderType],
+ isolated ? " -D BORDER_ISOLATED" : "", doubleSupport ? " -D DOUBLE_SUPPORT" : "",
+ normalize ? " -D NORMALIZE" : "", sqr ? " -D SQR" : "",
+ ocl::typeToStr(sdepth), ocl::typeToStr(ddepth), cn);
+
+ localsize[0] = BLOCK_SIZE_X;
+ globalsize[0] = divUp(size.width, BLOCK_SIZE_X - (ksize.width - 1)) * BLOCK_SIZE_X;
+ globalsize[1] = divUp(size.height, BLOCK_SIZE_Y);
+
+ kernel.create("boxFilter", cv::ocl::imgproc::boxFilter_oclsrc, opts);
+ if (kernel.empty())
+ return false;
+
+ size_t kernelWorkGroupSize = kernel.workGroupSize();
+ if (localsize[0] <= kernelWorkGroupSize)
+ break;
+ if (BLOCK_SIZE_X < (int)kernelWorkGroupSize)
+ return false;
+
+ tryWorkItems = (int)kernelWorkGroupSize;
+ }
+ }
+
+ _dst.create(size, CV_MAKETYPE(ddepth, cn));
+ UMat dst = _dst.getUMat();
+
+ int idxArg = kernel.set(0, ocl::KernelArg::PtrReadOnly(src));
+ idxArg = kernel.set(idxArg, (int)src.step);
+ int srcOffsetX = (int)((src.offset % src.step) / src.elemSize());
+ int srcOffsetY = (int)(src.offset / src.step);
+ int srcEndX = isolated ? srcOffsetX + size.width : wholeSize.width;
+ int srcEndY = isolated ? srcOffsetY + size.height : wholeSize.height;
+ idxArg = kernel.set(idxArg, srcOffsetX);
+ idxArg = kernel.set(idxArg, srcOffsetY);
+ idxArg = kernel.set(idxArg, srcEndX);
+ idxArg = kernel.set(idxArg, srcEndY);
+ idxArg = kernel.set(idxArg, ocl::KernelArg::WriteOnly(dst));
+ if (normalize)
+ idxArg = kernel.set(idxArg, (float)alpha);
+
+ return kernel.run(2, globalsize, localsize, false);
+}
+
+#endif
+
+Ptr<BaseRowFilter> getRowSumFilter(int srcType, int sumType, int ksize, int anchor)
+{
+ CV_INSTRUMENT_REGION();
+
+ CV_CPU_DISPATCH(getRowSumFilter, (srcType, sumType, ksize, anchor),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+
+Ptr<BaseColumnFilter> getColumnSumFilter(int sumType, int dstType, int ksize, int anchor, double scale)
+{
+ CV_INSTRUMENT_REGION();
+
+ CV_CPU_DISPATCH(getColumnSumFilter, (sumType, dstType, ksize, anchor, scale),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+
+Ptr<FilterEngine> createBoxFilter(int srcType, int dstType, Size ksize,
+ Point anchor, bool normalize, int borderType)
+{
+ CV_INSTRUMENT_REGION();
+
+ CV_CPU_DISPATCH(createBoxFilter, (srcType, dstType, ksize, anchor, normalize, borderType),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+#ifdef HAVE_OPENVX
+ namespace ovx {
+ template <> inline bool skipSmallImages<VX_KERNEL_BOX_3x3>(int w, int h) { return w*h < 640 * 480; }
+ }
+ static bool openvx_boxfilter(InputArray _src, OutputArray _dst, int ddepth,
+ Size ksize, Point anchor,
+ bool normalize, int borderType)
+ {
+ if (ddepth < 0)
+ ddepth = CV_8UC1;
+ if (_src.type() != CV_8UC1 || ddepth != CV_8U || !normalize ||
+ _src.cols() < 3 || _src.rows() < 3 ||
+ ksize.width != 3 || ksize.height != 3 ||
+ (anchor.x >= 0 && anchor.x != 1) ||
+ (anchor.y >= 0 && anchor.y != 1) ||
+ ovx::skipSmallImages<VX_KERNEL_BOX_3x3>(_src.cols(), _src.rows()))
+ return false;
+
+ Mat src = _src.getMat();
+
+ if ((borderType & BORDER_ISOLATED) == 0 && src.isSubmatrix())
+ return false; //Process isolated borders only
+ vx_enum border;
+ switch (borderType & ~BORDER_ISOLATED)
+ {
+ case BORDER_CONSTANT:
+ border = VX_BORDER_CONSTANT;
+ break;
+ case BORDER_REPLICATE:
+ border = VX_BORDER_REPLICATE;
+ break;
+ default:
+ return false;
+ }
+
+ _dst.create(src.size(), CV_8UC1);
+ Mat dst = _dst.getMat();
+
+ try
+ {
+ ivx::Context ctx = ovx::getOpenVXContext();
+
+ Mat a;
+ if (dst.data != src.data)
+ a = src;
+ else
+ src.copyTo(a);
+
+ ivx::Image
+ ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,
+ ivx::Image::createAddressing(a.cols, a.rows, 1, (vx_int32)(a.step)), a.data),
+ ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,
+ ivx::Image::createAddressing(dst.cols, dst.rows, 1, (vx_int32)(dst.step)), dst.data);
+
+ //ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments
+ //since OpenVX standard says nothing about thread-safety for now
+ ivx::border_t prevBorder = ctx.immediateBorder();
+ ctx.setImmediateBorder(border, (vx_uint8)(0));
+ ivx::IVX_CHECK_STATUS(vxuBox3x3(ctx, ia, ib));
+ ctx.setImmediateBorder(prevBorder);
+ }
+ catch (const ivx::RuntimeError & e)
+ {
+ VX_DbgThrow(e.what());
+ }
+ catch (const ivx::WrapperError & e)
+ {
+ VX_DbgThrow(e.what());
+ }
+
+ return true;
+ }
+#endif
+
+#if defined(HAVE_IPP)
+static bool ipp_boxfilter(Mat &src, Mat &dst, Size ksize, Point anchor, bool normalize, int borderType)
+{
+#ifdef HAVE_IPP_IW
+ CV_INSTRUMENT_REGION_IPP();
+
+#if IPP_VERSION_X100 < 201801
+ // Problem with SSE42 optimization for 16s and some 8u modes
+ if(ipp::getIppTopFeatures() == ippCPUID_SSE42 && (((src.depth() == CV_16S || src.depth() == CV_16U) && (src.channels() == 3 || src.channels() == 4)) || (src.depth() == CV_8U && src.channels() == 3 && (ksize.width > 5 || ksize.height > 5))))
+ return false;
+
+ // Other optimizations has some degradations too
+ if((((src.depth() == CV_16S || src.depth() == CV_16U) && (src.channels() == 4)) || (src.depth() == CV_8U && src.channels() == 1 && (ksize.width > 5 || ksize.height > 5))))
+ return false;
+#endif
+
+ if(!normalize)
+ return false;
+
+ if(!ippiCheckAnchor(anchor, ksize))
+ return false;
+
+ try
+ {
+ ::ipp::IwiImage iwSrc = ippiGetImage(src);
+ ::ipp::IwiImage iwDst = ippiGetImage(dst);
+ ::ipp::IwiSize iwKSize = ippiGetSize(ksize);
+ ::ipp::IwiBorderSize borderSize(iwKSize);
+ ::ipp::IwiBorderType ippBorder(ippiGetBorder(iwSrc, borderType, borderSize));
+ if(!ippBorder)
+ return false;
+
+ CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBox, iwSrc, iwDst, iwKSize, ::ipp::IwDefault(), ippBorder);
+ }
+ catch (const ::ipp::IwException &)
+ {
+ return false;
+ }
+
+ return true;
+#else
+ CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(ksize); CV_UNUSED(anchor); CV_UNUSED(normalize); CV_UNUSED(borderType);
+ return false;
+#endif
+}
+#endif
+
+
+void boxFilter(InputArray _src, OutputArray _dst, int ddepth,
+ Size ksize, Point anchor,
+ bool normalize, int borderType)
+{
+ CV_INSTRUMENT_REGION();
+
+ CV_OCL_RUN(_dst.isUMat() &&
+ (borderType == BORDER_REPLICATE || borderType == BORDER_CONSTANT ||
+ borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101),
+ ocl_boxFilter3x3_8UC1(_src, _dst, ddepth, ksize, anchor, borderType, normalize))
+
+ CV_OCL_RUN(_dst.isUMat(), ocl_boxFilter(_src, _dst, ddepth, ksize, anchor, borderType, normalize))
+
+ Mat src = _src.getMat();
+ int stype = src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype);
+ if( ddepth < 0 )
+ ddepth = sdepth;
+ _dst.create( src.size(), CV_MAKETYPE(ddepth, cn) );
+ Mat dst = _dst.getMat();
+ if( borderType != BORDER_CONSTANT && normalize && (borderType & BORDER_ISOLATED) != 0 )
+ {
+ if( src.rows == 1 )
+ ksize.height = 1;
+ if( src.cols == 1 )
+ ksize.width = 1;
+ }
+
+ Point ofs;
+ Size wsz(src.cols, src.rows);
+ if(!(borderType&BORDER_ISOLATED))
+ src.locateROI( wsz, ofs );
+
+ CALL_HAL(boxFilter, cv_hal_boxFilter, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, ddepth, cn,
+ ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, ksize.width, ksize.height,
+ anchor.x, anchor.y, normalize, borderType&~BORDER_ISOLATED);
+
+ CV_OVX_RUN(true,
+ openvx_boxfilter(src, dst, ddepth, ksize, anchor, normalize, borderType))
+
+ CV_IPP_RUN_FAST(ipp_boxfilter(src, dst, ksize, anchor, normalize, borderType));
+
+ borderType = (borderType&~BORDER_ISOLATED);
+
+ Ptr<FilterEngine> f = createBoxFilter( src.type(), dst.type(),
+ ksize, anchor, normalize, borderType );
+
+ f->apply( src, dst, wsz, ofs );
+}
+
+
+void blur(InputArray src, OutputArray dst,
+ Size ksize, Point anchor, int borderType)
+{
+ CV_INSTRUMENT_REGION();
+
+ boxFilter( src, dst, -1, ksize, anchor, true, borderType );
+}
+
+
+/****************************************************************************************\
+ Squared Box Filter
+\****************************************************************************************/
+
+static Ptr<BaseRowFilter> getSqrRowSumFilter(int srcType, int sumType, int ksize, int anchor)
+{
+ CV_INSTRUMENT_REGION();
+
+ CV_CPU_DISPATCH(getSqrRowSumFilter, (srcType, sumType, ksize, anchor),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void sqrBoxFilter(InputArray _src, OutputArray _dst, int ddepth,
+ Size ksize, Point anchor,
+ bool normalize, int borderType)
+{
+ CV_INSTRUMENT_REGION();
+
+ int srcType = _src.type(), sdepth = CV_MAT_DEPTH(srcType), cn = CV_MAT_CN(srcType);
+ Size size = _src.size();
+
+ if( ddepth < 0 )
+ ddepth = sdepth < CV_32F ? CV_32F : CV_64F;
+
+ if( borderType != BORDER_CONSTANT && normalize )
+ {
+ if( size.height == 1 )
+ ksize.height = 1;
+ if( size.width == 1 )
+ ksize.width = 1;
+ }
+
+ CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
+ ocl_boxFilter(_src, _dst, ddepth, ksize, anchor, borderType, normalize, true))
+
+ int sumDepth = CV_64F;
+ if( sdepth == CV_8U )
+ sumDepth = CV_32S;
+ int sumType = CV_MAKETYPE( sumDepth, cn ), dstType = CV_MAKETYPE(ddepth, cn);
+
+ Mat src = _src.getMat();
+ _dst.create( size, dstType );
+ Mat dst = _dst.getMat();
+
+ Ptr<BaseRowFilter> rowFilter = getSqrRowSumFilter(srcType, sumType, ksize.width, anchor.x );
+ Ptr<BaseColumnFilter> columnFilter = getColumnSumFilter(sumType,
+ dstType, ksize.height, anchor.y,
+ normalize ? 1./(ksize.width*ksize.height) : 1);
+
+ Ptr<FilterEngine> f = makePtr<FilterEngine>(Ptr<BaseFilter>(), rowFilter, columnFilter,
+ srcType, dstType, sumType, borderType );
+ Point ofs;
+ Size wsz(src.cols, src.rows);
+ src.locateROI( wsz, ofs );
+
+ f->apply( src, dst, wsz, ofs );
+}
+
+} // namespace
//M*/
#include "precomp.hpp"
-
-#include <vector>
-
#include "opencv2/core/hal/intrin.hpp"
-#include "opencl_kernels_imgproc.hpp"
-#include "opencv2/core/openvx/ovx_defs.hpp"
+namespace cv {
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+// forward declarations
+Ptr<BaseRowFilter> getRowSumFilter(int srcType, int sumType, int ksize, int anchor);
+Ptr<BaseColumnFilter> getColumnSumFilter(int sumType, int dstType, int ksize, int anchor, double scale);
+Ptr<FilterEngine> createBoxFilter(int srcType, int dstType, Size ksize,
+ Point anchor, bool normalize, int borderType);
-namespace cv
-{
+Ptr<BaseRowFilter> getSqrRowSumFilter(int srcType, int sumType, int ksize, int anchor);
+
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
/****************************************************************************************\
Box Filter
\****************************************************************************************/
+namespace {
template<typename T, typename ST>
struct RowSum :
public BaseRowFilter
virtual void operator()(const uchar* src, uchar* dst, int width, int cn) CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
const T* S = (const T*)src;
ST* D = (ST*)dst;
int i = 0, k, ksz_cn = ksize*cn;
virtual void operator()(const uchar** src, uchar* dst, int dststep, int count, int width) CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
int i;
ST* SUM;
bool haveScale = scale != 1;
virtual void operator()(const uchar** src, uchar* dst, int dststep, int count, int width) CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
int* SUM;
bool haveScale = scale != 1;
double _scale = scale;
}
dst += dststep;
}
-#if CV_SIMD
- vx_cleanup();
-#endif
}
double scale;
virtual void operator()(const uchar** src, uchar* dst, int dststep, int count, int width) CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
const int ds = divScale;
const int dd = divDelta;
ushort* SUM;
}
dst += dststep;
}
-#if CV_SIMD
- vx_cleanup();
-#endif
}
double scale;
virtual void operator()(const uchar** src, uchar* dst, int dststep, int count, int width) CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
int i;
int* SUM;
bool haveScale = scale != 1;
}
dst += dststep;
}
-#if CV_SIMD
- vx_cleanup();
-#endif
}
double scale;
virtual void operator()(const uchar** src, uchar* dst, int dststep, int count, int width) CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
int* SUM;
bool haveScale = scale != 1;
double _scale = scale;
}
dst += dststep;
}
-#if CV_SIMD
- vx_cleanup();
-#endif
}
double scale;
virtual void operator()(const uchar** src, uchar* dst, int dststep, int count, int width) CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
int* SUM;
bool haveScale = scale != 1;
double _scale = scale;
}
dst += dststep;
}
-#if CV_SIMD
- vx_cleanup();
-#endif
}
double scale;
virtual void operator()(const uchar** src, uchar* dst, int dststep, int count, int width) CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
int* SUM;
bool haveScale = scale != 1;
double _scale = scale;
}
dst += dststep;
}
-#if CV_SIMD
- vx_cleanup();
-#endif
}
double scale;
std::vector<int> sum;
};
-#ifdef HAVE_OPENCL
+} // namespace anon
-static bool ocl_boxFilter3x3_8UC1( InputArray _src, OutputArray _dst, int ddepth,
- Size ksize, Point anchor, int borderType, bool normalize )
-{
- const ocl::Device & dev = ocl::Device::getDefault();
- int type = _src.type(), sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
-
- if (ddepth < 0)
- ddepth = sdepth;
-
- if (anchor.x < 0)
- anchor.x = ksize.width / 2;
- if (anchor.y < 0)
- anchor.y = ksize.height / 2;
-
- if ( !(dev.isIntel() && (type == CV_8UC1) &&
- (_src.offset() == 0) && (_src.step() % 4 == 0) &&
- (_src.cols() % 16 == 0) && (_src.rows() % 2 == 0) &&
- (anchor.x == 1) && (anchor.y == 1) &&
- (ksize.width == 3) && (ksize.height == 3)) )
- return false;
-
- float alpha = 1.0f / (ksize.height * ksize.width);
- Size size = _src.size();
- size_t globalsize[2] = { 0, 0 };
- size_t localsize[2] = { 0, 0 };
- const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", 0, "BORDER_REFLECT_101" };
-
- globalsize[0] = size.width / 16;
- globalsize[1] = size.height / 2;
-
- char build_opts[1024];
- sprintf(build_opts, "-D %s %s", borderMap[borderType], normalize ? "-D NORMALIZE" : "");
-
- ocl::Kernel kernel("boxFilter3x3_8UC1_cols16_rows2", cv::ocl::imgproc::boxFilter3x3_oclsrc, build_opts);
- if (kernel.empty())
- return false;
-
- UMat src = _src.getUMat();
- _dst.create(size, CV_MAKETYPE(ddepth, cn));
- if (!(_dst.offset() == 0 && _dst.step() % 4 == 0))
- return false;
- UMat dst = _dst.getUMat();
-
- int idxArg = kernel.set(0, ocl::KernelArg::PtrReadOnly(src));
- idxArg = kernel.set(idxArg, (int)src.step);
- idxArg = kernel.set(idxArg, ocl::KernelArg::PtrWriteOnly(dst));
- idxArg = kernel.set(idxArg, (int)dst.step);
- idxArg = kernel.set(idxArg, (int)dst.rows);
- idxArg = kernel.set(idxArg, (int)dst.cols);
- if (normalize)
- idxArg = kernel.set(idxArg, (float)alpha);
-
- return kernel.run(2, globalsize, (localsize[0] == 0) ? NULL : localsize, false);
-}
-static bool ocl_boxFilter( InputArray _src, OutputArray _dst, int ddepth,
- Size ksize, Point anchor, int borderType, bool normalize, bool sqr = false )
+Ptr<BaseRowFilter> getRowSumFilter(int srcType, int sumType, int ksize, int anchor)
{
- const ocl::Device & dev = ocl::Device::getDefault();
- int type = _src.type(), sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), esz = CV_ELEM_SIZE(type);
- bool doubleSupport = dev.doubleFPConfig() > 0;
-
- if (ddepth < 0)
- ddepth = sdepth;
-
- if (cn > 4 || (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F)) ||
- _src.offset() % esz != 0 || _src.step() % esz != 0)
- return false;
-
- if (anchor.x < 0)
- anchor.x = ksize.width / 2;
- if (anchor.y < 0)
- anchor.y = ksize.height / 2;
-
- int computeUnits = ocl::Device::getDefault().maxComputeUnits();
- float alpha = 1.0f / (ksize.height * ksize.width);
- Size size = _src.size(), wholeSize;
- bool isolated = (borderType & BORDER_ISOLATED) != 0;
- borderType &= ~BORDER_ISOLATED;
- int wdepth = std::max(CV_32F, std::max(ddepth, sdepth)),
- wtype = CV_MAKE_TYPE(wdepth, cn), dtype = CV_MAKE_TYPE(ddepth, cn);
-
- const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", 0, "BORDER_REFLECT_101" };
- size_t globalsize[2] = { (size_t)size.width, (size_t)size.height };
- size_t localsize_general[2] = { 0, 1 }, * localsize = NULL;
-
- UMat src = _src.getUMat();
- if (!isolated)
- {
- Point ofs;
- src.locateROI(wholeSize, ofs);
- }
-
- int h = isolated ? size.height : wholeSize.height;
- int w = isolated ? size.width : wholeSize.width;
-
- size_t maxWorkItemSizes[32];
- ocl::Device::getDefault().maxWorkItemSizes(maxWorkItemSizes);
- int tryWorkItems = (int)maxWorkItemSizes[0];
-
- ocl::Kernel kernel;
-
- if (dev.isIntel() && !(dev.type() & ocl::Device::TYPE_CPU) &&
- ((ksize.width < 5 && ksize.height < 5 && esz <= 4) ||
- (ksize.width == 5 && ksize.height == 5 && cn == 1)))
- {
- if (w < ksize.width || h < ksize.height)
- return false;
-
- // Figure out what vector size to use for loading the pixels.
- int pxLoadNumPixels = cn != 1 || size.width % 4 ? 1 : 4;
- int pxLoadVecSize = cn * pxLoadNumPixels;
-
- // Figure out how many pixels per work item to compute in X and Y
- // directions. Too many and we run out of registers.
- int pxPerWorkItemX = 1, pxPerWorkItemY = 1;
- if (cn <= 2 && ksize.width <= 4 && ksize.height <= 4)
- {
- pxPerWorkItemX = size.width % 8 ? size.width % 4 ? size.width % 2 ? 1 : 2 : 4 : 8;
- pxPerWorkItemY = size.height % 2 ? 1 : 2;
- }
- else if (cn < 4 || (ksize.width <= 4 && ksize.height <= 4))
- {
- pxPerWorkItemX = size.width % 2 ? 1 : 2;
- pxPerWorkItemY = size.height % 2 ? 1 : 2;
- }
- globalsize[0] = size.width / pxPerWorkItemX;
- globalsize[1] = size.height / pxPerWorkItemY;
-
- // Need some padding in the private array for pixels
- int privDataWidth = roundUp(pxPerWorkItemX + ksize.width - 1, pxLoadNumPixels);
-
- // Make the global size a nice round number so the runtime can pick
- // from reasonable choices for the workgroup size
- const int wgRound = 256;
- globalsize[0] = roundUp(globalsize[0], wgRound);
-
- char build_options[1024], cvt[2][40];
- sprintf(build_options, "-D cn=%d "
- "-D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d "
- "-D PX_LOAD_VEC_SIZE=%d -D PX_LOAD_NUM_PX=%d "
- "-D PX_PER_WI_X=%d -D PX_PER_WI_Y=%d -D PRIV_DATA_WIDTH=%d -D %s -D %s "
- "-D PX_LOAD_X_ITERATIONS=%d -D PX_LOAD_Y_ITERATIONS=%d "
- "-D srcT=%s -D srcT1=%s -D dstT=%s -D dstT1=%s -D WT=%s -D WT1=%s "
- "-D convertToWT=%s -D convertToDstT=%s%s%s -D PX_LOAD_FLOAT_VEC_CONV=convert_%s -D OP_BOX_FILTER",
- cn, anchor.x, anchor.y, ksize.width, ksize.height,
- pxLoadVecSize, pxLoadNumPixels,
- pxPerWorkItemX, pxPerWorkItemY, privDataWidth, borderMap[borderType],
- isolated ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED",
- privDataWidth / pxLoadNumPixels, pxPerWorkItemY + ksize.height - 1,
- ocl::typeToStr(type), ocl::typeToStr(sdepth), ocl::typeToStr(dtype),
- ocl::typeToStr(ddepth), ocl::typeToStr(wtype), ocl::typeToStr(wdepth),
- ocl::convertTypeStr(sdepth, wdepth, cn, cvt[0]),
- ocl::convertTypeStr(wdepth, ddepth, cn, cvt[1]),
- normalize ? " -D NORMALIZE" : "", sqr ? " -D SQR" : "",
- ocl::typeToStr(CV_MAKE_TYPE(wdepth, pxLoadVecSize)) //PX_LOAD_FLOAT_VEC_CONV
- );
-
-
- if (!kernel.create("filterSmall", cv::ocl::imgproc::filterSmall_oclsrc, build_options))
- return false;
- }
- else
- {
- localsize = localsize_general;
- for ( ; ; )
- {
- int BLOCK_SIZE_X = tryWorkItems, BLOCK_SIZE_Y = std::min(ksize.height * 10, size.height);
-
- while (BLOCK_SIZE_X > 32 && BLOCK_SIZE_X >= ksize.width * 2 && BLOCK_SIZE_X > size.width * 2)
- BLOCK_SIZE_X /= 2;
- while (BLOCK_SIZE_Y < BLOCK_SIZE_X / 8 && BLOCK_SIZE_Y * computeUnits * 32 < size.height)
- BLOCK_SIZE_Y *= 2;
-
- if (ksize.width > BLOCK_SIZE_X || w < ksize.width || h < ksize.height)
- return false;
-
- char cvt[2][50];
- String opts = format("-D LOCAL_SIZE_X=%d -D BLOCK_SIZE_Y=%d -D ST=%s -D DT=%s -D WT=%s -D convertToDT=%s -D convertToWT=%s"
- " -D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d -D %s%s%s%s%s"
- " -D ST1=%s -D DT1=%s -D cn=%d",
- BLOCK_SIZE_X, BLOCK_SIZE_Y, ocl::typeToStr(type), ocl::typeToStr(CV_MAKE_TYPE(ddepth, cn)),
- ocl::typeToStr(CV_MAKE_TYPE(wdepth, cn)),
- ocl::convertTypeStr(wdepth, ddepth, cn, cvt[0]),
- ocl::convertTypeStr(sdepth, wdepth, cn, cvt[1]),
- anchor.x, anchor.y, ksize.width, ksize.height, borderMap[borderType],
- isolated ? " -D BORDER_ISOLATED" : "", doubleSupport ? " -D DOUBLE_SUPPORT" : "",
- normalize ? " -D NORMALIZE" : "", sqr ? " -D SQR" : "",
- ocl::typeToStr(sdepth), ocl::typeToStr(ddepth), cn);
-
- localsize[0] = BLOCK_SIZE_X;
- globalsize[0] = divUp(size.width, BLOCK_SIZE_X - (ksize.width - 1)) * BLOCK_SIZE_X;
- globalsize[1] = divUp(size.height, BLOCK_SIZE_Y);
-
- kernel.create("boxFilter", cv::ocl::imgproc::boxFilter_oclsrc, opts);
- if (kernel.empty())
- return false;
-
- size_t kernelWorkGroupSize = kernel.workGroupSize();
- if (localsize[0] <= kernelWorkGroupSize)
- break;
- if (BLOCK_SIZE_X < (int)kernelWorkGroupSize)
- return false;
-
- tryWorkItems = (int)kernelWorkGroupSize;
- }
- }
-
- _dst.create(size, CV_MAKETYPE(ddepth, cn));
- UMat dst = _dst.getUMat();
-
- int idxArg = kernel.set(0, ocl::KernelArg::PtrReadOnly(src));
- idxArg = kernel.set(idxArg, (int)src.step);
- int srcOffsetX = (int)((src.offset % src.step) / src.elemSize());
- int srcOffsetY = (int)(src.offset / src.step);
- int srcEndX = isolated ? srcOffsetX + size.width : wholeSize.width;
- int srcEndY = isolated ? srcOffsetY + size.height : wholeSize.height;
- idxArg = kernel.set(idxArg, srcOffsetX);
- idxArg = kernel.set(idxArg, srcOffsetY);
- idxArg = kernel.set(idxArg, srcEndX);
- idxArg = kernel.set(idxArg, srcEndY);
- idxArg = kernel.set(idxArg, ocl::KernelArg::WriteOnly(dst));
- if (normalize)
- idxArg = kernel.set(idxArg, (float)alpha);
-
- return kernel.run(2, globalsize, localsize, false);
-}
-
-#endif
-
-}
-
+ CV_INSTRUMENT_REGION();
-cv::Ptr<cv::BaseRowFilter> cv::getRowSumFilter(int srcType, int sumType, int ksize, int anchor)
-{
int sdepth = CV_MAT_DEPTH(srcType), ddepth = CV_MAT_DEPTH(sumType);
CV_Assert( CV_MAT_CN(sumType) == CV_MAT_CN(srcType) );
}
-cv::Ptr<cv::BaseColumnFilter> cv::getColumnSumFilter(int sumType, int dstType, int ksize,
- int anchor, double scale)
+Ptr<BaseColumnFilter> getColumnSumFilter(int sumType, int dstType, int ksize, int anchor, double scale)
{
+ CV_INSTRUMENT_REGION();
+
int sdepth = CV_MAT_DEPTH(sumType), ddepth = CV_MAT_DEPTH(dstType);
CV_Assert( CV_MAT_CN(sumType) == CV_MAT_CN(dstType) );
}
-cv::Ptr<cv::FilterEngine> cv::createBoxFilter( int srcType, int dstType, Size ksize,
- Point anchor, bool normalize, int borderType )
+Ptr<FilterEngine> createBoxFilter(int srcType, int dstType, Size ksize,
+ Point anchor, bool normalize, int borderType)
{
+ CV_INSTRUMENT_REGION();
+
int sdepth = CV_MAT_DEPTH(srcType);
int cn = CV_MAT_CN(srcType), sumType = CV_64F;
if( sdepth == CV_8U && CV_MAT_DEPTH(dstType) == CV_8U &&
srcType, dstType, sumType, borderType );
}
-#ifdef HAVE_OPENVX
-namespace cv
-{
- namespace ovx {
- template <> inline bool skipSmallImages<VX_KERNEL_BOX_3x3>(int w, int h) { return w*h < 640 * 480; }
- }
- static bool openvx_boxfilter(InputArray _src, OutputArray _dst, int ddepth,
- Size ksize, Point anchor,
- bool normalize, int borderType)
- {
- if (ddepth < 0)
- ddepth = CV_8UC1;
- if (_src.type() != CV_8UC1 || ddepth != CV_8U || !normalize ||
- _src.cols() < 3 || _src.rows() < 3 ||
- ksize.width != 3 || ksize.height != 3 ||
- (anchor.x >= 0 && anchor.x != 1) ||
- (anchor.y >= 0 && anchor.y != 1) ||
- ovx::skipSmallImages<VX_KERNEL_BOX_3x3>(_src.cols(), _src.rows()))
- return false;
-
- Mat src = _src.getMat();
-
- if ((borderType & BORDER_ISOLATED) == 0 && src.isSubmatrix())
- return false; //Process isolated borders only
- vx_enum border;
- switch (borderType & ~BORDER_ISOLATED)
- {
- case BORDER_CONSTANT:
- border = VX_BORDER_CONSTANT;
- break;
- case BORDER_REPLICATE:
- border = VX_BORDER_REPLICATE;
- break;
- default:
- return false;
- }
-
- _dst.create(src.size(), CV_8UC1);
- Mat dst = _dst.getMat();
-
- try
- {
- ivx::Context ctx = ovx::getOpenVXContext();
-
- Mat a;
- if (dst.data != src.data)
- a = src;
- else
- src.copyTo(a);
-
- ivx::Image
- ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,
- ivx::Image::createAddressing(a.cols, a.rows, 1, (vx_int32)(a.step)), a.data),
- ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,
- ivx::Image::createAddressing(dst.cols, dst.rows, 1, (vx_int32)(dst.step)), dst.data);
-
- //ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments
- //since OpenVX standard says nothing about thread-safety for now
- ivx::border_t prevBorder = ctx.immediateBorder();
- ctx.setImmediateBorder(border, (vx_uint8)(0));
- ivx::IVX_CHECK_STATUS(vxuBox3x3(ctx, ia, ib));
- ctx.setImmediateBorder(prevBorder);
- }
- catch (const ivx::RuntimeError & e)
- {
- VX_DbgThrow(e.what());
- }
- catch (const ivx::WrapperError & e)
- {
- VX_DbgThrow(e.what());
- }
-
- return true;
- }
-}
-#endif
-
-#if defined(HAVE_IPP) && OPENCV_IPP_REDUCE_SIZE == 0
-namespace cv
-{
-static bool ipp_boxfilter(Mat &src, Mat &dst, Size ksize, Point anchor, bool normalize, int borderType)
-{
-#ifdef HAVE_IPP_IW
- CV_INSTRUMENT_REGION_IPP();
-
-#if IPP_VERSION_X100 < 201801
- // Problem with SSE42 optimization for 16s and some 8u modes
- if(ipp::getIppTopFeatures() == ippCPUID_SSE42 && (((src.depth() == CV_16S || src.depth() == CV_16U) && (src.channels() == 3 || src.channels() == 4)) || (src.depth() == CV_8U && src.channels() == 3 && (ksize.width > 5 || ksize.height > 5))))
- return false;
-
- // Other optimizations has some degradations too
- if((((src.depth() == CV_16S || src.depth() == CV_16U) && (src.channels() == 4)) || (src.depth() == CV_8U && src.channels() == 1 && (ksize.width > 5 || ksize.height > 5))))
- return false;
-#endif
-
- if(!normalize)
- return false;
-
- if(!ippiCheckAnchor(anchor, ksize))
- return false;
-
- try
- {
- ::ipp::IwiImage iwSrc = ippiGetImage(src);
- ::ipp::IwiImage iwDst = ippiGetImage(dst);
- ::ipp::IwiSize iwKSize = ippiGetSize(ksize);
- ::ipp::IwiBorderSize borderSize(iwKSize);
- ::ipp::IwiBorderType ippBorder(ippiGetBorder(iwSrc, borderType, borderSize));
- if(!ippBorder)
- return false;
-
- CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBox, iwSrc, iwDst, iwKSize, ::ipp::IwDefault(), ippBorder);
- }
- catch (const ::ipp::IwException &)
- {
- return false;
- }
-
- return true;
-#else
- CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(ksize); CV_UNUSED(anchor); CV_UNUSED(normalize); CV_UNUSED(borderType);
- return false;
-#endif
-}
-}
-#endif
-
-
-void cv::boxFilter( InputArray _src, OutputArray _dst, int ddepth,
- Size ksize, Point anchor,
- bool normalize, int borderType )
-{
- CV_INSTRUMENT_REGION();
-
- CV_OCL_RUN(_dst.isUMat() &&
- (borderType == BORDER_REPLICATE || borderType == BORDER_CONSTANT ||
- borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101),
- ocl_boxFilter3x3_8UC1(_src, _dst, ddepth, ksize, anchor, borderType, normalize))
-
- CV_OCL_RUN(_dst.isUMat(), ocl_boxFilter(_src, _dst, ddepth, ksize, anchor, borderType, normalize))
-
- Mat src = _src.getMat();
- int stype = src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype);
- if( ddepth < 0 )
- ddepth = sdepth;
- _dst.create( src.size(), CV_MAKETYPE(ddepth, cn) );
- Mat dst = _dst.getMat();
- if( borderType != BORDER_CONSTANT && normalize && (borderType & BORDER_ISOLATED) != 0 )
- {
- if( src.rows == 1 )
- ksize.height = 1;
- if( src.cols == 1 )
- ksize.width = 1;
- }
-
- Point ofs;
- Size wsz(src.cols, src.rows);
- if(!(borderType&BORDER_ISOLATED))
- src.locateROI( wsz, ofs );
-
- CALL_HAL(boxFilter, cv_hal_boxFilter, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, ddepth, cn,
- ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, ksize.width, ksize.height,
- anchor.x, anchor.y, normalize, borderType&~BORDER_ISOLATED);
-
- CV_OVX_RUN(true,
- openvx_boxfilter(src, dst, ddepth, ksize, anchor, normalize, borderType))
-
-#if OPENCV_IPP_REDUCE_SIZE == 0
- CV_IPP_RUN_FAST(ipp_boxfilter(src, dst, ksize, anchor, normalize, borderType));
-#endif
-
- borderType = (borderType&~BORDER_ISOLATED);
-
- Ptr<FilterEngine> f = createBoxFilter( src.type(), dst.type(),
- ksize, anchor, normalize, borderType );
-
- f->apply( src, dst, wsz, ofs );
-}
-
-
-void cv::blur( InputArray src, OutputArray dst,
- Size ksize, Point anchor, int borderType )
-{
- CV_INSTRUMENT_REGION();
-
- boxFilter( src, dst, -1, ksize, anchor, true, borderType );
-}
-
/****************************************************************************************\
Squared Box Filter
\****************************************************************************************/
-
-namespace cv
-{
+namespace {
template<typename T, typename ST>
struct SqrRowSum :
virtual void operator()(const uchar* src, uchar* dst, int width, int cn) CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
const T* S = (const T*)src;
ST* D = (ST*)dst;
int i = 0, k, ksz_cn = ksize*cn;
}
};
-static Ptr<BaseRowFilter> getSqrRowSumFilter(int srcType, int sumType, int ksize, int anchor)
+} // namespace anon
+
+Ptr<BaseRowFilter> getSqrRowSumFilter(int srcType, int sumType, int ksize, int anchor)
{
int sdepth = CV_MAT_DEPTH(srcType), ddepth = CV_MAT_DEPTH(sumType);
CV_Assert( CV_MAT_CN(sumType) == CV_MAT_CN(srcType) );
srcType, sumType));
}
-}
-
-void cv::sqrBoxFilter( InputArray _src, OutputArray _dst, int ddepth,
- Size ksize, Point anchor,
- bool normalize, int borderType )
-{
- CV_INSTRUMENT_REGION();
-
- int srcType = _src.type(), sdepth = CV_MAT_DEPTH(srcType), cn = CV_MAT_CN(srcType);
- Size size = _src.size();
-
- if( ddepth < 0 )
- ddepth = sdepth < CV_32F ? CV_32F : CV_64F;
-
- if( borderType != BORDER_CONSTANT && normalize )
- {
- if( size.height == 1 )
- ksize.height = 1;
- if( size.width == 1 )
- ksize.width = 1;
- }
-
- CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
- ocl_boxFilter(_src, _dst, ddepth, ksize, anchor, borderType, normalize, true))
-
- int sumDepth = CV_64F;
- if( sdepth == CV_8U )
- sumDepth = CV_32S;
- int sumType = CV_MAKETYPE( sumDepth, cn ), dstType = CV_MAKETYPE(ddepth, cn);
-
- Mat src = _src.getMat();
- _dst.create( size, dstType );
- Mat dst = _dst.getMat();
-
- Ptr<BaseRowFilter> rowFilter = getSqrRowSumFilter(srcType, sumType, ksize.width, anchor.x );
- Ptr<BaseColumnFilter> columnFilter = getColumnSumFilter(sumType,
- dstType, ksize.height, anchor.y,
- normalize ? 1./(ksize.width*ksize.height) : 1);
-
- Ptr<FilterEngine> f = makePtr<FilterEngine>(Ptr<BaseFilter>(), rowFilter, columnFilter,
- srcType, dstType, sumType, borderType );
- Point ofs;
- Size wsz(src.cols, src.rows);
- src.locateROI( wsz, ofs );
-
- f->apply( src, dst, wsz, ofs );
-}
-
-/* End of file. */
+#endif
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+} // namespace
{
CV_TRACE_FUNCTION();
+ CV_DbgAssert(cn > 0);
+
Mat dx, dy;
AutoBuffer<short> dxMax(0), dyMax(0);
std::deque<uchar*> stack, borderPeaksLocal;
// of this distribution and at http://opencv.org/license.html
#include "precomp.hpp"
+#include "opencl_kernels_imgproc.hpp"
#include "color.hpp"
namespace cv
// of this distribution and at http://opencv.org/license.html
#include "opencv2/imgproc.hpp"
-#include "opencv2/core/utility.hpp"
-#include <limits>
-#include "opencl_kernels_imgproc.hpp"
#include "hal_replacement.hpp"
-#include "opencv2/core/hal/intrin.hpp"
-#include "opencv2/core/softfloat.hpp"
-#define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n))
-
-namespace cv
-{
-
-//constants for conversion from/to RGB and Gray, YUV, YCrCb according to BT.601
-const float B2YF = 0.114f;
-const float G2YF = 0.587f;
-const float R2YF = 0.299f;
-
-enum
-{
- gray_shift = 15,
- yuv_shift = 14,
- xyz_shift = 12,
- R2Y = 4899, // == R2YF*16384
- G2Y = 9617, // == G2YF*16384
- B2Y = 1868, // == B2YF*16384
- RY15 = 9798, // == R2YF*32768 + 0.5
- GY15 = 19235, // == G2YF*32768 + 0.5
- BY15 = 3735, // == B2YF*32768 + 0.5
- BLOCK_SIZE = 256
-};
-
-template<typename _Tp> struct ColorChannel
-{
- typedef float worktype_f;
- static _Tp max() { return std::numeric_limits<_Tp>::max(); }
- static _Tp half() { return (_Tp)(max()/2 + 1); }
-};
-
-template<> struct ColorChannel<float>
-{
- typedef float worktype_f;
- static float max() { return 1.f; }
- static float half() { return 0.5f; }
-};
-
-/*template<> struct ColorChannel<double>
-{
- typedef double worktype_f;
- static double max() { return 1.; }
- static double half() { return 0.5; }
-};*/
+namespace cv {
//
// Helper functions
//
-namespace {
+namespace impl {
+
+#include "color.simd_helpers.hpp"
inline bool isHSV(int code)
{
}
} // namespace::
+using namespace impl;
-template<int i0, int i1 = -1, int i2 = -1>
-struct Set
-{
- static bool contains(int i)
- {
- return (i == i0 || i == i1 || i == i2);
- }
-};
-
-template<int i0, int i1>
-struct Set<i0, i1, -1>
-{
- static bool contains(int i)
- {
- return (i == i0 || i == i1);
- }
-};
-
-template<int i0>
-struct Set<i0, -1, -1>
-{
- static bool contains(int i)
- {
- return (i == i0);
- }
-};
-
-enum SizePolicy
-{
- TO_YUV, FROM_YUV, NONE
-};
-
-template< typename VScn, typename VDcn, typename VDepth, SizePolicy sizePolicy = NONE >
+/*template< typename VScn, typename VDcn, typename VDepth, SizePolicy sizePolicy = NONE >
struct CvtHelper
{
CvtHelper(InputArray _src, OutputArray _dst, int dcn)
Mat src, dst;
int depth, scn;
Size dstSz;
-};
+};*/
#ifdef HAVE_OPENCL
#endif
-///////////////////////////// Top-level template function ////////////////////////////////
-
-template <typename Cvt>
-class CvtColorLoop_Invoker : public ParallelLoopBody
-{
- typedef typename Cvt::channel_type _Tp;
-public:
-
- CvtColorLoop_Invoker(const uchar * src_data_, size_t src_step_, uchar * dst_data_, size_t dst_step_, int width_, const Cvt& _cvt) :
- ParallelLoopBody(), src_data(src_data_), src_step(src_step_), dst_data(dst_data_), dst_step(dst_step_),
- width(width_), cvt(_cvt)
- {
- }
-
- virtual void operator()(const Range& range) const CV_OVERRIDE
- {
- CV_TRACE_FUNCTION();
-
- const uchar* yS = src_data + static_cast<size_t>(range.start) * src_step;
- uchar* yD = dst_data + static_cast<size_t>(range.start) * dst_step;
- for( int i = range.start; i < range.end; ++i, yS += src_step, yD += dst_step )
- cvt(reinterpret_cast<const _Tp*>(yS), reinterpret_cast<_Tp*>(yD), width);
- }
-
-private:
- const uchar * src_data;
- const size_t src_step;
- uchar * dst_data;
- const size_t dst_step;
- const int width;
- const Cvt& cvt;
-
- const CvtColorLoop_Invoker& operator= (const CvtColorLoop_Invoker&);
-};
-
-template <typename Cvt>
-void CvtColorLoop(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, const Cvt& cvt)
-{
- parallel_for_(Range(0, height),
- CvtColorLoop_Invoker<Cvt>(src_data, src_step, dst_data, dst_step, width, cvt),
- (width * height) / static_cast<double>(1<<16));
-}
#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700)
# define NEED_IPP 1
--- /dev/null
+// 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
+
+#define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n))
+
+namespace {
+
+//constants for conversion from/to RGB and Gray, YUV, YCrCb according to BT.601
+static const float B2YF = 0.114f;
+static const float G2YF = 0.587f;
+static const float R2YF = 0.299f;
+
+enum
+{
+ gray_shift = 15,
+ yuv_shift = 14,
+ xyz_shift = 12,
+ R2Y = 4899, // == R2YF*16384
+ G2Y = 9617, // == G2YF*16384
+ B2Y = 1868, // == B2YF*16384
+ RY15 = 9798, // == R2YF*32768 + 0.5
+ GY15 = 19235, // == G2YF*32768 + 0.5
+ BY15 = 3735, // == B2YF*32768 + 0.5
+ BLOCK_SIZE = 256
+};
+
+template<typename _Tp> struct ColorChannel
+{
+ typedef float worktype_f;
+ static inline _Tp max() { return std::numeric_limits<_Tp>::max(); }
+ static inline _Tp half() { return (_Tp)(max()/2 + 1); }
+};
+
+template<> struct ColorChannel<float>
+{
+ typedef float worktype_f;
+ static inline float max() { return 1.f; }
+ static inline float half() { return 0.5f; }
+};
+
+/*template<> struct ColorChannel<double>
+{
+ typedef double worktype_f;
+ static double max() { return 1.; }
+ static double half() { return 0.5; }
+};*/
+
+
+template<int i0, int i1 = -1, int i2 = -1>
+struct Set
+{
+ static inline bool contains(int i)
+ {
+ return (i == i0 || i == i1 || i == i2);
+ }
+};
+
+template<int i0, int i1>
+struct Set<i0, i1, -1>
+{
+ static inline bool contains(int i)
+ {
+ return (i == i0 || i == i1);
+ }
+};
+
+template<int i0>
+struct Set<i0, -1, -1>
+{
+ static inline bool contains(int i)
+ {
+ return (i == i0);
+ }
+};
+
+enum SizePolicy
+{
+ TO_YUV, FROM_YUV, NONE
+};
+
+template< typename VScn, typename VDcn, typename VDepth, SizePolicy sizePolicy = NONE >
+struct CvtHelper
+{
+ CvtHelper(InputArray _src, OutputArray _dst, int dcn)
+ {
+ CV_Assert(!_src.empty());
+
+ int stype = _src.type();
+ scn = CV_MAT_CN(stype), depth = CV_MAT_DEPTH(stype);
+
+ CV_Check(scn, VScn::contains(scn), "Invalid number of channels in input image");
+ CV_Check(dcn, VDcn::contains(dcn), "Invalid number of channels in output image");
+ CV_CheckDepth(depth, VDepth::contains(depth), "Unsupported depth of input image");
+
+ if (_src.getObj() == _dst.getObj()) // inplace processing (#6653)
+ _src.copyTo(src);
+ else
+ src = _src.getMat();
+ Size sz = src.size();
+ switch (sizePolicy)
+ {
+ case TO_YUV:
+ CV_Assert( sz.width % 2 == 0 && sz.height % 2 == 0);
+ dstSz = Size(sz.width, sz.height / 2 * 3);
+ break;
+ case FROM_YUV:
+ CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0);
+ dstSz = Size(sz.width, sz.height * 2 / 3);
+ break;
+ case NONE:
+ default:
+ dstSz = sz;
+ break;
+ }
+ _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
+ dst = _dst.getMat();
+ }
+ Mat src, dst;
+ int depth, scn;
+ Size dstSz;
+};
+
+
+///////////////////////////// Top-level template function ////////////////////////////////
+
+template <typename Cvt>
+class CvtColorLoop_Invoker : public ParallelLoopBody
+{
+ typedef typename Cvt::channel_type _Tp;
+public:
+
+ CvtColorLoop_Invoker(const uchar * src_data_, size_t src_step_, uchar * dst_data_, size_t dst_step_, int width_, const Cvt& _cvt) :
+ ParallelLoopBody(), src_data(src_data_), src_step(src_step_), dst_data(dst_data_), dst_step(dst_step_),
+ width(width_), cvt(_cvt)
+ {
+ }
+
+ virtual void operator()(const Range& range) const CV_OVERRIDE
+ {
+ CV_TRACE_FUNCTION();
+
+ const uchar* yS = src_data + static_cast<size_t>(range.start) * src_step;
+ uchar* yD = dst_data + static_cast<size_t>(range.start) * dst_step;
+
+ for( int i = range.start; i < range.end; ++i, yS += src_step, yD += dst_step )
+ cvt(reinterpret_cast<const _Tp*>(yS), reinterpret_cast<_Tp*>(yD), width);
+ }
+
+private:
+ const uchar * src_data;
+ const size_t src_step;
+ uchar * dst_data;
+ const size_t dst_step;
+ const int width;
+ const Cvt& cvt;
+
+ CvtColorLoop_Invoker(const CvtColorLoop_Invoker&); // = delete;
+ const CvtColorLoop_Invoker& operator= (const CvtColorLoop_Invoker&); // = delete;
+};
+
+template <typename Cvt> static inline
+void CvtColorLoop(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, const Cvt& cvt)
+{
+ CV_AVX_GUARD
+ parallel_for_(Range(0, height),
+ CvtColorLoop_Invoker<Cvt>(src_data, src_step, dst_data, dst_step, width, cvt),
+ (width * height) / static_cast<double>(1<<16));
+}
+
+} //namespace
--- /dev/null
+// 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 "precomp.hpp"
+
+#include "opencl_kernels_imgproc.hpp"
+
+#include "color.hpp"
+
+#include "color_hsv.simd.hpp"
+#include "color_hsv.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
+
+namespace cv {
+
+//
+// IPP functions
+//
+
+#if NEED_IPP
+
+#if !IPP_DISABLE_RGB_HSV
+static ippiGeneralFunc ippiRGB2HSVTab[] =
+{
+ (ippiGeneralFunc)ippiRGBToHSV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHSV_16u_C3R, 0,
+ 0, 0, 0, 0
+};
+#endif
+
+static ippiGeneralFunc ippiHSV2RGBTab[] =
+{
+ (ippiGeneralFunc)ippiHSVToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHSVToRGB_16u_C3R, 0,
+ 0, 0, 0, 0
+};
+
+static ippiGeneralFunc ippiRGB2HLSTab[] =
+{
+ (ippiGeneralFunc)ippiRGBToHLS_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHLS_16u_C3R, 0,
+ 0, (ippiGeneralFunc)ippiRGBToHLS_32f_C3R, 0, 0
+};
+
+static ippiGeneralFunc ippiHLS2RGBTab[] =
+{
+ (ippiGeneralFunc)ippiHLSToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHLSToRGB_16u_C3R, 0,
+ 0, (ippiGeneralFunc)ippiHLSToRGB_32f_C3R, 0, 0
+};
+
+#endif
+
+//
+// HAL functions
+//
+
+namespace hal
+{
+
+// 8u, 32f
+void cvtBGRtoHSV(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int scn, bool swapBlue, bool isFullRange, bool isHSV)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtBGRtoHSV, cv_hal_cvtBGRtoHSV, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isFullRange, isHSV);
+
+#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700
+ CV_IPP_CHECK()
+ {
+ if(depth == CV_8U && isFullRange)
+ {
+ if (isHSV)
+ {
+#if !IPP_DISABLE_RGB_HSV // breaks OCL accuracy tests
+ if(scn == 3 && !swapBlue)
+ {
+ if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height,
+ IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) )
+ return;
+ }
+ else if(scn == 4 && !swapBlue)
+ {
+ if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) )
+ return;
+ }
+ else if(scn == 4 && swapBlue)
+ {
+ if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 0, 1, 2, depth)) )
+ return;
+ }
+#endif
+ }
+ else
+ {
+ if(scn == 3 && !swapBlue)
+ {
+ if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height,
+ IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) )
+ return;
+ }
+ else if(scn == 4 && !swapBlue)
+ {
+ if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) )
+ return;
+ }
+ else if(scn == 3 && swapBlue)
+ {
+ if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height,
+ IPPGeneralFunctor(ippiRGB2HLSTab[depth])) )
+ return;
+ }
+ else if(scn == 4 && swapBlue)
+ {
+ if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 0, 1, 2, depth)) )
+ return;
+ }
+ }
+ }
+ }
+#endif
+
+ CV_CPU_DISPATCH(cvtBGRtoHSV, (src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isFullRange, isHSV),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+// 8u, 32f
+void cvtHSVtoBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int dcn, bool swapBlue, bool isFullRange, bool isHSV)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtHSVtoBGR, cv_hal_cvtHSVtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isFullRange, isHSV);
+
+#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700
+ CV_IPP_CHECK()
+ {
+ if (depth == CV_8U && isFullRange)
+ {
+ if (isHSV)
+ {
+ if(dcn == 3 && !swapBlue)
+ {
+ if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height,
+ IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
+ return;
+ }
+ else if(dcn == 4 && !swapBlue)
+ {
+ if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
+ return;
+ }
+ else if(dcn == 3 && swapBlue)
+ {
+ if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height,
+ IPPGeneralFunctor(ippiHSV2RGBTab[depth])) )
+ return;
+ }
+ else if(dcn == 4 && swapBlue)
+ {
+ if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
+ return;
+ }
+ }
+ else
+ {
+ if(dcn == 3 && !swapBlue)
+ {
+ if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height,
+ IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
+ return;
+ }
+ else if(dcn == 4 && !swapBlue)
+ {
+ if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
+ return;
+ }
+ else if(dcn == 3 && swapBlue)
+ {
+ if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height,
+ IPPGeneralFunctor(ippiHLS2RGBTab[depth])) )
+ return;
+ }
+ else if(dcn == 4 && swapBlue)
+ {
+ if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
+ return;
+ }
+ }
+ }
+ }
+#endif
+
+ CV_CPU_DISPATCH(cvtHSVtoBGR, (src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isFullRange, isHSV),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+} // namespace hal
+
+//
+// OCL calls
+//
+
+#ifdef HAVE_OPENCL
+
+bool oclCvtColorHSV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, bool full )
+{
+ OclHelper< Set<3>, Set<3, 4>, Set<CV_8U, CV_32F> > h(_src, _dst, dcn);
+
+ int hrange = _src.depth() == CV_32F ? 360 : (!full ? 180 : 255);
+
+ if(!h.createKernel("HSV2RGB", ocl::imgproc::color_hsv_oclsrc,
+ format("-D dcn=%d -D bidx=%d -D hrange=%d -D hscale=%ff", dcn, bidx, hrange, 6.f/hrange)))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColorHLS2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, bool full )
+{
+ OclHelper< Set<3>, Set<3, 4>, Set<CV_8U, CV_32F> > h(_src, _dst, dcn);
+
+ int hrange = _src.depth() == CV_32F ? 360 : (!full ? 180 : 255);
+
+ if(!h.createKernel("HLS2RGB", ocl::imgproc::color_hsv_oclsrc,
+ format("-D dcn=%d -D bidx=%d -D hrange=%d -D hscale=%ff", dcn, bidx, hrange, 6.f/hrange)))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColorBGR2HLS( InputArray _src, OutputArray _dst, int bidx, bool full )
+{
+ OclHelper< Set<3, 4>, Set<3>, Set<CV_8U, CV_32F> > h(_src, _dst, 3);
+
+ float hscale = (_src.depth() == CV_32F ? 360.f : (!full ? 180.f : 256.f))/360.f;
+
+ if(!h.createKernel("RGB2HLS", ocl::imgproc::color_hsv_oclsrc,
+ format("-D hscale=%ff -D bidx=%d -D dcn=3", hscale, bidx)))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColorBGR2HSV( InputArray _src, OutputArray _dst, int bidx, bool full )
+{
+ OclHelper< Set<3, 4>, Set<3>, Set<CV_8U, CV_32F> > h(_src, _dst, 3);
+
+ int hrange = _src.depth() == CV_32F ? 360 : (!full ? 180 : 256);
+
+ cv::String options = (_src.depth() == CV_8U ?
+ format("-D hrange=%d -D bidx=%d -D dcn=3", hrange, bidx) :
+ format("-D hscale=%ff -D bidx=%d -D dcn=3", hrange*(1.f/360.f), bidx));
+
+ if(!h.createKernel("RGB2HSV", ocl::imgproc::color_hsv_oclsrc, options))
+ {
+ return false;
+ }
+
+ if(_src.depth() == CV_8U)
+ {
+ static UMat sdiv_data;
+ static UMat hdiv_data180;
+ static UMat hdiv_data256;
+ static int sdiv_table[256];
+ static int hdiv_table180[256];
+ static int hdiv_table256[256];
+ static volatile bool initialized180 = false, initialized256 = false;
+ volatile bool & initialized = hrange == 180 ? initialized180 : initialized256;
+
+ if (!initialized)
+ {
+ int * const hdiv_table = hrange == 180 ? hdiv_table180 : hdiv_table256, hsv_shift = 12;
+ UMat & hdiv_data = hrange == 180 ? hdiv_data180 : hdiv_data256;
+
+ sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0;
+
+ int v = 255 << hsv_shift;
+ if (!initialized180 && !initialized256)
+ {
+ for(int i = 1; i < 256; i++ )
+ sdiv_table[i] = saturate_cast<int>(v/(1.*i));
+ Mat(1, 256, CV_32SC1, sdiv_table).copyTo(sdiv_data);
+ }
+
+ v = hrange << hsv_shift;
+ for (int i = 1; i < 256; i++ )
+ hdiv_table[i] = saturate_cast<int>(v/(6.*i));
+
+ Mat(1, 256, CV_32SC1, hdiv_table).copyTo(hdiv_data);
+ initialized = true;
+ }
+
+ h.setArg(ocl::KernelArg::PtrReadOnly(sdiv_data));
+ h.setArg(hrange == 256 ? ocl::KernelArg::PtrReadOnly(hdiv_data256) :
+ ocl::KernelArg::PtrReadOnly(hdiv_data180));
+ }
+
+ return h.run();
+}
+
+#endif
+
+//
+// HAL calls
+//
+
+void cvtColorBGR2HLS( InputArray _src, OutputArray _dst, bool swapb, bool fullRange )
+{
+ CvtHelper< Set<3, 4>, Set<3>, Set<CV_8U, CV_32F> > h(_src, _dst, 3);
+
+ hal::cvtBGRtoHSV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
+ h.depth, h.scn, swapb, fullRange, false);
+}
+
+void cvtColorBGR2HSV( InputArray _src, OutputArray _dst, bool swapb, bool fullRange )
+{
+ CvtHelper< Set<3, 4>, Set<3>, Set<CV_8U, CV_32F> > h(_src, _dst, 3);
+
+ hal::cvtBGRtoHSV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
+ h.depth, h.scn, swapb, fullRange, true);
+}
+
+void cvtColorHLS2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, bool fullRange)
+{
+ if(dcn <= 0) dcn = 3;
+ CvtHelper< Set<3>, Set<3, 4>, Set<CV_8U, CV_32F> > h(_src, _dst, dcn);
+
+ hal::cvtHSVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
+ h.depth, dcn, swapb, fullRange, false);
+}
+
+void cvtColorHSV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, bool fullRange)
+{
+ if(dcn <= 0) dcn = 3;
+ CvtHelper< Set<3>, Set<3, 4>, Set<CV_8U, CV_32F> > h(_src, _dst, dcn);
+
+ hal::cvtHSVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
+ h.depth, dcn, swapb, fullRange, true);
+}
+
+
+} // namespace cv
// of this distribution and at http://opencv.org/license.html
#include "precomp.hpp"
-#include "color.hpp"
+#include "opencv2/core/hal/intrin.hpp"
-namespace cv
-{
+namespace cv {
+namespace hal {
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+// forward declarations
+
+void cvtBGRtoHSV(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int scn, bool swapBlue, bool isFullRange, bool isHSV);
+void cvtHSVtoBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int dcn, bool swapBlue, bool isFullRange, bool isHSV);
+
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
+
+#if defined(CV_CPU_BASELINE_MODE)
+// included in color.hpp
+#else
+#include "color.simd_helpers.hpp"
+#endif
+namespace {
////////////////////////////////////// RGB <-> HSV ///////////////////////////////////////
#endif
};
-//
-// IPP functions
-//
-
-#if NEED_IPP
-
-#if !IPP_DISABLE_RGB_HSV
-static ippiGeneralFunc ippiRGB2HSVTab[] =
-{
- (ippiGeneralFunc)ippiRGBToHSV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHSV_16u_C3R, 0,
- 0, 0, 0, 0
-};
-#endif
-
-static ippiGeneralFunc ippiHSV2RGBTab[] =
-{
- (ippiGeneralFunc)ippiHSVToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHSVToRGB_16u_C3R, 0,
- 0, 0, 0, 0
-};
-
-static ippiGeneralFunc ippiRGB2HLSTab[] =
-{
- (ippiGeneralFunc)ippiRGBToHLS_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHLS_16u_C3R, 0,
- 0, (ippiGeneralFunc)ippiRGBToHLS_32f_C3R, 0, 0
-};
-
-static ippiGeneralFunc ippiHLS2RGBTab[] =
-{
- (ippiGeneralFunc)ippiHLSToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHLSToRGB_16u_C3R, 0,
- 0, (ippiGeneralFunc)ippiHLSToRGB_32f_C3R, 0, 0
-};
-
-#endif
-
-//
-// HAL functions
-//
-
-namespace hal
-{
+} // namespace anon
// 8u, 32f
void cvtBGRtoHSV(const uchar * src_data, size_t src_step,
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtBGRtoHSV, cv_hal_cvtBGRtoHSV, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isFullRange, isHSV);
-
-#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700
- CV_IPP_CHECK()
- {
- if(depth == CV_8U && isFullRange)
- {
- if (isHSV)
- {
-#if !IPP_DISABLE_RGB_HSV // breaks OCL accuracy tests
- if(scn == 3 && !swapBlue)
- {
- if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height,
- IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) )
- return;
- }
- else if(scn == 4 && !swapBlue)
- {
- if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) )
- return;
- }
- else if(scn == 4 && swapBlue)
- {
- if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 0, 1, 2, depth)) )
- return;
- }
-#endif
- }
- else
- {
- if(scn == 3 && !swapBlue)
- {
- if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height,
- IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) )
- return;
- }
- else if(scn == 4 && !swapBlue)
- {
- if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) )
- return;
- }
- else if(scn == 3 && swapBlue)
- {
- if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height,
- IPPGeneralFunctor(ippiRGB2HLSTab[depth])) )
- return;
- }
- else if(scn == 4 && swapBlue)
- {
- if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 0, 1, 2, depth)) )
- return;
- }
- }
- }
- }
-#endif
-
int hrange = depth == CV_32F ? 360 : isFullRange ? 256 : 180;
int blueIdx = swapBlue ? 2 : 0;
if(isHSV)
// 8u, 32f
void cvtHSVtoBGR(const uchar * src_data, size_t src_step,
- uchar * dst_data, size_t dst_step,
- int width, int height,
- int depth, int dcn, bool swapBlue, bool isFullRange, bool isHSV)
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int dcn, bool swapBlue, bool isFullRange, bool isHSV)
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtHSVtoBGR, cv_hal_cvtHSVtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isFullRange, isHSV);
-
-#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700
- CV_IPP_CHECK()
- {
- if (depth == CV_8U && isFullRange)
- {
- if (isHSV)
- {
- if(dcn == 3 && !swapBlue)
- {
- if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height,
- IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
- return;
- }
- else if(dcn == 4 && !swapBlue)
- {
- if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
- return;
- }
- else if(dcn == 3 && swapBlue)
- {
- if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height,
- IPPGeneralFunctor(ippiHSV2RGBTab[depth])) )
- return;
- }
- else if(dcn == 4 && swapBlue)
- {
- if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
- return;
- }
- }
- else
- {
- if(dcn == 3 && !swapBlue)
- {
- if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height,
- IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
- return;
- }
- else if(dcn == 4 && !swapBlue)
- {
- if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
- return;
- }
- else if(dcn == 3 && swapBlue)
- {
- if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height,
- IPPGeneralFunctor(ippiHLS2RGBTab[depth])) )
- return;
- }
- else if(dcn == 4 && swapBlue)
- {
- if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
- return;
- }
- }
- }
- }
-#endif
-
int hrange = depth == CV_32F ? 360 : isFullRange ? 255 : 180;
int blueIdx = swapBlue ? 2 : 0;
if(isHSV)
}
}
-} // namespace hal
-
-//
-// OCL calls
-//
-
-#ifdef HAVE_OPENCL
-
-bool oclCvtColorHSV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, bool full )
-{
- OclHelper< Set<3>, Set<3, 4>, Set<CV_8U, CV_32F> > h(_src, _dst, dcn);
-
- int hrange = _src.depth() == CV_32F ? 360 : (!full ? 180 : 255);
-
- if(!h.createKernel("HSV2RGB", ocl::imgproc::color_hsv_oclsrc,
- format("-D dcn=%d -D bidx=%d -D hrange=%d -D hscale=%ff", dcn, bidx, hrange, 6.f/hrange)))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColorHLS2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, bool full )
-{
- OclHelper< Set<3>, Set<3, 4>, Set<CV_8U, CV_32F> > h(_src, _dst, dcn);
-
- int hrange = _src.depth() == CV_32F ? 360 : (!full ? 180 : 255);
-
- if(!h.createKernel("HLS2RGB", ocl::imgproc::color_hsv_oclsrc,
- format("-D dcn=%d -D bidx=%d -D hrange=%d -D hscale=%ff", dcn, bidx, hrange, 6.f/hrange)))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColorBGR2HLS( InputArray _src, OutputArray _dst, int bidx, bool full )
-{
- OclHelper< Set<3, 4>, Set<3>, Set<CV_8U, CV_32F> > h(_src, _dst, 3);
-
- float hscale = (_src.depth() == CV_32F ? 360.f : (!full ? 180.f : 256.f))/360.f;
-
- if(!h.createKernel("RGB2HLS", ocl::imgproc::color_hsv_oclsrc,
- format("-D hscale=%ff -D bidx=%d -D dcn=3", hscale, bidx)))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColorBGR2HSV( InputArray _src, OutputArray _dst, int bidx, bool full )
-{
- OclHelper< Set<3, 4>, Set<3>, Set<CV_8U, CV_32F> > h(_src, _dst, 3);
-
- int hrange = _src.depth() == CV_32F ? 360 : (!full ? 180 : 256);
-
- cv::String options = (_src.depth() == CV_8U ?
- format("-D hrange=%d -D bidx=%d -D dcn=3", hrange, bidx) :
- format("-D hscale=%ff -D bidx=%d -D dcn=3", hrange*(1.f/360.f), bidx));
-
- if(!h.createKernel("RGB2HSV", ocl::imgproc::color_hsv_oclsrc, options))
- {
- return false;
- }
-
- if(_src.depth() == CV_8U)
- {
- static UMat sdiv_data;
- static UMat hdiv_data180;
- static UMat hdiv_data256;
- static int sdiv_table[256];
- static int hdiv_table180[256];
- static int hdiv_table256[256];
- static volatile bool initialized180 = false, initialized256 = false;
- volatile bool & initialized = hrange == 180 ? initialized180 : initialized256;
-
- if (!initialized)
- {
- int * const hdiv_table = hrange == 180 ? hdiv_table180 : hdiv_table256, hsv_shift = 12;
- UMat & hdiv_data = hrange == 180 ? hdiv_data180 : hdiv_data256;
-
- sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0;
-
- int v = 255 << hsv_shift;
- if (!initialized180 && !initialized256)
- {
- for(int i = 1; i < 256; i++ )
- sdiv_table[i] = saturate_cast<int>(v/(1.*i));
- Mat(1, 256, CV_32SC1, sdiv_table).copyTo(sdiv_data);
- }
-
- v = hrange << hsv_shift;
- for (int i = 1; i < 256; i++ )
- hdiv_table[i] = saturate_cast<int>(v/(6.*i));
-
- Mat(1, 256, CV_32SC1, hdiv_table).copyTo(hdiv_data);
- initialized = true;
- }
-
- h.setArg(ocl::KernelArg::PtrReadOnly(sdiv_data));
- h.setArg(hrange == 256 ? ocl::KernelArg::PtrReadOnly(hdiv_data256) :
- ocl::KernelArg::PtrReadOnly(hdiv_data180));
- }
-
- return h.run();
-}
-
#endif
-
-//
-// HAL calls
-//
-
-void cvtColorBGR2HLS( InputArray _src, OutputArray _dst, bool swapb, bool fullRange )
-{
- CvtHelper< Set<3, 4>, Set<3>, Set<CV_8U, CV_32F> > h(_src, _dst, 3);
-
- hal::cvtBGRtoHSV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
- h.depth, h.scn, swapb, fullRange, false);
-}
-
-void cvtColorBGR2HSV( InputArray _src, OutputArray _dst, bool swapb, bool fullRange )
-{
- CvtHelper< Set<3, 4>, Set<3>, Set<CV_8U, CV_32F> > h(_src, _dst, 3);
-
- hal::cvtBGRtoHSV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
- h.depth, h.scn, swapb, fullRange, true);
-}
-
-void cvtColorHLS2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, bool fullRange)
-{
- if(dcn <= 0) dcn = 3;
- CvtHelper< Set<3>, Set<3, 4>, Set<CV_8U, CV_32F> > h(_src, _dst, dcn);
-
- hal::cvtHSVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
- h.depth, dcn, swapb, fullRange, false);
-}
-
-void cvtColorHSV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, bool fullRange)
-{
- if(dcn <= 0) dcn = 3;
- CvtHelper< Set<3>, Set<3, 4>, Set<CV_8U, CV_32F> > h(_src, _dst, dcn);
-
- hal::cvtHSVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
- h.depth, dcn, swapb, fullRange, true);
-}
-
-
-} // namespace cv
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+}} // namespace
\**********************************************************************************/
#include "precomp.hpp"
+#include "opencl_kernels_imgproc.hpp"
+#include "opencv2/core/hal/intrin.hpp"
+#include "opencv2/core/softfloat.hpp"
+
#include "color.hpp"
using cv::softfloat;
--- /dev/null
+// 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 "precomp.hpp"
+#include "opencl_kernels_imgproc.hpp"
+
+#include "color.hpp"
+
+#include "color_rgb.simd.hpp"
+#include "color_rgb.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
+
+#define IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3 1
+
+namespace cv {
+
+//
+// IPP functions
+//
+
+#if NEED_IPP
+
+static const ippiColor2GrayFunc ippiColor2GrayC3Tab[] =
+{
+ (ippiColor2GrayFunc)ippiColorToGray_8u_C3C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_C3C1R, 0,
+ 0, (ippiColor2GrayFunc)ippiColorToGray_32f_C3C1R, 0, 0
+};
+
+static const ippiColor2GrayFunc ippiColor2GrayC4Tab[] =
+{
+ (ippiColor2GrayFunc)ippiColorToGray_8u_AC4C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_AC4C1R, 0,
+ 0, (ippiColor2GrayFunc)ippiColorToGray_32f_AC4C1R, 0, 0
+};
+
+static const ippiGeneralFunc ippiRGB2GrayC3Tab[] =
+{
+ (ippiGeneralFunc)ippiRGBToGray_8u_C3C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_C3C1R, 0,
+ 0, (ippiGeneralFunc)ippiRGBToGray_32f_C3C1R, 0, 0
+};
+
+static const ippiGeneralFunc ippiRGB2GrayC4Tab[] =
+{
+ (ippiGeneralFunc)ippiRGBToGray_8u_AC4C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_AC4C1R, 0,
+ 0, (ippiGeneralFunc)ippiRGBToGray_32f_AC4C1R, 0, 0
+};
+
+
+#if !IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3
+static IppStatus ippiGrayToRGB_C1C3R(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, IppiSize roiSize)
+{
+ return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_8u_C1C3R, pSrc, srcStep, pDst, dstStep, roiSize);
+}
+#endif
+static IppStatus ippiGrayToRGB_C1C3R(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep, IppiSize roiSize)
+{
+ return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_16u_C1C3R, pSrc, srcStep, pDst, dstStep, roiSize);
+}
+static IppStatus ippiGrayToRGB_C1C3R(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, IppiSize roiSize)
+{
+ return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_32f_C1C3R, pSrc, srcStep, pDst, dstStep, roiSize);
+}
+
+static IppStatus ippiGrayToRGB_C1C4R(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, IppiSize roiSize, Ipp8u aval)
+{
+ return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_8u_C1C4R, pSrc, srcStep, pDst, dstStep, roiSize, aval);
+}
+static IppStatus ippiGrayToRGB_C1C4R(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep, IppiSize roiSize, Ipp16u aval)
+{
+ return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_16u_C1C4R, pSrc, srcStep, pDst, dstStep, roiSize, aval);
+}
+static IppStatus ippiGrayToRGB_C1C4R(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, IppiSize roiSize, Ipp32f aval)
+{
+ return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_32f_C1C4R, pSrc, srcStep, pDst, dstStep, roiSize, aval);
+}
+
+struct IPPColor2GrayFunctor
+{
+ IPPColor2GrayFunctor(ippiColor2GrayFunc _func) :
+ ippiColorToGray(_func)
+ {
+ coeffs[0] = B2YF;
+ coeffs[1] = G2YF;
+ coeffs[2] = R2YF;
+ }
+ bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
+ {
+ return ippiColorToGray ? CV_INSTRUMENT_FUN_IPP(ippiColorToGray, src, srcStep, dst, dstStep, ippiSize(cols, rows), coeffs) >= 0 : false;
+ }
+private:
+ ippiColor2GrayFunc ippiColorToGray;
+ Ipp32f coeffs[3];
+};
+
+template <typename T>
+struct IPPGray2BGRFunctor
+{
+ IPPGray2BGRFunctor(){}
+
+ bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
+ {
+ return ippiGrayToRGB_C1C3R((T*)src, srcStep, (T*)dst, dstStep, ippiSize(cols, rows)) >= 0;
+ }
+};
+
+template <typename T>
+struct IPPGray2BGRAFunctor
+{
+ IPPGray2BGRAFunctor()
+ {
+ alpha = ColorChannel<T>::max();
+ }
+
+ bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
+ {
+ return ippiGrayToRGB_C1C4R((T*)src, srcStep, (T*)dst, dstStep, ippiSize(cols, rows), alpha) >= 0;
+ }
+
+ T alpha;
+};
+
+static IppStatus CV_STDCALL ippiSwapChannels_8u_C3C4Rf(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep,
+ IppiSize roiSize, const int *dstOrder)
+{
+ return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_8u_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP8u);
+}
+
+static IppStatus CV_STDCALL ippiSwapChannels_16u_C3C4Rf(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep,
+ IppiSize roiSize, const int *dstOrder)
+{
+ return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_16u_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP16u);
+}
+
+static IppStatus CV_STDCALL ippiSwapChannels_32f_C3C4Rf(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep,
+ IppiSize roiSize, const int *dstOrder)
+{
+ return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_32f_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP32f);
+}
+
+// shared
+ippiReorderFunc ippiSwapChannelsC3C4RTab[] =
+{
+ (ippiReorderFunc)ippiSwapChannels_8u_C3C4Rf, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3C4Rf, 0,
+ 0, (ippiReorderFunc)ippiSwapChannels_32f_C3C4Rf, 0, 0
+};
+
+static ippiGeneralFunc ippiCopyAC4C3RTab[] =
+{
+ (ippiGeneralFunc)ippiCopy_8u_AC4C3R, 0, (ippiGeneralFunc)ippiCopy_16u_AC4C3R, 0,
+ 0, (ippiGeneralFunc)ippiCopy_32f_AC4C3R, 0, 0
+};
+
+// shared
+ippiReorderFunc ippiSwapChannelsC4C3RTab[] =
+{
+ (ippiReorderFunc)ippiSwapChannels_8u_C4C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4C3R, 0,
+ 0, (ippiReorderFunc)ippiSwapChannels_32f_C4C3R, 0, 0
+};
+
+// shared
+ippiReorderFunc ippiSwapChannelsC3RTab[] =
+{
+ (ippiReorderFunc)ippiSwapChannels_8u_C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3R, 0,
+ 0, (ippiReorderFunc)ippiSwapChannels_32f_C3R, 0, 0
+};
+
+#if IPP_VERSION_X100 >= 810
+static ippiReorderFunc ippiSwapChannelsC4RTab[] =
+{
+ (ippiReorderFunc)ippiSwapChannels_8u_C4R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4R, 0,
+ 0, (ippiReorderFunc)ippiSwapChannels_32f_C4R, 0, 0
+};
+#endif
+
+#endif
+
+//
+// HAL functions
+//
+
+namespace hal {
+
+// 8u, 16u, 32f
+void cvtBGRtoBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int scn, int dcn, bool swapBlue)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtBGRtoBGR, cv_hal_cvtBGRtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, scn, dcn, swapBlue);
+
+#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700
+ CV_IPP_CHECK()
+ {
+ if(scn == 3 && dcn == 4 && !swapBlue)
+ {
+ if ( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 0, 1, 2)) )
+ return;
+ }
+ else if(scn == 4 && dcn == 3 && !swapBlue)
+ {
+ if ( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPGeneralFunctor(ippiCopyAC4C3RTab[depth])) )
+ return;
+ }
+ else if(scn == 3 && dcn == 4 && swapBlue)
+ {
+ if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 2, 1, 0)) )
+ return;
+ }
+ else if(scn == 4 && dcn == 3 && swapBlue)
+ {
+ if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPReorderFunctor(ippiSwapChannelsC4C3RTab[depth], 2, 1, 0)) )
+ return;
+ }
+ else if(scn == 3 && dcn == 3 && swapBlue)
+ {
+ if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height,
+ IPPReorderFunctor(ippiSwapChannelsC3RTab[depth], 2, 1, 0)) )
+ return;
+ }
+#if IPP_VERSION_X100 >= 810
+ else if(scn == 4 && dcn == 4 && swapBlue)
+ {
+ if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height,
+ IPPReorderFunctor(ippiSwapChannelsC4RTab[depth], 2, 1, 0)) )
+ return;
+ }
+ }
+#endif
+#endif
+
+ CV_CPU_DISPATCH(cvtBGRtoBGR, (src_data, src_step, dst_data, dst_step, width, height, depth, scn, dcn, swapBlue),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+// only 8u
+void cvtBGRtoBGR5x5(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int scn, bool swapBlue, int greenBits)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtBGRtoBGR5x5, cv_hal_cvtBGRtoBGR5x5, src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, greenBits);
+
+ CV_CPU_DISPATCH(cvtBGRtoBGR5x5, (src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, greenBits),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+// only 8u
+void cvtBGR5x5toBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int dcn, bool swapBlue, int greenBits)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtBGR5x5toBGR, cv_hal_cvtBGR5x5toBGR, src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, greenBits);
+
+ CV_CPU_DISPATCH(cvtBGR5x5toBGR, (src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, greenBits),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+// 8u, 16u, 32f
+void cvtBGRtoGray(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int scn, bool swapBlue)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtBGRtoGray, cv_hal_cvtBGRtoGray, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue);
+
+#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700
+ CV_IPP_CHECK()
+ {
+ if(depth == CV_32F && scn == 3 && !swapBlue)
+ {
+ if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPColor2GrayFunctor(ippiColor2GrayC3Tab[depth])) )
+ return;
+ }
+ else if(depth == CV_32F && scn == 3 && swapBlue)
+ {
+ if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPGeneralFunctor(ippiRGB2GrayC3Tab[depth])) )
+ return;
+ }
+ else if(depth == CV_32F && scn == 4 && !swapBlue)
+ {
+ if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPColor2GrayFunctor(ippiColor2GrayC4Tab[depth])) )
+ return;
+ }
+ else if(depth == CV_32F && scn == 4 && swapBlue)
+ {
+ if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPGeneralFunctor(ippiRGB2GrayC4Tab[depth])) )
+ return;
+ }
+ }
+#endif
+
+ CV_CPU_DISPATCH(cvtBGRtoGray, (src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+// 8u, 16u, 32f
+void cvtGraytoBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int dcn)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtGraytoBGR, cv_hal_cvtGraytoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn);
+
+#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700
+ CV_IPP_CHECK()
+ {
+ bool ippres = false;
+ if(dcn == 3)
+ {
+ if( depth == CV_8U )
+ {
+#if !IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3
+ ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor<Ipp8u>());
+#endif
+ }
+ else if( depth == CV_16U )
+ ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor<Ipp16u>());
+ else
+ ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor<Ipp32f>());
+ }
+ else if(dcn == 4)
+ {
+ if( depth == CV_8U )
+ ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRAFunctor<Ipp8u>());
+ else if( depth == CV_16U )
+ ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRAFunctor<Ipp16u>());
+ else
+ ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRAFunctor<Ipp32f>());
+ }
+ if(ippres)
+ return;
+ }
+#endif
+
+ CV_CPU_DISPATCH(cvtGraytoBGR, (src_data, src_step, dst_data, dst_step, width, height, depth, dcn),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+// only 8u
+void cvtBGR5x5toGray(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int greenBits)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtBGR5x5toGray, cv_hal_cvtBGR5x5toGray, src_data, src_step, dst_data, dst_step, width, height, greenBits);
+
+ CV_CPU_DISPATCH(cvtBGR5x5toGray, (src_data, src_step, dst_data, dst_step, width, height, greenBits),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+// only 8u
+void cvtGraytoBGR5x5(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int greenBits)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtGraytoBGR5x5, cv_hal_cvtGraytoBGR5x5, src_data, src_step, dst_data, dst_step, width, height, greenBits);
+
+ CV_CPU_DISPATCH(cvtGraytoBGR5x5, (src_data, src_step, dst_data, dst_step, width, height, greenBits),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void cvtRGBAtoMultipliedRGBA(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtRGBAtoMultipliedRGBA, cv_hal_cvtRGBAtoMultipliedRGBA, src_data, src_step, dst_data, dst_step, width, height);
+
+#ifdef HAVE_IPP
+ CV_IPP_CHECK()
+ {
+ if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPGeneralFunctor((ippiGeneralFunc)ippiAlphaPremul_8u_AC4R)))
+ return;
+ }
+#endif
+
+ CV_CPU_DISPATCH(cvtRGBAtoMultipliedRGBA, (src_data, src_step, dst_data, dst_step, width, height),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void cvtMultipliedRGBAtoRGBA(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtMultipliedRGBAtoRGBA, cv_hal_cvtMultipliedRGBAtoRGBA, src_data, src_step, dst_data, dst_step, width, height);
+
+ CV_CPU_DISPATCH(cvtMultipliedRGBAtoRGBA, (src_data, src_step, dst_data, dst_step, width, height),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+} // namespace hal
+
+//
+// OCL calls
+//
+
+#ifdef HAVE_OPENCL
+
+bool oclCvtColorBGR2BGR( InputArray _src, OutputArray _dst, int dcn, bool reverse )
+{
+ OclHelper< Set<3, 4>, Set<3, 4>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, dcn);
+
+ if(!h.createKernel("RGB", ocl::imgproc::color_rgb_oclsrc,
+ format("-D dcn=%d -D bidx=0 -D %s", dcn, reverse ? "REVERSE" : "ORDER")))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColorBGR25x5( InputArray _src, OutputArray _dst, int bidx, int gbits )
+{
+ OclHelper< Set<3, 4>, Set<2>, Set<CV_8U> > h(_src, _dst, 2);
+
+ if(!h.createKernel("RGB2RGB5x5", ocl::imgproc::color_rgb_oclsrc,
+ format("-D dcn=2 -D bidx=%d -D greenbits=%d", bidx, gbits)))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColor5x52BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int gbits)
+{
+ OclHelper< Set<2>, Set<3, 4>, Set<CV_8U> > h(_src, _dst, dcn);
+
+ if(!h.createKernel("RGB5x52RGB", ocl::imgproc::color_rgb_oclsrc,
+ format("-D dcn=%d -D bidx=%d -D greenbits=%d", dcn, bidx, gbits)))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColor5x52Gray( InputArray _src, OutputArray _dst, int gbits)
+{
+ OclHelper< Set<2>, Set<1>, Set<CV_8U> > h(_src, _dst, 1);
+
+ if(!h.createKernel("BGR5x52Gray", ocl::imgproc::color_rgb_oclsrc,
+ format("-D dcn=1 -D bidx=0 -D greenbits=%d", gbits)))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColorGray25x5( InputArray _src, OutputArray _dst, int gbits)
+{
+ OclHelper< Set<1>, Set<2>, Set<CV_8U> > h(_src, _dst, 2);
+
+ if(!h.createKernel("Gray2BGR5x5", ocl::imgproc::color_rgb_oclsrc,
+ format("-D dcn=2 -D bidx=0 -D greenbits=%d", gbits)))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColorBGR2Gray( InputArray _src, OutputArray _dst, int bidx)
+{
+ OclHelper< Set<3, 4>, Set<1>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, 1);
+
+ int stripeSize = 1;
+ if(!h.createKernel("RGB2Gray", ocl::imgproc::color_rgb_oclsrc,
+ format("-D dcn=1 -D bidx=%d -D STRIPE_SIZE=%d", bidx, stripeSize)))
+ {
+ return false;
+ }
+
+ h.globalSize[0] = (h.src.cols + stripeSize - 1)/stripeSize;
+ return h.run();
+}
+
+bool oclCvtColorGray2BGR( InputArray _src, OutputArray _dst, int dcn)
+{
+ OclHelper< Set<1>, Set<3, 4>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, dcn);
+ if(!h.createKernel("Gray2RGB", ocl::imgproc::color_rgb_oclsrc,
+ format("-D bidx=0 -D dcn=%d", dcn)))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColorRGBA2mRGBA( InputArray _src, OutputArray _dst)
+{
+ OclHelper< Set<4>, Set<4>, Set<CV_8U> > h(_src, _dst, 4);
+
+ if(!h.createKernel("RGBA2mRGBA", ocl::imgproc::color_rgb_oclsrc,
+ "-D dcn=4 -D bidx=3"))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColormRGBA2RGBA( InputArray _src, OutputArray _dst)
+{
+ OclHelper< Set<4>, Set<4>, Set<CV_8U> > h(_src, _dst, 4);
+
+ if(!h.createKernel("mRGBA2RGBA", ocl::imgproc::color_rgb_oclsrc,
+ "-D dcn=4 -D bidx=3"))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+#endif
+
+//
+// HAL calls
+//
+
+void cvtColorBGR2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb)
+{
+ CvtHelper< Set<3, 4>, Set<3, 4>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, dcn);
+
+ hal::cvtBGRtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
+ h.depth, h.scn, dcn, swapb);
+}
+
+void cvtColorBGR25x5( InputArray _src, OutputArray _dst, bool swapb, int gbits)
+{
+ CvtHelper< Set<3, 4>, Set<2>, Set<CV_8U> > h(_src, _dst, 2);
+
+ hal::cvtBGRtoBGR5x5(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
+ h.scn, swapb, gbits);
+}
+
+void cvtColor5x52BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int gbits)
+{
+ if(dcn <= 0) dcn = 3;
+ CvtHelper< Set<2>, Set<3, 4>, Set<CV_8U> > h(_src, _dst, dcn);
+
+ hal::cvtBGR5x5toBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
+ dcn, swapb, gbits);
+}
+
+void cvtColorBGR2Gray( InputArray _src, OutputArray _dst, bool swapb)
+{
+ CvtHelper< Set<3, 4>, Set<1>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, 1);
+
+ hal::cvtBGRtoGray(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
+ h.depth, h.scn, swapb);
+}
+
+void cvtColorGray2BGR( InputArray _src, OutputArray _dst, int dcn)
+{
+ if(dcn <= 0) dcn = 3;
+ CvtHelper< Set<1>, Set<3, 4>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, dcn);
+
+ hal::cvtGraytoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, h.depth, dcn);
+}
+
+void cvtColor5x52Gray( InputArray _src, OutputArray _dst, int gbits)
+{
+ CvtHelper< Set<2>, Set<1>, Set<CV_8U> > h(_src, _dst, 1);
+
+ hal::cvtBGR5x5toGray(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, gbits);
+}
+
+void cvtColorGray25x5( InputArray _src, OutputArray _dst, int gbits)
+{
+ CvtHelper< Set<1>, Set<2>, Set<CV_8U> > h(_src, _dst, 2);
+
+ hal::cvtGraytoBGR5x5(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, gbits);
+}
+
+void cvtColorRGBA2mRGBA( InputArray _src, OutputArray _dst)
+{
+ CvtHelper< Set<4>, Set<4>, Set<CV_8U> > h(_src, _dst, 4);
+
+ hal::cvtRGBAtoMultipliedRGBA(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows);
+}
+
+void cvtColormRGBA2RGBA( InputArray _src, OutputArray _dst)
+{
+ CvtHelper< Set<4>, Set<4>, Set<CV_8U> > h(_src, _dst, 4);
+
+ hal::cvtMultipliedRGBAtoRGBA(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows);
+}
+
+} // namespace cv
// of this distribution and at http://opencv.org/license.html
#include "precomp.hpp"
-#include "color.hpp"
+#include "opencv2/core/hal/intrin.hpp"
-#define IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3 1
+namespace cv {
+namespace hal {
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+// forward declarations
-namespace cv
-{
+void cvtBGRtoBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int scn, int dcn, bool swapBlue);
+void cvtBGRtoBGR5x5(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int scn, bool swapBlue, int greenBits);
+void cvtBGR5x5toBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int dcn, bool swapBlue, int greenBits);
+void cvtBGRtoGray(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int scn, bool swapBlue);
+void cvtGraytoBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int dcn);
+void cvtBGR5x5toGray(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int greenBits);
+void cvtGraytoBGR5x5(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int greenBits);
+void cvtRGBAtoMultipliedRGBA(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height);
+void cvtMultipliedRGBAtoRGBA(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height);
+
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
+
+#if defined(CV_CPU_BASELINE_MODE)
+// included in color.hpp
+#else
+#include "color.simd_helpers.hpp"
+#endif
+
+namespace {
////////////////// Various 3/4-channel to 3/4-channel RGB transformations /////////////////
template<typename _Tp> struct v_type;
}
}
};
-
-//
-// IPP functions
-//
-
-#if NEED_IPP
-
-static ippiColor2GrayFunc ippiColor2GrayC3Tab[] =
-{
- (ippiColor2GrayFunc)ippiColorToGray_8u_C3C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_C3C1R, 0,
- 0, (ippiColor2GrayFunc)ippiColorToGray_32f_C3C1R, 0, 0
-};
-
-static ippiColor2GrayFunc ippiColor2GrayC4Tab[] =
-{
- (ippiColor2GrayFunc)ippiColorToGray_8u_AC4C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_AC4C1R, 0,
- 0, (ippiColor2GrayFunc)ippiColorToGray_32f_AC4C1R, 0, 0
-};
-
-static ippiGeneralFunc ippiRGB2GrayC3Tab[] =
-{
- (ippiGeneralFunc)ippiRGBToGray_8u_C3C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_C3C1R, 0,
- 0, (ippiGeneralFunc)ippiRGBToGray_32f_C3C1R, 0, 0
-};
-
-static ippiGeneralFunc ippiRGB2GrayC4Tab[] =
-{
- (ippiGeneralFunc)ippiRGBToGray_8u_AC4C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_AC4C1R, 0,
- 0, (ippiGeneralFunc)ippiRGBToGray_32f_AC4C1R, 0, 0
-};
-
-
-#if !IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3
-static IppStatus ippiGrayToRGB_C1C3R(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, IppiSize roiSize)
-{
- return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_8u_C1C3R, pSrc, srcStep, pDst, dstStep, roiSize);
-}
-#endif
-static IppStatus ippiGrayToRGB_C1C3R(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep, IppiSize roiSize)
-{
- return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_16u_C1C3R, pSrc, srcStep, pDst, dstStep, roiSize);
-}
-static IppStatus ippiGrayToRGB_C1C3R(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, IppiSize roiSize)
-{
- return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_32f_C1C3R, pSrc, srcStep, pDst, dstStep, roiSize);
-}
-
-static IppStatus ippiGrayToRGB_C1C4R(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, IppiSize roiSize, Ipp8u aval)
-{
- return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_8u_C1C4R, pSrc, srcStep, pDst, dstStep, roiSize, aval);
-}
-static IppStatus ippiGrayToRGB_C1C4R(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep, IppiSize roiSize, Ipp16u aval)
-{
- return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_16u_C1C4R, pSrc, srcStep, pDst, dstStep, roiSize, aval);
-}
-static IppStatus ippiGrayToRGB_C1C4R(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, IppiSize roiSize, Ipp32f aval)
-{
- return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_32f_C1C4R, pSrc, srcStep, pDst, dstStep, roiSize, aval);
-}
-
-struct IPPColor2GrayFunctor
-{
- IPPColor2GrayFunctor(ippiColor2GrayFunc _func) :
- ippiColorToGray(_func)
- {
- coeffs[0] = B2YF;
- coeffs[1] = G2YF;
- coeffs[2] = R2YF;
- }
- bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
- {
- return ippiColorToGray ? CV_INSTRUMENT_FUN_IPP(ippiColorToGray, src, srcStep, dst, dstStep, ippiSize(cols, rows), coeffs) >= 0 : false;
- }
-private:
- ippiColor2GrayFunc ippiColorToGray;
- Ipp32f coeffs[3];
-};
-
-template <typename T>
-struct IPPGray2BGRFunctor
-{
- IPPGray2BGRFunctor(){}
-
- bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
- {
- return ippiGrayToRGB_C1C3R((T*)src, srcStep, (T*)dst, dstStep, ippiSize(cols, rows)) >= 0;
- }
-};
-
-template <typename T>
-struct IPPGray2BGRAFunctor
-{
- IPPGray2BGRAFunctor()
- {
- alpha = ColorChannel<T>::max();
- }
-
- bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
- {
- return ippiGrayToRGB_C1C4R((T*)src, srcStep, (T*)dst, dstStep, ippiSize(cols, rows), alpha) >= 0;
- }
-
- T alpha;
-};
-
-static IppStatus CV_STDCALL ippiSwapChannels_8u_C3C4Rf(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep,
- IppiSize roiSize, const int *dstOrder)
-{
- return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_8u_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP8u);
-}
-
-static IppStatus CV_STDCALL ippiSwapChannels_16u_C3C4Rf(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep,
- IppiSize roiSize, const int *dstOrder)
-{
- return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_16u_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP16u);
-}
-
-static IppStatus CV_STDCALL ippiSwapChannels_32f_C3C4Rf(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep,
- IppiSize roiSize, const int *dstOrder)
-{
- return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_32f_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP32f);
-}
-
-// shared
-ippiReorderFunc ippiSwapChannelsC3C4RTab[] =
-{
- (ippiReorderFunc)ippiSwapChannels_8u_C3C4Rf, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3C4Rf, 0,
- 0, (ippiReorderFunc)ippiSwapChannels_32f_C3C4Rf, 0, 0
-};
-
-static ippiGeneralFunc ippiCopyAC4C3RTab[] =
-{
- (ippiGeneralFunc)ippiCopy_8u_AC4C3R, 0, (ippiGeneralFunc)ippiCopy_16u_AC4C3R, 0,
- 0, (ippiGeneralFunc)ippiCopy_32f_AC4C3R, 0, 0
-};
-
-// shared
-ippiReorderFunc ippiSwapChannelsC4C3RTab[] =
-{
- (ippiReorderFunc)ippiSwapChannels_8u_C4C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4C3R, 0,
- 0, (ippiReorderFunc)ippiSwapChannels_32f_C4C3R, 0, 0
-};
-
-// shared
-ippiReorderFunc ippiSwapChannelsC3RTab[] =
-{
- (ippiReorderFunc)ippiSwapChannels_8u_C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3R, 0,
- 0, (ippiReorderFunc)ippiSwapChannels_32f_C3R, 0, 0
-};
-
-#if IPP_VERSION_X100 >= 810
-static ippiReorderFunc ippiSwapChannelsC4RTab[] =
-{
- (ippiReorderFunc)ippiSwapChannels_8u_C4R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4R, 0,
- 0, (ippiReorderFunc)ippiSwapChannels_32f_C4R, 0, 0
-};
-#endif
-
-#endif
-
-//
-// HAL functions
-//
-
-namespace hal
-{
+} // namespace anon
// 8u, 16u, 32f
void cvtBGRtoBGR(const uchar * src_data, size_t src_step,
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtBGRtoBGR, cv_hal_cvtBGRtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, scn, dcn, swapBlue);
-
-#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700
- CV_IPP_CHECK()
- {
- if(scn == 3 && dcn == 4 && !swapBlue)
- {
- if ( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 0, 1, 2)) )
- return;
- }
- else if(scn == 4 && dcn == 3 && !swapBlue)
- {
- if ( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPGeneralFunctor(ippiCopyAC4C3RTab[depth])) )
- return;
- }
- else if(scn == 3 && dcn == 4 && swapBlue)
- {
- if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 2, 1, 0)) )
- return;
- }
- else if(scn == 4 && dcn == 3 && swapBlue)
- {
- if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPReorderFunctor(ippiSwapChannelsC4C3RTab[depth], 2, 1, 0)) )
- return;
- }
- else if(scn == 3 && dcn == 3 && swapBlue)
- {
- if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height,
- IPPReorderFunctor(ippiSwapChannelsC3RTab[depth], 2, 1, 0)) )
- return;
- }
-#if IPP_VERSION_X100 >= 810
- else if(scn == 4 && dcn == 4 && swapBlue)
- {
- if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height,
- IPPReorderFunctor(ippiSwapChannelsC4RTab[depth], 2, 1, 0)) )
- return;
- }
- }
-#endif
-#endif
-
int blueIdx = swapBlue ? 2 : 0;
if( depth == CV_8U )
CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2RGB<uchar>(scn, dcn, blueIdx));
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtBGRtoBGR5x5, cv_hal_cvtBGRtoBGR5x5, src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, greenBits);
-
CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2RGB5x5(scn, swapBlue ? 2 : 0, greenBits));
}
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtBGR5x5toBGR, cv_hal_cvtBGR5x5toBGR, src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, greenBits);
-
CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB5x52RGB(dcn, swapBlue ? 2 : 0, greenBits));
}
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtBGRtoGray, cv_hal_cvtBGRtoGray, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue);
-
-#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700
- CV_IPP_CHECK()
- {
- if(depth == CV_32F && scn == 3 && !swapBlue)
- {
- if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPColor2GrayFunctor(ippiColor2GrayC3Tab[depth])) )
- return;
- }
- else if(depth == CV_32F && scn == 3 && swapBlue)
- {
- if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPGeneralFunctor(ippiRGB2GrayC3Tab[depth])) )
- return;
- }
- else if(depth == CV_32F && scn == 4 && !swapBlue)
- {
- if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPColor2GrayFunctor(ippiColor2GrayC4Tab[depth])) )
- return;
- }
- else if(depth == CV_32F && scn == 4 && swapBlue)
- {
- if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPGeneralFunctor(ippiRGB2GrayC4Tab[depth])) )
- return;
- }
- }
-#endif
-
int blueIdx = swapBlue ? 2 : 0;
if( depth == CV_8U )
CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2Gray<uchar>(scn, blueIdx, 0));
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtGraytoBGR, cv_hal_cvtGraytoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn);
-
-#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700
- CV_IPP_CHECK()
- {
- bool ippres = false;
- if(dcn == 3)
- {
- if( depth == CV_8U )
- {
-#if !IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3
- ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor<Ipp8u>());
-#endif
- }
- else if( depth == CV_16U )
- ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor<Ipp16u>());
- else
- ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor<Ipp32f>());
- }
- else if(dcn == 4)
- {
- if( depth == CV_8U )
- ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRAFunctor<Ipp8u>());
- else if( depth == CV_16U )
- ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRAFunctor<Ipp16u>());
- else
- ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRAFunctor<Ipp32f>());
- }
- if(ippres)
- return;
- }
-#endif
-
if( depth == CV_8U )
CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, Gray2RGB<uchar>(dcn));
else if( depth == CV_16U )
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtBGR5x5toGray, cv_hal_cvtBGR5x5toGray, src_data, src_step, dst_data, dst_step, width, height, greenBits);
CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB5x52Gray(greenBits));
}
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtGraytoBGR5x5, cv_hal_cvtGraytoBGR5x5, src_data, src_step, dst_data, dst_step, width, height, greenBits);
CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, Gray2RGB5x5(greenBits));
}
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtRGBAtoMultipliedRGBA, cv_hal_cvtRGBAtoMultipliedRGBA, src_data, src_step, dst_data, dst_step, width, height);
-
-#ifdef HAVE_IPP
- CV_IPP_CHECK()
- {
- if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPGeneralFunctor((ippiGeneralFunc)ippiAlphaPremul_8u_AC4R)))
- return;
- }
-#endif
-
CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGBA2mRGBA<uchar>());
}
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtMultipliedRGBAtoRGBA, cv_hal_cvtMultipliedRGBAtoRGBA, src_data, src_step, dst_data, dst_step, width, height);
CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, mRGBA2RGBA<uchar>());
}
-} // namespace hal
-
-//
-// OCL calls
-//
-
-#ifdef HAVE_OPENCL
-
-bool oclCvtColorBGR2BGR( InputArray _src, OutputArray _dst, int dcn, bool reverse )
-{
- OclHelper< Set<3, 4>, Set<3, 4>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, dcn);
-
- if(!h.createKernel("RGB", ocl::imgproc::color_rgb_oclsrc,
- format("-D dcn=%d -D bidx=0 -D %s", dcn, reverse ? "REVERSE" : "ORDER")))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColorBGR25x5( InputArray _src, OutputArray _dst, int bidx, int gbits )
-{
- OclHelper< Set<3, 4>, Set<2>, Set<CV_8U> > h(_src, _dst, 2);
-
- if(!h.createKernel("RGB2RGB5x5", ocl::imgproc::color_rgb_oclsrc,
- format("-D dcn=2 -D bidx=%d -D greenbits=%d", bidx, gbits)))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColor5x52BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int gbits)
-{
- OclHelper< Set<2>, Set<3, 4>, Set<CV_8U> > h(_src, _dst, dcn);
-
- if(!h.createKernel("RGB5x52RGB", ocl::imgproc::color_rgb_oclsrc,
- format("-D dcn=%d -D bidx=%d -D greenbits=%d", dcn, bidx, gbits)))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColor5x52Gray( InputArray _src, OutputArray _dst, int gbits)
-{
- OclHelper< Set<2>, Set<1>, Set<CV_8U> > h(_src, _dst, 1);
-
- if(!h.createKernel("BGR5x52Gray", ocl::imgproc::color_rgb_oclsrc,
- format("-D dcn=1 -D bidx=0 -D greenbits=%d", gbits)))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColorGray25x5( InputArray _src, OutputArray _dst, int gbits)
-{
- OclHelper< Set<1>, Set<2>, Set<CV_8U> > h(_src, _dst, 2);
-
- if(!h.createKernel("Gray2BGR5x5", ocl::imgproc::color_rgb_oclsrc,
- format("-D dcn=2 -D bidx=0 -D greenbits=%d", gbits)))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColorBGR2Gray( InputArray _src, OutputArray _dst, int bidx)
-{
- OclHelper< Set<3, 4>, Set<1>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, 1);
-
- int stripeSize = 1;
- if(!h.createKernel("RGB2Gray", ocl::imgproc::color_rgb_oclsrc,
- format("-D dcn=1 -D bidx=%d -D STRIPE_SIZE=%d", bidx, stripeSize)))
- {
- return false;
- }
-
- h.globalSize[0] = (h.src.cols + stripeSize - 1)/stripeSize;
- return h.run();
-}
-
-bool oclCvtColorGray2BGR( InputArray _src, OutputArray _dst, int dcn)
-{
- OclHelper< Set<1>, Set<3, 4>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, dcn);
- if(!h.createKernel("Gray2RGB", ocl::imgproc::color_rgb_oclsrc,
- format("-D bidx=0 -D dcn=%d", dcn)))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColorRGBA2mRGBA( InputArray _src, OutputArray _dst)
-{
- OclHelper< Set<4>, Set<4>, Set<CV_8U> > h(_src, _dst, 4);
-
- if(!h.createKernel("RGBA2mRGBA", ocl::imgproc::color_rgb_oclsrc,
- "-D dcn=4 -D bidx=3"))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColormRGBA2RGBA( InputArray _src, OutputArray _dst)
-{
- OclHelper< Set<4>, Set<4>, Set<CV_8U> > h(_src, _dst, 4);
-
- if(!h.createKernel("mRGBA2RGBA", ocl::imgproc::color_rgb_oclsrc,
- "-D dcn=4 -D bidx=3"))
- {
- return false;
- }
-
- return h.run();
-}
-
#endif
-
-//
-// HAL calls
-//
-
-void cvtColorBGR2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb)
-{
- CvtHelper< Set<3, 4>, Set<3, 4>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, dcn);
-
- hal::cvtBGRtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
- h.depth, h.scn, dcn, swapb);
-}
-
-void cvtColorBGR25x5( InputArray _src, OutputArray _dst, bool swapb, int gbits)
-{
- CvtHelper< Set<3, 4>, Set<2>, Set<CV_8U> > h(_src, _dst, 2);
-
- hal::cvtBGRtoBGR5x5(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
- h.scn, swapb, gbits);
-}
-
-void cvtColor5x52BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int gbits)
-{
- if(dcn <= 0) dcn = 3;
- CvtHelper< Set<2>, Set<3, 4>, Set<CV_8U> > h(_src, _dst, dcn);
-
- hal::cvtBGR5x5toBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
- dcn, swapb, gbits);
-}
-
-void cvtColorBGR2Gray( InputArray _src, OutputArray _dst, bool swapb)
-{
- CvtHelper< Set<3, 4>, Set<1>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, 1);
-
- hal::cvtBGRtoGray(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
- h.depth, h.scn, swapb);
-}
-
-void cvtColorGray2BGR( InputArray _src, OutputArray _dst, int dcn)
-{
- if(dcn <= 0) dcn = 3;
- CvtHelper< Set<1>, Set<3, 4>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, dcn);
-
- hal::cvtGraytoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, h.depth, dcn);
-}
-
-void cvtColor5x52Gray( InputArray _src, OutputArray _dst, int gbits)
-{
- CvtHelper< Set<2>, Set<1>, Set<CV_8U> > h(_src, _dst, 1);
-
- hal::cvtBGR5x5toGray(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, gbits);
-}
-
-void cvtColorGray25x5( InputArray _src, OutputArray _dst, int gbits)
-{
- CvtHelper< Set<1>, Set<2>, Set<CV_8U> > h(_src, _dst, 2);
-
- hal::cvtGraytoBGR5x5(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, gbits);
-}
-
-void cvtColorRGBA2mRGBA( InputArray _src, OutputArray _dst)
-{
- CvtHelper< Set<4>, Set<4>, Set<CV_8U> > h(_src, _dst, 4);
-
- hal::cvtRGBAtoMultipliedRGBA(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows);
-}
-
-void cvtColormRGBA2RGBA( InputArray _src, OutputArray _dst)
-{
- CvtHelper< Set<4>, Set<4>, Set<CV_8U> > h(_src, _dst, 4);
-
- hal::cvtMultipliedRGBAtoRGBA(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows);
-}
-
-} // namespace cv
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+}} // namespace
--- /dev/null
+// 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 "precomp.hpp"
+#include "opencl_kernels_imgproc.hpp"
+
+#include "color.hpp"
+
+#include "color_yuv.simd.hpp"
+#include "color_yuv.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
+
+namespace cv {
+
+//
+// HAL functions
+//
+namespace hal {
+
+// 8u, 16u, 32f
+void cvtBGRtoYUV(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int scn, bool swapBlue, bool isCbCr)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtBGRtoYUV, cv_hal_cvtBGRtoYUV, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isCbCr);
+
+#if defined(HAVE_IPP)
+#if !IPP_DISABLE_RGB_YUV
+ CV_IPP_CHECK()
+ {
+ if (scn == 3 && depth == CV_8U && swapBlue && !isCbCr)
+ {
+ if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPGeneralFunctor((ippiGeneralFunc)ippiRGBToYUV_8u_C3R)))
+ return;
+ }
+ else if (scn == 3 && depth == CV_8U && !swapBlue && !isCbCr)
+ {
+ if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
+ (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth)))
+ return;
+ }
+ else if (scn == 4 && depth == CV_8U && swapBlue && !isCbCr)
+ {
+ if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
+ (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 0, 1, 2, depth)))
+ return;
+ }
+ else if (scn == 4 && depth == CV_8U && !swapBlue && !isCbCr)
+ {
+ if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
+ (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth)))
+ return;
+ }
+ }
+#endif
+#endif
+
+ CV_CPU_DISPATCH(cvtBGRtoYUV, (src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isCbCr),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void cvtYUVtoBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int dcn, bool swapBlue, bool isCbCr)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtYUVtoBGR, cv_hal_cvtYUVtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isCbCr);
+
+
+#if defined(HAVE_IPP)
+#if !IPP_DISABLE_YUV_RGB
+ CV_IPP_CHECK()
+ {
+ if (dcn == 3 && depth == CV_8U && swapBlue && !isCbCr)
+ {
+ if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPGeneralFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R)))
+ return;
+ }
+ else if (dcn == 3 && depth == CV_8U && !swapBlue && !isCbCr)
+ {
+ if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
+ ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)))
+ return;
+ }
+ else if (dcn == 4 && depth == CV_8U && swapBlue && !isCbCr)
+ {
+ if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
+ ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)))
+ return;
+ }
+ else if (dcn == 4 && depth == CV_8U && !swapBlue && !isCbCr)
+ {
+ if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
+ IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
+ ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)))
+ return;
+ }
+ }
+#endif
+#endif
+
+ CV_CPU_DISPATCH(cvtYUVtoBGR, (src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isCbCr),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void cvtTwoPlaneYUVtoBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int dst_width, int dst_height,
+ int dcn, bool swapBlue, int uIdx)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtTwoPlaneYUVtoBGR, cv_hal_cvtTwoPlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx);
+
+ CV_CPU_DISPATCH(cvtTwoPlaneYUVtoBGR, (src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void cvtTwoPlaneYUVtoBGR(const uchar * y_data, const uchar * uv_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int dst_width, int dst_height,
+ int dcn, bool swapBlue, int uIdx)
+{
+ CV_INSTRUMENT_REGION();
+
+ CV_CPU_DISPATCH(cvtTwoPlaneYUVtoBGR, (y_data, uv_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void cvtThreePlaneYUVtoBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int dst_width, int dst_height,
+ int dcn, bool swapBlue, int uIdx)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtThreePlaneYUVtoBGR, cv_hal_cvtThreePlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx);
+
+ CV_CPU_DISPATCH(cvtThreePlaneYUVtoBGR, (src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void cvtBGRtoThreePlaneYUV(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int scn, bool swapBlue, int uIdx)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtBGRtoThreePlaneYUV, cv_hal_cvtBGRtoThreePlaneYUV, src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, uIdx);
+
+ CV_CPU_DISPATCH(cvtBGRtoThreePlaneYUV, (src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, uIdx),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void cvtBGRtoTwoPlaneYUV(const uchar * src_data, size_t src_step,
+ uchar * y_data, uchar * uv_data, size_t dst_step,
+ int width, int height,
+ int scn, bool swapBlue, int uIdx)
+{
+ CV_INSTRUMENT_REGION();
+
+ // TODO: add hal replacement method
+
+ CV_CPU_DISPATCH(cvtBGRtoTwoPlaneYUV, (src_data, src_step, y_data, uv_data, dst_step, width, height, scn, swapBlue, uIdx),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int dcn, bool swapBlue, int uIdx, int ycn)
+{
+ CV_INSTRUMENT_REGION();
+
+ CALL_HAL(cvtOnePlaneYUVtoBGR, cv_hal_cvtOnePlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, uIdx, ycn);
+
+ CV_CPU_DISPATCH(cvtOnePlaneYUVtoBGR, (src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, uIdx, ycn),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+} // namespace hal
+
+//
+// OCL calls
+//
+
+#ifdef HAVE_OPENCL
+
+bool oclCvtColorYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx )
+{
+ OclHelper< Set<3>, Set<3, 4>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, dcn);
+
+ if(!h.createKernel("YUV2RGB", ocl::imgproc::color_yuv_oclsrc,
+ format("-D dcn=%d -D bidx=%d", dcn, bidx)))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColorBGR2YUV( InputArray _src, OutputArray _dst, int bidx )
+{
+ OclHelper< Set<3, 4>, Set<3>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, 3);
+
+ if(!h.createKernel("RGB2YUV", ocl::imgproc::color_yuv_oclsrc,
+ format("-D dcn=3 -D bidx=%d", bidx)))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtcolorYCrCb2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx)
+{
+ OclHelper< Set<3>, Set<3, 4>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, dcn);
+
+ if(!h.createKernel("YCrCb2RGB", ocl::imgproc::color_yuv_oclsrc,
+ format("-D dcn=%d -D bidx=%d", dcn, bidx)))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColorBGR2YCrCb( InputArray _src, OutputArray _dst, int bidx)
+{
+ OclHelper< Set<3, 4>, Set<3>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, 3);
+
+ if(!h.createKernel("RGB2YCrCb", ocl::imgproc::color_yuv_oclsrc,
+ format("-D dcn=3 -D bidx=%d", bidx)))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColorOnePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx, int yidx )
+{
+ OclHelper< Set<2>, Set<3, 4>, Set<CV_8U> > h(_src, _dst, dcn);
+
+ bool optimized = _src.offset() % 4 == 0 && _src.step() % 4 == 0;
+ if(!h.createKernel("YUV2RGB_422", ocl::imgproc::color_yuv_oclsrc,
+ format("-D dcn=%d -D bidx=%d -D uidx=%d -D yidx=%d%s", dcn, bidx, uidx, yidx,
+ optimized ? " -D USE_OPTIMIZED_LOAD" : "")))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColorYUV2Gray_420( InputArray _src, OutputArray _dst )
+{
+ OclHelper< Set<1>, Set<1>, Set<CV_8U>, FROM_YUV> h(_src, _dst, 1);
+
+ h.src.rowRange(0, _dst.rows()).copyTo(_dst);
+ return true;
+}
+
+bool oclCvtColorTwoPlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx )
+{
+ OclHelper< Set<1>, Set<3, 4>, Set<CV_8U>, FROM_YUV > h(_src, _dst, dcn);
+
+ if(!h.createKernel("YUV2RGB_NVx", ocl::imgproc::color_yuv_oclsrc,
+ format("-D dcn=%d -D bidx=%d -D uidx=%d", dcn, bidx, uidx)))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColorThreePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx )
+{
+ OclHelper< Set<1>, Set<3, 4>, Set<CV_8U>, FROM_YUV > h(_src, _dst, dcn);
+
+ if(!h.createKernel("YUV2RGB_YV12_IYUV", ocl::imgproc::color_yuv_oclsrc,
+ format("-D dcn=%d -D bidx=%d -D uidx=%d%s", dcn, bidx, uidx,
+ _src.isContinuous() ? " -D SRC_CONT" : "")))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+bool oclCvtColorBGR2ThreePlaneYUV( InputArray _src, OutputArray _dst, int bidx, int uidx )
+{
+ OclHelper< Set<3, 4>, Set<1>, Set<CV_8U>, TO_YUV > h(_src, _dst, 1);
+
+ if(!h.createKernel("RGB2YUV_YV12_IYUV", ocl::imgproc::color_yuv_oclsrc,
+ format("-D dcn=1 -D bidx=%d -D uidx=%d", bidx, uidx)))
+ {
+ return false;
+ }
+
+ return h.run();
+}
+
+#endif
+
+//
+// HAL calls
+//
+
+void cvtColorBGR2YUV(InputArray _src, OutputArray _dst, bool swapb, bool crcb)
+{
+ CvtHelper< Set<3, 4>, Set<3>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, 3);
+
+ hal::cvtBGRtoYUV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
+ h.depth, h.scn, swapb, crcb);
+}
+
+void cvtColorYUV2BGR(InputArray _src, OutputArray _dst, int dcn, bool swapb, bool crcb)
+{
+ if(dcn <= 0) dcn = 3;
+ CvtHelper< Set<3>, Set<3, 4>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, dcn);
+
+ hal::cvtYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
+ h.depth, dcn, swapb, crcb);
+}
+
+void cvtColorOnePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx, int ycn)
+{
+ CvtHelper< Set<2>, Set<3, 4>, Set<CV_8U> > h(_src, _dst, dcn);
+
+ hal::cvtOnePlaneYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
+ dcn, swapb, uidx, ycn);
+}
+
+void cvtColorYUV2Gray_ch( InputArray _src, OutputArray _dst, int coi )
+{
+ CV_Assert( _src.channels() == 2 && _src.depth() == CV_8U );
+
+ extractChannel(_src, _dst, coi);
+}
+
+void cvtColorBGR2ThreePlaneYUV( InputArray _src, OutputArray _dst, bool swapb, int uidx)
+{
+ CvtHelper< Set<3, 4>, Set<1>, Set<CV_8U>, TO_YUV > h(_src, _dst, 1);
+
+ hal::cvtBGRtoThreePlaneYUV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
+ h.scn, swapb, uidx);
+}
+
+void cvtColorYUV2Gray_420( InputArray _src, OutputArray _dst )
+{
+ CvtHelper< Set<1>, Set<1>, Set<CV_8U>, FROM_YUV > h(_src, _dst, 1);
+
+#ifdef HAVE_IPP
+#if IPP_VERSION_X100 >= 201700
+ if (CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1R_L, h.src.data, (IppSizeL)h.src.step, h.dst.data, (IppSizeL)h.dst.step,
+ ippiSizeL(h.dstSz.width, h.dstSz.height)) >= 0)
+ return;
+#endif
+#endif
+ h.src(Range(0, h.dstSz.height), Range::all()).copyTo(h.dst);
+}
+
+void cvtColorThreePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx)
+{
+ if(dcn <= 0) dcn = 3;
+ CvtHelper< Set<1>, Set<3, 4>, Set<CV_8U>, FROM_YUV> h(_src, _dst, dcn);
+
+ hal::cvtThreePlaneYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.dst.cols, h.dst.rows,
+ dcn, swapb, uidx);
+}
+
+// http://www.fourcc.org/yuv.php#NV21 == yuv420sp -> a plane of 8 bit Y samples followed by an interleaved V/U plane containing 8 bit 2x2 subsampled chroma samples
+// http://www.fourcc.org/yuv.php#NV12 -> a plane of 8 bit Y samples followed by an interleaved U/V plane containing 8 bit 2x2 subsampled colour difference samples
+
+void cvtColorTwoPlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx )
+{
+ if(dcn <= 0) dcn = 3;
+ CvtHelper< Set<1>, Set<3, 4>, Set<CV_8U>, FROM_YUV> h(_src, _dst, dcn);
+
+ hal::cvtTwoPlaneYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.dst.cols, h.dst.rows,
+ dcn, swapb, uidx);
+}
+
+void cvtColorTwoPlaneYUV2BGRpair( InputArray _ysrc, InputArray _uvsrc, OutputArray _dst, int dcn, bool swapb, int uidx )
+{
+ int stype = _ysrc.type();
+ int depth = CV_MAT_DEPTH(stype);
+ Size ysz = _ysrc.size(), uvs = _uvsrc.size();
+ CV_Assert( dcn == 3 || dcn == 4 );
+ CV_Assert( depth == CV_8U );
+ CV_Assert( ysz.width == uvs.width * 2 && ysz.height == uvs.height * 2 );
+
+ Mat ysrc = _ysrc.getMat(), uvsrc = _uvsrc.getMat();
+
+ _dst.create( ysz, CV_MAKETYPE(depth, dcn));
+ Mat dst = _dst.getMat();
+
+ hal::cvtTwoPlaneYUVtoBGR(ysrc.data, uvsrc.data, ysrc.step,
+ dst.data, dst.step, dst.cols, dst.rows,
+ dcn, swapb, uidx);
+}
+
+} // namespace cv
// of this distribution and at http://opencv.org/license.html
#include "precomp.hpp"
-#include "color.hpp"
+#include "opencv2/core/hal/intrin.hpp"
-namespace cv
-{
+namespace cv {
+namespace hal {
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+// forward declarations
+void cvtBGRtoYUV(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int scn, bool swapBlue, bool isCbCr);
+void cvtYUVtoBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int depth, int dcn, bool swapBlue, bool isCbCr);
+void cvtTwoPlaneYUVtoBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int dst_width, int dst_height,
+ int dcn, bool swapBlue, int uIdx);
+void cvtTwoPlaneYUVtoBGR(const uchar * y_data, const uchar * uv_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int dst_width, int dst_height,
+ int dcn, bool swapBlue, int uIdx);
+void cvtThreePlaneYUVtoBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int dst_width, int dst_height,
+ int dcn, bool swapBlue, int uIdx);
+void cvtBGRtoThreePlaneYUV(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int scn, bool swapBlue, int uIdx);
+void cvtBGRtoTwoPlaneYUV(const uchar * src_data, size_t src_step,
+ uchar * y_data, uchar * uv_data, size_t dst_step,
+ int width, int height,
+ int scn, bool swapBlue, int uIdx);
+void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int dcn, bool swapBlue, int uIdx, int ycn);
+
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
+
+#if defined(CV_CPU_BASELINE_MODE)
+// included in color.hpp
+#else
+#include "color.simd_helpers.hpp"
+#endif
+namespace {
//constants for conversion from/to RGB and YUV, YCrCb according to BT.601
//to YCbCr
converter(Range(0, height));
}
-//
-// HAL functions
-//
+} // namespace anon
-namespace hal
-{
// 8u, 16u, 32f
void cvtBGRtoYUV(const uchar * src_data, size_t src_step,
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtBGRtoYUV, cv_hal_cvtBGRtoYUV, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isCbCr);
-
-#if defined(HAVE_IPP)
-#if !IPP_DISABLE_RGB_YUV
- CV_IPP_CHECK()
- {
- if (scn == 3 && depth == CV_8U && swapBlue && !isCbCr)
- {
- if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPGeneralFunctor((ippiGeneralFunc)ippiRGBToYUV_8u_C3R)))
- return;
- }
- else if (scn == 3 && depth == CV_8U && !swapBlue && !isCbCr)
- {
- if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
- (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth)))
- return;
- }
- else if (scn == 4 && depth == CV_8U && swapBlue && !isCbCr)
- {
- if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
- (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 0, 1, 2, depth)))
- return;
- }
- else if (scn == 4 && depth == CV_8U && !swapBlue && !isCbCr)
- {
- if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
- (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth)))
- return;
- }
- }
-#endif
-#endif
-
int blueIdx = swapBlue ? 2 : 0;
if( depth == CV_8U )
CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2YCrCb_i<uchar>(scn, blueIdx, isCbCr));
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtYUVtoBGR, cv_hal_cvtYUVtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isCbCr);
-
-
-#if defined(HAVE_IPP)
-#if !IPP_DISABLE_YUV_RGB
- CV_IPP_CHECK()
- {
- if (dcn == 3 && depth == CV_8U && swapBlue && !isCbCr)
- {
- if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPGeneralFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R)))
- return;
- }
- else if (dcn == 3 && depth == CV_8U && !swapBlue && !isCbCr)
- {
- if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
- ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)))
- return;
- }
- else if (dcn == 4 && depth == CV_8U && swapBlue && !isCbCr)
- {
- if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
- ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)))
- return;
- }
- else if (dcn == 4 && depth == CV_8U && !swapBlue && !isCbCr)
- {
- if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height,
- IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
- ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)))
- return;
- }
- }
-#endif
-#endif
-
int blueIdx = swapBlue ? 2 : 0;
if( depth == CV_8U )
CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, YCrCb2RGB_i<uchar>(dcn, blueIdx, isCbCr));
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtTwoPlaneYUVtoBGR, cv_hal_cvtTwoPlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx);
const uchar* uv = src_data + src_step * static_cast<size_t>(dst_height);
cvtTwoPlaneYUVtoBGR(src_data, uv, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx);
}
{
CV_INSTRUMENT_REGION();
- // TODO: add hal replacement method
-
int blueIdx = swapBlue ? 2 : 0;
cvt_2plane_yuv_ptr_t cvtPtr;
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtThreePlaneYUVtoBGR, cv_hal_cvtThreePlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx);
const uchar* u = src_data + src_step * static_cast<size_t>(dst_height);
const uchar* v = src_data + src_step * static_cast<size_t>(dst_height + dst_height/4) + (dst_width/2) * ((dst_height % 4)/2);
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtBGRtoThreePlaneYUV, cv_hal_cvtBGRtoThreePlaneYUV, src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, uIdx);
uchar * uv_data = dst_data + dst_step * height;
RGB8toYUV420pInvoker cvt(src_data, src_step, dst_data, uv_data, dst_step, width, height,
{
CV_INSTRUMENT_REGION();
- // TODO: add hal replacement method
-
RGB8toYUV420pInvoker cvt(src_data, src_step, y_data, uv_data, dst_step, width, height,
scn, swapBlue, uIdx == 2, true);
{
CV_INSTRUMENT_REGION();
- CALL_HAL(cvtOnePlaneYUVtoBGR, cv_hal_cvtOnePlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, uIdx, ycn);
-
cvt_1plane_yuv_ptr_t cvtPtr;
int blueIdx = swapBlue ? 2 : 0;
switch(dcn*1000 + blueIdx*100 + uIdx*10 + ycn)
cvtPtr(dst_data, dst_step, src_data, src_step, width, height);
}
-} // namespace hal
-
-//
-// OCL calls
-//
-
-#ifdef HAVE_OPENCL
-
-bool oclCvtColorYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx )
-{
- OclHelper< Set<3>, Set<3, 4>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, dcn);
-
- if(!h.createKernel("YUV2RGB", ocl::imgproc::color_yuv_oclsrc,
- format("-D dcn=%d -D bidx=%d", dcn, bidx)))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColorBGR2YUV( InputArray _src, OutputArray _dst, int bidx )
-{
- OclHelper< Set<3, 4>, Set<3>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, 3);
-
- if(!h.createKernel("RGB2YUV", ocl::imgproc::color_yuv_oclsrc,
- format("-D dcn=3 -D bidx=%d", bidx)))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtcolorYCrCb2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx)
-{
- OclHelper< Set<3>, Set<3, 4>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, dcn);
-
- if(!h.createKernel("YCrCb2RGB", ocl::imgproc::color_yuv_oclsrc,
- format("-D dcn=%d -D bidx=%d", dcn, bidx)))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColorBGR2YCrCb( InputArray _src, OutputArray _dst, int bidx)
-{
- OclHelper< Set<3, 4>, Set<3>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, 3);
-
- if(!h.createKernel("RGB2YCrCb", ocl::imgproc::color_yuv_oclsrc,
- format("-D dcn=3 -D bidx=%d", bidx)))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColorOnePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx, int yidx )
-{
- OclHelper< Set<2>, Set<3, 4>, Set<CV_8U> > h(_src, _dst, dcn);
-
- bool optimized = _src.offset() % 4 == 0 && _src.step() % 4 == 0;
- if(!h.createKernel("YUV2RGB_422", ocl::imgproc::color_yuv_oclsrc,
- format("-D dcn=%d -D bidx=%d -D uidx=%d -D yidx=%d%s", dcn, bidx, uidx, yidx,
- optimized ? " -D USE_OPTIMIZED_LOAD" : "")))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColorYUV2Gray_420( InputArray _src, OutputArray _dst )
-{
- OclHelper< Set<1>, Set<1>, Set<CV_8U>, FROM_YUV> h(_src, _dst, 1);
-
- h.src.rowRange(0, _dst.rows()).copyTo(_dst);
- return true;
-}
-
-bool oclCvtColorTwoPlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx )
-{
- OclHelper< Set<1>, Set<3, 4>, Set<CV_8U>, FROM_YUV > h(_src, _dst, dcn);
-
- if(!h.createKernel("YUV2RGB_NVx", ocl::imgproc::color_yuv_oclsrc,
- format("-D dcn=%d -D bidx=%d -D uidx=%d", dcn, bidx, uidx)))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColorThreePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx )
-{
- OclHelper< Set<1>, Set<3, 4>, Set<CV_8U>, FROM_YUV > h(_src, _dst, dcn);
-
- if(!h.createKernel("YUV2RGB_YV12_IYUV", ocl::imgproc::color_yuv_oclsrc,
- format("-D dcn=%d -D bidx=%d -D uidx=%d%s", dcn, bidx, uidx,
- _src.isContinuous() ? " -D SRC_CONT" : "")))
- {
- return false;
- }
-
- return h.run();
-}
-
-bool oclCvtColorBGR2ThreePlaneYUV( InputArray _src, OutputArray _dst, int bidx, int uidx )
-{
- OclHelper< Set<3, 4>, Set<1>, Set<CV_8U>, TO_YUV > h(_src, _dst, 1);
-
- if(!h.createKernel("RGB2YUV_YV12_IYUV", ocl::imgproc::color_yuv_oclsrc,
- format("-D dcn=1 -D bidx=%d -D uidx=%d", bidx, uidx)))
- {
- return false;
- }
-
- return h.run();
-}
-
#endif
-
-//
-// HAL calls
-//
-
-void cvtColorBGR2YUV(InputArray _src, OutputArray _dst, bool swapb, bool crcb)
-{
- CvtHelper< Set<3, 4>, Set<3>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, 3);
-
- hal::cvtBGRtoYUV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
- h.depth, h.scn, swapb, crcb);
-}
-
-void cvtColorYUV2BGR(InputArray _src, OutputArray _dst, int dcn, bool swapb, bool crcb)
-{
- if(dcn <= 0) dcn = 3;
- CvtHelper< Set<3>, Set<3, 4>, Set<CV_8U, CV_16U, CV_32F> > h(_src, _dst, dcn);
-
- hal::cvtYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
- h.depth, dcn, swapb, crcb);
-}
-
-void cvtColorOnePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx, int ycn)
-{
- CvtHelper< Set<2>, Set<3, 4>, Set<CV_8U> > h(_src, _dst, dcn);
-
- hal::cvtOnePlaneYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
- dcn, swapb, uidx, ycn);
-}
-
-void cvtColorYUV2Gray_ch( InputArray _src, OutputArray _dst, int coi )
-{
- CV_Assert( _src.channels() == 2 && _src.depth() == CV_8U );
-
- extractChannel(_src, _dst, coi);
-}
-
-void cvtColorBGR2ThreePlaneYUV( InputArray _src, OutputArray _dst, bool swapb, int uidx)
-{
- CvtHelper< Set<3, 4>, Set<1>, Set<CV_8U>, TO_YUV > h(_src, _dst, 1);
-
- hal::cvtBGRtoThreePlaneYUV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows,
- h.scn, swapb, uidx);
-}
-
-void cvtColorYUV2Gray_420( InputArray _src, OutputArray _dst )
-{
- CvtHelper< Set<1>, Set<1>, Set<CV_8U>, FROM_YUV > h(_src, _dst, 1);
-
-#ifdef HAVE_IPP
-#if IPP_VERSION_X100 >= 201700
- if (CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1R_L, h.src.data, (IppSizeL)h.src.step, h.dst.data, (IppSizeL)h.dst.step,
- ippiSizeL(h.dstSz.width, h.dstSz.height)) >= 0)
- return;
-#endif
-#endif
- h.src(Range(0, h.dstSz.height), Range::all()).copyTo(h.dst);
-}
-
-void cvtColorThreePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx)
-{
- if(dcn <= 0) dcn = 3;
- CvtHelper< Set<1>, Set<3, 4>, Set<CV_8U>, FROM_YUV> h(_src, _dst, dcn);
-
- hal::cvtThreePlaneYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.dst.cols, h.dst.rows,
- dcn, swapb, uidx);
-}
-
-// http://www.fourcc.org/yuv.php#NV21 == yuv420sp -> a plane of 8 bit Y samples followed by an interleaved V/U plane containing 8 bit 2x2 subsampled chroma samples
-// http://www.fourcc.org/yuv.php#NV12 -> a plane of 8 bit Y samples followed by an interleaved U/V plane containing 8 bit 2x2 subsampled colour difference samples
-
-void cvtColorTwoPlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx )
-{
- if(dcn <= 0) dcn = 3;
- CvtHelper< Set<1>, Set<3, 4>, Set<CV_8U>, FROM_YUV> h(_src, _dst, dcn);
-
- hal::cvtTwoPlaneYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.dst.cols, h.dst.rows,
- dcn, swapb, uidx);
-}
-
-void cvtColorTwoPlaneYUV2BGRpair( InputArray _ysrc, InputArray _uvsrc, OutputArray _dst, int dcn, bool swapb, int uidx )
-{
- int stype = _ysrc.type();
- int depth = CV_MAT_DEPTH(stype);
- Size ysz = _ysrc.size(), uvs = _uvsrc.size();
- CV_Assert( dcn == 3 || dcn == 4 );
- CV_Assert( depth == CV_8U );
- CV_Assert( ysz.width == uvs.width * 2 && ysz.height == uvs.height * 2 );
-
- Mat ysrc = _ysrc.getMat(), uvsrc = _uvsrc.getMat();
-
- _dst.create( ysz, CV_MAKETYPE(depth, dcn));
- Mat dst = _dst.getMat();
-
- hal::cvtTwoPlaneYUVtoBGR(ysrc.data, uvsrc.data, ysrc.step,
- dst.data, dst.step, dst.cols, dst.rows,
- dcn, swapb, uidx);
-}
-
-} // namespace cv
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+}} // namespace
+++ /dev/null
-/*M///////////////////////////////////////////////////////////////////////////////////////
-//
-// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
-//
-// By downloading, copying, installing or using the software you agree to this license.
-// If you do not agree to this license, do not download, install,
-// copy or use the software.
-//
-//
-// License Agreement
-// For Open Source Computer Vision Library
-//
-// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
-// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
-// Third party copyrights are property of their respective owners.
-//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-// * Redistribution's of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// * Redistribution's in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// * The name of the copyright holders may not be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// This software is provided by the copyright holders and contributors "as is" and
-// any express or implied warranties, including, but not limited to, the implied
-// warranties of merchantability and fitness for a particular purpose are disclaimed.
-// In no event shall the Intel Corporation or contributors be liable for any direct,
-// indirect, incidental, special, exemplary, or consequential damages
-// (including, but not limited to, procurement of substitute goods or services;
-// loss of use, data, or profits; or business interruption) however caused
-// and on any theory of liability, whether in contract, strict liability,
-// or tort (including negligence or otherwise) arising in any way out of
-// the use of this software, even if advised of the possibility of such damage.
-//
-//M*/
-
-#include "precomp.hpp"
-#include "filter.hpp"
-
-namespace cv
-{
-
-int RowVec_32f_AVX(const float* src0, const float* _kx, float* dst, int width, int cn, int _ksize)
-{
- int i = 0, k;
- for (; i <= width - 8; i += 8)
- {
- const float* src = src0 + i;
- __m256 f, x0;
- __m256 s0 = _mm256_set1_ps(0.0f);
- for (k = 0; k < _ksize; k++, src += cn)
- {
- f = _mm256_set1_ps(_kx[k]);
- x0 = _mm256_loadu_ps(src);
-#if CV_FMA3
- s0 = _mm256_fmadd_ps(x0, f, s0);
-#else
- s0 = _mm256_add_ps(s0, _mm256_mul_ps(x0, f));
-#endif
- }
- _mm256_storeu_ps(dst + i, s0);
- }
- _mm256_zeroupper();
- return i;
-}
-
-int SymmColumnVec_32f_Symm_AVX(const float** src, const float* ky, float* dst, float delta, int width, int ksize2)
-{
- int i = 0, k;
- const float *S, *S2;
- const __m128 d4 = _mm_set1_ps(delta);
- const __m256 d8 = _mm256_set1_ps(delta);
-
- for( ; i <= width - 16; i += 16 )
- {
- __m256 f = _mm256_set1_ps(ky[0]);
- __m256 s0, s1;
- __m256 x0;
- S = src[0] + i;
- s0 = _mm256_loadu_ps(S);
-#if CV_FMA3
- s0 = _mm256_fmadd_ps(s0, f, d8);
-#else
- s0 = _mm256_add_ps(_mm256_mul_ps(s0, f), d8);
-#endif
- s1 = _mm256_loadu_ps(S+8);
-#if CV_FMA3
- s1 = _mm256_fmadd_ps(s1, f, d8);
-#else
- s1 = _mm256_add_ps(_mm256_mul_ps(s1, f), d8);
-#endif
-
- for( k = 1; k <= ksize2; k++ )
- {
- S = src[k] + i;
- S2 = src[-k] + i;
- f = _mm256_set1_ps(ky[k]);
- x0 = _mm256_add_ps(_mm256_loadu_ps(S), _mm256_loadu_ps(S2));
-#if CV_FMA3
- s0 = _mm256_fmadd_ps(x0, f, s0);
-#else
- s0 = _mm256_add_ps(s0, _mm256_mul_ps(x0, f));
-#endif
- x0 = _mm256_add_ps(_mm256_loadu_ps(S+8), _mm256_loadu_ps(S2+8));
-#if CV_FMA3
- s1 = _mm256_fmadd_ps(x0, f, s1);
-#else
- s1 = _mm256_add_ps(s1, _mm256_mul_ps(x0, f));
-#endif
- }
-
- _mm256_storeu_ps(dst + i, s0);
- _mm256_storeu_ps(dst + i + 8, s1);
- }
-
- for( ; i <= width - 4; i += 4 )
- {
- __m128 f = _mm_set1_ps(ky[0]);
- __m128 x0, s0 = _mm_load_ps(src[0] + i);
- s0 = _mm_add_ps(_mm_mul_ps(s0, f), d4);
-
- for( k = 1; k <= ksize2; k++ )
- {
- f = _mm_set1_ps(ky[k]);
- x0 = _mm_add_ps(_mm_load_ps(src[k]+i), _mm_load_ps(src[-k] + i));
- s0 = _mm_add_ps(s0, _mm_mul_ps(x0, f));
- }
-
- _mm_storeu_ps(dst + i, s0);
- }
-
- _mm256_zeroupper();
- return i;
-}
-
-int SymmColumnVec_32f_Unsymm_AVX(const float** src, const float* ky, float* dst, float delta, int width, int ksize2)
-{
- int i = 0, k;
- const float *S2;
- const __m128 d4 = _mm_set1_ps(delta);
- const __m256 d8 = _mm256_set1_ps(delta);
-
- for (; i <= width - 16; i += 16)
- {
- __m256 f, s0 = d8, s1 = d8;
- __m256 x0;
-
- for (k = 1; k <= ksize2; k++)
- {
- const float *S = src[k] + i;
- S2 = src[-k] + i;
- f = _mm256_set1_ps(ky[k]);
- x0 = _mm256_sub_ps(_mm256_loadu_ps(S), _mm256_loadu_ps(S2));
-#if CV_FMA3
- s0 = _mm256_fmadd_ps(x0, f, s0);
-#else
- s0 = _mm256_add_ps(s0, _mm256_mul_ps(x0, f));
-#endif
- x0 = _mm256_sub_ps(_mm256_loadu_ps(S + 8), _mm256_loadu_ps(S2 + 8));
-#if CV_FMA3
- s1 = _mm256_fmadd_ps(x0, f, s1);
-#else
- s1 = _mm256_add_ps(s1, _mm256_mul_ps(x0, f));
-#endif
- }
-
- _mm256_storeu_ps(dst + i, s0);
- _mm256_storeu_ps(dst + i + 8, s1);
- }
-
- for (; i <= width - 4; i += 4)
- {
- __m128 f, x0, s0 = d4;
-
- for (k = 1; k <= ksize2; k++)
- {
- f = _mm_set1_ps(ky[k]);
- x0 = _mm_sub_ps(_mm_load_ps(src[k] + i), _mm_load_ps(src[-k] + i));
- s0 = _mm_add_ps(s0, _mm_mul_ps(x0, f));
- }
-
- _mm_storeu_ps(dst + i, s0);
- }
-
- _mm256_zeroupper();
- return i;
-}
-
-}
-
-/* End of file. */
--- /dev/null
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "precomp.hpp"
+#include "opencv2/core/opencl/ocl_defs.hpp"
+#include "opencl_kernels_imgproc.hpp"
+#include "hal_replacement.hpp"
+#include "opencv2/core/hal/intrin.hpp"
+#include "filter.hpp"
+
+#include "filter.simd.hpp"
+#include "filter.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
+
+
+/****************************************************************************************\
+ Base Image Filter
+\****************************************************************************************/
+
+namespace cv {
+
+BaseRowFilter::BaseRowFilter() { ksize = anchor = -1; }
+BaseRowFilter::~BaseRowFilter() {}
+
+BaseColumnFilter::BaseColumnFilter() { ksize = anchor = -1; }
+BaseColumnFilter::~BaseColumnFilter() {}
+void BaseColumnFilter::reset() {}
+
+BaseFilter::BaseFilter() { ksize = Size(-1,-1); anchor = Point(-1,-1); }
+BaseFilter::~BaseFilter() {}
+void BaseFilter::reset() {}
+
+FilterEngine::FilterEngine()
+ : srcType(-1), dstType(-1), bufType(-1), maxWidth(0), wholeSize(-1, -1), dx1(0), dx2(0),
+ rowBorderType(BORDER_REPLICATE), columnBorderType(BORDER_REPLICATE),
+ borderElemSize(0), bufStep(0), startY(0), startY0(0), endY(0), rowCount(0), dstY(0)
+{
+}
+
+
+FilterEngine::FilterEngine( const Ptr<BaseFilter>& _filter2D,
+ const Ptr<BaseRowFilter>& _rowFilter,
+ const Ptr<BaseColumnFilter>& _columnFilter,
+ int _srcType, int _dstType, int _bufType,
+ int _rowBorderType, int _columnBorderType,
+ const Scalar& _borderValue )
+ : srcType(-1), dstType(-1), bufType(-1), maxWidth(0), wholeSize(-1, -1), dx1(0), dx2(0),
+ rowBorderType(BORDER_REPLICATE), columnBorderType(BORDER_REPLICATE),
+ borderElemSize(0), bufStep(0), startY(0), startY0(0), endY(0), rowCount(0), dstY(0)
+{
+ init(_filter2D, _rowFilter, _columnFilter, _srcType, _dstType, _bufType,
+ _rowBorderType, _columnBorderType, _borderValue);
+}
+
+FilterEngine::~FilterEngine()
+{
+}
+
+
+void FilterEngine::init( const Ptr<BaseFilter>& _filter2D,
+ const Ptr<BaseRowFilter>& _rowFilter,
+ const Ptr<BaseColumnFilter>& _columnFilter,
+ int _srcType, int _dstType, int _bufType,
+ int _rowBorderType, int _columnBorderType,
+ const Scalar& _borderValue )
+{
+ _srcType = CV_MAT_TYPE(_srcType);
+ _bufType = CV_MAT_TYPE(_bufType);
+ _dstType = CV_MAT_TYPE(_dstType);
+
+ srcType = _srcType;
+ int srcElemSize = (int)getElemSize(srcType);
+ dstType = _dstType;
+ bufType = _bufType;
+
+ filter2D = _filter2D;
+ rowFilter = _rowFilter;
+ columnFilter = _columnFilter;
+
+ if( _columnBorderType < 0 )
+ _columnBorderType = _rowBorderType;
+
+ rowBorderType = _rowBorderType;
+ columnBorderType = _columnBorderType;
+
+ CV_Assert( columnBorderType != BORDER_WRAP );
+
+ if( isSeparable() )
+ {
+ CV_Assert( rowFilter && columnFilter );
+ ksize = Size(rowFilter->ksize, columnFilter->ksize);
+ anchor = Point(rowFilter->anchor, columnFilter->anchor);
+ }
+ else
+ {
+ CV_Assert( bufType == srcType );
+ ksize = filter2D->ksize;
+ anchor = filter2D->anchor;
+ }
+
+ CV_Assert( 0 <= anchor.x && anchor.x < ksize.width &&
+ 0 <= anchor.y && anchor.y < ksize.height );
+
+ borderElemSize = srcElemSize/(CV_MAT_DEPTH(srcType) >= CV_32S ? sizeof(int) : 1);
+ int borderLength = std::max(ksize.width - 1, 1);
+ borderTab.resize(borderLength*borderElemSize);
+
+ maxWidth = bufStep = 0;
+ constBorderRow.clear();
+
+ if( rowBorderType == BORDER_CONSTANT || columnBorderType == BORDER_CONSTANT )
+ {
+ constBorderValue.resize(srcElemSize*borderLength);
+ int srcType1 = CV_MAKETYPE(CV_MAT_DEPTH(srcType), MIN(CV_MAT_CN(srcType), 4));
+ scalarToRawData(_borderValue, &constBorderValue[0], srcType1,
+ borderLength*CV_MAT_CN(srcType));
+ }
+
+ wholeSize = Size(-1,-1);
+}
+
+#define VEC_ALIGN CV_MALLOC_ALIGN
+
+int FilterEngine::start(const Size& _wholeSize, const Size& sz, const Point& ofs)
+{
+ CV_INSTRUMENT_REGION();
+
+ CV_CPU_DISPATCH(FilterEngine__start, (*this, _wholeSize, sz, ofs),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+
+int FilterEngine::start(const Mat& src, const Size &wsz, const Point &ofs)
+{
+ start( wsz, src.size(), ofs);
+ return startY - ofs.y;
+}
+
+int FilterEngine::remainingInputRows() const
+{
+ return endY - startY - rowCount;
+}
+
+int FilterEngine::remainingOutputRows() const
+{
+ return roi.height - dstY;
+}
+
+int FilterEngine::proceed(const uchar* src, int srcstep, int count,
+ uchar* dst, int dststep)
+{
+ CV_INSTRUMENT_REGION();
+
+ CV_Assert( wholeSize.width > 0 && wholeSize.height > 0 );
+
+ CV_CPU_DISPATCH(FilterEngine__proceed, (*this, src, srcstep, count, dst, dststep),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+void FilterEngine::apply(const Mat& src, Mat& dst, const Size& wsz, const Point& ofs)
+{
+ CV_INSTRUMENT_REGION();
+
+ CV_CheckTypeEQ(src.type(), srcType, "");
+ CV_CheckTypeEQ(dst.type(), dstType, "");
+
+ CV_CPU_DISPATCH(FilterEngine__apply, (*this, src, dst, wsz, ofs),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+/****************************************************************************************\
+* Separable linear filter *
+\****************************************************************************************/
+
+int getKernelType(InputArray filter_kernel, Point anchor)
+{
+ Mat _kernel = filter_kernel.getMat();
+ CV_Assert( _kernel.channels() == 1 );
+ int i, sz = _kernel.rows*_kernel.cols;
+
+ Mat kernel;
+ _kernel.convertTo(kernel, CV_64F);
+
+ const double* coeffs = kernel.ptr<double>();
+ double sum = 0;
+ int type = KERNEL_SMOOTH + KERNEL_INTEGER;
+ if( (_kernel.rows == 1 || _kernel.cols == 1) &&
+ anchor.x*2 + 1 == _kernel.cols &&
+ anchor.y*2 + 1 == _kernel.rows )
+ type |= (KERNEL_SYMMETRICAL + KERNEL_ASYMMETRICAL);
+
+ for( i = 0; i < sz; i++ )
+ {
+ double a = coeffs[i], b = coeffs[sz - i - 1];
+ if( a != b )
+ type &= ~KERNEL_SYMMETRICAL;
+ if( a != -b )
+ type &= ~KERNEL_ASYMMETRICAL;
+ if( a < 0 )
+ type &= ~KERNEL_SMOOTH;
+ if( a != saturate_cast<int>(a) )
+ type &= ~KERNEL_INTEGER;
+ sum += a;
+ }
+
+ if( fabs(sum - 1) > FLT_EPSILON*(fabs(sum) + 1) )
+ type &= ~KERNEL_SMOOTH;
+ return type;
+}
+
+
+Ptr<BaseRowFilter> getLinearRowFilter(
+ int srcType, int bufType,
+ InputArray _kernel, int anchor,
+ int symmetryType)
+{
+ CV_INSTRUMENT_REGION();
+
+ Mat kernelMat = _kernel.getMat();
+ CV_CPU_DISPATCH(getLinearRowFilter, (srcType, bufType, kernelMat, anchor, symmetryType),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+
+Ptr<BaseColumnFilter> getLinearColumnFilter(
+ int bufType, int dstType,
+ InputArray kernel, int anchor,
+ int symmetryType, double delta,
+ int bits)
+{
+ CV_INSTRUMENT_REGION();
+
+ Mat kernelMat = kernel.getMat();
+ CV_CPU_DISPATCH(getLinearColumnFilter, (bufType, dstType, kernelMat, anchor, symmetryType, delta, bits),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+
+Ptr<FilterEngine> createSeparableLinearFilter(
+ int _srcType, int _dstType,
+ InputArray __rowKernel, InputArray __columnKernel,
+ Point _anchor, double _delta,
+ int _rowBorderType, int _columnBorderType,
+ const Scalar& _borderValue)
+{
+ Mat _rowKernel = __rowKernel.getMat(), _columnKernel = __columnKernel.getMat();
+ _srcType = CV_MAT_TYPE(_srcType);
+ _dstType = CV_MAT_TYPE(_dstType);
+ int sdepth = CV_MAT_DEPTH(_srcType), ddepth = CV_MAT_DEPTH(_dstType);
+ int cn = CV_MAT_CN(_srcType);
+ CV_Assert( cn == CV_MAT_CN(_dstType) );
+ int rsize = _rowKernel.rows + _rowKernel.cols - 1;
+ int csize = _columnKernel.rows + _columnKernel.cols - 1;
+ if( _anchor.x < 0 )
+ _anchor.x = rsize/2;
+ if( _anchor.y < 0 )
+ _anchor.y = csize/2;
+ int rtype = getKernelType(_rowKernel,
+ _rowKernel.rows == 1 ? Point(_anchor.x, 0) : Point(0, _anchor.x));
+ int ctype = getKernelType(_columnKernel,
+ _columnKernel.rows == 1 ? Point(_anchor.y, 0) : Point(0, _anchor.y));
+ Mat rowKernel, columnKernel;
+
+ int bdepth = std::max(CV_32F,std::max(sdepth, ddepth));
+ int bits = 0;
+
+ if( sdepth == CV_8U &&
+ ((rtype == KERNEL_SMOOTH+KERNEL_SYMMETRICAL &&
+ ctype == KERNEL_SMOOTH+KERNEL_SYMMETRICAL &&
+ ddepth == CV_8U) ||
+ ((rtype & (KERNEL_SYMMETRICAL+KERNEL_ASYMMETRICAL)) &&
+ (ctype & (KERNEL_SYMMETRICAL+KERNEL_ASYMMETRICAL)) &&
+ (rtype & ctype & KERNEL_INTEGER) &&
+ ddepth == CV_16S)) )
+ {
+ bdepth = CV_32S;
+ bits = ddepth == CV_8U ? 8 : 0;
+ _rowKernel.convertTo( rowKernel, CV_32S, 1 << bits );
+ _columnKernel.convertTo( columnKernel, CV_32S, 1 << bits );
+ bits *= 2;
+ _delta *= (1 << bits);
+ }
+ else
+ {
+ if( _rowKernel.type() != bdepth )
+ _rowKernel.convertTo( rowKernel, bdepth );
+ else
+ rowKernel = _rowKernel;
+ if( _columnKernel.type() != bdepth )
+ _columnKernel.convertTo( columnKernel, bdepth );
+ else
+ columnKernel = _columnKernel;
+ }
+
+ int _bufType = CV_MAKETYPE(bdepth, cn);
+ Ptr<BaseRowFilter> _rowFilter = getLinearRowFilter(
+ _srcType, _bufType, rowKernel, _anchor.x, rtype);
+ Ptr<BaseColumnFilter> _columnFilter = getLinearColumnFilter(
+ _bufType, _dstType, columnKernel, _anchor.y, ctype, _delta, bits );
+
+ return Ptr<FilterEngine>( new FilterEngine(Ptr<BaseFilter>(), _rowFilter, _columnFilter,
+ _srcType, _dstType, _bufType, _rowBorderType, _columnBorderType, _borderValue ));
+}
+
+
+/****************************************************************************************\
+* Non-separable linear filter *
+\****************************************************************************************/
+
+void preprocess2DKernel( const Mat& kernel, std::vector<Point>& coords, std::vector<uchar>& coeffs )
+{
+ int i, j, k, nz = countNonZero(kernel), ktype = kernel.type();
+ if(nz == 0)
+ nz = 1;
+ CV_Assert( ktype == CV_8U || ktype == CV_32S || ktype == CV_32F || ktype == CV_64F );
+ coords.resize(nz);
+ coeffs.resize(nz*getElemSize(ktype));
+ uchar* _coeffs = &coeffs[0];
+
+ for( i = k = 0; i < kernel.rows; i++ )
+ {
+ const uchar* krow = kernel.ptr(i);
+ for( j = 0; j < kernel.cols; j++ )
+ {
+ if( ktype == CV_8U )
+ {
+ uchar val = krow[j];
+ if( val == 0 )
+ continue;
+ coords[k] = Point(j,i);
+ _coeffs[k++] = val;
+ }
+ else if( ktype == CV_32S )
+ {
+ int val = ((const int*)krow)[j];
+ if( val == 0 )
+ continue;
+ coords[k] = Point(j,i);
+ ((int*)_coeffs)[k++] = val;
+ }
+ else if( ktype == CV_32F )
+ {
+ float val = ((const float*)krow)[j];
+ if( val == 0 )
+ continue;
+ coords[k] = Point(j,i);
+ ((float*)_coeffs)[k++] = val;
+ }
+ else
+ {
+ double val = ((const double*)krow)[j];
+ if( val == 0 )
+ continue;
+ coords[k] = Point(j,i);
+ ((double*)_coeffs)[k++] = val;
+ }
+ }
+ }
+}
+
+
+template<typename ST, class CastOp, class VecOp> struct Filter2D : public BaseFilter
+{
+ typedef typename CastOp::type1 KT;
+ typedef typename CastOp::rtype DT;
+
+ Filter2D( const Mat& _kernel, Point _anchor,
+ double _delta, const CastOp& _castOp=CastOp(),
+ const VecOp& _vecOp=VecOp() )
+ {
+ anchor = _anchor;
+ ksize = _kernel.size();
+ delta = saturate_cast<KT>(_delta);
+ castOp0 = _castOp;
+ vecOp = _vecOp;
+ CV_Assert( _kernel.type() == DataType<KT>::type );
+ preprocess2DKernel( _kernel, coords, coeffs );
+ ptrs.resize( coords.size() );
+ }
+
+ void operator()(const uchar** src, uchar* dst, int dststep, int count, int width, int cn) CV_OVERRIDE
+ {
+ KT _delta = delta;
+ const Point* pt = &coords[0];
+ const KT* kf = (const KT*)&coeffs[0];
+ const ST** kp = (const ST**)&ptrs[0];
+ int i, k, nz = (int)coords.size();
+ CastOp castOp = castOp0;
+
+ width *= cn;
+ for( ; count > 0; count--, dst += dststep, src++ )
+ {
+ DT* D = (DT*)dst;
+
+ for( k = 0; k < nz; k++ )
+ kp[k] = (const ST*)src[pt[k].y] + pt[k].x*cn;
+
+ i = vecOp((const uchar**)kp, dst, width);
+ #if CV_ENABLE_UNROLLED
+ for( ; i <= width - 4; i += 4 )
+ {
+ KT s0 = _delta, s1 = _delta, s2 = _delta, s3 = _delta;
+
+ for( k = 0; k < nz; k++ )
+ {
+ const ST* sptr = kp[k] + i;
+ KT f = kf[k];
+ s0 += f*sptr[0];
+ s1 += f*sptr[1];
+ s2 += f*sptr[2];
+ s3 += f*sptr[3];
+ }
+
+ D[i] = castOp(s0); D[i+1] = castOp(s1);
+ D[i+2] = castOp(s2); D[i+3] = castOp(s3);
+ }
+ #endif
+ for( ; i < width; i++ )
+ {
+ KT s0 = _delta;
+ for( k = 0; k < nz; k++ )
+ s0 += kf[k]*kp[k][i];
+ D[i] = castOp(s0);
+ }
+ }
+ }
+
+ std::vector<Point> coords;
+ std::vector<uchar> coeffs;
+ std::vector<uchar*> ptrs;
+ KT delta;
+ CastOp castOp0;
+ VecOp vecOp;
+};
+
+#ifdef HAVE_OPENCL
+
+#define DIVUP(total, grain) (((total) + (grain) - 1) / (grain))
+#define ROUNDUP(sz, n) ((sz) + (n) - 1 - (((sz) + (n) - 1) % (n)))
+
+// prepare kernel: transpose and make double rows (+align). Returns size of aligned row
+// Samples:
+// a b c
+// Input: d e f
+// g h i
+// Output, last two zeros is the alignment:
+// a d g a d g 0 0
+// b e h b e h 0 0
+// c f i c f i 0 0
+template <typename T>
+static int _prepareKernelFilter2D(std::vector<T> & data, const Mat & kernel)
+{
+ Mat _kernel; kernel.convertTo(_kernel, DataDepth<T>::value);
+ int size_y_aligned = ROUNDUP(kernel.rows * 2, 4);
+ data.clear(); data.resize(size_y_aligned * kernel.cols, 0);
+ for (int x = 0; x < kernel.cols; x++)
+ {
+ for (int y = 0; y < kernel.rows; y++)
+ {
+ data[x * size_y_aligned + y] = _kernel.at<T>(y, x);
+ data[x * size_y_aligned + y + kernel.rows] = _kernel.at<T>(y, x);
+ }
+ }
+ return size_y_aligned;
+}
+
+static bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth,
+ InputArray _kernel, Point anchor,
+ double delta, int borderType )
+{
+ int type = _src.type(), sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
+ ddepth = ddepth < 0 ? sdepth : ddepth;
+ int dtype = CV_MAKE_TYPE(ddepth, cn), wdepth = std::max(std::max(sdepth, ddepth), CV_32F),
+ wtype = CV_MAKE_TYPE(wdepth, cn);
+ if (cn > 4)
+ return false;
+
+ Size ksize = _kernel.size();
+ if (anchor.x < 0)
+ anchor.x = ksize.width / 2;
+ if (anchor.y < 0)
+ anchor.y = ksize.height / 2;
+
+ bool isolated = (borderType & BORDER_ISOLATED) != 0;
+ borderType &= ~BORDER_ISOLATED;
+ const cv::ocl::Device &device = cv::ocl::Device::getDefault();
+ bool doubleSupport = device.doubleFPConfig() > 0;
+ if (wdepth == CV_64F && !doubleSupport)
+ return false;
+
+ const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT",
+ "BORDER_WRAP", "BORDER_REFLECT_101" };
+
+ cv::Mat kernelMat = _kernel.getMat();
+ cv::Size sz = _src.size(), wholeSize;
+ size_t globalsize[2] = { (size_t)sz.width, (size_t)sz.height };
+ size_t localsize_general[2] = {0, 1};
+ size_t* localsize = NULL;
+
+ ocl::Kernel k;
+ UMat src = _src.getUMat();
+ if (!isolated)
+ {
+ Point ofs;
+ src.locateROI(wholeSize, ofs);
+ }
+
+ size_t tryWorkItems = device.maxWorkGroupSize();
+ if (device.isIntel() && 128 < tryWorkItems)
+ tryWorkItems = 128;
+ char cvt[2][40];
+
+ // For smaller filter kernels, there is a special kernel that is more
+ // efficient than the general one.
+ UMat kernalDataUMat;
+ if (device.isIntel() && (device.type() & ocl::Device::TYPE_GPU) &&
+ ((ksize.width < 5 && ksize.height < 5) ||
+ (ksize.width == 5 && ksize.height == 5 && cn == 1)))
+ {
+ kernelMat = kernelMat.reshape(0, 1);
+ String kerStr = ocl::kernelToStr(kernelMat, CV_32F);
+ int h = isolated ? sz.height : wholeSize.height;
+ int w = isolated ? sz.width : wholeSize.width;
+
+ if (w < ksize.width || h < ksize.height)
+ return false;
+
+ // Figure out what vector size to use for loading the pixels.
+ int pxLoadNumPixels = cn != 1 || sz.width % 4 ? 1 : 4;
+ int pxLoadVecSize = cn * pxLoadNumPixels;
+
+ // Figure out how many pixels per work item to compute in X and Y
+ // directions. Too many and we run out of registers.
+ int pxPerWorkItemX = 1;
+ int pxPerWorkItemY = 1;
+ if (cn <= 2 && ksize.width <= 4 && ksize.height <= 4)
+ {
+ pxPerWorkItemX = sz.width % 8 ? sz.width % 4 ? sz.width % 2 ? 1 : 2 : 4 : 8;
+ pxPerWorkItemY = sz.height % 2 ? 1 : 2;
+ }
+ else if (cn < 4 || (ksize.width <= 4 && ksize.height <= 4))
+ {
+ pxPerWorkItemX = sz.width % 2 ? 1 : 2;
+ pxPerWorkItemY = sz.height % 2 ? 1 : 2;
+ }
+ globalsize[0] = sz.width / pxPerWorkItemX;
+ globalsize[1] = sz.height / pxPerWorkItemY;
+
+ // Need some padding in the private array for pixels
+ int privDataWidth = ROUNDUP(pxPerWorkItemX + ksize.width - 1, pxLoadNumPixels);
+
+ // Make the global size a nice round number so the runtime can pick
+ // from reasonable choices for the workgroup size
+ const int wgRound = 256;
+ globalsize[0] = ROUNDUP(globalsize[0], wgRound);
+
+ char build_options[1024];
+ sprintf(build_options, "-D cn=%d "
+ "-D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d "
+ "-D PX_LOAD_VEC_SIZE=%d -D PX_LOAD_NUM_PX=%d "
+ "-D PX_PER_WI_X=%d -D PX_PER_WI_Y=%d -D PRIV_DATA_WIDTH=%d -D %s -D %s "
+ "-D PX_LOAD_X_ITERATIONS=%d -D PX_LOAD_Y_ITERATIONS=%d "
+ "-D srcT=%s -D srcT1=%s -D dstT=%s -D dstT1=%s -D WT=%s -D WT1=%s "
+ "-D convertToWT=%s -D convertToDstT=%s %s",
+ cn, anchor.x, anchor.y, ksize.width, ksize.height,
+ pxLoadVecSize, pxLoadNumPixels,
+ pxPerWorkItemX, pxPerWorkItemY, privDataWidth, borderMap[borderType],
+ isolated ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED",
+ privDataWidth / pxLoadNumPixels, pxPerWorkItemY + ksize.height - 1,
+ ocl::typeToStr(type), ocl::typeToStr(sdepth), ocl::typeToStr(dtype),
+ ocl::typeToStr(ddepth), ocl::typeToStr(wtype), ocl::typeToStr(wdepth),
+ ocl::convertTypeStr(sdepth, wdepth, cn, cvt[0]),
+ ocl::convertTypeStr(wdepth, ddepth, cn, cvt[1]), kerStr.c_str());
+
+ if (!k.create("filter2DSmall", cv::ocl::imgproc::filter2DSmall_oclsrc, build_options))
+ return false;
+ }
+ else
+ {
+ localsize = localsize_general;
+ std::vector<float> kernelMatDataFloat;
+ int kernel_size_y2_aligned = _prepareKernelFilter2D<float>(kernelMatDataFloat, kernelMat);
+ String kerStr = ocl::kernelToStr(kernelMatDataFloat, CV_32F);
+
+ for ( ; ; )
+ {
+ size_t BLOCK_SIZE = tryWorkItems;
+ while (BLOCK_SIZE > 32 && BLOCK_SIZE >= (size_t)ksize.width * 2 && BLOCK_SIZE > (size_t)sz.width * 2)
+ BLOCK_SIZE /= 2;
+
+ if ((size_t)ksize.width > BLOCK_SIZE)
+ return false;
+
+ int requiredTop = anchor.y;
+ int requiredLeft = (int)BLOCK_SIZE; // not this: anchor.x;
+ int requiredBottom = ksize.height - 1 - anchor.y;
+ int requiredRight = (int)BLOCK_SIZE; // not this: ksize.width - 1 - anchor.x;
+ int h = isolated ? sz.height : wholeSize.height;
+ int w = isolated ? sz.width : wholeSize.width;
+ bool extra_extrapolation = h < requiredTop || h < requiredBottom || w < requiredLeft || w < requiredRight;
+
+ if ((w < ksize.width) || (h < ksize.height))
+ return false;
+
+ String opts = format("-D LOCAL_SIZE=%d -D cn=%d "
+ "-D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d "
+ "-D KERNEL_SIZE_Y2_ALIGNED=%d -D %s -D %s -D %s%s%s "
+ "-D srcT=%s -D srcT1=%s -D dstT=%s -D dstT1=%s -D WT=%s -D WT1=%s "
+ "-D convertToWT=%s -D convertToDstT=%s",
+ (int)BLOCK_SIZE, cn, anchor.x, anchor.y,
+ ksize.width, ksize.height, kernel_size_y2_aligned, borderMap[borderType],
+ extra_extrapolation ? "EXTRA_EXTRAPOLATION" : "NO_EXTRA_EXTRAPOLATION",
+ isolated ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED",
+ doubleSupport ? " -D DOUBLE_SUPPORT" : "", kerStr.c_str(),
+ ocl::typeToStr(type), ocl::typeToStr(sdepth), ocl::typeToStr(dtype),
+ ocl::typeToStr(ddepth), ocl::typeToStr(wtype), ocl::typeToStr(wdepth),
+ ocl::convertTypeStr(sdepth, wdepth, cn, cvt[0]),
+ ocl::convertTypeStr(wdepth, ddepth, cn, cvt[1]));
+
+ localsize[0] = BLOCK_SIZE;
+ globalsize[0] = DIVUP(sz.width, BLOCK_SIZE - (ksize.width - 1)) * BLOCK_SIZE;
+ globalsize[1] = sz.height;
+
+ if (!k.create("filter2D", cv::ocl::imgproc::filter2D_oclsrc, opts))
+ return false;
+
+ size_t kernelWorkGroupSize = k.workGroupSize();
+ if (localsize[0] <= kernelWorkGroupSize)
+ break;
+ if (BLOCK_SIZE < kernelWorkGroupSize)
+ return false;
+ tryWorkItems = kernelWorkGroupSize;
+ }
+ }
+
+ _dst.create(sz, dtype);
+ UMat dst = _dst.getUMat();
+
+ int srcOffsetX = (int)((src.offset % src.step) / src.elemSize());
+ int srcOffsetY = (int)(src.offset / src.step);
+ int srcEndX = (isolated ? (srcOffsetX + sz.width) : wholeSize.width);
+ int srcEndY = (isolated ? (srcOffsetY + sz.height) : wholeSize.height);
+
+ k.args(ocl::KernelArg::PtrReadOnly(src), (int)src.step, srcOffsetX, srcOffsetY,
+ srcEndX, srcEndY, ocl::KernelArg::WriteOnly(dst), (float)delta);
+
+ return k.run(2, globalsize, localsize, false);
+}
+
+const int shift_bits = 8;
+
+static bool ocl_sepRowFilter2D(const UMat & src, UMat & buf, const Mat & kernelX, int anchor,
+ int borderType, int ddepth, bool fast8uc1, bool int_arithm)
+{
+ int type = src.type(), cn = CV_MAT_CN(type), sdepth = CV_MAT_DEPTH(type);
+ bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
+ Size bufSize = buf.size();
+ int buf_type = buf.type(), bdepth = CV_MAT_DEPTH(buf_type);
+
+ if (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F))
+ return false;
+
+#ifdef __ANDROID__
+ size_t localsize[2] = {16, 10};
+#else
+ size_t localsize[2] = {16, 16};
+#endif
+
+ size_t globalsize[2] = {DIVUP(bufSize.width, localsize[0]) * localsize[0], DIVUP(bufSize.height, localsize[1]) * localsize[1]};
+ if (fast8uc1)
+ globalsize[0] = DIVUP((bufSize.width + 3) >> 2, localsize[0]) * localsize[0];
+
+ int radiusX = anchor, radiusY = (buf.rows - src.rows) >> 1;
+
+ bool isolated = (borderType & BORDER_ISOLATED) != 0;
+ const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", "BORDER_REFLECT_101" },
+ * const btype = borderMap[borderType & ~BORDER_ISOLATED];
+
+ bool extra_extrapolation = src.rows < (int)((-radiusY + globalsize[1]) >> 1) + 1;
+ extra_extrapolation |= src.rows < radiusY;
+ extra_extrapolation |= src.cols < (int)((-radiusX + globalsize[0] + 8 * localsize[0] + 3) >> 1) + 1;
+ extra_extrapolation |= src.cols < radiusX;
+
+ char cvt[40];
+ cv::String build_options = cv::format("-D RADIUSX=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D %s -D %s -D %s"
+ " -D srcT=%s -D dstT=%s -D convertToDstT=%s -D srcT1=%s -D dstT1=%s%s%s",
+ radiusX, (int)localsize[0], (int)localsize[1], cn, btype,
+ extra_extrapolation ? "EXTRA_EXTRAPOLATION" : "NO_EXTRA_EXTRAPOLATION",
+ isolated ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED",
+ ocl::typeToStr(type), ocl::typeToStr(buf_type),
+ ocl::convertTypeStr(sdepth, bdepth, cn, cvt),
+ ocl::typeToStr(sdepth), ocl::typeToStr(bdepth),
+ doubleSupport ? " -D DOUBLE_SUPPORT" : "",
+ int_arithm ? " -D INTEGER_ARITHMETIC" : "");
+ build_options += ocl::kernelToStr(kernelX, bdepth);
+
+ Size srcWholeSize; Point srcOffset;
+ src.locateROI(srcWholeSize, srcOffset);
+
+ String kernelName("row_filter");
+ if (fast8uc1)
+ kernelName += "_C1_D0";
+
+ ocl::Kernel k(kernelName.c_str(), cv::ocl::imgproc::filterSepRow_oclsrc,
+ build_options);
+ if (k.empty())
+ return false;
+
+ if (fast8uc1)
+ k.args(ocl::KernelArg::PtrReadOnly(src), (int)(src.step / src.elemSize()), srcOffset.x,
+ srcOffset.y, src.cols, src.rows, srcWholeSize.width, srcWholeSize.height,
+ ocl::KernelArg::PtrWriteOnly(buf), (int)(buf.step / buf.elemSize()),
+ buf.cols, buf.rows, radiusY);
+ else
+ k.args(ocl::KernelArg::PtrReadOnly(src), (int)src.step, srcOffset.x,
+ srcOffset.y, src.cols, src.rows, srcWholeSize.width, srcWholeSize.height,
+ ocl::KernelArg::PtrWriteOnly(buf), (int)buf.step, buf.cols, buf.rows, radiusY);
+
+ return k.run(2, globalsize, localsize, false);
+}
+
+static bool ocl_sepColFilter2D(const UMat & buf, UMat & dst, const Mat & kernelY, double delta, int anchor, bool int_arithm)
+{
+ bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
+ if (dst.depth() == CV_64F && !doubleSupport)
+ return false;
+
+#ifdef __ANDROID__
+ size_t localsize[2] = { 16, 10 };
+#else
+ size_t localsize[2] = { 16, 16 };
+#endif
+ size_t globalsize[2] = { 0, 0 };
+
+ int dtype = dst.type(), cn = CV_MAT_CN(dtype), ddepth = CV_MAT_DEPTH(dtype);
+ Size sz = dst.size();
+ int buf_type = buf.type(), bdepth = CV_MAT_DEPTH(buf_type);
+
+ globalsize[1] = DIVUP(sz.height, localsize[1]) * localsize[1];
+ globalsize[0] = DIVUP(sz.width, localsize[0]) * localsize[0];
+
+ char cvt[40];
+ cv::String build_options = cv::format("-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d"
+ " -D srcT=%s -D dstT=%s -D convertToDstT=%s"
+ " -D srcT1=%s -D dstT1=%s -D SHIFT_BITS=%d%s%s",
+ anchor, (int)localsize[0], (int)localsize[1], cn,
+ ocl::typeToStr(buf_type), ocl::typeToStr(dtype),
+ ocl::convertTypeStr(bdepth, ddepth, cn, cvt),
+ ocl::typeToStr(bdepth), ocl::typeToStr(ddepth),
+ 2*shift_bits, doubleSupport ? " -D DOUBLE_SUPPORT" : "",
+ int_arithm ? " -D INTEGER_ARITHMETIC" : "");
+ build_options += ocl::kernelToStr(kernelY, bdepth);
+
+ ocl::Kernel k("col_filter", cv::ocl::imgproc::filterSepCol_oclsrc,
+ build_options);
+ if (k.empty())
+ return false;
+
+ k.args(ocl::KernelArg::ReadOnly(buf), ocl::KernelArg::WriteOnly(dst),
+ static_cast<float>(delta));
+
+ return k.run(2, globalsize, localsize, false);
+}
+
+const int optimizedSepFilterLocalWidth = 16;
+const int optimizedSepFilterLocalHeight = 8;
+
+static bool ocl_sepFilter2D_SinglePass(InputArray _src, OutputArray _dst,
+ Mat row_kernel, Mat col_kernel,
+ double delta, int borderType, int ddepth, int bdepth, bool int_arithm)
+{
+ Size size = _src.size(), wholeSize;
+ Point origin;
+ int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype),
+ esz = CV_ELEM_SIZE(stype), wdepth = std::max(std::max(sdepth, ddepth), bdepth),
+ dtype = CV_MAKE_TYPE(ddepth, cn);
+ size_t src_step = _src.step(), src_offset = _src.offset();
+ bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
+
+ if (esz == 0 || src_step == 0
+ || (src_offset % src_step) % esz != 0
+ || (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F))
+ || !(borderType == BORDER_CONSTANT
+ || borderType == BORDER_REPLICATE
+ || borderType == BORDER_REFLECT
+ || borderType == BORDER_WRAP
+ || borderType == BORDER_REFLECT_101))
+ return false;
+
+ size_t lt2[2] = { optimizedSepFilterLocalWidth, optimizedSepFilterLocalHeight };
+ size_t gt2[2] = { lt2[0] * (1 + (size.width - 1) / lt2[0]), lt2[1]};
+
+ char cvt[2][40];
+ const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP",
+ "BORDER_REFLECT_101" };
+
+ String opts = cv::format("-D BLK_X=%d -D BLK_Y=%d -D RADIUSX=%d -D RADIUSY=%d%s%s"
+ " -D srcT=%s -D convertToWT=%s -D WT=%s -D dstT=%s -D convertToDstT=%s"
+ " -D %s -D srcT1=%s -D dstT1=%s -D WT1=%s -D CN=%d -D SHIFT_BITS=%d%s",
+ (int)lt2[0], (int)lt2[1], row_kernel.cols / 2, col_kernel.cols / 2,
+ ocl::kernelToStr(row_kernel, wdepth, "KERNEL_MATRIX_X").c_str(),
+ ocl::kernelToStr(col_kernel, wdepth, "KERNEL_MATRIX_Y").c_str(),
+ ocl::typeToStr(stype), ocl::convertTypeStr(sdepth, wdepth, cn, cvt[0]),
+ ocl::typeToStr(CV_MAKE_TYPE(wdepth, cn)), ocl::typeToStr(dtype),
+ ocl::convertTypeStr(wdepth, ddepth, cn, cvt[1]), borderMap[borderType],
+ ocl::typeToStr(sdepth), ocl::typeToStr(ddepth), ocl::typeToStr(wdepth),
+ cn, 2*shift_bits, int_arithm ? " -D INTEGER_ARITHMETIC" : "");
+
+ ocl::Kernel k("sep_filter", ocl::imgproc::filterSep_singlePass_oclsrc, opts);
+ if (k.empty())
+ return false;
+
+ UMat src = _src.getUMat();
+ _dst.create(size, dtype);
+ UMat dst = _dst.getUMat();
+
+ int src_offset_x = static_cast<int>((src_offset % src_step) / esz);
+ int src_offset_y = static_cast<int>(src_offset / src_step);
+
+ src.locateROI(wholeSize, origin);
+
+ k.args(ocl::KernelArg::PtrReadOnly(src), (int)src_step, src_offset_x, src_offset_y,
+ wholeSize.height, wholeSize.width, ocl::KernelArg::WriteOnly(dst),
+ static_cast<float>(delta));
+
+ return k.run(2, gt2, lt2, false);
+}
+
+bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth,
+ InputArray _kernelX, InputArray _kernelY, Point anchor,
+ double delta, int borderType )
+{
+ const ocl::Device & d = ocl::Device::getDefault();
+ Size imgSize = _src.size();
+
+ int type = _src.type(), sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
+ if (cn > 4)
+ return false;
+
+ Mat kernelX = _kernelX.getMat().reshape(1, 1);
+ if (kernelX.cols % 2 != 1)
+ return false;
+ Mat kernelY = _kernelY.getMat().reshape(1, 1);
+ if (kernelY.cols % 2 != 1)
+ return false;
+
+ if (ddepth < 0)
+ ddepth = sdepth;
+
+ if (anchor.x < 0)
+ anchor.x = kernelX.cols >> 1;
+ if (anchor.y < 0)
+ anchor.y = kernelY.cols >> 1;
+
+ int rtype = getKernelType(kernelX,
+ kernelX.rows == 1 ? Point(anchor.x, 0) : Point(0, anchor.x));
+ int ctype = getKernelType(kernelY,
+ kernelY.rows == 1 ? Point(anchor.y, 0) : Point(0, anchor.y));
+
+ int bdepth = CV_32F;
+ bool int_arithm = false;
+ if( sdepth == CV_8U && ddepth == CV_8U &&
+ rtype == KERNEL_SMOOTH+KERNEL_SYMMETRICAL &&
+ ctype == KERNEL_SMOOTH+KERNEL_SYMMETRICAL)
+ {
+ if (ocl::Device::getDefault().isIntel())
+ {
+ for (int i=0; i<kernelX.cols; i++)
+ kernelX.at<float>(0, i) = (float) cvRound(kernelX.at<float>(0, i) * (1 << shift_bits));
+ if (kernelX.data != kernelY.data)
+ for (int i=0; i<kernelX.cols; i++)
+ kernelY.at<float>(0, i) = (float) cvRound(kernelY.at<float>(0, i) * (1 << shift_bits));
+ } else
+ {
+ bdepth = CV_32S;
+ kernelX.convertTo( kernelX, bdepth, 1 << shift_bits );
+ kernelY.convertTo( kernelY, bdepth, 1 << shift_bits );
+ }
+ int_arithm = true;
+ }
+
+ CV_OCL_RUN_(kernelY.cols <= 21 && kernelX.cols <= 21 &&
+ imgSize.width > optimizedSepFilterLocalWidth + anchor.x &&
+ imgSize.height > optimizedSepFilterLocalHeight + anchor.y &&
+ (!(borderType & BORDER_ISOLATED) || _src.offset() == 0) &&
+ anchor == Point(kernelX.cols >> 1, kernelY.cols >> 1) &&
+ OCL_PERFORMANCE_CHECK(d.isIntel()), // TODO FIXIT
+ ocl_sepFilter2D_SinglePass(_src, _dst, kernelX, kernelY, delta,
+ borderType & ~BORDER_ISOLATED, ddepth, bdepth, int_arithm), true)
+
+ UMat src = _src.getUMat();
+ Size srcWholeSize; Point srcOffset;
+ src.locateROI(srcWholeSize, srcOffset);
+
+ bool fast8uc1 = type == CV_8UC1 && srcOffset.x % 4 == 0 &&
+ src.cols % 4 == 0 && src.step % 4 == 0;
+
+ Size srcSize = src.size();
+ Size bufSize(srcSize.width, srcSize.height + kernelY.cols - 1);
+ UMat buf(bufSize, CV_MAKETYPE(bdepth, cn));
+ if (!ocl_sepRowFilter2D(src, buf, kernelX, anchor.x, borderType, ddepth, fast8uc1, int_arithm))
+ return false;
+
+ _dst.create(srcSize, CV_MAKETYPE(ddepth, cn));
+ UMat dst = _dst.getUMat();
+
+ return ocl_sepColFilter2D(buf, dst, kernelY, delta, anchor.y, int_arithm);
+}
+
+#endif
+
+Ptr<cv::BaseFilter> getLinearFilter(
+ int srcType, int dstType,
+ InputArray filter_kernel, Point anchor,
+ double delta, int bits)
+{
+ CV_INSTRUMENT_REGION();
+
+ Mat kernelMat = filter_kernel.getMat();
+ CV_CPU_DISPATCH(getLinearFilter, (srcType, dstType, kernelMat, anchor, delta, bits),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+
+Ptr<cv::FilterEngine> createLinearFilter(
+ int _srcType, int _dstType,
+ InputArray filter_kernel,
+ Point _anchor, double _delta,
+ int _rowBorderType, int _columnBorderType,
+ const Scalar& _borderValue)
+{
+ Mat _kernel = filter_kernel.getMat();
+ _srcType = CV_MAT_TYPE(_srcType);
+ _dstType = CV_MAT_TYPE(_dstType);
+ int cn = CV_MAT_CN(_srcType);
+ CV_Assert( cn == CV_MAT_CN(_dstType) );
+
+ Mat kernel = _kernel;
+ int bits = 0;
+
+ /*int sdepth = CV_MAT_DEPTH(_srcType), ddepth = CV_MAT_DEPTH(_dstType);
+ int ktype = _kernel.depth() == CV_32S ? KERNEL_INTEGER : getKernelType(_kernel, _anchor);
+ if( sdepth == CV_8U && (ddepth == CV_8U || ddepth == CV_16S) &&
+ _kernel.rows*_kernel.cols <= (1 << 10) )
+ {
+ bits = (ktype & KERNEL_INTEGER) ? 0 : 11;
+ _kernel.convertTo(kernel, CV_32S, 1 << bits);
+ }*/
+
+ Ptr<BaseFilter> _filter2D = getLinearFilter(_srcType, _dstType,
+ kernel, _anchor, _delta, bits);
+
+ return makePtr<FilterEngine>(_filter2D, Ptr<BaseRowFilter>(),
+ Ptr<BaseColumnFilter>(), _srcType, _dstType, _srcType,
+ _rowBorderType, _columnBorderType, _borderValue );
+}
+
+
+//================================================================
+// HAL interface
+//================================================================
+
+static bool replacementFilter2D(int stype, int dtype, int kernel_type,
+ uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int full_width, int full_height,
+ int offset_x, int offset_y,
+ uchar * kernel_data, size_t kernel_step,
+ int kernel_width, int kernel_height,
+ int anchor_x, int anchor_y,
+ double delta, int borderType, bool isSubmatrix)
+{
+ cvhalFilter2D* ctx;
+ int res = cv_hal_filterInit(&ctx, kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, width, height,
+ stype, dtype, borderType, delta, anchor_x, anchor_y, isSubmatrix, src_data == dst_data);
+ if (res != CV_HAL_ERROR_OK)
+ return false;
+ res = cv_hal_filter(ctx, src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y);
+ bool success = (res == CV_HAL_ERROR_OK);
+ res = cv_hal_filterFree(ctx);
+ if (res != CV_HAL_ERROR_OK)
+ return false;
+ return success;
+}
+
+#ifdef HAVE_IPP
+static bool ippFilter2D(int stype, int dtype, int kernel_type,
+ uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int full_width, int full_height,
+ int offset_x, int offset_y,
+ uchar * kernel_data, size_t kernel_step,
+ int kernel_width, int kernel_height,
+ int anchor_x, int anchor_y,
+ double delta, int borderType,
+ bool isSubmatrix)
+{
+#ifdef HAVE_IPP_IW
+ CV_INSTRUMENT_REGION_IPP();
+
+ ::ipp::IwiSize iwSize(width, height);
+ ::ipp::IwiSize kernelSize(kernel_width, kernel_height);
+ IppDataType type = ippiGetDataType(CV_MAT_DEPTH(stype));
+ int channels = CV_MAT_CN(stype);
+
+ CV_UNUSED(isSubmatrix);
+
+#if IPP_VERSION_X100 >= 201700 && IPP_VERSION_X100 <= 201702 // IPP bug with 1x1 kernel
+ if(kernel_width == 1 && kernel_height == 1)
+ return false;
+#endif
+
+#if IPP_DISABLE_FILTER2D_BIG_MASK
+ // Too big difference compared to OpenCV FFT-based convolution
+ if(kernel_type == CV_32FC1 && (type == ipp16s || type == ipp16u) && (kernel_width > 7 || kernel_height > 7))
+ return false;
+
+ // Poor optimization for big kernels
+ if(kernel_width > 7 || kernel_height > 7)
+ return false;
+#endif
+
+ if(src_data == dst_data)
+ return false;
+
+ if(stype != dtype)
+ return false;
+
+ if(kernel_type != CV_16SC1 && kernel_type != CV_32FC1)
+ return false;
+
+ // TODO: Implement offset for 8u, 16u
+ if(std::fabs(delta) >= DBL_EPSILON)
+ return false;
+
+ if(!ippiCheckAnchor(anchor_x, anchor_y, kernel_width, kernel_height))
+ return false;
+
+ try
+ {
+ ::ipp::IwiBorderSize iwBorderSize;
+ ::ipp::IwiBorderType iwBorderType;
+ ::ipp::IwiImage iwKernel(ippiSize(kernel_width, kernel_height), ippiGetDataType(CV_MAT_DEPTH(kernel_type)), CV_MAT_CN(kernel_type), 0, (void*)kernel_data, kernel_step);
+ ::ipp::IwiImage iwSrc(iwSize, type, channels, ::ipp::IwiBorderSize(offset_x, offset_y, full_width-offset_x-width, full_height-offset_y-height), (void*)src_data, src_step);
+ ::ipp::IwiImage iwDst(iwSize, type, channels, ::ipp::IwiBorderSize(offset_x, offset_y, full_width-offset_x-width, full_height-offset_y-height), (void*)dst_data, dst_step);
+
+ iwBorderSize = ::ipp::iwiSizeToBorderSize(kernelSize);
+ iwBorderType = ippiGetBorder(iwSrc, borderType, iwBorderSize);
+ if(!iwBorderType)
+ return false;
+
+ CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilter, iwSrc, iwDst, iwKernel, ::ipp::IwiFilterParams(1, 0, ippAlgHintNone, ippRndFinancial), iwBorderType);
+ }
+ catch(const ::ipp::IwException& ex)
+ {
+ CV_UNUSED(ex);
+ return false;
+ }
+
+ return true;
+#else
+ CV_UNUSED(stype); CV_UNUSED(dtype); CV_UNUSED(kernel_type); CV_UNUSED(src_data); CV_UNUSED(src_step);
+ CV_UNUSED(dst_data); CV_UNUSED(dst_step); CV_UNUSED(width); CV_UNUSED(height); CV_UNUSED(full_width);
+ CV_UNUSED(full_height); CV_UNUSED(offset_x); CV_UNUSED(offset_y); CV_UNUSED(kernel_data); CV_UNUSED(kernel_step);
+ CV_UNUSED(kernel_width); CV_UNUSED(kernel_height); CV_UNUSED(anchor_x); CV_UNUSED(anchor_y); CV_UNUSED(delta);
+ CV_UNUSED(borderType); CV_UNUSED(isSubmatrix);
+ return false;
+#endif
+}
+#endif
+
+static bool dftFilter2D(int stype, int dtype, int kernel_type,
+ uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int full_width, int full_height,
+ int offset_x, int offset_y,
+ uchar * kernel_data, size_t kernel_step,
+ int kernel_width, int kernel_height,
+ int anchor_x, int anchor_y,
+ double delta, int borderType)
+{
+ {
+ int sdepth = CV_MAT_DEPTH(stype);
+ int ddepth = CV_MAT_DEPTH(dtype);
+ int dft_filter_size = checkHardwareSupport(CV_CPU_SSE3) && ((sdepth == CV_8U && (ddepth == CV_8U || ddepth == CV_16S)) || (sdepth == CV_32F && ddepth == CV_32F)) ? 130 : 50;
+ if (kernel_width * kernel_height < dft_filter_size)
+ return false;
+ }
+
+ Point anchor = Point(anchor_x, anchor_y);
+ Mat kernel = Mat(Size(kernel_width, kernel_height), kernel_type, kernel_data, kernel_step);
+
+ Mat src(Size(full_width-offset_x, full_height-offset_y), stype, src_data, src_step);
+ Mat dst(Size(full_width, full_height), dtype, dst_data, dst_step);
+ Mat temp;
+ int src_channels = CV_MAT_CN(stype);
+ int dst_channels = CV_MAT_CN(dtype);
+ int ddepth = CV_MAT_DEPTH(dtype);
+ // crossCorr doesn't accept non-zero delta with multiple channels
+ if (src_channels != 1 && delta != 0) {
+ // The semantics of filter2D require that the delta be applied
+ // as floating-point math. So wee need an intermediate Mat
+ // with a float datatype. If the dest is already floats,
+ // we just use that.
+ int corrDepth = ddepth;
+ if ((ddepth == CV_32F || ddepth == CV_64F) && src_data != dst_data) {
+ temp = Mat(Size(full_width, full_height), dtype, dst_data, dst_step);
+ } else {
+ corrDepth = ddepth == CV_64F ? CV_64F : CV_32F;
+ temp.create(Size(full_width, full_height), CV_MAKETYPE(corrDepth, dst_channels));
+ }
+ crossCorr(src, kernel, temp, src.size(),
+ CV_MAKETYPE(corrDepth, src_channels),
+ anchor, 0, borderType);
+ add(temp, delta, temp);
+ if (temp.data != dst_data) {
+ temp.convertTo(dst, dst.type());
+ }
+ } else {
+ if (src_data != dst_data)
+ temp = Mat(Size(full_width, full_height), dtype, dst_data, dst_step);
+ else
+ temp.create(Size(full_width, full_height), dtype);
+ crossCorr(src, kernel, temp, src.size(),
+ CV_MAKETYPE(ddepth, src_channels),
+ anchor, delta, borderType);
+ if (temp.data != dst_data)
+ temp.copyTo(dst);
+ }
+ return true;
+}
+
+static void ocvFilter2D(int stype, int dtype, int kernel_type,
+ uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int full_width, int full_height,
+ int offset_x, int offset_y,
+ uchar * kernel_data, size_t kernel_step,
+ int kernel_width, int kernel_height,
+ int anchor_x, int anchor_y,
+ double delta, int borderType)
+{
+ int borderTypeValue = borderType & ~BORDER_ISOLATED;
+ Mat kernel = Mat(Size(kernel_width, kernel_height), kernel_type, kernel_data, kernel_step);
+ Ptr<FilterEngine> f = createLinearFilter(stype, dtype, kernel, Point(anchor_x, anchor_y), delta,
+ borderTypeValue);
+ Mat src(Size(width, height), stype, src_data, src_step);
+ Mat dst(Size(width, height), dtype, dst_data, dst_step);
+ f->apply(src, dst, Size(full_width, full_height), Point(offset_x, offset_y));
+}
+
+static bool replacementSepFilter(int stype, int dtype, int ktype,
+ uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
+ int width, int height, int full_width, int full_height,
+ int offset_x, int offset_y,
+ uchar * kernelx_data, int kernelx_len,
+ uchar * kernely_data, int kernely_len,
+ int anchor_x, int anchor_y, double delta, int borderType)
+{
+ cvhalFilter2D *ctx;
+ int res = cv_hal_sepFilterInit(&ctx, stype, dtype, ktype,
+ kernelx_data, kernelx_len,
+ kernely_data, kernely_len,
+ anchor_x, anchor_y, delta, borderType);
+ if (res != CV_HAL_ERROR_OK)
+ return false;
+ res = cv_hal_sepFilter(ctx, src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y);
+ bool success = (res == CV_HAL_ERROR_OK);
+ res = cv_hal_sepFilterFree(ctx);
+ if (res != CV_HAL_ERROR_OK)
+ return false;
+ return success;
+}
+
+static void ocvSepFilter(int stype, int dtype, int ktype,
+ uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
+ int width, int height, int full_width, int full_height,
+ int offset_x, int offset_y,
+ uchar * kernelx_data, int kernelx_len,
+ uchar * kernely_data, int kernely_len,
+ int anchor_x, int anchor_y, double delta, int borderType)
+{
+ Mat kernelX(Size(kernelx_len, 1), ktype, kernelx_data);
+ Mat kernelY(Size(kernely_len, 1), ktype, kernely_data);
+ Ptr<FilterEngine> f = createSeparableLinearFilter(stype, dtype, kernelX, kernelY,
+ Point(anchor_x, anchor_y),
+ delta, borderType & ~BORDER_ISOLATED);
+ Mat src(Size(width, height), stype, src_data, src_step);
+ Mat dst(Size(width, height), dtype, dst_data, dst_step);
+ f->apply(src, dst, Size(full_width, full_height), Point(offset_x, offset_y));
+};
+
+//===================================================================
+// HAL functions
+//===================================================================
+
+namespace hal {
+
+
+CV_DEPRECATED Ptr<hal::Filter2D> Filter2D::create(uchar * , size_t , int ,
+ int , int ,
+ int , int ,
+ int , int ,
+ int , double ,
+ int , int ,
+ bool , bool ) { return Ptr<hal::Filter2D>(); }
+
+CV_DEPRECATED Ptr<hal::SepFilter2D> SepFilter2D::create(int , int , int ,
+ uchar * , int ,
+ uchar * , int ,
+ int , int ,
+ double , int ) { return Ptr<hal::SepFilter2D>(); }
+
+
+void filter2D(int stype, int dtype, int kernel_type,
+ uchar * src_data, size_t src_step,
+ uchar * dst_data, size_t dst_step,
+ int width, int height,
+ int full_width, int full_height,
+ int offset_x, int offset_y,
+ uchar * kernel_data, size_t kernel_step,
+ int kernel_width, int kernel_height,
+ int anchor_x, int anchor_y,
+ double delta, int borderType,
+ bool isSubmatrix)
+{
+ bool res;
+ res = replacementFilter2D(stype, dtype, kernel_type,
+ src_data, src_step,
+ dst_data, dst_step,
+ width, height,
+ full_width, full_height,
+ offset_x, offset_y,
+ kernel_data, kernel_step,
+ kernel_width, kernel_height,
+ anchor_x, anchor_y,
+ delta, borderType, isSubmatrix);
+ if (res)
+ return;
+
+ CV_IPP_RUN_FAST(ippFilter2D(stype, dtype, kernel_type,
+ src_data, src_step,
+ dst_data, dst_step,
+ width, height,
+ full_width, full_height,
+ offset_x, offset_y,
+ kernel_data, kernel_step,
+ kernel_width, kernel_height,
+ anchor_x, anchor_y,
+ delta, borderType, isSubmatrix))
+
+ res = dftFilter2D(stype, dtype, kernel_type,
+ src_data, src_step,
+ dst_data, dst_step,
+ full_width, full_height,
+ offset_x, offset_y,
+ kernel_data, kernel_step,
+ kernel_width, kernel_height,
+ anchor_x, anchor_y,
+ delta, borderType);
+ if (res)
+ return;
+ ocvFilter2D(stype, dtype, kernel_type,
+ src_data, src_step,
+ dst_data, dst_step,
+ width, height,
+ full_width, full_height,
+ offset_x, offset_y,
+ kernel_data, kernel_step,
+ kernel_width, kernel_height,
+ anchor_x, anchor_y,
+ delta, borderType);
+}
+
+//---------------------------------------------------------------
+
+void sepFilter2D(int stype, int dtype, int ktype,
+ uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
+ int width, int height, int full_width, int full_height,
+ int offset_x, int offset_y,
+ uchar * kernelx_data, int kernelx_len,
+ uchar * kernely_data, int kernely_len,
+ int anchor_x, int anchor_y, double delta, int borderType)
+{
+
+ bool res = replacementSepFilter(stype, dtype, ktype,
+ src_data, src_step, dst_data, dst_step,
+ width, height, full_width, full_height,
+ offset_x, offset_y,
+ kernelx_data, kernelx_len,
+ kernely_data, kernely_len,
+ anchor_x, anchor_y, delta, borderType);
+ if (res)
+ return;
+ ocvSepFilter(stype, dtype, ktype,
+ src_data, src_step, dst_data, dst_step,
+ width, height, full_width, full_height,
+ offset_x, offset_y,
+ kernelx_data, kernelx_len,
+ kernely_data, kernely_len,
+ anchor_x, anchor_y, delta, borderType);
+}
+
+} // namespace cv::hal::
+
+//================================================================
+// Main interface
+//================================================================
+
+void filter2D(InputArray _src, OutputArray _dst, int ddepth,
+ InputArray _kernel, Point anchor0,
+ double delta, int borderType)
+{
+ CV_INSTRUMENT_REGION();
+
+ CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
+ ocl_filter2D(_src, _dst, ddepth, _kernel, anchor0, delta, borderType))
+
+ Mat src = _src.getMat(), kernel = _kernel.getMat();
+
+ if( ddepth < 0 )
+ ddepth = src.depth();
+
+ _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) );
+ Mat dst = _dst.getMat();
+ Point anchor = normalizeAnchor(anchor0, kernel.size());
+
+ Point ofs;
+ Size wsz(src.cols, src.rows);
+ if( (borderType & BORDER_ISOLATED) == 0 )
+ src.locateROI( wsz, ofs );
+
+ hal::filter2D(src.type(), dst.type(), kernel.type(),
+ src.data, src.step, dst.data, dst.step,
+ dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y,
+ kernel.data, kernel.step, kernel.cols, kernel.rows,
+ anchor.x, anchor.y,
+ delta, borderType, src.isSubmatrix());
+}
+
+void sepFilter2D(InputArray _src, OutputArray _dst, int ddepth,
+ InputArray _kernelX, InputArray _kernelY, Point anchor,
+ double delta, int borderType)
+{
+ CV_INSTRUMENT_REGION();
+
+ CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && (size_t)_src.rows() > _kernelY.total() && (size_t)_src.cols() > _kernelX.total(),
+ ocl_sepFilter2D(_src, _dst, ddepth, _kernelX, _kernelY, anchor, delta, borderType))
+
+ Mat src = _src.getMat(), kernelX = _kernelX.getMat(), kernelY = _kernelY.getMat();
+
+ if( ddepth < 0 )
+ ddepth = src.depth();
+
+ _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) );
+ Mat dst = _dst.getMat();
+
+ Point ofs;
+ Size wsz(src.cols, src.rows);
+ if( (borderType & BORDER_ISOLATED) == 0 )
+ src.locateROI( wsz, ofs );
+
+ CV_Assert( kernelX.type() == kernelY.type() &&
+ (kernelX.cols == 1 || kernelX.rows == 1) &&
+ (kernelY.cols == 1 || kernelY.rows == 1) );
+
+ Mat contKernelX = kernelX.isContinuous() ? kernelX : kernelX.clone();
+ Mat contKernelY = kernelY.isContinuous() ? kernelY : kernelY.clone();
+
+ hal::sepFilter2D(src.type(), dst.type(), kernelX.type(),
+ src.data, src.step, dst.data, dst.step,
+ dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y,
+ contKernelX.data, kernelX.cols + kernelX.rows - 1,
+ contKernelY.data, kernelY.cols + kernelY.rows - 1,
+ anchor.x, anchor.y, delta, borderType & ~BORDER_ISOLATED);
+}
+
+} // namespace
+
+CV_IMPL void
+cvFilter2D( const CvArr* srcarr, CvArr* dstarr, const CvMat* _kernel, CvPoint anchor )
+{
+ cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
+ cv::Mat kernel = cv::cvarrToMat(_kernel);
+
+ CV_Assert( src.size() == dst.size() && src.channels() == dst.channels() );
+
+ cv::filter2D( src, dst, dst.depth(), kernel, anchor, 0, cv::BORDER_REPLICATE );
+}
+
+/* End of file. */
namespace cv
{
-#if CV_TRY_AVX2
- int RowVec_32f_AVX(const float* src0, const float* _kx, float* dst, int width, int cn, int _ksize);
- int SymmColumnVec_32f_Symm_AVX(const float** src, const float* ky, float* dst, float delta, int width, int ksize2);
- int SymmColumnVec_32f_Unsymm_AVX(const float** src, const float* ky, float* dst, float delta, int width, int ksize2);
-#endif
-
#ifdef HAVE_OPENCL
bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth,
InputArray _kernelX, InputArray _kernelY, Point anchor,
double delta, int borderType );
#endif
+
+ void preprocess2DKernel(const Mat& kernel, std::vector<Point>& coords, std::vector<uchar>& coeffs);
}
#endif
//M*/
#include "precomp.hpp"
-#include "opencv2/core/opencl/ocl_defs.hpp"
-#include "opencl_kernels_imgproc.hpp"
-#include "hal_replacement.hpp"
#include "opencv2/core/hal/intrin.hpp"
#include "filter.hpp"
-
-/****************************************************************************************\
- Base Image Filter
-\****************************************************************************************/
-
+#if defined(CV_CPU_BASELINE_MODE)
#if IPP_VERSION_X100 >= 710
#define USE_IPP_SEP_FILTERS 1
#else
#undef USE_IPP_SEP_FILTERS
#endif
+#endif
-namespace cv
-{
-
-BaseRowFilter::BaseRowFilter() { ksize = anchor = -1; }
-BaseRowFilter::~BaseRowFilter() {}
-
-BaseColumnFilter::BaseColumnFilter() { ksize = anchor = -1; }
-BaseColumnFilter::~BaseColumnFilter() {}
-void BaseColumnFilter::reset() {}
-
-BaseFilter::BaseFilter() { ksize = Size(-1,-1); anchor = Point(-1,-1); }
-BaseFilter::~BaseFilter() {}
-void BaseFilter::reset() {}
-
-FilterEngine::FilterEngine()
- : srcType(-1), dstType(-1), bufType(-1), maxWidth(0), wholeSize(-1, -1), dx1(0), dx2(0),
- rowBorderType(BORDER_REPLICATE), columnBorderType(BORDER_REPLICATE),
- borderElemSize(0), bufStep(0), startY(0), startY0(0), endY(0), rowCount(0), dstY(0)
-{
-}
-
-
-FilterEngine::FilterEngine( const Ptr<BaseFilter>& _filter2D,
- const Ptr<BaseRowFilter>& _rowFilter,
- const Ptr<BaseColumnFilter>& _columnFilter,
- int _srcType, int _dstType, int _bufType,
- int _rowBorderType, int _columnBorderType,
- const Scalar& _borderValue )
- : srcType(-1), dstType(-1), bufType(-1), maxWidth(0), wholeSize(-1, -1), dx1(0), dx2(0),
- rowBorderType(BORDER_REPLICATE), columnBorderType(BORDER_REPLICATE),
- borderElemSize(0), bufStep(0), startY(0), startY0(0), endY(0), rowCount(0), dstY(0)
-{
- init(_filter2D, _rowFilter, _columnFilter, _srcType, _dstType, _bufType,
- _rowBorderType, _columnBorderType, _borderValue);
-}
-
-FilterEngine::~FilterEngine()
-{
-}
-
-
-void FilterEngine::init( const Ptr<BaseFilter>& _filter2D,
- const Ptr<BaseRowFilter>& _rowFilter,
- const Ptr<BaseColumnFilter>& _columnFilter,
- int _srcType, int _dstType, int _bufType,
- int _rowBorderType, int _columnBorderType,
- const Scalar& _borderValue )
-{
- _srcType = CV_MAT_TYPE(_srcType);
- _bufType = CV_MAT_TYPE(_bufType);
- _dstType = CV_MAT_TYPE(_dstType);
-
- srcType = _srcType;
- int srcElemSize = (int)getElemSize(srcType);
- dstType = _dstType;
- bufType = _bufType;
-
- filter2D = _filter2D;
- rowFilter = _rowFilter;
- columnFilter = _columnFilter;
-
- if( _columnBorderType < 0 )
- _columnBorderType = _rowBorderType;
-
- rowBorderType = _rowBorderType;
- columnBorderType = _columnBorderType;
- CV_Assert( columnBorderType != BORDER_WRAP );
+/****************************************************************************************\
+ Base Image Filter
+\****************************************************************************************/
- if( isSeparable() )
- {
- CV_Assert( rowFilter && columnFilter );
- ksize = Size(rowFilter->ksize, columnFilter->ksize);
- anchor = Point(rowFilter->anchor, columnFilter->anchor);
- }
- else
- {
- CV_Assert( bufType == srcType );
- ksize = filter2D->ksize;
- anchor = filter2D->anchor;
- }
+namespace cv {
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+// forward declarations
+int FilterEngine__start(FilterEngine& this_, const Size &_wholeSize, const Size &sz, const Point &ofs);
+int FilterEngine__proceed(FilterEngine& this_, const uchar* src, int srcstep, int count,
+ uchar* dst, int dststep);
+void FilterEngine__apply(FilterEngine& this_, const Mat& src, Mat& dst, const Size& wsz, const Point& ofs);
- CV_Assert( 0 <= anchor.x && anchor.x < ksize.width &&
- 0 <= anchor.y && anchor.y < ksize.height );
+Ptr<BaseRowFilter> getLinearRowFilter(
+ int srcType, int bufType,
+ const Mat& kernel, int anchor,
+ int symmetryType);
- borderElemSize = srcElemSize/(CV_MAT_DEPTH(srcType) >= CV_32S ? sizeof(int) : 1);
- int borderLength = std::max(ksize.width - 1, 1);
- borderTab.resize(borderLength*borderElemSize);
+Ptr<BaseColumnFilter> getLinearColumnFilter(
+ int bufType, int dstType,
+ const Mat& kernel, int anchor,
+ int symmetryType, double delta,
+ int bits);
- maxWidth = bufStep = 0;
- constBorderRow.clear();
+Ptr<BaseFilter> getLinearFilter(
+ int srcType, int dstType,
+ const Mat& filter_kernel, Point anchor,
+ double delta, int bits);
- if( rowBorderType == BORDER_CONSTANT || columnBorderType == BORDER_CONSTANT )
- {
- constBorderValue.resize(srcElemSize*borderLength);
- int srcType1 = CV_MAKETYPE(CV_MAT_DEPTH(srcType), MIN(CV_MAT_CN(srcType), 4));
- scalarToRawData(_borderValue, &constBorderValue[0], srcType1,
- borderLength*CV_MAT_CN(srcType));
- }
- wholeSize = Size(-1,-1);
-}
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
#define VEC_ALIGN CV_MALLOC_ALIGN
-int FilterEngine::start(const Size &_wholeSize, const Size &sz, const Point &ofs)
+int FilterEngine__start(FilterEngine& this_, const Size &_wholeSize, const Size &sz, const Point &ofs)
{
+ CV_INSTRUMENT_REGION();
+
int i, j;
- wholeSize = _wholeSize;
- roi = Rect(ofs, sz);
- CV_Assert( roi.x >= 0 && roi.y >= 0 && roi.width >= 0 && roi.height >= 0 &&
- roi.x + roi.width <= wholeSize.width &&
- roi.y + roi.height <= wholeSize.height );
+ this_.wholeSize = _wholeSize;
+ this_.roi = Rect(ofs, sz);
+ CV_Assert( this_.roi.x >= 0 && this_.roi.y >= 0 && this_.roi.width >= 0 && this_.roi.height >= 0 &&
+ this_.roi.x + this_.roi.width <= this_.wholeSize.width &&
+ this_.roi.y + this_.roi.height <= this_.wholeSize.height );
- int esz = (int)getElemSize(srcType);
- int bufElemSize = (int)getElemSize(bufType);
- const uchar* constVal = !constBorderValue.empty() ? &constBorderValue[0] : 0;
+ int esz = (int)getElemSize(this_.srcType);
+ int bufElemSize = (int)getElemSize(this_.bufType);
+ const uchar* constVal = !this_.constBorderValue.empty() ? &this_.constBorderValue[0] : 0;
- int _maxBufRows = std::max(ksize.height + 3,
- std::max(anchor.y,
- ksize.height-anchor.y-1)*2+1);
+ int _maxBufRows = std::max(this_.ksize.height + 3,
+ std::max(this_.anchor.y,
+ this_.ksize.height-this_.anchor.y-1)*2+1);
- if( maxWidth < roi.width || _maxBufRows != (int)rows.size() )
+ if (this_.maxWidth < this_.roi.width || _maxBufRows != (int)this_.rows.size() )
{
- rows.resize(_maxBufRows);
- maxWidth = std::max(maxWidth, roi.width);
- int cn = CV_MAT_CN(srcType);
- srcRow.resize(esz*(maxWidth + ksize.width - 1));
- if( columnBorderType == BORDER_CONSTANT )
+ this_.rows.resize(_maxBufRows);
+ this_.maxWidth = std::max(this_.maxWidth, this_.roi.width);
+ int cn = CV_MAT_CN(this_.srcType);
+ this_.srcRow.resize(esz*(this_.maxWidth + this_.ksize.width - 1));
+ if (this_.columnBorderType == BORDER_CONSTANT)
{
CV_Assert(constVal != NULL);
- constBorderRow.resize(getElemSize(bufType)*(maxWidth + ksize.width - 1 + VEC_ALIGN));
- uchar *dst = alignPtr(&constBorderRow[0], VEC_ALIGN), *tdst;
- int n = (int)constBorderValue.size(), N;
- N = (maxWidth + ksize.width - 1)*esz;
- tdst = isSeparable() ? &srcRow[0] : dst;
+ this_.constBorderRow.resize(getElemSize(this_.bufType)*(this_.maxWidth + this_.ksize.width - 1 + VEC_ALIGN));
+ uchar *dst = alignPtr(&this_.constBorderRow[0], VEC_ALIGN);
+ int n = (int)this_.constBorderValue.size();
+ int N = (this_.maxWidth + this_.ksize.width - 1)*esz;
+ uchar *tdst = this_.isSeparable() ? &this_.srcRow[0] : dst;
for( i = 0; i < N; i += n )
{
tdst[i+j] = constVal[j];
}
- if( isSeparable() )
- (*rowFilter)(&srcRow[0], dst, maxWidth, cn);
+ if (this_.isSeparable())
+ (*this_.rowFilter)(&this_.srcRow[0], dst, this_.maxWidth, cn);
}
- int maxBufStep = bufElemSize*(int)alignSize(maxWidth +
- (!isSeparable() ? ksize.width - 1 : 0),VEC_ALIGN);
- ringBuf.resize(maxBufStep*rows.size()+VEC_ALIGN);
+ int maxBufStep = bufElemSize*(int)alignSize(this_.maxWidth +
+ (!this_.isSeparable() ? this_.ksize.width - 1 : 0), VEC_ALIGN);
+ this_.ringBuf.resize(maxBufStep*this_.rows.size()+VEC_ALIGN);
}
// adjust bufstep so that the used part of the ring buffer stays compact in memory
- bufStep = bufElemSize*(int)alignSize(roi.width + (!isSeparable() ? ksize.width - 1 : 0),VEC_ALIGN);
+ this_.bufStep = bufElemSize*(int)alignSize(this_.roi.width + (!this_.isSeparable() ? this_.ksize.width - 1 : 0), VEC_ALIGN);
- dx1 = std::max(anchor.x - roi.x, 0);
- dx2 = std::max(ksize.width - anchor.x - 1 + roi.x + roi.width - wholeSize.width, 0);
+ this_.dx1 = std::max(this_.anchor.x - this_.roi.x, 0);
+ this_.dx2 = std::max(this_.ksize.width - this_.anchor.x - 1 + this_.roi.x + this_.roi.width - this_.wholeSize.width, 0);
// recompute border tables
- if( dx1 > 0 || dx2 > 0 )
+ if (this_.dx1 > 0 || this_.dx2 > 0)
{
- if( rowBorderType == BORDER_CONSTANT )
+ if (this_.rowBorderType == BORDER_CONSTANT )
{
CV_Assert(constVal != NULL);
- int nr = isSeparable() ? 1 : (int)rows.size();
+ int nr = this_.isSeparable() ? 1 : (int)this_.rows.size();
for( i = 0; i < nr; i++ )
{
- uchar* dst = isSeparable() ? &srcRow[0] : alignPtr(&ringBuf[0],VEC_ALIGN) + bufStep*i;
- memcpy( dst, constVal, dx1*esz );
- memcpy( dst + (roi.width + ksize.width - 1 - dx2)*esz, constVal, dx2*esz );
+ uchar* dst = this_.isSeparable() ? &this_.srcRow[0] : alignPtr(&this_.ringBuf[0], VEC_ALIGN) + this_.bufStep*i;
+ memcpy(dst, constVal, this_.dx1*esz);
+ memcpy(dst + (this_.roi.width + this_.ksize.width - 1 - this_.dx2)*esz, constVal, this_.dx2*esz);
}
}
else
{
- int xofs1 = std::min(roi.x, anchor.x) - roi.x;
+ int xofs1 = std::min(this_.roi.x, this_.anchor.x) - this_.roi.x;
- int btab_esz = borderElemSize, wholeWidth = wholeSize.width;
- int* btab = (int*)&borderTab[0];
+ int btab_esz = this_.borderElemSize, wholeWidth = this_.wholeSize.width;
+ int* btab = (int*)&this_.borderTab[0];
- for( i = 0; i < dx1; i++ )
+ for( i = 0; i < this_.dx1; i++ )
{
- int p0 = (borderInterpolate(i-dx1, wholeWidth, rowBorderType) + xofs1)*btab_esz;
+ int p0 = (borderInterpolate(i-this_.dx1, wholeWidth, this_.rowBorderType) + xofs1)*btab_esz;
for( j = 0; j < btab_esz; j++ )
btab[i*btab_esz + j] = p0 + j;
}
- for( i = 0; i < dx2; i++ )
+ for( i = 0; i < this_.dx2; i++ )
{
- int p0 = (borderInterpolate(wholeWidth + i, wholeWidth, rowBorderType) + xofs1)*btab_esz;
+ int p0 = (borderInterpolate(wholeWidth + i, wholeWidth, this_.rowBorderType) + xofs1)*btab_esz;
for( j = 0; j < btab_esz; j++ )
- btab[(i + dx1)*btab_esz + j] = p0 + j;
+ btab[(i + this_.dx1)*btab_esz + j] = p0 + j;
}
}
}
- rowCount = dstY = 0;
- startY = startY0 = std::max(roi.y - anchor.y, 0);
- endY = std::min(roi.y + roi.height + ksize.height - anchor.y - 1, wholeSize.height);
- if( columnFilter )
- columnFilter->reset();
- if( filter2D )
- filter2D->reset();
-
- return startY;
-}
+ this_.rowCount = this_.dstY = 0;
+ this_.startY = this_.startY0 = std::max(this_.roi.y - this_.anchor.y, 0);
+ this_.endY = std::min(this_.roi.y + this_.roi.height + this_.ksize.height - this_.anchor.y - 1, this_.wholeSize.height);
+ if (this_.columnFilter)
+ this_.columnFilter->reset();
+ if (this_.filter2D)
+ this_.filter2D->reset();
-int FilterEngine::start(const Mat& src, const Size &wsz, const Point &ofs)
-{
- start( wsz, src.size(), ofs);
- return startY - ofs.y;
+ return this_.startY;
}
-int FilterEngine::remainingInputRows() const
-{
- return endY - startY - rowCount;
-}
-int FilterEngine::remainingOutputRows() const
+int FilterEngine__proceed(FilterEngine& this_, const uchar* src, int srcstep, int count,
+ uchar* dst, int dststep)
{
- return roi.height - dstY;
-}
+ CV_INSTRUMENT_REGION();
-int FilterEngine::proceed( const uchar* src, int srcstep, int count,
- uchar* dst, int dststep )
-{
- CV_Assert( wholeSize.width > 0 && wholeSize.height > 0 );
-
- const int *btab = &borderTab[0];
- int esz = (int)getElemSize(srcType), btab_esz = borderElemSize;
- uchar** brows = &rows[0];
- int bufRows = (int)rows.size();
- int cn = CV_MAT_CN(bufType);
- int width = roi.width, kwidth = ksize.width;
- int kheight = ksize.height, ay = anchor.y;
- int _dx1 = dx1, _dx2 = dx2;
- int width1 = roi.width + kwidth - 1;
- int xofs1 = std::min(roi.x, anchor.x);
- bool isSep = isSeparable();
- bool makeBorder = (_dx1 > 0 || _dx2 > 0) && rowBorderType != BORDER_CONSTANT;
+ CV_DbgAssert(this_.wholeSize.width > 0 && this_.wholeSize.height > 0 );
+
+ const int *btab = &this_.borderTab[0];
+ int esz = (int)getElemSize(this_.srcType), btab_esz = this_.borderElemSize;
+ uchar** brows = &this_.rows[0];
+ int bufRows = (int)this_.rows.size();
+ int cn = CV_MAT_CN(this_.bufType);
+ int width = this_.roi.width, kwidth = this_.ksize.width;
+ int kheight = this_.ksize.height, ay = this_.anchor.y;
+ int _dx1 = this_.dx1, _dx2 = this_.dx2;
+ int width1 = this_.roi.width + kwidth - 1;
+ int xofs1 = std::min(this_.roi.x, this_.anchor.x);
+ bool isSep = this_.isSeparable();
+ bool makeBorder = (_dx1 > 0 || _dx2 > 0) && this_.rowBorderType != BORDER_CONSTANT;
int dy = 0, i = 0;
src -= xofs1*esz;
- count = std::min(count, remainingInputRows());
+ count = std::min(count, this_.remainingInputRows());
- CV_Assert( src && dst && count > 0 );
+ CV_Assert(src && dst && count > 0);
for(;; dst += dststep*i, dy += i)
{
- int dcount = bufRows - ay - startY - rowCount + roi.y;
+ int dcount = bufRows - ay - this_.startY - this_.rowCount + this_.roi.y;
dcount = dcount > 0 ? dcount : bufRows - kheight + 1;
dcount = std::min(dcount, count);
count -= dcount;
for( ; dcount-- > 0; src += srcstep )
{
- int bi = (startY - startY0 + rowCount) % bufRows;
- uchar* brow = alignPtr(&ringBuf[0], VEC_ALIGN) + bi*bufStep;
- uchar* row = isSep ? &srcRow[0] : brow;
+ int bi = (this_.startY - this_.startY0 + this_.rowCount) % bufRows;
+ uchar* brow = alignPtr(&this_.ringBuf[0], VEC_ALIGN) + bi*this_.bufStep;
+ uchar* row = isSep ? &this_.srcRow[0] : brow;
- if( ++rowCount > bufRows )
+ if (++this_.rowCount > bufRows)
{
- --rowCount;
- ++startY;
+ --this_.rowCount;
+ ++this_.startY;
}
memcpy( row + _dx1*esz, src, (width1 - _dx2 - _dx1)*esz );
}
if( isSep )
- (*rowFilter)(row, brow, width, CV_MAT_CN(srcType));
+ (*this_.rowFilter)(row, brow, width, CV_MAT_CN(this_.srcType));
}
- int max_i = std::min(bufRows, roi.height - (dstY + dy) + (kheight - 1));
+ int max_i = std::min(bufRows, this_.roi.height - (this_.dstY + dy) + (kheight - 1));
for( i = 0; i < max_i; i++ )
{
- int srcY = borderInterpolate(dstY + dy + i + roi.y - ay,
- wholeSize.height, columnBorderType);
+ int srcY = borderInterpolate(this_.dstY + dy + i + this_.roi.y - ay,
+ this_.wholeSize.height, this_.columnBorderType);
if( srcY < 0 ) // can happen only with constant border type
- brows[i] = alignPtr(&constBorderRow[0], VEC_ALIGN);
+ brows[i] = alignPtr(&this_.constBorderRow[0], VEC_ALIGN);
else
{
- CV_Assert( srcY >= startY );
- if( srcY >= startY + rowCount )
+ CV_Assert(srcY >= this_.startY);
+ if( srcY >= this_.startY + this_.rowCount)
break;
- int bi = (srcY - startY0) % bufRows;
- brows[i] = alignPtr(&ringBuf[0], VEC_ALIGN) + bi*bufStep;
+ int bi = (srcY - this_.startY0) % bufRows;
+ brows[i] = alignPtr(&this_.ringBuf[0], VEC_ALIGN) + bi*this_.bufStep;
}
}
if( i < kheight )
break;
i -= kheight - 1;
- if( isSeparable() )
- (*columnFilter)((const uchar**)brows, dst, dststep, i, roi.width*cn);
+ if (isSep)
+ (*this_.columnFilter)((const uchar**)brows, dst, dststep, i, this_.roi.width*cn);
else
- (*filter2D)((const uchar**)brows, dst, dststep, i, roi.width, cn);
+ (*this_.filter2D)((const uchar**)brows, dst, dststep, i, this_.roi.width, cn);
}
- dstY += dy;
- CV_Assert( dstY <= roi.height );
+ this_.dstY += dy;
+ CV_Assert(this_.dstY <= this_.roi.height);
return dy;
}
-void FilterEngine::apply(const Mat& src, Mat& dst, const Size & wsz, const Point & ofs)
+void FilterEngine__apply(FilterEngine& this_, const Mat& src, Mat& dst, const Size& wsz, const Point& ofs)
{
CV_INSTRUMENT_REGION();
- CV_Assert( src.type() == srcType && dst.type() == dstType );
+ CV_DbgAssert(src.type() == this_.srcType && dst.type() == this_.dstType);
- int y = start(src, wsz, ofs);
- proceed(src.ptr() + y*src.step,
+ FilterEngine__start(this_, wsz, src.size(), ofs);
+ int y = this_.startY - ofs.y;
+ FilterEngine__proceed(this_,
+ src.ptr() + y*src.step,
(int)src.step,
- endY - startY,
+ this_.endY - this_.startY,
dst.ptr(),
(int)dst.step );
}
-}
-
-/****************************************************************************************\
-* Separable linear filter *
-\****************************************************************************************/
-
-int cv::getKernelType(InputArray filter_kernel, Point anchor)
-{
- Mat _kernel = filter_kernel.getMat();
- CV_Assert( _kernel.channels() == 1 );
- int i, sz = _kernel.rows*_kernel.cols;
-
- Mat kernel;
- _kernel.convertTo(kernel, CV_64F);
-
- const double* coeffs = kernel.ptr<double>();
- double sum = 0;
- int type = KERNEL_SMOOTH + KERNEL_INTEGER;
- if( (_kernel.rows == 1 || _kernel.cols == 1) &&
- anchor.x*2 + 1 == _kernel.cols &&
- anchor.y*2 + 1 == _kernel.rows )
- type |= (KERNEL_SYMMETRICAL + KERNEL_ASYMMETRICAL);
-
- for( i = 0; i < sz; i++ )
- {
- double a = coeffs[i], b = coeffs[sz - i - 1];
- if( a != b )
- type &= ~KERNEL_SYMMETRICAL;
- if( a != -b )
- type &= ~KERNEL_ASYMMETRICAL;
- if( a < 0 )
- type &= ~KERNEL_SMOOTH;
- if( a != saturate_cast<int>(a) )
- type &= ~KERNEL_INTEGER;
- sum += a;
- }
-
- if( fabs(sum - 1) > FLT_EPSILON*(fabs(sum) + 1) )
- type &= ~KERNEL_SMOOTH;
- return type;
-}
-
-
-namespace cv
-{
-
struct RowNoVec
{
RowNoVec() {}
int operator()(const uchar* _src, uchar* _dst, int width, int cn) const
{
+ CV_INSTRUMENT_REGION();
+
int i = 0, k, _ksize = kernel.rows + kernel.cols - 1;
int* dst = (int*)_dst;
const int* _kx = kernel.ptr<int>();
i += v_uint32::nlanes;
}
}
- vx_cleanup();
return i;
}
int operator()(const uchar* src, uchar* _dst, int width, int cn) const
{
+ CV_INSTRUMENT_REGION();
+
int i = 0, j, k, _ksize = kernel.rows + kernel.cols - 1;
int* dst = (int*)_dst;
bool symmetrical = (symmetryType & KERNEL_SYMMETRICAL) != 0;
}
}
}
-
- vx_cleanup();
return i;
}
int operator()(const uchar** _src, uchar* dst, int width) const
{
+ CV_INSTRUMENT_REGION();
+
int _ksize = kernel.rows + kernel.cols - 1;
if( _ksize == 1 )
return 0;
i += v_int32x4::nlanes;
}
}
-
- vx_cleanup();
return i;
}
int operator()(const uchar** _src, uchar* _dst, int width) const
{
+ CV_INSTRUMENT_REGION();
+
int ksize2 = (kernel.rows + kernel.cols - 1)/2;
const float* ky = kernel.ptr<float>() + ksize2;
int i = 0;
}
}
}
-
- vx_cleanup();
return i;
}
int operator()(const uchar* _src, uchar* _dst, int width, int cn) const
{
+ CV_INSTRUMENT_REGION();
+
int i = 0, k, _ksize = kernel.rows + kernel.cols - 1;
float* dst = (float*)_dst;
const float* _kx = kernel.ptr<float>();
v_store(dst + i, s0);
i += v_float32::nlanes;
}
- vx_cleanup();
return i;
}
int operator()(const uchar** _src, uchar* _dst, int width) const
{
+ CV_INSTRUMENT_REGION();
+
int _ksize = kernel.rows + kernel.cols - 1;
if( _ksize == 1 )
return 0;
}
}
- vx_cleanup();
return i;
}
{
RowVec_32f()
{
- haveAVX2 = CV_CPU_HAS_SUPPORT_AVX2;
#if defined USE_IPP_SEP_FILTERS
bufsz = -1;
#endif
RowVec_32f( const Mat& _kernel )
{
kernel = _kernel;
- haveAVX2 = CV_CPU_HAS_SUPPORT_AVX2;
#if defined USE_IPP_SEP_FILTERS
bufsz = -1;
#endif
int operator()(const uchar* _src, uchar* _dst, int width, int cn) const
{
+ CV_INSTRUMENT_REGION();
+
#if defined USE_IPP_SEP_FILTERS
CV_IPP_CHECK()
{
int i = 0, k;
width *= cn;
-#if CV_TRY_AVX2
- if (haveAVX2)
- return RowVec_32f_AVX(src0, _kx, dst, width, cn, _ksize);
+#if CV_AVX
+ for (; i <= width - 8; i += 8)
+ {
+ const float* src = src0 + i;
+ __m256 f, x0;
+ __m256 s0 = _mm256_set1_ps(0.0f);
+ for (k = 0; k < _ksize; k++, src += cn)
+ {
+ f = _mm256_set1_ps(_kx[k]);
+ x0 = _mm256_loadu_ps(src);
+#if CV_FMA3
+ s0 = _mm256_fmadd_ps(x0, f, s0);
+#else
+ s0 = _mm256_add_ps(s0, _mm256_mul_ps(x0, f));
+#endif
+ }
+ _mm256_storeu_ps(dst + i, s0);
+ }
#endif
v_float32 k0 = vx_setall_f32(_kx[0]);
for( ; i <= width - 4*v_float32::nlanes; i += 4*v_float32::nlanes )
v_store(dst + i, s0);
i += v_float32::nlanes;
}
- vx_cleanup();
return i;
}
Mat kernel;
- bool haveAVX2;
#if defined USE_IPP_SEP_FILTERS
private:
mutable int bufsz;
int operator()(const uchar* _src, uchar* _dst, int width, int cn) const
{
+ CV_INSTRUMENT_REGION();
+
int i = 0, _ksize = kernel.rows + kernel.cols - 1;
if( _ksize == 1 )
return 0;
v_store(dst + i, v_muladd(vx_load(src + 2*cn) - vx_load(src - 2*cn), k2, (vx_load(src + cn) - vx_load(src - cn)) * k1));
}
}
-
- vx_cleanup();
return i;
}
{
SymmColumnVec_32f() {
symmetryType=0;
- haveAVX2 = CV_CPU_HAS_SUPPORT_AVX2;
delta = 0;
}
SymmColumnVec_32f(const Mat& _kernel, int _symmetryType, int, double _delta)
symmetryType = _symmetryType;
kernel = _kernel;
delta = (float)_delta;
- haveAVX2 = CV_CPU_HAS_SUPPORT_AVX2;
CV_Assert( (symmetryType & (KERNEL_SYMMETRICAL | KERNEL_ASYMMETRICAL)) != 0 );
}
int operator()(const uchar** _src, uchar* _dst, int width) const
{
+ CV_INSTRUMENT_REGION();
+
int ksize2 = (kernel.rows + kernel.cols - 1)/2;
const float* ky = kernel.ptr<float>() + ksize2;
int i = 0, k;
if( symmetrical )
{
-#if CV_TRY_AVX2
- if (haveAVX2)
- return SymmColumnVec_32f_Symm_AVX(src, ky, dst, delta, width, ksize2);
+#if CV_AVX
+ {
+ const float *S, *S2;
+ const __m256 d8 = _mm256_set1_ps(delta);
+
+ for( ; i <= width - 16; i += 16 )
+ {
+ __m256 f = _mm256_set1_ps(ky[0]);
+ __m256 s0, s1;
+ __m256 x0;
+ S = src[0] + i;
+ s0 = _mm256_loadu_ps(S);
+#if CV_FMA3
+ s0 = _mm256_fmadd_ps(s0, f, d8);
+#else
+ s0 = _mm256_add_ps(_mm256_mul_ps(s0, f), d8);
+#endif
+ s1 = _mm256_loadu_ps(S+8);
+#if CV_FMA3
+ s1 = _mm256_fmadd_ps(s1, f, d8);
+#else
+ s1 = _mm256_add_ps(_mm256_mul_ps(s1, f), d8);
+#endif
+
+ for( k = 1; k <= ksize2; k++ )
+ {
+ S = src[k] + i;
+ S2 = src[-k] + i;
+ f = _mm256_set1_ps(ky[k]);
+ x0 = _mm256_add_ps(_mm256_loadu_ps(S), _mm256_loadu_ps(S2));
+#if CV_FMA3
+ s0 = _mm256_fmadd_ps(x0, f, s0);
+#else
+ s0 = _mm256_add_ps(s0, _mm256_mul_ps(x0, f));
+#endif
+ x0 = _mm256_add_ps(_mm256_loadu_ps(S+8), _mm256_loadu_ps(S2+8));
+#if CV_FMA3
+ s1 = _mm256_fmadd_ps(x0, f, s1);
+#else
+ s1 = _mm256_add_ps(s1, _mm256_mul_ps(x0, f));
+#endif
+ }
+
+ _mm256_storeu_ps(dst + i, s0);
+ _mm256_storeu_ps(dst + i + 8, s1);
+ }
+ }
#endif
const v_float32 d4 = vx_setall_f32(delta);
const v_float32 k0 = vx_setall_f32(ky[0]);
}
else
{
-#if CV_TRY_AVX2
- if (haveAVX2)
- return SymmColumnVec_32f_Unsymm_AVX(src, ky, dst, delta, width, ksize2);
-#endif
CV_DbgAssert(ksize2 > 0);
+#if CV_AVX
+ {
+ const float *S2;
+ const __m256 d8 = _mm256_set1_ps(delta);
+
+ for (; i <= width - 16; i += 16)
+ {
+ __m256 f, s0 = d8, s1 = d8;
+ __m256 x0;
+
+ for (k = 1; k <= ksize2; k++)
+ {
+ const float *S = src[k] + i;
+ S2 = src[-k] + i;
+ f = _mm256_set1_ps(ky[k]);
+ x0 = _mm256_sub_ps(_mm256_loadu_ps(S), _mm256_loadu_ps(S2));
+#if CV_FMA3
+ s0 = _mm256_fmadd_ps(x0, f, s0);
+#else
+ s0 = _mm256_add_ps(s0, _mm256_mul_ps(x0, f));
+#endif
+ x0 = _mm256_sub_ps(_mm256_loadu_ps(S + 8), _mm256_loadu_ps(S2 + 8));
+#if CV_FMA3
+ s1 = _mm256_fmadd_ps(x0, f, s1);
+#else
+ s1 = _mm256_add_ps(s1, _mm256_mul_ps(x0, f));
+#endif
+ }
+
+ _mm256_storeu_ps(dst + i, s0);
+ _mm256_storeu_ps(dst + i + 8, s1);
+ }
+ }
+#endif
const v_float32 d4 = vx_setall_f32(delta);
const v_float32 k1 = vx_setall_f32(ky[1]);
for( ; i <= width - 4*v_float32::nlanes; i += 4*v_float32::nlanes )
i += v_float32::nlanes;
}
}
-
- vx_cleanup();
return i;
}
int symmetryType;
float delta;
Mat kernel;
- bool haveAVX2;
};
int operator()(const uchar** _src, uchar* _dst, int width) const
{
+ CV_INSTRUMENT_REGION();
+
int ksize2 = (kernel.rows + kernel.cols - 1)/2;
const float* ky = kernel.ptr<float>() + ksize2;
int i = 0;
v_store(dst + i, v_muladd(vx_load(S2 + i) - vx_load(S0 + i), k1, d4));
}
}
-
- vx_cleanup();
return i;
}
int operator()(const uchar** src, uchar* dst, int width) const
{
+ CV_INSTRUMENT_REGION();
+
CV_DbgAssert(_nz > 0);
const float* kf = (const float*)&coeffs[0];
int i = 0, k, nz = _nz;
*(int*)(dst + i) = v_reinterpret_as_s32(v_pack_u(s16, s16)).get0();
i += v_int32x4::nlanes;
}
-
- vx_cleanup();
return i;
}
int operator()(const uchar** src, uchar* _dst, int width) const
{
+ CV_INSTRUMENT_REGION();
+
CV_DbgAssert(_nz > 0);
const float* kf = (const float*)&coeffs[0];
short* dst = (short*)_dst;
v_pack_store(dst + i, v_round(s0));
i += v_int32::nlanes;
}
-
- vx_cleanup();
return i;
}
int operator()(const uchar** _src, uchar* _dst, int width) const
{
+ CV_INSTRUMENT_REGION();
+
const float* kf = (const float*)&coeffs[0];
const float** src = (const float**)_src;
float* dst = (float*)_dst;
v_store(dst + i, s0);
i += v_float32::nlanes;
}
-
- vx_cleanup();
return i;
}
void operator()(const uchar* src, uchar* dst, int width, int cn) CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
int _ksize = ksize;
const DT* kx = kernel.ptr<DT>();
const ST* S;
void operator()(const uchar* src, uchar* dst, int width, int cn) CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
int ksize2 = this->ksize/2, ksize2n = ksize2*cn;
const DT* kx = this->kernel.template ptr<DT>() + ksize2;
bool symmetrical = (this->symmetryType & KERNEL_SYMMETRICAL) != 0;
void operator()(const uchar** src, uchar* dst, int dststep, int count, int width) CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
const ST* ky = kernel.template ptr<ST>();
ST _delta = delta;
int _ksize = ksize;
void operator()(const uchar** src, uchar* dst, int dststep, int count, int width) CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
int ksize2 = this->ksize/2;
const ST* ky = this->kernel.template ptr<ST>() + ksize2;
int i, k;
void operator()(const uchar** src, uchar* dst, int dststep, int count, int width) CV_OVERRIDE
{
+ CV_INSTRUMENT_REGION();
+
int ksize2 = this->ksize/2;
const ST* ky = this->kernel.template ptr<ST>() + ksize2;
int i;
int SHIFT, DELTA;
};
-}
-cv::Ptr<cv::BaseRowFilter> cv::getLinearRowFilter( int srcType, int bufType,
- InputArray _kernel, int anchor,
- int symmetryType )
+Ptr<BaseRowFilter> getLinearRowFilter(
+ int srcType, int bufType,
+ const Mat& kernel, int anchor,
+ int symmetryType)
{
- Mat kernel = _kernel.getMat();
+ CV_INSTRUMENT_REGION();
+
int sdepth = CV_MAT_DEPTH(srcType), ddepth = CV_MAT_DEPTH(bufType);
int cn = CV_MAT_CN(srcType);
CV_Assert( cn == CV_MAT_CN(bufType) &&
}
-cv::Ptr<cv::BaseColumnFilter> cv::getLinearColumnFilter( int bufType, int dstType,
- InputArray _kernel, int anchor,
- int symmetryType, double delta,
- int bits )
+Ptr<BaseColumnFilter> getLinearColumnFilter(
+ int bufType, int dstType,
+ const Mat& kernel, int anchor,
+ int symmetryType, double delta,
+ int bits)
{
- Mat kernel = _kernel.getMat();
+ CV_INSTRUMENT_REGION();
+
int sdepth = CV_MAT_DEPTH(bufType), ddepth = CV_MAT_DEPTH(dstType);
int cn = CV_MAT_CN(dstType);
CV_Assert( cn == CV_MAT_CN(bufType) &&
}
-cv::Ptr<cv::FilterEngine> cv::createSeparableLinearFilter(
- int _srcType, int _dstType,
- InputArray __rowKernel, InputArray __columnKernel,
- Point _anchor, double _delta,
- int _rowBorderType, int _columnBorderType,
- const Scalar& _borderValue )
-{
- Mat _rowKernel = __rowKernel.getMat(), _columnKernel = __columnKernel.getMat();
- _srcType = CV_MAT_TYPE(_srcType);
- _dstType = CV_MAT_TYPE(_dstType);
- int sdepth = CV_MAT_DEPTH(_srcType), ddepth = CV_MAT_DEPTH(_dstType);
- int cn = CV_MAT_CN(_srcType);
- CV_Assert( cn == CV_MAT_CN(_dstType) );
- int rsize = _rowKernel.rows + _rowKernel.cols - 1;
- int csize = _columnKernel.rows + _columnKernel.cols - 1;
- if( _anchor.x < 0 )
- _anchor.x = rsize/2;
- if( _anchor.y < 0 )
- _anchor.y = csize/2;
- int rtype = getKernelType(_rowKernel,
- _rowKernel.rows == 1 ? Point(_anchor.x, 0) : Point(0, _anchor.x));
- int ctype = getKernelType(_columnKernel,
- _columnKernel.rows == 1 ? Point(_anchor.y, 0) : Point(0, _anchor.y));
- Mat rowKernel, columnKernel;
-
- int bdepth = std::max(CV_32F,std::max(sdepth, ddepth));
- int bits = 0;
-
- if( sdepth == CV_8U &&
- ((rtype == KERNEL_SMOOTH+KERNEL_SYMMETRICAL &&
- ctype == KERNEL_SMOOTH+KERNEL_SYMMETRICAL &&
- ddepth == CV_8U) ||
- ((rtype & (KERNEL_SYMMETRICAL+KERNEL_ASYMMETRICAL)) &&
- (ctype & (KERNEL_SYMMETRICAL+KERNEL_ASYMMETRICAL)) &&
- (rtype & ctype & KERNEL_INTEGER) &&
- ddepth == CV_16S)) )
- {
- bdepth = CV_32S;
- bits = ddepth == CV_8U ? 8 : 0;
- _rowKernel.convertTo( rowKernel, CV_32S, 1 << bits );
- _columnKernel.convertTo( columnKernel, CV_32S, 1 << bits );
- bits *= 2;
- _delta *= (1 << bits);
- }
- else
- {
- if( _rowKernel.type() != bdepth )
- _rowKernel.convertTo( rowKernel, bdepth );
- else
- rowKernel = _rowKernel;
- if( _columnKernel.type() != bdepth )
- _columnKernel.convertTo( columnKernel, bdepth );
- else
- columnKernel = _columnKernel;
- }
-
- int _bufType = CV_MAKETYPE(bdepth, cn);
- Ptr<BaseRowFilter> _rowFilter = getLinearRowFilter(
- _srcType, _bufType, rowKernel, _anchor.x, rtype);
- Ptr<BaseColumnFilter> _columnFilter = getLinearColumnFilter(
- _bufType, _dstType, columnKernel, _anchor.y, ctype, _delta, bits );
-
- return Ptr<FilterEngine>( new FilterEngine(Ptr<BaseFilter>(), _rowFilter, _columnFilter,
- _srcType, _dstType, _bufType, _rowBorderType, _columnBorderType, _borderValue ));
-}
-
-
-/****************************************************************************************\
-* Non-separable linear filter *
-\****************************************************************************************/
-
-namespace cv
-{
-
-void preprocess2DKernel( const Mat& kernel, std::vector<Point>& coords, std::vector<uchar>& coeffs )
-{
- int i, j, k, nz = countNonZero(kernel), ktype = kernel.type();
- if(nz == 0)
- nz = 1;
- CV_Assert( ktype == CV_8U || ktype == CV_32S || ktype == CV_32F || ktype == CV_64F );
- coords.resize(nz);
- coeffs.resize(nz*getElemSize(ktype));
- uchar* _coeffs = &coeffs[0];
-
- for( i = k = 0; i < kernel.rows; i++ )
- {
- const uchar* krow = kernel.ptr(i);
- for( j = 0; j < kernel.cols; j++ )
- {
- if( ktype == CV_8U )
- {
- uchar val = krow[j];
- if( val == 0 )
- continue;
- coords[k] = Point(j,i);
- _coeffs[k++] = val;
- }
- else if( ktype == CV_32S )
- {
- int val = ((const int*)krow)[j];
- if( val == 0 )
- continue;
- coords[k] = Point(j,i);
- ((int*)_coeffs)[k++] = val;
- }
- else if( ktype == CV_32F )
- {
- float val = ((const float*)krow)[j];
- if( val == 0 )
- continue;
- coords[k] = Point(j,i);
- ((float*)_coeffs)[k++] = val;
- }
- else
- {
- double val = ((const double*)krow)[j];
- if( val == 0 )
- continue;
- coords[k] = Point(j,i);
- ((double*)_coeffs)[k++] = val;
- }
- }
- }
-}
-
template<typename ST, class CastOp, class VecOp> struct Filter2D : public BaseFilter
{
VecOp vecOp;
};
-#ifdef HAVE_OPENCL
-
-#define DIVUP(total, grain) (((total) + (grain) - 1) / (grain))
-#define ROUNDUP(sz, n) ((sz) + (n) - 1 - (((sz) + (n) - 1) % (n)))
-
-// prepare kernel: transpose and make double rows (+align). Returns size of aligned row
-// Samples:
-// a b c
-// Input: d e f
-// g h i
-// Output, last two zeros is the alignment:
-// a d g a d g 0 0
-// b e h b e h 0 0
-// c f i c f i 0 0
-template <typename T>
-static int _prepareKernelFilter2D(std::vector<T> & data, const Mat & kernel)
-{
- Mat _kernel; kernel.convertTo(_kernel, DataDepth<T>::value);
- int size_y_aligned = ROUNDUP(kernel.rows * 2, 4);
- data.clear(); data.resize(size_y_aligned * kernel.cols, 0);
- for (int x = 0; x < kernel.cols; x++)
- {
- for (int y = 0; y < kernel.rows; y++)
- {
- data[x * size_y_aligned + y] = _kernel.at<T>(y, x);
- data[x * size_y_aligned + y + kernel.rows] = _kernel.at<T>(y, x);
- }
- }
- return size_y_aligned;
-}
-
-static bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth,
- InputArray _kernel, Point anchor,
- double delta, int borderType )
-{
- int type = _src.type(), sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
- ddepth = ddepth < 0 ? sdepth : ddepth;
- int dtype = CV_MAKE_TYPE(ddepth, cn), wdepth = std::max(std::max(sdepth, ddepth), CV_32F),
- wtype = CV_MAKE_TYPE(wdepth, cn);
- if (cn > 4)
- return false;
-
- Size ksize = _kernel.size();
- if (anchor.x < 0)
- anchor.x = ksize.width / 2;
- if (anchor.y < 0)
- anchor.y = ksize.height / 2;
-
- bool isolated = (borderType & BORDER_ISOLATED) != 0;
- borderType &= ~BORDER_ISOLATED;
- const cv::ocl::Device &device = cv::ocl::Device::getDefault();
- bool doubleSupport = device.doubleFPConfig() > 0;
- if (wdepth == CV_64F && !doubleSupport)
- return false;
-
- const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT",
- "BORDER_WRAP", "BORDER_REFLECT_101" };
-
- cv::Mat kernelMat = _kernel.getMat();
- cv::Size sz = _src.size(), wholeSize;
- size_t globalsize[2] = { (size_t)sz.width, (size_t)sz.height };
- size_t localsize_general[2] = {0, 1};
- size_t* localsize = NULL;
-
- ocl::Kernel k;
- UMat src = _src.getUMat();
- if (!isolated)
- {
- Point ofs;
- src.locateROI(wholeSize, ofs);
- }
-
- size_t tryWorkItems = device.maxWorkGroupSize();
- if (device.isIntel() && 128 < tryWorkItems)
- tryWorkItems = 128;
- char cvt[2][40];
-
- // For smaller filter kernels, there is a special kernel that is more
- // efficient than the general one.
- UMat kernalDataUMat;
- if (device.isIntel() && (device.type() & ocl::Device::TYPE_GPU) &&
- ((ksize.width < 5 && ksize.height < 5) ||
- (ksize.width == 5 && ksize.height == 5 && cn == 1)))
- {
- kernelMat = kernelMat.reshape(0, 1);
- String kerStr = ocl::kernelToStr(kernelMat, CV_32F);
- int h = isolated ? sz.height : wholeSize.height;
- int w = isolated ? sz.width : wholeSize.width;
-
- if (w < ksize.width || h < ksize.height)
- return false;
-
- // Figure out what vector size to use for loading the pixels.
- int pxLoadNumPixels = cn != 1 || sz.width % 4 ? 1 : 4;
- int pxLoadVecSize = cn * pxLoadNumPixels;
-
- // Figure out how many pixels per work item to compute in X and Y
- // directions. Too many and we run out of registers.
- int pxPerWorkItemX = 1;
- int pxPerWorkItemY = 1;
- if (cn <= 2 && ksize.width <= 4 && ksize.height <= 4)
- {
- pxPerWorkItemX = sz.width % 8 ? sz.width % 4 ? sz.width % 2 ? 1 : 2 : 4 : 8;
- pxPerWorkItemY = sz.height % 2 ? 1 : 2;
- }
- else if (cn < 4 || (ksize.width <= 4 && ksize.height <= 4))
- {
- pxPerWorkItemX = sz.width % 2 ? 1 : 2;
- pxPerWorkItemY = sz.height % 2 ? 1 : 2;
- }
- globalsize[0] = sz.width / pxPerWorkItemX;
- globalsize[1] = sz.height / pxPerWorkItemY;
-
- // Need some padding in the private array for pixels
- int privDataWidth = ROUNDUP(pxPerWorkItemX + ksize.width - 1, pxLoadNumPixels);
-
- // Make the global size a nice round number so the runtime can pick
- // from reasonable choices for the workgroup size
- const int wgRound = 256;
- globalsize[0] = ROUNDUP(globalsize[0], wgRound);
-
- char build_options[1024];
- sprintf(build_options, "-D cn=%d "
- "-D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d "
- "-D PX_LOAD_VEC_SIZE=%d -D PX_LOAD_NUM_PX=%d "
- "-D PX_PER_WI_X=%d -D PX_PER_WI_Y=%d -D PRIV_DATA_WIDTH=%d -D %s -D %s "
- "-D PX_LOAD_X_ITERATIONS=%d -D PX_LOAD_Y_ITERATIONS=%d "
- "-D srcT=%s -D srcT1=%s -D dstT=%s -D dstT1=%s -D WT=%s -D WT1=%s "
- "-D convertToWT=%s -D convertToDstT=%s %s",
- cn, anchor.x, anchor.y, ksize.width, ksize.height,
- pxLoadVecSize, pxLoadNumPixels,
- pxPerWorkItemX, pxPerWorkItemY, privDataWidth, borderMap[borderType],
- isolated ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED",
- privDataWidth / pxLoadNumPixels, pxPerWorkItemY + ksize.height - 1,
- ocl::typeToStr(type), ocl::typeToStr(sdepth), ocl::typeToStr(dtype),
- ocl::typeToStr(ddepth), ocl::typeToStr(wtype), ocl::typeToStr(wdepth),
- ocl::convertTypeStr(sdepth, wdepth, cn, cvt[0]),
- ocl::convertTypeStr(wdepth, ddepth, cn, cvt[1]), kerStr.c_str());
-
- if (!k.create("filter2DSmall", cv::ocl::imgproc::filter2DSmall_oclsrc, build_options))
- return false;
- }
- else
- {
- localsize = localsize_general;
- std::vector<float> kernelMatDataFloat;
- int kernel_size_y2_aligned = _prepareKernelFilter2D<float>(kernelMatDataFloat, kernelMat);
- String kerStr = ocl::kernelToStr(kernelMatDataFloat, CV_32F);
-
- for ( ; ; )
- {
- size_t BLOCK_SIZE = tryWorkItems;
- while (BLOCK_SIZE > 32 && BLOCK_SIZE >= (size_t)ksize.width * 2 && BLOCK_SIZE > (size_t)sz.width * 2)
- BLOCK_SIZE /= 2;
-
- if ((size_t)ksize.width > BLOCK_SIZE)
- return false;
-
- int requiredTop = anchor.y;
- int requiredLeft = (int)BLOCK_SIZE; // not this: anchor.x;
- int requiredBottom = ksize.height - 1 - anchor.y;
- int requiredRight = (int)BLOCK_SIZE; // not this: ksize.width - 1 - anchor.x;
- int h = isolated ? sz.height : wholeSize.height;
- int w = isolated ? sz.width : wholeSize.width;
- bool extra_extrapolation = h < requiredTop || h < requiredBottom || w < requiredLeft || w < requiredRight;
-
- if ((w < ksize.width) || (h < ksize.height))
- return false;
-
- String opts = format("-D LOCAL_SIZE=%d -D cn=%d "
- "-D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d "
- "-D KERNEL_SIZE_Y2_ALIGNED=%d -D %s -D %s -D %s%s%s "
- "-D srcT=%s -D srcT1=%s -D dstT=%s -D dstT1=%s -D WT=%s -D WT1=%s "
- "-D convertToWT=%s -D convertToDstT=%s",
- (int)BLOCK_SIZE, cn, anchor.x, anchor.y,
- ksize.width, ksize.height, kernel_size_y2_aligned, borderMap[borderType],
- extra_extrapolation ? "EXTRA_EXTRAPOLATION" : "NO_EXTRA_EXTRAPOLATION",
- isolated ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED",
- doubleSupport ? " -D DOUBLE_SUPPORT" : "", kerStr.c_str(),
- ocl::typeToStr(type), ocl::typeToStr(sdepth), ocl::typeToStr(dtype),
- ocl::typeToStr(ddepth), ocl::typeToStr(wtype), ocl::typeToStr(wdepth),
- ocl::convertTypeStr(sdepth, wdepth, cn, cvt[0]),
- ocl::convertTypeStr(wdepth, ddepth, cn, cvt[1]));
-
- localsize[0] = BLOCK_SIZE;
- globalsize[0] = DIVUP(sz.width, BLOCK_SIZE - (ksize.width - 1)) * BLOCK_SIZE;
- globalsize[1] = sz.height;
-
- if (!k.create("filter2D", cv::ocl::imgproc::filter2D_oclsrc, opts))
- return false;
-
- size_t kernelWorkGroupSize = k.workGroupSize();
- if (localsize[0] <= kernelWorkGroupSize)
- break;
- if (BLOCK_SIZE < kernelWorkGroupSize)
- return false;
- tryWorkItems = kernelWorkGroupSize;
- }
- }
-
- _dst.create(sz, dtype);
- UMat dst = _dst.getUMat();
-
- int srcOffsetX = (int)((src.offset % src.step) / src.elemSize());
- int srcOffsetY = (int)(src.offset / src.step);
- int srcEndX = (isolated ? (srcOffsetX + sz.width) : wholeSize.width);
- int srcEndY = (isolated ? (srcOffsetY + sz.height) : wholeSize.height);
-
- k.args(ocl::KernelArg::PtrReadOnly(src), (int)src.step, srcOffsetX, srcOffsetY,
- srcEndX, srcEndY, ocl::KernelArg::WriteOnly(dst), (float)delta);
-
- return k.run(2, globalsize, localsize, false);
-}
-
-const int shift_bits = 8;
-
-static bool ocl_sepRowFilter2D(const UMat & src, UMat & buf, const Mat & kernelX, int anchor,
- int borderType, int ddepth, bool fast8uc1, bool int_arithm)
-{
- int type = src.type(), cn = CV_MAT_CN(type), sdepth = CV_MAT_DEPTH(type);
- bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
- Size bufSize = buf.size();
- int buf_type = buf.type(), bdepth = CV_MAT_DEPTH(buf_type);
-
- if (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F))
- return false;
-
-#ifdef __ANDROID__
- size_t localsize[2] = {16, 10};
-#else
- size_t localsize[2] = {16, 16};
-#endif
-
- size_t globalsize[2] = {DIVUP(bufSize.width, localsize[0]) * localsize[0], DIVUP(bufSize.height, localsize[1]) * localsize[1]};
- if (fast8uc1)
- globalsize[0] = DIVUP((bufSize.width + 3) >> 2, localsize[0]) * localsize[0];
-
- int radiusX = anchor, radiusY = (buf.rows - src.rows) >> 1;
-
- bool isolated = (borderType & BORDER_ISOLATED) != 0;
- const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", "BORDER_REFLECT_101" },
- * const btype = borderMap[borderType & ~BORDER_ISOLATED];
-
- bool extra_extrapolation = src.rows < (int)((-radiusY + globalsize[1]) >> 1) + 1;
- extra_extrapolation |= src.rows < radiusY;
- extra_extrapolation |= src.cols < (int)((-radiusX + globalsize[0] + 8 * localsize[0] + 3) >> 1) + 1;
- extra_extrapolation |= src.cols < radiusX;
-
- char cvt[40];
- cv::String build_options = cv::format("-D RADIUSX=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D %s -D %s -D %s"
- " -D srcT=%s -D dstT=%s -D convertToDstT=%s -D srcT1=%s -D dstT1=%s%s%s",
- radiusX, (int)localsize[0], (int)localsize[1], cn, btype,
- extra_extrapolation ? "EXTRA_EXTRAPOLATION" : "NO_EXTRA_EXTRAPOLATION",
- isolated ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED",
- ocl::typeToStr(type), ocl::typeToStr(buf_type),
- ocl::convertTypeStr(sdepth, bdepth, cn, cvt),
- ocl::typeToStr(sdepth), ocl::typeToStr(bdepth),
- doubleSupport ? " -D DOUBLE_SUPPORT" : "",
- int_arithm ? " -D INTEGER_ARITHMETIC" : "");
- build_options += ocl::kernelToStr(kernelX, bdepth);
-
- Size srcWholeSize; Point srcOffset;
- src.locateROI(srcWholeSize, srcOffset);
-
- String kernelName("row_filter");
- if (fast8uc1)
- kernelName += "_C1_D0";
-
- ocl::Kernel k(kernelName.c_str(), cv::ocl::imgproc::filterSepRow_oclsrc,
- build_options);
- if (k.empty())
- return false;
-
- if (fast8uc1)
- k.args(ocl::KernelArg::PtrReadOnly(src), (int)(src.step / src.elemSize()), srcOffset.x,
- srcOffset.y, src.cols, src.rows, srcWholeSize.width, srcWholeSize.height,
- ocl::KernelArg::PtrWriteOnly(buf), (int)(buf.step / buf.elemSize()),
- buf.cols, buf.rows, radiusY);
- else
- k.args(ocl::KernelArg::PtrReadOnly(src), (int)src.step, srcOffset.x,
- srcOffset.y, src.cols, src.rows, srcWholeSize.width, srcWholeSize.height,
- ocl::KernelArg::PtrWriteOnly(buf), (int)buf.step, buf.cols, buf.rows, radiusY);
-
- return k.run(2, globalsize, localsize, false);
-}
-static bool ocl_sepColFilter2D(const UMat & buf, UMat & dst, const Mat & kernelY, double delta, int anchor, bool int_arithm)
+Ptr<BaseFilter> getLinearFilter(
+ int srcType, int dstType,
+ const Mat& _kernel, Point anchor,
+ double delta, int bits)
{
- bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
- if (dst.depth() == CV_64F && !doubleSupport)
- return false;
-
-#ifdef __ANDROID__
- size_t localsize[2] = { 16, 10 };
-#else
- size_t localsize[2] = { 16, 16 };
-#endif
- size_t globalsize[2] = { 0, 0 };
-
- int dtype = dst.type(), cn = CV_MAT_CN(dtype), ddepth = CV_MAT_DEPTH(dtype);
- Size sz = dst.size();
- int buf_type = buf.type(), bdepth = CV_MAT_DEPTH(buf_type);
-
- globalsize[1] = DIVUP(sz.height, localsize[1]) * localsize[1];
- globalsize[0] = DIVUP(sz.width, localsize[0]) * localsize[0];
-
- char cvt[40];
- cv::String build_options = cv::format("-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d"
- " -D srcT=%s -D dstT=%s -D convertToDstT=%s"
- " -D srcT1=%s -D dstT1=%s -D SHIFT_BITS=%d%s%s",
- anchor, (int)localsize[0], (int)localsize[1], cn,
- ocl::typeToStr(buf_type), ocl::typeToStr(dtype),
- ocl::convertTypeStr(bdepth, ddepth, cn, cvt),
- ocl::typeToStr(bdepth), ocl::typeToStr(ddepth),
- 2*shift_bits, doubleSupport ? " -D DOUBLE_SUPPORT" : "",
- int_arithm ? " -D INTEGER_ARITHMETIC" : "");
- build_options += ocl::kernelToStr(kernelY, bdepth);
-
- ocl::Kernel k("col_filter", cv::ocl::imgproc::filterSepCol_oclsrc,
- build_options);
- if (k.empty())
- return false;
-
- k.args(ocl::KernelArg::ReadOnly(buf), ocl::KernelArg::WriteOnly(dst),
- static_cast<float>(delta));
-
- return k.run(2, globalsize, localsize, false);
-}
-
-const int optimizedSepFilterLocalWidth = 16;
-const int optimizedSepFilterLocalHeight = 8;
-
-static bool ocl_sepFilter2D_SinglePass(InputArray _src, OutputArray _dst,
- Mat row_kernel, Mat col_kernel,
- double delta, int borderType, int ddepth, int bdepth, bool int_arithm)
-{
- Size size = _src.size(), wholeSize;
- Point origin;
- int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype),
- esz = CV_ELEM_SIZE(stype), wdepth = std::max(std::max(sdepth, ddepth), bdepth),
- dtype = CV_MAKE_TYPE(ddepth, cn);
- size_t src_step = _src.step(), src_offset = _src.offset();
- bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
-
- if (esz == 0 || src_step == 0
- || (src_offset % src_step) % esz != 0
- || (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F))
- || !(borderType == BORDER_CONSTANT
- || borderType == BORDER_REPLICATE
- || borderType == BORDER_REFLECT
- || borderType == BORDER_WRAP
- || borderType == BORDER_REFLECT_101))
- return false;
-
- size_t lt2[2] = { optimizedSepFilterLocalWidth, optimizedSepFilterLocalHeight };
- size_t gt2[2] = { lt2[0] * (1 + (size.width - 1) / lt2[0]), lt2[1]};
-
- char cvt[2][40];
- const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP",
- "BORDER_REFLECT_101" };
-
- String opts = cv::format("-D BLK_X=%d -D BLK_Y=%d -D RADIUSX=%d -D RADIUSY=%d%s%s"
- " -D srcT=%s -D convertToWT=%s -D WT=%s -D dstT=%s -D convertToDstT=%s"
- " -D %s -D srcT1=%s -D dstT1=%s -D WT1=%s -D CN=%d -D SHIFT_BITS=%d%s",
- (int)lt2[0], (int)lt2[1], row_kernel.cols / 2, col_kernel.cols / 2,
- ocl::kernelToStr(row_kernel, wdepth, "KERNEL_MATRIX_X").c_str(),
- ocl::kernelToStr(col_kernel, wdepth, "KERNEL_MATRIX_Y").c_str(),
- ocl::typeToStr(stype), ocl::convertTypeStr(sdepth, wdepth, cn, cvt[0]),
- ocl::typeToStr(CV_MAKE_TYPE(wdepth, cn)), ocl::typeToStr(dtype),
- ocl::convertTypeStr(wdepth, ddepth, cn, cvt[1]), borderMap[borderType],
- ocl::typeToStr(sdepth), ocl::typeToStr(ddepth), ocl::typeToStr(wdepth),
- cn, 2*shift_bits, int_arithm ? " -D INTEGER_ARITHMETIC" : "");
-
- ocl::Kernel k("sep_filter", ocl::imgproc::filterSep_singlePass_oclsrc, opts);
- if (k.empty())
- return false;
-
- UMat src = _src.getUMat();
- _dst.create(size, dtype);
- UMat dst = _dst.getUMat();
-
- int src_offset_x = static_cast<int>((src_offset % src_step) / esz);
- int src_offset_y = static_cast<int>(src_offset / src_step);
-
- src.locateROI(wholeSize, origin);
-
- k.args(ocl::KernelArg::PtrReadOnly(src), (int)src_step, src_offset_x, src_offset_y,
- wholeSize.height, wholeSize.width, ocl::KernelArg::WriteOnly(dst),
- static_cast<float>(delta));
-
- return k.run(2, gt2, lt2, false);
-}
-
-bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth,
- InputArray _kernelX, InputArray _kernelY, Point anchor,
- double delta, int borderType )
-{
- const ocl::Device & d = ocl::Device::getDefault();
- Size imgSize = _src.size();
-
- int type = _src.type(), sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
- if (cn > 4)
- return false;
-
- Mat kernelX = _kernelX.getMat().reshape(1, 1);
- if (kernelX.cols % 2 != 1)
- return false;
- Mat kernelY = _kernelY.getMat().reshape(1, 1);
- if (kernelY.cols % 2 != 1)
- return false;
-
- if (ddepth < 0)
- ddepth = sdepth;
-
- if (anchor.x < 0)
- anchor.x = kernelX.cols >> 1;
- if (anchor.y < 0)
- anchor.y = kernelY.cols >> 1;
-
- int rtype = getKernelType(kernelX,
- kernelX.rows == 1 ? Point(anchor.x, 0) : Point(0, anchor.x));
- int ctype = getKernelType(kernelY,
- kernelY.rows == 1 ? Point(anchor.y, 0) : Point(0, anchor.y));
-
- int bdepth = CV_32F;
- bool int_arithm = false;
- if( sdepth == CV_8U && ddepth == CV_8U &&
- rtype == KERNEL_SMOOTH+KERNEL_SYMMETRICAL &&
- ctype == KERNEL_SMOOTH+KERNEL_SYMMETRICAL)
- {
- if (ocl::Device::getDefault().isIntel())
- {
- for (int i=0; i<kernelX.cols; i++)
- kernelX.at<float>(0, i) = (float) cvRound(kernelX.at<float>(0, i) * (1 << shift_bits));
- if (kernelX.data != kernelY.data)
- for (int i=0; i<kernelX.cols; i++)
- kernelY.at<float>(0, i) = (float) cvRound(kernelY.at<float>(0, i) * (1 << shift_bits));
- } else
- {
- bdepth = CV_32S;
- kernelX.convertTo( kernelX, bdepth, 1 << shift_bits );
- kernelY.convertTo( kernelY, bdepth, 1 << shift_bits );
- }
- int_arithm = true;
- }
-
- CV_OCL_RUN_(kernelY.cols <= 21 && kernelX.cols <= 21 &&
- imgSize.width > optimizedSepFilterLocalWidth + anchor.x &&
- imgSize.height > optimizedSepFilterLocalHeight + anchor.y &&
- (!(borderType & BORDER_ISOLATED) || _src.offset() == 0) &&
- anchor == Point(kernelX.cols >> 1, kernelY.cols >> 1) &&
- OCL_PERFORMANCE_CHECK(d.isIntel()), // TODO FIXIT
- ocl_sepFilter2D_SinglePass(_src, _dst, kernelX, kernelY, delta,
- borderType & ~BORDER_ISOLATED, ddepth, bdepth, int_arithm), true)
-
- UMat src = _src.getUMat();
- Size srcWholeSize; Point srcOffset;
- src.locateROI(srcWholeSize, srcOffset);
-
- bool fast8uc1 = type == CV_8UC1 && srcOffset.x % 4 == 0 &&
- src.cols % 4 == 0 && src.step % 4 == 0;
-
- Size srcSize = src.size();
- Size bufSize(srcSize.width, srcSize.height + kernelY.cols - 1);
- UMat buf(bufSize, CV_MAKETYPE(bdepth, cn));
- if (!ocl_sepRowFilter2D(src, buf, kernelX, anchor.x, borderType, ddepth, fast8uc1, int_arithm))
- return false;
-
- _dst.create(srcSize, CV_MAKETYPE(ddepth, cn));
- UMat dst = _dst.getUMat();
-
- return ocl_sepColFilter2D(buf, dst, kernelY, delta, anchor.y, int_arithm);
-}
-
-#endif
-
-}
+ CV_INSTRUMENT_REGION();
-cv::Ptr<cv::BaseFilter> cv::getLinearFilter(int srcType, int dstType,
- InputArray filter_kernel, Point anchor,
- double delta, int bits)
-{
- Mat _kernel = filter_kernel.getMat();
int sdepth = CV_MAT_DEPTH(srcType), ddepth = CV_MAT_DEPTH(dstType);
int cn = CV_MAT_CN(srcType), kdepth = _kernel.depth();
CV_Assert( cn == CV_MAT_CN(dstType) && ddepth >= sdepth );
srcType, dstType));
}
-
-cv::Ptr<cv::FilterEngine> cv::createLinearFilter( int _srcType, int _dstType,
- InputArray filter_kernel,
- Point _anchor, double _delta,
- int _rowBorderType, int _columnBorderType,
- const Scalar& _borderValue )
-{
- Mat _kernel = filter_kernel.getMat();
- _srcType = CV_MAT_TYPE(_srcType);
- _dstType = CV_MAT_TYPE(_dstType);
- int cn = CV_MAT_CN(_srcType);
- CV_Assert( cn == CV_MAT_CN(_dstType) );
-
- Mat kernel = _kernel;
- int bits = 0;
-
- /*int sdepth = CV_MAT_DEPTH(_srcType), ddepth = CV_MAT_DEPTH(_dstType);
- int ktype = _kernel.depth() == CV_32S ? KERNEL_INTEGER : getKernelType(_kernel, _anchor);
- if( sdepth == CV_8U && (ddepth == CV_8U || ddepth == CV_16S) &&
- _kernel.rows*_kernel.cols <= (1 << 10) )
- {
- bits = (ktype & KERNEL_INTEGER) ? 0 : 11;
- _kernel.convertTo(kernel, CV_32S, 1 << bits);
- }*/
-
- Ptr<BaseFilter> _filter2D = getLinearFilter(_srcType, _dstType,
- kernel, _anchor, _delta, bits);
-
- return makePtr<FilterEngine>(_filter2D, Ptr<BaseRowFilter>(),
- Ptr<BaseColumnFilter>(), _srcType, _dstType, _srcType,
- _rowBorderType, _columnBorderType, _borderValue );
-}
-
-
-//================================================================
-// HAL interface
-//================================================================
-
-using namespace cv;
-
-static bool replacementFilter2D(int stype, int dtype, int kernel_type,
- uchar * src_data, size_t src_step,
- uchar * dst_data, size_t dst_step,
- int width, int height,
- int full_width, int full_height,
- int offset_x, int offset_y,
- uchar * kernel_data, size_t kernel_step,
- int kernel_width, int kernel_height,
- int anchor_x, int anchor_y,
- double delta, int borderType, bool isSubmatrix)
-{
- cvhalFilter2D* ctx;
- int res = cv_hal_filterInit(&ctx, kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, width, height,
- stype, dtype, borderType, delta, anchor_x, anchor_y, isSubmatrix, src_data == dst_data);
- if (res != CV_HAL_ERROR_OK)
- return false;
- res = cv_hal_filter(ctx, src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y);
- bool success = (res == CV_HAL_ERROR_OK);
- res = cv_hal_filterFree(ctx);
- if (res != CV_HAL_ERROR_OK)
- return false;
- return success;
-}
-
-#if 0 //defined HAVE_IPP
-static bool ippFilter2D(int stype, int dtype, int kernel_type,
- uchar * src_data, size_t src_step,
- uchar * dst_data, size_t dst_step,
- int width, int height,
- int full_width, int full_height,
- int offset_x, int offset_y,
- uchar * kernel_data, size_t kernel_step,
- int kernel_width, int kernel_height,
- int anchor_x, int anchor_y,
- double delta, int borderType,
- bool isSubmatrix)
-{
-#ifdef HAVE_IPP_IW
- CV_INSTRUMENT_REGION_IPP();
-
- ::ipp::IwiSize iwSize(width, height);
- ::ipp::IwiSize kernelSize(kernel_width, kernel_height);
- IppDataType type = ippiGetDataType(CV_MAT_DEPTH(stype));
- int channels = CV_MAT_CN(stype);
-
- CV_UNUSED(isSubmatrix);
-
-#if IPP_VERSION_X100 >= 201700 && IPP_VERSION_X100 <= 201702 // IPP bug with 1x1 kernel
- if(kernel_width == 1 && kernel_height == 1)
- return false;
-#endif
-
-#if IPP_DISABLE_FILTER2D_BIG_MASK
- // Too big difference compared to OpenCV FFT-based convolution
- if(kernel_type == CV_32FC1 && (type == ipp16s || type == ipp16u) && (kernel_width > 7 || kernel_height > 7))
- return false;
-
- // Poor optimization for big kernels
- if(kernel_width > 7 || kernel_height > 7)
- return false;
-#endif
-
- if(src_data == dst_data)
- return false;
-
- if(stype != dtype)
- return false;
-
- if(kernel_type != CV_16SC1 && kernel_type != CV_32FC1)
- return false;
-
- // TODO: Implement offset for 8u, 16u
- if(std::fabs(delta) >= DBL_EPSILON)
- return false;
-
- if(!ippiCheckAnchor(anchor_x, anchor_y, kernel_width, kernel_height))
- return false;
-
- try
- {
- ::ipp::IwiBorderSize iwBorderSize;
- ::ipp::IwiBorderType iwBorderType;
- ::ipp::IwiImage iwKernel(ippiSize(kernel_width, kernel_height), ippiGetDataType(CV_MAT_DEPTH(kernel_type)), CV_MAT_CN(kernel_type), 0, (void*)kernel_data, kernel_step);
- ::ipp::IwiImage iwSrc(iwSize, type, channels, ::ipp::IwiBorderSize(offset_x, offset_y, full_width-offset_x-width, full_height-offset_y-height), (void*)src_data, src_step);
- ::ipp::IwiImage iwDst(iwSize, type, channels, ::ipp::IwiBorderSize(offset_x, offset_y, full_width-offset_x-width, full_height-offset_y-height), (void*)dst_data, dst_step);
-
- iwBorderSize = ::ipp::iwiSizeToBorderSize(kernelSize);
- iwBorderType = ippiGetBorder(iwSrc, borderType, iwBorderSize);
- if(!iwBorderType)
- return false;
-
- CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilter, iwSrc, iwDst, iwKernel, ::ipp::IwiFilterParams(1, 0, ippAlgHintNone, ippRndFinancial), iwBorderType);
- }
- catch(const ::ipp::IwException& ex)
- {
- CV_UNUSED(ex);
- return false;
- }
-
- return true;
-#else
- CV_UNUSED(stype); CV_UNUSED(dtype); CV_UNUSED(kernel_type); CV_UNUSED(src_data); CV_UNUSED(src_step);
- CV_UNUSED(dst_data); CV_UNUSED(dst_step); CV_UNUSED(width); CV_UNUSED(height); CV_UNUSED(full_width);
- CV_UNUSED(full_height); CV_UNUSED(offset_x); CV_UNUSED(offset_y); CV_UNUSED(kernel_data); CV_UNUSED(kernel_step);
- CV_UNUSED(kernel_width); CV_UNUSED(kernel_height); CV_UNUSED(anchor_x); CV_UNUSED(anchor_y); CV_UNUSED(delta);
- CV_UNUSED(borderType); CV_UNUSED(isSubmatrix);
- return false;
#endif
-}
-#endif
-
-static bool dftFilter2D(int stype, int dtype, int kernel_type,
- uchar * src_data, size_t src_step,
- uchar * dst_data, size_t dst_step,
- int full_width, int full_height,
- int offset_x, int offset_y,
- uchar * kernel_data, size_t kernel_step,
- int kernel_width, int kernel_height,
- int anchor_x, int anchor_y,
- double delta, int borderType)
-{
- {
- int sdepth = CV_MAT_DEPTH(stype);
- int ddepth = CV_MAT_DEPTH(dtype);
- int dft_filter_size = checkHardwareSupport(CV_CPU_SSE3) && ((sdepth == CV_8U && (ddepth == CV_8U || ddepth == CV_16S)) || (sdepth == CV_32F && ddepth == CV_32F)) ? 130 : 50;
- if (kernel_width * kernel_height < dft_filter_size)
- return false;
- }
-
- Point anchor = Point(anchor_x, anchor_y);
- Mat kernel = Mat(Size(kernel_width, kernel_height), kernel_type, kernel_data, kernel_step);
-
- Mat src(Size(full_width-offset_x, full_height-offset_y), stype, src_data, src_step);
- Mat dst(Size(full_width, full_height), dtype, dst_data, dst_step);
- Mat temp;
- int src_channels = CV_MAT_CN(stype);
- int dst_channels = CV_MAT_CN(dtype);
- int ddepth = CV_MAT_DEPTH(dtype);
- // crossCorr doesn't accept non-zero delta with multiple channels
- if (src_channels != 1 && delta != 0) {
- // The semantics of filter2D require that the delta be applied
- // as floating-point math. So wee need an intermediate Mat
- // with a float datatype. If the dest is already floats,
- // we just use that.
- int corrDepth = ddepth;
- if ((ddepth == CV_32F || ddepth == CV_64F) && src_data != dst_data) {
- temp = Mat(Size(full_width, full_height), dtype, dst_data, dst_step);
- } else {
- corrDepth = ddepth == CV_64F ? CV_64F : CV_32F;
- temp.create(Size(full_width, full_height), CV_MAKETYPE(corrDepth, dst_channels));
- }
- crossCorr(src, kernel, temp, src.size(),
- CV_MAKETYPE(corrDepth, src_channels),
- anchor, 0, borderType);
- add(temp, delta, temp);
- if (temp.data != dst_data) {
- temp.convertTo(dst, dst.type());
- }
- } else {
- if (src_data != dst_data)
- temp = Mat(Size(full_width, full_height), dtype, dst_data, dst_step);
- else
- temp.create(Size(full_width, full_height), dtype);
- crossCorr(src, kernel, temp, src.size(),
- CV_MAKETYPE(ddepth, src_channels),
- anchor, delta, borderType);
- if (temp.data != dst_data)
- temp.copyTo(dst);
- }
- return true;
-}
-
-static void ocvFilter2D(int stype, int dtype, int kernel_type,
- uchar * src_data, size_t src_step,
- uchar * dst_data, size_t dst_step,
- int width, int height,
- int full_width, int full_height,
- int offset_x, int offset_y,
- uchar * kernel_data, size_t kernel_step,
- int kernel_width, int kernel_height,
- int anchor_x, int anchor_y,
- double delta, int borderType)
-{
- int borderTypeValue = borderType & ~BORDER_ISOLATED;
- Mat kernel = Mat(Size(kernel_width, kernel_height), kernel_type, kernel_data, kernel_step);
- Ptr<FilterEngine> f = createLinearFilter(stype, dtype, kernel, Point(anchor_x, anchor_y), delta,
- borderTypeValue);
- Mat src(Size(width, height), stype, src_data, src_step);
- Mat dst(Size(width, height), dtype, dst_data, dst_step);
- f->apply(src, dst, Size(full_width, full_height), Point(offset_x, offset_y));
-}
-
-static bool replacementSepFilter(int stype, int dtype, int ktype,
- uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
- int width, int height, int full_width, int full_height,
- int offset_x, int offset_y,
- uchar * kernelx_data, int kernelx_len,
- uchar * kernely_data, int kernely_len,
- int anchor_x, int anchor_y, double delta, int borderType)
-{
- cvhalFilter2D *ctx;
- int res = cv_hal_sepFilterInit(&ctx, stype, dtype, ktype,
- kernelx_data, kernelx_len,
- kernely_data, kernely_len,
- anchor_x, anchor_y, delta, borderType);
- if (res != CV_HAL_ERROR_OK)
- return false;
- res = cv_hal_sepFilter(ctx, src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y);
- bool success = (res == CV_HAL_ERROR_OK);
- res = cv_hal_sepFilterFree(ctx);
- if (res != CV_HAL_ERROR_OK)
- return false;
- return success;
-}
-
-static void ocvSepFilter(int stype, int dtype, int ktype,
- uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
- int width, int height, int full_width, int full_height,
- int offset_x, int offset_y,
- uchar * kernelx_data, int kernelx_len,
- uchar * kernely_data, int kernely_len,
- int anchor_x, int anchor_y, double delta, int borderType)
-{
- Mat kernelX(Size(kernelx_len, 1), ktype, kernelx_data);
- Mat kernelY(Size(kernely_len, 1), ktype, kernely_data);
- Ptr<FilterEngine> f = createSeparableLinearFilter(stype, dtype, kernelX, kernelY,
- Point(anchor_x, anchor_y),
- delta, borderType & ~BORDER_ISOLATED);
- Mat src(Size(width, height), stype, src_data, src_step);
- Mat dst(Size(width, height), dtype, dst_data, dst_step);
- f->apply(src, dst, Size(full_width, full_height), Point(offset_x, offset_y));
-};
-
-//===================================================================
-// HAL functions
-//===================================================================
-
-namespace cv {
-namespace hal {
-
-
-CV_DEPRECATED Ptr<hal::Filter2D> Filter2D::create(uchar * , size_t , int ,
- int , int ,
- int , int ,
- int , int ,
- int , double ,
- int , int ,
- bool , bool ) { return Ptr<hal::Filter2D>(); }
-
-CV_DEPRECATED Ptr<hal::SepFilter2D> SepFilter2D::create(int , int , int ,
- uchar * , int ,
- uchar * , int ,
- int , int ,
- double , int ) { return Ptr<hal::SepFilter2D>(); }
-
-
-void filter2D(int stype, int dtype, int kernel_type,
- uchar * src_data, size_t src_step,
- uchar * dst_data, size_t dst_step,
- int width, int height,
- int full_width, int full_height,
- int offset_x, int offset_y,
- uchar * kernel_data, size_t kernel_step,
- int kernel_width, int kernel_height,
- int anchor_x, int anchor_y,
- double delta, int borderType,
- bool isSubmatrix)
-{
- bool res;
- res = replacementFilter2D(stype, dtype, kernel_type,
- src_data, src_step,
- dst_data, dst_step,
- width, height,
- full_width, full_height,
- offset_x, offset_y,
- kernel_data, kernel_step,
- kernel_width, kernel_height,
- anchor_x, anchor_y,
- delta, borderType, isSubmatrix);
- if (res)
- return;
-
- /*CV_IPP_RUN_FAST(ippFilter2D(stype, dtype, kernel_type,
- src_data, src_step,
- dst_data, dst_step,
- width, height,
- full_width, full_height,
- offset_x, offset_y,
- kernel_data, kernel_step,
- kernel_width, kernel_height,
- anchor_x, anchor_y,
- delta, borderType, isSubmatrix))*/
-
- res = dftFilter2D(stype, dtype, kernel_type,
- src_data, src_step,
- dst_data, dst_step,
- full_width, full_height,
- offset_x, offset_y,
- kernel_data, kernel_step,
- kernel_width, kernel_height,
- anchor_x, anchor_y,
- delta, borderType);
- if (res)
- return;
- ocvFilter2D(stype, dtype, kernel_type,
- src_data, src_step,
- dst_data, dst_step,
- width, height,
- full_width, full_height,
- offset_x, offset_y,
- kernel_data, kernel_step,
- kernel_width, kernel_height,
- anchor_x, anchor_y,
- delta, borderType);
-}
-
-//---------------------------------------------------------------
-
-void sepFilter2D(int stype, int dtype, int ktype,
- uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
- int width, int height, int full_width, int full_height,
- int offset_x, int offset_y,
- uchar * kernelx_data, int kernelx_len,
- uchar * kernely_data, int kernely_len,
- int anchor_x, int anchor_y, double delta, int borderType)
-{
-
- bool res = replacementSepFilter(stype, dtype, ktype,
- src_data, src_step, dst_data, dst_step,
- width, height, full_width, full_height,
- offset_x, offset_y,
- kernelx_data, kernelx_len,
- kernely_data, kernely_len,
- anchor_x, anchor_y, delta, borderType);
- if (res)
- return;
- ocvSepFilter(stype, dtype, ktype,
- src_data, src_step, dst_data, dst_step,
- width, height, full_width, full_height,
- offset_x, offset_y,
- kernelx_data, kernelx_len,
- kernely_data, kernely_len,
- anchor_x, anchor_y, delta, borderType);
-}
-
-} // cv::hal::
-} // cv::
-
-//================================================================
-// Main interface
-//================================================================
-
-void cv::filter2D( InputArray _src, OutputArray _dst, int ddepth,
- InputArray _kernel, Point anchor0,
- double delta, int borderType )
-{
- CV_INSTRUMENT_REGION();
-
- CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
- ocl_filter2D(_src, _dst, ddepth, _kernel, anchor0, delta, borderType))
-
- Mat src = _src.getMat(), kernel = _kernel.getMat();
-
- if( ddepth < 0 )
- ddepth = src.depth();
-
- _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) );
- Mat dst = _dst.getMat();
- Point anchor = normalizeAnchor(anchor0, kernel.size());
-
- Point ofs;
- Size wsz(src.cols, src.rows);
- if( (borderType & BORDER_ISOLATED) == 0 )
- src.locateROI( wsz, ofs );
-
- hal::filter2D(src.type(), dst.type(), kernel.type(),
- src.data, src.step, dst.data, dst.step,
- dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y,
- kernel.data, kernel.step, kernel.cols, kernel.rows,
- anchor.x, anchor.y,
- delta, borderType, src.isSubmatrix());
-}
-
-void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth,
- InputArray _kernelX, InputArray _kernelY, Point anchor,
- double delta, int borderType )
-{
- CV_INSTRUMENT_REGION();
-
- CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && (size_t)_src.rows() > _kernelY.total() && (size_t)_src.cols() > _kernelX.total(),
- ocl_sepFilter2D(_src, _dst, ddepth, _kernelX, _kernelY, anchor, delta, borderType))
-
- Mat src = _src.getMat(), kernelX = _kernelX.getMat(), kernelY = _kernelY.getMat();
-
- if( ddepth < 0 )
- ddepth = src.depth();
-
- _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) );
- Mat dst = _dst.getMat();
-
- Point ofs;
- Size wsz(src.cols, src.rows);
- if( (borderType & BORDER_ISOLATED) == 0 )
- src.locateROI( wsz, ofs );
-
- CV_Assert( kernelX.type() == kernelY.type() &&
- (kernelX.cols == 1 || kernelX.rows == 1) &&
- (kernelY.cols == 1 || kernelY.rows == 1) );
-
- Mat contKernelX = kernelX.isContinuous() ? kernelX : kernelX.clone();
- Mat contKernelY = kernelY.isContinuous() ? kernelY : kernelY.clone();
-
- hal::sepFilter2D(src.type(), dst.type(), kernelX.type(),
- src.data, src.step, dst.data, dst.step,
- dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y,
- contKernelX.data, kernelX.cols + kernelX.rows - 1,
- contKernelY.data, kernelY.cols + kernelY.rows - 1,
- anchor.x, anchor.y, delta, borderType & ~BORDER_ISOLATED);
-}
-
-
-CV_IMPL void
-cvFilter2D( const CvArr* srcarr, CvArr* dstarr, const CvMat* _kernel, CvPoint anchor )
-{
- cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
- cv::Mat kernel = cv::cvarrToMat(_kernel);
-
- CV_Assert( src.size() == dst.size() && src.channels() == dst.channels() );
-
- cv::filter2D( src, dst, dst.depth(), kernel, anchor, 0, cv::BORDER_REPLICATE );
-}
-
-/* End of file. */
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+} // namespace
#ifndef _CV_FIXEDPOINT_HPP_
#define _CV_FIXEDPOINT_HPP_
-#include "opencv2/core/softfloat.hpp"
-
-namespace
-{
+namespace {
class fixedpoint64
{
#include "precomp.hpp"
#include <vector>
-/////////////////////////////////////////////////////////////////////////////////////////
-// Default LSD parameters
-// SIGMA_SCALE 0.6 - Sigma for Gaussian filter is computed as sigma = sigma_scale/scale.
-// QUANT 2.0 - Bound to the quantization error on the gradient norm.
-// ANG_TH 22.5 - Gradient angle tolerance in degrees.
-// LOG_EPS 0.0 - Detection threshold: -log10(NFA) > log_eps
-// DENSITY_TH 0.7 - Minimal density of region points in rectangle.
-// N_BINS 1024 - Number of bins in pseudo-ordering of gradient modulus.
-
-#define M_3_2_PI (3 * CV_PI) / 2 // 3/2 pi
-#define M_2__PI (2 * CV_PI) // 2 pi
-
-#ifndef M_LN10
-#define M_LN10 2.30258509299404568402
+#if defined(_MSC_VER)
+# pragma warning(disable:4702) // unreachable code
#endif
-#define NOTDEF double(-1024.0) // Label for pixels with undefined gradient.
-
-#define NOTUSED 0 // Label for pixels not used in yet.
-#define USED 1 // Label for pixels already used in detection.
-
-#define RELATIVE_ERROR_FACTOR 100.0
-
-const double DEG_TO_RADS = CV_PI / 180;
-
-#define log_gamma(x) ((x)>15.0?log_gamma_windschitl(x):log_gamma_lanczos(x))
-
-struct edge
-{
- cv::Point p;
- bool taken;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-inline double distSq(const double x1, const double y1,
- const double x2, const double y2)
-{
- return (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1);
-}
-
-inline double dist(const double x1, const double y1,
- const double x2, const double y2)
-{
- return sqrt(distSq(x1, y1, x2, y2));
-}
-
-// Signed angle difference
-inline double angle_diff_signed(const double& a, const double& b)
-{
- double diff = a - b;
- while(diff <= -CV_PI) diff += M_2__PI;
- while(diff > CV_PI) diff -= M_2__PI;
- return diff;
-}
-
-// Absolute value angle difference
-inline double angle_diff(const double& a, const double& b)
-{
- return std::fabs(angle_diff_signed(a, b));
-}
-
-// Compare doubles by relative error.
-inline bool double_equal(const double& a, const double& b)
-{
- // trivial case
- if(a == b) return true;
-
- double abs_diff = fabs(a - b);
- double aa = fabs(a);
- double bb = fabs(b);
- double abs_max = (aa > bb)? aa : bb;
-
- if(abs_max < DBL_MIN) abs_max = DBL_MIN;
-
- return (abs_diff / abs_max) <= (RELATIVE_ERROR_FACTOR * DBL_EPSILON);
-}
-
-inline bool AsmallerB_XoverY(const edge& a, const edge& b)
-{
- if (a.p.x == b.p.x) return a.p.y < b.p.y;
- else return a.p.x < b.p.x;
-}
-
-/**
- * Computes the natural logarithm of the absolute value of
- * the gamma function of x using Windschitl method.
- * See http://www.rskey.org/gamma.htm
- */
-inline double log_gamma_windschitl(const double& x)
-{
- return 0.918938533204673 + (x-0.5)*log(x) - x
- + 0.5*x*log(x*sinh(1/x) + 1/(810.0*pow(x, 6.0)));
-}
-
-/**
- * Computes the natural logarithm of the absolute value of
- * the gamma function of x using the Lanczos approximation.
- * See http://www.rskey.org/gamma.htm
- */
-inline double log_gamma_lanczos(const double& x)
-{
- static double q[7] = { 75122.6331530, 80916.6278952, 36308.2951477,
- 8687.24529705, 1168.92649479, 83.8676043424,
- 2.50662827511 };
- double a = (x + 0.5) * log(x + 5.5) - (x + 5.5);
- double b = 0;
- for(int n = 0; n < 7; ++n)
- {
- a -= log(x + double(n));
- b += q[n] * pow(x, double(n));
- }
- return a + log(b);
-}
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-namespace cv{
+namespace cv {
class LineSegmentDetectorImpl CV_FINAL : public LineSegmentDetector
{
int compareSegments(const Size& size, InputArray lines1, InputArray lines2, InputOutputArray _image = noArray()) CV_OVERRIDE;
private:
- Mat image;
- Mat scaled_image;
- Mat_<double> angles; // in rads
- Mat_<double> modgrad;
- Mat_<uchar> used;
-
- int img_width;
- int img_height;
- double LOG_NT;
-
- bool w_needed;
- bool p_needed;
- bool n_needed;
-
- const double SCALE;
- const int doRefine;
- const double SIGMA_SCALE;
- const double QUANT;
- const double ANG_TH;
- const double LOG_EPS;
- const double DENSITY_TH;
- const int N_BINS;
-
- struct RegionPoint {
- int x;
- int y;
- uchar* used;
- double angle;
- double modgrad;
- };
-
- struct normPoint
- {
- Point2i p;
- int norm;
- };
-
- std::vector<normPoint> ordered_points;
-
- struct rect
- {
- double x1, y1, x2, y2; // first and second point of the line segment
- double width; // rectangle width
- double x, y; // center of the rectangle
- double theta; // angle
- double dx,dy; // (dx,dy) is vector oriented as the line segment
- double prec; // tolerance angle
- double p; // probability of a point with angle within 'prec'
- };
-
LineSegmentDetectorImpl& operator= (const LineSegmentDetectorImpl&); // to quiet MSVC
-
-/**
- * Detect lines in the whole input image.
- *
- * @param lines Return: A vector of Vec4f elements specifying the beginning and ending point of a line.
- * Where Vec4f is (x1, y1, x2, y2), point 1 is the start, point 2 - end.
- * Returned lines are strictly oriented depending on the gradient.
- * @param widths Return: Vector of widths of the regions, where the lines are found. E.g. Width of line.
- * @param precisions Return: Vector of precisions with which the lines are found.
- * @param nfas Return: Vector containing number of false alarms in the line region, with precision of 10%.
- * The bigger the value, logarithmically better the detection.
- * * -1 corresponds to 10 mean false alarms
- * * 0 corresponds to 1 mean false alarm
- * * 1 corresponds to 0.1 mean false alarms
- */
- void flsd(std::vector<Vec4f>& lines,
- std::vector<double>& widths, std::vector<double>& precisions,
- std::vector<double>& nfas);
-
-/**
- * Finds the angles and the gradients of the image. Generates a list of pseudo ordered points.
- *
- * @param threshold The minimum value of the angle that is considered defined, otherwise NOTDEF
- * @param n_bins The number of bins with which gradients are ordered by, using bucket sort.
- * @param ordered_points Return: Vector of coordinate points that are pseudo ordered by magnitude.
- * Pixels would be ordered by norm value, up to a precision given by max_grad/n_bins.
- */
- void ll_angle(const double& threshold, const unsigned int& n_bins);
-
-/**
- * Grow a region starting from point s with a defined precision,
- * returning the containing points size and the angle of the gradients.
- *
- * @param s Starting point for the region.
- * @param reg Return: Vector of points, that are part of the region
- * @param reg_angle Return: The mean angle of the region.
- * @param prec The precision by which each region angle should be aligned to the mean.
- */
- void region_grow(const Point2i& s, std::vector<RegionPoint>& reg,
- double& reg_angle, const double& prec);
-
-/**
- * Finds the bounding rotated rectangle of a region.
- *
- * @param reg The region of points, from which the rectangle to be constructed from.
- * @param reg_angle The mean angle of the region.
- * @param prec The precision by which points were found.
- * @param p Probability of a point with angle within 'prec'.
- * @param rec Return: The generated rectangle.
- */
- void region2rect(const std::vector<RegionPoint>& reg, const double reg_angle,
- const double prec, const double p, rect& rec) const;
-
-/**
- * Compute region's angle as the principal inertia axis of the region.
- * @return Regions angle.
- */
- double get_theta(const std::vector<RegionPoint>& reg, const double& x,
- const double& y, const double& reg_angle, const double& prec) const;
-
-/**
- * An estimation of the angle tolerance is performed by the standard deviation of the angle at points
- * near the region's starting point. Then, a new region is grown starting from the same point, but using the
- * estimated angle tolerance. If this fails to produce a rectangle with the right density of region points,
- * 'reduce_region_radius' is called to try to satisfy this condition.
- */
- bool refine(std::vector<RegionPoint>& reg, double reg_angle,
- const double prec, double p, rect& rec, const double& density_th);
-
-/**
- * Reduce the region size, by elimination the points far from the starting point, until that leads to
- * rectangle with the right density of region points or to discard the region if too small.
- */
- bool reduce_region_radius(std::vector<RegionPoint>& reg, double reg_angle,
- const double prec, double p, rect& rec, double density, const double& density_th);
-
-/**
- * Try some rectangles variations to improve NFA value. Only if the rectangle is not meaningful (i.e., log_nfa <= log_eps).
- * @return The new NFA value.
- */
- double rect_improve(rect& rec) const;
-
-/**
- * Calculates the number of correctly aligned points within the rectangle.
- * @return The new NFA value.
- */
- double rect_nfa(const rect& rec) const;
-
-/**
- * Computes the NFA values based on the total number of points, points that agree.
- * n, k, p are the binomial parameters.
- * @return The new NFA value.
- */
- double nfa(const int& n, const int& k, const double& p) const;
-
-/**
- * Is the point at place 'address' aligned to angle theta, up to precision 'prec'?
- * @return Whether the point is aligned.
- */
- bool isAligned(int x, int y, const double& theta, const double& prec) const;
-
-public:
- // Compare norm
- static inline bool compare_norm( const normPoint& n1, const normPoint& n2 )
- {
- return (n1.norm > n2.norm);
- }
};
/////////////////////////////////////////////////////////////////////////////////////////
LineSegmentDetectorImpl::LineSegmentDetectorImpl(int _refine, double _scale, double _sigma_scale, double _quant,
double _ang_th, double _log_eps, double _density_th, int _n_bins)
- : img_width(0), img_height(0), LOG_NT(0), w_needed(false), p_needed(false), n_needed(false),
- SCALE(_scale), doRefine(_refine), SIGMA_SCALE(_sigma_scale), QUANT(_quant),
- ANG_TH(_ang_th), LOG_EPS(_log_eps), DENSITY_TH(_density_th), N_BINS(_n_bins)
{
CV_Assert(_scale > 0 && _sigma_scale > 0 && _quant >= 0 &&
_ang_th > 0 && _ang_th < 180 && _density_th >= 0 && _density_th < 1 &&
_n_bins > 0);
+ CV_UNUSED(_refine); CV_UNUSED(_log_eps);
+ CV_Error(Error::StsNotImplemented, "Implementation has been removed due original code license issues");
}
void LineSegmentDetectorImpl::detect(InputArray _image, OutputArray _lines,
{
CV_INSTRUMENT_REGION();
- image = _image.getMat();
- CV_Assert(!image.empty() && image.type() == CV_8UC1);
-
- std::vector<Vec4f> lines;
- std::vector<double> w, p, n;
- w_needed = _width.needed();
- p_needed = _prec.needed();
- if (doRefine < LSD_REFINE_ADV)
- n_needed = false;
- else
- n_needed = _nfa.needed();
-
- flsd(lines, w, p, n);
-
- Mat(lines).copyTo(_lines);
- if(w_needed) Mat(w).copyTo(_width);
- if(p_needed) Mat(p).copyTo(_prec);
- if(n_needed) Mat(n).copyTo(_nfa);
-
- // Clear used structures
- ordered_points.clear();
-}
-
-void LineSegmentDetectorImpl::flsd(std::vector<Vec4f>& lines,
- std::vector<double>& widths, std::vector<double>& precisions,
- std::vector<double>& nfas)
-{
- // Angle tolerance
- const double prec = CV_PI * ANG_TH / 180;
- const double p = ANG_TH / 180;
- const double rho = QUANT / sin(prec); // gradient magnitude threshold
-
- if(SCALE != 1)
- {
- Mat gaussian_img;
- const double sigma = (SCALE < 1)?(SIGMA_SCALE / SCALE):(SIGMA_SCALE);
- const double sprec = 3;
- const unsigned int h = (unsigned int)(ceil(sigma * sqrt(2 * sprec * log(10.0))));
- Size ksize(1 + 2 * h, 1 + 2 * h); // kernel size
- GaussianBlur(image, gaussian_img, ksize, sigma);
- // Scale image to needed size
- resize(gaussian_img, scaled_image, Size(), SCALE, SCALE, INTER_LINEAR_EXACT);
- ll_angle(rho, N_BINS);
- }
- else
- {
- scaled_image = image;
- ll_angle(rho, N_BINS);
- }
-
- LOG_NT = 5 * (log10(double(img_width)) + log10(double(img_height))) / 2 + log10(11.0);
- const size_t min_reg_size = size_t(-LOG_NT/log10(p)); // minimal number of points in region that can give a meaningful event
-
- // // Initialize region only when needed
- // Mat region = Mat::zeros(scaled_image.size(), CV_8UC1);
- used = Mat_<uchar>::zeros(scaled_image.size()); // zeros = NOTUSED
- std::vector<RegionPoint> reg;
-
- // Search for line segments
- for(size_t i = 0, points_size = ordered_points.size(); i < points_size; ++i)
- {
- const Point2i& point = ordered_points[i].p;
- if((used.at<uchar>(point) == NOTUSED) && (angles.at<double>(point) != NOTDEF))
- {
- double reg_angle;
- region_grow(ordered_points[i].p, reg, reg_angle, prec);
-
- // Ignore small regions
- if(reg.size() < min_reg_size) { continue; }
-
- // Construct rectangular approximation for the region
- rect rec;
- region2rect(reg, reg_angle, prec, p, rec);
-
- double log_nfa = -1;
- if(doRefine > LSD_REFINE_NONE)
- {
- // At least REFINE_STANDARD lvl.
- if(!refine(reg, reg_angle, prec, p, rec, DENSITY_TH)) { continue; }
-
- if(doRefine >= LSD_REFINE_ADV)
- {
- // Compute NFA
- log_nfa = rect_improve(rec);
- if(log_nfa <= LOG_EPS) { continue; }
- }
- }
- // Found new line
-
- // Add the offset
- rec.x1 += 0.5; rec.y1 += 0.5;
- rec.x2 += 0.5; rec.y2 += 0.5;
-
- // scale the result values if a sub-sampling was performed
- if(SCALE != 1)
- {
- rec.x1 /= SCALE; rec.y1 /= SCALE;
- rec.x2 /= SCALE; rec.y2 /= SCALE;
- rec.width /= SCALE;
- }
-
- //Store the relevant data
- lines.push_back(Vec4f(float(rec.x1), float(rec.y1), float(rec.x2), float(rec.y2)));
- if(w_needed) widths.push_back(rec.width);
- if(p_needed) precisions.push_back(rec.p);
- if(n_needed && doRefine >= LSD_REFINE_ADV) nfas.push_back(log_nfa);
- }
- }
-}
-
-void LineSegmentDetectorImpl::ll_angle(const double& threshold,
- const unsigned int& n_bins)
-{
- //Initialize data
- angles = Mat_<double>(scaled_image.size());
- modgrad = Mat_<double>(scaled_image.size());
-
- img_width = scaled_image.cols;
- img_height = scaled_image.rows;
-
- // Undefined the down and right boundaries
- angles.row(img_height - 1).setTo(NOTDEF);
- angles.col(img_width - 1).setTo(NOTDEF);
-
- // Computing gradient for remaining pixels
- double max_grad = -1;
- for(int y = 0; y < img_height - 1; ++y)
- {
- const uchar* scaled_image_row = scaled_image.ptr<uchar>(y);
- const uchar* next_scaled_image_row = scaled_image.ptr<uchar>(y+1);
- double* angles_row = angles.ptr<double>(y);
- double* modgrad_row = modgrad.ptr<double>(y);
- for(int x = 0; x < img_width-1; ++x)
- {
- int DA = next_scaled_image_row[x + 1] - scaled_image_row[x];
- int BC = scaled_image_row[x + 1] - next_scaled_image_row[x];
- int gx = DA + BC; // gradient x component
- int gy = DA - BC; // gradient y component
- double norm = std::sqrt((gx * gx + gy * gy) / 4.0); // gradient norm
-
- modgrad_row[x] = norm; // store gradient
-
- if (norm <= threshold) // norm too small, gradient no defined
- {
- angles_row[x] = NOTDEF;
- }
- else
- {
- angles_row[x] = fastAtan2(float(gx), float(-gy)) * DEG_TO_RADS; // gradient angle computation
- if (norm > max_grad) { max_grad = norm; }
- }
-
- }
- }
-
- // Compute histogram of gradient values
- double bin_coef = (max_grad > 0) ? double(n_bins - 1) / max_grad : 0; // If all image is smooth, max_grad <= 0
- for(int y = 0; y < img_height - 1; ++y)
- {
- const double* modgrad_row = modgrad.ptr<double>(y);
- for(int x = 0; x < img_width - 1; ++x)
- {
- normPoint _point;
- int i = int(modgrad_row[x] * bin_coef);
- _point.p = Point(x, y);
- _point.norm = i;
- ordered_points.push_back(_point);
- }
- }
-
- // Sort
- std::sort(ordered_points.begin(), ordered_points.end(), compare_norm);
-}
-
-void LineSegmentDetectorImpl::region_grow(const Point2i& s, std::vector<RegionPoint>& reg,
- double& reg_angle, const double& prec)
-{
- reg.clear();
-
- // Point to this region
- RegionPoint seed;
- seed.x = s.x;
- seed.y = s.y;
- seed.used = &used.at<uchar>(s);
- reg_angle = angles.at<double>(s);
- seed.angle = reg_angle;
- seed.modgrad = modgrad.at<double>(s);
- reg.push_back(seed);
-
- float sumdx = float(std::cos(reg_angle));
- float sumdy = float(std::sin(reg_angle));
- *seed.used = USED;
-
- //Try neighboring regions
- for (size_t i = 0;i<reg.size();i++)
- {
- const RegionPoint& rpoint = reg[i];
- int xx_min = std::max(rpoint.x - 1, 0), xx_max = std::min(rpoint.x + 1, img_width - 1);
- int yy_min = std::max(rpoint.y - 1, 0), yy_max = std::min(rpoint.y + 1, img_height - 1);
- for(int yy = yy_min; yy <= yy_max; ++yy)
- {
- uchar* used_row = used.ptr<uchar>(yy);
- const double* angles_row = angles.ptr<double>(yy);
- const double* modgrad_row = modgrad.ptr<double>(yy);
- for(int xx = xx_min; xx <= xx_max; ++xx)
- {
- uchar& is_used = used_row[xx];
- if(is_used != USED &&
- (isAligned(xx, yy, reg_angle, prec)))
- {
- const double& angle = angles_row[xx];
- // Add point
- is_used = USED;
- RegionPoint region_point;
- region_point.x = xx;
- region_point.y = yy;
- region_point.used = &is_used;
- region_point.modgrad = modgrad_row[xx];
- region_point.angle = angle;
- reg.push_back(region_point);
-
- // Update region's angle
- sumdx += cos(float(angle));
- sumdy += sin(float(angle));
- // reg_angle is used in the isAligned, so it needs to be updates?
- reg_angle = fastAtan2(sumdy, sumdx) * DEG_TO_RADS;
- }
- }
- }
- }
-}
-
-void LineSegmentDetectorImpl::region2rect(const std::vector<RegionPoint>& reg,
- const double reg_angle, const double prec, const double p, rect& rec) const
-{
- double x = 0, y = 0, sum = 0;
- for(size_t i = 0; i < reg.size(); ++i)
- {
- const RegionPoint& pnt = reg[i];
- const double& weight = pnt.modgrad;
- x += double(pnt.x) * weight;
- y += double(pnt.y) * weight;
- sum += weight;
- }
-
- // Weighted sum must differ from 0
- CV_Assert(sum > 0);
-
- x /= sum;
- y /= sum;
-
- double theta = get_theta(reg, x, y, reg_angle, prec);
-
- // Find length and width
- double dx = cos(theta);
- double dy = sin(theta);
- double l_min = 0, l_max = 0, w_min = 0, w_max = 0;
-
- for(size_t i = 0; i < reg.size(); ++i)
- {
- double regdx = double(reg[i].x) - x;
- double regdy = double(reg[i].y) - y;
-
- double l = regdx * dx + regdy * dy;
- double w = -regdx * dy + regdy * dx;
-
- if(l > l_max) l_max = l;
- else if(l < l_min) l_min = l;
- if(w > w_max) w_max = w;
- else if(w < w_min) w_min = w;
- }
-
- // Store values
- rec.x1 = x + l_min * dx;
- rec.y1 = y + l_min * dy;
- rec.x2 = x + l_max * dx;
- rec.y2 = y + l_max * dy;
- rec.width = w_max - w_min;
- rec.x = x;
- rec.y = y;
- rec.theta = theta;
- rec.dx = dx;
- rec.dy = dy;
- rec.prec = prec;
- rec.p = p;
-
- // Min width of 1 pixel
- if(rec.width < 1.0) rec.width = 1.0;
+ CV_UNUSED(_image); CV_UNUSED(_lines);
+ CV_UNUSED(_width); CV_UNUSED(_prec); CV_UNUSED(_nfa);
+ CV_Error(Error::StsNotImplemented, "Implementation has been removed due original code license issues");
}
-double LineSegmentDetectorImpl::get_theta(const std::vector<RegionPoint>& reg, const double& x,
- const double& y, const double& reg_angle, const double& prec) const
-{
- double Ixx = 0.0;
- double Iyy = 0.0;
- double Ixy = 0.0;
-
- // Compute inertia matrix
- for(size_t i = 0; i < reg.size(); ++i)
- {
- const double& regx = reg[i].x;
- const double& regy = reg[i].y;
- const double& weight = reg[i].modgrad;
- double dx = regx - x;
- double dy = regy - y;
- Ixx += dy * dy * weight;
- Iyy += dx * dx * weight;
- Ixy -= dx * dy * weight;
- }
-
- // Check if inertia matrix is null
- CV_Assert(!(double_equal(Ixx, 0) && double_equal(Iyy, 0) && double_equal(Ixy, 0)));
-
- // Compute smallest eigenvalue
- double lambda = 0.5 * (Ixx + Iyy - sqrt((Ixx - Iyy) * (Ixx - Iyy) + 4.0 * Ixy * Ixy));
-
- // Compute angle
- double theta = (fabs(Ixx)>fabs(Iyy))?
- double(fastAtan2(float(lambda - Ixx), float(Ixy))):
- double(fastAtan2(float(Ixy), float(lambda - Iyy))); // in degs
- theta *= DEG_TO_RADS;
-
- // Correct angle by 180 deg if necessary
- if(angle_diff(theta, reg_angle) > prec) { theta += CV_PI; }
-
- return theta;
-}
-
-bool LineSegmentDetectorImpl::refine(std::vector<RegionPoint>& reg, double reg_angle,
- const double prec, double p, rect& rec, const double& density_th)
-{
- double density = double(reg.size()) / (dist(rec.x1, rec.y1, rec.x2, rec.y2) * rec.width);
-
- if (density >= density_th) { return true; }
-
- // Try to reduce angle tolerance
- double xc = double(reg[0].x);
- double yc = double(reg[0].y);
- const double& ang_c = reg[0].angle;
- double sum = 0, s_sum = 0;
- int n = 0;
-
- for (size_t i = 0; i < reg.size(); ++i)
- {
- *(reg[i].used) = NOTUSED;
- if (dist(xc, yc, reg[i].x, reg[i].y) < rec.width)
- {
- const double& angle = reg[i].angle;
- double ang_d = angle_diff_signed(angle, ang_c);
- sum += ang_d;
- s_sum += ang_d * ang_d;
- ++n;
- }
- }
- CV_Assert(n > 0);
- double mean_angle = sum / double(n);
- // 2 * standard deviation
- double tau = 2.0 * sqrt((s_sum - 2.0 * mean_angle * sum) / double(n) + mean_angle * mean_angle);
-
- // Try new region
- region_grow(Point(reg[0].x, reg[0].y), reg, reg_angle, tau);
-
- if (reg.size() < 2) { return false; }
-
- region2rect(reg, reg_angle, prec, p, rec);
- density = double(reg.size()) / (dist(rec.x1, rec.y1, rec.x2, rec.y2) * rec.width);
-
- if (density < density_th)
- {
- return reduce_region_radius(reg, reg_angle, prec, p, rec, density, density_th);
- }
- else
- {
- return true;
- }
-}
-
-bool LineSegmentDetectorImpl::reduce_region_radius(std::vector<RegionPoint>& reg, double reg_angle,
- const double prec, double p, rect& rec, double density, const double& density_th)
-{
- // Compute region's radius
- double xc = double(reg[0].x);
- double yc = double(reg[0].y);
- double radSq1 = distSq(xc, yc, rec.x1, rec.y1);
- double radSq2 = distSq(xc, yc, rec.x2, rec.y2);
- double radSq = radSq1 > radSq2 ? radSq1 : radSq2;
-
- while(density < density_th)
- {
- radSq *= 0.75*0.75; // Reduce region's radius to 75% of its value
- // Remove points from the region and update 'used' map
- for (size_t i = 0; i < reg.size(); ++i)
- {
- if(distSq(xc, yc, double(reg[i].x), double(reg[i].y)) > radSq)
- {
- // Remove point from the region
- *(reg[i].used) = NOTUSED;
- std::swap(reg[i], reg[reg.size() - 1]);
- reg.pop_back();
- --i; // To avoid skipping one point
- }
- }
-
- if(reg.size() < 2) { return false; }
-
- // Re-compute rectangle
- region2rect(reg ,reg_angle, prec, p, rec);
-
- // Re-compute region points density
- density = double(reg.size()) /
- (dist(rec.x1, rec.y1, rec.x2, rec.y2) * rec.width);
- }
-
- return true;
-}
-
-double LineSegmentDetectorImpl::rect_improve(rect& rec) const
-{
- double delta = 0.5;
- double delta_2 = delta / 2.0;
-
- double log_nfa = rect_nfa(rec);
-
- if(log_nfa > LOG_EPS) return log_nfa; // Good rectangle
-
- // Try to improve
- // Finer precision
- rect r = rect(rec); // Copy
- for(int n = 0; n < 5; ++n)
- {
- r.p /= 2;
- r.prec = r.p * CV_PI;
- double log_nfa_new = rect_nfa(r);
- if(log_nfa_new > log_nfa)
- {
- log_nfa = log_nfa_new;
- rec = rect(r);
- }
- }
- if(log_nfa > LOG_EPS) return log_nfa;
-
- // Try to reduce width
- r = rect(rec);
- for(unsigned int n = 0; n < 5; ++n)
- {
- if((r.width - delta) >= 0.5)
- {
- r.width -= delta;
- double log_nfa_new = rect_nfa(r);
- if(log_nfa_new > log_nfa)
- {
- rec = rect(r);
- log_nfa = log_nfa_new;
- }
- }
- }
- if(log_nfa > LOG_EPS) return log_nfa;
-
- // Try to reduce one side of rectangle
- r = rect(rec);
- for(unsigned int n = 0; n < 5; ++n)
- {
- if((r.width - delta) >= 0.5)
- {
- r.x1 += -r.dy * delta_2;
- r.y1 += r.dx * delta_2;
- r.x2 += -r.dy * delta_2;
- r.y2 += r.dx * delta_2;
- r.width -= delta;
- double log_nfa_new = rect_nfa(r);
- if(log_nfa_new > log_nfa)
- {
- rec = rect(r);
- log_nfa = log_nfa_new;
- }
- }
- }
- if(log_nfa > LOG_EPS) return log_nfa;
-
- // Try to reduce other side of rectangle
- r = rect(rec);
- for(unsigned int n = 0; n < 5; ++n)
- {
- if((r.width - delta) >= 0.5)
- {
- r.x1 -= -r.dy * delta_2;
- r.y1 -= r.dx * delta_2;
- r.x2 -= -r.dy * delta_2;
- r.y2 -= r.dx * delta_2;
- r.width -= delta;
- double log_nfa_new = rect_nfa(r);
- if(log_nfa_new > log_nfa)
- {
- rec = rect(r);
- log_nfa = log_nfa_new;
- }
- }
- }
- if(log_nfa > LOG_EPS) return log_nfa;
-
- // Try finer precision
- r = rect(rec);
- for(unsigned int n = 0; n < 5; ++n)
- {
- if((r.width - delta) >= 0.5)
- {
- r.p /= 2;
- r.prec = r.p * CV_PI;
- double log_nfa_new = rect_nfa(r);
- if(log_nfa_new > log_nfa)
- {
- rec = rect(r);
- log_nfa = log_nfa_new;
- }
- }
- }
-
- return log_nfa;
-}
-
-double LineSegmentDetectorImpl::rect_nfa(const rect& rec) const
-{
- int total_pts = 0, alg_pts = 0;
- double half_width = rec.width / 2.0;
- double dyhw = rec.dy * half_width;
- double dxhw = rec.dx * half_width;
-
- edge ordered_x[4];
- edge* min_y = &ordered_x[0];
- edge* max_y = &ordered_x[0]; // Will be used for loop range
-
- ordered_x[0].p.x = int(rec.x1 - dyhw); ordered_x[0].p.y = int(rec.y1 + dxhw); ordered_x[0].taken = false;
- ordered_x[1].p.x = int(rec.x2 - dyhw); ordered_x[1].p.y = int(rec.y2 + dxhw); ordered_x[1].taken = false;
- ordered_x[2].p.x = int(rec.x2 + dyhw); ordered_x[2].p.y = int(rec.y2 - dxhw); ordered_x[2].taken = false;
- ordered_x[3].p.x = int(rec.x1 + dyhw); ordered_x[3].p.y = int(rec.y1 - dxhw); ordered_x[3].taken = false;
-
- std::sort(ordered_x, ordered_x + 4, AsmallerB_XoverY);
-
- // Find min y. And mark as taken. find max y.
- for(unsigned int i = 1; i < 4; ++i)
- {
- if(min_y->p.y > ordered_x[i].p.y) {min_y = &ordered_x[i]; }
- if(max_y->p.y < ordered_x[i].p.y) {max_y = &ordered_x[i]; }
- }
- min_y->taken = true;
-
- // Find leftmost untaken point;
- edge* leftmost = 0;
- for(unsigned int i = 0; i < 4; ++i)
- {
- if(!ordered_x[i].taken)
- {
- if(!leftmost) // if uninitialized
- {
- leftmost = &ordered_x[i];
- }
- else if (leftmost->p.x > ordered_x[i].p.x)
- {
- leftmost = &ordered_x[i];
- }
- }
- }
- CV_Assert(leftmost != NULL);
- leftmost->taken = true;
-
- // Find rightmost untaken point;
- edge* rightmost = 0;
- for(unsigned int i = 0; i < 4; ++i)
- {
- if(!ordered_x[i].taken)
- {
- if(!rightmost) // if uninitialized
- {
- rightmost = &ordered_x[i];
- }
- else if (rightmost->p.x < ordered_x[i].p.x)
- {
- rightmost = &ordered_x[i];
- }
- }
- }
- CV_Assert(rightmost != NULL);
- rightmost->taken = true;
-
- // Find last untaken point;
- edge* tailp = 0;
- for(unsigned int i = 0; i < 4; ++i)
- {
- if(!ordered_x[i].taken)
- {
- if(!tailp) // if uninitialized
- {
- tailp = &ordered_x[i];
- }
- else if (tailp->p.x > ordered_x[i].p.x)
- {
- tailp = &ordered_x[i];
- }
- }
- }
- CV_Assert(tailp != NULL);
- tailp->taken = true;
-
- double flstep = (min_y->p.y != leftmost->p.y) ?
- (min_y->p.x - leftmost->p.x) / (min_y->p.y - leftmost->p.y) : 0; //first left step
- double slstep = (leftmost->p.y != tailp->p.x) ?
- (leftmost->p.x - tailp->p.x) / (leftmost->p.y - tailp->p.x) : 0; //second left step
-
- double frstep = (min_y->p.y != rightmost->p.y) ?
- (min_y->p.x - rightmost->p.x) / (min_y->p.y - rightmost->p.y) : 0; //first right step
- double srstep = (rightmost->p.y != tailp->p.x) ?
- (rightmost->p.x - tailp->p.x) / (rightmost->p.y - tailp->p.x) : 0; //second right step
-
- double lstep = flstep, rstep = frstep;
-
- double left_x = min_y->p.x, right_x = min_y->p.x;
-
- // Loop around all points in the region and count those that are aligned.
- int min_iter = min_y->p.y;
- int max_iter = max_y->p.y;
- for(int y = min_iter; y <= max_iter; ++y)
- {
- if (y < 0 || y >= img_height) continue;
-
- for(int x = int(left_x); x <= int(right_x); ++x)
- {
- if (x < 0 || x >= img_width) continue;
-
- ++total_pts;
- if(isAligned(x, y, rec.theta, rec.prec))
- {
- ++alg_pts;
- }
- }
-
- if(y >= leftmost->p.y) { lstep = slstep; }
- if(y >= rightmost->p.y) { rstep = srstep; }
-
- left_x += lstep;
- right_x += rstep;
- }
-
- return nfa(total_pts, alg_pts, rec.p);
-}
-
-double LineSegmentDetectorImpl::nfa(const int& n, const int& k, const double& p) const
-{
- // Trivial cases
- if(n == 0 || k == 0) { return -LOG_NT; }
- if(n == k) { return -LOG_NT - double(n) * log10(p); }
-
- double p_term = p / (1 - p);
-
- double log1term = (double(n) + 1) - log_gamma(double(k) + 1)
- - log_gamma(double(n-k) + 1)
- + double(k) * log(p) + double(n-k) * log(1.0 - p);
- double term = exp(log1term);
-
- if(double_equal(term, 0))
- {
- if(k > n * p) return -log1term / M_LN10 - LOG_NT;
- else return -LOG_NT;
- }
-
- // Compute more terms if needed
- double bin_tail = term;
- double tolerance = 0.1; // an error of 10% in the result is accepted
- for(int i = k + 1; i <= n; ++i)
- {
- double bin_term = double(n - i + 1) / double(i);
- double mult_term = bin_term * p_term;
- term *= mult_term;
- bin_tail += term;
- if(bin_term < 1)
- {
- double err = term * ((1 - pow(mult_term, double(n-i+1))) / (1 - mult_term) - 1);
- if(err < tolerance * fabs(-log10(bin_tail) - LOG_NT) * bin_tail) break;
- }
-
- }
- return -log10(bin_tail) - LOG_NT;
-}
-
-inline bool LineSegmentDetectorImpl::isAligned(int x, int y, const double& theta, const double& prec) const
-{
- if(x < 0 || y < 0 || x >= angles.cols || y >= angles.rows) { return false; }
- const double& a = angles.at<double>(y, x);
- if(a == NOTDEF) { return false; }
-
- // It is assumed that 'theta' and 'a' are in the range [-pi,pi]
- double n_theta = theta - a;
- if(n_theta < 0) { n_theta = -n_theta; }
- if(n_theta > M_3_2_PI)
- {
- n_theta -= M_2__PI;
- if(n_theta < 0) n_theta = -n_theta;
- }
-
- return n_theta <= prec;
-}
-
-
void LineSegmentDetectorImpl::drawSegments(InputOutputArray _image, InputArray lines)
{
CV_INSTRUMENT_REGION();
--- /dev/null
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, 2018, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Copyright (C) 2014-2015, Itseez Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "precomp.hpp"
+
+#include <vector>
+
+#include "opencv2/core/hal/intrin.hpp"
+#include "opencl_kernels_imgproc.hpp"
+
+#include "opencv2/core/openvx/ovx_defs.hpp"
+
+#include "median_blur.simd.hpp"
+#include "median_blur.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
+
+namespace cv {
+
+#ifdef HAVE_OPENCL
+
+#define DIVUP(total, grain) ((total + grain - 1) / (grain))
+
+static bool ocl_medianFilter(InputArray _src, OutputArray _dst, int m)
+{
+ size_t localsize[2] = { 16, 16 };
+ size_t globalsize[2];
+ int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
+
+ if ( !((depth == CV_8U || depth == CV_16U || depth == CV_16S || depth == CV_32F) && cn <= 4 && (m == 3 || m == 5)) )
+ return false;
+
+ Size imgSize = _src.size();
+ bool useOptimized = (1 == cn) &&
+ (size_t)imgSize.width >= localsize[0] * 8 &&
+ (size_t)imgSize.height >= localsize[1] * 8 &&
+ imgSize.width % 4 == 0 &&
+ imgSize.height % 4 == 0 &&
+ (ocl::Device::getDefault().isIntel());
+
+ cv::String kname = format( useOptimized ? "medianFilter%d_u" : "medianFilter%d", m) ;
+ cv::String kdefs = useOptimized ?
+ format("-D T=%s -D T1=%s -D T4=%s%d -D cn=%d -D USE_4OPT", ocl::typeToStr(type),
+ ocl::typeToStr(depth), ocl::typeToStr(depth), cn*4, cn)
+ :
+ format("-D T=%s -D T1=%s -D cn=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn) ;
+
+ ocl::Kernel k(kname.c_str(), ocl::imgproc::medianFilter_oclsrc, kdefs.c_str() );
+
+ if (k.empty())
+ return false;
+
+ UMat src = _src.getUMat();
+ _dst.create(src.size(), type);
+ UMat dst = _dst.getUMat();
+
+ k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst));
+
+ if( useOptimized )
+ {
+ globalsize[0] = DIVUP(src.cols / 4, localsize[0]) * localsize[0];
+ globalsize[1] = DIVUP(src.rows / 4, localsize[1]) * localsize[1];
+ }
+ else
+ {
+ globalsize[0] = (src.cols + localsize[0] + 2) / localsize[0] * localsize[0];
+ globalsize[1] = (src.rows + localsize[1] - 1) / localsize[1] * localsize[1];
+ }
+
+ return k.run(2, globalsize, localsize, false);
+}
+
+#undef DIVUP
+
+#endif
+
+#ifdef HAVE_OPENVX
+namespace ovx {
+ template <> inline bool skipSmallImages<VX_KERNEL_MEDIAN_3x3>(int w, int h) { return w*h < 1280 * 720; }
+}
+static bool openvx_medianFilter(InputArray _src, OutputArray _dst, int ksize)
+{
+ if (_src.type() != CV_8UC1 || _dst.type() != CV_8U
+#ifndef VX_VERSION_1_1
+ || ksize != 3
+#endif
+ )
+ return false;
+
+ Mat src = _src.getMat();
+ Mat dst = _dst.getMat();
+
+ if (
+#ifdef VX_VERSION_1_1
+ ksize != 3 ? ovx::skipSmallImages<VX_KERNEL_NON_LINEAR_FILTER>(src.cols, src.rows) :
+#endif
+ ovx::skipSmallImages<VX_KERNEL_MEDIAN_3x3>(src.cols, src.rows)
+ )
+ return false;
+
+ try
+ {
+ ivx::Context ctx = ovx::getOpenVXContext();
+#ifdef VX_VERSION_1_1
+ if ((vx_size)ksize > ctx.nonlinearMaxDimension())
+ return false;
+#endif
+
+ Mat a;
+ if (dst.data != src.data)
+ a = src;
+ else
+ src.copyTo(a);
+
+ ivx::Image
+ ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,
+ ivx::Image::createAddressing(a.cols, a.rows, 1, (vx_int32)(a.step)), a.data),
+ ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,
+ ivx::Image::createAddressing(dst.cols, dst.rows, 1, (vx_int32)(dst.step)), dst.data);
+
+ //ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments
+ //since OpenVX standard says nothing about thread-safety for now
+ ivx::border_t prevBorder = ctx.immediateBorder();
+ ctx.setImmediateBorder(VX_BORDER_REPLICATE);
+#ifdef VX_VERSION_1_1
+ if (ksize == 3)
+#endif
+ {
+ ivx::IVX_CHECK_STATUS(vxuMedian3x3(ctx, ia, ib));
+ }
+#ifdef VX_VERSION_1_1
+ else
+ {
+ ivx::Matrix mtx;
+ if(ksize == 5)
+ mtx = ivx::Matrix::createFromPattern(ctx, VX_PATTERN_BOX, ksize, ksize);
+ else
+ {
+ vx_size supportedSize;
+ ivx::IVX_CHECK_STATUS(vxQueryContext(ctx, VX_CONTEXT_NONLINEAR_MAX_DIMENSION, &supportedSize, sizeof(supportedSize)));
+ if ((vx_size)ksize > supportedSize)
+ {
+ ctx.setImmediateBorder(prevBorder);
+ return false;
+ }
+ Mat mask(ksize, ksize, CV_8UC1, Scalar(255));
+ mtx = ivx::Matrix::create(ctx, VX_TYPE_UINT8, ksize, ksize);
+ mtx.copyFrom(mask);
+ }
+ ivx::IVX_CHECK_STATUS(vxuNonLinearFilter(ctx, VX_NONLINEAR_FILTER_MEDIAN, ia, mtx, ib));
+ }
+#endif
+ ctx.setImmediateBorder(prevBorder);
+ }
+ catch (const ivx::RuntimeError & e)
+ {
+ VX_DbgThrow(e.what());
+ }
+ catch (const ivx::WrapperError & e)
+ {
+ VX_DbgThrow(e.what());
+ }
+
+ return true;
+}
+#endif
+
+#ifdef HAVE_IPP
+static bool ipp_medianFilter(Mat &src0, Mat &dst, int ksize)
+{
+ CV_INSTRUMENT_REGION_IPP();
+
+#if IPP_VERSION_X100 < 201801
+ // Degradations for big kernel
+ if(ksize > 7)
+ return false;
+#endif
+
+ {
+ int bufSize;
+ IppiSize dstRoiSize = ippiSize(dst.cols, dst.rows), maskSize = ippiSize(ksize, ksize);
+ IppDataType ippType = ippiGetDataType(src0.type());
+ int channels = src0.channels();
+ IppAutoBuffer<Ipp8u> buffer;
+
+ if(src0.isSubmatrix())
+ return false;
+
+ Mat src;
+ if(dst.data != src0.data)
+ src = src0;
+ else
+ src0.copyTo(src);
+
+ if(ippiFilterMedianBorderGetBufferSize(dstRoiSize, maskSize, ippType, channels, &bufSize) < 0)
+ return false;
+
+ buffer.allocate(bufSize);
+
+ switch(ippType)
+ {
+ case ipp8u:
+ if(channels == 1)
+ return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_8u_C1R, src.ptr<Ipp8u>(), (int)src.step, dst.ptr<Ipp8u>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
+ else if(channels == 3)
+ return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_8u_C3R, src.ptr<Ipp8u>(), (int)src.step, dst.ptr<Ipp8u>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
+ else if(channels == 4)
+ return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_8u_C4R, src.ptr<Ipp8u>(), (int)src.step, dst.ptr<Ipp8u>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
+ else
+ return false;
+ case ipp16u:
+ if(channels == 1)
+ return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16u_C1R, src.ptr<Ipp16u>(), (int)src.step, dst.ptr<Ipp16u>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
+ else if(channels == 3)
+ return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16u_C3R, src.ptr<Ipp16u>(), (int)src.step, dst.ptr<Ipp16u>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
+ else if(channels == 4)
+ return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16u_C4R, src.ptr<Ipp16u>(), (int)src.step, dst.ptr<Ipp16u>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
+ else
+ return false;
+ case ipp16s:
+ if(channels == 1)
+ return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16s_C1R, src.ptr<Ipp16s>(), (int)src.step, dst.ptr<Ipp16s>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
+ else if(channels == 3)
+ return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16s_C3R, src.ptr<Ipp16s>(), (int)src.step, dst.ptr<Ipp16s>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
+ else if(channels == 4)
+ return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16s_C4R, src.ptr<Ipp16s>(), (int)src.step, dst.ptr<Ipp16s>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
+ else
+ return false;
+ case ipp32f:
+ if(channels == 1)
+ return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_32f_C1R, src.ptr<Ipp32f>(), (int)src.step, dst.ptr<Ipp32f>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
+ else
+ return false;
+ default:
+ return false;
+ }
+ }
+}
+#endif
+
+void medianBlur( InputArray _src0, OutputArray _dst, int ksize )
+{
+ CV_INSTRUMENT_REGION();
+
+ CV_Assert( (ksize % 2 == 1) && (_src0.dims() <= 2 ));
+
+ if( ksize <= 1 || _src0.empty() )
+ {
+ _src0.copyTo(_dst);
+ return;
+ }
+
+ CV_OCL_RUN(_dst.isUMat(),
+ ocl_medianFilter(_src0,_dst, ksize))
+
+ Mat src0 = _src0.getMat();
+ _dst.create( src0.size(), src0.type() );
+ Mat dst = _dst.getMat();
+
+ CALL_HAL(medianBlur, cv_hal_medianBlur, src0.data, src0.step, dst.data, dst.step, src0.cols, src0.rows, src0.depth(),
+ src0.channels(), ksize);
+
+ CV_OVX_RUN(true,
+ openvx_medianFilter(_src0, _dst, ksize))
+
+ CV_IPP_RUN_FAST(ipp_medianFilter(src0, dst, ksize));
+
+#ifdef HAVE_TEGRA_OPTIMIZATION
+ if (tegra::useTegra() && tegra::medianBlur(src0, dst, ksize))
+ return;
+#endif
+
+ CV_CPU_DISPATCH(medianBlur, (src0, dst, ksize),
+ CV_CPU_DISPATCH_MODES_ALL);
+}
+
+} // namespace
+
+/* End of file. */
#include <vector>
#include "opencv2/core/hal/intrin.hpp"
-#include "opencl_kernels_imgproc.hpp"
-#include "opencv2/core/openvx/ovx_defs.hpp"
+#ifdef _MSC_VER
+#pragma warning(disable: 4244) // warning C4244: 'argument': conversion from 'int' to 'ushort', possible loss of data
+ // triggered on intrinsic code from medianBlur_8u_O1()
+#endif
/*
* This file includes the code, contributed by Simon Perreault
Median Filter
\****************************************************************************************/
-namespace cv
-{
+namespace cv {
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+// forward declarations
+void medianBlur(const Mat& src0, /*const*/ Mat& dst, int ksize);
+
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
static void
medianBlur_8u_O1( const Mat& _src, Mat& _dst, int ksize )
{
+ CV_INSTRUMENT_REGION();
+
typedef ushort HT;
/**
}
}
}
-#if CV_SIMD
- vx_cleanup();
-#endif
}
#undef HOP
static void
medianBlur_8u_Om( const Mat& _src, Mat& _dst, int m )
{
+ CV_INSTRUMENT_REGION();
+
#define N 16
int zone0[4][N];
int zone1[4][N*N];
static void
medianBlur_SortNet( const Mat& _src, Mat& _dst, int m )
{
+ CV_INSTRUMENT_REGION();
+
typedef typename Op::value_type T;
typedef typename Op::arg_type WT;
typedef typename VecOp::arg_type VT;
limit = size.width;
}
}
-#if CV_SIMD
- vx_cleanup();
-#endif
}
else if( m == 5 )
{
limit = size.width;
}
}
-#if CV_SIMD
- vx_cleanup();
-#endif
- }
-}
-
-#ifdef HAVE_OPENCL
-
-#define DIVUP(total, grain) ((total + grain - 1) / (grain))
-
-static bool ocl_medianFilter(InputArray _src, OutputArray _dst, int m)
-{
- size_t localsize[2] = { 16, 16 };
- size_t globalsize[2];
- int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
-
- if ( !((depth == CV_8U || depth == CV_16U || depth == CV_16S || depth == CV_32F) && cn <= 4 && (m == 3 || m == 5)) )
- return false;
-
- Size imgSize = _src.size();
- bool useOptimized = (1 == cn) &&
- (size_t)imgSize.width >= localsize[0] * 8 &&
- (size_t)imgSize.height >= localsize[1] * 8 &&
- imgSize.width % 4 == 0 &&
- imgSize.height % 4 == 0 &&
- (ocl::Device::getDefault().isIntel());
-
- cv::String kname = format( useOptimized ? "medianFilter%d_u" : "medianFilter%d", m) ;
- cv::String kdefs = useOptimized ?
- format("-D T=%s -D T1=%s -D T4=%s%d -D cn=%d -D USE_4OPT", ocl::typeToStr(type),
- ocl::typeToStr(depth), ocl::typeToStr(depth), cn*4, cn)
- :
- format("-D T=%s -D T1=%s -D cn=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn) ;
-
- ocl::Kernel k(kname.c_str(), ocl::imgproc::medianFilter_oclsrc, kdefs.c_str() );
-
- if (k.empty())
- return false;
-
- UMat src = _src.getUMat();
- _dst.create(src.size(), type);
- UMat dst = _dst.getUMat();
-
- k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst));
-
- if( useOptimized )
- {
- globalsize[0] = DIVUP(src.cols / 4, localsize[0]) * localsize[0];
- globalsize[1] = DIVUP(src.rows / 4, localsize[1]) * localsize[1];
- }
- else
- {
- globalsize[0] = (src.cols + localsize[0] + 2) / localsize[0] * localsize[0];
- globalsize[1] = (src.rows + localsize[1] - 1) / localsize[1] * localsize[1];
- }
-
- return k.run(2, globalsize, localsize, false);
-}
-
-#undef DIVUP
-
-#endif
-
-#ifdef HAVE_OPENVX
-} // close anonymous namespace #13634
-namespace ovx {
- template <> inline bool skipSmallImages<VX_KERNEL_MEDIAN_3x3>(int w, int h) { return w*h < 1280 * 720; }
-}
-namespace { // reopen it
-static bool openvx_medianFilter(InputArray _src, OutputArray _dst, int ksize)
-{
- if (_src.type() != CV_8UC1 || _dst.type() != CV_8U
-#ifndef VX_VERSION_1_1
- || ksize != 3
-#endif
- )
- return false;
-
- Mat src = _src.getMat();
- Mat dst = _dst.getMat();
-
- if (
-#ifdef VX_VERSION_1_1
- ksize != 3 ? ovx::skipSmallImages<VX_KERNEL_NON_LINEAR_FILTER>(src.cols, src.rows) :
-#endif
- ovx::skipSmallImages<VX_KERNEL_MEDIAN_3x3>(src.cols, src.rows)
- )
- return false;
-
- try
- {
- ivx::Context ctx = ovx::getOpenVXContext();
-#ifdef VX_VERSION_1_1
- if ((vx_size)ksize > ctx.nonlinearMaxDimension())
- return false;
-#endif
-
- Mat a;
- if (dst.data != src.data)
- a = src;
- else
- src.copyTo(a);
-
- ivx::Image
- ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,
- ivx::Image::createAddressing(a.cols, a.rows, 1, (vx_int32)(a.step)), a.data),
- ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,
- ivx::Image::createAddressing(dst.cols, dst.rows, 1, (vx_int32)(dst.step)), dst.data);
-
- //ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments
- //since OpenVX standard says nothing about thread-safety for now
- ivx::border_t prevBorder = ctx.immediateBorder();
- ctx.setImmediateBorder(VX_BORDER_REPLICATE);
-#ifdef VX_VERSION_1_1
- if (ksize == 3)
-#endif
- {
- ivx::IVX_CHECK_STATUS(vxuMedian3x3(ctx, ia, ib));
- }
-#ifdef VX_VERSION_1_1
- else
- {
- ivx::Matrix mtx;
- if(ksize == 5)
- mtx = ivx::Matrix::createFromPattern(ctx, VX_PATTERN_BOX, ksize, ksize);
- else
- {
- vx_size supportedSize;
- ivx::IVX_CHECK_STATUS(vxQueryContext(ctx, VX_CONTEXT_NONLINEAR_MAX_DIMENSION, &supportedSize, sizeof(supportedSize)));
- if ((vx_size)ksize > supportedSize)
- {
- ctx.setImmediateBorder(prevBorder);
- return false;
- }
- Mat mask(ksize, ksize, CV_8UC1, Scalar(255));
- mtx = ivx::Matrix::create(ctx, VX_TYPE_UINT8, ksize, ksize);
- mtx.copyFrom(mask);
- }
- ivx::IVX_CHECK_STATUS(vxuNonLinearFilter(ctx, VX_NONLINEAR_FILTER_MEDIAN, ia, mtx, ib));
- }
-#endif
- ctx.setImmediateBorder(prevBorder);
- }
- catch (const ivx::RuntimeError & e)
- {
- VX_DbgThrow(e.what());
}
- catch (const ivx::WrapperError & e)
- {
- VX_DbgThrow(e.what());
- }
-
- return true;
}
-#endif
-
-#if 0 //defined HAVE_IPP
-static bool ipp_medianFilter(Mat &src0, Mat &dst, int ksize)
-{
- CV_INSTRUMENT_REGION_IPP();
-
-#if IPP_VERSION_X100 < 201801
- // Degradations for big kernel
- if(ksize > 7)
- return false;
-#endif
-
- {
- int bufSize;
- IppiSize dstRoiSize = ippiSize(dst.cols, dst.rows), maskSize = ippiSize(ksize, ksize);
- IppDataType ippType = ippiGetDataType(src0.type());
- int channels = src0.channels();
- IppAutoBuffer<Ipp8u> buffer;
-
- if(src0.isSubmatrix())
- return false;
-
- Mat src;
- if(dst.data != src0.data)
- src = src0;
- else
- src0.copyTo(src);
-
- if(ippiFilterMedianBorderGetBufferSize(dstRoiSize, maskSize, ippType, channels, &bufSize) < 0)
- return false;
- buffer.allocate(bufSize);
+} // namespace anon
- switch(ippType)
- {
- case ipp8u:
- if(channels == 1)
- return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_8u_C1R, src.ptr<Ipp8u>(), (int)src.step, dst.ptr<Ipp8u>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
- else if(channels == 3)
- return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_8u_C3R, src.ptr<Ipp8u>(), (int)src.step, dst.ptr<Ipp8u>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
- else if(channels == 4)
- return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_8u_C4R, src.ptr<Ipp8u>(), (int)src.step, dst.ptr<Ipp8u>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
- else
- return false;
- case ipp16u:
- if(channels == 1)
- return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16u_C1R, src.ptr<Ipp16u>(), (int)src.step, dst.ptr<Ipp16u>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
- else if(channels == 3)
- return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16u_C3R, src.ptr<Ipp16u>(), (int)src.step, dst.ptr<Ipp16u>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
- else if(channels == 4)
- return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16u_C4R, src.ptr<Ipp16u>(), (int)src.step, dst.ptr<Ipp16u>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
- else
- return false;
- case ipp16s:
- if(channels == 1)
- return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16s_C1R, src.ptr<Ipp16s>(), (int)src.step, dst.ptr<Ipp16s>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
- else if(channels == 3)
- return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16s_C3R, src.ptr<Ipp16s>(), (int)src.step, dst.ptr<Ipp16s>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
- else if(channels == 4)
- return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16s_C4R, src.ptr<Ipp16s>(), (int)src.step, dst.ptr<Ipp16s>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
- else
- return false;
- case ipp32f:
- if(channels == 1)
- return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_32f_C1R, src.ptr<Ipp32f>(), (int)src.step, dst.ptr<Ipp32f>(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0;
- else
- return false;
- default:
- return false;
- }
- }
-}
-#endif
-}
-
-void medianBlur( InputArray _src0, OutputArray _dst, int ksize )
+void medianBlur(const Mat& src0, /*const*/ Mat& dst, int ksize)
{
CV_INSTRUMENT_REGION();
- CV_Assert( (ksize % 2 == 1) && (_src0.dims() <= 2 ));
-
- if( ksize <= 1 || _src0.empty() )
- {
- _src0.copyTo(_dst);
- return;
- }
-
- CV_OCL_RUN(_dst.isUMat(),
- ocl_medianFilter(_src0,_dst, ksize))
-
- Mat src0 = _src0.getMat();
- _dst.create( src0.size(), src0.type() );
- Mat dst = _dst.getMat();
-
- CALL_HAL(medianBlur, cv_hal_medianBlur, src0.data, src0.step, dst.data, dst.step, src0.cols, src0.rows, src0.depth(),
- src0.channels(), ksize);
-
- CV_OVX_RUN(true,
- openvx_medianFilter(_src0, _dst, ksize))
-
- //CV_IPP_RUN_FAST(ipp_medianFilter(src0, dst, ksize));
-
-#ifdef HAVE_TEGRA_OPTIMIZATION
- if (tegra::useTegra() && tegra::medianBlur(src0, dst, ksize))
- return;
-#endif
-
bool useSortNet = ksize == 3 || (ksize == 5
#if !(CV_SIMD)
&& ( src0.depth() > CV_8U || src0.channels() == 2 || src0.channels() > 4 )
}
else
{
+ // TODO AVX guard (external call)
cv::copyMakeBorder( src0, src, 0, 0, ksize/2, ksize/2, BORDER_REPLICATE|BORDER_ISOLATED);
int cn = src0.channels();
}
}
-}
-
-/* End of file. */
+#endif
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+} // namespace
#include "opencv2/core/hal/intrin.hpp"
#include <opencv2/core/utils/configuration.private.hpp>
+#include "morph.simd.hpp"
+#include "morph.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
+
+
/****************************************************************************************\
Basic Morphological Operations: Erosion & Dilation
\****************************************************************************************/
-using namespace std;
-
-namespace cv
-{
-
-template<typename T> struct MinOp
-{
- typedef T type1;
- typedef T type2;
- typedef T rtype;
- T operator ()(const T a, const T b) const { return std::min(a, b); }
-};
-
-template<typename T> struct MaxOp
-{
- typedef T type1;
- typedef T type2;
- typedef T rtype;
- T operator ()(const T a, const T b) const { return std::max(a, b); }
-};
-
-#undef CV_MIN_8U
-#undef CV_MAX_8U
-#define CV_MIN_8U(a,b) ((a) - CV_FAST_CAST_8U((a) - (b)))
-#define CV_MAX_8U(a,b) ((a) + CV_FAST_CAST_8U((b) - (a)))
-
-template<> inline uchar MinOp<uchar>::operator ()(const uchar a, const uchar b) const { return CV_MIN_8U(a, b); }
-template<> inline uchar MaxOp<uchar>::operator ()(const uchar a, const uchar b) const { return CV_MAX_8U(a, b); }
-
-struct MorphRowNoVec
-{
- MorphRowNoVec(int, int) {}
- int operator()(const uchar*, uchar*, int, int) const { return 0; }
-};
-
-struct MorphColumnNoVec
-{
- MorphColumnNoVec(int, int) {}
- int operator()(const uchar**, uchar*, int, int, int) const { return 0; }
-};
-
-struct MorphNoVec
-{
- int operator()(uchar**, int, uchar*, int) const { return 0; }
-};
-
-#if CV_SIMD
-
-template<class VecUpdate> struct MorphRowVec
-{
- typedef typename VecUpdate::vtype vtype;
- typedef typename vtype::lane_type stype;
- MorphRowVec(int _ksize, int _anchor) : ksize(_ksize), anchor(_anchor) {}
- int operator()(const uchar* src, uchar* dst, int width, int cn) const
- {
- int i, k, _ksize = ksize*cn;
- width *= cn;
- VecUpdate updateOp;
-
- for( i = 0; i <= width - 4*vtype::nlanes; i += 4*vtype::nlanes )
- {
- vtype s0 = vx_load((const stype*)src + i);
- vtype s1 = vx_load((const stype*)src + i + vtype::nlanes);
- vtype s2 = vx_load((const stype*)src + i + 2*vtype::nlanes);
- vtype s3 = vx_load((const stype*)src + i + 3*vtype::nlanes);
- for (k = cn; k < _ksize; k += cn)
- {
- s0 = updateOp(s0, vx_load((const stype*)src + i + k));
- s1 = updateOp(s1, vx_load((const stype*)src + i + k + vtype::nlanes));
- s2 = updateOp(s2, vx_load((const stype*)src + i + k + 2*vtype::nlanes));
- s3 = updateOp(s3, vx_load((const stype*)src + i + k + 3*vtype::nlanes));
- }
- v_store((stype*)dst + i, s0);
- v_store((stype*)dst + i + vtype::nlanes, s1);
- v_store((stype*)dst + i + 2*vtype::nlanes, s2);
- v_store((stype*)dst + i + 3*vtype::nlanes, s3);
- }
- if( i <= width - 2*vtype::nlanes )
- {
- vtype s0 = vx_load((const stype*)src + i);
- vtype s1 = vx_load((const stype*)src + i + vtype::nlanes);
- for( k = cn; k < _ksize; k += cn )
- {
- s0 = updateOp(s0, vx_load((const stype*)src + i + k));
- s1 = updateOp(s1, vx_load((const stype*)src + i + k + vtype::nlanes));
- }
- v_store((stype*)dst + i, s0);
- v_store((stype*)dst + i + vtype::nlanes, s1);
- i += 2*vtype::nlanes;
- }
- if( i <= width - vtype::nlanes )
- {
- vtype s = vx_load((const stype*)src + i);
- for( k = cn; k < _ksize; k += cn )
- s = updateOp(s, vx_load((const stype*)src + i + k));
- v_store((stype*)dst + i, s);
- i += vtype::nlanes;
- }
- if( i <= width - vtype::nlanes/2 )
- {
- vtype s = vx_load_low((const stype*)src + i);
- for( k = cn; k < _ksize; k += cn )
- s = updateOp(s, vx_load_low((const stype*)src + i + k));
- v_store_low((stype*)dst + i, s);
- i += vtype::nlanes/2;
- }
-
- return i - i % cn;
- }
-
- int ksize, anchor;
-};
-
-
-template<class VecUpdate> struct MorphColumnVec
-{
- typedef typename VecUpdate::vtype vtype;
- typedef typename vtype::lane_type stype;
- MorphColumnVec(int _ksize, int _anchor) : ksize(_ksize), anchor(_anchor) {}
- int operator()(const uchar** _src, uchar* _dst, int dststep, int count, int width) const
- {
- int i = 0, k, _ksize = ksize;
- VecUpdate updateOp;
-
- for( i = 0; i < count + ksize - 1; i++ )
- CV_Assert( ((size_t)_src[i] & (CV_SIMD_WIDTH-1)) == 0 );
-
- const stype** src = (const stype**)_src;
- stype* dst = (stype*)_dst;
- dststep /= sizeof(dst[0]);
-
- for( ; _ksize > 1 && count > 1; count -= 2, dst += dststep*2, src += 2 )
- {
- for( i = 0; i <= width - 4*vtype::nlanes; i += 4*vtype::nlanes)
- {
- const stype* sptr = src[1] + i;
- vtype s0 = vx_load_aligned(sptr);
- vtype s1 = vx_load_aligned(sptr + vtype::nlanes);
- vtype s2 = vx_load_aligned(sptr + 2*vtype::nlanes);
- vtype s3 = vx_load_aligned(sptr + 3*vtype::nlanes);
-
- for( k = 2; k < _ksize; k++ )
- {
- sptr = src[k] + i;
- s0 = updateOp(s0, vx_load_aligned(sptr));
- s1 = updateOp(s1, vx_load_aligned(sptr + vtype::nlanes));
- s2 = updateOp(s2, vx_load_aligned(sptr + 2*vtype::nlanes));
- s3 = updateOp(s3, vx_load_aligned(sptr + 3*vtype::nlanes));
- }
-
- sptr = src[0] + i;
- v_store(dst + i, updateOp(s0, vx_load_aligned(sptr)));
- v_store(dst + i + vtype::nlanes, updateOp(s1, vx_load_aligned(sptr + vtype::nlanes)));
- v_store(dst + i + 2*vtype::nlanes, updateOp(s2, vx_load_aligned(sptr + 2*vtype::nlanes)));
- v_store(dst + i + 3*vtype::nlanes, updateOp(s3, vx_load_aligned(sptr + 3*vtype::nlanes)));
-
- sptr = src[k] + i;
- v_store(dst + dststep + i, updateOp(s0, vx_load_aligned(sptr)));
- v_store(dst + dststep + i + vtype::nlanes, updateOp(s1, vx_load_aligned(sptr + vtype::nlanes)));
- v_store(dst + dststep + i + 2*vtype::nlanes, updateOp(s2, vx_load_aligned(sptr + 2*vtype::nlanes)));
- v_store(dst + dststep + i + 3*vtype::nlanes, updateOp(s3, vx_load_aligned(sptr + 3*vtype::nlanes)));
- }
- if( i <= width - 2*vtype::nlanes )
- {
- const stype* sptr = src[1] + i;
- vtype s0 = vx_load_aligned(sptr);
- vtype s1 = vx_load_aligned(sptr + vtype::nlanes);
-
- for( k = 2; k < _ksize; k++ )
- {
- sptr = src[k] + i;
- s0 = updateOp(s0, vx_load_aligned(sptr));
- s1 = updateOp(s1, vx_load_aligned(sptr + vtype::nlanes));
- }
-
- sptr = src[0] + i;
- v_store(dst + i, updateOp(s0, vx_load_aligned(sptr)));
- v_store(dst + i + vtype::nlanes, updateOp(s1, vx_load_aligned(sptr + vtype::nlanes)));
-
- sptr = src[k] + i;
- v_store(dst + dststep + i, updateOp(s0, vx_load_aligned(sptr)));
- v_store(dst + dststep + i + vtype::nlanes, updateOp(s1, vx_load_aligned(sptr + vtype::nlanes)));
- i += 2*vtype::nlanes;
- }
- if( i <= width - vtype::nlanes )
- {
- vtype s0 = vx_load_aligned(src[1] + i);
-
- for( k = 2; k < _ksize; k++ )
- s0 = updateOp(s0, vx_load_aligned(src[k] + i));
-
- v_store(dst + i, updateOp(s0, vx_load_aligned(src[0] + i)));
- v_store(dst + dststep + i, updateOp(s0, vx_load_aligned(src[k] + i)));
- i += vtype::nlanes;
- }
- if( i <= width - vtype::nlanes/2 )
- {
- vtype s0 = vx_load_low(src[1] + i);
-
- for( k = 2; k < _ksize; k++ )
- s0 = updateOp(s0, vx_load_low(src[k] + i));
-
- v_store_low(dst + i, updateOp(s0, vx_load_low(src[0] + i)));
- v_store_low(dst + dststep + i, updateOp(s0, vx_load_low(src[k] + i)));
- i += vtype::nlanes/2;
- }
- }
-
- for( ; count > 0; count--, dst += dststep, src++ )
- {
- for( i = 0; i <= width - 4*vtype::nlanes; i += 4*vtype::nlanes)
- {
- const stype* sptr = src[0] + i;
- vtype s0 = vx_load_aligned(sptr);
- vtype s1 = vx_load_aligned(sptr + vtype::nlanes);
- vtype s2 = vx_load_aligned(sptr + 2*vtype::nlanes);
- vtype s3 = vx_load_aligned(sptr + 3*vtype::nlanes);
-
- for( k = 1; k < _ksize; k++ )
- {
- sptr = src[k] + i;
- s0 = updateOp(s0, vx_load_aligned(sptr));
- s1 = updateOp(s1, vx_load_aligned(sptr + vtype::nlanes));
- s2 = updateOp(s2, vx_load_aligned(sptr + 2*vtype::nlanes));
- s3 = updateOp(s3, vx_load_aligned(sptr + 3*vtype::nlanes));
- }
- v_store(dst + i, s0);
- v_store(dst + i + vtype::nlanes, s1);
- v_store(dst + i + 2*vtype::nlanes, s2);
- v_store(dst + i + 3*vtype::nlanes, s3);
- }
- if( i <= width - 2*vtype::nlanes )
- {
- const stype* sptr = src[0] + i;
- vtype s0 = vx_load_aligned(sptr);
- vtype s1 = vx_load_aligned(sptr + vtype::nlanes);
-
- for( k = 1; k < _ksize; k++ )
- {
- sptr = src[k] + i;
- s0 = updateOp(s0, vx_load_aligned(sptr));
- s1 = updateOp(s1, vx_load_aligned(sptr + vtype::nlanes));
- }
- v_store(dst + i, s0);
- v_store(dst + i + vtype::nlanes, s1);
- i += 2*vtype::nlanes;
- }
- if( i <= width - vtype::nlanes )
- {
- vtype s0 = vx_load_aligned(src[0] + i);
-
- for( k = 1; k < _ksize; k++ )
- s0 = updateOp(s0, vx_load_aligned(src[k] + i));
- v_store(dst + i, s0);
- i += vtype::nlanes;
- }
- if( i <= width - vtype::nlanes/2 )
- {
- vtype s0 = vx_load_low(src[0] + i);
-
- for( k = 1; k < _ksize; k++ )
- s0 = updateOp(s0, vx_load_low(src[k] + i));
- v_store_low(dst + i, s0);
- i += vtype::nlanes/2;
- }
- }
-
- return i;
- }
-
- int ksize, anchor;
-};
-
-
-template<class VecUpdate> struct MorphVec
-{
- typedef typename VecUpdate::vtype vtype;
- typedef typename vtype::lane_type stype;
- int operator()(uchar** _src, int nz, uchar* _dst, int width) const
- {
- const stype** src = (const stype**)_src;
- stype* dst = (stype*)_dst;
- int i, k;
- VecUpdate updateOp;
-
- for( i = 0; i <= width - 4*vtype::nlanes; i += 4*vtype::nlanes )
- {
- const stype* sptr = src[0] + i;
- vtype s0 = vx_load(sptr);
- vtype s1 = vx_load(sptr + vtype::nlanes);
- vtype s2 = vx_load(sptr + 2*vtype::nlanes);
- vtype s3 = vx_load(sptr + 3*vtype::nlanes);
- for( k = 1; k < nz; k++ )
- {
- sptr = src[k] + i;
- s0 = updateOp(s0, vx_load(sptr));
- s1 = updateOp(s1, vx_load(sptr + vtype::nlanes));
- s2 = updateOp(s2, vx_load(sptr + 2*vtype::nlanes));
- s3 = updateOp(s3, vx_load(sptr + 3*vtype::nlanes));
- }
- v_store(dst + i, s0);
- v_store(dst + i + vtype::nlanes, s1);
- v_store(dst + i + 2*vtype::nlanes, s2);
- v_store(dst + i + 3*vtype::nlanes, s3);
- }
- if( i <= width - 2*vtype::nlanes )
- {
- const stype* sptr = src[0] + i;
- vtype s0 = vx_load(sptr);
- vtype s1 = vx_load(sptr + vtype::nlanes);
- for( k = 1; k < nz; k++ )
- {
- sptr = src[k] + i;
- s0 = updateOp(s0, vx_load(sptr));
- s1 = updateOp(s1, vx_load(sptr + vtype::nlanes));
- }
- v_store(dst + i, s0);
- v_store(dst + i + vtype::nlanes, s1);
- i += 2*vtype::nlanes;
- }
- if( i <= width - vtype::nlanes )
- {
- vtype s0 = vx_load(src[0] + i);
- for( k = 1; k < nz; k++ )
- s0 = updateOp(s0, vx_load(src[k] + i));
- v_store(dst + i, s0);
- i += vtype::nlanes;
- }
- if( i <= width - vtype::nlanes/2 )
- {
- vtype s0 = vx_load_low(src[0] + i);
- for( k = 1; k < nz; k++ )
- s0 = updateOp(s0, vx_load_low(src[k] + i));
- v_store_low(dst + i, s0);
- i += vtype::nlanes/2;
- }
- return i;
- }
-};
-
-template <typename T> struct VMin
-{
- typedef T vtype;
- vtype operator()(const vtype& a, const vtype& b) const { return v_min(a,b); }
-};
-template <typename T> struct VMax
-{
- typedef T vtype;
- vtype operator()(const vtype& a, const vtype& b) const { return v_max(a,b); }
-};
-
-typedef MorphRowVec<VMin<v_uint8> > ErodeRowVec8u;
-typedef MorphRowVec<VMax<v_uint8> > DilateRowVec8u;
-typedef MorphRowVec<VMin<v_uint16> > ErodeRowVec16u;
-typedef MorphRowVec<VMax<v_uint16> > DilateRowVec16u;
-typedef MorphRowVec<VMin<v_int16> > ErodeRowVec16s;
-typedef MorphRowVec<VMax<v_int16> > DilateRowVec16s;
-typedef MorphRowVec<VMin<v_float32> > ErodeRowVec32f;
-typedef MorphRowVec<VMax<v_float32> > DilateRowVec32f;
-
-typedef MorphColumnVec<VMin<v_uint8> > ErodeColumnVec8u;
-typedef MorphColumnVec<VMax<v_uint8> > DilateColumnVec8u;
-typedef MorphColumnVec<VMin<v_uint16> > ErodeColumnVec16u;
-typedef MorphColumnVec<VMax<v_uint16> > DilateColumnVec16u;
-typedef MorphColumnVec<VMin<v_int16> > ErodeColumnVec16s;
-typedef MorphColumnVec<VMax<v_int16> > DilateColumnVec16s;
-typedef MorphColumnVec<VMin<v_float32> > ErodeColumnVec32f;
-typedef MorphColumnVec<VMax<v_float32> > DilateColumnVec32f;
-
-typedef MorphVec<VMin<v_uint8> > ErodeVec8u;
-typedef MorphVec<VMax<v_uint8> > DilateVec8u;
-typedef MorphVec<VMin<v_uint16> > ErodeVec16u;
-typedef MorphVec<VMax<v_uint16> > DilateVec16u;
-typedef MorphVec<VMin<v_int16> > ErodeVec16s;
-typedef MorphVec<VMax<v_int16> > DilateVec16s;
-typedef MorphVec<VMin<v_float32> > ErodeVec32f;
-typedef MorphVec<VMax<v_float32> > DilateVec32f;
-
-#else
-
-typedef MorphRowNoVec ErodeRowVec8u;
-typedef MorphRowNoVec DilateRowVec8u;
-
-typedef MorphColumnNoVec ErodeColumnVec8u;
-typedef MorphColumnNoVec DilateColumnVec8u;
-
-typedef MorphRowNoVec ErodeRowVec16u;
-typedef MorphRowNoVec DilateRowVec16u;
-typedef MorphRowNoVec ErodeRowVec16s;
-typedef MorphRowNoVec DilateRowVec16s;
-typedef MorphRowNoVec ErodeRowVec32f;
-typedef MorphRowNoVec DilateRowVec32f;
-
-typedef MorphColumnNoVec ErodeColumnVec16u;
-typedef MorphColumnNoVec DilateColumnVec16u;
-typedef MorphColumnNoVec ErodeColumnVec16s;
-typedef MorphColumnNoVec DilateColumnVec16s;
-typedef MorphColumnNoVec ErodeColumnVec32f;
-typedef MorphColumnNoVec DilateColumnVec32f;
-
-typedef MorphNoVec ErodeVec8u;
-typedef MorphNoVec DilateVec8u;
-typedef MorphNoVec ErodeVec16u;
-typedef MorphNoVec DilateVec16u;
-typedef MorphNoVec ErodeVec16s;
-typedef MorphNoVec DilateVec16s;
-typedef MorphNoVec ErodeVec32f;
-typedef MorphNoVec DilateVec32f;
-
-#endif
-
-typedef MorphRowNoVec ErodeRowVec64f;
-typedef MorphRowNoVec DilateRowVec64f;
-typedef MorphColumnNoVec ErodeColumnVec64f;
-typedef MorphColumnNoVec DilateColumnVec64f;
-typedef MorphNoVec ErodeVec64f;
-typedef MorphNoVec DilateVec64f;
-
-
-template<class Op, class VecOp> struct MorphRowFilter : public BaseRowFilter
-{
- typedef typename Op::rtype T;
-
- MorphRowFilter( int _ksize, int _anchor ) : vecOp(_ksize, _anchor)
- {
- ksize = _ksize;
- anchor = _anchor;
- }
-
- void operator()(const uchar* src, uchar* dst, int width, int cn) CV_OVERRIDE
- {
- int i, j, k, _ksize = ksize*cn;
- const T* S = (const T*)src;
- Op op;
- T* D = (T*)dst;
-
- if( _ksize == cn )
- {
- for( i = 0; i < width*cn; i++ )
- D[i] = S[i];
- return;
- }
-
- int i0 = vecOp(src, dst, width, cn);
- width *= cn;
-
- for( k = 0; k < cn; k++, S++, D++ )
- {
- for( i = i0; i <= width - cn*2; i += cn*2 )
- {
- const T* s = S + i;
- T m = s[cn];
- for( j = cn*2; j < _ksize; j += cn )
- m = op(m, s[j]);
- D[i] = op(m, s[0]);
- D[i+cn] = op(m, s[j]);
- }
-
- for( ; i < width; i += cn )
- {
- const T* s = S + i;
- T m = s[0];
- for( j = cn; j < _ksize; j += cn )
- m = op(m, s[j]);
- D[i] = m;
- }
- }
- }
-
- VecOp vecOp;
-};
-
-
-template<class Op, class VecOp> struct MorphColumnFilter : public BaseColumnFilter
-{
- typedef typename Op::rtype T;
-
- MorphColumnFilter( int _ksize, int _anchor ) : vecOp(_ksize, _anchor)
- {
- ksize = _ksize;
- anchor = _anchor;
- }
-
- void operator()(const uchar** _src, uchar* dst, int dststep, int count, int width) CV_OVERRIDE
- {
- int i, k, _ksize = ksize;
- const T** src = (const T**)_src;
- T* D = (T*)dst;
- Op op;
-
- int i0 = vecOp(_src, dst, dststep, count, width);
- dststep /= sizeof(D[0]);
-
- for( ; _ksize > 1 && count > 1; count -= 2, D += dststep*2, src += 2 )
- {
- i = i0;
- #if CV_ENABLE_UNROLLED
- for( ; i <= width - 4; i += 4 )
- {
- const T* sptr = src[1] + i;
- T s0 = sptr[0], s1 = sptr[1], s2 = sptr[2], s3 = sptr[3];
-
- for( k = 2; k < _ksize; k++ )
- {
- sptr = src[k] + i;
- s0 = op(s0, sptr[0]); s1 = op(s1, sptr[1]);
- s2 = op(s2, sptr[2]); s3 = op(s3, sptr[3]);
- }
-
- sptr = src[0] + i;
- D[i] = op(s0, sptr[0]);
- D[i+1] = op(s1, sptr[1]);
- D[i+2] = op(s2, sptr[2]);
- D[i+3] = op(s3, sptr[3]);
-
- sptr = src[k] + i;
- D[i+dststep] = op(s0, sptr[0]);
- D[i+dststep+1] = op(s1, sptr[1]);
- D[i+dststep+2] = op(s2, sptr[2]);
- D[i+dststep+3] = op(s3, sptr[3]);
- }
- #endif
- for( ; i < width; i++ )
- {
- T s0 = src[1][i];
-
- for( k = 2; k < _ksize; k++ )
- s0 = op(s0, src[k][i]);
-
- D[i] = op(s0, src[0][i]);
- D[i+dststep] = op(s0, src[k][i]);
- }
- }
-
- for( ; count > 0; count--, D += dststep, src++ )
- {
- i = i0;
- #if CV_ENABLE_UNROLLED
- for( ; i <= width - 4; i += 4 )
- {
- const T* sptr = src[0] + i;
- T s0 = sptr[0], s1 = sptr[1], s2 = sptr[2], s3 = sptr[3];
-
- for( k = 1; k < _ksize; k++ )
- {
- sptr = src[k] + i;
- s0 = op(s0, sptr[0]); s1 = op(s1, sptr[1]);
- s2 = op(s2, sptr[2]); s3 = op(s3, sptr[3]);
- }
-
- D[i] = s0; D[i+1] = s1;
- D[i+2] = s2; D[i+3] = s3;
- }
- #endif
- for( ; i < width; i++ )
- {
- T s0 = src[0][i];
- for( k = 1; k < _ksize; k++ )
- s0 = op(s0, src[k][i]);
- D[i] = s0;
- }
- }
- }
-
- VecOp vecOp;
-};
-
-
-template<class Op, class VecOp> struct MorphFilter : BaseFilter
-{
- typedef typename Op::rtype T;
-
- MorphFilter( const Mat& _kernel, Point _anchor )
- {
- anchor = _anchor;
- ksize = _kernel.size();
- CV_Assert( _kernel.type() == CV_8U );
-
- std::vector<uchar> coeffs; // we do not really the values of non-zero
- // kernel elements, just their locations
- preprocess2DKernel( _kernel, coords, coeffs );
- ptrs.resize( coords.size() );
- }
-
- void operator()(const uchar** src, uchar* dst, int dststep, int count, int width, int cn) CV_OVERRIDE
- {
- const Point* pt = &coords[0];
- const T** kp = (const T**)&ptrs[0];
- int i, k, nz = (int)coords.size();
- Op op;
-
- width *= cn;
- for( ; count > 0; count--, dst += dststep, src++ )
- {
- T* D = (T*)dst;
-
- for( k = 0; k < nz; k++ )
- kp[k] = (const T*)src[pt[k].y] + pt[k].x*cn;
-
- i = vecOp(&ptrs[0], nz, dst, width);
- #if CV_ENABLE_UNROLLED
- for( ; i <= width - 4; i += 4 )
- {
- const T* sptr = kp[0] + i;
- T s0 = sptr[0], s1 = sptr[1], s2 = sptr[2], s3 = sptr[3];
-
- for( k = 1; k < nz; k++ )
- {
- sptr = kp[k] + i;
- s0 = op(s0, sptr[0]); s1 = op(s1, sptr[1]);
- s2 = op(s2, sptr[2]); s3 = op(s3, sptr[3]);
- }
-
- D[i] = s0; D[i+1] = s1;
- D[i+2] = s2; D[i+3] = s3;
- }
- #endif
- for( ; i < width; i++ )
- {
- T s0 = kp[0][i];
- for( k = 1; k < nz; k++ )
- s0 = op(s0, kp[k][i]);
- D[i] = s0;
- }
- }
- }
-
- std::vector<Point> coords;
- std::vector<uchar*> ptrs;
- VecOp vecOp;
-};
-
-}
+namespace cv {
/////////////////////////////////// External Interface /////////////////////////////////////
-cv::Ptr<cv::BaseRowFilter> cv::getMorphologyRowFilter(int op, int type, int ksize, int anchor)
+Ptr<BaseRowFilter> getMorphologyRowFilter(int op, int type, int ksize, int anchor)
{
- int depth = CV_MAT_DEPTH(type);
- if( anchor < 0 )
- anchor = ksize/2;
- CV_Assert( op == MORPH_ERODE || op == MORPH_DILATE );
- if( op == MORPH_ERODE )
- {
- if( depth == CV_8U )
- return makePtr<MorphRowFilter<MinOp<uchar>,
- ErodeRowVec8u> >(ksize, anchor);
- if( depth == CV_16U )
- return makePtr<MorphRowFilter<MinOp<ushort>,
- ErodeRowVec16u> >(ksize, anchor);
- if( depth == CV_16S )
- return makePtr<MorphRowFilter<MinOp<short>,
- ErodeRowVec16s> >(ksize, anchor);
- if( depth == CV_32F )
- return makePtr<MorphRowFilter<MinOp<float>,
- ErodeRowVec32f> >(ksize, anchor);
- if( depth == CV_64F )
- return makePtr<MorphRowFilter<MinOp<double>,
- ErodeRowVec64f> >(ksize, anchor);
- }
- else
- {
- if( depth == CV_8U )
- return makePtr<MorphRowFilter<MaxOp<uchar>,
- DilateRowVec8u> >(ksize, anchor);
- if( depth == CV_16U )
- return makePtr<MorphRowFilter<MaxOp<ushort>,
- DilateRowVec16u> >(ksize, anchor);
- if( depth == CV_16S )
- return makePtr<MorphRowFilter<MaxOp<short>,
- DilateRowVec16s> >(ksize, anchor);
- if( depth == CV_32F )
- return makePtr<MorphRowFilter<MaxOp<float>,
- DilateRowVec32f> >(ksize, anchor);
- if( depth == CV_64F )
- return makePtr<MorphRowFilter<MaxOp<double>,
- DilateRowVec64f> >(ksize, anchor);
- }
+ CV_INSTRUMENT_REGION();
- CV_Error_( CV_StsNotImplemented, ("Unsupported data type (=%d)", type));
+ CV_CPU_DISPATCH(getMorphologyRowFilter, (op, type, ksize, anchor),
+ CV_CPU_DISPATCH_MODES_ALL);
}
-cv::Ptr<cv::BaseColumnFilter> cv::getMorphologyColumnFilter(int op, int type, int ksize, int anchor)
+Ptr<BaseColumnFilter> getMorphologyColumnFilter(int op, int type, int ksize, int anchor)
{
- int depth = CV_MAT_DEPTH(type);
- if( anchor < 0 )
- anchor = ksize/2;
- CV_Assert( op == MORPH_ERODE || op == MORPH_DILATE );
- if( op == MORPH_ERODE )
- {
- if( depth == CV_8U )
- return makePtr<MorphColumnFilter<MinOp<uchar>,
- ErodeColumnVec8u> >(ksize, anchor);
- if( depth == CV_16U )
- return makePtr<MorphColumnFilter<MinOp<ushort>,
- ErodeColumnVec16u> >(ksize, anchor);
- if( depth == CV_16S )
- return makePtr<MorphColumnFilter<MinOp<short>,
- ErodeColumnVec16s> >(ksize, anchor);
- if( depth == CV_32F )
- return makePtr<MorphColumnFilter<MinOp<float>,
- ErodeColumnVec32f> >(ksize, anchor);
- if( depth == CV_64F )
- return makePtr<MorphColumnFilter<MinOp<double>,
- ErodeColumnVec64f> >(ksize, anchor);
- }
- else
- {
- if( depth == CV_8U )
- return makePtr<MorphColumnFilter<MaxOp<uchar>,
- DilateColumnVec8u> >(ksize, anchor);
- if( depth == CV_16U )
- return makePtr<MorphColumnFilter<MaxOp<ushort>,
- DilateColumnVec16u> >(ksize, anchor);
- if( depth == CV_16S )
- return makePtr<MorphColumnFilter<MaxOp<short>,
- DilateColumnVec16s> >(ksize, anchor);
- if( depth == CV_32F )
- return makePtr<MorphColumnFilter<MaxOp<float>,
- DilateColumnVec32f> >(ksize, anchor);
- if( depth == CV_64F )
- return makePtr<MorphColumnFilter<MaxOp<double>,
- DilateColumnVec64f> >(ksize, anchor);
- }
+ CV_INSTRUMENT_REGION();
- CV_Error_( CV_StsNotImplemented, ("Unsupported data type (=%d)", type));
+ CV_CPU_DISPATCH(getMorphologyColumnFilter, (op, type, ksize, anchor),
+ CV_CPU_DISPATCH_MODES_ALL);
}
-cv::Ptr<cv::BaseFilter> cv::getMorphologyFilter(int op, int type, InputArray _kernel, Point anchor)
+Ptr<BaseFilter> getMorphologyFilter(int op, int type, InputArray _kernel, Point anchor)
{
- Mat kernel = _kernel.getMat();
- int depth = CV_MAT_DEPTH(type);
- anchor = normalizeAnchor(anchor, kernel.size());
- CV_Assert( op == MORPH_ERODE || op == MORPH_DILATE );
- if( op == MORPH_ERODE )
- {
- if( depth == CV_8U )
- return makePtr<MorphFilter<MinOp<uchar>, ErodeVec8u> >(kernel, anchor);
- if( depth == CV_16U )
- return makePtr<MorphFilter<MinOp<ushort>, ErodeVec16u> >(kernel, anchor);
- if( depth == CV_16S )
- return makePtr<MorphFilter<MinOp<short>, ErodeVec16s> >(kernel, anchor);
- if( depth == CV_32F )
- return makePtr<MorphFilter<MinOp<float>, ErodeVec32f> >(kernel, anchor);
- if( depth == CV_64F )
- return makePtr<MorphFilter<MinOp<double>, ErodeVec64f> >(kernel, anchor);
- }
- else
- {
- if( depth == CV_8U )
- return makePtr<MorphFilter<MaxOp<uchar>, DilateVec8u> >(kernel, anchor);
- if( depth == CV_16U )
- return makePtr<MorphFilter<MaxOp<ushort>, DilateVec16u> >(kernel, anchor);
- if( depth == CV_16S )
- return makePtr<MorphFilter<MaxOp<short>, DilateVec16s> >(kernel, anchor);
- if( depth == CV_32F )
- return makePtr<MorphFilter<MaxOp<float>, DilateVec32f> >(kernel, anchor);
- if( depth == CV_64F )
- return makePtr<MorphFilter<MaxOp<double>, DilateVec64f> >(kernel, anchor);
- }
+ CV_INSTRUMENT_REGION();
- CV_Error_( CV_StsNotImplemented, ("Unsupported data type (=%d)", type));
+ Mat kernel = _kernel.getMat();
+ CV_CPU_DISPATCH(getMorphologyFilter, (op, type, kernel, anchor),
+ CV_CPU_DISPATCH_MODES_ALL);
}
-cv::Ptr<cv::FilterEngine> cv::createMorphologyFilter( int op, int type, InputArray _kernel,
- Point anchor, int _rowBorderType, int _columnBorderType,
- const Scalar& _borderValue )
+Ptr<FilterEngine> createMorphologyFilter(
+ int op, int type, InputArray _kernel,
+ Point anchor, int _rowBorderType, int _columnBorderType,
+ const Scalar& _borderValue)
{
Mat kernel = _kernel.getMat();
anchor = normalizeAnchor(anchor, kernel.size());
}
-cv::Mat cv::getStructuringElement(int shape, Size ksize, Point anchor)
+Mat getStructuringElement(int shape, Size ksize, Point anchor)
{
int i, j;
int r = 0, c = 0;
return elem;
}
-namespace cv
-{
-
// ===== 1. replacement implementation
static bool halMorph(int op, int src_type, int dst_type,
(src.isSubmatrix() && !isolated));
}
-}
-
-void cv::erode( InputArray src, OutputArray dst, InputArray kernel,
+void erode( InputArray src, OutputArray dst, InputArray kernel,
Point anchor, int iterations,
int borderType, const Scalar& borderValue )
{
}
-void cv::dilate( InputArray src, OutputArray dst, InputArray kernel,
+void dilate( InputArray src, OutputArray dst, InputArray kernel,
Point anchor, int iterations,
int borderType, const Scalar& borderValue )
{
#ifdef HAVE_OPENCL
-namespace cv {
-
static bool ocl_morphologyEx(InputArray _src, OutputArray _dst, int op,
InputArray kernel, Point anchor, int iterations,
int borderType, const Scalar& borderValue)
return true;
}
-}
#endif
#define IPP_DISABLE_MORPH_ADV 1
#if 0 //defined HAVE_IPP
#if !IPP_DISABLE_MORPH_ADV
-namespace cv {
static bool ipp_morphologyEx(int op, InputArray _src, OutputArray _dst,
InputArray _kernel,
Point anchor, int iterations,
return false;
#endif
}
-}
#endif
#endif
-void cv::morphologyEx( InputArray _src, OutputArray _dst, int op,
+void morphologyEx( InputArray _src, OutputArray _dst, int op,
InputArray _kernel, Point anchor, int iterations,
int borderType, const Scalar& borderValue )
{
}
}
+} // namespace cv
+
CV_IMPL IplConvKernel *
cvCreateStructuringElementEx( int cols, int rows,
int anchorX, int anchorY,
--- /dev/null
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "precomp.hpp"
+#include <limits.h>
+#include "opencv2/core/hal/intrin.hpp"
+
+/****************************************************************************************\
+ Basic Morphological Operations: Erosion & Dilation
+\****************************************************************************************/
+
+namespace cv {
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+// forward declarations
+Ptr<BaseRowFilter> getMorphologyRowFilter(int op, int type, int ksize, int anchor);
+Ptr<BaseColumnFilter> getMorphologyColumnFilter(int op, int type, int ksize, int anchor);
+Ptr<BaseFilter> getMorphologyFilter(int op, int type, const Mat& kernel, Point anchor);
+
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
+
+namespace {
+template<typename T> struct MinOp
+{
+ typedef T type1;
+ typedef T type2;
+ typedef T rtype;
+ T operator ()(const T a, const T b) const { return std::min(a, b); }
+};
+
+template<typename T> struct MaxOp
+{
+ typedef T type1;
+ typedef T type2;
+ typedef T rtype;
+ T operator ()(const T a, const T b) const { return std::max(a, b); }
+};
+
+
+#if !defined(CV_SIMD) // min/max operation are usually fast enough (without using of control flow 'if' statements)
+
+#undef CV_MIN_8U
+#undef CV_MAX_8U
+#define CV_MIN_8U(a,b) ((a) - CV_FAST_CAST_8U((a) - (b)))
+#define CV_MAX_8U(a,b) ((a) + CV_FAST_CAST_8U((b) - (a)))
+
+template<> inline uchar MinOp<uchar>::operator ()(const uchar a, const uchar b) const { return CV_MIN_8U(a, b); }
+template<> inline uchar MaxOp<uchar>::operator ()(const uchar a, const uchar b) const { return CV_MAX_8U(a, b); }
+
+#endif
+
+
+
+struct MorphRowNoVec
+{
+ MorphRowNoVec(int, int) {}
+ int operator()(const uchar*, uchar*, int, int) const { return 0; }
+};
+
+struct MorphColumnNoVec
+{
+ MorphColumnNoVec(int, int) {}
+ int operator()(const uchar**, uchar*, int, int, int) const { return 0; }
+};
+
+struct MorphNoVec
+{
+ int operator()(uchar**, int, uchar*, int) const { return 0; }
+};
+
+#if CV_SIMD
+
+template<class VecUpdate> struct MorphRowVec
+{
+ typedef typename VecUpdate::vtype vtype;
+ typedef typename vtype::lane_type stype;
+ MorphRowVec(int _ksize, int _anchor) : ksize(_ksize), anchor(_anchor) {}
+ int operator()(const uchar* src, uchar* dst, int width, int cn) const
+ {
+ CV_INSTRUMENT_REGION();
+
+ int i, k, _ksize = ksize*cn;
+ width *= cn;
+ VecUpdate updateOp;
+
+ for( i = 0; i <= width - 4*vtype::nlanes; i += 4*vtype::nlanes )
+ {
+ vtype s0 = vx_load((const stype*)src + i);
+ vtype s1 = vx_load((const stype*)src + i + vtype::nlanes);
+ vtype s2 = vx_load((const stype*)src + i + 2*vtype::nlanes);
+ vtype s3 = vx_load((const stype*)src + i + 3*vtype::nlanes);
+ for (k = cn; k < _ksize; k += cn)
+ {
+ s0 = updateOp(s0, vx_load((const stype*)src + i + k));
+ s1 = updateOp(s1, vx_load((const stype*)src + i + k + vtype::nlanes));
+ s2 = updateOp(s2, vx_load((const stype*)src + i + k + 2*vtype::nlanes));
+ s3 = updateOp(s3, vx_load((const stype*)src + i + k + 3*vtype::nlanes));
+ }
+ v_store((stype*)dst + i, s0);
+ v_store((stype*)dst + i + vtype::nlanes, s1);
+ v_store((stype*)dst + i + 2*vtype::nlanes, s2);
+ v_store((stype*)dst + i + 3*vtype::nlanes, s3);
+ }
+ if( i <= width - 2*vtype::nlanes )
+ {
+ vtype s0 = vx_load((const stype*)src + i);
+ vtype s1 = vx_load((const stype*)src + i + vtype::nlanes);
+ for( k = cn; k < _ksize; k += cn )
+ {
+ s0 = updateOp(s0, vx_load((const stype*)src + i + k));
+ s1 = updateOp(s1, vx_load((const stype*)src + i + k + vtype::nlanes));
+ }
+ v_store((stype*)dst + i, s0);
+ v_store((stype*)dst + i + vtype::nlanes, s1);
+ i += 2*vtype::nlanes;
+ }
+ if( i <= width - vtype::nlanes )
+ {
+ vtype s = vx_load((const stype*)src + i);
+ for( k = cn; k < _ksize; k += cn )
+ s = updateOp(s, vx_load((const stype*)src + i + k));
+ v_store((stype*)dst + i, s);
+ i += vtype::nlanes;
+ }
+ if( i <= width - vtype::nlanes/2 )
+ {
+ vtype s = vx_load_low((const stype*)src + i);
+ for( k = cn; k < _ksize; k += cn )
+ s = updateOp(s, vx_load_low((const stype*)src + i + k));
+ v_store_low((stype*)dst + i, s);
+ i += vtype::nlanes/2;
+ }
+
+ return i - i % cn;
+ }
+
+ int ksize, anchor;
+};
+
+
+template<class VecUpdate> struct MorphColumnVec
+{
+ typedef typename VecUpdate::vtype vtype;
+ typedef typename vtype::lane_type stype;
+ MorphColumnVec(int _ksize, int _anchor) : ksize(_ksize), anchor(_anchor) {}
+ int operator()(const uchar** _src, uchar* _dst, int dststep, int count, int width) const
+ {
+ CV_INSTRUMENT_REGION();
+
+ int i = 0, k, _ksize = ksize;
+ VecUpdate updateOp;
+
+ for( i = 0; i < count + ksize - 1; i++ )
+ CV_Assert( ((size_t)_src[i] & (CV_SIMD_WIDTH-1)) == 0 );
+
+ const stype** src = (const stype**)_src;
+ stype* dst = (stype*)_dst;
+ dststep /= sizeof(dst[0]);
+
+ for( ; _ksize > 1 && count > 1; count -= 2, dst += dststep*2, src += 2 )
+ {
+ for( i = 0; i <= width - 4*vtype::nlanes; i += 4*vtype::nlanes)
+ {
+ const stype* sptr = src[1] + i;
+ vtype s0 = vx_load_aligned(sptr);
+ vtype s1 = vx_load_aligned(sptr + vtype::nlanes);
+ vtype s2 = vx_load_aligned(sptr + 2*vtype::nlanes);
+ vtype s3 = vx_load_aligned(sptr + 3*vtype::nlanes);
+
+ for( k = 2; k < _ksize; k++ )
+ {
+ sptr = src[k] + i;
+ s0 = updateOp(s0, vx_load_aligned(sptr));
+ s1 = updateOp(s1, vx_load_aligned(sptr + vtype::nlanes));
+ s2 = updateOp(s2, vx_load_aligned(sptr + 2*vtype::nlanes));
+ s3 = updateOp(s3, vx_load_aligned(sptr + 3*vtype::nlanes));
+ }
+
+ sptr = src[0] + i;
+ v_store(dst + i, updateOp(s0, vx_load_aligned(sptr)));
+ v_store(dst + i + vtype::nlanes, updateOp(s1, vx_load_aligned(sptr + vtype::nlanes)));
+ v_store(dst + i + 2*vtype::nlanes, updateOp(s2, vx_load_aligned(sptr + 2*vtype::nlanes)));
+ v_store(dst + i + 3*vtype::nlanes, updateOp(s3, vx_load_aligned(sptr + 3*vtype::nlanes)));
+
+ sptr = src[k] + i;
+ v_store(dst + dststep + i, updateOp(s0, vx_load_aligned(sptr)));
+ v_store(dst + dststep + i + vtype::nlanes, updateOp(s1, vx_load_aligned(sptr + vtype::nlanes)));
+ v_store(dst + dststep + i + 2*vtype::nlanes, updateOp(s2, vx_load_aligned(sptr + 2*vtype::nlanes)));
+ v_store(dst + dststep + i + 3*vtype::nlanes, updateOp(s3, vx_load_aligned(sptr + 3*vtype::nlanes)));
+ }
+ if( i <= width - 2*vtype::nlanes )
+ {
+ const stype* sptr = src[1] + i;
+ vtype s0 = vx_load_aligned(sptr);
+ vtype s1 = vx_load_aligned(sptr + vtype::nlanes);
+
+ for( k = 2; k < _ksize; k++ )
+ {
+ sptr = src[k] + i;
+ s0 = updateOp(s0, vx_load_aligned(sptr));
+ s1 = updateOp(s1, vx_load_aligned(sptr + vtype::nlanes));
+ }
+
+ sptr = src[0] + i;
+ v_store(dst + i, updateOp(s0, vx_load_aligned(sptr)));
+ v_store(dst + i + vtype::nlanes, updateOp(s1, vx_load_aligned(sptr + vtype::nlanes)));
+
+ sptr = src[k] + i;
+ v_store(dst + dststep + i, updateOp(s0, vx_load_aligned(sptr)));
+ v_store(dst + dststep + i + vtype::nlanes, updateOp(s1, vx_load_aligned(sptr + vtype::nlanes)));
+ i += 2*vtype::nlanes;
+ }
+ if( i <= width - vtype::nlanes )
+ {
+ vtype s0 = vx_load_aligned(src[1] + i);
+
+ for( k = 2; k < _ksize; k++ )
+ s0 = updateOp(s0, vx_load_aligned(src[k] + i));
+
+ v_store(dst + i, updateOp(s0, vx_load_aligned(src[0] + i)));
+ v_store(dst + dststep + i, updateOp(s0, vx_load_aligned(src[k] + i)));
+ i += vtype::nlanes;
+ }
+ if( i <= width - vtype::nlanes/2 )
+ {
+ vtype s0 = vx_load_low(src[1] + i);
+
+ for( k = 2; k < _ksize; k++ )
+ s0 = updateOp(s0, vx_load_low(src[k] + i));
+
+ v_store_low(dst + i, updateOp(s0, vx_load_low(src[0] + i)));
+ v_store_low(dst + dststep + i, updateOp(s0, vx_load_low(src[k] + i)));
+ i += vtype::nlanes/2;
+ }
+ }
+
+ for( ; count > 0; count--, dst += dststep, src++ )
+ {
+ for( i = 0; i <= width - 4*vtype::nlanes; i += 4*vtype::nlanes)
+ {
+ const stype* sptr = src[0] + i;
+ vtype s0 = vx_load_aligned(sptr);
+ vtype s1 = vx_load_aligned(sptr + vtype::nlanes);
+ vtype s2 = vx_load_aligned(sptr + 2*vtype::nlanes);
+ vtype s3 = vx_load_aligned(sptr + 3*vtype::nlanes);
+
+ for( k = 1; k < _ksize; k++ )
+ {
+ sptr = src[k] + i;
+ s0 = updateOp(s0, vx_load_aligned(sptr));
+ s1 = updateOp(s1, vx_load_aligned(sptr + vtype::nlanes));
+ s2 = updateOp(s2, vx_load_aligned(sptr + 2*vtype::nlanes));
+ s3 = updateOp(s3, vx_load_aligned(sptr + 3*vtype::nlanes));
+ }
+ v_store(dst + i, s0);
+ v_store(dst + i + vtype::nlanes, s1);
+ v_store(dst + i + 2*vtype::nlanes, s2);
+ v_store(dst + i + 3*vtype::nlanes, s3);
+ }
+ if( i <= width - 2*vtype::nlanes )
+ {
+ const stype* sptr = src[0] + i;
+ vtype s0 = vx_load_aligned(sptr);
+ vtype s1 = vx_load_aligned(sptr + vtype::nlanes);
+
+ for( k = 1; k < _ksize; k++ )
+ {
+ sptr = src[k] + i;
+ s0 = updateOp(s0, vx_load_aligned(sptr));
+ s1 = updateOp(s1, vx_load_aligned(sptr + vtype::nlanes));
+ }
+ v_store(dst + i, s0);
+ v_store(dst + i + vtype::nlanes, s1);
+ i += 2*vtype::nlanes;
+ }
+ if( i <= width - vtype::nlanes )
+ {
+ vtype s0 = vx_load_aligned(src[0] + i);
+
+ for( k = 1; k < _ksize; k++ )
+ s0 = updateOp(s0, vx_load_aligned(src[k] + i));
+ v_store(dst + i, s0);
+ i += vtype::nlanes;
+ }
+ if( i <= width - vtype::nlanes/2 )
+ {
+ vtype s0 = vx_load_low(src[0] + i);
+
+ for( k = 1; k < _ksize; k++ )
+ s0 = updateOp(s0, vx_load_low(src[k] + i));
+ v_store_low(dst + i, s0);
+ i += vtype::nlanes/2;
+ }
+ }
+
+ return i;
+ }
+
+ int ksize, anchor;
+};
+
+
+template<class VecUpdate> struct MorphVec
+{
+ typedef typename VecUpdate::vtype vtype;
+ typedef typename vtype::lane_type stype;
+ int operator()(uchar** _src, int nz, uchar* _dst, int width) const
+ {
+ CV_INSTRUMENT_REGION();
+
+ const stype** src = (const stype**)_src;
+ stype* dst = (stype*)_dst;
+ int i, k;
+ VecUpdate updateOp;
+
+ for( i = 0; i <= width - 4*vtype::nlanes; i += 4*vtype::nlanes )
+ {
+ const stype* sptr = src[0] + i;
+ vtype s0 = vx_load(sptr);
+ vtype s1 = vx_load(sptr + vtype::nlanes);
+ vtype s2 = vx_load(sptr + 2*vtype::nlanes);
+ vtype s3 = vx_load(sptr + 3*vtype::nlanes);
+ for( k = 1; k < nz; k++ )
+ {
+ sptr = src[k] + i;
+ s0 = updateOp(s0, vx_load(sptr));
+ s1 = updateOp(s1, vx_load(sptr + vtype::nlanes));
+ s2 = updateOp(s2, vx_load(sptr + 2*vtype::nlanes));
+ s3 = updateOp(s3, vx_load(sptr + 3*vtype::nlanes));
+ }
+ v_store(dst + i, s0);
+ v_store(dst + i + vtype::nlanes, s1);
+ v_store(dst + i + 2*vtype::nlanes, s2);
+ v_store(dst + i + 3*vtype::nlanes, s3);
+ }
+ if( i <= width - 2*vtype::nlanes )
+ {
+ const stype* sptr = src[0] + i;
+ vtype s0 = vx_load(sptr);
+ vtype s1 = vx_load(sptr + vtype::nlanes);
+ for( k = 1; k < nz; k++ )
+ {
+ sptr = src[k] + i;
+ s0 = updateOp(s0, vx_load(sptr));
+ s1 = updateOp(s1, vx_load(sptr + vtype::nlanes));
+ }
+ v_store(dst + i, s0);
+ v_store(dst + i + vtype::nlanes, s1);
+ i += 2*vtype::nlanes;
+ }
+ if( i <= width - vtype::nlanes )
+ {
+ vtype s0 = vx_load(src[0] + i);
+ for( k = 1; k < nz; k++ )
+ s0 = updateOp(s0, vx_load(src[k] + i));
+ v_store(dst + i, s0);
+ i += vtype::nlanes;
+ }
+ if( i <= width - vtype::nlanes/2 )
+ {
+ vtype s0 = vx_load_low(src[0] + i);
+ for( k = 1; k < nz; k++ )
+ s0 = updateOp(s0, vx_load_low(src[k] + i));
+ v_store_low(dst + i, s0);
+ i += vtype::nlanes/2;
+ }
+ return i;
+ }
+};
+
+template <typename T> struct VMin
+{
+ typedef T vtype;
+ vtype operator()(const vtype& a, const vtype& b) const { return v_min(a,b); }
+};
+template <typename T> struct VMax
+{
+ typedef T vtype;
+ vtype operator()(const vtype& a, const vtype& b) const { return v_max(a,b); }
+};
+
+typedef MorphRowVec<VMin<v_uint8> > ErodeRowVec8u;
+typedef MorphRowVec<VMax<v_uint8> > DilateRowVec8u;
+typedef MorphRowVec<VMin<v_uint16> > ErodeRowVec16u;
+typedef MorphRowVec<VMax<v_uint16> > DilateRowVec16u;
+typedef MorphRowVec<VMin<v_int16> > ErodeRowVec16s;
+typedef MorphRowVec<VMax<v_int16> > DilateRowVec16s;
+typedef MorphRowVec<VMin<v_float32> > ErodeRowVec32f;
+typedef MorphRowVec<VMax<v_float32> > DilateRowVec32f;
+
+typedef MorphColumnVec<VMin<v_uint8> > ErodeColumnVec8u;
+typedef MorphColumnVec<VMax<v_uint8> > DilateColumnVec8u;
+typedef MorphColumnVec<VMin<v_uint16> > ErodeColumnVec16u;
+typedef MorphColumnVec<VMax<v_uint16> > DilateColumnVec16u;
+typedef MorphColumnVec<VMin<v_int16> > ErodeColumnVec16s;
+typedef MorphColumnVec<VMax<v_int16> > DilateColumnVec16s;
+typedef MorphColumnVec<VMin<v_float32> > ErodeColumnVec32f;
+typedef MorphColumnVec<VMax<v_float32> > DilateColumnVec32f;
+
+typedef MorphVec<VMin<v_uint8> > ErodeVec8u;
+typedef MorphVec<VMax<v_uint8> > DilateVec8u;
+typedef MorphVec<VMin<v_uint16> > ErodeVec16u;
+typedef MorphVec<VMax<v_uint16> > DilateVec16u;
+typedef MorphVec<VMin<v_int16> > ErodeVec16s;
+typedef MorphVec<VMax<v_int16> > DilateVec16s;
+typedef MorphVec<VMin<v_float32> > ErodeVec32f;
+typedef MorphVec<VMax<v_float32> > DilateVec32f;
+
+#else
+
+typedef MorphRowNoVec ErodeRowVec8u;
+typedef MorphRowNoVec DilateRowVec8u;
+
+typedef MorphColumnNoVec ErodeColumnVec8u;
+typedef MorphColumnNoVec DilateColumnVec8u;
+
+typedef MorphRowNoVec ErodeRowVec16u;
+typedef MorphRowNoVec DilateRowVec16u;
+typedef MorphRowNoVec ErodeRowVec16s;
+typedef MorphRowNoVec DilateRowVec16s;
+typedef MorphRowNoVec ErodeRowVec32f;
+typedef MorphRowNoVec DilateRowVec32f;
+
+typedef MorphColumnNoVec ErodeColumnVec16u;
+typedef MorphColumnNoVec DilateColumnVec16u;
+typedef MorphColumnNoVec ErodeColumnVec16s;
+typedef MorphColumnNoVec DilateColumnVec16s;
+typedef MorphColumnNoVec ErodeColumnVec32f;
+typedef MorphColumnNoVec DilateColumnVec32f;
+
+typedef MorphNoVec ErodeVec8u;
+typedef MorphNoVec DilateVec8u;
+typedef MorphNoVec ErodeVec16u;
+typedef MorphNoVec DilateVec16u;
+typedef MorphNoVec ErodeVec16s;
+typedef MorphNoVec DilateVec16s;
+typedef MorphNoVec ErodeVec32f;
+typedef MorphNoVec DilateVec32f;
+
+#endif
+
+typedef MorphRowNoVec ErodeRowVec64f;
+typedef MorphRowNoVec DilateRowVec64f;
+typedef MorphColumnNoVec ErodeColumnVec64f;
+typedef MorphColumnNoVec DilateColumnVec64f;
+typedef MorphNoVec ErodeVec64f;
+typedef MorphNoVec DilateVec64f;
+
+
+template<class Op, class VecOp> struct MorphRowFilter : public BaseRowFilter
+{
+ typedef typename Op::rtype T;
+
+ MorphRowFilter( int _ksize, int _anchor ) : vecOp(_ksize, _anchor)
+ {
+ ksize = _ksize;
+ anchor = _anchor;
+ }
+
+ void operator()(const uchar* src, uchar* dst, int width, int cn) CV_OVERRIDE
+ {
+ CV_INSTRUMENT_REGION();
+
+ int i, j, k, _ksize = ksize*cn;
+ const T* S = (const T*)src;
+ Op op;
+ T* D = (T*)dst;
+
+ if( _ksize == cn )
+ {
+ for( i = 0; i < width*cn; i++ )
+ D[i] = S[i];
+ return;
+ }
+
+ int i0 = vecOp(src, dst, width, cn);
+ width *= cn;
+
+ for( k = 0; k < cn; k++, S++, D++ )
+ {
+ for( i = i0; i <= width - cn*2; i += cn*2 )
+ {
+ const T* s = S + i;
+ T m = s[cn];
+ for( j = cn*2; j < _ksize; j += cn )
+ m = op(m, s[j]);
+ D[i] = op(m, s[0]);
+ D[i+cn] = op(m, s[j]);
+ }
+
+ for( ; i < width; i += cn )
+ {
+ const T* s = S + i;
+ T m = s[0];
+ for( j = cn; j < _ksize; j += cn )
+ m = op(m, s[j]);
+ D[i] = m;
+ }
+ }
+ }
+
+ VecOp vecOp;
+};
+
+
+template<class Op, class VecOp> struct MorphColumnFilter : public BaseColumnFilter
+{
+ typedef typename Op::rtype T;
+
+ MorphColumnFilter( int _ksize, int _anchor ) : vecOp(_ksize, _anchor)
+ {
+ ksize = _ksize;
+ anchor = _anchor;
+ }
+
+ void operator()(const uchar** _src, uchar* dst, int dststep, int count, int width) CV_OVERRIDE
+ {
+ CV_INSTRUMENT_REGION();
+
+ int i, k, _ksize = ksize;
+ const T** src = (const T**)_src;
+ T* D = (T*)dst;
+ Op op;
+
+ int i0 = vecOp(_src, dst, dststep, count, width);
+ dststep /= sizeof(D[0]);
+
+ for( ; _ksize > 1 && count > 1; count -= 2, D += dststep*2, src += 2 )
+ {
+ i = i0;
+ #if CV_ENABLE_UNROLLED
+ for( ; i <= width - 4; i += 4 )
+ {
+ const T* sptr = src[1] + i;
+ T s0 = sptr[0], s1 = sptr[1], s2 = sptr[2], s3 = sptr[3];
+
+ for( k = 2; k < _ksize; k++ )
+ {
+ sptr = src[k] + i;
+ s0 = op(s0, sptr[0]); s1 = op(s1, sptr[1]);
+ s2 = op(s2, sptr[2]); s3 = op(s3, sptr[3]);
+ }
+
+ sptr = src[0] + i;
+ D[i] = op(s0, sptr[0]);
+ D[i+1] = op(s1, sptr[1]);
+ D[i+2] = op(s2, sptr[2]);
+ D[i+3] = op(s3, sptr[3]);
+
+ sptr = src[k] + i;
+ D[i+dststep] = op(s0, sptr[0]);
+ D[i+dststep+1] = op(s1, sptr[1]);
+ D[i+dststep+2] = op(s2, sptr[2]);
+ D[i+dststep+3] = op(s3, sptr[3]);
+ }
+ #endif
+ for( ; i < width; i++ )
+ {
+ T s0 = src[1][i];
+
+ for( k = 2; k < _ksize; k++ )
+ s0 = op(s0, src[k][i]);
+
+ D[i] = op(s0, src[0][i]);
+ D[i+dststep] = op(s0, src[k][i]);
+ }
+ }
+
+ for( ; count > 0; count--, D += dststep, src++ )
+ {
+ i = i0;
+ #if CV_ENABLE_UNROLLED
+ for( ; i <= width - 4; i += 4 )
+ {
+ const T* sptr = src[0] + i;
+ T s0 = sptr[0], s1 = sptr[1], s2 = sptr[2], s3 = sptr[3];
+
+ for( k = 1; k < _ksize; k++ )
+ {
+ sptr = src[k] + i;
+ s0 = op(s0, sptr[0]); s1 = op(s1, sptr[1]);
+ s2 = op(s2, sptr[2]); s3 = op(s3, sptr[3]);
+ }
+
+ D[i] = s0; D[i+1] = s1;
+ D[i+2] = s2; D[i+3] = s3;
+ }
+ #endif
+ for( ; i < width; i++ )
+ {
+ T s0 = src[0][i];
+ for( k = 1; k < _ksize; k++ )
+ s0 = op(s0, src[k][i]);
+ D[i] = s0;
+ }
+ }
+ }
+
+ VecOp vecOp;
+};
+
+
+template<class Op, class VecOp> struct MorphFilter : BaseFilter
+{
+ typedef typename Op::rtype T;
+
+ MorphFilter( const Mat& _kernel, Point _anchor )
+ {
+ anchor = _anchor;
+ ksize = _kernel.size();
+ CV_Assert( _kernel.type() == CV_8U );
+
+ std::vector<uchar> coeffs; // we do not really the values of non-zero
+ // kernel elements, just their locations
+ preprocess2DKernel( _kernel, coords, coeffs );
+ ptrs.resize( coords.size() );
+ }
+
+ void operator()(const uchar** src, uchar* dst, int dststep, int count, int width, int cn) CV_OVERRIDE
+ {
+ CV_INSTRUMENT_REGION();
+
+ const Point* pt = &coords[0];
+ const T** kp = (const T**)&ptrs[0];
+ int i, k, nz = (int)coords.size();
+ Op op;
+
+ width *= cn;
+ for( ; count > 0; count--, dst += dststep, src++ )
+ {
+ T* D = (T*)dst;
+
+ for( k = 0; k < nz; k++ )
+ kp[k] = (const T*)src[pt[k].y] + pt[k].x*cn;
+
+ i = vecOp(&ptrs[0], nz, dst, width);
+ #if CV_ENABLE_UNROLLED
+ for( ; i <= width - 4; i += 4 )
+ {
+ const T* sptr = kp[0] + i;
+ T s0 = sptr[0], s1 = sptr[1], s2 = sptr[2], s3 = sptr[3];
+
+ for( k = 1; k < nz; k++ )
+ {
+ sptr = kp[k] + i;
+ s0 = op(s0, sptr[0]); s1 = op(s1, sptr[1]);
+ s2 = op(s2, sptr[2]); s3 = op(s3, sptr[3]);
+ }
+
+ D[i] = s0; D[i+1] = s1;
+ D[i+2] = s2; D[i+3] = s3;
+ }
+ #endif
+ for( ; i < width; i++ )
+ {
+ T s0 = kp[0][i];
+ for( k = 1; k < nz; k++ )
+ s0 = op(s0, kp[k][i]);
+ D[i] = s0;
+ }
+ }
+ }
+
+ std::vector<Point> coords;
+ std::vector<uchar*> ptrs;
+ VecOp vecOp;
+};
+
+} // namespace anon
+
+/////////////////////////////////// External Interface /////////////////////////////////////
+
+Ptr<BaseRowFilter> getMorphologyRowFilter(int op, int type, int ksize, int anchor)
+{
+ CV_INSTRUMENT_REGION();
+
+ int depth = CV_MAT_DEPTH(type);
+ if( anchor < 0 )
+ anchor = ksize/2;
+ CV_Assert( op == MORPH_ERODE || op == MORPH_DILATE );
+ if( op == MORPH_ERODE )
+ {
+ if( depth == CV_8U )
+ return makePtr<MorphRowFilter<MinOp<uchar>,
+ ErodeRowVec8u> >(ksize, anchor);
+ if( depth == CV_16U )
+ return makePtr<MorphRowFilter<MinOp<ushort>,
+ ErodeRowVec16u> >(ksize, anchor);
+ if( depth == CV_16S )
+ return makePtr<MorphRowFilter<MinOp<short>,
+ ErodeRowVec16s> >(ksize, anchor);
+ if( depth == CV_32F )
+ return makePtr<MorphRowFilter<MinOp<float>,
+ ErodeRowVec32f> >(ksize, anchor);
+ if( depth == CV_64F )
+ return makePtr<MorphRowFilter<MinOp<double>,
+ ErodeRowVec64f> >(ksize, anchor);
+ }
+ else
+ {
+ if( depth == CV_8U )
+ return makePtr<MorphRowFilter<MaxOp<uchar>,
+ DilateRowVec8u> >(ksize, anchor);
+ if( depth == CV_16U )
+ return makePtr<MorphRowFilter<MaxOp<ushort>,
+ DilateRowVec16u> >(ksize, anchor);
+ if( depth == CV_16S )
+ return makePtr<MorphRowFilter<MaxOp<short>,
+ DilateRowVec16s> >(ksize, anchor);
+ if( depth == CV_32F )
+ return makePtr<MorphRowFilter<MaxOp<float>,
+ DilateRowVec32f> >(ksize, anchor);
+ if( depth == CV_64F )
+ return makePtr<MorphRowFilter<MaxOp<double>,
+ DilateRowVec64f> >(ksize, anchor);
+ }
+
+ CV_Error_( CV_StsNotImplemented, ("Unsupported data type (=%d)", type));
+}
+
+Ptr<BaseColumnFilter> getMorphologyColumnFilter(int op, int type, int ksize, int anchor)
+{
+ CV_INSTRUMENT_REGION();
+
+ int depth = CV_MAT_DEPTH(type);
+ if( anchor < 0 )
+ anchor = ksize/2;
+ CV_Assert( op == MORPH_ERODE || op == MORPH_DILATE );
+ if( op == MORPH_ERODE )
+ {
+ if( depth == CV_8U )
+ return makePtr<MorphColumnFilter<MinOp<uchar>,
+ ErodeColumnVec8u> >(ksize, anchor);
+ if( depth == CV_16U )
+ return makePtr<MorphColumnFilter<MinOp<ushort>,
+ ErodeColumnVec16u> >(ksize, anchor);
+ if( depth == CV_16S )
+ return makePtr<MorphColumnFilter<MinOp<short>,
+ ErodeColumnVec16s> >(ksize, anchor);
+ if( depth == CV_32F )
+ return makePtr<MorphColumnFilter<MinOp<float>,
+ ErodeColumnVec32f> >(ksize, anchor);
+ if( depth == CV_64F )
+ return makePtr<MorphColumnFilter<MinOp<double>,
+ ErodeColumnVec64f> >(ksize, anchor);
+ }
+ else
+ {
+ if( depth == CV_8U )
+ return makePtr<MorphColumnFilter<MaxOp<uchar>,
+ DilateColumnVec8u> >(ksize, anchor);
+ if( depth == CV_16U )
+ return makePtr<MorphColumnFilter<MaxOp<ushort>,
+ DilateColumnVec16u> >(ksize, anchor);
+ if( depth == CV_16S )
+ return makePtr<MorphColumnFilter<MaxOp<short>,
+ DilateColumnVec16s> >(ksize, anchor);
+ if( depth == CV_32F )
+ return makePtr<MorphColumnFilter<MaxOp<float>,
+ DilateColumnVec32f> >(ksize, anchor);
+ if( depth == CV_64F )
+ return makePtr<MorphColumnFilter<MaxOp<double>,
+ DilateColumnVec64f> >(ksize, anchor);
+ }
+
+ CV_Error_( CV_StsNotImplemented, ("Unsupported data type (=%d)", type));
+}
+
+Ptr<BaseFilter> getMorphologyFilter(int op, int type, const Mat& kernel, Point anchor)
+{
+ CV_INSTRUMENT_REGION();
+
+ int depth = CV_MAT_DEPTH(type);
+ anchor = normalizeAnchor(anchor, kernel.size());
+ CV_Assert( op == MORPH_ERODE || op == MORPH_DILATE );
+ if( op == MORPH_ERODE )
+ {
+ if( depth == CV_8U )
+ return makePtr<MorphFilter<MinOp<uchar>, ErodeVec8u> >(kernel, anchor);
+ if( depth == CV_16U )
+ return makePtr<MorphFilter<MinOp<ushort>, ErodeVec16u> >(kernel, anchor);
+ if( depth == CV_16S )
+ return makePtr<MorphFilter<MinOp<short>, ErodeVec16s> >(kernel, anchor);
+ if( depth == CV_32F )
+ return makePtr<MorphFilter<MinOp<float>, ErodeVec32f> >(kernel, anchor);
+ if( depth == CV_64F )
+ return makePtr<MorphFilter<MinOp<double>, ErodeVec64f> >(kernel, anchor);
+ }
+ else
+ {
+ if( depth == CV_8U )
+ return makePtr<MorphFilter<MaxOp<uchar>, DilateVec8u> >(kernel, anchor);
+ if( depth == CV_16U )
+ return makePtr<MorphFilter<MaxOp<ushort>, DilateVec16u> >(kernel, anchor);
+ if( depth == CV_16S )
+ return makePtr<MorphFilter<MaxOp<short>, DilateVec16s> >(kernel, anchor);
+ if( depth == CV_32F )
+ return makePtr<MorphFilter<MaxOp<float>, DilateVec32f> >(kernel, anchor);
+ if( depth == CV_64F )
+ return makePtr<MorphFilter<MaxOp<double>, DilateVec64f> >(kernel, anchor);
+ }
+
+ CV_Error_( CV_StsNotImplemented, ("Unsupported data type (=%d)", type));
+}
+
+#endif
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+} // namespace
rtype operator ()(type1 arg) const { return arg*(T)(1./(1 << shift)); }
};
-template<typename T1, typename T2> struct PyrDownNoVec
+template<typename T1, typename T2, int cn> int PyrDownVecH(const T1*, T2*, int)
{
- int operator()(T1**, T2*, int, int) const { return 0; }
-};
+ // row[x ] = src[x * 2 + 2*cn ] * 6 + (src[x * 2 + cn ] + src[x * 2 + 3*cn ]) * 4 + src[x * 2 ] + src[x * 2 + 4*cn ];
+ // row[x + 1] = src[x * 2 + 2*cn+1] * 6 + (src[x * 2 + cn+1] + src[x * 2 + 3*cn+1]) * 4 + src[x * 2 + 1] + src[x * 2 + 4*cn+1];
+ // ....
+ // row[x + cn-1] = src[x * 2 + 3*cn-1] * 6 + (src[x * 2 + 2*cn-1] + src[x * 2 + 4*cn-1]) * 4 + src[x * 2 + cn-1] + src[x * 2 + 5*cn-1];
+ return 0;
+}
-template<typename T1, typename T2> struct PyrUpNoVec
+template<typename T1, typename T2, int cn> int PyrUpVecH(const T1*, T2*, int)
{
- int operator()(T1**, T2**, int, int) const { return 0; }
-};
+ return 0;
+}
+
+template<typename T1, typename T2> int PyrDownVecV(T1**, T2*, int) { return 0; }
+
+template<typename T1, typename T2> int PyrUpVecV(T1**, T2**, int) { return 0; }
#if CV_SIMD
-struct PyrDownVec_32s8u
+template<> int PyrDownVecH<uchar, int, 1>(const uchar* src, int* row, int width)
{
- int operator()(int** src, uchar* dst, int, int width) const
+ int x = 0;
+ const uchar *src0 = src, *src2 = src + 2, *src4 = src + 3;
+
+ v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
+ v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
+ for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src0 += v_int16::nlanes, src2 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
+ v_store(row, v_dotprod(v_reinterpret_as_s16(vx_load_expand(src0)), v_1_4) +
+ v_dotprod(v_reinterpret_as_s16(vx_load_expand(src2)), v_6_4) +
+ (v_reinterpret_as_s32(vx_load_expand(src4)) >> 16));
+ vx_cleanup();
+
+ return x;
+}
+template<> int PyrDownVecH<uchar, int, 2>(const uchar* src, int* row, int width)
+{
+ int x = 0;
+ const uchar *src0 = src, *src2 = src + 4, *src4 = src + 6;
+
+ v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
+ v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
+ for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src0 += v_int16::nlanes, src2 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
+ v_store(row, v_dotprod(v_interleave_pairs(v_reinterpret_as_s16(vx_load_expand(src0))), v_1_4) +
+ v_dotprod(v_interleave_pairs(v_reinterpret_as_s16(vx_load_expand(src2))), v_6_4) +
+ (v_reinterpret_as_s32(v_interleave_pairs(vx_load_expand(src4))) >> 16));
+ vx_cleanup();
+
+ return x;
+}
+template<> int PyrDownVecH<uchar, int, 3>(const uchar* src, int* row, int width)
+{
+ int idx[v_int8::nlanes/2 + 4];
+ for (int i = 0; i < v_int8::nlanes/4 + 2; i++)
{
- int x = 0;
- const int *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
-
- for( ; x <= width - v_uint8::nlanes; x += v_uint8::nlanes )
- {
- v_uint16 r0, r1, r2, r3, r4, t0, t1;
- r0 = v_reinterpret_as_u16(v_pack(vx_load(row0 + x), vx_load(row0 + x + v_int32::nlanes)));
- r1 = v_reinterpret_as_u16(v_pack(vx_load(row1 + x), vx_load(row1 + x + v_int32::nlanes)));
- r2 = v_reinterpret_as_u16(v_pack(vx_load(row2 + x), vx_load(row2 + x + v_int32::nlanes)));
- r3 = v_reinterpret_as_u16(v_pack(vx_load(row3 + x), vx_load(row3 + x + v_int32::nlanes)));
- r4 = v_reinterpret_as_u16(v_pack(vx_load(row4 + x), vx_load(row4 + x + v_int32::nlanes)));
- t0 = r0 + r4 + (r2 + r2) + ((r1 + r3 + r2) << 2);
- r0 = v_reinterpret_as_u16(v_pack(vx_load(row0 + x + 2*v_int32::nlanes), vx_load(row0 + x + 3*v_int32::nlanes)));
- r1 = v_reinterpret_as_u16(v_pack(vx_load(row1 + x + 2*v_int32::nlanes), vx_load(row1 + x + 3*v_int32::nlanes)));
- r2 = v_reinterpret_as_u16(v_pack(vx_load(row2 + x + 2*v_int32::nlanes), vx_load(row2 + x + 3*v_int32::nlanes)));
- r3 = v_reinterpret_as_u16(v_pack(vx_load(row3 + x + 2*v_int32::nlanes), vx_load(row3 + x + 3*v_int32::nlanes)));
- r4 = v_reinterpret_as_u16(v_pack(vx_load(row4 + x + 2*v_int32::nlanes), vx_load(row4 + x + 3*v_int32::nlanes)));
- t1 = r0 + r4 + (r2 + r2) + ((r1 + r3 + r2) << 2);
- v_store(dst + x, v_rshr_pack<8>(t0, t1));
- }
- if (x <= width - v_int16::nlanes)
- {
- v_uint16 r0, r1, r2, r3, r4, t0;
- r0 = v_reinterpret_as_u16(v_pack(vx_load(row0 + x), vx_load(row0 + x + v_int32::nlanes)));
- r1 = v_reinterpret_as_u16(v_pack(vx_load(row1 + x), vx_load(row1 + x + v_int32::nlanes)));
- r2 = v_reinterpret_as_u16(v_pack(vx_load(row2 + x), vx_load(row2 + x + v_int32::nlanes)));
- r3 = v_reinterpret_as_u16(v_pack(vx_load(row3 + x), vx_load(row3 + x + v_int32::nlanes)));
- r4 = v_reinterpret_as_u16(v_pack(vx_load(row4 + x), vx_load(row4 + x + v_int32::nlanes)));
- t0 = r0 + r4 + (r2 + r2) + ((r1 + r3 + r2) << 2);
- v_rshr_pack_store<8>(dst + x, t0);
- x += v_uint16::nlanes;
- }
- typedef int CV_DECL_ALIGNED(1) unaligned_int;
- for ( ; x <= width - v_int32x4::nlanes; x += v_int32x4::nlanes)
- {
- v_int32x4 r0, r1, r2, r3, r4, t0;
- r0 = v_load(row0 + x);
- r1 = v_load(row1 + x);
- r2 = v_load(row2 + x);
- r3 = v_load(row3 + x);
- r4 = v_load(row4 + x);
- t0 = r0 + r4 + (r2 + r2) + ((r1 + r3 + r2) << 2);
-
- *((unaligned_int*) (dst + x)) = v_reinterpret_as_s32(v_rshr_pack<8>(v_pack_u(t0, t0), v_setzero_u16())).get0();
- }
+ idx[i] = 6*i;
+ idx[i + v_int8::nlanes/4 + 2] = 6*i + 3;
+ }
- return x;
+ int x = 0;
+ v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
+ for (; x <= width - v_int8::nlanes; x += 3*v_int8::nlanes/4, src += 6*v_int8::nlanes/4, row += 3*v_int8::nlanes/4)
+ {
+ v_uint16 r0l, r0h, r1l, r1h, r2l, r2h, r3l, r3h, r4l, r4h;
+ v_expand(vx_lut_quads(src, idx ), r0l, r0h);
+ v_expand(vx_lut_quads(src, idx + v_int8::nlanes/4 + 2), r1l, r1h);
+ v_expand(vx_lut_quads(src, idx + 1 ), r2l, r2h);
+ v_expand(vx_lut_quads(src, idx + v_int8::nlanes/4 + 3), r3l, r3h);
+ v_expand(vx_lut_quads(src, idx + 2 ), r4l, r4h);
+
+ v_zip(r2l, r1l + r3l, r1l, r3l);
+ v_zip(r2h, r1h + r3h, r1h, r3h);
+ r0l += r4l; r0h += r4h;
+
+ v_store(row , v_pack_triplets(v_dotprod(v_reinterpret_as_s16(r1l), v_6_4) + v_reinterpret_as_s32(v_expand_low( r0l))));
+ v_store(row + 3*v_int32::nlanes/4, v_pack_triplets(v_dotprod(v_reinterpret_as_s16(r3l), v_6_4) + v_reinterpret_as_s32(v_expand_high(r0l))));
+ v_store(row + 6*v_int32::nlanes/4, v_pack_triplets(v_dotprod(v_reinterpret_as_s16(r1h), v_6_4) + v_reinterpret_as_s32(v_expand_low( r0h))));
+ v_store(row + 9*v_int32::nlanes/4, v_pack_triplets(v_dotprod(v_reinterpret_as_s16(r3h), v_6_4) + v_reinterpret_as_s32(v_expand_high(r0h))));
}
-};
+ vx_cleanup();
-struct PyrDownVec_32f
+ return x;
+}
+template<> int PyrDownVecH<uchar, int, 4>(const uchar* src, int* row, int width)
{
- int operator()(float** src, float* dst, int, int width) const
+ int x = 0;
+ const uchar *src0 = src, *src2 = src + 8, *src4 = src + 12;
+
+ v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
+ v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
+ for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src0 += v_int16::nlanes, src2 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
+ v_store(row, v_dotprod(v_interleave_quads(v_reinterpret_as_s16(vx_load_expand(src0))), v_1_4) +
+ v_dotprod(v_interleave_quads(v_reinterpret_as_s16(vx_load_expand(src2))), v_6_4) +
+ (v_reinterpret_as_s32(v_interleave_quads(vx_load_expand(src4))) >> 16));
+ vx_cleanup();
+
+ return x;
+}
+
+template<> int PyrDownVecH<short, int, 1>(const short* src, int* row, int width)
+{
+ int x = 0;
+ const short *src0 = src, *src2 = src + 2, *src4 = src + 3;
+
+ v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
+ v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
+ for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src0 += v_int16::nlanes, src2 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
+ v_store(row, v_dotprod(vx_load(src0), v_1_4) +
+ v_dotprod(vx_load(src2), v_6_4) +
+ (v_reinterpret_as_s32(vx_load(src4)) >> 16));
+ vx_cleanup();
+
+ return x;
+}
+template<> int PyrDownVecH<short, int, 2>(const short* src, int* row, int width)
+{
+ int x = 0;
+ const short *src0 = src, *src2 = src + 4, *src4 = src + 6;
+
+ v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
+ v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
+ for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src0 += v_int16::nlanes, src2 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
+ v_store(row, v_dotprod(v_interleave_pairs(vx_load(src0)), v_1_4) +
+ v_dotprod(v_interleave_pairs(vx_load(src2)), v_6_4) +
+ (v_reinterpret_as_s32(v_interleave_pairs(vx_load(src4))) >> 16));
+ vx_cleanup();
+
+ return x;
+}
+template<> int PyrDownVecH<short, int, 3>(const short* src, int* row, int width)
+{
+ int idx[v_int16::nlanes/2 + 4];
+ for (int i = 0; i < v_int16::nlanes/4 + 2; i++)
{
- int x = 0;
- const float *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
+ idx[i] = 6*i;
+ idx[i + v_int16::nlanes/4 + 2] = 6*i + 3;
+ }
- v_float32 _4 = vx_setall_f32(4.f), _scale = vx_setall_f32(1.f/256);
- for( ; x <= width - v_float32::nlanes; x += v_float32::nlanes)
- {
- v_float32 r0, r1, r2, r3, r4;
- r0 = vx_load(row0 + x);
- r1 = vx_load(row1 + x);
- r2 = vx_load(row2 + x);
- r3 = vx_load(row3 + x);
- r4 = vx_load(row4 + x);
- v_store(dst + x, v_muladd(r1 + r3 + r2, _4, r0 + r4 + (r2 + r2)) * _scale);
- }
+ int x = 0;
+ v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
+ v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
+ for (; x <= width - v_int16::nlanes; x += 3*v_int16::nlanes/4, src += 6*v_int16::nlanes/4, row += 3*v_int16::nlanes/4)
+ {
+ v_int16 r0, r1, r2, r3, r4;
+ v_zip(vx_lut_quads(src, idx), vx_lut_quads(src, idx + v_int16::nlanes/4 + 2), r0, r1);
+ v_zip(vx_lut_quads(src, idx + 1), vx_lut_quads(src, idx + v_int16::nlanes/4 + 3), r2, r3);
+ r4 = vx_lut_quads(src, idx + 2);
+ v_store(row, v_pack_triplets(v_dotprod(r0, v_1_4) + v_dotprod(r2, v_6_4) + v_expand_low(r4)));
+ v_store(row + 3*v_int32::nlanes/4, v_pack_triplets(v_dotprod(r1, v_1_4) + v_dotprod(r3, v_6_4) + v_expand_high(r4)));
+ }
+ vx_cleanup();
+
+ return x;
+}
+template<> int PyrDownVecH<short, int, 4>(const short* src, int* row, int width)
+{
+ int idx[v_int16::nlanes/2 + 4];
+ for (int i = 0; i < v_int16::nlanes/4 + 2; i++)
+ {
+ idx[i] = 8*i;
+ idx[i + v_int16::nlanes/4 + 2] = 8*i + 4;
+ }
- return x;
+ int x = 0;
+ v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
+ v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
+ for (; x <= width - v_int16::nlanes; x += v_int16::nlanes, src += 2*v_int16::nlanes, row += v_int16::nlanes)
+ {
+ v_int16 r0, r1, r2, r3, r4;
+ v_zip(vx_lut_quads(src, idx), vx_lut_quads(src, idx + v_int16::nlanes/4 + 2), r0, r1);
+ v_zip(vx_lut_quads(src, idx + 1), vx_lut_quads(src, idx + v_int16::nlanes/4 + 3), r2, r3);
+ r4 = vx_lut_quads(src, idx + 2);
+ v_store(row, v_dotprod(r0, v_1_4) + v_dotprod(r2, v_6_4) + v_expand_low(r4));
+ v_store(row + v_int32::nlanes, v_dotprod(r1, v_1_4) + v_dotprod(r3, v_6_4) + v_expand_high(r4));
}
-};
+ vx_cleanup();
-#if CV_SSE4_1 || CV_NEON || CV_VSX
+ return x;
+}
-struct PyrDownVec_32s16u
+template<> int PyrDownVecH<ushort, int, 1>(const ushort* src, int* row, int width)
+{
+ int x = 0;
+ const ushort *src0 = src, *src2 = src + 2, *src4 = src + 3;
+
+ v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
+ v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
+ v_uint16 v_half = vx_setall_u16(0x8000);
+ v_int32 v_half15 = vx_setall_s32(0x00078000);
+ for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src0 += v_int16::nlanes, src2 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
+ v_store(row, v_dotprod(v_reinterpret_as_s16(v_sub_wrap(vx_load(src0), v_half)), v_1_4) +
+ v_dotprod(v_reinterpret_as_s16(v_sub_wrap(vx_load(src2), v_half)), v_6_4) +
+ v_reinterpret_as_s32(v_reinterpret_as_u32(vx_load(src4)) >> 16) + v_half15);
+ vx_cleanup();
+
+ return x;
+}
+template<> int PyrDownVecH<ushort, int, 2>(const ushort* src, int* row, int width)
+{
+ int x = 0;
+ const ushort *src0 = src, *src2 = src + 4, *src4 = src + 6;
+
+ v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
+ v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
+ v_uint16 v_half = vx_setall_u16(0x8000);
+ v_int32 v_half15 = vx_setall_s32(0x00078000);
+ for (; x <= width - v_int32::nlanes; x += v_int32::nlanes, src0 += v_int16::nlanes, src2 += v_int16::nlanes, src4 += v_int16::nlanes, row += v_int32::nlanes)
+ v_store(row, v_dotprod(v_interleave_pairs(v_reinterpret_as_s16(v_sub_wrap(vx_load(src0), v_half))), v_1_4) +
+ v_dotprod(v_interleave_pairs(v_reinterpret_as_s16(v_sub_wrap(vx_load(src2), v_half))), v_6_4) +
+ v_reinterpret_as_s32(v_reinterpret_as_u32(v_interleave_pairs(vx_load(src4))) >> 16) + v_half15);
+ vx_cleanup();
+
+ return x;
+}
+template<> int PyrDownVecH<ushort, int, 3>(const ushort* src, int* row, int width)
{
- int operator()(int** src, ushort* dst, int, int width) const
+ int idx[v_int16::nlanes/2 + 4];
+ for (int i = 0; i < v_int16::nlanes/4 + 2; i++)
{
- int x = 0;
- const int *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
+ idx[i] = 6*i;
+ idx[i + v_int16::nlanes/4 + 2] = 6*i + 3;
+ }
- for( ; x <= width - v_uint16::nlanes; x += v_uint16::nlanes)
- {
- v_int32 r00 = vx_load(row0 + x),
- r01 = vx_load(row0 + x + v_int32::nlanes),
- r10 = vx_load(row1 + x),
- r11 = vx_load(row1 + x + v_int32::nlanes),
- r20 = vx_load(row2 + x),
- r21 = vx_load(row2 + x + v_int32::nlanes),
- r30 = vx_load(row3 + x),
- r31 = vx_load(row3 + x + v_int32::nlanes),
- r40 = vx_load(row4 + x),
- r41 = vx_load(row4 + x + v_int32::nlanes);
- v_store(dst + x, v_rshr_pack_u<8>(r00 + r40 + (r20 + r20) + ((r10 + r20 + r30) << 2),
- r01 + r41 + (r21 + r21) + ((r11 + r21 + r31) << 2)));
- }
- if (x <= width - v_int32::nlanes)
- {
- v_int32 r00 = vx_load(row0 + x),
- r10 = vx_load(row1 + x),
- r20 = vx_load(row2 + x),
- r30 = vx_load(row3 + x),
- r40 = vx_load(row4 + x);
- v_rshr_pack_u_store<8>(dst + x, r00 + r40 + (r20 + r20) + ((r10 + r20 + r30) << 2));
- x += v_int32::nlanes;
- }
+ int x = 0;
+ v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
+ v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
+ v_uint16 v_half = vx_setall_u16(0x8000);
+ v_int32 v_half15 = vx_setall_s32(0x00078000);
+ for (; x <= width - v_int16::nlanes; x += 3*v_int16::nlanes/4, src += 6*v_int16::nlanes/4, row += 3*v_int16::nlanes/4)
+ {
+ v_uint16 r0, r1, r2, r3, r4;
+ v_zip(vx_lut_quads(src, idx), vx_lut_quads(src, idx + v_int16::nlanes/4 + 2), r0, r1);
+ v_zip(vx_lut_quads(src, idx + 1), vx_lut_quads(src, idx + v_int16::nlanes/4 + 3), r2, r3);
+ r4 = vx_lut_quads(src, idx + 2);
+ v_store(row , v_pack_triplets(v_dotprod(v_reinterpret_as_s16(v_sub_wrap(r0, v_half)), v_1_4) +
+ v_dotprod(v_reinterpret_as_s16(v_sub_wrap(r2, v_half)), v_6_4) +
+ v_reinterpret_as_s32(v_expand_low(r4)) + v_half15));
+ v_store(row + 3*v_int32::nlanes/4, v_pack_triplets(v_dotprod(v_reinterpret_as_s16(v_sub_wrap(r1, v_half)), v_1_4) +
+ v_dotprod(v_reinterpret_as_s16(v_sub_wrap(r3, v_half)), v_6_4) +
+ v_reinterpret_as_s32(v_expand_high(r4)) + v_half15));
+ }
+ vx_cleanup();
- return x;
+ return x;
+}
+template<> int PyrDownVecH<ushort, int, 4>(const ushort* src, int* row, int width)
+{
+ int idx[v_int16::nlanes/2 + 4];
+ for (int i = 0; i < v_int16::nlanes/4 + 2; i++)
+ {
+ idx[i] = 8*i;
+ idx[i + v_int16::nlanes/4 + 2] = 8*i + 4;
}
-};
-#else
+ int x = 0;
+ v_int16 v_1_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040001));
+ v_int16 v_6_4 = v_reinterpret_as_s16(vx_setall_u32(0x00040006));
+ v_uint16 v_half = vx_setall_u16(0x8000);
+ v_int32 v_half15 = vx_setall_s32(0x00078000);
+ for (; x <= width - v_int16::nlanes; x += v_int16::nlanes, src += 2*v_int16::nlanes, row += v_int16::nlanes)
+ {
+ v_uint16 r0, r1, r2, r3, r4;
+ v_zip(vx_lut_quads(src, idx), vx_lut_quads(src, idx + v_int16::nlanes/4 + 2), r0, r1);
+ v_zip(vx_lut_quads(src, idx + 1), vx_lut_quads(src, idx + v_int16::nlanes/4 + 3), r2, r3);
+ r4 = vx_lut_quads(src, idx + 2);
+ v_store(row , v_dotprod(v_reinterpret_as_s16(v_sub_wrap(r0, v_half)), v_1_4) +
+ v_dotprod(v_reinterpret_as_s16(v_sub_wrap(r2, v_half)), v_6_4) +
+ v_reinterpret_as_s32(v_expand_low(r4)) + v_half15);
+ v_store(row + v_int32::nlanes, v_dotprod(v_reinterpret_as_s16(v_sub_wrap(r1, v_half)), v_1_4) +
+ v_dotprod(v_reinterpret_as_s16(v_sub_wrap(r3, v_half)), v_6_4) +
+ v_reinterpret_as_s32(v_expand_high(r4)) + v_half15);
+ }
+ vx_cleanup();
-typedef PyrDownNoVec<int, ushort> PyrDownVec_32s16u;
+ return x;
+}
-#endif
+template<> int PyrDownVecH<float, float, 1>(const float* src, float* row, int width)
+{
+ int x = 0;
+ const float *src0 = src, *src2 = src + 2, *src4 = src + 4;
-struct PyrDownVec_32s16s
+ v_float32 _4 = vx_setall_f32(4.f), _6 = vx_setall_f32(6.f);
+ for (; x <= width - v_float32::nlanes; x += v_float32::nlanes, src0 += 2*v_float32::nlanes, src2 += 2*v_float32::nlanes, src4 += 2*v_float32::nlanes, row+=v_float32::nlanes)
+ {
+ v_float32 r0, r1, r2, r3, r4, rtmp;
+ v_load_deinterleave(src0, r0, r1);
+ v_load_deinterleave(src2, r2, r3);
+ v_load_deinterleave(src4, r4, rtmp);
+ v_store(row, v_muladd(r2, _6, v_muladd(r1 + r3, _4, r0 + r4)));
+ }
+ vx_cleanup();
+
+ return x;
+}
+template<> int PyrDownVecH<float, float, 2>(const float* src, float* row, int width)
{
- int operator()(int** src, short* dst, int, int width) const
+ int x = 0;
+ const float *src0 = src, *src2 = src + 4, *src4 = src + 6;
+
+ v_float32 _4 = vx_setall_f32(4.f), _6 = vx_setall_f32(6.f);
+ for (; x <= width - 2*v_float32::nlanes; x += 2*v_float32::nlanes, src0 += 4*v_float32::nlanes, src2 += 4*v_float32::nlanes, src4 += 4*v_float32::nlanes, row += 2*v_float32::nlanes)
{
- int x = 0;
- const int *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
+ v_float32 r0a, r0b, r1a, r1b, r2a, r2b, r3a, r3b, r4a, r4b, rtmpa, rtmpb;
+ v_load_deinterleave(src0, r0a, r0b, r1a, r1b);
+ v_load_deinterleave(src2, r2a, r2b, r3a, r3b);
+ v_load_deinterleave(src4, rtmpa, rtmpb, r4a, r4b);
+ v_store_interleave(row, v_muladd(r2a, _6, v_muladd(r1a + r3a, _4, r0a + r4a)), v_muladd(r2b, _6, v_muladd(r1b + r3b, _4, r0b + r4b)));
+ }
+ vx_cleanup();
- for( ; x <= width - v_int16::nlanes; x += v_int16::nlanes)
- {
- v_int32 r00 = vx_load(row0 + x),
- r01 = vx_load(row0 + x + v_int32::nlanes),
- r10 = vx_load(row1 + x),
- r11 = vx_load(row1 + x + v_int32::nlanes),
- r20 = vx_load(row2 + x),
- r21 = vx_load(row2 + x + v_int32::nlanes),
- r30 = vx_load(row3 + x),
- r31 = vx_load(row3 + x + v_int32::nlanes),
- r40 = vx_load(row4 + x),
- r41 = vx_load(row4 + x + v_int32::nlanes);
- v_store(dst + x, v_rshr_pack<8>(r00 + r40 + (r20 + r20) + ((r10 + r20 + r30) << 2),
- r01 + r41 + (r21 + r21) + ((r11 + r21 + r31) << 2)));
- }
- if (x <= width - v_int32::nlanes)
- {
- v_int32 r00 = vx_load(row0 + x),
- r10 = vx_load(row1 + x),
- r20 = vx_load(row2 + x),
- r30 = vx_load(row3 + x),
- r40 = vx_load(row4 + x);
- v_rshr_pack_store<8>(dst + x, r00 + r40 + (r20 + r20) + ((r10 + r20 + r30) << 2));
- x += v_int32::nlanes;
- }
+ return x;
+}
+template<> int PyrDownVecH<float, float, 3>(const float* src, float* row, int width)
+{
+ int idx[v_float32::nlanes/2 + 4];
+ for (int i = 0; i < v_float32::nlanes/4 + 2; i++)
+ {
+ idx[i] = 6*i;
+ idx[i + v_float32::nlanes/4 + 2] = 6*i + 3;
+ }
- return x;
+ int x = 0;
+ v_float32 _4 = vx_setall_f32(4.f), _6 = vx_setall_f32(6.f);
+ for (; x <= width - v_float32::nlanes; x += 3*v_float32::nlanes/4, src += 6*v_float32::nlanes/4, row += 3*v_float32::nlanes/4)
+ {
+ v_float32 r0 = vx_lut_quads(src, idx);
+ v_float32 r1 = vx_lut_quads(src, idx + v_float32::nlanes/4 + 2);
+ v_float32 r2 = vx_lut_quads(src, idx + 1);
+ v_float32 r3 = vx_lut_quads(src, idx + v_float32::nlanes/4 + 3);
+ v_float32 r4 = vx_lut_quads(src, idx + 2);
+ v_store(row, v_pack_triplets(v_muladd(r2, _6, v_muladd(r1 + r3, _4, r0 + r4))));
}
-};
+ vx_cleanup();
-struct PyrUpVec_32s8u
+ return x;
+}
+template<> int PyrDownVecH<float, float, 4>(const float* src, float* row, int width)
{
- int operator()(int** src, uchar** dst, int, int width) const
+ int idx[v_float32::nlanes/2 + 4];
+ for (int i = 0; i < v_float32::nlanes/4 + 2; i++)
{
- int x = 0;
- uchar *dst0 = dst[0], *dst1 = dst[1];
- const int *row0 = src[0], *row1 = src[1], *row2 = src[2];
+ idx[i] = 8*i;
+ idx[i + v_float32::nlanes/4 + 2] = 8*i + 4;
+ }
- for( ; x <= width - v_uint8::nlanes; x += v_uint8::nlanes)
- {
- v_int16 v_r00 = v_pack(vx_load(row0 + x), vx_load(row0 + x + v_int32::nlanes)),
- v_r01 = v_pack(vx_load(row0 + x + 2 * v_int32::nlanes), vx_load(row0 + x + 3 * v_int32::nlanes)),
- v_r10 = v_pack(vx_load(row1 + x), vx_load(row1 + x + v_int32::nlanes)),
- v_r11 = v_pack(vx_load(row1 + x + 2 * v_int32::nlanes), vx_load(row1 + x + 3 * v_int32::nlanes)),
- v_r20 = v_pack(vx_load(row2 + x), vx_load(row2 + x + v_int32::nlanes)),
- v_r21 = v_pack(vx_load(row2 + x + 2 * v_int32::nlanes), vx_load(row2 + x + 3 * v_int32::nlanes));
- v_int16 v_2r10 = v_r10 + v_r10, v_2r11 = (v_r11 + v_r11);
- v_store(dst0 + x, v_rshr_pack_u<6>(v_r00 + v_r20 + (v_2r10 + v_2r10 + v_2r10), v_r01 + v_r21 + (v_2r11 + v_2r11 + v_2r11)));
- v_store(dst1 + x, v_rshr_pack_u<6>((v_r10 + v_r20) << 2, (v_r11 + v_r21) << 2));
- }
- if(x <= width - v_uint16::nlanes)
- {
- v_int16 v_r00 = v_pack(vx_load(row0 + x), vx_load(row0 + x + v_int32::nlanes)),
- v_r10 = v_pack(vx_load(row1 + x), vx_load(row1 + x + v_int32::nlanes)),
- v_r20 = v_pack(vx_load(row2 + x), vx_load(row2 + x + v_int32::nlanes));
- v_int16 v_2r10 = v_r10 + v_r10;
- v_rshr_pack_u_store<6>(dst0 + x, v_r00 + v_r20 + (v_2r10 + v_2r10 + v_2r10));
- v_rshr_pack_u_store<6>(dst1 + x, (v_r10 + v_r20) << 2);
- x += v_uint16::nlanes;
- }
- for (; x <= width - v_int32x4::nlanes; x += v_int32x4::nlanes)
- {
- v_int32 v_r00 = vx_load(row0 + x),
- v_r10 = vx_load(row1 + x),
- v_r20 = vx_load(row2 + x);
- v_int32 v_2r10 = v_r10 + v_r10;
- v_int16 d = v_pack(v_r00 + v_r20 + (v_2r10 + v_2r10 + v_2r10), (v_r10 + v_r20) << 2);
- *(int*)(dst0 + x) = v_reinterpret_as_s32(v_rshr_pack_u<6>(d, vx_setzero_s16())).get0();
- *(int*)(dst1 + x) = v_reinterpret_as_s32(v_rshr_pack_u<6>(v_combine_high(d, d), vx_setzero_s16())).get0();
- }
+ int x = 0;
+ v_float32 _4 = vx_setall_f32(4.f), _6 = vx_setall_f32(6.f);
+ for (; x <= width - v_float32::nlanes; x += v_float32::nlanes, src += 2*v_float32::nlanes, row += v_float32::nlanes)
+ {
+ v_float32 r0 = vx_lut_quads(src, idx);
+ v_float32 r1 = vx_lut_quads(src, idx + v_float32::nlanes/4 + 2);
+ v_float32 r2 = vx_lut_quads(src, idx + 1);
+ v_float32 r3 = vx_lut_quads(src, idx + v_float32::nlanes/4 + 3);
+ v_float32 r4 = vx_lut_quads(src, idx + 2);
+ v_store(row, v_muladd(r2, _6, v_muladd(r1 + r3, _4, r0 + r4)));
+ }
+ vx_cleanup();
+
+ return x;
+}
+
+#if CV_SIMD_64F
+template<> int PyrDownVecH<double, double, 1>(const double* src, double* row, int width)
+{
+ int x = 0;
+ const double *src0 = src, *src2 = src + 2, *src4 = src + 4;
- return x;
+ v_float64 _4 = vx_setall_f64(4.f), _6 = vx_setall_f64(6.f);
+ for (; x <= width - v_float64::nlanes; x += v_float64::nlanes, src0 += 2*v_float64::nlanes, src2 += 2*v_float64::nlanes, src4 += 2*v_float64::nlanes, row += v_float64::nlanes)
+ {
+ v_float64 r0, r1, r2, r3, r4, rtmp;
+ v_load_deinterleave(src0, r0, r1);
+ v_load_deinterleave(src2, r2, r3);
+ v_load_deinterleave(src4, r4, rtmp);
+ v_store(row, v_muladd(r2, _6, v_muladd(r1 + r3, _4, r0 + r4)));
}
-};
+ vx_cleanup();
+
+ return x;
+}
+#endif
-struct PyrUpVec_32s16s
+template<> int PyrDownVecV<int, uchar>(int** src, uchar* dst, int width)
{
- int operator()(int** src, short** dst, int, int width) const
+ int x = 0;
+ const int *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
+
+ for( ; x <= width - v_uint8::nlanes; x += v_uint8::nlanes )
+ {
+ v_uint16 r0, r1, r2, r3, r4, t0, t1;
+ r0 = v_reinterpret_as_u16(v_pack(vx_load(row0 + x), vx_load(row0 + x + v_int32::nlanes)));
+ r1 = v_reinterpret_as_u16(v_pack(vx_load(row1 + x), vx_load(row1 + x + v_int32::nlanes)));
+ r2 = v_reinterpret_as_u16(v_pack(vx_load(row2 + x), vx_load(row2 + x + v_int32::nlanes)));
+ r3 = v_reinterpret_as_u16(v_pack(vx_load(row3 + x), vx_load(row3 + x + v_int32::nlanes)));
+ r4 = v_reinterpret_as_u16(v_pack(vx_load(row4 + x), vx_load(row4 + x + v_int32::nlanes)));
+ t0 = r0 + r4 + (r2 + r2) + ((r1 + r3 + r2) << 2);
+ r0 = v_reinterpret_as_u16(v_pack(vx_load(row0 + x + 2*v_int32::nlanes), vx_load(row0 + x + 3*v_int32::nlanes)));
+ r1 = v_reinterpret_as_u16(v_pack(vx_load(row1 + x + 2*v_int32::nlanes), vx_load(row1 + x + 3*v_int32::nlanes)));
+ r2 = v_reinterpret_as_u16(v_pack(vx_load(row2 + x + 2*v_int32::nlanes), vx_load(row2 + x + 3*v_int32::nlanes)));
+ r3 = v_reinterpret_as_u16(v_pack(vx_load(row3 + x + 2*v_int32::nlanes), vx_load(row3 + x + 3*v_int32::nlanes)));
+ r4 = v_reinterpret_as_u16(v_pack(vx_load(row4 + x + 2*v_int32::nlanes), vx_load(row4 + x + 3*v_int32::nlanes)));
+ t1 = r0 + r4 + (r2 + r2) + ((r1 + r3 + r2) << 2);
+ v_store(dst + x, v_rshr_pack<8>(t0, t1));
+ }
+ if (x <= width - v_int16::nlanes)
{
- int x = 0;
- short *dst0 = dst[0], *dst1 = dst[1];
- const int *row0 = src[0], *row1 = src[1], *row2 = src[2];
+ v_uint16 r0, r1, r2, r3, r4, t0;
+ r0 = v_reinterpret_as_u16(v_pack(vx_load(row0 + x), vx_load(row0 + x + v_int32::nlanes)));
+ r1 = v_reinterpret_as_u16(v_pack(vx_load(row1 + x), vx_load(row1 + x + v_int32::nlanes)));
+ r2 = v_reinterpret_as_u16(v_pack(vx_load(row2 + x), vx_load(row2 + x + v_int32::nlanes)));
+ r3 = v_reinterpret_as_u16(v_pack(vx_load(row3 + x), vx_load(row3 + x + v_int32::nlanes)));
+ r4 = v_reinterpret_as_u16(v_pack(vx_load(row4 + x), vx_load(row4 + x + v_int32::nlanes)));
+ t0 = r0 + r4 + (r2 + r2) + ((r1 + r3 + r2) << 2);
+ v_rshr_pack_store<8>(dst + x, t0);
+ x += v_uint16::nlanes;
+ }
+ typedef int CV_DECL_ALIGNED(1) unaligned_int;
+ for ( ; x <= width - v_int32x4::nlanes; x += v_int32x4::nlanes)
+ {
+ v_int32x4 r0, r1, r2, r3, r4, t0;
+ r0 = v_load(row0 + x);
+ r1 = v_load(row1 + x);
+ r2 = v_load(row2 + x);
+ r3 = v_load(row3 + x);
+ r4 = v_load(row4 + x);
+ t0 = r0 + r4 + (r2 + r2) + ((r1 + r3 + r2) << 2);
+
+ *((unaligned_int*) (dst + x)) = v_reinterpret_as_s32(v_rshr_pack<8>(v_pack_u(t0, t0), v_setzero_u16())).get0();
+ }
+ vx_cleanup();
- for( ; x <= width - v_int16::nlanes; x += v_int16::nlanes)
- {
- v_int32 v_r00 = vx_load(row0 + x),
- v_r01 = vx_load(row0 + x + v_int32::nlanes),
- v_r10 = vx_load(row1 + x),
- v_r11 = vx_load(row1 + x + v_int32::nlanes),
- v_r20 = vx_load(row2 + x),
- v_r21 = vx_load(row2 + x + v_int32::nlanes);
- v_store(dst0 + x, v_rshr_pack<6>(v_r00 + v_r20 + ((v_r10 << 1) + (v_r10 << 2)), v_r01 + v_r21 + ((v_r11 << 1) + (v_r11 << 2))));
- v_store(dst1 + x, v_rshr_pack<6>((v_r10 + v_r20) << 2, (v_r11 + v_r21) << 2));
- }
- if(x <= width - v_int32::nlanes)
- {
- v_int32 v_r00 = vx_load(row0 + x),
- v_r10 = vx_load(row1 + x),
- v_r20 = vx_load(row2 + x);
- v_rshr_pack_store<6>(dst0 + x, v_r00 + v_r20 + ((v_r10 << 1) + (v_r10 << 2)));
- v_rshr_pack_store<6>(dst1 + x, (v_r10 + v_r20) << 2);
- x += v_int32::nlanes;
- }
+ return x;
+}
- return x;
+template <>
+int PyrDownVecV<float, float>(float** src, float* dst, int width)
+{
+ int x = 0;
+ const float *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
+
+ v_float32 _4 = vx_setall_f32(4.f), _scale = vx_setall_f32(1.f/256);
+ for( ; x <= width - v_float32::nlanes; x += v_float32::nlanes)
+ {
+ v_float32 r0, r1, r2, r3, r4;
+ r0 = vx_load(row0 + x);
+ r1 = vx_load(row1 + x);
+ r2 = vx_load(row2 + x);
+ r3 = vx_load(row3 + x);
+ r4 = vx_load(row4 + x);
+ v_store(dst + x, v_muladd(r1 + r3 + r2, _4, r0 + r4 + (r2 + r2)) * _scale);
}
-};
+ vx_cleanup();
-#if CV_SSE4_1 || CV_NEON || CV_VSX
+ return x;
+}
-struct PyrUpVec_32s16u
+template <> int PyrDownVecV<int, ushort>(int** src, ushort* dst, int width)
{
- int operator()(int** src, ushort** dst, int, int width) const
+ int x = 0;
+ const int *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
+
+ for( ; x <= width - v_uint16::nlanes; x += v_uint16::nlanes)
+ {
+ v_int32 r00 = vx_load(row0 + x),
+ r01 = vx_load(row0 + x + v_int32::nlanes),
+ r10 = vx_load(row1 + x),
+ r11 = vx_load(row1 + x + v_int32::nlanes),
+ r20 = vx_load(row2 + x),
+ r21 = vx_load(row2 + x + v_int32::nlanes),
+ r30 = vx_load(row3 + x),
+ r31 = vx_load(row3 + x + v_int32::nlanes),
+ r40 = vx_load(row4 + x),
+ r41 = vx_load(row4 + x + v_int32::nlanes);
+ v_store(dst + x, v_rshr_pack_u<8>(r00 + r40 + (r20 + r20) + ((r10 + r20 + r30) << 2),
+ r01 + r41 + (r21 + r21) + ((r11 + r21 + r31) << 2)));
+ }
+ if (x <= width - v_int32::nlanes)
{
- int x = 0;
- ushort *dst0 = dst[0], *dst1 = dst[1];
- const int *row0 = src[0], *row1 = src[1], *row2 = src[2];
+ v_int32 r00 = vx_load(row0 + x),
+ r10 = vx_load(row1 + x),
+ r20 = vx_load(row2 + x),
+ r30 = vx_load(row3 + x),
+ r40 = vx_load(row4 + x);
+ v_rshr_pack_u_store<8>(dst + x, r00 + r40 + (r20 + r20) + ((r10 + r20 + r30) << 2));
+ x += v_int32::nlanes;
+ }
+ vx_cleanup();
- for( ; x <= width - v_uint16::nlanes; x += v_uint16::nlanes)
- {
- v_int32 v_r00 = vx_load(row0 + x),
- v_r01 = vx_load(row0 + x + v_int32::nlanes),
- v_r10 = vx_load(row1 + x),
- v_r11 = vx_load(row1 + x + v_int32::nlanes),
- v_r20 = vx_load(row2 + x),
- v_r21 = vx_load(row2 + x + v_int32::nlanes);
- v_store(dst0 + x, v_rshr_pack_u<6>(v_r00 + v_r20 + ((v_r10 << 1) + (v_r10 << 2)), v_r01 + v_r21 + ((v_r11 << 1) + (v_r11 << 2))));
- v_store(dst1 + x, v_rshr_pack_u<6>((v_r10 + v_r20) << 2, (v_r11 + v_r21) << 2));
- }
- if(x <= width - v_int32::nlanes)
- {
- v_int32 v_r00 = vx_load(row0 + x),
- v_r10 = vx_load(row1 + x),
- v_r20 = vx_load(row2 + x);
- v_rshr_pack_u_store<6>(dst0 + x, v_r00 + v_r20 + ((v_r10 << 1) + (v_r10 << 2)));
- v_rshr_pack_u_store<6>(dst1 + x, (v_r10 + v_r20) << 2);
- x += v_int32::nlanes;
- }
+ return x;
+}
- return x;
+template <> int PyrDownVecV<int, short>(int** src, short* dst, int width)
+{
+ int x = 0;
+ const int *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
+
+ for( ; x <= width - v_int16::nlanes; x += v_int16::nlanes)
+ {
+ v_int32 r00 = vx_load(row0 + x),
+ r01 = vx_load(row0 + x + v_int32::nlanes),
+ r10 = vx_load(row1 + x),
+ r11 = vx_load(row1 + x + v_int32::nlanes),
+ r20 = vx_load(row2 + x),
+ r21 = vx_load(row2 + x + v_int32::nlanes),
+ r30 = vx_load(row3 + x),
+ r31 = vx_load(row3 + x + v_int32::nlanes),
+ r40 = vx_load(row4 + x),
+ r41 = vx_load(row4 + x + v_int32::nlanes);
+ v_store(dst + x, v_rshr_pack<8>(r00 + r40 + (r20 + r20) + ((r10 + r20 + r30) << 2),
+ r01 + r41 + (r21 + r21) + ((r11 + r21 + r31) << 2)));
}
-};
+ if (x <= width - v_int32::nlanes)
+ {
+ v_int32 r00 = vx_load(row0 + x),
+ r10 = vx_load(row1 + x),
+ r20 = vx_load(row2 + x),
+ r30 = vx_load(row3 + x),
+ r40 = vx_load(row4 + x);
+ v_rshr_pack_store<8>(dst + x, r00 + r40 + (r20 + r20) + ((r10 + r20 + r30) << 2));
+ x += v_int32::nlanes;
+ }
+ vx_cleanup();
-#else
+ return x;
+}
-typedef PyrUpNoVec<int, ushort> PyrUpVec_32s16u;
+template <> int PyrUpVecV<int, uchar>(int** src, uchar** dst, int width)
+{
+ int x = 0;
+ uchar *dst0 = dst[0], *dst1 = dst[1];
+ const int *row0 = src[0], *row1 = src[1], *row2 = src[2];
-#endif // CV_SSE4_1
+ for( ; x <= width - v_uint8::nlanes; x += v_uint8::nlanes)
+ {
+ v_int16 v_r00 = v_pack(vx_load(row0 + x), vx_load(row0 + x + v_int32::nlanes)),
+ v_r01 = v_pack(vx_load(row0 + x + 2 * v_int32::nlanes), vx_load(row0 + x + 3 * v_int32::nlanes)),
+ v_r10 = v_pack(vx_load(row1 + x), vx_load(row1 + x + v_int32::nlanes)),
+ v_r11 = v_pack(vx_load(row1 + x + 2 * v_int32::nlanes), vx_load(row1 + x + 3 * v_int32::nlanes)),
+ v_r20 = v_pack(vx_load(row2 + x), vx_load(row2 + x + v_int32::nlanes)),
+ v_r21 = v_pack(vx_load(row2 + x + 2 * v_int32::nlanes), vx_load(row2 + x + 3 * v_int32::nlanes));
+ v_int16 v_2r10 = v_r10 + v_r10, v_2r11 = (v_r11 + v_r11);
+ v_store(dst0 + x, v_rshr_pack_u<6>(v_r00 + v_r20 + (v_2r10 + v_2r10 + v_2r10), v_r01 + v_r21 + (v_2r11 + v_2r11 + v_2r11)));
+ v_store(dst1 + x, v_rshr_pack_u<6>((v_r10 + v_r20) << 2, (v_r11 + v_r21) << 2));
+ }
+ if(x <= width - v_uint16::nlanes)
+ {
+ v_int16 v_r00 = v_pack(vx_load(row0 + x), vx_load(row0 + x + v_int32::nlanes)),
+ v_r10 = v_pack(vx_load(row1 + x), vx_load(row1 + x + v_int32::nlanes)),
+ v_r20 = v_pack(vx_load(row2 + x), vx_load(row2 + x + v_int32::nlanes));
+ v_int16 v_2r10 = v_r10 + v_r10;
+ v_rshr_pack_u_store<6>(dst0 + x, v_r00 + v_r20 + (v_2r10 + v_2r10 + v_2r10));
+ v_rshr_pack_u_store<6>(dst1 + x, (v_r10 + v_r20) << 2);
+ x += v_uint16::nlanes;
+ }
+ typedef int CV_DECL_ALIGNED(1) unaligned_int;
+ for (; x <= width - v_int32x4::nlanes; x += v_int32x4::nlanes)
+ {
+ v_int32 v_r00 = vx_load(row0 + x),
+ v_r10 = vx_load(row1 + x),
+ v_r20 = vx_load(row2 + x);
+ v_int32 v_2r10 = v_r10 + v_r10;
+ v_int16 d = v_pack(v_r00 + v_r20 + (v_2r10 + v_2r10 + v_2r10), (v_r10 + v_r20) << 2);
+ *(unaligned_int*)(dst0 + x) = v_reinterpret_as_s32(v_rshr_pack_u<6>(d, vx_setzero_s16())).get0();
+ *(unaligned_int*)(dst1 + x) = v_reinterpret_as_s32(v_rshr_pack_u<6>(v_combine_high(d, d), vx_setzero_s16())).get0();
+ }
+ vx_cleanup();
-struct PyrUpVec_32f
+ return x;
+}
+
+template <> int PyrUpVecV<int, short>(int** src, short** dst, int width)
{
- int operator()(float** src, float** dst, int, int width) const
+ int x = 0;
+ short *dst0 = dst[0], *dst1 = dst[1];
+ const int *row0 = src[0], *row1 = src[1], *row2 = src[2];
+
+ for( ; x <= width - v_int16::nlanes; x += v_int16::nlanes)
+ {
+ v_int32 v_r00 = vx_load(row0 + x),
+ v_r01 = vx_load(row0 + x + v_int32::nlanes),
+ v_r10 = vx_load(row1 + x),
+ v_r11 = vx_load(row1 + x + v_int32::nlanes),
+ v_r20 = vx_load(row2 + x),
+ v_r21 = vx_load(row2 + x + v_int32::nlanes);
+ v_store(dst0 + x, v_rshr_pack<6>(v_r00 + v_r20 + ((v_r10 << 1) + (v_r10 << 2)), v_r01 + v_r21 + ((v_r11 << 1) + (v_r11 << 2))));
+ v_store(dst1 + x, v_rshr_pack<6>((v_r10 + v_r20) << 2, (v_r11 + v_r21) << 2));
+ }
+ if(x <= width - v_int32::nlanes)
{
- int x = 0;
- const float *row0 = src[0], *row1 = src[1], *row2 = src[2];
- float *dst0 = dst[0], *dst1 = dst[1];
+ v_int32 v_r00 = vx_load(row0 + x),
+ v_r10 = vx_load(row1 + x),
+ v_r20 = vx_load(row2 + x);
+ v_rshr_pack_store<6>(dst0 + x, v_r00 + v_r20 + ((v_r10 << 1) + (v_r10 << 2)));
+ v_rshr_pack_store<6>(dst1 + x, (v_r10 + v_r20) << 2);
+ x += v_int32::nlanes;
+ }
+ vx_cleanup();
- v_float32 v_6 = vx_setall_f32(6.0f), v_scale = vx_setall_f32(1.f/64.f), v_scale4 = vx_setall_f32(1.f/16.f);
- for( ; x <= width - v_float32::nlanes; x += v_float32::nlanes)
- {
- v_float32 v_r0 = vx_load(row0 + x),
- v_r1 = vx_load(row1 + x),
- v_r2 = vx_load(row2 + x);
- v_store(dst1 + x, v_scale4 * (v_r1 + v_r2));
- v_store(dst0 + x, v_scale * (v_muladd(v_6, v_r1, v_r0) + v_r2));
- }
+ return x;
+}
+
+template <> int PyrUpVecV<int, ushort>(int** src, ushort** dst, int width)
+{
+ int x = 0;
+ ushort *dst0 = dst[0], *dst1 = dst[1];
+ const int *row0 = src[0], *row1 = src[1], *row2 = src[2];
- return x;
+ for( ; x <= width - v_uint16::nlanes; x += v_uint16::nlanes)
+ {
+ v_int32 v_r00 = vx_load(row0 + x),
+ v_r01 = vx_load(row0 + x + v_int32::nlanes),
+ v_r10 = vx_load(row1 + x),
+ v_r11 = vx_load(row1 + x + v_int32::nlanes),
+ v_r20 = vx_load(row2 + x),
+ v_r21 = vx_load(row2 + x + v_int32::nlanes);
+ v_store(dst0 + x, v_rshr_pack_u<6>(v_r00 + v_r20 + ((v_r10 << 1) + (v_r10 << 2)), v_r01 + v_r21 + ((v_r11 << 1) + (v_r11 << 2))));
+ v_store(dst1 + x, v_rshr_pack_u<6>((v_r10 + v_r20) << 2, (v_r11 + v_r21) << 2));
}
-};
+ if(x <= width - v_int32::nlanes)
+ {
+ v_int32 v_r00 = vx_load(row0 + x),
+ v_r10 = vx_load(row1 + x),
+ v_r20 = vx_load(row2 + x);
+ v_rshr_pack_u_store<6>(dst0 + x, v_r00 + v_r20 + ((v_r10 << 1) + (v_r10 << 2)));
+ v_rshr_pack_u_store<6>(dst1 + x, (v_r10 + v_r20) << 2);
+ x += v_int32::nlanes;
+ }
+ vx_cleanup();
-#else
+ return x;
+}
+
+template <> int PyrUpVecV<float, float>(float** src, float** dst, int width)
+{
+ int x = 0;
+ const float *row0 = src[0], *row1 = src[1], *row2 = src[2];
+ float *dst0 = dst[0], *dst1 = dst[1];
-typedef PyrDownNoVec<int, uchar> PyrDownVec_32s8u;
-typedef PyrDownNoVec<int, ushort> PyrDownVec_32s16u;
-typedef PyrDownNoVec<int, short> PyrDownVec_32s16s;
-typedef PyrDownNoVec<float, float> PyrDownVec_32f;
+ v_float32 v_6 = vx_setall_f32(6.0f), v_scale = vx_setall_f32(1.f/64.f), v_scale4 = vx_setall_f32(1.f/16.f);
+ for( ; x <= width - v_float32::nlanes; x += v_float32::nlanes)
+ {
+ v_float32 v_r0 = vx_load(row0 + x),
+ v_r1 = vx_load(row1 + x),
+ v_r2 = vx_load(row2 + x);
+ v_store(dst1 + x, v_scale4 * (v_r1 + v_r2));
+ v_store(dst0 + x, v_scale * (v_muladd(v_6, v_r1, v_r0) + v_r2));
+ }
+ vx_cleanup();
-typedef PyrUpNoVec<int, uchar> PyrUpVec_32s8u;
-typedef PyrUpNoVec<int, short> PyrUpVec_32s16s;
-typedef PyrUpNoVec<int, ushort> PyrUpVec_32s16u;
-typedef PyrUpNoVec<float, float> PyrUpVec_32f;
+ return x;
+}
#endif
-template<class CastOp, class VecOp> void
+template<class CastOp> void
pyrDown_( const Mat& _src, Mat& _dst, int borderType )
{
const int PD_SZ = 5;
int* tabM = _tabM.data();
WT* rows[PD_SZ];
CastOp castOp;
- VecOp vecOp;
CV_Assert( ssize.width > 0 && ssize.height > 0 &&
std::abs(dsize.width*2 - ssize.width) <= 2 &&
if( cn == 1 )
{
+ x += PyrDownVecH<T, WT, 1>(src + x * 2 - 2, row + x, width0 - x);
for( ; x < width0; x++ )
row[x] = src[x*2]*6 + (src[x*2 - 1] + src[x*2 + 1])*4 +
src[x*2 - 2] + src[x*2 + 2];
}
+ else if( cn == 2 )
+ {
+ x += PyrDownVecH<T, WT, 2>(src + x * 2 - 4, row + x, width0 - x);
+ for( ; x < width0; x += 2 )
+ {
+ const T* s = src + x*2;
+ WT t0 = s[0] * 6 + (s[-2] + s[2]) * 4 + s[-4] + s[4];
+ WT t1 = s[1] * 6 + (s[-1] + s[3]) * 4 + s[-3] + s[5];
+ row[x] = t0; row[x + 1] = t1;
+ }
+ }
else if( cn == 3 )
{
+ x += PyrDownVecH<T, WT, 3>(src + x * 2 - 6, row + x, width0 - x);
for( ; x < width0; x += 3 )
{
const T* s = src + x*2;
}
else if( cn == 4 )
{
+ x += PyrDownVecH<T, WT, 4>(src + x * 2 - 8, row + x, width0 - x);
for( ; x < width0; x += 4 )
{
const T* s = src + x*2;
rows[k] = buf + ((y*2 - PD_SZ/2 + k - sy0) % PD_SZ)*bufstep;
row0 = rows[0]; row1 = rows[1]; row2 = rows[2]; row3 = rows[3]; row4 = rows[4];
- x = vecOp(rows, dst, (int)_dst.step, dsize.width);
+ x = PyrDownVecV<WT, T>(rows, dst, dsize.width);
for( ; x < dsize.width; x++ )
dst[x] = castOp(row2[x]*6 + (row1[x] + row3[x])*4 + row0[x] + row4[x]);
}
}
-template<class CastOp, class VecOp> void
+template<class CastOp> void
pyrUp_( const Mat& _src, Mat& _dst, int)
{
const int PU_SZ = 3;
WT* rows[PU_SZ];
T* dsts[2];
CastOp castOp;
- VecOp vecOp;
+ //PyrUpVecH<T, WT> vecOpH;
CV_Assert( std::abs(dsize.width - ssize.width*2) == dsize.width % 2 &&
std::abs(dsize.height - ssize.height*2) == dsize.height % 2);
row0 = rows[0]; row1 = rows[1]; row2 = rows[2];
dsts[0] = dst0; dsts[1] = dst1;
- x = vecOp(rows, dsts, (int)_dst.step, dsize.width);
+ x = PyrUpVecV<WT, T>(rows, dsts, dsize.width);
for( ; x < dsize.width; x++ )
{
T t1 = castOp((row1[x] + row2[x])*4);
PyrFunc func = 0;
if( depth == CV_8U )
- func = pyrDown_<FixPtCast<uchar, 8>, PyrDownVec_32s8u>;
+ func = pyrDown_< FixPtCast<uchar, 8> >;
else if( depth == CV_16S )
- func = pyrDown_<FixPtCast<short, 8>, PyrDownVec_32s16s >;
+ func = pyrDown_< FixPtCast<short, 8> >;
else if( depth == CV_16U )
- func = pyrDown_<FixPtCast<ushort, 8>, PyrDownVec_32s16u >;
+ func = pyrDown_< FixPtCast<ushort, 8> >;
else if( depth == CV_32F )
- func = pyrDown_<FltCast<float, 8>, PyrDownVec_32f>;
+ func = pyrDown_< FltCast<float, 8> >;
else if( depth == CV_64F )
- func = pyrDown_<FltCast<double, 8>, PyrDownNoVec<double, double> >;
+ func = pyrDown_< FltCast<double, 8> >;
else
CV_Error( CV_StsUnsupportedFormat, "" );
PyrFunc func = 0;
if( depth == CV_8U )
- func = pyrUp_<FixPtCast<uchar, 6>, PyrUpVec_32s8u >;
+ func = pyrUp_< FixPtCast<uchar, 6> >;
else if( depth == CV_16S )
- func = pyrUp_<FixPtCast<short, 6>, PyrUpVec_32s16s >;
+ func = pyrUp_< FixPtCast<short, 6> >;
else if( depth == CV_16U )
- func = pyrUp_<FixPtCast<ushort, 6>, PyrUpVec_32s16u >;
+ func = pyrUp_< FixPtCast<ushort, 6> >;
else if( depth == CV_32F )
- func = pyrUp_<FltCast<float, 6>, PyrUpVec_32f >;
+ func = pyrUp_< FltCast<float, 6> >;
else if( depth == CV_64F )
- func = pyrUp_<FltCast<double, 6>, PyrUpNoVec<double, double> >;
+ func = pyrUp_< FltCast<double, 6> >;
else
CV_Error( CV_StsUnsupportedFormat, "" );
hline<ET, FT, n, mulall, cncnt>::ResizeCn(src, cn, ofst, m, dst, dst_min, dst_max, dst_width);
};
-#if CV_SIMD512
-inline void v_load_indexed1(uint8_t* src, int *ofst, v_uint16 &v_src0, v_uint16 &v_src1)
-{
- v_expand(v_reinterpret_as_u8(v_uint16(
- *((uint16_t*)(src + ofst[ 0])), *((uint16_t*)(src + ofst[ 1])), *((uint16_t*)(src + ofst[ 2])), *((uint16_t*)(src + ofst[ 3])),
- *((uint16_t*)(src + ofst[ 4])), *((uint16_t*)(src + ofst[ 5])), *((uint16_t*)(src + ofst[ 6])), *((uint16_t*)(src + ofst[ 7])),
- *((uint16_t*)(src + ofst[ 8])), *((uint16_t*)(src + ofst[ 9])), *((uint16_t*)(src + ofst[10])), *((uint16_t*)(src + ofst[11])),
- *((uint16_t*)(src + ofst[12])), *((uint16_t*)(src + ofst[13])), *((uint16_t*)(src + ofst[14])), *((uint16_t*)(src + ofst[15])),
- *((uint16_t*)(src + ofst[16])), *((uint16_t*)(src + ofst[17])), *((uint16_t*)(src + ofst[14])), *((uint16_t*)(src + ofst[15])),
- *((uint16_t*)(src + ofst[20])), *((uint16_t*)(src + ofst[21])), *((uint16_t*)(src + ofst[14])), *((uint16_t*)(src + ofst[15])),
- *((uint16_t*)(src + ofst[24])), *((uint16_t*)(src + ofst[25])), *((uint16_t*)(src + ofst[14])), *((uint16_t*)(src + ofst[15])),
- *((uint16_t*)(src + ofst[28])), *((uint16_t*)(src + ofst[29])), *((uint16_t*)(src + ofst[14])), *((uint16_t*)(src + ofst[15])))),
- v_src0, v_src1);
-}
-inline void v_load_indexed2(uint8_t* src, int *ofst, v_uint16 &v_src0, v_uint16 &v_src1)
-{
- v_expand(v_reinterpret_as_u8(v_uint32(
- *((uint32_t*)(src + 2 * ofst[ 0])), *((uint32_t*)(src + 2 * ofst[ 1])), *((uint32_t*)(src + 2 * ofst[ 2])), *((uint32_t*)(src + 2 * ofst[ 3])),
- *((uint32_t*)(src + 2 * ofst[ 4])), *((uint32_t*)(src + 2 * ofst[ 5])), *((uint32_t*)(src + 2 * ofst[ 6])), *((uint32_t*)(src + 2 * ofst[ 7])),
- *((uint32_t*)(src + 2 * ofst[ 8])), *((uint32_t*)(src + 2 * ofst[ 9])), *((uint32_t*)(src + 2 * ofst[10])), *((uint32_t*)(src + 2 * ofst[11])),
- *((uint32_t*)(src + 2 * ofst[12])), *((uint32_t*)(src + 2 * ofst[13])), *((uint32_t*)(src + 2 * ofst[14])), *((uint32_t*)(src + 2 * ofst[15])))),
- v_src0, v_src1);
- v_uint32 v_tmp0, v_tmp1, v_tmp2, v_tmp3;
- v_zip(v_reinterpret_as_u32(v_src0), v_reinterpret_as_u32(v_src1), v_tmp2, v_tmp3);
- v_zip(v_tmp2, v_tmp3, v_tmp0, v_tmp1);
- v_zip(v_tmp0, v_tmp1, v_tmp2, v_tmp3);
- v_zip(v_tmp2, v_tmp3, v_tmp0, v_tmp1);
- v_zip(v_reinterpret_as_u16(v_tmp0), v_reinterpret_as_u16(v_tmp1), v_src0, v_src1);
-}
-inline void v_load_indexed4(uint8_t* src, int *ofst, v_uint16 &v_src0, v_uint16 &v_src1)
-{
- v_expand(v_reinterpret_as_u8(v_uint64(
- *((uint64_t*)(src + 4 * ofst[0])), *((uint64_t*)(src + 4 * ofst[1])), *((uint64_t*)(src + 4 * ofst[2])), *((uint64_t*)(src + 4 * ofst[3])),
- *((uint64_t*)(src + 4 * ofst[4])), *((uint64_t*)(src + 4 * ofst[5])), *((uint64_t*)(src + 4 * ofst[6])), *((uint64_t*)(src + 4 * ofst[7])))),
- v_src0, v_src1);
- v_uint64 v_tmp0, v_tmp1, v_tmp2, v_tmp3;
- v_zip(v_reinterpret_as_u64(v_src0), v_reinterpret_as_u64(v_src1), v_tmp2, v_tmp3);
- v_zip(v_tmp2, v_tmp3, v_tmp0, v_tmp1);
- v_zip(v_tmp0, v_tmp1, v_tmp2, v_tmp3);
- v_zip(v_reinterpret_as_u16(v_tmp2), v_reinterpret_as_u16(v_tmp3), v_src0, v_src1);
-}
-inline void v_load_indexed_deinterleave(uint16_t* src, int *ofst, v_uint32 &v_src0, v_uint32 &v_src1)
-{
- v_expand(v_reinterpret_as_u16(v_uint32(
- *((uint32_t*)(src + ofst[ 0])), *((uint32_t*)(src + ofst[ 1])), *((uint32_t*)(src + ofst[ 2])), *((uint32_t*)(src + ofst[ 3])),
- *((uint32_t*)(src + ofst[ 4])), *((uint32_t*)(src + ofst[ 5])), *((uint32_t*)(src + ofst[ 6])), *((uint32_t*)(src + ofst[ 7])),
- *((uint32_t*)(src + ofst[ 8])), *((uint32_t*)(src + ofst[ 9])), *((uint32_t*)(src + ofst[10])), *((uint32_t*)(src + ofst[11])),
- *((uint32_t*)(src + ofst[12])), *((uint32_t*)(src + ofst[13])), *((uint32_t*)(src + ofst[14])), *((uint32_t*)(src + ofst[15])))),
- v_src0, v_src1);
- v_uint32 v_tmp0, v_tmp1;
- v_zip(v_src0, v_src1, v_tmp0, v_tmp1);
- v_zip(v_tmp0, v_tmp1, v_src0, v_src1);
- v_zip(v_src0, v_src1, v_tmp0, v_tmp1);
- v_zip(v_tmp0, v_tmp1, v_src0, v_src1);
-}
-#elif CV_SIMD256
-inline void v_load_indexed1(uint8_t* src, int *ofst, v_uint16 &v_src0, v_uint16 &v_src1)
-{
- v_expand(v_reinterpret_as_u8(v_uint16(
- *((uint16_t*)(src + ofst[ 0])), *((uint16_t*)(src + ofst[ 1])), *((uint16_t*)(src + ofst[ 2])), *((uint16_t*)(src + ofst[ 3])),
- *((uint16_t*)(src + ofst[ 4])), *((uint16_t*)(src + ofst[ 5])), *((uint16_t*)(src + ofst[ 6])), *((uint16_t*)(src + ofst[ 7])),
- *((uint16_t*)(src + ofst[ 8])), *((uint16_t*)(src + ofst[ 9])), *((uint16_t*)(src + ofst[10])), *((uint16_t*)(src + ofst[11])),
- *((uint16_t*)(src + ofst[12])), *((uint16_t*)(src + ofst[13])), *((uint16_t*)(src + ofst[14])), *((uint16_t*)(src + ofst[15])))),
- v_src0, v_src1);
-}
-inline void v_load_indexed2(uint8_t* src, int *ofst, v_uint16 &v_src0, v_uint16 &v_src1)
-{
- v_expand(v_reinterpret_as_u8(v_uint32(
- *((uint32_t*)(src + 2 * ofst[0])), *((uint32_t*)(src + 2 * ofst[1])), *((uint32_t*)(src + 2 * ofst[2])), *((uint32_t*)(src + 2 * ofst[3])),
- *((uint32_t*)(src + 2 * ofst[4])), *((uint32_t*)(src + 2 * ofst[5])), *((uint32_t*)(src + 2 * ofst[6])), *((uint32_t*)(src + 2 * ofst[7])))),
- v_src0, v_src1);
- v_uint32 v_tmp0, v_tmp1, v_tmp2, v_tmp3;
- v_zip(v_reinterpret_as_u32(v_src0), v_reinterpret_as_u32(v_src1), v_tmp2, v_tmp3);
- v_zip(v_tmp2, v_tmp3, v_tmp0, v_tmp1);
- v_zip(v_tmp0, v_tmp1, v_tmp2, v_tmp3);
- v_zip(v_reinterpret_as_u16(v_tmp2), v_reinterpret_as_u16(v_tmp3), v_src0, v_src1);
-}
-inline void v_load_indexed4(uint8_t* src, int *ofst, v_uint16 &v_src0, v_uint16 &v_src1)
-{
- v_expand(v_reinterpret_as_u8(v_uint64(
- *((uint64_t*)(src + 4 * ofst[0])), *((uint64_t*)(src + 4 * ofst[1])), *((uint64_t*)(src + 4 * ofst[2])), *((uint64_t*)(src + 4 * ofst[3])))),
- v_src0, v_src1);
- v_uint64 v_tmp0, v_tmp1, v_tmp2, v_tmp3;
- v_zip(v_reinterpret_as_u64(v_src0), v_reinterpret_as_u64(v_src1), v_tmp2, v_tmp3);
- v_zip(v_tmp2, v_tmp3, v_tmp0, v_tmp1);
- v_zip(v_reinterpret_as_u16(v_tmp0), v_reinterpret_as_u16(v_tmp1), v_src0, v_src1);
-}
-inline void v_load_indexed_deinterleave(uint16_t* src, int *ofst, v_uint32 &v_src0, v_uint32 &v_src1)
-{
- v_uint32 v_tmp0, v_tmp1;
- v_expand(v_reinterpret_as_u16(v_uint32(
- *((uint32_t*)(src + ofst[0])), *((uint32_t*)(src + ofst[1])), *((uint32_t*)(src + ofst[2])), *((uint32_t*)(src + ofst[3])),
- *((uint32_t*)(src + ofst[4])), *((uint32_t*)(src + ofst[5])), *((uint32_t*)(src + ofst[6])), *((uint32_t*)(src + ofst[7])))),
- v_tmp0, v_tmp1);
- v_zip(v_tmp0, v_tmp1, v_src0, v_src1);
- v_zip(v_src0, v_src1, v_tmp0, v_tmp1);
- v_zip(v_tmp0, v_tmp1, v_src0, v_src1);
-}
-#elif CV_SIMD128
-inline void v_load_indexed1(uint8_t* src, int *ofst, v_uint16 &v_src0, v_uint16 &v_src1)
-{
- uint16_t buf[8];
- buf[0] = *((uint16_t*)(src + ofst[0]));
- buf[1] = *((uint16_t*)(src + ofst[1]));
- buf[2] = *((uint16_t*)(src + ofst[2]));
- buf[3] = *((uint16_t*)(src + ofst[3]));
- buf[4] = *((uint16_t*)(src + ofst[4]));
- buf[5] = *((uint16_t*)(src + ofst[5]));
- buf[6] = *((uint16_t*)(src + ofst[6]));
- buf[7] = *((uint16_t*)(src + ofst[7]));
- v_src0 = vx_load_expand((uint8_t*)buf);
- v_src1 = vx_load_expand((uint8_t*)buf + 8);
-}
-inline void v_load_indexed2(uint8_t* src, int *ofst, v_uint16 &v_src0, v_uint16 &v_src1)
-{
- uint32_t buf[4];
- buf[0] = *((uint32_t*)(src + 2 * ofst[0]));
- buf[1] = *((uint32_t*)(src + 2 * ofst[1]));
- buf[2] = *((uint32_t*)(src + 2 * ofst[2]));
- buf[3] = *((uint32_t*)(src + 2 * ofst[3]));
- v_uint32 v_tmp0, v_tmp1, v_tmp2, v_tmp3;
- v_tmp0 = v_reinterpret_as_u32(vx_load_expand((uint8_t*)buf));
- v_tmp1 = v_reinterpret_as_u32(vx_load_expand((uint8_t*)buf + 8));
- v_zip(v_tmp0, v_tmp1, v_tmp2, v_tmp3);
- v_zip(v_tmp2, v_tmp3, v_tmp0, v_tmp1);
- v_zip(v_reinterpret_as_u16(v_tmp0), v_reinterpret_as_u16(v_tmp1), v_src0, v_src1);
-}
-inline void v_load_indexed4(uint8_t* src, int *ofst, v_uint16 &v_src0, v_uint16 &v_src1)
-{
- v_uint16 v_tmp0, v_tmp1;
- v_src0 = vx_load_expand(src + 4 * ofst[0]);
- v_src1 = vx_load_expand(src + 4 * ofst[1]);
- v_recombine(v_src0, v_src1, v_tmp0, v_tmp1);
- v_zip(v_tmp0, v_tmp1, v_src0, v_src1);
-}
-inline void v_load_indexed_deinterleave(uint16_t* src, int *ofst, v_uint32 &v_src0, v_uint32 &v_src1)
-{
- uint32_t buf[4];
- buf[0] = *((uint32_t*)(src + ofst[0]));
- buf[1] = *((uint32_t*)(src + ofst[1]));
- buf[2] = *((uint32_t*)(src + ofst[2]));
- buf[3] = *((uint32_t*)(src + ofst[3]));
- v_src0 = vx_load_expand((uint16_t*)buf);
- v_src1 = vx_load_expand((uint16_t*)buf + 4);
- v_uint32 v_tmp0, v_tmp1;
- v_zip(v_src0, v_src1, v_tmp0, v_tmp1);
- v_zip(v_tmp0, v_tmp1, v_src0, v_src1);
-}
-#endif
template <>
void hlineResizeCn<uint8_t, ufixedpoint16, 2, true, 1>(uint8_t* src, int, int *ofst, ufixedpoint16* m, ufixedpoint16* dst, int dst_min, int dst_max, int dst_width)
{
*(dst++) = src_0;
}
#if CV_SIMD
- for (; i <= dst_max - VECSZ; i += VECSZ, m += 2*VECSZ, dst += VECSZ)
+ for (; i <= dst_max - 2*VECSZ; i += 2*VECSZ, m += 4*VECSZ, dst += 2*VECSZ)
{
v_uint16 v_src0, v_src1;
- v_load_indexed1(src, ofst + i, v_src0, v_src1);
-
- v_int16 v_mul0 = vx_load((int16_t*)m);
- v_int16 v_mul1 = vx_load((int16_t*)m + VECSZ);
- v_uint32 v_res0 = v_reinterpret_as_u32(v_dotprod(v_reinterpret_as_s16(v_src0), v_mul0));
- v_uint32 v_res1 = v_reinterpret_as_u32(v_dotprod(v_reinterpret_as_s16(v_src1), v_mul1));
- v_store((uint16_t*)dst, v_pack(v_res0, v_res1));
+ v_expand(vx_lut_pairs(src, ofst + i), v_src0, v_src1);
+ v_store((uint16_t*)dst , v_pack(v_reinterpret_as_u32(v_dotprod(v_reinterpret_as_s16(v_src0), vx_load((int16_t*)m))),
+ v_reinterpret_as_u32(v_dotprod(v_reinterpret_as_s16(v_src1), vx_load((int16_t*)m + VECSZ)))));
+ v_expand(vx_lut_pairs(src, ofst + i + VECSZ), v_src0, v_src1);
+ v_store((uint16_t*)dst+VECSZ, v_pack(v_reinterpret_as_u32(v_dotprod(v_reinterpret_as_s16(v_src0), vx_load((int16_t*)m + 2*VECSZ))),
+ v_reinterpret_as_u32(v_dotprod(v_reinterpret_as_s16(v_src1), vx_load((int16_t*)m + 3*VECSZ)))));
+ }
+ if (i <= dst_max - VECSZ)
+ {
+ v_uint16 v_src0, v_src1;
+ v_expand(vx_lut_pairs(src, ofst + i), v_src0, v_src1);
+ v_store((uint16_t*)dst, v_pack(v_reinterpret_as_u32(v_dotprod(v_reinterpret_as_s16(v_src0), vx_load((int16_t*)m))),
+ v_reinterpret_as_u32(v_dotprod(v_reinterpret_as_s16(v_src1), vx_load((int16_t*)m + VECSZ)))));
+ i += VECSZ; m += 2*VECSZ; dst += VECSZ;
}
#endif
for (; i < dst_max; i += 1, m += 2)
for (; i <= dst_max - VECSZ/2; i += VECSZ/2, m += VECSZ, dst += VECSZ)
{
v_uint16 v_src0, v_src1;
- v_load_indexed2(src, ofst + i, v_src0, v_src1);
+ v_expand(v_interleave_pairs(v_reinterpret_as_u8(vx_lut_pairs((uint16_t*)src, ofst + i))), v_src0, v_src1);
v_uint32 v_mul = vx_load((uint32_t*)m);//AaBbCcDd
v_uint32 v_zip0, v_zip1;
}
}
template <>
+void hlineResizeCn<uint8_t, ufixedpoint16, 2, true, 3>(uint8_t* src, int, int *ofst, ufixedpoint16* m, ufixedpoint16* dst, int dst_min, int dst_max, int dst_width)
+{
+ int i = 0;
+ union {
+ uint64_t q;
+ uint16_t w[4];
+ } srccn;
+ ((ufixedpoint16*)(srccn.w))[0] = src[0];
+ ((ufixedpoint16*)(srccn.w))[1] = src[1];
+ ((ufixedpoint16*)(srccn.w))[2] = src[2];
+ ((ufixedpoint16*)(srccn.w))[3] = 0;
+#if CV_SIMD
+ const int VECSZ = v_uint16::nlanes;
+ v_uint16 v_srccn = v_pack_triplets(v_reinterpret_as_u16(vx_setall_u64(srccn.q)));
+ for (; i <= dst_min - (VECSZ+2)/3; i += VECSZ/4, m += VECSZ/2, dst += 3*VECSZ/4) // Points that fall left from src image so became equal to leftmost src point
+ {
+ v_store((uint16_t*)dst, v_srccn);
+ }
+#endif
+ for (; i < dst_min; i++, m += 2)
+ {
+ *(dst++) = ((ufixedpoint16*)(srccn.w))[0];
+ *(dst++) = ((ufixedpoint16*)(srccn.w))[1];
+ *(dst++) = ((ufixedpoint16*)(srccn.w))[2];
+ }
+#if CV_SIMD
+ CV_DECL_ALIGNED(CV_SIMD_WIDTH) int ofst3[VECSZ/2];
+ for (; i <= dst_max - (3*VECSZ/4 + (VECSZ+2)/3); i += VECSZ/2, m += VECSZ, dst += 3*VECSZ/2)
+ {
+ v_store(ofst3, vx_load(ofst + i) * vx_setall_s32(3));
+ v_uint8 v_src01, v_src23;
+ v_uint16 v_src0, v_src1, v_src2, v_src3;
+ v_zip(vx_lut_quads(src, ofst3), v_reinterpret_as_u8(v_reinterpret_as_u32(vx_lut_quads(src+2, ofst3)) >> 8), v_src01, v_src23);
+ v_expand(v_src01, v_src0, v_src1);
+ v_expand(v_src23, v_src2, v_src3);
+
+ v_uint32 v_mul0, v_mul1, v_mul2, v_mul3, v_tmp;
+ v_mul0 = vx_load((uint32_t*)m);//AaBbCcDd
+ v_zip(v_mul0, v_mul0, v_mul3, v_tmp );//AaAaBbBb CcCcDdDd
+ v_zip(v_mul3, v_mul3, v_mul0, v_mul1);//AaAaAaAa BbBbBbBb
+ v_zip(v_tmp , v_tmp , v_mul2, v_mul3);//CcCcCcCc DdDdDdDd
+
+ v_uint32 v_res0 = v_reinterpret_as_u32(v_dotprod(v_reinterpret_as_s16(v_src0), v_reinterpret_as_s16(v_mul0)));
+ v_uint32 v_res1 = v_reinterpret_as_u32(v_dotprod(v_reinterpret_as_s16(v_src1), v_reinterpret_as_s16(v_mul1)));
+ v_uint32 v_res2 = v_reinterpret_as_u32(v_dotprod(v_reinterpret_as_s16(v_src2), v_reinterpret_as_s16(v_mul2)));
+ v_uint32 v_res3 = v_reinterpret_as_u32(v_dotprod(v_reinterpret_as_s16(v_src3), v_reinterpret_as_s16(v_mul3)));
+ v_store((uint16_t*)dst , v_pack_triplets(v_pack(v_res0, v_res1)));
+ v_store((uint16_t*)dst + 3*VECSZ/4, v_pack_triplets(v_pack(v_res2, v_res3)));
+ }
+#endif
+ for (; i < dst_max; i += 1, m += 2)
+ {
+ uint8_t* px = src + 3 * ofst[i];
+ *(dst++) = m[0] * px[0] + m[1] * px[3];
+ *(dst++) = m[0] * px[1] + m[1] * px[4];
+ *(dst++) = m[0] * px[2] + m[1] * px[5];
+ }
+ ((ufixedpoint16*)(srccn.w))[0] = (src + 3*ofst[dst_width - 1])[0];
+ ((ufixedpoint16*)(srccn.w))[1] = (src + 3*ofst[dst_width - 1])[1];
+ ((ufixedpoint16*)(srccn.w))[2] = (src + 3*ofst[dst_width - 1])[2];
+#if CV_SIMD
+ v_srccn = v_pack_triplets(v_reinterpret_as_u16(vx_setall_u64(srccn.q)));
+ for (; i <= dst_width - (VECSZ+2)/3; i += VECSZ/4, dst += 3*VECSZ/4) // Points that fall right from src image so became equal to rightmost src point
+ {
+ v_store((uint16_t*)dst, v_srccn);
+ }
+#endif
+ for (; i < dst_width; i++)
+ {
+ *(dst++) = ((ufixedpoint16*)(srccn.w))[0];
+ *(dst++) = ((ufixedpoint16*)(srccn.w))[1];
+ *(dst++) = ((ufixedpoint16*)(srccn.w))[2];
+ }
+}
+template <>
void hlineResizeCn<uint8_t, ufixedpoint16, 2, true, 4>(uint8_t* src, int, int *ofst, ufixedpoint16* m, ufixedpoint16* dst, int dst_min, int dst_max, int dst_width)
{
int i = 0;
v_store((uint16_t*)dst, v_srccn);
}
#endif
- if (i < dst_min) // Points that fall left from src image so became equal to leftmost src point
+ for (; i < dst_min; i++, m += 2)
{
*(dst++) = ((ufixedpoint16*)(srccn.w))[0];
*(dst++) = ((ufixedpoint16*)(srccn.w))[1];
*(dst++) = ((ufixedpoint16*)(srccn.w))[2];
*(dst++) = ((ufixedpoint16*)(srccn.w))[3];
- i++; m += 2;
}
#if CV_SIMD
for (; i <= dst_max - VECSZ/2; i += VECSZ/2, m += VECSZ, dst += 2*VECSZ)
{
v_uint16 v_src0, v_src1, v_src2, v_src3;
- v_load_indexed4(src, ofst + i, v_src0, v_src1);
- v_load_indexed4(src, ofst + i + VECSZ/4, v_src2, v_src3);
+ v_expand(v_interleave_quads(v_reinterpret_as_u8(vx_lut_pairs((uint32_t*)src, ofst + i))), v_src0, v_src1);
+ v_expand(v_interleave_quads(v_reinterpret_as_u8(vx_lut_pairs((uint32_t*)src, ofst + i + VECSZ/4))), v_src2, v_src3);
v_uint32 v_mul0, v_mul1, v_mul2, v_mul3, v_tmp;
v_mul0 = vx_load((uint32_t*)m);//AaBbCcDd
v_store((uint16_t*)dst, v_srccn);
}
#endif
- if (i < dst_width)
+ for (; i < dst_width; i++)
{
*(dst++) = ((ufixedpoint16*)(srccn.w))[0];
*(dst++) = ((ufixedpoint16*)(srccn.w))[1];
for (; i <= dst_max - VECSZ; i += VECSZ, m += 2*VECSZ, dst += VECSZ)
{
v_uint32 v_src0, v_src1;
- v_load_indexed_deinterleave(src, ofst + i, v_src0, v_src1);
- v_uint32 v_mul0, v_mul1;
- v_load_deinterleave((uint32_t*)m, v_mul0, v_mul1);
- v_store((uint32_t*)dst, v_src0 * v_mul0 + v_src1 * v_mul1);//abcd
+ v_expand(vx_lut_pairs(src, ofst + i), v_src0, v_src1);
+
+ v_uint64 v_res0 = v_reinterpret_as_u64(v_src0 * vx_load((uint32_t*)m));
+ v_uint64 v_res1 = v_reinterpret_as_u64(v_src1 * vx_load((uint32_t*)m + VECSZ));
+ v_store((uint32_t*)dst, v_pack((v_res0 & vx_setall_u64(0xFFFFFFFF)) + (v_res0 >> 32),
+ (v_res1 & vx_setall_u64(0xFFFFFFFF)) + (v_res1 >> 32)));
}
#endif
for (; i < dst_max; i += 1, m += 2)
--- /dev/null
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Copyright (C) 2014-2015, Itseez Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "precomp.hpp"
+
+#include <vector>
+
+#include "opencv2/core/hal/intrin.hpp"
+#include "opencl_kernels_imgproc.hpp"
+
+#include "opencv2/core/openvx/ovx_defs.hpp"
+
+#include "filter.hpp"
+
+#include "opencv2/core/softfloat.hpp"
+
+namespace cv {
+#include "fixedpoint.inl.hpp"
+}
+
+#include "smooth.simd.hpp"
+#include "smooth.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
+
+namespace cv {
+
+/****************************************************************************************\
+ Gaussian Blur
+\****************************************************************************************/
+
+Mat getGaussianKernel(int n, double sigma, int ktype)
+{
+ CV_Assert(n > 0);
+ const int SMALL_GAUSSIAN_SIZE = 7;
+ static const float small_gaussian_tab[][SMALL_GAUSSIAN_SIZE] =
+ {
+ {1.f},
+ {0.25f, 0.5f, 0.25f},
+ {0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f},
+ {0.03125f, 0.109375f, 0.21875f, 0.28125f, 0.21875f, 0.109375f, 0.03125f}
+ };
+
+ const float* fixed_kernel = n % 2 == 1 && n <= SMALL_GAUSSIAN_SIZE && sigma <= 0 ?
+ small_gaussian_tab[n>>1] : 0;
+
+ CV_Assert( ktype == CV_32F || ktype == CV_64F );
+ Mat kernel(n, 1, ktype);
+ float* cf = kernel.ptr<float>();
+ double* cd = kernel.ptr<double>();
+
+ double sigmaX = sigma > 0 ? sigma : ((n-1)*0.5 - 1)*0.3 + 0.8;
+ double scale2X = -0.5/(sigmaX*sigmaX);
+ double sum = 0;
+
+ int i;
+ for( i = 0; i < n; i++ )
+ {
+ double x = i - (n-1)*0.5;
+ double t = fixed_kernel ? (double)fixed_kernel[i] : std::exp(scale2X*x*x);
+ if( ktype == CV_32F )
+ {
+ cf[i] = (float)t;
+ sum += cf[i];
+ }
+ else
+ {
+ cd[i] = t;
+ sum += cd[i];
+ }
+ }
+
+ CV_DbgAssert(fabs(sum) > 0);
+ sum = 1./sum;
+ for( i = 0; i < n; i++ )
+ {
+ if( ktype == CV_32F )
+ cf[i] = (float)(cf[i]*sum);
+ else
+ cd[i] *= sum;
+ }
+
+ return kernel;
+}
+
+template <typename T>
+static std::vector<T> getFixedpointGaussianKernel( int n, double sigma )
+{
+ if (sigma <= 0)
+ {
+ if(n == 1)
+ return std::vector<T>(1, softdouble(1.0));
+ else if(n == 3)
+ {
+ T v3[] = { softdouble(0.25), softdouble(0.5), softdouble(0.25) };
+ return std::vector<T>(v3, v3 + 3);
+ }
+ else if(n == 5)
+ {
+ T v5[] = { softdouble(0.0625), softdouble(0.25), softdouble(0.375), softdouble(0.25), softdouble(0.0625) };
+ return std::vector<T>(v5, v5 + 5);
+ }
+ else if(n == 7)
+ {
+ T v7[] = { softdouble(0.03125), softdouble(0.109375), softdouble(0.21875), softdouble(0.28125), softdouble(0.21875), softdouble(0.109375), softdouble(0.03125) };
+ return std::vector<T>(v7, v7 + 7);
+ }
+ }
+
+
+ softdouble sigmaX = sigma > 0 ? softdouble(sigma) : mulAdd(softdouble(n),softdouble(0.15),softdouble(0.35));// softdouble(((n-1)*0.5 - 1)*0.3 + 0.8)
+ softdouble scale2X = softdouble(-0.5*0.25)/(sigmaX*sigmaX);
+ std::vector<softdouble> values(n);
+ softdouble sum(0.);
+ for(int i = 0, x = 1 - n; i < n; i++, x+=2 )
+ {
+ // x = i - (n - 1)*0.5
+ // t = std::exp(scale2X*x*x)
+ values[i] = exp(softdouble(x*x)*scale2X);
+ sum += values[i];
+ }
+ sum = softdouble::one()/sum;
+
+ std::vector<T> kernel(n);
+ for(int i = 0; i < n; i++ )
+ {
+ kernel[i] = values[i] * sum;
+ }
+
+ return kernel;
+};
+
+static void getGaussianKernel(int n, double sigma, int ktype, Mat& res) { res = getGaussianKernel(n, sigma, ktype); }
+template <typename T> static void getGaussianKernel(int n, double sigma, int, std::vector<T>& res) { res = getFixedpointGaussianKernel<T>(n, sigma); }
+
+template <typename T>
+static void createGaussianKernels( T & kx, T & ky, int type, Size &ksize,
+ double sigma1, double sigma2 )
+{
+ int depth = CV_MAT_DEPTH(type);
+ if( sigma2 <= 0 )
+ sigma2 = sigma1;
+
+ // automatic detection of kernel size from sigma
+ if( ksize.width <= 0 && sigma1 > 0 )
+ ksize.width = cvRound(sigma1*(depth == CV_8U ? 3 : 4)*2 + 1)|1;
+ if( ksize.height <= 0 && sigma2 > 0 )
+ ksize.height = cvRound(sigma2*(depth == CV_8U ? 3 : 4)*2 + 1)|1;
+
+ CV_Assert( ksize.width > 0 && ksize.width % 2 == 1 &&
+ ksize.height > 0 && ksize.height % 2 == 1 );
+
+ sigma1 = std::max( sigma1, 0. );
+ sigma2 = std::max( sigma2, 0. );
+
+ getGaussianKernel( ksize.width, sigma1, std::max(depth, CV_32F), kx );
+ if( ksize.height == ksize.width && std::abs(sigma1 - sigma2) < DBL_EPSILON )
+ ky = kx;
+ else
+ getGaussianKernel( ksize.height, sigma2, std::max(depth, CV_32F), ky );
+}
+
+Ptr<FilterEngine> createGaussianFilter( int type, Size ksize,
+ double sigma1, double sigma2,
+ int borderType )
+{
+ Mat kx, ky;
+ createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2);
+
+ return createSeparableLinearFilter( type, type, kx, ky, Point(-1,-1), 0, borderType );
+}
+
+#ifdef HAVE_OPENCL
+
+static bool ocl_GaussianBlur_8UC1(InputArray _src, OutputArray _dst, Size ksize, int ddepth,
+ InputArray _kernelX, InputArray _kernelY, int borderType)
+{
+ const ocl::Device & dev = ocl::Device::getDefault();
+ int type = _src.type(), sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
+
+ if ( !(dev.isIntel() && (type == CV_8UC1) &&
+ (_src.offset() == 0) && (_src.step() % 4 == 0) &&
+ ((ksize.width == 5 && (_src.cols() % 4 == 0)) ||
+ (ksize.width == 3 && (_src.cols() % 16 == 0) && (_src.rows() % 2 == 0)))) )
+ return false;
+
+ Mat kernelX = _kernelX.getMat().reshape(1, 1);
+ if (kernelX.cols % 2 != 1)
+ return false;
+ Mat kernelY = _kernelY.getMat().reshape(1, 1);
+ if (kernelY.cols % 2 != 1)
+ return false;
+
+ if (ddepth < 0)
+ ddepth = sdepth;
+
+ Size size = _src.size();
+ size_t globalsize[2] = { 0, 0 };
+ size_t localsize[2] = { 0, 0 };
+
+ if (ksize.width == 3)
+ {
+ globalsize[0] = size.width / 16;
+ globalsize[1] = size.height / 2;
+ }
+ else if (ksize.width == 5)
+ {
+ globalsize[0] = size.width / 4;
+ globalsize[1] = size.height / 1;
+ }
+
+ const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", 0, "BORDER_REFLECT_101" };
+ char build_opts[1024];
+ sprintf(build_opts, "-D %s %s%s", borderMap[borderType & ~BORDER_ISOLATED],
+ ocl::kernelToStr(kernelX, CV_32F, "KERNEL_MATRIX_X").c_str(),
+ ocl::kernelToStr(kernelY, CV_32F, "KERNEL_MATRIX_Y").c_str());
+
+ ocl::Kernel kernel;
+
+ if (ksize.width == 3)
+ kernel.create("gaussianBlur3x3_8UC1_cols16_rows2", cv::ocl::imgproc::gaussianBlur3x3_oclsrc, build_opts);
+ else if (ksize.width == 5)
+ kernel.create("gaussianBlur5x5_8UC1_cols4", cv::ocl::imgproc::gaussianBlur5x5_oclsrc, build_opts);
+
+ if (kernel.empty())
+ return false;
+
+ UMat src = _src.getUMat();
+ _dst.create(size, CV_MAKETYPE(ddepth, cn));
+ if (!(_dst.offset() == 0 && _dst.step() % 4 == 0))
+ return false;
+ UMat dst = _dst.getUMat();
+
+ int idxArg = kernel.set(0, ocl::KernelArg::PtrReadOnly(src));
+ idxArg = kernel.set(idxArg, (int)src.step);
+ idxArg = kernel.set(idxArg, ocl::KernelArg::PtrWriteOnly(dst));
+ idxArg = kernel.set(idxArg, (int)dst.step);
+ idxArg = kernel.set(idxArg, (int)dst.rows);
+ idxArg = kernel.set(idxArg, (int)dst.cols);
+
+ return kernel.run(2, globalsize, (localsize[0] == 0) ? NULL : localsize, false);
+}
+
+#endif
+
+#ifdef HAVE_OPENVX
+
+namespace ovx {
+ template <> inline bool skipSmallImages<VX_KERNEL_GAUSSIAN_3x3>(int w, int h) { return w*h < 320 * 240; }
+}
+static bool openvx_gaussianBlur(InputArray _src, OutputArray _dst, Size ksize,
+ double sigma1, double sigma2, int borderType)
+{
+ if (sigma2 <= 0)
+ sigma2 = sigma1;
+ // automatic detection of kernel size from sigma
+ if (ksize.width <= 0 && sigma1 > 0)
+ ksize.width = cvRound(sigma1*6 + 1) | 1;
+ if (ksize.height <= 0 && sigma2 > 0)
+ ksize.height = cvRound(sigma2*6 + 1) | 1;
+
+ if (_src.type() != CV_8UC1 ||
+ _src.cols() < 3 || _src.rows() < 3 ||
+ ksize.width != 3 || ksize.height != 3)
+ return false;
+
+ sigma1 = std::max(sigma1, 0.);
+ sigma2 = std::max(sigma2, 0.);
+
+ if (!(sigma1 == 0.0 || (sigma1 - 0.8) < DBL_EPSILON) || !(sigma2 == 0.0 || (sigma2 - 0.8) < DBL_EPSILON) ||
+ ovx::skipSmallImages<VX_KERNEL_GAUSSIAN_3x3>(_src.cols(), _src.rows()))
+ return false;
+
+ Mat src = _src.getMat();
+ Mat dst = _dst.getMat();
+
+ if ((borderType & BORDER_ISOLATED) == 0 && src.isSubmatrix())
+ return false; //Process isolated borders only
+ vx_enum border;
+ switch (borderType & ~BORDER_ISOLATED)
+ {
+ case BORDER_CONSTANT:
+ border = VX_BORDER_CONSTANT;
+ break;
+ case BORDER_REPLICATE:
+ border = VX_BORDER_REPLICATE;
+ break;
+ default:
+ return false;
+ }
+
+ try
+ {
+ ivx::Context ctx = ovx::getOpenVXContext();
+
+ Mat a;
+ if (dst.data != src.data)
+ a = src;
+ else
+ src.copyTo(a);
+
+ ivx::Image
+ ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,
+ ivx::Image::createAddressing(a.cols, a.rows, 1, (vx_int32)(a.step)), a.data),
+ ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,
+ ivx::Image::createAddressing(dst.cols, dst.rows, 1, (vx_int32)(dst.step)), dst.data);
+
+ //ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments
+ //since OpenVX standard says nothing about thread-safety for now
+ ivx::border_t prevBorder = ctx.immediateBorder();
+ ctx.setImmediateBorder(border, (vx_uint8)(0));
+ ivx::IVX_CHECK_STATUS(vxuGaussian3x3(ctx, ia, ib));
+ ctx.setImmediateBorder(prevBorder);
+ }
+ catch (const ivx::RuntimeError & e)
+ {
+ VX_DbgThrow(e.what());
+ }
+ catch (const ivx::WrapperError & e)
+ {
+ VX_DbgThrow(e.what());
+ }
+ return true;
+}
+
+#endif
+
+#ifdef HAVE_IPP
+// IW 2017u2 has bug which doesn't allow use of partial inMem with tiling
+#if IPP_DISABLE_GAUSSIANBLUR_PARALLEL
+#define IPP_GAUSSIANBLUR_PARALLEL 0
+#else
+#define IPP_GAUSSIANBLUR_PARALLEL 1
+#endif
+
+#ifdef HAVE_IPP_IW
+
+class ipp_gaussianBlurParallel: public ParallelLoopBody
+{
+public:
+ ipp_gaussianBlurParallel(::ipp::IwiImage &src, ::ipp::IwiImage &dst, int kernelSize, float sigma, ::ipp::IwiBorderType &border, bool *pOk):
+ m_src(src), m_dst(dst), m_kernelSize(kernelSize), m_sigma(sigma), m_border(border), m_pOk(pOk) {
+ *m_pOk = true;
+ }
+ ~ipp_gaussianBlurParallel()
+ {
+ }
+
+ virtual void operator() (const Range& range) const CV_OVERRIDE
+ {
+ CV_INSTRUMENT_REGION_IPP();
+
+ if(!*m_pOk)
+ return;
+
+ try
+ {
+ ::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, m_dst.m_size.width, range.end - range.start);
+ CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterGaussian, m_src, m_dst, m_kernelSize, m_sigma, ::ipp::IwDefault(), m_border, tile);
+ }
+ catch(const ::ipp::IwException &)
+ {
+ *m_pOk = false;
+ return;
+ }
+ }
+private:
+ ::ipp::IwiImage &m_src;
+ ::ipp::IwiImage &m_dst;
+
+ int m_kernelSize;
+ float m_sigma;
+ ::ipp::IwiBorderType &m_border;
+
+ volatile bool *m_pOk;
+ const ipp_gaussianBlurParallel& operator= (const ipp_gaussianBlurParallel&);
+};
+
+#endif
+
+static bool ipp_GaussianBlur(InputArray _src, OutputArray _dst, Size ksize,
+ double sigma1, double sigma2, int borderType )
+{
+#ifdef HAVE_IPP_IW
+ CV_INSTRUMENT_REGION_IPP();
+
+#if IPP_VERSION_X100 < 201800 && ((defined _MSC_VER && defined _M_IX86) || (defined __GNUC__ && defined __i386__))
+ CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(ksize); CV_UNUSED(sigma1); CV_UNUSED(sigma2); CV_UNUSED(borderType);
+ return false; // bug on ia32
+#else
+ if(sigma1 != sigma2)
+ return false;
+
+ if(sigma1 < FLT_EPSILON)
+ return false;
+
+ if(ksize.width != ksize.height)
+ return false;
+
+ // Acquire data and begin processing
+ try
+ {
+ Mat src = _src.getMat();
+ Mat dst = _dst.getMat();
+ ::ipp::IwiImage iwSrc = ippiGetImage(src);
+ ::ipp::IwiImage iwDst = ippiGetImage(dst);
+ ::ipp::IwiBorderSize borderSize = ::ipp::iwiSizeToBorderSize(ippiGetSize(ksize));
+ ::ipp::IwiBorderType ippBorder(ippiGetBorder(iwSrc, borderType, borderSize));
+ if(!ippBorder)
+ return false;
+
+ const int threads = ippiSuggestThreadsNum(iwDst, 2);
+ if(IPP_GAUSSIANBLUR_PARALLEL && threads > 1) {
+ bool ok;
+ ipp_gaussianBlurParallel invoker(iwSrc, iwDst, ksize.width, (float) sigma1, ippBorder, &ok);
+
+ if(!ok)
+ return false;
+ const Range range(0, (int) iwDst.m_size.height);
+ parallel_for_(range, invoker, threads*4);
+
+ if(!ok)
+ return false;
+ } else {
+ CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterGaussian, iwSrc, iwDst, ksize.width, sigma1, ::ipp::IwDefault(), ippBorder);
+ }
+ }
+ catch (const ::ipp::IwException &)
+ {
+ return false;
+ }
+
+ return true;
+#endif
+#else
+ CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(ksize); CV_UNUSED(sigma1); CV_UNUSED(sigma2); CV_UNUSED(borderType);
+ return false;
+#endif
+}
+#endif
+
+void GaussianBlur(InputArray _src, OutputArray _dst, Size ksize,
+ double sigma1, double sigma2,
+ int borderType)
+{
+ CV_INSTRUMENT_REGION();
+
+ int type = _src.type();
+ Size size = _src.size();
+ _dst.create( size, type );
+
+ if( (borderType & ~BORDER_ISOLATED) != BORDER_CONSTANT &&
+ ((borderType & BORDER_ISOLATED) != 0 || !_src.getMat().isSubmatrix()) )
+ {
+ if( size.height == 1 )
+ ksize.height = 1;
+ if( size.width == 1 )
+ ksize.width = 1;
+ }
+
+ if( ksize.width == 1 && ksize.height == 1 )
+ {
+ _src.copyTo(_dst);
+ return;
+ }
+
+ bool useOpenCL = (ocl::isOpenCLActivated() && _dst.isUMat() && _src.dims() <= 2 &&
+ ((ksize.width == 3 && ksize.height == 3) ||
+ (ksize.width == 5 && ksize.height == 5)) &&
+ _src.rows() > ksize.height && _src.cols() > ksize.width);
+ CV_UNUSED(useOpenCL);
+
+ int sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
+
+ Mat kx, ky;
+ createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2);
+
+ CV_OCL_RUN(useOpenCL, ocl_GaussianBlur_8UC1(_src, _dst, ksize, CV_MAT_DEPTH(type), kx, ky, borderType));
+
+ CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && (size_t)_src.rows() > kx.total() && (size_t)_src.cols() > kx.total(),
+ ocl_sepFilter2D(_src, _dst, sdepth, kx, ky, Point(-1, -1), 0, borderType))
+
+ Mat src = _src.getMat();
+ Mat dst = _dst.getMat();
+
+ Point ofs;
+ Size wsz(src.cols, src.rows);
+ if(!(borderType & BORDER_ISOLATED))
+ src.locateROI( wsz, ofs );
+
+ CALL_HAL(gaussianBlur, cv_hal_gaussianBlur, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, cn,
+ ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, ksize.width, ksize.height,
+ sigma1, sigma2, borderType&~BORDER_ISOLATED);
+
+ CV_OVX_RUN(true,
+ openvx_gaussianBlur(src, dst, ksize, sigma1, sigma2, borderType))
+
+ CV_IPP_RUN_FAST(ipp_GaussianBlur(src, dst, ksize, sigma1, sigma2, borderType));
+
+ if(sdepth == CV_8U && ((borderType & BORDER_ISOLATED) || !_src.getMat().isSubmatrix()))
+ {
+ std::vector<ufixedpoint16> fkx, fky;
+ createGaussianKernels(fkx, fky, type, ksize, sigma1, sigma2);
+ if (src.data == dst.data)
+ src = src.clone();
+ CV_CPU_DISPATCH(GaussianBlurFixedPoint, (src, dst, (const uint16_t*)&fkx[0], (int)fkx.size(), (const uint16_t*)&fky[0], (int)fky.size(), borderType),
+ CV_CPU_DISPATCH_MODES_ALL);
+ return;
+ }
+
+ sepFilter2D(src, dst, sdepth, kx, ky, Point(-1, -1), 0, borderType);
+}
+
+} // namespace
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+CV_IMPL void
+cvSmooth( const void* srcarr, void* dstarr, int smooth_type,
+ int param1, int param2, double param3, double param4 )
+{
+ cv::Mat src = cv::cvarrToMat(srcarr), dst0 = cv::cvarrToMat(dstarr), dst = dst0;
+
+ CV_Assert( dst.size() == src.size() &&
+ (smooth_type == CV_BLUR_NO_SCALE || dst.type() == src.type()) );
+
+ if( param2 <= 0 )
+ param2 = param1;
+
+ if( smooth_type == CV_BLUR || smooth_type == CV_BLUR_NO_SCALE )
+ cv::boxFilter( src, dst, dst.depth(), cv::Size(param1, param2), cv::Point(-1,-1),
+ smooth_type == CV_BLUR, cv::BORDER_REPLICATE );
+ else if( smooth_type == CV_GAUSSIAN )
+ cv::GaussianBlur( src, dst, cv::Size(param1, param2), param3, param4, cv::BORDER_REPLICATE );
+ else if( smooth_type == CV_MEDIAN )
+ cv::medianBlur( src, dst, param1 );
+ else
+ cv::bilateralFilter( src, dst, param1, param3, param4, cv::BORDER_REPLICATE );
+
+ if( dst.data != dst0.data )
+ CV_Error( CV_StsUnmatchedFormats, "The destination image does not have the proper type" );
+}
+
+/* End of file. */
#include <vector>
#include "opencv2/core/hal/intrin.hpp"
-#include "opencl_kernels_imgproc.hpp"
-
-#include "opencv2/core/openvx/ovx_defs.hpp"
#include "filter.hpp"
-#include "fixedpoint.inl.hpp"
-
-/****************************************************************************************\
- Gaussian Blur
-\****************************************************************************************/
-
-cv::Mat cv::getGaussianKernel( int n, double sigma, int ktype )
-{
- CV_Assert(n > 0);
- const int SMALL_GAUSSIAN_SIZE = 7;
- static const float small_gaussian_tab[][SMALL_GAUSSIAN_SIZE] =
- {
- {1.f},
- {0.25f, 0.5f, 0.25f},
- {0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f},
- {0.03125f, 0.109375f, 0.21875f, 0.28125f, 0.21875f, 0.109375f, 0.03125f}
- };
-
- const float* fixed_kernel = n % 2 == 1 && n <= SMALL_GAUSSIAN_SIZE && sigma <= 0 ?
- small_gaussian_tab[n>>1] : 0;
-
- CV_Assert( ktype == CV_32F || ktype == CV_64F );
- Mat kernel(n, 1, ktype);
- float* cf = kernel.ptr<float>();
- double* cd = kernel.ptr<double>();
-
- double sigmaX = sigma > 0 ? sigma : ((n-1)*0.5 - 1)*0.3 + 0.8;
- double scale2X = -0.5/(sigmaX*sigmaX);
- double sum = 0;
-
- int i;
- for( i = 0; i < n; i++ )
- {
- double x = i - (n-1)*0.5;
- double t = fixed_kernel ? (double)fixed_kernel[i] : std::exp(scale2X*x*x);
- if( ktype == CV_32F )
- {
- cf[i] = (float)t;
- sum += cf[i];
- }
- else
- {
- cd[i] = t;
- sum += cd[i];
- }
- }
-
- CV_DbgAssert(fabs(sum) > 0);
- sum = 1./sum;
- for( i = 0; i < n; i++ )
- {
- if( ktype == CV_32F )
- cf[i] = (float)(cf[i]*sum);
- else
- cd[i] *= sum;
- }
-
- return kernel;
-}
+#include "opencv2/core/softfloat.hpp"
namespace cv {
+CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
+// forward declarations
+void GaussianBlurFixedPoint(const Mat& src, /*const*/ Mat& dst,
+ const uint16_t/*ufixedpoint16*/* fkx, int fkx_size,
+ const uint16_t/*ufixedpoint16*/* fky, int fky_size,
+ int borderType);
-template <typename T>
-static std::vector<T> getFixedpointGaussianKernel( int n, double sigma )
-{
- if (sigma <= 0)
- {
- if(n == 1)
- return std::vector<T>(1, softdouble(1.0));
- else if(n == 3)
- {
- T v3[] = { softdouble(0.25), softdouble(0.5), softdouble(0.25) };
- return std::vector<T>(v3, v3 + 3);
- }
- else if(n == 5)
- {
- T v5[] = { softdouble(0.0625), softdouble(0.25), softdouble(0.375), softdouble(0.25), softdouble(0.0625) };
- return std::vector<T>(v5, v5 + 5);
- }
- else if(n == 7)
- {
- T v7[] = { softdouble(0.03125), softdouble(0.109375), softdouble(0.21875), softdouble(0.28125), softdouble(0.21875), softdouble(0.109375), softdouble(0.03125) };
- return std::vector<T>(v7, v7 + 7);
- }
- }
-
-
- softdouble sigmaX = sigma > 0 ? softdouble(sigma) : mulAdd(softdouble(n),softdouble(0.15),softdouble(0.35));// softdouble(((n-1)*0.5 - 1)*0.3 + 0.8)
- softdouble scale2X = softdouble(-0.5*0.25)/(sigmaX*sigmaX);
- std::vector<softdouble> values(n);
- softdouble sum(0.);
- for(int i = 0, x = 1 - n; i < n; i++, x+=2 )
- {
- // x = i - (n - 1)*0.5
- // t = std::exp(scale2X*x*x)
- values[i] = exp(softdouble(x*x)*scale2X);
- sum += values[i];
- }
- sum = softdouble::one()/sum;
+#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
- std::vector<T> kernel(n);
- for(int i = 0; i < n; i++ )
- {
- kernel[i] = values[i] * sum;
- }
+#if defined(CV_CPU_BASELINE_MODE)
+// included in dispatch.cpp
+#else
+#include "fixedpoint.inl.hpp"
+#endif
- return kernel;
-};
+namespace {
template <typename ET, typename FT>
void hlineSmooth1N(const ET* src, int cn, const FT* m, int, FT* dst, int len, int)
fixedSmoothInvoker& operator=(const fixedSmoothInvoker&);
};
-static void getGaussianKernel(int n, double sigma, int ktype, Mat& res) { res = getGaussianKernel(n, sigma, ktype); }
-template <typename T> static void getGaussianKernel(int n, double sigma, int, std::vector<T>& res) { res = getFixedpointGaussianKernel<T>(n, sigma); }
-
-template <typename T>
-static void createGaussianKernels( T & kx, T & ky, int type, Size &ksize,
- double sigma1, double sigma2 )
-{
- int depth = CV_MAT_DEPTH(type);
- if( sigma2 <= 0 )
- sigma2 = sigma1;
-
- // automatic detection of kernel size from sigma
- if( ksize.width <= 0 && sigma1 > 0 )
- ksize.width = cvRound(sigma1*(depth == CV_8U ? 3 : 4)*2 + 1)|1;
- if( ksize.height <= 0 && sigma2 > 0 )
- ksize.height = cvRound(sigma2*(depth == CV_8U ? 3 : 4)*2 + 1)|1;
-
- CV_Assert( ksize.width > 0 && ksize.width % 2 == 1 &&
- ksize.height > 0 && ksize.height % 2 == 1 );
-
- sigma1 = std::max( sigma1, 0. );
- sigma2 = std::max( sigma2, 0. );
+} // namespace anon
- getGaussianKernel( ksize.width, sigma1, std::max(depth, CV_32F), kx );
- if( ksize.height == ksize.width && std::abs(sigma1 - sigma2) < DBL_EPSILON )
- ky = kx;
- else
- getGaussianKernel( ksize.height, sigma2, std::max(depth, CV_32F), ky );
-}
-
-}
-
-cv::Ptr<cv::FilterEngine> cv::createGaussianFilter( int type, Size ksize,
- double sigma1, double sigma2,
- int borderType )
-{
- Mat kx, ky;
- createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2);
-
- return createSeparableLinearFilter( type, type, kx, ky, Point(-1,-1), 0, borderType );
-}
-
-namespace cv
-{
-#ifdef HAVE_OPENCL
-
-static bool ocl_GaussianBlur_8UC1(InputArray _src, OutputArray _dst, Size ksize, int ddepth,
- InputArray _kernelX, InputArray _kernelY, int borderType)
-{
- const ocl::Device & dev = ocl::Device::getDefault();
- int type = _src.type(), sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
-
- if ( !(dev.isIntel() && (type == CV_8UC1) &&
- (_src.offset() == 0) && (_src.step() % 4 == 0) &&
- ((ksize.width == 5 && (_src.cols() % 4 == 0)) ||
- (ksize.width == 3 && (_src.cols() % 16 == 0) && (_src.rows() % 2 == 0)))) )
- return false;
-
- Mat kernelX = _kernelX.getMat().reshape(1, 1);
- if (kernelX.cols % 2 != 1)
- return false;
- Mat kernelY = _kernelY.getMat().reshape(1, 1);
- if (kernelY.cols % 2 != 1)
- return false;
-
- if (ddepth < 0)
- ddepth = sdepth;
-
- Size size = _src.size();
- size_t globalsize[2] = { 0, 0 };
- size_t localsize[2] = { 0, 0 };
-
- if (ksize.width == 3)
- {
- globalsize[0] = size.width / 16;
- globalsize[1] = size.height / 2;
- }
- else if (ksize.width == 5)
- {
- globalsize[0] = size.width / 4;
- globalsize[1] = size.height / 1;
- }
-
- const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", 0, "BORDER_REFLECT_101" };
- char build_opts[1024];
- sprintf(build_opts, "-D %s %s%s", borderMap[borderType & ~BORDER_ISOLATED],
- ocl::kernelToStr(kernelX, CV_32F, "KERNEL_MATRIX_X").c_str(),
- ocl::kernelToStr(kernelY, CV_32F, "KERNEL_MATRIX_Y").c_str());
-
- ocl::Kernel kernel;
-
- if (ksize.width == 3)
- kernel.create("gaussianBlur3x3_8UC1_cols16_rows2", cv::ocl::imgproc::gaussianBlur3x3_oclsrc, build_opts);
- else if (ksize.width == 5)
- kernel.create("gaussianBlur5x5_8UC1_cols4", cv::ocl::imgproc::gaussianBlur5x5_oclsrc, build_opts);
-
- if (kernel.empty())
- return false;
-
- UMat src = _src.getUMat();
- _dst.create(size, CV_MAKETYPE(ddepth, cn));
- if (!(_dst.offset() == 0 && _dst.step() % 4 == 0))
- return false;
- UMat dst = _dst.getUMat();
-
- int idxArg = kernel.set(0, ocl::KernelArg::PtrReadOnly(src));
- idxArg = kernel.set(idxArg, (int)src.step);
- idxArg = kernel.set(idxArg, ocl::KernelArg::PtrWriteOnly(dst));
- idxArg = kernel.set(idxArg, (int)dst.step);
- idxArg = kernel.set(idxArg, (int)dst.rows);
- idxArg = kernel.set(idxArg, (int)dst.cols);
-
- return kernel.run(2, globalsize, (localsize[0] == 0) ? NULL : localsize, false);
-}
-
-#endif
-
-#ifdef HAVE_OPENVX
-
-namespace ovx {
- template <> inline bool skipSmallImages<VX_KERNEL_GAUSSIAN_3x3>(int w, int h) { return w*h < 320 * 240; }
-}
-static bool openvx_gaussianBlur(InputArray _src, OutputArray _dst, Size ksize,
- double sigma1, double sigma2, int borderType)
-{
- if (sigma2 <= 0)
- sigma2 = sigma1;
- // automatic detection of kernel size from sigma
- if (ksize.width <= 0 && sigma1 > 0)
- ksize.width = cvRound(sigma1*6 + 1) | 1;
- if (ksize.height <= 0 && sigma2 > 0)
- ksize.height = cvRound(sigma2*6 + 1) | 1;
-
- if (_src.type() != CV_8UC1 ||
- _src.cols() < 3 || _src.rows() < 3 ||
- ksize.width != 3 || ksize.height != 3)
- return false;
-
- sigma1 = std::max(sigma1, 0.);
- sigma2 = std::max(sigma2, 0.);
-
- if (!(sigma1 == 0.0 || (sigma1 - 0.8) < DBL_EPSILON) || !(sigma2 == 0.0 || (sigma2 - 0.8) < DBL_EPSILON) ||
- ovx::skipSmallImages<VX_KERNEL_GAUSSIAN_3x3>(_src.cols(), _src.rows()))
- return false;
-
- Mat src = _src.getMat();
- Mat dst = _dst.getMat();
-
- if ((borderType & BORDER_ISOLATED) == 0 && src.isSubmatrix())
- return false; //Process isolated borders only
- vx_enum border;
- switch (borderType & ~BORDER_ISOLATED)
- {
- case BORDER_CONSTANT:
- border = VX_BORDER_CONSTANT;
- break;
- case BORDER_REPLICATE:
- border = VX_BORDER_REPLICATE;
- break;
- default:
- return false;
- }
-
- try
- {
- ivx::Context ctx = ovx::getOpenVXContext();
-
- Mat a;
- if (dst.data != src.data)
- a = src;
- else
- src.copyTo(a);
-
- ivx::Image
- ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,
- ivx::Image::createAddressing(a.cols, a.rows, 1, (vx_int32)(a.step)), a.data),
- ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,
- ivx::Image::createAddressing(dst.cols, dst.rows, 1, (vx_int32)(dst.step)), dst.data);
-
- //ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments
- //since OpenVX standard says nothing about thread-safety for now
- ivx::border_t prevBorder = ctx.immediateBorder();
- ctx.setImmediateBorder(border, (vx_uint8)(0));
- ivx::IVX_CHECK_STATUS(vxuGaussian3x3(ctx, ia, ib));
- ctx.setImmediateBorder(prevBorder);
- }
- catch (const ivx::RuntimeError & e)
- {
- VX_DbgThrow(e.what());
- }
- catch (const ivx::WrapperError & e)
- {
- VX_DbgThrow(e.what());
- }
- return true;
-}
-
-#endif
-
-#if 0 //defined HAVE_IPP
-// IW 2017u2 has bug which doesn't allow use of partial inMem with tiling
-#if IPP_DISABLE_GAUSSIANBLUR_PARALLEL
-#define IPP_GAUSSIANBLUR_PARALLEL 0
-#else
-#define IPP_GAUSSIANBLUR_PARALLEL 1
-#endif
-
-#ifdef HAVE_IPP_IW
-
-class ipp_gaussianBlurParallel: public ParallelLoopBody
-{
-public:
- ipp_gaussianBlurParallel(::ipp::IwiImage &src, ::ipp::IwiImage &dst, int kernelSize, float sigma, ::ipp::IwiBorderType &border, bool *pOk):
- m_src(src), m_dst(dst), m_kernelSize(kernelSize), m_sigma(sigma), m_border(border), m_pOk(pOk) {
- *m_pOk = true;
- }
- ~ipp_gaussianBlurParallel()
- {
- }
-
- virtual void operator() (const Range& range) const CV_OVERRIDE
- {
- CV_INSTRUMENT_REGION_IPP();
-
- if(!*m_pOk)
- return;
-
- try
- {
- ::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, m_dst.m_size.width, range.end - range.start);
- CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterGaussian, m_src, m_dst, m_kernelSize, m_sigma, ::ipp::IwDefault(), m_border, tile);
- }
- catch(const ::ipp::IwException &)
- {
- *m_pOk = false;
- return;
- }
- }
-private:
- ::ipp::IwiImage &m_src;
- ::ipp::IwiImage &m_dst;
-
- int m_kernelSize;
- float m_sigma;
- ::ipp::IwiBorderType &m_border;
-
- volatile bool *m_pOk;
- const ipp_gaussianBlurParallel& operator= (const ipp_gaussianBlurParallel&);
-};
-
-#endif
-
-static bool ipp_GaussianBlur(InputArray _src, OutputArray _dst, Size ksize,
- double sigma1, double sigma2, int borderType )
-{
-#ifdef HAVE_IPP_IW
- CV_INSTRUMENT_REGION_IPP();
-
-#if IPP_VERSION_X100 < 201800 && ((defined _MSC_VER && defined _M_IX86) || (defined __GNUC__ && defined __i386__))
- CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(ksize); CV_UNUSED(sigma1); CV_UNUSED(sigma2); CV_UNUSED(borderType);
- return false; // bug on ia32
-#else
- if(sigma1 != sigma2)
- return false;
-
- if(sigma1 < FLT_EPSILON)
- return false;
-
- if(ksize.width != ksize.height)
- return false;
-
- // Acquire data and begin processing
- try
- {
- Mat src = _src.getMat();
- Mat dst = _dst.getMat();
- ::ipp::IwiImage iwSrc = ippiGetImage(src);
- ::ipp::IwiImage iwDst = ippiGetImage(dst);
- ::ipp::IwiBorderSize borderSize = ::ipp::iwiSizeToBorderSize(ippiGetSize(ksize));
- ::ipp::IwiBorderType ippBorder(ippiGetBorder(iwSrc, borderType, borderSize));
- if(!ippBorder)
- return false;
-
- const int threads = ippiSuggestThreadsNum(iwDst, 2);
- if(IPP_GAUSSIANBLUR_PARALLEL && threads > 1) {
- bool ok;
- ipp_gaussianBlurParallel invoker(iwSrc, iwDst, ksize.width, (float) sigma1, ippBorder, &ok);
-
- if(!ok)
- return false;
- const Range range(0, (int) iwDst.m_size.height);
- parallel_for_(range, invoker, threads*4);
-
- if(!ok)
- return false;
- } else {
- CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterGaussian, iwSrc, iwDst, ksize.width, sigma1, ::ipp::IwDefault(), ippBorder);
- }
- }
- catch (const ::ipp::IwException &)
- {
- return false;
- }
-
- return true;
-#endif
-#else
- CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(ksize); CV_UNUSED(sigma1); CV_UNUSED(sigma2); CV_UNUSED(borderType);
- return false;
-#endif
-}
-#endif
-}
-
-void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize,
- double sigma1, double sigma2,
- int borderType )
+void GaussianBlurFixedPoint(const Mat& src, /*const*/ Mat& dst,
+ const uint16_t/*ufixedpoint16*/* fkx, int fkx_size,
+ const uint16_t/*ufixedpoint16*/* fky, int fky_size,
+ int borderType)
{
CV_INSTRUMENT_REGION();
- int type = _src.type();
- Size size = _src.size();
- _dst.create( size, type );
-
- if( (borderType & ~BORDER_ISOLATED) != BORDER_CONSTANT &&
- ((borderType & BORDER_ISOLATED) != 0 || !_src.getMat().isSubmatrix()) )
+ CV_Assert(src.depth() == CV_8U && ((borderType & BORDER_ISOLATED) || !src.isSubmatrix()));
+ fixedSmoothInvoker<uint8_t, ufixedpoint16> invoker(
+ src.ptr<uint8_t>(), src.step1(),
+ dst.ptr<uint8_t>(), dst.step1(), dst.cols, dst.rows, dst.channels(),
+ (const ufixedpoint16*)fkx, fkx_size, (const ufixedpoint16*)fky, fky_size,
+ borderType & ~BORDER_ISOLATED);
{
- if( size.height == 1 )
- ksize.height = 1;
- if( size.width == 1 )
- ksize.width = 1;
- }
-
- if( ksize.width == 1 && ksize.height == 1 )
- {
- _src.copyTo(_dst);
- return;
- }
-
- bool useOpenCL = (ocl::isOpenCLActivated() && _dst.isUMat() && _src.dims() <= 2 &&
- ((ksize.width == 3 && ksize.height == 3) ||
- (ksize.width == 5 && ksize.height == 5)) &&
- _src.rows() > ksize.height && _src.cols() > ksize.width);
- CV_UNUSED(useOpenCL);
-
- int sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
-
- Mat kx, ky;
- createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2);
-
- CV_OCL_RUN(useOpenCL, ocl_GaussianBlur_8UC1(_src, _dst, ksize, CV_MAT_DEPTH(type), kx, ky, borderType));
-
- CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && (size_t)_src.rows() > kx.total() && (size_t)_src.cols() > kx.total(),
- ocl_sepFilter2D(_src, _dst, sdepth, kx, ky, Point(-1, -1), 0, borderType))
-
- Mat src = _src.getMat();
- Mat dst = _dst.getMat();
-
- Point ofs;
- Size wsz(src.cols, src.rows);
- if(!(borderType & BORDER_ISOLATED))
- src.locateROI( wsz, ofs );
-
- CALL_HAL(gaussianBlur, cv_hal_gaussianBlur, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, cn,
- ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, ksize.width, ksize.height,
- sigma1, sigma2, borderType&~BORDER_ISOLATED);
-
- CV_OVX_RUN(true,
- openvx_gaussianBlur(src, dst, ksize, sigma1, sigma2, borderType))
-
- //CV_IPP_RUN_FAST(ipp_GaussianBlur(src, dst, ksize, sigma1, sigma2, borderType));
-
- if(sdepth == CV_8U && ((borderType & BORDER_ISOLATED) || !_src.getMat().isSubmatrix()))
- {
- std::vector<ufixedpoint16> fkx, fky;
- createGaussianKernels(fkx, fky, type, ksize, sigma1, sigma2);
- if (src.data == dst.data)
- src = src.clone();
- fixedSmoothInvoker<uint8_t, ufixedpoint16> invoker(src.ptr<uint8_t>(), src.step1(), dst.ptr<uint8_t>(), dst.step1(), dst.cols, dst.rows, dst.channels(), &fkx[0], (int)fkx.size(), &fky[0], (int)fky.size(), borderType & ~BORDER_ISOLATED);
+ // TODO AVX guard (external call)
parallel_for_(Range(0, dst.rows), invoker, std::max(1, std::min(getNumThreads(), getNumberOfCPUs())));
- return;
}
-
- sepFilter2D(src, dst, sdepth, kx, ky, Point(-1, -1), 0, borderType);
}
-//////////////////////////////////////////////////////////////////////////////////////////
-
-CV_IMPL void
-cvSmooth( const void* srcarr, void* dstarr, int smooth_type,
- int param1, int param2, double param3, double param4 )
-{
- cv::Mat src = cv::cvarrToMat(srcarr), dst0 = cv::cvarrToMat(dstarr), dst = dst0;
-
- CV_Assert( dst.size() == src.size() &&
- (smooth_type == CV_BLUR_NO_SCALE || dst.type() == src.type()) );
-
- if( param2 <= 0 )
- param2 = param1;
-
- if( smooth_type == CV_BLUR || smooth_type == CV_BLUR_NO_SCALE )
- cv::boxFilter( src, dst, dst.depth(), cv::Size(param1, param2), cv::Point(-1,-1),
- smooth_type == CV_BLUR, cv::BORDER_REPLICATE );
- else if( smooth_type == CV_GAUSSIAN )
- cv::GaussianBlur( src, dst, cv::Size(param1, param2), param3, param4, cv::BORDER_REPLICATE );
- else if( smooth_type == CV_MEDIAN )
- cv::medianBlur( src, dst, param1 );
- else
- cv::bilateralFilter( src, dst, param1, param3, param4, cv::BORDER_REPLICATE );
-
- if( dst.data != dst0.data )
- CV_Error( CV_StsUnmatchedFormats, "The destination image does not have the proper type" );
-}
-
-/* End of file. */
+#endif
+CV_CPU_OPTIMIZATION_NAMESPACE_END
+} // namespace
// NOTE: Look at the bottom of the file for the entry-point function for external callers
//
-// At the moment only 3 channel support untilted is supported
-// More channel support coming soon.
-// TODO: Add support for sqsum and 1,2, and 4 channels
-class IntegralCalculator_3Channel {
+template<size_t num_channels> class IntegralCalculator;
+
+template<size_t num_channels>
+class IntegralCalculator {
public:
- IntegralCalculator_3Channel() {};
+ IntegralCalculator() {};
void calculate_integral_avx512(const uchar *src, size_t _srcstep,
double *sum, size_t _sumstep,
double *sqsum, size_t _sqsumstep,
- int width, int height, int cn)
+ int width, int height)
{
const int srcstep = (int)(_srcstep/sizeof(uchar));
const int sumstep = (int)(_sumstep/sizeof(double));
const int sqsumstep = (int)(_sqsumstep/sizeof(double));
- const int ops_per_line = width * cn;
+ const int ops_per_line = width * num_channels;
// Clear the first line of the sum as per spec (see integral documentation)
// Also adjust the index of sum and sqsum to be at the real 0th element
// and not point to the border pixel so it stays in sync with the src pointer
- memset( sum, 0, (ops_per_line+cn)*sizeof(double));
- sum += cn;
+ memset( sum, 0, (ops_per_line+num_channels)*sizeof(double));
+ sum += num_channels;
if (sqsum) {
- memset( sqsum, 0, (ops_per_line+cn)*sizeof(double));
- sqsum += cn;
+ memset( sqsum, 0, (ops_per_line+num_channels)*sizeof(double));
+ sqsum += num_channels;
}
// Now calculate the integral over the whole image one line at a time
double * sqsum_above = (sqsum) ? &sqsum[y*sqsumstep] : NULL;
double * sqsum_line = (sqsum) ? &sqsum_above[sqsumstep] : NULL;
- integral_line_3channel_avx512(src_line, sum_line, sum_above, sqsum_line, sqsum_above, ops_per_line);
+ calculate_integral_for_line(src_line, sum_line, sum_above, sqsum_line, sqsum_above, ops_per_line);
}
}
- static inline
- void integral_line_3channel_avx512(const uchar *srcs,
- double *sums, double *sums_above,
- double *sqsums, double *sqsums_above,
- int num_ops_in_line)
+ static CV_ALWAYS_INLINE
+ void calculate_integral_for_line(const uchar *srcs,
+ double *sums, double *sums_above,
+ double *sqsums, double *sqsums_above,
+ int num_ops_in_line)
{
__m512i sum_accumulator = _mm512_setzero_si512(); // holds rolling sums for the line
__m512i sqsum_accumulator = _mm512_setzero_si512(); // holds rolling sqsums for the line
// The first element on each line must be zeroes as per spec (see integral documentation)
- set_border_pixel_value(sums, sqsums);
+ zero_out_border_pixel(sums, sqsums);
// Do all 64 byte chunk operations then do the last bits that don't fit in a 64 byte chunk
aligned_integral( srcs, sums, sums_above, sqsums, sqsums_above, sum_accumulator, sqsum_accumulator, num_ops_in_line);
}
- static inline
- void set_border_pixel_value(double *sums, double *sqsums)
+ static CV_ALWAYS_INLINE
+ void zero_out_border_pixel(double *sums, double *sqsums)
{
- // Sets the border pixel value to 0s.
- // Note the hard coded -3 and the 0x7 mask is because we only support 3 channel right now
- __m512i zeroes = _mm512_setzero_si512();
-
- _mm512_mask_storeu_epi64(&sums[-3], 0x7, zeroes);
+ // Note the negative index is because the sums/sqsums pointers point to the first real pixel
+ // after the border pixel so we have to look backwards
+ _mm512_mask_storeu_epi64(&sums[-num_channels], (1<<num_channels)-1, _mm512_setzero_si512());
if (sqsums)
- _mm512_mask_storeu_epi64(&sqsums[-3], 0x7, zeroes);
+ _mm512_mask_storeu_epi64(&sqsums[-num_channels], (1<<num_channels)-1, _mm512_setzero_si512());
}
- static inline
+ static CV_ALWAYS_INLINE
void aligned_integral(const uchar *&srcs,
double *&sums, double *&sums_above,
double *&sqsum, double *&sqsum_above,
}
- static inline
+ static CV_ALWAYS_INLINE
void post_aligned_integral(const uchar *srcs,
const double *sums, const double *sums_above,
const double *sqsum, const double *sqsum_above,
}
- static inline
+ static CV_ALWAYS_INLINE
void integral_64_operations_avx512(const __m512i *srcs,
__m512i *sums, const __m512i *sums_above,
__m512i *sqsums, const __m512i *sqsums_above,
__mmask64 data_mask,
__m512i &sum_accumulator, __m512i &sqsum_accumulator)
{
- __m512i src_64byte_chunk = read_64_bytes(srcs, data_mask);
-
- for(int num_16byte_chunks=0; num_16byte_chunks<4; num_16byte_chunks++) {
- __m128i src_16bytes = _mm512_extracti64x2_epi64(src_64byte_chunk, 0x0); // Get lower 16 bytes of data
+ __m512i src_64byte_chunk = read_64_bytes(srcs, data_mask);
- for (int num_8byte_chunks = 0; num_8byte_chunks < 2; num_8byte_chunks++) {
+ while (data_mask) {
+ __m128i src_16bytes = extract_lower_16bytes(src_64byte_chunk);
- __m512i src_longs = convert_lower_8bytes_to_longs(src_16bytes);
+ __m512i src_longs_lo = convert_lower_8bytes_to_longs(src_16bytes);
+ __m512i src_longs_hi = convert_lower_8bytes_to_longs(shift_right_8_bytes(src_16bytes));
- // Calculate integral for the sum on the 8 entries
- integral_8_operations(src_longs, sums_above, data_mask, sums, sum_accumulator);
- sums++; sums_above++;
+ // Calculate integral for the sum on the 8 lanes at a time
+ integral_8_operations(src_longs_lo, sums_above, data_mask, sums, sum_accumulator);
+ integral_8_operations(src_longs_hi, sums_above+1, data_mask>>8, sums+1, sum_accumulator);
- if (sqsums){ // Calculate integral for the sum on the 8 entries
- __m512i squared_source = _mm512_mullo_epi64(src_longs, src_longs);
-
- integral_8_operations(squared_source, sqsums_above, data_mask, sqsums, sqsum_accumulator);
- sqsums++; sqsums_above++;
- }
-
- // Prepare for next iteration of inner loop
- // shift source to align next 8 bytes to lane 0 and shift the mask
- src_16bytes = shift_right_8_bytes(src_16bytes);
- data_mask = data_mask >> 8;
+ if (sqsums) {
+ __m512i squared_source_lo = square_m512(src_longs_lo);
+ __m512i squared_source_hi = square_m512(src_longs_hi);
+ integral_8_operations(squared_source_lo, sqsums_above, data_mask, sqsums, sqsum_accumulator);
+ integral_8_operations(squared_source_hi, sqsums_above+1, data_mask>>8, sqsums+1, sqsum_accumulator);
+ sqsums += 2;
+ sqsums_above+=2;
}
- // Prepare for next iteration of outer loop
+ // Prepare for next iteration of loop
+ // shift source to align next 16 bytes to lane 0, shift the mask, and advance the pointers
+ sums += 2;
+ sums_above += 2;
+ data_mask = data_mask >> 16;
src_64byte_chunk = shift_right_16_bytes(src_64byte_chunk);
+
}
+
}
- static inline
+ static CV_ALWAYS_INLINE
void integral_8_operations(const __m512i src_longs, const __m512i *above_values_ptr, __mmask64 data_mask,
__m512i *results_ptr, __m512i &accumulator)
{
+ // NOTE that the calculate_integral function referenced here must be implemented in the templated
+ // derivatives because the algorithm depends heavily on the number of channels in the image
+ //
_mm512_mask_storeu_pd(
results_ptr, // Store the result here
data_mask, // Using the data mask to avoid overrunning the line
}
- static inline
- __m512d calculate_integral(__m512i src_longs, const __m512d above_values, __m512i &accumulator)
- {
- __m512i carryover_idxs = _mm512_set_epi64(6, 5, 7, 6, 5, 7, 6, 5);
-
- // Align data to prepare for the adds:
- // shifts data left by 3 and 6 qwords(lanes) and gets rolling sum in all lanes
- // Vertical LANES: 76543210
- // src_longs : HGFEDCBA
- // shited3lanes : + EDCBA
- // shifted6lanes : + BA
- // carry_over_idxs : + 65765765 (index position of result from previous iteration)
- // = integral
- __m512i shifted3lanes = _mm512_maskz_expand_epi64(0xF8, src_longs);
- __m512i shifted6lanes = _mm512_maskz_expand_epi64(0xC0, src_longs);
- __m512i carry_over = _mm512_permutex2var_epi64(accumulator, carryover_idxs, accumulator);
-
- // Do the adds in tree form (shift3 + shift 6) + (current_source_values + accumulator)
- __m512i sum_shift3and6 = _mm512_add_epi64(shifted3lanes, shifted6lanes);
- __m512i sum_src_carry = _mm512_add_epi64(src_longs, carry_over);
- accumulator = _mm512_add_epi64(sum_shift3and6, sum_src_carry);
-
- // Convert to packed double and add to the line above to get the true integral value
- __m512d accumulator_pd = _mm512_cvtepu64_pd(accumulator);
- __m512d integral_pd = _mm512_add_pd(accumulator_pd, above_values);
- return integral_pd;
+ static CV_ALWAYS_INLINE
+ __m512i read_64_bytes(const __m512i *srcs, const __mmask64 data_mask) {
+ return _mm512_maskz_loadu_epi8(data_mask, srcs);
}
- static inline
- __m512i read_64_bytes(const __m512i *srcs, __mmask64 data_mask) {
- return _mm512_maskz_loadu_epi8(data_mask, srcs);
+ static CV_ALWAYS_INLINE
+ __m128i extract_lower_16bytes(const __m512i src_64byte_chunk) {
+ return _mm512_extracti64x2_epi64(src_64byte_chunk, 0x0);
}
- static inline
- __m512i convert_lower_8bytes_to_longs(__m128i src_16bytes) {
+ static CV_ALWAYS_INLINE
+ __m512i convert_lower_8bytes_to_longs(const __m128i src_16bytes) {
return _mm512_cvtepu8_epi64(src_16bytes);
}
- static inline
- __m128i shift_right_8_bytes(__m128i src_16bytes) {
+ static CV_ALWAYS_INLINE
+ __m512i square_m512(const __m512i src_longs) {
+ return _mm512_mullo_epi64(src_longs, src_longs);
+ }
+
+
+ static CV_ALWAYS_INLINE
+ __m128i shift_right_8_bytes(const __m128i src_16bytes) {
return _mm_maskz_compress_epi64(2, src_16bytes);
}
- static inline
- __m512i shift_right_16_bytes(__m512i src_64byte_chunk) {
+ static CV_ALWAYS_INLINE
+ __m512i shift_right_16_bytes(const __m512i src_64byte_chunk) {
return _mm512_maskz_compress_epi64(0xFC, src_64byte_chunk);
}
+
+ static CV_ALWAYS_INLINE
+ __m512i m512_hadd(const __m512i a){
+ return _mm512_add_epi64(_mm512_maskz_compress_epi64(0xAA, a), _mm512_maskz_compress_epi64(0x55, a));
+ }
+
+
+ // The calculate_integral function referenced here must be implemented in the templated derivatives
+ // because the algorithm depends heavily on the number of channels in the image
+ // This is the incomplete definition (just the prototype) here.
+ //
+ static CV_ALWAYS_INLINE
+ __m512d calculate_integral(const __m512i src_longs, const __m512d above_values, __m512i &accumulator);
+
};
+
+
+//============================================================================================================
+// This the only section that needs to change with respect to algorithm based on the number of channels
+// It is responsible for returning the calculation of 8 lanes worth of the integral and returning in the
+// accumulated sums in the accumulator parameter (NOTE: accumulator is an input and output parameter)
+//
+// The function prototype that needs to be implemented is:
+//
+// __m512d calculate_integral(const __m512i src_longs, const __m512d above_values, __m512i &accumulator){ ... }
+//
+// Description of parameters:
+// INPUTS:
+// src_longs : 8 lanes worth of the source bytes converted to 64 bit integers
+// above_values: 8 lanes worth of the result values from the line above (See the integral spec)
+// accumulator : 8 lanes worth of sums from the previous iteration
+// IMPORTANT NOTE: This parameter is both an INPUT AND OUTPUT parameter to this function
+//
+// OUTPUTS:
+// return value: The actual integral value for all 8 lanes which is defined by the spec as
+// the sum of all channel values to the left of a given pixel plus the result
+// written to the line directly above the current line.
+// accumulator: This is an input and and output. This parameter should be left with the accumulated
+// sums for the current 8 lanes keeping all entries in the proper lane (do not shuffle it)
+//
+// Below here is the channel specific implementation
+//
+
+//========================================
+// 1 Channel Integral Implementation
+//========================================
+template<>
+CV_ALWAYS_INLINE
+__m512d IntegralCalculator < 1 > ::calculate_integral(const __m512i src_longs, const __m512d above_values, __m512i &accumulator)
+{
+ // One channel support is implemented differently than 2, 3, or 4 channel
+ // One channel support has more horizontal operations that cannot be made vertical without losing performance
+ // The logical operations needed look like:
+ // Vertical LANES : |7|6|5|4|3|2|1|0|
+ // src_longs : |H|G|F|E|D|C|B|A|
+ // shift_by_1 : + |G|F|E|D|C|B|A| |
+ // shift_by_2 : + |F|E|D|C|B|A| | |
+ // shift_by_3 : + |E|D|C|B|A| | | |
+ // shift_by_4 : + |D|C|B|A| | | | |
+ // shift_by_5 : + |C|B|A| | | | | |
+ // shift_by_6 : + |B|A| | | | | | |
+ // shift_by_7 : + |A| | | | | | | |
+ // carry_over_idxs : + |7|7|7|7|7|7|7|7| (index position of result from previous iteration)
+ // = integral
+ //
+ // If we do this vertically we end up losing performance because of the number of operations. We will instead
+ // do a horizontal add tree to create the vertical sections we need as a tree
+ // Vertical Lanes: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ // src_longs: | H | G | F | E | D | C | B | A |
+ // horiz_sum_1: | | | | | G+H | E+F | C+D | A+B |
+ // horiz_sum_2: | | | | | | | EFGH | ABCD |
+ //
+ const __m512i horiz_sum_1 = m512_hadd(src_longs); // indexes for the permutes below (3,2,1,0) = (GH, EF, CD, AB)
+ const __m512i horiz_sum_2 = m512_hadd(horiz_sum_1); // indexes for the permutes below (9, 8) = (EFGH, ABCD)
+
+ // Then we can use the partial sums by looking at the vertical stacks above and realize that, for example
+ // ABCD appears vertically in lanes 7, 6, 5, 4, and 3 so we will permute the values so that all partial products
+ // appear in the right lanes. and sum them up along with the carry over value from the accumulator. So we setup
+ // the lanes like:
+ // Vertical Lanes: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ // s1 : | 0 | G | 0 | E | 0 | C | 0 | A |
+ // s2 : | ABCD | ABCD | ABCD | ABCD | ABCD | AB | AB | 0 |
+ // s3 : | EFGH | EF | EF | 0 | 0 | 0 | 0 | 0 |
+ // +------+------+------+------+------+------+------+------+
+ // sum : | A..H | A..G | A..F | A..E | A..D | A..C | A..B | A | Integral :-)
+ //
+ const __m512i s1 = _mm512_maskz_mov_epi64(0x55, src_longs); // 0 G 0 E 0 D 0 C 0 A
+ const __m512i s2 = _mm512_permutex2var_epi64(horiz_sum_1, _mm512_set_epi64(8,8,8,8,8,0,0,4), horiz_sum_2);
+ const __m512i s3 = _mm512_permutex2var_epi64(horiz_sum_1, _mm512_set_epi64(9,2,2,4,4,4,4,4), horiz_sum_2);
+
+ // Now we use the rolling sum from the previous iteration from accumulator and replicate it into carry_over
+ // And sum everything up into the accumulator
+ //
+ const __m512i carry_over = _mm512_permutex2var_epi64(accumulator, _mm512_set_epi64(7,7,7,7,7,7,7,7), accumulator);
+ accumulator = _mm512_add_epi64(_mm512_add_epi64(s2, s3), _mm512_add_epi64(carry_over, s1));
+
+ // Convert to double precision and store
+ //
+ __m512d integral_pd = _mm512_add_pd(_mm512_cvtepu64_pd(accumulator), above_values);
+ return integral_pd;
+}
+
+
+//========================================
+// 2 Channel Integral Implementation
+//========================================
+template<>
+CV_ALWAYS_INLINE
+__m512d IntegralCalculator < 2 > ::calculate_integral(const __m512i src_longs, const __m512d above_values, __m512i &accumulator)
+{
+ __m512i carryover_idxs = _mm512_set_epi64(7, 6, 7, 6, 7, 6, 7, 6);
+
+ // Align data to prepare for the adds:
+ // shifts data left by 3 and 6 qwords(lanes) and gets rolling sum in all lanes
+ // Vertical LANES : 76543210
+ // src_longs : HGFEDCBA
+ // shift2lanes : + FEDCBA
+ // shift4lanes : + DCBA
+ // shift6lanes : + BA
+ // carry_over_idxs : + 76767676 (index position of result from previous iteration)
+ // = integral
+ __m512i shift2lanes = _mm512_maskz_expand_epi64(0xFC, src_longs);
+ __m512i shift4lanes = _mm512_maskz_expand_epi64(0xF0, src_longs);
+ __m512i shift6lanes = _mm512_maskz_expand_epi64(0xC0, src_longs);
+ __m512i carry_over = _mm512_permutex2var_epi64(accumulator, carryover_idxs, accumulator);
+
+ // Add all values in tree form for perf ((0+2) + (4+6))
+ __m512i sum_shift_02 = _mm512_add_epi64(src_longs, shift2lanes);
+ __m512i sum_shift_46 = _mm512_add_epi64(shift4lanes, shift6lanes);
+ __m512i sum_all = _mm512_add_epi64(sum_shift_02, sum_shift_46);
+ accumulator = _mm512_add_epi64(sum_all, carry_over);
+
+ // Convert to packed double and add to the line above to get the true integral value
+ __m512d accumulator_pd = _mm512_cvtepu64_pd(accumulator);
+ __m512d integral_pd = _mm512_add_pd(accumulator_pd, above_values);
+ return integral_pd;
+}
+
+
+//========================================
+// 3 Channel Integral Implementation
+//========================================
+template<>
+CV_ALWAYS_INLINE
+__m512d IntegralCalculator < 3 > ::calculate_integral(const __m512i src_longs, const __m512d above_values, __m512i &accumulator)
+{
+ __m512i carryover_idxs = _mm512_set_epi64(6, 5, 7, 6, 5, 7, 6, 5);
+
+ // Align data to prepare for the adds:
+ // shifts data left by 3 and 6 qwords(lanes) and gets rolling sum in all lanes
+ // Vertical LANES: 76543210
+ // src_longs : HGFEDCBA
+ // shit3lanes : + EDCBA
+ // shift6lanes : + BA
+ // carry_over_idxs : + 65765765 (index position of result from previous iteration)
+ // = integral
+ __m512i shift3lanes = _mm512_maskz_expand_epi64(0xF8, src_longs);
+ __m512i shift6lanes = _mm512_maskz_expand_epi64(0xC0, src_longs);
+ __m512i carry_over = _mm512_permutex2var_epi64(accumulator, carryover_idxs, accumulator);
+
+ // Do the adds in tree form
+ __m512i sum_shift_03 = _mm512_add_epi64(src_longs, shift3lanes);
+ __m512i sum_rest = _mm512_add_epi64(shift6lanes, carry_over);
+ accumulator = _mm512_add_epi64(sum_shift_03, sum_rest);
+
+ // Convert to packed double and add to the line above to get the true integral value
+ __m512d accumulator_pd = _mm512_cvtepu64_pd(accumulator);
+ __m512d integral_pd = _mm512_add_pd(accumulator_pd, above_values);
+ return integral_pd;
+}
+
+
+//========================================
+// 4 Channel Integral Implementation
+//========================================
+template<>
+CV_ALWAYS_INLINE
+__m512d IntegralCalculator < 4 > ::calculate_integral(const __m512i src_longs, const __m512d above_values, __m512i &accumulator)
+{
+ __m512i carryover_idxs = _mm512_set_epi64(7, 6, 5, 4, 7, 6, 5, 4);
+
+ // Align data to prepare for the adds:
+ // shifts data left by 3 and 6 qwords(lanes) and gets rolling sum in all lanes
+ // Vertical LANES: 76543210
+ // src_longs : HGFEDCBA
+ // shit4lanes : + DCBA
+ // carry_over_idxs : + 76547654 (index position of result from previous iteration)
+ // = integral
+ __m512i shifted4lanes = _mm512_maskz_expand_epi64(0xF0, src_longs);
+ __m512i carry_over = _mm512_permutex2var_epi64(accumulator, carryover_idxs, accumulator);
+
+ // Add data pixels and carry over from last iteration
+ __m512i sum_shift_04 = _mm512_add_epi64(src_longs, shifted4lanes);
+ accumulator = _mm512_add_epi64(sum_shift_04, carry_over);
+
+ // Convert to packed double and add to the line above to get the true integral value
+ __m512d accumulator_pd = _mm512_cvtepu64_pd(accumulator);
+ __m512d integral_pd = _mm512_add_pd(accumulator_pd, above_values);
+ return integral_pd;
+}
+
+
} // end of anonymous namespace
namespace opt_AVX512_SKX {
double *sqsum, size_t _sqsumstep,
int width, int height, int cn)
{
- IntegralCalculator_3Channel calculator;
- calculator.calculate_integral_avx512(src, _srcstep, sum, _sumstep, sqsum, _sqsumstep, width, height, cn);
+ switch(cn){
+ case 1: {
+ IntegralCalculator< 1 > calculator;
+ calculator.calculate_integral_avx512(src, _srcstep, sum, _sumstep, sqsum, _sqsumstep, width, height);
+ break;
+ }
+ case 2: {
+ IntegralCalculator< 2 > calculator;
+ calculator.calculate_integral_avx512(src, _srcstep, sum, _sumstep, sqsum, _sqsumstep, width, height);
+ break;
+ }
+ case 3: {
+ IntegralCalculator< 3 > calculator;
+ calculator.calculate_integral_avx512(src, _srcstep, sum, _sumstep, sqsum, _sqsumstep, width, height);
+ break;
+ }
+ case 4: {
+ IntegralCalculator< 4 > calculator;
+ calculator.calculate_integral_avx512(src, _srcstep, sum, _sumstep, sqsum, _sqsumstep, width, height);
+ }
+ }
}
#include "opencv2/core/hal/intrin.hpp"
#include "sumpixels.hpp"
-
namespace cv
{
{
#if CV_TRY_AVX512_SKX
CV_UNUSED(_tiltedstep);
- // TODO: Add support for 1,2, and 4 channels
- if (CV_CPU_HAS_SUPPORT_AVX512_SKX && !tilted && cn == 3){
+ // TODO: Add support for 1 channel input (WIP)
+ if (CV_CPU_HAS_SUPPORT_AVX512_SKX && !tilted && (cn <= 4)){
opt_AVX512_SKX::calculate_integral_avx512(src, _srcstep, sum, _sumstep,
sqsum, _sqsumstep, width, height, cn);
return true;
{
RNG& rng = ts->get_rng();
int depth = cvtest::randInt(rng) % 2, sum_depth;
- int cn = cvtest::randInt(rng) % 3 + 1;
+ int cn = cvtest::randInt(rng) % 4 + 1;
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
Size sum_size;
depth = depth == 0 ? CV_8U : CV_32F;
- cn += cn == 2;
int b = (cvtest::randInt(rng) & 1) != 0;
sum_depth = depth == CV_8U && b ? CV_32S : b ? CV_32F : CV_64F;
namespace opencv_test { namespace {
+#if 0 // LSD implementation has been removed due original code license issues
+
const Size img_size(640, 480);
const int LSD_TEST_SEED = 0x134679;
const int EPOCHS = 20;
ASSERT_EQ(result2, 11);
}
+#endif
+
}} // namespace
configure_file("${__base_dir}/${file}" "${OPENCV_JAVA_DIR}/${file}" @ONLY)
list(APPEND depends "${__base_dir}/${file}")
get_filename_component(install_subdir "${file}" PATH)
- install(FILES "${OPENCV_JAVA_DIR}/${file}" DESTINATION "${JAVA_INSTALL_ROOT}/${install_subdir}" COMPONENT java)
+ if(NOT file STREQUAL "build.gradle")
+ install(FILES "${OPENCV_JAVA_DIR}/${file}" DESTINATION "${JAVA_INSTALL_ROOT}/${install_subdir}" COMPONENT java)
+ endif()
endforeach()
list(APPEND depends gen_opencv_java_source "${OPENCV_DEPHELPER}/gen_opencv_java_source")
}
buildTypes {
+ debug {
+ packagingOptions{
+ doNotStrip '*.so'
+ }
+ }
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
if (mCameraID != null) {
Log.i(LOGTAG, "Opening camera: " + mCameraID);
manager.openCamera(mCameraID, mStateCallback, mBackgroundHandler);
+ } else { // make JavaCamera2View behaves in the same way as JavaCameraView
+ Log.i(LOGTAG, "Trying to open camera with the value (" + mCameraIndex + ")");
+ if (mCameraIndex < camList.length) {
+ mCameraID = camList[mCameraIndex];
+ manager.openCamera(mCameraID, mStateCallback, mBackgroundHandler);
+ } else {
+ // CAMERA_DISCONNECTED is used when the camera id is no longer valid
+ throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED);
+ }
}
return true;
} catch (CameraAccessException e) {
}
protected Context mAppContext;
- private final static String TAG = "OpenCVLoader/BaseLoaderCallback";
+ private final static String TAG = "OCV/BaseLoaderCallback";
}
def gen_class(self, ci):
logging.info("%s", ci)
# constants
+ consts_map = {c.name: c for c in ci.private_consts}
+ consts_map.update({c.name: c for c in ci.consts})
+ def const_value(v):
+ if v in consts_map:
+ target = consts_map[v]
+ assert target.value != v
+ return const_value(target.value)
+ return v
if ci.private_consts:
logging.info("%s", ci.private_consts)
ci.j_code.write("""
private static final int
- %s;\n\n""" % (",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in ci.private_consts])
+ %s;\n\n""" % (",\n"+" "*12).join(["%s = %s" % (c.name, const_value(c.value)) for c in ci.private_consts])
)
if ci.consts:
enumTypes = set(map(lambda c: c.enumType, ci.consts))
CV_UNUSED(method); // avoid "unused" warning
}
+// jint could be int or int32_t so casting jint* to int* in general wouldn't work
+static std::vector<int> convertJintArrayToVector(JNIEnv* env, jintArray in) {
+ std::vector<int> out;
+ int len = env->GetArrayLength(in);
+ jint* inArray = env->GetIntArrayElements(in, 0);
+ for ( int i = 0; i < len; i++ ) {
+ out.push_back(inArray[i]);
+ }
+ env->ReleaseIntArrayElements(in, inArray, 0);
+ return out;
+}
+
extern "C" {
return 0;
}
+//
+// Mat::Mat(int[] sizes, int type)
+//
+
+JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__I_3II
+ (JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type);
+
+JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__I_3II
+ (JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type)
+{
+ static const char method_name[] = "Mat::n_1Mat__I_3II()";
+ try {
+ LOGD("%s", method_name);
+ std::vector<int> sizes = convertJintArrayToVector(env, sizesArray);
+ return (jlong) new Mat( ndims, sizes.data(), type );
+ } catch(const std::exception &e) {
+ throwJavaException(env, &e, method_name);
+ } catch (...) {
+ throwJavaException(env, 0, method_name);
+ }
+
+ return 0;
+}
+
//
//
+// Mat::Mat(int[] sizes, int type, Scalar s)
+//
+
+JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__I_3IIDDDD
+ (JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type, jdouble s_val0, jdouble s_val1, jdouble s_val2, jdouble s_val3);
+
+JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__I_3IIDDDD
+ (JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type, jdouble s_val0, jdouble s_val1, jdouble s_val2, jdouble s_val3)
+{
+ static const char method_name[] = "Mat::n_1Mat__I_3IIDDDD()";
+ try {
+ LOGD("%s", method_name);
+ std::vector<int> sizes = convertJintArrayToVector(env, sizesArray);
+ Scalar s(s_val0, s_val1, s_val2, s_val3);
+ return (jlong) new Mat( ndims, sizes.data(), type, s );
+ } catch(const std::exception &e) {
+ throwJavaException(env, &e, method_name);
+ } catch (...) {
+ throwJavaException(env, 0, method_name);
+ }
+
+ return 0;
+}
+
+
+
+//
// Mat::Mat(Mat m, Range rowRange, Range colRange = Range::all())
//
return 0;
}
+jint getObjectIntField(JNIEnv* env, jobject obj, const char * fieldName);
+
+jint getObjectIntField(JNIEnv* env, jobject obj, const char * fieldName) {
+ jfieldID fid; /* store the field ID */
+
+ /* Get a reference to obj's class */
+ jclass cls = env->GetObjectClass(obj);
+
+ /* Look for the instance field s in cls */
+ fid = env->GetFieldID(cls, fieldName, "I");
+ if (fid == NULL)
+ {
+ return 0; /* failed to find the field */
+ }
+
+ /* Read the instance field s */
+ return env->GetIntField(obj, fid);
+}
+
+#define RANGE_START_FIELD "start"
+#define RANGE_END_FIELD "end"
+
+//
+// Mat::Mat(Mat m, Range[] ranges)
+//
+
+JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__J_3Lorg_opencv_core_Range_2
+ (JNIEnv* env, jclass, jlong m_nativeObj, jobjectArray rangesArray);
+
+JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__J_3Lorg_opencv_core_Range_2
+ (JNIEnv* env, jclass, jlong m_nativeObj, jobjectArray rangesArray)
+{
+ static const char method_name[] = "Mat::n_1Mat__J_3Lorg_opencv_core_Range_2()";
+ try {
+ LOGD("%s", method_name);
+ std::vector<Range> ranges;
+ int rangeCount = env->GetArrayLength(rangesArray);
+ for (int i = 0; i < rangeCount; i++) {
+ jobject range = env->GetObjectArrayElement(rangesArray, i);
+ jint start = getObjectIntField(env, range, RANGE_START_FIELD);
+ jint end = getObjectIntField(env, range, RANGE_END_FIELD);
+ ranges.push_back(Range(start, end));
+ }
+ return (jlong) new Mat( (*(Mat*)m_nativeObj), ranges );
+ } catch(const std::exception &e) {
+ throwJavaException(env, &e, method_name);
+ } catch (...) {
+ throwJavaException(env, 0, method_name);
+ }
+
+ return 0;
+}
+
JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__JII
(JNIEnv* env, jclass, jlong m_nativeObj, jint rowRange_start, jint rowRange_end);
//
+// void Mat::create(int[] sizes, int type)
+//
+
+JNIEXPORT void JNICALL Java_org_opencv_core_Mat_n_1create__JI_3II
+ (JNIEnv* env, jclass, jlong self, jint ndims, jintArray sizesArray, jint type);
+
+JNIEXPORT void JNICALL Java_org_opencv_core_Mat_n_1create__JI_3II
+ (JNIEnv* env, jclass, jlong self, jint ndims, jintArray sizesArray, jint type)
+{
+ static const char method_name[] = "Mat::n_1create__JI_3II()";
+ try {
+ LOGD("%s", method_name);
+ Mat* me = (Mat*) self;
+ std::vector<int> sizes = convertJintArrayToVector(env, sizesArray);
+ me->create( ndims, sizes.data(), type );
+ } catch(const std::exception &e) {
+ throwJavaException(env, &e, method_name);
+ } catch (...) {
+ throwJavaException(env, 0, method_name);
+ }
+}
+
+
+
+//
+// Mat Mat::copySize(Mat m)
+//
+
+JNIEXPORT void JNICALL Java_org_opencv_core_Mat_n_1copySize
+ (JNIEnv* env, jclass, jlong self, jlong m_nativeObj);
+
+JNIEXPORT void JNICALL Java_org_opencv_core_Mat_n_1copySize
+ (JNIEnv* env, jclass, jlong self, jlong m_nativeObj)
+{
+ static const char method_name[] = "Mat::n_1copySize()";
+ try {
+ LOGD("%s", method_name);
+ Mat* me = (Mat*) self;
+ Mat& m = *((Mat*)m_nativeObj);
+ me->copySize( m );
+ } catch(const std::exception &e) {
+ throwJavaException(env, &e, method_name);
+ } catch (...) {
+ throwJavaException(env, 0, method_name);
+ }
+}
+
+
+
+//
// Mat Mat::cross(Mat m)
//
//
+// static Mat Mat::ones(int[] sizes, int type)
+//
+
+JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1ones__I_3II
+ (JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type);
+
+JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1ones__I_3II
+ (JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type)
+{
+ static const char method_name[] = "Mat::n_1ones__I_3II()";
+ try {
+ LOGD("%s", method_name);
+ std::vector<int> sizes = convertJintArrayToVector(env, sizesArray);
+ Mat _retval_ = Mat::ones( ndims, sizes.data(), type );
+ return (jlong) new Mat(_retval_);
+ } catch(const std::exception &e) {
+ throwJavaException(env, &e, method_name);
+ } catch (...) {
+ throwJavaException(env, 0, method_name);
+ }
+
+ return 0;
+}
+
+
+
+//
// void Mat::push_back(Mat m)
//
try {
LOGD("%s", method_name);
Mat* me = (Mat*) self; //TODO: check for NULL
- int* newsz = (int*)env->GetPrimitiveArrayCritical(newshape, 0);
- Mat _retval_ = me->reshape( cn, newndims, newsz );
+ std::vector<int> newsz = convertJintArrayToVector(env, newshape);
+ Mat _retval_ = me->reshape( cn, newndims, newsz.data() );
return (jlong) new Mat(_retval_);
} catch(const std::exception &e) {
throwJavaException(env, &e, method_name);
return 0;
}
+//
+// Mat Mat::operator()(Range[] ranges)
+//
+
+JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1submat_1ranges
+(JNIEnv* env, jclass, jlong self, jobjectArray rangesArray);
+
+JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1submat_1ranges
+(JNIEnv* env, jclass, jlong self, jobjectArray rangesArray)
+{
+ static const char method_name[] = "Mat::n_1submat_1ranges()";
+ try {
+ LOGD("%s", method_name);
+ Mat* me = (Mat*) self;
+ std::vector<Range> ranges;
+ int rangeCount = env->GetArrayLength(rangesArray);
+ for (int i = 0; i < rangeCount; i++) {
+ jobject range = env->GetObjectArrayElement(rangesArray, i);
+ jint start = getObjectIntField(env, range, RANGE_START_FIELD);
+ jint end = getObjectIntField(env, range, RANGE_END_FIELD);
+ ranges.push_back(Range(start, end));
+ }
+ Mat _retval_ = me->operator()( ranges );
+ return (jlong) new Mat(_retval_);
+ } catch(const std::exception &e) {
+ throwJavaException(env, &e, method_name);
+ } catch (...) {
+ throwJavaException(env, 0, method_name);
+ }
+
+ return 0;
+}
+
//
//
+// static Mat Mat::zeros(int[] sizes, int type)
+//
+
+JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1zeros__I_3II
+(JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type);
+
+JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1zeros__I_3II
+(JNIEnv* env, jclass, jint ndims, jintArray sizesArray, jint type)
+{
+ static const char method_name[] = "Mat::n_1zeros__I_3II()";
+ try {
+ LOGD("%s", method_name);
+ std::vector<int> sizes = convertJintArrayToVector(env, sizesArray);
+ Mat _retval_ = Mat::zeros( ndims, sizes.data(), type );
+ return (jlong) new Mat(_retval_);
+ } catch(const std::exception &e) {
+ throwJavaException(env, &e, method_name);
+ } catch (...) {
+ throwJavaException(env, 0, method_name);
+ }
+
+ return 0;
+}
+
+
+
+//
// native support for java finalize()
// static void Mat::n_delete( __int64 self )
//
return res;
}
+// returns true if final index was reached
+static bool updateIdx(cv::Mat* m, std::vector<int>& idx, int inc) {
+ for (int i=m->dims-1; i>=0; i--) {
+ if (inc == 0) return false;
+ idx[i] = (idx[i] + 1) % m->size[i];
+ inc--;
+ }
+ return true;
+}
+
+template<typename T> static int mat_put_idx(cv::Mat* m, std::vector<int>& idx, int count, int offset, char* buff)
+{
+ if(! m) return 0;
+ if(! buff) return 0;
+
+ count *= sizeof(T);
+ int rest = (int)m->elemSize();
+ for (int i = 0; i < m->dims; i++) {
+ rest *= (m->size[i] - idx[i]);
+ }
+ if(count>rest) count = rest;
+ int res = count;
+
+ if( m->isContinuous() )
+ {
+ memcpy(m->ptr(idx.data()), buff + offset, count);
+ } else {
+ // dim by dim
+ int num = (m->size[m->dims-1] - idx[m->dims-1]) * (int)m->elemSize(); // 1st partial row
+ if(count<num) num = count;
+ uchar* data = m->ptr(idx.data());
+ while(count>0){
+ memcpy(data, buff + offset, num);
+ updateIdx(m, idx, num / (int)m->elemSize());
+ count -= num;
+ buff += num;
+ num = m->size[m->dims-1] * (int)m->elemSize();
+ if(count<num) num = count;
+ data = m->ptr(idx.data());
+ }
+ }
+ return res;
+}
+
template<class ARRAY> static jint java_mat_put(JNIEnv* env, jlong self, jint row, jint col, jint count, jint offset, ARRAY vals)
{
static const char *method_name = JavaOpenCVTrait<ARRAY>::put;
return 0;
}
+template<class ARRAY> static jint java_mat_put_idx(JNIEnv* env, jlong self, jintArray idxArray, jint count, jint offset, ARRAY vals)
+{
+ static const char *method_name = JavaOpenCVTrait<ARRAY>::put;
+ try {
+ LOGD("%s", method_name);
+ cv::Mat* me = (cv::Mat*) self;
+ if(! self) return 0; // no native object behind
+ if(me->depth() != JavaOpenCVTrait<ARRAY>::cvtype_1 && me->depth() != JavaOpenCVTrait<ARRAY>::cvtype_2) return 0; // incompatible type
+ std::vector<int> idx = convertJintArrayToVector(env, idxArray);
+ for (int i = 0; i < me->dims ; i++ ) {
+ if (me->size[i]<=idx[i]) return 0;
+ }
+ char* values = (char*)env->GetPrimitiveArrayCritical(vals, 0);
+ int res = mat_put_idx<typename JavaOpenCVTrait<ARRAY>::value_type>(me, idx, count, offset, values);
+ env->ReleasePrimitiveArrayCritical(vals, values, JNI_ABORT);
+ return res;
+ } catch(const std::exception &e) {
+ throwJavaException(env, &e, method_name);
+ } catch (...) {
+ throwJavaException(env, 0, method_name);
+ }
+
+ return 0;
+}
+
extern "C" {
JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutB
return java_mat_put(env, self, row, col, count, 0, vals);
}
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutBIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jbyteArray vals);
+
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutBIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jbyteArray vals)
+{
+ return java_mat_put_idx(env, self, idxArray, count, 0, vals);
+}
+
JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutBwOffset
(JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jint offset, jbyteArray vals);
return java_mat_put(env, self, row, col, count, offset, vals);
}
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutBwIdxOffset
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jint offset, jbyteArray vals);
+
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutBwIdxOffset
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jint offset, jbyteArray vals)
+{
+ return java_mat_put_idx(env, self, idxArray, count, offset, vals);
+}
+
JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutS
(JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jshortArray vals);
return java_mat_put(env, self, row, col, count, 0, vals);
}
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutSIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jshortArray vals);
+
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutSIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jshortArray vals)
+{
+ return java_mat_put_idx(env, self, idxArray, count, 0, vals);
+}
+
JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutI
(JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jintArray vals);
return java_mat_put(env, self, row, col, count, 0, vals);
}
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutIIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jintArray vals);
+
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutIIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jintArray vals)
+{
+ return java_mat_put_idx(env, self, idxArray, count, 0, vals);
+}
+
JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutF
(JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jfloatArray vals);
return java_mat_put(env, self, row, col, count, 0, vals);
}
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutFIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jfloatArray vals);
+
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutFIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jfloatArray vals)
+{
+ return java_mat_put_idx(env, self, idxArray, count, 0, vals);
+}
+
// unlike other nPut()-s this one (with double[]) should convert input values to correct type
#define PUT_ITEM(T, R, C) { T*dst = (T*)me->ptr(R, C); for(int ch=0; ch<me->channels() && count>0; count--,ch++,src++,dst++) *dst = cv::saturate_cast<T>(*src); }
return 0;
}
+// unlike other nPut()-s this one (with double[]) should convert input values to correct type
+#define PUT_ITEM_IDX(T, I) { T*dst = (T*)me->ptr(I); for(int ch=0; ch<me->channels() && count>0; count--,ch++,src++,dst++) *dst = cv::saturate_cast<T>(*src); }
+
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutDIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jdoubleArray vals);
+
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutDIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jdoubleArray vals)
+{
+ static const char* method_name = JavaOpenCVTrait<jdoubleArray>::put;
+ try {
+ LOGD("%s", method_name);
+ cv::Mat* me = (cv::Mat*) self;
+ if(!me || !me->data) return 0; // no native object behind
+ std::vector<int> idx = convertJintArrayToVector(env, idxArray);
+ for (int i=0; i<me->dims; i++) {
+ if (me->size[i]<=idx[i]) return 0; // indexes out of range
+ }
+ int rest = me->channels();
+ for (int i=0; i<me->dims; i++) {
+ rest *= (me->size[i] - idx[i]);
+ }
+ if(count>rest) count = rest;
+ int res = count;
+ double* values = (double*)env->GetPrimitiveArrayCritical(vals, 0);
+ double* src = values;
+ bool reachedFinalIndex = false;
+ for(; !reachedFinalIndex && count>0; reachedFinalIndex = updateIdx(me, idx, 1))
+ {
+ switch(me->depth()) {
+ case CV_8U: PUT_ITEM_IDX(uchar, idx.data()); break;
+ case CV_8S: PUT_ITEM_IDX(schar, idx.data()); break;
+ case CV_16U: PUT_ITEM_IDX(ushort, idx.data()); break;
+ case CV_16S: PUT_ITEM_IDX(short, idx.data()); break;
+ case CV_32S: PUT_ITEM_IDX(int, idx.data()); break;
+ case CV_32F: PUT_ITEM_IDX(float, idx.data()); break;
+ case CV_64F: PUT_ITEM_IDX(double, idx.data()); break;
+ }
+ }
+ env->ReleasePrimitiveArrayCritical(vals, values, 0);
+ return res;
+ } catch(const std::exception &e) {
+ throwJavaException(env, &e, method_name);
+ } catch (...) {
+ throwJavaException(env, 0, method_name);
+ }
+
+ return 0;
+}
+
} // extern "C"
template<typename T> static int mat_get(cv::Mat* m, int row, int col, int count, char* buff)
return res;
}
+template<typename T> static int mat_get_idx(cv::Mat* m, std::vector<int>& idx, int count, char* buff)
+{
+ if(! m) return 0;
+ if(! buff) return 0;
+
+ count *= sizeof(T);
+ int rest = (int)m->elemSize();
+ for (int i = 0; i < m->dims; i++) {
+ rest *= (m->size[i] - idx[i]);
+ }
+ if(count>rest) count = rest;
+ int res = count;
+
+ if( m->isContinuous() )
+ {
+ memcpy(buff, m->ptr(idx.data()), count);
+ } else {
+ // dim by dim
+ int num = (m->size[m->dims-1] - idx[m->dims-1]) * (int)m->elemSize(); // 1st partial row
+ if(count<num) num = count;
+ uchar* data = m->ptr(idx.data());
+ while(count>0){
+ memcpy(buff, data, num);
+ updateIdx(m, idx, num / (int)m->elemSize());
+ count -= num;
+ buff += num;
+ num = m->size[m->dims-1] * (int)m->elemSize();
+ if(count<num) num = count;
+ data = m->ptr(idx.data());
+ }
+ }
+ return res;
+}
+
template<class ARRAY> static jint java_mat_get(JNIEnv* env, jlong self, jint row, jint col, jint count, ARRAY vals) {
static const char *method_name = JavaOpenCVTrait<ARRAY>::get;
try {
return 0;
}
+template<class ARRAY> static jint java_mat_get_idx(JNIEnv* env, jlong self, jintArray idxArray, jint count, ARRAY vals) {
+ static const char *method_name = JavaOpenCVTrait<ARRAY>::get;
+ try {
+ LOGD("%s", method_name);
+ cv::Mat* me = (cv::Mat*) self;
+ if(! self) return 0; // no native object behind
+ if(me->depth() != JavaOpenCVTrait<ARRAY>::cvtype_1 && me->depth() != JavaOpenCVTrait<ARRAY>::cvtype_2) return 0; // incompatible type
+ std::vector<int> idx = convertJintArrayToVector(env, idxArray);
+ for (int i = 0; i < me->dims ; i++ ) {
+ if (me->size[i]<=idx[i]) return 0;
+ }
+
+ char* values = (char*)env->GetPrimitiveArrayCritical(vals, 0);
+ int res = mat_get_idx<typename JavaOpenCVTrait<ARRAY>::value_type>(me, idx, count, values);
+ env->ReleasePrimitiveArrayCritical(vals, values, 0);
+ return res;
+ } catch(const std::exception &e) {
+ throwJavaException(env, &e, method_name);
+ } catch (...) {
+ throwJavaException(env, 0, method_name);
+ }
+
+ return 0;
+}
+
extern "C" {
JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetB
return java_mat_get(env, self, row, col, count, vals);
}
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetBIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jbyteArray vals);
+
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetBIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jbyteArray vals)
+{
+ return java_mat_get_idx(env, self, idxArray, count, vals);
+}
+
JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetS
(JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jshortArray vals);
return java_mat_get(env, self, row, col, count, vals);
}
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetSIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jshortArray vals);
+
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetSIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jshortArray vals)
+{
+ return java_mat_get_idx(env, self, idxArray, count, vals);
+}
+
JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetI
(JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jintArray vals);
return java_mat_get(env, self, row, col, count, vals);
}
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetIIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jintArray vals);
+
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetIIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jintArray vals)
+{
+ return java_mat_get_idx(env, self, idxArray, count, vals);
+}
+
JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetF
(JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jfloatArray vals);
return java_mat_get(env, self, row, col, count, vals);
}
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetFIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jfloatArray vals);
+
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetFIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jfloatArray vals)
+{
+ return java_mat_get_idx(env, self, idxArray, count, vals);
+}
+
JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetD
(JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jdoubleArray vals);
return java_mat_get(env, self, row, col, count, vals);
}
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetDIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jdoubleArray vals);
+
+JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nGetDIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jdoubleArray vals)
+{
+ return java_mat_get_idx(env, self, idxArray, count, vals);
+}
+
JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Mat_nGet
(JNIEnv* env, jclass, jlong self, jint row, jint col);
return 0;
}
+JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Mat_nGetIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray);
+
+JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Mat_nGetIdx
+ (JNIEnv* env, jclass, jlong self, jintArray idxArray)
+{
+ static const char method_name[] = "Mat::nGetIdx()";
+ try {
+ LOGD("%s", method_name);
+ cv::Mat* me = (cv::Mat*) self;
+ if(! self) return 0; // no native object behind
+ std::vector<int> idx = convertJintArrayToVector(env, idxArray);
+ for (int i=0; i<me->dims; i++) {
+ if (me->size[i]<=idx[i]) return 0; // indexes out of range
+ }
+
+ jdoubleArray res = env->NewDoubleArray(me->channels());
+ if(res){
+ jdouble buff[CV_CN_MAX];//me->channels()
+ int i;
+ switch(me->depth()){
+ case CV_8U: for(i=0; i<me->channels(); i++) buff[i] = *((unsigned char*) me->ptr(idx.data()) + i); break;
+ case CV_8S: for(i=0; i<me->channels(); i++) buff[i] = *((signed char*) me->ptr(idx.data()) + i); break;
+ case CV_16U: for(i=0; i<me->channels(); i++) buff[i] = *((unsigned short*)me->ptr(idx.data()) + i); break;
+ case CV_16S: for(i=0; i<me->channels(); i++) buff[i] = *((signed short*) me->ptr(idx.data()) + i); break;
+ case CV_32S: for(i=0; i<me->channels(); i++) buff[i] = *((int*) me->ptr(idx.data()) + i); break;
+ case CV_32F: for(i=0; i<me->channels(); i++) buff[i] = *((float*) me->ptr(idx.data()) + i); break;
+ case CV_64F: for(i=0; i<me->channels(); i++) buff[i] = *((double*) me->ptr(idx.data()) + i); break;
+ }
+ env->SetDoubleArrayRegion(res, 0, me->channels(), buff);
+ }
+ return res;
+ } catch(const std::exception &e) {
+ throwJavaException(env, &e, method_name);
+ } catch (...) {
+ throwJavaException(env, 0, method_name);
+ }
+
+ return 0;
+}
+
JNIEXPORT jstring JNICALL Java_org_opencv_core_Mat_nDump
(JNIEnv *env, jclass, jlong self);
protected Mat rgbLena;
protected Mat grayChess;
+ protected Mat gray255_32f_3d;
+
protected Mat v1;
protected Mat v2;
rgbLena = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH);
grayChess = Imgcodecs.imread(OpenCVTestRunner.CHESS_PATH, 0);
+ gray255_32f_3d = new Mat(new int[]{matSize, matSize, matSize}, CvType.CV_32F, new Scalar(255.0));
+
v1 = new Mat(1, 3, CvType.CV_32F);
v1.put(0, 0, 1.0, 3.0, 2.0);
v2 = new Mat(1, 3, CvType.CV_32F);
rgba128.release();
rgbLena.release();
grayChess.release();
+ gray255_32f_3d.release();
v1.release();
v2.release();
assertEquals(msg, expected.z, actual.z, eps);
}
+ static private boolean dimensionsEqual(Mat expected, Mat actual) {
+ if (expected.dims() != actual.dims()) {
+ return false;
+ }
+ if (expected.dims() > 2) {
+ for (int i = 0; i < expected.dims(); i++) {
+ if (expected.size(i) != actual.size(i)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return expected.cols() == actual.cols() && expected.rows() == actual.rows();
+ }
+ }
+
static private void compareMats(Mat expected, Mat actual, boolean isEqualityMeasured) {
- if (expected.type() != actual.type() || expected.cols() != actual.cols() || expected.rows() != actual.rows()) {
+ if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) {
throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual);
}
}
static private void compareMats(Mat expected, Mat actual, double eps, boolean isEqualityMeasured) {
- if (expected.type() != actual.type() || expected.cols() != actual.cols() || expected.rows() != actual.rows()) {
+ if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) {
throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual);
}
protected Mat rgbLena;
protected Mat grayChess;
+ protected Mat gray255_32f_3d;
+
protected Mat v1;
protected Mat v2;
rgbLena = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH);
grayChess = Imgcodecs.imread(OpenCVTestRunner.CHESS_PATH, 0);
+ gray255_32f_3d = new Mat(new int[]{matSize, matSize, matSize}, CvType.CV_32F, new Scalar(255.0));
+
v1 = new Mat(1, 3, CvType.CV_32F);
v1.put(0, 0, 1.0, 3.0, 2.0);
v2 = new Mat(1, 3, CvType.CV_32F);
rgba128.release();
rgbLena.release();
grayChess.release();
+ gray255_32f_3d.release();
v1.release();
v2.release();
assertEquals(msg, expected.z, actual.z, eps);
}
+ static private boolean dimensionsEqual(Mat expected, Mat actual) {
+ if (expected.dims() != actual.dims()) {
+ return false;
+ }
+ if (expected.dims() > 2) {
+ for (int i = 0; i < expected.dims(); i++) {
+ if (expected.size(i) != actual.size(i)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return expected.cols() == actual.cols() && expected.rows() == actual.rows();
+ }
+ }
+
static private void compareMats(Mat expected, Mat actual, boolean isEqualityMeasured) {
- if (expected.type() != actual.type() || expected.cols() != actual.cols() || expected.rows() != actual.rows()) {
+ if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) {
throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual);
}
}
static private void compareMats(Mat expected, Mat actual, double eps, boolean isEqualityMeasured) {
- if (expected.type() != actual.type() || expected.cols() != actual.cols() || expected.rows() != actual.rows()) {
+ if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) {
throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual);
}
int count = inputs.rows;
int iter = -1, max_iter = termCrit.maxCount*count;
- double epsilon = termCrit.epsilon*count;
+ double epsilon = (termCrit.type & CV_TERMCRIT_EPS) ? termCrit.epsilon*count : 0;
int l_count = layer_count();
int ivcount = layer_sizes[0];
for( j = 0; j < vcount; j++ )
{
Qfloat t = results[j];
- Qfloat e = std::exp(std::abs(t));
- if( t > 0 )
- results[j] = (Qfloat)((e - 1.)/(e + 1.));
- else
- results[j] = (Qfloat)((1. - e)/(1. + e));
+ Qfloat e = std::exp(std::abs(t)); // Inf value is possible here
+ Qfloat r = (Qfloat)((e - 1.) / (e + 1.)); // NaN value is possible here (Inf/Inf or similar)
+ if (cvIsNaN(r))
+ r = std::numeric_limits<Qfloat>::infinity();
+ if (t < 0)
+ r = -r;
+ CV_DbgAssert(!cvIsNaN(r));
+ results[j] = r;
}
}
const Qfloat max_val = (Qfloat)(FLT_MAX*1e-3);
for( int j = 0; j < vcount; j++ )
{
- if( results[j] > max_val )
+ if (!(results[j] <= max_val)) // handle NaNs too
results[j] = max_val;
}
}
const DecisionFunc& df = svm->decision_func[dfi];
sum = -df.rho;
int sv_count = svm->getSVCount(dfi);
+ CV_DbgAssert(sv_count > 0);
const double* alpha = &svm->df_alpha[df.ofs];
const int* sv_index = &svm->df_index[df.ofs];
for( k = 0; k < sv_count; k++ )
/**
@defgroup photo Computational Photography
+
+This module includes photo processing algorithms
@{
+ @defgroup photo_inpaint Inpainting
@defgroup photo_denoise Denoising
@defgroup photo_hdr HDR imaging
This section describes high dynamic range imaging algorithms namely tonemapping, exposure alignment,
camera calibration with multiple exposures and exposure fusion.
+ @defgroup photo_decolor Contrast Preserving Decolorization
+
+Useful links:
+
+http://www.cse.cuhk.edu.hk/leojia/projects/color2gray/index.html
+
@defgroup photo_clone Seamless Cloning
+
+Useful links:
+
+https://www.learnopencv.com/seamless-cloning-using-opencv-python-cpp
+
@defgroup photo_render Non-Photorealistic Rendering
- @defgroup photo_c C API
+
+Useful links:
+
+http://www.inf.ufrgs.br/~eslgastal/DomainTransform
+
+https://www.learnopencv.com/non-photorealistic-rendering-using-opencv-python-c/
@}
*/
//! @addtogroup photo
//! @{
+//! @addtogroup photo_inpaint
+//! @{
//! the inpainting algorithm
enum
{
- INPAINT_NS = 0, // Navier-Stokes algorithm
- INPAINT_TELEA = 1 // A. Telea algorithm
-};
-
-enum
-{
- NORMAL_CLONE = 1,
- MIXED_CLONE = 2,
- MONOCHROME_TRANSFER = 3
-};
-
-enum
-{
- RECURS_FILTER = 1,
- NORMCONV_FILTER = 2
+ INPAINT_NS = 0, //!< Use Navier-Stokes based method
+ INPAINT_TELEA = 1 //!< Use the algorithm proposed by Alexandru Telea @cite Telea04
};
/** @brief Restores the selected region in an image using the region neighborhood.
@param dst Output image with the same size and type as src .
@param inpaintRadius Radius of a circular neighborhood of each point inpainted that is considered
by the algorithm.
-@param flags Inpainting method that could be one of the following:
-- **INPAINT_NS** Navier-Stokes based method [Navier01]
-- **INPAINT_TELEA** Method by Alexandru Telea @cite Telea04 .
+@param flags Inpainting method that could be cv::INPAINT_NS or cv::INPAINT_TELEA
The function reconstructs the selected image area from the pixel near the area boundary. The
function may be used to remove dust and scratches from a scanned photo, or to remove undesirable
@note
- An example using the inpainting technique can be found at
opencv_source_code/samples/cpp/inpaint.cpp
- - (Python) An example using the inpainting technique can be found at
+ - (Python) An example using the inpainting technique can be found at
opencv_source_code/samples/python/inpaint.py
*/
CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask,
OutputArray dst, double inpaintRadius, int flags );
+//! @} photo_inpaint
+
//! @addtogroup photo_denoise
//! @{
public:
/** @brief Tonemaps image
- @param src source image - 32-bit 3-channel Mat
- @param dst destination image - 32-bit 3-channel Mat with values in [0, 1] range
+ @param src source image - CV_32FC3 Mat (float 32 bits 3 channels)
+ @param dst destination image - CV_32FC3 Mat with values in [0, 1] range
*/
CV_WRAP virtual void process(InputArray src, OutputArray dst) = 0;
//! @} photo_hdr
+//! @addtogroup photo_decolor
+//! @{
+
/** @brief Transforms a color image to a grayscale image. It is a basic tool in digital printing, stylized
black-and-white photograph rendering, and in many single channel image processing applications
@cite CL12 .
*/
CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost);
+//! @} photo_decolor
+
//! @addtogroup photo_clone
//! @{
+
+//! seamlessClone algorithm flags
+enum
+{
+ /** The power of the method is fully expressed when inserting objects with complex outlines into a new background*/
+ NORMAL_CLONE = 1,
+ /** The classic method, color-based selection and alpha masking might be time consuming and often leaves an undesirable
+ halo. Seamless cloning, even averaged with the original image, is not effective. Mixed seamless cloning based on a loose selection proves effective.*/
+ MIXED_CLONE = 2,
+ /** Monochrome transfer allows the user to easily replace certain features of one object by alternative features.*/
+ MONOCHROME_TRANSFER = 3};
+
+
/** @example samples/cpp/tutorial_code/photo/seamless_cloning/cloning_demo.cpp
An example using seamlessClone function
*/
@param mask Input 8-bit 1 or 3-channel image.
@param p Point in dst image where object is placed.
@param blend Output image with the same size and type as dst.
-@param flags Cloning method that could be one of the following:
-- **NORMAL_CLONE** The power of the method is fully expressed when inserting objects with
-complex outlines into a new background
-- **MIXED_CLONE** The classic method, color-based selection and alpha masking might be time
-consuming and often leaves an undesirable halo. Seamless cloning, even averaged with the
-original image, is not effective. Mixed seamless cloning based on a loose selection proves
-effective.
-- **MONOCHROME_TRANSFER** Monochrome transfer allows the user to easily replace certain features of
-one object by alternative features.
+@param flags Cloning method that could be cv::NORMAL_CLONE, cv::MIXED_CLONE or cv::MONOCHROME_TRANSFER
*/
CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p,
OutputArray blend, int flags);
float alpha = 0.2f, float beta = 0.4f);
/** @brief By retaining only the gradients at edge locations, before integrating with the Poisson solver, one
-washes out the texture of the selected region, giving its contents a flat aspect. Here Canny Edge
-Detector is used.
+washes out the texture of the selected region, giving its contents a flat aspect. Here Canny Edge %Detector is used.
@param src Input 8-bit 3-channel image.
@param mask Input 8-bit 1 or 3-channel image.
@param dst Output image with the same size and type as src.
-@param low_threshold Range from 0 to 100.
+@param low_threshold %Range from 0 to 100.
@param high_threshold Value \> 100.
@param kernel_size The size of the Sobel kernel to be used.
-**NOTE:**
-
+@note
The algorithm assumes that the color of the source image is close to that of the destination. This
assumption means that when the colors don't match, the source image color gets tinted toward the
color of the destination image.
//! @addtogroup photo_render
//! @{
+//! Edge preserving filters
+enum
+{
+ RECURS_FILTER = 1, //!< Recursive Filtering
+ NORMCONV_FILTER = 2 //!< Normalized Convolution Filtering
+};
+
/** @brief Filtering is the fundamental operation in image and video processing. Edge-preserving smoothing
filters are used in many different applications @cite EM11 .
@param src Input 8-bit 3-channel image.
@param dst Output 8-bit 3-channel image.
-@param flags Edge preserving filters:
-- **RECURS_FILTER** = 1
-- **NORMCONV_FILTER** = 2
-@param sigma_s Range between 0 to 200.
-@param sigma_r Range between 0 to 1.
+@param flags Edge preserving filters: cv::RECURS_FILTER or cv::NORMCONV_FILTER
+@param sigma_s %Range between 0 to 200.
+@param sigma_r %Range between 0 to 1.
*/
CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1,
float sigma_s = 60, float sigma_r = 0.4f);
@param src Input 8-bit 3-channel image.
@param dst Output image with the same size and type as src.
-@param sigma_s Range between 0 to 200.
-@param sigma_r Range between 0 to 1.
+@param sigma_s %Range between 0 to 200.
+@param sigma_r %Range between 0 to 1.
*/
CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10,
float sigma_r = 0.15f);
@param src Input 8-bit 3-channel image.
@param dst1 Output 8-bit 1-channel image.
@param dst2 Output image with the same size and type as src.
-@param sigma_s Range between 0 to 200.
-@param sigma_r Range between 0 to 1.
-@param shade_factor Range between 0 to 0.1.
+@param sigma_s %Range between 0 to 200.
+@param sigma_r %Range between 0 to 1.
+@param shade_factor %Range between 0 to 0.1.
*/
CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2,
float sigma_s = 60, float sigma_r = 0.07f, float shade_factor = 0.02f);
@param src Input 8-bit 3-channel image.
@param dst Output image with the same size and type as src.
-@param sigma_s Range between 0 to 200.
-@param sigma_r Range between 0 to 1.
+@param sigma_s %Range between 0 to 200.
+@param sigma_r %Range between 0 to 1.
*/
CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60,
float sigma_r = 0.45f);
Mat src = _src.getMat();
CV_Assert(!src.empty());
+ CV_Assert(_src.dims() == 2 && _src.type() == CV_32FC3);
_dst.create(src.size(), CV_32FC3);
Mat dst = _dst.getMat();
set(OPENCV_PYTHON_INSTALL_PATH_SETUPVARS "${OPENCV_PYTHON_INSTALL_PATH}" CACHE INTERNAL "")
endif()
-if(NOT " ${PYTHON}" STREQUAL " PYTHON" AND DEFINED OPENCV_${PYTHON}_INSTALL_PATH)
- set(__python_binary_install_path "${OPENCV_${PYTHON}_INSTALL_PATH}")
-elseif(OPENCV_SKIP_PYTHON_LOADER AND DEFINED ${PYTHON}_PACKAGES_PATH)
- set(__python_binary_install_path "${${PYTHON}_PACKAGES_PATH}")
+if(OPENCV_SKIP_PYTHON_LOADER)
+ if(DEFINED OPENCV_${PYTHON}_INSTALL_PATH)
+ set(__python_binary_install_path "${OPENCV_${PYTHON}_INSTALL_PATH}")
+ elseif(DEFINED ${PYTHON}_PACKAGES_PATH)
+ set(__python_binary_install_path "${${PYTHON}_PACKAGES_PATH}")
+ else()
+ message(FATAL_ERROR "Specify 'OPENCV_${PYTHON}_INSTALL_PATH' variable")
+ endif()
else()
ocv_assert(DEFINED OPENCV_PYTHON_INSTALL_PATH)
set(__python_binary_install_path "${OPENCV_PYTHON_INSTALL_PATH}/${__python_loader_subdir}python-${${PYTHON}_VERSION_MAJOR}.${${PYTHON}_VERSION_MINOR}")
os.chdir(SCRIPT_DIR)
package_name = 'opencv'
- package_version = os.environ.get('OPENCV_VERSION', '4.0.1') # TODO
+ package_version = os.environ.get('OPENCV_VERSION', '4.1.0') # TODO
long_description = 'Open Source Computer Vision Library Python bindings' # TODO
{ \
if (!dst || dst == Py_None) \
return true; \
- std::underlying_type<TYPE>::type underlying = 0; \
+ int underlying = 0; \
\
if (!pyopencv_to(dst, underlying, name)) return false; \
src = static_cast<TYPE>(underlying); \
template<> \
PyObject* pyopencv_from(const TYPE& src) \
{ \
- return pyopencv_from(static_cast<std::underlying_type<TYPE>::type>(src)); \
+ return pyopencv_from(static_cast<int>(src)); \
}
#include "pyopencv_generated_include.h"
CV_UNUSED(name);
if(!obj || obj == Py_None)
return true;
+ while (PySequence_Check(obj))
+ {
+ PyObject *fi = PySequence_Fast(obj, name);
+ if (fi == NULL)
+ break;
+ if (2 != PySequence_Fast_GET_SIZE(fi))
+ {
+ failmsg("Range value for argument '%s' is longer than 2", name);
+ Py_DECREF(fi);
+ return false;
+ }
+ {
+ PyObject *item = PySequence_Fast_GET_ITEM(fi, 0);
+ if (PyInt_Check(item)) {
+ r.start = (int)PyInt_AsLong(item);
+ } else {
+ failmsg("Range.start value for argument '%s' is not integer", name);
+ Py_DECREF(fi);
+ break;
+ }
+ }
+ {
+ PyObject *item = PySequence_Fast_GET_ITEM(fi, 1);
+ if (PyInt_Check(item)) {
+ r.end = (int)PyInt_AsLong(item);
+ } else {
+ failmsg("Range.end value for argument '%s' is not integer", name);
+ Py_DECREF(fi);
+ break;
+ }
+ }
+ Py_DECREF(fi);
+ return true;
+ }
if(PyObject_Size(obj) == 0)
{
r = Range::all();
struct ConstDef
{
const char * name;
- long val;
+ long long val;
};
static void init_submodule(PyObject * root, const char * name, PyMethodDef * methods, ConstDef * consts)
}
for (ConstDef * c = consts; c->name != NULL; ++c)
{
- PyDict_SetItemString(d, c->name, PyInt_FromLong(c->val));
+ PyDict_SetItemString(d, c->name, PyLong_FromLongLong(c->val));
}
}
if(NOT DEFINED OpenCV_SOURCE_DIR)
message(FATAL_ERROR "Missing OpenCV_SOURCE_DIR")
endif()
-if(NOT OPENCV_PYTHON_INSTALL_PATH)
- if(NOT DEFINED OPENCV_PYTHON_STANDALONE_INSTALL_PATH)
- message(FATAL_ERROR "Missing OPENCV_PYTHON_STANDALONE_INSTALL_PATH / OPENCV_PYTHON_INSTALL_PATH")
- endif()
+if(DEFINED OPENCV_PYTHON_STANDALONE_INSTALL_PATH)
set(OPENCV_PYTHON_INSTALL_PATH "${OPENCV_PYTHON_STANDALONE_INSTALL_PATH}")
+elseif(NOT OPENCV_PYTHON_INSTALL_PATH)
+ message(FATAL_ERROR "Missing OPENCV_PYTHON_STANDALONE_INSTALL_PATH / OPENCV_PYTHON_INSTALL_PATH")
endif()
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVUtils.cmake")
* When setting a resolution for stitching, this values is a placeholder
* for preserving the original resolution.
*/
- static constexpr const double ORIG_RESOL = -1.0;
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900/*MSVS 2015*/)
+ static constexpr double ORIG_RESOL = -1.0;
+#else
+ // support MSVS 2013
+ static const double ORIG_RESOL; // Initialized in stitcher.cpp
+#endif
enum Status
{
namespace cv {
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900/*MSVS 2015*/)
+// Stitcher::ORIG_RESOL is initialized in stitching.hpp.
+#else
+const double Stitcher::ORIG_RESOL = -1.0;
+#endif
+
Ptr<Stitcher> Stitcher::create(Mode mode)
{
Ptr<Stitcher> stitcher = makePtr<Stitcher>();
MOTION_HOMOGRAPHY = 3
};
+/** @brief Computes the Enhanced Correlation Coefficient value between two images @cite EP08 .
+
+@param templateImage single-channel template image; CV_8U or CV_32F array.
+@param inputImage single-channel input image to be warped to provide an image similar to
+ templateImage, same type as templateImage.
+@param inputMask An optional mask to indicate valid values of inputImage.
+
+@sa
+findTransformECC
+ */
+
+CV_EXPORTS_W double computeECC(InputArray templateImage, InputArray inputImage, InputArray inputMask = noArray());
+
/** @example samples/cpp/image_alignment.cpp
An example using the image alignment ECC algorithm
*/
@param templateImage single-channel template image; CV_8U or CV_32F array.
@param inputImage single-channel input image which should be warped with the final warpMatrix in
-order to provide an image similar to templateImage, same type as temlateImage.
+order to provide an image similar to templateImage, same type as templateImage.
@param warpMatrix floating-point \f$2\times 3\f$ or \f$3\times 3\f$ mapping matrix (warp).
@param motionType parameter, specifying the type of motion:
- **MOTION_TRANSLATION** sets a translational motion model; warpMatrix is \f$2\times 3\f$ with
iterations (a negative criteria.epsilon makes criteria.maxcount the only termination criterion).
Default values are shown in the declaration above.
@param inputMask An optional mask to indicate valid values of inputImage.
+@param gaussFiltSize An optional value indicating size of gaussian blur filter; (DEFAULT: 5)
The function estimates the optimum transformation (warpMatrix) with respect to ECC criterion
(@cite EP08), that is
an exception if algorithm does not converges.
@sa
-estimateAffine2D, estimateAffinePartial2D, findHomography
+computeECC, estimateAffine2D, estimateAffinePartial2D, findHomography
*/
CV_EXPORTS_W double findTransformECC( InputArray templateImage, InputArray inputImage,
- InputOutputArray warpMatrix, int motionType = MOTION_AFFINE,
- TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 50, 0.001),
- InputArray inputMask = noArray());
+ InputOutputArray warpMatrix, int motionType,
+ TermCriteria criteria,
+ InputArray inputMask, int gaussFiltSize);
+
+/** @overload */
+CV_EXPORTS
+double findTransformECC(InputArray templateImage, InputArray inputImage,
+ InputOutputArray warpMatrix, int motionType = MOTION_AFFINE,
+ TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 50, 0.001),
+ InputArray inputMask = noArray());
/** @example samples/cpp/kalman.cpp
An example using the standard Kalman filter
typedef tuple<std::string, int, tuple<int, int>, int> Path_Idx_NPoints_WSize_t;
typedef TestBaseWithParam<Path_Idx_NPoints_WSize_t> Path_Idx_NPoints_WSize;
-PERF_TEST_P(Path_Idx_NPoints_WSize, OpticalFlowPyrLK_ovx, testing::Combine(
+PERF_TEST_P(Path_Idx_NPoints_WSize, DISABLED_OpticalFlowPyrLK_ovx, testing::Combine(
testing::Values<std::string>("cv/optflow/frames/VGA_%02d.png", "cv/optflow/frames/720p_%02d.png"),
testing::Range(1, 3),
testing::Values(make_tuple(9, 9), make_tuple(15, 15)),
}
+/** Function that computes enhanced corelation coefficient from Georgios et.al. 2008
+* See https://github.com/opencv/opencv/issues/12432
+*/
+double cv::computeECC(InputArray templateImage, InputArray inputImage, InputArray inputMask)
+{
+ CV_Assert(!templateImage.empty());
+ CV_Assert(!inputImage.empty());
+
+ if( ! (templateImage.type()==inputImage.type()))
+ CV_Error( Error::StsUnmatchedFormats, "Both input images must have the same data type" );
+
+ Scalar meanTemplate, sdTemplate;
+
+ int active_pixels = inputMask.empty() ? templateImage.size().area() : countNonZero(inputMask);
+
+ meanStdDev(templateImage, meanTemplate, sdTemplate, inputMask);
+ Mat templateImage_zeromean = Mat::zeros(templateImage.size(), templateImage.type());
+ subtract(templateImage, meanTemplate, templateImage_zeromean, inputMask);
+ double templateImagenorm = std::sqrt(active_pixels*sdTemplate.val[0]*sdTemplate.val[0]);
+
+ Scalar meanInput, sdInput;
+
+ Mat inputImage_zeromean = Mat::zeros(inputImage.size(), inputImage.type());
+ meanStdDev(inputImage, meanInput, sdInput, inputMask);
+ subtract(inputImage, meanInput, inputImage_zeromean, inputMask);
+ double inputImagenorm = std::sqrt(active_pixels*sdInput.val[0]*sdInput.val[0]);
+
+ return templateImage_zeromean.dot(inputImage_zeromean)/(templateImagenorm*inputImagenorm);
+}
+
+
double cv::findTransformECC(InputArray templateImage,
InputArray inputImage,
InputOutputArray warpMatrix,
int motionType,
TermCriteria criteria,
- InputArray inputMask)
+ InputArray inputMask,
+ int gaussFiltSize)
{
- Mat src = templateImage.getMat();//template iamge
+ Mat src = templateImage.getMat();//template image
Mat dst = inputImage.getMat(); //input image (to be warped)
Mat map = warpMatrix.getMat(); //warp (transformation)
//gaussian filtering is optional
src.convertTo(templateFloat, templateFloat.type());
- GaussianBlur(templateFloat, templateFloat, Size(5, 5), 0, 0);
+ GaussianBlur(templateFloat, templateFloat, Size(gaussFiltSize, gaussFiltSize), 0, 0);
Mat preMaskFloat;
preMask.convertTo(preMaskFloat, CV_32F);
- GaussianBlur(preMaskFloat, preMaskFloat, Size(5, 5), 0, 0);
+ GaussianBlur(preMaskFloat, preMaskFloat, Size(gaussFiltSize, gaussFiltSize), 0, 0);
// Change threshold.
preMaskFloat *= (0.5/0.95);
// Rounding conversion.
preMask.convertTo(preMaskFloat, preMaskFloat.type());
dst.convertTo(imageFloat, imageFloat.type());
- GaussianBlur(imageFloat, imageFloat, Size(5, 5), 0, 0);
+ GaussianBlur(imageFloat, imageFloat, Size(gaussFiltSize, gaussFiltSize), 0, 0);
// needed matrices for gradients and warped gradients
Mat gradientX = Mat::zeros(hd, wd, CV_32FC1);
return rho;
}
+double cv::findTransformECC(InputArray templateImage, InputArray inputImage,
+ InputOutputArray warpMatrix, int motionType,
+ TermCriteria criteria,
+ InputArray inputMask)
+{
+ // Use default value of 5 for gaussFiltSize to maintain backward compatibility.
+ return findTransformECC(templateImage, inputImage, warpMatrix, motionType, criteria, inputMask, 5);
+}
/* End of file. */
return sqrt(errorMat.dot(errorMat)/(mat1.rows*mat1.cols));
}
-
class CV_ECC_Test_Translation : public CV_ECC_BaseTest
{
public:
return false;
}
+ // Test with non-default gaussian blur.
+ findTransformECC(warpedImage, testImg, mapTranslation, 0,
+ TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon), mask, 1);
+
+ if (!isMapCorrect(mapTranslation)){
+ ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
+ return false;
+ }
+
+ if (computeRMS(mapTranslation, translationGround)>MAX_RMS_ECC){
+ ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
+ ts->printf( ts->LOG, "RMS = %f",
+ computeRMS(mapTranslation, translationGround));
+ return false;
+ }
+
}
return true;
}
ts->set_failed_test_info(cvtest::TS::OK);
}
+TEST(Video_ECC_Test_Compute, accuracy)
+{
+ Mat testImg = (Mat_<float>(3, 3) << 1, 0, 0, 1, 0, 0, 1, 0, 0);
+ Mat warpedImage = (Mat_<float>(3, 3) << 0, 1, 0, 0, 1, 0, 0, 1, 0);
+ Mat_<unsigned char> mask = Mat_<unsigned char>::ones(testImg.rows, testImg.cols);
+ double ecc = computeECC(warpedImage, testImg, mask);
+
+ EXPECT_NEAR(ecc, -0.5f, 1e-5f);
+}
+
TEST(Video_ECC_Translation, accuracy) { CV_ECC_Test_Translation test; test.safe_run();}
TEST(Video_ECC_Euclidean, accuracy) { CV_ECC_Test_Euclidean test; test.safe_run(); }
TEST(Video_ECC_Affine, accuracy) { CV_ECC_Test_Affine test; test.safe_run(); }
+set(VIDEOIO_PLUGIN_LIST "" CACHE STRING "List of videoio backends to be compiled as plugins (ffmpeg, gstreamer)")
+set(VIDEOIO_ENABLE_PLUGINS "ON" CACHE BOOL "Allow building videoio plugin support")
+set(VIDEOIO_ENABLE_STRICT_PLUGIN_CHECK "ON" CACHE BOOL "Make sure OpenCV version is the same in plugin and host code")
+mark_as_advanced(VIDEOIO_PLUGIN_LIST VIDEOIO_ENABLE_PLUGINS VIDEOIO_ENABLE_STRICT_PLUGIN_CHECK)
+
+string(REPLACE "," ";" VIDEOIO_PLUGIN_LIST "${VIDEOIO_PLUGIN_LIST}") # support comma-separated list (,) too
+
+# Make virtual opencv_videoio_plugins target
+if(NOT TARGET opencv_videoio_plugins)
+ add_custom_target(opencv_videoio_plugins ALL)
+endif()
+
ocv_add_module(videoio opencv_imgproc opencv_imgcodecs WRAP java python)
set(videoio_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/precomp.hpp)
"${CMAKE_CURRENT_LIST_DIR}/src/cap_images.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/cap_mjpeg_encoder.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/cap_mjpeg_decoder.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/src/backend_plugin.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/src/backend_static.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/container_avi.cpp")
file(GLOB videoio_ext_hdrs
list(APPEND tgts ocv.3rdparty.dc1394_2)
endif()
+include(${CMAKE_CURRENT_LIST_DIR}/cmake/plugin.cmake)
+
if(TARGET ocv.3rdparty.gstreamer)
- list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_gstreamer.cpp)
- list(APPEND tgts ocv.3rdparty.gstreamer)
+ if("gstreamer" IN_LIST VIDEOIO_PLUGIN_LIST)
+ ocv_create_builtin_videoio_plugin("opencv_videoio_gstreamer" ocv.3rdparty.gstreamer "cap_gstreamer.cpp")
+ else()
+ list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_gstreamer.cpp)
+ list(APPEND tgts ocv.3rdparty.gstreamer)
+ endif()
endif()
if(TARGET ocv.3rdparty.v4l)
endif()
if(TARGET ocv.3rdparty.ffmpeg)
- list(APPEND videoio_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/cap_ffmpeg_impl.hpp)
- list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_ffmpeg.cpp)
- list(APPEND tgts ocv.3rdparty.ffmpeg)
+ if("ffmpeg" IN_LIST VIDEOIO_PLUGIN_LIST)
+ ocv_create_builtin_videoio_plugin("opencv_videoio_ffmpeg" ocv.3rdparty.ffmpeg "cap_ffmpeg.cpp")
+ else()
+ list(APPEND videoio_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/cap_ffmpeg_impl.hpp)
+ list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_ffmpeg.cpp)
+ list(APPEND tgts ocv.3rdparty.ffmpeg)
+ endif()
endif()
if(TARGET ocv.3rdparty.pvapi)
list(APPEND tgts ocv.3rdparty.cap_ios)
endif()
+if(TARGET ocv.3rdparty.android_mediandk)
+ list(APPEND videoio_srcs
+ ${CMAKE_CURRENT_LIST_DIR}/src/cap_android_mediandk.cpp)
+ list(APPEND tgts ocv.3rdparty.android_mediandk)
+endif()
+
ocv_set_module_sources(HEADERS ${videoio_ext_hdrs} ${videoio_hdrs} SOURCES ${videoio_srcs})
ocv_module_include_directories()
ocv_create_module()
ocv_add_accuracy_tests(${tgts})
ocv_add_perf_tests(${tgts})
+if(VIDEOIO_ENABLE_PLUGINS)
+ ocv_target_compile_definitions(${the_module} PRIVATE ENABLE_PLUGINS)
+endif()
+
+if(VIDEOIO_ENABLE_STRICT_PLUGIN_CHECK)
+ ocv_target_compile_definitions(${the_module} PRIVATE STRICT_PLUGIN_CHECK)
+endif()
+
ocv_target_link_libraries(${the_module} LINK_PRIVATE ${tgts})
# copy FFmpeg dll to the output folder
--- /dev/null
+# if(ANDROID AND ANDROID_NATIVE_API_LEVEL GREATER_EQUAL 21) <-- would be nicer but requires CMake 3.7 or later
+if(ANDROID AND ANDROID_NATIVE_API_LEVEL GREATER 20)
+ set(HAVE_ANDROID_MEDIANDK TRUE)
+ set(libs "-landroid -llog -lmediandk")
+ ocv_add_external_target(android_mediandk "" "${libs}" "HAVE_ANDROID_MEDIANDK")
+endif()
+
+set(HAVE_ANDROID_MEDIANDK ${HAVE_ANDROID_MEDIANDK} PARENT_SCOPE)
if(FFMPEG_libavresample_FOUND)
list(APPEND FFMPEG_LIBRARIES ${FFMPEG_libavresample_LIBRARIES})
endif()
-
# rewrite libraries to absolute paths
foreach(lib ${FFMPEG_LIBRARIES})
- find_library(FFMPEG_ABSOLUTE_${lib} "${lib}" PATHS "${FFMPEG_lib${lib}_LIBDIR}" NO_DEFAULT_PATH)
+ find_library(FFMPEG_ABSOLUTE_${lib} "${lib}" PATHS "${FFMPEG_lib${lib}_LIBDIR}" "${FFMPEG_LIBRARY_DIRS}" NO_DEFAULT_PATH)
if(FFMPEG_ABSOLUTE_${lib})
list(APPEND ffmpeg_abs_libs "${FFMPEG_ABSOLUTE_${lib}}")
else()
#==================================
-if(HAVE_FFMPEG AND NOT HAVE_FFMPEG_WRAPPER)
+if(HAVE_FFMPEG AND NOT HAVE_FFMPEG_WRAPPER AND NOT OPENCV_FFMPEG_SKIP_BUILD_CHECK)
try_compile(__VALID_FFMPEG
"${OpenCV_BINARY_DIR}"
"${OpenCV_SOURCE_DIR}/cmake/checks/ffmpeg_test.cpp"
endif()
endfunction()
+include(FindPkgConfig)
+
add_backend("ffmpeg" WITH_FFMPEG)
add_backend("gstreamer" WITH_GSTREAMER)
add_backend("v4l" WITH_V4L)
add_backend("dshow" WITH_DSHOW)
add_backend("msmf" WITH_MSMF)
+
+add_backend("android_mediandk" WITH_ANDROID_MEDIANDK)
--- /dev/null
+#=============================================
+# build with OpenCV
+
+function(ocv_create_builtin_videoio_plugin name target videoio_src_file)
+
+ ocv_debug_message("ocv_create_builtin_videoio_plugin(${ARGV})")
+
+ if(NOT TARGET ${target})
+ message(FATAL_ERROR "${target} does not exist!")
+ endif()
+ if(NOT OpenCV_SOURCE_DIR)
+ message(FATAL_ERROR "OpenCV_SOURCE_DIR must be set to build the plugin!")
+ endif()
+
+ message(STATUS "Video I/O: add builtin plugin '${name}'")
+
+ add_library(${name} MODULE
+ "${CMAKE_CURRENT_LIST_DIR}/src/${videoio_src_file}"
+ )
+ target_include_directories(${name} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
+ target_compile_definitions(${name} PRIVATE BUILD_PLUGIN)
+ target_link_libraries(${name} PRIVATE ${target})
+
+ foreach(mod opencv_videoio opencv_core opencv_imgproc opencv_imgcodecs)
+ target_link_libraries(${name} PRIVATE ${mod})
+ target_include_directories(${name} PRIVATE "${OPENCV_MODULE_${mod}_LOCATION}/include")
+ endforeach()
+
+ set_target_properties(${name} PROPERTIES
+ CXX_STANDARD 11
+ CXX_VISIBILITY_PRESET hidden
+ )
+ install(TARGETS ${name} LIBRARY DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT plugins OPTIONAL)
+
+ add_dependencies(opencv_videoio_plugins ${name})
+
+endfunction()
+
+#=============================================
+# standalone build
+
+function(ocv_create_videoio_plugin default_name target target_desc videoio_src_file)
+
+ set(OPENCV_PLUGIN_NAME ${default_name} CACHE STRING "")
+ set(OPENCV_PLUGIN_DESTINATION "" CACHE PATH "")
+ project(${OPENCV_PLUGIN_NAME} LANGUAGES CXX)
+
+ set(BUILD_SHARED_LIBS ON CACHE BOOL "")
+ if(NOT BUILD_SHARED_LIBS)
+ message(FATAL_ERROR "Static plugin build does not make sense")
+ endif()
+
+ if(NOT OpenCV_SOURCE_DIR)
+ message(FATAL_ERROR "OpenCV_SOURCE_DIR must be set to build the plugin!")
+ endif()
+
+ include("${OpenCV_SOURCE_DIR}/modules/videoio/cmake/init.cmake")
+
+ if(NOT TARGET ${target})
+ message(FATAL_ERROR "${target_desc} was not found!")
+ endif()
+
+ set(modules_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../..")
+ set(videoio_ROOT "${modules_ROOT}/videoio")
+ set(core_ROOT "${modules_ROOT}/core")
+ set(imgproc_ROOT "${modules_ROOT}/imgproc")
+ set(imgcodecs_ROOT "${modules_ROOT}/imgcodecs")
+
+ add_library(${OPENCV_PLUGIN_NAME} MODULE "${videoio_ROOT}/src/${videoio_src_file}")
+ target_include_directories(${OPENCV_PLUGIN_NAME} PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ "${videoio_ROOT}/src"
+ "${videoio_ROOT}/include"
+ "${core_ROOT}/include"
+ "${imgproc_ROOT}/include"
+ "${imgcodecs_ROOT}/include"
+ )
+ target_compile_definitions(${OPENCV_PLUGIN_NAME} PRIVATE BUILD_PLUGIN)
+
+ # Fixes for build
+ target_compile_definitions(${OPENCV_PLUGIN_NAME} PRIVATE __OPENCV_BUILD)
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cvconfig.h" "#pragma once")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cv_cpu_config.h" "#pragma once")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/opencv2/opencv_modules.hpp" "#pragma once")
+
+ target_link_libraries(${OPENCV_PLUGIN_NAME} PRIVATE ${target})
+ set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES
+ CXX_STANDARD 11
+ CXX_VISIBILITY_PRESET hidden
+ )
+
+ # Hack for Windows
+ if(WIN32)
+ find_package(OpenCV REQUIRED core imgproc videoio)
+ target_link_libraries(${OPENCV_PLUGIN_NAME} ${OpenCV_LIBS})
+ endif()
+
+ if(OPENCV_PLUGIN_DESTINATION)
+ set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${OPENCV_PLUGIN_DESTINATION}")
+ message(STATUS "Output destination: ${OPENCV_PLUGIN_DESTINATION}")
+ endif()
+
+ message(STATUS "Library name: ${OPENCV_PLUGIN_NAME}")
+
+endfunction()
/** @brief Returns list of available backends which works via `cv::VideoWriter()` */
CV_EXPORTS_W std::vector<VideoCaptureAPIs> getWriterBackends();
+/** @brief Returns true if backend is available */
+CV_EXPORTS bool hasBackend(VideoCaptureAPIs api);
+
//! @}
}} // namespace
--- /dev/null
+#!/bin/bash
+
+set -e
+
+if [ -z $1 ] ; then
+ echo "<script> <destination directory>"
+ exit 1
+fi
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+OCV="$( cd "${DIR}/../../.." >/dev/null 2>&1 && pwd )"
+mkdir -p "${1}" # Docker creates non-existed mounts with 'root' owner, lets ensure that dir exists under the current user to avoid "Permission denied" problem
+DST="$( cd "$1" >/dev/null 2>&1 && pwd )"
+CFG=$2
+
+do_build()
+{
+TAG=$1
+D=$2
+F=$3
+shift 3
+docker build \
+ --build-arg http_proxy \
+ --build-arg https_proxy \
+ $@ \
+ -t $TAG \
+ -f "${D}/${F}" \
+ "${D}"
+}
+
+do_run()
+{
+TAG=$1
+shift 1
+docker run \
+ -it \
+ --rm \
+ -v "${OCV}":/opencv:ro \
+ -v "${DST}":/dst \
+ -e CFG=$CFG \
+ --user $(id -u):$(id -g) \
+ $TAG \
+ $@
+}
+
+build_gstreamer()
+{
+TAG=opencv_gstreamer_builder
+do_build $TAG "${DIR}/plugin_gstreamer" Dockerfile
+do_run $TAG /opencv/modules/videoio/misc/plugin_gstreamer/build.sh /dst $CFG
+}
+
+build_ffmpeg_ubuntu()
+{
+VER=$1
+TAG=opencv_ffmpeg_ubuntu_builder:${VER}
+do_build $TAG "${DIR}/plugin_ffmpeg" Dockerfile-ubuntu --build-arg VER=${VER}
+do_run $TAG /opencv/modules/videoio/misc/plugin_ffmpeg/build-ubuntu.sh /dst ${VER} ${CFG}
+}
+
+build_ffmpeg()
+{
+VER=$1
+TAG=opencv_ffmpeg_builder:${VER}
+ARCHIVE="${DIR}/plugin_ffmpeg/ffmpeg-${VER}.tar.xz"
+if [ ! -f "${ARCHIVE}" ] ; then
+ wget https://www.ffmpeg.org/releases/ffmpeg-${VER}.tar.xz -O "${ARCHIVE}"
+fi
+do_build $TAG "${DIR}/plugin_ffmpeg" Dockerfile-ffmpeg --build-arg VER=${VER}
+do_run $TAG /opencv/modules/videoio/misc/plugin_ffmpeg/build-standalone.sh /dst ${VER} ${CFG}
+}
+
+echo "OpenCV: ${OCV}"
+echo "Destination: ${DST}"
+
+build_gstreamer
+build_ffmpeg_ubuntu 18.04
+build_ffmpeg_ubuntu 16.04
+build_ffmpeg 4.1
+build_ffmpeg 3.4.5
+build_ffmpeg 2.8.15
--- /dev/null
+cmake_minimum_required(VERSION 3.5)
+
+set(OpenCV_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../..")
+set(WITH_FFMPEG ON)
+set(OPENCV_FFMPEG_SKIP_BUILD_CHECK ON)
+include("${OpenCV_SOURCE_DIR}/modules/videoio/cmake/plugin.cmake")
+ocv_create_videoio_plugin("opencv_videoio_ffmpeg" "ocv.3rdparty.ffmpeg" "FFmpeg" "cap_ffmpeg.cpp")
+
+message(STATUS "FFMPEG_libavcodec_VERSION=${FFMPEG_libavcodec_VERSION}")
+message(STATUS "FFMPEG_libavformat_VERSION=${FFMPEG_libavformat_VERSION}")
+message(STATUS "FFMPEG_libavutil_VERSION=${FFMPEG_libavutil_VERSION}")
+message(STATUS "FFMPEG_libswscale_VERSION=${FFMPEG_libswscale_VERSION}")
+message(STATUS "FFMPEG_libavresample_VERSION=${FFMPEG_libavresample_VERSION}")
--- /dev/null
+FROM ubuntu:18.04
+
+RUN apt-get update && apt-get install -y \
+ pkg-config \
+ cmake \
+ g++ \
+ ninja-build \
+ make \
+ nasm \
+ && \
+ rm -rf /var/lib/apt/lists/*
+
+ARG VER
+
+ADD ffmpeg-${VER}.tar.xz /ffmpeg/
+
+WORKDIR /ffmpeg/ffmpeg-${VER}
+RUN ./configure \
+ --enable-avresample \
+ --prefix=/ffmpeg-shared \
+ --enable-shared \
+ --disable-static \
+ --disable-programs \
+ --disable-doc \
+ --disable-avdevice \
+ --disable-postproc \
+ && make -j8 install \
+ && make clean \
+ && make distclean
+
+RUN ./configure \
+ --enable-avresample \
+ --prefix=/ffmpeg-static \
+ --disable-shared \
+ --enable-static \
+ --enable-pic \
+ --disable-programs \
+ --disable-doc \
+ --disable-avdevice \
+ --disable-postproc \
+ && make -j8 install \
+ && make clean \
+ && make distclean
+
+WORKDIR /tmp
--- /dev/null
+ARG VER
+FROM ubuntu:$VER
+
+RUN apt-get update && apt-get install -y \
+ libavcodec-dev \
+ libavfilter-dev \
+ libavformat-dev \
+ libavresample-dev \
+ libavutil-dev \
+ pkg-config \
+ cmake \
+ g++ \
+ ninja-build \
+ && \
+ rm -rf /var/lib/apt/lists/*
+
+WORKDIR /tmp
--- /dev/null
+#!/bin/bash
+
+set -e
+
+mkdir -p build_shared && pushd build_shared
+PKG_CONFIG_PATH=/ffmpeg-shared/lib/pkgconfig \
+cmake -GNinja \
+ -DOPENCV_PLUGIN_NAME=opencv_videoio_ffmpeg_shared_$2 \
+ -DOPENCV_PLUGIN_DESTINATION=$1 \
+ -DCMAKE_BUILD_TYPE=$3 \
+ /opencv/modules/videoio/misc/plugin_ffmpeg
+ninja
+popd
+
+mkdir -p build_static && pushd build_static
+PKG_CONFIG_PATH=/ffmpeg-static/lib/pkgconfig \
+cmake -GNinja \
+ -DOPENCV_PLUGIN_NAME=opencv_videoio_ffmpeg_static_$2 \
+ -DOPENCV_PLUGIN_DESTINATION=$1 \
+ -DCMAKE_MODULE_LINKER_FLAGS=-Wl,-Bsymbolic \
+ -DCMAKE_BUILD_TYPE=$3 \
+ /opencv/modules/videoio/misc/plugin_ffmpeg
+ninja
+popd
--- /dev/null
+#!/bin/bash
+
+set -e
+
+cmake -GNinja \
+ -DOPENCV_PLUGIN_NAME=opencv_videoio_ffmpeg_ubuntu_$2 \
+ -DOPENCV_PLUGIN_DESTINATION=$1 \
+ -DCMAKE_BUILD_TYPE=$3 \
+ /opencv/modules/videoio/misc/plugin_ffmpeg
+ninja
--- /dev/null
+cmake_minimum_required(VERSION 3.5)
+
+set(OpenCV_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../..")
+set(WITH_GSTREAMER ON)
+include("${OpenCV_SOURCE_DIR}/modules/videoio/cmake/plugin.cmake")
+ocv_create_videoio_plugin("opencv_videoio_gstreamer" "ocv.3rdparty.gstreamer" "GStreamer" "cap_gstreamer.cpp")
+
+message(STATUS "Using GStreamer: ${GSTREAMER_VERSION}")
--- /dev/null
+FROM ubuntu:18.04
+
+RUN apt-get update && apt-get install -y \
+ libgstreamer-plugins-base1.0-dev \
+ libgstreamer-plugins-good1.0-dev \
+ libgstreamer1.0-dev \
+ cmake \
+ g++ \
+ ninja-build \
+ && \
+ rm -rf /var/lib/apt/lists/*
+
+WORKDIR /tmp
--- /dev/null
+#!/bin/bash
+
+set -e
+
+cmake -GNinja \
+ -DOPENCV_PLUGIN_NAME=opencv_videoio_gstreamer \
+ -DOPENCV_PLUGIN_DESTINATION=$1 \
+ -DCMAKE_BUILD_TYPE=$2 \
+ /opencv/modules/videoio/misc/plugin_gstreamer
+
+ninja
--- /dev/null
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+
+#ifndef BACKEND_HPP_DEFINED
+#define BACKEND_HPP_DEFINED
+
+#include "cap_interface.hpp"
+#include "opencv2/videoio/registry.hpp"
+
+namespace cv {
+
+// TODO: move to public interface
+// TODO: allow runtime backend registration
+class IBackend
+{
+public:
+ virtual ~IBackend() {}
+ virtual Ptr<IVideoCapture> createCapture(int camera) const = 0;
+ virtual Ptr<IVideoCapture> createCapture(const std::string &filename) const = 0;
+ virtual Ptr<IVideoWriter> createWriter(const std::string &filename, int fourcc, double fps, const cv::Size &sz, bool isColor) const = 0;
+};
+
+class IBackendFactory
+{
+public:
+ virtual ~IBackendFactory() {}
+ virtual Ptr<IBackend> getBackend() const = 0;
+};
+
+//=============================================================================
+
+typedef Ptr<IVideoCapture> (*FN_createCaptureFile)(const std::string & filename);
+typedef Ptr<IVideoCapture> (*FN_createCaptureCamera)(int camera);
+typedef Ptr<IVideoWriter> (*FN_createWriter)(const std::string& filename, int fourcc, double fps, const Size& sz, bool isColor);
+Ptr<IBackendFactory> createBackendFactory(FN_createCaptureFile createCaptureFile,
+ FN_createCaptureCamera createCaptureCamera,
+ FN_createWriter createWriter);
+
+Ptr<IBackendFactory> createPluginBackendFactory(VideoCaptureAPIs id, const char* baseName);
+
+} // namespace cv::
+
+#endif // BACKEND_HPP_DEFINED
--- /dev/null
+// 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 "precomp.hpp"
+
+#include "backend.hpp"
+#include "plugin_api.hpp"
+
+#include "opencv2/core/utils/filesystem.hpp"
+#include "opencv2/core/utils/configuration.private.hpp"
+#include "opencv2/core/private.hpp"
+#include "videoio_registry.hpp"
+
+//==================================================================================================
+// Dynamic backend implementation
+
+#include "opencv2/core/utils/logger.hpp"
+#include <sstream>
+using namespace std;
+
+#if defined(_WIN32)
+#include <windows.h>
+#elif defined(__linux__) || defined(__APPLE__)
+#include <dlfcn.h>
+#endif
+
+namespace cv { namespace impl {
+
+#if defined(_WIN32)
+typedef HMODULE LibHandle_t;
+#elif defined(__linux__) || defined(__APPLE__)
+typedef void* LibHandle_t;
+#endif
+
+static Mutex& getInitializationMutex()
+{
+ static Mutex initializationMutex;
+ return initializationMutex;
+}
+
+static inline
+void* getSymbol_(LibHandle_t h, const char* symbolName)
+{
+#if defined(_WIN32)
+ return (void*)GetProcAddress(h, symbolName);
+#elif defined(__linux__) || defined(__APPLE__)
+ return dlsym(h, symbolName);
+#endif
+}
+
+static inline
+LibHandle_t libraryLoad_(const char* filename)
+{
+#if defined(_WIN32)
+ return LoadLibraryA(filename);
+#elif defined(__linux__) || defined(__APPLE__)
+ return dlopen(filename, RTLD_LAZY);
+#endif
+}
+
+static inline
+void libraryRelease_(LibHandle_t h)
+{
+#if defined(_WIN32)
+ FreeLibrary(h);
+#elif defined(__linux__) || defined(__APPLE__)
+ dlclose(h);
+#endif
+}
+
+static inline
+std::string libraryPrefix()
+{
+#if defined(_WIN32)
+ return string();
+#else
+ return "lib";
+#endif
+}
+static inline
+std::string librarySuffix()
+{
+#if defined(_WIN32)
+ return ".dll";
+#elif defined(__APPLE__)
+ return ".dylib";
+#else
+ return ".so";
+#endif
+}
+
+//============================
+
+class DynamicLib
+{
+private:
+ LibHandle_t handle;
+ const std::string fname;
+
+public:
+ DynamicLib(const std::string &filename)
+ : handle(0), fname(filename)
+ {
+ libraryLoad(filename);
+ }
+ ~DynamicLib()
+ {
+ libraryRelease();
+ }
+ bool isLoaded() const
+ {
+ return handle != NULL;
+ }
+ void* getSymbol(const char* symbolName) const
+ {
+ if (!handle)
+ {
+ return 0;
+ }
+ void * res = getSymbol_(handle, symbolName);
+ if (!res)
+ CV_LOG_ERROR(NULL, "No symbol '" << symbolName << "' in " << fname);
+ return res;
+ }
+ const std::string& getName() const { return fname; }
+private:
+ void libraryLoad(const std::string &filename)
+ {
+ handle = libraryLoad_(filename.c_str());
+ CV_LOG_INFO(NULL, "load " << filename << " => " << (handle ? "OK" : "FAILED"));
+ }
+ void libraryRelease()
+ {
+ CV_LOG_INFO(NULL, "unload "<< fname);
+ if (handle)
+ {
+ libraryRelease_(handle);
+ handle = 0;
+ }
+ }
+
+private:
+ DynamicLib(const DynamicLib &);
+ DynamicLib &operator=(const DynamicLib &);
+};
+
+
+//============================
+
+class PluginBackend: public IBackend
+{
+public:
+ Ptr<DynamicLib> lib_;
+ const OpenCV_VideoIO_Plugin_API_preview* plugin_api_;
+
+ PluginBackend(const Ptr<DynamicLib>& lib) :
+ lib_(lib), plugin_api_(NULL)
+ {
+ const char* init_name = "opencv_videoio_plugin_init_v0";
+ FN_opencv_videoio_plugin_init_t fn_init = reinterpret_cast<FN_opencv_videoio_plugin_init_t>(lib_->getSymbol(init_name));
+ if (fn_init)
+ {
+ plugin_api_ = fn_init(ABI_VERSION, API_VERSION, NULL);
+ if (!plugin_api_)
+ {
+ CV_LOG_INFO(NULL, "Video I/O: plugin is incompatible: " << lib->getName());
+ return;
+ }
+ if (plugin_api_->api_header.opencv_version_major != CV_VERSION_MAJOR ||
+ plugin_api_->api_header.opencv_version_minor != CV_VERSION_MINOR)
+ {
+ CV_LOG_ERROR(NULL, "Video I/O: wrong OpenCV version used by plugin '" << plugin_api_->api_header.api_description << "': " <<
+ cv::format("%d.%d, OpenCV version is '" CV_VERSION "'", plugin_api_->api_header.opencv_version_major, plugin_api_->api_header.opencv_version_minor))
+ plugin_api_ = NULL;
+ return;
+ }
+ // TODO Preview: add compatibility API/ABI checks
+ CV_LOG_INFO(NULL, "Video I/O: loaded plugin '" << plugin_api_->api_header.api_description << "'");
+ }
+ else
+ {
+ CV_LOG_INFO(NULL, "Video I/O: plugin is incompatible, missing init function: '" << init_name << "', file: " << lib->getName());
+ }
+ }
+
+ Ptr<IVideoCapture> createCapture(int camera) const CV_OVERRIDE;
+ Ptr<IVideoCapture> createCapture(const std::string &filename) const CV_OVERRIDE;
+ Ptr<IVideoWriter> createWriter(const std::string &filename, int fourcc, double fps, const cv::Size &sz, bool isColor) const CV_OVERRIDE;
+};
+
+class PluginBackendFactory : public IBackendFactory
+{
+public:
+ VideoCaptureAPIs id_;
+ const char* baseName_;
+ Ptr<PluginBackend> backend;
+ bool initialized;
+public:
+ PluginBackendFactory(VideoCaptureAPIs id, const char* baseName) :
+ id_(id), baseName_(baseName),
+ initialized(false)
+ {
+ // nothing, plugins are loaded on demand
+ }
+
+ Ptr<IBackend> getBackend() const CV_OVERRIDE
+ {
+ if (!initialized)
+ {
+ const_cast<PluginBackendFactory*>(this)->initBackend();
+ }
+ return backend.staticCast<IBackend>();
+ }
+protected:
+ void initBackend()
+ {
+ AutoLock lock(getInitializationMutex());
+ try {
+ if (!initialized)
+ loadPlugin();
+ }
+ catch (...)
+ {
+ CV_LOG_INFO(NULL, "Video I/O: exception during plugin loading: " << baseName_ << ". SKIP");
+ }
+ initialized = true;
+ }
+ void loadPlugin();
+};
+
+static
+std::vector<string> getPluginCandidates(const std::string& baseName)
+{
+ using namespace cv::utils;
+ using namespace cv::utils::fs;
+#ifndef CV_VIDEOIO_PLUGIN_SUBDIRECTORY
+#define CV_VIDEOIO_PLUGIN_SUBDIRECTORY_STR ""
+#else
+#define CV_VIDEOIO_PLUGIN_SUBDIRECTORY_STR CVAUX_STR(CV_VIDEOIO_PLUGIN_SUBDIRECTORY)
+#endif
+ const vector<string> default_paths = { utils::fs::join(getParent(getBinLocation()), CV_VIDEOIO_PLUGIN_SUBDIRECTORY_STR) };
+ const vector<string> paths = getConfigurationParameterPaths("OPENCV_VIDEOIO_PLUGIN_PATH", default_paths);
+ const string baseName_l = toLowerCase(baseName);
+ const string baseName_u = toUpperCase(baseName);
+ const string default_expr = libraryPrefix() + "opencv_videoio_" + baseName_l + "*" + librarySuffix();
+ const string expr = getConfigurationParameterString((std::string("OPENCV_VIDEOIO_PLUGIN_") + baseName_u).c_str(), default_expr.c_str());
+ CV_LOG_INFO(NULL, "VideoIO pluigin (" << baseName << "): glob is '" << expr << "', " << paths.size() << " location(s)");
+ vector<string> results;
+ for(const string & path : paths)
+ {
+ if (path.empty())
+ continue;
+ vector<string> candidates;
+ cv::glob(utils::fs::join(path, expr), candidates);
+ CV_LOG_INFO(NULL, " - " << path << ": " << candidates.size());
+ copy(candidates.begin(), candidates.end(), back_inserter(results));
+ }
+ CV_LOG_INFO(NULL, "Found " << results.size() << " plugin(s) for " << baseName);
+ return results;
+}
+
+void PluginBackendFactory::loadPlugin()
+{
+ for(const std::string & plugin : getPluginCandidates(baseName_))
+ {
+ Ptr<DynamicLib> lib = makePtr<DynamicLib>(plugin);
+ if (!lib->isLoaded())
+ continue;
+ try
+ {
+ Ptr<PluginBackend> pluginBackend = makePtr<PluginBackend>(lib);
+ if (pluginBackend && pluginBackend->plugin_api_)
+ {
+ if (pluginBackend->plugin_api_->captureAPI != id_)
+ {
+ CV_LOG_ERROR(NULL, "Video I/O: plugin '" << pluginBackend->plugin_api_->api_header.api_description <<
+ "': unexpected backend ID: " <<
+ pluginBackend->plugin_api_->captureAPI << " vs " << (int)id_ << " (expected)");
+ }
+ else
+ {
+ backend = pluginBackend;
+ return;
+ }
+ }
+ }
+ catch (...)
+ {
+ CV_LOG_INFO(NULL, "Video I/O: exception during plugin initialization: " << plugin << ". SKIP");
+ }
+ }
+}
+
+
+//==================================================================================================
+
+class PluginCapture : public cv::IVideoCapture
+{
+ const OpenCV_VideoIO_Plugin_API_preview* plugin_api_;
+ CvPluginCapture capture_;
+
+public:
+ static
+ Ptr<PluginCapture> create(const OpenCV_VideoIO_Plugin_API_preview* plugin_api,
+ const std::string &filename, int camera)
+ {
+ CV_Assert(plugin_api);
+ CvPluginCapture capture = NULL;
+ if (plugin_api->Capture_open)
+ {
+ CV_Assert(plugin_api->Capture_release);
+ if (CV_ERROR_OK == plugin_api->Capture_open(filename.empty() ? 0 : filename.c_str(), camera, &capture))
+ {
+ CV_Assert(capture);
+ return makePtr<PluginCapture>(plugin_api, capture);
+ }
+ }
+ return Ptr<PluginCapture>();
+ }
+
+ PluginCapture(const OpenCV_VideoIO_Plugin_API_preview* plugin_api, CvPluginCapture capture)
+ : plugin_api_(plugin_api), capture_(capture)
+ {
+ CV_Assert(plugin_api_); CV_Assert(capture_);
+ }
+
+ ~PluginCapture()
+ {
+ CV_DbgAssert(plugin_api_->Capture_release);
+ if (CV_ERROR_OK != plugin_api_->Capture_release(capture_))
+ CV_LOG_ERROR(NULL, "Video I/O: Can't release capture by plugin '" << plugin_api_->api_header.api_description << "'");
+ capture_ = NULL;
+ }
+ double getProperty(int prop) const CV_OVERRIDE
+ {
+ double val = -1;
+ if (plugin_api_->Capture_getProperty)
+ if (CV_ERROR_OK != plugin_api_->Capture_getProperty(capture_, prop, &val))
+ val = -1;
+ return val;
+ }
+ bool setProperty(int prop, double val) CV_OVERRIDE
+ {
+ if (plugin_api_->Capture_setProperty)
+ if (CV_ERROR_OK == plugin_api_->Capture_setProperty(capture_, prop, val))
+ return true;
+ return false;
+ }
+ bool grabFrame() CV_OVERRIDE
+ {
+ if (plugin_api_->Capture_grab)
+ if (CV_ERROR_OK == plugin_api_->Capture_grab(capture_))
+ return true;
+ return false;
+ }
+ static CvResult CV_API_CALL retrieve_callback(int stream_idx, const unsigned char* data, int step, int width, int height, int cn, void* userdata)
+ {
+ CV_UNUSED(stream_idx);
+ cv::_OutputArray* dst = static_cast<cv::_OutputArray*>(userdata);
+ if (!dst)
+ return CV_ERROR_FAIL;
+ cv::Mat(cv::Size(width, height), CV_MAKETYPE(CV_8U, cn), (void*)data, step).copyTo(*dst);
+ return CV_ERROR_OK;
+ }
+ bool retrieveFrame(int idx, cv::OutputArray img) CV_OVERRIDE
+ {
+ bool res = false;
+ if (plugin_api_->Capture_retreive)
+ if (CV_ERROR_OK == plugin_api_->Capture_retreive(capture_, idx, retrieve_callback, (cv::_OutputArray*)&img))
+ res = true;
+ return res;
+ }
+ bool isOpened() const CV_OVERRIDE
+ {
+ return capture_ != NULL; // TODO always true
+ }
+ int getCaptureDomain() CV_OVERRIDE
+ {
+ return plugin_api_->captureAPI;
+ }
+};
+
+
+//==================================================================================================
+
+class PluginWriter : public cv::IVideoWriter
+{
+ const OpenCV_VideoIO_Plugin_API_preview* plugin_api_;
+ CvPluginWriter writer_;
+
+public:
+ static
+ Ptr<PluginWriter> create(const OpenCV_VideoIO_Plugin_API_preview* plugin_api,
+ const std::string &filename, int fourcc, double fps, const cv::Size &sz, bool isColor)
+ {
+ CV_Assert(plugin_api);
+ CvPluginWriter writer = NULL;
+ if (plugin_api->Writer_open)
+ {
+ CV_Assert(plugin_api->Writer_release);
+ if (CV_ERROR_OK == plugin_api->Writer_open(filename.empty() ? 0 : filename.c_str(), fourcc, fps, sz.width, sz.height, isColor, &writer))
+ {
+ CV_Assert(writer);
+ return makePtr<PluginWriter>(plugin_api, writer);
+ }
+ }
+ return Ptr<PluginWriter>();
+ }
+
+ PluginWriter(const OpenCV_VideoIO_Plugin_API_preview* plugin_api, CvPluginWriter writer)
+ : plugin_api_(plugin_api), writer_(writer)
+ {
+ CV_Assert(plugin_api_); CV_Assert(writer_);
+ }
+
+ ~PluginWriter()
+ {
+ CV_DbgAssert(plugin_api_->Writer_release);
+ if (CV_ERROR_OK != plugin_api_->Writer_release(writer_))
+ CV_LOG_ERROR(NULL, "Video I/O: Can't release writer by plugin '" << plugin_api_->api_header.api_description << "'");
+ writer_ = NULL;
+ }
+ double getProperty(int prop) const CV_OVERRIDE
+ {
+ double val = -1;
+ if (plugin_api_->Writer_getProperty)
+ if (CV_ERROR_OK != plugin_api_->Writer_getProperty(writer_, prop, &val))
+ val = -1;
+ return val;
+ }
+ bool setProperty(int prop, double val) CV_OVERRIDE
+ {
+ if (plugin_api_->Writer_setProperty)
+ if (CV_ERROR_OK == plugin_api_->Writer_setProperty(writer_, prop, val))
+ return true;
+ return false;
+ }
+ bool isOpened() const CV_OVERRIDE
+ {
+ return writer_ != NULL; // TODO always true
+ }
+ void write(cv::InputArray arr) CV_OVERRIDE
+ {
+ cv::Mat img = arr.getMat();
+ CV_DbgAssert(writer_);
+ CV_Assert(plugin_api_->Writer_write);
+ if (CV_ERROR_OK != plugin_api_->Writer_write(writer_, img.data, (int)img.step[0], img.cols, img.rows, img.channels()))
+ {
+ CV_LOG_DEBUG(NULL, "Video I/O: Can't write frame by plugin '" << plugin_api_->api_header.api_description << "'");
+ }
+ // TODO return bool result?
+ }
+ int getCaptureDomain() const CV_OVERRIDE
+ {
+ return plugin_api_->captureAPI;
+ }
+};
+
+
+Ptr<IVideoCapture> PluginBackend::createCapture(int camera) const
+{
+ try
+ {
+ if (plugin_api_)
+ return PluginCapture::create(plugin_api_, std::string(), camera); //.staticCast<IVideoCapture>();
+ }
+ catch (...)
+ {
+ CV_LOG_DEBUG(NULL, "Video I/O: can't create camera capture: " << camera);
+ }
+ return Ptr<IVideoCapture>();
+}
+
+Ptr<IVideoCapture> PluginBackend::createCapture(const std::string &filename) const
+{
+ try
+ {
+ if (plugin_api_)
+ return PluginCapture::create(plugin_api_, filename, 0); //.staticCast<IVideoCapture>();
+ }
+ catch (...)
+ {
+ CV_LOG_DEBUG(NULL, "Video I/O: can't open file capture: " << filename);
+ }
+ return Ptr<IVideoCapture>();
+}
+
+Ptr<IVideoWriter> PluginBackend::createWriter(const std::string &filename, int fourcc, double fps, const cv::Size &sz, bool isColor) const
+{
+ try
+ {
+ if (plugin_api_)
+ return PluginWriter::create(plugin_api_, filename, fourcc, fps, sz, isColor); //.staticCast<IVideoWriter>();
+ }
+ catch (...)
+ {
+ CV_LOG_DEBUG(NULL, "Video I/O: can't open writer: " << filename);
+ }
+ return Ptr<IVideoWriter>();
+}
+
+} // namespace
+
+Ptr<IBackendFactory> createPluginBackendFactory(VideoCaptureAPIs id, const char* baseName)
+{
+ return makePtr<impl::PluginBackendFactory>(id, baseName); //.staticCast<IBackendFactory>();
+}
+
+} // namespace
--- /dev/null
+// 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 "precomp.hpp"
+
+#include "backend.hpp"
+
+namespace cv {
+
+class StaticBackend: public IBackend
+{
+public:
+ FN_createCaptureFile fn_createCaptureFile_;
+ FN_createCaptureCamera fn_createCaptureCamera_;
+ FN_createWriter fn_createWriter_;
+
+ StaticBackend(FN_createCaptureFile fn_createCaptureFile, FN_createCaptureCamera fn_createCaptureCamera, FN_createWriter fn_createWriter)
+ : fn_createCaptureFile_(fn_createCaptureFile), fn_createCaptureCamera_(fn_createCaptureCamera), fn_createWriter_(fn_createWriter)
+ {
+ // nothing
+ }
+ ~StaticBackend() CV_OVERRIDE {}
+
+ Ptr<IVideoCapture> createCapture(int camera) const CV_OVERRIDE
+ {
+ if (fn_createCaptureCamera_)
+ return fn_createCaptureCamera_(camera);
+ return Ptr<IVideoCapture>();
+ }
+ Ptr<IVideoCapture> createCapture(const std::string &filename) const CV_OVERRIDE
+ {
+ if (fn_createCaptureFile_)
+ return fn_createCaptureFile_(filename);
+ return Ptr<IVideoCapture>();
+ }
+ Ptr<IVideoWriter> createWriter(const std::string &filename, int fourcc, double fps, const cv::Size &sz, bool isColor) const CV_OVERRIDE
+ {
+ if (fn_createWriter_)
+ return fn_createWriter_(filename, fourcc, fps, sz, isColor);
+ return Ptr<IVideoWriter>();
+ }
+}; // StaticBackend
+
+class StaticBackendFactory : public IBackendFactory
+{
+protected:
+ Ptr<StaticBackend> backend;
+
+public:
+ StaticBackendFactory(FN_createCaptureFile createCaptureFile, FN_createCaptureCamera createCaptureCamera, FN_createWriter createWriter)
+ : backend(makePtr<StaticBackend>(createCaptureFile, createCaptureCamera, createWriter))
+ {
+ // nothing
+ }
+
+ ~StaticBackendFactory() CV_OVERRIDE {}
+
+ Ptr<IBackend> getBackend() const CV_OVERRIDE
+ {
+ return backend.staticCast<IBackend>();
+ }
+};
+
+Ptr<IBackendFactory> createBackendFactory(FN_createCaptureFile createCaptureFile,
+ FN_createCaptureCamera createCaptureCamera,
+ FN_createWriter createWriter)
+{
+ return makePtr<StaticBackendFactory>(createCaptureFile, createCaptureCamera, createWriter).staticCast<IBackendFactory>();
+}
+
+} // namespace
namespace cv {
+static bool param_VIDEOIO_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOIO_DEBUG", false);
+static bool param_VIDEOCAPTURE_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOCAPTURE_DEBUG", false);
+static bool param_VIDEOWRITER_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOWRITER_DEBUG", false);
+
+
void DefaultDeleter<CvCapture>::operator ()(CvCapture* obj) const { cvReleaseCapture(&obj); }
void DefaultDeleter<CvVideoWriter>::operator ()(CvVideoWriter* obj) const { cvReleaseVideoWriter(&obj); }
VideoCapture::~VideoCapture()
{
CV_TRACE_FUNCTION();
-
icap.release();
- cap.release();
}
bool VideoCapture::open(const String& filename, int apiPreference)
const VideoBackendInfo& info = backends[i];
if (apiPreference == CAP_ANY || apiPreference == info.id)
{
- CvCapture* capture = NULL;
- VideoCapture_create(capture, icap, info.id, filename);
- if (!icap.empty())
+ if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
+ CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying capture filename='%s' ...", info.name, filename.c_str()));
+ CV_Assert(!info.backendFactory.empty());
+ const Ptr<IBackend> backend = info.backendFactory->getBackend();
+ if (!backend.empty())
{
- if (icap->isOpened())
- return true;
- icap.release();
+ try
+ {
+ icap = backend->createCapture(filename);
+ if (!icap.empty())
+ {
+ if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
+ CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): created, isOpened=%d",
+ info.name, icap->isOpened()));
+ if (icap->isOpened())
+ return true;
+ icap.release();
+ }
+ else
+ {
+ if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
+ CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): can't create capture", info.name));
+ }
+ } catch(const cv::Exception& e) {
+ CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", info.name, e.what()));
+ } catch (const std::exception& e) {
+ CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", info.name, e.what()));
+ } catch(...) {
+ CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", info.name));
+ }
}
- if (capture)
+ else
{
- cap.reset(capture);
- // assume it is opened
- return true;
+ if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
+ CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): backend is not available (plugin is missing, or can't be loaded due dependencies or it is not compatible)", info.name));
}
}
}
const VideoBackendInfo& info = backends[i];
if (apiPreference == CAP_ANY || apiPreference == info.id)
{
- CvCapture* capture = NULL;
- VideoCapture_create(capture, icap, info.id, cameraNum);
- if (!icap.empty())
+ if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
+ CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying capture cameraNum=%d ...", info.name, cameraNum));
+ CV_Assert(!info.backendFactory.empty());
+ const Ptr<IBackend> backend = info.backendFactory->getBackend();
+ if (!backend.empty())
{
- if (icap->isOpened())
- return true;
- icap.release();
+ try
+ {
+ icap = backend->createCapture(cameraNum);
+ if (!icap.empty())
+ {
+ if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
+ CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): created, isOpened=%d",
+ info.name, icap->isOpened()));
+ if (icap->isOpened())
+ return true;
+ icap.release();
+ }
+ else
+ {
+ if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
+ CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): can't create capture", info.name));
+ }
+ } catch(const cv::Exception& e) {
+ CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", info.name, e.what()));
+ } catch (const std::exception& e) {
+ CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", info.name, e.what()));
+ } catch(...) {
+ CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", info.name));
+ }
}
- if (capture)
+ else
{
- cap.reset(capture);
- // assume it is opened
- return true;
+ if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
+ CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): backend is not available (plugin is missing, or can't be loaded due dependencies or it is not compatible)", info.name));
}
}
}
bool VideoCapture::isOpened() const
{
- if (!icap.empty())
- return icap->isOpened();
- return !cap.empty(); // legacy interface doesn't support closed files
+ return !icap.empty() ? icap->isOpened() : false;
}
String VideoCapture::getBackendName() const
int api = 0;
if (icap)
api = icap->isOpened() ? icap->getCaptureDomain() : 0;
- else if (cap)
- api = cap->getCaptureDomain();
CV_Assert(api != 0);
return cv::videoio_registry::getBackendName((VideoCaptureAPIs)api);
}
{
CV_TRACE_FUNCTION();
icap.release();
- cap.release();
}
bool VideoCapture::grab()
{
CV_INSTRUMENT_REGION();
-
- if (!icap.empty())
- return icap->grabFrame();
- return cvGrabFrame(cap) != 0;
+ return !icap.empty() ? icap->grabFrame() : false;
}
bool VideoCapture::retrieve(OutputArray image, int channel)
{
CV_INSTRUMENT_REGION();
-
if (!icap.empty())
return icap->retrieveFrame(channel, image);
-
- IplImage* _img = cvRetrieveFrame(cap, channel);
- if( !_img )
- {
- image.release();
- return false;
- }
- if(_img->origin == IPL_ORIGIN_TL)
- cv::cvarrToMat(_img).copyTo(image);
- else
- {
- Mat temp = cv::cvarrToMat(_img);
- flip(temp, image, 0);
- }
- return true;
+ return false;
}
bool VideoCapture::read(OutputArray image)
bool VideoCapture::set(int propId, double value)
{
CV_CheckNE(propId, (int)CAP_PROP_BACKEND, "Can't set read-only property");
-
- if (!icap.empty())
- return icap->setProperty(propId, value);
- return cvSetCaptureProperty(cap, propId, value) != 0;
+ return !icap.empty() ? icap->setProperty(propId, value) : false;
}
double VideoCapture::get(int propId) const
int api = 0;
if (icap)
api = icap->isOpened() ? icap->getCaptureDomain() : 0;
- else if (cap)
- api = cap->getCaptureDomain();
if (api <= 0)
return -1.0;
return (double)api;
}
- if (!icap.empty())
- return icap->getProperty(propId);
- return cap ? cap->getProperty(propId) : 0;
+ return !icap.empty() ? icap->getProperty(propId) : 0;
}
void VideoWriter::release()
{
iwriter.release();
- writer.release();
}
VideoWriter::~VideoWriter()
const VideoBackendInfo& info = backends[i];
if (apiPreference == CAP_ANY || apiPreference == info.id)
{
- CvVideoWriter* writer_ = NULL;
- VideoWriter_create(writer_, iwriter, info.id, filename, _fourcc, fps, frameSize, isColor);
- if (!iwriter.empty())
+ if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG)
+ CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying writer with filename='%s' fourcc=0x%08x fps=%g sz=%dx%d isColor=%d...",
+ info.name, filename.c_str(), (unsigned)_fourcc, fps, frameSize.width, frameSize.height, (int)isColor));
+ CV_Assert(!info.backendFactory.empty());
+ const Ptr<IBackend> backend = info.backendFactory->getBackend();
+ if (!backend.empty())
{
- if (iwriter->isOpened())
- return true;
- iwriter.release();
+ try
+ {
+ iwriter = backend->createWriter(filename, _fourcc, fps, frameSize, isColor);
+ if (!iwriter.empty())
+ {
+ if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG)
+ CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): created, isOpened=%d",
+ info.name, iwriter->isOpened()));
+ if (iwriter->isOpened())
+ return true;
+ iwriter.release();
+ }
+ else
+ {
+ if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG)
+ CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): can't create writer", info.name));
+ }
+ } catch(const cv::Exception& e) {
+ CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", info.name, e.what()));
+ } catch (const std::exception& e) {
+ CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", info.name, e.what()));
+ } catch(...) {
+ CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", info.name));
+ }
}
- if (writer_)
+ else
{
- // assume it is opened
- writer.reset(writer_);
- return true;
+ if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
+ CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): backend is not available (plugin is missing, or can't be loaded due dependencies or it is not compatible)", info.name));
}
}
}
bool VideoWriter::isOpened() const
{
- return !iwriter.empty() || !writer.empty();
+ return !iwriter.empty();
}
int api = 0;
if (iwriter)
api = iwriter->getCaptureDomain();
- else if (writer)
- api = writer->getCaptureDomain();
if (api <= 0)
return -1.0;
return (double)api;
int api = 0;
if (iwriter)
api = iwriter->getCaptureDomain();
- else if (writer)
- api = writer->getCaptureDomain();
CV_Assert(api != 0);
return cv::videoio_registry::getBackendName((VideoCaptureAPIs)api);
}
if( iwriter )
iwriter->write(image);
- else
- {
- IplImage _img = cvIplImage(image.getMat());
- cvWriteFrame(writer, &_img);
- }
}
VideoWriter& VideoWriter::operator << (const Mat& image)
--- /dev/null
+// 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 "precomp.hpp"
+
+#include <stdio.h>
+#include <string.h>
+#include <fstream>
+#include <iostream>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <android/log.h>
+
+#include "media/NdkMediaCodec.h"
+#include "media/NdkMediaExtractor.h"
+
+#define INPUT_TIMEOUT_MS 2000
+
+#define COLOR_FormatYUV420Planar 19
+#define COLOR_FormatYUV420SemiPlanar 21
+
+using namespace cv;
+
+#define TAG "NativeCodec"
+#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
+
+
+static inline void deleter_AMediaExtractor(AMediaExtractor *extractor) {
+ AMediaExtractor_delete(extractor);
+}
+
+static inline void deleter_AMediaCodec(AMediaCodec *codec) {
+ AMediaCodec_stop(codec);
+ AMediaCodec_delete(codec);
+}
+
+static inline void deleter_AMediaFormat(AMediaFormat *format) {
+ AMediaFormat_delete(format);
+}
+
+class AndroidMediaNdkCapture : public IVideoCapture
+{
+
+public:
+ AndroidMediaNdkCapture():
+ sawInputEOS(false), sawOutputEOS(false),
+ frameWidth(0), frameHeight(0), colorFormat(0) {}
+ std::shared_ptr<AMediaExtractor> mediaExtractor;
+ std::shared_ptr<AMediaCodec> mediaCodec;
+ bool sawInputEOS;
+ bool sawOutputEOS;
+ int32_t frameWidth;
+ int32_t frameHeight;
+ int32_t colorFormat;
+ std::vector<uint8_t> buffer;
+
+ ~AndroidMediaNdkCapture() { cleanUp(); }
+
+ bool decodeFrame() {
+ while (!sawInputEOS || !sawOutputEOS) {
+ if (!sawInputEOS) {
+ auto bufferIndex = AMediaCodec_dequeueInputBuffer(mediaCodec.get(), INPUT_TIMEOUT_MS);
+ LOGV("input buffer %zd", bufferIndex);
+ if (bufferIndex >= 0) {
+ size_t bufferSize;
+ auto inputBuffer = AMediaCodec_getInputBuffer(mediaCodec.get(), bufferIndex, &bufferSize);
+ auto sampleSize = AMediaExtractor_readSampleData(mediaExtractor.get(), inputBuffer, bufferSize);
+ if (sampleSize < 0) {
+ sampleSize = 0;
+ sawInputEOS = true;
+ LOGV("EOS");
+ }
+ auto presentationTimeUs = AMediaExtractor_getSampleTime(mediaExtractor.get());
+
+ AMediaCodec_queueInputBuffer(mediaCodec.get(), bufferIndex, 0, sampleSize,
+ presentationTimeUs, sawInputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
+ AMediaExtractor_advance(mediaExtractor.get());
+ }
+ }
+
+ if (!sawOutputEOS) {
+ AMediaCodecBufferInfo info;
+ auto bufferIndex = AMediaCodec_dequeueOutputBuffer(mediaCodec.get(), &info, 0);
+ if (bufferIndex >= 0) {
+ size_t bufferSize = 0;
+ auto mediaFormat = std::shared_ptr<AMediaFormat>(AMediaCodec_getOutputFormat(mediaCodec.get()), deleter_AMediaFormat);
+ AMediaFormat_getInt32(mediaFormat.get(), AMEDIAFORMAT_KEY_WIDTH, &frameWidth);
+ AMediaFormat_getInt32(mediaFormat.get(), AMEDIAFORMAT_KEY_HEIGHT, &frameHeight);
+ AMediaFormat_getInt32(mediaFormat.get(), AMEDIAFORMAT_KEY_COLOR_FORMAT, &colorFormat);
+ uint8_t* codecBuffer = AMediaCodec_getOutputBuffer(mediaCodec.get(), bufferIndex, &bufferSize);
+ buffer = std::vector<uint8_t>(codecBuffer + info.offset, codecBuffer + bufferSize);
+ LOGV("colorFormat: %d", colorFormat);
+ LOGV("buffer size: %zu", bufferSize);
+ LOGV("width (frame): %d", frameWidth);
+ LOGV("height (frame): %d", frameHeight);
+ if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
+ LOGV("output EOS");
+ sawOutputEOS = true;
+ }
+ AMediaCodec_releaseOutputBuffer(mediaCodec.get(), bufferIndex, info.size != 0);
+ return true;
+ } else if (bufferIndex == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
+ LOGV("output buffers changed");
+ } else if (bufferIndex == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
+ auto format = AMediaCodec_getOutputFormat(mediaCodec.get());
+ LOGV("format changed to: %s", AMediaFormat_toString(format));
+ AMediaFormat_delete(format);
+ } else if (bufferIndex == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
+ LOGV("no output buffer right now");
+ } else {
+ LOGV("unexpected info code: %zd", bufferIndex);
+ }
+ }
+ }
+ return false;
+ }
+
+ bool isOpened() const CV_OVERRIDE { return mediaCodec.get() != nullptr; }
+
+ int getCaptureDomain() CV_OVERRIDE { return CAP_ANDROID; }
+
+ bool grabFrame() CV_OVERRIDE
+ {
+ // clear the previous frame
+ buffer.clear();
+ return decodeFrame();
+ }
+
+ bool retrieveFrame(int, OutputArray out) CV_OVERRIDE
+ {
+ if (buffer.empty()) {
+ return false;
+ }
+ Mat yuv(frameHeight + frameHeight/2, frameWidth, CV_8UC1, buffer.data());
+ if (colorFormat == COLOR_FormatYUV420Planar) {
+ cv::cvtColor(yuv, out, cv::COLOR_YUV2BGR_YV12);
+ } else if (colorFormat == COLOR_FormatYUV420SemiPlanar) {
+ cv::cvtColor(yuv, out, cv::COLOR_YUV2BGR_NV21);
+ } else {
+ LOGE("Unsupported video format: %d", colorFormat);
+ return false;
+ }
+ return true;
+ }
+
+ double getProperty(int property_id) const CV_OVERRIDE
+ {
+ switch (property_id)
+ {
+ case CV_CAP_PROP_FRAME_WIDTH: return frameWidth;
+ case CV_CAP_PROP_FRAME_HEIGHT: return frameHeight;
+ }
+ return 0;
+ }
+
+ bool setProperty(int /* property_id */, double /* value */) CV_OVERRIDE
+ {
+ return false;
+ }
+
+ bool initCapture(const char * filename)
+ {
+ struct stat statBuffer;
+ if (stat(filename, &statBuffer) != 0) {
+ LOGE("failed to stat file: %s (%s)", filename, strerror(errno));
+ return false;
+ }
+
+ int fd = open(filename, O_RDONLY);
+
+ if (fd < 0) {
+ LOGE("failed to open file: %s %d (%s)", filename, fd, strerror(errno));
+ return false;
+ }
+
+ mediaExtractor = std::shared_ptr<AMediaExtractor>(AMediaExtractor_new(), deleter_AMediaExtractor);
+ if (!mediaExtractor) {
+ return false;
+ }
+ media_status_t err = AMediaExtractor_setDataSourceFd(mediaExtractor.get(), fd, 0, statBuffer.st_size);
+ close(fd);
+ if (err != AMEDIA_OK) {
+ LOGV("setDataSource error: %d", err);
+ return false;
+ }
+
+ int numtracks = AMediaExtractor_getTrackCount(mediaExtractor.get());
+
+ LOGV("input has %d tracks", numtracks);
+ for (int i = 0; i < numtracks; i++) {
+ auto format = std::shared_ptr<AMediaFormat>(AMediaExtractor_getTrackFormat(mediaExtractor.get(), i), deleter_AMediaFormat);
+ if (!format) {
+ continue;
+ }
+ const char *s = AMediaFormat_toString(format.get());
+ LOGV("track %d format: %s", i, s);
+ const char *mime;
+ if (!AMediaFormat_getString(format.get(), AMEDIAFORMAT_KEY_MIME, &mime)) {
+ LOGV("no mime type");
+ } else if (!strncmp(mime, "video/", 6)) {
+ int32_t trackWidth, trackHeight;
+ AMediaFormat_getInt32(format.get(), AMEDIAFORMAT_KEY_WIDTH, &trackWidth);
+ AMediaFormat_getInt32(format.get(), AMEDIAFORMAT_KEY_HEIGHT, &trackHeight);
+ LOGV("width (track): %d", trackWidth);
+ LOGV("height (track): %d", trackHeight);
+ if (AMediaExtractor_selectTrack(mediaExtractor.get(), i) != AMEDIA_OK) {
+ continue;
+ }
+ mediaCodec = std::shared_ptr<AMediaCodec>(AMediaCodec_createDecoderByType(mime), deleter_AMediaCodec);
+ if (!mediaCodec) {
+ continue;
+ }
+ if (AMediaCodec_configure(mediaCodec.get(), format.get(), NULL, NULL, 0) != AMEDIA_OK) {
+ continue;
+ }
+ sawInputEOS = false;
+ sawOutputEOS = false;
+ if (AMediaCodec_start(mediaCodec.get()) != AMEDIA_OK) {
+ continue;
+ }
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ void cleanUp() {
+ sawInputEOS = true;
+ sawOutputEOS = true;
+ frameWidth = 0;
+ frameHeight = 0;
+ colorFormat = 0;
+ }
+};
+
+/****************** Implementation of interface functions ********************/
+
+Ptr<IVideoCapture> cv::createAndroidCapture_file(const std::string &filename) {
+ Ptr<AndroidMediaNdkCapture> res = makePtr<AndroidMediaNdkCapture>();
+ if (res && res->initCapture(filename.c_str()))
+ return res;
+ return Ptr<IVideoCapture>();
+}
//
#include "precomp.hpp"
+#include "cap_interface.hpp"
#ifdef HAVE_ARAVIS_API
return false;
}
-CvCapture* cvCreateCameraCapture_Aravis( int index )
+cv::Ptr<cv::IVideoCapture> cv::create_Aravis_capture( int index )
{
CvCaptureCAM_Aravis* capture = new CvCaptureCAM_Aravis;
if(capture->open(index)) {
- return capture;
+ return cv::makePtr<cv::LegacyCapture>(capture);
}
delete capture;
#include "precomp.hpp"
#include "opencv2/imgproc.hpp"
+#include "cap_interface.hpp"
#include <iostream>
#import <AVFoundation/AVFoundation.h>
#import <Foundation/NSException.h>
/****************** Implementation of interface functions ********************/
-CvCapture* cvCreateFileCapture_AVFoundation(const char* filename) {
- CvCaptureFile *retval = new CvCaptureFile(filename);
-
+cv::Ptr<cv::IVideoCapture> cv::create_AVFoundation_capture_file(const std::string &filename)
+{
+ CvCaptureFile *retval = new CvCaptureFile(filename.c_str());
if(retval->didStart())
- return retval;
+ return makePtr<LegacyCapture>(retval);
delete retval;
return NULL;
-}
-CvCapture* cvCreateCameraCapture_AVFoundation(int index ) {
-
- CvCapture* retval = new CvCaptureCAM(index);
- if (!((CvCaptureCAM *)retval)->didStart())
- cvReleaseCapture(&retval);
- return retval;
+}
+cv::Ptr<cv::IVideoCapture> cv::create_AVFoundation_capture_cam(int index)
+{
+ CvCaptureCAM* retval = new CvCaptureCAM(index);
+ if (retval->didStart())
+ return cv::makePtr<cv::LegacyCapture>(retval);
+ delete retval;
+ return 0;
}
-CvVideoWriter* cvCreateVideoWriter_AVFoundation(const char* filename, int fourcc,
- double fps, CvSize frame_size,
- int is_color) {
- return new CvVideoWriter_AVFoundation(filename, fourcc, fps, frame_size,is_color);
+cv::Ptr<cv::IVideoWriter> cv::create_AVFoundation_writer(const std::string& filename, int fourcc, double fps, const cv::Size &frameSize, bool isColor)
+{
+ CvSize sz = { frameSize.width, frameSize.height };
+ CvVideoWriter_AVFoundation* wrt = new CvVideoWriter_AVFoundation(filename.c_str(), fourcc, fps, sz, isColor);
+ return cv::makePtr<cv::LegacyWriter>(wrt);
}
/********************** Implementation of Classes ****************************/
#include "precomp.hpp"
#include "opencv2/imgproc.hpp"
#include <stdio.h>
+#include <AvailabilityMacros.h>
#import <AVFoundation/AVFoundation.h>
#define CV_CAP_MODE_BGR CV_FOURCC_MACRO('B','G','R','3')
class CvVideoWriter_AVFoundation : public CvVideoWriter {
public:
- CvVideoWriter_AVFoundation(const char* filename, int fourcc,
- double fps, CvSize frame_size,
- int is_color=1);
+ CvVideoWriter_AVFoundation(const std::string &filename, int fourcc, double fps, CvSize frame_size, int is_color);
~CvVideoWriter_AVFoundation();
bool writeFrame(const IplImage* image) CV_OVERRIDE;
int getCaptureDomain() const CV_OVERRIDE { return cv::CAP_AVFOUNDATION; }
+ bool isOpened() const
+ {
+ return is_good;
+ }
private:
IplImage* argbimage;
CvSize movieSize;
int movieColor;
unsigned long mFrameNum;
+ bool is_good;
};
/****************** Implementation of interface functions ********************/
-
-CvCapture* cvCreateFileCapture_AVFoundation(const char* filename) {
- CvCaptureFile *retval = new CvCaptureFile(filename);
-
+cv::Ptr<cv::IVideoCapture> cv::create_AVFoundation_capture_file(const std::string &filename)
+{
+ CvCaptureFile *retval = new CvCaptureFile(filename.c_str());
if(retval->didStart())
- return retval;
+ return makePtr<LegacyCapture>(retval);
delete retval;
return NULL;
+
}
-CvCapture* cvCreateCameraCapture_AVFoundation(int index ) {
- CvCapture* retval = new CvCaptureCAM(index);
- if (!((CvCaptureCAM *)retval)->didStart())
- cvReleaseCapture(&retval);
- return retval;
+cv::Ptr<cv::IVideoCapture> cv::create_AVFoundation_capture_cam(int index)
+{
+ CvCaptureCAM* retval = new CvCaptureCAM(index);
+ if (retval->didStart())
+ return cv::makePtr<cv::LegacyCapture>(retval);
+ delete retval;
+ return 0;
}
-CvVideoWriter* cvCreateVideoWriter_AVFoundation(const char* filename, int fourcc,
- double fps, CvSize frame_size,
- int is_color) {
- return new CvVideoWriter_AVFoundation(filename, fourcc, fps, frame_size,is_color);
+cv::Ptr<cv::IVideoWriter> cv::create_AVFoundation_writer(const std::string& filename, int fourcc, double fps, const cv::Size &frameSize, bool isColor)
+{
+ CvSize sz = { frameSize.width, frameSize.height };
+ CvVideoWriter_AVFoundation* wrt = new CvVideoWriter_AVFoundation(filename, fourcc, fps, sz, isColor);
+ if (wrt->isOpened())
+ {
+ return cv::makePtr<cv::LegacyWriter>(wrt);
+ }
+ delete wrt;
+ return NULL;
}
/********************** Implementation of Classes ****************************/
*****************************************************************************/
-CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const char* filename, int fourcc,
- double fps, CvSize frame_size,
- int is_color) {
-
+CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const std::string &filename, int fourcc, double fps, CvSize frame_size, int is_color)
+ : argbimage(nil), mMovieWriter(nil), mMovieWriterInput(nil), mMovieWriterAdaptor(nil), path(nil),
+ codec(nil), fileType(nil), mMovieFPS(fps), movieSize(frame_size), movieColor(is_color), mFrameNum(0),
+ is_good(true)
+{
+ if (mMovieFPS <= 0 || movieSize.width <= 0 || movieSize.height <= 0)
+ {
+ is_good = false;
+ return;
+ }
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
-
- mFrameNum = 0;
- mMovieFPS = fps;
- movieSize = frame_size;
- movieColor = is_color;
argbimage = cvCreateImage(movieSize, IPL_DEPTH_8U, 4);
- path = [[[NSString stringWithCString:filename encoding:NSASCIIStringEncoding] stringByExpandingTildeInPath] retain];
-
-
- /*
- AVFileTypeQuickTimeMovie
- UTI for the QuickTime movie file format.
- The value of this UTI is com.apple.quicktime-movie. Files are identified with the .mov and .qt extensions.
-
- AVFileTypeMPEG4
- UTI for the MPEG-4 file format.
- The value of this UTI is public.mpeg-4. Files are identified with the .mp4 extension.
-
- AVFileTypeAppleM4V
- UTI for the iTunes video file format.
- The value of this UTI is com.apple.mpeg-4-video. Files are identified with the .m4v extension.
-
- AVFileType3GPP
- UTI for the 3GPP file format.
- The value of this UTI is public.3gpp. Files are identified with the .3gp, .3gpp, and .sdv extensions.
- */
+ path = [[[NSString stringWithUTF8String:filename.c_str()] stringByExpandingTildeInPath] retain];
NSString *fileExt =[[[path pathExtension] lowercaseString] copy];
if ([fileExt isEqualToString:@"mov"] || [fileExt isEqualToString:@"qt"]){
fileType = [AVFileTypeMPEG4 copy];
}else if ([fileExt isEqualToString:@"m4v"]){
fileType = [AVFileTypeAppleM4V copy];
-#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
- }else if ([fileExt isEqualToString:@"3gp"] || [fileExt isEqualToString:@"3gpp"] || [fileExt isEqualToString:@"sdv"] ){
- fileType = [AVFileType3GPP copy];
-#endif
} else{
- fileType = [AVFileTypeMPEG4 copy]; //default mp4
+ is_good = false;
}
[fileExt release];
cc[4] = 0;
int cc2 = CV_FOURCC(cc[0], cc[1], cc[2], cc[3]);
if (cc2!=fourcc) {
- fprintf(stderr, "OpenCV: Didn't properly encode FourCC. Expected 0x%08X but got 0x%08X.\n", fourcc, cc2);
- //exception;
+ is_good = false;
}
// Two codec supported AVVideoCodecH264 AVVideoCodecJPEG
}else if(fourcc == CV_FOURCC('H','2','6','4') || fourcc == CV_FOURCC('a','v','c','1')){
codec = [AVVideoCodecH264 copy];
}else{
- codec = [AVVideoCodecH264 copy]; // default canonical H264.
-
+ is_good = false;
}
//NSLog(@"Path: %@", path);
- NSError *error = nil;
-
+ if (is_good)
+ {
+ NSError *error = nil;
- // Make sure the file does not already exist. Necessary to overwirte??
- /*
- NSFileManager *fileManager = [NSFileManager defaultManager];
- if ([fileManager fileExistsAtPath:path]){
- [fileManager removeItemAtPath:path error:&error];
- }
- */
- // Wire the writer:
- // Supported file types:
- // AVFileTypeQuickTimeMovie AVFileTypeMPEG4 AVFileTypeAppleM4V AVFileType3GPP
+ // Make sure the file does not already exist. Necessary to overwirte??
+ /*
+ NSFileManager *fileManager = [NSFileManager defaultManager];
+ if ([fileManager fileExistsAtPath:path]){
+ [fileManager removeItemAtPath:path error:&error];
+ }
+ */
- mMovieWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path]
- fileType:fileType
- error:&error];
- //NSParameterAssert(mMovieWriter);
+ // Wire the writer:
+ // Supported file types:
+ // AVFileTypeQuickTimeMovie AVFileTypeMPEG4 AVFileTypeAppleM4V AVFileType3GPP
- NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
- codec, AVVideoCodecKey,
- [NSNumber numberWithInt:movieSize.width], AVVideoWidthKey,
- [NSNumber numberWithInt:movieSize.height], AVVideoHeightKey,
- nil];
+ mMovieWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path]
+ fileType:fileType
+ error:&error];
+ //NSParameterAssert(mMovieWriter);
- mMovieWriterInput = [[AVAssetWriterInput
- assetWriterInputWithMediaType:AVMediaTypeVideo
- outputSettings:videoSettings] retain];
+ NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
+ codec, AVVideoCodecKey,
+ [NSNumber numberWithInt:movieSize.width], AVVideoWidthKey,
+ [NSNumber numberWithInt:movieSize.height], AVVideoHeightKey,
+ nil];
- //NSParameterAssert(mMovieWriterInput);
- //NSParameterAssert([mMovieWriter canAddInput:mMovieWriterInput]);
+ mMovieWriterInput = [[AVAssetWriterInput
+ assetWriterInputWithMediaType:AVMediaTypeVideo
+ outputSettings:videoSettings] retain];
- [mMovieWriter addInput:mMovieWriterInput];
+ //NSParameterAssert(mMovieWriterInput);
+ //NSParameterAssert([mMovieWriter canAddInput:mMovieWriterInput]);
- mMovieWriterAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc] initWithAssetWriterInput:mMovieWriterInput sourcePixelBufferAttributes:nil];
+ [mMovieWriter addInput:mMovieWriterInput];
+ mMovieWriterAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc] initWithAssetWriterInput:mMovieWriterInput sourcePixelBufferAttributes:nil];
- //Start a session:
- [mMovieWriter startWriting];
- [mMovieWriter startSessionAtSourceTime:kCMTimeZero];
+ //Start a session:
+ [mMovieWriter startWriting];
+ [mMovieWriter startSessionAtSourceTime:kCMTimeZero];
- if(mMovieWriter.status == AVAssetWriterStatusFailed){
- NSLog(@"AVF: AVAssetWriter status: %@", [mMovieWriter.error localizedDescription]);
- // TODO: error handling, cleanup. Throw execption?
- // return;
+ if(mMovieWriter.status == AVAssetWriterStatusFailed){
+ NSLog(@"AVF: AVAssetWriter status: %@", [mMovieWriter.error localizedDescription]);
+ is_good = false;
+ }
}
[localpool drain];
CvVideoWriter_AVFoundation::~CvVideoWriter_AVFoundation() {
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
- [mMovieWriterInput markAsFinished];
- [mMovieWriter finishWriting];
- [mMovieWriter release];
- [mMovieWriterInput release];
- [mMovieWriterAdaptor release];
- [path release];
- [codec release];
- [fileType release];
- cvReleaseImage(&argbimage);
+ if (mMovieWriterInput && mMovieWriter && mMovieWriterAdaptor)
+ {
+ [mMovieWriterInput markAsFinished];
+ [mMovieWriter finishWriting];
+ [mMovieWriter release];
+ [mMovieWriterInput release];
+ [mMovieWriterAdaptor release];
+ }
+ if (path)
+ [path release];
+ if (codec)
+ [codec release];
+ if (fileType)
+ [fileType release];
+ if (argbimage)
+ cvReleaseImage(&argbimage);
[localpool drain];
//M*/
#include "precomp.hpp"
+#include "cap_interface.hpp"
#ifdef HAVE_DC1394_2
#include <stdlib.h>
#include <string.h>
-static dc1394error_t adaptBufferStereoLocal(dc1394video_frame_t *in, dc1394video_frame_t *out)
-{
- uint32_t bpp;
-
- // buffer position is not changed. Size is boubled in Y
- out->size[0] = in->size[0];
- out->size[1] = in->size[1] * 2;
- out->position[0] = in->position[0];
- out->position[1] = in->position[1];
-
- // color coding is set to mono8 or raw8.
- switch (in->color_coding)
- {
- case DC1394_COLOR_CODING_RAW16:
- out->color_coding = DC1394_COLOR_CODING_RAW8;
- break;
- case DC1394_COLOR_CODING_MONO16:
- case DC1394_COLOR_CODING_YUV422:
- out->color_coding = DC1394_COLOR_CODING_MONO8;
- break;
- default:
- return DC1394_INVALID_COLOR_CODING;
- }
-
- // keep the color filter value in all cases. if the format is not raw it will not be further used anyway
- out->color_filter = in->color_filter;
-
- // the output YUV byte order must be already set if the buffer is YUV422 at the output
- // if the output is not YUV we don't care about this field.
- // Hence nothing to do.
- // we always convert to 8bits (at this point) we can safely set this value to 8.
- out->data_depth = 8;
-
- // don't know what to do with stride... >>>> TODO: STRIDE SHOULD BE TAKEN INTO ACCOUNT... <<<<
- // out->stride=??
- // the video mode should not change. Color coding and other stuff can be accessed in specific fields of this struct
- out->video_mode = in->video_mode;
-
- // padding is kept:
- out->padding_bytes = in->padding_bytes;
-
- // image bytes changes: >>>> TODO: STRIDE SHOULD BE TAKEN INTO ACCOUNT... <<<<
- dc1394_get_color_coding_bit_size(out->color_coding, &bpp);
- out->image_bytes = (out->size[0] * out->size[1] * bpp) / 8;
-
- // total is image_bytes + padding_bytes
- out->total_bytes = out->image_bytes + out->padding_bytes;
-
- // bytes-per-packet and packets_per_frame are internal data that can be kept as is.
- out->packet_size = in->packet_size;
- out->packets_per_frame = in->packets_per_frame;
-
- // timestamp, frame_behind, id and camera are copied too:
- out->timestamp = in->timestamp;
- out->frames_behind = in->frames_behind;
- out->camera = in->camera;
- out->id = in->id;
-
- // verify memory allocation:
- if (out->total_bytes > out->allocated_image_bytes)
- {
- free(out->image);
- out->image = (uint8_t*)malloc(out->total_bytes * sizeof(uint8_t));
- out->allocated_image_bytes = out->total_bytes;
- }
-
- // Copy padding bytes:
- memcpy(&(out->image[out->image_bytes]), &(in->image[in->image_bytes]), out->padding_bytes);
- out->little_endian = DC1394_FALSE; // not used before 1.32 is out.
- out->data_in_padding = DC1394_FALSE; // not used before 1.32 is out.
- return DC1394_SUCCESS;
-}
-
-static dc1394error_t dc1394_deinterlace_stereo_frames_fixed(dc1394video_frame_t *in,
- dc1394video_frame_t *out, dc1394stereo_method_t method)
-{
- if((in->color_coding == DC1394_COLOR_CODING_RAW16) ||
- (in->color_coding == DC1394_COLOR_CODING_MONO16) ||
- (in->color_coding == DC1394_COLOR_CODING_YUV422))
- {
- switch (method)
- {
-
- case DC1394_STEREO_METHOD_INTERLACED:
- adaptBufferStereoLocal(in, out);
-//FIXED by AB:
-// dc1394_deinterlace_stereo(in->image, out->image, in->size[0], in->size[1]);
- dc1394_deinterlace_stereo(in->image, out->image, out->size[0], out->size[1]);
- break;
-
- case DC1394_STEREO_METHOD_FIELD:
- adaptBufferStereoLocal(in, out);
- memcpy(out->image, in->image, out->image_bytes);
- break;
- }
-
- return DC1394_INVALID_STEREO_METHOD;
- }
- else
- return DC1394_FUNCTION_NOT_SUPPORTED;
-}
-
struct CvDC1394
{
CvDC1394();
if (nimages == 2)
{
fs = (dc1394video_frame_t*)calloc(1, sizeof(*fs));
-
- //dc1394_deinterlace_stereo_frames(dcFrame, fs, DC1394_STEREO_METHOD_INTERLACED);
- dc1394_deinterlace_stereo_frames_fixed(dcFrame, fs, DC1394_STEREO_METHOD_INTERLACED);
-
+ dc1394_deinterlace_stereo_frames(dcFrame, fs, DC1394_STEREO_METHOD_INTERLACED);
dc1394_capture_enqueue(dcCam, dcFrame); // release the captured frame as soon as possible
dcFrame = 0;
if (!fs->image)
}
-CvCapture* cvCreateCameraCapture_DC1394_2(int index)
+cv::Ptr<cv::IVideoCapture> cv::create_DC1394_capture(int index)
{
CvCaptureCAM_DC1394_v2_CPP* capture = new CvCaptureCAM_DC1394_v2_CPP;
-
if (capture->open(index))
- return capture;
-
+ return cv::makePtr<cv::LegacyCapture>(capture);
delete capture;
return 0;
}
m_widthSet = m_heightSet = m_width = m_height = -1;
}
+Ptr<IVideoCapture> create_DShow_capture(int index)
+{
+ return makePtr<VideoCapture_DShow>(index);
+}
+
+
}
#endif
}
#endif //HAVE_DSHOW
-#endif //_CAP_DSHOW_HPP_
\ No newline at end of file
+#endif //_CAP_DSHOW_HPP_
} // namespace
-cv::Ptr<cv::IVideoCapture> cvCreateFileCapture_FFMPEG_proxy(const cv::String& filename)
+cv::Ptr<cv::IVideoCapture> cvCreateFileCapture_FFMPEG_proxy(const std::string &filename)
{
#if defined(HAVE_FFMPEG_WRAPPER)
icvInitFFMPEG::Init();
} // namespace
-cv::Ptr<cv::IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const cv::String& filename, int fourcc,
- double fps, cv::Size frameSize, int isColor)
+cv::Ptr<cv::IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const std::string& filename, int fourcc, double fps, const cv::Size &frameSize, bool isColor)
{
#if defined(HAVE_FFMPEG_WRAPPER)
icvInitFFMPEG::Init();
} // namespace
#endif // defined(HAVE_FFMPEG)
+
+//==================================================================================================
+
+#if defined(BUILD_PLUGIN)
+
+#include "plugin_api.hpp"
+
+namespace cv {
+
+static
+CvResult CV_API_CALL cv_capture_open(const char* filename, int camera_index, CV_OUT CvPluginCapture* handle)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ *handle = NULL;
+ if (!filename)
+ return CV_ERROR_FAIL;
+ CV_UNUSED(camera_index);
+ CvCapture_FFMPEG_proxy *cap = 0;
+ try
+ {
+ cap = new CvCapture_FFMPEG_proxy(filename);
+ if (cap->isOpened())
+ {
+ *handle = (CvPluginCapture)cap;
+ return CV_ERROR_OK;
+ }
+ }
+ catch (...)
+ {
+ }
+ if (cap)
+ delete cap;
+ return CV_ERROR_FAIL;
+}
+
+static
+CvResult CV_API_CALL cv_capture_release(CvPluginCapture handle)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ CvCapture_FFMPEG_proxy* instance = (CvCapture_FFMPEG_proxy*)handle;
+ delete instance;
+ return CV_ERROR_OK;
+}
+
+
+static
+CvResult CV_API_CALL cv_capture_get_prop(CvPluginCapture handle, int prop, CV_OUT double* val)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ if (!val)
+ return CV_ERROR_FAIL;
+ try
+ {
+ CvCapture_FFMPEG_proxy* instance = (CvCapture_FFMPEG_proxy*)handle;
+ *val = instance->getProperty(prop);
+ return CV_ERROR_OK;
+ }
+ catch (...)
+ {
+ return CV_ERROR_FAIL;
+ }
+}
+
+static
+CvResult CV_API_CALL cv_capture_set_prop(CvPluginCapture handle, int prop, double val)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ try
+ {
+ CvCapture_FFMPEG_proxy* instance = (CvCapture_FFMPEG_proxy*)handle;
+ return instance->setProperty(prop, val) ? CV_ERROR_OK : CV_ERROR_FAIL;
+ }
+ catch(...)
+ {
+ return CV_ERROR_FAIL;
+ }
+}
+
+static
+CvResult CV_API_CALL cv_capture_grab(CvPluginCapture handle)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ try
+ {
+ CvCapture_FFMPEG_proxy* instance = (CvCapture_FFMPEG_proxy*)handle;
+ return instance->grabFrame() ? CV_ERROR_OK : CV_ERROR_FAIL;
+ }
+ catch(...)
+ {
+ return CV_ERROR_FAIL;
+ }
+}
+
+static
+CvResult CV_API_CALL cv_capture_retrieve(CvPluginCapture handle, int stream_idx, cv_videoio_retrieve_cb_t callback, void* userdata)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ try
+ {
+ CvCapture_FFMPEG_proxy* instance = (CvCapture_FFMPEG_proxy*)handle;
+ Mat img;
+ // TODO: avoid unnecessary copying
+ if (instance->retrieveFrame(stream_idx, img))
+ return callback(stream_idx, img.data, img.step, img.cols, img.rows, img.channels(), userdata);
+ return CV_ERROR_FAIL;
+ }
+ catch(...)
+ {
+ return CV_ERROR_FAIL;
+ }
+}
+
+static
+CvResult CV_API_CALL cv_writer_open(const char* filename, int fourcc, double fps, int width, int height, int isColor,
+ CV_OUT CvPluginWriter* handle)
+{
+ Size sz(width, height);
+ CvVideoWriter_FFMPEG_proxy* wrt = 0;
+ try
+ {
+ wrt = new CvVideoWriter_FFMPEG_proxy(filename, fourcc, fps, sz, isColor != 0);
+ if(wrt && wrt->isOpened())
+ {
+ *handle = (CvPluginWriter)wrt;
+ return CV_ERROR_OK;
+ }
+ }
+ catch(...)
+ {
+ }
+ if (wrt)
+ delete wrt;
+ return CV_ERROR_FAIL;
+}
+
+static
+CvResult CV_API_CALL cv_writer_release(CvPluginWriter handle)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ CvVideoWriter_FFMPEG_proxy* instance = (CvVideoWriter_FFMPEG_proxy*)handle;
+ delete instance;
+ return CV_ERROR_OK;
+}
+
+static
+CvResult CV_API_CALL cv_writer_get_prop(CvPluginWriter /*handle*/, int /*prop*/, CV_OUT double* /*val*/)
+{
+ return CV_ERROR_FAIL;
+}
+
+static
+CvResult CV_API_CALL cv_writer_set_prop(CvPluginWriter /*handle*/, int /*prop*/, double /*val*/)
+{
+ return CV_ERROR_FAIL;
+}
+
+static
+CvResult CV_API_CALL cv_writer_write(CvPluginWriter handle, const unsigned char *data, int step, int width, int height, int cn)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ try
+ {
+ CvVideoWriter_FFMPEG_proxy* instance = (CvVideoWriter_FFMPEG_proxy*)handle;
+ Mat img(Size(width, height), CV_MAKETYPE(CV_8U, cn), const_cast<uchar*>(data), step);
+ instance->write(img);
+ return CV_ERROR_OK;
+ }
+ catch(...)
+ {
+ return CV_ERROR_FAIL;
+ }
+}
+
+static const OpenCV_VideoIO_Plugin_API_preview plugin_api_v0 =
+{
+ {
+ sizeof(OpenCV_VideoIO_Plugin_API_preview), ABI_VERSION, API_VERSION,
+ CV_VERSION_MAJOR, CV_VERSION_MINOR, CV_VERSION_REVISION, CV_VERSION_STATUS,
+ "FFmpeg OpenCV Video I/O plugin"
+ },
+ /* 1*/CAP_FFMPEG,
+ /* 2*/cv_capture_open,
+ /* 3*/cv_capture_release,
+ /* 4*/cv_capture_get_prop,
+ /* 5*/cv_capture_set_prop,
+ /* 6*/cv_capture_grab,
+ /* 7*/cv_capture_retrieve,
+ /* 8*/cv_writer_open,
+ /* 9*/cv_writer_release,
+ /* 10*/cv_writer_get_prop,
+ /* 11*/cv_writer_set_prop,
+ /* 12*/cv_writer_write
+};
+
+} // namespace
+
+const OpenCV_VideoIO_Plugin_API_preview* opencv_videoio_plugin_init_v0(int requested_abi_version, int requested_api_version, void* /*reserved=NULL*/) CV_NOEXCEPT
+{
+ if (requested_abi_version != 0)
+ return NULL;
+ if (requested_api_version != 0)
+ return NULL;
+ return &cv::plugin_api_v0;
+}
+
+#endif // BUILD_PLUGIN
{
#endif
-#if defined _WIN32
+#ifndef OPENCV_FFMPEG_API
+#if defined(__OPENCV_BUILD) || defined(BUILD_PLUGIN)
+# define OPENCV_FFMPEG_API
+#elif defined _WIN32
# define OPENCV_FFMPEG_API __declspec(dllexport)
#elif defined __GNUC__ && __GNUC__ >= 4
# define OPENCV_FFMPEG_API __attribute__ ((visibility ("default")))
#else
# define OPENCV_FFMPEG_API
#endif
+#endif
enum
{
}
static ImplMutex _mutex;
-static bool _initialized = false;
class AutoLock
{
class InternalFFMpegRegister
{
public:
- InternalFFMpegRegister()
+ static void init()
{
AutoLock lock(_mutex);
- if (!_initialized)
- {
- #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
- avformat_network_init();
- #endif
+ static InternalFFMpegRegister instance;
+ }
+ InternalFFMpegRegister()
+ {
+#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
+ avformat_network_init();
+#endif
- /* register all codecs, demux and protocols */
- av_register_all();
+ /* register all codecs, demux and protocols */
+ av_register_all();
- /* register a callback function for synchronization */
- av_lockmgr_register(&LockCallBack);
+ /* register a callback function for synchronization */
+ av_lockmgr_register(&LockCallBack);
#ifndef NO_GETENV
- char* debug_option = getenv("OPENCV_FFMPEG_DEBUG");
- if (debug_option != NULL)
- {
- av_log_set_level(AV_LOG_VERBOSE);
- av_log_set_callback(ffmpeg_log_callback);
- }
- else
+ char* debug_option = getenv("OPENCV_FFMPEG_DEBUG");
+ if (debug_option != NULL)
+ {
+ av_log_set_level(AV_LOG_VERBOSE);
+ av_log_set_callback(ffmpeg_log_callback);
+ }
+ else
#endif
- {
- av_log_set_level(AV_LOG_ERROR);
- }
-
- _initialized = true;
+ {
+ av_log_set_level(AV_LOG_ERROR);
}
}
-
~InternalFFMpegRegister()
{
- _initialized = false;
av_lockmgr_register(NULL);
}
};
-static InternalFFMpegRegister _init;
-
bool CvCapture_FFMPEG::open( const char* _filename )
{
+ InternalFFMpegRegister::init();
AutoLock lock(_mutex);
unsigned i;
bool valid = false;
bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
double fps, int width, int height, bool is_color )
{
+ InternalFFMpegRegister::init();
CV_CODEC_ID codec_id = CV_CODEC(CODEC_ID_NONE);
int err, codec_pix_fmt;
double bitrate_scale = 1;
*
* @param deviceName is a substring in digital camera model name.
*/
-Ptr<IVideoCapture> createGPhoto2Capture(const String & deviceName)
+Ptr<IVideoCapture> createGPhoto2Capture(const std::string & deviceName)
{
Ptr<IVideoCapture> capture = makePtr<gphoto2::DigitalCameraCapture>(deviceName);
#ifdef NDEBUG
#define CV_WARN(message)
#else
-#define CV_WARN(message) fprintf(stderr, "OpenCV | GStreamer warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
+#define CV_WARN(message) CV_LOG_WARNING(0, message)
#endif
#define COLOR_ELEM "videoconvert"
*/
bool GStreamerCapture::grabFrame()
{
- if(!pipeline)
+ if(!GST_IS_ELEMENT(pipeline))
return false;
// start the pipeline if it was not in playing state yet
*/
bool GStreamerCapture::isPipelinePlaying()
{
+ if (!GST_IS_ELEMENT(pipeline))
+ {
+ CV_WARN("GStreamer: pipeline have not been created");
+ return false;
+ }
GstState current, pending;
GstClockTime timeout = 5*GST_SECOND;
GstStateChangeReturn ret = gst_element_get_state(pipeline, ¤t, &pending, timeout);
*/
void GStreamerCapture::startPipeline()
{
- //fprintf(stderr, "relinked, pausing\n");
- GstStateChangeReturn status = gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
+ if (!GST_IS_ELEMENT(pipeline))
+ {
+ CV_WARN("GStreamer: pipeline have not been created");
+ return;
+ }
+ GstStateChangeReturn status = gst_element_set_state(pipeline, GST_STATE_PLAYING);
if (status == GST_STATE_CHANGE_ASYNC)
{
// wait for status update
if (isPosFramesEmulated)
emulatedFrameNumber = 0;
- //printf("state now playing\n");
handleMessage(pipeline);
}
*/
void GStreamerCapture::stopPipeline()
{
- //fprintf(stderr, "restarting pipeline, going to ready\n");
- if(gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE)
+ if (!GST_IS_ELEMENT(pipeline))
+ {
+ CV_WARN("GStreamer: pipeline have not been created");
+ return;
+ }
+ if(gst_element_set_state(pipeline, GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE)
{
CV_WARN("GStreamer: unable to stop pipeline");
gst_object_unref(pipeline);
*/
void GStreamerCapture::setFilter(const char *prop, int type, int v1, int v2)
{
- //printf("GStreamer: setFilter \n");
if(!caps || !( GST_IS_CAPS (caps) ))
{
if(type == G_TYPE_INT)
caps = gst_caps_fixate(caps);
gst_app_sink_set_caps(GST_APP_SINK(sink), caps);
- //printf("filtering with %s\n", gst_caps_to_string(caps));
}
/*!
sinkpad = gst_element_get_static_pad (color, "sink");
if (!sinkpad){
- //fprintf(stderr, "Gstreamer: no pad named sink\n");
return;
}
uridecodebin = gst_parse_launch(filename, &err);
if(!uridecodebin)
{
- fprintf(stderr, "GStreamer: Error opening bin: %s\n", err->message);
+ CV_WARN("GStreamer: Error opening bin: " << err->message);
return false;
}
//stream = true;
gboolean status_;
format_ = GST_FORMAT_DEFAULT;
+
status_ = gst_element_query_position(sink, format_, &value_);
if (!status_ || value_ != 0 || duration < 0)
{
- CV_WARN(cv::format("Cannot query video position: status=%d value=%lld duration=%lld\n",
- (int)status_, (long long int)value_, (long long int)duration).c_str());
+ CV_WARN("Cannot query video position: status=" << status_ << ", value=" << value_ << ", duration=" << duration);
isPosFramesSupported = false;
isPosFramesEmulated = true;
emulatedFrameNumber = 0;
}
-Ptr<IVideoCapture> cv::createGStreamerCapture(const String& filename)
+Ptr<IVideoCapture> cv::createGStreamerCapture_file(const String& filename)
{
Ptr<GStreamerCapture> cap = makePtr<GStreamerCapture>();
if (cap && cap->open(filename))
return Ptr<IVideoCapture>();
}
-Ptr<IVideoCapture> cv::createGStreamerCapture(int index)
+Ptr<IVideoCapture> cv::createGStreamerCapture_cam(int index)
{
Ptr<GStreamerCapture> cap = makePtr<GStreamerCapture>();
if (cap && cap->open(index))
int getCaptureDomain() const CV_OVERRIDE { return cv::CAP_GSTREAMER; }
- virtual bool open( const char* filename, int fourcc,
- double fps, CvSize frameSize, bool isColor );
- virtual void close();
- virtual bool writeFrame( const IplImage* image ) CV_OVERRIDE;
+ bool open(const std::string &filename, int fourcc,
+ double fps, const Size &frameSize, bool isColor );
+ void close();
+ bool writeFrame( const IplImage* image ) CV_OVERRIDE;
protected:
const char* filenameToMimetype(const char* filename);
GstElement* pipeline;
* If the file extension did was not recognize, an avi container is used
*
*/
-bool CvVideoWriter_GStreamer::open( const char * filename, int fourcc,
- double fps, CvSize frameSize, bool is_color )
+bool CvVideoWriter_GStreamer::open( const std::string &filename, int fourcc,
+ double fps, const cv::Size &frameSize, bool is_color )
{
// check arguments
- assert (filename);
- assert (fps > 0);
- assert (frameSize.width > 0 && frameSize.height > 0);
+ if (filename.empty() || frameSize.width <= 0 || frameSize.height <= 0 || fps <= 0)
+ return false;
// init gstreamer
gst_initializer::init();
// we first try to construct a pipeline from the given string.
// if that fails, we assume it is an ordinary filename
- encodebin = gst_parse_launch(filename, &err);
+ encodebin = gst_parse_launch(filename.c_str(), &err);
manualpipeline = (encodebin != NULL);
if(manualpipeline)
}
//create container caps from file extension
- mime = filenameToMimetype(filename);
+ mime = filenameToMimetype(filename.c_str());
if (!mime) {
CV_WARN("Gstreamer Opencv backend does not support this file type.");
return false;
g_object_set(G_OBJECT(encodebin), "profile", containerprofile, NULL);
source = gst_element_factory_make("appsrc", NULL);
file = gst_element_factory_make("filesink", NULL);
- g_object_set(G_OBJECT(file), "location", filename, NULL);
+ g_object_set(G_OBJECT(file), "location", filename.c_str(), NULL);
}
if (fourcc == CV_FOURCC('M','J','P','G') && frameSize.height == 1)
return true;
}
-/*!
- * \brief cvCreateVideoWriter_GStreamer
- * \param filename
- * \param fourcc
- * \param fps
- * \param frameSize
- * \param isColor
- * \return
- * Constructor
- */
-CvVideoWriter* cvCreateVideoWriter_GStreamer(const char* filename, int fourcc, double fps,
- CvSize frameSize, int isColor )
+Ptr<IVideoWriter> cv::create_GStreamer_writer(const std::string &filename, int fourcc, double fps, const cv::Size &frameSize, bool isColor)
{
CvVideoWriter_GStreamer* wrt = new CvVideoWriter_GStreamer;
- if( wrt->open(filename, fourcc, fps,frameSize, isColor))
- return wrt;
-
+ if (wrt->open(filename, fourcc, fps, frameSize, isColor))
+ return makePtr<LegacyWriter>(wrt);
delete wrt;
return 0;
}
while(gst_bus_have_pending(bus)) {
msg = gst_bus_pop(bus);
-
- //printf("\t\tGot %s message\n", GST_MESSAGE_TYPE_NAME(msg));
+ if (!msg || !GST_IS_MESSAGE(msg))
+ {
+ continue;
+ }
if(gst_is_missing_plugin_message(msg))
{
case GST_MESSAGE_STATE_CHANGED:
GstState oldstate, newstate, pendstate;
gst_message_parse_state_changed(msg, &oldstate, &newstate, &pendstate);
- //fprintf(stderr, "\t\t%s: state changed from %s to %s (pending: %s)\n",
- // gst_element_get_name(GST_MESSAGE_SRC (msg)),
- // gst_element_state_get_name(oldstate),
- // gst_element_state_get_name(newstate), gst_element_state_get_name(pendstate));
break;
case GST_MESSAGE_ERROR:
gst_message_parse_error(msg, &err, &debug);
- //fprintf(stderr, "\t\tGStreamer Plugin: Embedded video playback halted; module %s reported: %s\n",
- // gst_element_get_name(GST_MESSAGE_SRC (msg)), err->message);
-
g_error_free(err);
g_free(debug);
-
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
break;
case GST_MESSAGE_EOS:
- //fprintf(stderr, "\t\treached the end of the stream.");
break;
case GST_MESSAGE_STREAM_STATUS:
gst_message_parse_stream_status(msg,&tp,&elem);
- //fprintf(stderr, "\t\tstream status: elem %s, %i\n", GST_ELEMENT_NAME(elem), tp);
break;
default:
- //fprintf(stderr, "\t\tunhandled message %s\n",GST_MESSAGE_TYPE_NAME(msg));
break;
}
}
gst_object_unref(GST_OBJECT(bus));
}
+
+//==================================================================================================
+
+#if defined(BUILD_PLUGIN)
+
+#include "plugin_api.hpp"
+
+namespace cv {
+
+static
+CvResult CV_API_CALL cv_capture_open(const char* filename, int camera_index, CV_OUT CvPluginCapture* handle)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ *handle = NULL;
+ if (!filename)
+ return CV_ERROR_FAIL;
+ GStreamerCapture *cap = 0;
+ try
+ {
+ cap = new GStreamerCapture();
+ bool res;
+ if (filename)
+ res = cap->open(string(filename));
+ else
+ res = cap->open(camera_index);
+ if (res)
+ {
+ *handle = (CvPluginCapture)cap;
+ return CV_ERROR_OK;
+ }
+ }
+ catch (...)
+ {
+ }
+ if (cap)
+ delete cap;
+ return CV_ERROR_FAIL;
+}
+
+static
+CvResult CV_API_CALL cv_capture_release(CvPluginCapture handle)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ GStreamerCapture* instance = (GStreamerCapture*)handle;
+ delete instance;
+ return CV_ERROR_OK;
+}
+
+
+static
+CvResult CV_API_CALL cv_capture_get_prop(CvPluginCapture handle, int prop, CV_OUT double* val)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ if (!val)
+ return CV_ERROR_FAIL;
+ try
+ {
+ GStreamerCapture* instance = (GStreamerCapture*)handle;
+ *val = instance->getProperty(prop);
+ return CV_ERROR_OK;
+ }
+ catch (...)
+ {
+ return CV_ERROR_FAIL;
+ }
+}
+
+static
+CvResult CV_API_CALL cv_capture_set_prop(CvPluginCapture handle, int prop, double val)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ try
+ {
+ GStreamerCapture* instance = (GStreamerCapture*)handle;
+ return instance->setProperty(prop, val) ? CV_ERROR_OK : CV_ERROR_FAIL;
+ }
+ catch(...)
+ {
+ return CV_ERROR_FAIL;
+ }
+}
+
+static
+CvResult CV_API_CALL cv_capture_grab(CvPluginCapture handle)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ try
+ {
+ GStreamerCapture* instance = (GStreamerCapture*)handle;
+ return instance->grabFrame() ? CV_ERROR_OK : CV_ERROR_FAIL;
+ }
+ catch(...)
+ {
+ return CV_ERROR_FAIL;
+ }
+}
+
+static
+CvResult CV_API_CALL cv_capture_retrieve(CvPluginCapture handle, int stream_idx, cv_videoio_retrieve_cb_t callback, void* userdata)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ try
+ {
+ GStreamerCapture* instance = (GStreamerCapture*)handle;
+ Mat img;
+ // TODO: avoid unnecessary copying - implement lower level GStreamerCapture::retrieve
+ if (instance->retrieveFrame(stream_idx, img))
+ return callback(stream_idx, img.data, img.step, img.cols, img.rows, img.channels(), userdata);
+ return CV_ERROR_FAIL;
+ }
+ catch(...)
+ {
+ return CV_ERROR_FAIL;
+ }
+}
+
+static
+CvResult CV_API_CALL cv_writer_open(const char* filename, int fourcc, double fps, int width, int height, int isColor,
+ CV_OUT CvPluginWriter* handle)
+{
+ CvVideoWriter_GStreamer* wrt = 0;
+ try
+ {
+ wrt = new CvVideoWriter_GStreamer();
+ CvSize sz = { width, height };
+ if(wrt && wrt->open(filename, fourcc, fps, sz, isColor))
+ {
+ *handle = (CvPluginWriter)wrt;
+ return CV_ERROR_OK;
+ }
+ }
+ catch(...)
+ {
+ }
+ if (wrt)
+ delete wrt;
+ return CV_ERROR_FAIL;
+}
+
+static
+CvResult CV_API_CALL cv_writer_release(CvPluginWriter handle)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ CvVideoWriter_GStreamer* instance = (CvVideoWriter_GStreamer*)handle;
+ delete instance;
+ return CV_ERROR_OK;
+}
+
+static
+CvResult CV_API_CALL cv_writer_get_prop(CvPluginWriter /*handle*/, int /*prop*/, CV_OUT double* /*val*/)
+{
+ return CV_ERROR_FAIL;
+}
+
+static
+CvResult CV_API_CALL cv_writer_set_prop(CvPluginWriter /*handle*/, int /*prop*/, double /*val*/)
+{
+ return CV_ERROR_FAIL;
+}
+
+static
+CvResult CV_API_CALL cv_writer_write(CvPluginWriter handle, const unsigned char *data, int step, int width, int height, int cn)
+{
+ if (!handle)
+ return CV_ERROR_FAIL;
+ try
+ {
+ CvVideoWriter_GStreamer* instance = (CvVideoWriter_GStreamer*)handle;
+ CvSize sz = { width, height };
+ IplImage img;
+ cvInitImageHeader(&img, sz, IPL_DEPTH_8U, cn);
+ cvSetData(&img, const_cast<unsigned char*>(data), step);
+ return instance->writeFrame(&img) ? CV_ERROR_OK : CV_ERROR_FAIL;
+ }
+ catch(...)
+ {
+ return CV_ERROR_FAIL;
+ }
+}
+
+static const OpenCV_VideoIO_Plugin_API_preview plugin_api_v0 =
+{
+ {
+ sizeof(OpenCV_VideoIO_Plugin_API_preview), ABI_VERSION, API_VERSION,
+ CV_VERSION_MAJOR, CV_VERSION_MINOR, CV_VERSION_REVISION, CV_VERSION_STATUS,
+ "GStreamer OpenCV Video I/O plugin"
+ },
+ /* 1*/CAP_GSTREAMER,
+ /* 2*/cv_capture_open,
+ /* 3*/cv_capture_release,
+ /* 4*/cv_capture_get_prop,
+ /* 5*/cv_capture_set_prop,
+ /* 6*/cv_capture_grab,
+ /* 7*/cv_capture_retrieve,
+ /* 8*/cv_writer_open,
+ /* 9*/cv_writer_release,
+ /* 10*/cv_writer_get_prop,
+ /* 11*/cv_writer_set_prop,
+ /* 12*/cv_writer_write
+};
+
+} // namespace
+
+const OpenCV_VideoIO_Plugin_API_preview* opencv_videoio_plugin_init_v0(int requested_abi_version, int requested_api_version, void* /*reserved=NULL*/) CV_NOEXCEPT
+{
+ if (requested_abi_version != 0)
+ return NULL;
+ if (requested_api_version != 0)
+ return NULL;
+ return &cv::plugin_api_v0;
+}
+
+#endif // BUILD_PLUGIN
return !filename.empty();
}
-Ptr<IVideoCapture> createFileCapture_Images(const String& filename)
+Ptr<IVideoCapture> create_Images_capture(const std::string &filename)
{
- Ptr<IVideoCapture> capture(new CvCapture_Images(filename));
- if( capture->isOpened() )
- return capture;
- return Ptr<IVideoCapture>();
-}
-
+ return makePtr<CvCapture_Images>(filename);
}
//
return false; // not supported
}
-
-CvVideoWriter* cvCreateVideoWriter_Images( const char* filename )
+Ptr<IVideoWriter> create_Images_writer(const std::string &filename, int, double, const Size &, bool)
{
CvVideoWriter_Images *writer = new CvVideoWriter_Images;
- if( writer->open( filename ))
- return writer;
+ if( writer->open( filename.c_str() ))
+ return makePtr<LegacyWriter>(writer);
delete writer;
return 0;
}
+
+} // cv::
--- /dev/null
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+
+#ifndef CAP_INTERFACE_HPP
+#define CAP_INTERFACE_HPP
+
+#include "opencv2/core.hpp"
+#include "opencv2/core/core_c.h"
+#include "opencv2/videoio.hpp"
+#include "opencv2/videoio/videoio_c.h"
+
+//===================================================
+
+// Legacy structs
+
+struct CvCapture
+{
+ virtual ~CvCapture() {}
+ virtual double getProperty(int) const { return 0; }
+ virtual bool setProperty(int, double) { return 0; }
+ virtual bool grabFrame() { return true; }
+ virtual IplImage* retrieveFrame(int) { return 0; }
+ virtual int getCaptureDomain() { return cv::CAP_ANY; } // Return the type of the capture object: CAP_DSHOW, etc...
+};
+
+struct CvVideoWriter
+{
+ virtual ~CvVideoWriter() {}
+ virtual bool writeFrame(const IplImage*) { return false; }
+ virtual int getCaptureDomain() const { return cv::CAP_ANY; } // Return the type of the capture object: CAP_FFMPEG, etc...
+};
+
+//===================================================
+
+// Modern classes
+
+namespace cv
+{
+
+class IVideoCapture
+{
+public:
+ virtual ~IVideoCapture() {}
+ virtual double getProperty(int) const { return 0; }
+ virtual bool setProperty(int, double) { return false; }
+ virtual bool grabFrame() = 0;
+ virtual bool retrieveFrame(int, OutputArray) = 0;
+ virtual bool isOpened() const = 0;
+ virtual int getCaptureDomain() { return CAP_ANY; } // Return the type of the capture object: CAP_DSHOW, etc...
+};
+
+class IVideoWriter
+{
+public:
+ virtual ~IVideoWriter() {}
+ virtual double getProperty(int) const { return 0; }
+ virtual bool setProperty(int, double) { return false; }
+ virtual bool isOpened() const = 0;
+ virtual void write(InputArray) = 0;
+ virtual int getCaptureDomain() const { return cv::CAP_ANY; } // Return the type of the capture object: CAP_FFMPEG, etc...
+};
+
+//===================================================
+
+// Wrapper
+
+class LegacyCapture : public IVideoCapture
+{
+private:
+ CvCapture * cap;
+ LegacyCapture(const LegacyCapture &);
+ LegacyCapture& operator=(const LegacyCapture &);
+public:
+ LegacyCapture(CvCapture * cap_) : cap(cap_) {}
+ ~LegacyCapture()
+ {
+ cvReleaseCapture(&cap);
+ }
+ double getProperty(int propId) const CV_OVERRIDE
+ {
+ return cap ? cap->getProperty(propId) : 0;
+ }
+ bool setProperty(int propId, double value) CV_OVERRIDE
+ {
+ return cvSetCaptureProperty(cap, propId, value) != 0;
+ }
+ bool grabFrame() CV_OVERRIDE
+ {
+ return cap ? cvGrabFrame(cap) != 0 : false;
+ }
+ bool retrieveFrame(int channel, OutputArray image) CV_OVERRIDE
+ {
+ IplImage* _img = cvRetrieveFrame(cap, channel);
+ if( !_img )
+ {
+ image.release();
+ return false;
+ }
+ if(_img->origin == IPL_ORIGIN_TL)
+ {
+ cv::cvarrToMat(_img).copyTo(image);
+ }
+ else
+ {
+ Mat temp = cv::cvarrToMat(_img);
+ flip(temp, image, 0);
+ }
+ return true;
+ }
+ bool isOpened() const CV_OVERRIDE
+ {
+ return cap != 0; // legacy interface doesn't support closed files
+ }
+ int getCaptureDomain() CV_OVERRIDE
+ {
+ return cap ? cap->getCaptureDomain() : 0;
+ }
+};
+
+class LegacyWriter : public IVideoWriter
+{
+private:
+ CvVideoWriter * writer;
+ LegacyWriter(const LegacyWriter &);
+ LegacyWriter& operator=(const LegacyWriter &);
+public:
+ LegacyWriter(CvVideoWriter * wri_) : writer(wri_)
+ {}
+ ~LegacyWriter()
+ {
+ cvReleaseVideoWriter(&writer);
+ }
+ double getProperty(int) const CV_OVERRIDE
+ {
+ return 0.;
+ }
+ bool setProperty(int, double) CV_OVERRIDE
+ {
+ return false;
+ }
+ bool isOpened() const CV_OVERRIDE
+ {
+ return writer != NULL;
+ }
+ void write(InputArray image) CV_OVERRIDE
+ {
+ IplImage _img = cvIplImage(image.getMat());
+ cvWriteFrame(writer, &_img);
+ }
+ int getCaptureDomain() const CV_OVERRIDE
+ {
+ return writer ? writer->getCaptureDomain() : 0;
+ }
+};
+
+//==================================================================================================
+
+Ptr<IVideoCapture> cvCreateFileCapture_FFMPEG_proxy(const std::string &filename);
+Ptr<IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const std::string& filename, int fourcc, double fps, const Size &frameSize, bool isColor);
+
+Ptr<IVideoCapture> createGStreamerCapture_file(const std::string& filename);
+Ptr<IVideoCapture> createGStreamerCapture_cam(int index);
+Ptr<IVideoWriter> create_GStreamer_writer(const std::string& filename, int fourcc, double fps, const Size &frameSize, bool isColor);
+
+Ptr<IVideoCapture> create_MFX_capture(const std::string &filename);
+Ptr<IVideoWriter> create_MFX_writer(const std::string &filename, int _fourcc, double fps, const Size &frameSize, bool isColor);
+
+Ptr<IVideoCapture> create_AVFoundation_capture_file(const std::string &filename);
+Ptr<IVideoCapture> create_AVFoundation_capture_cam(int index);
+Ptr<IVideoWriter> create_AVFoundation_writer(const std::string& filename, int fourcc, double fps, const Size &frameSize, bool isColor);
+
+Ptr<IVideoCapture> create_WRT_capture(int device);
+
+Ptr<IVideoCapture> cvCreateCapture_MSMF(int index);
+Ptr<IVideoCapture> cvCreateCapture_MSMF(const std::string& filename);
+Ptr<IVideoWriter> cvCreateVideoWriter_MSMF(const std::string& filename, int fourcc, double fps, const Size &frameSize, bool is_color);
+
+Ptr<IVideoCapture> create_DShow_capture(int index);
+
+Ptr<IVideoCapture> create_V4L_capture_cam(int index);
+Ptr<IVideoCapture> create_V4L_capture_file(const std::string &filename);
+
+Ptr<IVideoCapture> create_OpenNI2_capture_cam( int index );
+Ptr<IVideoCapture> create_OpenNI2_capture_file( const std::string &filename );
+
+Ptr<IVideoCapture> create_Images_capture(const std::string &filename);
+Ptr<IVideoWriter> create_Images_writer(const std::string &filename, int fourcc, double fps, const Size &frameSize, bool iscolor);
+
+Ptr<IVideoCapture> create_DC1394_capture(int index);
+
+Ptr<IVideoCapture> create_RealSense_capture(int index);
+
+Ptr<IVideoCapture> create_PvAPI_capture( int index );
+
+Ptr<IVideoCapture> create_XIMEA_capture_cam( int index );
+Ptr<IVideoCapture> create_XIMEA_capture_file( const std::string &serialNumber );
+
+Ptr<IVideoCapture> create_Aravis_capture( int index );
+
+Ptr<IVideoCapture> createMotionJpegCapture(const std::string& filename);
+Ptr<IVideoWriter> createMotionJpegWriter(const std::string &filename, int fourcc, double fps, const Size &frameSize, bool iscolor);
+
+Ptr<IVideoCapture> createGPhoto2Capture(int index);
+Ptr<IVideoCapture> createGPhoto2Capture(const std::string& deviceName);
+
+Ptr<IVideoCapture> createXINECapture(const std::string &filename);
+
+Ptr<IVideoCapture> createAndroidCapture_file(const std::string &filename);
+
+} // cv::
+
+#endif // CAP_INTERFACE_HPP
return bool(std::shared_ptr<rs2_pipeline>(mPipe));
}
+Ptr<IVideoCapture> create_RealSense_capture(int index)
+{
+ return makePtr<VideoCapture_LibRealsense>(index);
+}
+
+
}
#endif
virtual bool retrieveFrame(int outputType, OutputArray frame) CV_OVERRIDE;
virtual int getCaptureDomain() CV_OVERRIDE;
virtual bool isOpened() const CV_OVERRIDE;
+
protected:
rs2::pipeline mPipe;
rs2::frameset mData;
private:
VAHandle(const VAHandle &);
VAHandle &operator=(const VAHandle &);
- virtual bool initDeviceSession(MFXVideoSession &session);
+ bool initDeviceSession(MFXVideoSession &session) CV_OVERRIDE;
private:
VADisplay display;
int file;
private:
DXHandle(const DXHandle &);
DXHandle &operator=(const DXHandle &);
- virtual bool initDeviceSession(MFXVideoSession &) { return true; }
+ bool initDeviceSession(MFXVideoSession &) CV_OVERRIDE { return true; }
};
#endif // _WIN32
#include "opencv2/core/base.hpp"
#include "cap_mfx_common.hpp"
#include "opencv2/imgproc/hal/hal.hpp"
+#include "cap_interface.hpp"
using namespace cv;
using namespace std;
}
//==================================================================================================
+
+cv::Ptr<IVideoCapture> cv::create_MFX_capture(const std::string &filename)
+{
+ return cv::makePtr<VideoCapture_IntelMFX>(filename);
+}
{
public:
VideoCapture_IntelMFX(const cv::String &filename);
- virtual ~VideoCapture_IntelMFX();
- virtual double getProperty(int) const CV_OVERRIDE;
- virtual bool setProperty(int, double) CV_OVERRIDE;
- virtual bool grabFrame() CV_OVERRIDE;
- virtual bool retrieveFrame(int, cv::OutputArray out) CV_OVERRIDE;
- virtual bool isOpened() const CV_OVERRIDE;
- virtual int getCaptureDomain() CV_OVERRIDE;
+ ~VideoCapture_IntelMFX();
+ double getProperty(int) const CV_OVERRIDE;
+ bool setProperty(int, double) CV_OVERRIDE;
+ bool grabFrame() CV_OVERRIDE;
+ bool retrieveFrame(int, cv::OutputArray out) CV_OVERRIDE;
+ bool isOpened() const CV_OVERRIDE;
+ int getCaptureDomain() CV_OVERRIDE;
private:
MFXVideoSession *session;
Plugin *plugin;
#include "opencv2/core/base.hpp"
#include "cap_mfx_common.hpp"
#include "opencv2/imgproc/hal/hal.hpp"
+#include "cap_interface.hpp"
using namespace std;
using namespace cv;
return;
}
+ if (fps <= 0)
+ {
+ MSG(cerr << "MFX: Invalid FPS passed to encoder" << endl);
+ return;
+ }
+
// Init device and session
deviceHandler = createDeviceHandler();
session = new MFXVideoSession();
}
}
-Ptr<VideoWriter_IntelMFX> VideoWriter_IntelMFX::create(const String &filename, int _fourcc, double fps, Size frameSize, bool isColor)
+Ptr<IVideoWriter> cv::create_MFX_writer(const std::string &filename, int _fourcc, double fps, const Size &frameSize, bool isColor)
{
if (codecIdByFourCC(_fourcc) > 0)
{
{
public:
VideoWriter_IntelMFX(const cv::String &filename, int _fourcc, double fps, cv::Size frameSize, bool isColor);
- virtual ~VideoWriter_IntelMFX();
- virtual double getProperty(int) const;
- virtual bool setProperty(int, double);
- virtual bool isOpened() const;
- virtual void write(cv::InputArray input);
- static cv::Ptr<VideoWriter_IntelMFX> create(const cv::String& filename, int _fourcc, double fps, cv::Size frameSize, bool isColor);
-
- virtual int getCaptureDomain() const { return cv::CAP_INTEL_MFX; }
+ ~VideoWriter_IntelMFX() CV_OVERRIDE;
+ double getProperty(int) const CV_OVERRIDE;
+ bool setProperty(int, double) CV_OVERRIDE;
+ bool isOpened() const CV_OVERRIDE;
+ void write(cv::InputArray input) CV_OVERRIDE;
+ int getCaptureDomain() const CV_OVERRIDE { return cv::CAP_INTEL_MFX; }
protected:
bool write_one(cv::InputArray bgr);
}
-Ptr<IVideoWriter> createMotionJpegWriter(const String& filename, int fourcc, double fps, Size frameSize, bool iscolor)
+Ptr<IVideoWriter> createMotionJpegWriter(const std::string &filename, int fourcc, double fps, const Size &frameSize, bool iscolor)
{
if (fourcc != CV_FOURCC('M', 'J', 'P', 'G'))
return Ptr<IVideoWriter>();
}
}
-cv::Ptr<cv::IVideoWriter> cv::cvCreateVideoWriter_MSMF( const cv::String& filename, int fourcc,
- double fps, cv::Size frameSize, int isColor )
+cv::Ptr<cv::IVideoWriter> cv::cvCreateVideoWriter_MSMF( const std::string& filename, int fourcc,
+ double fps, const cv::Size &frameSize, bool isColor )
{
cv::Ptr<CvVideoWriter_MSMF> writer = cv::makePtr<CvVideoWriter_MSMF>();
if (writer)
{
- writer->open(filename, fourcc, fps, frameSize, isColor != 0);
+ writer->open(filename, fourcc, fps, frameSize, isColor);
if (writer->isOpened())
return writer;
}
//
//M*/
#include "precomp.hpp"
+#include "cap_interface.hpp"
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
return image;
}
-CvCapture* cvCreateCameraCapture_OpenNI2( int index )
+cv::Ptr<cv::IVideoCapture> cv::create_OpenNI2_capture_cam( int index )
{
CvCapture_OpenNI2* capture = new CvCapture_OpenNI2( index );
if( capture->isOpened() )
- return capture;
+ return cv::makePtr<cv::LegacyCapture>(capture);
delete capture;
return 0;
}
-CvCapture* cvCreateFileCapture_OpenNI2( const char* filename )
+cv::Ptr<cv::IVideoCapture> cv::create_OpenNI2_capture_file( const std::string &filename )
{
- CvCapture_OpenNI2* capture = new CvCapture_OpenNI2( filename );
+ CvCapture_OpenNI2* capture = new CvCapture_OpenNI2( filename.c_str() );
if( capture->isOpened() )
- return capture;
+ return cv::makePtr<cv::LegacyCapture>(capture);
delete capture;
return 0;
//
#include "precomp.hpp"
+#include "cap_interface.hpp"
#ifdef HAVE_PVAPI
#if !defined _WIN32 && !defined _LINUX
return true;
}
-CvCapture* cvCreateCameraCapture_PvAPI( int index )
+cv::Ptr<cv::IVideoCapture> cv::create_PvAPI_capture( int index )
{
CvCaptureCAM_PvAPI* capture = new CvCaptureCAM_PvAPI;
if ( capture->open( index ))
- return capture;
+ return cv::makePtr<cv::LegacyCapture>(capture);
delete capture;
return NULL;
#include <assert.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
+#include <limits>
#ifdef HAVE_CAMV4L2
#include <asm/types.h> /* for videodev2.h */
#define V4L2_CID_ISO_SENSITIVITY (V4L2_CID_CAMERA_CLASS_BASE+23)
#endif
+// https://github.com/opencv/opencv/issues/13929
+#ifndef V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT
+#define V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT (V4L2_CID_MPEG_BASE+364)
+#endif
+#ifndef V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH
+#define V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH (V4L2_CID_MPEG_BASE+365)
+#endif
+
/* Defaults - If your board can do better, set it here. Set for the most common type inputs. */
#define DEFAULT_V4L_WIDTH 640
#define DEFAULT_V4L_HEIGHT 480
void CvCaptureCAM_V4L::v4l2_create_frame()
{
- CvSize size = {form.fmt.pix.width, form.fmt.pix.height};
+ CV_Assert(form.fmt.pix.width <= (uint)std::numeric_limits<int>::max());
+ CV_Assert(form.fmt.pix.height <= (uint)std::numeric_limits<int>::max());
+ CvSize size = {(int)form.fmt.pix.width, (int)form.fmt.pix.height};
int channels = 3;
int depth = IPL_DEPTH_8U;
if (bool(value)) {
convert_rgb = convertableToRgb();
return convert_rgb;
+ }else{
+ convert_rgb = false;
+ releaseFrame();
+ return true;
}
- convert_rgb = false;
- return true;
case cv::CAP_PROP_FOURCC:
{
if (palette == static_cast<__u32>(value))
return &frame;
}
-} // end namespace cv
-
-CvCapture* cvCreateCameraCapture_V4L( int index )
+Ptr<IVideoCapture> create_V4L_capture_cam(int index)
{
cv::CvCaptureCAM_V4L* capture = new cv::CvCaptureCAM_V4L();
- if(capture->open(index))
- return capture;
+ if (capture->open(index))
+ return makePtr<LegacyCapture>(capture);
delete capture;
return NULL;
}
-CvCapture* cvCreateCameraCapture_V4L( const char * deviceName )
+Ptr<IVideoCapture> create_V4L_capture_file(const std::string &filename)
{
cv::CvCaptureCAM_V4L* capture = new cv::CvCaptureCAM_V4L();
- if(capture->open( deviceName ))
- return capture;
+ if (capture->open(filename.c_str()))
+ return makePtr<LegacyCapture>(capture);
delete capture;
return NULL;
}
+} // cv::
+
#endif
}
return true;
}
+
+Ptr<IVideoCapture> create_WRT_capture(int device)
+{
+ return makePtr<VideoCapture_WinRT>(device);
+}
+
}
-// end
\ No newline at end of file
+// end
unsigned long frameCurrent;
std::atomic<bool> isFrameNew;
};
-}
\ No newline at end of file
+}
/**********************************************************************************/
-CvCapture* cvCreateCameraCapture_XIMEA( int index )
+cv::Ptr<cv::IVideoCapture> cv::create_XIMEA_capture_cam( int index )
{
CvCaptureCAM_XIMEA* capture = new CvCaptureCAM_XIMEA;
if( capture->open( index ))
- return capture;
+ return cv::makePtr<cv::LegacyCapture>(capture);
delete capture;
return 0;
}
-CvCapture* cvCreateCameraCapture_XIMEA( const char* serialNumber )
+cv::Ptr<cv::IVideoCapture> cv::create_XIMEA_capture_file( const std::string &serialNumber )
{
CvCaptureCAM_XIMEA* capture = new CvCaptureCAM_XIMEA;
- if( capture->open( serialNumber ))
- return capture;
+ if( capture->open( serialNumber.c_str() ))
+ return cv::makePtr<cv::LegacyCapture>(capture);
delete capture;
return 0;
#endif
}
-/**********************************************************************************/
\ No newline at end of file
+/**********************************************************************************/
}
};
-Ptr<IVideoCapture> cv::createXINECapture(const char *filename)
+Ptr<IVideoCapture> cv::createXINECapture(const std::string &filename)
{
Ptr<XINECapture> res = makePtr<XINECapture>();
- if (res && res->open(filename))
+ if (res && res->open(filename.c_str()))
return res;
return Ptr<IVideoCapture>();
}
--- /dev/null
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+
+#ifndef PLUGIN_API_HPP
+#define PLUGIN_API_HPP
+
+#include <opencv2/core/cvdef.h>
+#include <opencv2/core/llapi/llapi.h>
+
+// increase for backward-compatible changes, e.g. add new function
+// Main API <= Plugin API -> plugin is compatible
+#define API_VERSION 0 // preview
+// increase for incompatible changes, e.g. remove function argument
+// Main ABI == Plugin ABI -> plugin is compatible
+#define ABI_VERSION 0 // preview
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef CvResult (CV_API_CALL *cv_videoio_retrieve_cb_t)(int stream_idx, unsigned const char* data, int step, int width, int height, int cn, void* userdata);
+
+typedef struct CvPluginCapture_t* CvPluginCapture;
+typedef struct CvPluginWriter_t* CvPluginWriter;
+
+typedef struct OpenCV_VideoIO_Plugin_API_preview
+{
+ OpenCV_API_Header api_header;
+
+ /** OpenCV capture ID (VideoCaptureAPIs)
+ @note API-ENTRY 1, API-Version == 0
+ */
+ int captureAPI;
+
+ /** @brief Open video capture
+
+ @param filename File name or NULL to use camera_index instead
+ @param camera_index Camera index (used if filename == NULL)
+ @param[out] handle pointer on Capture handle
+
+ @note API-CALL 2, API-Version == 0
+ */
+ CvResult (CV_API_CALL *Capture_open)(const char* filename, int camera_index, CV_OUT CvPluginCapture* handle);
+
+ /** @brief Release Capture handle
+
+ @param handle Capture handle
+
+ @note API-CALL 3, API-Version == 0
+ */
+ CvResult (CV_API_CALL *Capture_release)(CvPluginCapture handle);
+
+ /** @brief Get property value
+
+ @param handle Capture handle
+ @param prop Property index
+ @param[out] val property value
+
+ @note API-CALL 4, API-Version == 0
+ */
+ CvResult (CV_API_CALL *Capture_getProperty)(CvPluginCapture handle, int prop, CV_OUT double* val);
+
+ /** @brief Set property value
+
+ @param handle Capture handle
+ @param prop Property index
+ @param val property value
+
+ @note API-CALL 5, API-Version == 0
+ */
+ CvResult (CV_API_CALL *Capture_setProperty)(CvPluginCapture handle, int prop, double val);
+
+ /** @brief Grab frame
+
+ @param handle Capture handle
+
+ @note API-CALL 6, API-Version == 0
+ */
+ CvResult (CV_API_CALL *Capture_grab)(CvPluginCapture handle);
+
+ /** @brief Retrieve frame
+
+ @param handle Capture handle
+ @param stream_idx stream index to retrieve (BGR/IR/depth data)
+ @param callback retrieve callback (synchronous)
+ @param userdata callback context data
+
+ @note API-CALL 7, API-Version == 0
+ */
+ CvResult (CV_API_CALL *Capture_retreive)(CvPluginCapture handle, int stream_idx, cv_videoio_retrieve_cb_t callback, void* userdata);
+
+
+ /** @brief Try to open video writer
+
+ @param filename File name or NULL to use camera_index instead
+ @param camera_index Camera index (used if filename == NULL)
+ @param[out] handle pointer on Writer handle
+
+ @note API-CALL 8, API-Version == 0
+ */
+ CvResult (CV_API_CALL *Writer_open)(const char* filename, int fourcc, double fps, int width, int height, int isColor,
+ CV_OUT CvPluginWriter* handle);
+
+ /** @brief Release Writer handle
+
+ @param handle Writer handle
+
+ @note API-CALL 9, API-Version == 0
+ */
+ CvResult (CV_API_CALL *Writer_release)(CvPluginWriter handle);
+
+ /** @brief Get property value
+
+ @param handle Capture handle
+ @param prop Property index
+ @param[out] val property value
+
+ @note API-CALL 10, API-Version == 0
+ */
+ CvResult (CV_API_CALL *Writer_getProperty)(CvPluginWriter handle, int prop, CV_OUT double* val);
+
+ /** @brief Set property value
+
+ @param handle Capture handle
+ @param prop Property index
+ @param val property value
+
+ @note API-CALL 11, API-Version == 0
+ */
+ CvResult (CV_API_CALL *Writer_setProperty)(CvPluginWriter handle, int prop, double val);
+
+ /** @brief Write frame
+
+ @param handle Capture handle
+ @param data Capture handle
+ @param step step in bytes
+ @param width frame width in pixels
+ @param height frame height
+ @param cn number of channels per pixel
+
+ @note API-CALL 12, API-Version == 0
+ */
+ CvResult (CV_API_CALL *Writer_write)(CvPluginWriter handle, const unsigned char *data, int step, int width, int height, int cn);
+
+} OpenCV_VideoIO_Plugin_API_preview;
+
+#ifdef BUILD_PLUGIN
+
+#ifndef CV_PLUGIN_EXPORTS
+#if (defined _WIN32 || defined WINCE || defined __CYGWIN__)
+# define CV_PLUGIN_EXPORTS __declspec(dllexport)
+#elif defined __GNUC__ && __GNUC__ >= 4
+# define CV_PLUGIN_EXPORTS __attribute__ ((visibility ("default")))
+#endif
+#endif
+
+CV_PLUGIN_EXPORTS
+const OpenCV_VideoIO_Plugin_API_preview* CV_API_CALL opencv_videoio_plugin_init_v0
+ (int requested_abi_version, int requested_api_version, void* reserved /*NULL*/) CV_NOEXCEPT;
+
+#else // BUILD_PLUGIN
+typedef const OpenCV_VideoIO_Plugin_API_preview* (CV_API_CALL *FN_opencv_videoio_plugin_init_t)
+ (int requested_abi_version, int requested_api_version, void* reserved /*NULL*/);
+#endif // BUILD_PLUGIN
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // PLUGIN_API_HPP
#undef abs
#endif
-#define __BEGIN__ __CV_BEGIN__
-#define __END__ __CV_END__
-#define EXIT __CV_EXIT__
-
-/***************************** CvCapture structure ******************************/
-
-struct CvCapture
-{
- virtual ~CvCapture() {}
- virtual double getProperty(int) const { return 0; }
- virtual bool setProperty(int, double) { return 0; }
- virtual bool grabFrame() { return true; }
- virtual IplImage* retrieveFrame(int) { return 0; }
- virtual int getCaptureDomain() { return cv::CAP_ANY; } // Return the type of the capture object: CAP_DSHOW, etc...
-};
-
-/*************************** CvVideoWriter structure ****************************/
-
-struct CvVideoWriter
-{
- virtual ~CvVideoWriter() {}
- virtual bool writeFrame(const IplImage*) { return false; }
- virtual int getCaptureDomain() const { return cv::CAP_ANY; } // Return the type of the capture object: CAP_FFMPEG, etc...
-};
-
-CvCapture * cvCreateCameraCapture_V4L( int index );
-CvCapture * cvCreateCameraCapture_V4L( const char* deviceName );
-CvCapture * cvCreateCameraCapture_DC1394_2( int index );
-CvCapture* cvCreateCameraCapture_MIL( int index );
-CvCapture* cvCreateCameraCapture_Giganetix( int index );
-CvCapture* cvCreateFileCapture_Win32( const char* filename );
-CvVideoWriter* cvCreateVideoWriter_Win32( const char* filename, int fourcc,
- double fps, CvSize frameSize, int is_color );
-CvCapture* cvCreateCameraCapture_DShow( int index );
-CvCapture* cvCreateCameraCapture_OpenNI( int index );
-CvCapture* cvCreateCameraCapture_OpenNI2( int index );
-CvCapture* cvCreateFileCapture_OpenNI( const char* filename );
-CvCapture* cvCreateFileCapture_OpenNI2( const char* filename );
-CvCapture* cvCreateCameraCapture_Android( int index );
-CvCapture* cvCreateCameraCapture_XIMEA( int index );
-CvCapture* cvCreateCameraCapture_XIMEA( const char* serialNumber );
-CvCapture* cvCreateCameraCapture_AVFoundation(int index);
-CvCapture* cvCreateCameraCapture_Aravis( int index );
-
-CvVideoWriter* cvCreateVideoWriter_Images(const char* filename);
-
-
-#define CV_CAP_GSTREAMER_1394 0
-#define CV_CAP_GSTREAMER_V4L 1
-#define CV_CAP_GSTREAMER_V4L2 2
-#define CV_CAP_GSTREAMER_FILE 3
-
-CvCapture * cvCreateFileCapture_QT (const char * filename);
-CvCapture * cvCreateCameraCapture_QT (const int index);
-
-CvVideoWriter* cvCreateVideoWriter_QT ( const char* filename, int fourcc,
- double fps, CvSize frameSize, int is_color );
-
-CvCapture* cvCreateFileCapture_AVFoundation (const char * filename);
-CvVideoWriter* cvCreateVideoWriter_AVFoundation( const char* filename, int fourcc,
- double fps, CvSize frameSize, int is_color );
-
-
-CvCapture * cvCreateCameraCapture_PvAPI (const int index);
-CvVideoWriter* cvCreateVideoWriter_GStreamer( const char* filename, int fourcc,
- double fps, CvSize frameSize, int is_color );
-
-
-namespace cv
-{
- class IVideoCapture
- {
- public:
- virtual ~IVideoCapture() {}
- virtual double getProperty(int) const { return 0; }
- virtual bool setProperty(int, double) { return false; }
- virtual bool grabFrame() = 0;
- virtual bool retrieveFrame(int, OutputArray) = 0;
- virtual bool isOpened() const = 0;
- virtual int getCaptureDomain() { return CAP_ANY; } // Return the type of the capture object: CAP_DSHOW, etc...
- };
-
- class IVideoWriter
- {
- public:
- virtual ~IVideoWriter() {}
- virtual double getProperty(int) const { return 0; }
- virtual bool setProperty(int, double) { return false; }
-
- virtual bool isOpened() const = 0;
- virtual void write(InputArray) = 0;
-
- virtual int getCaptureDomain() const { return cv::CAP_ANY; } // Return the type of the capture object: CAP_FFMPEG, etc...
- };
-
- Ptr<IVideoCapture> createFileCapture_Images(const String& filename);
-
- Ptr<IVideoCapture> createMotionJpegCapture(const String& filename);
- Ptr<IVideoWriter> createMotionJpegWriter(const String& filename, int fourcc, double fps, Size frameSize, bool iscolor);
-
- Ptr<IVideoCapture> createGPhoto2Capture(int index);
- Ptr<IVideoCapture> createGPhoto2Capture(const String& deviceName);
-
-
- Ptr<IVideoCapture> createXINECapture(const char* filename);
-
- Ptr<IVideoCapture> createGStreamerCapture(const String& filename);
- Ptr<IVideoCapture> createGStreamerCapture(int index);
-
- Ptr<cv::IVideoCapture> cvCreateFileCapture_FFMPEG_proxy(const String& filename);
- Ptr<IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const String& filename, int fourcc, double fps, Size frameSize, int isColor);
-
- Ptr<IVideoCapture> cvCreateCapture_MSMF(int index);
- Ptr<IVideoCapture> cvCreateCapture_MSMF(const String& filename);
- Ptr<IVideoWriter> cvCreateVideoWriter_MSMF(const String& filename, int fourcc, double fps, Size frameSize, int is_color);
-}
+#include "cap_interface.hpp"
#endif /* __VIDEOIO_H_ */
// of this distribution and at http://opencv.org/license.html.
#include "precomp.hpp"
-
+#include "opencv2/videoio/registry.hpp"
#include "videoio_registry.hpp"
using namespace cv;
// Legacy C-like API
-CV_IMPL CvCapture* cvCreateCameraCapture(int index)
+CV_IMPL CvCapture* cvCreateCameraCapture(int)
{
- // interpret preferred interface (0 = autodetect)
- int apiPreference = (index / 100) * 100;
- if (apiPreference)
- {
- index %= 100;
- }
-
- const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_CaptureByIndex();
- for (size_t i = 0; i < backends.size(); i++)
- {
- const VideoBackendInfo& info = backends[i];
- if (apiPreference == CAP_ANY || apiPreference == info.id)
- {
- CvCapture* capture = NULL;
- Ptr<IVideoCapture> icap; // unused
- VideoCapture_create(capture, icap, info.id, index);
- if (capture)
- {
- return capture;
- }
- if (!icap.empty())
- {
- CV_LOG_WARNING(NULL, "cvCreateFileCaptureWithPreference: backend " << info.name << " doesn't support legacy API anymore.")
- }
- }
- }
+ CV_LOG_WARNING(NULL, "cvCreateCameraCapture doesn't support legacy API anymore.")
return NULL;
}
-CV_IMPL CvCapture* cvCreateFileCaptureWithPreference(const char* filename, int apiPreference)
+CV_IMPL CvCapture* cvCreateFileCaptureWithPreference(const char*, int)
{
- const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_CaptureByFilename();
- for (size_t i = 0; i < backends.size(); i++)
- {
- const VideoBackendInfo& info = backends[i];
- if (apiPreference == CAP_ANY || apiPreference == info.id)
- {
- CvCapture* capture = NULL;
- Ptr<IVideoCapture> icap; // unused
- VideoCapture_create(capture, icap, info.id, filename);
- if (capture)
- {
- return capture;
- }
- if (!icap.empty())
- {
- CV_LOG_WARNING(NULL, "cvCreateFileCaptureWithPreference: backend " << info.name << " doesn't support legacy API anymore.")
- }
- }
- }
+ CV_LOG_WARNING(NULL, "cvCreateFileCaptureWithPreference doesn't support legacy API anymore.")
return NULL;
}
return cvCreateFileCaptureWithPreference(filename, CAP_ANY);
}
-CV_IMPL CvVideoWriter* cvCreateVideoWriter(const char* filename, int fourcc,
- double fps, CvSize frameSize, int is_color)
+CV_IMPL CvVideoWriter* cvCreateVideoWriter(const char*, int, double, CvSize, int)
{
- const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_Writer();
- for (size_t i = 0; i < backends.size(); i++)
- {
- const VideoBackendInfo& info = backends[i];
- {
- CvVideoWriter* writer_ = NULL;
- Ptr<IVideoWriter> iwriter; // unused
- VideoWriter_create(writer_, iwriter, info.id, filename, fourcc, fps, frameSize, is_color != 0);
- if (writer_)
- {
- return writer_;
- }
- if (!iwriter.empty())
- {
- CV_LOG_WARNING(NULL, "cvCreateVideoWriter: backend " << info.name << " doesn't support legacy API anymore.")
- }
- }
- }
+ CV_LOG_WARNING(NULL, "cvCreateVideoWriter doesn't support legacy API anymore.")
return NULL;
}
#include "cap_mfx_writer.hpp"
#endif
+#include "plugin_api.hpp"
+
// All WinRT versions older than 8.0 should provide classes used for video support
#if defined(WINRT) && !defined(WINRT_8_0) && defined(__cplusplus_winrt)
# include "cap_winrt_capture.hpp"
using namespace cv;
-namespace cv
-{
-
-static bool param_VIDEOIO_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOIO_DEBUG", false);
-static bool param_VIDEOCAPTURE_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOCAPTURE_DEBUG", false);
-static bool param_VIDEOWRITER_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOWRITER_DEBUG", false);
+namespace cv {
namespace {
-#define DECLARE_BACKEND(cap, name, mode) { cap, (BackendMode)(mode), 1000, name }
+#define DECLARE_DYNAMIC_BACKEND(cap, name, mode) \
+{ \
+ cap, (BackendMode)(mode), 1000, name, createPluginBackendFactory(cap, name) \
+}
+
+#define DECLARE_STATIC_BACKEND(cap, name, mode, createCaptureFile, createCaptureCamera, createWriter) \
+{ \
+ cap, (BackendMode)(mode), 1000, name, createBackendFactory(createCaptureFile, createCaptureCamera, createWriter) \
+}
/** Ordering guidelines:
- modern optimized, multi-platform libraries: ffmpeg, gstreamer, Media SDK
static const struct VideoBackendInfo builtin_backends[] =
{
#ifdef HAVE_FFMPEG
- DECLARE_BACKEND(CAP_FFMPEG, "FFMPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
+ DECLARE_STATIC_BACKEND(CAP_FFMPEG, "FFMPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER, cvCreateFileCapture_FFMPEG_proxy, 0, cvCreateVideoWriter_FFMPEG_proxy),
+#elif defined(ENABLE_PLUGINS)
+ DECLARE_DYNAMIC_BACKEND(CAP_FFMPEG, "FFMPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
#endif
+
#ifdef HAVE_GSTREAMER
- DECLARE_BACKEND(CAP_GSTREAMER, "GSTREAMER", MODE_CAPTURE_ALL | MODE_WRITER),
+ DECLARE_STATIC_BACKEND(CAP_GSTREAMER, "GSTREAMER", MODE_CAPTURE_ALL | MODE_WRITER, createGStreamerCapture_file, createGStreamerCapture_cam, create_GStreamer_writer),
+#elif defined(ENABLE_PLUGINS)
+ DECLARE_DYNAMIC_BACKEND(CAP_GSTREAMER, "GSTREAMER", MODE_CAPTURE_ALL | MODE_WRITER),
#endif
+
#ifdef HAVE_MFX // Media SDK
- DECLARE_BACKEND(CAP_INTEL_MFX, "INTEL_MFX", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
+ DECLARE_STATIC_BACKEND(CAP_INTEL_MFX, "INTEL_MFX", MODE_CAPTURE_BY_FILENAME | MODE_WRITER, create_MFX_capture, 0, create_MFX_writer),
#endif
-
// Apple platform
#ifdef HAVE_AVFOUNDATION
- DECLARE_BACKEND(CAP_AVFOUNDATION, "AVFOUNDATION", MODE_CAPTURE_ALL | MODE_WRITER),
+ DECLARE_STATIC_BACKEND(CAP_AVFOUNDATION, "AVFOUNDATION", MODE_CAPTURE_ALL | MODE_WRITER, create_AVFoundation_capture_file, create_AVFoundation_capture_cam, create_AVFoundation_writer),
#endif
// Windows
#ifdef WINRT_VIDEO
- DECLARE_BACKEND(CAP_WINRT, "WINRT", MODE_CAPTURE_BY_INDEX),
+ DECLARE_STATIC_BACKEND(CAP_WINRT, "WINRT", MODE_CAPTURE_BY_INDEX, 0, create_WRT_capture, 0),
#endif
#ifdef HAVE_MSMF
- DECLARE_BACKEND(CAP_MSMF, "MSMF", MODE_CAPTURE_ALL | MODE_WRITER),
+ DECLARE_STATIC_BACKEND(CAP_MSMF, "MSMF", MODE_CAPTURE_ALL | MODE_WRITER, cvCreateCapture_MSMF, cvCreateCapture_MSMF, cvCreateVideoWriter_MSMF),
#endif
#ifdef HAVE_DSHOW
- DECLARE_BACKEND(CAP_DSHOW, "DSHOW", MODE_CAPTURE_BY_INDEX),
+ DECLARE_STATIC_BACKEND(CAP_DSHOW, "DSHOW", MODE_CAPTURE_BY_INDEX, 0, create_DShow_capture, 0),
#endif
// Linux, some Unix
#if defined HAVE_CAMV4L2
- DECLARE_BACKEND(CAP_V4L2, "V4L2", MODE_CAPTURE_ALL),
+ DECLARE_STATIC_BACKEND(CAP_V4L2, "V4L2", MODE_CAPTURE_ALL, create_V4L_capture_file, create_V4L_capture_cam, 0),
#elif defined HAVE_VIDEOIO
- DECLARE_BACKEND(CAP_V4L, "V4L_BSD", MODE_CAPTURE_ALL),
+ DECLARE_STATIC_BACKEND(CAP_V4L, "V4L_BSD", MODE_CAPTURE_ALL, create_V4L_capture_file, create_V4L_capture_cam, 0),
#endif
// RGB-D universal
#ifdef HAVE_OPENNI2
- DECLARE_BACKEND(CAP_OPENNI2, "OPENNI2", MODE_CAPTURE_ALL),
+ DECLARE_STATIC_BACKEND(CAP_OPENNI2, "OPENNI2", MODE_CAPTURE_ALL, create_OpenNI2_capture_file, create_OpenNI2_capture_cam, 0),
#endif
#ifdef HAVE_LIBREALSENSE
- DECLARE_BACKEND(CAP_REALSENSE, "INTEL_REALSENSE", MODE_CAPTURE_BY_INDEX),
+ DECLARE_STATIC_BACKEND(CAP_REALSENSE, "INTEL_REALSENSE", MODE_CAPTURE_BY_INDEX, 0, create_RealSense_capture, 0),
#endif
// OpenCV file-based only
- DECLARE_BACKEND(CAP_IMAGES, "CV_IMAGES", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
- DECLARE_BACKEND(CAP_OPENCV_MJPEG, "CV_MJPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
+ DECLARE_STATIC_BACKEND(CAP_IMAGES, "CV_IMAGES", MODE_CAPTURE_BY_FILENAME | MODE_WRITER, create_Images_capture, 0, create_Images_writer),
+ DECLARE_STATIC_BACKEND(CAP_OPENCV_MJPEG, "CV_MJPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER, createMotionJpegCapture, 0, createMotionJpegWriter),
// special interfaces / stereo cameras / other SDKs
#if defined(HAVE_DC1394_2)
- DECLARE_BACKEND(CAP_FIREWIRE, "FIREWIRE", MODE_CAPTURE_BY_INDEX),
+ DECLARE_STATIC_BACKEND(CAP_FIREWIRE, "FIREWIRE", MODE_CAPTURE_BY_INDEX, 0, create_DC1394_capture, 0),
#endif
// GigE
#ifdef HAVE_PVAPI
- DECLARE_BACKEND(CAP_PVAPI, "PVAPI", MODE_CAPTURE_BY_INDEX),
+ DECLARE_STATIC_BACKEND(CAP_PVAPI, "PVAPI", MODE_CAPTURE_BY_INDEX, 0, create_PvAPI_capture, 0),
#endif
#ifdef HAVE_XIMEA
- DECLARE_BACKEND(CAP_XIAPI, "XIMEA", MODE_CAPTURE_ALL),
+ DECLARE_STATIC_BACKEND(CAP_XIAPI, "XIMEA", MODE_CAPTURE_ALL, create_XIMEA_capture_file, create_XIMEA_capture_cam, 0),
#endif
#ifdef HAVE_ARAVIS_API
- DECLARE_BACKEND(CAP_ARAVIS, "ARAVIS", MODE_CAPTURE_BY_INDEX),
+ DECLARE_STATIC_BACKEND(CAP_ARAVIS, "ARAVIS", MODE_CAPTURE_BY_INDEX, 0, create_Aravis_capture, 0),
#endif
#ifdef HAVE_GPHOTO2
- DECLARE_BACKEND(CAP_GPHOTO2, "GPHOTO2", MODE_CAPTURE_ALL),
+ DECLARE_STATIC_BACKEND(CAP_GPHOTO2, "GPHOTO2", MODE_CAPTURE_ALL, createGPhoto2Capture, createGPhoto2Capture, 0),
#endif
#ifdef HAVE_XINE
- DECLARE_BACKEND(CAP_XINE, "XINE", MODE_CAPTURE_BY_FILENAME),
+ DECLARE_STATIC_BACKEND(CAP_XINE, "XINE", MODE_CAPTURE_BY_FILENAME, createXINECapture, 0, 0),
#endif
-
- // dropped backends: MIL, TYZX, Android
+#ifdef HAVE_ANDROID_MEDIANDK
+ DECLARE_STATIC_BACKEND(CAP_ANDROID, "ANDROID_MEDIANDK", MODE_CAPTURE_BY_FILENAME, createAndroidCapture_file, 0, 0),
+#endif
+ // dropped backends: MIL, TYZX
};
bool sortByPriority(const VideoBackendInfo &lhs, const VideoBackendInfo &rhs)
return result;
}
-} // namespace registry
-
-#define TRY_OPEN(backend_func) \
-{ \
- try { \
- if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
- CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
- icap = backend_func; \
- if (param_VIDEOIO_DEBUG ||param_VIDEOCAPTURE_DEBUG) \
- CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p isOpened=%d ...\n", \
- #backend_func, icap.empty() ? NULL : icap.get(), icap.empty() ? -1: icap->isOpened())); \
- } catch(const cv::Exception& e) { \
- CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
- } catch (const std::exception& e) { \
- CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
- } catch(...) { \
- CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
- } \
- break; \
-}
-
-#define TRY_OPEN_LEGACY(backend_func) \
-{ \
- try { \
- if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
- CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
- capture = backend_func; \
- if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
- CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p ...\n", #backend_func, capture)); \
- } catch(const cv::Exception& e) { \
- CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
- } catch (const std::exception& e) { \
- CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
- } catch(...) { \
- CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
- } \
- break; \
-}
-
-
-void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, int index)
+bool hasBackend(VideoCaptureAPIs api)
{
- CV_UNUSED(capture); CV_UNUSED(icap);
- switch (api)
- {
- default:
- CV_LOG_WARNING(NULL, "VideoCapture(index=" << index << ") was built without support of requested backendID=" << (int)api);
- break;
-#ifdef HAVE_GSTREAMER
- case CAP_GSTREAMER:
- TRY_OPEN(createGStreamerCapture(index));
- break;
-#endif
-#ifdef HAVE_MSMF
- case CAP_MSMF:
- TRY_OPEN(cvCreateCapture_MSMF(index));
- break;
-#endif
-#ifdef HAVE_DSHOW
- case CAP_DSHOW:
- TRY_OPEN(makePtr<VideoCapture_DShow>(index));
- break;
-#endif
-#ifdef HAVE_LIBREALSENSE
- case CAP_REALSENSE:
- TRY_OPEN(makePtr<VideoCapture_LibRealsense>(index));
- break;
-#endif
-#ifdef WINRT_VIDEO
- case CAP_WINRT:
- TRY_OPEN(makePtr<cv::VideoCapture_WinRT>(index));
- break;
-#endif
-#ifdef HAVE_GPHOTO2
- case CAP_GPHOTO2:
- TRY_OPEN(createGPhoto2Capture(index));
- break;
-#endif
-#if defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO
- case CAP_V4L:
- TRY_OPEN_LEGACY(cvCreateCameraCapture_V4L(index))
- break;
-#endif
- case CAP_FIREWIRE:
-#ifdef HAVE_DC1394_2
- TRY_OPEN_LEGACY(cvCreateCameraCapture_DC1394_2(index))
-#endif
- break; // CAP_FIREWIRE
-#ifdef HAVE_MIL
- case CAP_MIL:
- TRY_OPEN_LEGACY(cvCreateCameraCapture_MIL(index))
- break;
-#endif
-#ifdef HAVE_PVAPI
- case CAP_PVAPI:
- TRY_OPEN_LEGACY(cvCreateCameraCapture_PvAPI(index))
- break;
-#endif
-#ifdef HAVE_OPENNI2
- case CAP_OPENNI2:
- TRY_OPEN_LEGACY(cvCreateCameraCapture_OpenNI2(index))
- break;
-#endif
-#ifdef HAVE_XIMEA
- case CAP_XIAPI:
- TRY_OPEN_LEGACY(cvCreateCameraCapture_XIMEA(index))
- break;
-#endif
-
-#ifdef HAVE_AVFOUNDATION
- case CAP_AVFOUNDATION:
- TRY_OPEN_LEGACY(cvCreateCameraCapture_AVFoundation(index))
- break;
-#endif
-
-#ifdef HAVE_ARAVIS_API
- case CAP_ARAVIS:
- TRY_OPEN_LEGACY(cvCreateCameraCapture_Aravis(index))
- break;
-#endif
- } // switch (api)
-}
-
-void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, const cv::String& filename)
-{
- CV_UNUSED(capture);
- switch (api)
- {
- default:
- CV_LOG_WARNING(NULL, "VideoCapture(filename=" << filename << ") was built without support of requested backendID=" << (int)api);
- break;
-#if defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO
- case CAP_V4L:
- TRY_OPEN_LEGACY(cvCreateCameraCapture_V4L(filename.c_str()))
- break;
-#endif
-
-#ifdef HAVE_AVFOUNDATION
- case CAP_AVFOUNDATION:
- TRY_OPEN_LEGACY(cvCreateFileCapture_AVFoundation(filename.c_str()))
- break;
-#endif
-
-#ifdef HAVE_OPENNI2
- case CAP_OPENNI2:
- TRY_OPEN_LEGACY(cvCreateFileCapture_OpenNI2(filename.c_str()))
- break;
-#endif
-#ifdef HAVE_XIMEA
- case CAP_XIAPI:
- TRY_OPEN_LEGACY(cvCreateCameraCapture_XIMEA(filename.c_str()))
- break;
-#endif
- case CAP_IMAGES:
- TRY_OPEN(createFileCapture_Images(filename))
- break;
-#ifdef HAVE_FFMPEG
- case CAP_FFMPEG:
- TRY_OPEN(cvCreateFileCapture_FFMPEG_proxy(filename))
- break;
-#endif
-#ifdef HAVE_GSTREAMER
- case CAP_GSTREAMER:
- TRY_OPEN(createGStreamerCapture(filename))
- break;
-#endif
-#ifdef HAVE_XINE
- case CAP_XINE:
- TRY_OPEN(createXINECapture(filename.c_str()))
- break;
-#endif
-#ifdef HAVE_MSMF
- case CAP_MSMF:
- TRY_OPEN(cvCreateCapture_MSMF(filename))
- break;
-#endif
-#ifdef HAVE_GPHOTO2
- case CAP_GPHOTO2:
- TRY_OPEN(createGPhoto2Capture(filename))
- break;
-#endif
-#ifdef HAVE_MFX
- case CAP_INTEL_MFX:
- TRY_OPEN(makePtr<VideoCapture_IntelMFX>(filename))
- break;
-#endif
- case CAP_OPENCV_MJPEG:
- TRY_OPEN(createMotionJpegCapture(filename))
- break;
- } // switch
-}
-
-
-void VideoWriter_create(CvVideoWriter*& writer, Ptr<IVideoWriter>& iwriter, VideoCaptureAPIs api,
- const String& filename, int fourcc, double fps, const Size& frameSize, bool isColor)
-{
-#define CREATE_WRITER(backend_func) \
-{ \
- try { \
- if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
- CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
- iwriter = backend_func; \
- if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
- CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p isOpened=%d...\n", #backend_func, iwriter.empty() ? NULL : iwriter.get(), iwriter.empty() ? iwriter->isOpened() : -1)); \
- } catch(const cv::Exception& e) { \
- CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
- } catch (const std::exception& e) { \
- CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
- } catch(...) { \
- CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
- } \
- break; \
-}
-
-#define CREATE_WRITER_LEGACY(backend_func) \
-{ \
- try { \
- if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
- CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
- writer = backend_func; \
- if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
- CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p...\n", #backend_func, writer)); \
- } catch(const cv::Exception& e) { \
- CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
- } catch (const std::exception& e) { \
- CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
- } catch(...) { \
- CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
- } \
- break; \
-}
-
- switch (api)
+ std::vector<VideoBackendInfo> backends = VideoBackendRegistry::getInstance().getEnabledBackends();
+ for (size_t i = 0; i < backends.size(); i++)
{
- default:
- CV_LOG_ERROR(NULL, "Unknown VideoWriter backend (check getBuildInformation()): " << (int)api);
- break;
-#ifdef HAVE_FFMPEG
- case CAP_FFMPEG:
- CREATE_WRITER(cvCreateVideoWriter_FFMPEG_proxy(filename, fourcc, fps, frameSize, isColor));
- break;
-#endif
-#ifdef HAVE_MSMF
- case CAP_MSMF:
- CREATE_WRITER(cvCreateVideoWriter_MSMF(filename, fourcc, fps, frameSize, isColor));
- break;
-#endif
-#ifdef HAVE_MFX
- case CAP_INTEL_MFX:
- CREATE_WRITER(VideoWriter_IntelMFX::create(filename, fourcc, fps, frameSize, isColor));
- break;
-#endif
-#ifdef HAVE_AVFOUNDATION
- case CAP_AVFOUNDATION:
- CREATE_WRITER_LEGACY(cvCreateVideoWriter_AVFoundation(filename.c_str(), fourcc, fps, cvSize(frameSize), isColor))
- break;
-#endif
-#ifdef HAVE_GSTREAMER
-case CAP_GSTREAMER:
- CREATE_WRITER_LEGACY(cvCreateVideoWriter_GStreamer (filename.c_str(), fourcc, fps, cvSize(frameSize), isColor))
- break;
-#endif
- case CAP_OPENCV_MJPEG:
- CREATE_WRITER(createMotionJpegWriter(filename, fourcc, fps, frameSize, isColor));
- break;
- case CAP_IMAGES:
- if(!fourcc || !fps)
+ const VideoBackendInfo& info = backends[i];
+ if (api == info.id)
{
- CREATE_WRITER_LEGACY(cvCreateVideoWriter_Images(filename.c_str()));
+ CV_Assert(!info.backendFactory.empty());
+ return !info.backendFactory->getBackend().empty();
}
- break;
- } // switch(api)
+ }
+ return false;
}
+} // namespace registry
} // namespace
#ifndef __OPENCV_VIDEOIO_VIDEOIO_REGISTRY_HPP__
#define __OPENCV_VIDEOIO_VIDEOIO_REGISTRY_HPP__
+#include "backend.hpp"
+
namespace cv
{
// 0 - disabled (OPENCV_VIDEOIO_PRIORITY_<name> = 0)
// >10000 - prioritized list (OPENCV_VIDEOIO_PRIORITY_LIST)
const char* name;
+ Ptr<IBackendFactory> backendFactory;
};
namespace videoio_registry {
} // namespace
-void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, int index);
-void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, const cv::String& filename);
-void VideoWriter_create(CvVideoWriter*& writer, Ptr<IVideoWriter>& iwriter, VideoCaptureAPIs api,
- const String& filename, int fourcc, double fps, const Size& frameSize, bool isColor);
-
} // namespace
#endif // __OPENCV_VIDEOIO_VIDEOIO_REGISTRY_HPP__
// Note: all tests here are DISABLED by default due specific requirements.
// Don't use #if 0 - these tests should be tested for compilation at least.
//
-// Usage: opencv_test_videoio --gtest_also_run_disabled_tests --gtest_filter=*VideoIO_Camera*<tested case>*
+// Usage: opencv_test_videoio --gtest_also_run_disabled_tests --gtest_filter=*videoio_camera*<tested case>*
#include "test_precomp.hpp"
if (lastFrame) *lastFrame = frame.clone();
}
-TEST(DISABLED_VideoIO_Camera, basic)
+TEST(DISABLED_videoio_camera, basic)
{
VideoCapture capture(0);
ASSERT_TRUE(capture.isOpened());
capture.release();
}
-TEST(DISABLED_VideoIO_Camera, validate_V4L2_MJPEG)
+TEST(DISABLED_videoio_camera, v4l_read_mjpg)
{
VideoCapture capture(CAP_V4L2);
ASSERT_TRUE(capture.isOpened());
}
//Following test if for capture device using PhysConn_Video_SerialDigital as crossbar input pin
-TEST(DISABLED_VideoIO_Camera, dshow_avermedia_capture)
+TEST(DISABLED_videoio_camera, channel6)
{
VideoCapture capture(0);
ASSERT_TRUE(capture.isOpened());
capture.release();
}
-TEST(DISABLED_VideoIO_Camera, validate_V4L2_FrameSize)
+TEST(DISABLED_videoio_camera, v4l_read_framesize)
{
VideoCapture capture(CAP_V4L2);
ASSERT_TRUE(capture.isOpened());
using namespace cv;
-namespace opencv_test
-{
+namespace opencv_test { namespace {
-TEST(videoio_avi, good_MJPG) {
+TEST(videoio_builtin, basic_avi)
+{
String filename = BunnyParameters::getFilename(".mjpg.avi");
AVIReadContainer in;
in.initStream(filename);
EXPECT_EQ(in.getFps(), static_cast<unsigned>(BunnyParameters::getFps()));
}
-TEST(videoio_avi, bad_MJPG) {
+TEST(videoio_builtin, invalid_avi)
+{
String filename = BunnyParameters::getFilename(".avi");
AVIReadContainer in;
in.initStream(filename);
EXPECT_EQ(frames.size(), static_cast<unsigned>(0));
}
-TEST(videoio_avi, basic)
+TEST(videoio_builtin, read_write_avi)
{
const String filename = cv::tempfile("test.avi");
const double fps = 100;
remove(filename.c_str());
}
-}
+}} // opencv_test::<anonymous>::
--- /dev/null
+// 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"
+
+using namespace std;
+
+namespace opencv_test { namespace {
+
+const int FRAME_COUNT = 120;
+
+inline void generateFrame(int i, Mat & frame)
+{
+ ::generateFrame(i, FRAME_COUNT, frame);
+}
+
+TEST(videoio_dynamic, basic_write)
+{
+ const Size FRAME_SIZE(640, 480);
+ const double FPS = 100;
+ const String filename = cv::tempfile(".avi");
+ const int fourcc = VideoWriter::fourcc('M', 'J', 'P', 'G');
+
+ bool fileExists = false;
+ {
+ vector<VideoCaptureAPIs> backends = videoio_registry::getWriterBackends();
+ for (VideoCaptureAPIs be : backends)
+ {
+ VideoWriter writer;
+ writer.open(filename, be, fourcc, FPS, FRAME_SIZE, true);
+ if (writer.isOpened())
+ {
+ Mat frame(FRAME_SIZE, CV_8UC3);
+ for (int j = 0; j < FRAME_COUNT; ++j)
+ {
+ generateFrame(j, frame);
+ writer << frame;
+ }
+ writer.release();
+ fileExists = true;
+ }
+ EXPECT_FALSE(writer.isOpened());
+ }
+ }
+ if (!fileExists)
+ {
+ cout << "None of backends has been able to write video file - SKIP reading part" << endl;
+ return;
+ }
+ {
+ vector<VideoCaptureAPIs> backends = videoio_registry::getStreamBackends();
+ for (VideoCaptureAPIs be : backends)
+ {
+ VideoCapture cap;
+ cap.open(filename, be);
+ if(cap.isOpened())
+ {
+ int count = 0;
+ while (true)
+ {
+ Mat frame;
+ if (cap.grab())
+ {
+ if (cap.retrieve(frame))
+ {
+ ++count;
+ continue;
+ }
+ }
+ break;
+ }
+ EXPECT_EQ(count, FRAME_COUNT);
+ cap.release();
+ }
+ EXPECT_FALSE(cap.isOpened());
+ }
+ }
+ remove(filename.c_str());
+}
+
+TEST(videoio_dynamic, write_invalid)
+{
+ vector<VideoCaptureAPIs> backends = videoio_registry::getWriterBackends();
+ for (VideoCaptureAPIs be : backends)
+ {
+ SCOPED_TRACE(be);
+ const string filename = cv::tempfile(".mkv");
+ VideoWriter writer;
+ bool res = true;
+
+ // Bad FourCC
+ EXPECT_NO_THROW(res = writer.open(filename, be, VideoWriter::fourcc('A', 'B', 'C', 'D'), 1, Size(640, 480), true));
+ EXPECT_FALSE(res);
+ EXPECT_FALSE(writer.isOpened());
+
+ // Empty filename
+ EXPECT_NO_THROW(res = writer.open(String(), be, VideoWriter::fourcc('H', '2', '6', '4'), 1, Size(640, 480), true));
+ EXPECT_FALSE(res);
+ EXPECT_FALSE(writer.isOpened());
+ EXPECT_NO_THROW(res = writer.open(String(), be, VideoWriter::fourcc('M', 'J', 'P', 'G'), 1, Size(640, 480), true));
+ EXPECT_FALSE(res);
+ EXPECT_FALSE(writer.isOpened());
+
+ // zero FPS
+ EXPECT_NO_THROW(res = writer.open(filename, be, VideoWriter::fourcc('H', '2', '6', '4'), 0, Size(640, 480), true));
+ EXPECT_FALSE(res);
+ EXPECT_FALSE(writer.isOpened());
+
+ // cleanup
+ EXPECT_NO_THROW(writer.release());
+ remove(filename.c_str());
+ }
+
+ // Generic
+ {
+ VideoWriter writer;
+ bool res = true;
+ EXPECT_NO_THROW(res = writer.open(std::string(), VideoWriter::fourcc('H', '2', '6', '4'), 1, Size(640, 480)));
+ EXPECT_FALSE(res);
+ EXPECT_FALSE(writer.isOpened());
+ EXPECT_NO_THROW(res = writer.open(std::string(), VideoWriter::fourcc('M', 'J', 'P', 'G'), 1, Size(640, 480)));
+ EXPECT_FALSE(res);
+ EXPECT_FALSE(writer.isOpened());
+ }
+}
+
+
+}} // opencv_test::<anonymous>::
-/*M///////////////////////////////////////////////////////////////////////////////////////
-//
-// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
-//
-// By downloading, copying, installing or using the software you agree to this license.
-// If you do not agree to this license, do not download, install,
-// copy or use the software.
-//
-//
-// License Agreement
-// For Open Source Computer Vision Library
-//
-// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
-// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
-// Third party copyrights are property of their respective owners.
-//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-// * Redistribution's of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// * Redistribution's in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// * The name of the copyright holders may not be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// This software is provided by the copyright holders and contributors "as is" and
-// any express or implied warranties, including, but not limited to, the implied
-// warranties of merchantability and fitness for a particular purpose are disclaimed.
-// In no event shall the Intel Corporation or contributors be liable for any direct,
-// indirect, incidental, special, exemplary, or consequential damages
-// (including, but not limited to, procurement of substitute goods or services;
-// loss of use, data, or profits; or business interruption) however caused
-// and on any theory of liability, whether in contract, strict liability,
-// or tort (including negligence or otherwise) arising in any way out of
-// the use of this software, even if advised of the possibility of such damage.
-//
-//M*/
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
#include "test_precomp.hpp"
-namespace opencv_test { namespace {
-
-#ifdef HAVE_FFMPEG
-
using namespace std;
-static const char* AVI_EXT = ".avi";
-static const char* MP4_EXT = ".mp4";
+namespace opencv_test { namespace {
-class CV_FFmpegWriteBigVideoTest : public cvtest::BaseTest
+static inline long long getFileSize(const string &filename)
{
- struct TestFormatEntry {
- int tag;
- const char* ext;
- bool required;
- };
-
- static long int getFileSize(string filename)
- {
- FILE *p_file = NULL;
- p_file = fopen(filename.c_str(), "rb");
- if (p_file == NULL)
- return -1;
- fseek(p_file, 0, SEEK_END);
- long int size = ftell(p_file);
- fclose(p_file);
- return size;
- }
-public:
- void run(int)
- {
- const int img_r = 4096;
- const int img_c = 4096;
- const double fps0 = 15;
- const double time_sec = 1;
-
- const TestFormatEntry entries[] = {
- {0, AVI_EXT, true},
- //{VideoWriter::fourcc('D', 'I', 'V', '3'), AVI_EXT, true},
- //{VideoWriter::fourcc('D', 'I', 'V', 'X'), AVI_EXT, true},
- {VideoWriter::fourcc('D', 'X', '5', '0'), AVI_EXT, true},
- {VideoWriter::fourcc('F', 'L', 'V', '1'), AVI_EXT, true},
- {VideoWriter::fourcc('H', '2', '6', '1'), AVI_EXT, true},
- {VideoWriter::fourcc('H', '2', '6', '3'), AVI_EXT, true},
- {VideoWriter::fourcc('I', '4', '2', '0'), AVI_EXT, true},
- //{VideoWriter::fourcc('j', 'p', 'e', 'g'), AVI_EXT, true},
- {VideoWriter::fourcc('M', 'J', 'P', 'G'), AVI_EXT, true},
- {VideoWriter::fourcc('m', 'p', '4', 'v'), AVI_EXT, true},
- {VideoWriter::fourcc('M', 'P', 'E', 'G'), AVI_EXT, true},
- //{VideoWriter::fourcc('W', 'M', 'V', '1'), AVI_EXT, true},
- //{VideoWriter::fourcc('W', 'M', 'V', '2'), AVI_EXT, true},
- {VideoWriter::fourcc('X', 'V', 'I', 'D'), AVI_EXT, true},
- //{VideoWriter::fourcc('Y', 'U', 'Y', '2'), AVI_EXT, true},
- {VideoWriter::fourcc('H', '2', '6', '4'), MP4_EXT, false}
- };
-
- const size_t n = sizeof(entries)/sizeof(entries[0]);
-
- for (size_t j = 0; j < n; ++j)
- {
- int tag = entries[j].tag;
- const char* ext = entries[j].ext;
- string s = cv::format("%08x%s", tag, ext);
-
- const string filename = tempfile(s.c_str());
-
- try
- {
- double fps = fps0;
- Size frame_s = Size(img_c, img_r);
+ ifstream f(filename, ios_base::in | ios_base::binary);
+ f.seekg(0, ios_base::end);
+ return f.tellg();
+}
- if( tag == VideoWriter::fourcc('H', '2', '6', '1') )
- frame_s = Size(352, 288);
- else if( tag == VideoWriter::fourcc('H', '2', '6', '3') )
- frame_s = Size(704, 576);
- else if( tag == VideoWriter::fourcc('H', '2', '6', '4') )
- // OpenH264 1.5.0 has resolution limitations, so lets use DCI 4K resolution
- frame_s = Size(4096, 2160);
- /*else if( tag == CV_FOURCC('M', 'J', 'P', 'G') ||
- tag == CV_FOURCC('j', 'p', 'e', 'g') )
- frame_s = Size(1920, 1080);*/
+typedef tuple<string, string, Size> FourCC_Ext_Size;
+typedef testing::TestWithParam< FourCC_Ext_Size > videoio_ffmpeg;
- if( tag == VideoWriter::fourcc('M', 'P', 'E', 'G') )
- {
- frame_s = Size(720, 576);
- fps = 25;
- }
+TEST_P(videoio_ffmpeg, write_big)
+{
+ if (!videoio_registry::hasBackend(CAP_FFMPEG))
+ throw SkipTestException("FFmpeg backend was not found");
- VideoWriter writer(filename, CAP_FFMPEG, tag, fps, frame_s);
+ const string fourcc = get<0>(GetParam());
+ const string ext = get<1>(GetParam());
+ const Size sz = get<2>(GetParam());
+ const double time_sec = 1;
+ const double fps = 25;
- if (writer.isOpened() == false)
- {
- fprintf(stderr, "\n\nFile name: %s\n", filename.c_str());
- fprintf(stderr, "Codec id: %d Codec tag: %c%c%c%c\n", (int)j,
- tag & 255, (tag >> 8) & 255, (tag >> 16) & 255, (tag >> 24) & 255);
- fprintf(stderr, "Error: cannot create video file.\n");
- if (entries[j].required)
- ts->set_failed_test_info(ts->FAIL_INVALID_OUTPUT);
- }
- else
- {
- Mat img(frame_s, CV_8UC3, Scalar::all(0));
- const int coeff = cvRound(min(frame_s.width, frame_s.height)/(fps0 * time_sec));
+ ostringstream buf;
+ buf << "write_big_" << fourcc << "." << ext;
+ const string filename = tempfile(buf.str().c_str());
- for (int i = 0 ; i < static_cast<int>(fps * time_sec); i++ )
- {
- //circle(img, Point2i(img_c / 2, img_r / 2), min(img_r, img_c) / 2 * (i + 1), Scalar(255, 0, 0, 0), 2);
- rectangle(img, Point2i(coeff * i, coeff * i), Point2i(coeff * (i + 1), coeff * (i + 1)),
- Scalar::all(255 * (1.0 - static_cast<double>(i) / (fps * time_sec * 2) )), -1);
- writer << img;
- }
-
- writer.release();
- long int sz = getFileSize(filename);
- if (sz < 0)
- {
- fprintf(stderr, "ERROR: File name: %s was not created\n", filename.c_str());
- if (entries[j].required)
- ts->set_failed_test_info(ts->FAIL_INVALID_OUTPUT);
- }
- else
- {
- printf("Case: '%s' (frame size %dx%d fps=%g). FileSize=%lld bytes\n",
- s.c_str(), frame_s.width, frame_s.height, fps, (long long int)sz);
- if (sz < 8192)
- {
- fprintf(stderr, "ERROR: File name: %s is very small (data write problems?)\n", filename.c_str());
- if (entries[j].required)
- ts->set_failed_test_info(ts->FAIL_INVALID_OUTPUT);
- }
- remove(filename.c_str());
- }
- }
- }
- catch(...)
- {
- ts->set_failed_test_info(ts->FAIL_INVALID_OUTPUT);
- }
- ts->set_failed_test_info(cvtest::TS::OK);
- }
+ VideoWriter writer(filename, CAP_FFMPEG, fourccFromString(fourcc), fps, sz);
+ if (ext == "mp4" && fourcc == "H264" && !writer.isOpened())
+ {
+ throw cvtest::SkipTestException("H264/mp4 codec is not supported - SKIP");
}
-};
-
-TEST(Videoio_Video, ffmpeg_writebig) { CV_FFmpegWriteBigVideoTest test; test.safe_run(); }
-
-class CV_FFmpegReadImageTest : public cvtest::BaseTest
-{
-public:
- void run(int)
+ ASSERT_TRUE(writer.isOpened());
+ Mat img(sz, CV_8UC3, Scalar::all(0));
+ const int coeff = cvRound(min(sz.width, sz.height)/(fps * time_sec));
+ for (int i = 0 ; i < static_cast<int>(fps * time_sec); i++ )
{
- try
- {
- string filename = ts->get_data_path() + "readwrite/ordinary.bmp";
- VideoCapture cap(filename, CAP_FFMPEG);
- Mat img0 = imread(filename, 1);
- Mat img, img_next;
- cap >> img;
- cap >> img_next;
-
- CV_Assert( !img0.empty() && !img.empty() && img_next.empty() );
-
- double diff = cvtest::norm(img0, img, CV_C);
- CV_Assert( diff == 0 );
- }
- catch(...)
- {
- ts->set_failed_test_info(ts->FAIL_INVALID_OUTPUT);
- }
- ts->set_failed_test_info(cvtest::TS::OK);
+ rectangle(img,
+ Point2i(coeff * i, coeff * i),
+ Point2i(coeff * (i + 1), coeff * (i + 1)),
+ Scalar::all(255 * (1.0 - static_cast<double>(i) / (fps * time_sec * 2))),
+ -1);
+ writer << img;
}
-};
-
-TEST(Videoio_Video, ffmpeg_image) { CV_FFmpegReadImageTest test; test.safe_run(); }
-
-#endif
-
-#if defined(HAVE_FFMPEG)
+ writer.release();
+ EXPECT_GT(getFileSize(filename), 8192);
+ remove(filename.c_str());
+}
-//////////////////////////////// Parallel VideoWriters and VideoCaptures ////////////////////////////////////
+static const Size bigSize(4096, 4096);
-class CreateVideoWriterInvoker :
- public ParallelLoopBody
+const FourCC_Ext_Size entries[] =
{
-public:
- const static Size FrameSize;
- static std::string TmpDirectory;
-
- CreateVideoWriterInvoker(std::vector<VideoWriter*>& _writers, std::vector<std::string>& _files) :
- writers(_writers), files(_files)
- {
- }
+ make_tuple("", "avi", bigSize),
+ make_tuple("DX50", "avi", bigSize),
+ make_tuple("FLV1", "avi", bigSize),
+ make_tuple("H261", "avi", Size(352, 288)),
+ make_tuple("H263", "avi", Size(704, 576)),
+ make_tuple("I420", "avi", bigSize),
+ make_tuple("MJPG", "avi", bigSize),
+ make_tuple("mp4v", "avi", bigSize),
+ make_tuple("MPEG", "avi", Size(720, 576)),
+ make_tuple("XVID", "avi", bigSize),
+ make_tuple("H264", "mp4", Size(4096, 2160))
+};
- virtual void operator() (const Range& range) const CV_OVERRIDE
- {
- for (int i = range.start; i != range.end; ++i)
- {
- std::ostringstream stream;
- stream << i << ".avi";
- std::string fileName = tempfile(stream.str().c_str());
+INSTANTIATE_TEST_CASE_P(videoio, videoio_ffmpeg, testing::ValuesIn(entries));
- files[i] = fileName;
- writers[i] = new VideoWriter(fileName, CAP_FFMPEG, VideoWriter::fourcc('X','V','I','D'), 25.0f, FrameSize);
+//==========================================================================
- CV_Assert(writers[i]->isOpened());
- }
- }
+TEST(videoio_ffmpeg, image)
+{
+ if (!videoio_registry::hasBackend(CAP_FFMPEG))
+ throw SkipTestException("FFmpeg backend was not found");
+
+ const string filename = findDataFile("readwrite/ordinary.bmp");
+ Mat image = imread(filename, IMREAD_COLOR);
+ ASSERT_FALSE(image.empty());
+ VideoCapture cap(filename, CAP_FFMPEG);
+ ASSERT_TRUE(cap.isOpened());
+ Mat frame1, frame2;
+ cap >> frame1 >> frame2;
+ ASSERT_FALSE(frame1.empty());
+ ASSERT_TRUE(frame2.empty());
+ ASSERT_EQ(0, cvtest::norm(image, frame1, NORM_INF));
+}
-private:
- std::vector<VideoWriter*>& writers;
- std::vector<std::string>& files;
-};
+//==========================================================================
-std::string CreateVideoWriterInvoker::TmpDirectory;
-const Size CreateVideoWriterInvoker::FrameSize(1020, 900);
-class WriteVideo_Invoker :
- public ParallelLoopBody
+static void generateFrame(Mat &frame, unsigned int i, const Point ¢er, const Scalar &color)
{
-public:
- enum { FrameCount = 300 };
-
- static const Scalar ObjectColor;
- static const Point Center;
-
- WriteVideo_Invoker(const std::vector<VideoWriter*>& _writers) :
- ParallelLoopBody(), writers(&_writers)
- {
- }
+ frame = Scalar::all(i % 255);
+ stringstream buf(ios::out);
+ buf << "frame #" << i;
+ putText(frame, buf.str(), Point(50, center.y), FONT_HERSHEY_SIMPLEX, 5.0, color, 5, CV_AA);
+ circle(frame, center, i + 2, color, 2, CV_AA);
+}
- static void GenerateFrame(Mat& frame, unsigned int i)
+TEST(videoio_ffmpeg, parallel)
+{
+ if (!videoio_registry::hasBackend(CAP_FFMPEG))
+ throw SkipTestException("FFmpeg backend was not found");
+
+ const int NUM = 4;
+ const int GRAN = 4;
+ const Range R(0, NUM);
+ const Size sz(1020, 900);
+ const int frameNum = 300;
+ const Scalar color(Scalar::all(0));
+ const Point center(sz.height / 2, sz.width / 2);
+
+ // Generate filenames
+ vector<string> files;
+ for (int i = 0; i < NUM; ++i)
{
- frame = Scalar::all(i % 255);
-
- std::string text = to_string(i);
- putText(frame, text, Point(50, Center.y), FONT_HERSHEY_SIMPLEX, 5.0, ObjectColor, 5, CV_AA);
- circle(frame, Center, i + 2, ObjectColor, 2, CV_AA);
+ ostringstream stream;
+ stream << i << ".avi";
+ files.push_back(tempfile(stream.str().c_str()));
}
-
- virtual void operator() (const Range& range) const CV_OVERRIDE
+ // Write videos
{
- for (int j = range.start; j < range.end; ++j)
+ vector< Ptr<VideoWriter> > writers(NUM);
+ auto makeWriters = [&](const Range &r)
{
- VideoWriter* writer = writers->operator[](j);
- CV_Assert(writer != NULL);
- CV_Assert(writer->isOpened());
-
- Mat frame(CreateVideoWriterInvoker::FrameSize, CV_8UC3);
- for (unsigned int i = 0; i < FrameCount; ++i)
+ for (int i = r.start; i != r.end; ++i)
+ writers[i] = makePtr<VideoWriter>(files[i],
+ CAP_FFMPEG,
+ VideoWriter::fourcc('X','V','I','D'),
+ 25.0f,
+ sz);
+ };
+ parallel_for_(R, makeWriters, GRAN);
+ for(int i = 0; i < NUM; ++i)
+ {
+ ASSERT_TRUE(writers[i]);
+ ASSERT_TRUE(writers[i]->isOpened());
+ }
+ auto writeFrames = [&](const Range &r)
+ {
+ for (int j = r.start; j < r.end; ++j)
{
- GenerateFrame(frame, i);
- writer->operator<< (frame);
+ Mat frame(sz, CV_8UC3);
+ for (int i = 0; i < frameNum; ++i)
+ {
+ generateFrame(frame, i, center, color);
+ writers[j]->write(frame);
+ }
}
- }
- }
-
-protected:
- static std::string to_string(unsigned int i)
- {
- std::stringstream stream(std::ios::out);
- stream << "frame #" << i;
- return stream.str();
+ };
+ parallel_for_(R, writeFrames, GRAN);
}
-
-private:
- const std::vector<VideoWriter*>* writers;
-};
-
-const Scalar WriteVideo_Invoker::ObjectColor(Scalar::all(0));
-const Point WriteVideo_Invoker::Center(CreateVideoWriterInvoker::FrameSize.height / 2,
- CreateVideoWriterInvoker::FrameSize.width / 2);
-
-class CreateVideoCaptureInvoker :
- public ParallelLoopBody
-{
-public:
- CreateVideoCaptureInvoker(std::vector<VideoCapture*>& _readers, const std::vector<std::string>& _files) :
- ParallelLoopBody(), readers(&_readers), files(&_files)
+ // Read videos
{
- }
-
- virtual void operator() (const Range& range) const CV_OVERRIDE
- {
- for (int i = range.start; i != range.end; ++i)
+ vector< Ptr<VideoCapture> > readers(NUM);
+ auto makeCaptures = [&](const Range &r)
+ {
+ for (int i = r.start; i != r.end; ++i)
+ readers[i] = makePtr<VideoCapture>(files[i], CAP_FFMPEG);
+ };
+ parallel_for_(R, makeCaptures, GRAN);
+ for(int i = 0; i < NUM; ++i)
{
- readers->operator[](i) = new VideoCapture(files->operator[](i), CAP_FFMPEG);
- CV_Assert(readers->operator[](i)->isOpened());
+ ASSERT_TRUE(readers[i]);
+ ASSERT_TRUE(readers[i]->isOpened());
}
- }
-private:
- std::vector<VideoCapture*>* readers;
- const std::vector<std::string>* files;
-};
-
-class ReadImageAndTest :
- public ParallelLoopBody
-{
-public:
- ReadImageAndTest(const std::vector<VideoCapture*>& _readers, cvtest::TS* _ts) :
- ParallelLoopBody(), readers(&_readers), ts(_ts)
- {
- }
-
- virtual void operator() (const Range& range) const CV_OVERRIDE
- {
- for (int j = range.start; j < range.end; ++j)
+ auto readFrames = [&](const Range &r)
{
- VideoCapture* capture = readers->operator[](j);
- CV_Assert(capture != NULL);
- CV_Assert(capture->isOpened());
-
- const static double eps = 23.0;
- unsigned int frameCount = static_cast<unsigned int>(capture->get(CAP_PROP_FRAME_COUNT));
- CV_Assert(frameCount == WriteVideo_Invoker::FrameCount);
- Mat reference(CreateVideoWriterInvoker::FrameSize, CV_8UC3);
-
- for (unsigned int i = 0; i < frameCount && next; ++i)
+ for (int j = r.start; j < r.end; ++j)
{
- SCOPED_TRACE(cv::format("frame=%d/%d", (int)i, (int)frameCount));
-
- Mat actual;
- (*capture) >> actual;
-
- WriteVideo_Invoker::GenerateFrame(reference, i);
-
- EXPECT_EQ(reference.cols, actual.cols);
- EXPECT_EQ(reference.rows, actual.rows);
- EXPECT_EQ(reference.depth(), actual.depth());
- EXPECT_EQ(reference.channels(), actual.channels());
-
- double psnr = cvtest::PSNR(actual, reference);
- if (psnr < eps)
+ Mat reference(sz, CV_8UC3);
+ for (int i = 0; i < frameNum; ++i)
{
- #define SUM cvtest::TS::SUMMARY
- ts->printf(SUM, "\nPSNR: %lf\n", psnr);
- ts->printf(SUM, "Video #: %d\n", range.start);
- ts->printf(SUM, "Frame #: %d\n", i);
- #undef SUM
- ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
- ts->set_gtest_status();
-
- Mat diff;
- absdiff(actual, reference, diff);
-
- EXPECT_EQ(countNonZero(diff.reshape(1) > 1), 0);
-
- next = false;
+ Mat actual;
+ EXPECT_TRUE(readers[j]->read(actual));
+ EXPECT_FALSE(actual.empty());
+ generateFrame(reference, i, center, color);
+ EXPECT_EQ(reference.size(), actual.size());
+ EXPECT_EQ(reference.depth(), actual.depth());
+ EXPECT_EQ(reference.channels(), actual.channels());
+ EXPECT_GE(cvtest::PSNR(actual, reference), 35.0) << "cap" << j << ", frame " << i;
}
}
- }
+ };
+ parallel_for_(R, readFrames, GRAN);
}
-
- static bool next;
-
-private:
- const std::vector<VideoCapture*>* readers;
- cvtest::TS* ts;
-};
-
-bool ReadImageAndTest::next;
-
-TEST(Videoio_Video_parallel_writers_and_readers, accuracy)
-{
- const unsigned int threadsCount = 4;
- cvtest::TS* ts = cvtest::TS::ptr();
-
- // creating VideoWriters
- std::vector<VideoWriter*> writers(threadsCount);
- Range range(0, threadsCount);
- std::vector<std::string> files(threadsCount);
- CreateVideoWriterInvoker invoker1(writers, files);
- parallel_for_(range, invoker1);
-
- // write a video
- parallel_for_(range, WriteVideo_Invoker(writers));
-
- // deleting the writers
- for (std::vector<VideoWriter*>::iterator i = writers.begin(), end = writers.end(); i != end; ++i)
- delete *i;
- writers.clear();
-
- std::vector<VideoCapture*> readers(threadsCount);
- CreateVideoCaptureInvoker invoker2(readers, files);
- parallel_for_(range, invoker2);
-
- ReadImageAndTest::next = true;
-
- parallel_for_(range, ReadImageAndTest(readers, ts));
-
- // deleting tmp video files
- for (std::vector<std::string>::const_iterator i = files.begin(), end = files.end(); i != end; ++i)
+ // Remove files
+ for(int i = 0; i < NUM; ++i)
{
- int code = remove(i->c_str());
- if (code == 1)
- std::cerr << "Couldn't delete " << *i << std::endl;
+ remove(files[i].c_str());
}
-
- // delete the readers
- for (std::vector<VideoCapture *>::iterator i = readers.begin(), end = readers.end(); i != end; ++i)
- delete *i;
}
-#endif
}} // namespace
+++ /dev/null
-/*M///////////////////////////////////////////////////////////////////////////////////////
-//
-// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
-//
-// By downloading, copying, installing or using the software you agree to this license.
-// If you do not agree to this license, do not download, install,
-// copy or use the software.
-//
-//
-// License Agreement
-// For Open Source Computer Vision Library
-//
-// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
-// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
-// Third party copyrights are property of their respective owners.
-//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-// * Redistribution's of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// * Redistribution's in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// * The name of the copyright holders may not be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// This software is provided by the copyright holders and contributors "as is" and
-// any express or implied warranties, including, but not limited to, the implied
-// warranties of merchantability and fitness for a particular purpose are disclaimed.
-// In no event shall the Intel Corporation or contributors be liable for any direct,
-// indirect, incidental, special, exemplary, or consequential damages
-// (including, but not limited to, procurement of substitute goods or services;
-// loss of use, data, or profits; or business interruption) however caused
-// and on any theory of liability, whether in contract, strict liability,
-// or tort (including negligence or otherwise) arising in any way out of
-// the use of this software, even if advised of the possibility of such damage.
-//
-//M*/
-
-#include "test_precomp.hpp"
-
-namespace opencv_test { namespace {
-
-#undef DEFINE_GUID
-#define DEFINE_GUID(n, fourcc, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) fourcc,
-
-unsigned long allfourcc[] = {
-
-DEFINE_GUID(MEDIASUBTYPE_GREY, 0x59455247, 0x0000, 0x0010, 0x80, 0x00,
- 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)
-DEFINE_GUID(MEDIASUBTYPE_Y8, 0x20203859, 0x0000, 0x0010, 0x80, 0x00,
- 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)
-DEFINE_GUID(MEDIASUBTYPE_Y800, 0x30303859, 0x0000, 0x0010, 0x80, 0x00,
- 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)
-
-DEFINE_GUID(CLSID_CaptureGraphBuilder2,0xbf87b6e1,0x8c27,0x11d0,0xb3,0xf0,0x00,0xaa,0x00,0x37,0x61,0xc5)
-DEFINE_GUID(CLSID_FilterGraph,0xe436ebb3,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70)
-DEFINE_GUID(CLSID_NullRenderer,0xc1f400a4,0x3f08,0x11d3,0x9f,0x0b,0x00,0x60,0x08,0x03,0x9e,0x37)
-DEFINE_GUID(CLSID_SampleGrabber,0xc1f400a0,0x3f08,0x11d3,0x9f,0x0b,0x00,0x60,0x08,0x03,0x9e,0x37)
-DEFINE_GUID(CLSID_SystemDeviceEnum,0x62be5d10,0x60eb,0x11d0,0xbd,0x3b,0x00,0xa0,0xc9,0x11,0xce,0x86)
-DEFINE_GUID(CLSID_VideoInputDeviceCategory,0x860bb310,0x5d01,0x11d0,0xbd,0x3b,0x00,0xa0,0xc9,0x11,0xce,0x86)
-DEFINE_GUID(FORMAT_VideoInfo,0x05589f80,0xc356,0x11ce,0xbf,0x01,0x00,0xaa,0x00,0x55,0x59,0x5a)
-DEFINE_GUID(IID_IAMAnalogVideoDecoder,0xc6e13350,0x30ac,0x11d0,0xa1,0x8c,0x00,0xa0,0xc9,0x11,0x89,0x56)
-DEFINE_GUID(IID_IAMCameraControl,0xc6e13370,0x30ac,0x11d0,0xa1,0x8c,0x00,0xa0,0xc9,0x11,0x89,0x56)
-DEFINE_GUID(IID_IAMCrossbar,0xc6e13380,0x30ac,0x11d0,0xa1,0x8c,0x00,0xa0,0xc9,0x11,0x89,0x56)
-DEFINE_GUID(IID_IAMStreamConfig,0xc6e13340,0x30ac,0x11d0,0xa1,0x8c,0x00,0xa0,0xc9,0x11,0x89,0x56)
-DEFINE_GUID(IID_IAMVideoProcAmp,0xc6e13360,0x30ac,0x11d0,0xa1,0x8c,0x00,0xa0,0xc9,0x11,0x89,0x56)
-DEFINE_GUID(IID_IBaseFilter,0x56a86895,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70)
-DEFINE_GUID(IID_ICaptureGraphBuilder2,0x93e5a4e0,0x2d50,0x11d2,0xab,0xfa,0x00,0xa0,0xc9,0xc6,0xe3,0x8d)
-DEFINE_GUID(IID_ICreateDevEnum,0x29840822,0x5b84,0x11d0,0xbd,0x3b,0x00,0xa0,0xc9,0x11,0xce,0x86)
-DEFINE_GUID(IID_IGraphBuilder,0x56a868a9,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70)
-DEFINE_GUID(IID_IMPEG2PIDMap,0xafb6c2a1,0x2c41,0x11d3,0x8a,0x60,0x00,0x00,0xf8,0x1e,0x0e,0x4a)
-DEFINE_GUID(IID_IMediaControl,0x56a868b1,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70)
-DEFINE_GUID(IID_IMediaFilter,0x56a86899,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70)
-DEFINE_GUID(IID_ISampleGrabber,0x6b652fff,0x11fe,0x4fce,0x92,0xad,0x02,0x66,0xb5,0xd7,0xc7,0x8f)
-DEFINE_GUID(LOOK_UPSTREAM_ONLY,0xac798be0,0x98e3,0x11d1,0xb3,0xf1,0x00,0xaa,0x00,0x37,0x61,0xc5)
-DEFINE_GUID(MEDIASUBTYPE_AYUV,0x56555941,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
-DEFINE_GUID(MEDIASUBTYPE_IYUV,0x56555949,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
-DEFINE_GUID(MEDIASUBTYPE_RGB24,0xe436eb7d,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70)
-DEFINE_GUID(MEDIASUBTYPE_RGB32,0xe436eb7e,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70)
-DEFINE_GUID(MEDIASUBTYPE_RGB555,0xe436eb7c,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70)
-DEFINE_GUID(MEDIASUBTYPE_RGB565,0xe436eb7b,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70)
-DEFINE_GUID(MEDIASUBTYPE_I420,0x49343230,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
-DEFINE_GUID(MEDIASUBTYPE_UYVY,0x59565955,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
-DEFINE_GUID(MEDIASUBTYPE_Y211,0x31313259,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
-DEFINE_GUID(MEDIASUBTYPE_Y411,0x31313459,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
-DEFINE_GUID(MEDIASUBTYPE_Y41P,0x50313459,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
-DEFINE_GUID(MEDIASUBTYPE_YUY2,0x32595559,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
-DEFINE_GUID(MEDIASUBTYPE_YUYV,0x56595559,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
-DEFINE_GUID(MEDIASUBTYPE_YV12,0x32315659,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
-DEFINE_GUID(MEDIASUBTYPE_YVU9,0x39555659,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
-DEFINE_GUID(MEDIASUBTYPE_YVYU,0x55595659,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
-DEFINE_GUID(MEDIASUBTYPE_MJPG,0x47504A4D, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71) // MGB
-DEFINE_GUID(MEDIATYPE_Interleaved,0x73766169,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
-DEFINE_GUID(MEDIATYPE_Video,0x73646976,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
-DEFINE_GUID(PIN_CATEGORY_CAPTURE,0xfb6c4281,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba)
-DEFINE_GUID(PIN_CATEGORY_PREVIEW,0xfb6c4282,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba)
-
-0};
-
-
-TEST(Videoio_dshow, fourcc_conversion)
-{
- for(int i = 0; allfourcc[i]; ++i)
- {
- unsigned long fourcc = allfourcc[i];
-
- double paramValue = fourcc;
- int fourccFromParam = (int)(unsigned long)(paramValue);
-
- EXPECT_EQ(fourcc, (unsigned long)(unsigned)fourccFromParam);
- }
-}
-
-}} // namespace
// of this distribution and at http://opencv.org/license.html.
#include "test_precomp.hpp"
-#ifdef HAVE_GSTREAMER
namespace opencv_test
{
typedef tuple< string, Size, Size, int > Param;
-typedef testing::TestWithParam< Param > Videoio_Gstreamer_Test;
+typedef testing::TestWithParam< Param > videoio_gstreamer;
-TEST_P(Videoio_Gstreamer_Test, test_object_structure)
+TEST_P(videoio_gstreamer, read_write)
{
+ if (!videoio_registry::hasBackend(CAP_GSTREAMER))
+ throw SkipTestException("GStreamer backend was not found");
+
string format = get<0>(GetParam());
Size frame_size = get<1>(GetParam());
Size mat_size = get<2>(GetParam());
make_tuple("jpegenc ! image/jpeg" , Size(640, 480), Size(640, 480), COLOR_BGR2RGB)
};
-INSTANTIATE_TEST_CASE_P(videoio, Videoio_Gstreamer_Test, testing::ValuesIn(test_data));
+INSTANTIATE_TEST_CASE_P(videoio, videoio_gstreamer, testing::ValuesIn(test_data));
} // namespace
-
-#endif
namespace opencv_test { namespace {
-TEST(Videoio_MFX, read_invalid)
+TEST(videoio_mfx, read_invalid)
{
VideoCapture cap;
ASSERT_NO_THROW(cap.open("nonexistent-file", CAP_INTEL_MFX));
ASSERT_TRUE(img.empty());
}
-TEST(Videoio_MFX, write_invalid)
+TEST(videoio_mfx, write_invalid)
{
const string filename = cv::tempfile(".264");
VideoWriter writer;
ASSERT_NO_THROW(res = writer.open(String(), CAP_INTEL_MFX, VideoWriter::fourcc('H', '2', '6', '4'), 1, Size(640, 480), true));
EXPECT_FALSE(res);
EXPECT_FALSE(writer.isOpened());
- ASSERT_ANY_THROW(res = writer.open(filename, CAP_INTEL_MFX, VideoWriter::fourcc('H', '2', '6', '4'), 0, Size(640, 480), true));
+ ASSERT_NO_THROW(res = writer.open(filename, CAP_INTEL_MFX, VideoWriter::fourcc('H', '2', '6', '4'), 0, Size(640, 480), true));
EXPECT_FALSE(res);
EXPECT_FALSE(writer.isOpened());
//==================================================================================================
typedef tuple<Size, double, const char *> Size_FPS_Ext;
-typedef testing::TestWithParam< Size_FPS_Ext > Videoio_MFX;
+typedef testing::TestWithParam< Size_FPS_Ext > videoio_mfx;
-TEST_P(Videoio_MFX, read_write_raw)
+TEST_P(videoio_mfx, read_write_raw)
{
const Size FRAME_SIZE = get<0>(GetParam());
const double FPS = get<1>(GetParam());
remove(filename.c_str());
}
-INSTANTIATE_TEST_CASE_P(videoio, Videoio_MFX,
+INSTANTIATE_TEST_CASE_P(videoio, videoio_mfx,
testing::Combine(
testing::Values(Size(640, 480), Size(638, 478), Size(636, 476), Size(1920, 1080)),
testing::Values(1, 30, 100),
protected:
Videoio_Test_Base() {}
virtual ~Videoio_Test_Base() {}
+ virtual void writeVideo() {}
virtual void checkFrameContent(Mat &, int) {}
virtual void checkFrameCount(int &) {}
void checkFrameRead(int idx, VideoCapture & cap)
public:
void doTest()
{
- if (!isBackendAvailable(apiPref, cv::videoio_registry::getStreamBackends()))
+ if (!videoio_registry::hasBackend(apiPref))
throw SkipTestException(cv::String("Backend is not available/disabled: ") + cv::videoio_registry::getBackendName(apiPref));
+ writeVideo();
VideoCapture cap;
ASSERT_NO_THROW(cap.open(video_file, apiPref));
if (!cap.isOpened())
//==================================================================================================
typedef tuple<string, VideoCaptureAPIs> Backend_Type_Params;
-class Videoio_Bunny : public Videoio_Test_Base, public testing::TestWithParam<Backend_Type_Params>
+class videoio_bunny : public Videoio_Test_Base, public testing::TestWithParam<Backend_Type_Params>
{
BunnyParameters bunny_param;
public:
- Videoio_Bunny()
+ videoio_bunny()
{
ext = get<0>(GetParam());
apiPref = get<1>(GetParam());
}
void doFrameCountTest()
{
- if (!isBackendAvailable(apiPref, cv::videoio_registry::getStreamBackends()))
+ if (!videoio_registry::hasBackend(apiPref))
throw SkipTestException(cv::String("Backend is not available/disabled: ") + cv::videoio_registry::getBackendName(apiPref));
VideoCapture cap;
EXPECT_NO_THROW(cap.open(video_file, apiPref));
};
typedef tuple<Size, Ext_Fourcc_PSNR> Size_Ext_Fourcc_PSNR;
-class Videoio_Synthetic : public Videoio_Test_Base, public testing::TestWithParam<Size_Ext_Fourcc_PSNR>
+class videoio_synthetic : public Videoio_Test_Base, public testing::TestWithParam<Size_Ext_Fourcc_PSNR>
{
Size frame_size;
int fourcc;
int frame_count;
double fps;
public:
- Videoio_Synthetic()
+ videoio_synthetic()
{
frame_size = get<0>(GetParam());
const Ext_Fourcc_PSNR p = get<1>(GetParam());
fps = 25.;
apiPref = p.api;
}
- void SetUp()
+ void TearDown()
+ {
+ remove(video_file.c_str());
+ }
+ virtual void writeVideo()
{
Mat img(frame_size, CV_8UC3);
VideoWriter writer;
}
EXPECT_NO_THROW(writer.release());
}
- void TearDown()
- {
- remove(video_file.c_str());
- }
virtual void checkFrameContent(Mat & img, int idx)
{
Mat imgGT(frame_size, CV_8UC3);
CAP_MSMF,
#endif
-#ifdef HAVE_GSTREAMER
CAP_GSTREAMER,
-#endif
-
-#ifdef HAVE_FFMPEG
CAP_FFMPEG,
-#endif
#ifdef HAVE_XINE
CAP_XINE,
string("mjpg.avi")
};
-TEST_P(Videoio_Bunny, read_position) { doTest(); }
+TEST_P(videoio_bunny, read_position) { doTest(); }
-TEST_P(Videoio_Bunny, frame_count) { doFrameCountTest(); }
+TEST_P(videoio_bunny, frame_count) { doFrameCountTest(); }
-INSTANTIATE_TEST_CASE_P(videoio, Videoio_Bunny,
+INSTANTIATE_TEST_CASE_P(videoio, videoio_bunny,
testing::Combine(
testing::ValuesIn(bunny_params),
testing::ValuesIn(backend_params)));
makeParam("mp4", "MJPG", 30.f, CAP_AVFOUNDATION),
makeParam("m4v", "H264", 30.f, CAP_AVFOUNDATION),
makeParam("m4v", "MJPG", 30.f, CAP_AVFOUNDATION),
- makeParam("3gp", "H264", 30.f, CAP_AVFOUNDATION),
- makeParam("3gp", "MJPG", 30.f, CAP_AVFOUNDATION),
#endif
-#ifdef HAVE_FFMPEG
makeParam("avi", "XVID", 30.f, CAP_FFMPEG),
makeParam("avi", "MPEG", 30.f, CAP_FFMPEG),
makeParam("avi", "IYUV", 30.f, CAP_FFMPEG),
makeParam("mkv", "XVID", 30.f, CAP_FFMPEG),
makeParam("mkv", "MPEG", 30.f, CAP_FFMPEG),
makeParam("mkv", "MJPG", 30.f, CAP_FFMPEG),
-#endif
-#ifdef HAVE_GSTREAMER
makeParam("avi", "MPEG", 30.f, CAP_GSTREAMER),
makeParam("avi", "MJPG", 30.f, CAP_GSTREAMER),
makeParam("avi", "H264", 30.f, CAP_GSTREAMER),
makeParam("mkv", "MJPG", 30.f, CAP_GSTREAMER),
makeParam("mkv", "H264", 30.f, CAP_GSTREAMER),
-#endif
makeParam("avi", "MJPG", 30.f, CAP_OPENCV_MJPEG),
};
Size(976, 768)
};
-TEST_P(Videoio_Synthetic, write_read_position) { doTest(); }
+TEST_P(videoio_synthetic, write_read_position) { doTest(); }
-INSTANTIATE_TEST_CASE_P(videoio, Videoio_Synthetic,
+INSTANTIATE_TEST_CASE_P(videoio, videoio_synthetic,
testing::Combine(
testing::ValuesIn(all_sizes),
testing::ValuesIn(synthetic_params)));
def suite(workdir, opencv_cmake_path):
abis = {
- "armeabi-v7a": { "ANDROID_ABI": "armeabi-v7a", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_static" },
- "arm64-v8a": { "ANDROID_ABI": "arm64-v8a", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_static" },
- "x86": { "ANDROID_ABI": "x86", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_static" },
- "x86_64": { "ANDROID_ABI": "x86_64", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_static" },
+ "armeabi-v7a": { "ANDROID_ABI": "armeabi-v7a", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_static", 'ANDROID_NATIVE_API_LEVEL': "21" },
+ "arm64-v8a": { "ANDROID_ABI": "arm64-v8a", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_static", 'ANDROID_NATIVE_API_LEVEL': "21" },
+ "x86": { "ANDROID_ABI": "x86", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_static", 'ANDROID_NATIVE_API_LEVEL': "21" },
+ "x86_64": { "ANDROID_ABI": "x86_64", "ANDROID_TOOLCHAIN": "clang", "ANDROID_STL": "c++_static", 'ANDROID_NATIVE_API_LEVEL': "21" },
}
suite = unittest.TestSuite()
os.makedirs(d)
return d
+def check_executable(cmd):
+ try:
+ log.debug("Executing: %s" % cmd)
+ result = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ log.debug("Result: %s" % (result+'\n').split('\n')[0])
+ return True
+ except Exception as e:
+ log.debug('Failed: %s' % e)
+ return False
+
def determine_opencv_version(version_hpp_path):
# version in 2.4 - CV_VERSION_EPOCH.CV_VERSION_MAJOR.CV_VERSION_MINOR.CV_VERSION_REVISION
# version in master - CV_VERSION_MAJOR.CV_VERSION_MINOR.CV_VERSION_REVISION-CV_VERSION_STATUS
self.extra_packs = []
self.opencv_version = determine_opencv_version(os.path.join(self.opencvdir, "modules", "core", "include", "opencv2", "core", "version.hpp"))
self.use_ccache = False if config.no_ccache else True
+ self.cmake_path = self.get_cmake()
+ self.ninja_path = self.get_ninja()
+ self.debug = True if config.debug else False
+
+ def get_cmake(self):
+ if not self.config.use_android_buildtools and check_executable(['cmake', '--version']):
+ log.info("Using cmake from PATH")
+ return 'cmake'
+ # look to see if Android SDK's cmake is installed
+ android_cmake = os.path.join(os.environ['ANDROID_SDK'], 'cmake')
+ if os.path.exists(android_cmake):
+ cmake_subdirs = [f for f in os.listdir(android_cmake) if check_executable([os.path.join(android_cmake, f, 'bin', 'cmake'), '--version'])]
+ if len(cmake_subdirs) > 0:
+ # there could be more than one - just take the first one
+ cmake_from_sdk = os.path.join(android_cmake, cmake_subdirs[0], 'bin', 'cmake')
+ log.info("Using cmake from Android SDK: %s", cmake_from_sdk)
+ return cmake_from_sdk
+ raise Fail("Can't find cmake")
+
+ def get_ninja(self):
+ if not self.config.use_android_buildtools and check_executable(['ninja', '--version']):
+ log.info("Using ninja from PATH")
+ return 'ninja'
+ # Android SDK's cmake includes a copy of ninja - look to see if its there
+ android_cmake = os.path.join(os.environ['ANDROID_SDK'], 'cmake')
+ if os.path.exists(android_cmake):
+ cmake_subdirs = [f for f in os.listdir(android_cmake) if check_executable([os.path.join(android_cmake, f, 'bin', 'ninja'), '--version'])]
+ if len(cmake_subdirs) > 0:
+ # there could be more than one - just take the first one
+ ninja_from_sdk = os.path.join(android_cmake, cmake_subdirs[0], 'bin', 'ninja')
+ log.info("Using ninja from Android SDK: %s", ninja_from_sdk)
+ return ninja_from_sdk
+ raise Fail("Can't find ninja")
def get_toolchain_file(self):
if not self.config.force_opencv_toolchain:
rm_one(d)
def build_library(self, abi, do_install):
- cmd = ["cmake", "-GNinja"]
+ cmd = [self.cmake_path, "-GNinja"]
cmake_vars = dict(
CMAKE_TOOLCHAIN_FILE=self.get_toolchain_file(),
INSTALL_CREATE_DISTRIB="ON",
BUILD_ANDROID_EXAMPLES="ON",
INSTALL_ANDROID_EXAMPLES="ON",
)
+ if self.ninja_path != 'ninja':
+ cmake_vars['CMAKE_MAKE_PROGRAM'] = self.ninja_path
+
+ if self.debug:
+ cmake_vars['CMAKE_BUILD_TYPE'] = "Debug"
+ cmake_vars['BUILD_WITH_DEBUG_INFO'] = "ON"
if self.config.extra_modules_path is not None:
cmd.append("-DOPENCV_EXTRA_MODULES_PATH='%s'" % self.config.extra_modules_path)
cmd += [ "-D%s='%s'" % (k, v) for (k, v) in cmake_vars.items() if v is not None]
cmd.append(self.opencvdir)
execute(cmd)
- execute(["ninja", "install/strip"])
+ # full parallelism for C++ compilation tasks
+ execute([self.ninja_path, "opencv_modules"])
+ # limit parallelism for Gradle steps (avoid huge memory consumption)
+ execute([self.ninja_path, '-j3', "install" if self.debug else "install/strip"])
def build_javadoc(self):
classpaths = []
parser = argparse.ArgumentParser(description='Build OpenCV for Android SDK')
parser.add_argument("work_dir", nargs='?', default='.', help="Working directory (and output)")
parser.add_argument("opencv_dir", nargs='?', default=os.path.join(SCRIPT_DIR, '../..'), help="Path to OpenCV source dir")
- parser.add_argument('--config', default='ndk-18.config.py', type=str, help="Package build configuration", )
+ parser.add_argument('--config', default='ndk-18-api-level-21.config.py', type=str, help="Package build configuration", )
parser.add_argument('--ndk_path', help="Path to Android NDK to use for build")
parser.add_argument('--sdk_path', help="Path to Android SDK to use for build")
+ parser.add_argument('--use_android_buildtools', action="store_true", help='Use cmake/ninja build tools from Android SDK')
parser.add_argument("--extra_modules_path", help="Path to extra modules to use for build")
parser.add_argument('--sign_with', help="Certificate to sign the Manager apk")
parser.add_argument('--build_doc', action="store_true", help="Build javadoc")
parser.add_argument('--no_ccache', action="store_true", help="Do not use ccache during library build")
parser.add_argument('--force_copy', action="store_true", help="Do not use file move during library build (useful for debug)")
parser.add_argument('--force_opencv_toolchain', action="store_true", help="Do not use toolchain from Android NDK")
+ parser.add_argument('--debug', action="store_true", help="Build for debug")
args = parser.parse_args()
log.basicConfig(format='%(message)s', level=log.DEBUG)
if not 'ANDROID_HOME' in os.environ and 'ANDROID_SDK' in os.environ:
os.environ['ANDROID_HOME'] = os.environ["ANDROID_SDK"]
+ if not 'ANDROID_SDK' in os.environ:
+ raise Fail("SDK location not set. Either pass --sdk_path or set ANDROID_SDK environment variable")
+
+ # look for an NDK installed with the Android SDK
+ if not 'ANDROID_NDK' in os.environ and 'ANDROID_SDK' in os.environ and os.path.exists(os.path.join(os.environ["ANDROID_SDK"], 'ndk-bundle')):
+ os.environ['ANDROID_NDK'] = os.path.join(os.environ["ANDROID_SDK"], 'ndk-bundle')
+
+ if not 'ANDROID_NDK' in os.environ:
+ raise Fail("NDK location not set. Either pass --ndk_path or set ANDROID_NDK environment variable")
+
+ if not check_executable(['ccache', '--version']):
+ log.info("ccache not found - disabling ccache support")
+ args.no_ccache = True
+
if os.path.realpath(args.work_dir) == os.path.realpath(SCRIPT_DIR):
raise Fail("Specify workdir (building from script directory is not supported)")
if os.path.realpath(args.work_dir) == os.path.realpath(args.opencv_dir):
--- /dev/null
+ABIs = [
+ ABI("2", "armeabi-v7a", None, 21, cmake_vars=dict(ANDROID_ABI='armeabi-v7a with NEON')),
+ ABI("3", "arm64-v8a", None, 21),
+ ABI("5", "x86_64", None, 21),
+ ABI("4", "x86", None, 21),
+]
if(NOT __IN_TRY_COMPILE)
set(_xcodebuild_wrapper "${CMAKE_BINARY_DIR}/xcodebuild_wrapper")
- if(NOT DEFINED CMAKE_MAKE_PROGRAM) # empty since CMake 3.10
- find_program(XCODEBUILD_PATH "xcodebuild")
- if(NOT XCODEBUILD_PATH)
- message(FATAL_ERROR "Specify CMAKE_MAKE_PROGRAM variable ('xcodebuild' absolute path)")
+ if(NOT EXISTS "${_xcodebuild_wrapper}")
+ set(_xcodebuild_wrapper_tmp "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/xcodebuild_wrapper")
+ if(NOT DEFINED CMAKE_MAKE_PROGRAM) # empty since CMake 3.10
+ find_program(XCODEBUILD_PATH "xcodebuild")
+ if(NOT XCODEBUILD_PATH)
+ message(FATAL_ERROR "Specify CMAKE_MAKE_PROGRAM variable ('xcodebuild' absolute path)")
+ endif()
+ set(CMAKE_MAKE_PROGRAM "${XCODEBUILD_PATH}")
+ endif()
+ if(CMAKE_MAKE_PROGRAM STREQUAL _xcodebuild_wrapper)
+ message(FATAL_ERROR "Can't prepare xcodebuild_wrapper")
endif()
- set(CMAKE_MAKE_PROGRAM "${XCODEBUILD_PATH}")
- endif()
- if(NOT CMAKE_MAKE_PROGRAM STREQUAL _xcodebuild_wrapper)
if(APPLE_FRAMEWORK AND BUILD_SHARED_LIBS)
- set(_xcodebuild_wrapper_tmp "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/xcodebuild_wrapper")
- file(WRITE "${_xcodebuild_wrapper_tmp}" "#!/bin/sh
-${CMAKE_MAKE_PROGRAM} IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET} -sdk ${CMAKE_OSX_SYSROOT} \$*")
- # Make executable
- file(COPY "${_xcodebuild_wrapper_tmp}" DESTINATION ${CMAKE_BINARY_DIR} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
- set(CMAKE_MAKE_PROGRAM "${_xcodebuild_wrapper}" CACHE INTERNAL "" FORCE)
+ set(XCODEBUILD_EXTRA_ARGS "${XCODEBUILD_EXTRA_ARGS} IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET} -sdk ${CMAKE_OSX_SYSROOT}")
else()
- set(_xcodebuild_wrapper_tmp "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/xcodebuild_wrapper")
- file(WRITE "${_xcodebuild_wrapper_tmp}" "#!/bin/sh
-${CMAKE_MAKE_PROGRAM} IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET} ARCHS=${IOS_ARCH} -sdk ${CMAKE_OSX_SYSROOT} \$*")
- # Make executable
- file(COPY "${_xcodebuild_wrapper_tmp}" DESTINATION ${CMAKE_BINARY_DIR} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
- set(CMAKE_MAKE_PROGRAM "${_xcodebuild_wrapper}" CACHE INTERNAL "" FORCE)
+ set(XCODEBUILD_EXTRA_ARGS "${XCODEBUILD_EXTRA_ARGS} IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET} ARCHS=${IOS_ARCH} -sdk ${CMAKE_OSX_SYSROOT}")
endif()
+ configure_file("${CMAKE_CURRENT_LIST_DIR}/xcodebuild_wrapper.in" "${_xcodebuild_wrapper_tmp}" @ONLY)
+ file(COPY "${_xcodebuild_wrapper_tmp}" DESTINATION ${CMAKE_BINARY_DIR} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
endif()
+ set(CMAKE_MAKE_PROGRAM "${_xcodebuild_wrapper}" CACHE INTERNAL "" FORCE)
endif()
# Standard settings
# Apple Framework settings
if(APPLE_FRAMEWORK AND BUILD_SHARED_LIBS)
- set(CMAKE_SYSTEM_VERSION 8.0)
+ set(CMAKE_SYSTEM_VERSION "${IPHONEOS_DEPLOYMENT_TARGET}")
set(CMAKE_C_SIZEOF_DATA_PTR 4)
set(CMAKE_CXX_SIZEOF_DATA_PTR 4)
else()
- set(CMAKE_SYSTEM_VERSION 6.0)
+ set(CMAKE_SYSTEM_VERSION "${IPHONEOS_DEPLOYMENT_TARGET}")
set(CMAKE_SYSTEM_PROCESSOR "${IOS_ARCH}")
if(AARCH64 OR X86_64)
--- /dev/null
+#!/bin/sh
+
+# Force 'Debug' configuration
+# Details: https://github.com/opencv/opencv/issues/13856
+if [[ "$@" =~ "-project CMAKE_TRY_COMPILE.xcodeproj" && -z "${OPENCV_SKIP_XCODEBUILD_FORCE_TRYCOMPILE_DEBUG}" ]]; then
+ ARGS=()
+ for ((i=1; i<=$#; i++))
+ do
+ arg=${!i}
+ ARGS+=("$arg")
+ if [[ "$arg" == "-configuration" ]]; then
+ ARGS+=("Debug")
+ i=$(($i+1))
+ fi
+ done
+ set -- "${ARGS[@]}"
+fi
+
+@CMAKE_MAKE_PROGRAM@ @XCODEBUILD_EXTRA_ARGS@ $*
<parent>
<groupId>org.opencv</groupId>
<artifactId>opencv-parent</artifactId>
- <version>4.0.1</version>
+ <version>4.1.0</version>
</parent>
<groupId>org.opencv</groupId>
<artifactId>opencv-it</artifactId>
<parent>
<groupId>org.opencv</groupId>
<artifactId>opencv-parent</artifactId>
- <version>4.0.1</version>
+ <version>4.1.0</version>
</parent>
<groupId>org.opencv</groupId>
<artifactId>opencv</artifactId>
<modelVersion>4.0.0</modelVersion>
<groupId>org.opencv</groupId>
<artifactId>opencv-parent</artifactId>
- <version>4.0.1</version>
+ <version>4.1.0</version>
<packaging>pom</packaging>
<name>OpenCV Parent POM</name>
<licenses>
<application
android:icon="@drawable/icon"
- android:label="@string/app_name"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ android:label="@string/app_name" >
<activity
android:name=".Puzzle15Activity"
<application
android:icon="@drawable/icon"
- android:label="@string/app_name"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ android:label="@string/app_name">
<activity
android:name=".Puzzle15Activity"
<application
android:label="@string/app_name"
- android:icon="@drawable/icon"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
+ android:icon="@drawable/icon">
<activity android:name="CameraCalibrationActivity"
android:label="@string/app_name"
<application
android:label="@string/app_name"
- android:icon="@drawable/icon"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
+ android:icon="@drawable/icon">
<activity android:name="CameraCalibrationActivity"
android:label="@string/app_name"
<application
android:label="@string/app_name"
- android:icon="@drawable/icon"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ android:icon="@drawable/icon">
<activity android:name="FdActivity"
android:label="@string/app_name"
<application
android:label="@string/app_name"
- android:icon="@drawable/icon"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ android:icon="@drawable/icon">
<activity android:name="FdActivity"
android:label="@string/app_name"
<application
android:label="@string/app_name"
- android:icon="@drawable/icon"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ android:icon="@drawable/icon">
<activity android:name="ImageManipulationsActivity"
android:label="@string/app_name"
<application
android:label="@string/app_name"
- android:icon="@drawable/icon"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ android:icon="@drawable/icon">
<activity android:name="ImageManipulationsActivity"
android:label="@string/app_name"
<application
android:label="@string/app_name"
- android:icon="@drawable/icon"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ android:icon="@drawable/icon">
<activity android:name="Tutorial2Activity"
android:label="@string/app_name"
<application
android:label="@string/app_name"
- android:icon="@drawable/icon"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ android:icon="@drawable/icon">
<activity android:name="Tutorial2Activity"
android:label="@string/app_name"
<application
android:label="@string/app_name"
- android:icon="@drawable/icon"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ android:icon="@drawable/icon">
<activity android:name="Tutorial3Activity"
android:label="@string/app_name"
<application
android:label="@string/app_name"
- android:icon="@drawable/icon"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ android:icon="@drawable/icon">
<activity android:name="Tutorial3Activity"
android:label="@string/app_name"
\r
<application\r
android:allowBackup="true"\r
- android:icon="@drawable/icon"\r
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >\r
+ android:icon="@drawable/icon">\r
<activity\r
android:name=".Tutorial4Activity"\r
android:label="@string/app_name"\r
\r
<application\r
android:allowBackup="true"\r
- android:icon="@drawable/icon"\r
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >\r
+ android:icon="@drawable/icon">\r
<activity\r
android:name=".Tutorial4Activity"\r
android:label="@string/app_name"\r
+++ /dev/null
-#include "opencv2/imgproc.hpp"
-#include "opencv2/imgcodecs.hpp"
-#include "opencv2/highgui.hpp"
-#include <iostream>
-
-using namespace std;
-using namespace cv;
-
-int main(int argc, char** argv)
-{
- cv::CommandLineParser parser(argc, argv,
- "{input i|building.jpg|input image}"
- "{refine r|false|if true use LSD_REFINE_STD method, if false use LSD_REFINE_NONE method}"
- "{canny c|false|use Canny edge detector}"
- "{overlay o|false|show result on input image}"
- "{help h|false|show help message}");
-
- if (parser.get<bool>("help"))
- {
- parser.printMessage();
- return 0;
- }
-
- parser.printMessage();
-
- String filename = samples::findFile(parser.get<String>("input"));
- bool useRefine = parser.get<bool>("refine");
- bool useCanny = parser.get<bool>("canny");
- bool overlay = parser.get<bool>("overlay");
-
- Mat image = imread(filename, IMREAD_GRAYSCALE);
-
- if( image.empty() )
- {
- cout << "Unable to load " << filename;
- return 1;
- }
-
- imshow("Source Image", image);
-
- if (useCanny)
- {
- Canny(image, image, 50, 200, 3); // Apply Canny edge detector
- }
-
- // Create and LSD detector with standard or no refinement.
- Ptr<LineSegmentDetector> ls = useRefine ? createLineSegmentDetector(LSD_REFINE_STD) : createLineSegmentDetector(LSD_REFINE_NONE);
-
- double start = double(getTickCount());
- vector<Vec4f> lines_std;
-
- // Detect the lines
- ls->detect(image, lines_std);
-
- double duration_ms = (double(getTickCount()) - start) * 1000 / getTickFrequency();
- std::cout << "It took " << duration_ms << " ms." << std::endl;
-
- // Show found lines
- if (!overlay || useCanny)
- {
- image = Scalar(0, 0, 0);
- }
-
- ls->drawSegments(image, lines_std);
-
- String window_name = useRefine ? "Result - standard refinement" : "Result - no refinement";
- window_name += useCanny ? " - Canny edge detector used" : "";
-
- imshow(window_name, image);
-
- waitKey();
- return 0;
-}
#include "CsvReader.h"
/** The default constructor of the CSV reader Class */
-CsvReader::CsvReader(const string &path, const char &separator){
+CsvReader::CsvReader(const string &path, char separator){
_file.open(path.c_str(), ifstream::in);
_separator = separator;
}
class CsvReader {
public:
- /**
- * The default constructor of the CSV reader Class.
- * The default separator is ' ' (empty space)
- *
- * @param path - The path of the file to read
- * @param separator - The separator character between words per line
- * @return
- */
- CsvReader(const string &path, const char &separator = ' ');
+ /**
+ * The default constructor of the CSV reader Class.
+ * The default separator is ' ' (empty space)
+ *
+ * @param path - The path of the file to read
+ * @param separator - The separator character between words per line
+ * @return
+ */
+ CsvReader(const string &path, char separator = ' ');
- /**
- * Read a plane text file with .ply format
- *
- * @param list_vertex - The container of the vertices list of the mesh
- * @param list_triangle - The container of the triangles list of the mesh
- * @return
- */
- void readPLY(vector<Point3f> &list_vertex, vector<vector<int> > &list_triangles);
+ /**
+ * Read a plane text file with .ply format
+ *
+ * @param list_vertex - The container of the vertices list of the mesh
+ * @param list_triangle - The container of the triangles list of the mesh
+ * @return
+ */
+ void readPLY(vector<Point3f> &list_vertex, vector<vector<int> > &list_triangles);
private:
- /** The current stream file for the reader */
- ifstream _file;
- /** The separator character between words for each line */
- char _separator;
+ /** The current stream file for the reader */
+ ifstream _file;
+ /** The separator character between words for each line */
+ char _separator;
};
#endif
#include "CsvWriter.h"
CsvWriter::CsvWriter(const string &path, const string &separator){
- _file.open(path.c_str(), ofstream::out);
- _isFirstTerm = true;
- _separator = separator;
+ _file.open(path.c_str(), ofstream::out);
+ _isFirstTerm = true;
+ _separator = separator;
}
CsvWriter::~CsvWriter() {
- _file.flush();
- _file.close();
+ _file.flush();
+ _file.close();
}
void CsvWriter::writeXYZ(const vector<Point3f> &list_points3d)
{
- string x, y, z;
- for(unsigned int i = 0; i < list_points3d.size(); ++i)
- {
- x = FloatToString(list_points3d[i].x);
- y = FloatToString(list_points3d[i].y);
- z = FloatToString(list_points3d[i].z);
-
- _file << x << _separator << y << _separator << z << std::endl;
- }
+ for(size_t i = 0; i < list_points3d.size(); ++i)
+ {
+ string x = FloatToString(list_points3d[i].x);
+ string y = FloatToString(list_points3d[i].y);
+ string z = FloatToString(list_points3d[i].z);
+ _file << x << _separator << y << _separator << z << std::endl;
+ }
}
void CsvWriter::writeUVXYZ(const vector<Point3f> &list_points3d, const vector<Point2f> &list_points2d, const Mat &descriptors)
{
- string u, v, x, y, z, descriptor_str;
- for(unsigned int i = 0; i < list_points3d.size(); ++i)
- {
- u = FloatToString(list_points2d[i].x);
- v = FloatToString(list_points2d[i].y);
- x = FloatToString(list_points3d[i].x);
- y = FloatToString(list_points3d[i].y);
- z = FloatToString(list_points3d[i].z);
-
- _file << u << _separator << v << _separator << x << _separator << y << _separator << z;
-
- for(int j = 0; j < 32; ++j)
+ for(size_t i = 0; i < list_points3d.size(); ++i)
{
- descriptor_str = FloatToString(descriptors.at<float>(i,j));
- _file << _separator << descriptor_str;
+ string u = FloatToString(list_points2d[i].x);
+ string v = FloatToString(list_points2d[i].y);
+ string x = FloatToString(list_points3d[i].x);
+ string y = FloatToString(list_points3d[i].y);
+ string z = FloatToString(list_points3d[i].z);
+
+ _file << u << _separator << v << _separator << x << _separator << y << _separator << z;
+
+ for(int j = 0; j < 32; ++j)
+ {
+ string descriptor_str = FloatToString(descriptors.at<float>((int)i,j));
+ _file << _separator << descriptor_str;
+ }
+ _file << std::endl;
}
- _file << std::endl;
- }
}
#ifndef CSVWRITER_H
-#define CSVWRITER_H
+#define CSVWRITER_H
#include <iostream>
#include <fstream>
class CsvWriter {
public:
- CsvWriter(const string &path, const string &separator = " ");
- ~CsvWriter();
- void writeXYZ(const vector<Point3f> &list_points3d);
- void writeUVXYZ(const vector<Point3f> &list_points3d, const vector<Point2f> &list_points2d, const Mat &descriptors);
+ CsvWriter(const string &path, const string &separator = " ");
+ ~CsvWriter();
+ void writeXYZ(const vector<Point3f> &list_points3d);
+ void writeUVXYZ(const vector<Point3f> &list_points3d, const vector<Point2f> &list_points2d, const Mat &descriptors);
private:
- ofstream _file;
- string _separator;
- bool _isFirstTerm;
+ ofstream _file;
+ string _separator;
+ bool _isFirstTerm;
};
#endif
// --------------------------------------------------- //
/** The custom constructor of the Triangle Class */
-Triangle::Triangle(int id, cv::Point3f V0, cv::Point3f V1, cv::Point3f V2)
+Triangle::Triangle(const cv::Point3f& V0, const cv::Point3f& V1, const cv::Point3f& V2) :
+ v0_(V0), v1_(V1), v2_(V2)
{
- id_ = id; v0_ = V0; v1_ = V1; v2_ = V2;
}
/** The default destructor of the Class */
Triangle::~Triangle()
{
- // TODO Auto-generated destructor stub
+ // TODO Auto-generated destructor stub
}
// --------------------------------------------------- //
/** The custom constructor of the Ray Class */
-Ray::Ray(cv::Point3f P0, cv::Point3f P1) {
- p0_ = P0; p1_ = P1;
+Ray::Ray(const cv::Point3f& P0, const cv::Point3f& P1) :
+ p0_(P0), p1_(P1)
+{
}
/** The default destructor of the Class */
Ray::~Ray()
{
- // TODO Auto-generated destructor stub
+ // TODO Auto-generated destructor stub
}
// --------------------------------------------------- //
/** The default constructor of the ObjectMesh Class */
-Mesh::Mesh() : list_vertex_(0) , list_triangles_(0)
+Mesh::Mesh() : num_vertices_(0), num_triangles_(0),
+ list_vertex_(0) , list_triangles_(0)
{
- id_ = 0;
- num_vertexs_ = 0;
- num_triangles_ = 0;
}
/** The default destructor of the ObjectMesh Class */
Mesh::~Mesh()
{
- // TODO Auto-generated destructor stub
+ // TODO Auto-generated destructor stub
}
-
/** Load a CSV with *.ply format **/
-void Mesh::load(const std::string path)
+void Mesh::load(const std::string& path)
{
+ // Create the reader
+ CsvReader csvReader(path);
- // Create the reader
- CsvReader csvReader(path);
-
- // Clear previous data
- list_vertex_.clear();
- list_triangles_.clear();
-
- // Read from .ply file
- csvReader.readPLY(list_vertex_, list_triangles_);
+ // Clear previous data
+ list_vertex_.clear();
+ list_triangles_.clear();
- // Update mesh attributes
- num_vertexs_ = (int)list_vertex_.size();
- num_triangles_ = (int)list_triangles_.size();
+ // Read from .ply file
+ csvReader.readPLY(list_vertex_, list_triangles_);
+ // Update mesh attributes
+ num_vertices_ = (int)list_vertex_.size();
+ num_triangles_ = (int)list_triangles_.size();
}
class Triangle {
public:
- explicit Triangle(int id, cv::Point3f V0, cv::Point3f V1, cv::Point3f V2);
- virtual ~Triangle();
+ explicit Triangle(const cv::Point3f& V0, const cv::Point3f& V1, const cv::Point3f& V2);
+ virtual ~Triangle();
- cv::Point3f getV0() const { return v0_; }
- cv::Point3f getV1() const { return v1_; }
- cv::Point3f getV2() const { return v2_; }
+ cv::Point3f getV0() const { return v0_; }
+ cv::Point3f getV1() const { return v1_; }
+ cv::Point3f getV2() const { return v2_; }
private:
- /** The identifier number of the triangle */
- int id_;
- /** The three vertices that defines the triangle */
- cv::Point3f v0_, v1_, v2_;
+ /** The three vertices that defines the triangle */
+ cv::Point3f v0_, v1_, v2_;
};
class Ray {
public:
- explicit Ray(cv::Point3f P0, cv::Point3f P1);
- virtual ~Ray();
+ explicit Ray(const cv::Point3f& P0, const cv::Point3f& P1);
+ virtual ~Ray();
- cv::Point3f getP0() { return p0_; }
- cv::Point3f getP1() { return p1_; }
+ cv::Point3f getP0() { return p0_; }
+ cv::Point3f getP1() { return p1_; }
private:
- /** The two points that defines the ray */
- cv::Point3f p0_, p1_;
+ /** The two points that defines the ray */
+ cv::Point3f p0_, p1_;
};
{
public:
- Mesh();
- virtual ~Mesh();
+ Mesh();
+ virtual ~Mesh();
- std::vector<std::vector<int> > getTrianglesList() const { return list_triangles_; }
- cv::Point3f getVertex(int pos) const { return list_vertex_[pos]; }
- int getNumVertices() const { return num_vertexs_; }
+ std::vector<std::vector<int> > getTrianglesList() const { return list_triangles_; }
+ cv::Point3f getVertex(int pos) const { return list_vertex_[pos]; }
+ int getNumVertices() const { return num_vertices_; }
- void load(const std::string path_file);
+ void load(const std::string& path_file);
private:
- /** The identification number of the mesh */
- int id_;
- /** The current number of vertices in the mesh */
- int num_vertexs_;
- /** The current number of triangles in the mesh */
- int num_triangles_;
- /* The list of triangles of the mesh */
- std::vector<cv::Point3f> list_vertex_;
- /* The list of triangles of the mesh */
- std::vector<std::vector<int> > list_triangles_;
+ /** The current number of vertices in the mesh */
+ int num_vertices_;
+ /** The current number of triangles in the mesh */
+ int num_triangles_;
+ /* The list of triangles of the mesh */
+ std::vector<cv::Point3f> list_vertex_;
+ /* The list of triangles of the mesh */
+ std::vector<std::vector<int> > list_triangles_;
};
#endif /* OBJECTMESH_H_ */
#include "Model.h"
#include "CsvWriter.h"
-Model::Model() : list_points2d_in_(0), list_points2d_out_(0), list_points3d_in_(0)
+Model::Model() : n_correspondences_(0), list_points2d_in_(0), list_points2d_out_(0), list_points3d_in_(0), training_img_path_()
{
- n_correspondences_ = 0;
}
Model::~Model()
{
- // TODO Auto-generated destructor stub
+ // TODO Auto-generated destructor stub
}
void Model::add_correspondence(const cv::Point2f &point2d, const cv::Point3f &point3d)
{
- list_points2d_in_.push_back(point2d);
- list_points3d_in_.push_back(point3d);
- n_correspondences_++;
+ list_points2d_in_.push_back(point2d);
+ list_points3d_in_.push_back(point3d);
+ n_correspondences_++;
}
void Model::add_outlier(const cv::Point2f &point2d)
{
- list_points2d_out_.push_back(point2d);
+ list_points2d_out_.push_back(point2d);
}
void Model::add_descriptor(const cv::Mat &descriptor)
{
- descriptors_.push_back(descriptor);
+ descriptors_.push_back(descriptor);
}
void Model::add_keypoint(const cv::KeyPoint &kp)
{
- list_keypoints_.push_back(kp);
+ list_keypoints_.push_back(kp);
}
+void Model::set_trainingImagePath(const std::string &path)
+{
+ training_img_path_ = path;
+}
-/** Save a CSV file and fill the object mesh */
-void Model::save(const std::string path)
+/** Save a YAML file and fill the object mesh */
+void Model::save(const std::string &path)
{
- cv::Mat points3dmatrix = cv::Mat(list_points3d_in_);
- cv::Mat points2dmatrix = cv::Mat(list_points2d_in_);
- //cv::Mat keyPointmatrix = cv::Mat(list_keypoints_);
+ cv::Mat points3dmatrix = cv::Mat(list_points3d_in_);
+ cv::Mat points2dmatrix = cv::Mat(list_points2d_in_);
- cv::FileStorage storage(path, cv::FileStorage::WRITE);
- storage << "points_3d" << points3dmatrix;
- storage << "points_2d" << points2dmatrix;
- storage << "keypoints" << list_keypoints_;
- storage << "descriptors" << descriptors_;
+ cv::FileStorage storage(path, cv::FileStorage::WRITE);
+ storage << "points_3d" << points3dmatrix;
+ storage << "points_2d" << points2dmatrix;
+ storage << "keypoints" << list_keypoints_;
+ storage << "descriptors" << descriptors_;
+ storage << "training_image_path" << training_img_path_;
- storage.release();
+ storage.release();
}
/** Load a YAML file using OpenCv functions **/
-void Model::load(const std::string path)
+void Model::load(const std::string &path)
{
- cv::Mat points3d_mat;
-
- cv::FileStorage storage(path, cv::FileStorage::READ);
- storage["points_3d"] >> points3d_mat;
- storage["descriptors"] >> descriptors_;
-
- points3d_mat.copyTo(list_points3d_in_);
-
- storage.release();
-
+ cv::Mat points3d_mat;
+
+ cv::FileStorage storage(path, cv::FileStorage::READ);
+ storage["points_3d"] >> points3d_mat;
+ storage["descriptors"] >> descriptors_;
+ if (!storage["keypoints"].empty())
+ {
+ storage["keypoints"] >> list_keypoints_;
+ }
+ if (!storage["training_image_path"].empty())
+ {
+ storage["training_image_path"] >> training_img_path_;
+ }
+
+ points3d_mat.copyTo(list_points3d_in_);
+
+ storage.release();
}
class Model
{
public:
- Model();
- virtual ~Model();
-
- std::vector<cv::Point2f> get_points2d_in() const { return list_points2d_in_; }
- std::vector<cv::Point2f> get_points2d_out() const { return list_points2d_out_; }
- std::vector<cv::Point3f> get_points3d() const { return list_points3d_in_; }
- std::vector<cv::KeyPoint> get_keypoints() const { return list_keypoints_; }
- cv::Mat get_descriptors() const { return descriptors_; }
- int get_numDescriptors() const { return descriptors_.rows; }
-
-
- void add_correspondence(const cv::Point2f &point2d, const cv::Point3f &point3d);
- void add_outlier(const cv::Point2f &point2d);
- void add_descriptor(const cv::Mat &descriptor);
- void add_keypoint(const cv::KeyPoint &kp);
-
-
- void save(const std::string path);
- void load(const std::string path);
-
+ Model();
+ virtual ~Model();
+
+ std::vector<cv::Point2f> get_points2d_in() const { return list_points2d_in_; }
+ std::vector<cv::Point2f> get_points2d_out() const { return list_points2d_out_; }
+ std::vector<cv::Point3f> get_points3d() const { return list_points3d_in_; }
+ std::vector<cv::KeyPoint> get_keypoints() const { return list_keypoints_; }
+ cv::Mat get_descriptors() const { return descriptors_; }
+ int get_numDescriptors() const { return descriptors_.rows; }
+ std::string get_trainingImagePath() const { return training_img_path_; }
+
+ void add_correspondence(const cv::Point2f &point2d, const cv::Point3f &point3d);
+ void add_outlier(const cv::Point2f &point2d);
+ void add_descriptor(const cv::Mat &descriptor);
+ void add_keypoint(const cv::KeyPoint &kp);
+ void set_trainingImagePath(const std::string &path);
+
+ void save(const std::string &path);
+ void load(const std::string &path);
private:
- /** The current number of correspondecnes */
- int n_correspondences_;
- /** The list of 2D points on the model surface */
- std::vector<cv::KeyPoint> list_keypoints_;
- /** The list of 2D points on the model surface */
- std::vector<cv::Point2f> list_points2d_in_;
- /** The list of 2D points outside the model surface */
- std::vector<cv::Point2f> list_points2d_out_;
- /** The list of 3D points on the model surface */
- std::vector<cv::Point3f> list_points3d_in_;
- /** The list of 2D points descriptors */
- cv::Mat descriptors_;
+ /** The current number of correspondecnes */
+ int n_correspondences_;
+ /** The list of 2D points on the model surface */
+ std::vector<cv::KeyPoint> list_keypoints_;
+ /** The list of 2D points on the model surface */
+ std::vector<cv::Point2f> list_points2d_in_;
+ /** The list of 2D points outside the model surface */
+ std::vector<cv::Point2f> list_points2d_out_;
+ /** The list of 3D points on the model surface */
+ std::vector<cv::Point3f> list_points3d_in_;
+ /** The list of 2D points descriptors */
+ cv::Mat descriptors_;
+ /** Path to the training image */
+ std::string training_img_path_;
};
#endif /* OBJECTMODEL_H_ */
#include "ModelRegistration.h"
-ModelRegistration::ModelRegistration()
+ModelRegistration::ModelRegistration() : n_registrations_(0), max_registrations_(0),
+ list_points2d_(), list_points3d_()
{
- n_registrations_ = 0;
- max_registrations_ = 0;
}
ModelRegistration::~ModelRegistration()
{
- // TODO Auto-generated destructor stub
+ // TODO Auto-generated destructor stub
}
void ModelRegistration::registerPoint(const cv::Point2f &point2d, const cv::Point3f &point3d)
- {
- // add correspondence at the end of the vector
+{
+ // add correspondence at the end of the vector
list_points2d_.push_back(point2d);
list_points3d_.push_back(point3d);
n_registrations_++;
- }
+}
void ModelRegistration::reset()
{
- n_registrations_ = 0;
- max_registrations_ = 0;
- list_points2d_.clear();
- list_points3d_.clear();
+ n_registrations_ = 0;
+ max_registrations_ = 0;
+ list_points2d_.clear();
+ list_points3d_.clear();
}
class ModelRegistration
{
public:
+ ModelRegistration();
+ virtual ~ModelRegistration();
- ModelRegistration();
- virtual ~ModelRegistration();
+ void setNumMax(int n) { max_registrations_ = n; }
- void setNumMax(int n) { max_registrations_ = n; }
+ std::vector<cv::Point2f> get_points2d() const { return list_points2d_; }
+ std::vector<cv::Point3f> get_points3d() const { return list_points3d_; }
+ int getNumMax() const { return max_registrations_; }
+ int getNumRegist() const { return n_registrations_; }
- std::vector<cv::Point2f> get_points2d() const { return list_points2d_; }
- std::vector<cv::Point3f> get_points3d() const { return list_points3d_; }
- int getNumMax() const { return max_registrations_; }
- int getNumRegist() const { return n_registrations_; }
-
- bool is_registrable() const { return (n_registrations_ < max_registrations_); }
- void registerPoint(const cv::Point2f &point2d, const cv::Point3f &point3d);
- void reset();
+ bool is_registrable() const { return (n_registrations_ < max_registrations_); }
+ void registerPoint(const cv::Point2f &point2d, const cv::Point3f &point3d);
+ void reset();
private:
-/** The current number of registered points */
-int n_registrations_;
-/** The total number of points to register */
-int max_registrations_;
-/** The list of 2D points to register the model */
-std::vector<cv::Point2f> list_points2d_;
-/** The list of 3D points to register the model */
-std::vector<cv::Point3f> list_points3d_;
+ /** The current number of registered points */
+ int n_registrations_;
+ /** The total number of points to register */
+ int max_registrations_;
+ /** The list of 2D points to register the model */
+ std::vector<cv::Point2f> list_points2d_;
+ /** The list of 3D points to register the model */
+ std::vector<cv::Point3f> list_points3d_;
};
#endif /* MODELREGISTRATION_H_ */
#include <opencv2/calib3d/calib3d.hpp>
-/* Functions headers */
-cv::Point3f CROSS(cv::Point3f v1, cv::Point3f v2);
-double DOT(cv::Point3f v1, cv::Point3f v2);
-cv::Point3f SUB(cv::Point3f v1, cv::Point3f v2);
-cv::Point3f get_nearest_3D_point(std::vector<cv::Point3f> &points_list, cv::Point3f origin);
-
-
/* Functions for Möller-Trumbore intersection algorithm */
-
-cv::Point3f CROSS(cv::Point3f v1, cv::Point3f v2)
+static cv::Point3f CROSS(cv::Point3f v1, cv::Point3f v2)
{
- cv::Point3f tmp_p;
- tmp_p.x = v1.y*v2.z - v1.z*v2.y;
- tmp_p.y = v1.z*v2.x - v1.x*v2.z;
- tmp_p.z = v1.x*v2.y - v1.y*v2.x;
- return tmp_p;
+ cv::Point3f tmp_p;
+ tmp_p.x = v1.y*v2.z - v1.z*v2.y;
+ tmp_p.y = v1.z*v2.x - v1.x*v2.z;
+ tmp_p.z = v1.x*v2.y - v1.y*v2.x;
+ return tmp_p;
}
-double DOT(cv::Point3f v1, cv::Point3f v2)
+static double DOT(cv::Point3f v1, cv::Point3f v2)
{
- return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
+ return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
}
-cv::Point3f SUB(cv::Point3f v1, cv::Point3f v2)
+static cv::Point3f SUB(cv::Point3f v1, cv::Point3f v2)
{
- cv::Point3f tmp_p;
- tmp_p.x = v1.x - v2.x;
- tmp_p.y = v1.y - v2.y;
- tmp_p.z = v1.z - v2.z;
- return tmp_p;
+ cv::Point3f tmp_p;
+ tmp_p.x = v1.x - v2.x;
+ tmp_p.y = v1.y - v2.y;
+ tmp_p.z = v1.z - v2.z;
+ return tmp_p;
}
-/* End functions for Möller-Trumbore intersection algorithm
- * */
+/* End functions for Möller-Trumbore intersection algorithm */
// Function to get the nearest 3D point to the Ray origin
-cv::Point3f get_nearest_3D_point(std::vector<cv::Point3f> &points_list, cv::Point3f origin)
+static cv::Point3f get_nearest_3D_point(std::vector<cv::Point3f> &points_list, cv::Point3f origin)
{
- cv::Point3f p1 = points_list[0];
- cv::Point3f p2 = points_list[1];
-
- double d1 = std::sqrt( std::pow(p1.x-origin.x, 2) + std::pow(p1.y-origin.y, 2) + std::pow(p1.z-origin.z, 2) );
- double d2 = std::sqrt( std::pow(p2.x-origin.x, 2) + std::pow(p2.y-origin.y, 2) + std::pow(p2.z-origin.z, 2) );
-
- if(d1 < d2)
- {
- return p1;
- }
- else
- {
- return p2;
- }
+ cv::Point3f p1 = points_list[0];
+ cv::Point3f p2 = points_list[1];
+
+ double d1 = std::sqrt( std::pow(p1.x-origin.x, 2) + std::pow(p1.y-origin.y, 2) + std::pow(p1.z-origin.z, 2) );
+ double d2 = std::sqrt( std::pow(p2.x-origin.x, 2) + std::pow(p2.y-origin.y, 2) + std::pow(p2.z-origin.z, 2) );
+
+ if(d1 < d2)
+ {
+ return p1;
+ }
+ else
+ {
+ return p2;
+ }
}
// Custom constructor given the intrinsic camera parameters
PnPProblem::PnPProblem(const double params[])
{
- _A_matrix = cv::Mat::zeros(3, 3, CV_64FC1); // intrinsic camera parameters
- _A_matrix.at<double>(0, 0) = params[0]; // [ fx 0 cx ]
- _A_matrix.at<double>(1, 1) = params[1]; // [ 0 fy cy ]
- _A_matrix.at<double>(0, 2) = params[2]; // [ 0 0 1 ]
- _A_matrix.at<double>(1, 2) = params[3];
- _A_matrix.at<double>(2, 2) = 1;
- _R_matrix = cv::Mat::zeros(3, 3, CV_64FC1); // rotation matrix
- _t_matrix = cv::Mat::zeros(3, 1, CV_64FC1); // translation matrix
- _P_matrix = cv::Mat::zeros(3, 4, CV_64FC1); // rotation-translation matrix
+ A_matrix_ = cv::Mat::zeros(3, 3, CV_64FC1); // intrinsic camera parameters
+ A_matrix_.at<double>(0, 0) = params[0]; // [ fx 0 cx ]
+ A_matrix_.at<double>(1, 1) = params[1]; // [ 0 fy cy ]
+ A_matrix_.at<double>(0, 2) = params[2]; // [ 0 0 1 ]
+ A_matrix_.at<double>(1, 2) = params[3];
+ A_matrix_.at<double>(2, 2) = 1;
+ R_matrix_ = cv::Mat::zeros(3, 3, CV_64FC1); // rotation matrix
+ t_matrix_ = cv::Mat::zeros(3, 1, CV_64FC1); // translation matrix
+ P_matrix_ = cv::Mat::zeros(3, 4, CV_64FC1); // rotation-translation matrix
}
PnPProblem::~PnPProblem()
{
- // TODO Auto-generated destructor stub
+ // TODO Auto-generated destructor stub
}
void PnPProblem::set_P_matrix( const cv::Mat &R_matrix, const cv::Mat &t_matrix)
{
- // Rotation-Translation Matrix Definition
- _P_matrix.at<double>(0,0) = R_matrix.at<double>(0,0);
- _P_matrix.at<double>(0,1) = R_matrix.at<double>(0,1);
- _P_matrix.at<double>(0,2) = R_matrix.at<double>(0,2);
- _P_matrix.at<double>(1,0) = R_matrix.at<double>(1,0);
- _P_matrix.at<double>(1,1) = R_matrix.at<double>(1,1);
- _P_matrix.at<double>(1,2) = R_matrix.at<double>(1,2);
- _P_matrix.at<double>(2,0) = R_matrix.at<double>(2,0);
- _P_matrix.at<double>(2,1) = R_matrix.at<double>(2,1);
- _P_matrix.at<double>(2,2) = R_matrix.at<double>(2,2);
- _P_matrix.at<double>(0,3) = t_matrix.at<double>(0);
- _P_matrix.at<double>(1,3) = t_matrix.at<double>(1);
- _P_matrix.at<double>(2,3) = t_matrix.at<double>(2);
+ // Rotation-Translation Matrix Definition
+ P_matrix_.at<double>(0,0) = R_matrix.at<double>(0,0);
+ P_matrix_.at<double>(0,1) = R_matrix.at<double>(0,1);
+ P_matrix_.at<double>(0,2) = R_matrix.at<double>(0,2);
+ P_matrix_.at<double>(1,0) = R_matrix.at<double>(1,0);
+ P_matrix_.at<double>(1,1) = R_matrix.at<double>(1,1);
+ P_matrix_.at<double>(1,2) = R_matrix.at<double>(1,2);
+ P_matrix_.at<double>(2,0) = R_matrix.at<double>(2,0);
+ P_matrix_.at<double>(2,1) = R_matrix.at<double>(2,1);
+ P_matrix_.at<double>(2,2) = R_matrix.at<double>(2,2);
+ P_matrix_.at<double>(0,3) = t_matrix.at<double>(0);
+ P_matrix_.at<double>(1,3) = t_matrix.at<double>(1);
+ P_matrix_.at<double>(2,3) = t_matrix.at<double>(2);
}
-
// Estimate the pose given a list of 2D/3D correspondences and the method to use
bool PnPProblem::estimatePose( const std::vector<cv::Point3f> &list_points3d,
const std::vector<cv::Point2f> &list_points2d,
int flags)
{
- cv::Mat distCoeffs = cv::Mat::zeros(4, 1, CV_64FC1);
- cv::Mat rvec = cv::Mat::zeros(3, 1, CV_64FC1);
- cv::Mat tvec = cv::Mat::zeros(3, 1, CV_64FC1);
+ cv::Mat distCoeffs = cv::Mat::zeros(4, 1, CV_64FC1);
+ cv::Mat rvec = cv::Mat::zeros(3, 1, CV_64FC1);
+ cv::Mat tvec = cv::Mat::zeros(3, 1, CV_64FC1);
- bool useExtrinsicGuess = false;
+ bool useExtrinsicGuess = false;
- // Pose estimation
- bool correspondence = cv::solvePnP( list_points3d, list_points2d, _A_matrix, distCoeffs, rvec, tvec,
- useExtrinsicGuess, flags);
+ // Pose estimation
+ bool correspondence = cv::solvePnP( list_points3d, list_points2d, A_matrix_, distCoeffs, rvec, tvec,
+ useExtrinsicGuess, flags);
- // Transforms Rotation Vector to Matrix
- Rodrigues(rvec,_R_matrix);
- _t_matrix = tvec;
+ // Transforms Rotation Vector to Matrix
+ Rodrigues(rvec, R_matrix_);
+ t_matrix_ = tvec;
- // Set projection matrix
- this->set_P_matrix(_R_matrix, _t_matrix);
+ // Set projection matrix
+ this->set_P_matrix(R_matrix_, t_matrix_);
- return correspondence;
+ return correspondence;
}
// Estimate the pose given a list of 2D/3D correspondences with RANSAC and the method to use
int flags, cv::Mat &inliers, int iterationsCount, // PnP method; inliers container
float reprojectionError, double confidence ) // Ransac parameters
{
- cv::Mat distCoeffs = cv::Mat::zeros(4, 1, CV_64FC1); // vector of distortion coefficients
- cv::Mat rvec = cv::Mat::zeros(3, 1, CV_64FC1); // output rotation vector
- cv::Mat tvec = cv::Mat::zeros(3, 1, CV_64FC1); // output translation vector
+ cv::Mat distCoeffs = cv::Mat::zeros(4, 1, CV_64FC1); // vector of distortion coefficients
+ cv::Mat rvec = cv::Mat::zeros(3, 1, CV_64FC1); // output rotation vector
+ cv::Mat tvec = cv::Mat::zeros(3, 1, CV_64FC1); // output translation vector
- bool useExtrinsicGuess = false; // if true the function uses the provided rvec and tvec values as
- // initial approximations of the rotation and translation vectors
+ bool useExtrinsicGuess = false; // if true the function uses the provided rvec and tvec values as
+ // initial approximations of the rotation and translation vectors
- cv::solvePnPRansac( list_points3d, list_points2d, _A_matrix, distCoeffs, rvec, tvec,
- useExtrinsicGuess, iterationsCount, reprojectionError, confidence,
- inliers, flags );
+ cv::solvePnPRansac( list_points3d, list_points2d, A_matrix_, distCoeffs, rvec, tvec,
+ useExtrinsicGuess, iterationsCount, reprojectionError, confidence,
+ inliers, flags );
- Rodrigues(rvec,_R_matrix); // converts Rotation Vector to Matrix
- _t_matrix = tvec; // set translation matrix
+ Rodrigues(rvec, R_matrix_); // converts Rotation Vector to Matrix
+ t_matrix_ = tvec; // set translation matrix
- this->set_P_matrix(_R_matrix, _t_matrix); // set rotation-translation matrix
+ this->set_P_matrix(R_matrix_, t_matrix_); // set rotation-translation matrix
}
// Given the mesh, backproject the 3D points to 2D to verify the pose estimation
std::vector<cv::Point2f> PnPProblem::verify_points(Mesh *mesh)
{
- std::vector<cv::Point2f> verified_points_2d;
- for( int i = 0; i < mesh->getNumVertices(); i++)
- {
- cv::Point3f point3d = mesh->getVertex(i);
- cv::Point2f point2d = this->backproject3DPoint(point3d);
- verified_points_2d.push_back(point2d);
- }
-
- return verified_points_2d;
-}
+ std::vector<cv::Point2f> verified_points_2d;
+ for( int i = 0; i < mesh->getNumVertices(); i++)
+ {
+ cv::Point3f point3d = mesh->getVertex(i);
+ cv::Point2f point2d = this->backproject3DPoint(point3d);
+ verified_points_2d.push_back(point2d);
+ }
+ return verified_points_2d;
+}
// Backproject a 3D point to 2D using the estimated pose parameters
-
cv::Point2f PnPProblem::backproject3DPoint(const cv::Point3f &point3d)
{
- // 3D point vector [x y z 1]'
- cv::Mat point3d_vec = cv::Mat(4, 1, CV_64FC1);
- point3d_vec.at<double>(0) = point3d.x;
- point3d_vec.at<double>(1) = point3d.y;
- point3d_vec.at<double>(2) = point3d.z;
- point3d_vec.at<double>(3) = 1;
-
- // 2D point vector [u v 1]'
- cv::Mat point2d_vec = cv::Mat(4, 1, CV_64FC1);
- point2d_vec = _A_matrix * _P_matrix * point3d_vec;
-
- // Normalization of [u v]'
- cv::Point2f point2d;
- point2d.x = (float)(point2d_vec.at<double>(0) / point2d_vec.at<double>(2));
- point2d.y = (float)(point2d_vec.at<double>(1) / point2d_vec.at<double>(2));
-
- return point2d;
+ // 3D point vector [x y z 1]'
+ cv::Mat point3d_vec = cv::Mat(4, 1, CV_64FC1);
+ point3d_vec.at<double>(0) = point3d.x;
+ point3d_vec.at<double>(1) = point3d.y;
+ point3d_vec.at<double>(2) = point3d.z;
+ point3d_vec.at<double>(3) = 1;
+
+ // 2D point vector [u v 1]'
+ cv::Mat point2d_vec = cv::Mat(4, 1, CV_64FC1);
+ point2d_vec = A_matrix_ * P_matrix_ * point3d_vec;
+
+ // Normalization of [u v]'
+ cv::Point2f point2d;
+ point2d.x = (float)(point2d_vec.at<double>(0) / point2d_vec.at<double>(2));
+ point2d.y = (float)(point2d_vec.at<double>(1) / point2d_vec.at<double>(2));
+
+ return point2d;
}
// Back project a 2D point to 3D and returns if it's on the object surface
bool PnPProblem::backproject2DPoint(const Mesh *mesh, const cv::Point2f &point2d, cv::Point3f &point3d)
{
- // Triangles list of the object mesh
- std::vector<std::vector<int> > triangles_list = mesh->getTrianglesList();
+ // Triangles list of the object mesh
+ std::vector<std::vector<int> > triangles_list = mesh->getTrianglesList();
- double lambda = 8;
- double u = point2d.x;
- double v = point2d.y;
+ double lambda = 8;
+ double u = point2d.x;
+ double v = point2d.y;
- // Point in vector form
- cv::Mat point2d_vec = cv::Mat::ones(3, 1, CV_64F); // 3x1
- point2d_vec.at<double>(0) = u * lambda;
- point2d_vec.at<double>(1) = v * lambda;
- point2d_vec.at<double>(2) = lambda;
+ // Point in vector form
+ cv::Mat point2d_vec = cv::Mat::ones(3, 1, CV_64F); // 3x1
+ point2d_vec.at<double>(0) = u * lambda;
+ point2d_vec.at<double>(1) = v * lambda;
+ point2d_vec.at<double>(2) = lambda;
- // Point in camera coordinates
- cv::Mat X_c = _A_matrix.inv() * point2d_vec ; // 3x1
+ // Point in camera coordinates
+ cv::Mat X_c = A_matrix_.inv() * point2d_vec ; // 3x1
- // Point in world coordinates
- cv::Mat X_w = _R_matrix.inv() * ( X_c - _t_matrix ); // 3x1
+ // Point in world coordinates
+ cv::Mat X_w = R_matrix_.inv() * ( X_c - t_matrix_ ); // 3x1
- // Center of projection
- cv::Mat C_op = cv::Mat(_R_matrix.inv()).mul(-1) * _t_matrix; // 3x1
+ // Center of projection
+ cv::Mat C_op = cv::Mat(R_matrix_.inv()).mul(-1) * t_matrix_; // 3x1
- // Ray direction vector
- cv::Mat ray = X_w - C_op; // 3x1
- ray = ray / cv::norm(ray); // 3x1
+ // Ray direction vector
+ cv::Mat ray = X_w - C_op; // 3x1
+ ray = ray / cv::norm(ray); // 3x1
- // Set up Ray
- Ray R((cv::Point3f)C_op, (cv::Point3f)ray);
+ // Set up Ray
+ Ray R((cv::Point3f)C_op, (cv::Point3f)ray);
- // A vector to store the intersections found
- std::vector<cv::Point3f> intersections_list;
+ // A vector to store the intersections found
+ std::vector<cv::Point3f> intersections_list;
- // Loop for all the triangles and check the intersection
- for (unsigned int i = 0; i < triangles_list.size(); i++)
- {
- cv::Point3f V0 = mesh->getVertex(triangles_list[i][0]);
- cv::Point3f V1 = mesh->getVertex(triangles_list[i][1]);
- cv::Point3f V2 = mesh->getVertex(triangles_list[i][2]);
-
- Triangle T(i, V0, V1, V2);
+ // Loop for all the triangles and check the intersection
+ for (unsigned int i = 0; i < triangles_list.size(); i++)
+ {
+ cv::Point3f V0 = mesh->getVertex(triangles_list[i][0]);
+ cv::Point3f V1 = mesh->getVertex(triangles_list[i][1]);
+ cv::Point3f V2 = mesh->getVertex(triangles_list[i][2]);
+
+ Triangle T(V0, V1, V2);
+
+ double out;
+ if(this->intersect_MollerTrumbore(R, T, &out))
+ {
+ cv::Point3f tmp_pt = R.getP0() + out*R.getP1(); // P = O + t*D
+ intersections_list.push_back(tmp_pt);
+ }
+ }
- double out;
- if(this->intersect_MollerTrumbore(R, T, &out))
+ // If there are intersection, find the nearest one
+ if (!intersections_list.empty())
{
- cv::Point3f tmp_pt = R.getP0() + out*R.getP1(); // P = O + t*D
- intersections_list.push_back(tmp_pt);
+ point3d = get_nearest_3D_point(intersections_list, R.getP0());
+ return true;
+ }
+ else
+ {
+ return false;
}
- }
-
- // If there are intersection, find the nearest one
- if (!intersections_list.empty())
- {
- point3d = get_nearest_3D_point(intersections_list, R.getP0());
- return true;
- }
- else
- {
- return false;
- }
}
// Möller-Trumbore intersection algorithm
bool PnPProblem::intersect_MollerTrumbore(Ray &Ray, Triangle &Triangle, double *out)
{
- const double EPSILON = 0.000001;
+ const double EPSILON = 0.000001;
- cv::Point3f e1, e2;
- cv::Point3f P, Q, T;
- double det, inv_det, u, v;
- double t;
+ cv::Point3f e1, e2;
+ cv::Point3f P, Q, T;
+ double det, inv_det, u, v;
+ double t;
- cv::Point3f V1 = Triangle.getV0(); // Triangle vertices
- cv::Point3f V2 = Triangle.getV1();
- cv::Point3f V3 = Triangle.getV2();
+ cv::Point3f V1 = Triangle.getV0(); // Triangle vertices
+ cv::Point3f V2 = Triangle.getV1();
+ cv::Point3f V3 = Triangle.getV2();
- cv::Point3f O = Ray.getP0(); // Ray origin
- cv::Point3f D = Ray.getP1(); // Ray direction
+ cv::Point3f O = Ray.getP0(); // Ray origin
+ cv::Point3f D = Ray.getP1(); // Ray direction
- //Find vectors for two edges sharing V1
- e1 = SUB(V2, V1);
- e2 = SUB(V3, V1);
+ //Find vectors for two edges sharing V1
+ e1 = SUB(V2, V1);
+ e2 = SUB(V3, V1);
- // Begin calculation determinant - also used to calculate U parameter
- P = CROSS(D, e2);
+ // Begin calculation determinant - also used to calculate U parameter
+ P = CROSS(D, e2);
- // If determinant is near zero, ray lie in plane of triangle
- det = DOT(e1, P);
+ // If determinant is near zero, ray lie in plane of triangle
+ det = DOT(e1, P);
- //NOT CULLING
- if(det > -EPSILON && det < EPSILON) return false;
- inv_det = 1.f / det;
+ //NOT CULLING
+ if(det > -EPSILON && det < EPSILON) return false;
+ inv_det = 1.f / det;
- //calculate distance from V1 to ray origin
- T = SUB(O, V1);
+ //calculate distance from V1 to ray origin
+ T = SUB(O, V1);
- //Calculate u parameter and test bound
- u = DOT(T, P) * inv_det;
+ //Calculate u parameter and test bound
+ u = DOT(T, P) * inv_det;
- //The intersection lies outside of the triangle
- if(u < 0.f || u > 1.f) return false;
+ //The intersection lies outside of the triangle
+ if(u < 0.f || u > 1.f) return false;
- //Prepare to test v parameter
- Q = CROSS(T, e1);
+ //Prepare to test v parameter
+ Q = CROSS(T, e1);
- //Calculate V parameter and test bound
- v = DOT(D, Q) * inv_det;
+ //Calculate V parameter and test bound
+ v = DOT(D, Q) * inv_det;
- //The intersection lies outside of the triangle
- if(v < 0.f || u + v > 1.f) return false;
+ //The intersection lies outside of the triangle
+ if(v < 0.f || u + v > 1.f) return false;
- t = DOT(e2, Q) * inv_det;
+ t = DOT(e2, Q) * inv_det;
- if(t > EPSILON) { //ray intersection
- *out = t;
- return true;
- }
+ if(t > EPSILON) { //ray intersection
+ *out = t;
+ return true;
+ }
- // No hit, no win
- return false;
+ // No hit, no win
+ return false;
}
class PnPProblem
{
-
public:
- explicit PnPProblem(const double param[]); // custom constructor
- virtual ~PnPProblem();
+ explicit PnPProblem(const double param[]); // custom constructor
+ virtual ~PnPProblem();
- bool backproject2DPoint(const Mesh *mesh, const cv::Point2f &point2d, cv::Point3f &point3d);
- bool intersect_MollerTrumbore(Ray &R, Triangle &T, double *out);
- std::vector<cv::Point2f> verify_points(Mesh *mesh);
- cv::Point2f backproject3DPoint(const cv::Point3f &point3d);
- bool estimatePose(const std::vector<cv::Point3f> &list_points3d, const std::vector<cv::Point2f> &list_points2d, int flags);
- void estimatePoseRANSAC( const std::vector<cv::Point3f> &list_points3d, const std::vector<cv::Point2f> &list_points2d,
- int flags, cv::Mat &inliers,
- int iterationsCount, float reprojectionError, double confidence );
+ bool backproject2DPoint(const Mesh *mesh, const cv::Point2f &point2d, cv::Point3f &point3d);
+ bool intersect_MollerTrumbore(Ray &R, Triangle &T, double *out);
+ std::vector<cv::Point2f> verify_points(Mesh *mesh);
+ cv::Point2f backproject3DPoint(const cv::Point3f &point3d);
+ bool estimatePose(const std::vector<cv::Point3f> &list_points3d, const std::vector<cv::Point2f> &list_points2d, int flags);
+ void estimatePoseRANSAC( const std::vector<cv::Point3f> &list_points3d, const std::vector<cv::Point2f> &list_points2d,
+ int flags, cv::Mat &inliers,
+ int iterationsCount, float reprojectionError, double confidence );
- cv::Mat get_A_matrix() const { return _A_matrix; }
- cv::Mat get_R_matrix() const { return _R_matrix; }
- cv::Mat get_t_matrix() const { return _t_matrix; }
- cv::Mat get_P_matrix() const { return _P_matrix; }
+ cv::Mat get_A_matrix() const { return A_matrix_; }
+ cv::Mat get_R_matrix() const { return R_matrix_; }
+ cv::Mat get_t_matrix() const { return t_matrix_; }
+ cv::Mat get_P_matrix() const { return P_matrix_; }
- void set_P_matrix( const cv::Mat &R_matrix, const cv::Mat &t_matrix);
+ void set_P_matrix( const cv::Mat &R_matrix, const cv::Mat &t_matrix);
private:
- /** The calibration matrix */
- cv::Mat _A_matrix;
- /** The computed rotation matrix */
- cv::Mat _R_matrix;
- /** The computed translation matrix */
- cv::Mat _t_matrix;
- /** The computed projection matrix */
- cv::Mat _P_matrix;
+ /** The calibration matrix */
+ cv::Mat A_matrix_;
+ /** The computed rotation matrix */
+ cv::Mat R_matrix_;
+ /** The computed translation matrix */
+ cv::Mat t_matrix_;
+ /** The computed projection matrix */
+ cv::Mat P_matrix_;
};
-// Functions for Möller-Trumbore intersection algorithm
-cv::Point3f CROSS(cv::Point3f v1, cv::Point3f v2);
-double DOT(cv::Point3f v1, cv::Point3f v2);
-cv::Point3f SUB(cv::Point3f v1, cv::Point3f v2);
-
#endif /* PNPPROBLEM_H_ */
RobustMatcher::~RobustMatcher()
{
- // TODO Auto-generated destructor stub
+ // TODO Auto-generated destructor stub
}
void RobustMatcher::computeKeyPoints( const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints)
{
- detector_->detect(image, keypoints);
+ detector_->detect(image, keypoints);
}
void RobustMatcher::computeDescriptors( const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, cv::Mat& descriptors)
{
- extractor_->compute(image, keypoints, descriptors);
+ extractor_->compute(image, keypoints, descriptors);
}
int RobustMatcher::ratioTest(std::vector<std::vector<cv::DMatch> > &matches)
{
- int removed = 0;
- // for all matches
- for ( std::vector<std::vector<cv::DMatch> >::iterator
- matchIterator= matches.begin(); matchIterator!= matches.end(); ++matchIterator)
- {
- // if 2 NN has been identified
- if (matchIterator->size() > 1)
+ int removed = 0;
+ // for all matches
+ for ( std::vector<std::vector<cv::DMatch> >::iterator
+ matchIterator= matches.begin(); matchIterator!= matches.end(); ++matchIterator)
{
- // check distance ratio
- if ((*matchIterator)[0].distance / (*matchIterator)[1].distance > ratio_)
- {
- matchIterator->clear(); // remove match
- removed++;
- }
- }
- else
- { // does not have 2 neighbours
- matchIterator->clear(); // remove match
- removed++;
+ // if 2 NN has been identified
+ if (matchIterator->size() > 1)
+ {
+ // check distance ratio
+ if ((*matchIterator)[0].distance / (*matchIterator)[1].distance > ratio_)
+ {
+ matchIterator->clear(); // remove match
+ removed++;
+ }
+ }
+ else
+ { // does not have 2 neighbours
+ matchIterator->clear(); // remove match
+ removed++;
+ }
}
- }
- return removed;
+ return removed;
}
void RobustMatcher::symmetryTest( const std::vector<std::vector<cv::DMatch> >& matches1,
- const std::vector<std::vector<cv::DMatch> >& matches2,
- std::vector<cv::DMatch>& symMatches )
+ const std::vector<std::vector<cv::DMatch> >& matches2,
+ std::vector<cv::DMatch>& symMatches )
{
-
- // for all matches image 1 -> image 2
- for (std::vector<std::vector<cv::DMatch> >::const_iterator
- matchIterator1 = matches1.begin(); matchIterator1 != matches1.end(); ++matchIterator1)
- {
-
- // ignore deleted matches
- if (matchIterator1->empty() || matchIterator1->size() < 2)
- continue;
-
- // for all matches image 2 -> image 1
- for (std::vector<std::vector<cv::DMatch> >::const_iterator
- matchIterator2 = matches2.begin(); matchIterator2 != matches2.end(); ++matchIterator2)
- {
+ // for all matches image 1 -> image 2
+ for (std::vector<std::vector<cv::DMatch> >::const_iterator
+ matchIterator1 = matches1.begin(); matchIterator1 != matches1.end(); ++matchIterator1)
+ {
// ignore deleted matches
- if (matchIterator2->empty() || matchIterator2->size() < 2)
- continue;
-
- // Match symmetry test
- if ((*matchIterator1)[0].queryIdx ==
- (*matchIterator2)[0].trainIdx &&
- (*matchIterator2)[0].queryIdx ==
- (*matchIterator1)[0].trainIdx)
+ if (matchIterator1->empty() || matchIterator1->size() < 2)
+ continue;
+
+ // for all matches image 2 -> image 1
+ for (std::vector<std::vector<cv::DMatch> >::const_iterator
+ matchIterator2 = matches2.begin(); matchIterator2 != matches2.end(); ++matchIterator2)
{
- // add symmetrical match
- symMatches.push_back(
- cv::DMatch((*matchIterator1)[0].queryIdx,
- (*matchIterator1)[0].trainIdx,
- (*matchIterator1)[0].distance));
- break; // next match in image 1 -> image 2
+ // ignore deleted matches
+ if (matchIterator2->empty() || matchIterator2->size() < 2)
+ continue;
+
+ // Match symmetry test
+ if ((*matchIterator1)[0].queryIdx == (*matchIterator2)[0].trainIdx &&
+ (*matchIterator2)[0].queryIdx == (*matchIterator1)[0].trainIdx)
+ {
+ // add symmetrical match
+ symMatches.push_back(cv::DMatch((*matchIterator1)[0].queryIdx,
+ (*matchIterator1)[0].trainIdx, (*matchIterator1)[0].distance));
+ break; // next match in image 1 -> image 2
+ }
}
- }
- }
-
+ }
}
void RobustMatcher::robustMatch( const cv::Mat& frame, std::vector<cv::DMatch>& good_matches,
- std::vector<cv::KeyPoint>& keypoints_frame, const cv::Mat& descriptors_model )
+ std::vector<cv::KeyPoint>& keypoints_frame, const cv::Mat& descriptors_model,
+ const std::vector<cv::KeyPoint>& keypoints_model)
{
+ // 1a. Detection of the ORB features
+ this->computeKeyPoints(frame, keypoints_frame);
- // 1a. Detection of the ORB features
- this->computeKeyPoints(frame, keypoints_frame);
-
- // 1b. Extraction of the ORB descriptors
- cv::Mat descriptors_frame;
- this->computeDescriptors(frame, keypoints_frame, descriptors_frame);
+ // 1b. Extraction of the ORB descriptors
+ cv::Mat descriptors_frame;
+ this->computeDescriptors(frame, keypoints_frame, descriptors_frame);
- // 2. Match the two image descriptors
- std::vector<std::vector<cv::DMatch> > matches12, matches21;
+ // 2. Match the two image descriptors
+ std::vector<std::vector<cv::DMatch> > matches12, matches21;
- // 2a. From image 1 to image 2
- matcher_->knnMatch(descriptors_frame, descriptors_model, matches12, 2); // return 2 nearest neighbours
+ // 2a. From image 1 to image 2
+ matcher_->knnMatch(descriptors_frame, descriptors_model, matches12, 2); // return 2 nearest neighbours
- // 2b. From image 2 to image 1
- matcher_->knnMatch(descriptors_model, descriptors_frame, matches21, 2); // return 2 nearest neighbours
+ // 2b. From image 2 to image 1
+ matcher_->knnMatch(descriptors_model, descriptors_frame, matches21, 2); // return 2 nearest neighbours
- // 3. Remove matches for which NN ratio is > than threshold
- // clean image 1 -> image 2 matches
- ratioTest(matches12);
- // clean image 2 -> image 1 matches
- ratioTest(matches21);
+ // 3. Remove matches for which NN ratio is > than threshold
+ // clean image 1 -> image 2 matches
+ ratioTest(matches12);
+ // clean image 2 -> image 1 matches
+ ratioTest(matches21);
- // 4. Remove non-symmetrical matches
- symmetryTest(matches12, matches21, good_matches);
+ // 4. Remove non-symmetrical matches
+ symmetryTest(matches12, matches21, good_matches);
+ if (!training_img_.empty() && !keypoints_model.empty())
+ {
+ cv::drawMatches(frame, keypoints_frame, training_img_, keypoints_model, good_matches, img_matching_);
+ }
}
void RobustMatcher::fastRobustMatch( const cv::Mat& frame, std::vector<cv::DMatch>& good_matches,
- std::vector<cv::KeyPoint>& keypoints_frame,
- const cv::Mat& descriptors_model )
+ std::vector<cv::KeyPoint>& keypoints_frame,
+ const cv::Mat& descriptors_model,
+ const std::vector<cv::KeyPoint>& keypoints_model)
{
- good_matches.clear();
+ good_matches.clear();
- // 1a. Detection of the ORB features
- this->computeKeyPoints(frame, keypoints_frame);
+ // 1a. Detection of the ORB features
+ this->computeKeyPoints(frame, keypoints_frame);
- // 1b. Extraction of the ORB descriptors
- cv::Mat descriptors_frame;
- this->computeDescriptors(frame, keypoints_frame, descriptors_frame);
+ // 1b. Extraction of the ORB descriptors
+ cv::Mat descriptors_frame;
+ this->computeDescriptors(frame, keypoints_frame, descriptors_frame);
- // 2. Match the two image descriptors
- std::vector<std::vector<cv::DMatch> > matches;
- matcher_->knnMatch(descriptors_frame, descriptors_model, matches, 2);
+ // 2. Match the two image descriptors
+ std::vector<std::vector<cv::DMatch> > matches;
+ matcher_->knnMatch(descriptors_frame, descriptors_model, matches, 2);
- // 3. Remove matches for which NN ratio is > than threshold
- ratioTest(matches);
+ // 3. Remove matches for which NN ratio is > than threshold
+ ratioTest(matches);
- // 4. Fill good matches container
- for ( std::vector<std::vector<cv::DMatch> >::iterator
- matchIterator= matches.begin(); matchIterator!= matches.end(); ++matchIterator)
- {
- if (!matchIterator->empty()) good_matches.push_back((*matchIterator)[0]);
- }
+ // 4. Fill good matches container
+ for ( std::vector<std::vector<cv::DMatch> >::iterator
+ matchIterator= matches.begin(); matchIterator!= matches.end(); ++matchIterator)
+ {
+ if (!matchIterator->empty()) good_matches.push_back((*matchIterator)[0]);
+ }
+ if (!training_img_.empty() && !keypoints_model.empty())
+ {
+ cv::drawMatches(frame, keypoints_frame, training_img_, keypoints_model, good_matches, img_matching_);
+ }
}
class RobustMatcher {
public:
- RobustMatcher() : ratio_(0.8f)
- {
- // ORB is the default feature
- detector_ = cv::ORB::create();
- extractor_ = cv::ORB::create();
+ RobustMatcher() : detector_(), extractor_(), matcher_(),
+ ratio_(0.8f), training_img_(), img_matching_()
+ {
+ // ORB is the default feature
+ detector_ = cv::ORB::create();
+ extractor_ = cv::ORB::create();
- // BruteFroce matcher with Norm Hamming is the default matcher
- matcher_ = cv::makePtr<cv::BFMatcher>((int)cv::NORM_HAMMING, false);
+ // BruteFroce matcher with Norm Hamming is the default matcher
+ matcher_ = cv::makePtr<cv::BFMatcher>((int)cv::NORM_HAMMING, false);
- }
- virtual ~RobustMatcher();
+ }
+ virtual ~RobustMatcher();
- // Set the feature detector
- void setFeatureDetector(const cv::Ptr<cv::FeatureDetector>& detect) { detector_ = detect; }
+ // Set the feature detector
+ void setFeatureDetector(const cv::Ptr<cv::FeatureDetector>& detect) { detector_ = detect; }
- // Set the descriptor extractor
- void setDescriptorExtractor(const cv::Ptr<cv::DescriptorExtractor>& desc) { extractor_ = desc; }
+ // Set the descriptor extractor
+ void setDescriptorExtractor(const cv::Ptr<cv::DescriptorExtractor>& desc) { extractor_ = desc; }
- // Set the matcher
- void setDescriptorMatcher(const cv::Ptr<cv::DescriptorMatcher>& match) { matcher_ = match; }
+ // Set the matcher
+ void setDescriptorMatcher(const cv::Ptr<cv::DescriptorMatcher>& match) { matcher_ = match; }
- // Compute the keypoints of an image
- void computeKeyPoints( const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints);
+ // Compute the keypoints of an image
+ void computeKeyPoints( const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints);
- // Compute the descriptors of an image given its keypoints
- void computeDescriptors( const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, cv::Mat& descriptors);
+ // Compute the descriptors of an image given its keypoints
+ void computeDescriptors( const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, cv::Mat& descriptors);
- // Set ratio parameter for the ratio test
- void setRatio( float rat) { ratio_ = rat; }
+ cv::Mat getImageMatching() const { return img_matching_; }
- // Clear matches for which NN ratio is > than threshold
- // return the number of removed points
- // (corresponding entries being cleared,
- // i.e. size will be 0)
- int ratioTest(std::vector<std::vector<cv::DMatch> > &matches);
+ // Set ratio parameter for the ratio test
+ void setRatio( float rat) { ratio_ = rat; }
- // Insert symmetrical matches in symMatches vector
- void symmetryTest( const std::vector<std::vector<cv::DMatch> >& matches1,
- const std::vector<std::vector<cv::DMatch> >& matches2,
- std::vector<cv::DMatch>& symMatches );
+ void setTrainingImage(const cv::Mat &img) { training_img_ = img; }
- // Match feature points using ratio and symmetry test
- void robustMatch( const cv::Mat& frame, std::vector<cv::DMatch>& good_matches,
+ // Clear matches for which NN ratio is > than threshold
+ // return the number of removed points
+ // (corresponding entries being cleared,
+ // i.e. size will be 0)
+ int ratioTest(std::vector<std::vector<cv::DMatch> > &matches);
+
+ // Insert symmetrical matches in symMatches vector
+ void symmetryTest( const std::vector<std::vector<cv::DMatch> >& matches1,
+ const std::vector<std::vector<cv::DMatch> >& matches2,
+ std::vector<cv::DMatch>& symMatches );
+
+ // Match feature points using ratio and symmetry test
+ void robustMatch( const cv::Mat& frame, std::vector<cv::DMatch>& good_matches,
std::vector<cv::KeyPoint>& keypoints_frame,
- const cv::Mat& descriptors_model );
+ const cv::Mat& descriptors_model,
+ const std::vector<cv::KeyPoint>& keypoints_model);
- // Match feature points using ratio test
- void fastRobustMatch( const cv::Mat& frame, std::vector<cv::DMatch>& good_matches,
- std::vector<cv::KeyPoint>& keypoints_frame,
- const cv::Mat& descriptors_model );
+ // Match feature points using ratio test
+ void fastRobustMatch( const cv::Mat& frame, std::vector<cv::DMatch>& good_matches,
+ std::vector<cv::KeyPoint>& keypoints_frame,
+ const cv::Mat& descriptors_model,
+ const std::vector<cv::KeyPoint>& keypoints_model);
private:
- // pointer to the feature point detector object
- cv::Ptr<cv::FeatureDetector> detector_;
- // pointer to the feature descriptor extractor object
- cv::Ptr<cv::DescriptorExtractor> extractor_;
- // pointer to the matcher object
- cv::Ptr<cv::DescriptorMatcher> matcher_;
- // max ratio between 1st and 2nd NN
- float ratio_;
+ // pointer to the feature point detector object
+ cv::Ptr<cv::FeatureDetector> detector_;
+ // pointer to the feature descriptor extractor object
+ cv::Ptr<cv::DescriptorExtractor> extractor_;
+ // pointer to the matcher object
+ cv::Ptr<cv::DescriptorMatcher> matcher_;
+ // max ratio between 1st and 2nd NN
+ float ratio_;
+ // training image
+ cv::Mat training_img_;
+ // matching image
+ cv::Mat img_matching_;
};
#endif /* ROBUSTMATCHER_H_ */
#include "ModelRegistration.h"
#include "Utils.h"
+#include <opencv2/opencv_modules.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/calib3d.hpp>
+#include <opencv2/flann.hpp>
+#if defined (HAVE_OPENCV_XFEATURES2D)
+#include <opencv2/xfeatures2d.hpp>
+#endif
// For text
-int fontFace = cv::FONT_ITALIC;
-double fontScale = 0.75;
-int thickness_font = 2;
+const int fontFace = cv::FONT_ITALIC;
+const double fontScale = 0.75;
+const int thickness_font = 2;
// For circles
-int lineType = 8;
-int radius = 4;
-double thickness_circ = -1;
+const int lineType = 8;
+const int radius = 4;
// Draw a text with the question point
void drawQuestion(cv::Mat image, cv::Point3f point, cv::Scalar color)
{
- std::string x = IntToString((int)point.x);
- std::string y = IntToString((int)point.y);
- std::string z = IntToString((int)point.z);
+ std::string x = IntToString((int)point.x);
+ std::string y = IntToString((int)point.y);
+ std::string z = IntToString((int)point.z);
- std::string text = " Where is point (" + x + "," + y + "," + z + ") ?";
- cv::putText(image, text, cv::Point(25,50), fontFace, fontScale, color, thickness_font, 8);
+ std::string text = " Where is point (" + x + "," + y + "," + z + ") ?";
+ cv::putText(image, text, cv::Point(25,50), fontFace, fontScale, color, thickness_font, 8);
}
// Draw a text with the number of entered points
void drawText(cv::Mat image, std::string text, cv::Scalar color)
{
- cv::putText(image, text, cv::Point(25,50), fontFace, fontScale, color, thickness_font, 8);
+ cv::putText(image, text, cv::Point(25,50), fontFace, fontScale, color, thickness_font, 8);
}
// Draw a text with the number of entered points
void drawText2(cv::Mat image, std::string text, cv::Scalar color)
{
- cv::putText(image, text, cv::Point(25,75), fontFace, fontScale, color, thickness_font, 8);
+ cv::putText(image, text, cv::Point(25,75), fontFace, fontScale, color, thickness_font, 8);
}
// Draw a text with the frame ratio
void drawFPS(cv::Mat image, double fps, cv::Scalar color)
{
- std::string fps_str = IntToString((int)fps);
- std::string text = fps_str + " FPS";
- cv::putText(image, text, cv::Point(500,50), fontFace, fontScale, color, thickness_font, 8);
+ std::string fps_str = cv::format("%.2f FPS", fps);
+ cv::putText(image, fps_str, cv::Point(500,50), fontFace, fontScale, color, thickness_font, 8);
}
// Draw a text with the frame ratio
void drawConfidence(cv::Mat image, double confidence, cv::Scalar color)
{
- std::string conf_str = IntToString((int)confidence);
- std::string text = conf_str + " %";
- cv::putText(image, text, cv::Point(500,75), fontFace, fontScale, color, thickness_font, 8);
+ std::string conf_str = IntToString((int)confidence);
+ std::string text = conf_str + " %";
+ cv::putText(image, text, cv::Point(500,75), fontFace, fontScale, color, thickness_font, 8);
}
// Draw a text with the number of entered points
void drawCounter(cv::Mat image, int n, int n_max, cv::Scalar color)
{
- std::string n_str = IntToString(n);
- std::string n_max_str = IntToString(n_max);
- std::string text = n_str + " of " + n_max_str + " points";
- cv::putText(image, text, cv::Point(500,50), fontFace, fontScale, color, thickness_font, 8);
+ std::string n_str = IntToString(n);
+ std::string n_max_str = IntToString(n_max);
+ std::string text = n_str + " of " + n_max_str + " points";
+ cv::putText(image, text, cv::Point(500,50), fontFace, fontScale, color, thickness_font, 8);
}
// Draw the points and the coordinates
void drawPoints(cv::Mat image, std::vector<cv::Point2f> &list_points_2d, std::vector<cv::Point3f> &list_points_3d, cv::Scalar color)
{
- for (unsigned int i = 0; i < list_points_2d.size(); ++i)
- {
- cv::Point2f point_2d = list_points_2d[i];
- cv::Point3f point_3d = list_points_3d[i];
-
- // Draw Selected points
- cv::circle(image, point_2d, radius, color, -1, lineType );
-
- std::string idx = IntToString(i+1);
- std::string x = IntToString((int)point_3d.x);
- std::string y = IntToString((int)point_3d.y);
- std::string z = IntToString((int)point_3d.z);
- std::string text = "P" + idx + " (" + x + "," + y + "," + z +")";
-
- point_2d.x = point_2d.x + 10;
- point_2d.y = point_2d.y - 10;
- cv::putText(image, text, point_2d, fontFace, fontScale*0.5, color, thickness_font, 8);
- }
+ for (unsigned int i = 0; i < list_points_2d.size(); ++i)
+ {
+ cv::Point2f point_2d = list_points_2d[i];
+ cv::Point3f point_3d = list_points_3d[i];
+
+ // Draw Selected points
+ cv::circle(image, point_2d, radius, color, -1, lineType );
+
+ std::string idx = IntToString(i+1);
+ std::string x = IntToString((int)point_3d.x);
+ std::string y = IntToString((int)point_3d.y);
+ std::string z = IntToString((int)point_3d.z);
+ std::string text = "P" + idx + " (" + x + "," + y + "," + z +")";
+
+ point_2d.x = point_2d.x + 10;
+ point_2d.y = point_2d.y - 10;
+ cv::putText(image, text, point_2d, fontFace, fontScale*0.5, color, thickness_font, 8);
+ }
}
// Draw only the 2D points
void draw2DPoints(cv::Mat image, std::vector<cv::Point2f> &list_points, cv::Scalar color)
{
- for( size_t i = 0; i < list_points.size(); i++)
- {
- cv::Point2f point_2d = list_points[i];
+ for( size_t i = 0; i < list_points.size(); i++)
+ {
+ cv::Point2f point_2d = list_points[i];
- // Draw Selected points
- cv::circle(image, point_2d, radius, color, -1, lineType );
- }
+ // Draw Selected points
+ cv::circle(image, point_2d, radius, color, -1, lineType );
+ }
}
// Draw an arrow into the image
void drawArrow(cv::Mat image, cv::Point2i p, cv::Point2i q, cv::Scalar color, int arrowMagnitude, int thickness, int line_type, int shift)
{
- //Draw the principle line
- cv::line(image, p, q, color, thickness, line_type, shift);
- const double PI = CV_PI;
- //compute the angle alpha
- double angle = atan2((double)p.y-q.y, (double)p.x-q.x);
- //compute the coordinates of the first segment
- p.x = (int) ( q.x + arrowMagnitude * cos(angle + PI/4));
- p.y = (int) ( q.y + arrowMagnitude * sin(angle + PI/4));
- //Draw the first segment
- cv::line(image, p, q, color, thickness, line_type, shift);
- //compute the coordinates of the second segment
- p.x = (int) ( q.x + arrowMagnitude * cos(angle - PI/4));
- p.y = (int) ( q.y + arrowMagnitude * sin(angle - PI/4));
- //Draw the second segment
- cv::line(image, p, q, color, thickness, line_type, shift);
+ //Draw the principle line
+ cv::line(image, p, q, color, thickness, line_type, shift);
+ const double PI = CV_PI;
+ //compute the angle alpha
+ double angle = atan2((double)p.y-q.y, (double)p.x-q.x);
+ //compute the coordinates of the first segment
+ p.x = (int) ( q.x + arrowMagnitude * cos(angle + PI/4));
+ p.y = (int) ( q.y + arrowMagnitude * sin(angle + PI/4));
+ //Draw the first segment
+ cv::line(image, p, q, color, thickness, line_type, shift);
+ //compute the coordinates of the second segment
+ p.x = (int) ( q.x + arrowMagnitude * cos(angle - PI/4));
+ p.y = (int) ( q.y + arrowMagnitude * sin(angle - PI/4));
+ //Draw the second segment
+ cv::line(image, p, q, color, thickness, line_type, shift);
}
// Draw the 3D coordinate axes
void draw3DCoordinateAxes(cv::Mat image, const std::vector<cv::Point2f> &list_points2d)
{
- cv::Scalar red(0, 0, 255);
- cv::Scalar green(0,255,0);
- cv::Scalar blue(255,0,0);
- cv::Scalar black(0,0,0);
-
- cv::Point2i origin = list_points2d[0];
- cv::Point2i pointX = list_points2d[1];
- cv::Point2i pointY = list_points2d[2];
- cv::Point2i pointZ = list_points2d[3];
-
- drawArrow(image, origin, pointX, red, 9, 2);
- drawArrow(image, origin, pointY, blue, 9, 2);
- drawArrow(image, origin, pointZ, green, 9, 2);
- cv::circle(image, origin, radius/2, black, -1, lineType );
-
+ cv::Scalar red(0, 0, 255);
+ cv::Scalar green(0,255,0);
+ cv::Scalar blue(255,0,0);
+ cv::Scalar black(0,0,0);
+
+ cv::Point2i origin = list_points2d[0];
+ cv::Point2i pointX = list_points2d[1];
+ cv::Point2i pointY = list_points2d[2];
+ cv::Point2i pointZ = list_points2d[3];
+
+ drawArrow(image, origin, pointX, red, 9, 2);
+ drawArrow(image, origin, pointY, green, 9, 2);
+ drawArrow(image, origin, pointZ, blue, 9, 2);
+ cv::circle(image, origin, radius/2, black, -1, lineType );
}
// Draw the object mesh
void drawObjectMesh(cv::Mat image, const Mesh *mesh, PnPProblem *pnpProblem, cv::Scalar color)
{
- std::vector<std::vector<int> > list_triangles = mesh->getTrianglesList();
- for( size_t i = 0; i < list_triangles.size(); i++)
- {
- std::vector<int> tmp_triangle = list_triangles.at(i);
-
- cv::Point3f point_3d_0 = mesh->getVertex(tmp_triangle[0]);
- cv::Point3f point_3d_1 = mesh->getVertex(tmp_triangle[1]);
- cv::Point3f point_3d_2 = mesh->getVertex(tmp_triangle[2]);
-
- cv::Point2f point_2d_0 = pnpProblem->backproject3DPoint(point_3d_0);
- cv::Point2f point_2d_1 = pnpProblem->backproject3DPoint(point_3d_1);
- cv::Point2f point_2d_2 = pnpProblem->backproject3DPoint(point_3d_2);
-
- cv::line(image, point_2d_0, point_2d_1, color, 1);
- cv::line(image, point_2d_1, point_2d_2, color, 1);
- cv::line(image, point_2d_2, point_2d_0, color, 1);
- }
+ std::vector<std::vector<int> > list_triangles = mesh->getTrianglesList();
+ for( size_t i = 0; i < list_triangles.size(); i++)
+ {
+ std::vector<int> tmp_triangle = list_triangles.at(i);
+
+ cv::Point3f point_3d_0 = mesh->getVertex(tmp_triangle[0]);
+ cv::Point3f point_3d_1 = mesh->getVertex(tmp_triangle[1]);
+ cv::Point3f point_3d_2 = mesh->getVertex(tmp_triangle[2]);
+
+ cv::Point2f point_2d_0 = pnpProblem->backproject3DPoint(point_3d_0);
+ cv::Point2f point_2d_1 = pnpProblem->backproject3DPoint(point_3d_1);
+ cv::Point2f point_2d_2 = pnpProblem->backproject3DPoint(point_3d_2);
+
+ cv::line(image, point_2d_0, point_2d_1, color, 1);
+ cv::line(image, point_2d_1, point_2d_2, color, 1);
+ cv::line(image, point_2d_2, point_2d_0, color, 1);
+ }
}
// Computes the norm of the translation error
double get_translation_error(const cv::Mat &t_true, const cv::Mat &t)
{
- return cv::norm( t_true - t );
+ return cv::norm( t_true - t );
}
// Computes the norm of the rotation error
double get_rotation_error(const cv::Mat &R_true, const cv::Mat &R)
{
- cv::Mat error_vec, error_mat;
- error_mat = -R_true * R.t();
- cv::Rodrigues(error_mat, error_vec);
+ cv::Mat error_vec, error_mat;
+ error_mat = -R_true * R.t();
+ cv::Rodrigues(error_mat, error_vec);
- return cv::norm(error_vec);
+ return cv::norm(error_vec);
}
// Converts a given Rotation Matrix to Euler angles
// https://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToEuler/index.htm
cv::Mat rot2euler(const cv::Mat & rotationMatrix)
{
- cv::Mat euler(3,1,CV_64F);
-
- double m00 = rotationMatrix.at<double>(0,0);
- double m02 = rotationMatrix.at<double>(0,2);
- double m10 = rotationMatrix.at<double>(1,0);
- double m11 = rotationMatrix.at<double>(1,1);
- double m12 = rotationMatrix.at<double>(1,2);
- double m20 = rotationMatrix.at<double>(2,0);
- double m22 = rotationMatrix.at<double>(2,2);
-
- double bank, attitude, heading;
-
- // Assuming the angles are in radians.
- if (m10 > 0.998) { // singularity at north pole
- bank = 0;
- attitude = CV_PI/2;
- heading = atan2(m02,m22);
- }
- else if (m10 < -0.998) { // singularity at south pole
- bank = 0;
- attitude = -CV_PI/2;
- heading = atan2(m02,m22);
- }
- else
- {
- bank = atan2(-m12,m11);
- attitude = asin(m10);
- heading = atan2(-m20,m00);
- }
-
- euler.at<double>(0) = bank;
- euler.at<double>(1) = attitude;
- euler.at<double>(2) = heading;
-
- return euler;
+ cv::Mat euler(3,1,CV_64F);
+
+ double m00 = rotationMatrix.at<double>(0,0);
+ double m02 = rotationMatrix.at<double>(0,2);
+ double m10 = rotationMatrix.at<double>(1,0);
+ double m11 = rotationMatrix.at<double>(1,1);
+ double m12 = rotationMatrix.at<double>(1,2);
+ double m20 = rotationMatrix.at<double>(2,0);
+ double m22 = rotationMatrix.at<double>(2,2);
+
+ double bank, attitude, heading;
+
+ // Assuming the angles are in radians.
+ if (m10 > 0.998) { // singularity at north pole
+ bank = 0;
+ attitude = CV_PI/2;
+ heading = atan2(m02,m22);
+ }
+ else if (m10 < -0.998) { // singularity at south pole
+ bank = 0;
+ attitude = -CV_PI/2;
+ heading = atan2(m02,m22);
+ }
+ else
+ {
+ bank = atan2(-m12,m11);
+ attitude = asin(m10);
+ heading = atan2(-m20,m00);
+ }
+
+ euler.at<double>(0) = bank;
+ euler.at<double>(1) = attitude;
+ euler.at<double>(2) = heading;
+
+ return euler;
}
// Converts a given Euler angles to Rotation Matrix
// https://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm
cv::Mat euler2rot(const cv::Mat & euler)
{
- cv::Mat rotationMatrix(3,3,CV_64F);
-
- double bank = euler.at<double>(0);
- double attitude = euler.at<double>(1);
- double heading = euler.at<double>(2);
-
- // Assuming the angles are in radians.
- double ch = cos(heading);
- double sh = sin(heading);
- double ca = cos(attitude);
- double sa = sin(attitude);
- double cb = cos(bank);
- double sb = sin(bank);
-
- double m00, m01, m02, m10, m11, m12, m20, m21, m22;
-
- m00 = ch * ca;
- m01 = sh*sb - ch*sa*cb;
- m02 = ch*sa*sb + sh*cb;
- m10 = sa;
- m11 = ca*cb;
- m12 = -ca*sb;
- m20 = -sh*ca;
- m21 = sh*sa*cb + ch*sb;
- m22 = -sh*sa*sb + ch*cb;
-
- rotationMatrix.at<double>(0,0) = m00;
- rotationMatrix.at<double>(0,1) = m01;
- rotationMatrix.at<double>(0,2) = m02;
- rotationMatrix.at<double>(1,0) = m10;
- rotationMatrix.at<double>(1,1) = m11;
- rotationMatrix.at<double>(1,2) = m12;
- rotationMatrix.at<double>(2,0) = m20;
- rotationMatrix.at<double>(2,1) = m21;
- rotationMatrix.at<double>(2,2) = m22;
-
- return rotationMatrix;
+ cv::Mat rotationMatrix(3,3,CV_64F);
+
+ double bank = euler.at<double>(0);
+ double attitude = euler.at<double>(1);
+ double heading = euler.at<double>(2);
+
+ // Assuming the angles are in radians.
+ double ch = cos(heading);
+ double sh = sin(heading);
+ double ca = cos(attitude);
+ double sa = sin(attitude);
+ double cb = cos(bank);
+ double sb = sin(bank);
+
+ double m00, m01, m02, m10, m11, m12, m20, m21, m22;
+
+ m00 = ch * ca;
+ m01 = sh*sb - ch*sa*cb;
+ m02 = ch*sa*sb + sh*cb;
+ m10 = sa;
+ m11 = ca*cb;
+ m12 = -ca*sb;
+ m20 = -sh*ca;
+ m21 = sh*sa*cb + ch*sb;
+ m22 = -sh*sa*sb + ch*cb;
+
+ rotationMatrix.at<double>(0,0) = m00;
+ rotationMatrix.at<double>(0,1) = m01;
+ rotationMatrix.at<double>(0,2) = m02;
+ rotationMatrix.at<double>(1,0) = m10;
+ rotationMatrix.at<double>(1,1) = m11;
+ rotationMatrix.at<double>(1,2) = m12;
+ rotationMatrix.at<double>(2,0) = m20;
+ rotationMatrix.at<double>(2,1) = m21;
+ rotationMatrix.at<double>(2,2) = m22;
+
+ return rotationMatrix;
}
// Converts a given string to an integer
int StringToInt ( const std::string &Text )
{
- std::istringstream ss(Text);
- int result;
- return ss >> result ? result : 0;
+ std::istringstream ss(Text);
+ int result;
+ return ss >> result ? result : 0;
}
// Converts a given float to a string
std::string FloatToString ( float Number )
{
- std::ostringstream ss;
- ss << Number;
- return ss.str();
+ std::ostringstream ss;
+ ss << Number;
+ return ss.str();
}
// Converts a given integer to a string
std::string IntToString ( int Number )
{
- std::ostringstream ss;
- ss << Number;
- return ss.str();
+ std::ostringstream ss;
+ ss << Number;
+ return ss.str();
+}
+
+void createFeatures(const std::string &featureName, int numKeypoints, cv::Ptr<cv::Feature2D> &detector, cv::Ptr<cv::Feature2D> &descriptor)
+{
+ if (featureName == "ORB")
+ {
+ detector = cv::ORB::create(numKeypoints);
+ descriptor = cv::ORB::create(numKeypoints);
+ }
+ else if (featureName == "KAZE")
+ {
+ detector = cv::KAZE::create();
+ descriptor = cv::KAZE::create();
+ }
+ else if (featureName == "AKAZE")
+ {
+ detector = cv::AKAZE::create();
+ descriptor = cv::AKAZE::create();
+ }
+ else if (featureName == "BRISK")
+ {
+ detector = cv::BRISK::create();
+ descriptor = cv::BRISK::create();
+ }
+ else if (featureName == "SIFT")
+ {
+#if defined (OPENCV_ENABLE_NONFREE) && defined (HAVE_OPENCV_XFEATURES2D)
+ detector = cv::xfeatures2d::SIFT::create();
+ descriptor = cv::xfeatures2d::SIFT::create();
+#else
+ std::cout << "xfeatures2d module is not available or nonfree is not enabled." << std::endl;
+ std::cout << "Default to ORB." << std::endl;
+ detector = cv::ORB::create(numKeypoints);
+ descriptor = cv::ORB::create(numKeypoints);
+#endif
+ }
+ else if (featureName == "SURF")
+ {
+#if defined (OPENCV_ENABLE_NONFREE) && defined (HAVE_OPENCV_XFEATURES2D)
+ detector = cv::xfeatures2d::SURF::create(100, 4, 3, true); //extended=true
+ descriptor = cv::xfeatures2d::SURF::create(100, 4, 3, true); //extended=true
+#else
+ std::cout << "xfeatures2d module is not available or nonfree is not enabled." << std::endl;
+ std::cout << "Default to ORB." << std::endl;
+ detector = cv::ORB::create(numKeypoints);
+ descriptor = cv::ORB::create(numKeypoints);
+#endif
+ }
+ else if (featureName == "BINBOOST")
+ {
+#if defined (HAVE_OPENCV_XFEATURES2D)
+ detector = cv::KAZE::create();
+ descriptor = cv::xfeatures2d::BoostDesc::create();
+#else
+ std::cout << "xfeatures2d module is not available." << std::endl;
+ std::cout << "Default to ORB." << std::endl;
+ detector = cv::ORB::create(numKeypoints);
+ descriptor = cv::ORB::create(numKeypoints);
+#endif
+ }
+ else if (featureName == "VGG")
+ {
+#if defined (HAVE_OPENCV_XFEATURES2D)
+ detector = cv::KAZE::create();
+ descriptor = cv::xfeatures2d::VGG::create();
+#else
+ std::cout << "xfeatures2d module is not available." << std::endl;
+ std::cout << "Default to ORB." << std::endl;
+ detector = cv::ORB::create(numKeypoints);
+ descriptor = cv::ORB::create(numKeypoints);
+#endif
+ }
+}
+
+cv::Ptr<cv::DescriptorMatcher> createMatcher(const std::string &featureName, bool useFLANN)
+{
+ if (featureName == "ORB" || featureName == "BRISK" || featureName == "AKAZE" || featureName == "BINBOOST")
+ {
+ if (useFLANN)
+ {
+ cv::Ptr<cv::flann::IndexParams> indexParams = cv::makePtr<cv::flann::LshIndexParams>(6, 12, 1); // instantiate LSH index parameters
+ cv::Ptr<cv::flann::SearchParams> searchParams = cv::makePtr<cv::flann::SearchParams>(50); // instantiate flann search parameters
+ return cv::makePtr<cv::FlannBasedMatcher>(indexParams, searchParams);
+ }
+ else
+ {
+ return cv::DescriptorMatcher::create("BruteForce-Hamming");
+ }
+
+ }
+ else
+ {
+ if (useFLANN)
+ {
+ return cv::DescriptorMatcher::create("FlannBased");
+ }
+ else
+ {
+ return cv::DescriptorMatcher::create("BruteForce");
+ }
+ }
}
#include <iostream>
+#include <opencv2/features2d.hpp>
#include "PnPProblem.h"
// Draw a text with the question point
// Converts a given integer to a string
std::string IntToString ( int Number );
+void createFeatures(const std::string &featureName, int numKeypoints, cv::Ptr<cv::Feature2D> &detector, cv::Ptr<cv::Feature2D> &descriptor);
+
+cv::Ptr<cv::DescriptorMatcher> createMatcher(const std::string &featureName, bool useFLANN);
+
#endif /* UTILS_H_ */
// C++
#include <iostream>
-#include <time.h>
// OpenCV
#include <opencv2/core.hpp>
-#include <opencv2/core/utility.hpp>
+#include <opencv2/core/utils/filesystem.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/calib3d.hpp>
using namespace cv;
using namespace std;
-string tutorial_path = "../../samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/"; // path to tutorial
-
-string video_read_path = tutorial_path + "Data/box.mp4"; // recorded video
-string yml_read_path = tutorial_path + "Data/cookies_ORB.yml"; // 3dpts + descriptors
-string ply_read_path = tutorial_path + "Data/box.ply"; // mesh
-
-// Intrinsic camera parameters: UVC WEBCAM
-double f = 55; // focal length in mm
-double sx = 22.3, sy = 14.9; // sensor size
-double width = 640, height = 480; // image size
-
-double params_WEBCAM[] = { width*f/sx, // fx
- height*f/sy, // fy
- width/2, // cx
- height/2}; // cy
-
-// Some basic colors
-Scalar red(0, 0, 255);
-Scalar green(0,255,0);
-Scalar blue(255,0,0);
-Scalar yellow(0,255,255);
-
-
-// Robust Matcher parameters
-int numKeyPoints = 2000; // number of detected keypoints
-float ratioTest = 0.70f; // ratio test
-bool fast_match = true; // fastRobustMatch() or robustMatch()
-
-// RANSAC parameters
-int iterationsCount = 500; // number of Ransac iterations.
-float reprojectionError = 2.0; // maximum allowed distance to consider it an inlier.
-double confidence = 0.95; // ransac successful confidence.
-
-// Kalman Filter parameters
-int minInliersKalman = 30; // Kalman threshold updating
-
-// PnP parameters
-int pnpMethod = SOLVEPNP_ITERATIVE;
-
-
/** Functions headers **/
void help();
void initKalmanFilter( KalmanFilter &KF, int nStates, int nMeasurements, int nInputs, double dt);
+void predictKalmanFilter( KalmanFilter &KF, Mat &translation_predicted, Mat &rotation_predicted );
void updateKalmanFilter( KalmanFilter &KF, Mat &measurements,
Mat &translation_estimated, Mat &rotation_estimated );
void fillMeasurements( Mat &measurements,
const Mat &translation_measured, const Mat &rotation_measured);
-
/** Main program **/
int main(int argc, char *argv[])
{
-
- help();
-
- const String keys =
- "{help h | | print this message }"
- "{video v | | path to recorded video }"
- "{model | | path to yml model }"
- "{mesh | | path to ply mesh }"
- "{keypoints k |2000 | number of keypoints to detect }"
- "{ratio r |0.7 | threshold for ratio test }"
- "{iterations it |500 | RANSAC maximum iterations count }"
- "{error e |2.0 | RANSAC reprojection error }"
- "{confidence c |0.95 | RANSAC confidence }"
- "{inliers in |30 | minimum inliers for Kalman update }"
- "{method pnp |0 | PnP method: (0) ITERATIVE - (1) EPNP - (2) P3P - (3) DLS}"
- "{fast f |true | use of robust fast match }"
- ;
- CommandLineParser parser(argc, argv, keys);
-
- if (parser.has("help"))
- {
- parser.printMessage();
- return 0;
- }
- else
- {
- video_read_path = parser.get<string>("video").size() > 0 ? parser.get<string>("video") : video_read_path;
- yml_read_path = parser.get<string>("model").size() > 0 ? parser.get<string>("model") : yml_read_path;
- ply_read_path = parser.get<string>("mesh").size() > 0 ? parser.get<string>("mesh") : ply_read_path;
- numKeyPoints = !parser.has("keypoints") ? parser.get<int>("keypoints") : numKeyPoints;
- ratioTest = !parser.has("ratio") ? parser.get<float>("ratio") : ratioTest;
- fast_match = !parser.has("fast") ? parser.get<bool>("fast") : fast_match;
- iterationsCount = !parser.has("iterations") ? parser.get<int>("iterations") : iterationsCount;
- reprojectionError = !parser.has("error") ? parser.get<float>("error") : reprojectionError;
- confidence = !parser.has("confidence") ? parser.get<float>("confidence") : confidence;
- minInliersKalman = !parser.has("inliers") ? parser.get<int>("inliers") : minInliersKalman;
- pnpMethod = !parser.has("method") ? parser.get<int>("method") : pnpMethod;
- }
-
- PnPProblem pnp_detection(params_WEBCAM);
- PnPProblem pnp_detection_est(params_WEBCAM);
-
- Model model; // instantiate Model object
- model.load(yml_read_path); // load a 3D textured object model
-
- Mesh mesh; // instantiate Mesh object
- mesh.load(ply_read_path); // load an object mesh
-
- RobustMatcher rmatcher; // instantiate RobustMatcher
-
- Ptr<FeatureDetector> orb = ORB::create();
-
- rmatcher.setFeatureDetector(orb); // set feature detector
- rmatcher.setDescriptorExtractor(orb); // set descriptor extractor
-
- Ptr<flann::IndexParams> indexParams = makePtr<flann::LshIndexParams>(6, 12, 1); // instantiate LSH index parameters
- Ptr<flann::SearchParams> searchParams = makePtr<flann::SearchParams>(50); // instantiate flann search parameters
-
- // instantiate FlannBased matcher
- Ptr<DescriptorMatcher> matcher = makePtr<FlannBasedMatcher>(indexParams, searchParams);
- rmatcher.setDescriptorMatcher(matcher); // set matcher
- rmatcher.setRatio(ratioTest); // set ratio test parameter
-
- KalmanFilter KF; // instantiate Kalman Filter
- int nStates = 18; // the number of states
- int nMeasurements = 6; // the number of measured states
- int nInputs = 0; // the number of control actions
- double dt = 0.125; // time between measurements (1/FPS)
-
- initKalmanFilter(KF, nStates, nMeasurements, nInputs, dt); // init function
- Mat measurements(nMeasurements, 1, CV_64F); measurements.setTo(Scalar(0));
- bool good_measurement = false;
-
-
- // Get the MODEL INFO
- vector<Point3f> list_points3d_model = model.get_points3d(); // list with model 3D coordinates
- Mat descriptors_model = model.get_descriptors(); // list with descriptors of each 3D coordinate
-
-
- // Create & Open Window
- namedWindow("REAL TIME DEMO", WINDOW_KEEPRATIO);
-
-
- VideoCapture cap; // instantiate VideoCapture
- cap.open(video_read_path); // open a recorded video
-
- if(!cap.isOpened()) // check if we succeeded
- {
- cout << "Could not open the camera device" << endl;
- return -1;
- }
-
- // start and end times
- time_t start, end;
-
- // fps calculated using number of frames / seconds
- // floating point seconds elapsed since start
- double fps, sec;
-
- // frame counter
- int counter = 0;
-
- // start the clock
- time(&start);
-
- Mat frame, frame_vis;
-
- while(cap.read(frame) && (char)waitKey(30) != 27) // capture frame until ESC is pressed
- {
-
- frame_vis = frame.clone(); // refresh visualisation frame
-
-
- // -- Step 1: Robust matching between model descriptors and scene descriptors
-
- vector<DMatch> good_matches; // to obtain the 3D points of the model
- vector<KeyPoint> keypoints_scene; // to obtain the 2D points of the scene
-
-
- if(fast_match)
+ help();
+
+ const String keys =
+ "{help h | | print this message }"
+ "{video v | | path to recorded video }"
+ "{model | | path to yml model }"
+ "{mesh | | path to ply mesh }"
+ "{keypoints k |2000 | number of keypoints to detect }"
+ "{ratio r |0.7 | threshold for ratio test }"
+ "{iterations it |500 | RANSAC maximum iterations count }"
+ "{error e |6.0 | RANSAC reprojection error }"
+ "{confidence c |0.99 | RANSAC confidence }"
+ "{inliers in |30 | minimum inliers for Kalman update }"
+ "{method pnp |0 | PnP method: (0) ITERATIVE - (1) EPNP - (2) P3P - (3) DLS - (5) AP3P}"
+ "{fast f |true | use of robust fast match }"
+ "{feature |ORB | feature name (ORB, KAZE, AKAZE, BRISK, SIFT, SURF, BINBOOST, VGG) }"
+ "{FLANN |false | use FLANN library for descriptors matching }"
+ "{save | | path to the directory where to save the image results }"
+ "{displayFiltered |false | display filtered pose (from Kalman filter) }"
+ ;
+ CommandLineParser parser(argc, argv, keys);
+
+ string video_read_path = samples::findFile("samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/Data/box.mp4"); // recorded video
+ string yml_read_path = samples::findFile("samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/Data/cookies_ORB.yml"); // 3dpts + descriptors
+ string ply_read_path = samples::findFile("samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/Data/box.ply"); // mesh
+
+ // Intrinsic camera parameters: UVC WEBCAM
+ double f = 55; // focal length in mm
+ double sx = 22.3, sy = 14.9; // sensor size
+ double width = 640, height = 480; // image size
+
+ double params_WEBCAM[] = { width*f/sx, // fx
+ height*f/sy, // fy
+ width/2, // cx
+ height/2}; // cy
+
+ // Some basic colors
+ Scalar red(0, 0, 255);
+ Scalar green(0,255,0);
+ Scalar blue(255,0,0);
+ Scalar yellow(0,255,255);
+
+ // Robust Matcher parameters
+ int numKeyPoints = 2000; // number of detected keypoints
+ float ratioTest = 0.70f; // ratio test
+ bool fast_match = true; // fastRobustMatch() or robustMatch()
+
+ // RANSAC parameters
+ int iterationsCount = 500; // number of Ransac iterations.
+ float reprojectionError = 6.0; // maximum allowed distance to consider it an inlier.
+ double confidence = 0.99; // ransac successful confidence.
+
+ // Kalman Filter parameters
+ int minInliersKalman = 30; // Kalman threshold updating
+
+ // PnP parameters
+ int pnpMethod = SOLVEPNP_ITERATIVE;
+ string featureName = "ORB";
+ bool useFLANN = false;
+
+ // Save results
+ string saveDirectory = "";
+ Mat frameSave;
+ int frameCount = 0;
+
+ bool displayFilteredPose = false;
+
+ if (parser.has("help"))
{
- rmatcher.fastRobustMatch(frame, good_matches, keypoints_scene, descriptors_model);
+ parser.printMessage();
+ return 0;
}
else
{
- rmatcher.robustMatch(frame, good_matches, keypoints_scene, descriptors_model);
+ video_read_path = parser.get<string>("video").size() > 0 ? parser.get<string>("video") : video_read_path;
+ yml_read_path = parser.get<string>("model").size() > 0 ? parser.get<string>("model") : yml_read_path;
+ ply_read_path = parser.get<string>("mesh").size() > 0 ? parser.get<string>("mesh") : ply_read_path;
+ numKeyPoints = parser.has("keypoints") ? parser.get<int>("keypoints") : numKeyPoints;
+ ratioTest = parser.has("ratio") ? parser.get<float>("ratio") : ratioTest;
+ fast_match = parser.has("fast") ? parser.get<bool>("fast") : fast_match;
+ iterationsCount = parser.has("iterations") ? parser.get<int>("iterations") : iterationsCount;
+ reprojectionError = parser.has("error") ? parser.get<float>("error") : reprojectionError;
+ confidence = parser.has("confidence") ? parser.get<float>("confidence") : confidence;
+ minInliersKalman = parser.has("inliers") ? parser.get<int>("inliers") : minInliersKalman;
+ pnpMethod = parser.has("method") ? parser.get<int>("method") : pnpMethod;
+ featureName = parser.has("feature") ? parser.get<string>("feature") : featureName;
+ useFLANN = parser.has("FLANN") ? parser.get<bool>("FLANN") : useFLANN;
+ saveDirectory = parser.has("save") ? parser.get<string>("save") : saveDirectory;
+ displayFilteredPose = parser.has("displayFiltered") ? parser.get<bool>("displayFiltered") : displayFilteredPose;
}
-
- // -- Step 2: Find out the 2D/3D correspondences
-
- vector<Point3f> list_points3d_model_match; // container for the model 3D coordinates found in the scene
- vector<Point2f> list_points2d_scene_match; // container for the model 2D coordinates found in the scene
-
- for(unsigned int match_index = 0; match_index < good_matches.size(); ++match_index)
+ std::cout << "Video: " << video_read_path << std::endl;
+ std::cout << "Training data: " << yml_read_path << std::endl;
+ std::cout << "CAD model: " << ply_read_path << std::endl;
+ std::cout << "Ratio test threshold: " << ratioTest << std::endl;
+ std::cout << "Fast match(no symmetry test)?: " << fast_match << std::endl;
+ std::cout << "RANSAC number of iterations: " << iterationsCount << std::endl;
+ std::cout << "RANSAC reprojection error: " << reprojectionError << std::endl;
+ std::cout << "RANSAC confidence threshold: " << confidence << std::endl;
+ std::cout << "Kalman number of inliers: " << minInliersKalman << std::endl;
+ std::cout << "PnP method: " << pnpMethod << std::endl;
+ std::cout << "Feature: " << featureName << std::endl;
+ std::cout << "Number of keypoints for ORB: " << numKeyPoints << std::endl;
+ std::cout << "Use FLANN-based matching? " << useFLANN << std::endl;
+ std::cout << "Save directory: " << saveDirectory << std::endl;
+ std::cout << "Display filtered pose from Kalman filter? " << displayFilteredPose << std::endl;
+
+ PnPProblem pnp_detection(params_WEBCAM);
+ PnPProblem pnp_detection_est(params_WEBCAM);
+
+ Model model; // instantiate Model object
+ model.load(yml_read_path); // load a 3D textured object model
+
+ Mesh mesh; // instantiate Mesh object
+ mesh.load(ply_read_path); // load an object mesh
+
+ RobustMatcher rmatcher; // instantiate RobustMatcher
+
+ Ptr<FeatureDetector> detector, descriptor;
+ createFeatures(featureName, numKeyPoints, detector, descriptor);
+ rmatcher.setFeatureDetector(detector); // set feature detector
+ rmatcher.setDescriptorExtractor(descriptor); // set descriptor extractor
+ rmatcher.setDescriptorMatcher(createMatcher(featureName, useFLANN)); // set matcher
+ rmatcher.setRatio(ratioTest); // set ratio test parameter
+ if (!model.get_trainingImagePath().empty())
{
- Point3f point3d_model = list_points3d_model[ good_matches[match_index].trainIdx ]; // 3D point from model
- Point2f point2d_scene = keypoints_scene[ good_matches[match_index].queryIdx ].pt; // 2D point from the scene
- list_points3d_model_match.push_back(point3d_model); // add 3D point
- list_points2d_scene_match.push_back(point2d_scene); // add 2D point
+ Mat trainingImg = imread(model.get_trainingImagePath());
+ rmatcher.setTrainingImage(trainingImg);
}
- // Draw outliers
- draw2DPoints(frame_vis, list_points2d_scene_match, red);
-
-
- Mat inliers_idx;
- vector<Point2f> list_points2d_inliers;
-
- if(good_matches.size() >= 4) // OpenCV requires solvePnPRANSAC to minimally have 4 set of points
- {
-
- // -- Step 3: Estimate the pose using RANSAC approach
- pnp_detection.estimatePoseRANSAC( list_points3d_model_match, list_points2d_scene_match,
- pnpMethod, inliers_idx,
- iterationsCount, reprojectionError, confidence );
-
- // -- Step 4: Catch the inliers keypoints to draw
- for(int inliers_index = 0; inliers_index < inliers_idx.rows; ++inliers_index)
- {
- int n = inliers_idx.at<int>(inliers_index); // i-inlier
- Point2f point2d = list_points2d_scene_match[n]; // i-inlier point 2D
- list_points2d_inliers.push_back(point2d); // add i-inlier to list
- }
-
- // Draw inliers points 2D
- draw2DPoints(frame_vis, list_points2d_inliers, blue);
+ KalmanFilter KF; // instantiate Kalman Filter
+ int nStates = 18; // the number of states
+ int nMeasurements = 6; // the number of measured states
+ int nInputs = 0; // the number of control actions
+ double dt = 0.125; // time between measurements (1/FPS)
+ initKalmanFilter(KF, nStates, nMeasurements, nInputs, dt); // init function
+ Mat measurements(nMeasurements, 1, CV_64FC1); measurements.setTo(Scalar(0));
+ bool good_measurement = false;
- // -- Step 5: Kalman Filter
+ // Get the MODEL INFO
+ vector<Point3f> list_points3d_model = model.get_points3d(); // list with model 3D coordinates
+ Mat descriptors_model = model.get_descriptors(); // list with descriptors of each 3D coordinate
+ vector<KeyPoint> keypoints_model = model.get_keypoints();
- good_measurement = false;
+ // Create & Open Window
+ namedWindow("REAL TIME DEMO", WINDOW_KEEPRATIO);
- // GOOD MEASUREMENT
- if( inliers_idx.rows >= minInliersKalman )
- {
+ VideoCapture cap; // instantiate VideoCapture
+ cap.open(video_read_path); // open a recorded video
- // Get the measured translation
- Mat translation_measured(3, 1, CV_64F);
- translation_measured = pnp_detection.get_t_matrix();
-
- // Get the measured rotation
- Mat rotation_measured(3, 3, CV_64F);
- rotation_measured = pnp_detection.get_R_matrix();
-
- // fill the measurements vector
- fillMeasurements(measurements, translation_measured, rotation_measured);
-
- good_measurement = true;
-
- }
-
- // Instantiate estimated translation and rotation
- Mat translation_estimated(3, 1, CV_64F);
- Mat rotation_estimated(3, 3, CV_64F);
-
- // update the Kalman filter with good measurements
- updateKalmanFilter( KF, measurements,
- translation_estimated, rotation_estimated);
-
-
- // -- Step 6: Set estimated projection matrix
- pnp_detection_est.set_P_matrix(rotation_estimated, translation_estimated);
-
- }
-
- // -- Step X: Draw pose
-
- if(good_measurement)
+ if(!cap.isOpened()) // check if we succeeded
{
- drawObjectMesh(frame_vis, &mesh, &pnp_detection, green); // draw current pose
+ cout << "Could not open the camera device" << endl;
+ return -1;
}
- else
+
+ if (!saveDirectory.empty())
{
- drawObjectMesh(frame_vis, &mesh, &pnp_detection_est, yellow); // draw estimated pose
+ if (!cv::utils::fs::exists(saveDirectory))
+ {
+ std::cout << "Create directory: " << saveDirectory << std::endl;
+ cv::utils::fs::createDirectories(saveDirectory);
+ }
}
- float l = 5;
- vector<Point2f> pose_points2d;
- pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,0,0))); // axis center
- pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(l,0,0))); // axis x
- pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,l,0))); // axis y
- pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,0,l))); // axis z
- draw3DCoordinateAxes(frame_vis, pose_points2d); // draw axes
-
- // FRAME RATE
-
- // see how much time has elapsed
- time(&end);
-
- // calculate current FPS
- ++counter;
- sec = difftime (end, start);
-
- fps = counter / sec;
-
- drawFPS(frame_vis, fps, yellow); // frame ratio
- double detection_ratio = ((double)inliers_idx.rows/(double)good_matches.size())*100;
- drawConfidence(frame_vis, detection_ratio, yellow);
-
+ // Measure elapsed time
+ TickMeter tm;
- // -- Step X: Draw some debugging text
-
- // Draw some debug text
- int inliers_int = inliers_idx.rows;
- int outliers_int = (int)good_matches.size() - inliers_int;
- string inliers_str = IntToString(inliers_int);
- string outliers_str = IntToString(outliers_int);
- string n = IntToString((int)good_matches.size());
- string text = "Found " + inliers_str + " of " + n + " matches";
- string text2 = "Inliers: " + inliers_str + " - Outliers: " + outliers_str;
-
- drawText(frame_vis, text, green);
- drawText2(frame_vis, text2, red);
-
- imshow("REAL TIME DEMO", frame_vis);
- }
-
- // Close and Destroy Window
- destroyWindow("REAL TIME DEMO");
+ Mat frame, frame_vis, frame_matching;
+ while(cap.read(frame) && (char)waitKey(30) != 27) // capture frame until ESC is pressed
+ {
+ tm.reset();
+ tm.start();
+ frame_vis = frame.clone(); // refresh visualisation frame
+
+ // -- Step 1: Robust matching between model descriptors and scene descriptors
+ vector<DMatch> good_matches; // to obtain the 3D points of the model
+ vector<KeyPoint> keypoints_scene; // to obtain the 2D points of the scene
+
+ if(fast_match)
+ {
+ rmatcher.fastRobustMatch(frame, good_matches, keypoints_scene, descriptors_model, keypoints_model);
+ }
+ else
+ {
+ rmatcher.robustMatch(frame, good_matches, keypoints_scene, descriptors_model, keypoints_model);
+ }
+
+ frame_matching = rmatcher.getImageMatching();
+ if (!frame_matching.empty())
+ {
+ imshow("Keypoints matching", frame_matching);
+ }
+
+ // -- Step 2: Find out the 2D/3D correspondences
+ vector<Point3f> list_points3d_model_match; // container for the model 3D coordinates found in the scene
+ vector<Point2f> list_points2d_scene_match; // container for the model 2D coordinates found in the scene
+
+ for(unsigned int match_index = 0; match_index < good_matches.size(); ++match_index)
+ {
+ Point3f point3d_model = list_points3d_model[ good_matches[match_index].trainIdx ]; // 3D point from model
+ Point2f point2d_scene = keypoints_scene[ good_matches[match_index].queryIdx ].pt; // 2D point from the scene
+ list_points3d_model_match.push_back(point3d_model); // add 3D point
+ list_points2d_scene_match.push_back(point2d_scene); // add 2D point
+ }
+
+ // Draw outliers
+ draw2DPoints(frame_vis, list_points2d_scene_match, red);
+
+ Mat inliers_idx;
+ vector<Point2f> list_points2d_inliers;
+
+ // Instantiate estimated translation and rotation
+ good_measurement = false;
+
+ if(good_matches.size() >= 4) // OpenCV requires solvePnPRANSAC to minimally have 4 set of points
+ {
+ // -- Step 3: Estimate the pose using RANSAC approach
+ pnp_detection.estimatePoseRANSAC( list_points3d_model_match, list_points2d_scene_match,
+ pnpMethod, inliers_idx,
+ iterationsCount, reprojectionError, confidence );
+
+ // -- Step 4: Catch the inliers keypoints to draw
+ for(int inliers_index = 0; inliers_index < inliers_idx.rows; ++inliers_index)
+ {
+ int n = inliers_idx.at<int>(inliers_index); // i-inlier
+ Point2f point2d = list_points2d_scene_match[n]; // i-inlier point 2D
+ list_points2d_inliers.push_back(point2d); // add i-inlier to list
+ }
+
+ // Draw inliers points 2D
+ draw2DPoints(frame_vis, list_points2d_inliers, blue);
+
+ // -- Step 5: Kalman Filter
+
+ // GOOD MEASUREMENT
+ if( inliers_idx.rows >= minInliersKalman )
+ {
+ // Get the measured translation
+ Mat translation_measured = pnp_detection.get_t_matrix();
+
+ // Get the measured rotation
+ Mat rotation_measured = pnp_detection.get_R_matrix();
+
+ // fill the measurements vector
+ fillMeasurements(measurements, translation_measured, rotation_measured);
+ good_measurement = true;
+ }
+
+ // update the Kalman filter with good measurements, otherwise with previous valid measurements
+ Mat translation_estimated(3, 1, CV_64FC1);
+ Mat rotation_estimated(3, 3, CV_64FC1);
+ updateKalmanFilter( KF, measurements,
+ translation_estimated, rotation_estimated);
+
+ // -- Step 6: Set estimated projection matrix
+ pnp_detection_est.set_P_matrix(rotation_estimated, translation_estimated);
+ }
+
+ // -- Step X: Draw pose and coordinate frame
+ float l = 5;
+ vector<Point2f> pose_points2d;
+ if (!good_measurement || displayFilteredPose)
+ {
+ drawObjectMesh(frame_vis, &mesh, &pnp_detection_est, yellow); // draw estimated pose
+
+ pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,0,0))); // axis center
+ pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(l,0,0))); // axis x
+ pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,l,0))); // axis y
+ pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,0,l))); // axis z
+ draw3DCoordinateAxes(frame_vis, pose_points2d); // draw axes
+ }
+ else
+ {
+ drawObjectMesh(frame_vis, &mesh, &pnp_detection, green); // draw current pose
+
+ pose_points2d.push_back(pnp_detection.backproject3DPoint(Point3f(0,0,0))); // axis center
+ pose_points2d.push_back(pnp_detection.backproject3DPoint(Point3f(l,0,0))); // axis x
+ pose_points2d.push_back(pnp_detection.backproject3DPoint(Point3f(0,l,0))); // axis y
+ pose_points2d.push_back(pnp_detection.backproject3DPoint(Point3f(0,0,l))); // axis z
+ draw3DCoordinateAxes(frame_vis, pose_points2d); // draw axes
+ }
+
+ // FRAME RATE
+ // see how much time has elapsed
+ tm.stop();
+
+ // calculate current FPS
+ double fps = 1.0 / tm.getTimeSec();
+
+ drawFPS(frame_vis, fps, yellow); // frame ratio
+ double detection_ratio = ((double)inliers_idx.rows/(double)good_matches.size())*100;
+ drawConfidence(frame_vis, detection_ratio, yellow);
+
+ // -- Step X: Draw some debugging text
+ // Draw some debug text
+ int inliers_int = inliers_idx.rows;
+ int outliers_int = (int)good_matches.size() - inliers_int;
+ string inliers_str = IntToString(inliers_int);
+ string outliers_str = IntToString(outliers_int);
+ string n = IntToString((int)good_matches.size());
+ string text = "Found " + inliers_str + " of " + n + " matches";
+ string text2 = "Inliers: " + inliers_str + " - Outliers: " + outliers_str;
+
+ drawText(frame_vis, text, green);
+ drawText2(frame_vis, text2, red);
+
+ imshow("REAL TIME DEMO", frame_vis);
+
+ if (!saveDirectory.empty())
+ {
+ const int widthSave = !frame_matching.empty() ? frame_matching.cols : frame_vis.cols;
+ const int heightSave = !frame_matching.empty() ? frame_matching.rows + frame_vis.rows : frame_vis.rows;
+ frameSave = Mat::zeros(heightSave, widthSave, CV_8UC3);
+ if (!frame_matching.empty())
+ {
+ int startX = (int)((widthSave - frame_vis.cols) / 2.0);
+ Mat roi = frameSave(Rect(startX, 0, frame_vis.cols, frame_vis.rows));
+ frame_vis.copyTo(roi);
+
+ roi = frameSave(Rect(0, frame_vis.rows, frame_matching.cols, frame_matching.rows));
+ frame_matching.copyTo(roi);
+ }
+ else
+ {
+ frame_vis.copyTo(frameSave);
+ }
+
+ string saveFilename = format(string(saveDirectory + "/image_%04d.png").c_str(), frameCount);
+ imwrite(saveFilename, frameSave);
+ frameCount++;
+ }
+ }
- cout << "GOODBYE ..." << endl;
+ // Close and Destroy Window
+ destroyWindow("REAL TIME DEMO");
+ cout << "GOODBYE ..." << endl;
}
/**********************************************************************************************************/
void help()
{
-cout
-<< "--------------------------------------------------------------------------" << endl
-<< "This program shows how to detect an object given its 3D textured model. You can choose to "
-<< "use a recorded video or the webcam." << endl
-<< "Usage:" << endl
-<< "./cpp-tutorial-pnp_detection -help" << endl
-<< "Keys:" << endl
-<< "'esc' - to quit." << endl
-<< "--------------------------------------------------------------------------" << endl
-<< endl;
+ cout
+ << "--------------------------------------------------------------------------" << endl
+ << "This program shows how to detect an object given its 3D textured model. You can choose to "
+ << "use a recorded video or the webcam." << endl
+ << "Usage:" << endl
+ << "./cpp-tutorial-pnp_detection -help" << endl
+ << "Keys:" << endl
+ << "'esc' - to quit." << endl
+ << "--------------------------------------------------------------------------" << endl
+ << endl;
}
/**********************************************************************************************************/
void initKalmanFilter(KalmanFilter &KF, int nStates, int nMeasurements, int nInputs, double dt)
{
-
- KF.init(nStates, nMeasurements, nInputs, CV_64F); // init Kalman Filter
-
- setIdentity(KF.processNoiseCov, Scalar::all(1e-5)); // set process noise
- setIdentity(KF.measurementNoiseCov, Scalar::all(1e-2)); // set measurement noise
- setIdentity(KF.errorCovPost, Scalar::all(1)); // error covariance
-
-
- /** DYNAMIC MODEL **/
-
- // [1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0 0 0]
- // [0 1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0 0]
- // [0 0 1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0]
- // [0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0 0 0]
- // [0 0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0 0]
- // [0 0 0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0]
- // [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0]
- // [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0]
- // [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]
- // [0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2 0 0]
- // [0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2 0]
- // [0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2]
- // [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0]
- // [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0]
- // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt]
- // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0]
- // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0]
- // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]
-
- // position
- KF.transitionMatrix.at<double>(0,3) = dt;
- KF.transitionMatrix.at<double>(1,4) = dt;
- KF.transitionMatrix.at<double>(2,5) = dt;
- KF.transitionMatrix.at<double>(3,6) = dt;
- KF.transitionMatrix.at<double>(4,7) = dt;
- KF.transitionMatrix.at<double>(5,8) = dt;
- KF.transitionMatrix.at<double>(0,6) = 0.5*pow(dt,2);
- KF.transitionMatrix.at<double>(1,7) = 0.5*pow(dt,2);
- KF.transitionMatrix.at<double>(2,8) = 0.5*pow(dt,2);
-
- // orientation
- KF.transitionMatrix.at<double>(9,12) = dt;
- KF.transitionMatrix.at<double>(10,13) = dt;
- KF.transitionMatrix.at<double>(11,14) = dt;
- KF.transitionMatrix.at<double>(12,15) = dt;
- KF.transitionMatrix.at<double>(13,16) = dt;
- KF.transitionMatrix.at<double>(14,17) = dt;
- KF.transitionMatrix.at<double>(9,15) = 0.5*pow(dt,2);
- KF.transitionMatrix.at<double>(10,16) = 0.5*pow(dt,2);
- KF.transitionMatrix.at<double>(11,17) = 0.5*pow(dt,2);
-
-
- /** MEASUREMENT MODEL **/
-
- // [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
- // [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
- // [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
- // [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0]
- // [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0]
- // [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0]
-
- KF.measurementMatrix.at<double>(0,0) = 1; // x
- KF.measurementMatrix.at<double>(1,1) = 1; // y
- KF.measurementMatrix.at<double>(2,2) = 1; // z
- KF.measurementMatrix.at<double>(3,9) = 1; // roll
- KF.measurementMatrix.at<double>(4,10) = 1; // pitch
- KF.measurementMatrix.at<double>(5,11) = 1; // yaw
-
+ KF.init(nStates, nMeasurements, nInputs, CV_64F); // init Kalman Filter
+
+ setIdentity(KF.processNoiseCov, Scalar::all(1e-5)); // set process noise
+ setIdentity(KF.measurementNoiseCov, Scalar::all(1e-2)); // set measurement noise
+ setIdentity(KF.errorCovPost, Scalar::all(1)); // error covariance
+
+ /** DYNAMIC MODEL **/
+
+ // [1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0 0 0]
+ // [0 1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0 0]
+ // [0 0 1 0 0 dt 0 0 dt2 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 1 0 0 dt 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2 0 0]
+ // [0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2 0]
+ // [0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0 dt2]
+ // [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0 0]
+ // [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt 0]
+ // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 dt]
+ // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0]
+ // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0]
+ // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]
+
+ // position
+ KF.transitionMatrix.at<double>(0,3) = dt;
+ KF.transitionMatrix.at<double>(1,4) = dt;
+ KF.transitionMatrix.at<double>(2,5) = dt;
+ KF.transitionMatrix.at<double>(3,6) = dt;
+ KF.transitionMatrix.at<double>(4,7) = dt;
+ KF.transitionMatrix.at<double>(5,8) = dt;
+ KF.transitionMatrix.at<double>(0,6) = 0.5*pow(dt,2);
+ KF.transitionMatrix.at<double>(1,7) = 0.5*pow(dt,2);
+ KF.transitionMatrix.at<double>(2,8) = 0.5*pow(dt,2);
+
+ // orientation
+ KF.transitionMatrix.at<double>(9,12) = dt;
+ KF.transitionMatrix.at<double>(10,13) = dt;
+ KF.transitionMatrix.at<double>(11,14) = dt;
+ KF.transitionMatrix.at<double>(12,15) = dt;
+ KF.transitionMatrix.at<double>(13,16) = dt;
+ KF.transitionMatrix.at<double>(14,17) = dt;
+ KF.transitionMatrix.at<double>(9,15) = 0.5*pow(dt,2);
+ KF.transitionMatrix.at<double>(10,16) = 0.5*pow(dt,2);
+ KF.transitionMatrix.at<double>(11,17) = 0.5*pow(dt,2);
+
+
+ /** MEASUREMENT MODEL **/
+
+ // [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
+ // [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
+ // [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0]
+ // [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0]
+
+ KF.measurementMatrix.at<double>(0,0) = 1; // x
+ KF.measurementMatrix.at<double>(1,1) = 1; // y
+ KF.measurementMatrix.at<double>(2,2) = 1; // z
+ KF.measurementMatrix.at<double>(3,9) = 1; // roll
+ KF.measurementMatrix.at<double>(4,10) = 1; // pitch
+ KF.measurementMatrix.at<double>(5,11) = 1; // yaw
}
/**********************************************************************************************************/
void updateKalmanFilter( KalmanFilter &KF, Mat &measurement,
Mat &translation_estimated, Mat &rotation_estimated )
{
+ // First predict, to update the internal statePre variable
+ Mat prediction = KF.predict();
- // First predict, to update the internal statePre variable
- Mat prediction = KF.predict();
-
- // The "correct" phase that is going to use the predicted value and our measurement
- Mat estimated = KF.correct(measurement);
-
- // Estimated translation
- translation_estimated.at<double>(0) = estimated.at<double>(0);
- translation_estimated.at<double>(1) = estimated.at<double>(1);
- translation_estimated.at<double>(2) = estimated.at<double>(2);
+ // The "correct" phase that is going to use the predicted value and our measurement
+ Mat estimated = KF.correct(measurement);
- // Estimated euler angles
- Mat eulers_estimated(3, 1, CV_64F);
- eulers_estimated.at<double>(0) = estimated.at<double>(9);
- eulers_estimated.at<double>(1) = estimated.at<double>(10);
- eulers_estimated.at<double>(2) = estimated.at<double>(11);
+ // Estimated translation
+ translation_estimated.at<double>(0) = estimated.at<double>(0);
+ translation_estimated.at<double>(1) = estimated.at<double>(1);
+ translation_estimated.at<double>(2) = estimated.at<double>(2);
- // Convert estimated quaternion to rotation matrix
- rotation_estimated = euler2rot(eulers_estimated);
+ // Estimated euler angles
+ Mat eulers_estimated(3, 1, CV_64F);
+ eulers_estimated.at<double>(0) = estimated.at<double>(9);
+ eulers_estimated.at<double>(1) = estimated.at<double>(10);
+ eulers_estimated.at<double>(2) = estimated.at<double>(11);
+ // Convert estimated quaternion to rotation matrix
+ rotation_estimated = euler2rot(eulers_estimated);
}
/**********************************************************************************************************/
void fillMeasurements( Mat &measurements,
const Mat &translation_measured, const Mat &rotation_measured)
{
- // Convert rotation matrix to euler angles
- Mat measured_eulers(3, 1, CV_64F);
- measured_eulers = rot2euler(rotation_measured);
-
- // Set measurement to predict
- measurements.at<double>(0) = translation_measured.at<double>(0); // x
- measurements.at<double>(1) = translation_measured.at<double>(1); // y
- measurements.at<double>(2) = translation_measured.at<double>(2); // z
- measurements.at<double>(3) = measured_eulers.at<double>(0); // roll
- measurements.at<double>(4) = measured_eulers.at<double>(1); // pitch
- measurements.at<double>(5) = measured_eulers.at<double>(2); // yaw
+ // Convert rotation matrix to euler angles
+ Mat measured_eulers(3, 1, CV_64F);
+ measured_eulers = rot2euler(rotation_measured);
+
+ // Set measurement to predict
+ measurements.at<double>(0) = translation_measured.at<double>(0); // x
+ measurements.at<double>(1) = translation_measured.at<double>(1); // y
+ measurements.at<double>(2) = translation_measured.at<double>(2); // z
+ measurements.at<double>(3) = measured_eulers.at<double>(0); // roll
+ measurements.at<double>(4) = measured_eulers.at<double>(1); // pitch
+ measurements.at<double>(5) = measured_eulers.at<double>(2); // yaw
}
/** GLOBAL VARIABLES **/
-string tutorial_path = "../../samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/"; // path to tutorial
-
-string img_path = tutorial_path + "Data/resized_IMG_3875.JPG"; // image to register
-string ply_read_path = tutorial_path + "Data/box.ply"; // object mesh
-string write_path = tutorial_path + "Data/cookies_ORB.yml"; // output file
-
// Boolean the know if the registration it's done
bool end_registration = false;
// Intrinsic camera parameters: UVC WEBCAM
-double f = 45; // focal length in mm
-double sx = 22.3, sy = 14.9;
-double width = 2592, height = 1944;
-double params_CANON[] = { width*f/sx, // fx
- height*f/sy, // fy
- width/2, // cx
- height/2}; // cy
+const double f = 45; // focal length in mm
+const double sx = 22.3, sy = 14.9;
+const double width = 2592, height = 1944;
+const double params_CANON[] = { width*f/sx, // fx
+ height*f/sy, // fy
+ width/2, // cx
+ height/2}; // cy
// Setup the points to register in the image
// In the order of the *.ply file and starting at 1
-int n = 8;
-int pts[] = {1, 2, 3, 4, 5, 6, 7, 8}; // 3 -> 4
-
-// Some basic colors
-Scalar red(0, 0, 255);
-Scalar green(0,255,0);
-Scalar blue(255,0,0);
-Scalar yellow(0,255,255);
+const int n = 8;
+const int pts[] = {1, 2, 3, 4, 5, 6, 7, 8}; // 3 -> 4
/*
* CREATE MODEL REGISTRATION OBJECT
Mesh mesh;
PnPProblem pnp_registration(params_CANON);
-/** Functions headers **/
-void help();
+/**********************************************************************************************************/
+static void help()
+{
+ cout
+ << "--------------------------------------------------------------------------" << endl
+ << "This program shows how to create your 3D textured model. " << endl
+ << "Usage:" << endl
+ << "./cpp-tutorial-pnp_registration" << endl
+ << "--------------------------------------------------------------------------" << endl
+ << endl;
+}
// Mouse events for model registration
static void onMouseModelRegistration( int event, int x, int y, int, void* )
{
- if ( event == EVENT_LBUTTONUP )
- {
- int n_regist = registration.getNumRegist();
- int n_vertex = pts[n_regist];
-
- Point2f point_2d = Point2f((float)x,(float)y);
- Point3f point_3d = mesh.getVertex(n_vertex-1);
-
- bool is_registrable = registration.is_registrable();
- if (is_registrable)
- {
- registration.registerPoint(point_2d, point_3d);
- if( registration.getNumRegist() == registration.getNumMax() ) end_registration = true;
- }
- }
+ if ( event == EVENT_LBUTTONUP )
+ {
+ bool is_registrable = registration.is_registrable();
+ if (is_registrable)
+ {
+ int n_regist = registration.getNumRegist();
+ int n_vertex = pts[n_regist];
+
+ Point2f point_2d = Point2f((float)x,(float)y);
+ Point3f point_3d = mesh.getVertex(n_vertex-1);
+
+ registration.registerPoint(point_2d, point_3d);
+ if( registration.getNumRegist() == registration.getNumMax() ) end_registration = true;
+ }
+ }
}
/** Main program **/
-int main()
+int main(int argc, char *argv[])
{
-
- help();
-
- // load a mesh given the *.ply file path
- mesh.load(ply_read_path);
-
- // set parameters
- int numKeyPoints = 10000;
-
- //Instantiate robust matcher: detector, extractor, matcher
- RobustMatcher rmatcher;
- Ptr<FeatureDetector> detector = ORB::create(numKeyPoints);
- rmatcher.setFeatureDetector(detector);
-
- /** GROUND TRUTH OF THE FIRST IMAGE **/
-
- // Create & Open Window
- namedWindow("MODEL REGISTRATION", WINDOW_KEEPRATIO);
-
- // Set up the mouse events
- setMouseCallback("MODEL REGISTRATION", onMouseModelRegistration, 0 );
-
- // Open the image to register
- Mat img_in = imread(img_path, IMREAD_COLOR);
- Mat img_vis = img_in.clone();
-
- if (!img_in.data) {
- cout << "Could not open or find the image" << endl;
- return -1;
- }
-
- // Set the number of points to register
- int num_registrations = n;
- registration.setNumMax(num_registrations);
-
- cout << "Click the box corners ..." << endl;
- cout << "Waiting ..." << endl;
-
- // Loop until all the points are registered
- while ( waitKey(30) < 0 )
- {
- // Refresh debug image
- img_vis = img_in.clone();
-
- // Current registered points
- vector<Point2f> list_points2d = registration.get_points2d();
- vector<Point3f> list_points3d = registration.get_points3d();
-
- // Draw current registered points
- drawPoints(img_vis, list_points2d, list_points3d, red);
-
- // If the registration is not finished, draw which 3D point we have to register.
- // If the registration is finished, breaks the loop.
- if (!end_registration)
+ help();
+
+ const String keys =
+ "{help h | | print this message }"
+ "{image i | | path to input image }"
+ "{model | | path to output yml model }"
+ "{mesh | | path to ply mesh }"
+ "{keypoints k |2000 | number of keypoints to detect (only for ORB) }"
+ "{feature |ORB | feature name (ORB, KAZE, AKAZE, BRISK, SIFT, SURF, BINBOOST, VGG) }"
+ ;
+ CommandLineParser parser(argc, argv, keys);
+
+ string img_path = samples::findFile("samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/Data/resized_IMG_3875.JPG"); // image to register
+ string ply_read_path = samples::findFile("samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/Data/box.ply"); // object mesh
+ string write_path = samples::findFile("samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/Data/cookies_ORB.yml"); // output file
+ int numKeyPoints = 2000;
+ string featureName = "ORB";
+
+ if (parser.has("help"))
{
- // Draw debug text
- int n_regist = registration.getNumRegist();
- int n_vertex = pts[n_regist];
- Point3f current_poin3d = mesh.getVertex(n_vertex-1);
-
- drawQuestion(img_vis, current_poin3d, green);
- drawCounter(img_vis, registration.getNumRegist(), registration.getNumMax(), red);
+ parser.printMessage();
+ return 0;
}
else
{
- // Draw debug text
- drawText(img_vis, "END REGISTRATION", green);
- drawCounter(img_vis, registration.getNumRegist(), registration.getNumMax(), green);
- break;
+ img_path = parser.get<string>("image").size() > 0 ? parser.get<string>("image") : img_path;
+ ply_read_path = parser.get<string>("mesh").size() > 0 ? parser.get<string>("mesh") : ply_read_path;
+ write_path = parser.get<string>("model").size() > 0 ? parser.get<string>("model") : write_path;
+ numKeyPoints = parser.has("keypoints") ? parser.get<int>("keypoints") : numKeyPoints;
+ featureName = parser.has("feature") ? parser.get<string>("feature") : featureName;
}
- // Show the image
- imshow("MODEL REGISTRATION", img_vis);
- }
-
- /** COMPUTE CAMERA POSE **/
+ std::cout << "Input image: " << img_path << std::endl;
+ std::cout << "CAD model: " << ply_read_path << std::endl;
+ std::cout << "Output training file: " << write_path << std::endl;
+ std::cout << "Feature: " << featureName << std::endl;
+ std::cout << "Number of keypoints for ORB: " << numKeyPoints << std::endl;
- cout << "COMPUTING POSE ..." << endl;
+ // load a mesh given the *.ply file path
+ mesh.load(ply_read_path);
- // The list of registered points
- vector<Point2f> list_points2d = registration.get_points2d();
- vector<Point3f> list_points3d = registration.get_points3d();
+ //Instantiate robust matcher: detector, extractor, matcher
+ RobustMatcher rmatcher;
+ Ptr<Feature2D> detector, descriptor;
+ createFeatures(featureName, numKeyPoints, detector, descriptor);
+ rmatcher.setFeatureDetector(detector);
+ rmatcher.setDescriptorExtractor(descriptor);
- // Estimate pose given the registered points
- bool is_correspondence = pnp_registration.estimatePose(list_points3d, list_points2d, SOLVEPNP_ITERATIVE);
- if ( is_correspondence )
- {
- cout << "Correspondence found" << endl;
- // Compute all the 2D points of the mesh to verify the algorithm and draw it
- vector<Point2f> list_points2d_mesh = pnp_registration.verify_points(&mesh);
- draw2DPoints(img_vis, list_points2d_mesh, green);
+ /** GROUND TRUTH OF THE FIRST IMAGE **/
- } else {
- cout << "Correspondence not found" << endl << endl;
- }
+ // Create & Open Window
+ namedWindow("MODEL REGISTRATION", WINDOW_KEEPRATIO);
- // Show the image
- imshow("MODEL REGISTRATION", img_vis);
+ // Set up the mouse events
+ setMouseCallback("MODEL REGISTRATION", onMouseModelRegistration, 0);
- // Show image until ESC pressed
- waitKey(0);
+ // Open the image to register
+ Mat img_in = imread(img_path, IMREAD_COLOR);
+ Mat img_vis;
+ if (img_in.empty()) {
+ cout << "Could not open or find the image" << endl;
+ return -1;
+ }
- /** COMPUTE 3D of the image Keypoints **/
+ // Set the number of points to register
+ int num_registrations = n;
+ registration.setNumMax(num_registrations);
- // Containers for keypoints and descriptors of the model
- vector<KeyPoint> keypoints_model;
- Mat descriptors;
+ cout << "Click the box corners ..." << endl;
+ cout << "Waiting ..." << endl;
- // Compute keypoints and descriptors
- rmatcher.computeKeyPoints(img_in, keypoints_model);
- rmatcher.computeDescriptors(img_in, keypoints_model, descriptors);
+ // Some basic colors
+ const Scalar red(0, 0, 255);
+ const Scalar green(0,255,0);
+ const Scalar blue(255,0,0);
+ const Scalar yellow(0,255,255);
- // Check if keypoints are on the surface of the registration image and add to the model
- for (unsigned int i = 0; i < keypoints_model.size(); ++i) {
- Point2f point2d(keypoints_model[i].pt);
- Point3f point3d;
- bool on_surface = pnp_registration.backproject2DPoint(&mesh, point2d, point3d);
- if (on_surface)
+ // Loop until all the points are registered
+ while ( waitKey(30) < 0 )
{
- model.add_correspondence(point2d, point3d);
- model.add_descriptor(descriptors.row(i));
- model.add_keypoint(keypoints_model[i]);
+ // Refresh debug image
+ img_vis = img_in.clone();
+
+ // Current registered points
+ vector<Point2f> list_points2d = registration.get_points2d();
+ vector<Point3f> list_points3d = registration.get_points3d();
+
+ // Draw current registered points
+ drawPoints(img_vis, list_points2d, list_points3d, red);
+
+ // If the registration is not finished, draw which 3D point we have to register.
+ // If the registration is finished, breaks the loop.
+ if (!end_registration)
+ {
+ // Draw debug text
+ int n_regist = registration.getNumRegist();
+ int n_vertex = pts[n_regist];
+ Point3f current_poin3d = mesh.getVertex(n_vertex-1);
+
+ drawQuestion(img_vis, current_poin3d, green);
+ drawCounter(img_vis, registration.getNumRegist(), registration.getNumMax(), red);
+ }
+ else
+ {
+ // Draw debug text
+ drawText(img_vis, "END REGISTRATION", green);
+ drawCounter(img_vis, registration.getNumRegist(), registration.getNumMax(), green);
+ break;
+ }
+
+ // Show the image
+ imshow("MODEL REGISTRATION", img_vis);
}
- else
+
+ /** COMPUTE CAMERA POSE **/
+
+ cout << "COMPUTING POSE ..." << endl;
+
+ // The list of registered points
+ vector<Point2f> list_points2d = registration.get_points2d();
+ vector<Point3f> list_points3d = registration.get_points3d();
+
+ // Estimate pose given the registered points
+ bool is_correspondence = pnp_registration.estimatePose(list_points3d, list_points2d, SOLVEPNP_ITERATIVE);
+ if ( is_correspondence )
{
- model.add_outlier(point2d);
+ cout << "Correspondence found" << endl;
+
+ // Compute all the 2D points of the mesh to verify the algorithm and draw it
+ vector<Point2f> list_points2d_mesh = pnp_registration.verify_points(&mesh);
+ draw2DPoints(img_vis, list_points2d_mesh, green);
+ } else {
+ cout << "Correspondence not found" << endl << endl;
}
- }
- // save the model into a *.yaml file
- model.save(write_path);
+ // Show the image
+ imshow("MODEL REGISTRATION", img_vis);
- // Out image
- img_vis = img_in.clone();
+ // Show image until ESC pressed
+ waitKey(0);
+
+
+ /** COMPUTE 3D of the image Keypoints **/
+
+ // Containers for keypoints and descriptors of the model
+ vector<KeyPoint> keypoints_model;
+ Mat descriptors;
+
+ // Compute keypoints and descriptors
+ rmatcher.computeKeyPoints(img_in, keypoints_model);
+ rmatcher.computeDescriptors(img_in, keypoints_model, descriptors);
+
+ // Check if keypoints are on the surface of the registration image and add to the model
+ for (unsigned int i = 0; i < keypoints_model.size(); ++i) {
+ Point2f point2d(keypoints_model[i].pt);
+ Point3f point3d;
+ bool on_surface = pnp_registration.backproject2DPoint(&mesh, point2d, point3d);
+ if (on_surface)
+ {
+ model.add_correspondence(point2d, point3d);
+ model.add_descriptor(descriptors.row(i));
+ model.add_keypoint(keypoints_model[i]);
+ }
+ else
+ {
+ model.add_outlier(point2d);
+ }
+ }
- // The list of the points2d of the model
- vector<Point2f> list_points_in = model.get_points2d_in();
- vector<Point2f> list_points_out = model.get_points2d_out();
+ model.set_trainingImagePath(img_path);
+ // save the model into a *.yaml file
+ model.save(write_path);
- // Draw some debug text
- string num = IntToString((int)list_points_in.size());
- string text = "There are " + num + " inliers";
- drawText(img_vis, text, green);
+ // Out image
+ img_vis = img_in.clone();
- // Draw some debug text
- num = IntToString((int)list_points_out.size());
- text = "There are " + num + " outliers";
- drawText2(img_vis, text, red);
+ // The list of the points2d of the model
+ vector<Point2f> list_points_in = model.get_points2d_in();
+ vector<Point2f> list_points_out = model.get_points2d_out();
- // Draw the object mesh
- drawObjectMesh(img_vis, &mesh, &pnp_registration, blue);
+ // Draw some debug text
+ string num = IntToString((int)list_points_in.size());
+ string text = "There are " + num + " inliers";
+ drawText(img_vis, text, green);
- // Draw found keypoints depending on if are or not on the surface
- draw2DPoints(img_vis, list_points_in, green);
- draw2DPoints(img_vis, list_points_out, red);
+ // Draw some debug text
+ num = IntToString((int)list_points_out.size());
+ text = "There are " + num + " outliers";
+ drawText2(img_vis, text, red);
- // Show the image
- imshow("MODEL REGISTRATION", img_vis);
+ // Draw the object mesh
+ drawObjectMesh(img_vis, &mesh, &pnp_registration, blue);
- // Wait until ESC pressed
- waitKey(0);
+ // Draw found keypoints depending on if are or not on the surface
+ draw2DPoints(img_vis, list_points_in, green);
+ draw2DPoints(img_vis, list_points_out, red);
- // Close and Destroy Window
- destroyWindow("MODEL REGISTRATION");
+ // Show the image
+ imshow("MODEL REGISTRATION", img_vis);
- cout << "GOODBYE" << endl;
+ // Wait until ESC pressed
+ waitKey(0);
-}
+ // Close and Destroy Window
+ destroyWindow("MODEL REGISTRATION");
-/**********************************************************************************************************/
-void help()
-{
- cout
- << "--------------------------------------------------------------------------" << endl
- << "This program shows how to create your 3D textured model. " << endl
- << "Usage:" << endl
- << "./cpp-tutorial-pnp_registration" << endl
- << "--------------------------------------------------------------------------" << endl
- << endl;
+ cout << "GOODBYE" << endl;
}
cv::GMat imgBin = imgCoherencyBin & imgOrientationBin;
cv::GMat out = cv::gapi::addWeighted(in, 0.5, imgBin, 0.5, 0.0);
+ // Normalize extra outputs
+ cv::GMat imgCoherencyNorm = cv::gapi::normalize(imgCoherency, 0, 255, cv::NORM_MINMAX);
+ cv::GMat imgOrientationNorm = cv::gapi::normalize(imgOrientation, 0, 255, cv::NORM_MINMAX);
+
// Capture the graph into object segm
- cv::GComputation segm(cv::GIn(in), cv::GOut(out, imgCoherency, imgOrientation));
+ cv::GComputation segm(cv::GIn(in), cv::GOut(out, imgCoherencyNorm, imgOrientationNorm));
// Define cv::Mats for output data
cv::Mat imgOut, imgOutCoherency, imgOutOrientation;
// Run the graph
segm.apply(cv::gin(imgIn), cv::gout(imgOut, imgOutCoherency, imgOutOrientation));
- // Normalize extra outputs (out of the graph)
- cv::normalize(imgOutCoherency, imgOutCoherency, 0, 255, cv::NORM_MINMAX);
- cv::normalize(imgOutOrientation, imgOutOrientation, 0, 255, cv::NORM_MINMAX);
-
cv::imwrite("result.jpg", imgOut);
cv::imwrite("Coherency.jpg", imgOutCoherency);
cv::imwrite("Orientation.jpg", imgOutOrientation);
auto imgBin = imgCoherencyBin & imgOrientationBin;
cv::GMat out = cv::gapi::addWeighted(in, 0.5, imgBin, 0.5, 0.0);
+ // Normalize extra outputs
+ cv::GMat imgCoherencyNorm = cv::gapi::normalize(imgCoherency, 0, 255, cv::NORM_MINMAX);
+ cv::GMat imgOrientationNorm = cv::gapi::normalize(imgOrientation, 0, 255, cv::NORM_MINMAX);
+
// Capture the graph into object segm
- cv::GComputation segm(cv::GIn(in), cv::GOut(out, imgCoherency, imgOrientation));
+ cv::GComputation segm(cv::GIn(in), cv::GOut(out, imgCoherencyNorm, imgOrientationNorm));
// Define cv::Mats for output data
cv::Mat imgOut, imgOutCoherency, imgOutOrientation;
//! [kernel_pkg_use]
//! [kernel_pkg_proper]
- // Normalize extra outputs (out of the graph)
- cv::normalize(imgOutCoherency, imgOutCoherency, 0, 255, cv::NORM_MINMAX);
- cv::normalize(imgOutOrientation, imgOutOrientation, 0, 255, cv::NORM_MINMAX);
-
cv::imwrite("result.jpg", imgOut);
cv::imwrite("Coherency.jpg", imgOutCoherency);
cv::imwrite("Orientation.jpg", imgOutOrientation);
for node in graph_def.node:
if node.op == 'Const':
if 'value' in node.attr and node.attr['value'].tensor.tensor_content:
- node.attr['value'].tensor.tensor_content = ''
+ node.attr['value'].tensor.tensor_content = b''
tf.train.write_graph(graph_def, "", outputPath, as_text=True)
widths += [sqrt(self.scales[layer_id] * self.scales[layer_id + 1])]
heights += [sqrt(self.scales[layer_id] * self.scales[layer_id + 1])]
- widths = [w * self.image_width for w in widths]
- heights = [h * self.image_height for h in heights]
+ min_size = min(self.image_width, self.image_height)
+ widths = [w * min_size for w in widths]
+ heights = [h * min_size for h in heights]
return widths, heights
#define CL_USE_DEPRECATED_OPENCL_2_0_APIS // eliminate build warning
#ifdef __APPLE__
+#define CL_SILENCE_DEPRECATION
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
print()
return keypoints, np.array(descrs)
-if __name__ == '__main__':
- print(__doc__)
+def main():
import sys, getopt
opts, args = getopt.getopt(sys.argv[1:], '', ['feature='])
opts = dict(opts)
match_and_draw('affine find_obj')
cv.waitKey()
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
# built-in modules
import sys
-if __name__ == '__main__':
- print('This sample shows how to implement a simple hi resolution image navigation.')
- print('USAGE: browse.py [image filename]')
- print()
-
+def main():
if len(sys.argv) > 1:
fn = cv.samples.findFile(sys.argv[1])
print('loading %s ...' % fn)
cv.imshow('preview', small)
cv.setMouseCallback('preview', onmouse)
cv.waitKey()
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
# built-in modules
import os
-if __name__ == '__main__':
+def main():
import sys
import getopt
from glob import glob
print('Undistorted image written to: %s' % outfile)
cv.imwrite(outfile, dst)
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from mpl_toolkits.mplot3d import Axes3D
-import matplotlib.pyplot as plt
+# Python 2/3 compatibility
+from __future__ import print_function
+
import numpy as np
-from matplotlib import cm
-from numpy import linspace
-import argparse
import cv2 as cv
+from numpy import linspace
+
def inverse_homogeneoux_matrix(M):
R = M[0:3, 0:3]
T = M[0:3, 3]
def draw_camera_boards(ax, camera_matrix, cam_width, cam_height, scale_focal,
extrinsics, board_width, board_height, square_size,
patternCentric):
+ from matplotlib import cm
+
min_values = np.zeros((3,1))
min_values = np.inf
max_values = np.zeros((3,1))
return min_values, max_values
def main():
+ import argparse
+
parser = argparse.ArgumentParser(description='Plot camera calibration extrinsics.',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--calibration', type=str, default='left_intrinsics.yml',
camera_matrix = fs.getNode('camera_matrix').mat()
extrinsics = fs.getNode('extrinsic_parameters').mat()
+ import matplotlib.pyplot as plt
+ from mpl_toolkits.mplot3d import Axes3D
+
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect("equal")
ax.set_title('Extrinsic Parameters Visualization')
plt.show()
+ print('Done')
+
-if __name__ == "__main__":
+if __name__ == '__main__':
+ print(__doc__)
main()
+ cv.destroyAllWindows()
if __name__ == '__main__':
+ print(__doc__)
import sys
try:
video_src = sys.argv[1]
except:
video_src = 0
- print(__doc__)
App(video_src).run()
return img
-if __name__ == '__main__':
+def main():
import sys
try:
fn = sys.argv[1]
update()
if ch == 27:
break
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
'''
+# Python 2/3 compatibility
+from __future__ import print_function
+
import numpy as np
import cv2 as cv
# local modules
import video
-if __name__ == '__main__':
+class App():
+
+ def set_scale(self, val):
+ self.hist_scale = val
+
+ def run(self):
+ hsv_map = np.zeros((180, 256, 3), np.uint8)
+ h, s = np.indices(hsv_map.shape[:2])
+ hsv_map[:,:,0] = h
+ hsv_map[:,:,1] = s
+ hsv_map[:,:,2] = 255
+ hsv_map = cv.cvtColor(hsv_map, cv.COLOR_HSV2BGR)
+ cv.imshow('hsv_map', hsv_map)
+
+ cv.namedWindow('hist', 0)
+ self.hist_scale = 10
+
+ cv.createTrackbar('scale', 'hist', self.hist_scale, 32, self.set_scale)
+
+ try:
+ fn = sys.argv[1]
+ except:
+ fn = 0
+ cam = video.create_capture(fn, fallback='synth:bg=baboon.jpg:class=chess:noise=0.05')
+
+ while True:
+ flag, frame = cam.read()
+ cv.imshow('camera', frame)
- hsv_map = np.zeros((180, 256, 3), np.uint8)
- h, s = np.indices(hsv_map.shape[:2])
- hsv_map[:,:,0] = h
- hsv_map[:,:,1] = s
- hsv_map[:,:,2] = 255
- hsv_map = cv.cvtColor(hsv_map, cv.COLOR_HSV2BGR)
- cv.imshow('hsv_map', hsv_map)
-
- cv.namedWindow('hist', 0)
- hist_scale = 10
-
- def set_scale(val):
- global hist_scale
- hist_scale = val
- cv.createTrackbar('scale', 'hist', hist_scale, 32, set_scale)
-
- try:
- fn = sys.argv[1]
- except:
- fn = 0
- cam = video.create_capture(fn, fallback='synth:bg=baboon.jpg:class=chess:noise=0.05')
-
- while True:
- flag, frame = cam.read()
- cv.imshow('camera', frame)
-
- small = cv.pyrDown(frame)
-
- hsv = cv.cvtColor(small, cv.COLOR_BGR2HSV)
- dark = hsv[...,2] < 32
- hsv[dark] = 0
- h = cv.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])
-
- h = np.clip(h*0.005*hist_scale, 0, 1)
- vis = hsv_map*h[:,:,np.newaxis] / 255.0
- cv.imshow('hist', vis)
-
- ch = cv.waitKey(1)
- if ch == 27:
- break
+ small = cv.pyrDown(frame)
+
+ hsv = cv.cvtColor(small, cv.COLOR_BGR2HSV)
+ dark = hsv[...,2] < 32
+ hsv[dark] = 0
+ h = cv.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])
+
+ h = np.clip(h*0.005*self.hist_scale, 0, 1)
+ vis = hsv_map*h[:,:,np.newaxis] / 255.0
+ cv.imshow('hist', vis)
+
+ ch = cv.waitKey(1)
+ if ch == 27:
+ break
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ App().run()
cv.destroyAllWindows()
cv.ellipse( img, (dx+273, dy+100), (20,35), 0, 0, 360, white, -1 )
return img
-if __name__ == '__main__':
- print(__doc__)
-
+def main():
img = make_image()
h, w = img.shape[:2]
cv.createTrackbar( "levels+3", "contours", 3, 7, update )
cv.imshow('image', img)
cv.waitKey()
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
return kern
-if __name__ == '__main__':
- print(__doc__)
+def main():
import sys, getopt
opts, args = getopt.getopt(sys.argv[1:], '', ['circle', 'angle=', 'd=', 'snr='])
opts = dict(opts)
if ch == ord(' '):
defocus = not defocus
update(None)
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
+ cv.destroyAllWindows()
# Python 2/3 compatibility
from __future__ import print_function
-import cv2 as cv
import numpy as np
+import cv2 as cv
+
import sys
return dst
-if __name__ == "__main__":
+def main():
if len(sys.argv) > 1:
fname = sys.argv[1]
else:
cv.imshow("magnitude", log_spectrum)
cv.waitKey(0)
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
# Python 2/3 compatibility
from __future__ import print_function
+import numpy as np
+import cv2 as cv
+
# built-in modules
from multiprocessing.pool import ThreadPool
-import cv2 as cv
-
-import numpy as np
from numpy.linalg import norm
# local modules
import numpy as np
import cv2 as cv
+
from multiprocessing.pool import ThreadPool
from digits import *
if ch == 27:
break
+ print('Done')
+
+
if __name__ == '__main__':
+ print(__doc__)
main()
cv.destroyAllWindows()
import numpy as np
import cv2 as cv
+
import video
return res
-if __name__ == '__main__':
+def main():
import sys
print(__doc__)
try:
if ch == ord('4'):
use_temporal_propagation = not use_temporal_propagation
print('temporal propagation is', ['off', 'on'][use_temporal_propagation])
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
from common import make_cmap
-if __name__ == '__main__':
+def main():
import sys
try:
fn = sys.argv[1]
except:
fn = 'fruits.jpg'
- print(__doc__)
fn = cv.samples.findFile(fn)
img = cv.imread(fn, cv.IMREAD_GRAYSCALE)
update()
if need_update:
update()
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
import sys
-if __name__ == '__main__':
- print(__doc__)
-
+def main():
try:
fn = sys.argv[1]
except:
ch = cv.waitKey(5)
if ch == 27:
break
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
for x1, y1, x2, y2 in rects:
cv.rectangle(img, (x1, y1), (x2, y2), color, 2)
-if __name__ == '__main__':
+def main():
import sys, getopt
- print(__doc__)
args, video_src = getopt.getopt(sys.argv[1:], '', ['cascade=', 'nested-cascade='])
try:
if cv.waitKey(5) == 27:
break
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
import numpy as np
import cv2 as cv
+
from common import anorm, getsize
FLANN_INDEX_KDTREE = 1 # bug: flann enums are missing
return vis
-if __name__ == '__main__':
- print(__doc__)
-
+def main():
import sys, getopt
opts, args = getopt.getopt(sys.argv[1:], '', ['feature='])
opts = dict(opts)
match_and_draw('find_obj')
cv.waitKey()
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
draw_str(img, (20, 20), cur_func_name)
cv.imshow('fit line', img)
-if __name__ == '__main__':
- print(__doc__)
-
+def main():
cv.namedWindow('fit line')
cv.createTrackbar('noise', 'fit line', 3, 50, update)
cv.createTrackbar('point n', 'fit line', 100, 500, update)
cur_func_name = dist_func_names.next()
if ch == 27:
break
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
+ cv.destroyAllWindows()
import numpy as np
import cv2 as cv
-if __name__ == '__main__':
- import sys
- try:
- fn = sys.argv[1]
- except:
- fn = 'fruits.jpg'
- print(__doc__)
+import sys
- img = cv.imread(cv.samples.findFile(fn))
- if img is None:
- print('Failed to load image file:', fn)
- sys.exit(1)
+class App():
- h, w = img.shape[:2]
- mask = np.zeros((h+2, w+2), np.uint8)
- seed_pt = None
- fixed_range = True
- connectivity = 4
-
- def update(dummy=None):
- if seed_pt is None:
- cv.imshow('floodfill', img)
+ def update(self, dummy=None):
+ if self.seed_pt is None:
+ cv.imshow('floodfill', self.img)
return
- flooded = img.copy()
- mask[:] = 0
+ flooded = self.img.copy()
+ self.mask[:] = 0
lo = cv.getTrackbarPos('lo', 'floodfill')
hi = cv.getTrackbarPos('hi', 'floodfill')
- flags = connectivity
- if fixed_range:
+ flags = self.connectivity
+ if self.fixed_range:
flags |= cv.FLOODFILL_FIXED_RANGE
- cv.floodFill(flooded, mask, seed_pt, (255, 255, 255), (lo,)*3, (hi,)*3, flags)
- cv.circle(flooded, seed_pt, 2, (0, 0, 255), -1)
+ cv.floodFill(flooded, self.mask, self.seed_pt, (255, 255, 255), (lo,)*3, (hi,)*3, flags)
+ cv.circle(flooded, self.seed_pt, 2, (0, 0, 255), -1)
cv.imshow('floodfill', flooded)
- def onmouse(event, x, y, flags, param):
- global seed_pt
+ def onmouse(self, event, x, y, flags, param):
if flags & cv.EVENT_FLAG_LBUTTON:
- seed_pt = x, y
- update()
-
- update()
- cv.setMouseCallback('floodfill', onmouse)
- cv.createTrackbar('lo', 'floodfill', 20, 255, update)
- cv.createTrackbar('hi', 'floodfill', 20, 255, update)
-
- while True:
- ch = cv.waitKey()
- if ch == 27:
- break
- if ch == ord('f'):
- fixed_range = not fixed_range
- print('using %s range' % ('floating', 'fixed')[fixed_range])
- update()
- if ch == ord('c'):
- connectivity = 12-connectivity
- print('connectivity =', connectivity)
- update()
+ self.seed_pt = x, y
+ self.update()
+
+ def run(self):
+ try:
+ fn = sys.argv[1]
+ except:
+ fn = 'fruits.jpg'
+
+ self.img = cv.imread(cv.samples.findFile(fn))
+ if self.img is None:
+ print('Failed to load image file:', fn)
+ sys.exit(1)
+
+ h, w = self.img.shape[:2]
+ self.mask = np.zeros((h+2, w+2), np.uint8)
+ self.seed_pt = None
+ self.fixed_range = True
+ self.connectivity = 4
+
+ self.update()
+ cv.setMouseCallback('floodfill', self.onmouse)
+ cv.createTrackbar('lo', 'floodfill', 20, 255, self.update)
+ cv.createTrackbar('hi', 'floodfill', 20, 255, self.update)
+
+ while True:
+ ch = cv.waitKey()
+ if ch == 27:
+ break
+ if ch == ord('f'):
+ self.fixed_range = not self.fixed_range
+ print('using %s range' % ('floating', 'fixed')[self.fixed_range])
+ self.update()
+ if ch == ord('c'):
+ self.connectivity = 12-self.connectivity
+ print('connectivity =', self.connectivity)
+ self.update()
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ App().run()
cv.destroyAllWindows()
import numpy as np
import cv2 as cv
+
from multiprocessing.pool import ThreadPool
np.maximum(accum, fimg, accum)
return accum
-if __name__ == '__main__':
+def main():
import sys
from common import Timer
- print(__doc__)
try:
img_fn = sys.argv[1]
except:
cv.imshow('img', img)
cv.imshow('result', res2)
cv.waitKey()
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
xrange = range
import numpy as np
-from numpy import random
import cv2 as cv
+from numpy import random
+
def make_gaussians(cluster_n, img_size):
points = []
ref_distrs = []
cv.ellipse(img, (x, y), (s1, s2), ang, 0, 360, color, 1, cv.LINE_AA)
-if __name__ == '__main__':
+def main():
cluster_n = 5
img_size = 512
ch = cv.waitKey(0)
if ch == 27:
break
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
import numpy as np
import cv2 as cv
+
import sys
-BLUE = [255,0,0] # rectangle color
-RED = [0,0,255] # PR BG
-GREEN = [0,255,0] # PR FG
-BLACK = [0,0,0] # sure BG
-WHITE = [255,255,255] # sure FG
-
-DRAW_BG = {'color' : BLACK, 'val' : 0}
-DRAW_FG = {'color' : WHITE, 'val' : 1}
-DRAW_PR_FG = {'color' : GREEN, 'val' : 3}
-DRAW_PR_BG = {'color' : RED, 'val' : 2}
-
-# setting up flags
-rect = (0,0,1,1)
-drawing = False # flag for drawing curves
-rectangle = False # flag for drawing rect
-rect_over = False # flag to check if rect drawn
-rect_or_mask = 100 # flag for selecting rect or mask mode
-value = DRAW_FG # drawing initialized to FG
-thickness = 3 # brush thickness
-
-def onmouse(event,x,y,flags,param):
- global img,img2,drawing,value,mask,rectangle,rect,rect_or_mask,ix,iy,rect_over
-
- # Draw Rectangle
- if event == cv.EVENT_RBUTTONDOWN:
- rectangle = True
- ix,iy = x,y
-
- elif event == cv.EVENT_MOUSEMOVE:
- if rectangle == True:
- img = img2.copy()
- cv.rectangle(img,(ix,iy),(x,y),BLUE,2)
- rect = (min(ix,x),min(iy,y),abs(ix-x),abs(iy-y))
- rect_or_mask = 0
-
- elif event == cv.EVENT_RBUTTONUP:
- rectangle = False
- rect_over = True
- cv.rectangle(img,(ix,iy),(x,y),BLUE,2)
- rect = (min(ix,x),min(iy,y),abs(ix-x),abs(iy-y))
- rect_or_mask = 0
- print(" Now press the key 'n' a few times until no further change \n")
-
- # draw touchup curves
-
- if event == cv.EVENT_LBUTTONDOWN:
- if rect_over == False:
- print("first draw rectangle \n")
+class App():
+ BLUE = [255,0,0] # rectangle color
+ RED = [0,0,255] # PR BG
+ GREEN = [0,255,0] # PR FG
+ BLACK = [0,0,0] # sure BG
+ WHITE = [255,255,255] # sure FG
+
+ DRAW_BG = {'color' : BLACK, 'val' : 0}
+ DRAW_FG = {'color' : WHITE, 'val' : 1}
+ DRAW_PR_FG = {'color' : GREEN, 'val' : 3}
+ DRAW_PR_BG = {'color' : RED, 'val' : 2}
+
+ # setting up flags
+ rect = (0,0,1,1)
+ drawing = False # flag for drawing curves
+ rectangle = False # flag for drawing rect
+ rect_over = False # flag to check if rect drawn
+ rect_or_mask = 100 # flag for selecting rect or mask mode
+ value = DRAW_FG # drawing initialized to FG
+ thickness = 3 # brush thickness
+
+ def onmouse(self, event, x, y, flags, param):
+ # Draw Rectangle
+ if event == cv.EVENT_RBUTTONDOWN:
+ self.rectangle = True
+ self.ix, self.iy = x,y
+
+ elif event == cv.EVENT_MOUSEMOVE:
+ if self.rectangle == True:
+ self.img = self.img2.copy()
+ cv.rectangle(self.img, (self.ix, self.iy), (x, y), self.BLUE, 2)
+ self.rect = (min(self.ix, x), min(self.iy, y), abs(self.ix - x), abs(self.iy - y))
+ self.rect_or_mask = 0
+
+ elif event == cv.EVENT_RBUTTONUP:
+ self.rectangle = False
+ self.rect_over = True
+ cv.rectangle(self.img, (self.ix, self.iy), (x, y), self.BLUE, 2)
+ self.rect = (min(self.ix, x), min(self.iy, y), abs(self.ix - x), abs(self.iy - y))
+ self.rect_or_mask = 0
+ print(" Now press the key 'n' a few times until no further change \n")
+
+ # draw touchup curves
+
+ if event == cv.EVENT_LBUTTONDOWN:
+ if self.rect_over == False:
+ print("first draw rectangle \n")
+ else:
+ self.drawing = True
+ cv.circle(self.img, (x,y), self.thickness, self.value['color'], -1)
+ cv.circle(self.mask, (x,y), self.thickness, self.value['val'], -1)
+
+ elif event == cv.EVENT_MOUSEMOVE:
+ if self.drawing == True:
+ cv.circle(self.img, (x, y), self.thickness, self.value['color'], -1)
+ cv.circle(self.mask, (x, y), self.thickness, self.value['val'], -1)
+
+ elif event == cv.EVENT_LBUTTONUP:
+ if self.drawing == True:
+ self.drawing = False
+ cv.circle(self.img, (x, y), self.thickness, self.value['color'], -1)
+ cv.circle(self.mask, (x, y), self.thickness, self.value['val'], -1)
+
+ def run(self):
+ # Loading images
+ if len(sys.argv) == 2:
+ filename = sys.argv[1] # for drawing purposes
else:
- drawing = True
- cv.circle(img,(x,y),thickness,value['color'],-1)
- cv.circle(mask,(x,y),thickness,value['val'],-1)
-
- elif event == cv.EVENT_MOUSEMOVE:
- if drawing == True:
- cv.circle(img,(x,y),thickness,value['color'],-1)
- cv.circle(mask,(x,y),thickness,value['val'],-1)
+ print("No input image given, so loading default image, lena.jpg \n")
+ print("Correct Usage: python grabcut.py <filename> \n")
+ filename = 'lena.jpg'
+
+ self.img = cv.imread(cv.samples.findFile(filename))
+ self.img2 = self.img.copy() # a copy of original image
+ self.mask = np.zeros(self.img.shape[:2], dtype = np.uint8) # mask initialized to PR_BG
+ self.output = np.zeros(self.img.shape, np.uint8) # output image to be shown
+
+ # input and output windows
+ cv.namedWindow('output')
+ cv.namedWindow('input')
+ cv.setMouseCallback('input', self.onmouse)
+ cv.moveWindow('input', self.img.shape[1]+10,90)
+
+ print(" Instructions: \n")
+ print(" Draw a rectangle around the object using right mouse button \n")
+
+ while(1):
+
+ cv.imshow('output', self.output)
+ cv.imshow('input', self.img)
+ k = cv.waitKey(1)
+
+ # key bindings
+ if k == 27: # esc to exit
+ break
+ elif k == ord('0'): # BG drawing
+ print(" mark background regions with left mouse button \n")
+ self.value = self.DRAW_BG
+ elif k == ord('1'): # FG drawing
+ print(" mark foreground regions with left mouse button \n")
+ self.value = self.DRAW_FG
+ elif k == ord('2'): # PR_BG drawing
+ self.value = self.DRAW_PR_BG
+ elif k == ord('3'): # PR_FG drawing
+ self.value = self.DRAW_PR_FG
+ elif k == ord('s'): # save image
+ bar = np.zeros((self.img.shape[0], 5, 3), np.uint8)
+ res = np.hstack((self.img2, bar, self.img, bar, self.output))
+ cv.imwrite('grabcut_output.png', res)
+ print(" Result saved as image \n")
+ elif k == ord('r'): # reset everything
+ print("resetting \n")
+ self.rect = (0,0,1,1)
+ self.drawing = False
+ self.rectangle = False
+ self.rect_or_mask = 100
+ self.rect_over = False
+ self.value = self.DRAW_FG
+ self.img = self.img2.copy()
+ self.mask = np.zeros(self.img.shape[:2], dtype = np.uint8) # mask initialized to PR_BG
+ self.output = np.zeros(self.img.shape, np.uint8) # output image to be shown
+ elif k == ord('n'): # segment the image
+ print(""" For finer touchups, mark foreground and background after pressing keys 0-3
+ and again press 'n' \n""")
+ try:
+ if (self.rect_or_mask == 0): # grabcut with rect
+ bgdmodel = np.zeros((1, 65), np.float64)
+ fgdmodel = np.zeros((1, 65), np.float64)
+ cv.grabCut(self.img2, self.mask, self.rect, bgdmodel, fgdmodel, 1, cv.GC_INIT_WITH_RECT)
+ self.rect_or_mask = 1
+ elif self.rect_or_mask == 1: # grabcut with mask
+ bgdmodel = np.zeros((1, 65), np.float64)
+ fgdmodel = np.zeros((1, 65), np.float64)
+ cv.grabCut(self.img2, self.mask, self.rect, bgdmodel, fgdmodel, 1, cv.GC_INIT_WITH_MASK)
+ except:
+ import traceback
+ traceback.print_exc()
+
+ mask2 = np.where((self.mask==1) + (self.mask==3), 255, 0).astype('uint8')
+ self.output = cv.bitwise_and(self.img2, self.img2, mask=mask2)
+
+ print('Done')
- elif event == cv.EVENT_LBUTTONUP:
- if drawing == True:
- drawing = False
- cv.circle(img,(x,y),thickness,value['color'],-1)
- cv.circle(mask,(x,y),thickness,value['val'],-1)
if __name__ == '__main__':
-
- # print documentation
print(__doc__)
-
- # Loading images
- if len(sys.argv) == 2:
- filename = sys.argv[1] # for drawing purposes
- else:
- print("No input image given, so loading default image, lena.jpg \n")
- print("Correct Usage: python grabcut.py <filename> \n")
- filename = 'lena.jpg'
-
- img = cv.imread(cv.samples.findFile(filename))
- img2 = img.copy() # a copy of original image
- mask = np.zeros(img.shape[:2],dtype = np.uint8) # mask initialized to PR_BG
- output = np.zeros(img.shape,np.uint8) # output image to be shown
-
- # input and output windows
- cv.namedWindow('output')
- cv.namedWindow('input')
- cv.setMouseCallback('input',onmouse)
- cv.moveWindow('input',img.shape[1]+10,90)
-
- print(" Instructions: \n")
- print(" Draw a rectangle around the object using right mouse button \n")
-
- while(1):
-
- cv.imshow('output',output)
- cv.imshow('input',img)
- k = cv.waitKey(1)
-
- # key bindings
- if k == 27: # esc to exit
- break
- elif k == ord('0'): # BG drawing
- print(" mark background regions with left mouse button \n")
- value = DRAW_BG
- elif k == ord('1'): # FG drawing
- print(" mark foreground regions with left mouse button \n")
- value = DRAW_FG
- elif k == ord('2'): # PR_BG drawing
- value = DRAW_PR_BG
- elif k == ord('3'): # PR_FG drawing
- value = DRAW_PR_FG
- elif k == ord('s'): # save image
- bar = np.zeros((img.shape[0],5,3),np.uint8)
- res = np.hstack((img2,bar,img,bar,output))
- cv.imwrite('grabcut_output.png',res)
- print(" Result saved as image \n")
- elif k == ord('r'): # reset everything
- print("resetting \n")
- rect = (0,0,1,1)
- drawing = False
- rectangle = False
- rect_or_mask = 100
- rect_over = False
- value = DRAW_FG
- img = img2.copy()
- mask = np.zeros(img.shape[:2],dtype = np.uint8) # mask initialized to PR_BG
- output = np.zeros(img.shape,np.uint8) # output image to be shown
- elif k == ord('n'): # segment the image
- print(""" For finer touchups, mark foreground and background after pressing keys 0-3
- and again press 'n' \n""")
- if (rect_or_mask == 0): # grabcut with rect
- bgdmodel = np.zeros((1,65),np.float64)
- fgdmodel = np.zeros((1,65),np.float64)
- cv.grabCut(img2,mask,rect,bgdmodel,fgdmodel,1,cv.GC_INIT_WITH_RECT)
- rect_or_mask = 1
- elif rect_or_mask == 1: # grabcut with mask
- bgdmodel = np.zeros((1,65),np.float64)
- fgdmodel = np.zeros((1,65),np.float64)
- cv.grabCut(img2,mask,rect,bgdmodel,fgdmodel,1,cv.GC_INIT_WITH_MASK)
-
- mask2 = np.where((mask==1) + (mask==3),255,0).astype('uint8')
- output = cv.bitwise_and(img2,img2,mask=mask2)
-
+ App().run()
cv.destroyAllWindows()
# Python 2/3 compatibility
from __future__ import print_function
-import cv2 as cv
import numpy as np
+import cv2 as cv
bins = np.arange(256).reshape(256,1)
return y
-if __name__ == '__main__':
-
+def main():
import sys
if len(sys.argv)>1:
print('ESC')
cv.destroyAllWindows()
break
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
# Python 2/3 compatibility
from __future__ import print_function
-import cv2 as cv
import numpy as np
-import sys
+import cv2 as cv
-if __name__ == '__main__':
- print(__doc__)
+import sys
+def main():
try:
fn = sys.argv[1]
except IndexError:
cv.imshow("source", src)
cv.waitKey(0)
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
+ cv.destroyAllWindows()
import cv2 as cv
import numpy as np
+
import sys
import math
-if __name__ == '__main__':
- print(__doc__)
-
+def main():
try:
fn = sys.argv[1]
except IndexError:
cv.imshow("source", src)
cv.waitKey(0)
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
+ cv.destroyAllWindows()
import numpy as np
import cv2 as cv
+
from common import Sketcher
-if __name__ == '__main__':
+def main():
import sys
try:
fn = sys.argv[1]
except:
fn = 'fruits.jpg'
- print(__doc__)
-
img = cv.imread(cv.samples.findFile(fn))
if img is None:
print('Failed to load image file:', fn)
img_mark[:] = img
mark[:] = 0
sketch.show()
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
if PY3:
long = int
+import numpy as np
import cv2 as cv
+
from math import cos, sin, sqrt
import numpy as np
-if __name__ == "__main__":
-
+def main():
img_height = 500
img_width = 500
kalman = cv.KalmanFilter(2, 1, 0)
if code in [27, ord('q'), ord('Q')]:
break
- cv.destroyWindow("Kalman")
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
+ cv.destroyAllWindows()
from gaussian_mix import make_gaussians
-if __name__ == '__main__':
+def main():
cluster_n = 5
img_size = 512
- print(__doc__)
-
# generating bright palette
colors = np.zeros((1, cluster_n, 3), np.uint8)
colors[0,:] = 255
cv.circle(img, (x, y), 1, c, -1)
- cv.imshow('gaussian mixture', img)
+ cv.imshow('kmeans', img)
ch = cv.waitKey(0)
if ch == 27:
break
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
import numpy as np
import cv2 as cv
+
import video
from common import nothing, getsize
return np.uint8(np.clip(img, 0, 255))
-if __name__ == '__main__':
+def main():
import sys
- print(__doc__)
try:
fn = sys.argv[1]
if cv.waitKey(1) == 27:
break
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
+ cv.destroyAllWindows()
-if __name__ == '__main__':
+def main():
import getopt
import sys
- print(__doc__)
-
models = [RTrees, KNearest, Boost, SVM, MLP] # NBayes
models = dict( [(cls.__name__.lower(), cls) for cls in models] )
fn = args['--save']
print('saving model to %s ...' % fn)
model.save(fn)
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
import numpy as np
import cv2 as cv
+
import video
from common import draw_str
from video import presets
except:
video_src = 0
- print(__doc__)
App(video_src).run()
- cv.destroyAllWindows()
+ print('Done')
+
if __name__ == '__main__':
+ print(__doc__)
main()
+ cv.destroyAllWindows()
import numpy as np
import cv2 as cv
+
import video
from common import anorm2, draw_str
from time import clock
except:
video_src = 0
- print(__doc__)
App(video_src).run()
- cv.destroyAllWindows()
+ print('Done')
+
if __name__ == '__main__':
+ print(__doc__)
main()
+ cv.destroyAllWindows()
# Python 2/3 compatibility
from __future__ import print_function
+import numpy as np
import cv2 as cv
-if __name__ == '__main__':
- print(__doc__)
-
+def main():
import sys
try:
fn = sys.argv[1]
cv.imshow('linearpolar', img3)
cv.waitKey(0)
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
+ cv.destroyAllWindows()
import cv2 as cv
-if __name__ == '__main__':
- print(__doc__)
-
+def main():
import sys
from itertools import cycle
from common import draw_str
else:
cur_str_mode = str_modes.next()
update()
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
from math import *
-drag_start = None
-sel = (0,0,0,0)
+class App():
+ drag_start = None
+ sel = (0,0,0,0)
-def onmouse(event, x, y, flags, param):
- global drag_start, sel
- if event == cv.EVENT_LBUTTONDOWN:
- drag_start = x, y
- sel = 0,0,0,0
- elif event == cv.EVENT_LBUTTONUP:
- if sel[2] > sel[0] and sel[3] > sel[1]:
- patch = gray[sel[1]:sel[3],sel[0]:sel[2]]
- result = cv.matchTemplate(gray,patch,cv.TM_CCOEFF_NORMED)
- result = np.abs(result)**3
- _val, result = cv.threshold(result, 0.01, 0, cv.THRESH_TOZERO)
- result8 = cv.normalize(result,None,0,255,cv.NORM_MINMAX,cv.CV_8U)
- cv.imshow("result", result8)
- drag_start = None
- elif drag_start:
- #print flags
- if flags & cv.EVENT_FLAG_LBUTTON:
- minpos = min(drag_start[0], x), min(drag_start[1], y)
- maxpos = max(drag_start[0], x), max(drag_start[1], y)
- sel = minpos[0], minpos[1], maxpos[0], maxpos[1]
- img = cv.cvtColor(gray, cv.COLOR_GRAY2BGR)
- cv.rectangle(img, (sel[0], sel[1]), (sel[2], sel[3]), (0,255,255), 1)
- cv.imshow("gray", img)
- else:
- print("selection is complete")
- drag_start = None
+ def onmouse(self, event, x, y, flags, param):
+ if event == cv.EVENT_LBUTTONDOWN:
+ self.drag_start = x, y
+ self.sel = (0,0,0,0)
+ elif event == cv.EVENT_LBUTTONUP:
+ if self.sel[2] > self.sel[0] and self.sel[3] > self.sel[1]:
+ patch = self.gray[self.sel[1]:self.sel[3], self.sel[0]:self.sel[2]]
+ result = cv.matchTemplate(self.gray, patch, cv.TM_CCOEFF_NORMED)
+ result = np.abs(result)**3
+ _val, result = cv.threshold(result, 0.01, 0, cv.THRESH_TOZERO)
+ result8 = cv.normalize(result, None, 0, 255, cv.NORM_MINMAX, cv.CV_8U)
+ cv.imshow("result", result8)
+ self.drag_start = None
+ elif self.drag_start:
+ #print flags
+ if flags & cv.EVENT_FLAG_LBUTTON:
+ minpos = min(self.drag_start[0], x), min(self.drag_start[1], y)
+ maxpos = max(self.drag_start[0], x), max(self.drag_start[1], y)
+ self.sel = (minpos[0], minpos[1], maxpos[0], maxpos[1])
+ img = cv.cvtColor(self.gray, cv.COLOR_GRAY2BGR)
+ cv.rectangle(img, (self.sel[0], self.sel[1]), (self.sel[2], self.sel[3]), (0,255,255), 1)
+ cv.imshow("gray", img)
+ else:
+ print("selection is complete")
+ self.drag_start = None
-if __name__ == '__main__':
- print(__doc__)
+ def run(self):
+ parser = argparse.ArgumentParser(description='Demonstrate mouse interaction with images')
+ parser.add_argument("-i","--input", default='../data/', help="Input directory.")
+ args = parser.parse_args()
+ path = args.input
+
+ cv.namedWindow("gray",1)
+ cv.setMouseCallback("gray", self.onmouse)
+ '''Loop through all the images in the directory'''
+ for infile in glob.glob( os.path.join(path, '*.*') ):
+ ext = os.path.splitext(infile)[1][1:] #get the filename extension
+ if ext == "png" or ext == "jpg" or ext == "bmp" or ext == "tiff" or ext == "pbm":
+ print(infile)
- parser = argparse.ArgumentParser(description='Demonstrate mouse interaction with images')
- parser.add_argument("-i","--input", default='../data/', help="Input directory.")
- args = parser.parse_args()
- path = args.input
+ img = cv.imread(infile,1)
+ if img is None:
+ continue
+ self.sel = (0,0,0,0)
+ self.drag_start = None
+ self.gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
+ cv.imshow("gray", self.gray)
+ if cv.waitKey() == 27:
+ break
- cv.namedWindow("gray",1)
- cv.setMouseCallback("gray", onmouse)
- '''Loop through all the images in the directory'''
- for infile in glob.glob( os.path.join(path, '*.*') ):
- ext = os.path.splitext(infile)[1][1:] #get the filename extension
- if ext == "png" or ext == "jpg" or ext == "bmp" or ext == "tiff" or ext == "pbm":
- print(infile)
+ print('Done')
- img=cv.imread(infile,1)
- if img is None:
- continue
- sel = (0,0,0,0)
- drag_start = None
- gray=cv.cvtColor(img, cv.COLOR_BGR2GRAY)
- cv.imshow("gray",gray)
- if cv.waitKey() == 27:
- break
+
+if __name__ == '__main__':
+ print(__doc__)
+ App().run()
cv.destroyAllWindows()
'''
+# Python 2/3 compatibility
+from __future__ import print_function
+
import numpy as np
import cv2 as cv
+
import video
import sys
-if __name__ == '__main__':
+def main():
try:
video_src = sys.argv[1]
except:
cv.imshow('img', vis)
if cv.waitKey(5) == 27:
break
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
# Python 2/3 compatibility
from __future__ import print_function
+import numpy as np
import cv2 as cv
-if __name__ == '__main__':
+def main():
import sys
- print(__doc__)
try:
param = sys.argv[1]
print("\t--help\n\t\tprint this help")
else:
print("Welcome to OpenCV")
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
+ cv.destroyAllWindows()
import numpy as np
import cv2 as cv
+
import video
res = cv.remap(img, flow, None, cv.INTER_LINEAR)
return res
-if __name__ == '__main__':
+def main():
import sys
- print(__doc__)
try:
fn = sys.argv[1]
except IndexError:
if show_glitch:
cur_glitch = img.copy()
print('glitch is', ['off', 'on'][show_glitch])
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
cv.rectangle(img, (x+pad_w, y+pad_h), (x+w-pad_w, y+h-pad_h), (0, 255, 0), thickness)
-if __name__ == '__main__':
+def main():
import sys
from glob import glob
import itertools as it
- print(__doc__)
-
hog = cv.HOGDescriptor()
hog.setSVMDetector( cv.HOGDescriptor_getDefaultPeopleDetector() )
ch = cv.waitKey()
if ch == 27:
break
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
'''
# Python 2/3 compatibility
+from __future__ import print_function
import sys
PY3 = sys.version_info[0] == 3
squares.append(cnt)
return squares
-if __name__ == '__main__':
+def main():
from glob import glob
for fn in glob('../data/pic*.png'):
img = cv.imread(fn)
ch = cv.waitKey()
if ch == 27:
break
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
np.savetxt(f, verts, fmt='%f %f %f %d %d %d ')
-if __name__ == '__main__':
+def main():
print('loading images...')
imgL = cv.pyrDown(cv.imread(cv.samples.findFile('aloeL.jpg'))) # downscale images for faster processing
imgR = cv.pyrDown(cv.imread(cv.samples.findFile('aloeR.jpg')))
cv.imshow('left', imgL)
cv.imshow('disparity', (disp-min_disp)/num_disp)
cv.waitKey()
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
or scans.
'''
+# Python 2/3 compatibility
from __future__ import print_function
-import cv2 as cv
+
import numpy as np
+import cv2 as cv
+
import argparse
import sys
modes = (cv.Stitcher_PANORAMA, cv.Stitcher_SCANS)
-parser = argparse.ArgumentParser(description='Stitching sample.')
+parser = argparse.ArgumentParser(prog='stitching.py', description='Stitching sample.')
parser.add_argument('--mode',
type = int, choices = modes, default = cv.Stitcher_PANORAMA,
help = 'Determines configuration of stitcher. The default is `PANORAMA` (%d), '
parser.add_argument('--output', default = 'result.jpg',
help = 'Resulting image. The default is `result.jpg`.')
parser.add_argument('img', nargs='+', help = 'input images')
-args = parser.parse_args()
-
-# read input images
-imgs = []
-for img_name in args.img:
- img = cv.imread(img_name)
- if img is None:
- print("can't read image " + img_name)
+
+__doc__ += '\n' + parser.format_help()
+
+def main():
+ args = parser.parse_args()
+
+ # read input images
+ imgs = []
+ for img_name in args.img:
+ img = cv.imread(cv.samples.findFile(img_name))
+ if img is None:
+ print("can't read image " + img_name)
+ sys.exit(-1)
+ imgs.append(img)
+
+ stitcher = cv.Stitcher.create(args.mode)
+ status, pano = stitcher.stitch(imgs)
+
+ if status != cv.Stitcher_OK:
+ print("Can't stitch images, error code = %d" % status)
sys.exit(-1)
- imgs.append(img)
-stitcher = cv.Stitcher.create(args.mode)
-status, pano = stitcher.stitch(imgs)
+ cv.imwrite(args.output, pano);
+ print("stitching completed successfully. %s saved!" % args.output)
+
+ print('Done')
-if status != cv.Stitcher_OK:
- print("Can't stitch images, error code = %d" % status)
- sys.exit(-1)
-cv.imwrite(args.output, pano);
-print("stitching completed successfully. %s saved!" % args.output)
+if __name__ == '__main__':
+ print(__doc__)
+ main()
+ cv.destroyAllWindows()
-"""Rotation model images stitcher.
-stitching_detailed img1 img2 [...imgN] [flags]
-Flags:
- --preview
- Run stitching in the preview mode. Works faster than usual mode,
- but output image will have lower resolution.
- --try_cuda (yes|no)
- Try to use CUDA. The default value is 'no'. All default values
- are for CPU mode.
-\nMotion Estimation Flags:
- --work_megapix <float>
- Resolution for image registration step. The default is 0.6 Mpx.
- --features (surf|orb|sift)
- Type of features used for images matching. The default is surf.
- --matcher (homography|affine)
- Matcher used for pairwise image matching.
- --estimator (homography|affine)
- Type of estimator used for transformation estimation.
- --match_conf <float>
- Confidence for feature matching step. The default is 0.65 for surf and 0.3 for orb.
- --conf_thresh <float>
- Threshold for two images are from the same panorama confidence.
- The default is 1.0.
- --ba (no|reproj|ray|affine)
- Bundle adjustment cost function. The default is ray.
- --ba_refine_mask (mask)
- Set refinement mask for bundle adjustment. It looks like 'x_xxx',
- where 'x' means refine respective parameter and '_' means don't
- refine one, and has the following format:
- <fx><skew><ppx><aspect><ppy>. The default mask is 'xxxxx'. If bundle
- adjustment doesn't support estimation of selected parameter then
- the respective flag is ignored.
- --wave_correct (no|horiz|vert)
- Perform wave effect correction. The default is 'horiz'.
- --save_graph <file_name>
- Save matches graph represented in DOT language to <file_name> file.
- Labels description: Nm is number of matches, Ni is number of inliers,
- C is confidence.
-\nCompositing Flags:
- --warp (affine|plane|cylindrical|spherical|fisheye|stereographic|compressedPlaneA2B1|compressedPlaneA1.5B1|compressedPlanePortraitA2B1|compressedPlanePortraitA1.5B1|paniniA2B1|paniniA1.5B1|paniniPortraitA2B1|paniniPortraitA1.5B1|mercator|transverseMercator)
- Warp surface type. The default is 'spherical'.
- --seam_megapix <float>
- Resolution for seam estimation step. The default is 0.1 Mpx.
- --seam (no|voronoi|gc_color|gc_colorgrad)
- Seam estimation method. The default is 'gc_color'.
- --compose_megapix <float>
- Resolution for compositing step. Use -1 for original resolution.
- The default is -1.
- --expos_comp (no|gain|gain_blocks)
- Exposure compensation method. The default is 'gain_blocks'.
- --blend (no|feather|multiband)
- Blending method. The default is 'multiband'.
- --blend_strength <float>
- Blending strength from [0,100] range. The default is 5.
- --output <result_img>
- The default is 'result.jpg'.
- --timelapse (as_is|crop)
- Output warped images separately as frames of a time lapse movie, with 'fixed_' prepended to input file names.
- --rangewidth <int>
- uses range_width to limit number of images to match with.\n
- """
+"""
+Stitching sample (advanced)
+===========================
+
+Show how to use Stitcher API from python.
+"""
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
import numpy as np
import cv2 as cv
+
import sys
import argparse
-parser = argparse.ArgumentParser(description='stitching_detailed')
+parser = argparse.ArgumentParser(prog='stitching_detailed.py', description='Rotation model images stitcher')
parser.add_argument('img_names', nargs='+',help='files to stitch',type=str)
parser.add_argument('--preview',help='Run stitching in the preview mode. Works faster than usual mode but output image will have lower resolution.',type=bool,dest = 'preview' )
parser.add_argument('--try_cuda',action = 'store', default = False,help='Try to use CUDA. The default value is no. All default values are for CPU mode.',type=bool,dest = 'try_cuda' )
parser.add_argument('--output',action = 'store', default = 'result.jpg',help='The default is "result.jpg"',type=str,dest = 'output' )
parser.add_argument('--timelapse',action = 'store', default = None,help='Output warped images separately as frames of a time lapse movie, with "fixed_" prepended to input file names.',type=str,dest = 'timelapse' )
parser.add_argument('--rangewidth',action = 'store', default = -1,help='uses range_width to limit number of images to match with.',type=int,dest = 'rangewidth' )
-args = parser.parse_args()
-img_names=args.img_names
-print(img_names)
-preview = args.preview
-try_cuda = args.try_cuda
-work_megapix = args.work_megapix
-seam_megapix = args.seam_megapix
-compose_megapix = args.compose_megapix
-conf_thresh = args.conf_thresh
-features_type = args.features
-matcher_type = args.matcher
-estimator_type = args.estimator
-ba_cost_func = args.ba
-ba_refine_mask = args.ba_refine_mask
-wave_correct = args.wave_correct
-if wave_correct=='no':
- do_wave_correct= False
-else:
- do_wave_correct=True
-if args.save_graph is None:
- save_graph = False
-else:
- save_graph =True
- save_graph_to = args.save_graph
-warp_type = args.warp
-if args.expos_comp=='no':
- expos_comp_type = cv.detail.ExposureCompensator_NO
-elif args.expos_comp=='gain':
- expos_comp_type = cv.detail.ExposureCompensator_GAIN
-elif args.expos_comp=='gain_blocks':
- expos_comp_type = cv.detail.ExposureCompensator_GAIN_BLOCKS
-elif args.expos_comp=='channel':
- expos_comp_type = cv.detail.ExposureCompensator_CHANNELS
-elif args.expos_comp=='channel_blocks':
- expos_comp_type = cv.detail.ExposureCompensator_CHANNELS_BLOCKS
-else:
- print("Bad exposure compensation method")
- exit()
-expos_comp_nr_feeds = args.expos_comp_nr_feeds
-expos_comp_nr_filtering = args.expos_comp_nr_filtering
-expos_comp_block_size = args.expos_comp_block_size
-match_conf = args.match_conf
-seam_find_type = args.seam
-blend_type = args.blend
-blend_strength = args.blend_strength
-result_name = args.output
-if args.timelapse is not None:
- timelapse = True
- if args.timelapse=="as_is":
- timelapse_type = cv.detail.Timelapser_AS_IS
- elif args.timelapse=="crop":
- timelapse_type = cv.detail.Timelapser_CROP
+
+__doc__ += '\n' + parser.format_help()
+
+def main():
+ args = parser.parse_args()
+ img_names=args.img_names
+ print(img_names)
+ preview = args.preview
+ try_cuda = args.try_cuda
+ work_megapix = args.work_megapix
+ seam_megapix = args.seam_megapix
+ compose_megapix = args.compose_megapix
+ conf_thresh = args.conf_thresh
+ features_type = args.features
+ matcher_type = args.matcher
+ estimator_type = args.estimator
+ ba_cost_func = args.ba
+ ba_refine_mask = args.ba_refine_mask
+ wave_correct = args.wave_correct
+ if wave_correct=='no':
+ do_wave_correct= False
else:
- print("Bad timelapse method")
- exit()
-else:
- timelapse= False
-range_width = args.rangewidth
-if features_type=='orb':
- finder= cv.ORB.create()
-elif features_type=='surf':
- finder= cv.xfeatures2d_SURF.create()
-elif features_type=='sift':
- finder= cv.xfeatures2d_SIFT.create()
-else:
- print ("Unknown descriptor type")
- exit()
-seam_work_aspect = 1
-full_img_sizes=[]
-features=[]
-images=[]
-is_work_scale_set = False
-is_seam_scale_set = False
-is_compose_scale_set = False;
-for name in img_names:
- full_img = cv.imread(name)
- if full_img is None:
- print("Cannot read image ",name)
+ do_wave_correct=True
+ if args.save_graph is None:
+ save_graph = False
+ else:
+ save_graph =True
+ save_graph_to = args.save_graph
+ warp_type = args.warp
+ if args.expos_comp=='no':
+ expos_comp_type = cv.detail.ExposureCompensator_NO
+ elif args.expos_comp=='gain':
+ expos_comp_type = cv.detail.ExposureCompensator_GAIN
+ elif args.expos_comp=='gain_blocks':
+ expos_comp_type = cv.detail.ExposureCompensator_GAIN_BLOCKS
+ elif args.expos_comp=='channel':
+ expos_comp_type = cv.detail.ExposureCompensator_CHANNELS
+ elif args.expos_comp=='channel_blocks':
+ expos_comp_type = cv.detail.ExposureCompensator_CHANNELS_BLOCKS
+ else:
+ print("Bad exposure compensation method")
exit()
- full_img_sizes.append((full_img.shape[1],full_img.shape[0]))
- if work_megapix < 0:
- img = full_img
- work_scale = 1
- is_work_scale_set = True
+ expos_comp_nr_feeds = args.expos_comp_nr_feeds
+ expos_comp_nr_filtering = args.expos_comp_nr_filtering
+ expos_comp_block_size = args.expos_comp_block_size
+ match_conf = args.match_conf
+ seam_find_type = args.seam
+ blend_type = args.blend
+ blend_strength = args.blend_strength
+ result_name = args.output
+ if args.timelapse is not None:
+ timelapse = True
+ if args.timelapse=="as_is":
+ timelapse_type = cv.detail.Timelapser_AS_IS
+ elif args.timelapse=="crop":
+ timelapse_type = cv.detail.Timelapser_CROP
+ else:
+ print("Bad timelapse method")
+ exit()
+ else:
+ timelapse= False
+ range_width = args.rangewidth
+ if features_type=='orb':
+ finder= cv.ORB.create()
+ elif features_type=='surf':
+ finder= cv.xfeatures2d_SURF.create()
+ elif features_type=='sift':
+ finder= cv.xfeatures2d_SIFT.create()
else:
- if is_work_scale_set is False:
- work_scale = min(1.0, np.sqrt(work_megapix * 1e6 / (full_img.shape[0]*full_img.shape[1])))
+ print ("Unknown descriptor type")
+ exit()
+ seam_work_aspect = 1
+ full_img_sizes=[]
+ features=[]
+ images=[]
+ is_work_scale_set = False
+ is_seam_scale_set = False
+ is_compose_scale_set = False;
+ for name in img_names:
+ full_img = cv.imread(cv.samples.findFile(name))
+ if full_img is None:
+ print("Cannot read image ", name)
+ exit()
+ full_img_sizes.append((full_img.shape[1],full_img.shape[0]))
+ if work_megapix < 0:
+ img = full_img
+ work_scale = 1
is_work_scale_set = True
- img = cv.resize(src=full_img, dsize=None, fx=work_scale, fy=work_scale, interpolation=cv.INTER_LINEAR_EXACT)
- if is_seam_scale_set is False:
- seam_scale = min(1.0, np.sqrt(seam_megapix * 1e6 / (full_img.shape[0]*full_img.shape[1])))
- seam_work_aspect = seam_scale / work_scale
- is_seam_scale_set = True
- imgFea= cv.detail.computeImageFeatures2(finder,img)
- features.append(imgFea)
- img = cv.resize(src=full_img, dsize=None, fx=seam_scale, fy=seam_scale, interpolation=cv.INTER_LINEAR_EXACT)
- images.append(img)
-if matcher_type== "affine":
- matcher = cv.detail_AffineBestOf2NearestMatcher(False, try_cuda, match_conf)
-elif range_width==-1:
- matcher = cv.detail.BestOf2NearestMatcher_create(try_cuda, match_conf)
-else:
- matcher = cv.detail.BestOf2NearestRangeMatcher_create(range_width, try_cuda, match_conf)
-p=matcher.apply2(features)
-matcher.collectGarbage()
-if save_graph:
- f = open(save_graph_to,"w")
- f.write(cv.detail.matchesGraphAsString(img_names, p, conf_thresh))
- f.close()
-indices=cv.detail.leaveBiggestComponent(features,p,0.3)
-img_subset =[]
-img_names_subset=[]
-full_img_sizes_subset=[]
-num_images=len(indices)
-for i in range(len(indices)):
- img_names_subset.append(img_names[indices[i,0]])
- img_subset.append(images[indices[i,0]])
- full_img_sizes_subset.append(full_img_sizes[indices[i,0]])
-images = img_subset;
-img_names = img_names_subset;
-full_img_sizes = full_img_sizes_subset;
-num_images = len(img_names)
-if num_images < 2:
- print("Need more images")
- exit()
+ else:
+ if is_work_scale_set is False:
+ work_scale = min(1.0, np.sqrt(work_megapix * 1e6 / (full_img.shape[0]*full_img.shape[1])))
+ is_work_scale_set = True
+ img = cv.resize(src=full_img, dsize=None, fx=work_scale, fy=work_scale, interpolation=cv.INTER_LINEAR_EXACT)
+ if is_seam_scale_set is False:
+ seam_scale = min(1.0, np.sqrt(seam_megapix * 1e6 / (full_img.shape[0]*full_img.shape[1])))
+ seam_work_aspect = seam_scale / work_scale
+ is_seam_scale_set = True
+ imgFea= cv.detail.computeImageFeatures2(finder,img)
+ features.append(imgFea)
+ img = cv.resize(src=full_img, dsize=None, fx=seam_scale, fy=seam_scale, interpolation=cv.INTER_LINEAR_EXACT)
+ images.append(img)
+ if matcher_type== "affine":
+ matcher = cv.detail_AffineBestOf2NearestMatcher(False, try_cuda, match_conf)
+ elif range_width==-1:
+ matcher = cv.detail.BestOf2NearestMatcher_create(try_cuda, match_conf)
+ else:
+ matcher = cv.detail.BestOf2NearestRangeMatcher_create(range_width, try_cuda, match_conf)
+ p=matcher.apply2(features)
+ matcher.collectGarbage()
+ if save_graph:
+ f = open(save_graph_to,"w")
+ f.write(cv.detail.matchesGraphAsString(img_names, p, conf_thresh))
+ f.close()
+ indices=cv.detail.leaveBiggestComponent(features,p,0.3)
+ img_subset =[]
+ img_names_subset=[]
+ full_img_sizes_subset=[]
+ num_images=len(indices)
+ for i in range(len(indices)):
+ img_names_subset.append(img_names[indices[i,0]])
+ img_subset.append(images[indices[i,0]])
+ full_img_sizes_subset.append(full_img_sizes[indices[i,0]])
+ images = img_subset;
+ img_names = img_names_subset;
+ full_img_sizes = full_img_sizes_subset;
+ num_images = len(img_names)
+ if num_images < 2:
+ print("Need more images")
+ exit()
-if estimator_type == "affine":
- estimator = cv.detail_AffineBasedEstimator()
-else:
- estimator = cv.detail_HomographyBasedEstimator()
-b, cameras =estimator.apply(features,p,None)
-if not b:
- print("Homography estimation failed.")
- exit()
-for cam in cameras:
- cam.R=cam.R.astype(np.float32)
+ if estimator_type == "affine":
+ estimator = cv.detail_AffineBasedEstimator()
+ else:
+ estimator = cv.detail_HomographyBasedEstimator()
+ b, cameras =estimator.apply(features,p,None)
+ if not b:
+ print("Homography estimation failed.")
+ exit()
+ for cam in cameras:
+ cam.R=cam.R.astype(np.float32)
-if ba_cost_func == "reproj":
- adjuster = cv.detail_BundleAdjusterReproj()
-elif ba_cost_func == "ray":
- adjuster = cv.detail_BundleAdjusterRay()
-elif ba_cost_func == "affine":
- adjuster = cv.detail_BundleAdjusterAffinePartial()
-elif ba_cost_func == "no":
- adjuster = cv.detail_NoBundleAdjuster()
-else:
- print( "Unknown bundle adjustment cost function: ", ba_cost_func )
- exit()
-adjuster.setConfThresh(1)
-refine_mask=np.zeros((3,3),np.uint8)
-if ba_refine_mask[0] == 'x':
- refine_mask[0,0] = 1
-if ba_refine_mask[1] == 'x':
- refine_mask[0,1] = 1
-if ba_refine_mask[2] == 'x':
- refine_mask[0,2] = 1
-if ba_refine_mask[3] == 'x':
- refine_mask[1,1] = 1
-if ba_refine_mask[4] == 'x':
- refine_mask[1,2] = 1
-adjuster.setRefinementMask(refine_mask)
-b,cameras = adjuster.apply(features,p,cameras)
-if not b:
- print("Camera parameters adjusting failed.")
- exit()
-focals=[]
-for cam in cameras:
- focals.append(cam.focal)
-sorted(focals)
-if len(focals)%2==1:
- warped_image_scale = focals[len(focals) // 2]
-else:
- warped_image_scale = (focals[len(focals) // 2]+focals[len(focals) // 2-1])/2
-if do_wave_correct:
- rmats=[]
+ if ba_cost_func == "reproj":
+ adjuster = cv.detail_BundleAdjusterReproj()
+ elif ba_cost_func == "ray":
+ adjuster = cv.detail_BundleAdjusterRay()
+ elif ba_cost_func == "affine":
+ adjuster = cv.detail_BundleAdjusterAffinePartial()
+ elif ba_cost_func == "no":
+ adjuster = cv.detail_NoBundleAdjuster()
+ else:
+ print( "Unknown bundle adjustment cost function: ", ba_cost_func )
+ exit()
+ adjuster.setConfThresh(1)
+ refine_mask=np.zeros((3,3),np.uint8)
+ if ba_refine_mask[0] == 'x':
+ refine_mask[0,0] = 1
+ if ba_refine_mask[1] == 'x':
+ refine_mask[0,1] = 1
+ if ba_refine_mask[2] == 'x':
+ refine_mask[0,2] = 1
+ if ba_refine_mask[3] == 'x':
+ refine_mask[1,1] = 1
+ if ba_refine_mask[4] == 'x':
+ refine_mask[1,2] = 1
+ adjuster.setRefinementMask(refine_mask)
+ b,cameras = adjuster.apply(features,p,cameras)
+ if not b:
+ print("Camera parameters adjusting failed.")
+ exit()
+ focals=[]
for cam in cameras:
- rmats.append(np.copy(cam.R))
- rmats = cv.detail.waveCorrect( rmats, cv.detail.WAVE_CORRECT_HORIZ)
- for idx,cam in enumerate(cameras):
- cam.R = rmats[idx]
-corners=[]
-mask=[]
-masks_warped=[]
-images_warped=[]
-sizes=[]
-masks=[]
-for i in range(0,num_images):
- um=cv.UMat(255*np.ones((images[i].shape[0],images[i].shape[1]),np.uint8))
- masks.append(um)
+ focals.append(cam.focal)
+ sorted(focals)
+ if len(focals)%2==1:
+ warped_image_scale = focals[len(focals) // 2]
+ else:
+ warped_image_scale = (focals[len(focals) // 2]+focals[len(focals) // 2-1])/2
+ if do_wave_correct:
+ rmats=[]
+ for cam in cameras:
+ rmats.append(np.copy(cam.R))
+ rmats = cv.detail.waveCorrect( rmats, cv.detail.WAVE_CORRECT_HORIZ)
+ for idx,cam in enumerate(cameras):
+ cam.R = rmats[idx]
+ corners=[]
+ mask=[]
+ masks_warped=[]
+ images_warped=[]
+ sizes=[]
+ masks=[]
+ for i in range(0,num_images):
+ um=cv.UMat(255*np.ones((images[i].shape[0],images[i].shape[1]),np.uint8))
+ masks.append(um)
-warper = cv.PyRotationWarper(warp_type,warped_image_scale*seam_work_aspect) # warper peut etre nullptr?
-for idx in range(0,num_images):
- K = cameras[idx].K().astype(np.float32)
- swa = seam_work_aspect
- K[0,0] *= swa
- K[0,2] *= swa
- K[1,1] *= swa
- K[1,2] *= swa
- corner,image_wp =warper.warp(images[idx],K,cameras[idx].R,cv.INTER_LINEAR, cv.BORDER_REFLECT)
- corners.append(corner)
- sizes.append((image_wp.shape[1],image_wp.shape[0]))
- images_warped.append(image_wp)
+ warper = cv.PyRotationWarper(warp_type,warped_image_scale*seam_work_aspect) # warper peut etre nullptr?
+ for idx in range(0,num_images):
+ K = cameras[idx].K().astype(np.float32)
+ swa = seam_work_aspect
+ K[0,0] *= swa
+ K[0,2] *= swa
+ K[1,1] *= swa
+ K[1,2] *= swa
+ corner,image_wp =warper.warp(images[idx],K,cameras[idx].R,cv.INTER_LINEAR, cv.BORDER_REFLECT)
+ corners.append(corner)
+ sizes.append((image_wp.shape[1],image_wp.shape[0]))
+ images_warped.append(image_wp)
- p,mask_wp =warper.warp(masks[idx],K,cameras[idx].R,cv.INTER_NEAREST, cv.BORDER_CONSTANT)
- masks_warped.append(mask_wp.get())
-images_warped_f=[]
-for img in images_warped:
- imgf=img.astype(np.float32)
- images_warped_f.append(imgf)
-if cv.detail.ExposureCompensator_CHANNELS == expos_comp_type:
- compensator = cv.detail_ChannelsCompensator(expos_comp_nr_feeds)
-# compensator.setNrGainsFilteringIterations(expos_comp_nr_filtering)
-elif cv.detail.ExposureCompensator_CHANNELS_BLOCKS == expos_comp_type:
- compensator=cv.detail_BlocksChannelsCompensator(expos_comp_block_size, expos_comp_block_size,expos_comp_nr_feeds)
-# compensator.setNrGainsFilteringIterations(expos_comp_nr_filtering)
-else:
- compensator=cv.detail.ExposureCompensator_createDefault(expos_comp_type)
-compensator.feed(corners=corners, images=images_warped, masks=masks_warped)
-if seam_find_type == "no":
- seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_NO)
-elif seam_find_type == "voronoi":
- seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_VORONOI_SEAM);
-elif seam_find_type == "gc_color":
- seam_finder = cv.detail_GraphCutSeamFinder("COST_COLOR")
-elif seam_find_type == "gc_colorgrad":
- seam_finder = cv.detail_GraphCutSeamFinder("COST_COLOR_GRAD")
-elif seam_find_type == "dp_color":
- seam_finder = cv.detail_DpSeamFinder("COLOR")
-elif seam_find_type == "dp_colorgrad":
- seam_finder = cv.detail_DpSeamFinder("COLOR_GRAD")
-if seam_finder is None:
- print("Can't create the following seam finder ",seam_find_type)
- exit()
-seam_finder.find(images_warped_f, corners,masks_warped )
-imgListe=[]
-compose_scale=1
-corners=[]
-sizes=[]
-images_warped=[]
-images_warped_f=[]
-masks=[]
-blender= None
-timelapser=None
-compose_work_aspect=1
-for idx,name in enumerate(img_names): # https://github.com/opencv/opencv/blob/master/samples/cpp/stitching_detailed.cpp#L725 ?
- full_img = cv.imread(name)
- if not is_compose_scale_set:
- if compose_megapix > 0:
- compose_scale = min(1.0, np.sqrt(compose_megapix * 1e6 / (full_img.shape[0]*full_img.shape[1])))
- is_compose_scale_set = True;
- compose_work_aspect = compose_scale / work_scale;
- warped_image_scale *= compose_work_aspect
- warper = cv.PyRotationWarper(warp_type,warped_image_scale)
- for i in range(0,len(img_names)):
- cameras[i].focal *= compose_work_aspect
- cameras[i].ppx *= compose_work_aspect
- cameras[i].ppy *= compose_work_aspect
- sz = (full_img_sizes[i][0] * compose_scale,full_img_sizes[i][1]* compose_scale)
- K = cameras[i].K().astype(np.float32)
- roi = warper.warpRoi(sz, K, cameras[i].R);
- corners.append(roi[0:2])
- sizes.append(roi[2:4])
- if abs(compose_scale - 1) > 1e-1:
- img =cv.resize(src=full_img, dsize=None, fx=compose_scale, fy=compose_scale, interpolation=cv.INTER_LINEAR_EXACT)
+ p,mask_wp =warper.warp(masks[idx],K,cameras[idx].R,cv.INTER_NEAREST, cv.BORDER_CONSTANT)
+ masks_warped.append(mask_wp.get())
+ images_warped_f=[]
+ for img in images_warped:
+ imgf=img.astype(np.float32)
+ images_warped_f.append(imgf)
+ if cv.detail.ExposureCompensator_CHANNELS == expos_comp_type:
+ compensator = cv.detail_ChannelsCompensator(expos_comp_nr_feeds)
+ # compensator.setNrGainsFilteringIterations(expos_comp_nr_filtering)
+ elif cv.detail.ExposureCompensator_CHANNELS_BLOCKS == expos_comp_type:
+ compensator=cv.detail_BlocksChannelsCompensator(expos_comp_block_size, expos_comp_block_size,expos_comp_nr_feeds)
+ # compensator.setNrGainsFilteringIterations(expos_comp_nr_filtering)
else:
- img = full_img;
- img_size = (img.shape[1],img.shape[0]);
- K=cameras[idx].K().astype(np.float32)
- corner,image_warped =warper.warp(img,K,cameras[idx].R,cv.INTER_LINEAR, cv.BORDER_REFLECT)
- mask =255*np.ones((img.shape[0],img.shape[1]),np.uint8)
- p,mask_warped =warper.warp(mask,K,cameras[idx].R,cv.INTER_NEAREST, cv.BORDER_CONSTANT)
- compensator.apply(idx,corners[idx],image_warped,mask_warped)
- image_warped_s = image_warped.astype(np.int16)
- image_warped=[]
- dilated_mask = cv.dilate(masks_warped[idx],None)
- seam_mask = cv.resize(dilated_mask,(mask_warped.shape[1],mask_warped.shape[0]),0,0,cv.INTER_LINEAR_EXACT)
- mask_warped = cv.bitwise_and(seam_mask,mask_warped)
- if blender==None and not timelapse:
- blender = cv.detail.Blender_createDefault(cv.detail.Blender_NO)
- dst_sz = cv.detail.resultRoi(corners=corners,sizes=sizes)
- blend_width = np.sqrt(dst_sz[2]*dst_sz[3]) * blend_strength / 100
- if blend_width < 1:
+ compensator=cv.detail.ExposureCompensator_createDefault(expos_comp_type)
+ compensator.feed(corners=corners, images=images_warped, masks=masks_warped)
+ if seam_find_type == "no":
+ seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_NO)
+ elif seam_find_type == "voronoi":
+ seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_VORONOI_SEAM);
+ elif seam_find_type == "gc_color":
+ seam_finder = cv.detail_GraphCutSeamFinder("COST_COLOR")
+ elif seam_find_type == "gc_colorgrad":
+ seam_finder = cv.detail_GraphCutSeamFinder("COST_COLOR_GRAD")
+ elif seam_find_type == "dp_color":
+ seam_finder = cv.detail_DpSeamFinder("COLOR")
+ elif seam_find_type == "dp_colorgrad":
+ seam_finder = cv.detail_DpSeamFinder("COLOR_GRAD")
+ if seam_finder is None:
+ print("Can't create the following seam finder ",seam_find_type)
+ exit()
+ seam_finder.find(images_warped_f, corners,masks_warped )
+ imgListe=[]
+ compose_scale=1
+ corners=[]
+ sizes=[]
+ images_warped=[]
+ images_warped_f=[]
+ masks=[]
+ blender= None
+ timelapser=None
+ compose_work_aspect=1
+ for idx,name in enumerate(img_names): # https://github.com/opencv/opencv/blob/master/samples/cpp/stitching_detailed.cpp#L725 ?
+ full_img = cv.imread(name)
+ if not is_compose_scale_set:
+ if compose_megapix > 0:
+ compose_scale = min(1.0, np.sqrt(compose_megapix * 1e6 / (full_img.shape[0]*full_img.shape[1])))
+ is_compose_scale_set = True;
+ compose_work_aspect = compose_scale / work_scale;
+ warped_image_scale *= compose_work_aspect
+ warper = cv.PyRotationWarper(warp_type,warped_image_scale)
+ for i in range(0,len(img_names)):
+ cameras[i].focal *= compose_work_aspect
+ cameras[i].ppx *= compose_work_aspect
+ cameras[i].ppy *= compose_work_aspect
+ sz = (full_img_sizes[i][0] * compose_scale,full_img_sizes[i][1]* compose_scale)
+ K = cameras[i].K().astype(np.float32)
+ roi = warper.warpRoi(sz, K, cameras[i].R);
+ corners.append(roi[0:2])
+ sizes.append(roi[2:4])
+ if abs(compose_scale - 1) > 1e-1:
+ img =cv.resize(src=full_img, dsize=None, fx=compose_scale, fy=compose_scale, interpolation=cv.INTER_LINEAR_EXACT)
+ else:
+ img = full_img;
+ img_size = (img.shape[1],img.shape[0]);
+ K=cameras[idx].K().astype(np.float32)
+ corner,image_warped =warper.warp(img,K,cameras[idx].R,cv.INTER_LINEAR, cv.BORDER_REFLECT)
+ mask =255*np.ones((img.shape[0],img.shape[1]),np.uint8)
+ p,mask_warped =warper.warp(mask,K,cameras[idx].R,cv.INTER_NEAREST, cv.BORDER_CONSTANT)
+ compensator.apply(idx,corners[idx],image_warped,mask_warped)
+ image_warped_s = image_warped.astype(np.int16)
+ image_warped=[]
+ dilated_mask = cv.dilate(masks_warped[idx],None)
+ seam_mask = cv.resize(dilated_mask,(mask_warped.shape[1],mask_warped.shape[0]),0,0,cv.INTER_LINEAR_EXACT)
+ mask_warped = cv.bitwise_and(seam_mask,mask_warped)
+ if blender==None and not timelapse:
blender = cv.detail.Blender_createDefault(cv.detail.Blender_NO)
- elif blend_type == "multiband":
- blender = cv.detail_MultiBandBlender()
- blender.setNumBands((np.log(blend_width)/np.log(2.) - 1.).astype(np.int))
- elif blend_type == "feather":
- blender = cv.detail_FeatherBlender()
- blender.setSharpness(1./blend_width)
- blender.prepare(dst_sz)
- elif timelapser==None and timelapse:
- timelapser = cv.detail.Timelapser_createDefault(timelapse_type)
- timelapser.initialize(corners, sizes)
- if timelapse:
- matones=np.ones((image_warped_s.shape[0],image_warped_s.shape[1]), np.uint8)
- timelapser.process(image_warped_s, matones, corners[idx])
- pos_s = img_names[idx].rfind("/");
- if pos_s == -1:
- fixedFileName = "fixed_" + img_names[idx];
+ dst_sz = cv.detail.resultRoi(corners=corners,sizes=sizes)
+ blend_width = np.sqrt(dst_sz[2]*dst_sz[3]) * blend_strength / 100
+ if blend_width < 1:
+ blender = cv.detail.Blender_createDefault(cv.detail.Blender_NO)
+ elif blend_type == "multiband":
+ blender = cv.detail_MultiBandBlender()
+ blender.setNumBands((np.log(blend_width)/np.log(2.) - 1.).astype(np.int))
+ elif blend_type == "feather":
+ blender = cv.detail_FeatherBlender()
+ blender.setSharpness(1./blend_width)
+ blender.prepare(dst_sz)
+ elif timelapser==None and timelapse:
+ timelapser = cv.detail.Timelapser_createDefault(timelapse_type)
+ timelapser.initialize(corners, sizes)
+ if timelapse:
+ matones=np.ones((image_warped_s.shape[0],image_warped_s.shape[1]), np.uint8)
+ timelapser.process(image_warped_s, matones, corners[idx])
+ pos_s = img_names[idx].rfind("/");
+ if pos_s == -1:
+ fixedFileName = "fixed_" + img_names[idx];
+ else:
+ fixedFileName = img_names[idx][:pos_s + 1 ]+"fixed_" + img_names[idx][pos_s + 1: ]
+ cv.imwrite(fixedFileName, timelapser.getDst())
else:
- fixedFileName = img_names[idx][:pos_s + 1 ]+"fixed_" + img_names[idx][pos_s + 1: ]
- cv.imwrite(fixedFileName, timelapser.getDst())
- else:
- blender.feed(cv.UMat(image_warped_s), mask_warped, corners[idx])
-if not timelapse:
- result=None
- result_mask=None
- result,result_mask = blender.blend(result,result_mask)
- cv.imwrite(result_name,result)
- zoomx =600/result.shape[1]
- dst=cv.normalize(src=result,dst=None,alpha=255.,norm_type=cv.NORM_MINMAX,dtype=cv.CV_8U)
- dst=cv.resize(dst,dsize=None,fx=zoomx,fy=zoomx)
- cv.imshow(result_name,dst)
- cv.waitKey()
+ blender.feed(cv.UMat(image_warped_s), mask_warped, corners[idx])
+ if not timelapse:
+ result=None
+ result_mask=None
+ result,result_mask = blender.blend(result,result_mask)
+ cv.imwrite(result_name,result)
+ zoomx = 600.0 / result.shape[1]
+ dst=cv.normalize(src=result,dst=None,alpha=255.,norm_type=cv.NORM_MINMAX,dtype=cv.CV_8U)
+ dst=cv.resize(dst,dsize=None,fx=zoomx,fy=zoomx)
+ cv.imshow(result_name,dst)
+ cv.waitKey()
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
+ cv.destroyAllWindows()
import numpy as np
import cv2 as cv
-if __name__ == '__main__':
+def main():
import sys
try:
fn = sys.argv[1]
cv.imshow('input', img)
cv.imshow('flow', vis)
cv.waitKey()
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
+ cv.destroyAllWindows()
from __future__ import print_function
import numpy as np
+import cv2 as cv
+
from numpy import pi, sin, cos
-import cv2 as cv
defaultSize = 512
else:
self.currentRect = self.initialRect + np.int( 30*cos(self.time*self.speed) + 50*sin(self.time*self.speed))
if self.deformation:
- self.currentRect[1:3] += self.h/20*cos(self.time)
+ self.currentRect[1:3] += int(self.h/20*cos(self.time))
cv.fillConvexPoly(img, self.currentRect, (0, 0, 255))
self.time += self.timeStep
self.time = 0.0
-if __name__ == '__main__':
-
+def main():
backGr = cv.imread(cv.samples.findFile('graf1.png'))
fgr = cv.imread(cv.samples.findFile('box.png'))
ch = cv.waitKey(3)
if ch == 27:
break
- #import os
- #print (os.environ['PYTHONPATH'])
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
Press ESC to stop.
'''
-if __name__ == '__main__':
+def main():
print(help_message)
w, h = 512, 512
cv.imshow('a', vis)
if cv.waitKey(5) == 27:
break
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
cv.destroyAllWindows()
--- /dev/null
+
+import cv2 as cv
+import numpy as np
+import argparse
+
+W = 52 # window size is WxW
+C_Thr = 0.43 # threshold for coherency
+LowThr = 35 # threshold1 for orientation, it ranges from 0 to 180
+HighThr = 57 # threshold2 for orientation, it ranges from 0 to 180
+
+## [calcGST]
+## [calcJ_header]
+## [calcGST_proto]
+def calcGST(inputIMG, w):
+## [calcGST_proto]
+ img = inputIMG.astype(np.float32)
+
+ # GST components calculation (start)
+ # J = (J11 J12; J12 J22) - GST
+ imgDiffX = cv.Sobel(img, cv.CV_32F, 1, 0, 3)
+ imgDiffY = cv.Sobel(img, cv.CV_32F, 0, 1, 3)
+ imgDiffXY = cv.multiply(imgDiffX, imgDiffY)
+ ## [calcJ_header]
+
+ imgDiffXX = cv.multiply(imgDiffX, imgDiffX)
+ imgDiffYY = cv.multiply(imgDiffY, imgDiffY)
+
+ J11 = cv.boxFilter(imgDiffXX, cv.CV_32F, (w,w))
+ J22 = cv.boxFilter(imgDiffYY, cv.CV_32F, (w,w))
+ J12 = cv.boxFilter(imgDiffXY, cv.CV_32F, (w,w))
+ # GST components calculations (stop)
+
+ # eigenvalue calculation (start)
+ # lambda1 = J11 + J22 + sqrt((J11-J22)^2 + 4*J12^2)
+ # lambda2 = J11 + J22 - sqrt((J11-J22)^2 + 4*J12^2)
+ tmp1 = J11 + J22
+ tmp2 = J11 - J22
+ tmp2 = cv.multiply(tmp2, tmp2)
+ tmp3 = cv.multiply(J12, J12)
+ tmp4 = np.sqrt(tmp2 + 4.0 * tmp3)
+
+ lambda1 = tmp1 + tmp4 # biggest eigenvalue
+ lambda2 = tmp1 - tmp4 # smallest eigenvalue
+ # eigenvalue calculation (stop)
+
+ # Coherency calculation (start)
+ # Coherency = (lambda1 - lambda2)/(lambda1 + lambda2)) - measure of anisotropism
+ # Coherency is anisotropy degree (consistency of local orientation)
+ imgCoherencyOut = cv.divide(lambda1 - lambda2, lambda1 + lambda2)
+ # Coherency calculation (stop)
+
+ # orientation angle calculation (start)
+ # tan(2*Alpha) = 2*J12/(J22 - J11)
+ # Alpha = 0.5 atan2(2*J12/(J22 - J11))
+ imgOrientationOut = cv.phase(J22 - J11, 2.0 * J12, angleInDegrees = True)
+ imgOrientationOut = 0.5 * imgOrientationOut
+ # orientation angle calculation (stop)
+
+ return imgCoherencyOut, imgOrientationOut
+## [calcGST]
+
+parser = argparse.ArgumentParser(description='Code for Anisotropic image segmentation tutorial.')
+parser.add_argument('-i', '--input', help='Path to input image.', required=True)
+args = parser.parse_args()
+
+imgIn = cv.imread(args.input, cv.IMREAD_GRAYSCALE)
+if imgIn is None:
+ print('Could not open or find the image: {}'.format(args.input))
+ exit(0)
+
+## [main_extra]
+## [main]
+imgCoherency, imgOrientation = calcGST(imgIn, W)
+
+## [thresholding]
+_, imgCoherencyBin = cv.threshold(imgCoherency, C_Thr, 255, cv.THRESH_BINARY)
+_, imgOrientationBin = cv.threshold(imgOrientation, LowThr, HighThr, cv.THRESH_BINARY)
+## [thresholding]
+
+## [combining]
+imgBin = cv.bitwise_and(imgCoherencyBin, imgOrientationBin)
+## [combining]
+## [main]
+
+imgCoherency = cv.normalize(imgCoherency, None, alpha=0, beta=1, norm_type=cv.NORM_MINMAX, dtype=cv.CV_32F)
+imgOrientation = cv.normalize(imgOrientation, None, alpha=0, beta=1, norm_type=cv.NORM_MINMAX, dtype=cv.CV_32F)
+
+cv.imshow('result.jpg', np.uint8(0.5*(imgIn + imgBin)))
+cv.imshow('Coherency.jpg', imgCoherency)
+cv.imshow('Orientation.jpg', imgOrientation)
+cv.waitKey(0)
+## [main_extra]
# Python 2/3 compatibility
from __future__ import print_function
+import numpy as np
+import cv2 as cv
+
import re
-import numpy as np
from numpy import pi, sin, cos
-import cv2 as cv
-
# built-in modules
from time import clock
def get(self):
return self.data
-if __name__ == '__main__':
+def main():
import sys
- print(__doc__)
-
try:
fn = sys.argv[1]
except:
threaded_mode = not threaded_mode
if ch == 27:
break
-cv.destroyAllWindows()
+
+ print('Done')
+
+
+if __name__ == '__main__':
+ print(__doc__)
+ main()
+ cv.destroyAllWindows()
# Python 2/3 compatibility
from __future__ import print_function
+import numpy as np
import cv2 as cv
-def decode_fourcc(v):
- v = int(v)
- return "".join([chr((v >> 8 * i) & 0xFF) for i in range(4)])
+def main():
-font = cv.FONT_HERSHEY_SIMPLEX
-color = (0, 255, 0)
+ def decode_fourcc(v):
+ v = int(v)
+ return "".join([chr((v >> 8 * i) & 0xFF) for i in range(4)])
-cap = cv.VideoCapture(0)
-cap.set(cv.CAP_PROP_AUTOFOCUS, False) # Known bug: https://github.com/opencv/opencv/pull/5474
+ font = cv.FONT_HERSHEY_SIMPLEX
+ color = (0, 255, 0)
-cv.namedWindow("Video")
+ cap = cv.VideoCapture(0)
+ cap.set(cv.CAP_PROP_AUTOFOCUS, False) # Known bug: https://github.com/opencv/opencv/pull/5474
-convert_rgb = True
-fps = int(cap.get(cv.CAP_PROP_FPS))
-focus = int(min(cap.get(cv.CAP_PROP_FOCUS) * 100, 2**31-1)) # ceil focus to C_LONG as Python3 int can go to +inf
+ cv.namedWindow("Video")
-cv.createTrackbar("FPS", "Video", fps, 30, lambda v: cap.set(cv.CAP_PROP_FPS, v))
-cv.createTrackbar("Focus", "Video", focus, 100, lambda v: cap.set(cv.CAP_PROP_FOCUS, v / 100))
+ convert_rgb = True
+ fps = int(cap.get(cv.CAP_PROP_FPS))
+ focus = int(min(cap.get(cv.CAP_PROP_FOCUS) * 100, 2**31-1)) # ceil focus to C_LONG as Python3 int can go to +inf
-while True:
- status, img = cap.read()
+ cv.createTrackbar("FPS", "Video", fps, 30, lambda v: cap.set(cv.CAP_PROP_FPS, v))
+ cv.createTrackbar("Focus", "Video", focus, 100, lambda v: cap.set(cv.CAP_PROP_FOCUS, v / 100))
- fourcc = decode_fourcc(cap.get(cv.CAP_PROP_FOURCC))
+ while True:
+ status, img = cap.read()
- fps = cap.get(cv.CAP_PROP_FPS)
+ fourcc = decode_fourcc(cap.get(cv.CAP_PROP_FOURCC))
- if not bool(cap.get(cv.CAP_PROP_CONVERT_RGB)):
- if fourcc == "MJPG":
- img = cv.imdecode(img, cv.IMREAD_GRAYSCALE)
- elif fourcc == "YUYV":
- img = cv.cvtColor(img, cv.COLOR_YUV2GRAY_YUYV)
- else:
- print("unsupported format")
+ fps = cap.get(cv.CAP_PROP_FPS)
+
+ if not bool(cap.get(cv.CAP_PROP_CONVERT_RGB)):
+ if fourcc == "MJPG":
+ img = cv.imdecode(img, cv.IMREAD_GRAYSCALE)
+ elif fourcc == "YUYV":
+ img = cv.cvtColor(img, cv.COLOR_YUV2GRAY_YUYV)
+ else:
+ print("unsupported format")
+ break
+
+ cv.putText(img, "Mode: {}".format(fourcc), (15, 40), font, 1.0, color)
+ cv.putText(img, "FPS: {}".format(fps), (15, 80), font, 1.0, color)
+ cv.imshow("Video", img)
+
+ k = cv.waitKey(1)
+
+ if k == 27:
break
+ elif k == ord('g'):
+ convert_rgb = not convert_rgb
+ cap.set(cv.CAP_PROP_CONVERT_RGB, convert_rgb)
- cv.putText(img, "Mode: {}".format(fourcc), (15, 40), font, 1.0, color)
- cv.putText(img, "FPS: {}".format(fps), (15, 80), font, 1.0, color)
- cv.imshow("Video", img)
+ print('Done')
- k = cv.waitKey(1)
- if k == 27:
- break
- elif k == ord('g'):
- convert_rgb = not convert_rgb
- cap.set(cv.CAP_PROP_CONVERT_RGB, convert_rgb)
+if __name__ == '__main__':
+ print(__doc__)
+ main()
+ cv.destroyAllWindows()
if __name__ == '__main__':
+ print(__doc__)
import sys
try:
fn = sys.argv[1]
except:
fn = 'fruits.jpg'
- print(__doc__)
App(cv.samples.findFile(fn)).run()