1 /*
   2  * Copyright (c) 1998, 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 #include "mlib_image.h"
  28 #include "mlib_ImageAffine.h"
  29 #include "mlib_ImageColormap.h"
  30 
  31 /***************************************************************/
  32 #define MLIB_LIMIT  512
  33 #define MLIB_SHIFT   16
  34 #define MLIB_PREC    (1 << MLIB_SHIFT)
  35 #define MLIB_MASK    (MLIB_PREC - 1)
  36 
  37 /***************************************************************/
  38 #define DTYPE  MLIB_TYPE
  39 
  40 /***************************************************************/
  41 #define DECLAREVAR_IND()                                        \
  42   DECLAREVAR0();                                                \
  43   mlib_s32  *warp_tbl   = param -> warp_tbl;                    \
  44   mlib_s32  xSrc, ySrc;                                         \
  45   mlib_s32  srcYStride = param -> srcYStride;                   \
  46   mlib_s32  max_xsize  = param -> max_xsize;                    \
  47   mlib_filter filter = param -> filter;                         \
  48   MLIB_TYPE *sp, *dl;                                           \
  49   mlib_d64  xf0, xf1, xf2, xf3;                                 \
  50   mlib_d64  yf0, yf1, yf2, yf3;                                 \
  51   mlib_d64  c0, c1, c2, c3, val0;                               \
  52   mlib_s32  filterpos;                                          \
  53   mlib_f32  *fptr;                                              \
  54   mlib_d64  s0, s1, s2, s3;                                     \
  55   mlib_s32  i, size
  56 
  57 /***************************************************************/
  58 #define GET_FILTERS_KOEF()                                         \
  59   filterpos = (X >> FILTER_SHIFT) & FILTER_MASK;                   \
  60   fptr = (mlib_f32 *) ((mlib_u8 *)mlib_filters_table + filterpos); \
  61                                                                    \
  62   xf0 = fptr[0];                                                   \
  63   xf1 = fptr[1];                                                   \
  64   xf2 = fptr[2];                                                   \
  65   xf3 = fptr[3];                                                   \
  66                                                                    \
  67   filterpos = (Y >> FILTER_SHIFT) & FILTER_MASK;                   \
  68   fptr = (mlib_f32 *) ((mlib_u8 *)mlib_filters_table + filterpos); \
  69                                                                    \
  70   yf0 = fptr[0];                                                   \
  71   yf1 = fptr[1];                                                   \
  72   yf2 = fptr[2];                                                   \
  73   yf3 = fptr[3]
  74 
  75 /***************************************************************/
  76 #define GET_POINTER()                                           \
  77   xSrc = (X >> MLIB_SHIFT)-1;                                   \
  78   ySrc = (Y >> MLIB_SHIFT)-1;                                   \
  79   sp = ((MLIB_TYPE **)lineAddr)[ySrc] + xSrc
  80 
  81 /***************************************************************/
  82 #define LOAD_FIRST_ROW(nchan, chan)                             \
  83   s0 = *(lut + sp[0]*nchan + chan);                             \
  84   s1 = *(lut + sp[1]*nchan + chan);                             \
  85   s2 = *(lut + sp[2]*nchan + chan);                             \
  86   s3 = *(lut + sp[3]*nchan + chan)
  87 
  88 /***************************************************************/
  89 #define COUNT_NEXT_ROW(dst, nchan, chan)                        \
  90   sp = (MLIB_TYPE*)((mlib_addr)sp + srcYStride);                \
  91   dst = ((*(lut + sp[0]*nchan + chan))*xf0 +                    \
  92          (*(lut + sp[1]*nchan + chan))*xf1 +                    \
  93          (*(lut + sp[2]*nchan + chan))*xf2 +                    \
  94          (*(lut + sp[3]*nchan + chan))*xf3)
  95 
  96 /***************************************************************/
  97 #ifdef MLIB_USE_FTOI_CLAMPING
  98 
  99 /***********/
 100 #define STORE_SAT_VALUE_U8(ind)                                 \
 101   dp[ind] = ((mlib_s32)(val0 - (mlib_d64)0x7F800000) >> 24) ^ 0x80
 102 
 103 /***********/
 104 #define STORE_SAT_VALUE_S16(ind)                                \
 105   dp[ind] = ((mlib_s32)(val0)) >> 16
 106 
 107 #else
 108 
 109 /***********/
 110 #define STORE_SAT_VALUE_U8(ind)                                 \
 111   val0 -= (mlib_d64)0x7F800000;                                 \
 112   if (val0 >= MLIB_S32_MAX)                                     \
 113     dp[ind] = MLIB_U8_MAX;                                      \
 114   else if (val0 <= MLIB_S32_MIN)                                \
 115     dp[ind] = MLIB_U8_MIN;                                      \
 116   else                                                          \
 117     dp[ind] = ((mlib_s32)val0 >> 24) ^ 0x80
 118 
 119 /***********/
 120 #define STORE_SAT_VALUE_S16(ind)                                \
 121   if (val0 >= MLIB_S32_MAX)                                     \
 122     dp[ind] = MLIB_S16_MAX;                                     \
 123   else if (val0 <= MLIB_S32_MIN)                                \
 124     dp[ind] = MLIB_S16_MIN;                                     \
 125   else                                                          \
 126     dp[ind] = (mlib_s32)val0 >> 16
 127 
 128 #endif /* MLIB_USE_FTOI_CLAMPING */
 129 
 130 /***************************************************************/
 131 #define MAKE_BC_3CH(lut_format)                                 \
 132   X += dX;                                                      \
 133   Y += dY;                                                      \
 134   c0 = (s0*xf0 + s1*xf1 + s2*xf2 + s3*xf3);                     \
 135   COUNT_NEXT_ROW(c1, 3, 0);                                     \
 136   COUNT_NEXT_ROW(c2, 3, 0);                                     \
 137   COUNT_NEXT_ROW(c3, 3, 0);                                     \
 138   val0 = (c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3);                   \
 139   sp = (MLIB_TYPE*)((mlib_addr)sp - 3*srcYStride);              \
 140   LOAD_FIRST_ROW(3, 1);                                         \
 141   STORE_SAT_VALUE_##lut_format(0);                              \
 142   c0 = (s0*xf0 + s1*xf1 + s2*xf2 + s3*xf3);                     \
 143   COUNT_NEXT_ROW(c1, 3, 1);                                     \
 144   COUNT_NEXT_ROW(c2, 3, 1);                                     \
 145   COUNT_NEXT_ROW(c3, 3, 1);                                     \
 146   val0 = (c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3);                   \
 147   sp = (MLIB_TYPE*)((mlib_addr)sp - 3*srcYStride);              \
 148   LOAD_FIRST_ROW(3, 2);                                         \
 149   STORE_SAT_VALUE_##lut_format(1);                              \
 150   c0 = (s0*xf0 + s1*xf1 + s2*xf2 + s3*xf3);                     \
 151   COUNT_NEXT_ROW(c1, 3, 2);                                     \
 152   COUNT_NEXT_ROW(c2, 3, 2);                                     \
 153   COUNT_NEXT_ROW(c3, 3, 2);                                     \
 154   val0 = (c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3);                   \
 155   GET_FILTERS_KOEF();                                           \
 156   GET_POINTER();                                                \
 157   LOAD_FIRST_ROW(3, 0);                                         \
 158   STORE_SAT_VALUE_##lut_format(2);
 159 
 160 /***************************************************************/
 161 #define MAKE_LAST_PIXEL_BC_3CH(lut_format)                      \
 162   c0 = (s0*xf0 + s1*xf1 + s2*xf2 + s3*xf3);                     \
 163   COUNT_NEXT_ROW(c1, 3, 0);                                     \
 164   COUNT_NEXT_ROW(c2, 3, 0);                                     \
 165   COUNT_NEXT_ROW(c3, 3, 0);                                     \
 166   val0 = (c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3);                   \
 167   sp = (MLIB_TYPE*)((mlib_addr)sp - 3*srcYStride);              \
 168   LOAD_FIRST_ROW(3, 1);                                         \
 169   STORE_SAT_VALUE_##lut_format(0);                              \
 170   c0 = (s0*xf0 + s1*xf1 + s2*xf2 + s3*xf3);                     \
 171   COUNT_NEXT_ROW(c1, 3, 1);                                     \
 172   COUNT_NEXT_ROW(c2, 3, 1);                                     \
 173   COUNT_NEXT_ROW(c3, 3, 1);                                     \
 174   val0 = (c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3);                   \
 175   sp = (MLIB_TYPE*)((mlib_addr)sp - 3*srcYStride);              \
 176   LOAD_FIRST_ROW(3, 2);                                         \
 177   STORE_SAT_VALUE_##lut_format(1);                              \
 178   c0 = (s0*xf0 + s1*xf1 + s2*xf2 + s3*xf3);                     \
 179   COUNT_NEXT_ROW(c1, 3, 2);                                     \
 180   COUNT_NEXT_ROW(c2, 3, 2);                                     \
 181   COUNT_NEXT_ROW(c3, 3, 2);                                     \
 182   val0 = (c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3);                   \
 183   STORE_SAT_VALUE_##lut_format(2);
 184 
 185 /***************************************************************/
 186 #define MAKE_BC_4CH(lut_format)                                 \
 187   X += dX;                                                      \
 188   Y += dY;                                                      \
 189   c0 = (s0*xf0 + s1*xf1 + s2*xf2 + s3*xf3);                     \
 190   COUNT_NEXT_ROW(c1, 4, 0);                                     \
 191   COUNT_NEXT_ROW(c2, 4, 0);                                     \
 192   COUNT_NEXT_ROW(c3, 4, 0);                                     \
 193   val0 = (c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3);                   \
 194   sp = (MLIB_TYPE*)((mlib_addr)sp - 3*srcYStride);              \
 195   LOAD_FIRST_ROW(4, 1);                                         \
 196   STORE_SAT_VALUE_##lut_format(0);                              \
 197   c0 = (s0*xf0 + s1*xf1 + s2*xf2 + s3*xf3);                     \
 198   COUNT_NEXT_ROW(c1, 4, 1);                                     \
 199   COUNT_NEXT_ROW(c2, 4, 1);                                     \
 200   COUNT_NEXT_ROW(c3, 4, 1);                                     \
 201   val0 = (c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3);                   \
 202   sp = (MLIB_TYPE*)((mlib_addr)sp - 3*srcYStride);              \
 203   LOAD_FIRST_ROW(4, 2);                                         \
 204   STORE_SAT_VALUE_##lut_format(1);                              \
 205   c0 = (s0*xf0 + s1*xf1 + s2*xf2 + s3*xf3);                     \
 206   COUNT_NEXT_ROW(c1, 4, 2);                                     \
 207   COUNT_NEXT_ROW(c2, 4, 2);                                     \
 208   COUNT_NEXT_ROW(c3, 4, 2);                                     \
 209   val0 = (c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3);                   \
 210   sp = (MLIB_TYPE*)((mlib_addr)sp - 3*srcYStride);              \
 211   LOAD_FIRST_ROW(4, 3);                                         \
 212   STORE_SAT_VALUE_##lut_format(2);                              \
 213   c0 = (s0*xf0 + s1*xf1 + s2*xf2 + s3*xf3);                     \
 214   COUNT_NEXT_ROW(c1, 4, 3);                                     \
 215   COUNT_NEXT_ROW(c2, 4, 3);                                     \
 216   COUNT_NEXT_ROW(c3, 4, 3);                                     \
 217   val0 = (c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3);                   \
 218   GET_FILTERS_KOEF();                                           \
 219   GET_POINTER();                                                \
 220   LOAD_FIRST_ROW(4, 0);                                         \
 221   STORE_SAT_VALUE_##lut_format(3);
 222 
 223 /***************************************************************/
 224 #define MAKE_LAST_PIXEL_BC_4CH(lut_format)                      \
 225   c0 = (s0*xf0 + s1*xf1 + s2*xf2 + s3*xf3);                     \
 226   COUNT_NEXT_ROW(c1, 4, 0);                                     \
 227   COUNT_NEXT_ROW(c2, 4, 0);                                     \
 228   COUNT_NEXT_ROW(c3, 4, 0);                                     \
 229   val0 = (c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3);                   \
 230   sp = (MLIB_TYPE*)((mlib_addr)sp - 3*srcYStride);              \
 231   LOAD_FIRST_ROW(4, 1);                                         \
 232   STORE_SAT_VALUE_##lut_format(0);                              \
 233   c0 = (s0*xf0 + s1*xf1 + s2*xf2 + s3*xf3);                     \
 234   COUNT_NEXT_ROW(c1, 4, 1);                                     \
 235   COUNT_NEXT_ROW(c2, 4, 1);                                     \
 236   COUNT_NEXT_ROW(c3, 4, 1);                                     \
 237   val0 = (c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3);                   \
 238   sp = (MLIB_TYPE*)((mlib_addr)sp - 3*srcYStride);              \
 239   LOAD_FIRST_ROW(4, 2);                                         \
 240   STORE_SAT_VALUE_##lut_format(1);                              \
 241   c0 = (s0*xf0 + s1*xf1 + s2*xf2 + s3*xf3);                     \
 242   COUNT_NEXT_ROW(c1, 4, 2);                                     \
 243   COUNT_NEXT_ROW(c2, 4, 2);                                     \
 244   COUNT_NEXT_ROW(c3, 4, 2);                                     \
 245   val0 = (c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3);                   \
 246   sp = (MLIB_TYPE*)((mlib_addr)sp - 3*srcYStride);              \
 247   LOAD_FIRST_ROW(4, 3);                                         \
 248   STORE_SAT_VALUE_##lut_format(2);                              \
 249   c0 = (s0*xf0 + s1*xf1 + s2*xf2 + s3*xf3);                     \
 250   COUNT_NEXT_ROW(c1, 4, 3);                                     \
 251   COUNT_NEXT_ROW(c2, 4, 3);                                     \
 252   COUNT_NEXT_ROW(c3, 4, 3);                                     \
 253   val0 = (c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3);                   \
 254   STORE_SAT_VALUE_##lut_format(3);
 255 
 256 /***************************************************************/
 257 #define FILTER_U8  ((filter == MLIB_BICUBIC) ? mlib_filters_u8f_bc  : mlib_filters_u8f_bc2)
 258 #define FILTER_S16 ((filter == MLIB_BICUBIC) ? mlib_filters_s16f_bc : mlib_filters_s16f_bc2)
 259 
 260 /***************************************************************/
 261 #define mlib_U8  mlib_u8
 262 #define mlib_S16 mlib_s16
 263 
 264 /***************************************************************/
 265 #define FUNC_AFFINEINDEX_BC_0(ITYPE, LTYPE, NCHAN)                                                  \
 266   mlib_status mlib_ImageAffineIndex_##ITYPE##_##LTYPE##_##NCHAN##CH_BC(mlib_affine_param *param,    \
 267                                                                        const void        *colormap) \
 268   {                                                                                                 \
 269     DECLAREVAR_IND();                                                                               \
 270     mlib_##LTYPE buff_lcl[NCHAN * MLIB_LIMIT], *pbuff = buff_lcl, *dp;                              \
 271     mlib_d64  *lut = ((mlib_d64*)mlib_ImageGetLutDoubleData(colormap) -                             \
 272                       NCHAN * mlib_ImageGetLutOffset(colormap));                                    \
 273     const mlib_f32 *mlib_filters_table = FILTER_##LTYPE;                                            \
 274                                                                                                     \
 275     if (max_xsize > MLIB_LIMIT) {                                                                   \
 276       pbuff = mlib_malloc(NCHAN * sizeof(mlib_##LTYPE) * max_xsize);                                \
 277       if (pbuff == NULL) return MLIB_FAILURE;                                                       \
 278     }                                                                                               \
 279                                                                                                     \
 280     for (j = yStart; j <= yFinish; j++) {                                                           \
 281                                                                                                     \
 282       NEW_LINE(1);                                                                                  \
 283       dp = pbuff;                                                                                   \
 284                                                                                                     \
 285       GET_FILTERS_KOEF();                                                                           \
 286       GET_POINTER();                                                                                \
 287       LOAD_FIRST_ROW(NCHAN, 0);
 288 
 289     /* pragma pipeloop(0) must be here */
 290 
 291 /***************************************************************/
 292 #define FUNC_AFFINEINDEX_BC_1(ITYPE, LTYPE, NCHAN)                         \
 293                                                                            \
 294       for (i = 0; i < (xRight - xLeft); i++, dp += NCHAN) {                \
 295         MAKE_BC_##NCHAN##CH(LTYPE);                                        \
 296       }                                                                    \
 297                                                                            \
 298       MAKE_LAST_PIXEL_BC_##NCHAN##CH(LTYPE);                               \
 299                                                                            \
 300       mlib_ImageColorTrue2IndexLine_##LTYPE##_##ITYPE##_##NCHAN            \
 301                                 (pbuff, dl, xRight - xLeft + 1, colormap); \
 302     }                                                                      \
 303                                                                            \
 304     if (pbuff != buff_lcl) mlib_free(pbuff);                               \
 305                                                                            \
 306     return MLIB_SUCCESS;                                                   \
 307   }
 308 
 309 /***************************************************************/
 310 #undef MLIB_TYPE
 311 #define MLIB_TYPE mlib_u8
 312 
 313 /***************************************************************/
 314 #undef  FILTER_SHIFT
 315 #define FILTER_SHIFT 4
 316 #undef  FILTER_MASK
 317 #define FILTER_MASK  (((1 << 8) - 1) << 4)
 318 
 319 FUNC_AFFINEINDEX_BC_0(U8, U8, 3)
 320 #ifdef __SUNPRO_C
 321 #pragma pipeloop(0)
 322 #endif /* __SUNPRO_C */
 323 FUNC_AFFINEINDEX_BC_1(U8, U8, 3)
 324 
 325 /***************************************************************/
 326 #undef  FILTER_SHIFT
 327 #define FILTER_SHIFT 3
 328 #undef  FILTER_MASK
 329 #define FILTER_MASK  (((1 << 9) - 1) << 4)
 330 
 331 FUNC_AFFINEINDEX_BC_0(U8, S16, 3)
 332 #ifdef __SUNPRO_C
 333 #pragma pipeloop(0)
 334 #endif /* __SUNPRO_C */
 335 FUNC_AFFINEINDEX_BC_1(U8, S16, 3)
 336 
 337 /***************************************************************/
 338 #undef  FILTER_SHIFT
 339 #define FILTER_SHIFT 4
 340 #undef  FILTER_MASK
 341 #define FILTER_MASK  (((1 << 8) - 1) << 4)
 342 
 343 FUNC_AFFINEINDEX_BC_0(U8, U8, 4)
 344 #ifdef __SUNPRO_C
 345 #pragma pipeloop(0)
 346 #endif /* __SUNPRO_C */
 347 FUNC_AFFINEINDEX_BC_1(U8, U8, 4)
 348 
 349 /***************************************************************/
 350 #undef  FILTER_SHIFT
 351 #define FILTER_SHIFT 3
 352 #undef  FILTER_MASK
 353 #define FILTER_MASK  (((1 << 9) - 1) << 4)
 354 
 355 FUNC_AFFINEINDEX_BC_0(U8, S16, 4)
 356 #ifdef __SUNPRO_C
 357 #pragma pipeloop(0)
 358 #endif /* __SUNPRO_C */
 359 FUNC_AFFINEINDEX_BC_1(U8, S16, 4)
 360 
 361 /***************************************************************/
 362 #undef  MLIB_TYPE
 363 #define MLIB_TYPE mlib_s16
 364 
 365 /***************************************************************/
 366 #undef  FILTER_SHIFT
 367 #define FILTER_SHIFT 4
 368 #undef  FILTER_MASK
 369 #define FILTER_MASK  (((1 << 8) - 1) << 4)
 370 
 371 FUNC_AFFINEINDEX_BC_0(S16, U8, 3)
 372 #ifdef __SUNPRO_C
 373 #pragma pipeloop(0)
 374 #endif /* __SUNPRO_C */
 375 FUNC_AFFINEINDEX_BC_1(S16, U8, 3)
 376 
 377 /***************************************************************/
 378 #undef  FILTER_SHIFT
 379 #define FILTER_SHIFT 3
 380 #undef  FILTER_MASK
 381 #define FILTER_MASK  (((1 << 9) - 1) << 4)
 382 
 383 FUNC_AFFINEINDEX_BC_0(S16, S16, 3)
 384 #ifdef __SUNPRO_C
 385 #pragma pipeloop(0)
 386 #endif /* __SUNPRO_C */
 387 FUNC_AFFINEINDEX_BC_1(S16, S16, 3)
 388 
 389 /***************************************************************/
 390 #undef  FILTER_SHIFT
 391 #define FILTER_SHIFT 4
 392 #undef  FILTER_MASK
 393 #define FILTER_MASK  (((1 << 8) - 1) << 4)
 394 
 395 FUNC_AFFINEINDEX_BC_0(S16, U8, 4)
 396 #ifdef __SUNPRO_C
 397 #pragma pipeloop(0)
 398 #endif /* __SUNPRO_C */
 399 FUNC_AFFINEINDEX_BC_1(S16, U8, 4)
 400 
 401 /***************************************************************/
 402 #undef  FILTER_SHIFT
 403 #define FILTER_SHIFT 3
 404 #undef  FILTER_MASK
 405 #define FILTER_MASK  (((1 << 9) - 1) << 4)
 406 
 407 FUNC_AFFINEINDEX_BC_0(S16, S16, 4)
 408 #ifdef __SUNPRO_C
 409 #pragma pipeloop(0)
 410 #endif /* __SUNPRO_C */
 411 FUNC_AFFINEINDEX_BC_1(S16, S16, 4)
 412 
 413 /***************************************************************/