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 /***************************************************************/