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