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