1 /*
   2  * Copyright (c) 1998, 2011, 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_ImageAffineEdgeZero - implementation of MLIB_EDGE_DST_FILL_ZERO
  30  *                                 edge condition
  31  *      mlib_ImageAffineEdgeNearest - implementation of MLIB_EDGE_OP_NEAREST
  32  *                                    edge condition
  33  *      void mlib_ImageAffineEdgeExtend_BL - implementation of MLIB_EDGE_SRC_EXTEND
  34  *                                           edge condition for MLIB_BILINEAR filter
  35  *      void mlib_ImageAffineEdgeExtend_BC - implementation of MLIB_EDGE_SRC_EXTEND
  36  *                                           edge condition for MLIB_BICUBIC filter
  37  *      void mlib_ImageAffineEdgeExtend_BC2 - implementation of MLIB_EDGE_SRC_EXTEND
  38  *                                            edge condition for MLIB_BICUBIC2 filter
  39  *
  40  * DESCRIPTION
  41  *      mlib_ImageAffineEdgeZero:
  42  *         This function fills the edge pixels (i.e. thouse one which can not
  43  *         be interpolated with given resampling filter because their prototypes
  44  *         in the source image lie too close to the border) in the destination
  45  *         image with zeroes.
  46  *
  47  *      mlib_ImageAffineEdgeNearest:
  48  *         This function fills the edge pixels (i.e. thouse one which can not
  49  *         be interpolated with given resampling filter because their prototypes
  50  *         in the source image lie too close to the border) in the destination
  51  *         image according to the nearest neighbour interpolation.
  52  *
  53  *      mlib_ImageAffineEdgeExtend_BL:
  54  *         This function fills the edge pixels (i.e. thouse one which can not
  55  *         be interpolated with given resampling filter because their prototypes
  56  *         in the source image lie too close to the border) in the destination
  57  *         image according to the bilinear interpolation with border pixels extend
  58  *         of source image.
  59  *
  60  *      mlib_ImageAffineEdgeExtend_BC:
  61  *         This function fills the edge pixels (i.e. thouse one which can not
  62  *         be interpolated with given resampling filter because their prototypes
  63  *         in the source image lie too close to the border) in the destination
  64  *         image according to the bicubic interpolation with border pixels extend
  65  *         of source image.
  66  *
  67  *      mlib_ImageAffineEdgeExtend_BC2:
  68  *         This function fills the edge pixels (i.e. thouse one which can not
  69  *         be interpolated with given resampling filter because their prototypes
  70  *         in the source image lie too close to the border) in the destination
  71  *         image according to the bicubic2 interpolation with border pixels extend
  72  *         of source image.
  73  */
  74 
  75 #include "mlib_image.h"
  76 #include "mlib_ImageAffine.h"
  77 
  78 /***************************************************************/
  79 #define FLT_SHIFT_U8  4
  80 #define FLT_MASK_U8   (((1 << 8) - 1) << 4)
  81 #define FLT_SHIFT_S16 3
  82 #define FLT_MASK_S16  (((1 << 9) - 1) << 4)
  83 
  84 #define MLIB_SIGN_SHIFT 31
  85 
  86 /***************************************************************/
  87 #define D64mlib_u8(X)   mlib_U82D64[X]
  88 #define D64mlib_s16(X)  ((mlib_d64)(X))
  89 #define D64mlib_u16(X)  ((mlib_d64)(X))
  90 #define D64mlib_s32(X)  ((mlib_d64)(X))
  91 #define D64mlib_f32(X)  ((mlib_d64)(X))
  92 #define D64mlib_d64(X)  ((mlib_d64)(X))
  93 
  94 /***************************************************************/
  95 #ifdef MLIB_USE_FTOI_CLAMPING
  96 
  97 #define SATmlib_u8(DST, val0)                                   \
  98   DST = ((mlib_s32)(val0 - sat) >> 24) ^ 0x80
  99 
 100 #define SATmlib_s16(DST, val0)                                  \
 101   DST = ((mlib_s32)val0) >> 16
 102 
 103 #define SATmlib_u16(DST, val0)                                  \
 104   DST = ((mlib_s32)(val0 - sat) >> 16) ^ 0x8000
 105 
 106 #define SATmlib_s32(DST, val0)                                  \
 107   DST = val0
 108 
 109 #else
 110 
 111 #define SATmlib_u8(DST, val0)                                   \
 112   val0 -= sat;                                                  \
 113   if (val0 >= MLIB_S32_MAX)                                     \
 114     val0 = MLIB_S32_MAX;                                        \
 115   if (val0 <= MLIB_S32_MIN)                                     \
 116     val0 = MLIB_S32_MIN;                                        \
 117   DST = ((mlib_s32) val0 >> 24) ^ 0x80
 118 
 119 #define SATmlib_s16(DST, val0)                                  \
 120   if (val0 >= MLIB_S32_MAX)                                     \
 121     val0 = MLIB_S32_MAX;                                        \
 122   if (val0 <= MLIB_S32_MIN)                                     \
 123     val0 = MLIB_S32_MIN;                                        \
 124   DST = (mlib_s32)val0 >> 16
 125 
 126 #define SATmlib_u16(DST, val0)                                  \
 127   val0 -= sat;                                                  \
 128   if (val0 >= MLIB_S32_MAX)                                     \
 129     val0 = MLIB_S32_MAX;                                        \
 130   if (val0 <= MLIB_S32_MIN)                                     \
 131     val0 = MLIB_S32_MIN;                                        \
 132   DST = ((mlib_s32)val0 >> 16) ^ 0x8000
 133 
 134 #define SATmlib_s32(DST, val0)                                  \
 135   if (val0 >= MLIB_S32_MAX)                                     \
 136     val0 = MLIB_S32_MAX;                                        \
 137   if (val0 <= MLIB_S32_MIN)                                     \
 138     val0 = MLIB_S32_MIN;                                        \
 139   DST = (mlib_s32)val0
 140 
 141 #endif
 142 
 143 /***************************************************************/
 144 #define SATmlib_f32(DST, val0)                                  \
 145   DST = (mlib_f32)val0
 146 
 147 /***************************************************************/
 148 #define SATmlib_d64(DST, val0)                                  \
 149   DST = val0
 150 
 151 /***************************************************************/
 152 #define MLIB_EDGE_ZERO_LINE(TYPE, Left, Right)                  \
 153   dp = (TYPE*)data + channels * Left;                           \
 154   dstLineEnd  = (TYPE*)data + channels * Right;                 \
 155                                                                 \
 156   for (; dp < dstLineEnd; dp++) {                               \
 157     *dp = zero;                                                 \
 158   }
 159 
 160 /***************************************************************/
 161 #define MLIB_EDGE_NEAREST_LINE(TYPE, Left, Right)               \
 162   dp = (TYPE*)data + channels * Left;                           \
 163   size = Right - Left;                                          \
 164                                                                 \
 165   for (j = 0; j < size; j++) {                                  \
 166     ySrc = Y >> MLIB_SHIFT;                                     \
 167     xSrc = X >> MLIB_SHIFT;                                     \
 168     sp = (TYPE*)lineAddr[ySrc] + xSrc * channels;               \
 169                                                                 \
 170     for (k = 0; k < channels; k++) dp[k] = sp[k];               \
 171                                                                 \
 172     Y += dY;                                                    \
 173     X += dX;                                                    \
 174     dp += channels;                                             \
 175   }
 176 
 177 /***************************************************************/
 178 #define MLIB_EDGE_BL(TYPE, Left, Right)                                 \
 179   dp = (TYPE*)data + channels * Left;                                   \
 180   size = Right - Left;                                                  \
 181                                                                         \
 182   for (j = 0; j < size; j++) {                                          \
 183     ySrc = ((Y - 32768) >> MLIB_SHIFT);                                 \
 184     xSrc = ((X - 32768) >> MLIB_SHIFT);                                 \
 185                                                                         \
 186     t = ((X - 32768) & MLIB_MASK) * scale;                              \
 187     u = ((Y - 32768) & MLIB_MASK) * scale;                              \
 188                                                                         \
 189     xDelta = (((xSrc + 1 - srcWidth )) >> MLIB_SIGN_SHIFT) & channels;  \
 190     yDelta = (((ySrc + 1 - srcHeight)) >> MLIB_SIGN_SHIFT) & srcStride; \
 191                                                                         \
 192     xFlag = (xSrc >> (MLIB_SIGN_SHIFT - MLIB_SHIFT));                   \
 193     xSrc = xSrc + (1 & xFlag);                                          \
 194     xDelta = xDelta &~ xFlag;                                           \
 195                                                                         \
 196     yFlag = (ySrc >> (MLIB_SIGN_SHIFT - MLIB_SHIFT));                   \
 197     ySrc = ySrc + (1 & yFlag);                                          \
 198     yDelta = yDelta &~ yFlag;                                           \
 199                                                                         \
 200     sp = (TYPE*)lineAddr[ySrc] + xSrc * channels;                       \
 201                                                                         \
 202     for (k = 0; k < channels; k++) {                                    \
 203       a00  = D64##TYPE(sp[0]);                                          \
 204       a01  = D64##TYPE(sp[xDelta]);                                     \
 205       a10  = D64##TYPE(sp[yDelta]);                                     \
 206       a11  = D64##TYPE(sp[yDelta + xDelta]);                            \
 207       pix0 = (a00 * (1 - t) + a01 * t) * (1 - u) +                      \
 208              (a10 * (1 - t) + a11 * t) * u;                             \
 209                                                                         \
 210       dp[k] = (TYPE)pix0;                                               \
 211       sp++;                                                             \
 212     }                                                                   \
 213                                                                         \
 214     X += dX;                                                            \
 215     Y += dY;                                                            \
 216     dp += channels;                                                     \
 217   }
 218 
 219 /***************************************************************/
 220 #define GET_FLT_TBL(X, xf0, xf1, xf2, xf3)                      \
 221   filterpos = ((X - 32768) >> flt_shift) & flt_mask;            \
 222   fptr = (mlib_f32 *) ((mlib_u8 *)flt_tbl + filterpos);         \
 223                                                                 \
 224   xf0 = fptr[0];                                                \
 225   xf1 = fptr[1];                                                \
 226   xf2 = fptr[2];                                                \
 227   xf3 = fptr[3]
 228 
 229 /***************************************************************/
 230 #define GET_FLT_BC(X, xf0, xf1, xf2, xf3)                       \
 231   dx = ((X - 32768) & MLIB_MASK) * scale;                       \
 232   dx_2  = 0.5 * dx;                                             \
 233   dx2   = dx * dx;                                              \
 234   dx3_2 = dx_2 * dx2;                                           \
 235   dx3_3 = 3.0 * dx3_2;                                          \
 236                                                                 \
 237   xf0 = dx2 - dx3_2 - dx_2;                                     \
 238   xf1 = dx3_3 - 2.5 * dx2 + 1.0;                                \
 239   xf2 = 2.0 * dx2 - dx3_3 + dx_2;                               \
 240   xf3 = dx3_2 - 0.5 * dx2
 241 
 242 /***************************************************************/
 243 #define GET_FLT_BC2(X, xf0, xf1, xf2, xf3)                      \
 244   dx =  ((X - 32768) & MLIB_MASK) * scale;                      \
 245   dx2   = dx  * dx;                                             \
 246   dx3_2 = dx  * dx2;                                            \
 247   dx3_3 = 2.0 * dx2;                                            \
 248                                                                 \
 249   xf0 = - dx3_2 + dx3_3 - dx;                                   \
 250   xf1 =   dx3_2 - dx3_3 + 1.0;                                  \
 251   xf2 = - dx3_2 + dx2   + dx;                                   \
 252   xf3 =   dx3_2 - dx2
 253 
 254 /***************************************************************/
 255 #define CALC_SRC_POS(X, Y, channels, srcStride)                                    \
 256   xSrc = ((X - 32768) >> MLIB_SHIFT);                                              \
 257   ySrc = ((Y - 32768) >> MLIB_SHIFT);                                              \
 258                                                                                    \
 259   xDelta0 = ((~((xSrc - 1) >> MLIB_SIGN_SHIFT)) & (- channels));                   \
 260   yDelta0 = ((~((ySrc - 1) >> MLIB_SIGN_SHIFT)) & (- srcStride));                  \
 261   xDelta1 = ((xSrc + 1 - srcWidth) >> MLIB_SIGN_SHIFT) & (channels);               \
 262   yDelta1 = ((ySrc + 1 - srcHeight) >> MLIB_SIGN_SHIFT) & (srcStride);             \
 263   xDelta2 = xDelta1 + (((xSrc + 2 - srcWidth) >> MLIB_SIGN_SHIFT) & (channels));   \
 264   yDelta2 = yDelta1 + (((ySrc + 2 - srcHeight) >> MLIB_SIGN_SHIFT) & (srcStride)); \
 265                                                                                    \
 266   xFlag = (xSrc >> (MLIB_SIGN_SHIFT - MLIB_SHIFT));                                \
 267   xSrc = xSrc + (1 & xFlag);                                                       \
 268   xDelta2 -= (xDelta1 & xFlag);                                                    \
 269   xDelta1 = (xDelta1 &~ xFlag);                                                    \
 270                                                                                    \
 271   yFlag = (ySrc >> (MLIB_SIGN_SHIFT - MLIB_SHIFT));                                \
 272   ySrc = ySrc + (1 & yFlag);                                                       \
 273   yDelta2  -= (yDelta1 & yFlag);                                                   \
 274   yDelta1 = yDelta1 &~ yFlag
 275 
 276 /***************************************************************/
 277 #define MLIB_EDGE_BC_LINE(TYPE, Left, Right, GET_FILTER)        \
 278   dp = (TYPE*)data + channels * Left;                           \
 279   size = Right - Left;                                          \
 280                                                                 \
 281   for (j = 0; j < size; j++) {                                  \
 282     GET_FILTER(X, xf0, xf1, xf2, xf3);                          \
 283     GET_FILTER(Y, yf0, yf1, yf2, yf3);                          \
 284                                                                 \
 285     CALC_SRC_POS(X, Y, channels, srcStride);                    \
 286                                                                 \
 287     sp = (TYPE*)lineAddr[ySrc] + channels*xSrc;                 \
 288                                                                 \
 289     for (k = 0; k < channels; k++) {                            \
 290       c0 = D64##TYPE(sp[yDelta0 + xDelta0]) * xf0 +             \
 291            D64##TYPE(sp[yDelta0          ]) * xf1 +             \
 292            D64##TYPE(sp[yDelta0 + xDelta1]) * xf2 +             \
 293            D64##TYPE(sp[yDelta0 + xDelta2]) * xf3;              \
 294                                                                 \
 295       c1 = D64##TYPE(sp[xDelta0]) * xf0 +                       \
 296            D64##TYPE(sp[      0]) * xf1 +                       \
 297            D64##TYPE(sp[xDelta1]) * xf2 +                       \
 298            D64##TYPE(sp[xDelta2]) * xf3;                        \
 299                                                                 \
 300       c2 = D64##TYPE(sp[yDelta1 + xDelta0]) * xf0 +             \
 301            D64##TYPE(sp[yDelta1          ]) * xf1 +             \
 302            D64##TYPE(sp[yDelta1 + xDelta1]) * xf2 +             \
 303            D64##TYPE(sp[yDelta1 + xDelta2]) * xf3;              \
 304                                                                 \
 305       c3 = D64##TYPE(sp[yDelta2 + xDelta0]) * xf0 +             \
 306            D64##TYPE(sp[yDelta2          ]) * xf1 +             \
 307            D64##TYPE(sp[yDelta2 + xDelta1]) * xf2 +             \
 308            D64##TYPE(sp[yDelta2 + xDelta2]) * xf3;              \
 309                                                                 \
 310       val0 = c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3;                 \
 311                                                                 \
 312       SAT##TYPE(dp[k], val0);                                   \
 313                                                                 \
 314       sp++;                                                     \
 315     }                                                           \
 316                                                                 \
 317     X += dX;                                                    \
 318     Y += dY;                                                    \
 319     dp += channels;                                             \
 320   }
 321 
 322 /***************************************************************/
 323 #define MLIB_EDGE_BC_TBL(TYPE, Left, Right)                     \
 324   MLIB_EDGE_BC_LINE(TYPE, Left, Right, GET_FLT_TBL)
 325 
 326 /***************************************************************/
 327 #define MLIB_EDGE_BC(TYPE, Left, Right)                         \
 328   MLIB_EDGE_BC_LINE(TYPE, Left, Right, GET_FLT_BC)
 329 
 330 /***************************************************************/
 331 #define MLIB_EDGE_BC2(TYPE, Left, Right)                        \
 332   MLIB_EDGE_BC_LINE(TYPE, Left, Right, GET_FLT_BC2)
 333 
 334 /***************************************************************/
 335 #define MLIB_PROCESS_EDGES_ZERO(TYPE) {                         \
 336   TYPE *dp, *dstLineEnd;                                        \
 337                                                                 \
 338   for (i = yStartE; i < yStart; i++) {                          \
 339     xLeftE  = leftEdgesE[i];                                    \
 340     xRightE = rightEdgesE[i] + 1;                               \
 341     data   += dstStride;                                        \
 342                                                                 \
 343     MLIB_EDGE_ZERO_LINE(TYPE, xLeftE, xRightE);                 \
 344   }                                                             \
 345                                                                 \
 346   for (; i <= yFinish; i++) {                                   \
 347     xLeftE  = leftEdgesE[i];                                    \
 348     xRightE = rightEdgesE[i] + 1;                               \
 349     xLeft   = leftEdges[i];                                     \
 350     xRight  = rightEdges[i] + 1;                                \
 351     data   += dstStride;                                        \
 352                                                                 \
 353     if (xLeft < xRight) {                                       \
 354       MLIB_EDGE_ZERO_LINE(TYPE, xLeftE, xLeft);                 \
 355     } else {                                                    \
 356       xRight = xLeftE;                                          \
 357     }                                                           \
 358                                                                 \
 359     MLIB_EDGE_ZERO_LINE(TYPE, xRight, xRightE);                 \
 360   }                                                             \
 361                                                                 \
 362   for (; i <= yFinishE; i++) {                                  \
 363     xLeftE  = leftEdgesE[i];                                    \
 364     xRightE = rightEdgesE[i] + 1;                               \
 365     data   += dstStride;                                        \
 366                                                                 \
 367     MLIB_EDGE_ZERO_LINE(TYPE, xLeftE, xRightE);                 \
 368   }                                                             \
 369 }
 370 
 371 /***************************************************************/
 372 #define MLIB_PROCESS_EDGES(PROCESS_LINE, TYPE) {                \
 373   TYPE *sp, *dp;                                                \
 374   mlib_s32 k, size;                                             \
 375                                                                 \
 376   for (i = yStartE; i < yStart; i++) {                          \
 377     xLeftE  = leftEdgesE[i];                                    \
 378     xRightE = rightEdgesE[i] + 1;                               \
 379     X       = xStartsE[i];                                      \
 380     Y       = yStartsE[i];                                      \
 381     data   += dstStride;                                        \
 382                                                                 \
 383     PROCESS_LINE(TYPE, xLeftE, xRightE);                        \
 384   }                                                             \
 385                                                                 \
 386   for (; i <= yFinish; i++) {                                   \
 387     xLeftE  = leftEdgesE[i];                                    \
 388     xRightE = rightEdgesE[i] + 1;                               \
 389     xLeft   = leftEdges[i];                                     \
 390     xRight  = rightEdges[i] + 1;                                \
 391     X       = xStartsE[i];                                      \
 392     Y       = yStartsE[i];                                      \
 393     data   += dstStride;                                        \
 394                                                                 \
 395     if (xLeft < xRight) {                                       \
 396       PROCESS_LINE(TYPE, xLeftE, xLeft);                        \
 397     } else {                                                    \
 398       xRight = xLeftE;                                          \
 399     }                                                           \
 400                                                                 \
 401     X = xStartsE[i] + dX * (xRight - xLeftE);                   \
 402     Y = yStartsE[i] + dY * (xRight - xLeftE);                   \
 403     PROCESS_LINE(TYPE, xRight, xRightE);                        \
 404   }                                                             \
 405                                                                 \
 406   for (; i <= yFinishE; i++) {                                  \
 407     xLeftE  = leftEdgesE[i];                                    \
 408     xRightE = rightEdgesE[i] + 1;                               \
 409     X       = xStartsE[i];                                      \
 410     Y       = yStartsE[i];                                      \
 411     data   += dstStride;                                        \
 412                                                                 \
 413     PROCESS_LINE(TYPE, xLeftE, xRightE);                        \
 414   }                                                             \
 415 }
 416 
 417 /***************************************************************/
 418 #define GET_EDGE_PARAMS_ZERO()                                  \
 419   mlib_image *dst = param -> dst;                               \
 420   mlib_s32  *leftEdges  = param -> leftEdges;                   \
 421   mlib_s32  *rightEdges = param -> rightEdges;                  \
 422   mlib_s32  *leftEdgesE  = param_e -> leftEdges;                \
 423   mlib_s32  *rightEdgesE = param_e -> rightEdges;               \
 424   mlib_type type      = mlib_ImageGetType(dst);                 \
 425   mlib_s32  channels  = mlib_ImageGetChannels(dst);             \
 426   mlib_s32  dstStride = mlib_ImageGetStride(dst);               \
 427   mlib_s32  yStart    = param -> yStart;                        \
 428   mlib_s32  yFinish   = param -> yFinish;                       \
 429   mlib_s32  yStartE   = param_e -> yStart;                      \
 430   mlib_s32  yFinishE  = param_e -> yFinish;                     \
 431   mlib_u8   *data     = param_e -> dstData;                     \
 432   mlib_s32  xLeft, xRight, xLeftE, xRightE;                     \
 433   mlib_s32  i
 434 
 435 /***************************************************************/
 436 #define GET_EDGE_PARAMS_NN()                                    \
 437   GET_EDGE_PARAMS_ZERO();                                       \
 438   mlib_s32  *xStartsE = param_e -> xStarts;                     \
 439   mlib_s32  *yStartsE = param_e -> yStarts;                     \
 440   mlib_u8   **lineAddr = param -> lineAddr;                     \
 441   mlib_s32  dX = param_e -> dX;                                 \
 442   mlib_s32  dY = param_e -> dY;                                 \
 443   mlib_s32  xSrc, ySrc, X, Y;                                   \
 444   mlib_s32  j
 445 
 446 /***************************************************************/
 447 #define GET_EDGE_PARAMS()                                       \
 448   GET_EDGE_PARAMS_NN();                                         \
 449   mlib_image *src = param -> src;                               \
 450   mlib_s32  srcWidth  = mlib_ImageGetWidth(src);                \
 451   mlib_s32  srcHeight = mlib_ImageGetHeight(src);               \
 452   mlib_s32  srcStride = mlib_ImageGetStride(src)
 453 
 454 /***************************************************************/
 455 void mlib_ImageAffineEdgeZero(mlib_affine_param *param,
 456                               mlib_affine_param *param_e)
 457 {
 458   GET_EDGE_PARAMS_ZERO();
 459   mlib_s32 zero = 0;
 460   
 461   switch (type) {
 462     case MLIB_BYTE:
 463       MLIB_PROCESS_EDGES_ZERO(mlib_u8);
 464       break;
 465 
 466     case MLIB_SHORT:
 467     case MLIB_USHORT:
 468       MLIB_PROCESS_EDGES_ZERO(mlib_s16);
 469       break;
 470 
 471     case MLIB_INT:
 472     case MLIB_FLOAT:
 473       MLIB_PROCESS_EDGES_ZERO(mlib_s32);
 474       break;
 475 
 476     case MLIB_DOUBLE:{
 477         mlib_d64 zero = 0;
 478         MLIB_PROCESS_EDGES_ZERO(mlib_d64);
 479         break;
 480       }
 481   default:
 482     /* Image type MLIB_BIT is not used in java, so we can ignore it. */
 483     break;
 484   }
 485 }
 486 
 487 /***************************************************************/
 488 void mlib_ImageAffineEdgeNearest(mlib_affine_param *param,
 489                                  mlib_affine_param *param_e)
 490 {
 491   GET_EDGE_PARAMS_NN();
 492 
 493   switch (type) {
 494     case MLIB_BYTE:
 495       MLIB_PROCESS_EDGES(MLIB_EDGE_NEAREST_LINE, mlib_u8);
 496       break;
 497 
 498     case MLIB_SHORT:
 499     case MLIB_USHORT:
 500       MLIB_PROCESS_EDGES(MLIB_EDGE_NEAREST_LINE, mlib_s16);
 501       break;
 502 
 503     case MLIB_INT:
 504     case MLIB_FLOAT:
 505       MLIB_PROCESS_EDGES(MLIB_EDGE_NEAREST_LINE, mlib_s32);
 506       break;
 507 
 508     case MLIB_DOUBLE:
 509       MLIB_PROCESS_EDGES(MLIB_EDGE_NEAREST_LINE, mlib_d64);
 510       break;
 511   default:
 512     /* Image type MLIB_BIT is not used in java, so we can ignore it. */
 513     break;
 514   }
 515 }
 516 
 517 /***************************************************************/
 518 mlib_status mlib_ImageAffineEdgeExtend_BL(mlib_affine_param *param,
 519                                           mlib_affine_param *param_e)
 520 {
 521   GET_EDGE_PARAMS();
 522   mlib_d64 scale = 1.0 / (mlib_d64) MLIB_PREC;
 523   mlib_s32 xDelta, yDelta, xFlag, yFlag;
 524   mlib_d64 t, u, pix0;
 525   mlib_d64 a00, a01, a10, a11;
 526 
 527   switch (type) {
 528     case MLIB_BYTE:
 529       MLIB_PROCESS_EDGES(MLIB_EDGE_BL, mlib_u8);
 530       break;
 531 
 532     case MLIB_SHORT:
 533       srcStride >>= 1;
 534       MLIB_PROCESS_EDGES(MLIB_EDGE_BL, mlib_s16);
 535       break;
 536 
 537     case MLIB_USHORT:
 538       srcStride >>= 1;
 539       MLIB_PROCESS_EDGES(MLIB_EDGE_BL, mlib_u16);
 540       break;
 541 
 542     case MLIB_INT:
 543       srcStride >>= 2;
 544       MLIB_PROCESS_EDGES(MLIB_EDGE_BL, mlib_s32);
 545       break;
 546 
 547     case MLIB_FLOAT:
 548       srcStride >>= 2;
 549       MLIB_PROCESS_EDGES(MLIB_EDGE_BL, mlib_f32);
 550       break;
 551 
 552     case MLIB_DOUBLE:
 553       srcStride >>= 3;
 554       MLIB_PROCESS_EDGES(MLIB_EDGE_BL, mlib_d64);
 555       break;
 556 
 557   default:
 558     /* Image type MLIB_BIT is not supported, ignore it. */
 559     break;
 560   }
 561 
 562   return MLIB_SUCCESS;
 563 }
 564 
 565 /***************************************************************/
 566 mlib_status mlib_ImageAffineEdgeExtend_BC(mlib_affine_param *param,
 567                                           mlib_affine_param *param_e)
 568 {
 569   GET_EDGE_PARAMS();
 570   mlib_d64 scale = 1.0 / (mlib_d64) MLIB_PREC;
 571   mlib_s32 xFlag, yFlag;
 572   mlib_d64 dx, dx_2, dx2, dx3_2, dx3_3;
 573   mlib_d64 xf0, xf1, xf2, xf3;
 574   mlib_d64 yf0, yf1, yf2, yf3;
 575   mlib_d64 c0, c1, c2, c3, val0;
 576   mlib_filter filter = param->filter;
 577   mlib_f32 *fptr;
 578   mlib_f32 const *flt_tbl;
 579   mlib_s32 filterpos, flt_shift, flt_mask;
 580   mlib_s32 xDelta0, xDelta1, xDelta2;
 581   mlib_s32 yDelta0, yDelta1, yDelta2;
 582   mlib_d64 sat;
 583 
 584   if (type == MLIB_BYTE) {
 585     flt_shift = FLT_SHIFT_U8;
 586     flt_mask = FLT_MASK_U8;
 587     flt_tbl = (filter == MLIB_BICUBIC) ? mlib_filters_u8f_bc : mlib_filters_u8f_bc2;
 588     sat = (mlib_d64) 0x7F800000;                           /* saturation for U8 */
 589   }
 590   else {
 591     flt_shift = FLT_SHIFT_S16;
 592     flt_mask = FLT_MASK_S16;
 593     flt_tbl = (filter == MLIB_BICUBIC) ? mlib_filters_s16f_bc : mlib_filters_s16f_bc2;
 594     sat = (mlib_d64) 0x7FFF8000;                           /* saturation for U16 */
 595   }
 596   
 597 
 598   switch (type) {
 599     case MLIB_BYTE:
 600       MLIB_PROCESS_EDGES(MLIB_EDGE_BC_TBL, mlib_u8);
 601       break;
 602 
 603     case MLIB_SHORT:
 604       srcStride >>= 1;
 605       MLIB_PROCESS_EDGES(MLIB_EDGE_BC_TBL, mlib_s16);
 606       break;
 607 
 608     case MLIB_USHORT:
 609       srcStride >>= 1;
 610       MLIB_PROCESS_EDGES(MLIB_EDGE_BC_TBL, mlib_u16);
 611       break;
 612 
 613     case MLIB_INT:
 614       srcStride >>= 2;
 615 
 616       if (filter == MLIB_BICUBIC) {
 617         MLIB_PROCESS_EDGES(MLIB_EDGE_BC, mlib_s32);
 618       }
 619       else {
 620         MLIB_PROCESS_EDGES(MLIB_EDGE_BC2, mlib_s32);
 621       }
 622 
 623       break;
 624 
 625     case MLIB_FLOAT:
 626       srcStride >>= 2;
 627 
 628       if (filter == MLIB_BICUBIC) {
 629         MLIB_PROCESS_EDGES(MLIB_EDGE_BC, mlib_f32);
 630       }
 631       else {
 632         MLIB_PROCESS_EDGES(MLIB_EDGE_BC2, mlib_f32);
 633       }
 634 
 635       break;
 636 
 637     case MLIB_DOUBLE:
 638       srcStride >>= 3;
 639 
 640       if (filter == MLIB_BICUBIC) {
 641         MLIB_PROCESS_EDGES(MLIB_EDGE_BC, mlib_d64);
 642       }
 643       else {
 644         MLIB_PROCESS_EDGES(MLIB_EDGE_BC2, mlib_d64);
 645       }
 646 
 647       break;
 648 
 649   default:
 650     /* Ignore unsupported image type MLIB_BIT */
 651     break;
 652   }
 653 
 654   return MLIB_SUCCESS;
 655 }
 656 
 657 /***************************************************************/