1 /*
   2  * Copyright (c) 1997, 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_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 #ifdef __SUNPRO_C
 144 #pragma pipeloop(0)
 145 #endif /* __SUNPRO_C */
 146     for (; dstPixelPtr < dstLineEnd; dstPixelPtr++) {
 147       COUNT(0);
 148       GET_POINTERS(1);
 149       LOAD(0, 0, 1);
 150       dstPixelPtr[0] = (DTYPE) res0;
 151     }
 152 
 153     COUNT(0);
 154     dstPixelPtr[0] = (DTYPE) res0;
 155   }
 156 
 157   return MLIB_SUCCESS;
 158 }
 159 
 160 /***************************************************************/
 161 mlib_status FUN_NAME(2ch)(mlib_affine_param *param)
 162 {
 163   DECLAREVAR_BL();
 164   DTYPE *dstLineEnd;
 165   DTYPE *srcPixelPtr2;
 166 
 167 #if MLIB_SHIFT == 15
 168   dX = (dX + 1) >> 1;
 169   dY = (dY + 1) >> 1;
 170 #endif /* MLIB_SHIFT == 15 */
 171 
 172   for (j = yStart; j <= yFinish; j++) {
 173     mlib_s32 fdx, fdy;
 174     mlib_s32 a00_0, a01_0, a10_0, a11_0;
 175     mlib_s32 a00_1, a01_1, a10_1, a11_1;
 176     mlib_s32 pix0_0, pix1_0, res0;
 177     mlib_s32 pix0_1, pix1_1, res1;
 178 
 179     CLIP(2);
 180     dstLineEnd = (DTYPE *) dstData + 2 * xRight;
 181 #if MLIB_SHIFT == 15
 182     X = X >> 1;
 183     Y = Y >> 1;
 184 #endif /* MLIB_SHIFT == 15 */
 185 
 186     GET_POINTERS(2);
 187     LOAD(0, 0, 2);
 188     LOAD(1, 1, 3);
 189 
 190 #ifdef __SUNPRO_C
 191 #pragma pipeloop(0)
 192 #endif /* __SUNPRO_C */
 193     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 2) {
 194       COUNT(0);
 195       COUNT(1);
 196       GET_POINTERS(2);
 197       LOAD(0, 0, 2);
 198       LOAD(1, 1, 3);
 199       dstPixelPtr[0] = (DTYPE) res0;
 200       dstPixelPtr[1] = (DTYPE) res1;
 201     }
 202 
 203     COUNT(0);
 204     COUNT(1);
 205     dstPixelPtr[0] = (DTYPE) res0;
 206     dstPixelPtr[1] = (DTYPE) res1;
 207   }
 208 
 209   return MLIB_SUCCESS;
 210 }
 211 
 212 /***************************************************************/
 213 mlib_status FUN_NAME(3ch)(mlib_affine_param *param)
 214 {
 215   DECLAREVAR_BL();
 216   DTYPE *dstLineEnd;
 217   DTYPE *srcPixelPtr2;
 218 
 219 #if MLIB_SHIFT == 15
 220   dX = (dX + 1) >> 1;
 221   dY = (dY + 1) >> 1;
 222 #endif /* MLIB_SHIFT == 15 */
 223 
 224   for (j = yStart; j <= yFinish; j++) {
 225     mlib_s32 fdx, fdy;
 226     mlib_s32 a00_0, a01_0, a10_0, a11_0;
 227     mlib_s32 a00_1, a01_1, a10_1, a11_1;
 228     mlib_s32 a00_2, a01_2, a10_2, a11_2;
 229     mlib_s32 pix0_0, pix1_0, res0;
 230     mlib_s32 pix0_1, pix1_1, res1;
 231     mlib_s32 pix0_2, pix1_2, res2;
 232 
 233     CLIP(3);
 234     dstLineEnd = (DTYPE *) dstData + 3 * xRight;
 235 #if MLIB_SHIFT == 15
 236     X = X >> 1;
 237     Y = Y >> 1;
 238 #endif /* MLIB_SHIFT == 15 */
 239 
 240     GET_POINTERS(3);
 241     LOAD(0, 0, 3);
 242     LOAD(1, 1, 4);
 243     LOAD(2, 2, 5);
 244 
 245 #ifdef __SUNPRO_C
 246 #pragma pipeloop(0)
 247 #endif /* __SUNPRO_C */
 248     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 3) {
 249       COUNT(0);
 250       COUNT(1);
 251       COUNT(2);
 252       GET_POINTERS(3);
 253       LOAD(0, 0, 3);
 254       LOAD(1, 1, 4);
 255       LOAD(2, 2, 5);
 256       dstPixelPtr[0] = (DTYPE) res0;
 257       dstPixelPtr[1] = (DTYPE) res1;
 258       dstPixelPtr[2] = (DTYPE) res2;
 259     }
 260 
 261     COUNT(0);
 262     COUNT(1);
 263     COUNT(2);
 264     dstPixelPtr[0] = (DTYPE) res0;
 265     dstPixelPtr[1] = (DTYPE) res1;
 266     dstPixelPtr[2] = (DTYPE) res2;
 267   }
 268 
 269   return MLIB_SUCCESS;
 270 }
 271 
 272 /***************************************************************/
 273 mlib_status FUN_NAME(4ch)(mlib_affine_param *param)
 274 {
 275   DECLAREVAR_BL();
 276   DTYPE *dstLineEnd;
 277   DTYPE *srcPixelPtr2;
 278 
 279 #if MLIB_SHIFT == 15
 280   dX = (dX + 1) >> 1;
 281   dY = (dY + 1) >> 1;
 282 #endif /* MLIB_SHIFT == 15 */
 283 
 284   for (j = yStart; j <= yFinish; j++) {
 285     mlib_s32 fdx, fdy;
 286     mlib_s32 a00_0, a01_0, a10_0, a11_0;
 287     mlib_s32 a00_1, a01_1, a10_1, a11_1;
 288     mlib_s32 a00_2, a01_2, a10_2, a11_2;
 289     mlib_s32 a00_3, a01_3, a10_3, a11_3;
 290     mlib_s32 pix0_0, pix1_0, res0;
 291     mlib_s32 pix0_1, pix1_1, res1;
 292     mlib_s32 pix0_2, pix1_2, res2;
 293     mlib_s32 pix0_3, pix1_3, res3;
 294 
 295     CLIP(4);
 296     dstLineEnd = (DTYPE *) dstData + 4 * xRight;
 297 #if MLIB_SHIFT == 15
 298     X = X >> 1;
 299     Y = Y >> 1;
 300 #endif /* MLIB_SHIFT == 15 */
 301 
 302     GET_POINTERS(4);
 303     LOAD(0, 0, 4);
 304     LOAD(1, 1, 5);
 305     LOAD(2, 2, 6);
 306     LOAD(3, 3, 7);
 307 
 308 #ifdef __SUNPRO_C
 309 #pragma pipeloop(0)
 310 #endif /* __SUNPRO_C */
 311     for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 4) {
 312       COUNT(0);
 313       COUNT(1);
 314       COUNT(2);
 315       COUNT(3);
 316       GET_POINTERS(4);
 317       LOAD(0, 0, 4);
 318       LOAD(1, 1, 5);
 319       LOAD(2, 2, 6);
 320       LOAD(3, 3, 7);
 321       dstPixelPtr[0] = (DTYPE) res0;
 322       dstPixelPtr[1] = (DTYPE) res1;
 323       dstPixelPtr[2] = (DTYPE) res2;
 324       dstPixelPtr[3] = (DTYPE) res3;
 325     }
 326 
 327     COUNT(0);
 328     COUNT(1);
 329     COUNT(2);
 330     COUNT(3);
 331     dstPixelPtr[0] = (DTYPE) res0;
 332     dstPixelPtr[1] = (DTYPE) res1;
 333     dstPixelPtr[2] = (DTYPE) res2;
 334     dstPixelPtr[3] = (DTYPE) res3;
 335   }
 336 
 337   return MLIB_SUCCESS;
 338 }
 339 
 340 /***************************************************************/