1 /*
2  * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 
27 /*
28  * FUNCTION
29  *      mlib_ImageAffine_u8_1ch_bl
30  *      mlib_ImageAffine_u8_2ch_bl
31  *      mlib_ImageAffine_u8_3ch_bl
32  *      mlib_ImageAffine_u8_4ch_bl
33  *        - image affine transformation with Bilinear filtering
34  * SYNOPSIS
35  *      mlib_status mlib_ImageAffine_u8_?ch_bl(mlib_s32 *leftEdges,
36  *                                             mlib_s32 *rightEdges,
37  *                                             mlib_s32 *xStarts,
38  *                                             mlib_s32 *yStarts,
39  *                                             mlib_s32 *sides,
40  *                                             mlib_u8  *dstData,
41  *                                             mlib_u8  **lineAddr,
42  *                                             mlib_s32 dstYStride,
43  *                                             mlib_s32 is_affine,
44  *                                             mlib_s32 srcYStride)
45  *
46  * ARGUMENTS
47  *      leftEdges  array[dstHeight] of xLeft coordinates
48  *      RightEdges array[dstHeight] of xRight coordinates
49  *      xStarts    array[dstHeight] of xStart * 65536 coordinates
50  *      yStarts    array[dstHeight] of yStart * 65536 coordinates
51  *      sides      output array[4]. sides[0] is yStart, sides[1] is yFinish,
52  *                 sides[2] is dx * 65536, sides[3] is dy * 65536
53  *      dstData    pointer to the first pixel on (yStart - 1) line
54  *      lineAddr   array[srcHeight] of pointers to the first pixel on
55  *                 the corresponding lines
56  *      dstYStride stride of destination image
57  *      is_affine  indicator (Affine - GridWarp)
58  *      srcYStride stride of source image
59  *
60  * DESCRIPTION
61  *      The functions step along the lines from xLeft to xRight and apply
62  *      the bilinear filtering.
63  *
64  */
65 
66 #include "mlib_ImageAffine.h"
67 
68 /***************************************************************/
69 #define DTYPE  mlib_u8
70 #define FTYPE  mlib_f32
71 
72 /***************************************************************/
73 #define TTYPE    mlib_f32
74 #define I2F(x)   mlib_U82F32[x]
75 #define ROUND(x) ((x) + 0.5f)
76 
77 #define FUN_NAME(CHAN) mlib_ImageAffine_u8_##CHAN##_bl
78 
79 /***************************************************************/
80 /* for x86, using integer multiplies is faster */
81 
82 /* for SHORT/USHORT decrease MLIB_SHIFT due to
83  * overflow in multiplies like fdy * (a10 - a00)
84  */
85 /*
86 #undef  MLIB_SHIFT
87 #define MLIB_SHIFT  15
88 */
89 
90 #define MLIB_ROUND   (1 << (MLIB_SHIFT - 1))
91 
92 /***************************************************************/
93 #define GET_POINTERS(ind)                                        \
94   fdx = X & MLIB_MASK;                                           \
95   fdy = Y & MLIB_MASK;                                           \
96   ySrc = MLIB_POINTER_SHIFT(Y);                                  \
97   xSrc = X >> MLIB_SHIFT;                                        \
98   srcPixelPtr = MLIB_POINTER_GET(lineAddr, ySrc) + ind * xSrc;   \
99   srcPixelPtr2 = (DTYPE *)((mlib_u8 *)srcPixelPtr + srcYStride); \
100   X += dX;                                                       \
101   Y += dY
102 
103 /***************************************************************/
104 #define COUNT(ind)                                                                       \
105   pix0_##ind = a00_##ind + ((fdy * (a10_##ind - a00_##ind) + MLIB_ROUND) >> MLIB_SHIFT); \
106   pix1_##ind = a01_##ind + ((fdy * (a11_##ind - a01_##ind) + MLIB_ROUND) >> MLIB_SHIFT); \
107   res##ind = pix0_##ind + ((fdx * (pix1_##ind - pix0_##ind) + MLIB_ROUND) >> MLIB_SHIFT)
108 
109 /***************************************************************/
110 #define LOAD(ind, ind1, ind2)                                   \
111   a00_##ind = srcPixelPtr[ind1];                                \
112   a01_##ind = srcPixelPtr[ind2];                                \
113   a10_##ind = srcPixelPtr2[ind1];                               \
114   a11_##ind = srcPixelPtr2[ind2]
115 
116 /***************************************************************/
117 mlib_status FUN_NAME(1ch)(mlib_affine_param *param)
118 {
119   DECLAREVAR_BL();
120   DTYPE *dstLineEnd;
121   DTYPE *srcPixelPtr2;
122 
123 #if MLIB_SHIFT == 15
124   dX = (dX + 1) >> 1;
125   dY = (dY + 1) >> 1;
126 #endif /* MLIB_SHIFT == 15 */
127 
128   for (j = yStart; j <= yFinish; j++) {
129     mlib_s32 fdx, fdy;
130     mlib_s32 a00_0, a01_0, a10_0, a11_0;
131     mlib_s32 pix0_0, pix1_0, res0;
132 
133     CLIP(1);
134     dstLineEnd = (DTYPE *) dstData + xRight;
135 #if MLIB_SHIFT == 15
136     X = X >> 1;
137     Y = Y >> 1;
138 #endif /* MLIB_SHIFT == 15 */
139 
140     GET_POINTERS(1);
141     LOAD(0, 0, 1);
142 
143     for (; dstPixelPtr < dstLineEnd; dstPixelPtr++) {
144       COUNT(0);
145       GET_POINTERS(1);
146       LOAD(0, 0, 1);
147       dstPixelPtr[0] = (DTYPE) res0;
148     }
149 
150     COUNT(0);
151     dstPixelPtr[0] = (DTYPE) res0;
152   }
153 
154   return MLIB_SUCCESS;
155 }
156 
157 /***************************************************************/
158 mlib_status FUN_NAME(2ch)(mlib_affine_param *param)
159 {
160   DECLAREVAR_BL();
161   DTYPE *dstLineEnd;
162   DTYPE *srcPixelPtr2;
163 
164 #if MLIB_SHIFT == 15
165   dX = (dX + 1) >> 1;
166   dY = (dY + 1) >> 1;
167 #endif /* MLIB_SHIFT == 15 */
168 
169   for (j = yStart; j <= yFinish; j++) {
170     mlib_s32 fdx, fdy;
171     mlib_s32 a00_0, a01_0, a10_0, a11_0;
172     mlib_s32 a00_1, a01_1, a10_1, a11_1;
173     mlib_s32 pix0_0, pix1_0, res0;
174     mlib_s32 pix0_1, pix1_1, res1;
175 
176     CLIP(2);
177     dstLineEnd = (DTYPE *) dstData + 2 * xRight;
178 #if MLIB_SHIFT == 15
179     X = X >> 1;
180     Y = Y >> 1;
181 #endif /* MLIB_SHIFT == 15 */
182 
183     GET_POINTERS(2);
184     LOAD(0, 0, 2);
185     LOAD(1, 1, 3);
186 
187     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 2) {
188       COUNT(0);
189       COUNT(1);
190       GET_POINTERS(2);
191       LOAD(0, 0, 2);
192       LOAD(1, 1, 3);
193       dstPixelPtr[0] = (DTYPE) res0;
194       dstPixelPtr[1] = (DTYPE) res1;
195     }
196 
197     COUNT(0);
198     COUNT(1);
199     dstPixelPtr[0] = (DTYPE) res0;
200     dstPixelPtr[1] = (DTYPE) res1;
201   }
202 
203   return MLIB_SUCCESS;
204 }
205 
206 /***************************************************************/
207 mlib_status FUN_NAME(3ch)(mlib_affine_param *param)
208 {
209   DECLAREVAR_BL();
210   DTYPE *dstLineEnd;
211   DTYPE *srcPixelPtr2;
212 
213 #if MLIB_SHIFT == 15
214   dX = (dX + 1) >> 1;
215   dY = (dY + 1) >> 1;
216 #endif /* MLIB_SHIFT == 15 */
217 
218   for (j = yStart; j <= yFinish; j++) {
219     mlib_s32 fdx, fdy;
220     mlib_s32 a00_0, a01_0, a10_0, a11_0;
221     mlib_s32 a00_1, a01_1, a10_1, a11_1;
222     mlib_s32 a00_2, a01_2, a10_2, a11_2;
223     mlib_s32 pix0_0, pix1_0, res0;
224     mlib_s32 pix0_1, pix1_1, res1;
225     mlib_s32 pix0_2, pix1_2, res2;
226 
227     CLIP(3);
228     dstLineEnd = (DTYPE *) dstData + 3 * xRight;
229 #if MLIB_SHIFT == 15
230     X = X >> 1;
231     Y = Y >> 1;
232 #endif /* MLIB_SHIFT == 15 */
233 
234     GET_POINTERS(3);
235     LOAD(0, 0, 3);
236     LOAD(1, 1, 4);
237     LOAD(2, 2, 5);
238 
239     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 3) {
240       COUNT(0);
241       COUNT(1);
242       COUNT(2);
243       GET_POINTERS(3);
244       LOAD(0, 0, 3);
245       LOAD(1, 1, 4);
246       LOAD(2, 2, 5);
247       dstPixelPtr[0] = (DTYPE) res0;
248       dstPixelPtr[1] = (DTYPE) res1;
249       dstPixelPtr[2] = (DTYPE) res2;
250     }
251 
252     COUNT(0);
253     COUNT(1);
254     COUNT(2);
255     dstPixelPtr[0] = (DTYPE) res0;
256     dstPixelPtr[1] = (DTYPE) res1;
257     dstPixelPtr[2] = (DTYPE) res2;
258   }
259 
260   return MLIB_SUCCESS;
261 }
262 
263 /***************************************************************/
264 mlib_status FUN_NAME(4ch)(mlib_affine_param *param)
265 {
266   DECLAREVAR_BL();
267   DTYPE *dstLineEnd;
268   DTYPE *srcPixelPtr2;
269 
270 #if MLIB_SHIFT == 15
271   dX = (dX + 1) >> 1;
272   dY = (dY + 1) >> 1;
273 #endif /* MLIB_SHIFT == 15 */
274 
275   for (j = yStart; j <= yFinish; j++) {
276     mlib_s32 fdx, fdy;
277     mlib_s32 a00_0, a01_0, a10_0, a11_0;
278     mlib_s32 a00_1, a01_1, a10_1, a11_1;
279     mlib_s32 a00_2, a01_2, a10_2, a11_2;
280     mlib_s32 a00_3, a01_3, a10_3, a11_3;
281     mlib_s32 pix0_0, pix1_0, res0;
282     mlib_s32 pix0_1, pix1_1, res1;
283     mlib_s32 pix0_2, pix1_2, res2;
284     mlib_s32 pix0_3, pix1_3, res3;
285 
286     CLIP(4);
287     dstLineEnd = (DTYPE *) dstData + 4 * xRight;
288 #if MLIB_SHIFT == 15
289     X = X >> 1;
290     Y = Y >> 1;
291 #endif /* MLIB_SHIFT == 15 */
292 
293     GET_POINTERS(4);
294     LOAD(0, 0, 4);
295     LOAD(1, 1, 5);
296     LOAD(2, 2, 6);
297     LOAD(3, 3, 7);
298 
299     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 4) {
300       COUNT(0);
301       COUNT(1);
302       COUNT(2);
303       COUNT(3);
304       GET_POINTERS(4);
305       LOAD(0, 0, 4);
306       LOAD(1, 1, 5);
307       LOAD(2, 2, 6);
308       LOAD(3, 3, 7);
309       dstPixelPtr[0] = (DTYPE) res0;
310       dstPixelPtr[1] = (DTYPE) res1;
311       dstPixelPtr[2] = (DTYPE) res2;
312       dstPixelPtr[3] = (DTYPE) res3;
313     }
314 
315     COUNT(0);
316     COUNT(1);
317     COUNT(2);
318     COUNT(3);
319     dstPixelPtr[0] = (DTYPE) res0;
320     dstPixelPtr[1] = (DTYPE) res1;
321     dstPixelPtr[2] = (DTYPE) res2;
322     dstPixelPtr[3] = (DTYPE) res3;
323   }
324 
325   return MLIB_SUCCESS;
326 }
327 
328 /***************************************************************/
329