1 /*******************************************************************************
2 * Copyright 2016-2019 Intel Corporation.
3 *
4 * This software and the related documents are Intel copyrighted  materials,  and
5 * your use of  them is  governed by the  express license  under which  they were
6 * provided to you (License).  Unless the License provides otherwise, you may not
7 * use, modify, copy, publish, distribute,  disclose or transmit this software or
8 * the related documents without Intel's prior written permission.
9 *
10 * This software and the related documents  are provided as  is,  with no express
11 * or implied  warranties,  other  than those  that are  expressly stated  in the
12 * License.
13 *******************************************************************************/
14 
15 #if !defined( __IPP_IWPP_IMAGE__ )
16 #define __IPP_IWPP_IMAGE__
17 
18 #include "iw++/iw_core.hpp"
19 #include "iw/iw_image_op.h"
20 
21 namespace ipp
22 {
23 
24 /* /////////////////////////////////////////////////////////////////////////////
25 //                   Image IW++ definitions
26 ///////////////////////////////////////////////////////////////////////////// */
27 
28 using ::IppiAxis;
29 using ::ippAxsHorizontal;
30 using ::ippAxsVertical;
31 using ::ippAxsBoth;
32 using ::ippAxs45;
33 using ::ippAxs135;
34 
35 using ::IppiMaskSize;
36 using ::ippMskSize3x3;
37 using ::ippMskSize5x5;
38 
39 using ::ippBorderRepl;
40 using ::ippBorderMirror;
41 using ::ippBorderDefault;
42 using ::ippBorderConst;
43 using ::ippBorderTransp;
44 using ::ippBorderInMemTop;
45 using ::ippBorderInMemBottom;
46 using ::ippBorderInMemLeft;
47 using ::ippBorderInMemRight;
48 using ::ippBorderInMem;
49 #if IPP_VERSION_COMPLEX >= 20170002
50 using ::ippBorderFirstStageInMem;
51 #endif
52 #if IPP_VERSION_COMPLEX >= 20180000
53 using ::ippBorderFirstStageInMemTop;
54 using ::ippBorderFirstStageInMemBottom;
55 using ::ippBorderFirstStageInMemLeft;
56 using ::ippBorderFirstStageInMemRight;
57 #endif
58 
59 // Stores the width and height of a rectangle. Extends IwiSize structure
60 class IwiSize: public ::IwiSize
61 {
62 public:
63     // Default constructor. Sets values to zero
IwiSize()64     IwiSize()
65     {
66         Set(0, 0);
67     }
68 
69     // One value template constructor. Sets size to same value. Useful for simple initialization, e.g.: size = 0
70     template<typename T>
IwiSize(T size)71     IwiSize(
72         T size // Size of square rectangle
73     )
74     {
75         Set((IwSize)size, (IwSize)size);
76     }
77 
78     // Constructor. Sets size to specified values
IwiSize(IwSize _width,IwSize _height)79     IwiSize(
80         IwSize _width, // Width of rectangle
81         IwSize _height // Height of rectangle
82     )
83     {
84         Set(_width, _height);
85     }
86 
87     // Constructor from IppiSize structure
IwiSize(IppiSize size)88     IwiSize(
89         IppiSize size // IppiSize structure
90     )
91     {
92         Set(size.width, size.height);
93     }
94 
95     // Constructor from C IwiSize structure
IwiSize(::IwiSize size)96     IwiSize(
97         ::IwiSize size // C IwiSize structure
98     )
99     {
100         Set(size.width, size.height);
101     }
102 
103     // Constructor from IppiRect structure
IwiSize(IppiRect rect)104     IwiSize(
105         IppiRect rect // IppiRect structure
106     )
107     {
108         Set(rect.width, rect.height);
109     }
110 
111     // Constructor from IwiRoi structure
IwiSize(IwiRoi rect)112     IwiSize(
113         IwiRoi rect // IwiRoi structure
114     )
115     {
116         Set(rect.width, rect.height);
117     }
118 
119     // Sets size to specified values
Set(IwSize _width,IwSize _height)120     void Set(
121         IwSize _width, // Width of rectangle
122         IwSize _height // Height of rectangle
123     )
124     {
125         width  = _width;
126         height = _height;
127     }
128 
129     // Retrns size of area covered by IwiSize
Area() const130     inline IwSize Area() const
131     {
132         return IPP_ABS(this->width*this->height);
133     }
134 
135     // IwiSize to IppiSize cast operator
operator IppiSize() const136     inline operator IppiSize()  const { IppiSize size = {(int)width, (int)height}; return size; }
137 };
138 
139 // Stores the geometric position of a point. Extends IppiPoint structure
140 class IwiPoint: public ::IwiPoint
141 {
142 public:
143     // Default constructor. Sets values to zero
IwiPoint()144     IwiPoint()
145     {
146         Set(0, 0);
147     }
148 
149     // One value template constructor. Sets position to same value. Useful for simple initialization, e.g.: point = 0
150     template<typename T>
IwiPoint(T point)151     IwiPoint(
152         T point // Position of point
153     )
154     {
155         Set((IwSize)point, (IwSize)point);
156     }
157 
158     // Constructor. Sets position to specified values
IwiPoint(IwSize _x,IwSize _y)159     IwiPoint(
160         IwSize _x, // X coordinate of point
161         IwSize _y  // Y coordinate of point
162     )
163     {
164         Set(_x, _y);
165     }
166 
167     // Constructor from IppiPoint structure
IwiPoint(IppiPoint point)168     IwiPoint(
169         IppiPoint point // IppiPoint structure
170     )
171     {
172         Set(point.x, point.y);
173     }
174 
175     // Constructor from IppiPointL structure
IwiPoint(IppiPointL point)176     IwiPoint(
177         IppiPointL point // IppiPointL structure
178     )
179     {
180         Set(point.x, point.y);
181     }
182 
183     // Constructor from IppiRect structure
IwiPoint(IppiRect rect)184     IwiPoint(
185         IppiRect  rect // IppiRect structure
186     )
187     {
188         Set(rect.x, rect.y);
189     }
190 
191     // Constructor from C IwiRoi structure
IwiPoint(::IwiRoi rect)192     IwiPoint(
193         ::IwiRoi rect // C IwiRoi structure
194     )
195     {
196         Set(rect.x, rect.y);
197     }
198 
199     // Sets position to specified values
Set(IwSize _x,IwSize _y)200     void Set(
201         IwSize _x, // X coordinate of point
202         IwSize _y  // Y coordinate of point
203     )
204     {
205         x = _x;
206         y = _y;
207     }
208 
209     // IwiPoint to IppiPoint cast operator
operator IppiPoint() const210     inline operator IppiPoint()  const { IppiPoint point = {(int)x, (int)y}; return point; }
211 };
212 
213 // Stores the geometric position and size of a rectangle. Extends IppiRect structure
214 class IwiRoi: public ::IwiRoi
215 {
216 public:
217     // Default constructor. Sets values to zero
IwiRoi()218     IwiRoi()
219     {
220         Set(0, 0, 0, 0);
221     }
222 
223     // One value template constructor. Sets position to zero and size to same value. Useful for simple initialization, e.g.: rect = 0
224     template<typename T>
IwiRoi(T size)225     IwiRoi(
226         T size // Size of rectangle
227     )
228     {
229         Set(0, 0, (IwSize)size, (IwSize)size);
230     }
231 
232     // Constructor. Sets rectangle to specified values
IwiRoi(IwSize _x,IwSize _y,IwSize _width,IwSize _height)233     IwiRoi(
234         IwSize _x,     // X coordinate of rectangle
235         IwSize _y,     // Y coordinate of rectangle
236         IwSize _width, // Width of rectangle
237         IwSize _height // Height of rectangle
238     )
239     {
240         Set(_x, _y, _width, _height);
241     }
242 
243     // Constructor from IppiSize structure. Sets position to 0 and size to IppiSize value
IwiRoi(IppiSize size)244     IwiRoi(
245         IppiSize size
246     )
247     {
248         Set(0, 0, size.width, size.height);
249     }
250 
251     // Constructor from C IwiSize structure. Sets position to 0 and size to IwiSize value
IwiRoi(::IwiSize size)252     IwiRoi(
253         ::IwiSize size
254     )
255     {
256         Set(0, 0, size.width, size.height);
257     }
258 
259     // Constructor from IwiSize class. Sets position to 0 and size to IwiSize value
IwiRoi(IwiSize size)260     IwiRoi(
261         IwiSize size
262     )
263     {
264         Set(0, 0, size.width, size.height);
265     }
266 
267     // Constructor from IppiRect class
IwiRoi(IppiRect rect)268     IwiRoi(
269         IppiRect rect
270     )
271     {
272         Set(rect.x, rect.y, rect.width, rect.height);
273     }
274 
275     // Constructor from C IwiRoi structure
IwiRoi(::IwiRoi rect)276     IwiRoi(
277         ::IwiRoi rect
278     )
279     {
280         Set(rect.x, rect.y, rect.width, rect.height);
281     }
282 
283     // Sets rectangle to specified values
Set(IwSize _x,IwSize _y,IwSize _width,IwSize _height)284     void Set(
285         IwSize _x,     // X coordinate of rectangle
286         IwSize _y,     // Y coordinate of rectangle
287         IwSize _width, // Width of rectangle
288         IwSize _height // Height of rectangle
289     )
290     {
291         x = _x;
292         y = _y;
293         width  = _width;
294         height = _height;
295     }
296 
297     // Retrns size of area covered by IwiRoi
Area() const298     inline IwSize Area() const
299     {
300         return IPP_ABS(this->width*this->height);
301     }
302 
303     // IwiRoi to IwiPoint cast operator
operator IwiPoint() const304     inline operator IwiPoint() const { return IwiPoint(x, y); }
305 
306     // IwiRoi to IwiSize cast operator
operator IwiSize() const307     inline operator IwiSize()  const { return IwiSize(width, height); }
308 
309     // IwiRoi to IppiPoint cast operator
operator IppiPoint() const310     inline operator IppiPoint() const { IppiPoint point = {(int)x, (int)y}; return point; }
311 
312     // IwiRoi to IppiSize cast operator
operator IppiSize() const313     inline operator IppiSize()  const { IppiSize  size  = {(int)width, (int)height}; return size; }
314 
315     // IwiRoi to IppiPointL cast operator
operator IppiPointL() const316     inline operator IppiPointL() const { IppiPointL point = {x, y}; return point; }
317 
318     // IwiRoi to C IwiSize cast operator
operator ::IwiSize() const319     inline operator ::IwiSize()  const { ::IwiSize size  = {width, height}; return size; }
320 };
321 
322 // Stores extrapolation type of border and border value for constant border
323 class IwiBorderType
324 {
325 public:
326     // Default constructor
IwiBorderType()327     IwiBorderType()
328     {
329         m_type  = ippBorderRepl;
330     }
331 
332     // Default constructor with border type
IwiBorderType(::IwiBorderType borderType)333     IwiBorderType(::IwiBorderType borderType)
334     {
335         m_type  = borderType;
336     }
337 
338     // Constructor for borders combination
IwiBorderType(int borderType)339     IwiBorderType(int borderType)
340     {
341         m_type  = (::IwiBorderType)(borderType);
342     }
343 
344     // Default constructor with border type and value
IwiBorderType(::IwiBorderType borderType,IwValueFloat value)345     IwiBorderType(::IwiBorderType borderType, IwValueFloat value)
346     {
347         m_value = value;
348         m_type  = borderType;
349     }
350 
351     // Set new border type without affecting flags
SetType(::IwiBorderType type)352     inline void SetType(::IwiBorderType type)
353     {
354         m_type = (::IwiBorderType)(StripType()|(0xF&type));
355     }
356 
357     // Set new border flags without affecting the type
SetFlags(int flags)358     inline void SetFlags(int flags)
359     {
360         m_type = (::IwiBorderType)(StripFlags()|(flags&(~0xF)));
361     }
362 
363     // Return border flags without type
StripType() const364     inline int StripType() const
365     {
366         return (m_type&(~0xF));
367     }
368 
369     // Return border type without flags
StripFlags() const370     inline IwiBorderType StripFlags() const
371     {
372         return (m_type&0xF);
373     }
374 
375     // IwiBorderType to bool cast operator
operator bool() const376     inline operator bool() const { return (m_type)?true:false; }
377 
378     // IwiBorderType to int cast operator
operator int() const379     inline operator int() const { return (int)m_type; }
380 
381     // IwiBorderType to ::IwiBorderType cast operator
operator ::IwiBorderType() const382     inline operator ::IwiBorderType() const { return m_type; }
383 
384     // Compares border type
operator ==(const IwiBorderType & rhs) const385     bool operator==(const IwiBorderType& rhs) const
386     {
387         if(this->m_type == rhs.m_type)
388         {
389             if(this->m_type == ippBorderConst)
390             {
391                 if(this->m_value == rhs.m_value)
392                     return true;
393                 else
394                     return false;
395             }
396             return true;
397         }
398         else
399             return false;
400     }
operator !=(const IwiBorderType & rhs) const401     bool operator!=(const IwiBorderType& rhs) const
402     {
403         return !(*this==rhs);
404     }
operator ==(const::IwiBorderType & rhs) const405     bool operator==(const ::IwiBorderType& rhs) const
406     {
407         if(this->m_type == rhs)
408             return true;
409         else
410             return false;
411     }
operator !=(const::IwiBorderType & rhs) const412     bool operator!=(const ::IwiBorderType& rhs) const
413     {
414         return !(*this==rhs);
415     }
operator !() const416     bool operator!() const
417     {
418         return !(m_type);
419     }
420 
421     // Computes logical OR for border type. This affects only flags part of the variable
operator |=(const int & rhs)422     inline IwiBorderType& operator|=(const int &rhs)
423     {
424         this->m_type = (IwiBorderType)(this->m_type|(rhs&(~0xF)));
425         return *this;
426     }
operator |(const int & rhs) const427     inline IwiBorderType operator|(const int &rhs) const
428     {
429         IwiBorderType result = *this;
430         result |= rhs;
431         return result;
432     }
operator |=(const IwiBorderType & rhs)433     inline IwiBorderType& operator|=(const IwiBorderType &rhs)
434     {
435         this->m_type = (IwiBorderType)(this->m_type|(rhs.m_type&(~0xF)));
436         return *this;
437     }
operator |(const IwiBorderType & rhs) const438     inline IwiBorderType operator|(const IwiBorderType &rhs) const
439     {
440         IwiBorderType result = *this;
441         result |= rhs;
442         return result;
443     }
operator |=(const IppiBorderType & rhs)444     inline IwiBorderType& operator|=(const IppiBorderType &rhs)
445     {
446         this->m_type = (IwiBorderType)(this->m_type|(rhs&(~0xF)));
447         return *this;
448     }
operator |(const IppiBorderType & rhs) const449     inline IwiBorderType operator|(const IppiBorderType &rhs) const
450     {
451         IwiBorderType result = *this;
452         result |= rhs;
453         return result;
454     }
455 
456     // Computes logical AND for border type. This affects only flags part of the variable
operator &=(const int & rhs)457     inline IwiBorderType& operator&=(const int &rhs)
458     {
459         this->m_type = (IwiBorderType)(this->m_type&(rhs&(~0xF)));
460         return *this;
461     }
operator &(const int & rhs) const462     inline IwiBorderType operator&(const int &rhs) const
463     {
464         IwiBorderType result = *this;
465         result &= rhs;
466         return result;
467     }
operator &=(const IwiBorderType & rhs)468     inline IwiBorderType& operator&=(const IwiBorderType &rhs)
469     {
470         this->m_type = (IwiBorderType)(this->m_type&(rhs.m_type&(~0xF)));
471         return *this;
472     }
operator &(const IwiBorderType & rhs) const473     inline IwiBorderType operator&(const IwiBorderType &rhs) const
474     {
475         IwiBorderType result = *this;
476         result &= rhs;
477         return result;
478     }
operator &=(const IppiBorderType & rhs)479     inline IwiBorderType& operator&=(const IppiBorderType &rhs)
480     {
481         this->m_type = (IwiBorderType)(this->m_type&(rhs&(~0xF)));
482         return *this;
483     }
operator &(const IppiBorderType & rhs) const484     inline IwiBorderType operator&(const IppiBorderType &rhs) const
485     {
486         IwiBorderType result = *this;
487         result &= rhs;
488         return result;
489     }
490 
491     ::IwiBorderType m_type;
492     IwValueFloat    m_value;
493 };
494 
495 // Stores border size data
496 class IwiBorderSize: public ::IwiBorderSize
497 {
498 public:
499     // Default constructor. Sets values to zero
IwiBorderSize()500     IwiBorderSize()
501     {
502         Set(0, 0, 0, 0);
503     }
504 
505     // One value template constructor. Sets border to same value. Useful for simple initialization, e.g.: border = 0
506     template<typename T>
IwiBorderSize(T border)507     IwiBorderSize(
508         T border // Position of point
509     )
510     {
511         Set((IwSize)border, (IwSize)border, (IwSize)border, (IwSize)border);
512     }
513 
514     // Constructor. Sets border to the specified values
IwiBorderSize(IwSize _left,IwSize _top,IwSize _right,IwSize _bottom)515     IwiBorderSize(
516         IwSize _left,   // Size of border to the left
517         IwSize _top,    // Size of border to the top
518         IwSize _right,  // Size of border to the right
519         IwSize _bottom  // Size of border to the bottom
520     )
521     {
522         Set(_left, _top, _right, _bottom);
523     }
524 
525     // Constructor from C IwiBorderSize structure
IwiBorderSize(::IwiBorderSize border)526     IwiBorderSize(
527         ::IwiBorderSize border // IwiBorderSize structure
528     )
529     {
530         Set(border.left, border.top, border.right, border.bottom);
531     }
532 
533     // Constructor from IppiBorderSize structure
IwiBorderSize(IppiBorderSize border)534     IwiBorderSize(
535         IppiBorderSize border // IwiBorderSize structure
536     )
537     {
538         Set(border.borderLeft, border.borderTop, border.borderRight, border.borderBottom);
539     }
540 
541     // Constructor from the image ROI
IwiBorderSize(IwiSize imageSize,IwiRoi imageRoi)542     IwiBorderSize(
543         IwiSize imageSize,   // Size of the image
544         IwiRoi  imageRoi     // Image ROI
545     )
546     {
547         Set(imageSize, imageRoi);
548     }
549 
550     // Constructor from the mask size enumerator
IwiBorderSize(IppiMaskSize mask)551     IwiBorderSize(
552         IppiMaskSize mask   // Processing mask size enumerator
553     )
554     {
555         IwiSize size = ::iwiMaskToSize(mask);
556         Set(size.width/2, size.height/2, size.width/2, size.height/2);
557     }
558 
559     // Constructor from the kernel size
IwiBorderSize(IwiSize kernel)560     IwiBorderSize(
561         IwiSize kernel   // Processing kernel size
562     )
563     {
564         Set(kernel.width/2, kernel.height/2, kernel.width/2, kernel.height/2);
565     }
566 
567     // Sets border to the specified values
Set(IwSize _left,IwSize _top,IwSize _right,IwSize _bottom)568     void Set(
569         IwSize _left,   // Size of border to the left
570         IwSize _top,    // Size of border to the top
571         IwSize _right,  // Size of border to the right
572         IwSize _bottom  // Size of border to the bottom
573     )
574     {
575         left      = _left;
576         top       = _top;
577         right     = _right;
578         bottom    = _bottom;
579     }
580 
581     // Sets border from the image ROI
Set(IwiSize imageSize,IwiRoi imageRoi)582     void Set(
583         IwiSize imageSize,   // Size of the image
584         IwiRoi  imageRoi     // Image ROI
585     )
586     {
587         left      = imageRoi.x;
588         top       = imageRoi.y;
589         right     = imageSize.width  - imageRoi.x - imageRoi.width;
590         bottom    = imageSize.height - imageRoi.y - imageRoi.height;
591     }
592 
593     // Returns true if all borders are zero
Empty() const594     bool Empty() const
595     {
596         return !(this->left || this->top || this->right || this->bottom);
597     }
598 
599     // Returns border size which contains maximum values of two border
Max(IwiBorderSize lhs,const IwiBorderSize & rhs)600     static IwiBorderSize Max(IwiBorderSize lhs, const IwiBorderSize &rhs)
601     {
602         lhs.left    = IPP_MAX(lhs.left, rhs.left);
603         lhs.top     = IPP_MAX(lhs.top, rhs.top);
604         lhs.right   = IPP_MAX(lhs.right, rhs.right);
605         lhs.bottom  = IPP_MAX(lhs.bottom, rhs.bottom);
606         return lhs;
607     }
608 
609     // Returns border size which contains minimum values of two border
Min(IwiBorderSize lhs,const IwiBorderSize & rhs)610     static IwiBorderSize Min(IwiBorderSize lhs, const IwiBorderSize &rhs)
611     {
612         lhs.left    = IPP_MIN(lhs.left, rhs.left);
613         lhs.top     = IPP_MIN(lhs.top, rhs.top);
614         lhs.right   = IPP_MIN(lhs.right, rhs.right);
615         lhs.bottom  = IPP_MIN(lhs.bottom, rhs.bottom);
616         return lhs;
617     }
618 
619     // Adds constant to the border
operator +=(const int & rhs)620     inline IwiBorderSize& operator+=(const int &rhs)
621     {
622         this->left   += rhs;
623         this->top    += rhs;
624         this->right  += rhs;
625         this->bottom += rhs;
626         return *this;
627     }
operator +(const int & rhs) const628     inline IwiBorderSize operator+(const int &rhs) const
629     {
630         IwiBorderSize result = *this;
631         result += rhs;
632         return result;
633     }
634 
635     // Subtracts constant from the border
operator -=(const int & rhs)636     inline IwiBorderSize& operator-=(const int &rhs)
637     {
638         this->left   -= rhs;
639         this->top    -= rhs;
640         this->right  -= rhs;
641         this->bottom -= rhs;
642         return *this;
643     }
operator -(const int & rhs) const644     inline IwiBorderSize operator-(const int &rhs) const
645     {
646         IwiBorderSize result = *this;
647         result -= rhs;
648         return result;
649     }
650 
651     // Multiplies the border by the constant
operator *=(const double & rhs)652     inline IwiBorderSize& operator*=(const double &rhs)
653     {
654         this->left   = (IwSize)(this->left*rhs);
655         this->top    = (IwSize)(this->top*rhs);
656         this->right  = (IwSize)(this->right*rhs);
657         this->bottom = (IwSize)(this->bottom*rhs);
658         return *this;
659     }
operator *(const double & rhs) const660     inline IwiBorderSize operator*(const double &rhs) const
661     {
662         IwiBorderSize result = *this;
663         result *= rhs;
664         return result;
665     }
666 
667     // Divides the border by the constant
operator /=(const double & rhs)668     inline IwiBorderSize& operator/=(const double &rhs)
669     {
670         this->left   = (IwSize)(this->left/rhs);
671         this->top    = (IwSize)(this->top/rhs);
672         this->right  = (IwSize)(this->right/rhs);
673         this->bottom = (IwSize)(this->bottom/rhs);
674         return *this;
675     }
operator /(const double & rhs) const676     inline IwiBorderSize operator/(const double &rhs) const
677     {
678         IwiBorderSize result = *this;
679         result /= rhs;
680         return result;
681     }
682 
683     // Adds border to the border
operator +=(const IwiBorderSize & rhs)684     inline IwiBorderSize& operator+=(const IwiBorderSize &rhs)
685     {
686         this->left   += rhs.left;
687         this->top    += rhs.top;
688         this->right  += rhs.right;
689         this->bottom += rhs.bottom;
690         return *this;
691     }
operator +(const IwiBorderSize & rhs) const692     inline IwiBorderSize operator+(const IwiBorderSize &rhs) const
693     {
694         IwiBorderSize result = *this;
695         result += rhs;
696         return result;
697     }
698 
699     // Subtracts border from the border
operator -=(const IwiBorderSize & rhs)700     inline IwiBorderSize& operator-=(const IwiBorderSize &rhs)
701     {
702         this->left   -= rhs.left;
703         this->top    -= rhs.top;
704         this->right  -= rhs.right;
705         this->bottom -= rhs.bottom;
706         return *this;
707     }
operator -(const IwiBorderSize & rhs) const708     inline IwiBorderSize operator-(const IwiBorderSize &rhs) const
709     {
710         IwiBorderSize result = *this;
711         result -= rhs;
712         return result;
713     }
714 
715 };
716 
717 // Convert IppiMaskSize enumerator to actual IwiSize size
718 // Returns:
719 //      Width and height of IppiMaskSize in pixels
iwiMaskToSize(IppiMaskSize mask)720 IW_DECL_CPP(IwiSize) iwiMaskToSize(
721     IppiMaskSize mask    // Kernel or mask size enumerator
722 )
723 {
724     return ::iwiMaskToSize(mask);
725 }
726 
727 // Convert kernel or mask size to border size
728 // Returns:
729 //      Border required for a filter with specified kernel size
iwiSizeToBorderSize(IwiSize kernelSize)730 IW_DECL_CPP(IwiBorderSize) iwiSizeToBorderSize(
731     IwiSize kernelSize   // Size of kernel as from iwiMaskToSize() or arbitrary
732 )
733 {
734     return ::iwiSizeToBorderSize(kernelSize);
735 }
736 
737 /* /////////////////////////////////////////////////////////////////////////////
738 //                   IwiImage - Image class
739 ///////////////////////////////////////////////////////////////////////////// */
740 
741 // IwiImage is a base class for IW image processing functions to store input and output data.
742 class IwiImage: public ::IwiImage
743 {
744 public:
745     // Default constructor. Sets values to zero
IwiImage()746     IwiImage()
747     {
748         iwiImage_Init(this);
749 
750         m_pRefCounter = new int;
751         if(!m_pRefCounter)
752             OWN_ERROR_THROW_ONLY(ippStsMemAllocErr)
753         (*m_pRefCounter) = 1;
754     }
755 
756     // Copy constructor for C++ object. Performs lazy copy of an internal image
IwiImage(const IwiImage & image)757     IwiImage(
758         const IwiImage &image           // Source image
759     )
760     {
761         iwiImage_Init(this);
762 
763         m_pRefCounter = new int;
764         if(!m_pRefCounter)
765             OWN_ERROR_THROW_ONLY(ippStsMemAllocErr)
766         (*m_pRefCounter) = 1;
767 
768         *this = image;
769     }
770 
771     // Copy constructor for C object. Initializes image structure with external buffer
IwiImage(const::IwiImage & image)772     IwiImage(
773         const ::IwiImage &image         // Source image
774     )
775     {
776         iwiImage_Init(this);
777 
778         m_pRefCounter = new int;
779         if(!m_pRefCounter)
780             OWN_ERROR_THROW_ONLY(ippStsMemAllocErr)
781         (*m_pRefCounter) = 1;
782 
783         *this = image;
784     }
785 
786     // Constructor with initialization. Initializes image structure with external buffer
IwiImage(IwiSize size,IppDataType dataType,int channels,IwiBorderSize inMemBorder=IwiBorderSize (),void * pBuffer=NULL,IwSize step=0)787     IwiImage(
788         IwiSize         size,                           // Image size, in pixels
789         IppDataType     dataType,                       // Image pixel type
790         int             channels,                       // Number of image channels
791         IwiBorderSize   inMemBorder = IwiBorderSize(),  // Size of border around image or NULL if there is no border
792         void           *pBuffer     = NULL,             // Pointer to the external buffer image buffer
793         IwSize          step        = 0                 // Distance, in bytes, between the starting points of consecutive lines in the external buffer
794     )
795     {
796         IppStatus status;
797         iwiImage_Init(this);
798 
799         m_pRefCounter = new int;
800         if(!m_pRefCounter)
801             OWN_ERROR_THROW_ONLY(ippStsMemAllocErr)
802         (*m_pRefCounter) = 1;
803 
804         status = Init(size, dataType, channels, inMemBorder, pBuffer, step);
805         OWN_ERROR_CHECK_THROW_ONLY(status);
806     }
807 
808     // Default destructor
~IwiImage()809     ~IwiImage()
810     {
811         Release();
812 
813         if(m_pRefCounter)
814         {
815             if(iwAtomic_AddInt(m_pRefCounter, -1) == 1)
816                 delete m_pRefCounter;
817         }
818     }
819 
820     // Copy operator for C++ object. Performs lazy copy of an internal image
operator =(const IwiImage & image)821     IwiImage& operator=(const IwiImage &image)
822     {
823         if(!m_pRefCounter)
824             OWN_ERROR_THROW_ONLY(ippStsNullPtrErr)
825 
826         if(&image == this)
827             return *this;
828 
829         if(image.m_ptr)
830         {
831             IppStatus status = Init(image.m_size, image.m_dataType, image.m_channels, image.m_inMemSize, image.m_ptr, image.m_step);
832             OWN_ERROR_CHECK_THROW_ONLY(status);
833         }
834         else
835         {
836             IppStatus status = Init(image.m_size, image.m_dataType, image.m_channels, image.m_inMemSize, image.m_ptrConst, image.m_step);
837             OWN_ERROR_CHECK_THROW_ONLY(status);
838         }
839 
840         if(image.m_pBuffer)
841         {
842             iwAtomic_AddInt(image.m_pRefCounter, 1);
843 
844             if(iwAtomic_AddInt(m_pRefCounter, -1) == 1)
845                 delete this->m_pRefCounter;
846             this->m_pRefCounter = image.m_pRefCounter;
847             this->m_pBuffer     = image.m_pBuffer;
848         }
849 
850         return *this;
851     }
852 
853     // Copy operator for C object. Initializes image structure with external buffer
operator =(const::IwiImage & image)854     IwiImage& operator=(const ::IwiImage &image)
855     {
856         if(!m_pRefCounter)
857             OWN_ERROR_THROW_ONLY(ippStsNullPtrErr)
858 
859         if(image.m_ptr)
860         {
861             IppStatus status = Init(image.m_size, image.m_dataType, image.m_channels, image.m_inMemSize, image.m_ptr, image.m_step);
862             OWN_ERROR_CHECK_THROW_ONLY(status);
863         }
864         else
865         {
866             IppStatus status = Init(image.m_size, image.m_dataType, image.m_channels, image.m_inMemSize, image.m_ptrConst, image.m_step);
867             OWN_ERROR_CHECK_THROW_ONLY(status);
868         }
869         return *this;
870     }
871 
872     // Initializes image structure with external buffer
873     // Returns:
874     //      ippStsNoErr                         no errors
Init(IwiSize size,IppDataType dataType,int channels,IwiBorderSize inMemBorder=IwiBorderSize (),void * pBuffer=NULL,IwSize step=0)875     IppStatus Init(
876         IwiSize         size,                           // Image size, in pixels
877         IppDataType     dataType,                       // Image pixel type
878         int             channels,                       // Number of image channels
879         IwiBorderSize   inMemBorder = IwiBorderSize(),  // Size of border around image or NULL if there is no border
880         void           *pBuffer     = NULL,             // Pointer to the external buffer image buffer
881         IwSize          step        = 0                 // Distance, in bytes, between the starting points of consecutive lines in the external buffer
882     )
883     {
884         if(this->m_pBuffer && this->m_pBuffer == pBuffer)
885             return ippStsNoErr;
886 
887         IppStatus status = Release();
888         OWN_ERROR_CHECK(status);
889 
890         status = iwiImage_InitExternal(this, size, dataType, channels, &inMemBorder, pBuffer, step);
891         OWN_ERROR_CHECK(status);
892         return status;
893     }
894 
895     // Initializes image structure with external read-only buffer
896     // Returns:
897     //      ippStsNoErr                         no errors
Init(IwiSize size,IppDataType dataType,int channels,IwiBorderSize inMemBorder,const void * pBuffer,IwSize step)898     IppStatus Init(
899         IwiSize         size,                           // Image size, in pixels
900         IppDataType     dataType,                       // Image pixel type
901         int             channels,                       // Number of image channels
902         IwiBorderSize   inMemBorder,                    // Size of border around image or NULL if there is no border
903         const void     *pBuffer,                        // Pointer to the external buffer image buffer
904         IwSize          step                            // Distance, in bytes, between the starting points of consecutive lines in the external buffer
905     )
906     {
907         if(this->m_pBuffer && this->m_pBuffer == pBuffer)
908             return ippStsNoErr;
909 
910         IppStatus status = Release();
911         OWN_ERROR_CHECK(status);
912 
913         status = iwiImage_InitExternalConst(this, size, dataType, channels, &inMemBorder, pBuffer, step);
914         OWN_ERROR_CHECK(status);
915         return status;
916     }
917 
918     // Initializes image structure and allocates image data
919     // Throws:
920     //      ippStsDataTypeErr                   data type is illegal
921     //      ippStsNumChannelsErr                channels value is illegal
922     // Returns:
923     //      ippStsNoErr                         no errors
Alloc(IwiSize size,IppDataType dataType,int channels,IwiBorderSize inMemBorder=IwiBorderSize ())924     IppStatus Alloc(
925         IwiSize         size,                           // Image size, in pixels
926         IppDataType     dataType,                       // Image pixel type
927         int             channels,                       // Number of image channels
928         IwiBorderSize   inMemBorder = IwiBorderSize()   // Size of border around image or NULL if there is no border
929     )
930     {
931         IppStatus status = Release();
932         OWN_ERROR_CHECK(status);
933 
934         status = iwiImage_Alloc(this, size, dataType, channels, &inMemBorder);
935         OWN_ERROR_CHECK(status);
936         return status;
937     }
938 
939     // Releases image data if it was allocated by IwiImage::Alloc
940     // Returns:
941     //      ippStsNoErr                         no errors
Release()942     IppStatus Release()
943     {
944         if(!m_pRefCounter)
945             OWN_ERROR_THROW_ONLY(ippStsNullPtrErr)
946 
947         if(iwAtomic_AddInt(m_pRefCounter, -1) > 1)
948         {
949             m_pRefCounter    = new int;
950             (*m_pRefCounter) = 1;
951 
952             m_pBuffer = NULL;
953             m_ptr     = NULL;
954             m_step    = 0;
955         }
956         else
957         {
958             (*m_pRefCounter) = 1;
959             iwiImage_Release(this);
960         }
961         return ippStsNoErr;
962     }
963 
964     // Returns pointer to specified pixel position in image buffer
965     // Returns:
966     //      Pointer to the image data
ptr(IwSize y=0,IwSize x=0,int ch=0) const967     inline void* ptr(
968         IwSize y  = 0,  // y shift, as rows
969         IwSize x  = 0,  // x shift, as columns
970         int    ch = 0   // channels shift
971     ) const
972     {
973         return iwiImage_GetPtr(this, y, x, ch);
974     }
975 
976     // Returns pointer to specified pixel position in read-only image buffer
977     // Returns:
978     //      Pointer to the image data
ptrConst(IwSize y=0,IwSize x=0,int ch=0) const979     inline const void* ptrConst(
980         IwSize y  = 0,  // y shift, as rows
981         IwSize x  = 0,  // x shift, as columns
982         int    ch = 0   // channels shift
983     ) const
984     {
985         return iwiImage_GetPtrConst(this, y, x, ch);
986     }
987 
988     // Applies ROI to the current image by adjusting size and starting point of the image. Can be applied recursively.
989     // This function saturates ROIs which step outside of the image border.
990     // If ROI has no intersection with the image then resulted image size will be 0x0
991     // Throws:
992     //      ippStsNullPtrErr                    unexpected NULL pointer
993     // Returns:
994     //      ippStsNoErr                         no errors
RoiSet(ipp::IwiRoi roi)995     IppStatus RoiSet(
996         ipp::IwiRoi roi // Roi rectangle of the required sub-image
997     )
998     {
999         IppStatus status = iwiImage_RoiSet(this, roi);
1000         OWN_ERROR_CHECK(status);
1001         return ippStsNoErr;
1002     }
1003 
1004     // Returns sub-image with size and starting point of the specified ROI
1005     // Returns:
1006     //      IwiImage object of sub-image
GetRoiImage(ipp::IwiRoi roi) const1007     IwiImage GetRoiImage(
1008         ipp::IwiRoi roi             // Roi rectangle of the required sub-image
1009     ) const
1010     {
1011         return iwiImage_GetRoiImage(this, roi);
1012     }
1013 
1014     // Add border size to current inMem image border, making image size smaller. Resulted image cannot be smaller than 1x1 pixels
1015     // Throws:
1016     //      ippStsSizeErr                       ROI size is illegal
1017     //      ippStsNullPtrErr                    unexpected NULL pointer
1018     // Returns:
1019     //      ippStsNoErr                         no errors
operator +=(const IwiBorderSize & rhs)1020     inline IwiImage& operator+=(const IwiBorderSize &rhs)
1021     {
1022         IppStatus status = iwiImage_BorderAdd(this, rhs);
1023         OWN_ERROR_CHECK_THROW_ONLY(status);
1024         return *this;
1025     }
operator +(const IwiBorderSize & rhs) const1026     inline IwiImage operator+(const IwiBorderSize &rhs) const
1027     {
1028         IwiImage  result = *this;
1029         IppStatus status = iwiImage_BorderAdd(&result, rhs);
1030         OWN_ERROR_CHECK_THROW_ONLY(status);
1031         return result;
1032     }
1033 
1034     // Subtracts border size from current inMem image border, making image size bigger. Resulted border cannot be lesser than 0
1035     // Throws:
1036     //      ippStsOutOfRangeErr                 ROI is out of image
1037     //      ippStsNullPtrErr                    unexpected NULL pointer
operator -=(const IwiBorderSize & rhs)1038     inline IwiImage& operator-=(const IwiBorderSize &rhs)
1039     {
1040         IppStatus status = iwiImage_BorderSub(this, rhs);
1041         OWN_ERROR_CHECK_THROW_ONLY(status);
1042         return *this;
1043     }
operator -(const IwiBorderSize & rhs) const1044     inline IwiImage operator-(const IwiBorderSize &rhs) const
1045     {
1046         IwiImage  result = *this;
1047         IppStatus status = iwiImage_BorderSub(&result, rhs);
1048         OWN_ERROR_CHECK_THROW_ONLY(status);
1049         return result;
1050     }
1051 
1052     // Set border size to current inMem image border, adjusting image size. Resulted image cannot be smaller than 1x1 pixels.
1053     // Throws:
1054     //      ippStsSizeErr                       ROI size is illegal
1055     //      ippStsNullPtrErr                    unexpected NULL pointer
operator =(const IwiBorderSize & rhs)1056     inline IwiImage& operator=(const IwiBorderSize &rhs)
1057     {
1058         IppStatus status = iwiImage_BorderSet(this, rhs);
1059         OWN_ERROR_CHECK_THROW_ONLY(status);
1060         return *this;
1061     }
1062 
1063     // Returns true if image has an assigned buffer
Exists() const1064     inline bool Exists() const
1065     {
1066         return (this->m_ptrConst)?true:false;
1067     }
1068 
1069     // Returns true if image doesn't have an assigned buffer or its dimensions have zero size
Empty() const1070     inline bool Empty() const
1071     {
1072         return (Exists() && this->m_size.width && this->m_size.height)?false:true;
1073     }
1074 
1075     // Compares image structures and returns true if structure parameters are compatible, e.g. copy operation can be performed without reallocation
Similar(const ipp::IwiImage & rhs) const1076     bool Similar(const ipp::IwiImage& rhs) const
1077     {
1078         if(this->m_dataType == rhs.m_dataType &&
1079             this->m_channels == rhs.m_channels)
1080             return true;
1081         else
1082             return false;
1083     }
1084 
1085     /**/////////////////////////////////////////////////////////////////////////////
1086     //                   Arithmetic operators
1087     ///////////////////////////////////////////////////////////////////////////// */
1088 
1089     // Adds one image to another
1090     // Throws:
1091     //      ippStsDataTypeErr                   data type is illegal
1092     //      ippStsNumChannelsErr                channels value is illegal
1093     //      ippStsSizeErr                       size fields values are illegal
1094     //      ippStsNullPtrErr                    unexpected NULL pointer
operator +=(const IwiImage & rhs)1095     inline IwiImage& operator+=(const IwiImage &rhs)
1096     {
1097         IppStatus status = ::iwiAdd(&rhs, this, this, NULL, NULL);
1098         OWN_ERROR_CHECK_THROW_ONLY(status);
1099         return *this;
1100     }
1101 
1102     // Adds constant to the image
1103     // Throws:
1104     //      ippStsDataTypeErr                   data type is illegal
1105     //      ippStsNumChannelsErr                channels value is illegal
1106     //      ippStsSizeErr                       size fields values are illegal
1107     //      ippStsNullPtrErr                    unexpected NULL pointer
operator +=(const IwValueFloat & rhs)1108     inline IwiImage& operator+=(const IwValueFloat &rhs)
1109     {
1110         IppStatus status = ::iwiAddC(rhs, rhs.ValuesNum(), this, this, NULL, NULL);
1111         OWN_ERROR_CHECK_THROW_ONLY(status);
1112         return *this;
1113     }
1114 
1115     // Subtracts one image from another
1116     // Throws:
1117     //      ippStsDataTypeErr                   data type is illegal
1118     //      ippStsNumChannelsErr                channels value is illegal
1119     //      ippStsSizeErr                       size fields values are illegal
1120     //      ippStsNullPtrErr                    unexpected NULL pointer
operator -=(const IwiImage & rhs)1121     inline IwiImage& operator-=(const IwiImage &rhs)
1122     {
1123         IppStatus status = ::iwiSub(&rhs, this, this, NULL, NULL);
1124         OWN_ERROR_CHECK_THROW_ONLY(status);
1125         return *this;
1126     }
1127 
1128     // Subtracts constant from the image
1129     // Throws:
1130     //      ippStsDataTypeErr                   data type is illegal
1131     //      ippStsNumChannelsErr                channels value is illegal
1132     //      ippStsSizeErr                       size fields values are illegal
1133     //      ippStsNullPtrErr                    unexpected NULL pointer
operator -=(const IwValueFloat & rhs)1134     inline IwiImage& operator-=(const IwValueFloat &rhs)
1135     {
1136         IppStatus status = ::iwiSubC(rhs, rhs.ValuesNum(), this, this, NULL, NULL);
1137         OWN_ERROR_CHECK_THROW_ONLY(status);
1138         return *this;
1139     }
1140 
1141     // Multiplies one image by another
1142     // Throws:
1143     //      ippStsDataTypeErr                   data type is illegal
1144     //      ippStsNumChannelsErr                channels value is illegal
1145     //      ippStsSizeErr                       size fields values are illegal
1146     //      ippStsNullPtrErr                    unexpected NULL pointer
operator *=(const IwiImage & rhs)1147     inline IwiImage& operator*=(const IwiImage &rhs)
1148     {
1149         IppStatus status = ::iwiMul(&rhs, this, this, NULL, NULL);
1150         OWN_ERROR_CHECK_THROW_ONLY(status);
1151         return *this;
1152     }
1153 
1154     // Multiplies the image by the constant
1155     // Throws:
1156     //      ippStsDataTypeErr                   data type is illegal
1157     //      ippStsNumChannelsErr                channels value is illegal
1158     //      ippStsSizeErr                       size fields values are illegal
1159     //      ippStsNullPtrErr                    unexpected NULL pointer
operator *=(const IwValueFloat & rhs)1160     inline IwiImage& operator*=(const IwValueFloat &rhs)
1161     {
1162         IppStatus status = ::iwiMulC(rhs, rhs.ValuesNum(), this, this, NULL, NULL);
1163         OWN_ERROR_CHECK_THROW_ONLY(status);
1164         return *this;
1165     }
1166 
1167     // Divides one image by another
1168     // Throws:
1169     //      ippStsDataTypeErr                   data type is illegal
1170     //      ippStsNumChannelsErr                channels value is illegal
1171     //      ippStsSizeErr                       size fields values are illegal
1172     //      ippStsNullPtrErr                    unexpected NULL pointer
operator /=(const IwiImage & rhs)1173     inline IwiImage& operator/=(const IwiImage &rhs)
1174     {
1175         IppStatus status = ::iwiDiv(&rhs, this, this, NULL, NULL);
1176         OWN_ERROR_CHECK_THROW_ONLY(status);
1177         return *this;
1178     }
1179 
1180     // Divides the image by the constant
1181     // Throws:
1182     //      ippStsDataTypeErr                   data type is illegal
1183     //      ippStsNumChannelsErr                channels value is illegal
1184     //      ippStsSizeErr                       size fields values are illegal
1185     //      ippStsNullPtrErr                    unexpected NULL pointer
operator /=(const IwValueFloat & rhs)1186     inline IwiImage& operator/=(const IwValueFloat &rhs)
1187     {
1188         IppStatus status = ::iwiDivC(rhs, rhs.ValuesNum(), this, this, NULL, NULL);
1189         OWN_ERROR_CHECK_THROW_ONLY(status);
1190         return *this;
1191     }
1192 
1193 private:
1194     int *m_pRefCounter;  // Shared reference counter for allocated memory
1195 };
1196 
1197 // IwiImageArray holds an array of IwiImages for processing
1198 class IwiImageArray
1199 {
1200 public:
1201     // Default constructor
IwiImageArray(const IwiImage & image1=IwiImage (),const IwiImage & image2=IwiImage (),const IwiImage & image3=IwiImage (),const IwiImage & image4=IwiImage ())1202     IwiImageArray(
1203         const IwiImage &image1 = IwiImage(),
1204         const IwiImage &image2 = IwiImage(),
1205         const IwiImage &image3 = IwiImage(),
1206         const IwiImage &image4 = IwiImage()
1207     )
1208     {
1209         imArray[0] = image1;
1210         imArray[1] = image2;
1211         imArray[2] = image3;
1212         imArray[3] = image4;
1213     }
1214 
1215     // Copy operator for single IwiImage object
operator =(const IwiImage & image)1216     const IwiImageArray& operator=(const IwiImage &image)
1217     {
1218         imArray[0] = image;
1219         return *this;
1220     }
1221 
1222     IwiImage imArray[4];
1223 };
1224 
1225 
1226 /* /////////////////////////////////////////////////////////////////////////////
1227 //                   IW Tiling
1228 ///////////////////////////////////////////////////////////////////////////// */
1229 
1230 /* /////////////////////////////////////////////////////////////////////////////
1231 //                   IwiTile-based basic tiling
1232 ///////////////////////////////////////////////////////////////////////////// */
1233 
1234 // This is a wrapper class for the basic IwiTile tiling API
1235 class IwiTile: public ::IwiTile
1236 {
1237 public:
1238     // Default constructor.
IwiTile()1239     IwiTile()
1240     {
1241         this->m_initialized = 0;
1242     }
1243 
1244     // Constructor with initialization.
IwiTile(const::IwiRoi & tileRoi)1245     IwiTile(
1246         const ::IwiRoi &tileRoi    // [in] Tile offset and size
1247     )
1248     {
1249         this->m_initialized = 0;
1250         SetRoi(tileRoi);
1251     }
1252 
1253     // Basic tiling initializer for IwiTile structure.
1254     // Use this method to set up single function tiling or tiling for pipelines with border-less functions.
1255     // For functions which operate with different sizes for source and destination images use destination size as a base
1256     // for tile parameters.
SetRoi(const::IwiRoi & tileRoi)1257     void SetRoi(
1258         const ::IwiRoi &tileRoi    // [in] Tile offset and size
1259     )
1260     {
1261         *(::IwiTile*)this = ::iwiTile_SetRoi(tileRoi);
1262     }
1263 
1264     // Assignment operator from C IwiRoi structure.
operator =(const::IwiRoi & tileRoi)1265     IwiTile& operator=(
1266         const ::IwiRoi &tileRoi    // [in] Tile offset and size
1267     )
1268     {
1269         SetRoi(tileRoi);
1270         return *this;
1271     }
1272 
1273 /* /////////////////////////////////////////////////////////////////////////////
1274 //                   Manual tiling control
1275 ///////////////////////////////////////////////////////////////////////////// */
1276 
1277     // Returns border with proper ippBorderInMem flags for current tile position, image size and border size
1278     // Returns:
1279     //      ippBorderInMem flags
GetTileBorder(IwiRoi roi,::IwiBorderType border,IwiBorderSize borderSize,IwiSize srcImageSize)1280     static IwiBorderType GetTileBorder(
1281         IwiRoi          roi,            // Tile position and size
1282         ::IwiBorderType border,         // Border type
1283         IwiBorderSize   borderSize,     // Border size
1284         IwiSize         srcImageSize    // Source image size
1285     )
1286     {
1287         return ::iwiTile_GetTileBorder(roi, border, borderSize, srcImageSize);
1288     }
1289 
1290     // Returns minimal acceptable tile size for the current border size and type
1291     // Returns:
1292     //      Minimal tile size
GetMinTileSize(::IwiBorderType border,IwiBorderSize borderSize)1293     static IwiSize GetMinTileSize(
1294         ::IwiBorderType border,     // Border type
1295         IwiBorderSize   borderSize  // Border size
1296     )
1297     {
1298         return ::iwiTile_GetMinTileSize(border, borderSize);
1299     }
1300 
1301     // Function corrects ROI position and size to prevent overlapping between filtering function border and image border in
1302     // case of border reconstruction. If image already has a right or a bottom border in memory and border type flags
1303     // ippBorderInMemRight or ippBorderInMemBottom were specified accordingly then no correction is required.
1304     //
1305     // C API descriptions has more details.
1306     // Returns:
1307     //      Corrected ROI
CorrectBordersOverlap(IwiRoi tile,::IwiBorderType border,IwiBorderSize borderSize,IwiSize srcImageSize)1308     static IwiRoi CorrectBordersOverlap(
1309         IwiRoi          tile,           // [in]     Tile position and size to be checked and corrected
1310         ::IwiBorderType border,         // [in]     Border type
1311         IwiBorderSize   borderSize,     // [in]     Border size
1312         IwiSize         srcImageSize    // [in]     Source image size
1313     )
1314     {
1315         return ::iwiTile_CorrectBordersOverlap(tile, border, borderSize, srcImageSize);
1316     }
1317 };
1318 
1319 /* /////////////////////////////////////////////////////////////////////////////
1320 //                   IwiTile-based pipeline tiling
1321 ///////////////////////////////////////////////////////////////////////////// */
1322 
1323 // Important notice:
1324 // This tiling API is created for tiling of complex pipelines with functions which use borders.
1325 // Tiling of pipelines instead of isolated functions can increase scalability of threading or performance of
1326 // non-threaded functions by performing all operations inside CPU cache.
1327 //
1328 // This is advanced tiling method, so you better know what you are doing.
1329 // 1. Pipeline tiling operates in reverse order: from destination to source.
1330 //    a. Use tile size based on final destination image size
1331 //    b. Initialize IwiTile structure with iwiTilePipeline_Init for the last operation
1332 //    c. Initialize IwiTile structure for other operations from last to first with iwiTilePipeline_InitChild
1333 // 2. Derive border size for each operation from its mask size, kernel size or specific border size getter if any
1334 // 3. If you have geometric transform inside pipeline, you need to implement IwiTileTransform interface for IwiTile for this transform operation
1335 // 4. In case of threading don't forget to copy initialized IwiTile structures to local thread or initialize them on
1336 //    per-thread basis. Access to structures is not thread safe!
1337 // 5. Do not exceed maximum tile size specified during initialization. This can lead to buffers overflow!
1338 //
1339 // There is a set of examples covering usage of tiling. Please refer to them for help.
1340 
1341 // Transform proxy function to loop-the-loop around interfaces an allow to use proper C++ approach. Don't use it directly.
1342 static int IPP_STDCALL __proxy_getSrcRoi__(::IwiRoi dstRoi, ::IwiRoi *pSrcRoi, void* pParams);
1343 
1344 // Geometric transform interface
1345 // To use geometric transforms inside pipeline tiling you need to implement this interface.
1346 class IwiTileTransform
1347 {
1348 public:
IwiTileTransform()1349     IwiTileTransform()
1350     {
1351         transformStruct.getSrcRoiFun = __proxy_getSrcRoi__;
1352         transformStruct.pParams      = this;
1353         transformStruct.srcImageSize = IwiSize();
1354     }
~IwiTileTransform()1355     virtual ~IwiTileTransform() {}
1356 
1357     // Source ROI getter
1358     virtual int GetSrcRoi(ipp::IwiRoi, ipp::IwiRoi&) const = 0;
1359 
1360     // Object clone method. This method is required to properly save transform object for current tile
1361     virtual void* Clone() const = 0;
1362 
1363     // IwiTileTransform to ::IwiTileTransform* cast operator
operator const::IwiTileTransform*() const1364     virtual operator const ::IwiTileTransform*() const { return &transformStruct; }
1365 
1366 protected:
1367     // Clone helper. This method can be use to implement Clone method for particular type
1368     template<class T>
CloneT() const1369     T* CloneT() const
1370     {
1371         T *clone = new T(*((T*)this));
1372         clone->transformStruct.pParams = clone; // Switch parameters for proxy function to address of new object
1373         return clone;
1374     }
1375 
1376     ::IwiTileTransform transformStruct;
1377 };
1378 
1379 // IwiTileTransform implementation for operation without transform.
1380 class IwiTileNoTransform: public IwiTileTransform
1381 {
1382 public:
IwiTileNoTransform()1383     IwiTileNoTransform()
1384     {
1385         transformStruct.getSrcRoiFun = NULL;
1386         transformStruct.pParams      = NULL;
1387     }
~IwiTileNoTransform()1388     virtual ~IwiTileNoTransform() {}
1389 
1390     // IwiTileTransform to ::IwiTileTransform* cast operator
operator const::IwiTileTransform*() const1391     virtual operator const ::IwiTileTransform*() const { return NULL; }
1392 
Clone() const1393     virtual void* Clone() const
1394     {
1395         return NULL;
1396     }
1397 
1398 private:
1399     // Source ROI getter
GetSrcRoi(ipp::IwiRoi,ipp::IwiRoi &) const1400     virtual int GetSrcRoi(ipp::IwiRoi, ipp::IwiRoi&) const
1401     {
1402         return -1;
1403     }
1404 };
1405 
1406 // Transform proxy function
__proxy_getSrcRoi__(::IwiRoi dstRoi,::IwiRoi * pSrcRoi,void * pParams)1407 static int IPP_STDCALL __proxy_getSrcRoi__(::IwiRoi dstRoi, ::IwiRoi *pSrcRoi, void* pParams)
1408 {
1409     if(!pSrcRoi || !pParams)
1410         return -1;
1411 
1412     ipp::IwiTileTransform *pTrans = (ipp::IwiTileTransform*)pParams;
1413     ipp::IwiRoi srcRoi;
1414     int status = pTrans->GetSrcRoi(dstRoi, srcRoi);
1415     if(!status)
1416         *pSrcRoi = srcRoi;
1417     return status;
1418 }
1419 
1420 // This is a wrapper class for the pipeline IwiTile tiling API
1421 class IwiTilePipeline: public IwiTile
1422 {
1423 public:
1424     // Default constructor.
IwiTilePipeline()1425     IwiTilePipeline()
1426     {
1427         this->pTransform    = NULL;
1428         this->m_initialized = 0;
1429     }
1430 
1431     // Constructor with initialization for the root node.
1432     // Throws:
1433     //      ippStsBadArgErr                     incorrect arg/param of the function
1434     //      ippStsNullPtrErr                    unexpected NULL pointer
IwiTilePipeline(IwiSize tileSizeMax,IwiSize dstImageSize,const IwiBorderType & borderType=IwiBorderType (),const IwiBorderSize & borderSize=IwiBorderSize (),const IwiTileTransform & transformStruct=IwiTileNoTransform ())1435     IwiTilePipeline(
1436         IwiSize                 tileSizeMax,                                // [in] Maximum tile size for intermediate buffers size calculation
1437         IwiSize                 dstImageSize,                               // [in] Destination image size for current operation
1438         const IwiBorderType    &borderType        = IwiBorderType(),        // [in] Border type for the current operation
1439         const IwiBorderSize    &borderSize        = IwiBorderSize(),        // [in] Border size for the current operation
1440         const IwiTileTransform &transformStruct   = IwiTileNoTransform()    // [in] Initialized transform structure if operation performs geometric transformation
1441     )
1442     {
1443         this->pTransform    = NULL;
1444         this->m_initialized = 0;
1445         IppStatus status = Init(tileSizeMax, dstImageSize, borderType, borderSize, transformStruct);
1446         OWN_ERROR_CHECK_THROW_ONLY(status);
1447     }
1448 
1449     // Constructor with initialization for the child node.
1450     // Throws:
1451     //      ippStsBadArgErr                     incorrect arg/param of the function
1452     //      ippStsNullPtrErr                    unexpected NULL pointer
IwiTilePipeline(IwiTilePipeline & parent,const IwiBorderType & borderType=IwiBorderType (),const IwiBorderSize & borderSize=IwiBorderSize (),const IwiTileTransform & transformStruct=IwiTileNoTransform ())1453     IwiTilePipeline(
1454         IwiTilePipeline        &parent,                                     // [in] IwiTile structure of previous operation
1455         const IwiBorderType    &borderType        = IwiBorderType(),        // [in] Border type for the current operation
1456         const IwiBorderSize    &borderSize        = IwiBorderSize(),        // [in] Border size for the current operation
1457         const IwiTileTransform &transformStruct   = IwiTileNoTransform()    // [in] Initialized transform structure if operation performs geometric transformation
1458     ) : IwiTile()
1459     {
1460         this->pTransform    = NULL;
1461         this->m_initialized = 0;
1462         IppStatus status = InitChild(parent, borderType, borderSize, transformStruct);
1463         OWN_ERROR_CHECK_THROW_ONLY(status);
1464     }
1465 
1466     // Default destructor
~IwiTilePipeline()1467     ~IwiTilePipeline()
1468     {
1469         iwiTilePipeline_Release(this);
1470         if(this->pTransform)
1471             delete this->pTransform;
1472     }
1473 
1474     // Pipeline tiling root node initializer for IwiTile structure.
1475     // This initializer should be used first and for IwiTile structure of the final operation.
1476     // Throws:
1477     //      ippStsBadArgErr                     incorrect arg/param of the function
1478     //      ippStsNullPtrErr                    unexpected NULL pointer
1479     // Returns:
1480     //      ippStsNoErr                         no errors
Init(IwiSize tileSizeMax,IwiSize dstImageSize,const IwiBorderType & borderType=IwiBorderType (),const IwiBorderSize & borderSize=IwiBorderSize (),const IwiTileTransform & transform=IwiTileNoTransform ())1481     IppStatus Init(
1482         IwiSize                 tileSizeMax,                        // [in] Maximum tile size for intermediate buffers size calculation
1483         IwiSize                 dstImageSize,                       // [in] Destination image size for current operation
1484         const IwiBorderType    &borderType  = IwiBorderType(),      // [in] Border type for the current operation
1485         const IwiBorderSize    &borderSize  = IwiBorderSize(),      // [in] Border size for the current operation
1486         const IwiTileTransform &transform   = IwiTileNoTransform()  // [in] Initialized transform structure if operation performs geometric transformation
1487     )
1488     {
1489         ::IwiBorderType border = borderType;
1490         if(this->pTransform)
1491             delete this->pTransform;
1492         pTransform = (IwiTileTransform*)transform.Clone();
1493         IppStatus status = ::iwiTilePipeline_Init(this, tileSizeMax, dstImageSize, &border, ((borderSize.Empty())?NULL:&borderSize), ((pTransform)?((const ::IwiTileTransform*)(*pTransform)):(NULL)));
1494         OWN_ERROR_CHECK(status);
1495         return status;
1496     }
1497 
1498     // Pipeline tiling child node initializer for IwiTile structure.
1499     // This initializer should be called for any operation preceding the last operation in reverse order.
1500     // Throws:
1501     //      ippStsBadArgErr                     incorrect arg/param of the function
1502     //      ippStsNullPtrErr                    unexpected NULL pointer
1503     // Returns:
1504     //      ippStsNoErr                         no errors
InitChild(IwiTilePipeline & parent,const IwiBorderType & borderType=IwiBorderType (),const IwiBorderSize & borderSize=IwiBorderSize (),const IwiTileTransform & transform=IwiTileNoTransform ())1505     IppStatus InitChild(
1506         IwiTilePipeline        &parent,                             // [in] IwiTile structure of previous operation
1507         const IwiBorderType    &borderType  = IwiBorderType(),      // [in] Border type for the current operation
1508         const IwiBorderSize    &borderSize  = IwiBorderSize(),      // [in] Border size for the current operation
1509         const IwiTileTransform &transform   = IwiTileNoTransform()  // [in] Initialized transform structure if operation performs geometric transformation
1510     )
1511     {
1512         ::IwiBorderType border = borderType;
1513         if(this->pTransform)
1514             delete this->pTransform;
1515         pTransform = (IwiTileTransform*)transform.Clone();
1516         IppStatus status = ::iwiTilePipeline_InitChild(this, &parent, &border, ((borderSize.Empty())?NULL:&borderSize), (pTransform)?((const ::IwiTileTransform*)(*pTransform)):NULL);
1517         OWN_ERROR_CHECK(status);
1518         return status;
1519     }
1520 
1521     // Sets current tile rectangle for the pipeline to process
1522     // Throws:
1523     //      ippStsContextMatchErr               internal structure is not initialized or of invalid type
1524     //      ippStsNullPtrErr                    unexpected NULL pointer
1525     // Returns:
1526     //      ippStsNoErr                         no errors
SetTile(IwiRoi tileRoi)1527     IppStatus SetTile(
1528         IwiRoi          tileRoi                // [in] Tile offset and size
1529     )
1530     {
1531         if(!this->m_initialized)
1532             OWN_ERROR_THROW(ippStsContextMatchErr);
1533 
1534         IppStatus status = ::iwiTilePipeline_SetRoi(this, tileRoi);
1535         OWN_ERROR_CHECK(status);
1536         return status;
1537     }
1538 
1539     // Pipeline tiling intermediate buffer size getter
1540     // Throws:
1541     //      ippStsContextMatchErr               internal structure is not initialized or of invalid type
1542     // Returns:
1543     //      Destination buffer size required by the current pipeline operation
GetDstBufferSize()1544     IwiSize GetDstBufferSize()
1545     {
1546         if(!this->m_initialized)
1547             OWN_ERROR_THROW_ONLY(ippStsContextMatchErr);
1548 
1549         IwiSize   size;
1550         IppStatus status = ::iwiTilePipeline_GetDstBufferSize(this, &size);
1551         OWN_ERROR_CHECK_THROW_ONLY(status);
1552 
1553         return size;
1554     }
1555 
1556     // Calculates actual border parameter with InMem flags for the current tile absolute and relative offsets and sizes
1557     // Throws:
1558     //      ippStsContextMatchErr               internal structure is not initialized or of invalid type
1559     // Returns:
1560     //      Border with InMem flags actual for the current tile
GetTileBorder(::IwiBorderType border)1561     IwiBorderType GetTileBorder(
1562         ::IwiBorderType border                 // [in] Extrapolation algorithm for out of image pixels
1563     )
1564     {
1565         if(!this->m_initialized)
1566             OWN_ERROR_THROW_ONLY(ippStsContextMatchErr);
1567 
1568         IppStatus status = ::iwiTilePipeline_GetTileBorder(this, &border);
1569         OWN_ERROR_CHECK_THROW_ONLY(status);
1570 
1571         return border;
1572     }
1573 
1574     // This function builds border for the current tile source buffer.
1575     // This allows to feed function with InMem borders only thus reducing possiblity of borders conflicts on image boundary.
1576     // By default this function is not applied to the first image in the pipeline, only to intermediate buffers, but
1577     // it can be used manually to construct border for it too.
1578     // Throws:
1579     //      ippStsContextMatchErr               internal structure is not initialized or of invalid type
1580     // Returns:
1581     //      ippStsNoErr                         no errors
BuildBorder(IwiImage & srcImage,IwiBorderType & border)1582     IppStatus BuildBorder(
1583         IwiImage        &srcImage,      // [in,out] Pointer to the source image for which to build border
1584         IwiBorderType   &border         // [in,out] Extrapolation algorithm for out of image pixels. Updated InMem flags will be returned here
1585     )
1586     {
1587         if(!this->m_initialized)
1588             OWN_ERROR_THROW(ippStsContextMatchErr);
1589 
1590         IppStatus status = ::iwiTilePipeline_BuildBorder(this, &srcImage, &border.m_type, border.m_value);
1591         OWN_ERROR_CHECK(status);
1592         return status;
1593     };
1594 
1595     // Returns full size of source image for the child pipeline element which includes required InMem borders.
1596     // This function is required to supply correct image size for geometric transform functions.
1597     // Throws:
1598     //      ippStsContextMatchErr               internal structure is not initialized or of invalid type
1599     //      ippStsNullPtrErr                    unexpected NULL pointer
1600     // Returns:
1601     //      Full image size with InMem part
GetChildSrcImageSize(IwiSize srcOrigSize)1602     IwiSize GetChildSrcImageSize(
1603         IwiSize srcOrigSize // [in]     Original source image size
1604     )
1605     {
1606         if(!this->m_initialized)
1607             OWN_ERROR_THROW_ONLY(ippStsContextMatchErr);
1608 
1609         IwiSize   size;
1610         IppStatus status =  ::iwiTilePipeline_GetChildSrcImageSize(this, srcOrigSize, &size);
1611         OWN_ERROR_CHECK_THROW_ONLY(status);
1612 
1613         return size;
1614     }
1615 
1616     // Returns full size of destination image for the child pipeline element which includes required InMem borders.
1617     // This function is required to supply correct image size for geometric transform functions.
1618     // Throws:
1619     //      ippStsContextMatchErr               internal structure is not initialized or of invalid type
1620     //      ippStsNullPtrErr                    unexpected NULL pointer
1621     // Returns:
1622     //      Full image size with InMem part
GetChildDstImageSize(IwiSize dstOrigSize)1623     IwiSize GetChildDstImageSize(
1624         IwiSize dstOrigSize // [in]     Original destination image size
1625     )
1626     {
1627         if(!this->m_initialized)
1628             OWN_ERROR_THROW_ONLY(ippStsContextMatchErr);
1629 
1630         IwiSize   size;
1631         IppStatus status =  ::iwiTilePipeline_GetChildDstImageSize(this, dstOrigSize, &size);
1632         OWN_ERROR_CHECK_THROW_ONLY(status);
1633 
1634         return size;
1635     }
1636 
1637     // Checks for image and buffer boundaries for the source buffer and limits tile rectangle
1638     // Throws:
1639     //      ippStsContextMatchErr               internal structure is not initialized or of invalid type
1640     // Returns:
1641     //      Source ROI bounded to the buffer size
GetBoundedSrcRoi()1642     IwiRoi GetBoundedSrcRoi()
1643     {
1644         if(!this->m_initialized)
1645             OWN_ERROR_THROW_ONLY(ippStsContextMatchErr);
1646 
1647         IwiRoi    roi;
1648         IppStatus status =  ::iwiTilePipeline_GetBoundedSrcRoi(this, &roi);
1649         OWN_ERROR_CHECK_THROW_ONLY(status);
1650 
1651         return roi;
1652     }
1653 
1654     // Checks for image and buffer boundaries for the destination buffer and limits tile rectangle
1655     // Throws:
1656     //      ippStsContextMatchErr               internal structure is not initialized or of invalid type
1657     // Returns:
1658     //      Destination ROI bounded to the buffer size
GetBoundedDstRoi()1659     IwiRoi GetBoundedDstRoi()
1660     {
1661         if(!this->m_initialized)
1662             OWN_ERROR_THROW_ONLY(ippStsContextMatchErr);
1663 
1664         IwiRoi    roi;
1665         IppStatus status =  ::iwiTilePipeline_GetBoundedDstRoi(this, &roi);
1666         OWN_ERROR_CHECK_THROW_ONLY(status);
1667 
1668         return roi;
1669     }
1670 
1671     // Returns minimal acceptable tile size for current pipeline
1672     // Throws:
1673     //      ippStsContextMatchErr               internal structure is not initialized or of invalid type
1674     //      ippStsErr                           tile calculation error
1675     // Returns:
1676     //      Minimal tile size allowed by the pipeline
GetMinTileSize()1677     IwiSize GetMinTileSize()
1678     {
1679         if(!this->m_initialized)
1680             OWN_ERROR_THROW_ONLY(ippStsContextMatchErr);
1681 
1682         IwiSize   minSize;
1683         IppStatus status = ::iwiTilePipeline_GetMinTileSize(this, &minSize);
1684         OWN_ERROR_CHECK_THROW_ONLY(status);
1685 
1686         return minSize;
1687     }
1688 
1689 private:
1690     // Disabled copy operator
operator =(const IwiTilePipeline &)1691     IwiTilePipeline& operator=(const IwiTilePipeline &) { return *this; }
1692 
1693     IwiTileTransform *pTransform;
1694 };
1695 
1696 }
1697 
1698 #endif
1699