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/iw_image_op.h"
16 #include "iw_owni.h"
17 
18 IW_DECL(IppStatus) llwiCopyMerge(const void* const pSrc[], int srcStep, void *pDst, int dstStep,
19                                    IppiSize size, int typeSize, int channels, int partial);
20 
21 IW_DECL(IppStatus) llwiCopyChannel(const void *pSrc, int srcStep, int srcChannels, int srcChannel, void *pDst, int dstStep,
22     int dstChannels, int dstChannel, IppiSize size, int typeSize);
23 
24 /**/////////////////////////////////////////////////////////////////////////////
25 //                   iwiMergeChannels
26 ///////////////////////////////////////////////////////////////////////////// */
iwiMergeChannels(const IwiImage * const pSrcImage[],IwiImage * pDstImage,const IwiMergeChannelsParams * pAuxParams,const IwiTile * pTile)27 IW_DECL(IppStatus) iwiMergeChannels(const IwiImage* const pSrcImage[], IwiImage *pDstImage, const IwiMergeChannelsParams *pAuxParams, const IwiTile *pTile)
28 {
29     IppStatus status;
30 
31     (void)pAuxParams;
32 
33     status = owniCheckImageWrite(pDstImage);
34     if(status)
35         return status;
36 
37     if(!pSrcImage)
38         return ippStsNullPtrErr;
39 
40     if(pDstImage->m_channels == 1)
41         return iwiCopy(pSrcImage[0], pDstImage, NULL, NULL, pTile);
42 
43     if(pDstImage->m_channels > 4)
44         return ippStsNumChannelsErr;
45 
46     {
47         const void* pSrc[4]       = {NULL};
48         IwSize      srcStep[4]    = {0};
49         int         srcPixSize[4] = {0};
50         void*       pDst          = pDstImage->m_ptr;
51         IwiSize     size          = pDstImage->m_size;
52         int         channels      = pDstImage->m_channels;
53         int         i;
54 
55         for(i = 0; i < pDstImage->m_channels; i++)
56         {
57             if(pSrcImage[i] && pSrcImage[i]->m_ptrConst)
58             {
59                 if(pSrcImage[i]->m_ptrConst == pDstImage->m_ptrConst)
60                     return ippStsInplaceModeNotSupportedErr;
61 
62                 if(pSrcImage[i]->m_typeSize != pDstImage->m_typeSize)
63                     return ippStsBadArgErr;
64 
65                 size          = owniGetMinSize(&pSrcImage[i]->m_size, &size);
66                 pSrc[i]       = pSrcImage[i]->m_ptrConst;
67                 srcStep[i]    = pSrcImage[i]->m_step;
68                 srcPixSize[i] = pSrcImage[i]->m_typeSize*pSrcImage[i]->m_channels;
69                 if(srcStep[i] != srcStep[0])
70                     return ippStsStepErr;
71                 if(srcPixSize[i] != srcPixSize[0])
72                     return ippStsBadArgErr;
73             }
74             else
75                 channels--;
76         }
77         if(!size.width || !size.height)
78             return ippStsNoOperation;
79         if(!channels)
80             return ippStsNoOperation;
81 
82         if(pTile && pTile->m_initialized != ownTileInitNone)
83         {
84             if(pTile->m_initialized == ownTileInitSimple)
85             {
86                 IwiRoi dstRoi = pTile->m_dstRoi;
87 
88                 if(!owniTile_BoundToSize(&dstRoi, &size))
89                     return ippStsNoOperation;
90 
91                 owniShiftPtrArrConst(pSrc, pSrc, srcStep, srcPixSize, pDstImage->m_channels, dstRoi.x, dstRoi.y);
92                 pDst = iwiImage_GetPtr(pDstImage, dstRoi.y, dstRoi.x, 0);
93             }
94             else if(pTile->m_initialized == ownTileInitPipe)
95             {
96                 IwiRoi srcLim;
97                 IwiRoi dstLim;
98                 iwiTilePipeline_GetBoundedSrcRoi(pTile, &srcLim);
99                 iwiTilePipeline_GetBoundedDstRoi(pTile, &dstLim);
100 
101                 owniShiftPtrArrConst(pSrc, pSrc, srcStep, srcPixSize, pDstImage->m_channels, srcLim.x, srcLim.y);
102                 pDst = iwiImage_GetPtr(pDstImage, dstLim.y, dstLim.x, 0);
103 
104                 size = owniGetMinSizeFromRect(&srcLim, &dstLim);
105             }
106             else
107                 return ippStsContextMatchErr;
108         }
109 
110         // Long compatibility check
111         {
112             IppiSize _size;
113 
114             status = ownLongCompatCheckValue(pSrcImage[0]->m_step, NULL);
115             if(status < 0)
116                 return status;
117 
118             status = ownLongCompatCheckValue(pDstImage->m_step, NULL);
119             if(status < 0)
120                 return status;
121 
122             status = owniLongCompatCheckSize(size, &_size);
123             if(status < 0)
124                 return status;
125 
126             return llwiCopyMerge((const void* const*)pSrc, (int)srcStep[0], pDst, (int)pDstImage->m_step, _size, pDstImage->m_typeSize, pDstImage->m_channels, (channels != pDstImage->m_channels)?1:0);
127         }
128     }
129 }
130 
131 
132 /**/////////////////////////////////////////////////////////////////////////////
133 //                   Low-Level Wrappers
134 ///////////////////////////////////////////////////////////////////////////// */
llwiCopyMerge(const void * const pSrc[],int srcStep,void * pDst,int dstStep,IppiSize size,int typeSize,int channels,int partial)135 IW_DECL(IppStatus) llwiCopyMerge(const void* const pSrc[], int srcStep, void *pDst, int dstStep,
136                                    IppiSize size, int typeSize, int channels, int partial)
137 {
138     if(partial)
139     {
140         IppStatus status = ippStsNoErr;
141         int       i = 0;
142         for(i = 0; i < channels; i++)
143         {
144             if(pSrc[i])
145             {
146                 status = llwiCopyChannel(pSrc[i], srcStep, 1, 0, pDst, dstStep, channels, i, size, typeSize);
147                 if(status < 0)
148                     return status;
149             }
150         }
151         return status;
152     }
153     else
154     {
155         switch(typeSize)
156         {
157         case 1:
158             switch(channels)
159             {
160             case 3:  return ippiCopy_8u_P3C3R((const Ipp8u**)pSrc, srcStep, (Ipp8u*)pDst, dstStep, size);
161             case 4:  return ippiCopy_8u_P4C4R((const Ipp8u**)pSrc, srcStep, (Ipp8u*)pDst, dstStep, size);
162             default: return ippStsNumChannelsErr;
163             }
164         case 2:
165             switch(channels)
166             {
167             case 3:  return ippiCopy_16u_P3C3R((const Ipp16u**)pSrc, srcStep, (Ipp16u*)pDst, dstStep, size);
168             case 4:  return ippiCopy_16u_P4C4R((const Ipp16u**)pSrc, srcStep, (Ipp16u*)pDst, dstStep, size);
169             default: return ippStsNumChannelsErr;
170             }
171         case 4:
172             switch(channels)
173             {
174             case 3:  return ippiCopy_32f_P3C3R((const Ipp32f**)pSrc, srcStep, (Ipp32f*)pDst, dstStep, size);
175             case 4:  return ippiCopy_32f_P4C4R((const Ipp32f**)pSrc, srcStep, (Ipp32f*)pDst, dstStep, size);
176             default: return ippStsNumChannelsErr;
177             }
178         default: return ippStsDataTypeErr;
179         }
180     }
181 }
182