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/***************************************************************/
105mlib_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/***************************************************************/
141mlib_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/***************************************************************/
185mlib_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/***************************************************************/
237mlib_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/***************************************************************/
331mlib_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/***************************************************************/
381mlib_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/***************************************************************/
439mlib_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/***************************************************************/
505mlib_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