1 /*
2  * Copyright (c) 2003, 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_u16_1ch_bl
30  *      mlib_ImageAffine_u16_2ch_bl
31  *      mlib_ImageAffine_u16_3ch_bl
32  *      mlib_ImageAffine_u16_4ch_bl
33  *        - image affine transformation with Bilinear filtering
34  * SYNOPSIS
35  *      mlib_status mlib_ImageAffine_u16_?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_u16
70 #define FTYPE  mlib_d64
71 
72 /***************************************************************/
73 #define TTYPE    mlib_s32
74 #define I2F(x)   (x)
75 #define ROUND(x) (x)
76 
77 #define FUN_NAME(CHAN) mlib_ImageAffine_u16_##CHAN##_bl
78 
79 /***************************************************************/
80 #ifdef __sparc /* for SPARC, using floating-point multiplies is faster */
81 
82 /***************************************************************/
83 #define GET_POINTERS(ind)                                       \
84   fdx = (FTYPE)(X & MLIB_MASK) * scale;                         \
85   fdy = (FTYPE)(Y & MLIB_MASK) * scale;                         \
86   ySrc = MLIB_POINTER_SHIFT(Y);  Y += dY;                       \
87   xSrc = X >> MLIB_SHIFT;  X += dX;                             \
88   srcPixelPtr = MLIB_POINTER_GET(lineAddr, ySrc) + ind * xSrc;  \
89   srcPixelPtr2 = (DTYPE *)((mlib_u8 *)srcPixelPtr + srcYStride)
90 
91 /***************************************************************/
92 #define COUNT(ind)                                              \
93   pix0_##ind = a00_##ind + fdy * (a10_##ind - a00_##ind);       \
94   pix1_##ind = a01_##ind + fdy * (a11_##ind - a01_##ind);       \
95   res##ind = ROUND(pix0_##ind + fdx * (pix1_##ind - pix0_##ind))
96 
97 /***************************************************************/
98 #define LOAD(ind, ind1, ind2)                                   \
99   a00_##ind = I2F(srcPixelPtr[ind1]);                           \
100   a01_##ind = I2F(srcPixelPtr[ind2]);                           \
101   a10_##ind = I2F(srcPixelPtr2[ind1]);                          \
102   a11_##ind = I2F(srcPixelPtr2[ind2])
103 
104 /***************************************************************/
105 mlib_status FUN_NAME(1ch)(mlib_affine_param *param)
106 {
107   DECLAREVAR_BL();
108   DTYPE *dstLineEnd;
109   DTYPE *srcPixelPtr2;
110   FTYPE scale = (FTYPE) 1.0 / MLIB_PREC;
111 
112   for (j = yStart; j <= yFinish; j++) {
113     FTYPE fdx, fdy;
114     TTYPE a00_0, a01_0, a10_0, a11_0;
115     FTYPE pix0_0, pix1_0, res0;
116 
117     CLIP(1);
118     dstLineEnd = (DTYPE *) dstData + xRight;
119 
120     GET_POINTERS(1);
121     LOAD(0, 0, 1);
122 
123 #ifdef __SUNPRO_C
124 #pragma pipeloop(0)
125 #endif /* __SUNPRO_C */
126     for (; dstPixelPtr < dstLineEnd; dstPixelPtr++) {
127       COUNT(0);
128       GET_POINTERS(1);
129       LOAD(0, 0, 1);
130       dstPixelPtr[0] = (DTYPE) res0;
131     }
132 
133     COUNT(0);
134     dstPixelPtr[0] = (DTYPE) res0;
135   }
136 
137   return MLIB_SUCCESS;
138 }
139 
140 /***************************************************************/
141 mlib_status FUN_NAME(2ch)(mlib_affine_param *param)
142 {
143   DECLAREVAR_BL();
144   DTYPE *dstLineEnd;
145   DTYPE *srcPixelPtr2;
146   FTYPE scale = (FTYPE) 1.0 / MLIB_PREC;
147 
148   for (j = yStart; j <= yFinish; j++) {
149     FTYPE fdx, fdy;
150     TTYPE a00_0, a01_0, a10_0, a11_0;
151     TTYPE a00_1, a01_1, a10_1, a11_1;
152     FTYPE pix0_0, pix1_0, res0;
153     FTYPE pix0_1, pix1_1, res1;
154 
155     CLIP(2);
156     dstLineEnd = (DTYPE *) dstData + 2 * xRight;
157 
158     GET_POINTERS(2);
159     LOAD(0, 0, 2);
160     LOAD(1, 1, 3);
161 
162 #ifdef __SUNPRO_C
163 #pragma pipeloop(0)
164 #endif /* __SUNPRO_C */
165     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 2) {
166       COUNT(0);
167       COUNT(1);
168       GET_POINTERS(2);
169       LOAD(0, 0, 2);
170       LOAD(1, 1, 3);
171       dstPixelPtr[0] = (DTYPE) res0;
172       dstPixelPtr[1] = (DTYPE) res1;
173     }
174 
175     COUNT(0);
176     COUNT(1);
177     dstPixelPtr[0] = (DTYPE) res0;
178     dstPixelPtr[1] = (DTYPE) res1;
179   }
180 
181   return MLIB_SUCCESS;
182 }
183 
184 /***************************************************************/
185 mlib_status FUN_NAME(3ch)(mlib_affine_param *param)
186 {
187   DECLAREVAR_BL();
188   DTYPE *dstLineEnd;
189   DTYPE *srcPixelPtr2;
190   FTYPE scale = (FTYPE) 1.0 / MLIB_PREC;
191 
192   for (j = yStart; j <= yFinish; j++) {
193     FTYPE fdx, fdy;
194     FTYPE a00_0, a01_0, a10_0, a11_0;
195     FTYPE a00_1, a01_1, a10_1, a11_1;
196     FTYPE a00_2, a01_2, a10_2, a11_2;
197     FTYPE pix0_0, pix1_0, res0;
198     FTYPE pix0_1, pix1_1, res1;
199     FTYPE pix0_2, pix1_2, res2;
200 
201     CLIP(3);
202     dstLineEnd = (DTYPE *) dstData + 3 * xRight;
203 
204     GET_POINTERS(3);
205     LOAD(0, 0, 3);
206     LOAD(1, 1, 4);
207     LOAD(2, 2, 5);
208 
209 #ifdef __SUNPRO_C
210 #pragma pipeloop(0)
211 #endif /* __SUNPRO_C */
212     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 3) {
213       COUNT(0);
214       COUNT(1);
215       COUNT(2);
216       GET_POINTERS(3);
217       LOAD(0, 0, 3);
218       LOAD(1, 1, 4);
219       LOAD(2, 2, 5);
220       dstPixelPtr[0] = (DTYPE) res0;
221       dstPixelPtr[1] = (DTYPE) res1;
222       dstPixelPtr[2] = (DTYPE) res2;
223     }
224 
225     COUNT(0);
226     COUNT(1);
227     COUNT(2);
228     dstPixelPtr[0] = (DTYPE) res0;
229     dstPixelPtr[1] = (DTYPE) res1;
230     dstPixelPtr[2] = (DTYPE) res2;
231   }
232 
233   return MLIB_SUCCESS;
234 }
235 
236 /***************************************************************/
237 mlib_status FUN_NAME(4ch)(mlib_affine_param *param)
238 {
239   DECLAREVAR_BL();
240   DTYPE *dstLineEnd;
241   DTYPE *srcPixelPtr2;
242   FTYPE scale = (FTYPE) 1.0 / MLIB_PREC;
243 
244   for (j = yStart; j <= yFinish; j++) {
245     FTYPE fdx, fdy;
246     TTYPE a00_0, a01_0, a10_0, a11_0;
247     TTYPE a00_1, a01_1, a10_1, a11_1;
248     TTYPE a00_2, a01_2, a10_2, a11_2;
249     TTYPE a00_3, a01_3, a10_3, a11_3;
250     FTYPE pix0_0, pix1_0, res0;
251     FTYPE pix0_1, pix1_1, res1;
252     FTYPE pix0_2, pix1_2, res2;
253     FTYPE pix0_3, pix1_3, res3;
254 
255     CLIP(4);
256     dstLineEnd = (DTYPE *) dstData + 4 * xRight;
257 
258     GET_POINTERS(4);
259     LOAD(0, 0, 4);
260     LOAD(1, 1, 5);
261     LOAD(2, 2, 6);
262     LOAD(3, 3, 7);
263 
264 #ifdef __SUNPRO_C
265 #pragma pipeloop(0)
266 #endif /* __SUNPRO_C */
267     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 4) {
268       COUNT(0);
269       COUNT(1);
270       COUNT(2);
271       COUNT(3);
272       GET_POINTERS(4);
273       LOAD(0, 0, 4);
274       LOAD(1, 1, 5);
275       LOAD(2, 2, 6);
276       LOAD(3, 3, 7);
277       dstPixelPtr[0] = (DTYPE) res0;
278       dstPixelPtr[1] = (DTYPE) res1;
279       dstPixelPtr[2] = (DTYPE) res2;
280       dstPixelPtr[3] = (DTYPE) res3;
281     }
282 
283     COUNT(0);
284     COUNT(1);
285     COUNT(2);
286     COUNT(3);
287     dstPixelPtr[0] = (DTYPE) res0;
288     dstPixelPtr[1] = (DTYPE) res1;
289     dstPixelPtr[2] = (DTYPE) res2;
290     dstPixelPtr[3] = (DTYPE) res3;
291   }
292 
293   return MLIB_SUCCESS;
294 }
295 
296 /***************************************************************/
297 #else       /* for x86, using integer multiplies is faster */
298 
299 /***************************************************************/
300 /* for SHORT/USHORT decrease MLIB_SHIFT due to overflow in multiplies like fdy * (a10 - a00) */
301 #undef  MLIB_SHIFT
302 #define MLIB_SHIFT  15
303 
304 #define MLIB_ROUND   (1 << (MLIB_SHIFT - 1))
305 
306 /***************************************************************/
307 #define GET_POINTERS(ind)                                        \
308   fdx = X & MLIB_MASK;                                           \
309   fdy = Y & MLIB_MASK;                                           \
310   ySrc = MLIB_POINTER_SHIFT(Y);                                  \
311   xSrc = X >> MLIB_SHIFT;                                        \
312   srcPixelPtr = MLIB_POINTER_GET(lineAddr, ySrc) + ind * xSrc;   \
313   srcPixelPtr2 = (DTYPE *)((mlib_u8 *)srcPixelPtr + srcYStride); \
314   X += dX;                                                       \
315   Y += dY
316 
317 /***************************************************************/
318 #define COUNT(ind)                                                                       \
319   pix0_##ind = a00_##ind + ((fdy * (a10_##ind - a00_##ind) + MLIB_ROUND) >> MLIB_SHIFT); \
320   pix1_##ind = a01_##ind + ((fdy * (a11_##ind - a01_##ind) + MLIB_ROUND) >> MLIB_SHIFT); \
321   res##ind = pix0_##ind + ((fdx * (pix1_##ind - pix0_##ind) + MLIB_ROUND) >> MLIB_SHIFT)
322 
323 /***************************************************************/
324 #define LOAD(ind, ind1, ind2)                                   \
325   a00_##ind = srcPixelPtr[ind1];                                \
326   a01_##ind = srcPixelPtr[ind2];                                \
327   a10_##ind = srcPixelPtr2[ind1];                               \
328   a11_##ind = srcPixelPtr2[ind2]
329 
330 /***************************************************************/
331 mlib_status FUN_NAME(1ch)(mlib_affine_param *param)
332 {
333   DECLAREVAR_BL();
334   DTYPE *dstLineEnd;
335   DTYPE *srcPixelPtr2;
336 
337 #if MLIB_SHIFT == 15
338   dX = (dX + 1) >> 1;
339   dY = (dY + 1) >> 1;
340 #endif
341 
342   for (j = yStart; j <= yFinish; j++) {
343     mlib_s32 fdx, fdy;
344     mlib_s32 a00_0, a01_0, a10_0, a11_0;
345     mlib_s32 pix0_0, pix1_0, res0;
346 
347     CLIP(1);
348     dstLineEnd = (DTYPE *) dstData + xRight;
349 #if MLIB_SHIFT == 15
350     X = X >> 1;
351     Y = Y >> 1;
352 
353     if (warp_tbl != NULL) {
354       dX = (dX + 1) >> 1;
355       dY = (dY + 1) >> 1;
356     }
357 
358 #endif
359 
360     GET_POINTERS(1);
361     LOAD(0, 0, 1);
362 
363 #ifdef __SUNPRO_C
364 #pragma pipeloop(0)
365 #endif /* __SUNPRO_C */
366     for (; dstPixelPtr < dstLineEnd; dstPixelPtr++) {
367       COUNT(0);
368       GET_POINTERS(1);
369       LOAD(0, 0, 1);
370       dstPixelPtr[0] = (DTYPE) res0;
371     }
372 
373     COUNT(0);
374     dstPixelPtr[0] = (DTYPE) res0;
375   }
376 
377   return MLIB_SUCCESS;
378 }
379 
380 /***************************************************************/
381 mlib_status FUN_NAME(2ch)(mlib_affine_param *param)
382 {
383   DECLAREVAR_BL();
384   DTYPE *dstLineEnd;
385   DTYPE *srcPixelPtr2;
386 
387 #if MLIB_SHIFT == 15
388   dX = (dX + 1) >> 1;
389   dY = (dY + 1) >> 1;
390 #endif
391 
392   for (j = yStart; j <= yFinish; j++) {
393     mlib_s32 fdx, fdy;
394     mlib_s32 a00_0, a01_0, a10_0, a11_0;
395     mlib_s32 a00_1, a01_1, a10_1, a11_1;
396     mlib_s32 pix0_0, pix1_0, res0;
397     mlib_s32 pix0_1, pix1_1, res1;
398 
399     CLIP(2);
400     dstLineEnd = (DTYPE *) dstData + 2 * xRight;
401 #if MLIB_SHIFT == 15
402     X = X >> 1;
403     Y = Y >> 1;
404 
405     if (warp_tbl != NULL) {
406       dX = (dX + 1) >> 1;
407       dY = (dY + 1) >> 1;
408     }
409 
410 #endif
411 
412     GET_POINTERS(2);
413     LOAD(0, 0, 2);
414     LOAD(1, 1, 3);
415 
416 #ifdef __SUNPRO_C
417 #pragma pipeloop(0)
418 #endif /* __SUNPRO_C */
419     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 2) {
420       COUNT(0);
421       COUNT(1);
422       GET_POINTERS(2);
423       LOAD(0, 0, 2);
424       LOAD(1, 1, 3);
425       dstPixelPtr[0] = (DTYPE) res0;
426       dstPixelPtr[1] = (DTYPE) res1;
427     }
428 
429     COUNT(0);
430     COUNT(1);
431     dstPixelPtr[0] = (DTYPE) res0;
432     dstPixelPtr[1] = (DTYPE) res1;
433   }
434 
435   return MLIB_SUCCESS;
436 }
437 
438 /***************************************************************/
439 mlib_status FUN_NAME(3ch)(mlib_affine_param *param)
440 {
441   DECLAREVAR_BL();
442   DTYPE *dstLineEnd;
443   DTYPE *srcPixelPtr2;
444 
445 #if MLIB_SHIFT == 15
446   dX = (dX + 1) >> 1;
447   dY = (dY + 1) >> 1;
448 #endif
449 
450   for (j = yStart; j <= yFinish; j++) {
451     mlib_s32 fdx, fdy;
452     mlib_s32 a00_0, a01_0, a10_0, a11_0;
453     mlib_s32 a00_1, a01_1, a10_1, a11_1;
454     mlib_s32 a00_2, a01_2, a10_2, a11_2;
455     mlib_s32 pix0_0, pix1_0, res0;
456     mlib_s32 pix0_1, pix1_1, res1;
457     mlib_s32 pix0_2, pix1_2, res2;
458 
459     CLIP(3);
460     dstLineEnd = (DTYPE *) dstData + 3 * xRight;
461 #if MLIB_SHIFT == 15
462     X = X >> 1;
463     Y = Y >> 1;
464 
465     if (warp_tbl != NULL) {
466       dX = (dX + 1) >> 1;
467       dY = (dY + 1) >> 1;
468     }
469 
470 #endif
471 
472     GET_POINTERS(3);
473     LOAD(0, 0, 3);
474     LOAD(1, 1, 4);
475     LOAD(2, 2, 5);
476 
477 #ifdef __SUNPRO_C
478 #pragma pipeloop(0)
479 #endif /* __SUNPRO_C */
480     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 3) {
481       COUNT(0);
482       COUNT(1);
483       COUNT(2);
484       GET_POINTERS(3);
485       LOAD(0, 0, 3);
486       LOAD(1, 1, 4);
487       LOAD(2, 2, 5);
488       dstPixelPtr[0] = (DTYPE) res0;
489       dstPixelPtr[1] = (DTYPE) res1;
490       dstPixelPtr[2] = (DTYPE) res2;
491     }
492 
493     COUNT(0);
494     COUNT(1);
495     COUNT(2);
496     dstPixelPtr[0] = (DTYPE) res0;
497     dstPixelPtr[1] = (DTYPE) res1;
498     dstPixelPtr[2] = (DTYPE) res2;
499   }
500 
501   return MLIB_SUCCESS;
502 }
503 
504 /***************************************************************/
505 mlib_status FUN_NAME(4ch)(mlib_affine_param *param)
506 {
507   DECLAREVAR_BL();
508   DTYPE *dstLineEnd;
509   DTYPE *srcPixelPtr2;
510 
511 #if MLIB_SHIFT == 15
512   dX = (dX + 1) >> 1;
513   dY = (dY + 1) >> 1;
514 #endif
515 
516   for (j = yStart; j <= yFinish; j++) {
517     mlib_s32 fdx, fdy;
518     mlib_s32 a00_0, a01_0, a10_0, a11_0;
519     mlib_s32 a00_1, a01_1, a10_1, a11_1;
520     mlib_s32 a00_2, a01_2, a10_2, a11_2;
521     mlib_s32 a00_3, a01_3, a10_3, a11_3;
522     mlib_s32 pix0_0, pix1_0, res0;
523     mlib_s32 pix0_1, pix1_1, res1;
524     mlib_s32 pix0_2, pix1_2, res2;
525     mlib_s32 pix0_3, pix1_3, res3;
526 
527     CLIP(4);
528     dstLineEnd = (DTYPE *) dstData + 4 * xRight;
529 #if MLIB_SHIFT == 15
530     X = X >> 1;
531     Y = Y >> 1;
532 
533     if (warp_tbl != NULL) {
534       dX = (dX + 1) >> 1;
535       dY = (dY + 1) >> 1;
536     }
537 
538 #endif
539 
540     GET_POINTERS(4);
541     LOAD(0, 0, 4);
542     LOAD(1, 1, 5);
543     LOAD(2, 2, 6);
544     LOAD(3, 3, 7);
545 
546 #ifdef __SUNPRO_C
547 #pragma pipeloop(0)
548 #endif /* __SUNPRO_C */
549     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 4) {
550       COUNT(0);
551       COUNT(1);
552       COUNT(2);
553       COUNT(3);
554       GET_POINTERS(4);
555       LOAD(0, 0, 4);
556       LOAD(1, 1, 5);
557       LOAD(2, 2, 6);
558       LOAD(3, 3, 7);
559       dstPixelPtr[0] = (DTYPE) res0;
560       dstPixelPtr[1] = (DTYPE) res1;
561       dstPixelPtr[2] = (DTYPE) res2;
562       dstPixelPtr[3] = (DTYPE) res3;
563     }
564 
565     COUNT(0);
566     COUNT(1);
567     COUNT(2);
568     COUNT(3);
569     dstPixelPtr[0] = (DTYPE) res0;
570     dstPixelPtr[1] = (DTYPE) res1;
571     dstPixelPtr[2] = (DTYPE) res2;
572     dstPixelPtr[3] = (DTYPE) res3;
573   }
574 
575   return MLIB_SUCCESS;
576 }
577 
578 #endif /* #ifdef __sparc */
579 
580 /***************************************************************/
581