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