1 /*
2 * Simd Library (http://ermig1979.github.io/Simd).
3 *
4 * Copyright (c) 2011-2019 Yermalayeu Ihar,
5 *               2014-2016 Antonenka Mikhail,
6 *               2019-2019 Facundo Galan.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26 
27 #include "Simd/SimdView.hpp"
28 #include "Simd/SimdPixel.hpp"
29 #include "Simd/SimdPyramid.hpp"
30 
31 #ifndef __SimdLib_hpp__
32 #define __SimdLib_hpp__
33 
34 /*! \namespace Simd */
35 namespace Simd
36 {
37     /*! @ingroup bgra_conversion
38 
39         \fn void BgraToBgr(const View<A>& bgra, View<A>& bgr)
40 
41         \short Converts 32-bit BGRA image to 24-bit BGR image.
42 
43         All images must have the same width and height.
44 
45         \note This function is a C++ wrapper for function ::SimdBgraToBgr.
46 
47         \param [in] bgra - an input 32-bit BGRA image.
48         \param [out] bgr - an output 24-bit BGR image.
49     */
BgraToBgr(const View<A> & bgra,View<A> & bgr)50     template<template<class> class A> SIMD_INLINE void BgraToBgr(const View<A>& bgra, View<A>& bgr)
51     {
52         assert(EqualSize(bgra, bgr) && bgra.format == View<A>::Bgra32 && bgr.format == View<A>::Bgr24);
53 
54         SimdBgraToBgr(bgra.data, bgra.width, bgra.height, bgra.stride, bgr.data, bgr.stride);
55     }
56 
57     /*! @ingroup bgra_conversion
58 
59         \fn void BgraToGray(const View<A>& bgra, View<A>& gray)
60 
61         \short Converts 32-bit BGRA image to 8-bit gray image.
62 
63         All images must have the same width and height.
64 
65         \note This function is a C++ wrapper for function ::SimdBgraToGray.
66 
67         \param [in] bgra - an input 32-bit BGRA image.
68         \param [out] gray - an output 8-bit gray image.
69     */
BgraToGray(const View<A> & bgra,View<A> & gray)70     template<template<class> class A> SIMD_INLINE void BgraToGray(const View<A>& bgra, View<A>& gray)
71     {
72         assert(EqualSize(bgra, gray) && bgra.format == View<A>::Bgra32 && gray.format == View<A>::Gray8);
73 
74         SimdBgraToGray(bgra.data, bgra.width, bgra.height, bgra.stride, gray.data, gray.stride);
75     }
76 
77     /*! @ingroup bgr_conversion
78 
79         \fn void BgrToBgra(const View<A>& bgr, View<A>& bgra, uint8_t alpha = 0xFF)
80 
81         \short Converts 24-bit BGR image to 32-bit BGRA image.
82 
83         All images must have the same width and height.
84 
85         \note This function is a C++ wrapper for function ::SimdBgrToBgra.
86 
87         \param [in] bgr - an input 24-bit BGR image.
88         \param [out] bgra - an output 32-bit BGRA image.
89         \param [in] alpha - a value of alpha channel. It is equal to 256 by default.
90     */
BgrToBgra(const View<A> & bgr,View<A> & bgra,uint8_t alpha=0xFF)91     template<template<class> class A> SIMD_INLINE void BgrToBgra(const View<A>& bgr, View<A>& bgra, uint8_t alpha = 0xFF)
92     {
93         assert(EqualSize(bgr, bgra) && bgra.format == View<A>::Bgra32 && bgr.format == View<A>::Bgr24);
94 
95         SimdBgrToBgra(bgr.data, bgr.width, bgr.height, bgr.stride, bgra.data, bgra.stride, alpha);
96     }
97 
98     /*! @ingroup other_conversion
99 
100         \fn void Bgr48pToBgra32(const View<A>& blue, const View<A>& green, const View<A>& red, View<A>& bgra, uint8_t alpha = 0xFF)
101 
102         \short Converts 48-bit planar BGR image to 32-bit BGRA image.
103 
104         All images must have the same width and height.
105 
106         \note This function is a C++ wrapper for function ::SimdBgr48pToBgra32.
107 
108         \param [in] blue - an input 16-bit image with blue color plane.
109         \param [in] green - an input 16-bit image with green color plane.
110         \param [in] red - an input 16-bit image with red color plane.
111         \param [out] bgra - an output 32-bit BGRA image.
112         \param [in] alpha - a value of alpha channel. It is equal to 256 by default.
113     */
Bgr48pToBgra32(const View<A> & blue,const View<A> & green,const View<A> & red,View<A> & bgra,uint8_t alpha=0xFF)114     template<template<class> class A> SIMD_INLINE void Bgr48pToBgra32(const View<A>& blue, const View<A>& green, const View<A>& red, View<A>& bgra, uint8_t alpha = 0xFF)
115     {
116         assert(Compatible(blue, green, red) && EqualSize(blue, bgra) && blue.format == View<A>::Int16 && bgra.format == View<A>::Bgra32);
117 
118         SimdBgr48pToBgra32(blue.data, blue.stride, blue.width, blue.height, green.data, green.stride, red.data, red.stride, bgra.data, bgra.stride, alpha);
119     }
120 
121     /*! @ingroup bgr_conversion
122 
123         \fn void BgrToGray(const View<A>& bgr, View<A>& gray)
124 
125         \short Converts 24-bit BGR image to 8-bit gray image.
126 
127         All images must have the same width and height.
128 
129         \note This function is a C++ wrapper for function ::SimdBgrToGray.
130 
131         \param [in] bgr - an input 24-bit BGR image.
132         \param [out] gray - an output 8-bit gray image.
133     */
BgrToGray(const View<A> & bgr,View<A> & gray)134     template<template<class> class A> SIMD_INLINE void BgrToGray(const View<A>& bgr, View<A>& gray)
135     {
136         assert(EqualSize(bgr, gray) && bgr.format == View<A>::Bgr24 && gray.format == View<A>::Gray8);
137 
138         SimdBgrToGray(bgr.data, bgr.width, bgr.height, bgr.stride, gray.data, gray.stride);
139     }
140 
141     /*! @ingroup bgr_conversion
142 
143         \fn void BgrToRgb(const View<A> & bgr, View<A> & rgb)
144 
145         \short Converts 24-bit BGR image to 24-bit RGB image (also it performs backward conversion).
146 
147         All images must have the same width and height.
148 
149         \note This function is a C++ wrapper for function ::SimdBgrToRgb.
150 
151         \param [in] bgr - an input 24-bit BGR image.
152         \param [out] rgb - an output 24-bit RGB image.
153     */
BgrToRgb(const View<A> & bgr,View<A> & rgb)154     template<template<class> class A> SIMD_INLINE void BgrToRgb(const View<A> & bgr, View<A> & rgb)
155     {
156         assert(EqualSize(bgr, rgb) && bgr.PixelSize() == 3 && rgb.PixelSize() == 3);
157 
158         SimdBgrToRgb(bgr.data, bgr.stride, bgr.width, bgr.height, rgb.data, rgb.stride);
159     }
160 
161     /*! @ingroup copying
162 
163         \fn void Copy(const View<A> & src, View<B> & dst)
164 
165         \short Copies pixels data of image from source to destination.
166 
167         All images must have the same width, height and format.
168 
169         \note This function is a C++ wrapper for function ::SimdCopy.
170 
171         \param [in] src - a source image.
172         \param [out] dst - a destination image.
173     */
Copy(const View<A> & src,View<B> & dst)174     template<template<class> class A, template<class> class B> SIMD_INLINE void Copy(const View<A> & src, View<B> & dst)
175     {
176         assert(Compatible(src, dst));
177 
178         if (src.format)
179         {
180             SimdCopy(src.data, src.stride, src.width, src.height, src.PixelSize(), dst.data, dst.stride);
181         }
182     }
183 
184     /*! @ingroup copying
185 
186         \fn void CopyFrame(const View<A>& src, const Rectangle<ptrdiff_t> & frame, View<A>& dst)
187 
188         \short Copies pixels data of image from source to destination except for the portion bounded frame.
189 
190         All images must have the same width, height and format.
191 
192         \note This function is a C++ wrapper for function ::SimdCopyFrame.
193 
194         \param [in] src - a source image.
195         \param [in] frame - a frame rectangle.
196         \param [out] dst - a destination image.
197     */
CopyFrame(const View<A> & src,const Rectangle<ptrdiff_t> & frame,View<A> & dst)198     template<template<class> class A> SIMD_INLINE void CopyFrame(const View<A>& src, const Rectangle<ptrdiff_t> & frame, View<A>& dst)
199     {
200         assert(Compatible(src, dst) && frame.Width() >= 0 && frame.Height() >= 0);
201         assert(frame.left >= 0 && frame.top >= 0 && frame.right <= ptrdiff_t(src.width) && frame.bottom <= ptrdiff_t(src.height));
202 
203         SimdCopyFrame(src.data, src.stride, src.width, src.height, src.PixelSize(),
204             frame.left, frame.top, frame.right, frame.bottom, dst.data, dst.stride);
205     }
206 
207     /*! @ingroup other_conversion
208 
209         \fn void DeinterleaveBgr(const View<A>& bgr, View<A>& b, View<A>& g, View<A>& r)
210 
211         \short Deinterleaves 24-bit BGR interleaved image into separated 8-bit Blue, Green and Red planar images.
212 
213         All images must have the same width and height.
214 
215         \note This function is a C++ wrapper for function ::SimdDeinterleaveBgr.
216 
217         \param [in] bgr - an input 24-bit BGR interleaved image.
218         \param [out] b - an output 8-bit Blue planar image.
219         \param [out] g - an output 8-bit Green planar image.
220         \param [out] r - an output 8-bit Red planar image.
221         */
DeinterleaveBgr(const View<A> & bgr,View<A> & b,View<A> & g,View<A> & r)222     template<template<class> class A> SIMD_INLINE void DeinterleaveBgr(const View<A>& bgr, View<A>& b, View<A>& g, View<A>& r)
223     {
224         assert(EqualSize(bgr, b) && Compatible(b, g, r) && bgr.format == View<A>::Bgr24 && b.format == View<A>::Gray8);
225 
226         SimdDeinterleaveBgr(bgr.data, bgr.stride, bgr.width, bgr.height, b.data, b.stride, g.data, g.stride, r.data, r.stride);
227     }
228 
229     /*! @ingroup other_conversion
230 
231         \fn void DeinterleaveBgra(const View<A>& bgra, View<A>& b, View<A>& g, View<A>& r, View<A>& a)
232 
233         \short Deinterleaves 32-bit BGRA interleaved image into separated 8-bit Blue, Green, Red and Alpha planar images.
234 
235         All images must have the same width and height.
236 
237         \note This function is a C++ wrapper for function ::SimdDeinterleaveBgra.
238 
239         \param [in] bgra - an input 32-bit BGRA interleaved image.
240         \param [out] b - an output 8-bit Blue planar image.
241         \param [out] g - an output 8-bit Green planar image.
242         \param [out] r - an output 8-bit Red planar image.
243         \param [out] a - an output 8-bit Alpha planar image.
244     */
DeinterleaveBgra(const View<A> & bgra,View<A> & b,View<A> & g,View<A> & r,View<A> & a)245     template<template<class> class A> SIMD_INLINE void DeinterleaveBgra(const View<A>& bgra, View<A>& b, View<A>& g, View<A>& r, View<A>& a)
246     {
247         assert(EqualSize(bgra, b) && Compatible(b, g, r, a) && bgra.format == View<A>::Bgra32 && b.format == View<A>::Gray8);
248 
249         SimdDeinterleaveBgra(bgra.data, bgra.stride, bgra.width, bgra.height, b.data, b.stride, g.data, g.stride, r.data, r.stride, a.data, a.stride);
250     }
251 
252     /*! @ingroup other_filter
253 
254         \fn void GaussianBlur3x3(const View<A>& src, View<A>& dst)
255 
256         \short Performs Gaussian blur filtration with window 3x3.
257 
258         For every point:
259         \verbatim
260         dst[x, y] = (src[x-1, y-1] + 2*src[x, y-1] + src[x+1, y-1] +
261                     2*(src[x-1, y] + 2*src[x, y] + src[x+1, y]) +
262                     src[x-1, y+1] + 2*src[x, y+1] + src[x+1, y+1] + 8) / 16;
263         \endverbatim
264         All images must have the same width, height and format (8-bit gray, 16-bit UV, 24-bit BGR or 32-bit BGRA).
265 
266         \note This function is a C++ wrapper for function ::SimdGaussianBlur3x3.
267 
268         \param [in] src - a source image.
269         \param [out] dst - a destination image.
270     */
GaussianBlur3x3(const View<A> & src,View<A> & dst)271     template<template<class> class A> SIMD_INLINE void GaussianBlur3x3(const View<A>& src, View<A>& dst)
272     {
273         assert(Compatible(src, dst) && src.ChannelSize() == 1);
274 
275         SimdGaussianBlur3x3(src.data, src.stride, src.width, src.height, src.ChannelCount(), dst.data, dst.stride);
276     }
277 
278     /*! @ingroup gray_conversion
279 
280         \fn void GrayToBgr(const View<A>& gray, View<A>& bgr)
281 
282         \short Converts 8-bit gray image to 24-bit BGR image.
283 
284         All images must have the same width and height.
285 
286         \note This function is a C++ wrapper for function ::SimdGrayToBgr.
287 
288         \param [in] gray - an input 8-bit gray image.
289         \param [out] bgr - an output 24-bit BGR image.
290     */
GrayToBgr(const View<A> & gray,View<A> & bgr)291     template<template<class> class A> SIMD_INLINE void GrayToBgr(const View<A>& gray, View<A>& bgr)
292     {
293         assert(EqualSize(gray, bgr) && bgr.format == View<A>::Bgr24 && gray.format == View<A>::Gray8);
294 
295         SimdGrayToBgr(gray.data, gray.width, gray.height, gray.stride, bgr.data, bgr.stride);
296     }
297 
298     /*! @ingroup gray_conversion
299 
300         \fn void GrayToBgra(const View<A>& gray, View<A>& bgra, uint8_t alpha = 0xFF)
301 
302         \short Converts 8-bit gray image to 32-bit BGRA image.
303 
304         All images must have the same width and height.
305 
306         \note This function is a C++ wrapper for function ::SimdGrayToBgra.
307 
308         \param [in] gray - an input 8-bit gray image.
309         \param [out] bgra - an output 32-bit BGRA image.
310         \param [in] alpha - a value of alpha channel. It is equal to 255 by default.
311     */
GrayToBgra(const View<A> & gray,View<A> & bgra,uint8_t alpha=0xFF)312     template<template<class> class A> SIMD_INLINE void GrayToBgra(const View<A>& gray, View<A>& bgra, uint8_t alpha = 0xFF)
313     {
314         assert(EqualSize(gray, bgra) && bgra.format == View<A>::Bgra32 && gray.format == View<A>::Gray8);
315 
316         SimdGrayToBgra(gray.data, gray.width, gray.height, gray.stride, bgra.data, bgra.stride, alpha);
317     }
318 
319     /*! @ingroup other_conversion
320 
321         \fn void InterleaveBgr(const View<A> & b, const View<A> & g, const View<A> & r, View<A> & bgr)
322 
323         \short Interleaves 8-bit Blue, Green and Red planar images into one 24-bit BGR interleaved image.
324 
325         All images must have the same width and height.
326 
327         \note This function is a C++ wrapper for function ::SimdInterleaveBgr.
328 
329         \param [in] b - an input 8-bit Blue planar image.
330         \param [in] g - an input 8-bit Green planar image.
331         \param [in] r - an input 8-bit Red planar image.
332         \param [out] bgr - an output 24-bit BGR interleaved image.
333     */
InterleaveBgr(const View<A> & b,const View<A> & g,const View<A> & r,View<A> & bgr)334     template<template<class> class A> SIMD_INLINE void InterleaveBgr(const View<A> & b, const View<A> & g, const View<A> & r, View<A> & bgr)
335     {
336         assert(EqualSize(bgr, b, g, r) && Compatible(b, g, r) && bgr.format == View<A>::Bgr24 && b.format == View<A>::Gray8);
337 
338         SimdInterleaveBgr(b.data, b.stride, g.data, g.stride, r.data, r.stride, bgr.width, bgr.height, bgr.data, bgr.stride);
339     }
340 
341     /*! @ingroup other_conversion
342 
343         \fn void InterleaveBgra(const View<A>& b, const View<A>& g, const View<A>& r, const View<A>& a, View<A>& bgra)
344 
345         \short Interleaves 8-bit Blue, Green, Red and Alpha planar images into one 32-bit BGRA interleaved image.
346 
347         All images must have the same width and height.
348 
349         \note This function is a C++ wrapper for function ::SimdInterleaveBgra.
350 
351         \param [in] b - an input 8-bit Blue planar image.
352         \param [in] g - an input 8-bit Green planar image.
353         \param [in] r - an input 8-bit Red planar image.
354         \param [in] a - an input 8-bit Alpha planar image.
355         \param [out] bgra - an output 32-bit BGRA interleaved image.
356     */
InterleaveBgra(const View<A> & b,const View<A> & g,const View<A> & r,const View<A> & a,View<A> & bgra)357     template<template<class> class A> SIMD_INLINE void InterleaveBgra(const View<A>& b, const View<A>& g, const View<A>& r, const View<A>& a, View<A>& bgra)
358     {
359         assert(EqualSize(bgra, b) && Compatible(b, g, r, a) && bgra.format == View<A>::Bgra32 && b.format == View<A>::Gray8);
360 
361         SimdInterleaveBgra(b.data, b.stride, g.data, g.stride, r.data, r.stride, a.data, a.stride, bgra.width, bgra.height, bgra.data, bgra.stride);
362     }
363 
364     /*! @ingroup other_filter
365 
366         \fn void MeanFilter3x3(const View<A>& src, View<A>& dst)
367 
368         \short Performs an averaging with window 3x3.
369 
370         For every point:
371         \verbatim
372         dst[x, y] = (src[x-1, y-1] + src[x, y-1] + src[x+1, y-1] +
373                      src[x-1, y] + src[x, y] + src[x+1, y] +
374                      src[x-1, y+1] + src[x, y+1] + src[x+1, y+1] + 4) / 9;
375         \endverbatim
376 
377         All images must have the same width, height and format (8-bit gray, 16-bit UV, 24-bit BGR or 32-bit BGRA).
378 
379         \note This function is a C++ wrapper for function ::SimdMeanFilter3x3.
380 
381         \param [in] src - a source image.
382         \param [out] dst - a destination image.
383     */
MeanFilter3x3(const View<A> & src,View<A> & dst)384     template<template<class> class A> SIMD_INLINE void MeanFilter3x3(const View<A>& src, View<A>& dst)
385     {
386         assert(Compatible(src, dst) && src.ChannelSize() == 1);
387 
388         SimdMeanFilter3x3(src.data, src.stride, src.width, src.height, src.ChannelCount(), dst.data, dst.stride);
389     }
390 
391     /*! @ingroup median_filter
392 
393         \fn void MedianFilterRhomb3x3(const View<A>& src, View<A>& dst)
394 
395         \short Performs median filtration of input image (filter window is a rhomb 3x3).
396 
397         All images must have the same width, height and format (8-bit gray, 16-bit UV, 24-bit BGR or 32-bit BGRA).
398 
399         \note This function is a C++ wrapper for function ::SimdMedianFilterRhomb3x3.
400 
401         \param [in] src - an original input image.
402         \param [out] dst - a filtered output image.
403     */
MedianFilterRhomb3x3(const View<A> & src,View<A> & dst)404     template<template<class> class A> SIMD_INLINE void MedianFilterRhomb3x3(const View<A>& src, View<A>& dst)
405     {
406         assert(Compatible(src, dst) && src.ChannelSize() == 1);
407 
408         SimdMedianFilterRhomb3x3(src.data, src.stride, src.width, src.height, src.ChannelCount(), dst.data, dst.stride);
409     }
410 
411     /*! @ingroup median_filter
412 
413         \fn void MedianFilterRhomb5x5(const View<A>& src, View<A>& dst)
414 
415         \short Performs median filtration of input image (filter window is a rhomb 5x5).
416 
417         All images must have the same width, height and format (8-bit gray, 16-bit UV, 24-bit BGR or 32-bit BGRA).
418 
419         \note This function is a C++ wrapper for function ::SimdMedianFilterRhomb5x5.
420 
421         \param [in] src - an original input image.
422         \param [out] dst - a filtered output image.
423     */
MedianFilterRhomb5x5(const View<A> & src,View<A> & dst)424     template<template<class> class A> SIMD_INLINE void MedianFilterRhomb5x5(const View<A>& src, View<A>& dst)
425     {
426         assert(Compatible(src, dst) && src.ChannelSize() == 1);
427 
428         SimdMedianFilterRhomb5x5(src.data, src.stride, src.width, src.height, src.ChannelCount(), dst.data, dst.stride);
429     }
430 
431     /*! @ingroup median_filter
432 
433         \fn void MedianFilterSquare3x3(const View<A>& src, View<A>& dst)
434 
435         \short Performs median filtration of input image (filter window is a square 3x3).
436 
437         All images must have the same width, height and format (8-bit gray, 16-bit UV, 24-bit BGR or 32-bit BGRA).
438 
439         \note This function is a C++ wrapper for function ::SimdMedianFilterSquare3x3.
440 
441         \param [in] src - an original input image.
442         \param [out] dst - a filtered output image.
443     */
MedianFilterSquare3x3(const View<A> & src,View<A> & dst)444     template<template<class> class A> SIMD_INLINE void MedianFilterSquare3x3(const View<A>& src, View<A>& dst)
445     {
446         assert(Compatible(src, dst) && src.ChannelSize() == 1);
447 
448         SimdMedianFilterSquare3x3(src.data, src.stride, src.width, src.height, src.ChannelCount(), dst.data, dst.stride);
449     }
450 
451     /*! @ingroup median_filter
452 
453         \fn void MedianFilterSquare5x5(const View<A>& src, View<A>& dst)
454 
455         \short Performs median filtration of input image (filter window is a square 5x5).
456 
457         All images must have the same width, height and format (8-bit gray, 16-bit UV, 24-bit BGR or 32-bit BGRA).
458 
459         \note This function is a C++ wrapper for function ::SimdMedianFilterSquare5x5.
460 
461         \param [in] src - an original input image.
462         \param [out] dst - a filtered output image.
463     */
MedianFilterSquare5x5(const View<A> & src,View<A> & dst)464     template<template<class> class A> SIMD_INLINE void MedianFilterSquare5x5(const View<A>& src, View<A>& dst)
465     {
466         assert(Compatible(src, dst) && src.ChannelSize() == 1);
467 
468         SimdMedianFilterSquare5x5(src.data, src.stride, src.width, src.height, src.ChannelCount(), dst.data, dst.stride);
469     }
470 
471     /*! @ingroup operation
472 
473         \fn void OperationBinary8u(const View<A>& a, const View<A>& b, View<A>& dst, SimdOperationBinary8uType type)
474 
475         \short Performs given operation between two images.
476 
477         All images must have the same width, height and format (8-bit gray, 16-bit UV (UV plane of NV12 pixel format), 24-bit BGR or 32-bit BGRA).
478 
479         \note This function is a C++ wrapper for function ::SimdOperationBinary8u.
480 
481         \param [in] a - a first input image.
482         \param [in] b - a second input image.
483         \param [out] dst - an output image.
484         \param [in] type - a type of operation (see ::SimdOperationBinary8uType).
485     */
OperationBinary8u(const View<A> & a,const View<A> & b,View<A> & dst,SimdOperationBinary8uType type)486     template<template<class> class A> SIMD_INLINE void OperationBinary8u(const View<A>& a, const View<A>& b, View<A>& dst, SimdOperationBinary8uType type)
487     {
488         assert(Compatible(a, b, dst) && a.ChannelSize() == 1);
489 
490         SimdOperationBinary8u(a.data, a.stride, b.data, b.stride, a.width, a.height, a.ChannelCount(), dst.data, dst.stride, type);
491     }
492 
493     /*! @ingroup resizing
494 
495         \fn void ReduceGray2x2(const View<A>& src, View<A>& dst)
496 
497         \short Performs reducing (in 2 times) and Gaussian blurring a 8-bit gray image with using window 2x2.
498 
499         For input and output image must be performed: dst.width = (src.width + 1)/2,  dst.height = (src.height + 1)/2.
500 
501         For all points:
502         \verbatim
503         dst[x, y] = (src[2*x, 2*y] + src[2*x, 2*y + 1] + src[2*x + 1, 2*y] + src[2*x + 1, 2*y + 1] + 2)/4;
504         \endverbatim
505 
506         \note This function is a C++ wrapper for function ::SimdReduceGray2x2.
507 
508         \param [in] src - an original input image.
509         \param [out] dst - a reduced output image.
510     */
ReduceGray2x2(const View<A> & src,View<A> & dst)511     template<template<class> class A> SIMD_INLINE void ReduceGray2x2(const View<A>& src, View<A>& dst)
512     {
513         assert(src.format == View<A>::Gray8 && dst.format == View<A>::Gray8 && Scale(src.Size()) == dst.Size());
514 
515         SimdReduceGray2x2(src.data, src.width, src.height, src.stride, dst.data, dst.width, dst.height, dst.stride);
516     }
517 
518     /*! @ingroup resizing
519 
520         \fn void ReduceGray3x3(const View<A>& src, View<A>& dst, bool compensation = true)
521 
522         \short Performs reducing (in 2 times) and Gaussian blurring a 8-bit gray image with using window 3x3.
523 
524         For input and output image must be performed: dst.width = (src.width + 1)/2,  dst.height = (src.height + 1)/2.
525 
526         For every point:
527         \verbatim
528         dst[x, y] = (src[2*x-1, 2*y-1] + 2*src[2*x, 2*y-1] + src[2*x+1, 2*y-1] +
529                   2*(src[2*x-1, 2*y]   + 2*src[2*x, 2*y]   + src[2*x+1, 2*y]) +
530                      src[2*x-1, 2*y+1] + 2*src[2*x, 2*y+1] + src[2*x+1, 2*y+1] + compensation ? 8 : 0) / 16;
531         \endverbatim
532 
533         \note This function is a C++ wrapper for function ::SimdReduceGray3x3.
534 
535         \param [in] src - an original input image.
536         \param [out] dst - a reduced output image.
537         \param [in] compensation - a flag of compensation of rounding. It is equal to 'true' by default.
538     */
ReduceGray3x3(const View<A> & src,View<A> & dst,bool compensation=true)539     template<template<class> class A> SIMD_INLINE void ReduceGray3x3(const View<A>& src, View<A>& dst, bool compensation = true)
540     {
541         assert(src.format == View<A>::Gray8 && dst.format == View<A>::Gray8 && Scale(src.Size()) == dst.Size());
542 
543         SimdReduceGray3x3(src.data, src.width, src.height, src.stride, dst.data, dst.width, dst.height, dst.stride, compensation ? 1 : 0);
544     }
545 
546     /*! @ingroup resizing
547 
548         \fn void ReduceGray4x4(const View<A>& src, View<A>& dst)
549 
550         \short Performs reducing (in 2 times) and Gaussian blurring a 8-bit gray image with using window 4x4.
551 
552         For input and output image must be performed: dst.width = (src.width + 1)/2,  dst.height = (src.height + 1)/2.
553 
554         For every point:
555         \verbatim
556         dst[x, y] =   (src[2*x-1, 2*y-1] + 3*src[2*x, 2*y-1] + 3*src[2*x+1, 2*y-1] + src[2*x+2, 2*y-1]
557                     3*(src[2*x-1, 2*y]   + 3*src[2*x, 2*y]   + 3*src[2*x+1, 2*y]   + src[2*x+2, 2*y]) +
558                     3*(src[2*x-1, 2*y+1] + 3*src[2*x, 2*y+1] + 3*src[2*x+1, 2*y+1] + src[2*x+2, 2*y+1]) +
559                        src[2*x-1, 2*y+2] + 3*src[2*x, 2*y+2] + 3*src[2*x+1, 2*y+2] + src[2*x+2, 2*y+2] + 32) / 64;
560         \endverbatim
561 
562         \note This function is a C++ wrapper for function ::SimdReduceGray4x4.
563 
564         \param [in] src - an original input image.
565         \param [out] dst - a reduced output image.
566     */
ReduceGray4x4(const View<A> & src,View<A> & dst)567     template<template<class> class A> SIMD_INLINE void ReduceGray4x4(const View<A>& src, View<A>& dst)
568     {
569         assert(src.format == View<A>::Gray8 && dst.format == View<A>::Gray8 && Scale(src.Size()) == dst.Size());
570 
571         SimdReduceGray4x4(src.data, src.width, src.height, src.stride, dst.data, dst.width, dst.height, dst.stride);
572     }
573 
574     /*! @ingroup resizing
575 
576         \fn void ReduceGray5x5(const View<A>& src, View<A>& dst, bool compensation = true)
577 
578         \short Performs reducing (in 2 times) and Gaussian blurring a 8-bit gray image with using window 5x5.
579 
580         For input and output image must be performed: dst.width = (src.width + 1)/2,  dst.height = (src.height + 1)/2.
581 
582         For every point:
583         \verbatim
584         dst[x, y] = (
585                src[2*x-2, 2*y-2] + 4*src[2*x-1, 2*y-2] + 6*src[2*x, 2*y-2] + 4*src[2*x+1, 2*y-2] + src[2*x+2, 2*y-2] +
586             4*(src[2*x-2, 2*y-1] + 4*src[2*x-1, 2*y-1] + 6*src[2*x, 2*y-1] + 4*src[2*x+1, 2*y-1] + src[2*x+2, 2*y-1]) +
587             6*(src[2*x-2, 2*y]   + 4*src[2*x-1, 2*y]   + 6*src[2*x, 2*y]   + 4*src[2*x+1, 2*y]   + src[2*x+2, 2*y]) +
588             4*(src[2*x-2, 2*y+1] + 4*src[2*x-1, 2*y+1] + 6*src[2*x, 2*y+1] + 4*src[2*x+1, 2*y+1] + src[2*x+2, 2*y+1]) +
589                src[2*x-2, 2*y+2] + 4*src[2*x-1, 2*y+2] + 6*src[2*x, 2*y+2] + 4*src[2*x+1, 2*y+2] + src[2*x+2, 2*y+2] +
590             compensation ? 128 : 0) / 256;
591         \endverbatim
592 
593         \note This function is a C++ wrapper for function ::SimdReduceGray5x5.
594 
595         \param [in] src - an original input image.
596         \param [out] dst - a reduced output image.
597         \param [in] compensation - a flag of compensation of rounding. It is equal to 'true' by default.
598     */
ReduceGray5x5(const View<A> & src,View<A> & dst,bool compensation=true)599     template<template<class> class A> SIMD_INLINE void ReduceGray5x5(const View<A>& src, View<A>& dst, bool compensation = true)
600     {
601         assert(src.format == View<A>::Gray8 && dst.format == View<A>::Gray8 && Scale(src.Size()) == dst.Size());
602 
603         SimdReduceGray5x5(src.data, src.width, src.height, src.stride, dst.data, dst.width, dst.height, dst.stride, compensation ? 1 : 0);
604     }
605 
606     /*! @ingroup resizing
607 
608         \fn void ReduceGray(const View<A> & src, View<A> & dst, ::SimdReduceType reduceType, bool compensation = true)
609 
610         \short Performs reducing (in 2 times) and Gaussian blurring a 8-bit gray image.
611 
612         For input and output image must be performed: dst.width = (src.width + 1)/2,  dst.height = (src.height + 1)/2.
613 
614         \param [in] src - an original input image.
615         \param [out] dst - a reduced output image.
616         \param [in] reduceType - a type of function used for image reducing.
617         \param [in] compensation - a flag of compensation of rounding. It is relevant only for ::SimdReduce3x3 and ::SimdReduce5x5. It is equal to 'true' by default.
618     */
ReduceGray(const View<A> & src,View<A> & dst,::SimdReduceType reduceType,bool compensation=true)619     template<template<class> class A> SIMD_INLINE void ReduceGray(const View<A> & src, View<A> & dst, ::SimdReduceType reduceType, bool compensation = true)
620     {
621         assert(src.format == View<A>::Gray8 && dst.format == View<A>::Gray8 && Scale(src.Size()) == dst.Size());
622 
623         switch (reduceType)
624         {
625         case SimdReduce2x2:
626             Simd::ReduceGray2x2(src, dst);
627             break;
628         case SimdReduce3x3:
629             Simd::ReduceGray3x3(src, dst, compensation);
630             break;
631         case SimdReduce4x4:
632             Simd::ReduceGray4x4(src, dst);
633             break;
634         case SimdReduce5x5:
635             Simd::ReduceGray5x5(src, dst, compensation);
636             break;
637         default:
638             assert(0);
639         }
640     }
641 
642     /*! @ingroup resizing
643 
644         \fn void Reduce2x2(const View<A> & src, View<A> & dst)
645 
646         \short Performs reducing of image (in 2 times).
647 
648         For input and output image must be performed: dst.width = (src.width + 1)/2,  dst.height = (src.height + 1)/2.
649 
650         \param [in] src - an original input image.
651         \param [out] dst - a reduced output image.
652     */
Reduce2x2(const View<A> & src,View<A> & dst)653     template<template<class> class A> SIMD_INLINE void Reduce2x2(const View<A> & src, View<A> & dst)
654     {
655         assert(src.format == dst.format && Scale(src.Size()) == dst.Size() && src.ChannelSize() == 1);
656 
657         SimdReduceColor2x2(src.data, src.width, src.height, src.stride, dst.data, dst.width, dst.height, dst.stride, src.ChannelCount());
658     }
659 
660     /*! @ingroup resizing
661 
662         \fn void ResizeBilinear(const View<A>& src, View<A>& dst)
663 
664         \short Performs resizing of input image with using bilinear interpolation.
665 
666         All images must have the same format (8-bit gray, 16-bit UV, 24-bit BGR or 32-bit BGRA).
667 
668         \note This function is a C++ wrapper for function ::SimdResizeBilinear.
669 
670         \param [in] src - an original input image.
671         \param [out] dst - a resized output image.
672     */
ResizeBilinear(const View<A> & src,View<A> & dst)673     template<template<class> class A> SIMD_INLINE void ResizeBilinear(const View<A> & src, View<A> & dst)
674     {
675         assert(src.format == dst.format && src.ChannelSize() == 1);
676 
677         if (EqualSize(src, dst))
678         {
679             Copy(src, dst);
680         }
681         else
682         {
683             SimdResizeBilinear(src.data, src.width, src.height, src.stride,
684                 dst.data, dst.width, dst.height, dst.stride, src.ChannelCount());
685         }
686     }
687 
688     /*! @ingroup resizing
689 
690         \fn void ResizeAreaGray(const View<A> & src, View<A> & dst)
691 
692         \short Performs resizing of input image with using area interpolation.
693 
694         All images must have the same format (8-bit gray).
695 
696         \param [in] src - an original input image.
697         \param [out] dst - a resized output image.
698     */
ResizeAreaGray(const View<A> & src,View<A> & dst)699     template<template<class> class A> SIMD_INLINE void ResizeAreaGray(const View<A> & src, View<A> & dst)
700     {
701         assert(src.format == dst.format && src.format == View<A>::Gray8);
702 
703         if (EqualSize(src, dst))
704         {
705             Copy(src, dst);
706         }
707         else
708         {
709             size_t level = 0;
710             for (; (dst.width << (level + 1)) < (size_t)src.width; level++);
711             Point<ptrdiff_t> size = src.Size() << level;
712             if (level)
713             {
714                 Pyramid<A> pyramid(size, level + 1);
715                 Simd::ResizeBilinear(src, pyramid[0]);
716                 for (size_t i = 0; i < level; ++i)
717                     Simd::ReduceGray(pyramid.At(i), pyramid.At(i + 1), ::SimdReduce2x2);
718                 Simd::Copy(pyramid[level], dst);
719             }
720             else
721                 Simd::ResizeBilinear(src, dst);
722         }
723     }
724 
725     /*! @ingroup resizing
726 
727         \fn void ResizeArea(const View<A> & src, View<A> & dst)
728 
729         \short Performs resizing of input image with using area interpolation.
730 
731         All images must have the same format.
732 
733         \param [in] src - an original input image.
734         \param [out] dst - a resized output image.
735     */
ResizeArea(const View<A> & src,View<A> & dst)736     template<template<class> class A> SIMD_INLINE void ResizeArea(const View<A> & src, View<A> & dst)
737     {
738         assert(src.format == dst.format);
739 
740         if (EqualSize(src, dst))
741         {
742             Copy(src, dst);
743         }
744         else
745         {
746             size_t level = 0;
747             for (; (dst.width << (level + 1)) < (size_t)src.width; level++);
748             Point<ptrdiff_t> size = src.Size() << level;
749             if (level)
750             {
751                 std::vector<View<A> > pyramid(level);
752                 pyramid[0].Resize(size, src.format);
753                 Simd::ResizeBilinear(src, pyramid[0]);
754                 for (size_t i = 1; i < level; ++i)
755                 {
756                     size = Simd::Scale(size);
757                     pyramid[i].Resize(size, src.format);
758                     Simd::Reduce2x2(pyramid.At(i - 1), pyramid.At(i));
759                 }
760                 Simd::Reduce2x2(pyramid.At(level - 1), dst);
761             }
762             else
763                 Simd::ResizeBilinear(src, dst);
764         }
765     }
766 
767     /*! @ingroup resizing
768 
769         \fn void Resize(const View<A> & src, View<A> & dst, ::SimdResizeMethodType method = ::SimdResizeMethodBilinear)
770 
771         \short Performs resizing of image.
772 
773         All images must have the same format.
774 
775         \param [in] src - an original input image.
776         \param [out] dst - a resized output image.
777         \param [in] method - a resizing method. By default it is equal to ::SimdResizeMethodBilinear.
778     */
Resize(const View<A> & src,View<A> & dst,::SimdResizeMethodType method=::SimdResizeMethodBilinear)779     template<template<class> class A> SIMD_INLINE void Resize(const View<A> & src, View<A> & dst, ::SimdResizeMethodType method = ::SimdResizeMethodBilinear)
780     {
781         assert(src.format == dst.format && (src.format == View<A>::Float || src.ChannelSize() == 1));
782 
783         if (EqualSize(src, dst))
784         {
785             Copy(src, dst);
786         }
787         else
788         {
789             SimdResizeChannelType type = src.format == View<A>::Float ? SimdResizeChannelFloat : SimdResizeChannelByte;
790             void * resizer = SimdResizerInit(src.width, src.height, dst.width, dst.height, src.ChannelCount(), type, method);
791             if (resizer)
792             {
793                 SimdResizerRun(resizer, src.data, src.stride, dst.data, dst.stride);
794                 SimdRelease(resizer);
795             }
796             else
797                 assert(0);
798         }
799     }
800 
801     /*! @ingroup resizing
802 
803         \fn void StretchGray2x2(const View<A>& src, View<A>& dst)
804 
805         \short Stretches input 8-bit gray image in two times.
806 
807         \note This function is a C++ wrapper for function ::SimdStretchGray2x2.
808 
809         \param [in] src - an original input image.
810         \param [out] dst - a stretched output image.
811     */
StretchGray2x2(const View<A> & src,View<A> & dst)812     template<template<class> class A> SIMD_INLINE void StretchGray2x2(const View<A> & src, View<A> & dst)
813     {
814         assert(src.format == View<A>::Gray8 && dst.format == View<A>::Gray8);
815         assert(src.width * 2 == dst.width && src.height * 2 == dst.height);
816 
817         SimdStretchGray2x2(src.data, src.width, src.height, src.stride, dst.data, dst.width, dst.height, dst.stride);
818     }
819 
820     /*! @ingroup universal_conversion
821 
822         \fn void Convert(const View<A> & src, View<A> & dst)
823 
824         \short Converts an image of one format to an image of another format.
825 
826         The input and output images must have the same width and height.
827 
828         \note This function supports conversion between Gray8, Bgr24 and Bgra32 image formats.
829 
830         \param [in] src - an input image.
831         \param [out] dst - an output image.
832     */
Convert(const View<A> & src,View<A> & dst)833     template<template<class> class A> SIMD_INLINE void Convert(const View<A> & src, View<A> & dst)
834     {
835         assert(EqualSize(src, dst) && src.format && dst.format);
836 
837         if (src.format == dst.format)
838         {
839             Copy(src, dst);
840             return;
841         }
842 
843         switch (src.format)
844         {
845         case View<A>::Gray8:
846             switch (dst.format)
847             {
848             case View<A>::Bgra32:
849                 GrayToBgra(src, dst);
850                 break;
851             case View<A>::Bgr24:
852                 GrayToBgr(src, dst);
853                 break;
854             default:
855                 assert(0);
856             }
857             break;
858 
859         case View<A>::Bgr24:
860             switch (dst.format)
861             {
862             case View<A>::Bgra32:
863                 BgrToBgra(src, dst);
864                 break;
865             case View<A>::Gray8:
866                 BgrToGray(src, dst);
867                 break;
868             default:
869                 assert(0);
870             }
871             break;
872 
873         case View<A>::Bgra32:
874             switch (dst.format)
875             {
876             case View<A>::Bgr24:
877                 BgraToBgr(src, dst);
878                 break;
879             case View<A>::Gray8:
880                 BgraToGray(src, dst);
881                 break;
882             default:
883                 assert(0);
884             }
885             break;
886 
887         default:
888             assert(0);
889         }
890     }
891 
892     /*! @ingroup cpp_pyramid_functions
893 
894         \fn void Fill(Pyramid<A> & pyramid, uint8_t value)
895 
896         \short Fills pixels data of images in the pyramid by given value.
897 
898         \param [out] pyramid - a pyramid.
899         \param [in] value - a value to fill the pyramid.
900     */
Fill(Pyramid<A> & pyramid,uint8_t value)901     template<template<class> class A> SIMD_INLINE void Fill(Pyramid<A> & pyramid, uint8_t value)
902     {
903         for (size_t level = 0; level < pyramid.Size(); ++level)
904             Simd::Fill(pyramid.At(level), value);
905     }
906 
907     /*! @ingroup cpp_pyramid_functions
908 
909         \fn void Copy(const Pyramid<A> & src, Pyramid<A> & dst)
910 
911         \short Copies one pyramid to another pyramid.
912 
913         \note Input and output pyramids must have the same size.
914 
915         \param [in] src - an input pyramid.
916         \param [out] dst - an output pyramid.
917     */
Copy(const Pyramid<A> & src,Pyramid<A> & dst)918     template<template<class> class A> SIMD_INLINE void Copy(const Pyramid<A> & src, Pyramid<A> & dst)
919     {
920         assert(src.Size() == dst.Size());
921         for (size_t level = 0; level < src.Size(); ++level)
922             Simd::Copy(src.At(level), dst.At(level));
923     }
924 
925     /*! @ingroup cpp_pyramid_functions
926 
927         \fn void Build(Pyramid<A> & pyramid, ::SimdReduceType reduceType, bool compensation = true)
928 
929         \short Builds the pyramid (fills upper levels on the base of the lowest level).
930 
931         \param [out] pyramid - a built pyramid.
932         \param [in] reduceType - a type of function used for image reducing.
933         \param [in] compensation - a flag of compensation of rounding. It is relevant only for ::SimdReduce3x3 and ::SimdReduce5x5. It is equal to 'true' by default.
934     */
Build(Pyramid<A> & pyramid,::SimdReduceType reduceType,bool compensation=true)935     template<template<class> class A> SIMD_INLINE void Build(Pyramid<A> & pyramid, ::SimdReduceType reduceType, bool compensation = true)
936     {
937         for (size_t level = 1; level < pyramid.Size(); ++level)
938             Simd::ReduceGray(pyramid.At(level - 1), pyramid.At(level), reduceType, compensation);
939     }
940 }
941 
942 #endif//__SimdLib_hpp__
943 
944