1 /*
   2  * Copyright (c) 1998, 2020, 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  *      Image affine transformation with Bicubic filtering
  30  * SYNOPSIS
  31  *      mlib_status mlib_ImageAffine_[u8|s16|u16]_?ch_bc(mlib_s32 *leftEdges,
  32  *                                                       mlib_s32 *rightEdges,
  33  *                                                       mlib_s32 *xStarts,
  34  *                                                       mlib_s32 *yStarts,
  35  *                                                       mlib_s32 *sides,
  36  *                                                       mlib_u8  *dstData,
  37  *                                                       mlib_u8  **lineAddr,
  38  *                                                       mlib_s32 dstYStride,
  39  *                                                       mlib_s32 is_affine,
  40  *                                                       mlib_s32 srcYStride,
  41  *                                                       mlib_filter filter)
  42  *
  43  *
  44  * ARGUMENTS
  45  *      leftEdges  array[dstHeight] of xLeft coordinates
  46  *      RightEdges array[dstHeight] of xRight coordinates
  47  *      xStarts    array[dstHeight] of xStart * 65536 coordinates
  48  *      yStarts    array[dstHeight] of yStart * 65536 coordinates
  49  *      sides      output array[4]. sides[0] is yStart, sides[1] is yFinish,
  50  *                 sides[2] is dx * 65536, sides[3] is dy * 65536
  51  *      dstData    pointer to the first pixel on (yStart - 1) line
  52  *      lineAddr   array[srcHeight] of pointers to the first pixel on
  53  *                 the corresponding lines
  54  *      dstYStride stride of destination image
  55  *      is_affine  indicator (Affine - GridWarp)
  56  *      srcYStride stride of source image
  57  *      filter     type of resampling filter
  58  *
  59  * DESCRIPTION
  60  *      The functions step along the lines from xLeft to xRight and apply
  61  *      the bicubic filtering.
  62  *
  63  */
  64 
  65 #include "mlib_ImageAffine.h"
  66 
  67 #define DTYPE  mlib_u8
  68 
  69 #define FUN_NAME(CHAN) mlib_ImageAffine_u8_##CHAN##_bc
  70 
  71 #define FILTER_BITS   8
  72 
  73 /***************************************************************/
  74 /* for x86, using integer multiplies is faster */
  75 
  76 #define SHIFT_X  12
  77 #define ROUND_X  0 /* (1 << (SHIFT_X - 1)) */
  78 
  79 #define SHIFT_Y  (14 + 14 - SHIFT_X)
  80 #define ROUND_Y  (1 << (SHIFT_Y - 1))
  81 
  82 /***************************************************************/
  83 /* Test for the presence of any "1" bit in bits
  84    8 to 31 of val. If present, then val is either
  85    negative or >255. If over/underflows of 8 bits
  86    are uncommon, then this technique can be a win,
  87    since only a single test, rather than two, is
  88    necessary to determine if clamping is needed.
  89    On the other hand, if over/underflows are common,
  90    it adds an extra test.
  91 */
  92 #define S32_TO_U8_SAT(DST)                                      \
  93   if (val0 & 0xffffff00) {                                      \
  94     if (val0 < MLIB_U8_MIN)                                     \
  95       DST = MLIB_U8_MIN;                                        \
  96     else                                                        \
  97       DST = MLIB_U8_MAX;                                        \
  98   } else {                                                      \
  99     DST = (mlib_u8)val0;                                        \
 100   }
 101 
 102 /***************************************************************/
 103 mlib_status FUN_NAME(1ch)(mlib_affine_param *param)
 104 {
 105   DECLAREVAR_BC();
 106   DTYPE *dstLineEnd;
 107   const mlib_s16 *mlib_filters_table;
 108 
 109   if (filter == MLIB_BICUBIC) {
 110     mlib_filters_table = (mlib_s16 *) mlib_filters_u8_bc;
 111   }
 112   else {
 113     mlib_filters_table = (mlib_s16 *) mlib_filters_u8_bc2;
 114   }
 115 
 116   for (j = yStart; j <= yFinish; j++) {
 117     mlib_s32 xf0, xf1, xf2, xf3;
 118     mlib_s32 yf0, yf1, yf2, yf3;
 119     mlib_s32 c0, c1, c2, c3, val0;
 120     mlib_s32 filterpos;
 121     mlib_s16 *fptr;
 122     mlib_u8 s0, s1, s2, s3;
 123 
 124     CLIP(1);
 125     dstLineEnd = (DTYPE *) dstData + xRight;
 126 
 127     filterpos = (X >> FILTER_SHIFT) & FILTER_MASK;
 128     fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 129 
 130     xf0 = fptr[0];
 131     xf1 = fptr[1];
 132     xf2 = fptr[2];
 133     xf3 = fptr[3];
 134 
 135     filterpos = (Y >> FILTER_SHIFT) & FILTER_MASK;
 136     fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 137 
 138     yf0 = fptr[0];
 139     yf1 = fptr[1];
 140     yf2 = fptr[2];
 141     yf3 = fptr[3];
 142 
 143     xSrc = (X >> MLIB_SHIFT) - 1;
 144     ySrc = (Y >> MLIB_SHIFT) - 1;
 145 
 146     srcPixelPtr = ((DTYPE **) lineAddr)[ySrc] + xSrc;
 147     s0 = srcPixelPtr[0];
 148     s1 = srcPixelPtr[1];
 149     s2 = srcPixelPtr[2];
 150     s3 = srcPixelPtr[3];
 151 
 152     for (; dstPixelPtr <= (dstLineEnd - 1); dstPixelPtr++) {
 153       X += dX;
 154       Y += dY;
 155 
 156       c0 = (s0 * xf0 + s1 * xf1 + s2 * xf2 + s3 * xf3 + ROUND_X) >> SHIFT_X;
 157       srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 158       c1 = (srcPixelPtr[0] * xf0 + srcPixelPtr[1] * xf1 +
 159             srcPixelPtr[2] * xf2 + srcPixelPtr[3] * xf3 + ROUND_X) >> SHIFT_X;
 160       srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 161       c2 = (srcPixelPtr[0] * xf0 + srcPixelPtr[1] * xf1 +
 162             srcPixelPtr[2] * xf2 + srcPixelPtr[3] * xf3 + ROUND_X) >> SHIFT_X;
 163       srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 164       c3 = (srcPixelPtr[0] * xf0 + srcPixelPtr[1] * xf1 +
 165             srcPixelPtr[2] * xf2 + srcPixelPtr[3] * xf3 + ROUND_X) >> SHIFT_X;
 166 
 167       filterpos = (X >> FILTER_SHIFT) & FILTER_MASK;
 168       fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 169 
 170       xf0 = fptr[0];
 171       xf1 = fptr[1];
 172       xf2 = fptr[2];
 173       xf3 = fptr[3];
 174 
 175       val0 = (c0 * yf0 + c1 * yf1 + c2 * yf2 + c3 * yf3 + ROUND_Y) >> SHIFT_Y;
 176 
 177       filterpos = (Y >> FILTER_SHIFT) & FILTER_MASK;
 178       fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 179 
 180       yf0 = fptr[0];
 181       yf1 = fptr[1];
 182       yf2 = fptr[2];
 183       yf3 = fptr[3];
 184 
 185       S32_TO_U8_SAT(dstPixelPtr[0]);
 186 
 187       xSrc = (X >> MLIB_SHIFT) - 1;
 188       ySrc = (Y >> MLIB_SHIFT) - 1;
 189 
 190       srcPixelPtr = ((DTYPE **) lineAddr)[ySrc] + xSrc;
 191       s0 = srcPixelPtr[0];
 192       s1 = srcPixelPtr[1];
 193       s2 = srcPixelPtr[2];
 194       s3 = srcPixelPtr[3];
 195     }
 196 
 197     c0 = (s0 * xf0 + s1 * xf1 + s2 * xf2 + s3 * xf3 + ROUND_X) >> SHIFT_X;
 198     srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 199     c1 = (srcPixelPtr[0] * xf0 + srcPixelPtr[1] * xf1 +
 200           srcPixelPtr[2] * xf2 + srcPixelPtr[3] * xf3 + ROUND_X) >> SHIFT_X;
 201     srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 202     c2 = (srcPixelPtr[0] * xf0 + srcPixelPtr[1] * xf1 +
 203           srcPixelPtr[2] * xf2 + srcPixelPtr[3] * xf3 + ROUND_X) >> SHIFT_X;
 204     srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 205     c3 = (srcPixelPtr[0] * xf0 + srcPixelPtr[1] * xf1 +
 206           srcPixelPtr[2] * xf2 + srcPixelPtr[3] * xf3 + ROUND_X) >> SHIFT_X;
 207 
 208     val0 = (c0 * yf0 + c1 * yf1 + c2 * yf2 + c3 * yf3 + ROUND_Y) >> SHIFT_Y;
 209 
 210     S32_TO_U8_SAT(dstPixelPtr[0]);
 211   }
 212 
 213   return MLIB_SUCCESS;
 214 }
 215 
 216 /***************************************************************/
 217 mlib_status FUN_NAME(2ch)(mlib_affine_param *param)
 218 {
 219   DECLAREVAR_BC();
 220   DTYPE *dstLineEnd;
 221   const mlib_s16 *mlib_filters_table;
 222 
 223   if (filter == MLIB_BICUBIC) {
 224     mlib_filters_table = (mlib_s16 *) mlib_filters_u8_bc;
 225   }
 226   else {
 227     mlib_filters_table = (mlib_s16 *) mlib_filters_u8_bc2;
 228   }
 229 
 230   for (j = yStart; j <= yFinish; j++) {
 231     mlib_s32 xf0, xf1, xf2, xf3;
 232     mlib_s32 yf0, yf1, yf2, yf3;
 233     mlib_s32 c0, c1, c2, c3, val0;
 234     mlib_s32 filterpos, k;
 235     mlib_s16 *fptr;
 236     mlib_u8 s0, s1, s2, s3;
 237 
 238     CLIP(2);
 239     dstLineEnd = (DTYPE *) dstData + 2 * xRight;
 240 
 241     for (k = 0; k < 2; k++) {
 242       mlib_s32 X1 = X;
 243       mlib_s32 Y1 = Y;
 244       DTYPE *dPtr = dstPixelPtr + k;
 245 
 246       filterpos = (X1 >> FILTER_SHIFT) & FILTER_MASK;
 247       fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 248 
 249       xf0 = fptr[0];
 250       xf1 = fptr[1];
 251       xf2 = fptr[2];
 252       xf3 = fptr[3];
 253 
 254       filterpos = (Y1 >> FILTER_SHIFT) & FILTER_MASK;
 255       fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 256 
 257       yf0 = fptr[0];
 258       yf1 = fptr[1];
 259       yf2 = fptr[2];
 260       yf3 = fptr[3];
 261 
 262       xSrc = (X1 >> MLIB_SHIFT) - 1;
 263       ySrc = (Y1 >> MLIB_SHIFT) - 1;
 264 
 265       srcPixelPtr = ((DTYPE **) lineAddr)[ySrc] + 2 * xSrc + k;
 266       s0 = srcPixelPtr[0];
 267       s1 = srcPixelPtr[2];
 268       s2 = srcPixelPtr[4];
 269       s3 = srcPixelPtr[6];
 270 
 271       for (; dPtr <= (dstLineEnd - 1); dPtr += 2) {
 272         X1 += dX;
 273         Y1 += dY;
 274 
 275         c0 = (s0 * xf0 + s1 * xf1 + s2 * xf2 + s3 * xf3 + ROUND_X) >> SHIFT_X;
 276         srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 277         c1 = (srcPixelPtr[0] * xf0 + srcPixelPtr[2] * xf1 +
 278               srcPixelPtr[4] * xf2 + srcPixelPtr[6] * xf3 + ROUND_X) >> SHIFT_X;
 279         srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 280         c2 = (srcPixelPtr[0] * xf0 + srcPixelPtr[2] * xf1 +
 281               srcPixelPtr[4] * xf2 + srcPixelPtr[6] * xf3 + ROUND_X) >> SHIFT_X;
 282         srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 283         c3 = (srcPixelPtr[0] * xf0 + srcPixelPtr[2] * xf1 +
 284               srcPixelPtr[4] * xf2 + srcPixelPtr[6] * xf3 + ROUND_X) >> SHIFT_X;
 285 
 286         filterpos = (X1 >> FILTER_SHIFT) & FILTER_MASK;
 287         fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 288 
 289         xf0 = fptr[0];
 290         xf1 = fptr[1];
 291         xf2 = fptr[2];
 292         xf3 = fptr[3];
 293 
 294         val0 = (c0 * yf0 + c1 * yf1 + c2 * yf2 + c3 * yf3 + ROUND_Y) >> SHIFT_Y;
 295 
 296         filterpos = (Y1 >> FILTER_SHIFT) & FILTER_MASK;
 297         fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 298 
 299         yf0 = fptr[0];
 300         yf1 = fptr[1];
 301         yf2 = fptr[2];
 302         yf3 = fptr[3];
 303 
 304         S32_TO_U8_SAT(dPtr[0]);
 305 
 306         xSrc = (X1 >> MLIB_SHIFT) - 1;
 307         ySrc = (Y1 >> MLIB_SHIFT) - 1;
 308 
 309         srcPixelPtr = ((DTYPE **) lineAddr)[ySrc] + 2 * xSrc + k;
 310         s0 = srcPixelPtr[0];
 311         s1 = srcPixelPtr[2];
 312         s2 = srcPixelPtr[4];
 313         s3 = srcPixelPtr[6];
 314       }
 315 
 316       c0 = (s0 * xf0 + s1 * xf1 + s2 * xf2 + s3 * xf3 + ROUND_X) >> SHIFT_X;
 317       srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 318       c1 = (srcPixelPtr[0] * xf0 + srcPixelPtr[2] * xf1 +
 319             srcPixelPtr[4] * xf2 + srcPixelPtr[6] * xf3 + ROUND_X) >> SHIFT_X;
 320       srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 321       c2 = (srcPixelPtr[0] * xf0 + srcPixelPtr[2] * xf1 +
 322             srcPixelPtr[4] * xf2 + srcPixelPtr[6] * xf3 + ROUND_X) >> SHIFT_X;
 323       srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 324       c3 = (srcPixelPtr[0] * xf0 + srcPixelPtr[2] * xf1 +
 325             srcPixelPtr[4] * xf2 + srcPixelPtr[6] * xf3 + ROUND_X) >> SHIFT_X;
 326 
 327       val0 = (c0 * yf0 + c1 * yf1 + c2 * yf2 + c3 * yf3 + ROUND_Y) >> SHIFT_Y;
 328 
 329       S32_TO_U8_SAT(dPtr[0]);
 330     }
 331   }
 332 
 333   return MLIB_SUCCESS;
 334 }
 335 
 336 /***************************************************************/
 337 mlib_status FUN_NAME(3ch)(mlib_affine_param *param)
 338 {
 339   DECLAREVAR_BC();
 340   DTYPE *dstLineEnd;
 341   const mlib_s16 *mlib_filters_table;
 342 
 343   if (filter == MLIB_BICUBIC) {
 344     mlib_filters_table = (mlib_s16 *) mlib_filters_u8_bc;
 345   }
 346   else {
 347     mlib_filters_table = (mlib_s16 *) mlib_filters_u8_bc2;
 348   }
 349 
 350   for (j = yStart; j <= yFinish; j++) {
 351     mlib_s32 xf0, xf1, xf2, xf3;
 352     mlib_s32 yf0, yf1, yf2, yf3;
 353     mlib_s32 c0, c1, c2, c3, val0;
 354     mlib_s32 filterpos, k;
 355     mlib_s16 *fptr;
 356     mlib_u8 s0, s1, s2, s3;
 357 
 358     CLIP(3);
 359     dstLineEnd = (DTYPE *) dstData + 3 * xRight;
 360 
 361     for (k = 0; k < 3; k++) {
 362       mlib_s32 X1 = X;
 363       mlib_s32 Y1 = Y;
 364       DTYPE *dPtr = dstPixelPtr + k;
 365 
 366       filterpos = (X1 >> FILTER_SHIFT) & FILTER_MASK;
 367       fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 368 
 369       xf0 = fptr[0];
 370       xf1 = fptr[1];
 371       xf2 = fptr[2];
 372       xf3 = fptr[3];
 373 
 374       filterpos = (Y1 >> FILTER_SHIFT) & FILTER_MASK;
 375       fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 376 
 377       yf0 = fptr[0];
 378       yf1 = fptr[1];
 379       yf2 = fptr[2];
 380       yf3 = fptr[3];
 381 
 382       xSrc = (X1 >> MLIB_SHIFT) - 1;
 383       ySrc = (Y1 >> MLIB_SHIFT) - 1;
 384 
 385       srcPixelPtr = ((DTYPE **) lineAddr)[ySrc] + 3 * xSrc + k;
 386       s0 = srcPixelPtr[0];
 387       s1 = srcPixelPtr[3];
 388       s2 = srcPixelPtr[6];
 389       s3 = srcPixelPtr[9];
 390 
 391       for (; dPtr <= (dstLineEnd - 1); dPtr += 3) {
 392         X1 += dX;
 393         Y1 += dY;
 394 
 395         c0 = (s0 * xf0 + s1 * xf1 + s2 * xf2 + s3 * xf3 + ROUND_X) >> SHIFT_X;
 396         srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 397         c1 = (srcPixelPtr[0] * xf0 + srcPixelPtr[3] * xf1 +
 398               srcPixelPtr[6] * xf2 + srcPixelPtr[9] * xf3 + ROUND_X) >> SHIFT_X;
 399         srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 400         c2 = (srcPixelPtr[0] * xf0 + srcPixelPtr[3] * xf1 +
 401               srcPixelPtr[6] * xf2 + srcPixelPtr[9] * xf3 + ROUND_X) >> SHIFT_X;
 402         srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 403         c3 = (srcPixelPtr[0] * xf0 + srcPixelPtr[3] * xf1 +
 404               srcPixelPtr[6] * xf2 + srcPixelPtr[9] * xf3 + ROUND_X) >> SHIFT_X;
 405 
 406         filterpos = (X1 >> FILTER_SHIFT) & FILTER_MASK;
 407         fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 408 
 409         xf0 = fptr[0];
 410         xf1 = fptr[1];
 411         xf2 = fptr[2];
 412         xf3 = fptr[3];
 413 
 414         val0 = (c0 * yf0 + c1 * yf1 + c2 * yf2 + c3 * yf3 + ROUND_Y) >> SHIFT_Y;
 415 
 416         filterpos = (Y1 >> FILTER_SHIFT) & FILTER_MASK;
 417         fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 418 
 419         yf0 = fptr[0];
 420         yf1 = fptr[1];
 421         yf2 = fptr[2];
 422         yf3 = fptr[3];
 423 
 424         S32_TO_U8_SAT(dPtr[0]);
 425 
 426         xSrc = (X1 >> MLIB_SHIFT) - 1;
 427         ySrc = (Y1 >> MLIB_SHIFT) - 1;
 428 
 429         srcPixelPtr = ((DTYPE **) lineAddr)[ySrc] + 3 * xSrc + k;
 430         s0 = srcPixelPtr[0];
 431         s1 = srcPixelPtr[3];
 432         s2 = srcPixelPtr[6];
 433         s3 = srcPixelPtr[9];
 434       }
 435 
 436       c0 = (s0 * xf0 + s1 * xf1 + s2 * xf2 + s3 * xf3 + ROUND_X) >> SHIFT_X;
 437       srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 438       c1 = (srcPixelPtr[0] * xf0 + srcPixelPtr[3] * xf1 +
 439             srcPixelPtr[6] * xf2 + srcPixelPtr[9] * xf3 + ROUND_X) >> SHIFT_X;
 440       srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 441       c2 = (srcPixelPtr[0] * xf0 + srcPixelPtr[3] * xf1 +
 442             srcPixelPtr[6] * xf2 + srcPixelPtr[9] * xf3 + ROUND_X) >> SHIFT_X;
 443       srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 444       c3 = (srcPixelPtr[0] * xf0 + srcPixelPtr[3] * xf1 +
 445             srcPixelPtr[6] * xf2 + srcPixelPtr[9] * xf3 + ROUND_X) >> SHIFT_X;
 446 
 447       val0 = (c0 * yf0 + c1 * yf1 + c2 * yf2 + c3 * yf3 + ROUND_Y) >> SHIFT_Y;
 448 
 449       S32_TO_U8_SAT(dPtr[0]);
 450     }
 451   }
 452 
 453   return MLIB_SUCCESS;
 454 }
 455 
 456 /***************************************************************/
 457 mlib_status FUN_NAME(4ch)(mlib_affine_param *param)
 458 {
 459   DECLAREVAR_BC();
 460   DTYPE *dstLineEnd;
 461   const mlib_s16 *mlib_filters_table;
 462 
 463   if (filter == MLIB_BICUBIC) {
 464     mlib_filters_table = (mlib_s16 *) mlib_filters_u8_bc;
 465   }
 466   else {
 467     mlib_filters_table = (mlib_s16 *) mlib_filters_u8_bc2;
 468   }
 469 
 470   for (j = yStart; j <= yFinish; j++) {
 471     mlib_s32 xf0, xf1, xf2, xf3;
 472     mlib_s32 yf0, yf1, yf2, yf3;
 473     mlib_s32 c0, c1, c2, c3, val0;
 474     mlib_s32 filterpos, k;
 475     mlib_s16 *fptr;
 476     mlib_u8 s0, s1, s2, s3;
 477 
 478     CLIP(4);
 479     dstLineEnd = (DTYPE *) dstData + 4 * xRight;
 480 
 481     for (k = 0; k < 4; k++) {
 482       mlib_s32 X1 = X;
 483       mlib_s32 Y1 = Y;
 484       DTYPE *dPtr = dstPixelPtr + k;
 485 
 486       filterpos = (X1 >> FILTER_SHIFT) & FILTER_MASK;
 487       fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 488 
 489       xf0 = fptr[0];
 490       xf1 = fptr[1];
 491       xf2 = fptr[2];
 492       xf3 = fptr[3];
 493 
 494       filterpos = (Y1 >> FILTER_SHIFT) & FILTER_MASK;
 495       fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 496 
 497       yf0 = fptr[0];
 498       yf1 = fptr[1];
 499       yf2 = fptr[2];
 500       yf3 = fptr[3];
 501 
 502       xSrc = (X1 >> MLIB_SHIFT) - 1;
 503       ySrc = (Y1 >> MLIB_SHIFT) - 1;
 504 
 505       srcPixelPtr = ((DTYPE **) lineAddr)[ySrc] + 4 * xSrc + k;
 506       s0 = srcPixelPtr[0];
 507       s1 = srcPixelPtr[4];
 508       s2 = srcPixelPtr[8];
 509       s3 = srcPixelPtr[12];
 510 
 511       for (; dPtr <= (dstLineEnd - 1); dPtr += 4) {
 512         X1 += dX;
 513         Y1 += dY;
 514 
 515         c0 = (s0 * xf0 + s1 * xf1 + s2 * xf2 + s3 * xf3 + ROUND_X) >> SHIFT_X;
 516         srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 517         c1 = (srcPixelPtr[0] * xf0 + srcPixelPtr[4] * xf1 +
 518               srcPixelPtr[8] * xf2 + srcPixelPtr[12] * xf3 + ROUND_X) >> SHIFT_X;
 519         srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 520         c2 = (srcPixelPtr[0] * xf0 + srcPixelPtr[4] * xf1 +
 521               srcPixelPtr[8] * xf2 + srcPixelPtr[12] * xf3 + ROUND_X) >> SHIFT_X;
 522         srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 523         c3 = (srcPixelPtr[0] * xf0 + srcPixelPtr[4] * xf1 +
 524               srcPixelPtr[8] * xf2 + srcPixelPtr[12] * xf3 + ROUND_X) >> SHIFT_X;
 525 
 526         filterpos = (X1 >> FILTER_SHIFT) & FILTER_MASK;
 527         fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 528 
 529         xf0 = fptr[0];
 530         xf1 = fptr[1];
 531         xf2 = fptr[2];
 532         xf3 = fptr[3];
 533 
 534         val0 = (c0 * yf0 + c1 * yf1 + c2 * yf2 + c3 * yf3 + ROUND_Y) >> SHIFT_Y;
 535 
 536         filterpos = (Y1 >> FILTER_SHIFT) & FILTER_MASK;
 537         fptr = (mlib_s16 *) ((mlib_u8 *) mlib_filters_table + filterpos);
 538 
 539         yf0 = fptr[0];
 540         yf1 = fptr[1];
 541         yf2 = fptr[2];
 542         yf3 = fptr[3];
 543 
 544         S32_TO_U8_SAT(dPtr[0]);
 545 
 546         xSrc = (X1 >> MLIB_SHIFT) - 1;
 547         ySrc = (Y1 >> MLIB_SHIFT) - 1;
 548 
 549         srcPixelPtr = ((DTYPE **) lineAddr)[ySrc] + 4 * xSrc + k;
 550         s0 = srcPixelPtr[0];
 551         s1 = srcPixelPtr[4];
 552         s2 = srcPixelPtr[8];
 553         s3 = srcPixelPtr[12];
 554       }
 555 
 556       c0 = (s0 * xf0 + s1 * xf1 + s2 * xf2 + s3 * xf3 + ROUND_X) >> SHIFT_X;
 557       srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 558       c1 = (srcPixelPtr[0] * xf0 + srcPixelPtr[4] * xf1 +
 559             srcPixelPtr[8] * xf2 + srcPixelPtr[12] * xf3 + ROUND_X) >> SHIFT_X;
 560       srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 561       c2 = (srcPixelPtr[0] * xf0 + srcPixelPtr[4] * xf1 +
 562             srcPixelPtr[8] * xf2 + srcPixelPtr[12] * xf3 + ROUND_X) >> SHIFT_X;
 563       srcPixelPtr = (DTYPE *) ((mlib_addr) srcPixelPtr + srcYStride);
 564       c3 = (srcPixelPtr[0] * xf0 + srcPixelPtr[4] * xf1 +
 565             srcPixelPtr[8] * xf2 + srcPixelPtr[12] * xf3 + ROUND_X) >> SHIFT_X;
 566 
 567       val0 = (c0 * yf0 + c1 * yf1 + c2 * yf2 + c3 * yf3 + ROUND_Y) >> SHIFT_Y;
 568 
 569       S32_TO_U8_SAT(dPtr[0]);
 570     }
 571   }
 572 
 573   return MLIB_SUCCESS;
 574 }
 575 
 576 /***************************************************************/