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 /* for x86, using integer multiplies is faster */
  81 
  82 /***************************************************************/
  83 /* for SHORT/USHORT decrease MLIB_SHIFT due to overflow in multiplies like fdy * (a10 - a00) */
  84 #undef  MLIB_SHIFT
  85 #define MLIB_SHIFT  15
  86 
  87 #define MLIB_ROUND   (1 << (MLIB_SHIFT - 1))
  88 
  89 /***************************************************************/
  90 #define GET_POINTERS(ind)                                        \
  91   fdx = X & MLIB_MASK;                                           \
  92   fdy = Y & MLIB_MASK;                                           \
  93   ySrc = MLIB_POINTER_SHIFT(Y);                                  \
  94   xSrc = X >> MLIB_SHIFT;                                        \
  95   srcPixelPtr = MLIB_POINTER_GET(lineAddr, ySrc) + ind * xSrc;   \
  96   srcPixelPtr2 = (DTYPE *)((mlib_u8 *)srcPixelPtr + srcYStride); \
  97   X += dX;                                                       \
  98   Y += dY
  99 
 100 /***************************************************************/
 101 #define COUNT(ind)                                                                       \
 102   pix0_##ind = a00_##ind + ((fdy * (a10_##ind - a00_##ind) + MLIB_ROUND) >> MLIB_SHIFT); \
 103   pix1_##ind = a01_##ind + ((fdy * (a11_##ind - a01_##ind) + MLIB_ROUND) >> MLIB_SHIFT); \
 104   res##ind = pix0_##ind + ((fdx * (pix1_##ind - pix0_##ind) + MLIB_ROUND) >> MLIB_SHIFT)
 105 
 106 /***************************************************************/
 107 #define LOAD(ind, ind1, ind2)                                   \
 108   a00_##ind = srcPixelPtr[ind1];                                \
 109   a01_##ind = srcPixelPtr[ind2];                                \
 110   a10_##ind = srcPixelPtr2[ind1];                               \
 111   a11_##ind = srcPixelPtr2[ind2]
 112 
 113 /***************************************************************/
 114 mlib_status FUN_NAME(1ch)(mlib_affine_param *param)
 115 {
 116   DECLAREVAR_BL();
 117   DTYPE *dstLineEnd;
 118   DTYPE *srcPixelPtr2;
 119 
 120 #if MLIB_SHIFT == 15
 121   dX = (dX + 1) >> 1;
 122   dY = (dY + 1) >> 1;
 123 #endif
 124 
 125   for (j = yStart; j <= yFinish; j++) {
 126     mlib_s32 fdx, fdy;
 127     mlib_s32 a00_0, a01_0, a10_0, a11_0;
 128     mlib_s32 pix0_0, pix1_0, res0;
 129 
 130     CLIP(1);
 131     dstLineEnd = (DTYPE *) dstData + xRight;
 132 #if MLIB_SHIFT == 15
 133     X = X >> 1;
 134     Y = Y >> 1;
 135 
 136     if (warp_tbl != NULL) {
 137       dX = (dX + 1) >> 1;
 138       dY = (dY + 1) >> 1;
 139     }
 140 
 141 #endif
 142 
 143     GET_POINTERS(1);
 144     LOAD(0, 0, 1);
 145 
 146 #ifdef __SUNPRO_C
 147 #pragma pipeloop(0)
 148 #endif /* __SUNPRO_C */
 149     for (; dstPixelPtr < dstLineEnd; dstPixelPtr++) {
 150       COUNT(0);
 151       GET_POINTERS(1);
 152       LOAD(0, 0, 1);
 153       dstPixelPtr[0] = (DTYPE) res0;
 154     }
 155 
 156     COUNT(0);
 157     dstPixelPtr[0] = (DTYPE) res0;
 158   }
 159 
 160   return MLIB_SUCCESS;
 161 }
 162 
 163 /***************************************************************/
 164 mlib_status FUN_NAME(2ch)(mlib_affine_param *param)
 165 {
 166   DECLAREVAR_BL();
 167   DTYPE *dstLineEnd;
 168   DTYPE *srcPixelPtr2;
 169 
 170 #if MLIB_SHIFT == 15
 171   dX = (dX + 1) >> 1;
 172   dY = (dY + 1) >> 1;
 173 #endif
 174 
 175   for (j = yStart; j <= yFinish; j++) {
 176     mlib_s32 fdx, fdy;
 177     mlib_s32 a00_0, a01_0, a10_0, a11_0;
 178     mlib_s32 a00_1, a01_1, a10_1, a11_1;
 179     mlib_s32 pix0_0, pix1_0, res0;
 180     mlib_s32 pix0_1, pix1_1, res1;
 181 
 182     CLIP(2);
 183     dstLineEnd = (DTYPE *) dstData + 2 * xRight;
 184 #if MLIB_SHIFT == 15
 185     X = X >> 1;
 186     Y = Y >> 1;
 187 
 188     if (warp_tbl != NULL) {
 189       dX = (dX + 1) >> 1;
 190       dY = (dY + 1) >> 1;
 191     }
 192 
 193 #endif
 194 
 195     GET_POINTERS(2);
 196     LOAD(0, 0, 2);
 197     LOAD(1, 1, 3);
 198 
 199 #ifdef __SUNPRO_C
 200 #pragma pipeloop(0)
 201 #endif /* __SUNPRO_C */
 202     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 2) {
 203       COUNT(0);
 204       COUNT(1);
 205       GET_POINTERS(2);
 206       LOAD(0, 0, 2);
 207       LOAD(1, 1, 3);
 208       dstPixelPtr[0] = (DTYPE) res0;
 209       dstPixelPtr[1] = (DTYPE) res1;
 210     }
 211 
 212     COUNT(0);
 213     COUNT(1);
 214     dstPixelPtr[0] = (DTYPE) res0;
 215     dstPixelPtr[1] = (DTYPE) res1;
 216   }
 217 
 218   return MLIB_SUCCESS;
 219 }
 220 
 221 /***************************************************************/
 222 mlib_status FUN_NAME(3ch)(mlib_affine_param *param)
 223 {
 224   DECLAREVAR_BL();
 225   DTYPE *dstLineEnd;
 226   DTYPE *srcPixelPtr2;
 227 
 228 #if MLIB_SHIFT == 15
 229   dX = (dX + 1) >> 1;
 230   dY = (dY + 1) >> 1;
 231 #endif
 232 
 233   for (j = yStart; j <= yFinish; j++) {
 234     mlib_s32 fdx, fdy;
 235     mlib_s32 a00_0, a01_0, a10_0, a11_0;
 236     mlib_s32 a00_1, a01_1, a10_1, a11_1;
 237     mlib_s32 a00_2, a01_2, a10_2, a11_2;
 238     mlib_s32 pix0_0, pix1_0, res0;
 239     mlib_s32 pix0_1, pix1_1, res1;
 240     mlib_s32 pix0_2, pix1_2, res2;
 241 
 242     CLIP(3);
 243     dstLineEnd = (DTYPE *) dstData + 3 * xRight;
 244 #if MLIB_SHIFT == 15
 245     X = X >> 1;
 246     Y = Y >> 1;
 247 
 248     if (warp_tbl != NULL) {
 249       dX = (dX + 1) >> 1;
 250       dY = (dY + 1) >> 1;
 251     }
 252 
 253 #endif
 254 
 255     GET_POINTERS(3);
 256     LOAD(0, 0, 3);
 257     LOAD(1, 1, 4);
 258     LOAD(2, 2, 5);
 259 
 260 #ifdef __SUNPRO_C
 261 #pragma pipeloop(0)
 262 #endif /* __SUNPRO_C */
 263     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 3) {
 264       COUNT(0);
 265       COUNT(1);
 266       COUNT(2);
 267       GET_POINTERS(3);
 268       LOAD(0, 0, 3);
 269       LOAD(1, 1, 4);
 270       LOAD(2, 2, 5);
 271       dstPixelPtr[0] = (DTYPE) res0;
 272       dstPixelPtr[1] = (DTYPE) res1;
 273       dstPixelPtr[2] = (DTYPE) res2;
 274     }
 275 
 276     COUNT(0);
 277     COUNT(1);
 278     COUNT(2);
 279     dstPixelPtr[0] = (DTYPE) res0;
 280     dstPixelPtr[1] = (DTYPE) res1;
 281     dstPixelPtr[2] = (DTYPE) res2;
 282   }
 283 
 284   return MLIB_SUCCESS;
 285 }
 286 
 287 /***************************************************************/
 288 mlib_status FUN_NAME(4ch)(mlib_affine_param *param)
 289 {
 290   DECLAREVAR_BL();
 291   DTYPE *dstLineEnd;
 292   DTYPE *srcPixelPtr2;
 293 
 294 #if MLIB_SHIFT == 15
 295   dX = (dX + 1) >> 1;
 296   dY = (dY + 1) >> 1;
 297 #endif
 298 
 299   for (j = yStart; j <= yFinish; j++) {
 300     mlib_s32 fdx, fdy;
 301     mlib_s32 a00_0, a01_0, a10_0, a11_0;
 302     mlib_s32 a00_1, a01_1, a10_1, a11_1;
 303     mlib_s32 a00_2, a01_2, a10_2, a11_2;
 304     mlib_s32 a00_3, a01_3, a10_3, a11_3;
 305     mlib_s32 pix0_0, pix1_0, res0;
 306     mlib_s32 pix0_1, pix1_1, res1;
 307     mlib_s32 pix0_2, pix1_2, res2;
 308     mlib_s32 pix0_3, pix1_3, res3;
 309 
 310     CLIP(4);
 311     dstLineEnd = (DTYPE *) dstData + 4 * xRight;
 312 #if MLIB_SHIFT == 15
 313     X = X >> 1;
 314     Y = Y >> 1;
 315 
 316     if (warp_tbl != NULL) {
 317       dX = (dX + 1) >> 1;
 318       dY = (dY + 1) >> 1;
 319     }
 320 
 321 #endif
 322 
 323     GET_POINTERS(4);
 324     LOAD(0, 0, 4);
 325     LOAD(1, 1, 5);
 326     LOAD(2, 2, 6);
 327     LOAD(3, 3, 7);
 328 
 329 #ifdef __SUNPRO_C
 330 #pragma pipeloop(0)
 331 #endif /* __SUNPRO_C */
 332     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 4) {
 333       COUNT(0);
 334       COUNT(1);
 335       COUNT(2);
 336       COUNT(3);
 337       GET_POINTERS(4);
 338       LOAD(0, 0, 4);
 339       LOAD(1, 1, 5);
 340       LOAD(2, 2, 6);
 341       LOAD(3, 3, 7);
 342       dstPixelPtr[0] = (DTYPE) res0;
 343       dstPixelPtr[1] = (DTYPE) res1;
 344       dstPixelPtr[2] = (DTYPE) res2;
 345       dstPixelPtr[3] = (DTYPE) res3;
 346     }
 347 
 348     COUNT(0);
 349     COUNT(1);
 350     COUNT(2);
 351     COUNT(3);
 352     dstPixelPtr[0] = (DTYPE) res0;
 353     dstPixelPtr[1] = (DTYPE) res1;
 354     dstPixelPtr[2] = (DTYPE) res2;
 355     dstPixelPtr[3] = (DTYPE) res3;
 356   }
 357 
 358   return MLIB_SUCCESS;
 359 }
 360 
 361 /***************************************************************/