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/***************************************************************/
455void 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/***************************************************************/
488void 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/***************************************************************/
518mlib_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/***************************************************************/
566mlib_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/***************************************************************/
658