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 #include "iw_owni.h"
16 #include "iw/iw_image.h"
17
18 IW_DECL(IppStatus) llwiCopyMakeBorder(const void *pSrc, IwSize srcStep, void *pDst, IwSize dstStep,
19 IwiSize size, IppDataType dataType, int channels, IwiBorderSize borderSize, IwiBorderType border, const Ipp64f *pBorderVal);
20
21 /* /////////////////////////////////////////////////////////////////////////////
22 // Utility functions
23 ///////////////////////////////////////////////////////////////////////////// */
iwiMaskToSize(IppiMaskSize mask)24 IW_DECL(IwiSize) iwiMaskToSize(IppiMaskSize mask)
25 {
26 IwiSize size;
27 size.width = 0;
28 size.height = 0;
29
30 switch(mask)
31 {
32 case ippMskSize1x3:
33 size.width = 1;
34 size.height = 3;
35 return size;
36 case ippMskSize1x5:
37 size.width = 1;
38 size.height = 5;
39 return size;
40 case ippMskSize3x1:
41 size.width = 3;
42 size.height = 1;
43 return size;
44 case ippMskSize3x3:
45 size.width = 3;
46 size.height = 3;
47 return size;
48 case ippMskSize5x1:
49 size.width = 5;
50 size.height = 1;
51 return size;
52 case ippMskSize5x5:
53 size.width = 5;
54 size.height = 5;
55 return size;
56 default:
57 return size;
58 }
59 }
60
owniChDescriptorToCode(IwiChDescriptor chDesc,int srcChannels,int dstChannels)61 IW_DECL(OwniChCodes) owniChDescriptorToCode(IwiChDescriptor chDesc, int srcChannels, int dstChannels)
62 {
63 if(srcChannels == dstChannels)
64 {
65 if((int)OWN_DESC_GET_CH(chDesc) != srcChannels)
66 chDesc = iwiChDesc_None;
67 }
68 else
69 chDesc = iwiChDesc_None;
70
71 switch(srcChannels)
72 {
73 case 1:
74 switch(dstChannels)
75 {
76 case 1:
77 switch(chDesc)
78 {
79 case iwiChDesc_None: return owniC1;
80 default: return owniC_Invalid;
81 }
82 case 3:
83 switch(chDesc)
84 {
85 case iwiChDesc_None: return owniC1C3;
86 default: return owniC_Invalid;
87 }
88 case 4:
89 switch(chDesc)
90 {
91 case iwiChDesc_None: return owniC1C4;
92 default: return owniC_Invalid;
93 }
94 default: return owniC_Invalid;
95 }
96 case 3:
97 switch(dstChannels)
98 {
99 case 1:
100 switch(chDesc)
101 {
102 case iwiChDesc_None: return owniC3C1;
103 default: return owniC_Invalid;
104 }
105 case 3:
106 switch(chDesc)
107 {
108 case iwiChDesc_None: return owniC3;
109 default: return owniC_Invalid;
110 }
111 case 4:
112 switch(chDesc)
113 {
114 case iwiChDesc_None: return owniC3C4;
115 default: return owniC_Invalid;
116 }
117 default: return owniC_Invalid;
118 }
119 case 4:
120 switch(dstChannels)
121 {
122 case 1:
123 switch(chDesc)
124 {
125 case iwiChDesc_None: return owniC4C1;
126 default: return owniC_Invalid;
127 }
128 case 3:
129 switch(chDesc)
130 {
131 case iwiChDesc_None: return owniC4C3;
132 default: return owniC_Invalid;
133 }
134 case 4:
135 switch(chDesc)
136 {
137 case iwiChDesc_None: return owniC4;
138 case iwiChDesc_C4M1110: return owniC4M1110;
139 case iwiChDesc_C4M1000: return owniC4M1000;
140 case iwiChDesc_C4M1001: return owniC4M1001;
141 case iwiChDesc_C4M1XX0: return owniC4M1RR0;
142 case iwiChDesc_C4M1XX1: return owniC4M1RR1;
143 default: return owniC_Invalid;
144 }
145 default: return owniC_Invalid;
146 }
147 default: return owniC_Invalid;
148 }
149 }
150
151 /* /////////////////////////////////////////////////////////////////////////////
152 // IwiImage - Image structure
153 ///////////////////////////////////////////////////////////////////////////// */
iwiImage_Init(IwiImage * pImage)154 IW_DECL(void) iwiImage_Init(IwiImage *pImage)
155 {
156 if(!pImage)
157 return;
158
159 pImage->m_channels = 0;
160 pImage->m_dataType = ipp8u;
161 pImage->m_typeSize = 0;
162 pImage->m_size.width = 0;
163 pImage->m_size.height = 0;
164 pImage->m_pBuffer = NULL;
165 pImage->m_ptr = NULL;
166 pImage->m_ptrConst = NULL;
167 pImage->m_step = 0;
168
169 pImage->m_inMemSize.left = pImage->m_inMemSize.right = 0;
170 pImage->m_inMemSize.top = pImage->m_inMemSize.bottom = 0;
171 }
172
iwiImage_InitExternal(IwiImage * pImage,IwiSize size,IppDataType dataType,int channels,IwiBorderSize const * pInMemBorder,void * pBuffer,IwSize step)173 IW_DECL(IppStatus) iwiImage_InitExternal(IwiImage *pImage, IwiSize size, IppDataType dataType, int channels, IwiBorderSize const *pInMemBorder, void *pBuffer, IwSize step)
174 {
175 if(!pImage)
176 return ippStsNullPtrErr;
177
178 iwiImage_Init(pImage);
179 if(channels < 0)
180 return ippStsNumChannelsErr;
181 if(size.width < 0 || size.height < 0)
182 return ippStsSizeErr;
183
184 pImage->m_typeSize = iwTypeToSize(dataType);
185 if(!pImage->m_typeSize)
186 return ippStsDataTypeErr;
187
188 pImage->m_dataType = dataType;
189 pImage->m_size = size;
190 pImage->m_channels = channels;
191
192 if(pInMemBorder)
193 {
194 if(owniBorderSizeIsNegative(pInMemBorder))
195 return iwStsBorderNegSizeErr;
196
197 pImage->m_inMemSize.left = pInMemBorder->left;
198 pImage->m_inMemSize.right = pInMemBorder->right;
199 pImage->m_inMemSize.top = pInMemBorder->top;
200 pImage->m_inMemSize.bottom = pInMemBorder->bottom;
201 }
202
203 pImage->m_ptr = pBuffer;
204 pImage->m_ptrConst = pImage->m_ptr;
205 pImage->m_step = step;
206
207 return ippStsNoErr;
208 }
209
iwiImage_InitExternalConst(IwiImage * pImage,IwiSize size,IppDataType dataType,int channels,IwiBorderSize const * pInMemBorder,const void * pBuffer,IwSize step)210 IW_DECL(IppStatus) iwiImage_InitExternalConst(IwiImage *pImage, IwiSize size, IppDataType dataType, int channels, IwiBorderSize const *pInMemBorder, const void *pBuffer, IwSize step)
211 {
212 if(!pImage)
213 return ippStsNullPtrErr;
214
215 iwiImage_Init(pImage);
216
217 if(channels < 0)
218 return ippStsNumChannelsErr;
219 if(size.width < 0 || size.height < 0)
220 return ippStsSizeErr;
221
222 pImage->m_typeSize = iwTypeToSize(dataType);
223 if(!pImage->m_typeSize)
224 return ippStsDataTypeErr;
225
226 pImage->m_dataType = dataType;
227 pImage->m_size = size;
228 pImage->m_channels = channels;
229
230 if(pInMemBorder)
231 {
232 if(owniBorderSizeIsNegative(pInMemBorder))
233 return iwStsBorderNegSizeErr;
234
235 pImage->m_inMemSize.left = pInMemBorder->left;
236 pImage->m_inMemSize.right = pInMemBorder->right;
237 pImage->m_inMemSize.top = pInMemBorder->top;
238 pImage->m_inMemSize.bottom = pInMemBorder->bottom;
239 }
240
241 pImage->m_ptrConst = pBuffer;
242 pImage->m_step = step;
243
244 return ippStsNoErr;
245 }
246
iwiImage_Alloc(IwiImage * pImage,IwiSize size,IppDataType dataType,int channels,IwiBorderSize const * pInMemBorder)247 IW_DECL(IppStatus) iwiImage_Alloc(IwiImage *pImage, IwiSize size, IppDataType dataType, int channels, IwiBorderSize const *pInMemBorder)
248 {
249 IwSize step;
250 IwiSize allocSize;
251
252 if(!pImage)
253 return ippStsNullPtrErr;
254
255 iwiImage_Release(pImage);
256
257 if(size.width < 0 || size.height < 0)
258 return ippStsSizeErr;
259
260 if(channels < 0)
261 return ippStsNumChannelsErr;
262
263 pImage->m_typeSize = iwTypeToSize(dataType);
264 if(!pImage->m_typeSize)
265 return ippStsDataTypeErr;
266
267 pImage->m_dataType = dataType;
268 pImage->m_size = size;
269 pImage->m_channels = channels;
270
271 if(pInMemBorder)
272 {
273 if(owniBorderSizeIsNegative(pInMemBorder))
274 return iwStsBorderNegSizeErr;
275
276 pImage->m_inMemSize.left = pInMemBorder->left;
277 pImage->m_inMemSize.right = pInMemBorder->right;
278 pImage->m_inMemSize.top = pInMemBorder->top;
279 pImage->m_inMemSize.bottom = pInMemBorder->bottom;
280 }
281 allocSize.width = pImage->m_size.width + pImage->m_inMemSize.left + pImage->m_inMemSize.right;
282 allocSize.height = pImage->m_size.height + pImage->m_inMemSize.top + pImage->m_inMemSize.bottom;
283 step = allocSize.width*pImage->m_typeSize*pImage->m_channels;
284 if(!step || !allocSize.height) // zero size memory request
285 return ippStsNoErr;
286
287 if(allocSize.height > 1 && step*allocSize.height > 64)
288 {
289 // Align rows by cache lines
290 if(step < 16)
291 step = 16;
292 else if(step < 32)
293 step = 32;
294 else
295 step = owniAlignStep(step, 64);
296 }
297
298 pImage->m_pBuffer = ippsMalloc_8u_L(step*allocSize.height);
299 if(!pImage->m_pBuffer)
300 return ippStsMemAllocErr;
301
302 pImage->m_ptr = (Ipp8u*)pImage->m_pBuffer + pImage->m_inMemSize.left*pImage->m_typeSize*pImage->m_channels + step*pImage->m_inMemSize.top;
303 pImage->m_ptrConst = pImage->m_ptr;
304 pImage->m_step = step;
305
306 return ippStsNoErr;
307 }
308
iwiImage_Release(IwiImage * pImage)309 IW_DECL(void) iwiImage_Release(IwiImage *pImage)
310 {
311 if(!pImage)
312 return;
313
314 if(pImage->m_pBuffer)
315 {
316 ippsFree(pImage->m_pBuffer);
317 pImage->m_pBuffer = NULL;
318 pImage->m_ptr = NULL;
319 pImage->m_ptrConst = NULL;
320 pImage->m_step = 0;
321 }
322 }
323
iwiImage_GetPtr(const IwiImage * pImage,IwSize y,IwSize x,int ch)324 IW_DECL(void*) iwiImage_GetPtr(const IwiImage *pImage, IwSize y, IwSize x, int ch)
325 {
326 if(!pImage || !pImage->m_ptr)
327 return NULL;
328 return (((Ipp8u*)pImage->m_ptr) + pImage->m_step*y + x*pImage->m_typeSize*pImage->m_channels + ch*pImage->m_typeSize);
329 }
330
iwiImage_GetPtrConst(const IwiImage * pImage,IwSize y,IwSize x,int ch)331 IW_DECL(const void*) iwiImage_GetPtrConst(const IwiImage *pImage, IwSize y, IwSize x, int ch)
332 {
333 if(!pImage || !pImage->m_ptrConst)
334 return NULL;
335 return (((const Ipp8u*)pImage->m_ptrConst) + pImage->m_step*y + x*pImage->m_typeSize*pImage->m_channels + ch*pImage->m_typeSize);
336 }
337
iwiImage_BorderAdd(IwiImage * pImage,IwiBorderSize borderSize)338 IW_DECL(IppStatus) iwiImage_BorderAdd(IwiImage *pImage, IwiBorderSize borderSize)
339 {
340 if(!pImage || !pImage->m_ptrConst)
341 return ippStsNullPtrErr;
342
343 if(owniBorderSizeIsNegative(&borderSize))
344 return iwStsBorderNegSizeErr;
345
346 if(borderSize.left + borderSize.right >= pImage->m_size.width)
347 return ippStsSizeErr;
348 if(borderSize.top + borderSize.bottom >= pImage->m_size.height)
349 return ippStsSizeErr;
350
351 if(pImage->m_ptr)
352 pImage->m_ptrConst = pImage->m_ptr = iwiImage_GetPtr(pImage, borderSize.top, borderSize.left, 0);
353 else
354 pImage->m_ptrConst = iwiImage_GetPtrConst(pImage, borderSize.top, borderSize.left, 0);
355 pImage->m_size.width = pImage->m_size.width - borderSize.left - borderSize.right;
356 pImage->m_size.height = pImage->m_size.height - borderSize.top - borderSize.bottom;
357 pImage->m_inMemSize.left += borderSize.left;
358 pImage->m_inMemSize.top += borderSize.top;
359 pImage->m_inMemSize.right += borderSize.right;
360 pImage->m_inMemSize.bottom += borderSize.bottom;
361
362 return ippStsNoErr;
363 }
364
iwiImage_BorderSub(IwiImage * pImage,IwiBorderSize borderSize)365 IW_DECL(IppStatus) iwiImage_BorderSub(IwiImage *pImage, IwiBorderSize borderSize)
366 {
367 if(!pImage || !pImage->m_ptrConst)
368 return ippStsNullPtrErr;
369
370 if(owniBorderSizeIsNegative(&borderSize))
371 return iwStsBorderNegSizeErr;
372
373 if(borderSize.left > pImage->m_inMemSize.left)
374 return ippStsOutOfRangeErr;
375 if(borderSize.top > pImage->m_inMemSize.top)
376 return ippStsOutOfRangeErr;
377 if(borderSize.right > pImage->m_inMemSize.right)
378 return ippStsOutOfRangeErr;
379 if(borderSize.bottom > pImage->m_inMemSize.bottom)
380 return ippStsOutOfRangeErr;
381
382 if(pImage->m_ptr)
383 pImage->m_ptrConst = pImage->m_ptr = iwiImage_GetPtr(pImage, -borderSize.top, -borderSize.left, 0);
384 else
385 pImage->m_ptrConst = iwiImage_GetPtrConst(pImage, -borderSize.top, -borderSize.left, 0);
386 pImage->m_size.width = pImage->m_size.width + borderSize.left + borderSize.right;
387 pImage->m_size.height = pImage->m_size.height + borderSize.top + borderSize.bottom;
388 pImage->m_inMemSize.left -= borderSize.left;
389 pImage->m_inMemSize.top -= borderSize.top;
390 pImage->m_inMemSize.right -= borderSize.right;
391 pImage->m_inMemSize.bottom -= borderSize.bottom;
392
393 return ippStsNoErr;
394 }
395
iwiImage_BorderSet(IwiImage * pImage,IwiBorderSize borderSize)396 IW_DECL(IppStatus) iwiImage_BorderSet(IwiImage *pImage, IwiBorderSize borderSize)
397 {
398 IwSize diffLeft, diffTop, diffRight, diffBottom;
399
400 if(!pImage || !pImage->m_ptrConst)
401 return ippStsNullPtrErr;
402
403 if(owniBorderSizeIsNegative(&borderSize))
404 return iwStsBorderNegSizeErr;
405
406 diffLeft = borderSize.left - pImage->m_inMemSize.left;
407 diffTop = borderSize.top - pImage->m_inMemSize.top;
408 diffRight = borderSize.right - pImage->m_inMemSize.right;
409 diffBottom = borderSize.bottom - pImage->m_inMemSize.bottom;
410
411 if(diffLeft+diffRight >= pImage->m_size.width)
412 return ippStsSizeErr;
413 if(diffTop+diffBottom >= pImage->m_size.height)
414 return ippStsSizeErr;
415
416 if(pImage->m_ptr)
417 pImage->m_ptrConst = pImage->m_ptr = iwiImage_GetPtr(pImage, diffTop, diffLeft, 0);
418 else
419 pImage->m_ptrConst = iwiImage_GetPtrConst(pImage, diffTop, diffLeft, 0);
420 pImage->m_size.width = pImage->m_size.width - (diffLeft + diffRight);
421 pImage->m_size.height = pImage->m_size.height - (diffTop + diffBottom);
422 pImage->m_inMemSize = borderSize;
423
424 return ippStsNoErr;
425 }
426
iwiImage_RoiSet(IwiImage * pImage,IwiRoi roi)427 IW_DECL(IppStatus) iwiImage_RoiSet(IwiImage *pImage, IwiRoi roi)
428 {
429 if(!pImage || !pImage->m_ptrConst)
430 return ippStsNullPtrErr;
431
432 // Unroll border
433 if(pImage->m_ptr)
434 pImage->m_ptrConst = pImage->m_ptr = iwiImage_GetPtr(pImage, -pImage->m_inMemSize.top, -pImage->m_inMemSize.left, 0);
435 else
436 pImage->m_ptrConst = iwiImage_GetPtrConst(pImage, -pImage->m_inMemSize.top, -pImage->m_inMemSize.left, 0);
437 pImage->m_size.width = pImage->m_size.width + pImage->m_inMemSize.left + pImage->m_inMemSize.right;
438 pImage->m_size.height = pImage->m_size.height + pImage->m_inMemSize.top + pImage->m_inMemSize.bottom;
439 roi.x += pImage->m_inMemSize.left;
440 roi.y += pImage->m_inMemSize.top;
441
442 // ROI saturation
443 if(roi.width < 0) // Inverted ROI
444 {
445 roi.x = roi.x + roi.width;
446 roi.width = -roi.width;
447 }
448 if(roi.x < 0) // "Left" saturation
449 {
450 roi.width += roi.x;
451 roi.x = 0;
452 }
453 if(roi.x + roi.width > pImage->m_size.width) // "Right" saturation
454 {
455 if(roi.x > pImage->m_size.width)
456 {
457 roi.x = pImage->m_size.width;
458 roi.width = 0;
459 }
460 else
461 roi.width = pImage->m_size.width - roi.x;
462 }
463
464 if(roi.height < 0) // Inverted ROI
465 {
466 roi.y = roi.y + roi.height;
467 roi.height = -roi.height;
468 }
469 if(roi.y < 0) // "Left" saturation
470 {
471 roi.height += roi.y;
472 roi.y = 0;
473 }
474 if(roi.y + roi.height > pImage->m_size.height) // "Right" saturation
475 {
476 if(roi.y > pImage->m_size.height)
477 {
478 roi.y = pImage->m_size.height;
479 roi.height = 0;
480 }
481 else
482 roi.height = pImage->m_size.height - roi.y;
483 }
484
485 // Rebuild border
486 pImage->m_inMemSize.left = roi.x;
487 pImage->m_inMemSize.top = roi.y;
488 pImage->m_inMemSize.right = pImage->m_size.width - roi.x - roi.width;
489 pImage->m_inMemSize.bottom = pImage->m_size.height - roi.y - roi.height;
490 pImage->m_size.width = roi.width;
491 pImage->m_size.height = roi.height;
492 if(pImage->m_ptr)
493 pImage->m_ptrConst = pImage->m_ptr = iwiImage_GetPtr(pImage, pImage->m_inMemSize.top, pImage->m_inMemSize.left, 0);
494 else
495 pImage->m_ptrConst = iwiImage_GetPtrConst(pImage, pImage->m_inMemSize.top, pImage->m_inMemSize.left, 0);
496
497 return ippStsNoErr;
498 }
499
iwiImage_GetRoiImage(const IwiImage * pImage,IwiRoi roi)500 IW_DECL(IwiImage) iwiImage_GetRoiImage(const IwiImage *pImage, IwiRoi roi)
501 {
502 IwiImage image;
503
504 iwiImage_Init(&image);
505 if(!pImage || !pImage->m_ptrConst)
506 return image;
507
508 if(pImage->m_ptr)
509 {
510 if(iwiImage_InitExternal(&image, pImage->m_size, pImage->m_dataType, pImage->m_channels, &pImage->m_inMemSize, pImage->m_ptr, pImage->m_step) < 0)
511 {
512 iwiImage_Init(&image);
513 return image;
514 }
515 }
516 else
517 {
518 if(iwiImage_InitExternalConst(&image, pImage->m_size, pImage->m_dataType, pImage->m_channels, &pImage->m_inMemSize, pImage->m_ptrConst, pImage->m_step) < 0)
519 {
520 iwiImage_Init(&image);
521 return image;
522 }
523 }
524 if(iwiImage_RoiSet(&image, roi) < 0)
525 {
526 iwiImage_Init(&image);
527 return image;
528 }
529 return image;
530 }
531
532 /* /////////////////////////////////////////////////////////////////////////////
533 // IW Tiling
534 ///////////////////////////////////////////////////////////////////////////// */
owniSuggestTileSize_k2(const IwiImage * pImage,IwiSize kernelSize,double multiplier)535 IW_DECL(IwiSize) owniSuggestTileSize_k2(const IwiImage *pImage, IwiSize kernelSize, double multiplier)
536 {
537 float nCaches;
538 IwiSize roi = {0,0};
539 IwSize opMemory = (IwSize)(pImage->m_size.width*pImage->m_size.height*pImage->m_typeSize*pImage->m_channels*multiplier);
540 IwSize minHeight = IPP_MAX(kernelSize.height, 64);
541 IwSize minWidth = IPP_MAX(kernelSize.width, 64);
542 IppCache *pCache;
543 int l2cache = 262144;
544 //int l3cache = 1048576;
545 if(ippGetCacheParams(&pCache) >= 0 && pCache[0].type != 0 && pCache[1].type != 0)
546 {
547 if(pCache[2].type != 0)
548 {
549 l2cache = pCache[2].size;
550 //if(pCache[3].type != 0)
551 // l3cache = pCache[3].size;
552 }
553 }
554
555 nCaches = ((float)opMemory/l2cache);
556 if(nCaches < 1) // Cache is enough to contain all operations
557 return pImage->m_size;
558 else if(pImage->m_size.height <= minHeight) // Height is small, divide by width only
559 {
560 roi.width = (IwSize)((pImage->m_size.width+nCaches-1)/nCaches);
561 roi.height = kernelSize.height;
562 }
563 else // General case
564 {
565 IwSize pixChunk = (IwSize)((pImage->m_size.width*pImage->m_size.height)/nCaches);
566 roi.height = (pixChunk+pImage->m_size.width-1)/pImage->m_size.width;
567 roi.width = pImage->m_size.width;
568 if(roi.height < minHeight && roi.width > minWidth) // Not enough space to process whole row efficiently, divide row
569 {
570 while(roi.height < minHeight)
571 {
572 roi.width /= 2;
573 roi.height = (pixChunk+roi.width-1)/roi.width;
574 }
575 }
576 }
577 return roi;
578 }
579
580 /* /////////////////////////////////////////////////////////////////////////////
581 // Manual tiling control
582 ///////////////////////////////////////////////////////////////////////////// */
iwiTile_GetTileBorder(IwiRoi roi,IwiBorderType border,IwiBorderSize borderSize,IwiSize srcImageSize)583 IW_DECL(IwiBorderType) iwiTile_GetTileBorder(IwiRoi roi, IwiBorderType border, IwiBorderSize borderSize, IwiSize srcImageSize)
584 {
585 owniTile_GetTileBorder(&border, &roi, &borderSize, &srcImageSize);
586 return border;
587 }
588
iwiTile_GetMinTileSize(IwiBorderType border,IwiBorderSize borderSize)589 IW_DECL(IwiSize) iwiTile_GetMinTileSize(IwiBorderType border, IwiBorderSize borderSize)
590 {
591 IwiSize size;
592 if(border&ippBorderInMemLeft)
593 borderSize.left = 0;
594 if(border&ippBorderInMemRight)
595 borderSize.right = 0;
596 if(border&ippBorderInMemTop)
597 borderSize.top = 0;
598 if(border&ippBorderInMemBottom)
599 borderSize.bottom = 0;
600
601 border = OWN_GET_PURE_BORDER(border);
602 size.width = IPP_MAX(borderSize.left, borderSize.right);
603 size.height = IPP_MAX(borderSize.top, borderSize.bottom);
604 if(size.width == 0)
605 size.width = 1;
606 if(size.height == 0)
607 size.height = 1;
608 if(border == ippBorderMirror)
609 {
610 size.width++;
611 size.height++;
612 }
613 return size;
614 }
615
iwiTile_CorrectBordersOverlap(IwiRoi roi,IwiBorderType border,IwiBorderSize borderSize,IwiSize srcImageSize)616 IW_DECL(IwiRoi) iwiTile_CorrectBordersOverlap(IwiRoi roi, IwiBorderType border, IwiBorderSize borderSize, IwiSize srcImageSize)
617 {
618 owniTile_CorrectBordersOverlap(&roi, NULL, &border, &borderSize, &borderSize, &srcImageSize);
619 return roi;
620 }
621
622 /* /////////////////////////////////////////////////////////////////////////////
623 // IwiTile tiling
624 ///////////////////////////////////////////////////////////////////////////// */
owniTile_BoundToSize(IwiRoi * pRoi,IwiSize * pMinSize)625 IW_DECL(int) owniTile_BoundToSize(IwiRoi *pRoi, IwiSize *pMinSize)
626 {
627 if(pRoi->x >= pMinSize->width)
628 return 0;
629 else if(pRoi->x < 0)
630 pRoi->x = 0;
631 if(pRoi->y >= pMinSize->height)
632 return 0;
633 else if(pRoi->y < 0)
634 pRoi->y = 0;
635
636 if(pRoi->width + pRoi->x > pMinSize->width)
637 pRoi->width = pMinSize->width - pRoi->x;
638 if(pRoi->height + pRoi->y > pMinSize->height)
639 pRoi->height = pMinSize->height - pRoi->y;
640
641 if(pRoi->width <= 0 || pRoi->height <= 0)
642 return 0;
643 else
644 {
645 pMinSize->width = pRoi->width;
646 pMinSize->height = pRoi->height;
647 return 1;
648 }
649 }
650
651
owniTile_CorrectBordersOverlap(IwiRoi * pRoi,IwiSize * pMinSize,const IwiBorderType * pBorder,const IwiBorderSize * pBorderSize,const IwiBorderSize * pBorderSizeAcc,const IwiSize * pSrcImageSize)652 IW_DECL(int) owniTile_CorrectBordersOverlap(IwiRoi *pRoi, IwiSize *pMinSize, const IwiBorderType *pBorder, const IwiBorderSize *pBorderSize, const IwiBorderSize *pBorderSizeAcc, const IwiSize *pSrcImageSize)
653 {
654 int corrected = 0;
655
656 // Check right border
657 if(pBorderSize->right > 1 && !(*pBorder&ippBorderInMemRight))
658 {
659 IwSize rightPos = pRoi->x + pRoi->width; // Get right tile border position
660 IwSize leftCheck = pRoi->x + (pBorderSizeAcc->left - pBorderSize->left) + (pBorderSizeAcc->right - pBorderSize->right); // Reconstruct previous tile position
661
662 // Border-phobic tile part
663 if(rightPos < pSrcImageSize->width &&
664 (rightPos + pBorderSize->right) > pSrcImageSize->width)
665 {
666 pRoi->width = pSrcImageSize->width - pBorderSize->right - pRoi->x;
667 corrected = 1;
668 }
669 // Border-filing tile part
670 else if(leftCheck < pSrcImageSize->width &&
671 (leftCheck + pBorderSize->right) > pSrcImageSize->width)
672 {
673 pRoi->x = pSrcImageSize->width - pBorderSize->right - (pBorderSizeAcc->left - pBorderSize->left)*2;
674 pRoi->width = pSrcImageSize->width - pRoi->x;
675 corrected = 1;
676 }
677 }
678
679 // Check bottom border
680 if(pBorderSize->bottom > 1 && !(*pBorder&ippBorderInMemBottom))
681 {
682 IwSize bottomPos = pRoi->y + pRoi->height; // Get bottom tile border position
683 IwSize topCheck = pRoi->y + (pBorderSizeAcc->top - pBorderSize->top) + (pBorderSizeAcc->bottom - pBorderSize->bottom); // Reconstruct previous tile position
684
685 // Border-phobic tile part
686 if(bottomPos < pSrcImageSize->height &&
687 (bottomPos + pBorderSize->bottom) > pSrcImageSize->height)
688 {
689 pRoi->height = pSrcImageSize->height - pBorderSize->bottom - pRoi->y;
690 corrected = 1;
691 }
692 // Border-filing tile part
693 else if(topCheck < pSrcImageSize->height &&
694 (topCheck + pBorderSize->bottom) > pSrcImageSize->height)
695 {
696 pRoi->y = pSrcImageSize->height - pBorderSize->bottom - (pBorderSizeAcc->top - pBorderSize->top)*2;
697 pRoi->height = pSrcImageSize->height - pRoi->y;
698 corrected = 1;
699 }
700 }
701
702 if(corrected && pMinSize)
703 {
704 pMinSize->width = pRoi->width;
705 pMinSize->height = pRoi->height;
706 }
707
708 return corrected;
709 }
710
owniTile_GetTileBorder(IwiBorderType * pBorder,const IwiRoi * pRoi,const IwiBorderSize * pBorderSize,const IwiSize * pSrcImageSize)711 IW_DECL(void) owniTile_GetTileBorder(IwiBorderType *pBorder, const IwiRoi *pRoi, const IwiBorderSize *pBorderSize, const IwiSize *pSrcImageSize)
712 {
713 if((*pBorder & ippBorderInMem) != ippBorderInMem)
714 {
715 int flags = (*pBorder)&(~0xF);
716
717 // Check left border
718 if(pBorderSize->left && (pRoi->x >= pBorderSize->left))
719 flags |= ippBorderInMemLeft;
720
721 // Check top border
722 if(pBorderSize->top && (pRoi->y >= pBorderSize->top))
723 flags |= ippBorderInMemTop;
724
725 // Check right border
726 if(pBorderSize->right && (pRoi->x + pRoi->width + pBorderSize->right <= pSrcImageSize->width))
727 flags |= ippBorderInMemRight;
728
729 // Check bottom border
730 if(pBorderSize->bottom && (pRoi->y + pRoi->height + pBorderSize->bottom <= pSrcImageSize->height))
731 flags |= ippBorderInMemBottom;
732
733 // If we have full InMem, then we should pass pure InMem border to function
734 if(flags == ippBorderInMem)
735 *pBorder = ippBorderInMem;
736 else
737 *pBorder = (IwiBorderType)((*pBorder)|flags);
738 }
739 }
740
741 /* /////////////////////////////////////////////////////////////////////////////
742 // IwiTile pipeline tiling
743 ///////////////////////////////////////////////////////////////////////////// */
744
owniTilePipeline_GetRoot(const IwiTile * pTile)745 static IW_INLINE IwiTile* owniTilePipeline_GetRoot(const IwiTile *pTile)
746 {
747 IwiTile *pRoiRoot = (IwiTile*)pTile;
748 if(!pTile || pTile->m_initialized != ownTileInitPipe)
749 return NULL;
750 while(pRoiRoot->m_pParent)
751 pRoiRoot = pRoiRoot->m_pParent;
752 return pRoiRoot;
753 }
owniTilePipeline_InitCheck(const IwiTile * pTile)754 static IW_INLINE IppStatus owniTilePipeline_InitCheck(const IwiTile *pTile)
755 {
756 if(!pTile)
757 return ippStsNullPtrErr;
758
759 if(pTile->m_initialized != ownTileInitPipe)
760 return ippStsContextMatchErr;
761
762 return ippStsNoErr;
763 }
764
iwiTile_SetRoi(IwiRoi tileRoi)765 IW_DECL(IwiTile) iwiTile_SetRoi(IwiRoi tileRoi)
766 {
767 IwiTile roi = {0};
768 roi.m_dstRoi = tileRoi;
769 roi.m_initialized = ownTileInitSimple;
770 return roi;
771 }
772
owniTilePipeline_GetSrcSizeMax(IwiRoi * pSrcRoiSize,IwiSize * pDstMaxTile,IwiSize * pDstImageSize,const IwiTileTransform * pTransformStruct)773 static IppStatus owniTilePipeline_GetSrcSizeMax(IwiRoi *pSrcRoiSize, IwiSize *pDstMaxTile, IwiSize *pDstImageSize, const IwiTileTransform *pTransformStruct)
774 {
775 IwiRoi srcTemp = {0, 0, 0, 0};
776 IwiRoi dstRoi = {0, 0, 0, 0};
777 pSrcRoiSize->width = 0;
778 pSrcRoiSize->height = 0;
779 dstRoi.width = pDstMaxTile->width;
780 dstRoi.height = pDstMaxTile->height;
781
782 for(dstRoi.x = 0; dstRoi.x <= pDstImageSize->width - dstRoi.width; dstRoi.x++)
783 {
784 if(pTransformStruct->getSrcRoiFun(dstRoi, &srcTemp, pTransformStruct->pParams))
785 return ippStsErr;
786
787 pSrcRoiSize->width = IPP_MAX(pSrcRoiSize->width, srcTemp.width);
788 }
789
790 for(dstRoi.y = 0; dstRoi.y <= pDstImageSize->height - dstRoi.height; dstRoi.y++)
791 {
792 if(pTransformStruct->getSrcRoiFun(dstRoi, &srcTemp, pTransformStruct->pParams))
793 return ippStsErr;
794
795 pSrcRoiSize->height = IPP_MAX(pSrcRoiSize->height, srcTemp.height);
796 }
797
798 pSrcRoiSize->x = 0;
799 pSrcRoiSize->y = 0;
800
801 return ippStsNoErr;
802 }
803
owniTilePipeline_BuildBorder(const IwiTile * pTile,IwiImage * pSrcImage,IwiBorderType * pBorder,const Ipp64f * pBorderVal,const IwiBorderSize * pBorderSize)804 static IppStatus owniTilePipeline_BuildBorder(const IwiTile *pTile, IwiImage *pSrcImage, IwiBorderType *pBorder, const Ipp64f *pBorderVal, const IwiBorderSize *pBorderSize)
805 {
806 IppStatus status;
807
808 if(((*pBorder)&ippBorderInMem) != ippBorderInMem)
809 {
810 if(pBorderSize)
811 status = llwiCopyMakeBorder(pSrcImage->m_ptrConst, pSrcImage->m_step, pSrcImage->m_ptr, pSrcImage->m_step, pSrcImage->m_size,
812 pSrcImage->m_dataType, pSrcImage->m_channels, *pBorderSize, *pBorder, pBorderVal);
813 else
814 status = llwiCopyMakeBorder(pSrcImage->m_ptrConst, pSrcImage->m_step, pSrcImage->m_ptr, pSrcImage->m_step, pSrcImage->m_size,
815 pSrcImage->m_dataType, pSrcImage->m_channels, pTile->m_borderSize, *pBorder, pBorderVal);
816 if(status < 0)
817 return status;
818
819 *pBorder = ippBorderInMem;
820 }
821
822 return ippStsNoErr;
823 }
824
owniTilePipeline_ProcBorder(const IwiTile * pTile,IwiImage * pSrcImage,IwiBorderType * pBorder,const Ipp64f * pBorderVal)825 IW_DECL(IppStatus) owniTilePipeline_ProcBorder(const IwiTile *pTile, IwiImage *pSrcImage, IwiBorderType *pBorder, const Ipp64f *pBorderVal)
826 {
827 *pBorder = pTile->m_borderType;
828 owniTile_GetTileBorder(pBorder, &pTile->m_srcRoi, &pTile->m_borderSize, &pTile->m_srcImageSize);
829
830 if(pTile->m_pChild)
831 {
832 IppStatus status;
833 IwiBorderSize borderSize = pTile->m_borderSize;
834 IwiBorderSize borderSizeDiff = {0, 0, 0, 0};
835 int overlap = 0;
836 IwSize rightPos = pTile->m_srcRoi.x + pTile->m_srcRoi.width;
837 IwSize bottomPos = pTile->m_srcRoi.y + pTile->m_srcRoi.height;
838
839 // Pre-process partial InMem border. Shift buffer in InMem boundary and extrapolate the rest
840 // Check left border
841 if(pTile->m_borderSize.left && (pTile->m_srcRoi.x > 0 && pTile->m_srcRoi.x < pTile->m_borderSize.left))
842 {
843 borderSizeDiff.left = pTile->m_srcRoi.x;
844 borderSize.left -= borderSizeDiff.left;
845 overlap = 1;
846 }
847
848 // Check top border
849 if(pTile->m_borderSize.top && (pTile->m_srcRoi.y > 0 && pTile->m_srcRoi.y < pTile->m_borderSize.top))
850 {
851 borderSizeDiff.top = pTile->m_srcRoi.y;
852 borderSize.top -= borderSizeDiff.top;
853 overlap = 1;
854 }
855
856 // Check right border
857 if(pTile->m_borderSize.right && (rightPos + pTile->m_borderSize.right > pTile->m_srcImageSize.width && rightPos < pTile->m_srcImageSize.width))
858 {
859 borderSizeDiff.right = pTile->m_srcImageSize.width - rightPos;
860 borderSize.right -= borderSizeDiff.right;
861 overlap = 1;
862 }
863
864 // Check bottom border
865 if(pTile->m_borderSize.bottom && (bottomPos + pTile->m_borderSize.bottom > pTile->m_srcImageSize.height && bottomPos < pTile->m_srcImageSize.height))
866 {
867 borderSizeDiff.bottom = pTile->m_srcImageSize.height - bottomPos;
868 borderSize.bottom -= borderSizeDiff.bottom;
869 overlap = 1;
870 }
871
872 if(overlap)
873 {
874 IwiImage tmpImage;
875
876 iwiImage_InitExternal(&tmpImage, pSrcImage->m_size, pSrcImage->m_dataType, pSrcImage->m_channels, &pSrcImage->m_inMemSize, pSrcImage->m_ptr, pSrcImage->m_step);
877
878 status = iwiImage_BorderSub(&tmpImage, borderSizeDiff);
879 if(status < 0)
880 return status;
881
882 // Extrapolate border for intermediate buffers
883 return owniTilePipeline_BuildBorder(pTile, &tmpImage, pBorder, pBorderVal, &borderSize);
884 }
885 else
886 {
887 // Extrapolate border for intermediate buffers
888 return owniTilePipeline_BuildBorder(pTile, pSrcImage, pBorder, pBorderVal, &borderSize);
889 }
890 }
891 return ippStsNoErr;
892 }
893
owniTilePipeline_InitCommon(IwiTile * pTile,const IwiBorderType * pBorderType,const IwiBorderSize * pBorderSize,const IwiTileTransform * pTransformStruct)894 static IppStatus owniTilePipeline_InitCommon(IwiTile *pTile, const IwiBorderType *pBorderType, const IwiBorderSize *pBorderSize, const IwiTileTransform *pTransformStruct)
895 {
896 IppStatus status;
897
898 if(pTile->m_maxTileSize.width > pTile->m_dstImageSize.width)
899 pTile->m_maxTileSize.width = pTile->m_dstImageSize.width;
900 if(pTile->m_maxTileSize.height > pTile->m_dstImageSize.height)
901 pTile->m_maxTileSize.height = pTile->m_dstImageSize.height;
902
903 if(pTransformStruct && pTransformStruct->getSrcRoiFun)
904 {
905 pTile->m_transformStruct = *pTransformStruct;
906
907 status = owniTilePipeline_GetSrcSizeMax(&pTile->m_srcRoi, &pTile->m_maxTileSize, &pTile->m_dstExImageSize, pTransformStruct);
908 if(status < 0)
909 return status;
910
911 pTile->m_srcImageSize = pTile->m_transformStruct.srcImageSize;
912 pTile->m_srcBufferSize = pTile->m_transformStruct.srcImageSize;
913 }
914
915 pTile->m_borderType = ippBorderRepl;
916 if(pBorderSize)
917 {
918 pTile->m_borderSize = *pBorderSize;
919 if(pBorderType)
920 {
921 pTile->m_borderType = *pBorderType;
922 if(pTile->m_borderType&ippBorderInMemLeft)
923 {
924 pTile->m_externalMemAcc.left += pTile->m_borderSize.left;
925 pTile->m_externalMem.left = pTile->m_borderSize.left;
926 }
927 if(pTile->m_borderType&ippBorderInMemRight)
928 {
929 pTile->m_externalMemAcc.right += pTile->m_borderSize.right;
930 pTile->m_externalMem.right = pTile->m_borderSize.right;
931 }
932 if(pTile->m_borderType&ippBorderInMemTop)
933 {
934 pTile->m_externalMemAcc.top += pTile->m_borderSize.top;
935 pTile->m_externalMem.top = pTile->m_borderSize.top;
936 }
937 if(pTile->m_borderType&ippBorderInMemBottom)
938 {
939 pTile->m_externalMemAcc.bottom += pTile->m_borderSize.bottom;
940 pTile->m_externalMem.bottom = pTile->m_borderSize.bottom;
941 }
942
943 pTile->m_srcExImageSize.width += (pTile->m_externalMem.left + pTile->m_externalMem.right);
944 pTile->m_srcExImageSize.height += (pTile->m_externalMem.top + pTile->m_externalMem.bottom);
945 }
946
947 pTile->m_borderSizeAcc.left += pTile->m_borderSize.left;
948 pTile->m_borderSizeAcc.top += pTile->m_borderSize.top;
949 pTile->m_borderSizeAcc.right += pTile->m_borderSize.right;
950 pTile->m_borderSizeAcc.bottom += pTile->m_borderSize.bottom;
951 }
952
953 return ippStsNoErr;
954 }
955
iwiTilePipeline_Init(IwiTile * pTile,IwiSize tileSizeMax,IwiSize imageSize,const IwiBorderType * pBorderType,const IwiBorderSize * pBorderSize,const IwiTileTransform * pTransformStruct)956 IW_DECL(IppStatus) iwiTilePipeline_Init(IwiTile *pTile, IwiSize tileSizeMax, IwiSize imageSize, const IwiBorderType *pBorderType, const IwiBorderSize *pBorderSize, const IwiTileTransform *pTransformStruct)
957 {
958 IppStatus status;
959
960 if(!pTile)
961 return ippStsNullPtrErr;
962
963 ippsZero_8u((Ipp8u*)pTile, sizeof(IwiTile));
964
965 if(tileSizeMax.width <= 0 || tileSizeMax.height <= 0)
966 return ippStsSizeErr;
967
968 if(tileSizeMax.width > imageSize.width)
969 tileSizeMax.width = imageSize.width;
970 if(tileSizeMax.height > imageSize.height)
971 tileSizeMax.height = imageSize.height;
972
973 pTile->m_maxTileSize = tileSizeMax;
974
975 pTile->m_srcRoi.width = pTile->m_dstRoi.width = pTile->m_maxTileSize.width;
976 pTile->m_srcRoi.height = pTile->m_dstRoi.height = pTile->m_maxTileSize.height;
977
978 pTile->m_srcImageSize = pTile->m_dstImageSize = imageSize;
979 pTile->m_dstBufferSize = pTile->m_srcBufferSize = imageSize;
980 pTile->m_dstExImageSize = pTile->m_srcExImageSize = imageSize;
981
982 status = owniTilePipeline_InitCommon(pTile, pBorderType, pBorderSize, pTransformStruct);
983 if(status < 0)
984 return status;
985
986 pTile->m_initialized = ownTileInitPipe;
987 return ippStsNoErr;
988 }
989
iwiTilePipeline_InitChild(IwiTile * pTile,IwiTile * pParent,const IwiBorderType * pBorderType,const IwiBorderSize * pBorderSize,const IwiTileTransform * pTransformStruct)990 IW_DECL(IppStatus) iwiTilePipeline_InitChild(IwiTile *pTile, IwiTile *pParent, const IwiBorderType *pBorderType, const IwiBorderSize *pBorderSize, const IwiTileTransform *pTransformStruct)
991 {
992 IppStatus status = owniTilePipeline_InitCheck(pParent);
993 if(status < 0)
994 return status;
995
996 if(!pTile)
997 return ippStsNullPtrErr;
998
999 ippsZero_8u((Ipp8u*)pTile, sizeof(IwiTile));
1000
1001 pParent->m_pChild = pTile;
1002 pTile->m_pParent = pParent;
1003
1004 pTile->m_maxTileSize.width = pParent->m_srcRoi.width + pParent->m_borderSize.left + pParent->m_borderSize.right;
1005 pTile->m_maxTileSize.height = pParent->m_srcRoi.height + pParent->m_borderSize.top + pParent->m_borderSize.bottom;
1006 if(pParent->m_borderType == ippBorderMirror)
1007 {
1008 if(pParent->m_borderSize.left || pParent->m_borderSize.right)
1009 pTile->m_maxTileSize.width++;
1010 if(pParent->m_borderSize.top || pParent->m_borderSize.bottom)
1011 pTile->m_maxTileSize.height++;
1012 }
1013
1014 pTile->m_dstImageSize = pParent->m_srcImageSize;
1015 pTile->m_dstExImageSize = pParent->m_srcExImageSize;
1016 pTile->m_srcExImageSize = pTile->m_dstExImageSize;
1017
1018 pTile->m_srcRoi.width = pTile->m_dstRoi.width = pTile->m_maxTileSize.width;
1019 pTile->m_srcRoi.height = pTile->m_dstRoi.height = pTile->m_maxTileSize.height;
1020
1021 pTile->m_dstBufferSize.width = pParent->m_srcBufferSize.width = pTile->m_dstRoi.width;
1022 pTile->m_dstBufferSize.height = pParent->m_srcBufferSize.height = pTile->m_dstRoi.height;
1023
1024 pTile->m_srcBufferSize = pTile->m_dstImageSize;
1025 pTile->m_srcImageSize = pTile->m_dstImageSize;
1026 pTile->m_borderSizeAcc = pParent->m_borderSizeAcc;
1027 pTile->m_externalMemAcc = pParent->m_externalMemAcc;
1028
1029 status = owniTilePipeline_InitCommon(pTile, pBorderType, pBorderSize, pTransformStruct);
1030 if(status < 0)
1031 return status;
1032
1033 pTile->m_initialized = pParent->m_initialized;
1034 return ippStsNoErr;
1035 }
1036
iwiTilePipeline_Release(IwiTile * pTile)1037 IW_DECL(void) iwiTilePipeline_Release(IwiTile *pTile)
1038 {
1039 pTile = owniTilePipeline_GetRoot(pTile);
1040 if(owniTilePipeline_InitCheck(pTile) < 0)
1041 return;
1042
1043 while(pTile)
1044 {
1045 // Nothing to actually deallocate yet, but this may be helpful in the future.
1046 pTile->m_initialized = ownTileInitNone;
1047
1048 pTile = pTile->m_pChild;
1049 }
1050 }
1051
iwiTilePipeline_SetRoi(IwiTile * pTile,IwiRoi tileRoi)1052 IW_DECL(IppStatus) iwiTilePipeline_SetRoi(IwiTile *pTile, IwiRoi tileRoi)
1053 {
1054 IppStatus status;
1055 IwiTile *pRoot = NULL;
1056 int hasScaling = 0;
1057 double scaleX = 1;
1058 double scaleY = 1;
1059
1060 pRoot = owniTilePipeline_GetRoot(pTile);
1061 status = owniTilePipeline_InitCheck(pTile);
1062 if(status < 0)
1063 return status;
1064
1065 if(tileRoi.x < 0)
1066 tileRoi.x = 0;
1067 if(tileRoi.y < 0)
1068 tileRoi.y = 0;
1069
1070 if(tileRoi.width <= 0 || tileRoi.height <= 0)
1071 return ippStsSizeErr;
1072
1073 if(tileRoi.width > pRoot->m_maxTileSize.width)
1074 tileRoi.width = pRoot->m_maxTileSize.width;
1075 if(tileRoi.height > pRoot->m_maxTileSize.height)
1076 tileRoi.height = pRoot->m_maxTileSize.height;
1077
1078 pTile = pRoot;
1079 while(pTile)
1080 {
1081 if(pTile->m_pParent)
1082 {
1083 pTile->m_dstRoi = pTile->m_pParent->m_srcRoi;
1084 pTile->m_untaintDstPos = pTile->m_pParent->m_untaintSrcPos;
1085
1086 pTile->m_dstRoi.width += pTile->m_pParent->m_borderSize.left;
1087 pTile->m_dstRoi.x -= pTile->m_pParent->m_borderSize.left;
1088 pTile->m_untaintDstPos.x -= pTile->m_pParent->m_borderSize.left;
1089
1090 pTile->m_dstRoi.height += pTile->m_pParent->m_borderSize.top;
1091 pTile->m_dstRoi.y -= pTile->m_pParent->m_borderSize.top;
1092 pTile->m_untaintDstPos.y -= pTile->m_pParent->m_borderSize.top;
1093
1094 pTile->m_dstRoi.width += pTile->m_pParent->m_borderSize.right;
1095 pTile->m_dstRoi.height += pTile->m_pParent->m_borderSize.bottom;
1096
1097 if(pTile->m_dstRoi.x < 0)
1098 {
1099 if(!pTile->m_pParent->m_externalMem.left)
1100 {
1101 pTile->m_dstRoi.width += pTile->m_dstRoi.x;
1102 pTile->m_dstRoi.x = 0;
1103 }
1104 }
1105
1106 if(pTile->m_dstRoi.y < 0)
1107 {
1108 if(!pTile->m_pParent->m_externalMem.top)
1109 {
1110 pTile->m_dstRoi.height += pTile->m_dstRoi.y;
1111 pTile->m_dstRoi.y = 0;
1112 }
1113 }
1114
1115 if(pTile->m_dstRoi.x + pTile->m_dstRoi.width > pTile->m_dstImageSize.width + pTile->m_pParent->m_externalMemAcc.right)
1116 pTile->m_dstRoi.width = pTile->m_dstImageSize.width - pTile->m_dstRoi.x + pTile->m_pParent->m_externalMemAcc.right;
1117 if(pTile->m_dstRoi.y + pTile->m_dstRoi.height > pTile->m_dstImageSize.height + pTile->m_pParent->m_externalMemAcc.bottom)
1118 pTile->m_dstRoi.height = pTile->m_dstImageSize.height - pTile->m_dstRoi.y + pTile->m_pParent->m_externalMemAcc.bottom;
1119 }
1120 else
1121 {
1122 pTile->m_dstRoi = tileRoi;
1123 pTile->m_untaintDstPos.x = pTile->m_dstRoi.x;
1124 pTile->m_untaintDstPos.y = pTile->m_dstRoi.y;
1125
1126 if(pTile->m_dstRoi.x + pTile->m_dstRoi.width > pTile->m_dstImageSize.width)
1127 pTile->m_dstRoi.width = pTile->m_dstImageSize.width - pTile->m_dstRoi.x;
1128 if(pTile->m_dstRoi.y + pTile->m_dstRoi.height > pTile->m_dstImageSize.height)
1129 pTile->m_dstRoi.height = pTile->m_dstImageSize.height - pTile->m_dstRoi.y;
1130 }
1131
1132 if(pTile->m_transformStruct.getSrcRoiFun)
1133 {
1134 // Scaling function should process partial borders correctly, so no overlap check is needed
1135 if(pTile->m_transformStruct.getSrcRoiFun(pTile->m_dstRoi, &pTile->m_srcRoi, pTile->m_transformStruct.pParams))
1136 return ippStsErr;
1137
1138 if(pTile->m_untaintDstPos.x < 0)
1139 {
1140 // pTile->m_srcRoi.x
1141 // pTile->m_untaintSrcPos.x = pTile->m_untaintDstPos.x + pTile->m_srcRoi.x;
1142 // pTile->m_srcRoi.width += -pTile->m_untaintDstPos.x;
1143 }
1144 if(pTile->m_untaintDstPos.y < 0)
1145 {
1146 pTile->m_untaintSrcPos.y = pTile->m_untaintDstPos.y + pTile->m_srcRoi.y;
1147 // pTile->m_srcRoi.height += -pTile->m_untaintDstPos.y;
1148 }
1149
1150 if(pTile->m_pParent)
1151 {
1152 if(pTile->m_srcRoi.x + pTile->m_srcRoi.width > pTile->m_srcImageSize.width + pTile->m_pParent->m_externalMemAcc.right)
1153 pTile->m_srcRoi.width = pTile->m_srcImageSize.width - pTile->m_srcRoi.x + pTile->m_pParent->m_externalMemAcc.right;
1154 if(pTile->m_srcRoi.y + pTile->m_srcRoi.height > pTile->m_srcImageSize.height + pTile->m_pParent->m_externalMemAcc.bottom)
1155 pTile->m_srcRoi.height = pTile->m_srcImageSize.height - pTile->m_srcRoi.y + pTile->m_pParent->m_externalMemAcc.bottom;
1156 }
1157
1158 //hasScaling = 1;
1159 }
1160 else
1161 {
1162 pTile->m_srcRoi = pTile->m_dstRoi;
1163 pTile->m_untaintSrcPos = pTile->m_untaintDstPos;
1164
1165 if(!pTile->m_pChild) // Correction is required only for the first tile int the pipe since all other tiles use iwiCreateBorder function
1166 {
1167 IwiRoi correctRoi = pTile->m_dstRoi;
1168
1169 // Shift source tile and start again
1170 if(owniTile_CorrectBordersOverlap(&correctRoi, NULL, &pTile->m_borderType, &pTile->m_borderSize, &pTile->m_borderSizeAcc, &pTile->m_srcImageSize))
1171 {
1172 if(hasScaling)
1173 {
1174 tileRoi.x += (IwSize)((correctRoi.x-pTile->m_srcRoi.x)*(scaleX + 0.5));
1175 tileRoi.y += (IwSize)((correctRoi.y-pTile->m_srcRoi.y)*(scaleY + 0.5));
1176 tileRoi.width += (IwSize)((correctRoi.width-pTile->m_srcRoi.width)*(scaleX + 0.5));
1177 tileRoi.height += (IwSize)((correctRoi.height-pTile->m_srcRoi.height)*(scaleY + 0.5));
1178 }
1179 else
1180 {
1181 tileRoi.x += correctRoi.x-pTile->m_srcRoi.x;
1182 tileRoi.y += correctRoi.y-pTile->m_srcRoi.y;
1183 tileRoi.width += correctRoi.width-pTile->m_srcRoi.width;
1184 tileRoi.height += correctRoi.height-pTile->m_srcRoi.height;
1185 }
1186
1187 hasScaling = 0;
1188 scaleX = 1;
1189 scaleY = 1;
1190 pTile = pRoot;
1191 continue;
1192 }
1193 }
1194 }
1195
1196 // Dst offset
1197 pTile->m_boundDstRoi = pTile->m_dstRoi;
1198 if(pTile->m_pParent)
1199 {
1200 // Intermediate dst buffer is aligned so that actual src image for parent will always be in the center
1201 if(pTile->m_untaintDstPos.x < 0 && !pTile->m_pParent->m_externalMem.left)
1202 {
1203 if(pTile->m_pParent->m_untaintDstPos.x <= 0)
1204 pTile->m_boundDstRoi.x = pTile->m_pParent->m_untaintDstPos.x - pTile->m_untaintDstPos.x;
1205 else
1206 pTile->m_boundDstRoi.x = -pTile->m_untaintDstPos.x;
1207 }
1208 else
1209 pTile->m_boundDstRoi.x = 0;
1210
1211 if(pTile->m_untaintDstPos.y < 0 && !pTile->m_pParent->m_externalMem.top)
1212 {
1213 if(pTile->m_pParent->m_untaintDstPos.y <= 0)
1214 pTile->m_boundDstRoi.y = pTile->m_pParent->m_untaintDstPos.y - pTile->m_untaintDstPos.y;
1215 else
1216 pTile->m_boundDstRoi.y = -pTile->m_untaintDstPos.y;
1217 }
1218 else
1219 pTile->m_boundDstRoi.y = 0;
1220 }
1221
1222 // Src offset
1223 pTile->m_boundSrcRoi = pTile->m_srcRoi;
1224 if(pTile->m_pChild)
1225 {
1226 // Intermediate src buffer is aligned to point inside border
1227 pTile->m_boundSrcRoi.x = pTile->m_borderSize.left;
1228 pTile->m_boundSrcRoi.y = pTile->m_borderSize.top;
1229 }
1230 else
1231 {
1232 // Shift source image to make InMem border a part of ROI
1233 if(pTile->m_pParent)
1234 {
1235 if(pTile->m_untaintSrcPos.x < 0)
1236 {
1237 if(pTile->m_pParent->m_externalMemAcc.left >= -pTile->m_untaintSrcPos.x)
1238 pTile->m_boundSrcRoi.x = pTile->m_untaintSrcPos.x;
1239 else
1240 pTile->m_boundSrcRoi.x = 0;
1241 }
1242
1243 if(pTile->m_untaintSrcPos.y < 0)
1244 {
1245 if(pTile->m_pParent->m_externalMemAcc.top >= -pTile->m_untaintSrcPos.y)
1246 pTile->m_boundSrcRoi.y = pTile->m_untaintSrcPos.y;
1247 else
1248 pTile->m_boundSrcRoi.y = 0;
1249 }
1250 }
1251 }
1252
1253 pTile = pTile->m_pChild;
1254 }
1255
1256 return ippStsNoErr;
1257 }
1258
iwiTilePipeline_GetDstBufferSize(const IwiTile * pTile,IwiSize * pDstSize)1259 IW_DECL(IppStatus) iwiTilePipeline_GetDstBufferSize(const IwiTile *pTile, IwiSize *pDstSize)
1260 {
1261 IppStatus status = owniTilePipeline_InitCheck(pTile);
1262 if(status < 0)
1263 return status;
1264 if(!pDstSize)
1265 return ippStsNullPtrErr;
1266
1267 *pDstSize = pTile->m_dstBufferSize;
1268
1269 return ippStsNoErr;
1270 }
1271
iwiTilePipeline_GetChildSrcImageSize(const IwiTile * pTile,IwiSize srcOrigSize,IwiSize * pSrcFullSize)1272 IW_DECL(IppStatus) iwiTilePipeline_GetChildSrcImageSize(const IwiTile *pTile, IwiSize srcOrigSize, IwiSize *pSrcFullSize)
1273 {
1274 IppStatus status = owniTilePipeline_InitCheck(pTile);
1275 if(status < 0)
1276 return status;
1277 if(!pSrcFullSize)
1278 return ippStsNullPtrErr;
1279
1280 pSrcFullSize->width = srcOrigSize.width + pTile->m_externalMemAcc.left + pTile->m_externalMemAcc.right;
1281 pSrcFullSize->height = srcOrigSize.height + pTile->m_externalMemAcc.top + pTile->m_externalMemAcc.bottom;
1282
1283 return ippStsNoErr;
1284 }
1285
iwiTilePipeline_GetChildDstImageSize(const IwiTile * pTile,IwiSize dstOrigSize,IwiSize * pDstFullSize)1286 IW_DECL(IppStatus) iwiTilePipeline_GetChildDstImageSize(const IwiTile *pTile, IwiSize dstOrigSize, IwiSize *pDstFullSize)
1287 {
1288 IppStatus status = owniTilePipeline_InitCheck(pTile);
1289 if(status < 0)
1290 return status;
1291 if(!pDstFullSize)
1292 return ippStsNullPtrErr;
1293
1294 pDstFullSize->width = dstOrigSize.width + pTile->m_externalMemAcc.left + pTile->m_externalMemAcc.right;
1295 pDstFullSize->height = dstOrigSize.height + pTile->m_externalMemAcc.top + pTile->m_externalMemAcc.bottom;
1296
1297 return ippStsNoErr;
1298 }
1299
iwiTilePipeline_BuildBorder(const IwiTile * pTile,IwiImage * pSrcImage,IwiBorderType * pBorder,const Ipp64f * pBorderVal)1300 IW_DECL(IppStatus) iwiTilePipeline_BuildBorder(const IwiTile *pTile, IwiImage *pSrcImage, IwiBorderType *pBorder, const Ipp64f *pBorderVal)
1301 {
1302 IppStatus status;
1303
1304 if(!pBorder)
1305 return ippStsNullPtrErr;
1306
1307 status = owniTilePipeline_InitCheck(pTile);
1308 if(status < 0)
1309 return status;
1310
1311 status = owniCheckImageWrite(pSrcImage);
1312 if(status < 0)
1313 return status;
1314
1315 return owniTilePipeline_BuildBorder(pTile, pSrcImage, pBorder, pBorderVal, NULL);
1316 }
1317
iwiTilePipeline_GetBoundedSrcRoi(const IwiTile * pTile,IwiRoi * pBoundedRoi)1318 IW_DECL(IppStatus) iwiTilePipeline_GetBoundedSrcRoi(const IwiTile *pTile, IwiRoi *pBoundedRoi)
1319 {
1320 IppStatus status = owniTilePipeline_InitCheck(pTile);
1321 if(status < 0)
1322 return status;
1323 if(!pBoundedRoi)
1324 return ippStsNullPtrErr;
1325
1326 *pBoundedRoi = pTile->m_boundSrcRoi;
1327
1328 return ippStsNoErr;
1329 }
1330
iwiTilePipeline_GetBoundedDstRoi(const IwiTile * pTile,IwiRoi * pBoundedRoi)1331 IW_DECL(IppStatus) iwiTilePipeline_GetBoundedDstRoi(const IwiTile *pTile, IwiRoi *pBoundedRoi)
1332 {
1333 IppStatus status = owniTilePipeline_InitCheck(pTile);
1334 if(status < 0)
1335 return status;
1336 if(!pBoundedRoi)
1337 return ippStsNullPtrErr;
1338
1339 *pBoundedRoi = pTile->m_boundDstRoi;
1340
1341 return ippStsNoErr;
1342 }
1343
iwiTilePipeline_GetTileBorder(const IwiTile * pTile,IwiBorderType * pBorder)1344 IW_DECL(IppStatus) iwiTilePipeline_GetTileBorder(const IwiTile *pTile, IwiBorderType *pBorder)
1345 {
1346 IppStatus status = owniTilePipeline_InitCheck(pTile);
1347 if(status < 0)
1348 return status;
1349 if(!pBorder)
1350 return ippStsNullPtrErr;
1351
1352 owniTile_GetTileBorder(pBorder, &pTile->m_srcRoi, &pTile->m_borderSize, &pTile->m_srcImageSize);
1353 return ippStsNoErr;
1354 }
1355
iwiTilePipeline_GetMinTileSize(const IwiTile * pTile,IwiSize * pMinTileSize)1356 IW_DECL(IppStatus) iwiTilePipeline_GetMinTileSize(const IwiTile *pTile, IwiSize *pMinTileSize)
1357 {
1358 IppStatus status;
1359 const IwiTile *pRoot;
1360
1361 if(!pMinTileSize)
1362 return ippStsNullPtrErr;
1363 pRoot = owniTilePipeline_GetRoot(pTile);
1364 status = owniTilePipeline_InitCheck(pTile);
1365 if(status < 0)
1366 return status;
1367
1368 // Check width
1369 pTile = pRoot;
1370 while(pTile)
1371 {
1372 if(!pTile->m_pChild)
1373 {
1374 *pMinTileSize = iwiTile_GetMinTileSize(pTile->m_borderType, pTile->m_borderSize);
1375 if(pTile->m_pParent && (pMinTileSize->width > 1 || pMinTileSize->height > 1))
1376 {
1377 *pMinTileSize = iwiTile_GetMinTileSize(pTile->m_borderType, pTile->m_borderSizeAcc);
1378 }
1379
1380 return ippStsNoErr;
1381 }
1382
1383 pTile = pTile->m_pChild;
1384 }
1385
1386 return ippStsNoErr;
1387 }
1388
1389