blob: 2f2da0015dfcf55aaf10f1dec048d0be16cfde39 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2003 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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_ImageColormap.h"
77#include "mlib_ImageAffine.h"
78
79/***************************************************************/
80#define FLT_SHIFT_U8 4
81#define FLT_MASK_U8 (((1 << 8) - 1) << 4)
82#define FLT_SHIFT_S16 3
83#define FLT_MASK_S16 (((1 << 9) - 1) << 4)
84
85#define MLIB_SIGN_SHIFT 31
86
87/***************************************************************/
88#define D64mlib_u8(X) mlib_U82D64[X]
89#define D64mlib_s16(X) ((mlib_d64)(X))
90#define D64mlib_u16(X) ((mlib_d64)(X))
91#define D64mlib_s32(X) ((mlib_d64)(X))
92#define D64mlib_f32(X) ((mlib_d64)(X))
93#define D64mlib_d64(X) ((mlib_d64)(X))
94
95/***************************************************************/
96#ifdef MLIB_USE_FTOI_CLAMPING
97
98#define SATmlib_u8(DST, val0) \
99 DST = ((mlib_s32)(val0 - sat) >> 24) ^ 0x80
100
101#define SATmlib_s16(DST, val0) \
102 DST = ((mlib_s32)val0) >> 16
103
104#define SATmlib_u16(DST, val0) \
105 DST = ((mlib_s32)(val0 - sat) >> 16) ^ 0x8000
106
107#define SATmlib_s32(DST, val0) \
108 DST = val0
109
110#else
111
112#define SATmlib_u8(DST, val0) \
113 val0 -= sat; \
114 if (val0 >= MLIB_S32_MAX) \
115 val0 = MLIB_S32_MAX; \
116 if (val0 <= MLIB_S32_MIN) \
117 val0 = MLIB_S32_MIN; \
118 DST = ((mlib_s32) val0 >> 24) ^ 0x80
119
120#define SATmlib_s16(DST, val0) \
121 if (val0 >= MLIB_S32_MAX) \
122 val0 = MLIB_S32_MAX; \
123 if (val0 <= MLIB_S32_MIN) \
124 val0 = MLIB_S32_MIN; \
125 DST = (mlib_s32)val0 >> 16
126
127#define SATmlib_u16(DST, val0) \
128 val0 -= sat; \
129 if (val0 >= MLIB_S32_MAX) \
130 val0 = MLIB_S32_MAX; \
131 if (val0 <= MLIB_S32_MIN) \
132 val0 = MLIB_S32_MIN; \
133 DST = ((mlib_s32)val0 >> 16) ^ 0x8000
134
135#define SATmlib_s32(DST, val0) \
136 if (val0 >= MLIB_S32_MAX) \
137 val0 = MLIB_S32_MAX; \
138 if (val0 <= MLIB_S32_MIN) \
139 val0 = MLIB_S32_MIN; \
140 DST = (mlib_s32)val0
141
142#endif
143
144/***************************************************************/
145#define SATmlib_f32(DST, val0) \
146 DST = (mlib_f32)val0
147
148/***************************************************************/
149#define SATmlib_d64(DST, val0) \
150 DST = val0
151
152/***************************************************************/
153#define MLIB_EDGE_ZERO_LINE(TYPE, Left, Right) \
154 dp = (TYPE*)data + channels * Left; \
155 dstLineEnd = (TYPE*)data + channels * Right; \
156 \
157 for (; dp < dstLineEnd; dp++) { \
158 *dp = zero; \
159 }
160
161/***************************************************************/
162#define MLIB_EDGE_NEAREST_LINE(TYPE, Left, Right) \
163 dp = (TYPE*)data + channels * Left; \
164 size = Right - Left; \
165 \
166 for (j = 0; j < size; j++) { \
167 ySrc = Y >> MLIB_SHIFT; \
168 xSrc = X >> MLIB_SHIFT; \
169 sp = (TYPE*)lineAddr[ySrc] + xSrc * channels; \
170 \
171 for (k = 0; k < channels; k++) dp[k] = sp[k]; \
172 \
173 Y += dY; \
174 X += dX; \
175 dp += channels; \
176 }
177
178/***************************************************************/
179#define MLIB_EDGE_BL(TYPE, Left, Right) \
180 dp = (TYPE*)data + channels * Left; \
181 size = Right - Left; \
182 \
183 for (j = 0; j < size; j++) { \
184 ySrc = ((Y - 32768) >> MLIB_SHIFT); \
185 xSrc = ((X - 32768) >> MLIB_SHIFT); \
186 \
187 t = ((X - 32768) & MLIB_MASK) * scale; \
188 u = ((Y - 32768) & MLIB_MASK) * scale; \
189 \
190 xDelta = (((xSrc + 1 - srcWidth )) >> MLIB_SIGN_SHIFT) & channels; \
191 yDelta = (((ySrc + 1 - srcHeight)) >> MLIB_SIGN_SHIFT) & srcStride; \
192 \
193 xFlag = (xSrc >> (MLIB_SIGN_SHIFT - MLIB_SHIFT)); \
194 xSrc = xSrc + (1 & xFlag); \
195 xDelta = xDelta &~ xFlag; \
196 \
197 yFlag = (ySrc >> (MLIB_SIGN_SHIFT - MLIB_SHIFT)); \
198 ySrc = ySrc + (1 & yFlag); \
199 yDelta = yDelta &~ yFlag; \
200 \
201 sp = (TYPE*)lineAddr[ySrc] + xSrc * channels; \
202 \
203 for (k = 0; k < channels; k++) { \
204 a00 = D64##TYPE(sp[0]); \
205 a01 = D64##TYPE(sp[xDelta]); \
206 a10 = D64##TYPE(sp[yDelta]); \
207 a11 = D64##TYPE(sp[yDelta + xDelta]); \
208 pix0 = (a00 * (1 - t) + a01 * t) * (1 - u) + \
209 (a10 * (1 - t) + a11 * t) * u; \
210 \
211 dp[k] = (TYPE)pix0; \
212 sp++; \
213 } \
214 \
215 X += dX; \
216 Y += dY; \
217 dp += channels; \
218 }
219
220/***************************************************************/
221#define LUT(k, ind) plut[channels*sp[ind] + k]
222
223/***************************************************************/
224#define MLIB_EDGE_INDEX(ITYPE, DTYPE, size) \
225 for (j = 0; j < size; j++) { \
226 ySrc = ((Y - 32768) >> MLIB_SHIFT); \
227 xSrc = ((X - 32768) >> MLIB_SHIFT); \
228 \
229 t = ((X - 32768) & MLIB_MASK) * scale; \
230 u = ((Y - 32768) & MLIB_MASK) * scale; \
231 \
232 xDelta = (((xSrc + 1 - srcWidth )) >> MLIB_SIGN_SHIFT) & 1; \
233 yDelta = (((ySrc + 1 - srcHeight)) >> MLIB_SIGN_SHIFT) & srcStride; \
234 \
235 xFlag = (xSrc >> (MLIB_SIGN_SHIFT - MLIB_SHIFT)); \
236 xSrc = xSrc + (1 & xFlag); \
237 xDelta = xDelta &~ xFlag; \
238 \
239 yFlag = (ySrc >> (MLIB_SIGN_SHIFT - MLIB_SHIFT)); \
240 ySrc = ySrc + (1 & yFlag); \
241 yDelta = yDelta &~ yFlag; \
242 \
243 sp = (ITYPE*)lineAddr[ySrc] + xSrc; \
244 \
245 for (k = 0; k < channels; k++) { \
246 a00 = LUT(k, 0); \
247 a01 = LUT(k, xDelta); \
248 a10 = LUT(k, yDelta); \
249 a11 = LUT(k, yDelta + xDelta); \
250 pix0 = (a00 * (1 - t) + a01 * t) * (1 - u) + \
251 (a10 * (1 - t) + a11 * t) * u; \
252 \
253 pbuff[k] = (mlib_s32)pix0; \
254 } \
255 pbuff += channels; \
256 \
257 X += dX; \
258 Y += dY; \
259 }
260
261/***************************************************************/
262#define MLIB_EDGE_INDEX_u8i(ITYPE, Left, Right) { \
263 mlib_u8 *pbuff = buff; \
264 \
265 size = Right - Left; \
266 \
267 MLIB_EDGE_INDEX(ITYPE, mlib_u8, size); \
268 \
269 dp = (ITYPE*)data + Left; \
270 \
271 if (channels == 3) { \
272 if (sizeof(ITYPE) == 1) { \
273 mlib_ImageColorTrue2IndexLine_U8_U8_3 (buff, (void*)dp, size, colormap); \
274 } else { \
275 mlib_ImageColorTrue2IndexLine_U8_S16_3(buff, (void*)dp, size, colormap); \
276 } \
277 } else { \
278 if (sizeof(ITYPE) == 1) { \
279 mlib_ImageColorTrue2IndexLine_U8_U8_4 (buff, (void*)dp, size, colormap); \
280 } else { \
281 mlib_ImageColorTrue2IndexLine_U8_S16_4(buff, (void*)dp, size, colormap); \
282 } \
283 } \
284}
285
286/***************************************************************/
287#define MLIB_EDGE_INDEX_s16i(ITYPE, Left, Right) { \
288 mlib_s16 *pbuff = buff; \
289 \
290 size = Right - Left; \
291 \
292 MLIB_EDGE_INDEX(ITYPE, mlib_s16, size); \
293 \
294 dp = (ITYPE*)data + Left; \
295 \
296 if (channels == 3) { \
297 if (sizeof(ITYPE) == 1) { \
298 mlib_ImageColorTrue2IndexLine_S16_U8_3 (buff, (void*)dp, size, colormap); \
299 } else { \
300 mlib_ImageColorTrue2IndexLine_S16_S16_3(buff, (void*)dp, size, colormap); \
301 } \
302 } else { \
303 if (sizeof(ITYPE) == 1) { \
304 mlib_ImageColorTrue2IndexLine_S16_U8_4 (buff, (void*)dp, size, colormap); \
305 } else { \
306 mlib_ImageColorTrue2IndexLine_S16_S16_4(buff, (void*)dp, size, colormap); \
307 } \
308 } \
309}
310
311/***************************************************************/
312#define GET_FLT_TBL(X, xf0, xf1, xf2, xf3) \
313 filterpos = ((X - 32768) >> flt_shift) & flt_mask; \
314 fptr = (mlib_f32 *) ((mlib_u8 *)flt_tbl + filterpos); \
315 \
316 xf0 = fptr[0]; \
317 xf1 = fptr[1]; \
318 xf2 = fptr[2]; \
319 xf3 = fptr[3]
320
321/***************************************************************/
322#define GET_FLT_BC(X, xf0, xf1, xf2, xf3) \
323 dx = ((X - 32768) & MLIB_MASK) * scale; \
324 dx_2 = 0.5 * dx; \
325 dx2 = dx * dx; \
326 dx3_2 = dx_2 * dx2; \
327 dx3_3 = 3.0 * dx3_2; \
328 \
329 xf0 = dx2 - dx3_2 - dx_2; \
330 xf1 = dx3_3 - 2.5 * dx2 + 1.0; \
331 xf2 = 2.0 * dx2 - dx3_3 + dx_2; \
332 xf3 = dx3_2 - 0.5 * dx2
333
334/***************************************************************/
335#define GET_FLT_BC2(X, xf0, xf1, xf2, xf3) \
336 dx = ((X - 32768) & MLIB_MASK) * scale; \
337 dx2 = dx * dx; \
338 dx3_2 = dx * dx2; \
339 dx3_3 = 2.0 * dx2; \
340 \
341 xf0 = - dx3_2 + dx3_3 - dx; \
342 xf1 = dx3_2 - dx3_3 + 1.0; \
343 xf2 = - dx3_2 + dx2 + dx; \
344 xf3 = dx3_2 - dx2
345
346/***************************************************************/
347#define CALC_SRC_POS(X, Y, channels, srcStride) \
348 xSrc = ((X - 32768) >> MLIB_SHIFT); \
349 ySrc = ((Y - 32768) >> MLIB_SHIFT); \
350 \
351 xDelta0 = ((~((xSrc - 1) >> MLIB_SIGN_SHIFT)) & (- channels)); \
352 yDelta0 = ((~((ySrc - 1) >> MLIB_SIGN_SHIFT)) & (- srcStride)); \
353 xDelta1 = ((xSrc + 1 - srcWidth) >> MLIB_SIGN_SHIFT) & (channels); \
354 yDelta1 = ((ySrc + 1 - srcHeight) >> MLIB_SIGN_SHIFT) & (srcStride); \
355 xDelta2 = xDelta1 + (((xSrc + 2 - srcWidth) >> MLIB_SIGN_SHIFT) & (channels)); \
356 yDelta2 = yDelta1 + (((ySrc + 2 - srcHeight) >> MLIB_SIGN_SHIFT) & (srcStride)); \
357 \
358 xFlag = (xSrc >> (MLIB_SIGN_SHIFT - MLIB_SHIFT)); \
359 xSrc = xSrc + (1 & xFlag); \
360 xDelta2 -= (xDelta1 & xFlag); \
361 xDelta1 = (xDelta1 &~ xFlag); \
362 \
363 yFlag = (ySrc >> (MLIB_SIGN_SHIFT - MLIB_SHIFT)); \
364 ySrc = ySrc + (1 & yFlag); \
365 yDelta2 -= (yDelta1 & yFlag); \
366 yDelta1 = yDelta1 &~ yFlag
367
368/***************************************************************/
369#define MLIB_EDGE_BC_LINE(TYPE, Left, Right, GET_FILTER) \
370 dp = (TYPE*)data + channels * Left; \
371 size = Right - Left; \
372 \
373 for (j = 0; j < size; j++) { \
374 GET_FILTER(X, xf0, xf1, xf2, xf3); \
375 GET_FILTER(Y, yf0, yf1, yf2, yf3); \
376 \
377 CALC_SRC_POS(X, Y, channels, srcStride); \
378 \
379 sp = (TYPE*)lineAddr[ySrc] + channels*xSrc; \
380 \
381 for (k = 0; k < channels; k++) { \
382 c0 = D64##TYPE(sp[yDelta0 + xDelta0]) * xf0 + \
383 D64##TYPE(sp[yDelta0 ]) * xf1 + \
384 D64##TYPE(sp[yDelta0 + xDelta1]) * xf2 + \
385 D64##TYPE(sp[yDelta0 + xDelta2]) * xf3; \
386 \
387 c1 = D64##TYPE(sp[xDelta0]) * xf0 + \
388 D64##TYPE(sp[ 0]) * xf1 + \
389 D64##TYPE(sp[xDelta1]) * xf2 + \
390 D64##TYPE(sp[xDelta2]) * xf3; \
391 \
392 c2 = D64##TYPE(sp[yDelta1 + xDelta0]) * xf0 + \
393 D64##TYPE(sp[yDelta1 ]) * xf1 + \
394 D64##TYPE(sp[yDelta1 + xDelta1]) * xf2 + \
395 D64##TYPE(sp[yDelta1 + xDelta2]) * xf3; \
396 \
397 c3 = D64##TYPE(sp[yDelta2 + xDelta0]) * xf0 + \
398 D64##TYPE(sp[yDelta2 ]) * xf1 + \
399 D64##TYPE(sp[yDelta2 + xDelta1]) * xf2 + \
400 D64##TYPE(sp[yDelta2 + xDelta2]) * xf3; \
401 \
402 val0 = c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3; \
403 \
404 SAT##TYPE(dp[k], val0); \
405 \
406 sp++; \
407 } \
408 \
409 X += dX; \
410 Y += dY; \
411 dp += channels; \
412 }
413
414/***************************************************************/
415#define MLIB_EDGE_BC_TBL(TYPE, Left, Right) \
416 MLIB_EDGE_BC_LINE(TYPE, Left, Right, GET_FLT_TBL)
417
418/***************************************************************/
419#define MLIB_EDGE_BC(TYPE, Left, Right) \
420 MLIB_EDGE_BC_LINE(TYPE, Left, Right, GET_FLT_BC)
421
422/***************************************************************/
423#define MLIB_EDGE_BC2(TYPE, Left, Right) \
424 MLIB_EDGE_BC_LINE(TYPE, Left, Right, GET_FLT_BC2)
425
426/***************************************************************/
427#define MLIB_EDGE_INDEX_BC(ITYPE, DTYPE, size) \
428 for (j = 0; j < size; j++) { \
429 GET_FLT_TBL(X, xf0, xf1, xf2, xf3); \
430 GET_FLT_TBL(Y, yf0, yf1, yf2, yf3); \
431 \
432 CALC_SRC_POS(X, Y, 1, srcStride); \
433 \
434 sp = (ITYPE*)lineAddr[ySrc] + xSrc; \
435 \
436 for (k = 0; k < channels; k++) { \
437 c0 = LUT(k, yDelta0 + xDelta0) * xf0 + \
438 LUT(k, yDelta0 ) * xf1 + \
439 LUT(k, yDelta0 + xDelta1) * xf2 + \
440 LUT(k, yDelta0 + xDelta2) * xf3; \
441 \
442 c1 = LUT(k, xDelta0) * xf0 + \
443 LUT(k, 0 ) * xf1 + \
444 LUT(k, xDelta1) * xf2 + \
445 LUT(k, xDelta2) * xf3; \
446 \
447 c2 = LUT(k, yDelta1 + xDelta0) * xf0 + \
448 LUT(k, yDelta1 ) * xf1 + \
449 LUT(k, yDelta1 + xDelta1) * xf2 + \
450 LUT(k, yDelta1 + xDelta2) * xf3; \
451 \
452 c3 = LUT(k, yDelta2 + xDelta0) * xf0 + \
453 LUT(k, yDelta2 ) * xf1 + \
454 LUT(k, yDelta2 + xDelta1) * xf2 + \
455 LUT(k, yDelta2 + xDelta2) * xf3; \
456 \
457 val0 = c0*yf0 + c1*yf1 + c2*yf2 + c3*yf3; \
458 \
459 SAT##DTYPE(pbuff[k], val0); \
460 } \
461 pbuff += channels; \
462 \
463 X += dX; \
464 Y += dY; \
465 }
466
467/***************************************************************/
468#define MLIB_PROCESS_EDGES_ZERO(TYPE) { \
469 TYPE *dp, *dstLineEnd; \
470 \
471 for (i = yStartE; i < yStart; i++) { \
472 xLeftE = leftEdgesE[i]; \
473 xRightE = rightEdgesE[i] + 1; \
474 data += dstStride; \
475 \
476 MLIB_EDGE_ZERO_LINE(TYPE, xLeftE, xRightE); \
477 } \
478 \
479 for (; i <= yFinish; i++) { \
480 xLeftE = leftEdgesE[i]; \
481 xRightE = rightEdgesE[i] + 1; \
482 xLeft = leftEdges[i]; \
483 xRight = rightEdges[i] + 1; \
484 data += dstStride; \
485 \
486 if (xLeft < xRight) { \
487 MLIB_EDGE_ZERO_LINE(TYPE, xLeftE, xLeft); \
488 } else { \
489 xRight = xLeftE; \
490 } \
491 \
492 MLIB_EDGE_ZERO_LINE(TYPE, xRight, xRightE); \
493 } \
494 \
495 for (; i <= yFinishE; i++) { \
496 xLeftE = leftEdgesE[i]; \
497 xRightE = rightEdgesE[i] + 1; \
498 data += dstStride; \
499 \
500 MLIB_EDGE_ZERO_LINE(TYPE, xLeftE, xRightE); \
501 } \
502}
503
504/***************************************************************/
505#define MLIB_PROCESS_EDGES(PROCESS_LINE, TYPE) { \
506 TYPE *sp, *dp; \
507 mlib_s32 k, size; \
508 \
509 for (i = yStartE; i < yStart; i++) { \
510 xLeftE = leftEdgesE[i]; \
511 xRightE = rightEdgesE[i] + 1; \
512 X = xStartsE[i]; \
513 Y = yStartsE[i]; \
514 data += dstStride; \
515 \
516 PROCESS_LINE(TYPE, xLeftE, xRightE); \
517 } \
518 \
519 for (; i <= yFinish; i++) { \
520 xLeftE = leftEdgesE[i]; \
521 xRightE = rightEdgesE[i] + 1; \
522 xLeft = leftEdges[i]; \
523 xRight = rightEdges[i] + 1; \
524 X = xStartsE[i]; \
525 Y = yStartsE[i]; \
526 data += dstStride; \
527 \
528 if (xLeft < xRight) { \
529 PROCESS_LINE(TYPE, xLeftE, xLeft); \
530 } else { \
531 xRight = xLeftE; \
532 } \
533 \
534 X = xStartsE[i] + dX * (xRight - xLeftE); \
535 Y = yStartsE[i] + dY * (xRight - xLeftE); \
536 PROCESS_LINE(TYPE, xRight, xRightE); \
537 } \
538 \
539 for (; i <= yFinishE; i++) { \
540 xLeftE = leftEdgesE[i]; \
541 xRightE = rightEdgesE[i] + 1; \
542 X = xStartsE[i]; \
543 Y = yStartsE[i]; \
544 data += dstStride; \
545 \
546 PROCESS_LINE(TYPE, xLeftE, xRightE); \
547 } \
548}
549
550/***************************************************************/
551#define GET_EDGE_PARAMS_ZERO() \
552 mlib_image *dst = param -> dst; \
553 mlib_s32 *leftEdges = param -> leftEdges; \
554 mlib_s32 *rightEdges = param -> rightEdges; \
555 mlib_s32 *leftEdgesE = param_e -> leftEdges; \
556 mlib_s32 *rightEdgesE = param_e -> rightEdges; \
557 mlib_type type = mlib_ImageGetType(dst); \
558 mlib_s32 channels = mlib_ImageGetChannels(dst); \
559 mlib_s32 dstStride = mlib_ImageGetStride(dst); \
560 mlib_s32 yStart = param -> yStart; \
561 mlib_s32 yFinish = param -> yFinish; \
562 mlib_s32 yStartE = param_e -> yStart; \
563 mlib_s32 yFinishE = param_e -> yFinish; \
564 mlib_u8 *data = param_e -> dstData; \
565 mlib_s32 xLeft, xRight, xLeftE, xRightE; \
566 mlib_s32 i
567
568/***************************************************************/
569#define GET_EDGE_PARAMS_NN() \
570 GET_EDGE_PARAMS_ZERO(); \
571 mlib_s32 *xStartsE = param_e -> xStarts; \
572 mlib_s32 *yStartsE = param_e -> yStarts; \
573 mlib_u8 **lineAddr = param -> lineAddr; \
574 mlib_s32 dX = param_e -> dX; \
575 mlib_s32 dY = param_e -> dY; \
576 mlib_s32 xSrc, ySrc, X, Y; \
577 mlib_s32 j
578
579/***************************************************************/
580#define GET_EDGE_PARAMS() \
581 GET_EDGE_PARAMS_NN(); \
582 mlib_image *src = param -> src; \
583 mlib_s32 srcWidth = mlib_ImageGetWidth(src); \
584 mlib_s32 srcHeight = mlib_ImageGetHeight(src); \
585 mlib_s32 srcStride = mlib_ImageGetStride(src)
586
587/***************************************************************/
588void mlib_ImageAffineEdgeZero(mlib_affine_param *param,
589 mlib_affine_param *param_e,
590 const void *colormap)
591{
592 GET_EDGE_PARAMS_ZERO();
593 mlib_s32 zero = 0;
594
595 if (colormap != NULL) {
596 zero = mlib_ImageGetLutOffset(colormap);
597 }
598
599 switch (type) {
600 case MLIB_BYTE:
601 MLIB_PROCESS_EDGES_ZERO(mlib_u8);
602 break;
603
604 case MLIB_SHORT:
605 case MLIB_USHORT:
606 MLIB_PROCESS_EDGES_ZERO(mlib_s16);
607 break;
608
609 case MLIB_INT:
610 case MLIB_FLOAT:
611 MLIB_PROCESS_EDGES_ZERO(mlib_s32);
612 break;
613
614 case MLIB_DOUBLE:{
615 mlib_d64 zero = 0;
616 MLIB_PROCESS_EDGES_ZERO(mlib_d64);
617 break;
618 }
619 }
620}
621
622/***************************************************************/
623void mlib_ImageAffineEdgeNearest(mlib_affine_param *param,
624 mlib_affine_param *param_e)
625{
626 GET_EDGE_PARAMS_NN();
627
628 switch (type) {
629 case MLIB_BYTE:
630 MLIB_PROCESS_EDGES(MLIB_EDGE_NEAREST_LINE, mlib_u8);
631 break;
632
633 case MLIB_SHORT:
634 case MLIB_USHORT:
635 MLIB_PROCESS_EDGES(MLIB_EDGE_NEAREST_LINE, mlib_s16);
636 break;
637
638 case MLIB_INT:
639 case MLIB_FLOAT:
640 MLIB_PROCESS_EDGES(MLIB_EDGE_NEAREST_LINE, mlib_s32);
641 break;
642
643 case MLIB_DOUBLE:
644 MLIB_PROCESS_EDGES(MLIB_EDGE_NEAREST_LINE, mlib_d64);
645 break;
646 }
647}
648
649/***************************************************************/
650mlib_status mlib_ImageAffineEdgeExtend_BL(mlib_affine_param *param,
651 mlib_affine_param *param_e,
652 const void *colormap)
653{
654 GET_EDGE_PARAMS();
655 mlib_d64 scale = 1.0 / (mlib_d64) MLIB_PREC;
656 mlib_s32 xDelta, yDelta, xFlag, yFlag;
657 mlib_d64 t, u, pix0;
658 mlib_d64 a00, a01, a10, a11;
659
660 if (colormap != NULL) {
661 mlib_s32 max_xsize = param_e->max_xsize;
662 mlib_type ltype = mlib_ImageGetLutType(colormap);
663 mlib_d64 *plut = (mlib_d64 *) mlib_ImageGetLutDoubleData(colormap);
664 void *buff;
665
666 channels = mlib_ImageGetLutChannels(colormap);
667 plut -= channels * mlib_ImageGetLutOffset(colormap);
668
669 if (max_xsize == 0) {
670 return MLIB_SUCCESS;
671 }
672
673 if (ltype == MLIB_BYTE) {
674 buff = mlib_malloc(channels * max_xsize);
675 }
676 else {
677 buff = mlib_malloc(channels * max_xsize * sizeof(mlib_s16));
678 }
679
680 if (buff == NULL)
681 return MLIB_FAILURE;
682
683 switch (ltype) {
684 case MLIB_BYTE:
685 switch (type) {
686 case MLIB_BYTE:
687 MLIB_PROCESS_EDGES(MLIB_EDGE_INDEX_u8i, mlib_u8);
688 break;
689
690 case MLIB_SHORT:
691 srcStride >>= 1;
692 MLIB_PROCESS_EDGES(MLIB_EDGE_INDEX_u8i, mlib_s16);
693 break;
694 }
695
696 break;
697
698 case MLIB_SHORT:
699 switch (type) {
700 case MLIB_BYTE:
701 MLIB_PROCESS_EDGES(MLIB_EDGE_INDEX_s16i, mlib_u8);
702 break;
703
704 case MLIB_SHORT:
705 srcStride >>= 1;
706 MLIB_PROCESS_EDGES(MLIB_EDGE_INDEX_s16i, mlib_s16);
707 break;
708 }
709
710 break;
711 }
712
713 mlib_free(buff);
714
715 return MLIB_SUCCESS;
716 }
717
718 switch (type) {
719 case MLIB_BYTE:
720 MLIB_PROCESS_EDGES(MLIB_EDGE_BL, mlib_u8);
721 break;
722
723 case MLIB_SHORT:
724 srcStride >>= 1;
725 MLIB_PROCESS_EDGES(MLIB_EDGE_BL, mlib_s16);
726 break;
727
728 case MLIB_USHORT:
729 srcStride >>= 1;
730 MLIB_PROCESS_EDGES(MLIB_EDGE_BL, mlib_u16);
731 break;
732
733 case MLIB_INT:
734 srcStride >>= 2;
735 MLIB_PROCESS_EDGES(MLIB_EDGE_BL, mlib_s32);
736 break;
737
738 case MLIB_FLOAT:
739 srcStride >>= 2;
740 MLIB_PROCESS_EDGES(MLIB_EDGE_BL, mlib_f32);
741 break;
742
743 case MLIB_DOUBLE:
744 srcStride >>= 3;
745 MLIB_PROCESS_EDGES(MLIB_EDGE_BL, mlib_d64);
746 break;
747 }
748
749 return MLIB_SUCCESS;
750}
751
752/***************************************************************/
753#undef MLIB_EDGE_INDEX
754#define MLIB_EDGE_INDEX MLIB_EDGE_INDEX_BC
755
756mlib_status mlib_ImageAffineEdgeExtend_BC(mlib_affine_param *param,
757 mlib_affine_param *param_e,
758 const void *colormap)
759{
760 GET_EDGE_PARAMS();
761 mlib_d64 scale = 1.0 / (mlib_d64) MLIB_PREC;
762 mlib_s32 xFlag, yFlag;
763 mlib_d64 dx, dx_2, dx2, dx3_2, dx3_3;
764 mlib_d64 xf0, xf1, xf2, xf3;
765 mlib_d64 yf0, yf1, yf2, yf3;
766 mlib_d64 c0, c1, c2, c3, val0;
767 mlib_type ltype;
768 mlib_filter filter = param->filter;
769 mlib_f32 *fptr;
770 mlib_f32 const *flt_tbl;
771 mlib_s32 filterpos, flt_shift, flt_mask;
772 mlib_s32 xDelta0, xDelta1, xDelta2;
773 mlib_s32 yDelta0, yDelta1, yDelta2;
774 mlib_d64 sat;
775
776 ltype = (colormap != NULL) ? mlib_ImageGetLutType(colormap) : type;
777
778 if (ltype == MLIB_BYTE) {
779 flt_shift = FLT_SHIFT_U8;
780 flt_mask = FLT_MASK_U8;
781 flt_tbl = (filter == MLIB_BICUBIC) ? mlib_filters_u8f_bc : mlib_filters_u8f_bc2;
782 sat = (mlib_d64) 0x7F800000; /* saturation for U8 */
783 }
784 else {
785 flt_shift = FLT_SHIFT_S16;
786 flt_mask = FLT_MASK_S16;
787 flt_tbl = (filter == MLIB_BICUBIC) ? mlib_filters_s16f_bc : mlib_filters_s16f_bc2;
788 sat = (mlib_d64) 0x7FFF8000; /* saturation for U16 */
789 }
790
791 if (colormap != NULL) {
792 mlib_s32 max_xsize = param_e->max_xsize;
793 mlib_d64 *plut = (mlib_d64 *) mlib_ImageGetLutDoubleData(colormap);
794 void *buff;
795
796 channels = mlib_ImageGetLutChannels(colormap);
797 plut -= channels * mlib_ImageGetLutOffset(colormap);
798
799 if (max_xsize == 0) {
800 return MLIB_SUCCESS;
801 }
802
803 if (ltype == MLIB_BYTE) {
804 buff = mlib_malloc(channels * max_xsize);
805 }
806 else {
807 buff = mlib_malloc(channels * max_xsize * sizeof(mlib_s16));
808 }
809
810 if (buff == NULL)
811 return MLIB_FAILURE;
812
813 switch (ltype) {
814 case MLIB_BYTE:
815 switch (type) {
816 case MLIB_BYTE:
817 MLIB_PROCESS_EDGES(MLIB_EDGE_INDEX_u8i, mlib_u8);
818 break;
819
820 case MLIB_SHORT:
821 srcStride >>= 1;
822 MLIB_PROCESS_EDGES(MLIB_EDGE_INDEX_u8i, mlib_s16);
823 break;
824 }
825
826 break;
827
828 case MLIB_SHORT:
829 switch (type) {
830 case MLIB_BYTE:
831 MLIB_PROCESS_EDGES(MLIB_EDGE_INDEX_s16i, mlib_u8);
832 break;
833
834 case MLIB_SHORT:
835 srcStride >>= 1;
836 MLIB_PROCESS_EDGES(MLIB_EDGE_INDEX_s16i, mlib_s16);
837 break;
838 }
839
840 break;
841 }
842
843 mlib_free(buff);
844
845 return MLIB_SUCCESS;
846 }
847
848 switch (type) {
849 case MLIB_BYTE:
850 MLIB_PROCESS_EDGES(MLIB_EDGE_BC_TBL, mlib_u8);
851 break;
852
853 case MLIB_SHORT:
854 srcStride >>= 1;
855 MLIB_PROCESS_EDGES(MLIB_EDGE_BC_TBL, mlib_s16);
856 break;
857
858 case MLIB_USHORT:
859 srcStride >>= 1;
860 MLIB_PROCESS_EDGES(MLIB_EDGE_BC_TBL, mlib_u16);
861 break;
862
863 case MLIB_INT:
864 srcStride >>= 2;
865
866 if (filter == MLIB_BICUBIC) {
867 MLIB_PROCESS_EDGES(MLIB_EDGE_BC, mlib_s32);
868 }
869 else {
870 MLIB_PROCESS_EDGES(MLIB_EDGE_BC2, mlib_s32);
871 }
872
873 break;
874
875 case MLIB_FLOAT:
876 srcStride >>= 2;
877
878 if (filter == MLIB_BICUBIC) {
879 MLIB_PROCESS_EDGES(MLIB_EDGE_BC, mlib_f32);
880 }
881 else {
882 MLIB_PROCESS_EDGES(MLIB_EDGE_BC2, mlib_f32);
883 }
884
885 break;
886
887 case MLIB_DOUBLE:
888 srcStride >>= 3;
889
890 if (filter == MLIB_BICUBIC) {
891 MLIB_PROCESS_EDGES(MLIB_EDGE_BC, mlib_d64);
892 }
893 else {
894 MLIB_PROCESS_EDGES(MLIB_EDGE_BC2, mlib_d64);
895 }
896
897 break;
898 }
899
900 return MLIB_SUCCESS;
901}
902
903/***************************************************************/