1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-25 21:33:04 +04:00

Compare commits

...

246 Commits

Author SHA1 Message Date
Alexander Alekhin 591708903b release: OpenCV 3.4.15 2021-07-04 21:10:13 +00:00
Alexander Alekhin f9d62fba7a Merge pull request #20350 from alalek:issue_20285 2021-07-04 21:07:02 +00:00
Alexander Alekhin 9d039c206b Merge pull request #20354 from alalek:issue_20353 2021-07-04 18:41:34 +00:00
Alexander Alekhin 4c3f9b2ef4 cmake: update Halide detection 2021-07-04 13:20:52 +03:00
Alexander Alekhin 0e523618a1 cmake: exclude -pthread from Emscripten default build 2021-07-03 11:13:28 +00:00
Alexander Alekhin 3b26105f68 Merge pull request #20346 from alalek:backport_20026 2021-07-03 00:27:55 +00:00
Alexander Alekhin 0f2f966a91 Merge pull request #20345 from mitruska:update_ngraph_normalizel2 2021-07-02 23:37:03 +00:00
Alexander Alekhin d7d491d445 Merge pull request #20344 from alalek:backport_20343 2021-07-02 23:35:12 +00:00
Alexander Alekhin 9b0d6862c4 cmake(IE): extract INF_ENGINE_RELEASE from InferenceEngine package 2021-07-02 23:29:35 +00:00
Alexander Alekhin 890fcdf842 Merge pull request #20337 from alalek:build_opencv_winpack_dldt_2021.4.0 2021-07-02 21:47:14 +00:00
mitruska 18dbac203f Use explicit version of ngraph NormalizeL2 2021-07-02 21:33:05 +00:00
Alexander Alekhin 8d1f254dcc java: force using of 'Ptr<>' for OpenCV classes
backport of commit: e5841d3126
2021-07-02 21:20:08 +00:00
Alexander Alekhin 90df3af6cf build: winpack_dldt with dldt 2021.4.0 2021-07-02 09:58:00 +00:00
Alexander Alekhin b699fe7a9d Merge pull request #20335 from SamFC10:concat-const-input 2021-07-01 10:25:35 +00:00
Alexander Alekhin b2ed5c3070 Merge pull request #20333 from APrigarina:fix_samples_3.4 2021-07-01 09:41:56 +00:00
SamFC10 5b8c10f2f8 modified onnx importer to concat const input blobs 2021-07-01 10:58:31 +05:30
Alexander Alekhin 24983f62e2 Merge pull request #20325 from alalek:dnn_openvino_2021.4.0 2021-06-30 23:58:26 +00:00
Alexander Alekhin f2057ce1ab dnn(ie): replace deprecated calls 2021-06-30 22:30:15 +00:00
Alexander Alekhin 6797fd65a5 dnn(test): update tests for OpenVINO 2021.4 2021-06-30 22:30:15 +00:00
Alexander Alekhin 947e06a860 Merge pull request #20328 from alalek:backport_20321 2021-06-30 20:51:49 +00:00
Alexander Alekhin 04d5ba266f Merge pull request #20330 from Wovchena:fix-arg-for-calcHist-in-demos 2021-06-30 14:59:22 +00:00
Vladimir 90be83ae99 Fix an arg for calcHist() in demos
`float* histRange = { range };` doesn't make much sense. `histRange` is
an array of array(s), so it should have a type of ptr to ptr. Strangely
some domos are correct as well as the example for the function
https://docs.opencv.org/master/d6/dc7/group__imgproc__hist.html#ga4b2b5fd75503ff9e6844cc4dcdaed35d
2021-06-30 17:22:56 +03:00
APrigarina 5e80bd3cc9 fix samples 3.4 2021-06-30 12:50:21 +03:00
Alexander Alekhin db4b1e613c core(persistence): fix types format handling
partial backport of 4eac198270
2021-06-29 21:54:52 +00:00
Alexander Alekhin 7d842f5bcf dnn: use OpenVINO 2021.4 defines 2021-06-29 18:48:21 +00:00
Alexander Alekhin 828304d587 Merge pull request #20128 from kikaxa:master 2021-06-21 21:52:17 +00:00
Alexander Alekhin 9d584475f6 Merge pull request #20283 from SamFC10:fix-batchnorm 2021-06-21 11:27:12 +00:00
kikaxa bb60cb0bf9 Reenable filesystem for ios builds 2021-06-20 16:33:25 +00:00
SamFC10 55e1dfb778 Fix BatchNorm reinitialization 2021-06-20 13:19:29 +05:30
Alexander Alekhin c2263db7bc Merge pull request #20232 from gasparitiago:drawMatches3.4 2021-06-18 19:47:52 +00:00
Alexander Alekhin 7bbbda71df Merge pull request #20253 from rogday:gtk_modifiers 2021-06-18 15:46:44 +00:00
Alexander Alekhin 8e0baf257c Merge pull request #20263 from vrabaud:3.4 2021-06-15 18:20:21 +00:00
Vincent Rabaud c8268e65fd Fix potential NaN in cv::norm.
There can be an int overflow.
cv::norm( InputArray _src, int normType, InputArray _mask ) is fine,
not cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask ).
2021-06-15 14:58:11 +02:00
Tiago De Gaspari 3cf4375387 Merge pull request #19842 from gasparitiago:3.4
Update rotatedRectangleIntersection function to calculate near to origin

* Change type used in points function from RotatedRect

In the function that sets the points of a RotatedRect, the types

should be double in order to keep the precision when dealing with
RotatedRects that are defined far from the origin.

This commit solves the problem in some assertions from
rotatedRectangleIntersection when dealing with rectangles far from
origin.

* added proper type casts

* Update rotatedRectangleIntersection function to calculate near to origin

This commit changes the rotatedRectangleIntersection function in order
to calculate the intersection of two rectangles considering that they
are shifted near the coordinates origin (0, 0).

This commit solves the problem in some assertions from
rotatedRectangleIntersection when dealing with rectangles far from
origin.

* Revert type changes in types.cpp and adequate code to c++98

* Revert unnecessary casts on types.cpp

Co-authored-by: Vadim Pisarevsky <vadim.pisarevsky@gmail.com>
2021-06-12 23:28:54 +03:00
Alexander Alekhin c1adbe3189 Merge pull request #20190 from rogday:tf_importer_ref 2021-06-11 20:06:09 +00:00
rogday 7ee1816612 split if into map of functions 2021-06-11 13:20:45 +03:00
Smirnov Egor 8f4f834ce6 applied modifier mask to the state 2021-06-10 10:57:15 +03:00
Alexander Alekhin 2b84c97a78 Merge pull request #20251 from alalek:python_sys_path_0_workaround 2021-06-09 10:58:18 +00:00
Alexander Alekhin 3ddf84534b Merge pull request #20248 from alalek:issue_20246 2021-06-09 10:52:16 +00:00
Alexander Alekhin bd26104088 python(loader): add workaround to detect and patch sys.path[0] 2021-06-09 09:51:07 +00:00
Alexander Alekhin 5f80f43ff5 core: fix nSize initialization in cvIplImage() 2021-06-09 07:31:38 +00:00
Alexander Alekhin b221143c0f Merge pull request #20241 from alalek:fixup_20149 2021-06-08 13:44:58 +00:00
Alexander Alekhin 995841624c highgui(gtk): fix NULL ptr checks 2021-06-08 10:57:24 +00:00
Alexander Alekhin bbcd06f42f Merge pull request #20236 from alalek:update_version_3.4.15-pre 2021-06-07 22:05:29 +00:00
Alexander Alekhin 43940f7ffc pre: OpenCV 3.4.15 (version++) 2021-06-07 20:10:34 +00:00
jogo- f4a79b0554 Merge pull request #20223 from jogo-:3.4_wp8_samples_typos
* Fix typo in App.xaml.cs

* Fix typo in App.xaml.cs

* Fix typo in App.xaml.cs
2021-06-07 17:32:14 +00:00
Tiago De Gaspari 411fd2b761 Add Thickness parameter in drawMatches function
This commit adds the feature of selecting the thickness
of the matches drawn by the drawMatches function.

In larger images, the default thickness of 1 pixel creates images
that are hard to visualize.
2021-06-07 12:52:48 -03:00
Alexander Alekhin 61e30c15a9 Merge pull request #20211 from kstuedem:fix_dshow_memory_leak 2021-06-05 16:02:12 +00:00
Alexander Alekhin d332f33346 Merge pull request #20210 from kstuedem:fix_invalid_media_type 2021-06-05 16:01:51 +00:00
Kai Stüdemann 636db09d73 videoio(dshow) fix incompatible media type left set on video device 2021-06-04 10:45:39 +02:00
Kai Stüdemann 64c018507b videoio(dshow) fix memory leak 2021-06-04 10:02:48 +02:00
Alexander Alekhin c34445a496 Merge pull request #20201 from PolarNick239:3.4 2021-06-03 16:20:24 +00:00
Paul Jurczak ff60abb575 Merge pull request #20080 from pauljurczak:patch-3
* Update dnn.hpp

getPerfProfile is not supported by the CUDA backend, see https://github.com/opencv/opencv/issues/20077

* dnn.hpp: fix doxygen formatting
2021-06-02 19:15:52 +00:00
Alexander Alekhin 7d91dfe339 Merge pull request #20146 from asmorkalov:as/java_test_filter 2021-06-02 17:50:29 +00:00
Alexander Alekhin 15af65d4cf Merge pull request #20149 from rogday:on_mouse_floor 2021-06-02 17:48:43 +00:00
Alexander Alekhin 81afeda537 Merge pull request #20192 from alalek:update_libjpeg-turbo 2021-06-02 16:30:25 +00:00
Alexander Alekhin e10de25e86 Merge pull request #20191 from alalek:issue_20032 2021-06-02 16:29:51 +00:00
Nikolay Polyarniy 746bd47ce5 EXR reading: support Z channel if no Y channel 2021-06-02 15:53:32 +03:00
Alexander Alekhin dcb4cabb26 3rdparty: libjpeg-turbo 2.0.6 => 2.1.0
https://github.com/libjpeg-turbo/libjpeg-turbo/releases/tag/2.1.0
2021-06-01 20:01:19 +00:00
Alexander Alekhin 59b4baee0c ts: migrate from cgi.escape to html.escape in .py file 2021-06-01 19:19:05 +00:00
Alexander Alekhin bb3bbd192b Merge pull request #20150 from rogday:svm_detector_test 2021-06-01 13:31:12 +00:00
Alexander Smorkalov 1212aef03b Analog of gtest_filter for java tests. 2021-06-01 11:04:18 +03:00
Developer-Ecosystem-Engineering 814550d2a6 Merge pull request #20011 from Developer-Ecosystem-Engineering:3.4
Improve performance on Arm64

* Improve performance on Apple silicon

This patch will
- Enable dot product intrinsics for macOS arm64 builds
- Enable for macOS arm64 builds
- Improve HAL primitives
  - reduction (sum, min, max, sad)
  - signmask
  - mul_expand
  - check_any / check_all

Results on a M1 Macbook Pro

* Updates to #20011 based on feedback

  - Removes Apple Silicon specific workarounds
  - Makes #ifdef sections smaller for v_mul_expand cases
  - Moves dot product optimization to compiler optimization check
  - Adds 4x4 matrix transpose optimization

* Remove dotprod and fix v_transpose

Based on the latest, we've removed dotprod entirely and will revisit in a future PR.

Added explicit cats with v_transpose4x4()

This should resolve all opens with this PR

* Remove commented out lines

Remove two extraneous comments
2021-06-01 09:39:55 +03:00
Smirnov Egor fb68fe8930 bring back bounds check and switch to floor 2021-05-31 19:03:50 +03:00
yo1990 d3be58b6d7 Merge pull request #20102 from yo1990:master
Add missing sqrt to magSpectrum().

* https://github.com/opencv/opencv/issues/20100

* slight optimization + fix for double-precision case

Co-authored-by: Yuma Oyama <yuma.oyama@acuity-inc.co.jp>
Co-authored-by: Vadim Pisarevsky <vadim.pisarevsky@me.com>
2021-05-29 17:43:21 +03:00
Jonathan Deakin 8ecfbdb4ff Merge pull request #19883 from jondea:arm-neon-optimised-color-lab-3.4
* Add Neon optimised RGB2Lab conversion

* Fix compile errors, change lambda to macro

* Change NEON optimised RGB2Lab to just use HAL

* Change [] to v_extract_n in RGB2Lab

* RGB2LAB Code quality, change to nlane agnostic

* Change RGB2Lab to use function rather than macro

* Remove whitespace

Co-authored-by: Francesco Petrogalli <25690309+fpetrogalli@users.noreply.github.com>
2021-05-28 14:20:26 +00:00
Alexander Alekhin 63256a00ff Merge pull request #20174 from alalek:issue_20159 2021-05-28 14:10:17 +00:00
Alexander Alekhin 450dc92452 Merge pull request #20172 from alalek:fixup_19334 2021-05-28 14:09:52 +00:00
Alexander Alekhin 3d2f4fa164 highgui: fix trackbar value pointer handling 2021-05-28 01:58:58 +00:00
Alexander Alekhin 3d394943e6 core(ocl): avoid limit of Image kernel args 2021-05-28 00:43:59 +00:00
Alexander Alekhin 3e25f32c9b Merge pull request #20158 from hyrodium:fix/latex 2021-05-26 06:31:05 +00:00
hyrodium 81567a9d3e fix latex script in the docs 2021-05-26 12:46:14 +09:00
Vadim Pisarevsky 4a2adba8f4 Merge pull request #20135 from mightbxg:bugfix_GaussianBlur 2021-05-25 12:54:56 +00:00
Smirnov Egor 84f78059d3 add reproducer and bugfix 2021-05-25 11:28:23 +03:00
Xinguang Bian 7499a15c92 fix data overflow problem in GaussianBlur 2021-05-21 15:17:20 +08:00
Alexander Alekhin 5f4e55bc68 Merge pull request #20123 from catree:fix_tsai_park_bib_render 2021-05-19 14:19:53 +00:00
catree c621384707 Use correct BibTeX syntax for month field. 2021-05-19 14:24:07 +02:00
thezane c0162a64d1 Merge pull request #20103 from thezane:make-div-spectrums-public
* Make divSpectrums public

* Add unit test
2021-05-19 12:14:11 +03:00
Alexander Alekhin 1ae16beb06 Merge pull request #20097 from komakai:fix_qrcode_test 2021-05-17 17:53:35 +00:00
Giles Payne e53a4ce64d Fix for failing QRCodeDetectorTest.testDetectAndDecodeMulti test 2021-05-17 20:09:12 +09:00
Alexander Alekhin 72655a9eea Merge pull request #20085 from changh95:fix_typo_calib3d_sample_code 2021-05-17 07:26:51 +00:00
Alexander Alekhin 125f890dc3 Merge pull request #20088 from alalek:cmake_module_linker_flags 2021-05-17 07:26:25 +00:00
changh95 101d50703c fix typo 'undistorsed'->'undistorted' 2021-05-16 15:08:37 +09:00
Alexander Alekhin 901ed5545f cmake: fix handling of CMAKE_MODULE_LINKER_FLAGS 2021-05-14 17:47:00 +00:00
Alexander Alekhin 699b4b9fc5 Merge pull request #20071 from rogday:depth_fallback_doc 2021-05-14 06:09:09 +00:00
Smirnov Egor 1d7d18afba Document imwrite depth fallback 2021-05-12 19:55:58 +03:00
Alexander Alekhin b335fe67b0 Merge pull request #20049 from jstaahl:jstaahl-static-inits 2021-05-11 17:06:11 +00:00
Alexander Alekhin dde029f105 Merge pull request #20053 from berak:core_mat_ptr_vec 2021-05-11 16:34:03 +00:00
berak 302c2354a3 core: add missing implementation for Mat::ptr(Vec) 2021-05-09 14:15:12 +02:00
Jake Staahl 158b13e0ba Remove static initializers caused by templated static member. 2021-05-07 12:53:14 -07:00
Alexander Alekhin b1dc7ed873 Merge pull request #20033 from berak:dnn_openpose_py 2021-05-07 12:42:16 +00:00
berak 1bced43e96 samples/dnn: better errormsg in openpose.py 2021-05-05 10:39:12 +02:00
Alexander Alekhin 8550f7e04d Merge pull request #20018 from lpea:doc_fixes_calib3d 2021-05-01 09:35:59 +00:00
Guillaume Jacob 9f3e83baf6 calib3d: Update documentation of calibrateCamera
- Added missing documentation for the CALIB_FIX_FOCAL_LENGTH flag
- Removed erroneous information about the number of distortion coefficients
returned
- Added some missing @ref tags
2021-04-30 20:34:04 +02:00
Alexander Alekhin 17ab61a40d Merge pull request #19956 from danielenricocahall:fix-edge-case-matcher-loop 2021-04-30 17:22:16 +00:00
Danny 1b844f8413 Merge pull request #19993 from danielenricocahall:fix-compute-ecc-issue
Fix unsigned int bug in computeECC

* address issue with unsigned ints in computeEcc

* remove additional logic checking firstOctave

* use swap instead of same src/dst

* simplify the unsigned check logic
2021-04-30 17:20:52 +00:00
Alexander Alekhin baa22fa808 Merge pull request #20006 from alalek:dnn_ie_gpu_cache_dir 2021-04-30 17:18:52 +00:00
Alexander Alekhin f78cebfc98 Merge pull request #20014 from alalek:fix_core_tls_process_termination 2021-04-30 16:06:40 +00:00
Alexander Alekhin d2a9ca13f1 core(tls): handle process termination / cleanup issues 2021-04-29 23:25:44 +00:00
Alexander Alekhin 71bae7c23f dnn(ie): implicit usage of IE::GPU OpenCL kernels cache 2021-04-29 12:43:22 +03:00
Alexander Alekhin d4f104f17f Merge pull request #19988 from alexkalmuk:fix-squares-cpp-sample 2021-04-28 22:03:14 +00:00
Alexander Alekhin fd44ba296d Merge pull request #19984 from sturkmen72:patch-4 2021-04-28 22:02:02 +00:00
Alex Kalmuk b04d6a2d9b Fix squares sample failure when a single file passed 2021-04-28 09:36:04 +03:00
Alexander Alekhin a08eac452e Merge pull request #19979 from micha137:patch-3 2021-04-27 13:31:05 +00:00
micha137 7021ea6748 Fix link 2021-04-27 11:22:07 +02:00
Alexander Alekhin 55aa1d4852 Merge pull request #19975 from danielenricocahall:fix-template-matcher-sqdiff 2021-04-26 22:52:13 +00:00
Suleyman TURKMEN 159534313e Update CMakeLists.txt 2021-04-26 22:43:04 +03:00
Alexander Alekhin 2f68c43e39 Merge pull request #19983 from hartmannathan:typo-fix-download 2021-04-26 19:25:56 +00:00
Nathan Hartman e2483aa072 Fix typo: 'DOWNLAOD' to 'DOWNLOAD' 2021-04-26 11:01:13 -04:00
Alexander Alekhin c69f37343c Merge pull request #19980 from zchrissirhcz:fix-CV_XADD-missing-return-type 2021-04-26 14:10:51 +00:00
Alexander Alekhin aec62a7fc5 Merge pull request #19969 from alalek:issue_19850 2021-04-26 13:23:29 +00:00
Zhuo Zhang bf26050f7e Fix missing return type for unsafe CV_XADD function 2021-04-26 20:08:45 +08:00
danielenricocahall 402bce1a31 address template matching sqdiff bug 2021-04-25 22:17:07 -04:00
Alexander Alekhin 8868350888 doxygen: fix quotes in add_toggle macro 2021-04-23 22:31:04 +00:00
Stefano Allegretti 1b64851fa8 Merge pull request #19951 from stal12:3.4
* Fix #4363 - wrong hierarchy (CV_RETR_TREE) in findContours

* Add regression test for findContours

* use C++11 => C++98 on 3.4 branch
2021-04-22 18:20:12 +00:00
Aleksandr Voron 2e143b8799 Merge pull request #19961 from alvoron:dnn_ngraph_int64_fix
Explicit usage of int64_t in CropAndResizeLayer (IE backend)

* Update crop_and_resize_layer.cpp
2021-04-21 18:29:19 +00:00
danielenricocahall 3930c9a492 fix loop boundary condition 2021-04-20 22:08:01 -04:00
Alexander Alekhin f0839d2703 Merge pull request #19944 from berak:patch-1 2021-04-20 17:16:52 +00:00
berak 405e820fe1 Update contrast_preserve.hpp
fix a build warning:

```
C:\Slave\workspace\precommit\windows10\opencv\modules\photo\src\contrast_preserve.hpp(289): warning C4244: '=': conversion from 'double' to '_Tp', possible loss of data
        with
        [
            _Tp=float
        ]
C:\Slave\workspace\precommit\windows10\opencv\modules\photo\src\contrast_preserve.hpp(361): warning C4244: '=': conversion from 'double' to '_Tp', possible loss of data
        with
        [
            _Tp=float
        ]
```

(from https://build.opencv.org.cn/job/precommit/job/windows10/1633/console)
2021-04-20 12:59:36 +02:00
Alexander Alekhin 6598e9d506 Merge pull request #19908 from CSBVision:patch-2 2021-04-15 20:45:30 +00:00
Alexander Alekhin 8c2cf89845 Merge pull request #19913 from mshabunin:fix-san-build 2021-04-15 11:15:37 +00:00
Maksim Shabunin aeb8dfc52d Fix header sorting for modules without headers 2021-04-15 12:13:15 +03:00
Alexander Alekhin 0649a2fbdb Merge pull request #19886 from alalek:issue_19875 2021-04-14 16:14:44 +00:00
CSBVision ec32061f5f Update __init__.py to support symbolic links
Currently, the LOADER_DIR is set as os.path.dirname(os.path.abspath(__file__)). This does not point to the true library path if the cv2 folder is symlinked into the Python package directory such that importing cv2 under Python fails. The proposed change only resolves symbolic links correctly by calling os.path.realpath(__file__) first and does not change anything if __file__ contains no symbolic link.
2021-04-14 16:13:45 +00:00
Alexander Alekhin f2da1a0a7a Merge pull request #19900 from berak:doc_fix_python_retval 2021-04-13 17:38:07 +00:00
Alexander Alekhin fda1e6f148 Merge pull request #19901 from alalek:ml_update_checks 2021-04-13 15:47:01 +00:00
berak 2a48730166 docs:fix python retvals 2021-04-13 15:48:31 +02:00
Alexander Alekhin 0bdbc745c4 ml: update checks 2021-04-13 11:09:14 +00:00
Alexander Alekhin 6f70b0524a Merge pull request #19894 from alalek:fix_ml_tree_legacy_import 2021-04-12 20:33:34 +00:00
Alexander Alekhin b9b19185bc ml: fix legacy import in DTreesImpl 2021-04-12 19:21:48 +00:00
Alexander Alekhin 63ba9970bd Merge pull request #19851 from sturkmen72:update_documentation 2021-04-11 21:44:03 +00:00
Danny a9a6801c6d Merge pull request #19884 from danielenricocahall:fix-prediction-features-bug
Fix bug with predictions in RTrees/Boost

* address bug where predict functions with invalid feature count in rtrees/boost models

* compact matrix rep in tests

* check 1..n-1 and n+1 in feature size validation test
2021-04-09 16:56:14 +00:00
Alexander Alekhin 222af8e7e4 core: avoid process cleanup deadlock if TlsStorage is not used 2021-04-09 16:08:08 +00:00
Suleyman TURKMEN ec8b7c933a Update Documentation 2021-04-08 22:29:45 +03:00
Danny 76860933f0 Merge pull request #19859 from danielenricocahall:fix-blob-detector-single-thresh
Fix Single ThresholdBug in Simple Blob Detector

* address bug with using min dist between blobs in blob detector

cast type in comparison and remove docs

address bug with using min dist between blobs in blob detector

use scalar instead of int

address bug with using min dist between blobs in blob detector

* fix namespace and formatting
2021-04-08 10:39:26 +00:00
Alexander Alekhin 19a936fc03 Merge pull request #19836 from 103yiran:warpaffine 2021-04-08 10:32:27 +00:00
Alexander Alekhin be17fce657 Merge pull request #19847 from gasparitiago:expose-max-iters 2021-04-08 10:31:36 +00:00
Alexander Alekhin 9a1d7736f8 Merge pull request #19838 from mshabunin:fix-intel-ipp-link 2021-04-07 09:42:32 +00:00
Tiago De Gaspari 9f295b2c91 Expose maxIters in findEssentialMat
Lets the user choose the maximum number of iterations the robust
estimator runs for, similary to findFundamentalMat
and findHomography functions.
2021-04-07 00:07:33 -03:00
Alexander Alekhin 3a8154051f Merge pull request #19810 from aarongreig:aaron/core/relaxClArithmTest 2021-04-06 19:56:46 +00:00
Aaron Greig f3f46096d6 Relax accuracy requirements in the OpenCL sqrt perf arithmetic test.
Also bring perf_imgproc CornerMinEigenVal accuracy requirements in line with
the test_imgproc accuracy requirements on that test and fix indentation on
the latter.

Partially addresses issue #9821
2021-04-06 17:32:48 +01:00
Alexander Alekhin ace37df941 Merge pull request #19854 from gasparitiago:fundamentalMat-fix 2021-04-06 10:19:57 +00:00
Tiago De Gaspari ac9182f20d Add maxIters parameter to LMeDS method in findFundamentalMat
This commit passes the parameter maxIters that represent
the maximum number of iterations, that can be passed to findFundamentalMat
to the method LMeDS.

This parameter were added to the function findFundamentalMat and
were passed just for the RANSAC method, but should be passed to
both methods to be consistent.
2021-04-03 21:56:05 -03:00
Alexander Alekhin 2cf1a13755 Merge tag '3.4.14' 2021-04-02 09:31:32 +00:00
Maksim Shabunin 6465e393b6 IPP: use linker workaround for Intel compiler on Linux 2021-04-02 10:44:32 +03:00
103yiran 6e6c0f31f7 delete unused variable 2021-04-02 10:30:27 +08:00
Alexander Alekhin d0e3e638c3 release: OpenCV 3.4.14 2021-04-01 21:37:19 +00:00
Alexander Alekhin 6a72bf5085 Merge pull request #19823 from alalek:issue_contrib_2895 2021-04-01 20:38:46 +00:00
Alexander Alekhin 0ff57e3292 Merge pull request #19830 from alalek:issue_19368 2021-04-01 15:30:18 +00:00
Alexander Alekhin 5db484b6c2 Merge pull request #19831 from alalek:backport_19771 2021-04-01 14:05:09 +00:00
Alexander Alekhin 6865787a75 Merge pull request #19827 from alalek:build_videoio_macosx_override_3.4 2021-04-01 12:34:23 +00:00
Alexander Alekhin 7f664850f5 Merge pull request #19825 from alalek:cmake_fix_headers_order_python_3.4 2021-04-01 12:34:10 +00:00
Alexander Alekhin 2907fb88f5 Merge pull request #19822 from alalek:core_wui_backward_compatibility 2021-04-01 12:32:33 +00:00
Alexander Alekhin d7cb2ea210 videoio(dshow): add NULL ptr check 2021-04-01 11:28:41 +00:00
Alexander Alekhin 4ae2c11520 videoio(build): eliminate inconsistent 'override' warnings 2021-04-01 09:56:21 +00:00
Alexander Alekhin 1b3e0b27af cmake: fix files order in Python bindings
- with changes backport from 4.x
2021-04-01 09:48:50 +00:00
Alexander Alekhin e4b0251e9d cuda: fix inplace condition in cv::cuda::flip 2021-04-01 02:26:59 +00:00
Alexander Alekhin b26f5b9468 core: backward compatibility for vx_store/vx_store_aligned calls 2021-04-01 02:17:47 +00:00
Alexander Alekhin 5340dc6686 Merge pull request #19819 from alalek:cmake_fix_headers_order 2021-04-01 01:34:21 +00:00
Alexander Alekhin 2b86de217a cmake: fix order of headers
- cmake uses filesystem's order which may vary
- unpredictable headers order may cause build failures (primary bindings)
2021-03-31 23:16:46 +00:00
Alexander Alekhin 1615afd7f4 Merge pull request #19814 from alalek:pyopencv_to_safe 2021-03-31 22:58:18 +00:00
Alexander Alekhin 908957317f Merge pull request #19813 from alalek:issue_19506 2021-03-31 22:57:50 +00:00
Alexander Alekhin 6fa2bdd7f2 Merge pull request #19812 from alalek:workaround_19634 2021-03-31 22:57:15 +00:00
Alexander Alekhin f82303d614 Merge pull request #19811 from alalek:issue_19599 2021-03-31 22:56:48 +00:00
Alexander Alekhin 6773fa03e2 Merge pull request #19808 from alalek:3.4_python_fix_wrap_as 2021-03-31 22:56:14 +00:00
Alexander Alekhin d651ff8d6b python: exception-free pyopencv_to() wrapper 2021-03-31 14:18:32 +00:00
Alexander Alekhin 8069a6b4f8 core(IPP): disable some ippsMagnitude_32f calls 2021-03-31 13:38:57 +00:00
Alexander Alekhin b697b3162f videoio(mjpeg): disable parallel encoder 2021-03-31 12:35:12 +00:00
Alexander Alekhin 53a16b1186 Merge pull request #19809 from alalek:issue_19513 2021-03-31 10:50:20 +00:00
Alexander Alekhin a2a92999be core(arithm_op): workaround problem with scalars handling 2021-03-31 10:35:52 +00:00
Alexander Alekhin 40c0830b63 videoio(avfoundation): add getCaptureDomain() 2021-03-31 09:35:11 +00:00
eplankin 6f1eefec69 Merge pull request #19681 from eplankin:link_problem
* Workaround for IPP linking problem

* Apply -Bsymbolic to all cases when IPP is on

* Tried to hide symbols on MacOS

* Tried on --exclude-libs option

* Fixed macos and win warnings

* Fixed win build

* cmake(IPP): move --exclude-libs,libippcore.a to IPP CMake file

Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com>
2021-03-31 09:24:37 +00:00
Alexander Alekhin bb6e15f2c0 python: fix CV_WRAP_AS handling 2021-03-30 22:02:48 +00:00
Alexander Alekhin 0dcb99cf23 Merge pull request #19798 from LupusSanctus:am/reduce_sum_ch 2021-03-30 21:37:13 +00:00
Anastasia Murzova cc6d48959e Added reduce sum by channel support 2021-03-30 23:01:22 +03:00
Vitaly Tuzov aab62aa6dd Merge pull request #18952 from terfendail:wui_doc
* Updated UI documentation to address WUI

* Added documentation for vx_ calls

* Removed vx_store operation overload

* Doxyfile updated to enable wide UI

* Enable doxygen documentation for vx_ WUI functions

* Wide intrinsics definition rework

* core: fix SIMD C++ emulator build (supports 128-bit only)
2021-03-30 16:18:03 +00:00
Alexander Alekhin ac9f3a1242 Merge pull request #19793 from aarongreig:aaron/imgproc/relaxCornerEigenValTest 2021-03-29 13:41:44 +00:00
Aaron Greig 53652a6194 Relax accuracy requirement on OpenCL MinEigenVal corner kernel test.
The MinEigenVal path through the corner.cl kernel makes use of native_sqrt,
a math builtin function which has implementation defined accuracy.

Partially addresses issue #9821
2021-03-29 12:06:02 +01:00
lionkun 8d232a63ad fix the perf tests of OpenCV.js so that it can run on Node.js successfully 2021-03-27 21:52:44 +00:00
Alexander Alekhin bf03f5fa3a Merge pull request #19786 from alalek:build_opencv_winpack_dldt_2021.3.0 2021-03-26 22:38:52 +00:00
Alexander Alekhin 6e8022a3af Merge pull request #19773 from jondea:add-aarch64-specialised-v_expand-3.4 2021-03-26 16:54:51 +00:00
Alexander Alekhin d27eb79fa6 Merge pull request #19785 from alalek:dnn_ocl_fix_async_kernels 2021-03-26 12:27:58 +00:00
Anastasia M 3e48a91d97 Merge pull request #19546 from LupusSanctus:am/slice_steps
* Added Steps support in DNN Slice layer

* Added code corrections

* dnn(slice): fix OCL and OCL_FP16 processing
2021-03-26 11:04:57 +00:00
Alexander Alekhin 144443d011 build: winpack_dldt with dldt 2021.3.0 2021-03-26 08:58:00 +00:00
Alexander Alekhin 86d0a86141 dnn(ocl): fix gemm kernel scheduling 2021-03-26 00:35:00 +00:00
Mikhail Nikolskii bf9f67e93f Merge pull request #19783 from mikhail-nikolskiy:interop-perf
Performance optimization in DirectX and VAAPI interop

* optimization in OpenCL NV12<>BGR kernels

* reduce kernel work-size
2021-03-25 21:27:31 +00:00
Alexander Alekhin 26ea4760ad Merge pull request #19774 from aarongreig:aaron/dnn/oclTestAccuracyThresholds 2021-03-25 16:58:07 +00:00
Aaron Greig f59917bea1 Introduce relaxed accuracy thresholds for CL target in some dnn tests.
Partially addresses #9821
2021-03-25 10:58:23 +00:00
Alexander Alekhin a394c8b10b Merge pull request #19770 from alalek:dnn_openvino_2021.3.0 2021-03-24 18:50:47 +00:00
Alexander Alekhin e56e4876e7 dnn(test): update tests for OpenVINO 2021.3 2021-03-24 14:50:42 +00:00
Alexander Alekhin 56bdd7db5c dnn: use OpenVINO 2021.3 defines
original commit: 6291503793
2021-03-24 10:26:24 +00:00
Alexander Alekhin 3df6bc58e9 Merge pull request #19765 from LupusSanctus:am/mobilenetv3 2021-03-24 09:43:27 +00:00
Anastasia Murzova e75f1b071b Added reshape corrections 2021-03-24 10:53:11 +03:00
Anastasia Murzova 7a2b3ed471 Corrected DNN elementwise multiplication 2021-03-24 10:53:11 +03:00
Anastasia M 551d4a8ec1 Merge pull request #19477 from LupusSanctus:am/eltwice_vec
* Aligned OpenCV DNN and TF sum op behaviour

Support Mat (shape: [1, m, k, n] ) + Vec (shape: [1, 1, 1, n]) operation
by vec to mat expansion

* Added code corrections: backend, minor refactoring
2021-03-23 22:16:09 +00:00
Jonathan Deakin 29a289dfa1 Add v_expand for AArch64, fuse vmovl+vget_high into vmovl_high 2021-03-23 15:06:41 +00:00
Alexander Alekhin bdd2b57e5d Merge pull request #19757 from alalek:js_setLogLevel 2021-03-21 17:37:05 +00:00
Alexander Alekhin a97f6f8058 js: support setLogLevel() / getLogLevel() calls 2021-03-20 18:14:10 +00:00
Liubov Batanina c0dd82fb53 Merge pull request #19632 from l-bat:lb/ie_arm_target
Added OpenVINO ARM target

* Added IE ARM target

* Added OpenVINO ARM target

* Delete ARM target

* Detect ARM platform

* Changed device name in ArmPlugin

* Change ARM detection
2021-03-20 11:20:02 +00:00
Alexander Alekhin 1211a8b9cd Merge pull request #19745 from alalek:issue_19729 2021-03-19 12:52:34 +00:00
Alexander Alekhin f680505086 features2d(mser): chi_table.h notes 2021-03-18 21:30:12 +00:00
Alexander Alekhin ae60bbc7e4 Merge pull request #19741 from alalek:ml_logistic_regression_use_opencv_license_header 2021-03-18 20:47:44 +00:00
Alexander Alekhin 7664e6d090 ml: use OpenCV license header for logistic regression 2021-03-17 20:29:52 +00:00
Ziachnix 960f501cc1 Merge pull request #19284 from Ziachnix:feature/js-qr-code-detector
Add QRCodeDetector to JavaScript Build

* ADD: js support for qrCodeDetector

- cherry picked commit to solve rebase error

* CHG. Revert haarcascade path

* FIX: Tests without images

* ADD: decodeCurved

* js(docs): don't require OPENCV_TEST_DATA_PATH

Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com>
2021-03-13 12:52:44 +00:00
Alexander Alekhin 7a8e171691 Merge pull request #19720 from alalek:ocl_test_skip_spir_amd 2021-03-13 12:48:20 +00:00
Alexander Alekhin 7ca9740da5 Merge pull request #19718 from alalek:backport_19683 2021-03-13 12:46:24 +00:00
Alexander Alekhin 68fae94cbb Merge pull request #19717 from danbey:bad_value_param_should_be_passed_by_reference 2021-03-13 12:45:55 +00:00
Alexander Alekhin 6da5c7c1d0 Merge pull request #19716 from l-bat:lb/fix_resize 2021-03-13 12:45:07 +00:00
Alexander Alekhin 87e607a19b core(ocl): skip SPIR test on AMD devices if problem detected 2021-03-13 06:12:52 +00:00
Dale Phurrough cbe236652b noexcept def construct Mat, UMat, Mat_, MatSize, MatStep
original commit: 1b0f781b7c
2021-03-12 20:26:32 +00:00
Dan Ben Yosef d4d805cb3e Avoiding copy by passing param by reference
It is best to pass bad_value_ param by reference to avoid copy.
2021-03-12 14:17:11 -05:00
Liubov Batanina 8d29a902e4 Added ngraph::op::v6::MVN 2021-03-12 21:02:03 +03:00
Alexander Alekhin f136adcad5 Merge pull request #19715 from seiko2plus:issue_19698 2021-03-12 09:45:19 +00:00
Liubov Batanina 95ab9468c1 Added ngraph::op::v4::Interpolation 2021-03-12 12:00:59 +03:00
Sayed Adel f8181fbef8 core:ppc64 fix detecting CPU features when optimization is off 2021-03-12 02:02:31 +00:00
Xinguang Bian b995de4ff3 Merge pull request #19253 from mightbxg:bugfix_PnPRansac
* fix unexpected Exception in solvePnPRansac caused by input points

* calib3d: solvePnPRansac - keep minimal changes to handle DLT 6 points requirement

Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com>
2021-03-12 00:53:06 +03:00
Alexander Alekhin 825dadfbdd Merge pull request #19703 from danbey:setting_StereoSGBMParams_in_init_list 2021-03-11 21:33:19 +00:00
Dan Ben Yosef 63048812c7 Init params (StereoSGBMParams) in StereoSGBMImpl constructor initialization list
To improve preformence it is better to init the params (StereoSGBMParams) in the
    initialization list.
2021-03-10 13:05:35 -05:00
Alexander Alekhin e4692ac079 Merge pull request #19613 from WeiChungChang:NMS_refine 2021-03-10 17:36:57 +00:00
Qoo 47337e2196 boost NMS performance 2021-03-10 15:59:26 +00:00
Alexander Alekhin 1d6a1e5f9c Merge pull request #19692 from seiko2plus:issue_19647 2021-03-09 18:14:41 +00:00
Sayed Adel 84fcc4ab9b core:ppc64 fix the build with the newer versions of Eigen on IBM/Power
It also fixes the build when universal intrinsics is disabled
   via `-DDCV_ENABLE_INTRINSICS=OFF`.
2021-03-09 19:20:18 +02:00
Daniel Playfair Cal 65b51e1538 Merge pull request #19690 from hedgepigdaniel:fix/calibration_fisheye
* fix(samples/camera_calibration): set new camera matrix for fisheye

* fix(camera_calibration): ignore inapplicable flags for fisheye
2021-03-09 15:09:08 +00:00
Alexander Alekhin 6c9be1bc1d Merge pull request #19675 from asmorkalov:as/pylint_warnings 2021-03-09 09:43:52 +00:00
Alexander Smorkalov 4c48f1eed2 Removed unused variables found by pylint. 2021-03-09 10:56:45 +03:00
Dan Ben-Yosef 31f66766b7 Merge pull request #19685 from danbey:setting_stereoBMImpl_in_init_list
Init params (StereoBMParams) in StereoBMImpl constructor initialization list

* Init StereoBMImpl in initialization list

To improve preformence it is better to init the params (StereoBMImpl) in the
initialization list.

* coding style

* drop useless copy/move ctor

Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com>
2021-03-07 20:06:08 +03:00
Alexander Alekhin 601690695e Merge pull request #19687 from alalek:videoio_docs_fixes_3.4 2021-03-07 16:23:24 +00:00
Alexander Alekhin 85009800b3 videoio(docs): fixes 2021-03-07 04:26:49 +00:00
Vitaly Tuzov 04a9ff88d8 Merge pull request #19622 from terfendail:ref_doc
* Updated cpp reference implementations for a few intrinsics to address wide universal intrinsics as well

* Updated cpp reference implementations for a few more universal intrinsics
2021-03-06 17:22:21 +00:00
Alexander Alekhin dc24663e8d Merge pull request #19641 from LupusSanctus:am/tf_reshape 2021-03-06 17:21:34 +00:00
Alexander Alekhin d2cc63e779 Merge pull request #19680 from alalek:cmake_update_python_linters 2021-03-06 17:20:02 +00:00
Alexander Alekhin 358878caf7 Merge pull request #19671 from SamFC10:sam-darknet 2021-03-05 15:12:21 +00:00
Mradul Agrawal 640f188ca2 Merge pull request #19583 from theroyalpekka:patch-1
* Update polynom_solver.cpp

This pull request is in the response to Issue  #19526. I have fixed the problem with the cube root calculation of 2*R. The Issue was in the usage of pow function with negative values of R, but if it is calculated for only positive values of R then changing x0 according to the parity of R, the Issue is resolved. Kindly consider it, Thanks!

* add cv::cubeRoot(double)

Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com>
2021-03-05 13:55:52 +00:00
Alexander Alekhin a1e2c4f338 Merge pull request #19655 from raaldrid:EXR_rw_alpha_support_16115 2021-03-05 16:54:31 +03:00
Alexander Alekhin 625d4fc884 cmake: update Python linters handling
- exclude from getBuildInformation()
- fix pylint version
2021-03-05 12:54:51 +00:00
Alexander Alekhin f821530eb0 Merge pull request #19677 from APrigarina:detection_fix 2021-03-05 08:40:27 +00:00
Anastasia Murzova 7894cd3c73 Aligned TF Reshape layer behaviour 2021-03-05 01:01:37 +03:00
APrigarina 125cc79c17 fix false positive detection 2021-03-04 19:20:31 +03:00
Alexander Alekhin 2a808aeec0 Merge pull request #19674 from l-bat:lb/fix_ie_tests 2021-03-04 14:52:20 +00:00
Liubov Batanina 94533e12eb Determine layout 2021-03-04 13:05:01 +03:00
Alexander Alekhin a0008de281 Merge pull request #19607 from alalek:backport_19606 2021-03-03 21:10:57 +00:00
SamFC10 a42d4da003 Added Spatial Attention Module in Darknet Importer 2021-03-03 22:42:47 +05:30
Alexander Alekhin 0689c70dba Merge pull request #19665 from alalek:update_ffmpeg_3.4 2021-03-03 11:22:56 +00:00
Alexander Alekhin 75ad74c893 ffmpeg/3.4: update FFmpeg wrapper 2021.03
- FFmpeg 3.4.8
2021-03-02 23:59:38 +00:00
Alexander Alekhin cbfd38bd41 core: rework code locality
- to reduce binaries size of FFmpeg Windows wrapper
- MinGW linker doesn't support -ffunction-sections (used for FFmpeg Windows wrapper)
- move code to improve locality with its used dependencies
- move UMat::dot() to matmul.dispatch.cpp (Mat::dot() is already there)
- move UMat::inv() to lapack.cpp
- move UMat::mul() to arithm.cpp
- move UMat:eye() to matrix_operations.cpp (near setIdentity() implementation)
- move normalize(): convert_scale.cpp => norm.cpp
- move convertAndUnrollScalar(): arithm.cpp => copy.cpp
- move scalarToRawData(): array.cpp => copy.cpp
- move transpose(): matrix_operations.cpp => matrix_transform.cpp
- move flip(), rotate(): copy.cpp => matrix_transform.cpp (rotate90 uses flip and transpose)
- add 'OPENCV_CORE_EXCLUDE_C_API' CMake variable to exclude compilation of C-API functions from the core module
- matrix_wrap.cpp: add compile-time checks for CUDA/OpenGL calls
- the steps above allow to reduce FFmpeg wrapper size for ~1.5Mb (initial size of OpenCV part is about 3Mb)

backport is done to improve merge experience (less conflicts)
backport of commit: 65eb946756
2021-03-02 23:24:28 +00:00
Rachel A cc22a73d0f EXR alpha support for 4 channel reading and writing. Issue https://github.com/opencv/opencv/issues/16115. 2021-03-02 11:49:56 -08:00
276 changed files with 9024 additions and 4651 deletions
+5 -5
View File
@@ -1,8 +1,8 @@
# Binaries branch name: ffmpeg/3.4_20200907
# Binaries were created for OpenCV: 03bee14372f5537daa56c62e771ec16181ca1f98
ocv_update(FFMPEG_BINARIES_COMMIT "2a96257b743695a47f8012aab1ffb995a1dee8b4")
ocv_update(FFMPEG_FILE_HASH_BIN32 "5e68a3ff82f43ac6524e50e448a34c9c")
ocv_update(FFMPEG_FILE_HASH_BIN64 "205db629d893e7d4865fd1459807ff47")
# Binaries branch name: ffmpeg/3.4_20210302
# Binaries were created for OpenCV: 2ab1f3f166fccc3a01497209cc01c5cea44ff201
ocv_update(FFMPEG_BINARIES_COMMIT "e99214251d9f3cde7c48abd46b2259bddc9885b6")
ocv_update(FFMPEG_FILE_HASH_BIN32 "fad5ada9be36120bba8966709e7953a8")
ocv_update(FFMPEG_FILE_HASH_BIN64 "650e2272728491923e566f784f79cfef")
ocv_update(FFMPEG_FILE_HASH_CMAKE "3b90f67f4b429e77d3da36698cef700c")
function(download_win_ffmpeg script_var)
+3 -4
View File
@@ -3,10 +3,10 @@ project(${JPEG_LIBRARY} C)
ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter -Wsign-compare -Wshorten-64-to-32 -Wimplicit-fallthrough)
set(VERSION_MAJOR 2)
set(VERSION_MINOR 0)
set(VERSION_REVISION 6)
set(VERSION_MINOR 1)
set(VERSION_REVISION 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION})
set(LIBJPEG_TURBO_VERSION_NUMBER 2000006)
set(LIBJPEG_TURBO_VERSION_NUMBER 2001000)
string(TIMESTAMP BUILD "opencv-${OPENCV_VERSION}-libjpeg-turbo")
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
@@ -46,7 +46,6 @@ if(UNIX)
ocv_update(HAVE_UNSIGNED_SHORT 1)
# undef INCOMPLETE_TYPES_BROKEN
ocv_update(RIGHT_SHIFT_IS_UNSIGNED 0)
ocv_update(__CHAR_UNSIGNED__ 0)
endif()
+1 -1
View File
@@ -91,7 +91,7 @@ best of our understanding.
The Modified (3-clause) BSD License
===================================
Copyright (C)2009-2020 D. R. Commander. All Rights Reserved.
Copyright (C)2009-2021 D. R. Commander. All Rights Reserved.<br>
Copyright (C)2015 Viktor Szathmáry. All Rights Reserved.
Redistribution and use in source and binary forms, with or without
+1 -14
View File
@@ -128,7 +128,7 @@ with respect to this software, its quality, accuracy, merchantability, or
fitness for a particular purpose. This software is provided "AS IS", and you,
its user, assume the entire risk as to its quality and accuracy.
This software is copyright (C) 1991-2016, Thomas G. Lane, Guido Vollbeding.
This software is copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding.
All Rights Reserved except as specified below.
Permission is hereby granted to use, copy, modify, and distribute this
@@ -159,19 +159,6 @@ commercial products, provided that all warranty or liability claims are
assumed by the product vendor.
The IJG distribution formerly included code to read and write GIF files.
To avoid entanglement with the Unisys LZW patent (now expired), GIF reading
support has been removed altogether, and the GIF writer has been simplified
to produce "uncompressed GIFs". This technique does not use the LZW
algorithm; the resulting GIF files are larger than usual, but are readable
by all standard GIF decoders.
We are required to state that
"The Graphics Interchange Format(c) is the Copyright property of
CompuServe Incorporated. GIF(sm) is a Service Mark property of
CompuServe Incorporated."
REFERENCES
==========
+1 -1
View File
@@ -3,7 +3,7 @@ Background
libjpeg-turbo is a JPEG image codec that uses SIMD instructions to accelerate
baseline JPEG compression and decompression on x86, x86-64, Arm, PowerPC, and
MIPS systems, as well as progressive JPEG compression on x86 and x86-64
MIPS systems, as well as progressive JPEG compression on x86, x86-64, and Arm
systems. On such systems, libjpeg-turbo is generally 2-6x as fast as libjpeg,
all else being equal. On other types of systems, libjpeg-turbo can still
outperform libjpeg by a significant amount, by virtue of its highly-optimized
-5
View File
@@ -61,11 +61,6 @@
unsigned. */
#cmakedefine RIGHT_SHIFT_IS_UNSIGNED 1
/* Define to 1 if type `char' is unsigned and you are not using gcc. */
#ifndef __CHAR_UNSIGNED__
#cmakedefine __CHAR_UNSIGNED__ 1
#endif
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
-1
View File
@@ -18,7 +18,6 @@
#define HAVE_UNSIGNED_SHORT
#undef INCOMPLETE_TYPES_BROKEN
#undef RIGHT_SHIFT_IS_UNSIGNED
#undef __CHAR_UNSIGNED__
/* Define "boolean" as unsigned char, not int, per Windows custom */
#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
+9 -9
View File
@@ -48,9 +48,9 @@ rgb_ycc_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf,
outptr2 = output_buf[2][output_row];
output_row++;
for (col = 0; col < num_cols; col++) {
r = GETJSAMPLE(inptr[RGB_RED]);
g = GETJSAMPLE(inptr[RGB_GREEN]);
b = GETJSAMPLE(inptr[RGB_BLUE]);
r = inptr[RGB_RED];
g = inptr[RGB_GREEN];
b = inptr[RGB_BLUE];
inptr += RGB_PIXELSIZE;
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
* must be too; we do not need an explicit range-limiting operation.
@@ -100,9 +100,9 @@ rgb_gray_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf,
outptr = output_buf[0][output_row];
output_row++;
for (col = 0; col < num_cols; col++) {
r = GETJSAMPLE(inptr[RGB_RED]);
g = GETJSAMPLE(inptr[RGB_GREEN]);
b = GETJSAMPLE(inptr[RGB_BLUE]);
r = inptr[RGB_RED];
g = inptr[RGB_GREEN];
b = inptr[RGB_BLUE];
inptr += RGB_PIXELSIZE;
/* Y */
outptr[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] +
@@ -135,9 +135,9 @@ rgb_rgb_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf,
outptr2 = output_buf[2][output_row];
output_row++;
for (col = 0; col < num_cols; col++) {
outptr0[col] = GETJSAMPLE(inptr[RGB_RED]);
outptr1[col] = GETJSAMPLE(inptr[RGB_GREEN]);
outptr2[col] = GETJSAMPLE(inptr[RGB_BLUE]);
outptr0[col] = inptr[RGB_RED];
outptr1[col] = inptr[RGB_GREEN];
outptr2[col] = inptr[RGB_BLUE];
inptr += RGB_PIXELSIZE;
}
}
+6 -6
View File
@@ -392,11 +392,11 @@ cmyk_ycck_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
outptr3 = output_buf[3][output_row];
output_row++;
for (col = 0; col < num_cols; col++) {
r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
r = MAXJSAMPLE - inptr[0];
g = MAXJSAMPLE - inptr[1];
b = MAXJSAMPLE - inptr[2];
/* K passes through as-is */
outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */
outptr3[col] = inptr[3];
inptr += 4;
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
* must be too; we do not need an explicit range-limiting operation.
@@ -438,7 +438,7 @@ grayscale_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
outptr = output_buf[0][output_row];
output_row++;
for (col = 0; col < num_cols; col++) {
outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */
outptr[col] = inptr[0];
inptr += instride;
}
}
@@ -497,7 +497,7 @@ null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
inptr = *input_buf;
outptr = output_buf[ci][output_row];
for (col = 0; col < num_cols; col++) {
outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
outptr[col] = inptr[ci];
inptr += nc;
}
}
+18 -19
View File
@@ -381,19 +381,19 @@ convsamp(JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace)
elemptr = sample_data[elemr] + start_col;
#if DCTSIZE == 8 /* unroll the inner loop */
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
#else
{
register int elemc;
for (elemc = DCTSIZE; elemc > 0; elemc--)
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
}
#endif
}
@@ -533,20 +533,19 @@ convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col,
for (elemr = 0; elemr < DCTSIZE; elemr++) {
elemptr = sample_data[elemr] + start_col;
#if DCTSIZE == 8 /* unroll the inner loop */
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
#else
{
register int elemc;
for (elemc = DCTSIZE; elemc > 0; elemc--)
*workspaceptr++ = (FAST_FLOAT)
(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
}
#endif
}
+220 -180
View File
@@ -4,8 +4,10 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2009-2011, 2014-2016, 2018-2019, D. R. Commander.
* Copyright (C) 2009-2011, 2014-2016, 2018-2021, D. R. Commander.
* Copyright (C) 2015, Matthieu Darbois.
* Copyright (C) 2018, Matthias Räncker.
* Copyright (C) 2020, Arm Limited.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -42,15 +44,19 @@
* flags (this defines __thumb__).
*/
/* NOTE: Both GCC and Clang define __GNUC__ */
#if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))
#if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || \
defined(_M_ARM64)
#if !defined(__thumb__) || defined(__thumb2__)
#define USE_CLZ_INTRINSIC
#endif
#endif
#ifdef USE_CLZ_INTRINSIC
#if defined(_MSC_VER) && !defined(__clang__)
#define JPEG_NBITS_NONZERO(x) (32 - _CountLeadingZeros(x))
#else
#define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x))
#endif
#define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0)
#else
#include "jpeg_nbits_table.h"
@@ -65,32 +71,43 @@
* but must not be updated permanently until we complete the MCU.
*/
#if defined(__x86_64__) && defined(__ILP32__)
typedef unsigned long long bit_buf_type;
#else
typedef size_t bit_buf_type;
#endif
/* NOTE: The more optimal Huffman encoding algorithm is only used by the
* intrinsics implementation of the Arm Neon SIMD extensions, which is why we
* retain the old Huffman encoder behavior when using the GAS implementation.
*/
#if defined(WITH_SIMD) && !(defined(__arm__) || defined(__aarch64__) || \
defined(_M_ARM) || defined(_M_ARM64))
typedef unsigned long long simd_bit_buf_type;
#else
typedef bit_buf_type simd_bit_buf_type;
#endif
#if (defined(SIZEOF_SIZE_T) && SIZEOF_SIZE_T == 8) || defined(_WIN64) || \
(defined(__x86_64__) && defined(__ILP32__))
#define BIT_BUF_SIZE 64
#elif (defined(SIZEOF_SIZE_T) && SIZEOF_SIZE_T == 4) || defined(_WIN32)
#define BIT_BUF_SIZE 32
#else
#error Cannot determine word size
#endif
#define SIMD_BIT_BUF_SIZE (sizeof(simd_bit_buf_type) * 8)
typedef struct {
size_t put_buffer; /* current bit-accumulation buffer */
int put_bits; /* # of bits now in it */
union {
bit_buf_type c;
simd_bit_buf_type simd;
} put_buffer; /* current bit accumulation buffer */
int free_bits; /* # of bits available in it */
/* (Neon GAS: # of bits now in it) */
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
} savable_state;
/* This macro is to work around compilers with missing or broken
* structure assignment. You'll need to fix this code if you have
* such a compiler and you change MAX_COMPS_IN_SCAN.
*/
#ifndef NO_STRUCT_ASSIGN
#define ASSIGN_STATE(dest, src) ((dest) = (src))
#else
#if MAX_COMPS_IN_SCAN == 4
#define ASSIGN_STATE(dest, src) \
((dest).put_buffer = (src).put_buffer, \
(dest).put_bits = (src).put_bits, \
(dest).last_dc_val[0] = (src).last_dc_val[0], \
(dest).last_dc_val[1] = (src).last_dc_val[1], \
(dest).last_dc_val[2] = (src).last_dc_val[2], \
(dest).last_dc_val[3] = (src).last_dc_val[3])
#endif
#endif
typedef struct {
struct jpeg_entropy_encoder pub; /* public fields */
@@ -123,6 +140,7 @@ typedef struct {
size_t free_in_buffer; /* # of byte spaces remaining in buffer */
savable_state cur; /* Current bit buffer & DC state */
j_compress_ptr cinfo; /* dump_buffer needs access to this */
int simd;
} working_state;
@@ -201,8 +219,17 @@ start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics)
}
/* Initialize bit buffer to empty */
entropy->saved.put_buffer = 0;
entropy->saved.put_bits = 0;
if (entropy->simd) {
entropy->saved.put_buffer.simd = 0;
#if defined(__aarch64__) && !defined(NEON_INTRINSICS)
entropy->saved.free_bits = 0;
#else
entropy->saved.free_bits = SIMD_BIT_BUF_SIZE;
#endif
} else {
entropy->saved.put_buffer.c = 0;
entropy->saved.free_bits = BIT_BUF_SIZE;
}
/* Initialize restart stuff */
entropy->restarts_to_go = cinfo->restart_interval;
@@ -287,6 +314,7 @@ jpeg_make_c_derived_tbl(j_compress_ptr cinfo, boolean isDC, int tblno,
* this lets us detect duplicate VAL entries here, and later
* allows emit_bits to detect any attempt to emit such symbols.
*/
MEMZERO(dtbl->ehufco, sizeof(dtbl->ehufco));
MEMZERO(dtbl->ehufsi, sizeof(dtbl->ehufsi));
/* This is also a convenient place to check for out-of-range
@@ -334,94 +362,94 @@ dump_buffer(working_state *state)
/* Outputting bits to the file */
/* These macros perform the same task as the emit_bits() function in the
* original libjpeg code. In addition to reducing overhead by explicitly
* inlining the code, additional performance is achieved by taking into
* account the size of the bit buffer and waiting until it is almost full
* before emptying it. This mostly benefits 64-bit platforms, since 6
* bytes can be stored in a 64-bit bit buffer before it has to be emptied.
/* Output byte b and, speculatively, an additional 0 byte. 0xFF must be
* encoded as 0xFF 0x00, so the output buffer pointer is advanced by 2 if the
* byte is 0xFF. Otherwise, the output buffer pointer is advanced by 1, and
* the speculative 0 byte will be overwritten by the next byte.
*/
#define EMIT_BYTE() { \
JOCTET c; \
put_bits -= 8; \
c = (JOCTET)GETJOCTET(put_buffer >> put_bits); \
*buffer++ = c; \
if (c == 0xFF) /* need to stuff a zero byte? */ \
*buffer++ = 0; \
#define EMIT_BYTE(b) { \
buffer[0] = (JOCTET)(b); \
buffer[1] = 0; \
buffer -= -2 + ((JOCTET)(b) < 0xFF); \
}
#define PUT_BITS(code, size) { \
put_bits += size; \
put_buffer = (put_buffer << size) | code; \
}
/* Output the entire bit buffer. If there are no 0xFF bytes in it, then write
* directly to the output buffer. Otherwise, use the EMIT_BYTE() macro to
* encode 0xFF as 0xFF 0x00.
*/
#if BIT_BUF_SIZE == 64
#if SIZEOF_SIZE_T != 8 && !defined(_WIN64)
#define CHECKBUF15() { \
if (put_bits > 15) { \
EMIT_BYTE() \
EMIT_BYTE() \
#define FLUSH() { \
if (put_buffer & 0x8080808080808080 & ~(put_buffer + 0x0101010101010101)) { \
EMIT_BYTE(put_buffer >> 56) \
EMIT_BYTE(put_buffer >> 48) \
EMIT_BYTE(put_buffer >> 40) \
EMIT_BYTE(put_buffer >> 32) \
EMIT_BYTE(put_buffer >> 24) \
EMIT_BYTE(put_buffer >> 16) \
EMIT_BYTE(put_buffer >> 8) \
EMIT_BYTE(put_buffer ) \
} else { \
buffer[0] = (JOCTET)(put_buffer >> 56); \
buffer[1] = (JOCTET)(put_buffer >> 48); \
buffer[2] = (JOCTET)(put_buffer >> 40); \
buffer[3] = (JOCTET)(put_buffer >> 32); \
buffer[4] = (JOCTET)(put_buffer >> 24); \
buffer[5] = (JOCTET)(put_buffer >> 16); \
buffer[6] = (JOCTET)(put_buffer >> 8); \
buffer[7] = (JOCTET)(put_buffer); \
buffer += 8; \
} \
}
#endif
#define CHECKBUF31() { \
if (put_bits > 31) { \
EMIT_BYTE() \
EMIT_BYTE() \
EMIT_BYTE() \
EMIT_BYTE() \
} \
}
#define CHECKBUF47() { \
if (put_bits > 47) { \
EMIT_BYTE() \
EMIT_BYTE() \
EMIT_BYTE() \
EMIT_BYTE() \
EMIT_BYTE() \
EMIT_BYTE() \
} \
}
#if !defined(_WIN32) && !defined(SIZEOF_SIZE_T)
#error Cannot determine word size
#endif
#if SIZEOF_SIZE_T == 8 || defined(_WIN64)
#define EMIT_BITS(code, size) { \
CHECKBUF47() \
PUT_BITS(code, size) \
}
#define EMIT_CODE(code, size) { \
temp2 &= (((JLONG)1) << nbits) - 1; \
CHECKBUF31() \
PUT_BITS(code, size) \
PUT_BITS(temp2, nbits) \
}
#else
#define EMIT_BITS(code, size) { \
PUT_BITS(code, size) \
CHECKBUF15() \
}
#define EMIT_CODE(code, size) { \
temp2 &= (((JLONG)1) << nbits) - 1; \
PUT_BITS(code, size) \
CHECKBUF15() \
PUT_BITS(temp2, nbits) \
CHECKBUF15() \
#define FLUSH() { \
if (put_buffer & 0x80808080 & ~(put_buffer + 0x01010101)) { \
EMIT_BYTE(put_buffer >> 24) \
EMIT_BYTE(put_buffer >> 16) \
EMIT_BYTE(put_buffer >> 8) \
EMIT_BYTE(put_buffer ) \
} else { \
buffer[0] = (JOCTET)(put_buffer >> 24); \
buffer[1] = (JOCTET)(put_buffer >> 16); \
buffer[2] = (JOCTET)(put_buffer >> 8); \
buffer[3] = (JOCTET)(put_buffer); \
buffer += 4; \
} \
}
#endif
/* Fill the bit buffer to capacity with the leading bits from code, then output
* the bit buffer and put the remaining bits from code into the bit buffer.
*/
#define PUT_AND_FLUSH(code, size) { \
put_buffer = (put_buffer << (size + free_bits)) | (code >> -free_bits); \
FLUSH() \
free_bits += BIT_BUF_SIZE; \
put_buffer = code; \
}
/* Insert code into the bit buffer and output the bit buffer if needed.
* NOTE: We can't flush with free_bits == 0, since the left shift in
* PUT_AND_FLUSH() would have undefined behavior.
*/
#define PUT_BITS(code, size) { \
free_bits -= size; \
if (free_bits < 0) \
PUT_AND_FLUSH(code, size) \
else \
put_buffer = (put_buffer << size) | code; \
}
#define PUT_CODE(code, size) { \
temp &= (((JLONG)1) << nbits) - 1; \
temp |= code << nbits; \
nbits += size; \
PUT_BITS(temp, nbits) \
}
/* Although it is exceedingly rare, it is possible for a Huffman-encoded
* coefficient block to be larger than the 128-byte unencoded block. For each
@@ -444,6 +472,7 @@ dump_buffer(working_state *state)
#define STORE_BUFFER() { \
if (localbuf) { \
size_t bytes, bytestocopy; \
bytes = buffer - _buffer; \
buffer = _buffer; \
while (bytes > 0) { \
@@ -466,20 +495,46 @@ dump_buffer(working_state *state)
LOCAL(boolean)
flush_bits(working_state *state)
{
JOCTET _buffer[BUFSIZE], *buffer;
size_t put_buffer; int put_bits;
size_t bytes, bytestocopy; int localbuf = 0;
JOCTET _buffer[BUFSIZE], *buffer, temp;
simd_bit_buf_type put_buffer; int put_bits;
int localbuf = 0;
if (state->simd) {
#if defined(__aarch64__) && !defined(NEON_INTRINSICS)
put_bits = state->cur.free_bits;
#else
put_bits = SIMD_BIT_BUF_SIZE - state->cur.free_bits;
#endif
put_buffer = state->cur.put_buffer.simd;
} else {
put_bits = BIT_BUF_SIZE - state->cur.free_bits;
put_buffer = state->cur.put_buffer.c;
}
put_buffer = state->cur.put_buffer;
put_bits = state->cur.put_bits;
LOAD_BUFFER()
/* fill any partial byte with ones */
PUT_BITS(0x7F, 7)
while (put_bits >= 8) EMIT_BYTE()
while (put_bits >= 8) {
put_bits -= 8;
temp = (JOCTET)(put_buffer >> put_bits);
EMIT_BYTE(temp)
}
if (put_bits) {
/* fill partial byte with ones */
temp = (JOCTET)((put_buffer << (8 - put_bits)) | (0xFF >> put_bits));
EMIT_BYTE(temp)
}
state->cur.put_buffer = 0; /* and reset bit-buffer to empty */
state->cur.put_bits = 0;
if (state->simd) { /* and reset bit buffer to empty */
state->cur.put_buffer.simd = 0;
#if defined(__aarch64__) && !defined(NEON_INTRINSICS)
state->cur.free_bits = 0;
#else
state->cur.free_bits = SIMD_BIT_BUF_SIZE;
#endif
} else {
state->cur.put_buffer.c = 0;
state->cur.free_bits = BIT_BUF_SIZE;
}
STORE_BUFFER()
return TRUE;
@@ -493,7 +548,7 @@ encode_one_block_simd(working_state *state, JCOEFPTR block, int last_dc_val,
c_derived_tbl *dctbl, c_derived_tbl *actbl)
{
JOCTET _buffer[BUFSIZE], *buffer;
size_t bytes, bytestocopy; int localbuf = 0;
int localbuf = 0;
LOAD_BUFFER()
@@ -509,53 +564,41 @@ LOCAL(boolean)
encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val,
c_derived_tbl *dctbl, c_derived_tbl *actbl)
{
int temp, temp2, temp3;
int nbits;
int r, code, size;
int temp, nbits, free_bits;
bit_buf_type put_buffer;
JOCTET _buffer[BUFSIZE], *buffer;
size_t put_buffer; int put_bits;
int code_0xf0 = actbl->ehufco[0xf0], size_0xf0 = actbl->ehufsi[0xf0];
size_t bytes, bytestocopy; int localbuf = 0;
int localbuf = 0;
put_buffer = state->cur.put_buffer;
put_bits = state->cur.put_bits;
free_bits = state->cur.free_bits;
put_buffer = state->cur.put_buffer.c;
LOAD_BUFFER()
/* Encode the DC coefficient difference per section F.1.2.1 */
temp = temp2 = block[0] - last_dc_val;
temp = block[0] - last_dc_val;
/* This is a well-known technique for obtaining the absolute value without a
* branch. It is derived from an assembly language technique presented in
* "How to Optimize for the Pentium Processors", Copyright (c) 1996, 1997 by
* Agner Fog.
* Agner Fog. This code assumes we are on a two's complement machine.
*/
temp3 = temp >> (CHAR_BIT * sizeof(int) - 1);
temp ^= temp3;
temp -= temp3;
/* For a negative input, want temp2 = bitwise complement of abs(input) */
/* This code assumes we are on a two's complement machine */
temp2 += temp3;
nbits = temp >> (CHAR_BIT * sizeof(int) - 1);
temp += nbits;
nbits ^= temp;
/* Find the number of bits needed for the magnitude of the coefficient */
nbits = JPEG_NBITS(temp);
nbits = JPEG_NBITS(nbits);
/* Emit the Huffman-coded symbol for the number of bits */
code = dctbl->ehufco[nbits];
size = dctbl->ehufsi[nbits];
EMIT_BITS(code, size)
/* Mask off any extra bits in code */
temp2 &= (((JLONG)1) << nbits) - 1;
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
EMIT_BITS(temp2, nbits)
/* Emit the Huffman-coded symbol for the number of bits.
* Emit that number of bits of the value, if positive,
* or the complement of its magnitude, if negative.
*/
PUT_CODE(dctbl->ehufco[nbits], dctbl->ehufsi[nbits])
/* Encode the AC coefficients per section F.1.2.2 */
r = 0; /* r = run length of zeros */
{
int r = 0; /* r = run length of zeros */
/* Manually unroll the k loop to eliminate the counter variable. This
* improves performance greatly on systems with a limited number of
@@ -563,51 +606,46 @@ encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val,
*/
#define kloop(jpeg_natural_order_of_k) { \
if ((temp = block[jpeg_natural_order_of_k]) == 0) { \
r++; \
r += 16; \
} else { \
temp2 = temp; \
/* Branch-less absolute value, bitwise complement, etc., same as above */ \
temp3 = temp >> (CHAR_BIT * sizeof(int) - 1); \
temp ^= temp3; \
temp -= temp3; \
temp2 += temp3; \
nbits = JPEG_NBITS_NONZERO(temp); \
nbits = temp >> (CHAR_BIT * sizeof(int) - 1); \
temp += nbits; \
nbits ^= temp; \
nbits = JPEG_NBITS_NONZERO(nbits); \
/* if run length > 15, must emit special run-length-16 codes (0xF0) */ \
while (r > 15) { \
EMIT_BITS(code_0xf0, size_0xf0) \
r -= 16; \
while (r >= 16 * 16) { \
r -= 16 * 16; \
PUT_BITS(actbl->ehufco[0xf0], actbl->ehufsi[0xf0]) \
} \
/* Emit Huffman symbol for run length / number of bits */ \
temp3 = (r << 4) + nbits; \
code = actbl->ehufco[temp3]; \
size = actbl->ehufsi[temp3]; \
EMIT_CODE(code, size) \
r += nbits; \
PUT_CODE(actbl->ehufco[r], actbl->ehufsi[r]) \
r = 0; \
} \
}
/* One iteration for each value in jpeg_natural_order[] */
kloop(1); kloop(8); kloop(16); kloop(9); kloop(2); kloop(3);
kloop(10); kloop(17); kloop(24); kloop(32); kloop(25); kloop(18);
kloop(11); kloop(4); kloop(5); kloop(12); kloop(19); kloop(26);
kloop(33); kloop(40); kloop(48); kloop(41); kloop(34); kloop(27);
kloop(20); kloop(13); kloop(6); kloop(7); kloop(14); kloop(21);
kloop(28); kloop(35); kloop(42); kloop(49); kloop(56); kloop(57);
kloop(50); kloop(43); kloop(36); kloop(29); kloop(22); kloop(15);
kloop(23); kloop(30); kloop(37); kloop(44); kloop(51); kloop(58);
kloop(59); kloop(52); kloop(45); kloop(38); kloop(31); kloop(39);
kloop(46); kloop(53); kloop(60); kloop(61); kloop(54); kloop(47);
kloop(55); kloop(62); kloop(63);
/* One iteration for each value in jpeg_natural_order[] */
kloop(1); kloop(8); kloop(16); kloop(9); kloop(2); kloop(3);
kloop(10); kloop(17); kloop(24); kloop(32); kloop(25); kloop(18);
kloop(11); kloop(4); kloop(5); kloop(12); kloop(19); kloop(26);
kloop(33); kloop(40); kloop(48); kloop(41); kloop(34); kloop(27);
kloop(20); kloop(13); kloop(6); kloop(7); kloop(14); kloop(21);
kloop(28); kloop(35); kloop(42); kloop(49); kloop(56); kloop(57);
kloop(50); kloop(43); kloop(36); kloop(29); kloop(22); kloop(15);
kloop(23); kloop(30); kloop(37); kloop(44); kloop(51); kloop(58);
kloop(59); kloop(52); kloop(45); kloop(38); kloop(31); kloop(39);
kloop(46); kloop(53); kloop(60); kloop(61); kloop(54); kloop(47);
kloop(55); kloop(62); kloop(63);
/* If the last coef(s) were zero, emit an end-of-block code */
if (r > 0) {
code = actbl->ehufco[0];
size = actbl->ehufsi[0];
EMIT_BITS(code, size)
/* If the last coef(s) were zero, emit an end-of-block code */
if (r > 0) {
PUT_BITS(actbl->ehufco[0], actbl->ehufsi[0])
}
}
state->cur.put_buffer = put_buffer;
state->cur.put_bits = put_bits;
state->cur.put_buffer.c = put_buffer;
state->cur.free_bits = free_bits;
STORE_BUFFER()
return TRUE;
@@ -654,8 +692,9 @@ encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* Load up working state */
state.next_output_byte = cinfo->dest->next_output_byte;
state.free_in_buffer = cinfo->dest->free_in_buffer;
ASSIGN_STATE(state.cur, entropy->saved);
state.cur = entropy->saved;
state.cinfo = cinfo;
state.simd = entropy->simd;
/* Emit restart marker if needed */
if (cinfo->restart_interval) {
@@ -694,7 +733,7 @@ encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* Completed MCU, so update state */
cinfo->dest->next_output_byte = state.next_output_byte;
cinfo->dest->free_in_buffer = state.free_in_buffer;
ASSIGN_STATE(entropy->saved, state.cur);
entropy->saved = state.cur;
/* Update restart-interval state too */
if (cinfo->restart_interval) {
@@ -723,8 +762,9 @@ finish_pass_huff(j_compress_ptr cinfo)
/* Load up working state ... flush_bits needs it */
state.next_output_byte = cinfo->dest->next_output_byte;
state.free_in_buffer = cinfo->dest->free_in_buffer;
ASSIGN_STATE(state.cur, entropy->saved);
state.cur = entropy->saved;
state.cinfo = cinfo;
state.simd = entropy->simd;
/* Flush out the last data */
if (!flush_bits(&state))
@@ -733,7 +773,7 @@ finish_pass_huff(j_compress_ptr cinfo)
/* Update state */
cinfo->dest->next_output_byte = state.next_output_byte;
cinfo->dest->free_in_buffer = state.free_in_buffer;
ASSIGN_STATE(entropy->saved, state.cur);
entropy->saved = state.cur;
}
+16 -9
View File
@@ -4,8 +4,9 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1995-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2011, 2015, 2018, D. R. Commander.
* Copyright (C) 2011, 2015, 2018, 2021, D. R. Commander.
* Copyright (C) 2016, 2018, Matthieu Darbois.
* Copyright (C) 2020, Arm Limited.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -51,15 +52,19 @@
* flags (this defines __thumb__).
*/
/* NOTE: Both GCC and Clang define __GNUC__ */
#if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))
#if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || \
defined(_M_ARM64)
#if !defined(__thumb__) || defined(__thumb2__)
#define USE_CLZ_INTRINSIC
#endif
#endif
#ifdef USE_CLZ_INTRINSIC
#if defined(_MSC_VER) && !defined(__clang__)
#define JPEG_NBITS_NONZERO(x) (32 - _CountLeadingZeros(x))
#else
#define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x))
#endif
#define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0)
#else
#include "jpeg_nbits_table.h"
@@ -169,24 +174,26 @@ INLINE
METHODDEF(int)
count_zeroes(size_t *x)
{
int result;
#if defined(HAVE_BUILTIN_CTZL)
int result;
result = __builtin_ctzl(*x);
*x >>= result;
#elif defined(HAVE_BITSCANFORWARD64)
unsigned long result;
_BitScanForward64(&result, *x);
*x >>= result;
#elif defined(HAVE_BITSCANFORWARD)
unsigned long result;
_BitScanForward(&result, *x);
*x >>= result;
#else
result = 0;
int result = 0;
while ((*x & 1) == 0) {
++result;
*x >>= 1;
}
#endif
return result;
return (int)result;
}
@@ -860,7 +867,7 @@ encode_mcu_AC_refine_prepare(const JCOEF *block,
#define ENCODE_COEFS_AC_REFINE(label) { \
while (zerobits) { \
int idx = count_zeroes(&zerobits); \
idx = count_zeroes(&zerobits); \
r += idx; \
cabsvalue += idx; \
signbits >>= idx; \
@@ -917,7 +924,7 @@ METHODDEF(boolean)
encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
register int temp, r;
register int temp, r, idx;
char *BR_buffer;
unsigned int BR;
int Sl = cinfo->Se - cinfo->Ss + 1;
@@ -968,7 +975,7 @@ encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
if (zerobits) {
int diff = ((absvalues + DCTSIZE2 / 2) - cabsvalue);
int idx = count_zeroes(&zerobits);
idx = count_zeroes(&zerobits);
signbits >>= idx;
idx += diff;
r += idx;
+23 -40
View File
@@ -6,7 +6,7 @@
* libjpeg-turbo Modifications:
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2014, MIPS Technologies, Inc., California.
* Copyright (C) 2015, D. R. Commander.
* Copyright (C) 2015, 2019, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -103,7 +103,7 @@ expand_right_edge(JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols,
if (numcols > 0) {
for (row = 0; row < num_rows; row++) {
ptr = image_data[row] + input_cols;
pixval = ptr[-1]; /* don't need GETJSAMPLE() here */
pixval = ptr[-1];
for (count = numcols; count > 0; count--)
*ptr++ = pixval;
}
@@ -174,7 +174,7 @@ int_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
for (v = 0; v < v_expand; v++) {
inptr = input_data[inrow + v] + outcol_h;
for (h = 0; h < h_expand; h++) {
outvalue += (JLONG)GETJSAMPLE(*inptr++);
outvalue += (JLONG)(*inptr++);
}
}
*outptr++ = (JSAMPLE)((outvalue + numpix2) / numpix);
@@ -237,8 +237,7 @@ h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
inptr = input_data[outrow];
bias = 0; /* bias = 0,1,0,1,... for successive samples */
for (outcol = 0; outcol < output_cols; outcol++) {
*outptr++ =
(JSAMPLE)((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + bias) >> 1);
*outptr++ = (JSAMPLE)((inptr[0] + inptr[1] + bias) >> 1);
bias ^= 1; /* 0=>1, 1=>0 */
inptr += 2;
}
@@ -277,8 +276,7 @@ h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
bias = 1; /* bias = 1,2,1,2,... for successive samples */
for (outcol = 0; outcol < output_cols; outcol++) {
*outptr++ =
(JSAMPLE)((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + bias) >> 2);
(JSAMPLE)((inptr0[0] + inptr0[1] + inptr1[0] + inptr1[1] + bias) >> 2);
bias ^= 3; /* 1=>2, 2=>1 */
inptr0 += 2; inptr1 += 2;
}
@@ -337,33 +335,25 @@ h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
below_ptr = input_data[inrow + 2];
/* Special case for first column: pretend column -1 is same as column 0 */
membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);
membersum = inptr0[0] + inptr0[1] + inptr1[0] + inptr1[1];
neighsum = above_ptr[0] + above_ptr[1] + below_ptr[0] + below_ptr[1] +
inptr0[0] + inptr0[2] + inptr1[0] + inptr1[2];
neighsum += neighsum;
neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
neighsum += above_ptr[0] + above_ptr[2] + below_ptr[0] + below_ptr[2];
membersum = membersum * memberscale + neighsum * neighscale;
*outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
for (colctr = output_cols - 2; colctr > 0; colctr--) {
/* sum of pixels directly mapped to this output element */
membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
membersum = inptr0[0] + inptr0[1] + inptr1[0] + inptr1[1];
/* sum of edge-neighbor pixels */
neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +
GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);
neighsum = above_ptr[0] + above_ptr[1] + below_ptr[0] + below_ptr[1] +
inptr0[-1] + inptr0[2] + inptr1[-1] + inptr1[2];
/* The edge-neighbors count twice as much as corner-neighbors */
neighsum += neighsum;
/* Add in the corner-neighbors */
neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +
GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);
neighsum += above_ptr[-1] + above_ptr[2] + below_ptr[-1] + below_ptr[2];
/* form final output scaled up by 2^16 */
membersum = membersum * memberscale + neighsum * neighscale;
/* round, descale and output it */
@@ -372,15 +362,11 @@ h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
}
/* Special case for last column */
membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +
GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);
membersum = inptr0[0] + inptr0[1] + inptr1[0] + inptr1[1];
neighsum = above_ptr[0] + above_ptr[1] + below_ptr[0] + below_ptr[1] +
inptr0[-1] + inptr0[1] + inptr1[-1] + inptr1[1];
neighsum += neighsum;
neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
neighsum += above_ptr[-1] + above_ptr[1] + below_ptr[-1] + below_ptr[1];
membersum = membersum * memberscale + neighsum * neighscale;
*outptr = (JSAMPLE)((membersum + 32768) >> 16);
@@ -429,21 +415,18 @@ fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
below_ptr = input_data[outrow + 1];
/* Special case for first column */
colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
GETJSAMPLE(*inptr);
membersum = GETJSAMPLE(*inptr++);
nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
GETJSAMPLE(*inptr);
colsum = (*above_ptr++) + (*below_ptr++) + inptr[0];
membersum = *inptr++;
nextcolsum = above_ptr[0] + below_ptr[0] + inptr[0];
neighsum = colsum + (colsum - membersum) + nextcolsum;
membersum = membersum * memberscale + neighsum * neighscale;
*outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
lastcolsum = colsum; colsum = nextcolsum;
for (colctr = output_cols - 2; colctr > 0; colctr--) {
membersum = GETJSAMPLE(*inptr++);
membersum = *inptr++;
above_ptr++; below_ptr++;
nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
GETJSAMPLE(*inptr);
nextcolsum = above_ptr[0] + below_ptr[0] + inptr[0];
neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
membersum = membersum * memberscale + neighsum * neighscale;
*outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
@@ -451,7 +434,7 @@ fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
}
/* Special case for last column */
membersum = GETJSAMPLE(*inptr);
membersum = *inptr;
neighsum = lastcolsum + (colsum - membersum) + colsum;
membersum = membersum * memberscale + neighsum * neighscale;
*outptr = (JSAMPLE)((membersum + 32768) >> 16);
+9 -1
View File
@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1994-1996, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2010, 2015-2018, 2020, D. R. Commander.
* Copyright (C) 2010, 2015-2020, D. R. Commander.
* Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
@@ -319,6 +319,8 @@ read_and_discard_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines)
{
JDIMENSION n;
my_master_ptr master = (my_master_ptr)cinfo->master;
JSAMPLE dummy_sample[1] = { 0 };
JSAMPROW dummy_row = dummy_sample;
JSAMPARRAY scanlines = NULL;
void (*color_convert) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
JDIMENSION input_row, JSAMPARRAY output_buf,
@@ -329,6 +331,10 @@ read_and_discard_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines)
if (cinfo->cconvert && cinfo->cconvert->color_convert) {
color_convert = cinfo->cconvert->color_convert;
cinfo->cconvert->color_convert = noop_convert;
/* This just prevents UBSan from complaining about adding 0 to a NULL
* pointer. The pointer isn't actually used.
*/
scanlines = &dummy_row;
}
if (cinfo->cquantize && cinfo->cquantize->color_quantize) {
@@ -532,6 +538,8 @@ jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines)
* decoded coefficients. This is ~5% faster for large subsets, but
* it's tough to tell a difference for smaller images.
*/
if (!cinfo->entropy->insufficient_data)
cinfo->master->last_good_iMCU_row = cinfo->input_iMCU_row;
(*cinfo->entropy->decode_mcu) (cinfo, NULL);
}
}
+12 -3
View File
@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Developed 1997-2015 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2015-2018, D. R. Commander.
* Copyright (C) 2015-2020, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -80,7 +80,7 @@ get_byte(j_decompress_ptr cinfo)
if (!(*src->fill_input_buffer) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
src->bytes_in_buffer--;
return GETJOCTET(*src->next_input_byte++);
return *src->next_input_byte++;
}
@@ -665,8 +665,16 @@ bad:
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
int coefi, cindex = cinfo->cur_comp_info[ci]->component_index;
int *coef_bit_ptr = &cinfo->coef_bits[cindex][0];
int *prev_coef_bit_ptr =
&cinfo->coef_bits[cindex + cinfo->num_components][0];
if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
for (coefi = MIN(cinfo->Ss, 1); coefi <= MAX(cinfo->Se, 9); coefi++) {
if (cinfo->input_scan_number > 1)
prev_coef_bit_ptr[coefi] = coef_bit_ptr[coefi];
else
prev_coef_bit_ptr[coefi] = 0;
}
for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi];
if (cinfo->Ah != expected)
@@ -727,6 +735,7 @@ bad:
entropy->c = 0;
entropy->a = 0;
entropy->ct = -16; /* force reading 2 initial bytes to fill C */
entropy->pub.insufficient_data = FALSE;
/* Initialize restart counter */
entropy->restarts_to_go = cinfo->restart_interval;
@@ -763,7 +772,7 @@ jinit_arith_decoder(j_decompress_ptr cinfo)
int *coef_bit_ptr, ci;
cinfo->coef_bits = (int (*)[DCTSIZE2])
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
cinfo->num_components * DCTSIZE2 *
cinfo->num_components * 2 * DCTSIZE2 *
sizeof(int));
coef_bit_ptr = &cinfo->coef_bits[0][0];
for (ci = 0; ci < cinfo->num_components; ci++)
+237 -53
View File
@@ -5,7 +5,7 @@
* Copyright (C) 1994-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2010, 2015-2016, D. R. Commander.
* Copyright (C) 2010, 2015-2016, 2019-2020, D. R. Commander.
* Copyright (C) 2015, 2020, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
@@ -102,6 +102,8 @@ decompress_onepass(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
/* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */
jzero_far((void *)coef->MCU_buffer[0],
(size_t)(cinfo->blocks_in_MCU * sizeof(JBLOCK)));
if (!cinfo->entropy->insufficient_data)
cinfo->master->last_good_iMCU_row = cinfo->input_iMCU_row;
if (!(*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
@@ -227,6 +229,8 @@ consume_data(j_decompress_ptr cinfo)
}
}
}
if (!cinfo->entropy->insufficient_data)
cinfo->master->last_good_iMCU_row = cinfo->input_iMCU_row;
/* Try to fetch the MCU. */
if (!(*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
@@ -326,19 +330,22 @@ decompress_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
#ifdef BLOCK_SMOOTHING_SUPPORTED
/*
* This code applies interblock smoothing as described by section K.8
* of the JPEG standard: the first 5 AC coefficients are estimated from
* the DC values of a DCT block and its 8 neighboring blocks.
* This code applies interblock smoothing; the first 9 AC coefficients are
* estimated from the DC values of a DCT block and its 24 neighboring blocks.
* We apply smoothing only for progressive JPEG decoding, and only if
* the coefficients it can estimate are not yet known to full precision.
*/
/* Natural-order array positions of the first 5 zigzag-order coefficients */
/* Natural-order array positions of the first 9 zigzag-order coefficients */
#define Q01_POS 1
#define Q10_POS 8
#define Q20_POS 16
#define Q11_POS 9
#define Q02_POS 2
#define Q03_POS 3
#define Q12_POS 10
#define Q21_POS 17
#define Q30_POS 24
/*
* Determine whether block smoothing is applicable and safe.
@@ -356,8 +363,8 @@ smoothing_ok(j_decompress_ptr cinfo)
int ci, coefi;
jpeg_component_info *compptr;
JQUANT_TBL *qtable;
int *coef_bits;
int *coef_bits_latch;
int *coef_bits, *prev_coef_bits;
int *coef_bits_latch, *prev_coef_bits_latch;
if (!cinfo->progressive_mode || cinfo->coef_bits == NULL)
return FALSE;
@@ -366,34 +373,47 @@ smoothing_ok(j_decompress_ptr cinfo)
if (coef->coef_bits_latch == NULL)
coef->coef_bits_latch = (int *)
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
cinfo->num_components *
cinfo->num_components * 2 *
(SAVED_COEFS * sizeof(int)));
coef_bits_latch = coef->coef_bits_latch;
prev_coef_bits_latch =
&coef->coef_bits_latch[cinfo->num_components * SAVED_COEFS];
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* All components' quantization values must already be latched. */
if ((qtable = compptr->quant_table) == NULL)
return FALSE;
/* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */
/* Verify DC & first 9 AC quantizers are nonzero to avoid zero-divide. */
if (qtable->quantval[0] == 0 ||
qtable->quantval[Q01_POS] == 0 ||
qtable->quantval[Q10_POS] == 0 ||
qtable->quantval[Q20_POS] == 0 ||
qtable->quantval[Q11_POS] == 0 ||
qtable->quantval[Q02_POS] == 0)
qtable->quantval[Q02_POS] == 0 ||
qtable->quantval[Q03_POS] == 0 ||
qtable->quantval[Q12_POS] == 0 ||
qtable->quantval[Q21_POS] == 0 ||
qtable->quantval[Q30_POS] == 0)
return FALSE;
/* DC values must be at least partly known for all components. */
coef_bits = cinfo->coef_bits[ci];
prev_coef_bits = cinfo->coef_bits[ci + cinfo->num_components];
if (coef_bits[0] < 0)
return FALSE;
coef_bits_latch[0] = coef_bits[0];
/* Block smoothing is helpful if some AC coefficients remain inaccurate. */
for (coefi = 1; coefi <= 5; coefi++) {
for (coefi = 1; coefi < SAVED_COEFS; coefi++) {
if (cinfo->input_scan_number > 1)
prev_coef_bits_latch[coefi] = prev_coef_bits[coefi];
else
prev_coef_bits_latch[coefi] = -1;
coef_bits_latch[coefi] = coef_bits[coefi];
if (coef_bits[coefi] != 0)
smoothing_useful = TRUE;
}
coef_bits_latch += SAVED_COEFS;
prev_coef_bits_latch += SAVED_COEFS;
}
return smoothing_useful;
@@ -412,17 +432,20 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
JDIMENSION block_num, last_block_column;
int ci, block_row, block_rows, access_rows;
JBLOCKARRAY buffer;
JBLOCKROW buffer_ptr, prev_block_row, next_block_row;
JBLOCKROW buffer_ptr, prev_prev_block_row, prev_block_row;
JBLOCKROW next_block_row, next_next_block_row;
JSAMPARRAY output_ptr;
JDIMENSION output_col;
jpeg_component_info *compptr;
inverse_DCT_method_ptr inverse_DCT;
boolean first_row, last_row;
boolean change_dc;
JCOEF *workspace;
int *coef_bits;
JQUANT_TBL *quanttbl;
JLONG Q00, Q01, Q02, Q10, Q11, Q20, num;
int DC1, DC2, DC3, DC4, DC5, DC6, DC7, DC8, DC9;
JLONG Q00, Q01, Q02, Q03 = 0, Q10, Q11, Q12 = 0, Q20, Q21 = 0, Q30 = 0, num;
int DC01, DC02, DC03, DC04, DC05, DC06, DC07, DC08, DC09, DC10, DC11, DC12,
DC13, DC14, DC15, DC16, DC17, DC18, DC19, DC20, DC21, DC22, DC23, DC24,
DC25;
int Al, pred;
/* Keep a local variable to avoid looking it up more than once */
@@ -434,10 +457,10 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
if (cinfo->input_scan_number == cinfo->output_scan_number) {
/* If input is working on current scan, we ordinarily want it to
* have completed the current row. But if input scan is DC,
* we want it to keep one row ahead so that next block row's DC
* we want it to keep two rows ahead so that next two block rows' DC
* values are up to date.
*/
JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0;
JDIMENSION delta = (cinfo->Ss == 0) ? 2 : 0;
if (cinfo->input_iMCU_row > cinfo->output_iMCU_row + delta)
break;
}
@@ -452,34 +475,53 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
if (!compptr->component_needed)
continue;
/* Count non-dummy DCT block rows in this iMCU row. */
if (cinfo->output_iMCU_row < last_iMCU_row) {
if (cinfo->output_iMCU_row < last_iMCU_row - 1) {
block_rows = compptr->v_samp_factor;
access_rows = block_rows * 3; /* this and next two iMCU rows */
} else if (cinfo->output_iMCU_row < last_iMCU_row) {
block_rows = compptr->v_samp_factor;
access_rows = block_rows * 2; /* this and next iMCU row */
last_row = FALSE;
} else {
/* NB: can't use last_row_height here; it is input-side-dependent! */
block_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
if (block_rows == 0) block_rows = compptr->v_samp_factor;
access_rows = block_rows; /* this iMCU row only */
last_row = TRUE;
}
/* Align the virtual buffer for this component. */
if (cinfo->output_iMCU_row > 0) {
access_rows += compptr->v_samp_factor; /* prior iMCU row too */
if (cinfo->output_iMCU_row > 1) {
access_rows += 2 * compptr->v_samp_factor; /* prior two iMCU rows too */
buffer = (*cinfo->mem->access_virt_barray)
((j_common_ptr)cinfo, coef->whole_image[ci],
(cinfo->output_iMCU_row - 2) * compptr->v_samp_factor,
(JDIMENSION)access_rows, FALSE);
buffer += 2 * compptr->v_samp_factor; /* point to current iMCU row */
} else if (cinfo->output_iMCU_row > 0) {
buffer = (*cinfo->mem->access_virt_barray)
((j_common_ptr)cinfo, coef->whole_image[ci],
(cinfo->output_iMCU_row - 1) * compptr->v_samp_factor,
(JDIMENSION)access_rows, FALSE);
buffer += compptr->v_samp_factor; /* point to current iMCU row */
first_row = FALSE;
} else {
buffer = (*cinfo->mem->access_virt_barray)
((j_common_ptr)cinfo, coef->whole_image[ci],
(JDIMENSION)0, (JDIMENSION)access_rows, FALSE);
first_row = TRUE;
}
/* Fetch component-dependent info */
coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS);
/* Fetch component-dependent info.
* If the current scan is incomplete, then we use the component-dependent
* info from the previous scan.
*/
if (cinfo->output_iMCU_row > cinfo->master->last_good_iMCU_row)
coef_bits =
coef->coef_bits_latch + ((ci + cinfo->num_components) * SAVED_COEFS);
else
coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS);
/* We only do DC interpolation if no AC coefficient data is available. */
change_dc =
coef_bits[1] == -1 && coef_bits[2] == -1 && coef_bits[3] == -1 &&
coef_bits[4] == -1 && coef_bits[5] == -1 && coef_bits[6] == -1 &&
coef_bits[7] == -1 && coef_bits[8] == -1 && coef_bits[9] == -1;
quanttbl = compptr->quant_table;
Q00 = quanttbl->quantval[0];
Q01 = quanttbl->quantval[Q01_POS];
@@ -487,27 +529,51 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
Q20 = quanttbl->quantval[Q20_POS];
Q11 = quanttbl->quantval[Q11_POS];
Q02 = quanttbl->quantval[Q02_POS];
if (change_dc) {
Q03 = quanttbl->quantval[Q03_POS];
Q12 = quanttbl->quantval[Q12_POS];
Q21 = quanttbl->quantval[Q21_POS];
Q30 = quanttbl->quantval[Q30_POS];
}
inverse_DCT = cinfo->idct->inverse_DCT[ci];
output_ptr = output_buf[ci];
/* Loop over all DCT blocks to be processed. */
for (block_row = 0; block_row < block_rows; block_row++) {
buffer_ptr = buffer[block_row] + cinfo->master->first_MCU_col[ci];
if (first_row && block_row == 0)
if (block_row > 0 || cinfo->output_iMCU_row > 0)
prev_block_row =
buffer[block_row - 1] + cinfo->master->first_MCU_col[ci];
else
prev_block_row = buffer_ptr;
if (block_row > 1 || cinfo->output_iMCU_row > 1)
prev_prev_block_row =
buffer[block_row - 2] + cinfo->master->first_MCU_col[ci];
else
prev_prev_block_row = prev_block_row;
if (block_row < block_rows - 1 || cinfo->output_iMCU_row < last_iMCU_row)
next_block_row =
buffer[block_row + 1] + cinfo->master->first_MCU_col[ci];
else
prev_block_row = buffer[block_row - 1] +
cinfo->master->first_MCU_col[ci];
if (last_row && block_row == block_rows - 1)
next_block_row = buffer_ptr;
if (block_row < block_rows - 2 ||
cinfo->output_iMCU_row < last_iMCU_row - 1)
next_next_block_row =
buffer[block_row + 2] + cinfo->master->first_MCU_col[ci];
else
next_block_row = buffer[block_row + 1] +
cinfo->master->first_MCU_col[ci];
next_next_block_row = next_block_row;
/* We fetch the surrounding DC values using a sliding-register approach.
* Initialize all nine here so as to do the right thing on narrow pics.
* Initialize all 25 here so as to do the right thing on narrow pics.
*/
DC1 = DC2 = DC3 = (int)prev_block_row[0][0];
DC4 = DC5 = DC6 = (int)buffer_ptr[0][0];
DC7 = DC8 = DC9 = (int)next_block_row[0][0];
DC01 = DC02 = DC03 = DC04 = DC05 = (int)prev_prev_block_row[0][0];
DC06 = DC07 = DC08 = DC09 = DC10 = (int)prev_block_row[0][0];
DC11 = DC12 = DC13 = DC14 = DC15 = (int)buffer_ptr[0][0];
DC16 = DC17 = DC18 = DC19 = DC20 = (int)next_block_row[0][0];
DC21 = DC22 = DC23 = DC24 = DC25 = (int)next_next_block_row[0][0];
output_col = 0;
last_block_column = compptr->width_in_blocks - 1;
for (block_num = cinfo->master->first_MCU_col[ci];
@@ -515,18 +581,39 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
/* Fetch current DCT block into workspace so we can modify it. */
jcopy_block_row(buffer_ptr, (JBLOCKROW)workspace, (JDIMENSION)1);
/* Update DC values */
if (block_num < last_block_column) {
DC3 = (int)prev_block_row[1][0];
DC6 = (int)buffer_ptr[1][0];
DC9 = (int)next_block_row[1][0];
if (block_num == cinfo->master->first_MCU_col[ci] &&
block_num < last_block_column) {
DC04 = (int)prev_prev_block_row[1][0];
DC09 = (int)prev_block_row[1][0];
DC14 = (int)buffer_ptr[1][0];
DC19 = (int)next_block_row[1][0];
DC24 = (int)next_next_block_row[1][0];
}
/* Compute coefficient estimates per K.8.
* An estimate is applied only if coefficient is still zero,
* and is not known to be fully accurate.
if (block_num + 1 < last_block_column) {
DC05 = (int)prev_prev_block_row[2][0];
DC10 = (int)prev_block_row[2][0];
DC15 = (int)buffer_ptr[2][0];
DC20 = (int)next_block_row[2][0];
DC25 = (int)next_next_block_row[2][0];
}
/* If DC interpolation is enabled, compute coefficient estimates using
* a Gaussian-like kernel, keeping the averages of the DC values.
*
* If DC interpolation is disabled, compute coefficient estimates using
* an algorithm similar to the one described in Section K.8 of the JPEG
* standard, except applied to a 5x5 window rather than a 3x3 window.
*
* An estimate is applied only if the coefficient is still zero and is
* not known to be fully accurate.
*/
/* AC01 */
if ((Al = coef_bits[1]) != 0 && workspace[1] == 0) {
num = 36 * Q00 * (DC4 - DC6);
num = Q00 * (change_dc ?
(-DC01 - DC02 + DC04 + DC05 - 3 * DC06 + 13 * DC07 -
13 * DC09 + 3 * DC10 - 3 * DC11 + 38 * DC12 - 38 * DC14 +
3 * DC15 - 3 * DC16 + 13 * DC17 - 13 * DC19 + 3 * DC20 -
DC21 - DC22 + DC24 + DC25) :
(-7 * DC11 + 50 * DC12 - 50 * DC14 + 7 * DC15));
if (num >= 0) {
pred = (int)(((Q01 << 7) + num) / (Q01 << 8));
if (Al > 0 && pred >= (1 << Al))
@@ -541,7 +628,12 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
}
/* AC10 */
if ((Al = coef_bits[2]) != 0 && workspace[8] == 0) {
num = 36 * Q00 * (DC2 - DC8);
num = Q00 * (change_dc ?
(-DC01 - 3 * DC02 - 3 * DC03 - 3 * DC04 - DC05 - DC06 +
13 * DC07 + 38 * DC08 + 13 * DC09 - DC10 + DC16 -
13 * DC17 - 38 * DC18 - 13 * DC19 + DC20 + DC21 +
3 * DC22 + 3 * DC23 + 3 * DC24 + DC25) :
(-7 * DC03 + 50 * DC08 - 50 * DC18 + 7 * DC23));
if (num >= 0) {
pred = (int)(((Q10 << 7) + num) / (Q10 << 8));
if (Al > 0 && pred >= (1 << Al))
@@ -556,7 +648,10 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
}
/* AC20 */
if ((Al = coef_bits[3]) != 0 && workspace[16] == 0) {
num = 9 * Q00 * (DC2 + DC8 - 2 * DC5);
num = Q00 * (change_dc ?
(DC03 + 2 * DC07 + 7 * DC08 + 2 * DC09 - 5 * DC12 - 14 * DC13 -
5 * DC14 + 2 * DC17 + 7 * DC18 + 2 * DC19 + DC23) :
(-DC03 + 13 * DC08 - 24 * DC13 + 13 * DC18 - DC23));
if (num >= 0) {
pred = (int)(((Q20 << 7) + num) / (Q20 << 8));
if (Al > 0 && pred >= (1 << Al))
@@ -571,7 +666,11 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
}
/* AC11 */
if ((Al = coef_bits[4]) != 0 && workspace[9] == 0) {
num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
num = Q00 * (change_dc ?
(-DC01 + DC05 + 9 * DC07 - 9 * DC09 - 9 * DC17 +
9 * DC19 + DC21 - DC25) :
(DC10 + DC16 - 10 * DC17 + 10 * DC19 - DC02 - DC20 + DC22 -
DC24 + DC04 - DC06 + 10 * DC07 - 10 * DC09));
if (num >= 0) {
pred = (int)(((Q11 << 7) + num) / (Q11 << 8));
if (Al > 0 && pred >= (1 << Al))
@@ -586,7 +685,10 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
}
/* AC02 */
if ((Al = coef_bits[5]) != 0 && workspace[2] == 0) {
num = 9 * Q00 * (DC4 + DC6 - 2 * DC5);
num = Q00 * (change_dc ?
(2 * DC07 - 5 * DC08 + 2 * DC09 + DC11 + 7 * DC12 - 14 * DC13 +
7 * DC14 + DC15 + 2 * DC17 - 5 * DC18 + 2 * DC19) :
(-DC11 + 13 * DC12 - 24 * DC13 + 13 * DC14 - DC15));
if (num >= 0) {
pred = (int)(((Q02 << 7) + num) / (Q02 << 8));
if (Al > 0 && pred >= (1 << Al))
@@ -599,14 +701,96 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
}
workspace[2] = (JCOEF)pred;
}
if (change_dc) {
/* AC03 */
if ((Al = coef_bits[6]) != 0 && workspace[3] == 0) {
num = Q00 * (DC07 - DC09 + 2 * DC12 - 2 * DC14 + DC17 - DC19);
if (num >= 0) {
pred = (int)(((Q03 << 7) + num) / (Q03 << 8));
if (Al > 0 && pred >= (1 << Al))
pred = (1 << Al) - 1;
} else {
pred = (int)(((Q03 << 7) - num) / (Q03 << 8));
if (Al > 0 && pred >= (1 << Al))
pred = (1 << Al) - 1;
pred = -pred;
}
workspace[3] = (JCOEF)pred;
}
/* AC12 */
if ((Al = coef_bits[7]) != 0 && workspace[10] == 0) {
num = Q00 * (DC07 - 3 * DC08 + DC09 - DC17 + 3 * DC18 - DC19);
if (num >= 0) {
pred = (int)(((Q12 << 7) + num) / (Q12 << 8));
if (Al > 0 && pred >= (1 << Al))
pred = (1 << Al) - 1;
} else {
pred = (int)(((Q12 << 7) - num) / (Q12 << 8));
if (Al > 0 && pred >= (1 << Al))
pred = (1 << Al) - 1;
pred = -pred;
}
workspace[10] = (JCOEF)pred;
}
/* AC21 */
if ((Al = coef_bits[8]) != 0 && workspace[17] == 0) {
num = Q00 * (DC07 - DC09 - 3 * DC12 + 3 * DC14 + DC17 - DC19);
if (num >= 0) {
pred = (int)(((Q21 << 7) + num) / (Q21 << 8));
if (Al > 0 && pred >= (1 << Al))
pred = (1 << Al) - 1;
} else {
pred = (int)(((Q21 << 7) - num) / (Q21 << 8));
if (Al > 0 && pred >= (1 << Al))
pred = (1 << Al) - 1;
pred = -pred;
}
workspace[17] = (JCOEF)pred;
}
/* AC30 */
if ((Al = coef_bits[9]) != 0 && workspace[24] == 0) {
num = Q00 * (DC07 + 2 * DC08 + DC09 - DC17 - 2 * DC18 - DC19);
if (num >= 0) {
pred = (int)(((Q30 << 7) + num) / (Q30 << 8));
if (Al > 0 && pred >= (1 << Al))
pred = (1 << Al) - 1;
} else {
pred = (int)(((Q30 << 7) - num) / (Q30 << 8));
if (Al > 0 && pred >= (1 << Al))
pred = (1 << Al) - 1;
pred = -pred;
}
workspace[24] = (JCOEF)pred;
}
/* coef_bits[0] is non-negative. Otherwise this function would not
* be called.
*/
num = Q00 *
(-2 * DC01 - 6 * DC02 - 8 * DC03 - 6 * DC04 - 2 * DC05 -
6 * DC06 + 6 * DC07 + 42 * DC08 + 6 * DC09 - 6 * DC10 -
8 * DC11 + 42 * DC12 + 152 * DC13 + 42 * DC14 - 8 * DC15 -
6 * DC16 + 6 * DC17 + 42 * DC18 + 6 * DC19 - 6 * DC20 -
2 * DC21 - 6 * DC22 - 8 * DC23 - 6 * DC24 - 2 * DC25);
if (num >= 0) {
pred = (int)(((Q00 << 7) + num) / (Q00 << 8));
} else {
pred = (int)(((Q00 << 7) - num) / (Q00 << 8));
pred = -pred;
}
workspace[0] = (JCOEF)pred;
} /* change_dc */
/* OK, do the IDCT */
(*inverse_DCT) (cinfo, compptr, (JCOEFPTR)workspace, output_ptr,
output_col);
/* Advance for next column */
DC1 = DC2; DC2 = DC3;
DC4 = DC5; DC5 = DC6;
DC7 = DC8; DC8 = DC9;
buffer_ptr++, prev_block_row++, next_block_row++;
DC01 = DC02; DC02 = DC03; DC03 = DC04; DC04 = DC05;
DC06 = DC07; DC07 = DC08; DC08 = DC09; DC09 = DC10;
DC11 = DC12; DC12 = DC13; DC13 = DC14; DC14 = DC15;
DC16 = DC17; DC17 = DC18; DC18 = DC19; DC19 = DC20;
DC21 = DC22; DC22 = DC23; DC23 = DC24; DC24 = DC25;
buffer_ptr++, prev_block_row++, next_block_row++,
prev_prev_block_row++, next_next_block_row++;
output_col += compptr->_DCT_scaled_size;
}
output_ptr += compptr->_DCT_scaled_size;
@@ -655,7 +839,7 @@ jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
#ifdef BLOCK_SMOOTHING_SUPPORTED
/* If block smoothing could be used, need a bigger window */
if (cinfo->progressive_mode)
access_rows *= 3;
access_rows *= 5;
#endif
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
((j_common_ptr)cinfo, JPOOL_IMAGE, TRUE,
+2 -1
View File
@@ -5,6 +5,7 @@
* Copyright (C) 1994-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2020, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*/
@@ -51,7 +52,7 @@ typedef struct {
#ifdef BLOCK_SMOOTHING_SUPPORTED
/* When doing block smoothing, we latch coefficient Al values here */
int *coef_bits_latch;
#define SAVED_COEFS 6 /* we save coef_bits[0..5] */
#define SAVED_COEFS 10 /* we save coef_bits[0..9] */
#endif
} my_coef_controller;
+48 -48
View File
@@ -45,9 +45,9 @@ ycc_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
outptr = *output_buf++;
if (PACK_NEED_ALIGNMENT(outptr)) {
y = GETJSAMPLE(*inptr0++);
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
y = *inptr0++;
cb = *inptr1++;
cr = *inptr2++;
r = range_limit[y + Crrtab[cr]];
g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
SCALEBITS))];
@@ -58,18 +58,18 @@ ycc_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
num_cols--;
}
for (col = 0; col < (num_cols >> 1); col++) {
y = GETJSAMPLE(*inptr0++);
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
y = *inptr0++;
cb = *inptr1++;
cr = *inptr2++;
r = range_limit[y + Crrtab[cr]];
g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
SCALEBITS))];
b = range_limit[y + Cbbtab[cb]];
rgb = PACK_SHORT_565(r, g, b);
y = GETJSAMPLE(*inptr0++);
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
y = *inptr0++;
cb = *inptr1++;
cr = *inptr2++;
r = range_limit[y + Crrtab[cr]];
g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
SCALEBITS))];
@@ -80,9 +80,9 @@ ycc_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
outptr += 4;
}
if (num_cols & 1) {
y = GETJSAMPLE(*inptr0);
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
y = *inptr0;
cb = *inptr1;
cr = *inptr2;
r = range_limit[y + Crrtab[cr]];
g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
SCALEBITS))];
@@ -125,9 +125,9 @@ ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
input_row++;
outptr = *output_buf++;
if (PACK_NEED_ALIGNMENT(outptr)) {
y = GETJSAMPLE(*inptr0++);
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
y = *inptr0++;
cb = *inptr1++;
cr = *inptr2++;
r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
g = range_limit[DITHER_565_G(y +
((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
@@ -139,9 +139,9 @@ ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
num_cols--;
}
for (col = 0; col < (num_cols >> 1); col++) {
y = GETJSAMPLE(*inptr0++);
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
y = *inptr0++;
cb = *inptr1++;
cr = *inptr2++;
r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
g = range_limit[DITHER_565_G(y +
((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
@@ -150,9 +150,9 @@ ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
d0 = DITHER_ROTATE(d0);
rgb = PACK_SHORT_565(r, g, b);
y = GETJSAMPLE(*inptr0++);
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
y = *inptr0++;
cb = *inptr1++;
cr = *inptr2++;
r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
g = range_limit[DITHER_565_G(y +
((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
@@ -165,9 +165,9 @@ ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
outptr += 4;
}
if (num_cols & 1) {
y = GETJSAMPLE(*inptr0);
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
y = *inptr0;
cb = *inptr1;
cr = *inptr2;
r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
g = range_limit[DITHER_565_G(y +
((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
@@ -202,32 +202,32 @@ rgb_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
input_row++;
outptr = *output_buf++;
if (PACK_NEED_ALIGNMENT(outptr)) {
r = GETJSAMPLE(*inptr0++);
g = GETJSAMPLE(*inptr1++);
b = GETJSAMPLE(*inptr2++);
r = *inptr0++;
g = *inptr1++;
b = *inptr2++;
rgb = PACK_SHORT_565(r, g, b);
*(INT16 *)outptr = (INT16)rgb;
outptr += 2;
num_cols--;
}
for (col = 0; col < (num_cols >> 1); col++) {
r = GETJSAMPLE(*inptr0++);
g = GETJSAMPLE(*inptr1++);
b = GETJSAMPLE(*inptr2++);
r = *inptr0++;
g = *inptr1++;
b = *inptr2++;
rgb = PACK_SHORT_565(r, g, b);
r = GETJSAMPLE(*inptr0++);
g = GETJSAMPLE(*inptr1++);
b = GETJSAMPLE(*inptr2++);
r = *inptr0++;
g = *inptr1++;
b = *inptr2++;
rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
outptr += 4;
}
if (num_cols & 1) {
r = GETJSAMPLE(*inptr0);
g = GETJSAMPLE(*inptr1);
b = GETJSAMPLE(*inptr2);
r = *inptr0;
g = *inptr1;
b = *inptr2;
rgb = PACK_SHORT_565(r, g, b);
*(INT16 *)outptr = (INT16)rgb;
}
@@ -259,24 +259,24 @@ rgb_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
input_row++;
outptr = *output_buf++;
if (PACK_NEED_ALIGNMENT(outptr)) {
r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
r = range_limit[DITHER_565_R(*inptr0++, d0)];
g = range_limit[DITHER_565_G(*inptr1++, d0)];
b = range_limit[DITHER_565_B(*inptr2++, d0)];
rgb = PACK_SHORT_565(r, g, b);
*(INT16 *)outptr = (INT16)rgb;
outptr += 2;
num_cols--;
}
for (col = 0; col < (num_cols >> 1); col++) {
r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
r = range_limit[DITHER_565_R(*inptr0++, d0)];
g = range_limit[DITHER_565_G(*inptr1++, d0)];
b = range_limit[DITHER_565_B(*inptr2++, d0)];
d0 = DITHER_ROTATE(d0);
rgb = PACK_SHORT_565(r, g, b);
r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
r = range_limit[DITHER_565_R(*inptr0++, d0)];
g = range_limit[DITHER_565_G(*inptr1++, d0)];
b = range_limit[DITHER_565_B(*inptr2++, d0)];
d0 = DITHER_ROTATE(d0);
rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
@@ -284,9 +284,9 @@ rgb_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
outptr += 4;
}
if (num_cols & 1) {
r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0), d0)];
g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1), d0)];
b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2), d0)];
r = range_limit[DITHER_565_R(*inptr0, d0)];
g = range_limit[DITHER_565_G(*inptr1, d0)];
b = range_limit[DITHER_565_B(*inptr2, d0)];
rgb = PACK_SHORT_565(r, g, b);
*(INT16 *)outptr = (INT16)rgb;
}
+3 -5
View File
@@ -53,9 +53,9 @@ ycc_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
input_row++;
outptr = *output_buf++;
for (col = 0; col < num_cols; col++) {
y = GETJSAMPLE(inptr0[col]);
cb = GETJSAMPLE(inptr1[col]);
cr = GETJSAMPLE(inptr2[col]);
y = inptr0[col];
cb = inptr1[col];
cr = inptr2[col];
/* Range-limiting is essential due to noise introduced by DCT losses. */
outptr[RGB_RED] = range_limit[y + Crrtab[cr]];
outptr[RGB_GREEN] = range_limit[y +
@@ -93,7 +93,6 @@ gray_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
inptr = input_buf[0][input_row++];
outptr = *output_buf++;
for (col = 0; col < num_cols; col++) {
/* We can dispense with GETJSAMPLE() here */
outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col];
/* Set unused byte to 0xFF so it can be interpreted as an opaque */
/* alpha channel value */
@@ -128,7 +127,6 @@ rgb_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
input_row++;
outptr = *output_buf++;
for (col = 0; col < num_cols; col++) {
/* We can dispense with GETJSAMPLE() here */
outptr[RGB_RED] = inptr0[col];
outptr[RGB_GREEN] = inptr1[col];
outptr[RGB_BLUE] = inptr2[col];
+7 -7
View File
@@ -341,9 +341,9 @@ rgb_gray_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
input_row++;
outptr = *output_buf++;
for (col = 0; col < num_cols; col++) {
r = GETJSAMPLE(inptr0[col]);
g = GETJSAMPLE(inptr1[col]);
b = GETJSAMPLE(inptr2[col]);
r = inptr0[col];
g = inptr1[col];
b = inptr2[col];
/* Y */
outptr[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] +
ctab[b + B_Y_OFF]) >> SCALEBITS);
@@ -550,9 +550,9 @@ ycck_cmyk_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
input_row++;
outptr = *output_buf++;
for (col = 0; col < num_cols; col++) {
y = GETJSAMPLE(inptr0[col]);
cb = GETJSAMPLE(inptr1[col]);
cr = GETJSAMPLE(inptr2[col]);
y = inptr0[col];
cb = inptr1[col];
cr = inptr2[col];
/* Range-limiting is essential due to noise introduced by DCT losses. */
outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */
outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */
@@ -560,7 +560,7 @@ ycck_cmyk_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
SCALEBITS)))];
outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */
/* K passes through unchanged */
outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */
outptr[3] = inptr3[col];
outptr += 4;
}
}
+27 -33
View File
@@ -5,6 +5,7 @@
* Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2009-2011, 2016, 2018-2019, D. R. Commander.
* Copyright (C) 2018, Matthias Räncker.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -39,24 +40,6 @@ typedef struct {
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
} savable_state;
/* This macro is to work around compilers with missing or broken
* structure assignment. You'll need to fix this code if you have
* such a compiler and you change MAX_COMPS_IN_SCAN.
*/
#ifndef NO_STRUCT_ASSIGN
#define ASSIGN_STATE(dest, src) ((dest) = (src))
#else
#if MAX_COMPS_IN_SCAN == 4
#define ASSIGN_STATE(dest, src) \
((dest).last_dc_val[0] = (src).last_dc_val[0], \
(dest).last_dc_val[1] = (src).last_dc_val[1], \
(dest).last_dc_val[2] = (src).last_dc_val[2], \
(dest).last_dc_val[3] = (src).last_dc_val[3])
#endif
#endif
typedef struct {
struct jpeg_entropy_decoder pub; /* public fields */
@@ -325,7 +308,7 @@ jpeg_fill_bit_buffer(bitread_working_state *state,
bytes_in_buffer = cinfo->src->bytes_in_buffer;
}
bytes_in_buffer--;
c = GETJOCTET(*next_input_byte++);
c = *next_input_byte++;
/* If it's 0xFF, check and discard stuffed zero byte */
if (c == 0xFF) {
@@ -342,7 +325,7 @@ jpeg_fill_bit_buffer(bitread_working_state *state,
bytes_in_buffer = cinfo->src->bytes_in_buffer;
}
bytes_in_buffer--;
c = GETJOCTET(*next_input_byte++);
c = *next_input_byte++;
} while (c == 0xFF);
if (c == 0) {
@@ -405,8 +388,8 @@ no_more_bytes:
#define GET_BYTE { \
register int c0, c1; \
c0 = GETJOCTET(*buffer++); \
c1 = GETJOCTET(*buffer); \
c0 = *buffer++; \
c1 = *buffer; \
/* Pre-execute most common case */ \
get_buffer = (get_buffer << 8) | c0; \
bits_left += 8; \
@@ -423,7 +406,7 @@ no_more_bytes:
} \
}
#if SIZEOF_SIZE_T == 8 || defined(_WIN64)
#if SIZEOF_SIZE_T == 8 || defined(_WIN64) || (defined(__x86_64__) && defined(__ILP32__))
/* Pre-fetch 48 bytes, because the holding register is 64-bit */
#define FILL_BIT_BUFFER_FAST \
@@ -557,6 +540,12 @@ process_restart(j_decompress_ptr cinfo)
}
#if defined(__has_feature)
#if __has_feature(undefined_behavior_sanitizer)
__attribute__((no_sanitize("signed-integer-overflow"),
no_sanitize("unsigned-integer-overflow")))
#endif
#endif
LOCAL(boolean)
decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
@@ -568,7 +557,7 @@ decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
/* Load up working state */
BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(state, entropy->saved);
state = entropy->saved;
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
JBLOCKROW block = MCU_data ? MCU_data[blkn] : NULL;
@@ -589,11 +578,15 @@ decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
if (entropy->dc_needed[blkn]) {
/* Convert DC difference to actual value, update last_dc_val */
int ci = cinfo->MCU_membership[blkn];
/* This is really just
* s += state.last_dc_val[ci];
* It is written this way in order to shut up UBSan.
/* Certain malformed JPEG images produce repeated DC coefficient
* differences of 2047 or -2047, which causes state.last_dc_val[ci] to
* grow until it overflows or underflows a 32-bit signed integer. This
* behavior is, to the best of our understanding, innocuous, and it is
* unclear how to work around it without potentially affecting
* performance. Thus, we (hopefully temporarily) suppress UBSan integer
* overflow errors for this function.
*/
s = (int)((unsigned int)s + (unsigned int)state.last_dc_val[ci]);
s += state.last_dc_val[ci];
state.last_dc_val[ci] = s;
if (block) {
/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
@@ -653,7 +646,7 @@ decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
/* Completed MCU, so update state */
BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(entropy->saved, state);
entropy->saved = state;
return TRUE;
}
@@ -671,7 +664,7 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
/* Load up working state */
BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
buffer = (JOCTET *)br_state.next_input_byte;
ASSIGN_STATE(state, entropy->saved);
state = entropy->saved;
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
JBLOCKROW block = MCU_data ? MCU_data[blkn] : NULL;
@@ -688,7 +681,7 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
if (entropy->dc_needed[blkn]) {
int ci = cinfo->MCU_membership[blkn];
s = (int)((unsigned int)s + (unsigned int)state.last_dc_val[ci]);
s += state.last_dc_val[ci];
state.last_dc_val[ci] = s;
if (block)
(*block)[0] = (JCOEF)s;
@@ -740,7 +733,7 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
br_state.bytes_in_buffer -= (buffer - br_state.next_input_byte);
br_state.next_input_byte = buffer;
BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(entropy->saved, state);
entropy->saved = state;
return TRUE;
}
@@ -795,7 +788,8 @@ use_slow:
}
/* Account for restart interval (no-op if not using restarts) */
entropy->restarts_to_go--;
if (cinfo->restart_interval)
entropy->restarts_to_go--;
return TRUE;
}
+11 -2
View File
@@ -4,7 +4,8 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2010-2011, 2015-2016, D. R. Commander.
* Copyright (C) 2010-2011, 2015-2016, 2021, D. R. Commander.
* Copyright (C) 2018, Matthias Räncker.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -78,6 +79,11 @@ EXTERN(void) jpeg_make_d_derived_tbl(j_decompress_ptr cinfo, boolean isDC,
typedef size_t bit_buf_type; /* type of bit-extraction buffer */
#define BIT_BUF_SIZE 64 /* size of buffer in bits */
#elif defined(__x86_64__) && defined(__ILP32__)
typedef unsigned long long bit_buf_type; /* type of bit-extraction buffer */
#define BIT_BUF_SIZE 64 /* size of buffer in bits */
#else
typedef unsigned long bit_buf_type; /* type of bit-extraction buffer */
@@ -228,7 +234,10 @@ slowlabel: \
s |= GET_BITS(1); \
nb++; \
} \
s = htbl->pub->huffval[(int)(s + htbl->valoffset[nb]) & 0xFF]; \
if (nb > 16) \
s = 0; \
else \
s = htbl->pub->huffval[(int)(s + htbl->valoffset[nb]) & 0xFF]; \
}
/* Out-of-line case for Huffman code fetching */
+16 -16
View File
@@ -38,18 +38,18 @@ marker_is_icc(jpeg_saved_marker_ptr marker)
marker->marker == ICC_MARKER &&
marker->data_length >= ICC_OVERHEAD_LEN &&
/* verify the identifying string */
GETJOCTET(marker->data[0]) == 0x49 &&
GETJOCTET(marker->data[1]) == 0x43 &&
GETJOCTET(marker->data[2]) == 0x43 &&
GETJOCTET(marker->data[3]) == 0x5F &&
GETJOCTET(marker->data[4]) == 0x50 &&
GETJOCTET(marker->data[5]) == 0x52 &&
GETJOCTET(marker->data[6]) == 0x4F &&
GETJOCTET(marker->data[7]) == 0x46 &&
GETJOCTET(marker->data[8]) == 0x49 &&
GETJOCTET(marker->data[9]) == 0x4C &&
GETJOCTET(marker->data[10]) == 0x45 &&
GETJOCTET(marker->data[11]) == 0x0;
marker->data[0] == 0x49 &&
marker->data[1] == 0x43 &&
marker->data[2] == 0x43 &&
marker->data[3] == 0x5F &&
marker->data[4] == 0x50 &&
marker->data[5] == 0x52 &&
marker->data[6] == 0x4F &&
marker->data[7] == 0x46 &&
marker->data[8] == 0x49 &&
marker->data[9] == 0x4C &&
marker->data[10] == 0x45 &&
marker->data[11] == 0x0;
}
@@ -102,12 +102,12 @@ jpeg_read_icc_profile(j_decompress_ptr cinfo, JOCTET **icc_data_ptr,
for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
if (marker_is_icc(marker)) {
if (num_markers == 0)
num_markers = GETJOCTET(marker->data[13]);
else if (num_markers != GETJOCTET(marker->data[13])) {
num_markers = marker->data[13];
else if (num_markers != marker->data[13]) {
WARNMS(cinfo, JWRN_BOGUS_ICC); /* inconsistent num_markers fields */
return FALSE;
}
seq_no = GETJOCTET(marker->data[12]);
seq_no = marker->data[12];
if (seq_no <= 0 || seq_no > num_markers) {
WARNMS(cinfo, JWRN_BOGUS_ICC); /* bogus sequence number */
return FALSE;
@@ -154,7 +154,7 @@ jpeg_read_icc_profile(j_decompress_ptr cinfo, JOCTET **icc_data_ptr,
JOCTET FAR *src_ptr;
JOCTET *dst_ptr;
unsigned int length;
seq_no = GETJOCTET(marker->data[12]);
seq_no = marker->data[12];
dst_ptr = icc_data + data_offset[seq_no];
src_ptr = marker->data + ICC_OVERHEAD_LEN;
length = data_length[seq_no];
+32 -35
View File
@@ -151,7 +151,7 @@ typedef my_marker_reader *my_marker_ptr;
#define INPUT_BYTE(cinfo, V, action) \
MAKESTMT( MAKE_BYTE_AVAIL(cinfo, action); \
bytes_in_buffer--; \
V = GETJOCTET(*next_input_byte++); )
V = *next_input_byte++; )
/* As above, but read two bytes interpreted as an unsigned 16-bit integer.
* V should be declared unsigned int or perhaps JLONG.
@@ -159,10 +159,10 @@ typedef my_marker_reader *my_marker_ptr;
#define INPUT_2BYTES(cinfo, V, action) \
MAKESTMT( MAKE_BYTE_AVAIL(cinfo, action); \
bytes_in_buffer--; \
V = ((unsigned int)GETJOCTET(*next_input_byte++)) << 8; \
V = ((unsigned int)(*next_input_byte++)) << 8; \
MAKE_BYTE_AVAIL(cinfo, action); \
bytes_in_buffer--; \
V += GETJOCTET(*next_input_byte++); )
V += *next_input_byte++; )
/*
@@ -608,18 +608,18 @@ examine_app0(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,
JLONG totallen = (JLONG)datalen + remaining;
if (datalen >= APP0_DATA_LEN &&
GETJOCTET(data[0]) == 0x4A &&
GETJOCTET(data[1]) == 0x46 &&
GETJOCTET(data[2]) == 0x49 &&
GETJOCTET(data[3]) == 0x46 &&
GETJOCTET(data[4]) == 0) {
data[0] == 0x4A &&
data[1] == 0x46 &&
data[2] == 0x49 &&
data[3] == 0x46 &&
data[4] == 0) {
/* Found JFIF APP0 marker: save info */
cinfo->saw_JFIF_marker = TRUE;
cinfo->JFIF_major_version = GETJOCTET(data[5]);
cinfo->JFIF_minor_version = GETJOCTET(data[6]);
cinfo->density_unit = GETJOCTET(data[7]);
cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]);
cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]);
cinfo->JFIF_major_version = data[5];
cinfo->JFIF_minor_version = data[6];
cinfo->density_unit = data[7];
cinfo->X_density = (data[8] << 8) + data[9];
cinfo->Y_density = (data[10] << 8) + data[11];
/* Check version.
* Major version must be 1, anything else signals an incompatible change.
* (We used to treat this as an error, but now it's a nonfatal warning,
@@ -634,24 +634,22 @@ examine_app0(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,
cinfo->JFIF_major_version, cinfo->JFIF_minor_version,
cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
/* Validate thumbnail dimensions and issue appropriate messages */
if (GETJOCTET(data[12]) | GETJOCTET(data[13]))
TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL,
GETJOCTET(data[12]), GETJOCTET(data[13]));
if (data[12] | data[13])
TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, data[12], data[13]);
totallen -= APP0_DATA_LEN;
if (totallen !=
((JLONG)GETJOCTET(data[12]) * (JLONG)GETJOCTET(data[13]) * (JLONG)3))
if (totallen != ((JLONG)data[12] * (JLONG)data[13] * (JLONG)3))
TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int)totallen);
} else if (datalen >= 6 &&
GETJOCTET(data[0]) == 0x4A &&
GETJOCTET(data[1]) == 0x46 &&
GETJOCTET(data[2]) == 0x58 &&
GETJOCTET(data[3]) == 0x58 &&
GETJOCTET(data[4]) == 0) {
data[0] == 0x4A &&
data[1] == 0x46 &&
data[2] == 0x58 &&
data[3] == 0x58 &&
data[4] == 0) {
/* Found JFIF "JFXX" extension APP0 marker */
/* The library doesn't actually do anything with these,
* but we try to produce a helpful trace message.
*/
switch (GETJOCTET(data[5])) {
switch (data[5]) {
case 0x10:
TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int)totallen);
break;
@@ -662,8 +660,7 @@ examine_app0(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,
TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int)totallen);
break;
default:
TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION,
GETJOCTET(data[5]), (int)totallen);
TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, data[5], (int)totallen);
break;
}
} else {
@@ -684,16 +681,16 @@ examine_app14(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,
unsigned int version, flags0, flags1, transform;
if (datalen >= APP14_DATA_LEN &&
GETJOCTET(data[0]) == 0x41 &&
GETJOCTET(data[1]) == 0x64 &&
GETJOCTET(data[2]) == 0x6F &&
GETJOCTET(data[3]) == 0x62 &&
GETJOCTET(data[4]) == 0x65) {
data[0] == 0x41 &&
data[1] == 0x64 &&
data[2] == 0x6F &&
data[3] == 0x62 &&
data[4] == 0x65) {
/* Found Adobe APP14 marker */
version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]);
flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]);
flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]);
transform = GETJOCTET(data[11]);
version = (data[5] << 8) + data[6];
flags0 = (data[7] << 8) + data[8];
flags1 = (data[9] << 8) + data[10];
transform = data[11];
TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);
cinfo->saw_Adobe_marker = TRUE;
cinfo->Adobe_transform = (UINT8)transform;
+2 -13
View File
@@ -5,7 +5,7 @@
* Copyright (C) 1991-1997, Thomas G. Lane.
* Modified 2002-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2009-2011, 2016, D. R. Commander.
* Copyright (C) 2009-2011, 2016, 2019, D. R. Commander.
* Copyright (C) 2013, Linaro Limited.
* Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg
@@ -22,7 +22,6 @@
#include "jpeglib.h"
#include "jpegcomp.h"
#include "jdmaster.h"
#include "jsimd.h"
/*
@@ -70,17 +69,6 @@ use_merged_upsample(j_decompress_ptr cinfo)
cinfo->comp_info[1]._DCT_scaled_size != cinfo->_min_DCT_scaled_size ||
cinfo->comp_info[2]._DCT_scaled_size != cinfo->_min_DCT_scaled_size)
return FALSE;
#ifdef WITH_SIMD
/* If YCbCr-to-RGB color conversion is SIMD-accelerated but merged upsampling
isn't, then disabling merged upsampling is likely to be faster when
decompressing YCbCr JPEG images. */
if (!jsimd_can_h2v2_merged_upsample() && !jsimd_can_h2v1_merged_upsample() &&
jsimd_can_ycc_rgb() && cinfo->jpeg_color_space == JCS_YCbCr &&
(cinfo->out_color_space == JCS_RGB ||
(cinfo->out_color_space >= JCS_EXT_RGB &&
cinfo->out_color_space <= JCS_EXT_ARGB)))
return FALSE;
#endif
/* ??? also need to test for upsample-time rescaling, when & if supported */
return TRUE; /* by golly, it'll work... */
#else
@@ -580,6 +568,7 @@ master_selection(j_decompress_ptr cinfo)
*/
cinfo->master->first_iMCU_col = 0;
cinfo->master->last_iMCU_col = cinfo->MCUs_per_row - 1;
cinfo->master->last_good_iMCU_row = 0;
#ifdef D_MULTISCAN_FILES_SUPPORTED
/* If jpeg_start_decompress will read the whole file, initialize
+34 -34
View File
@@ -43,20 +43,20 @@ h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
/* Loop for each pair of output pixels */
for (col = cinfo->output_width >> 1; col > 0; col--) {
/* Do the chroma part of the calculation */
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cb = *inptr1++;
cr = *inptr2++;
cred = Crrtab[cr];
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 2 Y values and emit 2 pixels */
y = GETJSAMPLE(*inptr0++);
y = *inptr0++;
r = range_limit[y + cred];
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
rgb = PACK_SHORT_565(r, g, b);
y = GETJSAMPLE(*inptr0++);
y = *inptr0++;
r = range_limit[y + cred];
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
@@ -68,12 +68,12 @@ h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
/* If image width is odd, do the last output column separately */
if (cinfo->output_width & 1) {
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cb = *inptr1;
cr = *inptr2;
cred = Crrtab[cr];
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr0);
y = *inptr0;
r = range_limit[y + cred];
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
@@ -115,21 +115,21 @@ h2v1_merged_upsample_565D_internal(j_decompress_ptr cinfo,
/* Loop for each pair of output pixels */
for (col = cinfo->output_width >> 1; col > 0; col--) {
/* Do the chroma part of the calculation */
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cb = *inptr1++;
cr = *inptr2++;
cred = Crrtab[cr];
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 2 Y values and emit 2 pixels */
y = GETJSAMPLE(*inptr0++);
y = *inptr0++;
r = range_limit[DITHER_565_R(y + cred, d0)];
g = range_limit[DITHER_565_G(y + cgreen, d0)];
b = range_limit[DITHER_565_B(y + cblue, d0)];
d0 = DITHER_ROTATE(d0);
rgb = PACK_SHORT_565(r, g, b);
y = GETJSAMPLE(*inptr0++);
y = *inptr0++;
r = range_limit[DITHER_565_R(y + cred, d0)];
g = range_limit[DITHER_565_G(y + cgreen, d0)];
b = range_limit[DITHER_565_B(y + cblue, d0)];
@@ -142,12 +142,12 @@ h2v1_merged_upsample_565D_internal(j_decompress_ptr cinfo,
/* If image width is odd, do the last output column separately */
if (cinfo->output_width & 1) {
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cb = *inptr1;
cr = *inptr2;
cred = Crrtab[cr];
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr0);
y = *inptr0;
r = range_limit[DITHER_565_R(y + cred, d0)];
g = range_limit[DITHER_565_G(y + cgreen, d0)];
b = range_limit[DITHER_565_B(y + cblue, d0)];
@@ -189,20 +189,20 @@ h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
/* Loop for each group of output pixels */
for (col = cinfo->output_width >> 1; col > 0; col--) {
/* Do the chroma part of the calculation */
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cb = *inptr1++;
cr = *inptr2++;
cred = Crrtab[cr];
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 4 Y values and emit 4 pixels */
y = GETJSAMPLE(*inptr00++);
y = *inptr00++;
r = range_limit[y + cred];
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
rgb = PACK_SHORT_565(r, g, b);
y = GETJSAMPLE(*inptr00++);
y = *inptr00++;
r = range_limit[y + cred];
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
@@ -211,13 +211,13 @@ h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
WRITE_TWO_PIXELS(outptr0, rgb);
outptr0 += 4;
y = GETJSAMPLE(*inptr01++);
y = *inptr01++;
r = range_limit[y + cred];
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
rgb = PACK_SHORT_565(r, g, b);
y = GETJSAMPLE(*inptr01++);
y = *inptr01++;
r = range_limit[y + cred];
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
@@ -229,20 +229,20 @@ h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
/* If image width is odd, do the last output column separately */
if (cinfo->output_width & 1) {
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cb = *inptr1;
cr = *inptr2;
cred = Crrtab[cr];
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr00);
y = *inptr00;
r = range_limit[y + cred];
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
rgb = PACK_SHORT_565(r, g, b);
*(INT16 *)outptr0 = (INT16)rgb;
y = GETJSAMPLE(*inptr01);
y = *inptr01;
r = range_limit[y + cred];
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
@@ -287,21 +287,21 @@ h2v2_merged_upsample_565D_internal(j_decompress_ptr cinfo,
/* Loop for each group of output pixels */
for (col = cinfo->output_width >> 1; col > 0; col--) {
/* Do the chroma part of the calculation */
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cb = *inptr1++;
cr = *inptr2++;
cred = Crrtab[cr];
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 4 Y values and emit 4 pixels */
y = GETJSAMPLE(*inptr00++);
y = *inptr00++;
r = range_limit[DITHER_565_R(y + cred, d0)];
g = range_limit[DITHER_565_G(y + cgreen, d0)];
b = range_limit[DITHER_565_B(y + cblue, d0)];
d0 = DITHER_ROTATE(d0);
rgb = PACK_SHORT_565(r, g, b);
y = GETJSAMPLE(*inptr00++);
y = *inptr00++;
r = range_limit[DITHER_565_R(y + cred, d0)];
g = range_limit[DITHER_565_G(y + cgreen, d0)];
b = range_limit[DITHER_565_B(y + cblue, d0)];
@@ -311,14 +311,14 @@ h2v2_merged_upsample_565D_internal(j_decompress_ptr cinfo,
WRITE_TWO_PIXELS(outptr0, rgb);
outptr0 += 4;
y = GETJSAMPLE(*inptr01++);
y = *inptr01++;
r = range_limit[DITHER_565_R(y + cred, d1)];
g = range_limit[DITHER_565_G(y + cgreen, d1)];
b = range_limit[DITHER_565_B(y + cblue, d1)];
d1 = DITHER_ROTATE(d1);
rgb = PACK_SHORT_565(r, g, b);
y = GETJSAMPLE(*inptr01++);
y = *inptr01++;
r = range_limit[DITHER_565_R(y + cred, d1)];
g = range_limit[DITHER_565_G(y + cgreen, d1)];
b = range_limit[DITHER_565_B(y + cblue, d1)];
@@ -331,20 +331,20 @@ h2v2_merged_upsample_565D_internal(j_decompress_ptr cinfo,
/* If image width is odd, do the last output column separately */
if (cinfo->output_width & 1) {
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cb = *inptr1;
cr = *inptr2;
cred = Crrtab[cr];
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr00);
y = *inptr00;
r = range_limit[DITHER_565_R(y + cred, d0)];
g = range_limit[DITHER_565_G(y + cgreen, d0)];
b = range_limit[DITHER_565_B(y + cblue, d0)];
rgb = PACK_SHORT_565(r, g, b);
*(INT16 *)outptr0 = (INT16)rgb;
y = GETJSAMPLE(*inptr01);
y = *inptr01;
r = range_limit[DITHER_565_R(y + cred, d1)];
g = range_limit[DITHER_565_G(y + cgreen, d1)];
b = range_limit[DITHER_565_B(y + cblue, d1)];
+17 -17
View File
@@ -46,13 +46,13 @@ h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
/* Loop for each pair of output pixels */
for (col = cinfo->output_width >> 1; col > 0; col--) {
/* Do the chroma part of the calculation */
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cb = *inptr1++;
cr = *inptr2++;
cred = Crrtab[cr];
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 2 Y values and emit 2 pixels */
y = GETJSAMPLE(*inptr0++);
y = *inptr0++;
outptr[RGB_RED] = range_limit[y + cred];
outptr[RGB_GREEN] = range_limit[y + cgreen];
outptr[RGB_BLUE] = range_limit[y + cblue];
@@ -60,7 +60,7 @@ h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
outptr[RGB_ALPHA] = 0xFF;
#endif
outptr += RGB_PIXELSIZE;
y = GETJSAMPLE(*inptr0++);
y = *inptr0++;
outptr[RGB_RED] = range_limit[y + cred];
outptr[RGB_GREEN] = range_limit[y + cgreen];
outptr[RGB_BLUE] = range_limit[y + cblue];
@@ -71,12 +71,12 @@ h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
}
/* If image width is odd, do the last output column separately */
if (cinfo->output_width & 1) {
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cb = *inptr1;
cr = *inptr2;
cred = Crrtab[cr];
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr0);
y = *inptr0;
outptr[RGB_RED] = range_limit[y + cred];
outptr[RGB_GREEN] = range_limit[y + cgreen];
outptr[RGB_BLUE] = range_limit[y + cblue];
@@ -120,13 +120,13 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
/* Loop for each group of output pixels */
for (col = cinfo->output_width >> 1; col > 0; col--) {
/* Do the chroma part of the calculation */
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cb = *inptr1++;
cr = *inptr2++;
cred = Crrtab[cr];
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 4 Y values and emit 4 pixels */
y = GETJSAMPLE(*inptr00++);
y = *inptr00++;
outptr0[RGB_RED] = range_limit[y + cred];
outptr0[RGB_GREEN] = range_limit[y + cgreen];
outptr0[RGB_BLUE] = range_limit[y + cblue];
@@ -134,7 +134,7 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
outptr0[RGB_ALPHA] = 0xFF;
#endif
outptr0 += RGB_PIXELSIZE;
y = GETJSAMPLE(*inptr00++);
y = *inptr00++;
outptr0[RGB_RED] = range_limit[y + cred];
outptr0[RGB_GREEN] = range_limit[y + cgreen];
outptr0[RGB_BLUE] = range_limit[y + cblue];
@@ -142,7 +142,7 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
outptr0[RGB_ALPHA] = 0xFF;
#endif
outptr0 += RGB_PIXELSIZE;
y = GETJSAMPLE(*inptr01++);
y = *inptr01++;
outptr1[RGB_RED] = range_limit[y + cred];
outptr1[RGB_GREEN] = range_limit[y + cgreen];
outptr1[RGB_BLUE] = range_limit[y + cblue];
@@ -150,7 +150,7 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
outptr1[RGB_ALPHA] = 0xFF;
#endif
outptr1 += RGB_PIXELSIZE;
y = GETJSAMPLE(*inptr01++);
y = *inptr01++;
outptr1[RGB_RED] = range_limit[y + cred];
outptr1[RGB_GREEN] = range_limit[y + cgreen];
outptr1[RGB_BLUE] = range_limit[y + cblue];
@@ -161,19 +161,19 @@ h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
}
/* If image width is odd, do the last output column separately */
if (cinfo->output_width & 1) {
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cb = *inptr1;
cr = *inptr2;
cred = Crrtab[cr];
cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr00);
y = *inptr00;
outptr0[RGB_RED] = range_limit[y + cred];
outptr0[RGB_GREEN] = range_limit[y + cgreen];
outptr0[RGB_BLUE] = range_limit[y + cblue];
#ifdef RGB_ALPHA
outptr0[RGB_ALPHA] = 0xFF;
#endif
y = GETJSAMPLE(*inptr01);
y = *inptr01;
outptr1[RGB_RED] = range_limit[y + cred];
outptr1[RGB_GREEN] = range_limit[y + cgreen];
outptr1[RGB_BLUE] = range_limit[y + cblue];
+20 -28
View File
@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1995-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2015-2016, 2018, D. R. Commander.
* Copyright (C) 2015-2016, 2018-2021, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -41,25 +41,6 @@ typedef struct {
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
} savable_state;
/* This macro is to work around compilers with missing or broken
* structure assignment. You'll need to fix this code if you have
* such a compiler and you change MAX_COMPS_IN_SCAN.
*/
#ifndef NO_STRUCT_ASSIGN
#define ASSIGN_STATE(dest, src) ((dest) = (src))
#else
#if MAX_COMPS_IN_SCAN == 4
#define ASSIGN_STATE(dest, src) \
((dest).EOBRUN = (src).EOBRUN, \
(dest).last_dc_val[0] = (src).last_dc_val[0], \
(dest).last_dc_val[1] = (src).last_dc_val[1], \
(dest).last_dc_val[2] = (src).last_dc_val[2], \
(dest).last_dc_val[3] = (src).last_dc_val[3])
#endif
#endif
typedef struct {
struct jpeg_entropy_decoder pub; /* public fields */
@@ -102,7 +83,7 @@ start_pass_phuff_decoder(j_decompress_ptr cinfo)
boolean is_DC_band, bad;
int ci, coefi, tbl;
d_derived_tbl **pdtbl;
int *coef_bit_ptr;
int *coef_bit_ptr, *prev_coef_bit_ptr;
jpeg_component_info *compptr;
is_DC_band = (cinfo->Ss == 0);
@@ -143,8 +124,15 @@ start_pass_phuff_decoder(j_decompress_ptr cinfo)
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
int cindex = cinfo->cur_comp_info[ci]->component_index;
coef_bit_ptr = &cinfo->coef_bits[cindex][0];
prev_coef_bit_ptr = &cinfo->coef_bits[cindex + cinfo->num_components][0];
if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
for (coefi = MIN(cinfo->Ss, 1); coefi <= MAX(cinfo->Se, 9); coefi++) {
if (cinfo->input_scan_number > 1)
prev_coef_bit_ptr[coefi] = coef_bit_ptr[coefi];
else
prev_coef_bit_ptr[coefi] = 0;
}
for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi];
if (cinfo->Ah != expected)
@@ -323,7 +311,7 @@ decode_mcu_DC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
/* Load up working state */
BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(state, entropy->saved);
state = entropy->saved;
/* Outer loop handles each block in the MCU */
@@ -356,11 +344,12 @@ decode_mcu_DC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
/* Completed MCU, so update state */
BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(entropy->saved, state);
entropy->saved = state;
}
/* Account for restart interval (no-op if not using restarts) */
entropy->restarts_to_go--;
if (cinfo->restart_interval)
entropy->restarts_to_go--;
return TRUE;
}
@@ -444,7 +433,8 @@ decode_mcu_AC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
}
/* Account for restart interval (no-op if not using restarts) */
entropy->restarts_to_go--;
if (cinfo->restart_interval)
entropy->restarts_to_go--;
return TRUE;
}
@@ -495,7 +485,8 @@ decode_mcu_DC_refine(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
/* Account for restart interval (no-op if not using restarts) */
entropy->restarts_to_go--;
if (cinfo->restart_interval)
entropy->restarts_to_go--;
return TRUE;
}
@@ -638,7 +629,8 @@ decode_mcu_AC_refine(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
}
/* Account for restart interval (no-op if not using restarts) */
entropy->restarts_to_go--;
if (cinfo->restart_interval)
entropy->restarts_to_go--;
return TRUE;
@@ -676,7 +668,7 @@ jinit_phuff_decoder(j_decompress_ptr cinfo)
/* Create progression status table */
cinfo->coef_bits = (int (*)[DCTSIZE2])
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
cinfo->num_components * DCTSIZE2 *
cinfo->num_components * 2 * DCTSIZE2 *
sizeof(int));
coef_bit_ptr = &cinfo->coef_bits[0][0];
for (ci = 0; ci < cinfo->num_components; ci++)
+22 -16
View File
@@ -8,7 +8,7 @@
* Copyright (C) 2010, 2015-2016, D. R. Commander.
* Copyright (C) 2014, MIPS Technologies, Inc., California.
* Copyright (C) 2015, Google, Inc.
* Copyright (C) 2019, Arm Limited.
* Copyright (C) 2019-2020, Arm Limited.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -177,7 +177,7 @@ int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
outptr = output_data[outrow];
outend = outptr + cinfo->output_width;
while (outptr < outend) {
invalue = *inptr++; /* don't need GETJSAMPLE() here */
invalue = *inptr++;
for (h = h_expand; h > 0; h--) {
*outptr++ = invalue;
}
@@ -213,7 +213,7 @@ h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
outptr = output_data[inrow];
outend = outptr + cinfo->output_width;
while (outptr < outend) {
invalue = *inptr++; /* don't need GETJSAMPLE() here */
invalue = *inptr++;
*outptr++ = invalue;
*outptr++ = invalue;
}
@@ -242,7 +242,7 @@ h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
outptr = output_data[outrow];
outend = outptr + cinfo->output_width;
while (outptr < outend) {
invalue = *inptr++; /* don't need GETJSAMPLE() here */
invalue = *inptr++;
*outptr++ = invalue;
*outptr++ = invalue;
}
@@ -283,20 +283,20 @@ h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
inptr = input_data[inrow];
outptr = output_data[inrow];
/* Special case for first column */
invalue = GETJSAMPLE(*inptr++);
invalue = *inptr++;
*outptr++ = (JSAMPLE)invalue;
*outptr++ = (JSAMPLE)((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
*outptr++ = (JSAMPLE)((invalue * 3 + inptr[0] + 2) >> 2);
for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
/* General case: 3/4 * nearer pixel + 1/4 * further pixel */
invalue = GETJSAMPLE(*inptr++) * 3;
*outptr++ = (JSAMPLE)((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
*outptr++ = (JSAMPLE)((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
invalue = (*inptr++) * 3;
*outptr++ = (JSAMPLE)((invalue + inptr[-2] + 1) >> 2);
*outptr++ = (JSAMPLE)((invalue + inptr[0] + 2) >> 2);
}
/* Special case for last column */
invalue = GETJSAMPLE(*inptr);
*outptr++ = (JSAMPLE)((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
invalue = *inptr;
*outptr++ = (JSAMPLE)((invalue * 3 + inptr[-1] + 1) >> 2);
*outptr++ = (JSAMPLE)invalue;
}
}
@@ -338,7 +338,7 @@ h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
outptr = output_data[outrow++];
for (colctr = 0; colctr < compptr->downsampled_width; colctr++) {
thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
thiscolsum = (*inptr0++) * 3 + (*inptr1++);
*outptr++ = (JSAMPLE)((thiscolsum + bias) >> 2);
}
}
@@ -381,8 +381,8 @@ h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
outptr = output_data[outrow++];
/* Special case for first column */
thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
thiscolsum = (*inptr0++) * 3 + (*inptr1++);
nextcolsum = (*inptr0++) * 3 + (*inptr1++);
*outptr++ = (JSAMPLE)((thiscolsum * 4 + 8) >> 4);
*outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4);
lastcolsum = thiscolsum; thiscolsum = nextcolsum;
@@ -390,7 +390,7 @@ h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
/* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
/* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
nextcolsum = (*inptr0++) * 3 + (*inptr1++);
*outptr++ = (JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4);
*outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4);
lastcolsum = thiscolsum; thiscolsum = nextcolsum;
@@ -477,7 +477,13 @@ jinit_upsampler(j_decompress_ptr cinfo)
} else if (h_in_group == h_out_group &&
v_in_group * 2 == v_out_group && do_fancy) {
/* Non-fancy upsampling is handled by the generic method */
upsample->methods[ci] = h1v2_fancy_upsample;
#if defined(__arm__) || defined(__aarch64__) || \
defined(_M_ARM) || defined(_M_ARM64)
if (jsimd_can_h1v2_fancy_upsample())
upsample->methods[ci] = jsimd_h1v2_fancy_upsample;
else
#endif
upsample->methods[ci] = h1v2_fancy_upsample;
upsample->pub.need_context_rows = TRUE;
} else if (h_in_group * 2 == h_out_group &&
v_in_group * 2 == v_out_group) {
+13
View File
@@ -207,6 +207,10 @@ JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
#endif
#endif
JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker")
#if JPEG_LIB_VERSION < 70
JMESSAGE(JERR_BAD_DROP_SAMPLING,
"Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c")
#endif
#ifdef JMAKE_ENUM_LIST
@@ -252,6 +256,15 @@ JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker")
(cinfo)->err->msg_parm.i[2] = (p3), \
(cinfo)->err->msg_parm.i[3] = (p4), \
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
#define ERREXIT6(cinfo, code, p1, p2, p3, p4, p5, p6) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(cinfo)->err->msg_parm.i[3] = (p4), \
(cinfo)->err->msg_parm.i[4] = (p5), \
(cinfo)->err->msg_parm.i[5] = (p6), \
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
#define ERREXITS(cinfo, code, str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
+4 -4
View File
@@ -3,7 +3,7 @@
*
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1998, Thomas G. Lane.
* Modification developed 2002-2009 by Guido Vollbeding.
* Modification developed 2002-2018 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2015, 2020, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
@@ -417,7 +417,7 @@ jpeg_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr,
/*
* Perform dequantization and inverse DCT on one block of coefficients,
* producing a 7x7 output block.
* producing a reduced-size 7x7 output block.
*
* Optimized algorithm with 12 multiplications in the 1-D kernel.
* cK represents sqrt(2) * cos(K*pi/14).
@@ -1258,7 +1258,7 @@ jpeg_idct_10x10(j_decompress_ptr cinfo, jpeg_component_info *compptr,
/*
* Perform dequantization and inverse DCT on one block of coefficients,
* producing a 11x11 output block.
* producing an 11x11 output block.
*
* Optimized algorithm with 24 multiplications in the 1-D kernel.
* cK represents sqrt(2) * cos(K*pi/22).
@@ -2398,7 +2398,7 @@ jpeg_idct_16x16(j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
/* Add fudge factor here for final descale. */
tmp0 += 1 << (CONST_BITS - PASS1_BITS - 1);
tmp0 += ONE << (CONST_BITS - PASS1_BITS - 1);
z1 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */
-35
View File
@@ -43,25 +43,11 @@
#if BITS_IN_JSAMPLE == 8
/* JSAMPLE should be the smallest type that will hold the values 0..255.
* You can use a signed char by having GETJSAMPLE mask it with 0xFF.
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JSAMPLE;
#define GETJSAMPLE(value) ((int)(value))
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JSAMPLE;
#ifdef __CHAR_UNSIGNED__
#define GETJSAMPLE(value) ((int)(value))
#else
#define GETJSAMPLE(value) ((int)(value) & 0xFF)
#endif /* __CHAR_UNSIGNED__ */
#endif /* HAVE_UNSIGNED_CHAR */
#define MAXJSAMPLE 255
#define CENTERJSAMPLE 128
@@ -97,22 +83,9 @@ typedef short JCOEF;
* managers, this is also the data type passed to fread/fwrite.
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JOCTET;
#define GETJOCTET(value) (value)
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JOCTET;
#ifdef __CHAR_UNSIGNED__
#define GETJOCTET(value) (value)
#else
#define GETJOCTET(value) ((value) & 0xFF)
#endif /* __CHAR_UNSIGNED__ */
#endif /* HAVE_UNSIGNED_CHAR */
/* These typedefs are used for various table entries and so forth.
* They must be at least as wide as specified; but making them too big
@@ -123,15 +96,7 @@ typedef char JOCTET;
/* UINT8 must hold at least the values 0..255. */
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char UINT8;
#else /* not HAVE_UNSIGNED_CHAR */
#ifdef __CHAR_UNSIGNED__
typedef char UINT8;
#else /* not __CHAR_UNSIGNED__ */
typedef short UINT8;
#endif /* __CHAR_UNSIGNED__ */
#endif /* HAVE_UNSIGNED_CHAR */
/* UINT16 must hold at least the values 0..65535. */
+4 -1
View File
@@ -5,7 +5,7 @@
* Copyright (C) 1991-1997, Thomas G. Lane.
* Modified 1997-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2015-2016, D. R. Commander.
* Copyright (C) 2015-2016, 2019, D. R. Commander.
* Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
@@ -158,6 +158,9 @@ struct jpeg_decomp_master {
JDIMENSION first_MCU_col[MAX_COMPONENTS];
JDIMENSION last_MCU_col[MAX_COMPONENTS];
boolean jinit_upsampler_no_alloc;
/* Last iMCU row that was successfully decoded */
JDIMENSION last_good_iMCU_row;
};
/* Input control module */
+12 -15
View File
@@ -479,7 +479,7 @@ color_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
for (col = width; col > 0; col--) {
pixcode = 0;
for (ci = 0; ci < nc; ci++) {
pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]);
pixcode += colorindex[ci][*ptrin++];
}
*ptrout++ = (JSAMPLE)pixcode;
}
@@ -506,9 +506,9 @@ color_quantize3(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
ptrin = input_buf[row];
ptrout = output_buf[row];
for (col = width; col > 0; col--) {
pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]);
pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]);
pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]);
pixcode = colorindex0[*ptrin++];
pixcode += colorindex1[*ptrin++];
pixcode += colorindex2[*ptrin++];
*ptrout++ = (JSAMPLE)pixcode;
}
}
@@ -552,7 +552,7 @@ quantize_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
* required amount of padding.
*/
*output_ptr +=
colorindex_ci[GETJSAMPLE(*input_ptr) + dither[col_index]];
colorindex_ci[*input_ptr + dither[col_index]];
input_ptr += nc;
output_ptr++;
col_index = (col_index + 1) & ODITHER_MASK;
@@ -595,12 +595,9 @@ quantize3_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
col_index = 0;
for (col = width; col > 0; col--) {
pixcode =
GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + dither0[col_index]]);
pixcode +=
GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + dither1[col_index]]);
pixcode +=
GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + dither2[col_index]]);
pixcode = colorindex0[(*input_ptr++) + dither0[col_index]];
pixcode += colorindex1[(*input_ptr++) + dither1[col_index]];
pixcode += colorindex2[(*input_ptr++) + dither2[col_index]];
*output_ptr++ = (JSAMPLE)pixcode;
col_index = (col_index + 1) & ODITHER_MASK;
}
@@ -677,15 +674,15 @@ quantize_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
* The maximum error is +- MAXJSAMPLE; this sets the required size
* of the range_limit array.
*/
cur += GETJSAMPLE(*input_ptr);
cur = GETJSAMPLE(range_limit[cur]);
cur += *input_ptr;
cur = range_limit[cur];
/* Select output value, accumulate into output code for this pixel */
pixcode = GETJSAMPLE(colorindex_ci[cur]);
pixcode = colorindex_ci[cur];
*output_ptr += (JSAMPLE)pixcode;
/* Compute actual representation error at this pixel */
/* Note: we can do this even though we don't have the final */
/* pixel code, because the colormap is orthogonal. */
cur -= GETJSAMPLE(colormap_ci[pixcode]);
cur -= colormap_ci[pixcode];
/* Compute error fractions to be propagated to adjacent pixels.
* Add these into the running sums, and simultaneously shift the
* next-line error sums left by 1 column.
+23 -23
View File
@@ -215,9 +215,9 @@ prescan_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
ptr = input_buf[row];
for (col = width; col > 0; col--) {
/* get pixel value and index into the histogram */
histp = &histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT]
[GETJSAMPLE(ptr[1]) >> C1_SHIFT]
[GETJSAMPLE(ptr[2]) >> C2_SHIFT];
histp = &histogram[ptr[0] >> C0_SHIFT]
[ptr[1] >> C1_SHIFT]
[ptr[2] >> C2_SHIFT];
/* increment, check for overflow and undo increment if so. */
if (++(*histp) <= 0)
(*histp)--;
@@ -665,7 +665,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
for (i = 0; i < numcolors; i++) {
/* We compute the squared-c0-distance term, then add in the other two. */
x = GETJSAMPLE(cinfo->colormap[0][i]);
x = cinfo->colormap[0][i];
if (x < minc0) {
tdist = (x - minc0) * C0_SCALE;
min_dist = tdist * tdist;
@@ -688,7 +688,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
}
}
x = GETJSAMPLE(cinfo->colormap[1][i]);
x = cinfo->colormap[1][i];
if (x < minc1) {
tdist = (x - minc1) * C1_SCALE;
min_dist += tdist * tdist;
@@ -710,7 +710,7 @@ find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
}
}
x = GETJSAMPLE(cinfo->colormap[2][i]);
x = cinfo->colormap[2][i];
if (x < minc2) {
tdist = (x - minc2) * C2_SCALE;
min_dist += tdist * tdist;
@@ -788,13 +788,13 @@ find_best_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE)
for (i = 0; i < numcolors; i++) {
icolor = GETJSAMPLE(colorlist[i]);
icolor = colorlist[i];
/* Compute (square of) distance from minc0/c1/c2 to this color */
inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE;
inc0 = (minc0 - cinfo->colormap[0][icolor]) * C0_SCALE;
dist0 = inc0 * inc0;
inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE;
inc1 = (minc1 - cinfo->colormap[1][icolor]) * C1_SCALE;
dist0 += inc1 * inc1;
inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE;
inc2 = (minc2 - cinfo->colormap[2][icolor]) * C2_SCALE;
dist0 += inc2 * inc2;
/* Form the initial difference increments */
inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;
@@ -879,7 +879,7 @@ fill_inverse_cmap(j_decompress_ptr cinfo, int c0, int c1, int c2)
for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) {
cachep = &histogram[c0 + ic0][c1 + ic1][c2];
for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) {
*cachep++ = (histcell)(GETJSAMPLE(*cptr++) + 1);
*cachep++ = (histcell)((*cptr++) + 1);
}
}
}
@@ -909,9 +909,9 @@ pass2_no_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
outptr = output_buf[row];
for (col = width; col > 0; col--) {
/* get pixel value and index into the cache */
c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT;
c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT;
c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT;
c0 = (*inptr++) >> C0_SHIFT;
c1 = (*inptr++) >> C1_SHIFT;
c2 = (*inptr++) >> C2_SHIFT;
cachep = &histogram[c0][c1][c2];
/* If we have not seen this color before, find nearest colormap entry */
/* and update the cache */
@@ -996,12 +996,12 @@ pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
* The maximum error is +- MAXJSAMPLE (or less with error limiting);
* this sets the required size of the range_limit array.
*/
cur0 += GETJSAMPLE(inptr[0]);
cur1 += GETJSAMPLE(inptr[1]);
cur2 += GETJSAMPLE(inptr[2]);
cur0 = GETJSAMPLE(range_limit[cur0]);
cur1 = GETJSAMPLE(range_limit[cur1]);
cur2 = GETJSAMPLE(range_limit[cur2]);
cur0 += inptr[0];
cur1 += inptr[1];
cur2 += inptr[2];
cur0 = range_limit[cur0];
cur1 = range_limit[cur1];
cur2 = range_limit[cur2];
/* Index into the cache with adjusted pixel value */
cachep =
&histogram[cur0 >> C0_SHIFT][cur1 >> C1_SHIFT][cur2 >> C2_SHIFT];
@@ -1015,9 +1015,9 @@ pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
register int pixcode = *cachep - 1;
*outptr = (JSAMPLE)pixcode;
/* Compute representation error for this pixel */
cur0 -= GETJSAMPLE(colormap0[pixcode]);
cur1 -= GETJSAMPLE(colormap1[pixcode]);
cur2 -= GETJSAMPLE(colormap2[pixcode]);
cur0 -= colormap0[pixcode];
cur1 -= colormap1[pixcode];
cur2 -= colormap2[pixcode];
}
/* Compute error fractions to be propagated to adjacent pixels.
* Add these into the running sums, and simultaneously shift the
+6
View File
@@ -4,6 +4,7 @@
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2011, 2014, D. R. Commander.
* Copyright (C) 2015-2016, 2018, Matthieu Darbois.
* Copyright (C) 2020, Arm Limited.
*
* Based on the x86 SIMD extension for IJG JPEG library,
* Copyright (C) 1999-2006, MIYASAKA Masaru.
@@ -75,6 +76,7 @@ EXTERN(void) jsimd_int_upsample(j_decompress_ptr cinfo,
EXTERN(int) jsimd_can_h2v2_fancy_upsample(void);
EXTERN(int) jsimd_can_h2v1_fancy_upsample(void);
EXTERN(int) jsimd_can_h1v2_fancy_upsample(void);
EXTERN(void) jsimd_h2v2_fancy_upsample(j_decompress_ptr cinfo,
jpeg_component_info *compptr,
@@ -84,6 +86,10 @@ EXTERN(void) jsimd_h2v1_fancy_upsample(j_decompress_ptr cinfo,
jpeg_component_info *compptr,
JSAMPARRAY input_data,
JSAMPARRAY *output_data_ptr);
EXTERN(void) jsimd_h1v2_fancy_upsample(j_decompress_ptr cinfo,
jpeg_component_info *compptr,
JSAMPARRAY input_data,
JSAMPARRAY *output_data_ptr);
EXTERN(int) jsimd_can_h2v2_merged_upsample(void);
EXTERN(int) jsimd_can_h2v1_merged_upsample(void);
+13
View File
@@ -4,6 +4,7 @@
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2009-2011, 2014, D. R. Commander.
* Copyright (C) 2015-2016, 2018, Matthieu Darbois.
* Copyright (C) 2020, Arm Limited.
*
* Based on the x86 SIMD extension for IJG JPEG library,
* Copyright (C) 1999-2006, MIYASAKA Masaru.
@@ -169,6 +170,12 @@ jsimd_can_h2v1_fancy_upsample(void)
return 0;
}
GLOBAL(int)
jsimd_can_h1v2_fancy_upsample(void)
{
return 0;
}
GLOBAL(void)
jsimd_h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
@@ -181,6 +188,12 @@ jsimd_h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
{
}
GLOBAL(void)
jsimd_h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
}
GLOBAL(int)
jsimd_can_h2v2_merged_upsample(void)
{
+6 -6
View File
@@ -2,9 +2,9 @@
* jversion.h
*
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding.
* Copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2010, 2012-2020, D. R. Commander.
* Copyright (C) 2010, 2012-2021, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -37,9 +37,9 @@
*/
#define JCOPYRIGHT \
"Copyright (C) 2009-2020 D. R. Commander\n" \
"Copyright (C) 2009-2021 D. R. Commander\n" \
"Copyright (C) 2015, 2020 Google, Inc.\n" \
"Copyright (C) 2019 Arm Limited\n" \
"Copyright (C) 2019-2020 Arm Limited\n" \
"Copyright (C) 2015-2016, 2018 Matthieu Darbois\n" \
"Copyright (C) 2011-2016 Siarhei Siamashka\n" \
"Copyright (C) 2015 Intel Corporation\n" \
@@ -48,7 +48,7 @@
"Copyright (C) 2009, 2012 Pierre Ossman for Cendio AB\n" \
"Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \
"Copyright (C) 1999-2006 MIYASAKA Masaru\n" \
"Copyright (C) 1991-2017 Thomas G. Lane, Guido Vollbeding"
"Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding"
#define JCOPYRIGHT_SHORT \
"Copyright (C) 1991-2020 The libjpeg-turbo Project and many others"
"Copyright (C) 1991-2021 The libjpeg-turbo Project and many others"
+6 -6
View File
@@ -1000,6 +1000,12 @@ if(COMMAND ocv_pylint_finalize)
ocv_pylint_add_directory_recurse(${CMAKE_CURRENT_LIST_DIR}/samples/python/tutorial_code)
ocv_pylint_finalize()
endif()
if(TARGET check_pylint)
message(STATUS "Registered 'check_pylint' target: using ${PYLINT_EXECUTABLE} (ver: ${PYLINT_VERSION}), checks: ${PYLINT_TOTAL_TARGETS}")
endif()
if(TARGET check_flake8)
message(STATUS "Registered 'check_flake8' target: using ${FLAKE8_EXECUTABLE} (ver: ${FLAKE8_VERSION})")
endif()
if(OPENCV_GENERATE_SETUPVARS)
include(cmake/OpenCVGenSetupVars.cmake)
@@ -1633,12 +1639,6 @@ endif()
status("")
status(" Python (for build):" PYTHON_DEFAULT_AVAILABLE THEN "${PYTHON_DEFAULT_EXECUTABLE}" ELSE NO)
if(PYLINT_FOUND AND PYLINT_EXECUTABLE)
status(" Pylint:" PYLINT_FOUND THEN "${PYLINT_EXECUTABLE} (ver: ${PYLINT_VERSION}, checks: ${PYLINT_TOTAL_TARGETS})" ELSE NO)
endif()
if(FLAKE8_FOUND AND FLAKE8_EXECUTABLE)
status(" Flake8:" FLAKE8_FOUND THEN "${FLAKE8_EXECUTABLE} (ver: ${FLAKE8_VERSION})" ELSE NO)
endif()
# ========================== java ==========================
if(BUILD_JAVA)
+1 -1
View File
@@ -16,7 +16,7 @@ if(PYLINT_EXECUTABLE AND NOT DEFINED PYLINT_VERSION)
execute_process(COMMAND ${PYLINT_EXECUTABLE} --version RESULT_VARIABLE _result OUTPUT_VARIABLE PYLINT_VERSION_RAW)
if(NOT _result EQUAL 0)
ocv_clear_vars(PYLINT_EXECUTABLE PYLINT_VERSION)
elseif(PYLINT_VERSION_RAW MATCHES "pylint([^,]*) ([0-9\\.]+[0-9])")
elseif(PYLINT_VERSION_RAW MATCHES "pylint([^,\n]*) ([0-9\\.]+[0-9])")
set(PYLINT_VERSION "${CMAKE_MATCH_2}")
else()
set(PYLINT_VERSION "unknown")
+14 -1
View File
@@ -177,7 +177,13 @@ if(CV_GCC OR CV_CLANG)
endif()
# We need pthread's
if(UNIX AND NOT ANDROID AND NOT (APPLE AND CV_CLANG)) # TODO
if((UNIX
AND NOT ANDROID
AND NOT (APPLE AND CV_CLANG)
AND NOT EMSCRIPTEN
)
OR (EMSCRIPTEN AND WITH_PTHREADS_PF) # https://github.com/opencv/opencv/issues/20285
)
add_extra_compiler_option(-pthread)
endif()
@@ -225,9 +231,11 @@ if(CV_GCC OR CV_CLANG)
if(APPLE)
set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} -Wl,-dead_strip")
set(OPENCV_EXTRA_SHARED_LINKER_FLAGS "${OPENCV_EXTRA_SHARED_LINKER_FLAGS} -Wl,-dead_strip")
set(OPENCV_EXTRA_MODULE_LINKER_FLAGS "${OPENCV_EXTRA_MODULE_LINKER_FLAGS} -Wl,-dead_strip")
else()
set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} -Wl,--gc-sections")
set(OPENCV_EXTRA_SHARED_LINKER_FLAGS "${OPENCV_EXTRA_SHARED_LINKER_FLAGS} -Wl,--gc-sections")
set(OPENCV_EXTRA_MODULE_LINKER_FLAGS "${OPENCV_EXTRA_MODULE_LINKER_FLAGS} -Wl,--gc-sections")
endif()
endif()
endif()
@@ -279,6 +287,7 @@ if(MSVC)
set(OPENCV_EXTRA_FLAGS_RELEASE "${OPENCV_EXTRA_FLAGS_RELEASE} /Zi")
set(OPENCV_EXTRA_EXE_LINKER_FLAGS_RELEASE "${OPENCV_EXTRA_EXE_LINKER_FLAGS_RELEASE} /debug")
set(OPENCV_EXTRA_SHARED_LINKER_FLAGS_RELEASE "${OPENCV_EXTRA_SHARED_LINKER_FLAGS_RELEASE} /debug")
set(OPENCV_EXTRA_MODULE_LINKER_FLAGS_RELEASE "${OPENCV_EXTRA_MODULE_LINKER_FLAGS_RELEASE} /debug")
endif()
# Remove unreferenced functions: function level linking
@@ -346,6 +355,7 @@ if(NOT OPENCV_SKIP_LINK_AS_NEEDED)
if(HAVE_LINK_AS_NEEDED)
set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} ${_option}")
set(OPENCV_EXTRA_SHARED_LINKER_FLAGS "${OPENCV_EXTRA_SHARED_LINKER_FLAGS} ${_option}")
set(OPENCV_EXTRA_MODULE_LINKER_FLAGS "${OPENCV_EXTRA_MODULE_LINKER_FLAGS} ${_option}")
endif()
endif()
endif()
@@ -364,6 +374,9 @@ if(NOT OPENCV_SKIP_EXTRA_COMPILER_FLAGS)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${OPENCV_EXTRA_SHARED_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${OPENCV_EXTRA_SHARED_LINKER_FLAGS_RELEASE}")
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${OPENCV_EXTRA_SHARED_LINKER_FLAGS_DEBUG}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${OPENCV_EXTRA_MODULE_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${OPENCV_EXTRA_MODULE_LINKER_FLAGS_RELEASE}")
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} ${OPENCV_EXTRA_MODULE_LINKER_FLAGS_DEBUG}")
endif()
if(MSVC)
+13 -11
View File
@@ -9,9 +9,14 @@ set(HALIDE_ROOT_DIR "${HALIDE_ROOT_DIR}" CACHE PATH "Halide root directory")
if(NOT HAVE_HALIDE)
find_package(Halide QUIET) # Try CMake-based config files
if(Halide_FOUND)
set(HALIDE_INCLUDE_DIRS "${Halide_INCLUDE_DIRS}" CACHE PATH "Halide include directories" FORCE)
set(HALIDE_LIBRARIES "${Halide_LIBRARIES}" CACHE PATH "Halide libraries" FORCE)
set(HAVE_HALIDE TRUE)
if(TARGET Halide::Halide) # modern Halide scripts defines imported target
set(HALIDE_INCLUDE_DIRS "")
set(HALIDE_LIBRARIES "Halide::Halide")
set(HAVE_HALIDE TRUE)
else()
# using HALIDE_INCLUDE_DIRS / Halide_LIBRARIES
set(HAVE_HALIDE TRUE)
endif()
endif()
endif()
@@ -28,18 +33,15 @@ if(NOT HAVE_HALIDE AND HALIDE_ROOT_DIR)
)
if(HALIDE_LIBRARY AND HALIDE_INCLUDE_DIR)
# TODO try_compile
set(HALIDE_INCLUDE_DIRS "${HALIDE_INCLUDE_DIR}" CACHE PATH "Halide include directories" FORCE)
set(HALIDE_LIBRARIES "${HALIDE_LIBRARY}" CACHE PATH "Halide libraries" FORCE)
set(HALIDE_INCLUDE_DIRS "${HALIDE_INCLUDE_DIR}")
set(HALIDE_LIBRARIES "${HALIDE_LIBRARY}")
set(HAVE_HALIDE TRUE)
endif()
if(NOT HAVE_HALIDE)
ocv_clear_vars(HALIDE_LIBRARIES HALIDE_INCLUDE_DIRS CACHE)
endif()
endif()
if(HAVE_HALIDE)
include_directories(${HALIDE_INCLUDE_DIRS})
if(HALIDE_INCLUDE_DIRS)
include_directories(${HALIDE_INCLUDE_DIRS})
endif()
list(APPEND OPENCV_LINKER_LIBS ${HALIDE_LIBRARIES})
else()
ocv_clear_vars(HALIDE_INCLUDE_DIRS HALIDE_LIBRARIES)
endif()
+13 -4
View File
@@ -140,12 +140,21 @@ endif()
# Add more features to the target
if(INF_ENGINE_TARGET)
if(NOT INF_ENGINE_RELEASE)
message(WARNING "InferenceEngine version has not been set, 2021.2 will be used by default. Set INF_ENGINE_RELEASE variable if you experience build errors.")
if(DEFINED InferenceEngine_VERSION)
message(STATUS "InferenceEngine: ${InferenceEngine_VERSION}")
if(NOT INF_ENGINE_RELEASE AND NOT (InferenceEngine_VERSION VERSION_LESS "2021.4"))
math(EXPR INF_ENGINE_RELEASE_INIT "${InferenceEngine_VERSION_MAJOR} * 1000000 + ${InferenceEngine_VERSION_MINOR} * 10000 + ${InferenceEngine_VERSION_PATCH} * 100")
endif()
endif()
set(INF_ENGINE_RELEASE "2021020000" CACHE STRING "Force IE version, should be in form YYYYAABBCC (e.g. 2020.1.0.2 -> 2020010002)")
if(NOT INF_ENGINE_RELEASE AND NOT INF_ENGINE_RELEASE_INIT)
message(WARNING "InferenceEngine version has not been set, 2021.4 will be used by default. Set INF_ENGINE_RELEASE variable if you experience build errors.")
set(INF_ENGINE_RELEASE_INIT "2021040000")
elseif(DEFINED INF_ENGINE_RELEASE)
set(INF_ENGINE_RELEASE_INIT "${INF_ENGINE_RELEASE}")
endif()
set(INF_ENGINE_RELEASE "${INF_ENGINE_RELEASE_INIT}" CACHE STRING "Force IE version, should be in form YYYYAABBCC (e.g. 2020.1.0.2 -> 2020010002)")
set_target_properties(${INF_ENGINE_TARGET} PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "HAVE_INF_ENGINE=1;INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}"
INTERFACE_COMPILE_DEFINITIONS "HAVE_INF_ENGINE=1;INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}"
)
endif()
+1 -1
View File
@@ -23,7 +23,7 @@ set(OPENCV_DOWNLOAD_LOG "${OpenCV_BINARY_DIR}/CMakeDownloadLog.txt")
set(OPENCV_DOWNLOAD_WITH_CURL "${OpenCV_BINARY_DIR}/download_with_curl.sh")
set(OPENCV_DOWNLOAD_WITH_WGET "${OpenCV_BINARY_DIR}/download_with_wget.sh")
set(OPENCV_DOWNLOAD_TRIES_LIST 1 CACHE STRING "List of download tries") # a list
set(OPENCV_DOWNLOAD_PARAMS INACTIVITY_TIMEOUT 60 TIMEOUT 600 CACHE STRING "Download parameters to be passed to file(DOWNLAOD ...)")
set(OPENCV_DOWNLOAD_PARAMS INACTIVITY_TIMEOUT 60 TIMEOUT 600 CACHE STRING "Download parameters to be passed to file(DOWNLOAD ...)")
mark_as_advanced(OPENCV_DOWNLOAD_TRIES_LIST OPENCV_DOWNLOAD_PARAMS)
# Init download cache directory and log file and helper scripts
+16 -1
View File
@@ -143,10 +143,25 @@ macro(ipp_detect_version)
list(APPEND IPP_LIBRARIES ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX})
else ()
add_library(ipp${name} STATIC IMPORTED)
set(_filename "${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX}")
set_target_properties(ipp${name} PROPERTIES
IMPORTED_LINK_INTERFACE_LIBRARIES ""
IMPORTED_LOCATION ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX}
IMPORTED_LOCATION ${IPP_LIBRARY_DIR}/${_filename}
)
if("${name}" STREQUAL "core") # https://github.com/opencv/opencv/pull/19681
if(OPENCV_FORCE_IPP_EXCLUDE_LIBS OR OPENCV_FORCE_IPP_EXCLUDE_LIBS_CORE
OR (UNIX AND NOT ANDROID AND NOT APPLE
AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|Intel"
)
AND NOT OPENCV_SKIP_IPP_EXCLUDE_LIBS_CORE
)
if(CMAKE_VERSION VERSION_LESS "3.13.0")
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--exclude-libs,${_filename} ${CMAKE_SHARED_LINKER_FLAGS}")
else()
target_link_options(ipp${name} INTERFACE "LINKER:--exclude-libs,${_filename}")
endif()
endif()
endif()
list(APPEND IPP_LIBRARIES ipp${name})
if (NOT BUILD_SHARED_LIBS AND (HAVE_IPP_ICV OR ";${OPENCV_INSTALL_EXTERNAL_DEPENDENCIES};" MATCHES ";ipp;"))
# CMake doesn't support "install(TARGETS ${IPP_PREFIX}${name} " command with imported targets
+1 -1
View File
@@ -29,7 +29,7 @@ if(WITH_IPP)
if(OPENCV_FORCE_IPP_EXCLUDE_LIBS
OR (HAVE_IPP_ICV
AND UNIX AND NOT ANDROID AND NOT APPLE
AND (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|Intel"
)
AND NOT OPENCV_SKIP_IPP_EXCLUDE_LIBS
)
+5 -1
View File
@@ -876,7 +876,11 @@ endmacro()
macro(_ocv_create_module)
ocv_compiler_optimization_process_sources(OPENCV_MODULE_${the_module}_SOURCES OPENCV_MODULE_${the_module}_DEPS_EXT ${the_module})
set(OPENCV_MODULE_${the_module}_HEADERS ${OPENCV_MODULE_${the_module}_HEADERS} CACHE INTERNAL "List of header files for ${the_module}")
set(__module_headers ${OPENCV_MODULE_${the_module}_HEADERS})
if(__module_headers)
list(SORT __module_headers) # fix headers order, useful for bindings
endif()
set(OPENCV_MODULE_${the_module}_HEADERS ${__module_headers} CACHE INTERNAL "List of header files for ${the_module}")
set(OPENCV_MODULE_${the_module}_SOURCES ${OPENCV_MODULE_${the_module}_SOURCES} CACHE INTERNAL "List of source files for ${the_module}")
# The condition we ought to be testing here is whether ocv_add_precompiled_headers will
-1
View File
@@ -122,7 +122,6 @@ function(ocv_pylint_finalize)
list(LENGTH PYLINT_TARGET_ID __total)
set(PYLINT_TOTAL_TARGETS "${__total}" CACHE INTERNAL "")
message(STATUS "Pylint: registered ${__total} targets. Build 'check_pylint' target to run checks (\"cmake --build . --target check_pylint\" or \"make check_pylint\")")
configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/pylint.cmake.in" "${CMAKE_BINARY_DIR}/pylint.cmake" @ONLY)
add_custom_target(check_pylint
+7 -1
View File
@@ -31,7 +31,7 @@ MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 4
ALIASES += add_toggle{1}="@htmlonly[block] <div class='newInnerHTML'>\1</div><div> <script type="text/javascript"> addToggle(); </script>@endhtmlonly"
ALIASES += add_toggle{1}="@htmlonly[block] <div class='newInnerHTML'>\1</div><div> <script type='text/javascript'> addToggle(); </script>@endhtmlonly"
ALIASES += add_toggle_cpp="@htmlonly[block] <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'>@endhtmlonly"
ALIASES += add_toggle_java="@htmlonly[block] <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'>@endhtmlonly"
ALIASES += add_toggle_python="@htmlonly[block] <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'>@endhtmlonly"
@@ -249,6 +249,12 @@ PREDEFINED = __cplusplus=1 \
CV_DEFAULT(x)=" = x" \
CV_NEON=1 \
CV_SSE2=1 \
CV_SIMD128=1 \
CV_SIMD256=1 \
CV_SIMD512=1 \
CV_SIMD128_64F=1 \
CV_SIMD256_64F=1 \
CV_SIMD512_64F=1 \
CV__DEBUG_NS_BEGIN= \
CV__DEBUG_NS_END= \
CV_DEPRECATED_EXTERNAL= \
@@ -138,6 +138,7 @@ Building OpenCV.js from Source
python ./platforms/js/build_js.py build_js --cmake_option="-DOPENCV_EXTRA_MODULES_PATH=opencv_contrib/modules"
@endcode
Running OpenCV.js Tests
---------------------------------------
@@ -303,6 +304,12 @@ The example uses latest version of emscripten. If the build fails you should try
docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk:2.0.10 emcmake python3 ./platforms/js/build_js.py build_js
@endcode
In Windows use the following PowerShell command:
@code{.bash}
docker run --rm --workdir /src -v "$(get-location):/src" "emscripten/emsdk:2.0.10" emcmake python3 ./platforms/js/build_js.py build_js
@endcode
### Building the documentation with Docker
To build the documentation `doxygen` needs to be installed. Create a file named `Dockerfile` with the following content:
+4 -4
View File
@@ -835,12 +835,12 @@
journal = {IEEE Transactions on Robotics and Automation},
title = {Robot sensor calibration: solving AX=XB on the Euclidean group},
year = {1994},
month = oct,
volume = {10},
number = {5},
pages = {717-721},
doi = {10.1109/70.326576},
ISSN = {1042-296X},
month = {Oct}
issn = {1042-296X}
}
@inproceedings{PM03,
author = {P{\'e}rez, Patrick and Gangnet, Michel and Blake, Andrew},
@@ -1028,12 +1028,12 @@
journal = {IEEE Transactions on Robotics and Automation},
title = {A new technique for fully autonomous and efficient 3D robotics hand/eye calibration},
year = {1989},
month = jun,
volume = {5},
number = {3},
pages = {345-358},
doi = {10.1109/70.34770},
ISSN = {1042-296X},
month = {June}
issn = {1042-296X}
}
@inproceedings{UES01,
author = {Uyttendaele, Matthew and Eden, Ashley and Skeliski, R},
@@ -40,12 +40,12 @@ using **cv.Sobel()**).
Then comes the main part. After this, they created a score, basically an equation, which
determines if a window can contain a corner or not.
\f[R = det(M) - k(trace(M))^2\f]
\f[R = \det(M) - k(\operatorname{trace}(M))^2\f]
where
- \f$det(M) = \lambda_1 \lambda_2\f$
- \f$trace(M) = \lambda_1 + \lambda_2\f$
- \f$\lambda_1\f$ and \f$\lambda_2\f$ are the eigenvalues of M
- \f$\det(M) = \lambda_1 \lambda_2\f$
- \f$\operatorname{trace}(M) = \lambda_1 + \lambda_2\f$
- \f$\lambda_1\f$ and \f$\lambda_2\f$ are the eigenvalues of \f$M\f$
So the magnitudes of these eigenvalues decide whether a region is a corner, an edge, or flat.
@@ -20,7 +20,7 @@ Harris Corner Detector. The scoring function in Harris Corner Detector was given
Instead of this, Shi-Tomasi proposed:
\f[R = min(\lambda_1, \lambda_2)\f]
\f[R = \min(\lambda_1, \lambda_2)\f]
If it is a greater than a threshold value, it is considered as a corner. If we plot it in
\f$\lambda_1 - \lambda_2\f$ space as we did in Harris Corner Detector, we get an image as below:
@@ -28,7 +28,7 @@ If it is a greater than a threshold value, it is considered as a corner. If we p
![image](images/shitomasi_space.png)
From the figure, you can see that only when \f$\lambda_1\f$ and \f$\lambda_2\f$ are above a minimum value,
\f$\lambda_{min}\f$, it is considered as a corner(green region).
\f$\lambda_{\min}\f$, it is considered as a corner(green region).
Code
----
@@ -156,7 +156,7 @@ sift = cv.SIFT_create()
kp, des = sift.detectAndCompute(gray,None)
@endcode
Here kp will be a list of keypoints and des is a numpy array of shape
\f$Number\_of\_Keypoints \times 128\f$.
\f$\text{(Number of Keypoints)} \times 128\f$.
So we got keypoints, descriptors etc. Now we want to see how to match keypoints in different images.
That we will learn in coming chapters.
+2 -9
View File
@@ -107,17 +107,10 @@ def add_signature_to_table(soup, table, signature, language, type):
""" Add a signature to an html table"""
row = soup.new_tag('tr')
row.append(soup.new_tag('td', style='width: 20px;'))
if 'ret' in signature:
row.append(append(soup.new_tag('td'), signature['ret']))
row.append(append(soup.new_tag('td'), '='))
else:
row.append(soup.new_tag('td')) # return values
row.append(soup.new_tag('td')) # '='
row.append(append(soup.new_tag('td'), signature['name'] + '('))
row.append(append(soup.new_tag('td', **{'class': 'paramname'}), signature['arg']))
row.append(append(soup.new_tag('td'), ')'))
row.append(append(soup.new_tag('td'), ') -> '))
row.append(append(soup.new_tag('td'), signature['ret']))
table.append(row)
@@ -80,7 +80,7 @@ The tutorial consists of two main programs:
The application starts up extracting the ORB features and descriptors from the input image and
then uses the mesh along with the [MöllerTrumbore intersection
algorithm](http://http://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm/)
algorithm](http://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm/)
to compute the 3D coordinates of the found features. Finally, the 3D points and the descriptors
are stored in different lists in a file with YAML format which each row is a different point. The
technical background on how to store the files can be found in the @ref tutorial_file_input_output_with_xml_yml
@@ -39,14 +39,14 @@ Open your Doxyfile using your favorite text editor and search for the key
`TAGFILES`. Change it as follows:
@code
TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.14
TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.15
@endcode
If you had other definitions already, you can append the line using a `\`:
@code
TAGFILES = ./docs/doxygen-tags/libstdc++.tag=https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen \
./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.14
./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/3.4.15
@endcode
Doxygen can now use the information from the tag file to link to the OpenCV
@@ -59,7 +59,7 @@ extension, its first version. A direct limitation of this is that you cannot sav
larger than 2 GB. Furthermore you can only create and expand a single video track inside the
container. No audio or other track editing support here. Nevertheless, any video codec present on
your system might work. If you encounter some of these limitations you will need to look into more
specialized video writing libraries such as *FFMpeg* or codecs as *HuffYUV*, *CorePNG* and *LCL*. As
specialized video writing libraries such as *FFmpeg* or codecs as *HuffYUV*, *CorePNG* and *LCL*. As
an alternative, create the video track with OpenCV and expand it with sound tracks or convert it to
other formats by using video manipulation programs such as *VirtualDub* or *AviSynth*.
+25 -11
View File
@@ -1510,8 +1510,8 @@ concatenated together.
@param imageSize Size of the image used only to initialize the camera intrinsic matrix.
@param cameraMatrix Input/output 3x3 floating-point camera intrinsic matrix
\f$\cameramatrix{A}\f$ . If @ref CALIB_USE_INTRINSIC_GUESS
and/or @ref CALIB_FIX_ASPECT_RATIO are specified, some or all of fx, fy, cx, cy must be
initialized before calling the function.
and/or @ref CALIB_FIX_ASPECT_RATIO, @ref CALIB_FIX_PRINCIPAL_POINT or @ref CALIB_FIX_FOCAL_LENGTH
are specified, some or all of fx, fy, cx, cy must be initialized before calling the function.
@param distCoeffs Input/output vector of distortion coefficients
\f$\distcoeffs\f$.
@param rvecs Output vector of rotation vectors (@ref Rodrigues ) estimated for each pattern view
@@ -1537,7 +1537,7 @@ the number of pattern views. \f$R_i, T_i\f$ are concatenated 1x3 vectors.
fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set to the image
center ( imageSize is used), and focal distances are computed in a least-squares fashion.
Note, that if intrinsic parameters are known, there is no need to use this function just to
estimate extrinsic parameters. Use solvePnP instead.
estimate extrinsic parameters. Use @ref solvePnP instead.
- @ref CALIB_FIX_PRINCIPAL_POINT The principal point is not changed during the global
optimization. It stays at the center or at a different location specified when
@ref CALIB_USE_INTRINSIC_GUESS is set too.
@@ -1547,24 +1547,23 @@ ratio fx/fy stays the same as in the input cameraMatrix . When
ignored, only their ratio is computed and used further.
- @ref CALIB_ZERO_TANGENT_DIST Tangential distortion coefficients \f$(p_1, p_2)\f$ are set
to zeros and stay zero.
- @ref CALIB_FIX_FOCAL_LENGTH The focal length is not changed during the global optimization if
@ref CALIB_USE_INTRINSIC_GUESS is set.
- @ref CALIB_FIX_K1,..., @ref CALIB_FIX_K6 The corresponding radial distortion
coefficient is not changed during the optimization. If @ref CALIB_USE_INTRINSIC_GUESS is
set, the coefficient from the supplied distCoeffs matrix is used. Otherwise, it is set to 0.
- @ref CALIB_RATIONAL_MODEL Coefficients k4, k5, and k6 are enabled. To provide the
backward compatibility, this extra flag should be explicitly specified to make the
calibration function use the rational model and return 8 coefficients. If the flag is not
set, the function computes and returns only 5 distortion coefficients.
calibration function use the rational model and return 8 coefficients or more.
- @ref CALIB_THIN_PRISM_MODEL Coefficients s1, s2, s3 and s4 are enabled. To provide the
backward compatibility, this extra flag should be explicitly specified to make the
calibration function use the thin prism model and return 12 coefficients. If the flag is not
set, the function computes and returns only 5 distortion coefficients.
calibration function use the thin prism model and return 12 coefficients or more.
- @ref CALIB_FIX_S1_S2_S3_S4 The thin prism distortion coefficients are not changed during
the optimization. If @ref CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the
supplied distCoeffs matrix is used. Otherwise, it is set to 0.
- @ref CALIB_TILTED_MODEL Coefficients tauX and tauY are enabled. To provide the
backward compatibility, this extra flag should be explicitly specified to make the
calibration function use the tilted sensor model and return 14 coefficients. If the flag is not
set, the function computes and returns only 5 distortion coefficients.
calibration function use the tilted sensor model and return 14 coefficients.
- @ref CALIB_FIX_TAUX_TAUY The coefficients of the tilted sensor model are not changed during
the optimization. If @ref CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the
supplied distCoeffs matrix is used. Otherwise, it is set to 0.
@@ -1589,12 +1588,12 @@ The algorithm performs the following steps:
zeros initially unless some of CALIB_FIX_K? are specified.
- Estimate the initial camera pose as if the intrinsic parameters have been already known. This is
done using solvePnP .
done using @ref solvePnP .
- Run the global Levenberg-Marquardt optimization algorithm to minimize the reprojection error,
that is, the total sum of squared distances between the observed feature points imagePoints and
the projected (using the current estimates for camera parameters and the poses) object points
objectPoints. See projectPoints for details.
objectPoints. See @ref projectPoints for details.
@note
If you use a non-square (i.e. non-N-by-N) grid and @ref findChessboardCorners for calibration,
@@ -2241,6 +2240,7 @@ final fundamental matrix. It can be set to something like 1-3, depending on the
point localization, image resolution, and the image noise.
@param mask Output array of N elements, every element of which is set to 0 for outliers and to 1
for the other points. The array is computed only in the RANSAC and LMedS methods.
@param maxIters The maximum number of robust method iterations.
This function estimates essential matrix based on the five-point algorithm solver in @cite Nister03 .
@cite SteweniusCFS is also a related. The epipolar geometry is described by the following equation:
@@ -2251,6 +2251,12 @@ where \f$E\f$ is an essential matrix, \f$p_1\f$ and \f$p_2\f$ are corresponding
second images, respectively. The result of this function may be passed further to
decomposeEssentialMat or recoverPose to recover the relative pose between cameras.
*/
CV_EXPORTS_W Mat findEssentialMat( InputArray points1, InputArray points2,
InputArray cameraMatrix, int method,
double prob, double threshold,
int maxIters, OutputArray mask = noArray() );
/** @overload */
CV_EXPORTS_W Mat findEssentialMat( InputArray points1, InputArray points2,
InputArray cameraMatrix, int method = RANSAC,
double prob = 0.999, double threshold = 1.0,
@@ -2274,6 +2280,7 @@ point localization, image resolution, and the image noise.
confidence (probability) that the estimated matrix is correct.
@param mask Output array of N elements, every element of which is set to 0 for outliers and to 1
for the other points. The array is computed only in the RANSAC and LMedS methods.
@param maxIters The maximum number of robust method iterations.
This function differs from the one above that it computes camera intrinsic matrix from focal length and
principal point:
@@ -2285,6 +2292,13 @@ f & 0 & x_{pp} \\
0 & 0 & 1
\end{bmatrix}\f]
*/
CV_EXPORTS_W Mat findEssentialMat( InputArray points1, InputArray points2,
double focal, Point2d pp,
int method, double prob,
double threshold, int maxIters,
OutputArray mask = noArray() );
/** @overload */
CV_EXPORTS_W Mat findEssentialMat( InputArray points1, InputArray points2,
double focal = 1.0, Point2d pp = Point2d(0, 0),
int method = RANSAC, double prob = 0.999,
+21 -4
View File
@@ -403,7 +403,8 @@ protected:
// Input should be a vector of n 2D points or a Nx2 matrix
cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, InputArray _cameraMatrix,
int method, double prob, double threshold, OutputArray _mask)
int method, double prob, double threshold,
int maxIters, OutputArray _mask)
{
CV_INSTRUMENT_REGION();
@@ -442,20 +443,36 @@ cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, InputArr
Mat E;
if( method == RANSAC )
createRANSACPointSetRegistrator(makePtr<EMEstimatorCallback>(), 5, threshold, prob)->run(points1, points2, E, _mask);
createRANSACPointSetRegistrator(makePtr<EMEstimatorCallback>(), 5, threshold, prob, maxIters)->run(points1, points2, E, _mask);
else
createLMeDSPointSetRegistrator(makePtr<EMEstimatorCallback>(), 5, prob)->run(points1, points2, E, _mask);
createLMeDSPointSetRegistrator(makePtr<EMEstimatorCallback>(), 5, prob, maxIters)->run(points1, points2, E, _mask);
return E;
}
cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, InputArray _cameraMatrix,
int method, double prob, double threshold,
OutputArray _mask)
{
return cv::findEssentialMat(_points1, _points2, _cameraMatrix, method, prob, threshold, 1000, _mask);
}
cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, double focal, Point2d pp,
int method, double prob, double threshold, int maxIters, OutputArray _mask)
{
CV_INSTRUMENT_REGION();
Mat cameraMatrix = (Mat_<double>(3,3) << focal, 0, pp.x, 0, focal, pp.y, 0, 0, 1);
return cv::findEssentialMat(_points1, _points2, cameraMatrix, method, prob, threshold, maxIters, _mask);
}
cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, double focal, Point2d pp,
int method, double prob, double threshold, OutputArray _mask)
{
CV_INSTRUMENT_REGION();
Mat cameraMatrix = (Mat_<double>(3,3) << focal, 0, pp.x, 0, focal, pp.y, 0, 0, 1);
return cv::findEssentialMat(_points1, _points2, cameraMatrix, method, prob, threshold, _mask);
return cv::findEssentialMat(_points1, _points2, cameraMatrix, method, prob, threshold, 1000, _mask);
}
int cv::recoverPose( InputArray E, InputArray _points1, InputArray _points2,
+1 -1
View File
@@ -866,7 +866,7 @@ cv::Mat cv::findFundamentalMat( InputArray _points1, InputArray _points2,
if( (method & ~3) == FM_RANSAC && npoints >= 15 )
result = createRANSACPointSetRegistrator(cb, 7, ransacReprojThreshold, confidence, maxIters)->run(m1, m2, F, _mask);
else
result = createLMeDSPointSetRegistrator(cb, 7, confidence)->run(m1, m2, F, _mask);
result = createLMeDSPointSetRegistrator(cb, 7, confidence, maxIters)->run(m1, m2, F, _mask);
}
if( result <= 0 )
+11 -3
View File
@@ -65,7 +65,8 @@ int solve_deg3(double a, double b, double c, double d,
return 3;
}
else {
x0 = pow(2 * R, 1 / 3.0) - b_a_3;
double cube_root = cv::cubeRoot(2 * R);
x0 = cube_root - b_a_3;
return 1;
}
}
@@ -82,8 +83,15 @@ int solve_deg3(double a, double b, double c, double d,
}
// D > 0, only one real root
double AD = pow(fabs(R) + sqrt(D), 1.0 / 3.0) * (R > 0 ? 1 : (R < 0 ? -1 : 0));
double BD = (AD == 0) ? 0 : -Q / AD;
double AD = 0.;
double BD = 0.;
double R_abs = fabs(R);
if (R_abs > DBL_EPSILON)
{
AD = cv::cubeRoot(R_abs + sqrt(D));
AD = (R >= 0) ? AD : -AD;
BD = -Q / AD;
}
// Calculate the only real root
x0 = AD + BD - b_a_3;
+29 -5
View File
@@ -311,18 +311,42 @@ bool solvePnPRansac(InputArray _opoints, InputArray _ipoints,
opoints_inliers.resize(npoints1);
ipoints_inliers.resize(npoints1);
result = solvePnP(opoints_inliers, ipoints_inliers, cameraMatrix,
distCoeffs, rvec, tvec, useExtrinsicGuess,
(flags == SOLVEPNP_P3P || flags == SOLVEPNP_AP3P) ? SOLVEPNP_EPNP : flags) ? 1 : -1;
try
{
result = solvePnP(opoints_inliers, ipoints_inliers, cameraMatrix,
distCoeffs, rvec, tvec, useExtrinsicGuess,
(flags == SOLVEPNP_P3P || flags == SOLVEPNP_AP3P) ? SOLVEPNP_EPNP : flags) ? 1 : -1;
}
catch (const cv::Exception& e)
{
if (flags == SOLVEPNP_ITERATIVE &&
npoints1 == 5 &&
e.what() &&
std::string(e.what()).find("DLT algorithm needs at least 6 points") != std::string::npos
)
{
CV_LOG_INFO(NULL, "solvePnPRansac(): solvePnP stage to compute the final pose using points "
"in the consensus set raised DLT 6 points exception, use result from MSS (Minimal Sample Sets) stage instead.");
rvec = _local_model.col(0); // output rotation vector
tvec = _local_model.col(1); // output translation vector
result = 1;
}
else
{
// raise other exceptions
throw;
}
}
if( result <= 0 )
if (result <= 0)
{
_rvec.assign(_local_model.col(0)); // output rotation vector
_tvec.assign(_local_model.col(1)); // output translation vector
if( _inliers.needed() )
if (_inliers.needed())
_inliers.release();
CV_LOG_DEBUG(NULL, "solvePnPRansac(): solvePnP stage to compute the final pose using points in the consensus set failed. Return false");
return false;
}
else
+4 -2
View File
@@ -1148,13 +1148,15 @@ class StereoBMImpl CV_FINAL : public StereoBM
{
public:
StereoBMImpl()
: params()
{
params = StereoBMParams();
// nothing
}
StereoBMImpl( int _numDisparities, int _SADWindowSize )
: params(_numDisparities, _SADWindowSize)
{
params = StereoBMParams(_numDisparities, _SADWindowSize);
// nothing
}
void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) CV_OVERRIDE
+7 -5
View File
@@ -2186,19 +2186,21 @@ class StereoSGBMImpl CV_FINAL : public StereoSGBM
{
public:
StereoSGBMImpl()
: params()
{
params = StereoSGBMParams();
// nothing
}
StereoSGBMImpl( int _minDisparity, int _numDisparities, int _SADWindowSize,
int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap,
int _uniquenessRatio, int _speckleWindowSize, int _speckleRange,
int _mode )
: params(_minDisparity, _numDisparities, _SADWindowSize,
_P1, _P2, _disp12MaxDiff, _preFilterCap,
_uniquenessRatio, _speckleWindowSize, _speckleRange,
_mode)
{
params = StereoSGBMParams( _minDisparity, _numDisparities, _SADWindowSize,
_P1, _P2, _disp12MaxDiff, _preFilterCap,
_uniquenessRatio, _speckleWindowSize, _speckleRange,
_mode );
// nothing
}
void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) CV_OVERRIDE
@@ -837,6 +837,43 @@ TEST(Calib3d_SolvePnPRansac, double_support)
EXPECT_LE(cvtest::norm(t, Mat_<double>(tF), NORM_INF), 1e-3);
}
TEST(Calib3d_SolvePnPRansac, bad_input_points_19253)
{
// with this specific data
// when computing the final pose using points in the consensus set with SOLVEPNP_ITERATIVE and solvePnP()
// an exception is thrown from solvePnP because there are 5 non-coplanar 3D points and the DLT algorithm needs at least 6 non-coplanar 3D points
// with PR #19253 we choose to return true, with the pose estimated from the MSS stage instead of throwing the exception
float pts2d_[] = {
-5.38358629e-01f, -5.09638414e-02f,
-5.07192254e-01f, -2.20743284e-01f,
-5.43107152e-01f, -4.90474701e-02f,
-5.54325163e-01f, -1.86715424e-01f,
-5.59334219e-01f, -4.01909500e-02f,
-5.43504596e-01f, -4.61776406e-02f
};
Mat pts2d(6, 2, CV_32FC1, pts2d_);
float pts3d_[] = {
-3.01153604e-02f, -1.55665115e-01f, 4.50000018e-01f,
4.27827090e-01f, 4.28645730e-01f, 1.08600008e+00f,
-3.14165242e-02f, -1.52656138e-01f, 4.50000018e-01f,
-1.46217480e-01f, 5.57961613e-02f, 7.17000008e-01f,
-4.89348806e-02f, -1.38795510e-01f, 4.47000027e-01f,
-3.13065052e-02f, -1.52636901e-01f, 4.51000035e-01f
};
Mat pts3d(6, 3, CV_32FC1, pts3d_);
Mat camera_mat = Mat::eye(3, 3, CV_64FC1);
Mat rvec, tvec;
vector<int> inliers;
// solvePnPRansac will return true with 5 inliers, which means the result is from MSS stage.
bool result = solvePnPRansac(pts3d, pts2d, camera_mat, noArray(), rvec, tvec, false, 100, 4.f / 460.f, 0.99, inliers);
EXPECT_EQ(inliers.size(), size_t(5));
EXPECT_TRUE(result);
}
TEST(Calib3d_SolvePnP, input_type)
{
Matx33d intrinsics(5.4794130238156129e+002, 0., 2.9835545700043139e+002, 0.,
+4
View File
@@ -112,6 +112,10 @@ ocv_target_link_libraries(${the_module} PRIVATE
"${OPENCV_HAL_LINKER_LIBS}"
)
if(OPENCV_CORE_EXCLUDE_C_API)
ocv_target_compile_definitions(${the_module} PRIVATE "OPENCV_EXCLUDE_C_API=1")
endif()
ocv_add_accuracy_tests()
ocv_add_perf_tests()
@@ -587,6 +587,21 @@ _AccTp normInf(const _Tp* a, const _Tp* b, int n)
*/
CV_EXPORTS_W float cubeRoot(float val);
/** @overload
cubeRoot with argument of `double` type calls `std::cbrt(double)` (C++11) or falls back on `pow()` for C++98 compilation mode.
*/
static inline
double cubeRoot(double val)
{
#ifdef CV_CXX11
return std::cbrt(val);
#else
double v = pow(abs(val), 1/3.); // pow doesn't support negative inputs with fractional exponents
return val >= 0 ? v : -v;
#endif
}
/** @brief Calculates the angle of a 2D vector in degrees.
The function fastAtan2 calculates the full-range angle of an input 2D vector. The angle is measured
@@ -7,6 +7,7 @@
#include <opencv2/core/async.hpp>
#include <opencv2/core/detail/async_promise.hpp>
#include <opencv2/core/utils/logger.hpp>
#include <stdexcept>
@@ -144,7 +145,26 @@ AsyncArray testAsyncException()
return p.getArrayResult();
}
//! @}
}} // namespace
//! @} // core_utils
} // namespace cv::utils
//! @cond IGNORED
CV_WRAP static inline
int setLogLevel(int level)
{
// NB: Binding generators doesn't work with enums properly yet, so we define separate overload here
return cv::utils::logging::setLogLevel((cv::utils::logging::LogLevel)level);
}
CV_WRAP static inline
int getLogLevel()
{
return cv::utils::logging::getLogLevel();
}
//! @endcond IGNORED
} // namespaces cv / utils
#endif // OPENCV_CORE_BINDINGS_UTILS_HPP
+1 -1
View File
@@ -554,7 +554,7 @@ Cv64suf;
# define CV_XADD(addr, delta) (int)_InterlockedExchangeAdd((long volatile*)addr, delta)
#else
#ifdef OPENCV_FORCE_UNSAFE_XADD
CV_INLINE CV_XADD(int* addr, int delta) { int tmp = *addr; *addr += delta; return tmp; }
CV_INLINE int CV_XADD(int* addr, int delta) { int tmp = *addr; *addr += delta; return tmp; }
#else
#error "OpenCV: can't define safe CV_XADD macro for current platform (unsupported). Define CV_XADD macro through custom port header (see OPENCV_INCLUDE_PORT_FILE)"
#endif
@@ -76,6 +76,9 @@
#if defined __PPC64__ && defined __GNUC__ && defined _ARCH_PWR8 \
&& !defined(OPENCV_SKIP_INCLUDE_ALTIVEC_H)
#include <altivec.h>
#undef vector
#undef bool
#undef pixel
#endif
#if defined(CV_INLINE_ROUND_FLT)
+251 -73
View File
@@ -104,7 +104,7 @@ template<typename _Tp> struct V_TypeTraits
{
};
#define CV_INTRIN_DEF_TYPE_TRAITS(type, int_type_, uint_type_, abs_type_, w_type_, q_type_, sum_type_, nlanes128_) \
#define CV_INTRIN_DEF_TYPE_TRAITS(type, int_type_, uint_type_, abs_type_, w_type_, q_type_, sum_type_) \
template<> struct V_TypeTraits<type> \
{ \
typedef type value_type; \
@@ -114,7 +114,6 @@ template<typename _Tp> struct V_TypeTraits
typedef w_type_ w_type; \
typedef q_type_ q_type; \
typedef sum_type_ sum_type; \
enum { nlanes128 = nlanes128_ }; \
\
static inline int_type reinterpret_int(type x) \
{ \
@@ -131,7 +130,7 @@ template<typename _Tp> struct V_TypeTraits
} \
}
#define CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(type, int_type_, uint_type_, abs_type_, w_type_, sum_type_, nlanes128_) \
#define CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(type, int_type_, uint_type_, abs_type_, w_type_, sum_type_) \
template<> struct V_TypeTraits<type> \
{ \
typedef type value_type; \
@@ -140,7 +139,6 @@ template<typename _Tp> struct V_TypeTraits
typedef uint_type_ uint_type; \
typedef w_type_ w_type; \
typedef sum_type_ sum_type; \
enum { nlanes128 = nlanes128_ }; \
\
static inline int_type reinterpret_int(type x) \
{ \
@@ -157,16 +155,16 @@ template<typename _Tp> struct V_TypeTraits
} \
}
CV_INTRIN_DEF_TYPE_TRAITS(uchar, schar, uchar, uchar, ushort, unsigned, unsigned, 16);
CV_INTRIN_DEF_TYPE_TRAITS(schar, schar, uchar, uchar, short, int, int, 16);
CV_INTRIN_DEF_TYPE_TRAITS(ushort, short, ushort, ushort, unsigned, uint64, unsigned, 8);
CV_INTRIN_DEF_TYPE_TRAITS(short, short, ushort, ushort, int, int64, int, 8);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(unsigned, int, unsigned, unsigned, uint64, unsigned, 4);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(int, int, unsigned, unsigned, int64, int, 4);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(float, int, unsigned, float, double, float, 4);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(uint64, int64, uint64, uint64, void, uint64, 2);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(int64, int64, uint64, uint64, void, int64, 2);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(double, int64, uint64, double, void, double, 2);
CV_INTRIN_DEF_TYPE_TRAITS(uchar, schar, uchar, uchar, ushort, unsigned, unsigned);
CV_INTRIN_DEF_TYPE_TRAITS(schar, schar, uchar, uchar, short, int, int);
CV_INTRIN_DEF_TYPE_TRAITS(ushort, short, ushort, ushort, unsigned, uint64, unsigned);
CV_INTRIN_DEF_TYPE_TRAITS(short, short, ushort, ushort, int, int64, int);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(unsigned, int, unsigned, unsigned, uint64, unsigned);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(int, int, unsigned, unsigned, int64, int);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(float, int, unsigned, float, double, float);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(uint64, int64, uint64, uint64, void, uint64);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(int64, int64, uint64, uint64, void, int64);
CV_INTRIN_DEF_TYPE_TRAITS_NO_Q_TYPE(double, int64, uint64, double, void, double);
#ifndef CV_DOXYGEN
@@ -310,54 +308,6 @@ CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN
//==================================================================================================
#define CV_INTRIN_DEFINE_WIDE_INTRIN(typ, vtyp, short_typ, prefix, loadsfx) \
inline vtyp vx_setall_##short_typ(typ v) { return prefix##_setall_##short_typ(v); } \
inline vtyp vx_setzero_##short_typ() { return prefix##_setzero_##short_typ(); } \
inline vtyp vx_##loadsfx(const typ* ptr) { return prefix##_##loadsfx(ptr); } \
inline vtyp vx_##loadsfx##_aligned(const typ* ptr) { return prefix##_##loadsfx##_aligned(ptr); } \
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 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_LOAD_EXPAND_Q(typ, qtyp, prefix) \
inline qtyp vx_load_expand_q(const typ* ptr) { return prefix##_load_expand_q(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)
#define CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(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)
template<typename _Tp> struct V_RegTraits
{
};
@@ -417,6 +367,7 @@ template<typename _Tp> struct V_RegTraits
CV_DEF_REG_TRAITS(v512, v_int64x8, int64, s64, v_uint64x8, void, void, v_int64x8, void);
CV_DEF_REG_TRAITS(v512, v_float64x8, double, f64, v_float64x8, void, void, v_int64x8, v_int32x16);
#endif
//! @endcond
#if CV_SIMD512 && (!defined(CV__SIMD_FORCE_WIDTH) || CV__SIMD_FORCE_WIDTH == 512)
#define CV__SIMD_NAMESPACE simd512
@@ -425,21 +376,33 @@ namespace CV__SIMD_NAMESPACE {
#define CV_SIMD_64F CV_SIMD512_64F
#define CV_SIMD_FP16 CV_SIMD512_FP16
#define CV_SIMD_WIDTH 64
//! @addtogroup core_hal_intrin
//! @{
//! @brief Maximum available vector register capacity 8-bit unsigned integer values
typedef v_uint8x64 v_uint8;
//! @brief Maximum available vector register capacity 8-bit signed integer values
typedef v_int8x64 v_int8;
//! @brief Maximum available vector register capacity 16-bit unsigned integer values
typedef v_uint16x32 v_uint16;
//! @brief Maximum available vector register capacity 16-bit signed integer values
typedef v_int16x32 v_int16;
//! @brief Maximum available vector register capacity 32-bit unsigned integer values
typedef v_uint32x16 v_uint32;
//! @brief Maximum available vector register capacity 32-bit signed integer values
typedef v_int32x16 v_int32;
//! @brief Maximum available vector register capacity 64-bit unsigned integer values
typedef v_uint64x8 v_uint64;
//! @brief Maximum available vector register capacity 64-bit signed integer values
typedef v_int64x8 v_int64;
//! @brief Maximum available vector register capacity 32-bit floating point values (single precision)
typedef v_float32x16 v_float32;
CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v512)
#if CV_SIMD512_64F
#if CV_SIMD512_64F
//! @brief Maximum available vector register capacity 64-bit floating point values (double precision)
typedef v_float64x8 v_float64;
CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v512, load)
#endif
inline void vx_cleanup() { v512_cleanup(); }
#endif
//! @}
#define VXPREFIX(func) v512##func
} // namespace
using namespace CV__SIMD_NAMESPACE;
#elif CV_SIMD256 && (!defined(CV__SIMD_FORCE_WIDTH) || CV__SIMD_FORCE_WIDTH == 256)
@@ -449,21 +412,33 @@ namespace CV__SIMD_NAMESPACE {
#define CV_SIMD_64F CV_SIMD256_64F
#define CV_SIMD_FP16 CV_SIMD256_FP16
#define CV_SIMD_WIDTH 32
//! @addtogroup core_hal_intrin
//! @{
//! @brief Maximum available vector register capacity 8-bit unsigned integer values
typedef v_uint8x32 v_uint8;
//! @brief Maximum available vector register capacity 8-bit signed integer values
typedef v_int8x32 v_int8;
//! @brief Maximum available vector register capacity 16-bit unsigned integer values
typedef v_uint16x16 v_uint16;
//! @brief Maximum available vector register capacity 16-bit signed integer values
typedef v_int16x16 v_int16;
//! @brief Maximum available vector register capacity 32-bit unsigned integer values
typedef v_uint32x8 v_uint32;
//! @brief Maximum available vector register capacity 32-bit signed integer values
typedef v_int32x8 v_int32;
//! @brief Maximum available vector register capacity 64-bit unsigned integer values
typedef v_uint64x4 v_uint64;
//! @brief Maximum available vector register capacity 64-bit signed integer values
typedef v_int64x4 v_int64;
//! @brief Maximum available vector register capacity 32-bit floating point values (single precision)
typedef v_float32x8 v_float32;
CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v256)
#if CV_SIMD256_64F
//! @brief Maximum available vector register capacity 64-bit floating point values (double precision)
typedef v_float64x4 v_float64;
CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v256, load)
#endif
inline void vx_cleanup() { v256_cleanup(); }
//! @}
#define VXPREFIX(func) v256##func
} // namespace
using namespace CV__SIMD_NAMESPACE;
#elif (CV_SIMD128 || CV_SIMD128_CPP) && (!defined(CV__SIMD_FORCE_WIDTH) || CV__SIMD_FORCE_WIDTH == 128)
@@ -476,25 +451,228 @@ namespace CV__SIMD_NAMESPACE {
#define CV_SIMD CV_SIMD128
#define CV_SIMD_64F CV_SIMD128_64F
#define CV_SIMD_WIDTH 16
//! @addtogroup core_hal_intrin
//! @{
//! @brief Maximum available vector register capacity 8-bit unsigned integer values
typedef v_uint8x16 v_uint8;
//! @brief Maximum available vector register capacity 8-bit signed integer values
typedef v_int8x16 v_int8;
//! @brief Maximum available vector register capacity 16-bit unsigned integer values
typedef v_uint16x8 v_uint16;
//! @brief Maximum available vector register capacity 16-bit signed integer values
typedef v_int16x8 v_int16;
//! @brief Maximum available vector register capacity 32-bit unsigned integer values
typedef v_uint32x4 v_uint32;
//! @brief Maximum available vector register capacity 32-bit signed integer values
typedef v_int32x4 v_int32;
//! @brief Maximum available vector register capacity 64-bit unsigned integer values
typedef v_uint64x2 v_uint64;
//! @brief Maximum available vector register capacity 64-bit signed integer values
typedef v_int64x2 v_int64;
//! @brief Maximum available vector register capacity 32-bit floating point values (single precision)
typedef v_float32x4 v_float32;
CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v)
#if CV_SIMD128_64F
//! @brief Maximum available vector register capacity 64-bit floating point values (double precision)
typedef v_float64x2 v_float64;
CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v, load)
#endif
inline void vx_cleanup() { v_cleanup(); }
//! @}
#define VXPREFIX(func) v##func
} // namespace
using namespace CV__SIMD_NAMESPACE;
#endif
namespace CV__SIMD_NAMESPACE {
//! @addtogroup core_hal_intrin
//! @{
//! @name Wide init with value
//! @{
//! @brief Create maximum available capacity vector with elements set to a specific value
inline v_uint8 vx_setall_u8(uchar v) { return VXPREFIX(_setall_u8)(v); }
inline v_int8 vx_setall_s8(schar v) { return VXPREFIX(_setall_s8)(v); }
inline v_uint16 vx_setall_u16(ushort v) { return VXPREFIX(_setall_u16)(v); }
inline v_int16 vx_setall_s16(short v) { return VXPREFIX(_setall_s16)(v); }
inline v_int32 vx_setall_s32(int v) { return VXPREFIX(_setall_s32)(v); }
inline v_uint32 vx_setall_u32(unsigned v) { return VXPREFIX(_setall_u32)(v); }
inline v_float32 vx_setall_f32(float v) { return VXPREFIX(_setall_f32)(v); }
inline v_int64 vx_setall_s64(int64 v) { return VXPREFIX(_setall_s64)(v); }
inline v_uint64 vx_setall_u64(uint64 v) { return VXPREFIX(_setall_u64)(v); }
#if CV_SIMD_64F
inline v_float64 vx_setall_f64(double v) { return VXPREFIX(_setall_f64)(v); }
#endif
//! @}
//! @name Wide init with zero
//! @{
//! @brief Create maximum available capacity vector with elements set to zero
inline v_uint8 vx_setzero_u8() { return VXPREFIX(_setzero_u8)(); }
inline v_int8 vx_setzero_s8() { return VXPREFIX(_setzero_s8)(); }
inline v_uint16 vx_setzero_u16() { return VXPREFIX(_setzero_u16)(); }
inline v_int16 vx_setzero_s16() { return VXPREFIX(_setzero_s16)(); }
inline v_int32 vx_setzero_s32() { return VXPREFIX(_setzero_s32)(); }
inline v_uint32 vx_setzero_u32() { return VXPREFIX(_setzero_u32)(); }
inline v_float32 vx_setzero_f32() { return VXPREFIX(_setzero_f32)(); }
inline v_int64 vx_setzero_s64() { return VXPREFIX(_setzero_s64)(); }
inline v_uint64 vx_setzero_u64() { return VXPREFIX(_setzero_u64)(); }
#if CV_SIMD_64F
inline v_float64 vx_setzero_f64() { return VXPREFIX(_setzero_f64)(); }
#endif
//! @}
//! @name Wide load from memory
//! @{
//! @brief Load maximum available capacity register contents from memory
inline v_uint8 vx_load(const uchar * ptr) { return VXPREFIX(_load)(ptr); }
inline v_int8 vx_load(const schar * ptr) { return VXPREFIX(_load)(ptr); }
inline v_uint16 vx_load(const ushort * ptr) { return VXPREFIX(_load)(ptr); }
inline v_int16 vx_load(const short * ptr) { return VXPREFIX(_load)(ptr); }
inline v_int32 vx_load(const int * ptr) { return VXPREFIX(_load)(ptr); }
inline v_uint32 vx_load(const unsigned * ptr) { return VXPREFIX(_load)(ptr); }
inline v_float32 vx_load(const float * ptr) { return VXPREFIX(_load)(ptr); }
inline v_int64 vx_load(const int64 * ptr) { return VXPREFIX(_load)(ptr); }
inline v_uint64 vx_load(const uint64 * ptr) { return VXPREFIX(_load)(ptr); }
#if CV_SIMD_64F
inline v_float64 vx_load(const double * ptr) { return VXPREFIX(_load)(ptr); }
#endif
//! @}
//! @name Wide load from memory(aligned)
//! @{
//! @brief Load maximum available capacity register contents from memory(aligned)
inline v_uint8 vx_load_aligned(const uchar * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_int8 vx_load_aligned(const schar * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_uint16 vx_load_aligned(const ushort * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_int16 vx_load_aligned(const short * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_int32 vx_load_aligned(const int * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_uint32 vx_load_aligned(const unsigned * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_float32 vx_load_aligned(const float * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_int64 vx_load_aligned(const int64 * ptr) { return VXPREFIX(_load_aligned)(ptr); }
inline v_uint64 vx_load_aligned(const uint64 * ptr) { return VXPREFIX(_load_aligned)(ptr); }
#if CV_SIMD_64F
inline v_float64 vx_load_aligned(const double * ptr) { return VXPREFIX(_load_aligned)(ptr); }
#endif
//! @}
//! @name Wide load lower half from memory
//! @{
//! @brief Load lower half of maximum available capacity register from memory
inline v_uint8 vx_load_low(const uchar * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_int8 vx_load_low(const schar * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_uint16 vx_load_low(const ushort * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_int16 vx_load_low(const short * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_int32 vx_load_low(const int * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_uint32 vx_load_low(const unsigned * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_float32 vx_load_low(const float * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_int64 vx_load_low(const int64 * ptr) { return VXPREFIX(_load_low)(ptr); }
inline v_uint64 vx_load_low(const uint64 * ptr) { return VXPREFIX(_load_low)(ptr); }
#if CV_SIMD_64F
inline v_float64 vx_load_low(const double * ptr) { return VXPREFIX(_load_low)(ptr); }
#endif
//! @}
//! @name Wide load halfs from memory
//! @{
//! @brief Load maximum available capacity register contents from two memory blocks
inline v_uint8 vx_load_halves(const uchar * ptr0, const uchar * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_int8 vx_load_halves(const schar * ptr0, const schar * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_uint16 vx_load_halves(const ushort * ptr0, const ushort * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_int16 vx_load_halves(const short * ptr0, const short * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_int32 vx_load_halves(const int * ptr0, const int * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_uint32 vx_load_halves(const unsigned * ptr0, const unsigned * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_float32 vx_load_halves(const float * ptr0, const float * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_int64 vx_load_halves(const int64 * ptr0, const int64 * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
inline v_uint64 vx_load_halves(const uint64 * ptr0, const uint64 * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
#if CV_SIMD_64F
inline v_float64 vx_load_halves(const double * ptr0, const double * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); }
#endif
//! @}
//! @name Wide LUT of elements
//! @{
//! @brief Load maximum available capacity register contents with array elements by provided indexes
inline v_uint8 vx_lut(const uchar * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_int8 vx_lut(const schar * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_uint16 vx_lut(const ushort * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_int16 vx_lut(const short* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_int32 vx_lut(const int* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_uint32 vx_lut(const unsigned* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_float32 vx_lut(const float* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_int64 vx_lut(const int64 * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
inline v_uint64 vx_lut(const uint64 * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
#if CV_SIMD_64F
inline v_float64 vx_lut(const double* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); }
#endif
//! @}
//! @name Wide LUT of element pairs
//! @{
//! @brief Load maximum available capacity register contents with array element pairs by provided indexes
inline v_uint8 vx_lut_pairs(const uchar * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_int8 vx_lut_pairs(const schar * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_uint16 vx_lut_pairs(const ushort * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_int16 vx_lut_pairs(const short* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_int32 vx_lut_pairs(const int* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_uint32 vx_lut_pairs(const unsigned* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_float32 vx_lut_pairs(const float* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_int64 vx_lut_pairs(const int64 * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
inline v_uint64 vx_lut_pairs(const uint64 * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
#if CV_SIMD_64F
inline v_float64 vx_lut_pairs(const double* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); }
#endif
//! @}
//! @name Wide LUT of element quads
//! @{
//! @brief Load maximum available capacity register contents with array element quads by provided indexes
inline v_uint8 vx_lut_quads(const uchar* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
inline v_int8 vx_lut_quads(const schar* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
inline v_uint16 vx_lut_quads(const ushort* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
inline v_int16 vx_lut_quads(const short* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
inline v_int32 vx_lut_quads(const int* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
inline v_uint32 vx_lut_quads(const unsigned* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
inline v_float32 vx_lut_quads(const float* ptr, const int* idx) { return VXPREFIX(_lut_quads)(ptr, idx); }
//! @}
//! @name Wide load with double expansion
//! @{
//! @brief Load maximum available capacity register contents from memory with double expand
inline v_uint16 vx_load_expand(const uchar * ptr) { return VXPREFIX(_load_expand)(ptr); }
inline v_int16 vx_load_expand(const schar * ptr) { return VXPREFIX(_load_expand)(ptr); }
inline v_uint32 vx_load_expand(const ushort * ptr) { return VXPREFIX(_load_expand)(ptr); }
inline v_int32 vx_load_expand(const short* ptr) { return VXPREFIX(_load_expand)(ptr); }
inline v_int64 vx_load_expand(const int* ptr) { return VXPREFIX(_load_expand)(ptr); }
inline v_uint64 vx_load_expand(const unsigned* ptr) { return VXPREFIX(_load_expand)(ptr); }
inline v_float32 vx_load_expand(const float16_t * ptr) { return VXPREFIX(_load_expand)(ptr); }
//! @}
//! @name Wide load with quad expansion
//! @{
//! @brief Load maximum available capacity register contents from memory with quad expand
inline v_uint32 vx_load_expand_q(const uchar * ptr) { return VXPREFIX(_load_expand_q)(ptr); }
inline v_int32 vx_load_expand_q(const schar * ptr) { return VXPREFIX(_load_expand_q)(ptr); }
//! @}
/** @brief SIMD processing state cleanup call */
inline void vx_cleanup() { VXPREFIX(_cleanup)(); }
//! @cond IGNORED
// backward compatibility
template<typename _Tp, typename _Tvec> static inline
void vx_store(_Tp* dst, const _Tvec& v) { return v_store(dst, v); }
// backward compatibility
template<typename _Tp, typename _Tvec> static inline
void vx_store_aligned(_Tp* dst, const _Tvec& v) { return v_store_aligned(dst, v); }
//! @endcond
//! @}
#undef VXPREFIX
} // namespace
//! @cond IGNORED
#ifndef CV_SIMD_64F
#define CV_SIMD_64F 0
#endif
File diff suppressed because it is too large Load Diff
@@ -538,49 +538,81 @@ inline void v_mul_expand(const v_int8x16& a, const v_int8x16& b,
v_int16x8& c, v_int16x8& d)
{
c.val = vmull_s8(vget_low_s8(a.val), vget_low_s8(b.val));
#if CV_NEON_AARCH64
d.val = vmull_high_s8(a.val, b.val);
#else // #if CV_NEON_AARCH64
d.val = vmull_s8(vget_high_s8(a.val), vget_high_s8(b.val));
#endif // #if CV_NEON_AARCH64
}
inline void v_mul_expand(const v_uint8x16& a, const v_uint8x16& b,
v_uint16x8& c, v_uint16x8& d)
{
c.val = vmull_u8(vget_low_u8(a.val), vget_low_u8(b.val));
#if CV_NEON_AARCH64
d.val = vmull_high_u8(a.val, b.val);
#else // #if CV_NEON_AARCH64
d.val = vmull_u8(vget_high_u8(a.val), vget_high_u8(b.val));
#endif // #if CV_NEON_AARCH64
}
inline void v_mul_expand(const v_int16x8& a, const v_int16x8& b,
v_int32x4& c, v_int32x4& d)
{
c.val = vmull_s16(vget_low_s16(a.val), vget_low_s16(b.val));
#if CV_NEON_AARCH64
d.val = vmull_high_s16(a.val, b.val);
#else // #if CV_NEON_AARCH64
d.val = vmull_s16(vget_high_s16(a.val), vget_high_s16(b.val));
#endif // #if CV_NEON_AARCH64
}
inline void v_mul_expand(const v_uint16x8& a, const v_uint16x8& b,
v_uint32x4& c, v_uint32x4& d)
{
c.val = vmull_u16(vget_low_u16(a.val), vget_low_u16(b.val));
#if CV_NEON_AARCH64
d.val = vmull_high_u16(a.val, b.val);
#else // #if CV_NEON_AARCH64
d.val = vmull_u16(vget_high_u16(a.val), vget_high_u16(b.val));
#endif // #if CV_NEON_AARCH64
}
inline void v_mul_expand(const v_uint32x4& a, const v_uint32x4& b,
v_uint64x2& c, v_uint64x2& d)
{
c.val = vmull_u32(vget_low_u32(a.val), vget_low_u32(b.val));
#if CV_NEON_AARCH64
d.val = vmull_high_u32(a.val, b.val);
#else // #if CV_NEON_AARCH64
d.val = vmull_u32(vget_high_u32(a.val), vget_high_u32(b.val));
#endif // #if CV_NEON_AARCH64
}
inline v_int16x8 v_mul_hi(const v_int16x8& a, const v_int16x8& b)
{
return v_int16x8(vcombine_s16(
vshrn_n_s32(vmull_s16( vget_low_s16(a.val), vget_low_s16(b.val)), 16),
vshrn_n_s32(vmull_s16(vget_high_s16(a.val), vget_high_s16(b.val)), 16)
vshrn_n_s32(
#if CV_NEON_AARCH64
vmull_high_s16(a.val, b.val)
#else // #if CV_NEON_AARCH64
vmull_s16(vget_high_s16(a.val), vget_high_s16(b.val))
#endif // #if CV_NEON_AARCH64
, 16)
));
}
inline v_uint16x8 v_mul_hi(const v_uint16x8& a, const v_uint16x8& b)
{
return v_uint16x8(vcombine_u16(
vshrn_n_u32(vmull_u16( vget_low_u16(a.val), vget_low_u16(b.val)), 16),
vshrn_n_u32(vmull_u16(vget_high_u16(a.val), vget_high_u16(b.val)), 16)
vshrn_n_u32(
#if CV_NEON_AARCH64
vmull_high_u16(a.val, b.val)
#else // #if CV_NEON_AARCH64
vmull_u16(vget_high_u16(a.val), vget_high_u16(b.val))
#endif // #if CV_NEON_AARCH64
, 16)
));
}
@@ -1254,29 +1286,56 @@ OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_float64x2, double, f64)
inline unsigned v_reduce_sum(const v_uint8x16& a)
{
#if CV_NEON_AARCH64
uint16_t t0 = vaddlvq_u8(a.val);
return t0;
#else // #if CV_NEON_AARCH64
uint32x4_t t0 = vpaddlq_u16(vpaddlq_u8(a.val));
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
return vget_lane_u32(vpadd_u32(t1, t1), 0);
#endif // #if CV_NEON_AARCH64
}
inline int v_reduce_sum(const v_int8x16& a)
{
#if CV_NEON_AARCH64
int16_t t0 = vaddlvq_s8(a.val);
return t0;
#else // #if CV_NEON_AARCH64
int32x4_t t0 = vpaddlq_s16(vpaddlq_s8(a.val));
int32x2_t t1 = vpadd_s32(vget_low_s32(t0), vget_high_s32(t0));
return vget_lane_s32(vpadd_s32(t1, t1), 0);
#endif // #if CV_NEON_AARCH64
}
inline unsigned v_reduce_sum(const v_uint16x8& a)
{
#if CV_NEON_AARCH64
uint32_t t0 = vaddlvq_u16(a.val);
return t0;
#else // #if CV_NEON_AARCH64
uint32x4_t t0 = vpaddlq_u16(a.val);
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
return vget_lane_u32(vpadd_u32(t1, t1), 0);
#endif // #if CV_NEON_AARCH64
}
inline int v_reduce_sum(const v_int16x8& a)
{
#if CV_NEON_AARCH64
int32_t t0 = vaddlvq_s16(a.val);
return t0;
#else // #if CV_NEON_AARCH64
int32x4_t t0 = vpaddlq_s16(a.val);
int32x2_t t1 = vpadd_s32(vget_low_s32(t0), vget_high_s32(t0));
return vget_lane_s32(vpadd_s32(t1, t1), 0);
#endif // #if CV_NEON_AARCH64
}
#if CV_NEON_AARCH64
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
inline scalartype v_reduce_##func(const _Tpvec& a) \
{ \
return v##vectorfunc##vq_##suffix(a.val); \
}
#else // #if CV_NEON_AARCH64
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
inline scalartype v_reduce_##func(const _Tpvec& a) \
{ \
@@ -1285,12 +1344,20 @@ inline scalartype v_reduce_##func(const _Tpvec& a) \
a0 = vp##vectorfunc##_##suffix(a0, a0); \
return (scalartype)vget_lane_##suffix(vp##vectorfunc##_##suffix(a0, a0),0); \
}
#endif // #if CV_NEON_AARCH64
OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(v_uint8x16, uint8x8, uchar, max, max, u8)
OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(v_uint8x16, uint8x8, uchar, min, min, u8)
OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(v_int8x16, int8x8, schar, max, max, s8)
OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(v_int8x16, int8x8, schar, min, min, s8)
#if CV_NEON_AARCH64
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
inline scalartype v_reduce_##func(const _Tpvec& a) \
{ \
return v##vectorfunc##vq_##suffix(a.val); \
}
#else // #if CV_NEON_AARCH64
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
inline scalartype v_reduce_##func(const _Tpvec& a) \
{ \
@@ -1298,18 +1365,27 @@ inline scalartype v_reduce_##func(const _Tpvec& a) \
a0 = vp##vectorfunc##_##suffix(a0, a0); \
return (scalartype)vget_lane_##suffix(vp##vectorfunc##_##suffix(a0, a0),0); \
}
#endif // #if CV_NEON_AARCH64
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_uint16x8, uint16x4, ushort, max, max, u16)
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_uint16x8, uint16x4, ushort, min, min, u16)
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_int16x8, int16x4, short, max, max, s16)
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_int16x8, int16x4, short, min, min, s16)
#if CV_NEON_AARCH64
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
inline scalartype v_reduce_##func(const _Tpvec& a) \
{ \
return v##vectorfunc##vq_##suffix(a.val); \
}
#else // #if CV_NEON_AARCH64
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
inline scalartype v_reduce_##func(const _Tpvec& a) \
{ \
_Tpnvec##_t a0 = vp##vectorfunc##_##suffix(vget_low_##suffix(a.val), vget_high_##suffix(a.val)); \
return (scalartype)vget_lane_##suffix(vp##vectorfunc##_##suffix(a0, vget_high_##suffix(a.val)),0); \
}
#endif // #if CV_NEON_AARCH64
OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_uint32x4, uint32x2, unsigned, sum, add, u32)
OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_uint32x4, uint32x2, unsigned, max, max, u32)
@@ -1322,9 +1398,21 @@ OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_float32x4, float32x2, float, max, max, f32)
OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_float32x4, float32x2, float, min, min, f32)
inline uint64 v_reduce_sum(const v_uint64x2& a)
{ return vget_lane_u64(vadd_u64(vget_low_u64(a.val), vget_high_u64(a.val)),0); }
{
#if CV_NEON_AARCH64
return vaddvq_u64(a.val);
#else // #if CV_NEON_AARCH64
return vget_lane_u64(vadd_u64(vget_low_u64(a.val), vget_high_u64(a.val)),0);
#endif // #if CV_NEON_AARCH64
}
inline int64 v_reduce_sum(const v_int64x2& a)
{ return vget_lane_s64(vadd_s64(vget_low_s64(a.val), vget_high_s64(a.val)),0); }
{
#if CV_NEON_AARCH64
return vaddvq_s64(a.val);
#else // #if CV_NEON_AARCH64
return vget_lane_s64(vadd_s64(vget_low_s64(a.val), vget_high_s64(a.val)),0);
#endif // #if CV_NEON_AARCH64
}
#if CV_SIMD128_64F
inline double v_reduce_sum(const v_float64x2& a)
{
@@ -1335,6 +1423,11 @@ inline double v_reduce_sum(const v_float64x2& a)
inline v_float32x4 v_reduce_sum4(const v_float32x4& a, const v_float32x4& b,
const v_float32x4& c, const v_float32x4& d)
{
#if CV_NEON_AARCH64
float32x4_t ab = vpaddq_f32(a.val, b.val); // a0+a1 a2+a3 b0+b1 b2+b3
float32x4_t cd = vpaddq_f32(c.val, d.val); // c0+c1 d0+d1 c2+c3 d2+d3
return v_float32x4(vpaddq_f32(ab, cd)); // sumA sumB sumC sumD
#else // #if CV_NEON_AARCH64
float32x4x2_t ab = vtrnq_f32(a.val, b.val);
float32x4x2_t cd = vtrnq_f32(c.val, d.val);
@@ -1345,49 +1438,91 @@ inline v_float32x4 v_reduce_sum4(const v_float32x4& a, const v_float32x4& b,
float32x4_t v1 = vcombine_f32(vget_high_f32(u0), vget_high_f32(u1));
return v_float32x4(vaddq_f32(v0, v1));
#endif // #if CV_NEON_AARCH64
}
inline unsigned v_reduce_sad(const v_uint8x16& a, const v_uint8x16& b)
{
#if CV_NEON_AARCH64
uint8x16_t t0 = vabdq_u8(a.val, b.val);
uint16_t t1 = vaddlvq_u8(t0);
return t1;
#else // #if CV_NEON_AARCH64
uint32x4_t t0 = vpaddlq_u16(vpaddlq_u8(vabdq_u8(a.val, b.val)));
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
return vget_lane_u32(vpadd_u32(t1, t1), 0);
#endif // #if CV_NEON_AARCH64
}
inline unsigned v_reduce_sad(const v_int8x16& a, const v_int8x16& b)
{
#if CV_NEON_AARCH64
uint8x16_t t0 = vreinterpretq_u8_s8(vabdq_s8(a.val, b.val));
uint16_t t1 = vaddlvq_u8(t0);
return t1;
#else // #if CV_NEON_AARCH64
uint32x4_t t0 = vpaddlq_u16(vpaddlq_u8(vreinterpretq_u8_s8(vabdq_s8(a.val, b.val))));
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
return vget_lane_u32(vpadd_u32(t1, t1), 0);
#endif // #if CV_NEON_AARCH64
}
inline unsigned v_reduce_sad(const v_uint16x8& a, const v_uint16x8& b)
{
#if CV_NEON_AARCH64
uint16x8_t t0 = vabdq_u16(a.val, b.val);
uint32_t t1 = vaddlvq_u16(t0);
return t1;
#else // #if CV_NEON_AARCH64
uint32x4_t t0 = vpaddlq_u16(vabdq_u16(a.val, b.val));
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
return vget_lane_u32(vpadd_u32(t1, t1), 0);
#endif // #if CV_NEON_AARCH64
}
inline unsigned v_reduce_sad(const v_int16x8& a, const v_int16x8& b)
{
#if CV_NEON_AARCH64
uint16x8_t t0 = vreinterpretq_u16_s16(vabdq_s16(a.val, b.val));
uint32_t t1 = vaddlvq_u16(t0);
return t1;
#else // #if CV_NEON_AARCH64
uint32x4_t t0 = vpaddlq_u16(vreinterpretq_u16_s16(vabdq_s16(a.val, b.val)));
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
return vget_lane_u32(vpadd_u32(t1, t1), 0);
#endif // #if CV_NEON_AARCH64
}
inline unsigned v_reduce_sad(const v_uint32x4& a, const v_uint32x4& b)
{
#if CV_NEON_AARCH64
uint32x4_t t0 = vabdq_u32(a.val, b.val);
uint32_t t1 = vaddvq_u32(t0);
return t1;
#else // #if CV_NEON_AARCH64
uint32x4_t t0 = vabdq_u32(a.val, b.val);
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
return vget_lane_u32(vpadd_u32(t1, t1), 0);
#endif // #if CV_NEON_AARCH64
}
inline unsigned v_reduce_sad(const v_int32x4& a, const v_int32x4& b)
{
#if CV_NEON_AARCH64
uint32x4_t t0 = vreinterpretq_u32_s32(vabdq_s32(a.val, b.val));
uint32_t t1 = vaddvq_u32(t0);
return t1;
#else // #if CV_NEON_AARCH64
uint32x4_t t0 = vreinterpretq_u32_s32(vabdq_s32(a.val, b.val));
uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0));
return vget_lane_u32(vpadd_u32(t1, t1), 0);
#endif // #if CV_NEON_AARCH64
}
inline float v_reduce_sad(const v_float32x4& a, const v_float32x4& b)
{
#if CV_NEON_AARCH64
float32x4_t t0 = vabdq_f32(a.val, b.val);
return vaddvq_f32(t0);
#else // #if CV_NEON_AARCH64
float32x4_t t0 = vabdq_f32(a.val, b.val);
float32x2_t t1 = vpadd_f32(vget_low_f32(t0), vget_high_f32(t0));
return vget_lane_f32(vpadd_f32(t1, t1), 0);
#endif // #if CV_NEON_AARCH64
}
inline v_uint8x16 v_popcount(const v_uint8x16& a)
@@ -1409,30 +1544,54 @@ inline v_uint64x2 v_popcount(const v_int64x2& a)
inline int v_signmask(const v_uint8x16& a)
{
#if CV_NEON_AARCH64
const int8x16_t signPosition = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7};
const uint8x16_t byteOrder = {0,8,1,9,2,10,3,11,4,12,5,13,6,14,7,15};
uint8x16_t v0 = vshlq_u8(vshrq_n_u8(a.val, 7), signPosition);
uint8x16_t v1 = vqtbl1q_u8(v0, byteOrder);
uint32_t t0 = vaddlvq_u16(vreinterpretq_u16_u8(v1));
return t0;
#else // #if CV_NEON_AARCH64
int8x8_t m0 = vcreate_s8(CV_BIG_UINT(0x0706050403020100));
uint8x16_t v0 = vshlq_u8(vshrq_n_u8(a.val, 7), vcombine_s8(m0, m0));
uint64x2_t v1 = vpaddlq_u32(vpaddlq_u16(vpaddlq_u8(v0)));
return (int)vgetq_lane_u64(v1, 0) + ((int)vgetq_lane_u64(v1, 1) << 8);
#endif // #if CV_NEON_AARCH64
}
inline int v_signmask(const v_int8x16& a)
{ return v_signmask(v_reinterpret_as_u8(a)); }
inline int v_signmask(const v_uint16x8& a)
{
#if CV_NEON_AARCH64
const int16x8_t signPosition = {0,1,2,3,4,5,6,7};
uint16x8_t v0 = vshlq_u16(vshrq_n_u16(a.val, 15), signPosition);
uint32_t t0 = vaddlvq_u16(v0);
return t0;
#else // #if CV_NEON_AARCH64
int16x4_t m0 = vcreate_s16(CV_BIG_UINT(0x0003000200010000));
uint16x8_t v0 = vshlq_u16(vshrq_n_u16(a.val, 15), vcombine_s16(m0, m0));
uint64x2_t v1 = vpaddlq_u32(vpaddlq_u16(v0));
return (int)vgetq_lane_u64(v1, 0) + ((int)vgetq_lane_u64(v1, 1) << 4);
#endif // #if CV_NEON_AARCH64
}
inline int v_signmask(const v_int16x8& a)
{ return v_signmask(v_reinterpret_as_u16(a)); }
inline int v_signmask(const v_uint32x4& a)
{
#if CV_NEON_AARCH64
const int32x4_t signPosition = {0,1,2,3};
uint32x4_t v0 = vshlq_u32(vshrq_n_u32(a.val, 31), signPosition);
uint32_t t0 = vaddvq_u32(v0);
return t0;
#else // #if CV_NEON_AARCH64
int32x2_t m0 = vcreate_s32(CV_BIG_UINT(0x0000000100000000));
uint32x4_t v0 = vshlq_u32(vshrq_n_u32(a.val, 31), vcombine_s32(m0, m0));
uint64x2_t v1 = vpaddlq_u32(v0);
return (int)vgetq_lane_u64(v1, 0) + ((int)vgetq_lane_u64(v1, 1) << 2);
#endif // #if CV_NEON_AARCH64
}
inline int v_signmask(const v_int32x4& a)
{ return v_signmask(v_reinterpret_as_u32(a)); }
@@ -1440,9 +1599,16 @@ inline int v_signmask(const v_float32x4& a)
{ return v_signmask(v_reinterpret_as_u32(a)); }
inline int v_signmask(const v_uint64x2& a)
{
#if CV_NEON_AARCH64
const int64x2_t signPosition = {0,1};
uint64x2_t v0 = vshlq_u64(vshrq_n_u64(a.val, 63), signPosition);
uint64_t t0 = vaddvq_u64(v0);
return t0;
#else // #if CV_NEON_AARCH64
int64x1_t m0 = vdup_n_s64(0);
uint64x2_t v0 = vshlq_u64(vshrq_n_u64(a.val, 63), vcombine_s64(m0, m0));
return (int)vgetq_lane_u64(v0, 0) + ((int)vgetq_lane_u64(v0, 1) << 1);
#endif // #if CV_NEON_AARCH64
}
inline int v_signmask(const v_int64x2& a)
{ return v_signmask(v_reinterpret_as_u64(a)); }
@@ -1464,19 +1630,31 @@ inline int v_scan_forward(const v_uint64x2& a) { return trailingZeros32(v_signma
inline int v_scan_forward(const v_float64x2& a) { return trailingZeros32(v_signmask(a)); }
#endif
#define OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(_Tpvec, suffix, shift) \
inline bool v_check_all(const v_##_Tpvec& a) \
{ \
_Tpvec##_t v0 = vshrq_n_##suffix(vmvnq_##suffix(a.val), shift); \
uint64x2_t v1 = vreinterpretq_u64_##suffix(v0); \
return (vgetq_lane_u64(v1, 0) | vgetq_lane_u64(v1, 1)) == 0; \
} \
inline bool v_check_any(const v_##_Tpvec& a) \
{ \
_Tpvec##_t v0 = vshrq_n_##suffix(a.val, shift); \
uint64x2_t v1 = vreinterpretq_u64_##suffix(v0); \
return (vgetq_lane_u64(v1, 0) | vgetq_lane_u64(v1, 1)) != 0; \
}
#if CV_NEON_AARCH64
#define OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(_Tpvec, suffix, shift) \
inline bool v_check_all(const v_##_Tpvec& a) \
{ \
return (vminvq_##suffix(a.val) >> shift) != 0; \
} \
inline bool v_check_any(const v_##_Tpvec& a) \
{ \
return (vmaxvq_##suffix(a.val) >> shift) != 0; \
}
#else // #if CV_NEON_AARCH64
#define OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(_Tpvec, suffix, shift) \
inline bool v_check_all(const v_##_Tpvec& a) \
{ \
_Tpvec##_t v0 = vshrq_n_##suffix(vmvnq_##suffix(a.val), shift); \
uint64x2_t v1 = vreinterpretq_u64_##suffix(v0); \
return (vgetq_lane_u64(v1, 0) | vgetq_lane_u64(v1, 1)) == 0; \
} \
inline bool v_check_any(const v_##_Tpvec& a) \
{ \
_Tpvec##_t v0 = vshrq_n_##suffix(a.val, shift); \
uint64x2_t v1 = vreinterpretq_u64_##suffix(v0); \
return (vgetq_lane_u64(v1, 0) | vgetq_lane_u64(v1, 1)) != 0; \
}
#endif // #if CV_NEON_AARCH64
OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint8x16, u8, 7)
OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint16x8, u16, 15)
@@ -1539,6 +1717,26 @@ OPENCV_HAL_IMPL_NEON_SELECT(v_float32x4, f32, u32)
OPENCV_HAL_IMPL_NEON_SELECT(v_float64x2, f64, u64)
#endif
#if CV_NEON_AARCH64
#define OPENCV_HAL_IMPL_NEON_EXPAND(_Tpvec, _Tpwvec, _Tp, suffix) \
inline void v_expand(const _Tpvec& a, _Tpwvec& b0, _Tpwvec& b1) \
{ \
b0.val = vmovl_##suffix(vget_low_##suffix(a.val)); \
b1.val = vmovl_high_##suffix(a.val); \
} \
inline _Tpwvec v_expand_low(const _Tpvec& a) \
{ \
return _Tpwvec(vmovl_##suffix(vget_low_##suffix(a.val))); \
} \
inline _Tpwvec v_expand_high(const _Tpvec& a) \
{ \
return _Tpwvec(vmovl_high_##suffix(a.val)); \
} \
inline _Tpwvec v_load_expand(const _Tp* ptr) \
{ \
return _Tpwvec(vmovl_##suffix(vld1_##suffix(ptr))); \
}
#else
#define OPENCV_HAL_IMPL_NEON_EXPAND(_Tpvec, _Tpwvec, _Tp, suffix) \
inline void v_expand(const _Tpvec& a, _Tpwvec& b0, _Tpwvec& b1) \
{ \
@@ -1557,6 +1755,7 @@ inline _Tpwvec v_load_expand(const _Tp* ptr) \
{ \
return _Tpwvec(vmovl_##suffix(vld1_##suffix(ptr))); \
}
#endif
OPENCV_HAL_IMPL_NEON_EXPAND(v_uint8x16, v_uint16x8, uchar, u8)
OPENCV_HAL_IMPL_NEON_EXPAND(v_int8x16, v_int16x8, schar, s8)
@@ -1808,6 +2007,37 @@ inline v_int32x4 v_trunc(const v_float64x2& a)
}
#endif
#if CV_NEON_AARCH64
#define OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(_Tpvec, suffix) \
inline void v_transpose4x4(const v_##_Tpvec& a0, const v_##_Tpvec& a1, \
const v_##_Tpvec& a2, const v_##_Tpvec& a3, \
v_##_Tpvec& b0, v_##_Tpvec& b1, \
v_##_Tpvec& b2, v_##_Tpvec& b3) \
{ \
/* -- Pass 1: 64b transpose */ \
_Tpvec##_t t0 = vreinterpretq_##suffix##32_##suffix##64( \
vtrn1q_##suffix##64(vreinterpretq_##suffix##64_##suffix##32(a0.val), \
vreinterpretq_##suffix##64_##suffix##32(a2.val))); \
_Tpvec##_t t1 = vreinterpretq_##suffix##32_##suffix##64( \
vtrn1q_##suffix##64(vreinterpretq_##suffix##64_##suffix##32(a1.val), \
vreinterpretq_##suffix##64_##suffix##32(a3.val))); \
_Tpvec##_t t2 = vreinterpretq_##suffix##32_##suffix##64( \
vtrn2q_##suffix##64(vreinterpretq_##suffix##64_##suffix##32(a0.val), \
vreinterpretq_##suffix##64_##suffix##32(a2.val))); \
_Tpvec##_t t3 = vreinterpretq_##suffix##32_##suffix##64( \
vtrn2q_##suffix##64(vreinterpretq_##suffix##64_##suffix##32(a1.val), \
vreinterpretq_##suffix##64_##suffix##32(a3.val))); \
/* -- Pass 2: 32b transpose */ \
b0.val = vtrn1q_##suffix##32(t0, t1); \
b1.val = vtrn2q_##suffix##32(t0, t1); \
b2.val = vtrn1q_##suffix##32(t2, t3); \
b3.val = vtrn2q_##suffix##32(t2, t3); \
}
OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(uint32x4, u)
OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(int32x4, s)
OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(float32x4, f)
#else // #if CV_NEON_AARCH64
#define OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(_Tpvec, suffix) \
inline void v_transpose4x4(const v_##_Tpvec& a0, const v_##_Tpvec& a1, \
const v_##_Tpvec& a2, const v_##_Tpvec& a3, \
@@ -1833,6 +2063,7 @@ inline void v_transpose4x4(const v_##_Tpvec& a0, const v_##_Tpvec& a1, \
OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(uint32x4, u32)
OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(int32x4, s32)
OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(float32x4, f32)
#endif // #if CV_NEON_AARCH64
#define OPENCV_HAL_IMPL_NEON_INTERLEAVED(_Tpvec, _Tp, suffix) \
inline void v_load_deinterleave(const _Tp* ptr, v_##_Tpvec& a, v_##_Tpvec& b) \
+12 -12
View File
@@ -583,24 +583,24 @@ struct CV_EXPORTS UMatData
struct CV_EXPORTS MatSize
{
explicit MatSize(int* _p);
int dims() const;
explicit MatSize(int* _p) CV_NOEXCEPT;
int dims() const CV_NOEXCEPT;
Size operator()() const;
const int& operator[](int i) const;
int& operator[](int i);
operator const int*() const; // TODO OpenCV 4.0: drop this
bool operator == (const MatSize& sz) const;
bool operator != (const MatSize& sz) const;
operator const int*() const CV_NOEXCEPT; // TODO OpenCV 4.0: drop this
bool operator == (const MatSize& sz) const CV_NOEXCEPT;
bool operator != (const MatSize& sz) const CV_NOEXCEPT;
int* p;
};
struct CV_EXPORTS MatStep
{
MatStep();
explicit MatStep(size_t s);
const size_t& operator[](int i) const;
size_t& operator[](int i);
MatStep() CV_NOEXCEPT;
explicit MatStep(size_t s) CV_NOEXCEPT;
const size_t& operator[](int i) const CV_NOEXCEPT;
size_t& operator[](int i) CV_NOEXCEPT;
operator size_t() const;
MatStep& operator = (size_t s);
@@ -819,7 +819,7 @@ public:
The constructed matrix can further be assigned to another matrix or matrix expression or can be
allocated with Mat::create . In the former case, the old content is de-referenced.
*/
Mat();
Mat() CV_NOEXCEPT;
/** @overload
@param rows Number of rows in a 2D array.
@@ -2220,7 +2220,7 @@ public:
typedef MatConstIterator_<_Tp> const_iterator;
//! default constructor
Mat_();
Mat_() CV_NOEXCEPT;
//! equivalent to Mat(_rows, _cols, DataType<_Tp>::type)
Mat_(int _rows, int _cols);
//! constructor that sets each matrix element to specified value
@@ -2420,7 +2420,7 @@ class CV_EXPORTS UMat
{
public:
//! default constructor
UMat(UMatUsageFlags usageFlags = USAGE_DEFAULT);
UMat(UMatUsageFlags usageFlags = USAGE_DEFAULT) CV_NOEXCEPT;
//! constructs 2D matrix of the specified size and type
// (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
UMat(int rows, int cols, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
+36 -9
View File
@@ -898,6 +898,33 @@ const _Tp* Mat::ptr(const int* idx) const
return (const _Tp*)p;
}
template<int n> inline
uchar* Mat::ptr(const Vec<int, n>& idx)
{
return Mat::ptr(idx.val);
}
template<int n> inline
const uchar* Mat::ptr(const Vec<int, n>& idx) const
{
return Mat::ptr(idx.val);
}
template<typename _Tp, int n> inline
_Tp* Mat::ptr(const Vec<int, n>& idx)
{
CV_DbgAssert( elemSize() == sizeof(_Tp) );
return Mat::ptr<_Tp>(idx.val);
}
template<typename _Tp, int n> inline
const _Tp* Mat::ptr(const Vec<int, n>& idx) const
{
CV_DbgAssert( elemSize() == sizeof(_Tp) );
return Mat::ptr<_Tp>(idx.val);
}
template<typename _Tp> inline
_Tp& Mat::at(int i0, int i1)
{
@@ -1218,11 +1245,11 @@ Mat& Mat::operator = (Mat&& m)
///////////////////////////// MatSize ////////////////////////////
inline
MatSize::MatSize(int* _p)
MatSize::MatSize(int* _p) CV_NOEXCEPT
: p(_p) {}
inline
int MatSize::dims() const
int MatSize::dims() const CV_NOEXCEPT
{
return (p - 1)[0];
}
@@ -1255,13 +1282,13 @@ int& MatSize::operator[](int i)
}
inline
MatSize::operator const int*() const
MatSize::operator const int*() const CV_NOEXCEPT
{
return p;
}
inline
bool MatSize::operator != (const MatSize& sz) const
bool MatSize::operator != (const MatSize& sz) const CV_NOEXCEPT
{
return !(*this == sz);
}
@@ -1271,25 +1298,25 @@ bool MatSize::operator != (const MatSize& sz) const
///////////////////////////// MatStep ////////////////////////////
inline
MatStep::MatStep()
MatStep::MatStep() CV_NOEXCEPT
{
p = buf; p[0] = p[1] = 0;
}
inline
MatStep::MatStep(size_t s)
MatStep::MatStep(size_t s) CV_NOEXCEPT
{
p = buf; p[0] = s; p[1] = 0;
}
inline
const size_t& MatStep::operator[](int i) const
const size_t& MatStep::operator[](int i) const CV_NOEXCEPT
{
return p[i];
}
inline
size_t& MatStep::operator[](int i)
size_t& MatStep::operator[](int i) CV_NOEXCEPT
{
return p[i];
}
@@ -1312,7 +1339,7 @@ inline MatStep& MatStep::operator = (size_t s)
////////////////////////////// Mat_<_Tp> ////////////////////////////
template<typename _Tp> inline
Mat_<_Tp>::Mat_()
Mat_<_Tp>::Mat_() CV_NOEXCEPT
: Mat()
{
flags = (flags & ~CV_MAT_TYPE_MASK) | traits::Type<_Tp>::value;
+13 -13
View File
@@ -702,24 +702,24 @@ public:
//! the default constructor
CV_WRAP KeyPoint();
/**
@param _pt x & y coordinates of the keypoint
@param _size keypoint diameter
@param _angle keypoint orientation
@param _response keypoint detector response on the keypoint (that is, strength of the keypoint)
@param _octave pyramid octave in which the keypoint has been detected
@param _class_id object id
@param pt x & y coordinates of the keypoint
@param size keypoint diameter
@param angle keypoint orientation
@param response keypoint detector response on the keypoint (that is, strength of the keypoint)
@param octave pyramid octave in which the keypoint has been detected
@param class_id object id
*/
KeyPoint(Point2f _pt, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1);
KeyPoint(Point2f pt, float size, float angle=-1, float response=0, int octave=0, int class_id=-1);
/**
@param x x-coordinate of the keypoint
@param y y-coordinate of the keypoint
@param _size keypoint diameter
@param _angle keypoint orientation
@param _response keypoint detector response on the keypoint (that is, strength of the keypoint)
@param _octave pyramid octave in which the keypoint has been detected
@param _class_id object id
@param size keypoint diameter
@param angle keypoint orientation
@param response keypoint detector response on the keypoint (that is, strength of the keypoint)
@param octave pyramid octave in which the keypoint has been detected
@param class_id object id
*/
CV_WRAP KeyPoint(float x, float y, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1);
CV_WRAP KeyPoint(float x, float y, float size, float angle=-1, float response=0, int octave=0, int class_id=-1);
size_t hash() const;
+5 -1
View File
@@ -358,7 +358,11 @@ _IplImage
needed for correct deallocation */
#if defined(CV__ENABLE_C_API_CTORS) && defined(__cplusplus)
_IplImage() {}
_IplImage()
{
memset(this, 0, sizeof(*this)); // valid for POD structure
nSize = sizeof(IplImage);
}
_IplImage(const cv::Mat& m) { *this = cvIplImage(m); }
#endif
}
@@ -16,8 +16,8 @@
# define OPENCV_HAVE_FILESYSTEM_SUPPORT 1
# elif defined(__APPLE__)
# include <TargetConditionals.h>
# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX) || (!defined(TARGET_OS_OSX) && !TARGET_OS_IPHONE)
# define OPENCV_HAVE_FILESYSTEM_SUPPORT 1 // OSX only
# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS)
# define OPENCV_HAVE_FILESYSTEM_SUPPORT 1 // OSX, iOS only
# endif
# else
/* unknown */
@@ -7,8 +7,8 @@
#define CV_VERSION_MAJOR 3
#define CV_VERSION_MINOR 4
#define CV_VERSION_REVISION 14
#define CV_VERSION_STATUS "-pre"
#define CV_VERSION_REVISION 15
#define CV_VERSION_STATUS ""
#define CVAUX_STR_EXP(__A) #__A
#define CVAUX_STR(__A) CVAUX_STR_EXP(__A)
@@ -497,11 +497,13 @@ VSX_IMPL_CONV_EVEN_2_4(vec_uint4, vec_double2, vec_ctu, vec_ctuo)
VSX_FINLINE(rt) fnm(const rg& a, int only_truncate) \
{ \
assert(only_truncate == 0); \
CV_UNUSED(only_truncate); \
CV_UNUSED(only_truncate); \
return fn2(a); \
}
VSX_IMPL_CONV_2VARIANT(vec_int4, vec_float4, vec_cts, vec_cts)
VSX_IMPL_CONV_2VARIANT(vec_uint4, vec_float4, vec_ctu, vec_ctu)
VSX_IMPL_CONV_2VARIANT(vec_float4, vec_int4, vec_ctf, vec_ctf)
VSX_IMPL_CONV_2VARIANT(vec_float4, vec_uint4, vec_ctf, vec_ctf)
// define vec_cts for converting double precision to signed doubleword
// which isn't compatible with xlc but its okay since Eigen only uses it for gcc
VSX_IMPL_CONV_2VARIANT(vec_dword2, vec_double2, vec_cts, vec_ctsl)
+6 -1
View File
@@ -678,7 +678,12 @@ OCL_PERF_TEST_P(SqrtFixture, Sqrt, ::testing::Combine(
OCL_TEST_CYCLE() cv::sqrt(src, dst);
if (CV_MAT_DEPTH(type) >= CV_32F)
// To square root 32 bit floats we use native_sqrt, which has implementation
// defined accuracy. We know intel devices have accurate native_sqrt, but
// otherwise stick to a relaxed sanity check. For types larger than 32 bits
// we can do the accuracy check for all devices as normal.
if (CV_MAT_DEPTH(type) > CV_32F || !ocl::useOpenCL() ||
ocl::Device::getDefault().isIntel())
SANITY_CHECK(dst, 1e-5, ERROR_RELATIVE);
else
SANITY_CHECK(dst, 1);
+16 -27
View File
@@ -57,24 +57,6 @@ namespace cv
* logical operations *
\****************************************************************************************/
void convertAndUnrollScalar( const Mat& sc, int buftype, uchar* scbuf, size_t blocksize )
{
int scn = (int)sc.total(), cn = CV_MAT_CN(buftype);
size_t esz = CV_ELEM_SIZE(buftype);
getConvertFunc(sc.depth(), buftype)(sc.ptr(), 1, 0, 1, scbuf, 1, Size(std::min(cn, scn), 1), 0);
// unroll the scalar
if( scn < cn )
{
CV_Assert( scn == 1 );
size_t esz1 = CV_ELEM_SIZE1(buftype);
for( size_t i = esz1; i < esz; i++ )
scbuf[i] = scbuf[i - esz1];
}
for( size_t i = esz; i < blocksize*esz; i++ )
scbuf[i] = scbuf[i - esz];
}
enum { OCL_OP_ADD=0, OCL_OP_SUB=1, OCL_OP_RSUB=2, OCL_OP_ABSDIFF=3, OCL_OP_MUL=4,
OCL_OP_MUL_SCALE=5, OCL_OP_DIV_SCALE=6, OCL_OP_RECIP_SCALE=7, OCL_OP_ADDW=8,
OCL_OP_AND=9, OCL_OP_OR=10, OCL_OP_XOR=11, OCL_OP_NOT=12, OCL_OP_MIN=13, OCL_OP_MAX=14,
@@ -641,7 +623,8 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst,
(kind1 == _InputArray::MATX && (sz1 == Size(1,4) || sz1 == Size(1,1))) ||
(kind2 == _InputArray::MATX && (sz2 == Size(1,4) || sz2 == Size(1,1))) )
{
if( checkScalar(*psrc1, type2, kind1, kind2) )
if ((type1 == CV_64F && (sz1.height == 1 || sz1.height == 4)) &&
checkScalar(*psrc1, type2, kind1, kind2))
{
// src1 is a scalar; swap it with src2
swap(psrc1, psrc2);
@@ -1041,9 +1024,7 @@ static BinaryFuncC* getRecipTab()
return recipTab;
}
}
void cv::multiply(InputArray src1, InputArray src2,
void multiply(InputArray src1, InputArray src2,
OutputArray dst, double scale, int dtype)
{
CV_INSTRUMENT_REGION();
@@ -1052,7 +1033,7 @@ void cv::multiply(InputArray src1, InputArray src2,
true, &scale, std::abs(scale - 1.0) < DBL_EPSILON ? OCL_OP_MUL : OCL_OP_MUL_SCALE);
}
void cv::divide(InputArray src1, InputArray src2,
void divide(InputArray src1, InputArray src2,
OutputArray dst, double scale, int dtype)
{
CV_INSTRUMENT_REGION();
@@ -1060,7 +1041,7 @@ void cv::divide(InputArray src1, InputArray src2,
arithm_op(src1, src2, dst, noArray(), dtype, getDivTab(), true, &scale, OCL_OP_DIV_SCALE);
}
void cv::divide(double scale, InputArray src2,
void divide(double scale, InputArray src2,
OutputArray dst, int dtype)
{
CV_INSTRUMENT_REGION();
@@ -1068,13 +1049,17 @@ void cv::divide(double scale, InputArray src2,
arithm_op(src2, src2, dst, noArray(), dtype, getRecipTab(), true, &scale, OCL_OP_RECIP_SCALE);
}
UMat UMat::mul(InputArray m, double scale) const
{
UMat dst;
multiply(*this, m, dst, scale);
return dst;
}
/****************************************************************************************\
* addWeighted *
\****************************************************************************************/
namespace cv
{
static BinaryFuncC* getAddWeightedTab()
{
static BinaryFuncC addWeightedTab[] =
@@ -1879,6 +1864,9 @@ void cv::inRange(InputArray _src, InputArray _lowerb,
}
}
#ifndef OPENCV_EXCLUDE_C_API
/****************************************************************************************\
* Earlier API: cvAdd etc. *
\****************************************************************************************/
@@ -2141,4 +2129,5 @@ cvMaxS( const void* srcarr1, double value, void* dstarr )
cv::max( src1, value, dst );
}
#endif // OPENCV_EXCLUDE_C_API
/* End of file. */
+45 -44
View File
@@ -48,6 +48,8 @@
#include "precomp.hpp"
#ifndef OPENCV_EXCLUDE_C_API
#define CV_ORIGIN_TL 0
#define CV_ORIGIN_BL 1
@@ -3223,51 +3225,50 @@ template<> void DefaultDeleter<CvMemStorage>::operator ()(CvMemStorage* obj) con
template<> void DefaultDeleter<CvFileStorage>::operator ()(CvFileStorage* obj) const
{ cvReleaseFileStorage(&obj); }
template <typename T> static inline
void scalarToRawData_(const Scalar& s, T * const buf, const int cn, const int unroll_to)
{
int i = 0;
for(; i < cn; i++)
buf[i] = saturate_cast<T>(s.val[i]);
for(; i < unroll_to; i++)
buf[i] = buf[i-cn];
}
void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to)
{
CV_INSTRUMENT_REGION();
const int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
CV_Assert(cn <= 4);
switch(depth)
{
case CV_8U:
scalarToRawData_<uchar>(s, (uchar*)_buf, cn, unroll_to);
break;
case CV_8S:
scalarToRawData_<schar>(s, (schar*)_buf, cn, unroll_to);
break;
case CV_16U:
scalarToRawData_<ushort>(s, (ushort*)_buf, cn, unroll_to);
break;
case CV_16S:
scalarToRawData_<short>(s, (short*)_buf, cn, unroll_to);
break;
case CV_32S:
scalarToRawData_<int>(s, (int*)_buf, cn, unroll_to);
break;
case CV_32F:
scalarToRawData_<float>(s, (float*)_buf, cn, unroll_to);
break;
case CV_64F:
scalarToRawData_<double>(s, (double*)_buf, cn, unroll_to);
break;
default:
CV_Error(CV_StsUnsupportedFormat,"");
}
}
} // cv::
/* universal functions */
CV_IMPL void
cvRelease( void** struct_ptr )
{
CvTypeInfo* info;
if( !struct_ptr )
CV_Error( CV_StsNullPtr, "NULL double pointer" );
if( *struct_ptr )
{
info = cvTypeOf( *struct_ptr );
if( !info )
CV_Error( CV_StsError, "Unknown object type" );
if( !info->release )
CV_Error( CV_StsError, "release function pointer is NULL" );
info->release( struct_ptr );
*struct_ptr = 0;
}
}
void* cvClone( const void* struct_ptr )
{
void* struct_copy = 0;
CvTypeInfo* info;
if( !struct_ptr )
CV_Error( CV_StsNullPtr, "NULL structure pointer" );
info = cvTypeOf( struct_ptr );
if( !info )
CV_Error( CV_StsError, "Unknown object type" );
if( !info->clone )
CV_Error( CV_StsError, "clone function pointer is NULL" );
struct_copy = info->clone( struct_ptr );
return struct_copy;
}
#endif // OPENCV_EXCLUDE_C_API
/* End of file. */
+3
View File
@@ -5,6 +5,7 @@
#include "precomp.hpp"
#ifndef OPENCV_EXCLUDE_C_API
CV_IMPL void
cvSplit( const void* srcarr, void* dstarr0, void* dstarr1, void* dstarr2, void* dstarr3 )
@@ -132,3 +133,5 @@ CV_IMPL void cvNormalize( const CvArr* srcarr, CvArr* dstarr,
CV_Assert( dst.size() == src.size() && src.channels() == dst.channels() );
cv::normalize( src, dst, a, b, norm_type, dst.type(), mask );
}
#endif // OPENCV_EXCLUDE_C_API
-140
View File
@@ -9,7 +9,6 @@
#include "convert_scale.simd.hpp"
#include "convert_scale.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
namespace cv
{
@@ -117,143 +116,4 @@ void convertScaleAbs(InputArray _src, OutputArray _dst, double alpha, double bet
}
}
//==================================================================================================
#ifdef HAVE_OPENCL
static bool ocl_normalize( InputArray _src, InputOutputArray _dst, InputArray _mask, int dtype,
double scale, double delta )
{
UMat src = _src.getUMat();
if( _mask.empty() )
src.convertTo( _dst, dtype, scale, delta );
else if (src.channels() <= 4)
{
const ocl::Device & dev = ocl::Device::getDefault();
int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype),
ddepth = CV_MAT_DEPTH(dtype), wdepth = std::max(CV_32F, std::max(sdepth, ddepth)),
rowsPerWI = dev.isIntel() ? 4 : 1;
float fscale = static_cast<float>(scale), fdelta = static_cast<float>(delta);
bool haveScale = std::fabs(scale - 1) > DBL_EPSILON,
haveZeroScale = !(std::fabs(scale) > DBL_EPSILON),
haveDelta = std::fabs(delta) > DBL_EPSILON,
doubleSupport = dev.doubleFPConfig() > 0;
if (!haveScale && !haveDelta && stype == dtype)
{
_src.copyTo(_dst, _mask);
return true;
}
if (haveZeroScale)
{
_dst.setTo(Scalar(delta), _mask);
return true;
}
if ((sdepth == CV_64F || ddepth == CV_64F) && !doubleSupport)
return false;
char cvt[2][40];
String opts = format("-D srcT=%s -D dstT=%s -D convertToWT=%s -D cn=%d -D rowsPerWI=%d"
" -D convertToDT=%s -D workT=%s%s%s%s -D srcT1=%s -D dstT1=%s",
ocl::typeToStr(stype), ocl::typeToStr(dtype),
ocl::convertTypeStr(sdepth, wdepth, cn, cvt[0]), cn,
rowsPerWI, ocl::convertTypeStr(wdepth, ddepth, cn, cvt[1]),
ocl::typeToStr(CV_MAKE_TYPE(wdepth, cn)),
doubleSupport ? " -D DOUBLE_SUPPORT" : "",
haveScale ? " -D HAVE_SCALE" : "",
haveDelta ? " -D HAVE_DELTA" : "",
ocl::typeToStr(sdepth), ocl::typeToStr(ddepth));
ocl::Kernel k("normalizek", ocl::core::normalize_oclsrc, opts);
if (k.empty())
return false;
UMat mask = _mask.getUMat(), dst = _dst.getUMat();
ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
maskarg = ocl::KernelArg::ReadOnlyNoSize(mask),
dstarg = ocl::KernelArg::ReadWrite(dst);
if (haveScale)
{
if (haveDelta)
k.args(srcarg, maskarg, dstarg, fscale, fdelta);
else
k.args(srcarg, maskarg, dstarg, fscale);
}
else
{
if (haveDelta)
k.args(srcarg, maskarg, dstarg, fdelta);
else
k.args(srcarg, maskarg, dstarg);
}
size_t globalsize[2] = { (size_t)src.cols, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI };
return k.run(2, globalsize, NULL, false);
}
else
{
UMat temp;
src.convertTo( temp, dtype, scale, delta );
temp.copyTo( _dst, _mask );
}
return true;
}
#endif
void normalize(InputArray _src, InputOutputArray _dst, double a, double b,
int norm_type, int rtype, InputArray _mask)
{
CV_INSTRUMENT_REGION();
double scale = 1, shift = 0;
int type = _src.type(), depth = CV_MAT_DEPTH(type);
if( rtype < 0 )
rtype = _dst.fixedType() ? _dst.depth() : depth;
if( norm_type == CV_MINMAX )
{
double smin = 0, smax = 0;
double dmin = MIN( a, b ), dmax = MAX( a, b );
minMaxIdx( _src, &smin, &smax, 0, 0, _mask );
scale = (dmax - dmin)*(smax - smin > DBL_EPSILON ? 1./(smax - smin) : 0);
if( rtype == CV_32F )
{
scale = (float)scale;
shift = (float)dmin - (float)(smin*scale);
}
else
shift = dmin - smin*scale;
}
else if( norm_type == CV_L2 || norm_type == CV_L1 || norm_type == CV_C )
{
scale = norm( _src, norm_type, _mask );
scale = scale > DBL_EPSILON ? a/scale : 0.;
shift = 0;
}
else
CV_Error( CV_StsBadArg, "Unknown/unsupported norm type" );
CV_OCL_RUN(_dst.isUMat(),
ocl_normalize(_src, _dst, _mask, rtype, scale, shift))
Mat src = _src.getMat();
if( _mask.empty() )
src.convertTo( _dst, rtype, scale, shift );
else
{
Mat temp;
src.convertTo( temp, rtype, scale, shift );
temp.copyTo( _dst, _mask );
}
}
} // namespace
+73 -484
View File
@@ -53,6 +53,75 @@
namespace cv
{
template <typename T> static inline
void scalarToRawData_(const Scalar& s, T * const buf, const int cn, const int unroll_to)
{
int i = 0;
for(; i < cn; i++)
buf[i] = saturate_cast<T>(s.val[i]);
for(; i < unroll_to; i++)
buf[i] = buf[i-cn];
}
void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to)
{
CV_INSTRUMENT_REGION();
const int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
CV_Assert(cn <= 4);
switch(depth)
{
case CV_8U:
scalarToRawData_<uchar>(s, (uchar*)_buf, cn, unroll_to);
break;
case CV_8S:
scalarToRawData_<schar>(s, (schar*)_buf, cn, unroll_to);
break;
case CV_16U:
scalarToRawData_<ushort>(s, (ushort*)_buf, cn, unroll_to);
break;
case CV_16S:
scalarToRawData_<short>(s, (short*)_buf, cn, unroll_to);
break;
case CV_32S:
scalarToRawData_<int>(s, (int*)_buf, cn, unroll_to);
break;
case CV_32F:
scalarToRawData_<float>(s, (float*)_buf, cn, unroll_to);
break;
case CV_64F:
scalarToRawData_<double>(s, (double*)_buf, cn, unroll_to);
break;
#if CV_VERSION_MAJOR >= 4
case CV_16F:
scalarToRawData_<float16_t>(s, (float16_t*)_buf, cn, unroll_to);
break;
#endif
default:
CV_Error(CV_StsUnsupportedFormat,"");
}
}
void convertAndUnrollScalar( const Mat& sc, int buftype, uchar* scbuf, size_t blocksize )
{
int scn = (int)sc.total(), cn = CV_MAT_CN(buftype);
size_t esz = CV_ELEM_SIZE(buftype);
BinaryFunc cvtFn = getConvertFunc(sc.depth(), buftype);
CV_Assert(cvtFn);
cvtFn(sc.ptr(), 1, 0, 1, scbuf, 1, Size(std::min(cn, scn), 1), 0);
// unroll the scalar
if( scn < cn )
{
CV_Assert( scn == 1 );
size_t esz1 = CV_ELEM_SIZE1(buftype);
for( size_t i = esz1; i < esz; i++ )
scbuf[i] = scbuf[i - esz1];
}
for( size_t i = esz; i < blocksize*esz; i++ )
scbuf[i] = scbuf[i - esz];
}
template<typename T> static void
copyMask_(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
{
@@ -594,490 +663,6 @@ Mat& Mat::setTo(InputArray _value, InputArray _mask)
return *this;
}
#if CV_SIMD128
template<typename V> CV_ALWAYS_INLINE void flipHoriz_single( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
{
typedef typename V::lane_type T;
int end = (int)(size.width*esz);
int width = (end + 1)/2;
int width_1 = width & -v_uint8x16::nlanes;
int i, j;
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(T)>(src, dst));
#endif
for( ; size.height--; src += sstep, dst += dstep )
{
for( i = 0, j = end; i < width_1; i += v_uint8x16::nlanes, j -= v_uint8x16::nlanes )
{
V t0, t1;
t0 = v_load((T*)((uchar*)src + i));
t1 = v_load((T*)((uchar*)src + j - v_uint8x16::nlanes));
t0 = v_reverse(t0);
t1 = v_reverse(t1);
v_store((T*)(dst + j - v_uint8x16::nlanes), t0);
v_store((T*)(dst + i), t1);
}
if (isAligned<sizeof(T)>(src, dst))
{
for ( ; i < width; i += sizeof(T), j -= sizeof(T) )
{
T t0, t1;
t0 = *((T*)((uchar*)src + i));
t1 = *((T*)((uchar*)src + j - sizeof(T)));
*((T*)(dst + j - sizeof(T))) = t0;
*((T*)(dst + i)) = t1;
}
}
else
{
for ( ; i < width; i += sizeof(T), j -= sizeof(T) )
{
for (int k = 0; k < (int)sizeof(T); k++)
{
uchar t0, t1;
t0 = *((uchar*)src + i + k);
t1 = *((uchar*)src + j + k - sizeof(T));
*(dst + j + k - sizeof(T)) = t0;
*(dst + i + k) = t1;
}
}
}
}
}
template<typename T1, typename T2> CV_ALWAYS_INLINE void flipHoriz_double( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
{
int end = (int)(size.width*esz);
int width = (end + 1)/2;
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(T1)>(src, dst));
CV_Assert(isAligned<sizeof(T2)>(src, dst));
#endif
for( ; size.height--; src += sstep, dst += dstep )
{
for ( int i = 0, j = end; i < width; i += sizeof(T1) + sizeof(T2), j -= sizeof(T1) + sizeof(T2) )
{
T1 t0, t1;
T2 t2, t3;
t0 = *((T1*)((uchar*)src + i));
t2 = *((T2*)((uchar*)src + i + sizeof(T1)));
t1 = *((T1*)((uchar*)src + j - sizeof(T1) - sizeof(T2)));
t3 = *((T2*)((uchar*)src + j - sizeof(T2)));
*((T1*)(dst + j - sizeof(T1) - sizeof(T2))) = t0;
*((T2*)(dst + j - sizeof(T2))) = t2;
*((T1*)(dst + i)) = t1;
*((T2*)(dst + i + sizeof(T1))) = t3;
}
}
}
#endif
static void
flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
{
#if CV_SIMD
#if CV_STRONG_ALIGNMENT
size_t alignmentMark = ((size_t)src)|((size_t)dst)|sstep|dstep;
#endif
if (esz == 2 * v_uint8x16::nlanes)
{
int end = (int)(size.width*esz);
int width = end/2;
for( ; size.height--; src += sstep, dst += dstep )
{
for( int i = 0, j = end - 2 * v_uint8x16::nlanes; i < width; i += 2 * v_uint8x16::nlanes, j -= 2 * v_uint8x16::nlanes )
{
#if CV_SIMD256
v_uint8x32 t0, t1;
t0 = v256_load((uchar*)src + i);
t1 = v256_load((uchar*)src + j);
v_store(dst + j, t0);
v_store(dst + i, t1);
#else
v_uint8x16 t0, t1, t2, t3;
t0 = v_load((uchar*)src + i);
t1 = v_load((uchar*)src + i + v_uint8x16::nlanes);
t2 = v_load((uchar*)src + j);
t3 = v_load((uchar*)src + j + v_uint8x16::nlanes);
v_store(dst + j, t0);
v_store(dst + j + v_uint8x16::nlanes, t1);
v_store(dst + i, t2);
v_store(dst + i + v_uint8x16::nlanes, t3);
#endif
}
}
}
else if (esz == v_uint8x16::nlanes)
{
int end = (int)(size.width*esz);
int width = end/2;
for( ; size.height--; src += sstep, dst += dstep )
{
for( int i = 0, j = end - v_uint8x16::nlanes; i < width; i += v_uint8x16::nlanes, j -= v_uint8x16::nlanes )
{
v_uint8x16 t0, t1;
t0 = v_load((uchar*)src + i);
t1 = v_load((uchar*)src + j);
v_store(dst + j, t0);
v_store(dst + i, t1);
}
}
}
else if (esz == 8
#if CV_STRONG_ALIGNMENT
&& isAligned<sizeof(uint64)>(alignmentMark)
#endif
)
{
flipHoriz_single<v_uint64x2>(src, sstep, dst, dstep, size, esz);
}
else if (esz == 4
#if CV_STRONG_ALIGNMENT
&& isAligned<sizeof(unsigned)>(alignmentMark)
#endif
)
{
flipHoriz_single<v_uint32x4>(src, sstep, dst, dstep, size, esz);
}
else if (esz == 2
#if CV_STRONG_ALIGNMENT
&& isAligned<sizeof(ushort)>(alignmentMark)
#endif
)
{
flipHoriz_single<v_uint16x8>(src, sstep, dst, dstep, size, esz);
}
else if (esz == 1)
{
flipHoriz_single<v_uint8x16>(src, sstep, dst, dstep, size, esz);
}
else if (esz == 24
#if CV_STRONG_ALIGNMENT
&& isAligned<sizeof(uint64_t)>(alignmentMark)
#endif
)
{
int end = (int)(size.width*esz);
int width = (end + 1)/2;
for( ; size.height--; src += sstep, dst += dstep )
{
for ( int i = 0, j = end; i < width; i += v_uint8x16::nlanes + sizeof(uint64_t), j -= v_uint8x16::nlanes + sizeof(uint64_t) )
{
v_uint8x16 t0, t1;
uint64_t t2, t3;
t0 = v_load((uchar*)src + i);
t2 = *((uint64_t*)((uchar*)src + i + v_uint8x16::nlanes));
t1 = v_load((uchar*)src + j - v_uint8x16::nlanes - sizeof(uint64_t));
t3 = *((uint64_t*)((uchar*)src + j - sizeof(uint64_t)));
v_store(dst + j - v_uint8x16::nlanes - sizeof(uint64_t), t0);
*((uint64_t*)(dst + j - sizeof(uint64_t))) = t2;
v_store(dst + i, t1);
*((uint64_t*)(dst + i + v_uint8x16::nlanes)) = t3;
}
}
}
#if !CV_STRONG_ALIGNMENT
else if (esz == 12)
{
flipHoriz_double<uint64_t,uint>(src, sstep, dst, dstep, size, esz);
}
else if (esz == 6)
{
flipHoriz_double<uint,ushort>(src, sstep, dst, dstep, size, esz);
}
else if (esz == 3)
{
flipHoriz_double<ushort,uchar>(src, sstep, dst, dstep, size, esz);
}
#endif
else
#endif // CV_SIMD
{
int i, j, limit = (int)(((size.width + 1)/2)*esz);
AutoBuffer<int> _tab(size.width*esz);
int* tab = _tab.data();
for( i = 0; i < size.width; i++ )
for( size_t k = 0; k < esz; k++ )
tab[i*esz + k] = (int)((size.width - i - 1)*esz + k);
for( ; size.height--; src += sstep, dst += dstep )
{
for( i = 0; i < limit; i++ )
{
j = tab[i];
uchar t0 = src[i], t1 = src[j];
dst[i] = t1; dst[j] = t0;
}
}
}
}
static void
flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, size_t esz )
{
const uchar* src1 = src0 + (size.height - 1)*sstep;
uchar* dst1 = dst0 + (size.height - 1)*dstep;
size.width *= (int)esz;
for( int y = 0; y < (size.height + 1)/2; y++, src0 += sstep, src1 -= sstep,
dst0 += dstep, dst1 -= dstep )
{
int i = 0;
#if CV_SIMD
#if CV_STRONG_ALIGNMENT
if (isAligned<sizeof(int)>(src0, src1, dst0, dst1))
#endif
{
for (; i <= size.width - CV_SIMD_WIDTH; i += CV_SIMD_WIDTH)
{
v_int32 t0 = vx_load((int*)(src0 + i));
v_int32 t1 = vx_load((int*)(src1 + i));
vx_store((int*)(dst0 + i), t1);
vx_store((int*)(dst1 + i), t0);
}
}
#if CV_STRONG_ALIGNMENT
else
{
for (; i <= size.width - CV_SIMD_WIDTH; i += CV_SIMD_WIDTH)
{
v_uint8 t0 = vx_load(src0 + i);
v_uint8 t1 = vx_load(src1 + i);
vx_store(dst0 + i, t1);
vx_store(dst1 + i, t0);
}
}
#endif
#endif
if (isAligned<sizeof(int)>(src0, src1, dst0, dst1))
{
for( ; i <= size.width - 16; i += 16 )
{
int t0 = ((int*)(src0 + i))[0];
int t1 = ((int*)(src1 + i))[0];
((int*)(dst0 + i))[0] = t1;
((int*)(dst1 + i))[0] = t0;
t0 = ((int*)(src0 + i))[1];
t1 = ((int*)(src1 + i))[1];
((int*)(dst0 + i))[1] = t1;
((int*)(dst1 + i))[1] = t0;
t0 = ((int*)(src0 + i))[2];
t1 = ((int*)(src1 + i))[2];
((int*)(dst0 + i))[2] = t1;
((int*)(dst1 + i))[2] = t0;
t0 = ((int*)(src0 + i))[3];
t1 = ((int*)(src1 + i))[3];
((int*)(dst0 + i))[3] = t1;
((int*)(dst1 + i))[3] = t0;
}
for( ; i <= size.width - 4; i += 4 )
{
int t0 = ((int*)(src0 + i))[0];
int t1 = ((int*)(src1 + i))[0];
((int*)(dst0 + i))[0] = t1;
((int*)(dst1 + i))[0] = t0;
}
}
for( ; i < size.width; i++ )
{
uchar t0 = src0[i];
uchar t1 = src1[i];
dst0[i] = t1;
dst1[i] = t0;
}
}
}
#ifdef HAVE_OPENCL
enum { FLIP_COLS = 1 << 0, FLIP_ROWS = 1 << 1, FLIP_BOTH = FLIP_ROWS | FLIP_COLS };
static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode )
{
CV_Assert(flipCode >= -1 && flipCode <= 1);
const ocl::Device & dev = ocl::Device::getDefault();
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
flipType, kercn = std::min(ocl::predictOptimalVectorWidth(_src, _dst), 4);
bool doubleSupport = dev.doubleFPConfig() > 0;
if (!doubleSupport && depth == CV_64F)
kercn = cn;
if (cn > 4)
return false;
const char * kernelName;
if (flipCode == 0)
kernelName = "arithm_flip_rows", flipType = FLIP_ROWS;
else if (flipCode > 0)
kernelName = "arithm_flip_cols", flipType = FLIP_COLS;
else
kernelName = "arithm_flip_rows_cols", flipType = FLIP_BOTH;
int pxPerWIy = (dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU)) ? 4 : 1;
kercn = (cn!=3 || flipType == FLIP_ROWS) ? std::max(kercn, cn) : cn;
ocl::Kernel k(kernelName, ocl::core::flip_oclsrc,
format( "-D T=%s -D T1=%s -D DEPTH=%d -D cn=%d -D PIX_PER_WI_Y=%d -D kercn=%d",
kercn != cn ? ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)) : ocl::vecopTypeToStr(CV_MAKE_TYPE(depth, kercn)),
kercn != cn ? ocl::typeToStr(depth) : ocl::vecopTypeToStr(depth), depth, cn, pxPerWIy, kercn));
if (k.empty())
return false;
Size size = _src.size();
_dst.create(size, type);
UMat src = _src.getUMat(), dst = _dst.getUMat();
int cols = size.width * cn / kercn, rows = size.height;
cols = flipType == FLIP_COLS ? (cols + 1) >> 1 : cols;
rows = flipType & FLIP_ROWS ? (rows + 1) >> 1 : rows;
k.args(ocl::KernelArg::ReadOnlyNoSize(src),
ocl::KernelArg::WriteOnly(dst, cn, kercn), rows, cols);
size_t maxWorkGroupSize = dev.maxWorkGroupSize();
CV_Assert(maxWorkGroupSize % 4 == 0);
size_t globalsize[2] = { (size_t)cols, ((size_t)rows + pxPerWIy - 1) / pxPerWIy },
localsize[2] = { maxWorkGroupSize / 4, 4 };
return k.run(2, globalsize, (flipType == FLIP_COLS) && !dev.isIntel() ? localsize : NULL, false);
}
#endif
#if defined HAVE_IPP
static bool ipp_flip(Mat &src, Mat &dst, int flip_mode)
{
#ifdef HAVE_IPP_IW
CV_INSTRUMENT_REGION_IPP();
// Details: https://github.com/opencv/opencv/issues/12943
if (flip_mode <= 0 /* swap rows */
&& cv::ipp::getIppTopFeatures() != ippCPUID_SSE42
&& (int64_t)(src.total()) * src.elemSize() >= CV_BIG_INT(0x80000000)/*2Gb*/
)
return false;
IppiAxis ippMode;
if(flip_mode < 0)
ippMode = ippAxsBoth;
else if(flip_mode == 0)
ippMode = ippAxsHorizontal;
else
ippMode = ippAxsVertical;
try
{
::ipp::IwiImage iwSrc = ippiGetImage(src);
::ipp::IwiImage iwDst = ippiGetImage(dst);
CV_INSTRUMENT_FUN_IPP(::ipp::iwiMirror, iwSrc, iwDst, ippMode);
}
catch(const ::ipp::IwException &)
{
return false;
}
return true;
#else
CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(flip_mode);
return false;
#endif
}
#endif
void flip( InputArray _src, OutputArray _dst, int flip_mode )
{
CV_INSTRUMENT_REGION();
CV_Assert( _src.dims() <= 2 );
Size size = _src.size();
if (flip_mode < 0)
{
if (size.width == 1)
flip_mode = 0;
if (size.height == 1)
flip_mode = 1;
}
if ((size.width == 1 && flip_mode > 0) ||
(size.height == 1 && flip_mode == 0))
{
return _src.copyTo(_dst);
}
CV_OCL_RUN( _dst.isUMat(), ocl_flip(_src, _dst, flip_mode))
Mat src = _src.getMat();
int type = src.type();
_dst.create( size, type );
Mat dst = _dst.getMat();
CV_IPP_RUN_FAST(ipp_flip(src, dst, flip_mode));
size_t esz = CV_ELEM_SIZE(type);
if( flip_mode <= 0 )
flipVert( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
else
flipHoriz( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
if( flip_mode < 0 )
flipHoriz( dst.ptr(), dst.step, dst.ptr(), dst.step, dst.size(), esz );
}
void rotate(InputArray _src, OutputArray _dst, int rotateMode)
{
CV_Assert(_src.dims() <= 2);
switch (rotateMode)
{
case ROTATE_90_CLOCKWISE:
transpose(_src, _dst);
flip(_dst, _dst, 1);
break;
case ROTATE_180:
flip(_src, _dst, -1);
break;
case ROTATE_90_COUNTERCLOCKWISE:
transpose(_src, _dst);
flip(_dst, _dst, 0);
break;
default:
break;
}
}
#if defined HAVE_OPENCL && !defined __APPLE__
@@ -1499,6 +1084,9 @@ void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom,
}
}
#ifndef OPENCV_EXCLUDE_C_API
/* dst = src */
CV_IMPL void
cvCopy( const void* srcarr, void* dstarr, const void* maskarr )
@@ -1614,4 +1202,5 @@ cvRepeat( const CvArr* srcarr, CvArr* dstarr )
cv::repeat(src, dst.rows/src.rows, dst.cols/src.cols, dst);
}
#endif // OPENCV_EXCLUDE_C_API
/* End of file. */
+3
View File
@@ -40,6 +40,8 @@
//M*/
#include "precomp.hpp"
#ifndef OPENCV_EXCLUDE_C_API
/* default alignment for dynamic data strucutures, resided in storages. */
#define CV_STRUCT_ALIGN ((int)sizeof(double))
@@ -3585,4 +3587,5 @@ void seqInsertSlice( CvSeq* seq, int before_index, const CvArr* from_arr )
}
#endif // OPENCV_EXCLUDE_C_API
/* End of file. */
+2 -2
View File
@@ -901,7 +901,7 @@ bool ocl_convert_nv12_to_bgr(
k.args(clImageY, clImageUV, clBuffer, step, cols, rows);
size_t globalsize[] = { (size_t)cols, (size_t)rows };
size_t globalsize[] = { (size_t)cols/2, (size_t)rows/2 };
return k.run(2, globalsize, 0, false);
}
@@ -922,7 +922,7 @@ bool ocl_convert_bgr_to_nv12(
k.args(clBuffer, step, cols, rows, clImageY, clImageUV);
size_t globalsize[] = { (size_t)cols, (size_t)rows };
size_t globalsize[] = { (size_t)cols/2, (size_t)rows/2 };
return k.run(2, globalsize, 0, false);
}
+4
View File
@@ -4640,6 +4640,9 @@ int cv::getOptimalDFTSize( int size0 )
return optimalDFTSizeTab[b];
}
#ifndef OPENCV_EXCLUDE_C_API
CV_IMPL void
cvDFT( const CvArr* srcarr, CvArr* dstarr, int flags, int nonzero_rows )
{
@@ -4695,4 +4698,5 @@ cvGetOptimalDFTSize( int size0 )
return cv::getOptimalDFTSize(size0);
}
#endif // OPENCV_EXCLUDE_C_API
/* End of file. */
+15 -10
View File
@@ -753,8 +753,6 @@ SVBkSb( int m, int n, const double* w, size_t wstep,
(double*)alignPtr(buffer, sizeof(double)), DBL_EPSILON*2 );
}
}
/****************************************************************************************\
* Determinant of the matrix *
\****************************************************************************************/
@@ -764,7 +762,7 @@ SVBkSb( int m, int n, const double* w, size_t wstep,
m(0,1)*((double)m(1,0)*m(2,2) - (double)m(1,2)*m(2,0)) + \
m(0,2)*((double)m(1,0)*m(2,1) - (double)m(1,1)*m(2,0)))
double cv::determinant( InputArray _mat )
double determinant( InputArray _mat )
{
CV_INSTRUMENT_REGION();
@@ -842,7 +840,7 @@ double cv::determinant( InputArray _mat )
#define Df( y, x ) ((float*)(dstdata + y*dststep))[x]
#define Dd( y, x ) ((double*)(dstdata + y*dststep))[x]
double cv::invert( InputArray _src, OutputArray _dst, int method )
double invert( InputArray _src, OutputArray _dst, int method )
{
CV_INSTRUMENT_REGION();
@@ -1069,13 +1067,19 @@ double cv::invert( InputArray _src, OutputArray _dst, int method )
return result;
}
UMat UMat::inv(int method) const
{
UMat m;
invert(*this, m, method);
return m;
}
/****************************************************************************************\
* Solving a linear system *
\****************************************************************************************/
bool cv::solve( InputArray _src, InputArray _src2arg, OutputArray _dst, int method )
bool solve( InputArray _src, InputArray _src2arg, OutputArray _dst, int method )
{
CV_INSTRUMENT_REGION();
@@ -1374,7 +1378,7 @@ bool cv::solve( InputArray _src, InputArray _src2arg, OutputArray _dst, int meth
/////////////////// finding eigenvalues and eigenvectors of a symmetric matrix ///////////////
bool cv::eigen( InputArray _src, OutputArray _evals, OutputArray _evects )
bool eigen( InputArray _src, OutputArray _evals, OutputArray _evects )
{
CV_INSTRUMENT_REGION();
@@ -1396,7 +1400,7 @@ bool cv::eigen( InputArray _src, OutputArray _evals, OutputArray _evects )
const bool evecNeeded = _evects.needed();
const int esOptions = evecNeeded ? Eigen::ComputeEigenvectors : Eigen::EigenvaluesOnly;
_evals.create(n, 1, type);
cv::Mat evals = _evals.getMat();
Mat evals = _evals.getMat();
if ( type == CV_64F )
{
Eigen::MatrixXd src_eig, zeros_eig;
@@ -1448,9 +1452,6 @@ bool cv::eigen( InputArray _src, OutputArray _evals, OutputArray _evects )
#endif
}
namespace cv
{
static void _SVDcompute( InputArray _aarr, OutputArray _w,
OutputArray _u, OutputArray _vt, int flags )
{
@@ -1598,6 +1599,9 @@ void cv::SVBackSubst(InputArray w, InputArray u, InputArray vt, InputArray rhs,
}
#ifndef OPENCV_EXCLUDE_C_API
CV_IMPL double
cvDet( const CvArr* arr )
{
@@ -1789,3 +1793,4 @@ cvSVBkSb( const CvArr* warr, const CvArr* uarr,
cv::SVD::backSubst(w, u, v, rhs, dst);
CV_Assert( dst.data == dst0.data );
}
#endif // OPENCV_EXCLUDE_C_API
+7
View File
@@ -1637,6 +1637,9 @@ void patchNaNs( InputOutputArray _a, double _val )
}
#ifndef OPENCV_EXCLUDE_C_API
CV_IMPL float cvCbrt(float value) { return cv::cubeRoot(value); }
CV_IMPL float cvFastArctan(float y, float x) { return cv::fastAtan2(y, x); }
@@ -1720,6 +1723,7 @@ CV_IMPL int cvCheckArr( const CvArr* arr, int flags,
return cv::checkRange(cv::cvarrToMat(arr), (flags & CV_CHECK_QUIET) != 0, 0, minVal, maxVal );
}
#endif // OPENCV_EXCLUDE_C_API
/*
Finds real roots of cubic, quadratic or linear equation.
@@ -2015,6 +2019,8 @@ double cv::solvePoly( InputArray _coeffs0, OutputArray _roots0, int maxIters )
}
#ifndef OPENCV_EXCLUDE_C_API
CV_IMPL int
cvSolveCubic( const CvMat* coeffs, CvMat* roots )
{
@@ -2034,6 +2040,7 @@ void cvSolvePoly(const CvMat* a, CvMat *r, int maxiter, int)
CV_Assert( _r.data == _r0.data ); // check that the array of roots was not reallocated
}
#endif // OPENCV_EXCLUDE_C_API
// Common constants for dispatched code
+22 -1
View File
@@ -7,6 +7,10 @@
#include "mathfuncs_core.simd.hpp"
#include "mathfuncs_core.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
#define IPP_DISABLE_MAGNITUDE_32F 1 // accuracy: https://github.com/opencv/opencv/issues/19506
namespace cv { namespace hal {
///////////////////////////////////// ATAN2 ////////////////////////////////////
@@ -44,8 +48,25 @@ void magnitude32f(const float* x, const float* y, float* mag, int len)
CV_INSTRUMENT_REGION();
CALL_HAL(magnitude32f, cv_hal_magnitude32f, x, y, mag, len);
#ifdef HAVE_IPP
bool allowIPP = true;
#ifdef IPP_DISABLE_MAGNITUDE_32F
if (cv::ipp::getIppTopFeatures() & (
#if IPP_VERSION_X100 >= 201700
ippCPUID_AVX512F |
#endif
ippCPUID_AVX2)
)
{
allowIPP = (len & 7) == 0;
}
#endif
// SSE42 performance issues
CV_IPP_RUN(IPP_VERSION_X100 > 201800 || cv::ipp::getIppTopFeatures() != ippCPUID_SSE42, CV_INSTRUMENT_FUN_IPP(ippsMagnitude_32f, x, y, mag, len) >= 0);
CV_IPP_RUN((IPP_VERSION_X100 > 201800 || cv::ipp::getIppTopFeatures() != ippCPUID_SSE42) && allowIPP,
CV_INSTRUMENT_FUN_IPP(ippsMagnitude_32f, x, y, mag, len) >= 0);
#endif
CV_CPU_DISPATCH(magnitude32f, (x, y, mag, len),
CV_CPU_DISPATCH_MODES_ALL);
+73
View File
@@ -999,8 +999,79 @@ double Mat::dot(InputArray _mat) const
return r;
}
#ifdef HAVE_OPENCL
static bool ocl_dot( InputArray _src1, InputArray _src2, double & res )
{
UMat src1 = _src1.getUMat().reshape(1), src2 = _src2.getUMat().reshape(1);
int type = src1.type(), depth = CV_MAT_DEPTH(type),
kercn = ocl::predictOptimalVectorWidth(src1, src2);
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
if ( !doubleSupport && depth == CV_64F )
return false;
int dbsize = ocl::Device::getDefault().maxComputeUnits();
size_t wgs = ocl::Device::getDefault().maxWorkGroupSize();
int ddepth = std::max(CV_32F, depth);
int wgs2_aligned = 1;
while (wgs2_aligned < (int)wgs)
wgs2_aligned <<= 1;
wgs2_aligned >>= 1;
char cvt[40];
ocl::Kernel k("reduce", ocl::core::reduce_oclsrc,
format("-D srcT=%s -D srcT1=%s -D dstT=%s -D dstTK=%s -D ddepth=%d -D convertToDT=%s -D OP_DOT "
"-D WGS=%d -D WGS2_ALIGNED=%d%s%s%s -D kercn=%d",
ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)), ocl::typeToStr(depth),
ocl::typeToStr(ddepth), ocl::typeToStr(CV_MAKE_TYPE(ddepth, kercn)),
ddepth, ocl::convertTypeStr(depth, ddepth, kercn, cvt),
(int)wgs, wgs2_aligned, doubleSupport ? " -D DOUBLE_SUPPORT" : "",
_src1.isContinuous() ? " -D HAVE_SRC_CONT" : "",
_src2.isContinuous() ? " -D HAVE_SRC2_CONT" : "", kercn));
if (k.empty())
return false;
UMat db(1, dbsize, ddepth);
ocl::KernelArg src1arg = ocl::KernelArg::ReadOnlyNoSize(src1),
src2arg = ocl::KernelArg::ReadOnlyNoSize(src2),
dbarg = ocl::KernelArg::PtrWriteOnly(db);
k.args(src1arg, src1.cols, (int)src1.total(), dbsize, dbarg, src2arg);
size_t globalsize = dbsize * wgs;
if (k.run(1, &globalsize, &wgs, false))
{
res = sum(db.getMat(ACCESS_READ))[0];
return true;
}
return false;
}
#endif
double UMat::dot(InputArray m) const
{
CV_INSTRUMENT_REGION();
CV_Assert(m.sameSize(*this) && m.type() == type());
#ifdef HAVE_OPENCL
double r = 0;
CV_OCL_RUN_(dims <= 2, ocl_dot(*this, m, r), r)
#endif
return getMat(ACCESS_READ).dot(m);
}
} // namespace cv::
#ifndef OPENCV_EXCLUDE_C_API
/****************************************************************************************\
* Earlier API *
\****************************************************************************************/
@@ -1225,4 +1296,6 @@ cvBackProjectPCA( const CvArr* proj_arr, const CvArr* avg_arr,
CV_Assert(dst0.data == dst.data);
}
#endif // OPENCV_EXCLUDE_C_API
/* End of file. */
+2 -2
View File
@@ -204,7 +204,7 @@ MatAllocator* Mat::getStdAllocator()
//==================================================================================================
bool MatSize::operator==(const MatSize& sz) const
bool MatSize::operator==(const MatSize& sz) const CV_NOEXCEPT
{
int d = dims();
int dsz = sz.dims();
@@ -337,7 +337,7 @@ void finalizeHdr(Mat& m)
//======================================= Mat ======================================================
Mat::Mat()
Mat::Mat() CV_NOEXCEPT
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
datalimit(0), allocator(0), u(0), size(&rows), step(0)
{}
+3 -1
View File
@@ -6,6 +6,7 @@
#include "opencv2/core/mat.hpp"
#include "opencv2/core/types_c.h"
#ifndef OPENCV_EXCLUDE_C_API
// glue
CvMatND cvMatND(const cv::Mat& m)
@@ -360,7 +361,6 @@ cvSort( const CvArr* _src, CvArr* _dst, CvArr* _idx, int flags )
}
}
CV_IMPL int
cvKMeans2( const CvArr* _samples, int cluster_count, CvArr* _labels,
CvTermCriteria termcrit, int attempts, CvRNG*,
@@ -389,3 +389,5 @@ cvKMeans2( const CvArr* _samples, int cluster_count, CvArr* _labels,
*_compactness = compactness;
return 1;
}
#endif // OPENCV_EXCLUDE_C_API
+17 -279
View File
@@ -226,6 +226,23 @@ void cv::setIdentity( InputOutputArray _m, const Scalar& s )
}
}
namespace cv {
UMat UMat::eye(int rows, int cols, int type)
{
return UMat::eye(Size(cols, rows), type);
}
UMat UMat::eye(Size size, int type)
{
UMat m(size, type);
setIdentity(m);
return m;
}
} // namespace
//////////////////////////////////////////// trace ///////////////////////////////////////////
cv::Scalar cv::trace( InputArray _m )
@@ -260,285 +277,6 @@ cv::Scalar cv::trace( InputArray _m )
return cv::sum(m.diag());
}
////////////////////////////////////// transpose /////////////////////////////////////////
namespace cv
{
template<typename T> static void
transpose_( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz )
{
int i=0, j, m = sz.width, n = sz.height;
#if CV_ENABLE_UNROLLED
for(; i <= m - 4; i += 4 )
{
T* d0 = (T*)(dst + dstep*i);
T* d1 = (T*)(dst + dstep*(i+1));
T* d2 = (T*)(dst + dstep*(i+2));
T* d3 = (T*)(dst + dstep*(i+3));
for( j = 0; j <= n - 4; j += 4 )
{
const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
d1[j] = s0[1]; d1[j+1] = s1[1]; d1[j+2] = s2[1]; d1[j+3] = s3[1];
d2[j] = s0[2]; d2[j+1] = s1[2]; d2[j+2] = s2[2]; d2[j+3] = s3[2];
d3[j] = s0[3]; d3[j+1] = s1[3]; d3[j+2] = s2[3]; d3[j+3] = s3[3];
}
for( ; j < n; j++ )
{
const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
d0[j] = s0[0]; d1[j] = s0[1]; d2[j] = s0[2]; d3[j] = s0[3];
}
}
#endif
for( ; i < m; i++ )
{
T* d0 = (T*)(dst + dstep*i);
j = 0;
#if CV_ENABLE_UNROLLED
for(; j <= n - 4; j += 4 )
{
const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
}
#endif
for( ; j < n; j++ )
{
const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
d0[j] = s0[0];
}
}
}
template<typename T> static void
transposeI_( uchar* data, size_t step, int n )
{
for( int i = 0; i < n; i++ )
{
T* row = (T*)(data + step*i);
uchar* data1 = data + i*sizeof(T);
for( int j = i+1; j < n; j++ )
std::swap( row[j], *(T*)(data1 + step*j) );
}
}
typedef void (*TransposeFunc)( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz );
typedef void (*TransposeInplaceFunc)( uchar* data, size_t step, int n );
#define DEF_TRANSPOSE_FUNC(suffix, type) \
static void transpose_##suffix( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ) \
{ transpose_<type>(src, sstep, dst, dstep, sz); } \
\
static void transposeI_##suffix( uchar* data, size_t step, int n ) \
{ transposeI_<type>(data, step, n); }
DEF_TRANSPOSE_FUNC(8u, uchar)
DEF_TRANSPOSE_FUNC(16u, ushort)
DEF_TRANSPOSE_FUNC(8uC3, Vec3b)
DEF_TRANSPOSE_FUNC(32s, int)
DEF_TRANSPOSE_FUNC(16uC3, Vec3s)
DEF_TRANSPOSE_FUNC(32sC2, Vec2i)
DEF_TRANSPOSE_FUNC(32sC3, Vec3i)
DEF_TRANSPOSE_FUNC(32sC4, Vec4i)
DEF_TRANSPOSE_FUNC(32sC6, Vec6i)
DEF_TRANSPOSE_FUNC(32sC8, Vec8i)
static TransposeFunc transposeTab[] =
{
0, transpose_8u, transpose_16u, transpose_8uC3, transpose_32s, 0, transpose_16uC3, 0,
transpose_32sC2, 0, 0, 0, transpose_32sC3, 0, 0, 0, transpose_32sC4,
0, 0, 0, 0, 0, 0, 0, transpose_32sC6, 0, 0, 0, 0, 0, 0, 0, transpose_32sC8
};
static TransposeInplaceFunc transposeInplaceTab[] =
{
0, transposeI_8u, transposeI_16u, transposeI_8uC3, transposeI_32s, 0, transposeI_16uC3, 0,
transposeI_32sC2, 0, 0, 0, transposeI_32sC3, 0, 0, 0, transposeI_32sC4,
0, 0, 0, 0, 0, 0, 0, transposeI_32sC6, 0, 0, 0, 0, 0, 0, 0, transposeI_32sC8
};
#ifdef HAVE_OPENCL
static bool ocl_transpose( InputArray _src, OutputArray _dst )
{
const ocl::Device & dev = ocl::Device::getDefault();
const int TILE_DIM = 32, BLOCK_ROWS = 8;
int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type),
rowsPerWI = dev.isIntel() ? 4 : 1;
UMat src = _src.getUMat();
_dst.create(src.cols, src.rows, type);
UMat dst = _dst.getUMat();
String kernelName("transpose");
bool inplace = dst.u == src.u;
if (inplace)
{
CV_Assert(dst.cols == dst.rows);
kernelName += "_inplace";
}
else
{
// check required local memory size
size_t required_local_memory = (size_t) TILE_DIM*(TILE_DIM+1)*CV_ELEM_SIZE(type);
if (required_local_memory > ocl::Device::getDefault().localMemSize())
return false;
}
ocl::Kernel k(kernelName.c_str(), ocl::core::transpose_oclsrc,
format("-D T=%s -D T1=%s -D cn=%d -D TILE_DIM=%d -D BLOCK_ROWS=%d -D rowsPerWI=%d%s",
ocl::memopTypeToStr(type), ocl::memopTypeToStr(depth),
cn, TILE_DIM, BLOCK_ROWS, rowsPerWI, inplace ? " -D INPLACE" : ""));
if (k.empty())
return false;
if (inplace)
k.args(ocl::KernelArg::ReadWriteNoSize(dst), dst.rows);
else
k.args(ocl::KernelArg::ReadOnly(src),
ocl::KernelArg::WriteOnlyNoSize(dst));
size_t localsize[2] = { TILE_DIM, BLOCK_ROWS };
size_t globalsize[2] = { (size_t)src.cols, inplace ? ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI : (divUp((size_t)src.rows, TILE_DIM) * BLOCK_ROWS) };
if (inplace && dev.isIntel())
{
localsize[0] = 16;
localsize[1] = dev.maxWorkGroupSize() / localsize[0];
}
return k.run(2, globalsize, localsize, false);
}
#endif
#ifdef HAVE_IPP
static bool ipp_transpose( Mat &src, Mat &dst )
{
CV_INSTRUMENT_REGION_IPP();
int type = src.type();
typedef IppStatus (CV_STDCALL * IppiTranspose)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize);
typedef IppStatus (CV_STDCALL * IppiTransposeI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize);
IppiTranspose ippiTranspose = 0;
IppiTransposeI ippiTranspose_I = 0;
if (dst.data == src.data && dst.cols == dst.rows)
{
CV_SUPPRESS_DEPRECATED_START
ippiTranspose_I =
type == CV_8UC1 ? (IppiTransposeI)ippiTranspose_8u_C1IR :
type == CV_8UC3 ? (IppiTransposeI)ippiTranspose_8u_C3IR :
type == CV_8UC4 ? (IppiTransposeI)ippiTranspose_8u_C4IR :
type == CV_16UC1 ? (IppiTransposeI)ippiTranspose_16u_C1IR :
type == CV_16UC3 ? (IppiTransposeI)ippiTranspose_16u_C3IR :
type == CV_16UC4 ? (IppiTransposeI)ippiTranspose_16u_C4IR :
type == CV_16SC1 ? (IppiTransposeI)ippiTranspose_16s_C1IR :
type == CV_16SC3 ? (IppiTransposeI)ippiTranspose_16s_C3IR :
type == CV_16SC4 ? (IppiTransposeI)ippiTranspose_16s_C4IR :
type == CV_32SC1 ? (IppiTransposeI)ippiTranspose_32s_C1IR :
type == CV_32SC3 ? (IppiTransposeI)ippiTranspose_32s_C3IR :
type == CV_32SC4 ? (IppiTransposeI)ippiTranspose_32s_C4IR :
type == CV_32FC1 ? (IppiTransposeI)ippiTranspose_32f_C1IR :
type == CV_32FC3 ? (IppiTransposeI)ippiTranspose_32f_C3IR :
type == CV_32FC4 ? (IppiTransposeI)ippiTranspose_32f_C4IR : 0;
CV_SUPPRESS_DEPRECATED_END
}
else
{
ippiTranspose =
type == CV_8UC1 ? (IppiTranspose)ippiTranspose_8u_C1R :
type == CV_8UC3 ? (IppiTranspose)ippiTranspose_8u_C3R :
type == CV_8UC4 ? (IppiTranspose)ippiTranspose_8u_C4R :
type == CV_16UC1 ? (IppiTranspose)ippiTranspose_16u_C1R :
type == CV_16UC3 ? (IppiTranspose)ippiTranspose_16u_C3R :
type == CV_16UC4 ? (IppiTranspose)ippiTranspose_16u_C4R :
type == CV_16SC1 ? (IppiTranspose)ippiTranspose_16s_C1R :
type == CV_16SC3 ? (IppiTranspose)ippiTranspose_16s_C3R :
type == CV_16SC4 ? (IppiTranspose)ippiTranspose_16s_C4R :
type == CV_32SC1 ? (IppiTranspose)ippiTranspose_32s_C1R :
type == CV_32SC3 ? (IppiTranspose)ippiTranspose_32s_C3R :
type == CV_32SC4 ? (IppiTranspose)ippiTranspose_32s_C4R :
type == CV_32FC1 ? (IppiTranspose)ippiTranspose_32f_C1R :
type == CV_32FC3 ? (IppiTranspose)ippiTranspose_32f_C3R :
type == CV_32FC4 ? (IppiTranspose)ippiTranspose_32f_C4R : 0;
}
IppiSize roiSize = { src.cols, src.rows };
if (ippiTranspose != 0)
{
if (CV_INSTRUMENT_FUN_IPP(ippiTranspose, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize) >= 0)
return true;
}
else if (ippiTranspose_I != 0)
{
if (CV_INSTRUMENT_FUN_IPP(ippiTranspose_I, dst.ptr(), (int)dst.step, roiSize) >= 0)
return true;
}
return false;
}
#endif
}
void cv::transpose( InputArray _src, OutputArray _dst )
{
CV_INSTRUMENT_REGION();
int type = _src.type(), esz = CV_ELEM_SIZE(type);
CV_Assert( _src.dims() <= 2 && esz <= 32 );
CV_OCL_RUN(_dst.isUMat(),
ocl_transpose(_src, _dst))
Mat src = _src.getMat();
if( src.empty() )
{
_dst.release();
return;
}
_dst.create(src.cols, src.rows, src.type());
Mat dst = _dst.getMat();
// handle the case of single-column/single-row matrices, stored in STL vectors.
if( src.rows != dst.cols || src.cols != dst.rows )
{
CV_Assert( src.size() == dst.size() && (src.cols == 1 || src.rows == 1) );
src.copyTo(dst);
return;
}
CV_IPP_RUN_FAST(ipp_transpose(src, dst))
if( dst.data == src.data )
{
TransposeInplaceFunc func = transposeInplaceTab[esz];
CV_Assert( func != 0 );
CV_Assert( dst.cols == dst.rows );
func( dst.ptr(), dst.step, dst.rows );
}
else
{
TransposeFunc func = transposeTab[esz];
CV_Assert( func != 0 );
func( src.ptr(), src.step, dst.ptr(), dst.step, src.size() );
}
}
////////////////////////////////////// completeSymm /////////////////////////////////////////
+770
View File
@@ -0,0 +1,770 @@
// 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"
namespace cv {
////////////////////////////////////// transpose /////////////////////////////////////////
template<typename T> static void
transpose_( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz )
{
int i=0, j, m = sz.width, n = sz.height;
#if CV_ENABLE_UNROLLED
for(; i <= m - 4; i += 4 )
{
T* d0 = (T*)(dst + dstep*i);
T* d1 = (T*)(dst + dstep*(i+1));
T* d2 = (T*)(dst + dstep*(i+2));
T* d3 = (T*)(dst + dstep*(i+3));
for( j = 0; j <= n - 4; j += 4 )
{
const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
d1[j] = s0[1]; d1[j+1] = s1[1]; d1[j+2] = s2[1]; d1[j+3] = s3[1];
d2[j] = s0[2]; d2[j+1] = s1[2]; d2[j+2] = s2[2]; d2[j+3] = s3[2];
d3[j] = s0[3]; d3[j+1] = s1[3]; d3[j+2] = s2[3]; d3[j+3] = s3[3];
}
for( ; j < n; j++ )
{
const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
d0[j] = s0[0]; d1[j] = s0[1]; d2[j] = s0[2]; d3[j] = s0[3];
}
}
#endif
for( ; i < m; i++ )
{
T* d0 = (T*)(dst + dstep*i);
j = 0;
#if CV_ENABLE_UNROLLED
for(; j <= n - 4; j += 4 )
{
const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
}
#endif
for( ; j < n; j++ )
{
const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
d0[j] = s0[0];
}
}
}
template<typename T> static void
transposeI_( uchar* data, size_t step, int n )
{
for( int i = 0; i < n; i++ )
{
T* row = (T*)(data + step*i);
uchar* data1 = data + i*sizeof(T);
for( int j = i+1; j < n; j++ )
std::swap( row[j], *(T*)(data1 + step*j) );
}
}
typedef void (*TransposeFunc)( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz );
typedef void (*TransposeInplaceFunc)( uchar* data, size_t step, int n );
#define DEF_TRANSPOSE_FUNC(suffix, type) \
static void transpose_##suffix( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ) \
{ transpose_<type>(src, sstep, dst, dstep, sz); } \
\
static void transposeI_##suffix( uchar* data, size_t step, int n ) \
{ transposeI_<type>(data, step, n); }
DEF_TRANSPOSE_FUNC(8u, uchar)
DEF_TRANSPOSE_FUNC(16u, ushort)
DEF_TRANSPOSE_FUNC(8uC3, Vec3b)
DEF_TRANSPOSE_FUNC(32s, int)
DEF_TRANSPOSE_FUNC(16uC3, Vec3s)
DEF_TRANSPOSE_FUNC(32sC2, Vec2i)
DEF_TRANSPOSE_FUNC(32sC3, Vec3i)
DEF_TRANSPOSE_FUNC(32sC4, Vec4i)
DEF_TRANSPOSE_FUNC(32sC6, Vec6i)
DEF_TRANSPOSE_FUNC(32sC8, Vec8i)
static TransposeFunc transposeTab[] =
{
0, transpose_8u, transpose_16u, transpose_8uC3, transpose_32s, 0, transpose_16uC3, 0,
transpose_32sC2, 0, 0, 0, transpose_32sC3, 0, 0, 0, transpose_32sC4,
0, 0, 0, 0, 0, 0, 0, transpose_32sC6, 0, 0, 0, 0, 0, 0, 0, transpose_32sC8
};
static TransposeInplaceFunc transposeInplaceTab[] =
{
0, transposeI_8u, transposeI_16u, transposeI_8uC3, transposeI_32s, 0, transposeI_16uC3, 0,
transposeI_32sC2, 0, 0, 0, transposeI_32sC3, 0, 0, 0, transposeI_32sC4,
0, 0, 0, 0, 0, 0, 0, transposeI_32sC6, 0, 0, 0, 0, 0, 0, 0, transposeI_32sC8
};
#ifdef HAVE_OPENCL
static bool ocl_transpose( InputArray _src, OutputArray _dst )
{
const ocl::Device & dev = ocl::Device::getDefault();
const int TILE_DIM = 32, BLOCK_ROWS = 8;
int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type),
rowsPerWI = dev.isIntel() ? 4 : 1;
UMat src = _src.getUMat();
_dst.create(src.cols, src.rows, type);
UMat dst = _dst.getUMat();
String kernelName("transpose");
bool inplace = dst.u == src.u;
if (inplace)
{
CV_Assert(dst.cols == dst.rows);
kernelName += "_inplace";
}
else
{
// check required local memory size
size_t required_local_memory = (size_t) TILE_DIM*(TILE_DIM+1)*CV_ELEM_SIZE(type);
if (required_local_memory > ocl::Device::getDefault().localMemSize())
return false;
}
ocl::Kernel k(kernelName.c_str(), ocl::core::transpose_oclsrc,
format("-D T=%s -D T1=%s -D cn=%d -D TILE_DIM=%d -D BLOCK_ROWS=%d -D rowsPerWI=%d%s",
ocl::memopTypeToStr(type), ocl::memopTypeToStr(depth),
cn, TILE_DIM, BLOCK_ROWS, rowsPerWI, inplace ? " -D INPLACE" : ""));
if (k.empty())
return false;
if (inplace)
k.args(ocl::KernelArg::ReadWriteNoSize(dst), dst.rows);
else
k.args(ocl::KernelArg::ReadOnly(src),
ocl::KernelArg::WriteOnlyNoSize(dst));
size_t localsize[2] = { TILE_DIM, BLOCK_ROWS };
size_t globalsize[2] = { (size_t)src.cols, inplace ? ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI : (divUp((size_t)src.rows, TILE_DIM) * BLOCK_ROWS) };
if (inplace && dev.isIntel())
{
localsize[0] = 16;
localsize[1] = dev.maxWorkGroupSize() / localsize[0];
}
return k.run(2, globalsize, localsize, false);
}
#endif
#ifdef HAVE_IPP
static bool ipp_transpose( Mat &src, Mat &dst )
{
CV_INSTRUMENT_REGION_IPP();
int type = src.type();
typedef IppStatus (CV_STDCALL * IppiTranspose)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize);
typedef IppStatus (CV_STDCALL * IppiTransposeI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize);
IppiTranspose ippiTranspose = 0;
IppiTransposeI ippiTranspose_I = 0;
if (dst.data == src.data && dst.cols == dst.rows)
{
CV_SUPPRESS_DEPRECATED_START
ippiTranspose_I =
type == CV_8UC1 ? (IppiTransposeI)ippiTranspose_8u_C1IR :
type == CV_8UC3 ? (IppiTransposeI)ippiTranspose_8u_C3IR :
type == CV_8UC4 ? (IppiTransposeI)ippiTranspose_8u_C4IR :
type == CV_16UC1 ? (IppiTransposeI)ippiTranspose_16u_C1IR :
type == CV_16UC3 ? (IppiTransposeI)ippiTranspose_16u_C3IR :
type == CV_16UC4 ? (IppiTransposeI)ippiTranspose_16u_C4IR :
type == CV_16SC1 ? (IppiTransposeI)ippiTranspose_16s_C1IR :
type == CV_16SC3 ? (IppiTransposeI)ippiTranspose_16s_C3IR :
type == CV_16SC4 ? (IppiTransposeI)ippiTranspose_16s_C4IR :
type == CV_32SC1 ? (IppiTransposeI)ippiTranspose_32s_C1IR :
type == CV_32SC3 ? (IppiTransposeI)ippiTranspose_32s_C3IR :
type == CV_32SC4 ? (IppiTransposeI)ippiTranspose_32s_C4IR :
type == CV_32FC1 ? (IppiTransposeI)ippiTranspose_32f_C1IR :
type == CV_32FC3 ? (IppiTransposeI)ippiTranspose_32f_C3IR :
type == CV_32FC4 ? (IppiTransposeI)ippiTranspose_32f_C4IR : 0;
CV_SUPPRESS_DEPRECATED_END
}
else
{
ippiTranspose =
type == CV_8UC1 ? (IppiTranspose)ippiTranspose_8u_C1R :
type == CV_8UC3 ? (IppiTranspose)ippiTranspose_8u_C3R :
type == CV_8UC4 ? (IppiTranspose)ippiTranspose_8u_C4R :
type == CV_16UC1 ? (IppiTranspose)ippiTranspose_16u_C1R :
type == CV_16UC3 ? (IppiTranspose)ippiTranspose_16u_C3R :
type == CV_16UC4 ? (IppiTranspose)ippiTranspose_16u_C4R :
type == CV_16SC1 ? (IppiTranspose)ippiTranspose_16s_C1R :
type == CV_16SC3 ? (IppiTranspose)ippiTranspose_16s_C3R :
type == CV_16SC4 ? (IppiTranspose)ippiTranspose_16s_C4R :
type == CV_32SC1 ? (IppiTranspose)ippiTranspose_32s_C1R :
type == CV_32SC3 ? (IppiTranspose)ippiTranspose_32s_C3R :
type == CV_32SC4 ? (IppiTranspose)ippiTranspose_32s_C4R :
type == CV_32FC1 ? (IppiTranspose)ippiTranspose_32f_C1R :
type == CV_32FC3 ? (IppiTranspose)ippiTranspose_32f_C3R :
type == CV_32FC4 ? (IppiTranspose)ippiTranspose_32f_C4R : 0;
}
IppiSize roiSize = { src.cols, src.rows };
if (ippiTranspose != 0)
{
if (CV_INSTRUMENT_FUN_IPP(ippiTranspose, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize) >= 0)
return true;
}
else if (ippiTranspose_I != 0)
{
if (CV_INSTRUMENT_FUN_IPP(ippiTranspose_I, dst.ptr(), (int)dst.step, roiSize) >= 0)
return true;
}
return false;
}
#endif
void transpose( InputArray _src, OutputArray _dst )
{
CV_INSTRUMENT_REGION();
int type = _src.type(), esz = CV_ELEM_SIZE(type);
CV_Assert( _src.dims() <= 2 && esz <= 32 );
CV_OCL_RUN(_dst.isUMat(),
ocl_transpose(_src, _dst))
Mat src = _src.getMat();
if( src.empty() )
{
_dst.release();
return;
}
_dst.create(src.cols, src.rows, src.type());
Mat dst = _dst.getMat();
// handle the case of single-column/single-row matrices, stored in STL vectors.
if( src.rows != dst.cols || src.cols != dst.rows )
{
CV_Assert( src.size() == dst.size() && (src.cols == 1 || src.rows == 1) );
src.copyTo(dst);
return;
}
CV_IPP_RUN_FAST(ipp_transpose(src, dst))
if( dst.data == src.data )
{
TransposeInplaceFunc func = transposeInplaceTab[esz];
CV_Assert( func != 0 );
CV_Assert( dst.cols == dst.rows );
func( dst.ptr(), dst.step, dst.rows );
}
else
{
TransposeFunc func = transposeTab[esz];
CV_Assert( func != 0 );
func( src.ptr(), src.step, dst.ptr(), dst.step, src.size() );
}
}
#if CV_SIMD128
template<typename V> CV_ALWAYS_INLINE void flipHoriz_single( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
{
typedef typename V::lane_type T;
int end = (int)(size.width*esz);
int width = (end + 1)/2;
int width_1 = width & -v_uint8x16::nlanes;
int i, j;
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(T)>(src, dst));
#endif
for( ; size.height--; src += sstep, dst += dstep )
{
for( i = 0, j = end; i < width_1; i += v_uint8x16::nlanes, j -= v_uint8x16::nlanes )
{
V t0, t1;
t0 = v_load((T*)((uchar*)src + i));
t1 = v_load((T*)((uchar*)src + j - v_uint8x16::nlanes));
t0 = v_reverse(t0);
t1 = v_reverse(t1);
v_store((T*)(dst + j - v_uint8x16::nlanes), t0);
v_store((T*)(dst + i), t1);
}
if (isAligned<sizeof(T)>(src, dst))
{
for ( ; i < width; i += sizeof(T), j -= sizeof(T) )
{
T t0, t1;
t0 = *((T*)((uchar*)src + i));
t1 = *((T*)((uchar*)src + j - sizeof(T)));
*((T*)(dst + j - sizeof(T))) = t0;
*((T*)(dst + i)) = t1;
}
}
else
{
for ( ; i < width; i += sizeof(T), j -= sizeof(T) )
{
for (int k = 0; k < (int)sizeof(T); k++)
{
uchar t0, t1;
t0 = *((uchar*)src + i + k);
t1 = *((uchar*)src + j + k - sizeof(T));
*(dst + j + k - sizeof(T)) = t0;
*(dst + i + k) = t1;
}
}
}
}
}
template<typename T1, typename T2> CV_ALWAYS_INLINE void flipHoriz_double( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
{
int end = (int)(size.width*esz);
int width = (end + 1)/2;
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(T1)>(src, dst));
CV_Assert(isAligned<sizeof(T2)>(src, dst));
#endif
for( ; size.height--; src += sstep, dst += dstep )
{
for ( int i = 0, j = end; i < width; i += sizeof(T1) + sizeof(T2), j -= sizeof(T1) + sizeof(T2) )
{
T1 t0, t1;
T2 t2, t3;
t0 = *((T1*)((uchar*)src + i));
t2 = *((T2*)((uchar*)src + i + sizeof(T1)));
t1 = *((T1*)((uchar*)src + j - sizeof(T1) - sizeof(T2)));
t3 = *((T2*)((uchar*)src + j - sizeof(T2)));
*((T1*)(dst + j - sizeof(T1) - sizeof(T2))) = t0;
*((T2*)(dst + j - sizeof(T2))) = t2;
*((T1*)(dst + i)) = t1;
*((T2*)(dst + i + sizeof(T1))) = t3;
}
}
}
#endif
static void
flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
{
#if CV_SIMD
#if CV_STRONG_ALIGNMENT
size_t alignmentMark = ((size_t)src)|((size_t)dst)|sstep|dstep;
#endif
if (esz == 2 * v_uint8x16::nlanes)
{
int end = (int)(size.width*esz);
int width = end/2;
for( ; size.height--; src += sstep, dst += dstep )
{
for( int i = 0, j = end - 2 * v_uint8x16::nlanes; i < width; i += 2 * v_uint8x16::nlanes, j -= 2 * v_uint8x16::nlanes )
{
#if CV_SIMD256
v_uint8x32 t0, t1;
t0 = v256_load((uchar*)src + i);
t1 = v256_load((uchar*)src + j);
v_store(dst + j, t0);
v_store(dst + i, t1);
#else
v_uint8x16 t0, t1, t2, t3;
t0 = v_load((uchar*)src + i);
t1 = v_load((uchar*)src + i + v_uint8x16::nlanes);
t2 = v_load((uchar*)src + j);
t3 = v_load((uchar*)src + j + v_uint8x16::nlanes);
v_store(dst + j, t0);
v_store(dst + j + v_uint8x16::nlanes, t1);
v_store(dst + i, t2);
v_store(dst + i + v_uint8x16::nlanes, t3);
#endif
}
}
}
else if (esz == v_uint8x16::nlanes)
{
int end = (int)(size.width*esz);
int width = end/2;
for( ; size.height--; src += sstep, dst += dstep )
{
for( int i = 0, j = end - v_uint8x16::nlanes; i < width; i += v_uint8x16::nlanes, j -= v_uint8x16::nlanes )
{
v_uint8x16 t0, t1;
t0 = v_load((uchar*)src + i);
t1 = v_load((uchar*)src + j);
v_store(dst + j, t0);
v_store(dst + i, t1);
}
}
}
else if (esz == 8
#if CV_STRONG_ALIGNMENT
&& isAligned<sizeof(uint64)>(alignmentMark)
#endif
)
{
flipHoriz_single<v_uint64x2>(src, sstep, dst, dstep, size, esz);
}
else if (esz == 4
#if CV_STRONG_ALIGNMENT
&& isAligned<sizeof(unsigned)>(alignmentMark)
#endif
)
{
flipHoriz_single<v_uint32x4>(src, sstep, dst, dstep, size, esz);
}
else if (esz == 2
#if CV_STRONG_ALIGNMENT
&& isAligned<sizeof(ushort)>(alignmentMark)
#endif
)
{
flipHoriz_single<v_uint16x8>(src, sstep, dst, dstep, size, esz);
}
else if (esz == 1)
{
flipHoriz_single<v_uint8x16>(src, sstep, dst, dstep, size, esz);
}
else if (esz == 24
#if CV_STRONG_ALIGNMENT
&& isAligned<sizeof(uint64_t)>(alignmentMark)
#endif
)
{
int end = (int)(size.width*esz);
int width = (end + 1)/2;
for( ; size.height--; src += sstep, dst += dstep )
{
for ( int i = 0, j = end; i < width; i += v_uint8x16::nlanes + sizeof(uint64_t), j -= v_uint8x16::nlanes + sizeof(uint64_t) )
{
v_uint8x16 t0, t1;
uint64_t t2, t3;
t0 = v_load((uchar*)src + i);
t2 = *((uint64_t*)((uchar*)src + i + v_uint8x16::nlanes));
t1 = v_load((uchar*)src + j - v_uint8x16::nlanes - sizeof(uint64_t));
t3 = *((uint64_t*)((uchar*)src + j - sizeof(uint64_t)));
v_store(dst + j - v_uint8x16::nlanes - sizeof(uint64_t), t0);
*((uint64_t*)(dst + j - sizeof(uint64_t))) = t2;
v_store(dst + i, t1);
*((uint64_t*)(dst + i + v_uint8x16::nlanes)) = t3;
}
}
}
#if !CV_STRONG_ALIGNMENT
else if (esz == 12)
{
flipHoriz_double<uint64_t,uint>(src, sstep, dst, dstep, size, esz);
}
else if (esz == 6)
{
flipHoriz_double<uint,ushort>(src, sstep, dst, dstep, size, esz);
}
else if (esz == 3)
{
flipHoriz_double<ushort,uchar>(src, sstep, dst, dstep, size, esz);
}
#endif
else
#endif // CV_SIMD
{
int i, j, limit = (int)(((size.width + 1)/2)*esz);
AutoBuffer<int> _tab(size.width*esz);
int* tab = _tab.data();
for( i = 0; i < size.width; i++ )
for( size_t k = 0; k < esz; k++ )
tab[i*esz + k] = (int)((size.width - i - 1)*esz + k);
for( ; size.height--; src += sstep, dst += dstep )
{
for( i = 0; i < limit; i++ )
{
j = tab[i];
uchar t0 = src[i], t1 = src[j];
dst[i] = t1; dst[j] = t0;
}
}
}
}
static void
flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, size_t esz )
{
const uchar* src1 = src0 + (size.height - 1)*sstep;
uchar* dst1 = dst0 + (size.height - 1)*dstep;
size.width *= (int)esz;
for( int y = 0; y < (size.height + 1)/2; y++, src0 += sstep, src1 -= sstep,
dst0 += dstep, dst1 -= dstep )
{
int i = 0;
#if CV_SIMD
#if CV_STRONG_ALIGNMENT
if (isAligned<sizeof(int)>(src0, src1, dst0, dst1))
#endif
{
for (; i <= size.width - CV_SIMD_WIDTH; i += CV_SIMD_WIDTH)
{
v_int32 t0 = vx_load((int*)(src0 + i));
v_int32 t1 = vx_load((int*)(src1 + i));
v_store((int*)(dst0 + i), t1);
v_store((int*)(dst1 + i), t0);
}
}
#if CV_STRONG_ALIGNMENT
else
{
for (; i <= size.width - CV_SIMD_WIDTH; i += CV_SIMD_WIDTH)
{
v_uint8 t0 = vx_load(src0 + i);
v_uint8 t1 = vx_load(src1 + i);
v_store(dst0 + i, t1);
v_store(dst1 + i, t0);
}
}
#endif
#endif
if (isAligned<sizeof(int)>(src0, src1, dst0, dst1))
{
for( ; i <= size.width - 16; i += 16 )
{
int t0 = ((int*)(src0 + i))[0];
int t1 = ((int*)(src1 + i))[0];
((int*)(dst0 + i))[0] = t1;
((int*)(dst1 + i))[0] = t0;
t0 = ((int*)(src0 + i))[1];
t1 = ((int*)(src1 + i))[1];
((int*)(dst0 + i))[1] = t1;
((int*)(dst1 + i))[1] = t0;
t0 = ((int*)(src0 + i))[2];
t1 = ((int*)(src1 + i))[2];
((int*)(dst0 + i))[2] = t1;
((int*)(dst1 + i))[2] = t0;
t0 = ((int*)(src0 + i))[3];
t1 = ((int*)(src1 + i))[3];
((int*)(dst0 + i))[3] = t1;
((int*)(dst1 + i))[3] = t0;
}
for( ; i <= size.width - 4; i += 4 )
{
int t0 = ((int*)(src0 + i))[0];
int t1 = ((int*)(src1 + i))[0];
((int*)(dst0 + i))[0] = t1;
((int*)(dst1 + i))[0] = t0;
}
}
for( ; i < size.width; i++ )
{
uchar t0 = src0[i];
uchar t1 = src1[i];
dst0[i] = t1;
dst1[i] = t0;
}
}
}
#ifdef HAVE_OPENCL
enum { FLIP_COLS = 1 << 0, FLIP_ROWS = 1 << 1, FLIP_BOTH = FLIP_ROWS | FLIP_COLS };
static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode )
{
CV_Assert(flipCode >= -1 && flipCode <= 1);
const ocl::Device & dev = ocl::Device::getDefault();
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
flipType, kercn = std::min(ocl::predictOptimalVectorWidth(_src, _dst), 4);
bool doubleSupport = dev.doubleFPConfig() > 0;
if (!doubleSupport && depth == CV_64F)
kercn = cn;
if (cn > 4)
return false;
const char * kernelName;
if (flipCode == 0)
kernelName = "arithm_flip_rows", flipType = FLIP_ROWS;
else if (flipCode > 0)
kernelName = "arithm_flip_cols", flipType = FLIP_COLS;
else
kernelName = "arithm_flip_rows_cols", flipType = FLIP_BOTH;
int pxPerWIy = (dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU)) ? 4 : 1;
kercn = (cn!=3 || flipType == FLIP_ROWS) ? std::max(kercn, cn) : cn;
ocl::Kernel k(kernelName, ocl::core::flip_oclsrc,
format( "-D T=%s -D T1=%s -D DEPTH=%d -D cn=%d -D PIX_PER_WI_Y=%d -D kercn=%d",
kercn != cn ? ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)) : ocl::vecopTypeToStr(CV_MAKE_TYPE(depth, kercn)),
kercn != cn ? ocl::typeToStr(depth) : ocl::vecopTypeToStr(depth), depth, cn, pxPerWIy, kercn));
if (k.empty())
return false;
Size size = _src.size();
_dst.create(size, type);
UMat src = _src.getUMat(), dst = _dst.getUMat();
int cols = size.width * cn / kercn, rows = size.height;
cols = flipType == FLIP_COLS ? (cols + 1) >> 1 : cols;
rows = flipType & FLIP_ROWS ? (rows + 1) >> 1 : rows;
k.args(ocl::KernelArg::ReadOnlyNoSize(src),
ocl::KernelArg::WriteOnly(dst, cn, kercn), rows, cols);
size_t maxWorkGroupSize = dev.maxWorkGroupSize();
CV_Assert(maxWorkGroupSize % 4 == 0);
size_t globalsize[2] = { (size_t)cols, ((size_t)rows + pxPerWIy - 1) / pxPerWIy },
localsize[2] = { maxWorkGroupSize / 4, 4 };
return k.run(2, globalsize, (flipType == FLIP_COLS) && !dev.isIntel() ? localsize : NULL, false);
}
#endif
#if defined HAVE_IPP
static bool ipp_flip(Mat &src, Mat &dst, int flip_mode)
{
#ifdef HAVE_IPP_IW
CV_INSTRUMENT_REGION_IPP();
// Details: https://github.com/opencv/opencv/issues/12943
if (flip_mode <= 0 /* swap rows */
&& cv::ipp::getIppTopFeatures() != ippCPUID_SSE42
&& (int64_t)(src.total()) * src.elemSize() >= CV_BIG_INT(0x80000000)/*2Gb*/
)
return false;
IppiAxis ippMode;
if(flip_mode < 0)
ippMode = ippAxsBoth;
else if(flip_mode == 0)
ippMode = ippAxsHorizontal;
else
ippMode = ippAxsVertical;
try
{
::ipp::IwiImage iwSrc = ippiGetImage(src);
::ipp::IwiImage iwDst = ippiGetImage(dst);
CV_INSTRUMENT_FUN_IPP(::ipp::iwiMirror, iwSrc, iwDst, ippMode);
}
catch(const ::ipp::IwException &)
{
return false;
}
return true;
#else
CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(flip_mode);
return false;
#endif
}
#endif
void flip( InputArray _src, OutputArray _dst, int flip_mode )
{
CV_INSTRUMENT_REGION();
CV_Assert( _src.dims() <= 2 );
Size size = _src.size();
if (flip_mode < 0)
{
if (size.width == 1)
flip_mode = 0;
if (size.height == 1)
flip_mode = 1;
}
if ((size.width == 1 && flip_mode > 0) ||
(size.height == 1 && flip_mode == 0))
{
return _src.copyTo(_dst);
}
CV_OCL_RUN( _dst.isUMat(), ocl_flip(_src, _dst, flip_mode))
Mat src = _src.getMat();
int type = src.type();
_dst.create( size, type );
Mat dst = _dst.getMat();
CV_IPP_RUN_FAST(ipp_flip(src, dst, flip_mode));
size_t esz = CV_ELEM_SIZE(type);
if( flip_mode <= 0 )
flipVert( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
else
flipHoriz( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
if( flip_mode < 0 )
flipHoriz( dst.ptr(), dst.step, dst.ptr(), dst.step, dst.size(), esz );
}
void rotate(InputArray _src, OutputArray _dst, int rotateMode)
{
CV_Assert(_src.dims() <= 2);
switch (rotateMode)
{
case ROTATE_90_CLOCKWISE:
transpose(_src, _dst);
flip(_dst, _dst, 1);
break;
case ROTATE_180:
flip(_src, _dst, -1);
break;
case ROTATE_90_COUNTERCLOCKWISE:
transpose(_src, _dst);
flip(_dst, _dst, 0);
break;
default:
break;
}
}
} // namespace
+61
View File
@@ -316,6 +316,7 @@ void _InputArray::getUMatVector(std::vector<UMat>& umv) const
cuda::GpuMat _InputArray::getGpuMat() const
{
#ifdef HAVE_CUDA
int k = kind();
if (k == CUDA_GPU_MAT)
@@ -339,14 +340,22 @@ cuda::GpuMat _InputArray::getGpuMat() const
return cuda::GpuMat();
CV_Error(cv::Error::StsNotImplemented, "getGpuMat is available only for cuda::GpuMat and cuda::HostMem");
#else
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
#endif
}
void _InputArray::getGpuMatVector(std::vector<cuda::GpuMat>& gpumv) const
{
#ifdef HAVE_CUDA
int k = kind();
if (k == STD_VECTOR_CUDA_GPU_MAT)
{
gpumv = *(std::vector<cuda::GpuMat>*)obj;
}
#else
CV_UNUSED(gpumv);
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
#endif
}
ogl::Buffer _InputArray::getOGlBuffer() const
{
@@ -457,11 +466,15 @@ Size _InputArray::size(int i) const
if (k == STD_VECTOR_CUDA_GPU_MAT)
{
#ifdef HAVE_CUDA
const std::vector<cuda::GpuMat>& vv = *(const std::vector<cuda::GpuMat>*)obj;
if (i < 0)
return vv.empty() ? Size() : Size((int)vv.size(), 1);
CV_Assert(i < (int)vv.size());
return vv[i].size();
#else
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
#endif
}
if( k == STD_VECTOR_UMAT )
@@ -795,6 +808,7 @@ int _InputArray::type(int i) const
if (k == STD_VECTOR_CUDA_GPU_MAT)
{
#ifdef HAVE_CUDA
const std::vector<cuda::GpuMat>& vv = *(const std::vector<cuda::GpuMat>*)obj;
if (vv.empty())
{
@@ -803,6 +817,9 @@ int _InputArray::type(int i) const
}
CV_Assert(i < (int)vv.size());
return vv[i >= 0 ? i : 0].type();
#else
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
#endif
}
if( k == OPENGL_BUFFER )
@@ -1164,22 +1181,34 @@ void _OutputArray::create(Size _sz, int mtype, int i, bool allowTransposed, int
{
CV_Assert(!fixedSize() || ((cuda::GpuMat*)obj)->size() == _sz);
CV_Assert(!fixedType() || ((cuda::GpuMat*)obj)->type() == mtype);
#ifdef HAVE_CUDA
((cuda::GpuMat*)obj)->create(_sz, mtype);
return;
#else
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
#endif
}
if( k == OPENGL_BUFFER && i < 0 && !allowTransposed && fixedDepthMask == 0 )
{
CV_Assert(!fixedSize() || ((ogl::Buffer*)obj)->size() == _sz);
CV_Assert(!fixedType() || ((ogl::Buffer*)obj)->type() == mtype);
#ifdef HAVE_OPENGL
((ogl::Buffer*)obj)->create(_sz, mtype);
return;
#else
CV_Error(Error::StsNotImplemented, "OpenGL support is not enabled in this OpenCV build (missing HAVE_OPENGL)");
#endif
}
if( k == CUDA_HOST_MEM && i < 0 && !allowTransposed && fixedDepthMask == 0 )
{
CV_Assert(!fixedSize() || ((cuda::HostMem*)obj)->size() == _sz);
CV_Assert(!fixedType() || ((cuda::HostMem*)obj)->type() == mtype);
#ifdef HAVE_CUDA
((cuda::HostMem*)obj)->create(_sz, mtype);
return;
#else
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
#endif
}
int sizes[] = {_sz.height, _sz.width};
create(2, sizes, mtype, i, allowTransposed, fixedDepthMask);
@@ -1206,22 +1235,34 @@ void _OutputArray::create(int _rows, int _cols, int mtype, int i, bool allowTran
{
CV_Assert(!fixedSize() || ((cuda::GpuMat*)obj)->size() == Size(_cols, _rows));
CV_Assert(!fixedType() || ((cuda::GpuMat*)obj)->type() == mtype);
#ifdef HAVE_CUDA
((cuda::GpuMat*)obj)->create(_rows, _cols, mtype);
return;
#else
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
#endif
}
if( k == OPENGL_BUFFER && i < 0 && !allowTransposed && fixedDepthMask == 0 )
{
CV_Assert(!fixedSize() || ((ogl::Buffer*)obj)->size() == Size(_cols, _rows));
CV_Assert(!fixedType() || ((ogl::Buffer*)obj)->type() == mtype);
#ifdef HAVE_OPENGL
((ogl::Buffer*)obj)->create(_rows, _cols, mtype);
return;
#else
CV_Error(Error::StsNotImplemented, "OpenGL support is not enabled in this OpenCV build (missing HAVE_OPENGL)");
#endif
}
if( k == CUDA_HOST_MEM && i < 0 && !allowTransposed && fixedDepthMask == 0 )
{
CV_Assert(!fixedSize() || ((cuda::HostMem*)obj)->size() == Size(_cols, _rows));
CV_Assert(!fixedType() || ((cuda::HostMem*)obj)->type() == mtype);
#ifdef HAVE_CUDA
((cuda::HostMem*)obj)->create(_rows, _cols, mtype);
return;
#else
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
#endif
}
int sizes[] = {_rows, _cols};
create(2, sizes, mtype, i, allowTransposed, fixedDepthMask);
@@ -1644,20 +1685,32 @@ void _OutputArray::release() const
if( k == CUDA_GPU_MAT )
{
#ifdef HAVE_CUDA
((cuda::GpuMat*)obj)->release();
return;
#else
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
#endif
}
if( k == CUDA_HOST_MEM )
{
#ifdef HAVE_CUDA
((cuda::HostMem*)obj)->release();
return;
#else
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
#endif
}
if( k == OPENGL_BUFFER )
{
#ifdef HAVE_OPENGL
((ogl::Buffer*)obj)->release();
return;
#else
CV_Error(Error::StsNotImplemented, "OpenGL support is not enabled in this OpenCV build (missing HAVE_OPENGL)");
#endif
}
if( k == NONE )
@@ -1688,8 +1741,12 @@ void _OutputArray::release() const
}
if (k == STD_VECTOR_CUDA_GPU_MAT)
{
#ifdef HAVE_CUDA
((std::vector<cuda::GpuMat>*)obj)->clear();
return;
#else
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
#endif
}
CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
}
@@ -1797,9 +1854,13 @@ void _OutputArray::setTo(const _InputArray& arr, const _InputArray & mask) const
((UMat*)obj)->setTo(arr, mask);
else if( k == CUDA_GPU_MAT )
{
#ifdef HAVE_CUDA
Mat value = arr.getMat();
CV_Assert( checkScalar(value, type(), arr.kind(), _InputArray::CUDA_GPU_MAT) );
((cuda::GpuMat*)obj)->setTo(Scalar(Vec<double, 4>(value.ptr<double>())), mask);
#else
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
#endif
}
else
CV_Error(Error::StsNotImplemented, "");
+150 -26
View File
@@ -205,13 +205,10 @@ int normL1_(const uchar* a, const uchar* b, int n)
return d;
}
}} //cv::hal
} //cv::hal
//==================================================================================================
namespace cv
{
template<typename T, typename ST> int
normInf_(const T* src, const uchar* mask, ST* _result, int len, int cn)
{
@@ -591,12 +588,10 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result)
CV_UNUSED(src); CV_UNUSED(normType); CV_UNUSED(mask); CV_UNUSED(result);
#endif
return false;
}
#endif
} // ipp_norm()
#endif // HAVE_IPP
} // cv::
double cv::norm( InputArray _src, int normType, InputArray _mask )
double norm( InputArray _src, int normType, InputArray _mask )
{
CV_INSTRUMENT_REGION();
@@ -769,9 +764,6 @@ double cv::norm( InputArray _src, int normType, InputArray _mask )
//==================================================================================================
#ifdef HAVE_OPENCL
namespace cv {
static bool ocl_norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask, double & result )
{
#ifdef __ANDROID__
@@ -826,15 +818,10 @@ static bool ocl_norm( InputArray _src1, InputArray _src2, int normType, InputArr
result /= (s2 + DBL_EPSILON);
return true;
}
}
#endif
} // ocl_norm()
#endif // HAVE_OPENCL
#ifdef HAVE_IPP
namespace cv
{
static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArray _mask, double &result)
{
CV_INSTRUMENT_REGION_IPP();
@@ -1060,12 +1047,11 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra
CV_UNUSED(_src1); CV_UNUSED(_src2); CV_UNUSED(normType); CV_UNUSED(_mask); CV_UNUSED(result);
#endif
return false;
}
}
#endif
} // ipp_norm
#endif // HAVE_IPP
double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask )
double norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask )
{
CV_INSTRUMENT_REGION();
@@ -1185,7 +1171,7 @@ double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _m
// special case to handle "integer" overflow in accumulator
const size_t esz = src1.elemSize();
const int total = (int)it.size;
const int intSumBlockSize = normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15);
const int intSumBlockSize = (normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15))/cn;
const int blockSize = std::min(total, intSumBlockSize);
int isum = 0;
int count = 0;
@@ -1234,12 +1220,12 @@ double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _m
return result.d;
}
cv::Hamming::ResultType cv::Hamming::operator()( const unsigned char* a, const unsigned char* b, int size ) const
cv::Hamming::ResultType Hamming::operator()( const unsigned char* a, const unsigned char* b, int size ) const
{
return cv::hal::normHamming(a, b, size);
}
double cv::PSNR(InputArray _src1, InputArray _src2)
double PSNR(InputArray _src1, InputArray _src2)
{
CV_INSTRUMENT_REGION();
@@ -1249,3 +1235,141 @@ double cv::PSNR(InputArray _src1, InputArray _src2)
double diff = std::sqrt(norm(_src1, _src2, NORM_L2SQR)/(_src1.total()*_src1.channels()));
return 20*log10(255./(diff+DBL_EPSILON));
}
#ifdef HAVE_OPENCL
static bool ocl_normalize( InputArray _src, InputOutputArray _dst, InputArray _mask, int dtype,
double scale, double delta )
{
UMat src = _src.getUMat();
if( _mask.empty() )
src.convertTo( _dst, dtype, scale, delta );
else if (src.channels() <= 4)
{
const ocl::Device & dev = ocl::Device::getDefault();
int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype),
ddepth = CV_MAT_DEPTH(dtype), wdepth = std::max(CV_32F, std::max(sdepth, ddepth)),
rowsPerWI = dev.isIntel() ? 4 : 1;
float fscale = static_cast<float>(scale), fdelta = static_cast<float>(delta);
bool haveScale = std::fabs(scale - 1) > DBL_EPSILON,
haveZeroScale = !(std::fabs(scale) > DBL_EPSILON),
haveDelta = std::fabs(delta) > DBL_EPSILON,
doubleSupport = dev.doubleFPConfig() > 0;
if (!haveScale && !haveDelta && stype == dtype)
{
_src.copyTo(_dst, _mask);
return true;
}
if (haveZeroScale)
{
_dst.setTo(Scalar(delta), _mask);
return true;
}
if ((sdepth == CV_64F || ddepth == CV_64F) && !doubleSupport)
return false;
char cvt[2][40];
String opts = format("-D srcT=%s -D dstT=%s -D convertToWT=%s -D cn=%d -D rowsPerWI=%d"
" -D convertToDT=%s -D workT=%s%s%s%s -D srcT1=%s -D dstT1=%s",
ocl::typeToStr(stype), ocl::typeToStr(dtype),
ocl::convertTypeStr(sdepth, wdepth, cn, cvt[0]), cn,
rowsPerWI, ocl::convertTypeStr(wdepth, ddepth, cn, cvt[1]),
ocl::typeToStr(CV_MAKE_TYPE(wdepth, cn)),
doubleSupport ? " -D DOUBLE_SUPPORT" : "",
haveScale ? " -D HAVE_SCALE" : "",
haveDelta ? " -D HAVE_DELTA" : "",
ocl::typeToStr(sdepth), ocl::typeToStr(ddepth));
ocl::Kernel k("normalizek", ocl::core::normalize_oclsrc, opts);
if (k.empty())
return false;
UMat mask = _mask.getUMat(), dst = _dst.getUMat();
ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
maskarg = ocl::KernelArg::ReadOnlyNoSize(mask),
dstarg = ocl::KernelArg::ReadWrite(dst);
if (haveScale)
{
if (haveDelta)
k.args(srcarg, maskarg, dstarg, fscale, fdelta);
else
k.args(srcarg, maskarg, dstarg, fscale);
}
else
{
if (haveDelta)
k.args(srcarg, maskarg, dstarg, fdelta);
else
k.args(srcarg, maskarg, dstarg);
}
size_t globalsize[2] = { (size_t)src.cols, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI };
return k.run(2, globalsize, NULL, false);
}
else
{
UMat temp;
src.convertTo( temp, dtype, scale, delta );
temp.copyTo( _dst, _mask );
}
return true;
} // ocl_normalize
#endif // HAVE_OPENCL
void normalize(InputArray _src, InputOutputArray _dst, double a, double b,
int norm_type, int rtype, InputArray _mask)
{
CV_INSTRUMENT_REGION();
double scale = 1, shift = 0;
int type = _src.type(), depth = CV_MAT_DEPTH(type);
if( rtype < 0 )
rtype = _dst.fixedType() ? _dst.depth() : depth;
if( norm_type == CV_MINMAX )
{
double smin = 0, smax = 0;
double dmin = MIN( a, b ), dmax = MAX( a, b );
minMaxIdx( _src, &smin, &smax, 0, 0, _mask );
scale = (dmax - dmin)*(smax - smin > DBL_EPSILON ? 1./(smax - smin) : 0);
if( rtype == CV_32F )
{
scale = (float)scale;
shift = (float)dmin - (float)(smin*scale);
}
else
shift = dmin - smin*scale;
}
else if( norm_type == CV_L2 || norm_type == CV_L1 || norm_type == CV_C )
{
scale = norm( _src, norm_type, _mask );
scale = scale > DBL_EPSILON ? a/scale : 0.;
shift = 0;
}
else
CV_Error( CV_StsBadArg, "Unknown/unsupported norm type" );
CV_OCL_RUN(_dst.isUMat(),
ocl_normalize(_src, _dst, _mask, rtype, scale, shift))
Mat src = _src.getMat();
if( _mask.empty() )
src.convertTo( _dst, rtype, scale, shift );
else
{
Mat temp;
src.convertTo( temp, rtype, scale, shift );
temp.copyTo( _dst, _mask );
}
}
} // namespace

Some files were not shown because too many files have changed in this diff Show More