1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /* ---- includes ----------------------------------------------------------- */
18
19 #include "b_ImageEm/Functions.h"
20
21 /* ---- related objects --------------------------------------------------- */
22
23 /* ---- typedefs ----------------------------------------------------------- */
24
25 /* ---- constants ---------------------------------------------------------- */
26
27 /* ------------------------------------------------------------------------- */
28
29 /* ========================================================================= */
30 /* */
31 /* ---- \ghd{ external functions } ----------------------------------------- */
32 /* */
33 /* ========================================================================= */
34
35 /* ------------------------------------------------------------------------- */
36
37 /** downscale by factor 2 (dstPtrA and srcPtrA may be identical) */
bim_downscaleBy2(uint8 * dstPtrA,const uint8 * srcPtrA,uint32 srcWidthA,uint32 effWidthA,uint32 effHeightA)38 void bim_downscaleBy2( uint8* dstPtrA,
39 const uint8* srcPtrA,
40 uint32 srcWidthA,
41 uint32 effWidthA,
42 uint32 effHeightA )
43 {
44 uint32 wsL = srcWidthA;
45 uint32 w0L = effWidthA;
46 uint32 h0L = effHeightA;
47 uint32 w1L = w0L >> 1;
48 uint32 h1L = h0L >> 1;
49
50 const uint8* srcL = srcPtrA;
51 uint8* dstL = dstPtrA;
52
53 uint32 iL, jL;
54 for( jL = 0; jL < h1L; jL++ )
55 {
56 for( iL = 0; iL < w1L; iL++ )
57 {
58 *dstL = ( ( uint32 )srcL[ 0 ] + srcL[ 1 ] + srcL[ wsL ] + srcL[ wsL + 1 ] + 2 ) >> 2;
59 dstL++;
60 srcL += 2;
61 }
62 srcL += ( wsL - w1L ) * 2;
63 }
64 }
65
66 /* ------------------------------------------------------------------------- */
67
bim_filterWarpInterpolation(struct bbs_Context * cpA,uint8 * dstImagePtrA,const uint8 * srcImagePtrA,uint32 srcImageWidthA,uint32 srcImageHeightA,const struct bts_Int16Vec2D * offsPtrA,const struct bts_Flt16Alt2D * altPtrA,uint32 dstWidthA,uint32 dstHeightA,struct bbs_UInt8Arr * bufPtrA,uint32 scaleThresholdA)68 void bim_filterWarpInterpolation( struct bbs_Context* cpA,
69 uint8* dstImagePtrA,
70 const uint8* srcImagePtrA,
71 uint32 srcImageWidthA,
72 uint32 srcImageHeightA,
73 const struct bts_Int16Vec2D* offsPtrA,
74 const struct bts_Flt16Alt2D* altPtrA,
75 uint32 dstWidthA,
76 uint32 dstHeightA,
77 struct bbs_UInt8Arr* bufPtrA,
78 uint32 scaleThresholdA )
79 {
80 bbs_DEF_fNameL( "bim_filterWarpInterpolation" )
81
82 uint32 w0L = srcImageWidthA;
83 uint32 h0L = srcImageHeightA;
84
85 const uint8* srcL = srcImagePtrA;
86 uint8* dstL = dstImagePtrA;
87
88 uint32 w1L = w0L;
89 uint32 h1L = h0L;
90
91 /* 16.16 */
92 uint32 scaleThrL = scaleThresholdA;
93 struct bts_Flt16Alt2D invAltL;
94
95 /* matrix variables */
96 int32 mxxL, mxyL, myxL, myyL, txL, tyL;
97
98 flag downScaledL = FALSE;
99 flag boundsOkL = TRUE;
100
101 if( w0L == 0 || h0L == 0 || bts_Flt16Mat2D_det( &altPtrA->matE ) == 0 )
102 {
103 uint32 iL;
104 for( iL = 0; iL < dstWidthA * dstHeightA; iL++ ) dstImagePtrA[ iL ] = 0;
105 return;
106 }
107
108 /* compute inverse ALT */
109 invAltL = bts_Flt16Alt2D_inverted( altPtrA );
110
111 /* fixed point ALT 16.16 */
112 if( invAltL.matE.bbpE <= 16 )
113 {
114 uint32 shlL = 16 - invAltL.matE.bbpE;
115 mxxL = invAltL.matE.xxE << shlL;
116 mxyL = invAltL.matE.xyE << shlL;
117 myxL = invAltL.matE.yxE << shlL;
118 myyL = invAltL.matE.yyE << shlL;
119 }
120 else
121 {
122 uint32 shrL = invAltL.matE.bbpE - 16;
123 mxxL = ( ( invAltL.matE.xxE >> ( shrL - 1 ) ) + 1 ) >> 1;
124 mxyL = ( ( invAltL.matE.xyE >> ( shrL - 1 ) ) + 1 ) >> 1;
125 myxL = ( ( invAltL.matE.yxE >> ( shrL - 1 ) ) + 1 ) >> 1;
126 myyL = ( ( invAltL.matE.yyE >> ( shrL - 1 ) ) + 1 ) >> 1;
127 }
128
129 if( invAltL.vecE.bbpE <= 16 )
130 {
131 uint32 shlL = 16 - invAltL.vecE.bbpE;
132 txL = invAltL.vecE.xE << shlL;
133 tyL = invAltL.vecE.yE << shlL;
134 }
135 else
136 {
137 uint32 shrL = invAltL.vecE.bbpE - 16;
138 txL = ( ( invAltL.vecE.xE >> ( shrL - 1 ) ) + 1 ) >> 1;
139 tyL = ( ( invAltL.vecE.yE >> ( shrL - 1 ) ) + 1 ) >> 1;
140 }
141
142 /* add offset */
143 txL += ( int32 )offsPtrA->xE << 16;
144 tyL += ( int32 )offsPtrA->yE << 16;
145
146 if( scaleThresholdA > 0 )
147 {
148 /* compute downscale exponent */
149 uint32 axxL = ( mxxL >= 0 ) ? mxxL : -mxxL;
150 uint32 axyL = ( mxyL >= 0 ) ? mxyL : -mxyL;
151 uint32 ayxL = ( myxL >= 0 ) ? myxL : -myxL;
152 uint32 ayyL = ( myyL >= 0 ) ? myyL : -myyL;
153
154 uint32 a1L = ( axxL > ayxL ) ? axxL : ayxL;
155 uint32 a2L = ( axyL > ayyL ) ? axyL : ayyL;
156
157 uint32 invScaleL = ( a1L < a2L ) ? a1L : a2L;
158 uint32 scaleExpL = 0;
159 while( ( invScaleL >> scaleExpL ) > scaleThrL ) scaleExpL++;
160 while( ( scaleExpL > 0 ) && ( w0L >> scaleExpL ) < 2 ) scaleExpL--;
161 while( ( scaleExpL > 0 ) && ( h0L >> scaleExpL ) < 2 ) scaleExpL--;
162
163 /* downscale image */
164 if( scaleExpL > 0 )
165 {
166 /* down sampling is limited to the effective area of the original image */
167
168 /* compute effective area by mapping all corners of the dst rectangle */
169 int32 xMinL = 0x7FFFFFFF;
170 int32 yMinL = 0x7FFFFFFF;
171 int32 xMaxL = 0x80000000;
172 int32 yMaxL = 0x80000000;
173 uint32 wEffL, hEffL;
174
175 {
176 int32 xL, yL;
177 xL = txL;
178 yL = tyL;
179 xMinL = xL < xMinL ? xL : xMinL;
180 yMinL = yL < yMinL ? yL : yMinL;
181 xMaxL = xL > xMaxL ? xL : xMaxL;
182 yMaxL = yL > yMaxL ? yL : yMaxL;
183 xL = txL + mxxL * ( int32 )dstWidthA + mxyL * ( int32 )dstHeightA;
184 yL = tyL + myxL * ( int32 )dstWidthA + myyL * ( int32 )dstHeightA;
185 xMinL = xL < xMinL ? xL : xMinL;
186 yMinL = yL < yMinL ? yL : yMinL;
187 xMaxL = xL > xMaxL ? xL : xMaxL;
188 yMaxL = yL > yMaxL ? yL : yMaxL;
189 xL = txL + mxyL * ( int32 )dstHeightA;
190 yL = tyL + myyL * ( int32 )dstHeightA;
191 xMinL = xL < xMinL ? xL : xMinL;
192 yMinL = yL < yMinL ? yL : yMinL;
193 xMaxL = xL > xMaxL ? xL : xMaxL;
194 yMaxL = yL > yMaxL ? yL : yMaxL;
195 xL = txL + mxxL * ( int32 )dstWidthA;
196 yL = tyL + myxL * ( int32 )dstWidthA;
197 xMinL = xL < xMinL ? xL : xMinL;
198 yMinL = yL < yMinL ? yL : yMinL;
199 xMaxL = xL > xMaxL ? xL : xMaxL;
200 yMaxL = yL > yMaxL ? yL : yMaxL;
201 }
202
203 xMaxL = ( xMaxL >> 16 ) + 2;
204 yMaxL = ( yMaxL >> 16 ) + 2;
205 xMinL >>= 16;
206 yMinL >>= 16;
207
208 /* ensre effective area stays within original frame */
209 xMinL = 0 > xMinL ? 0 : xMinL;
210 yMinL = 0 > yMinL ? 0 : yMinL;
211 xMinL = ( int32 )w0L < xMinL ? w0L : xMinL;
212 yMinL = ( int32 )h0L < yMinL ? h0L : yMinL;
213 xMaxL = 0 > xMaxL ? 0 : xMaxL;
214 yMaxL = 0 > yMaxL ? 0 : yMaxL;
215 xMaxL = ( int32 )w0L < xMaxL ? w0L : xMaxL;
216 yMaxL = ( int32 )h0L < yMaxL ? h0L : yMaxL;
217
218 wEffL = xMaxL - xMinL;
219 hEffL = yMaxL - yMinL;
220
221 /* ensure downscaling does not reduce image to 0 */
222 while( ( scaleExpL > 0 ) && ( wEffL >> scaleExpL ) < 2 ) scaleExpL--;
223 while( ( scaleExpL > 0 ) && ( hEffL >> scaleExpL ) < 2 ) scaleExpL--;
224
225 /* downscale */
226 if( scaleExpL > 0 )
227 {
228 uint32 iL;
229 w1L = wEffL >> 1;
230 h1L = hEffL >> 1;
231 if( bufPtrA == NULL ) bbs_ERROR1( "%s:\nPreallocated buffer is needed", fNameL );
232 bbs_UInt8Arr_size( cpA, bufPtrA, w1L * h1L );
233 bim_downscaleBy2( bufPtrA->arrPtrE, srcL + yMinL * w0L + xMinL, w0L, wEffL, hEffL );
234 for( iL = 1; iL < scaleExpL; iL++ )
235 {
236 bim_downscaleBy2( bufPtrA->arrPtrE, bufPtrA->arrPtrE, w1L, w1L, h1L );
237 w1L >>= 1;
238 h1L >>= 1;
239 }
240
241 /* adjust inverted cordinates */
242 txL -= ( xMinL << 16 );
243 tyL -= ( yMinL << 16 );
244 mxxL >>= scaleExpL;
245 mxyL >>= scaleExpL;
246 myxL >>= scaleExpL;
247 myyL >>= scaleExpL;
248 txL >>= scaleExpL;
249 tyL >>= scaleExpL;
250 srcL = bufPtrA->arrPtrE;
251 }
252
253 downScaledL = TRUE;
254 }
255 }
256
257 /* if not downscaled and src and dst images are identcal then copy srcImage into buffer */
258 if( !downScaledL && dstImagePtrA == srcImagePtrA )
259 {
260 uint32 iL;
261 uint32 srcSizeL = srcImageWidthA * srcImageHeightA;
262 if( bufPtrA == NULL ) bbs_ERROR1( "%s:\nPreallocated buffer is needed", fNameL );
263 bbs_UInt8Arr_size( cpA, bufPtrA, srcSizeL );
264 for( iL = 0; iL < srcSizeL; iL++ ) bufPtrA->arrPtrE[ iL ] = srcImagePtrA[ iL ];
265 srcL = bufPtrA->arrPtrE;
266 }
267
268 /* compute destination image */
269
270 /* bounds check (dst image fully inside src image? -> fast algorithm) */
271 {
272 int32 xL, yL;
273 int32 wbL = w1L - 1;
274 int32 hbL = h1L - 1;
275
276 xL = txL >> 16;
277 yL = tyL >> 16;
278 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL );
279
280 xL = ( txL + mxxL * ( int32 )( dstWidthA - 1 ) ) >> 16;
281 yL = ( tyL + myxL * ( int32 )( dstWidthA - 1 ) ) >> 16;
282 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL );
283
284 xL = ( txL + mxyL * ( int32 )( dstHeightA - 1 ) ) >> 16;
285 yL = ( tyL + myyL * ( int32 )( dstHeightA - 1 ) ) >> 16;
286 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL );
287
288 xL = ( txL + mxyL * ( int32 )( dstHeightA - 1 ) + mxxL * ( int32 )( dstWidthA - 1 ) ) >> 16;
289 yL = ( tyL + myyL * ( int32 )( dstHeightA - 1 ) + myxL * ( int32 )( dstWidthA - 1 ) ) >> 16;
290 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL );
291 }
292
293 if( boundsOkL )
294 {
295 int32 iL, jL;
296 for( jL = 0; jL < ( int32 )dstHeightA; jL++ )
297 {
298 /* 16.16 */
299 int32 xL = txL + mxyL * jL;
300 int32 yL = tyL + myyL * jL;
301 for( iL = 0; iL < ( int32 )dstWidthA; iL++ )
302 {
303 int32 x0L = xL >> 16;
304 int32 y0L = yL >> 16;
305 uint32 xf2L = xL & 0x0FFFF;
306 uint32 yf2L = yL & 0x0FFFF;
307 uint32 xf1L = 0x10000 - xf2L;
308 uint32 yf1L = 0x10000 - yf2L;
309
310 xL += mxxL;
311 yL += myxL;
312
313 {
314 uint32 idxL = y0L * w1L + x0L;
315 uint32 v1L = ( ( uint32 )srcL[ idxL ] * xf1L + ( uint32 )srcL[ idxL + 1 ] * xf2L + 0x0800 ) >> 12;
316 uint32 v2L = ( ( uint32 )srcL[ idxL + w1L ] * xf1L + ( uint32 )srcL[ idxL + w1L + 1 ] * xf2L + 0x0800 ) >> 12;
317 *dstL++ = ( v1L * yf1L + v2L * yf2L + 0x080000 ) >> 20;
318 }
319 }
320 }
321 }
322 else
323 {
324 int32 iL, jL;
325 for( jL = 0; jL < ( int32 )dstHeightA; jL++ )
326 {
327 /* 16.16 */
328 int32 xL = txL + mxyL * jL;
329 int32 yL = tyL + myyL * jL;
330 for( iL = 0; iL < ( int32 )dstWidthA; iL++ )
331 {
332 int32 x0L = xL >> 16;
333 int32 y0L = yL >> 16;
334 uint32 xf2L = xL & 0x0FFFF;
335 uint32 yf2L = yL & 0x0FFFF;
336 uint32 xf1L = 0x10000 - xf2L;
337 uint32 yf1L = 0x10000 - yf2L;
338
339 xL += mxxL;
340 yL += myxL;
341
342 if( y0L < 0 )
343 {
344 if( x0L < 0 )
345 {
346 *dstL++ = srcL[ 0 ];
347 }
348 else if( x0L >= ( int32 )w1L - 1 )
349 {
350 *dstL++ = srcL[ w1L - 1 ];
351 }
352 else
353 {
354 *dstL++ = ( ( uint32 )srcL[ x0L ] * xf1L + ( uint32 )srcL[ x0L + 1 ] * xf2L + 0x08000 ) >> 16;
355 }
356 }
357 else if( y0L >= ( int32 )h1L - 1 )
358 {
359 if( x0L < 0 )
360 {
361 *dstL++ = srcL[ ( h1L - 1 ) * w1L ];
362 }
363 else if( x0L >= ( int32 )w1L - 1 )
364 {
365 *dstL++ = srcL[ ( h1L * w1L ) - 1 ];
366 }
367 else
368 {
369 uint32 idxL = ( h1L - 1 ) * w1L + x0L;
370 *dstL++ = ( ( uint32 )srcL[ idxL ] * xf1L + ( uint32 )srcL[ idxL + 1 ] * xf2L + 0x08000 ) >> 16;
371 }
372 }
373 else
374 {
375 if( x0L < 0 )
376 {
377 uint32 idxL = y0L * w1L;
378 *dstL++ = ( ( uint32 )srcL[ idxL ] * yf1L + ( uint32 )srcL[ idxL + w1L ] * yf2L + 0x08000 ) >> 16;
379 }
380 else if( x0L >= ( int32 )w1L - 1 )
381 {
382 uint32 idxL = ( y0L + 1 ) * w1L - 1;
383 *dstL++ = ( ( uint32 )srcL[ idxL ] * yf1L + ( uint32 )srcL[ idxL + w1L ] * yf2L + 0x08000 ) >> 16;
384 }
385 else
386 {
387 uint32 idxL = y0L * w1L + x0L;
388 uint32 v1L = ( ( uint32 )srcL[ idxL ] * xf1L + ( uint32 )srcL[ idxL + 1 ] * xf2L + 0x0800 ) >> 12;
389 uint32 v2L = ( ( uint32 )srcL[ idxL + w1L ] * xf1L + ( uint32 )srcL[ idxL + w1L + 1 ] * xf2L + 0x0800 ) >> 12;
390 *dstL++ = ( v1L * yf1L + v2L * yf2L + 0x080000 ) >> 20;
391 }
392 }
393 }
394 }
395 }
396 }
397
398 /* ------------------------------------------------------------------------- */
399
bim_filterWarpPixelReplication(struct bbs_Context * cpA,uint8 * dstImagePtrA,const uint8 * srcImagePtrA,uint32 srcImageWidthA,uint32 srcImageHeightA,const struct bts_Int16Vec2D * offsPtrA,const struct bts_Flt16Alt2D * altPtrA,uint32 dstWidthA,uint32 dstHeightA,struct bbs_UInt8Arr * bufPtrA,uint32 scaleThresholdA)400 void bim_filterWarpPixelReplication( struct bbs_Context* cpA,
401 uint8* dstImagePtrA,
402 const uint8* srcImagePtrA,
403 uint32 srcImageWidthA,
404 uint32 srcImageHeightA,
405 const struct bts_Int16Vec2D* offsPtrA,
406 const struct bts_Flt16Alt2D* altPtrA,
407 uint32 dstWidthA,
408 uint32 dstHeightA,
409 struct bbs_UInt8Arr* bufPtrA,
410 uint32 scaleThresholdA )
411 {
412 bbs_DEF_fNameL( "bim_filterWarpPixelReplication" )
413
414 uint32 w0L = srcImageWidthA;
415 uint32 h0L = srcImageHeightA;
416
417 const uint8* srcL = srcImagePtrA;
418 uint8* dstL = dstImagePtrA;
419
420 uint32 w1L = w0L;
421 uint32 h1L = h0L;
422
423 /* 16.16 */
424 uint32 scaleThrL = scaleThresholdA;
425 struct bts_Flt16Alt2D invAltL;
426
427 /* matrix variables */
428 int32 mxxL, mxyL, myxL, myyL, txL, tyL;
429
430 flag downScaledL = FALSE;
431 flag boundsOkL = TRUE;
432
433 if( w0L == 0 || h0L == 0 || bts_Flt16Mat2D_det( &altPtrA->matE ) == 0 )
434 {
435 uint32 iL;
436 for( iL = 0; iL < dstWidthA * dstHeightA; iL++ ) dstImagePtrA[ iL ] = 0;
437 return;
438 }
439
440 /* compute inverse ALT */
441 invAltL = bts_Flt16Alt2D_inverted( altPtrA );
442
443 /* fixed point ALT 16.16 */
444 if( invAltL.matE.bbpE <= 16 )
445 {
446 uint32 shlL = 16 - invAltL.matE.bbpE;
447 mxxL = invAltL.matE.xxE << shlL;
448 mxyL = invAltL.matE.xyE << shlL;
449 myxL = invAltL.matE.yxE << shlL;
450 myyL = invAltL.matE.yyE << shlL;
451 }
452 else
453 {
454 uint32 shrL = invAltL.matE.bbpE - 16;
455 mxxL = ( ( invAltL.matE.xxE >> ( shrL - 1 ) ) + 1 ) >> 1;
456 mxyL = ( ( invAltL.matE.xyE >> ( shrL - 1 ) ) + 1 ) >> 1;
457 myxL = ( ( invAltL.matE.yxE >> ( shrL - 1 ) ) + 1 ) >> 1;
458 myyL = ( ( invAltL.matE.yyE >> ( shrL - 1 ) ) + 1 ) >> 1;
459 }
460
461 if( invAltL.vecE.bbpE <= 16 )
462 {
463 uint32 shlL = 16 - invAltL.vecE.bbpE;
464 txL = invAltL.vecE.xE << shlL;
465 tyL = invAltL.vecE.yE << shlL;
466 }
467 else
468 {
469 uint32 shrL = invAltL.vecE.bbpE - 16;
470 txL = ( ( invAltL.vecE.xE >> ( shrL - 1 ) ) + 1 ) >> 1;
471 tyL = ( ( invAltL.vecE.yE >> ( shrL - 1 ) ) + 1 ) >> 1;
472 }
473
474 /* add offset */
475 txL += ( int32 )offsPtrA->xE << 16;
476 tyL += ( int32 )offsPtrA->yE << 16;
477
478 if( scaleThresholdA > 0 )
479 {
480 /* compute downscale exponent */
481 uint32 axxL = ( mxxL >= 0 ) ? mxxL : -mxxL;
482 uint32 axyL = ( mxyL >= 0 ) ? mxyL : -mxyL;
483 uint32 ayxL = ( myxL >= 0 ) ? myxL : -myxL;
484 uint32 ayyL = ( myyL >= 0 ) ? myyL : -myyL;
485
486 uint32 a1L = ( axxL > ayxL ) ? axxL : ayxL;
487 uint32 a2L = ( axyL > ayyL ) ? axyL : ayyL;
488
489 uint32 invScaleL = ( a1L < a2L ) ? a1L : a2L;
490 uint32 scaleExpL = 0;
491 while( ( invScaleL >> scaleExpL ) > scaleThrL ) scaleExpL++;
492 while( ( scaleExpL > 0 ) && ( w0L >> scaleExpL ) < 2 ) scaleExpL--;
493 while( ( scaleExpL > 0 ) && ( h0L >> scaleExpL ) < 2 ) scaleExpL--;
494
495 /* downscale image */
496 if( scaleExpL > 0 )
497 {
498 /* down sampling is limited to the effective area of the original image */
499
500 /* compute effective area by mapping all corners of the dst rectangle */
501 int32 xMinL = 0x7FFFFFFF;
502 int32 yMinL = 0x7FFFFFFF;
503 int32 xMaxL = 0x80000000;
504 int32 yMaxL = 0x80000000;
505 uint32 wEffL, hEffL;
506
507 {
508 int32 xL, yL;
509 xL = txL;
510 yL = tyL;
511 xMinL = xL < xMinL ? xL : xMinL;
512 yMinL = yL < yMinL ? yL : yMinL;
513 xMaxL = xL > xMaxL ? xL : xMaxL;
514 yMaxL = yL > yMaxL ? yL : yMaxL;
515 xL = txL + mxxL * ( int32 )dstWidthA + mxyL * ( int32 )dstHeightA;
516 yL = tyL + myxL * ( int32 )dstWidthA + myyL * ( int32 )dstHeightA;
517 xMinL = xL < xMinL ? xL : xMinL;
518 yMinL = yL < yMinL ? yL : yMinL;
519 xMaxL = xL > xMaxL ? xL : xMaxL;
520 yMaxL = yL > yMaxL ? yL : yMaxL;
521 xL = txL + mxyL * ( int32 )dstHeightA;
522 yL = tyL + myyL * ( int32 )dstHeightA;
523 xMinL = xL < xMinL ? xL : xMinL;
524 yMinL = yL < yMinL ? yL : yMinL;
525 xMaxL = xL > xMaxL ? xL : xMaxL;
526 yMaxL = yL > yMaxL ? yL : yMaxL;
527 xL = txL + mxxL * ( int32 )dstWidthA;
528 yL = tyL + myxL * ( int32 )dstWidthA;
529 xMinL = xL < xMinL ? xL : xMinL;
530 yMinL = yL < yMinL ? yL : yMinL;
531 xMaxL = xL > xMaxL ? xL : xMaxL;
532 yMaxL = yL > yMaxL ? yL : yMaxL;
533 }
534
535 xMaxL = ( xMaxL >> 16 ) + 2;
536 yMaxL = ( yMaxL >> 16 ) + 2;
537 xMinL >>= 16;
538 yMinL >>= 16;
539
540 /* ensre effective area stays within original frame */
541 xMinL = 0 > xMinL ? 0 : xMinL;
542 yMinL = 0 > yMinL ? 0 : yMinL;
543 xMinL = ( int32 )w0L < xMinL ? w0L : xMinL;
544 yMinL = ( int32 )h0L < yMinL ? h0L : yMinL;
545 xMaxL = 0 > xMaxL ? 0 : xMaxL;
546 yMaxL = 0 > yMaxL ? 0 : yMaxL;
547 xMaxL = ( int32 )w0L < xMaxL ? w0L : xMaxL;
548 yMaxL = ( int32 )h0L < yMaxL ? h0L : yMaxL;
549
550 wEffL = xMaxL - xMinL;
551 hEffL = yMaxL - yMinL;
552
553 /* ensure downscaling does not reduce image to 0 */
554 while( ( scaleExpL > 0 ) && ( wEffL >> scaleExpL ) < 2 ) scaleExpL--;
555 while( ( scaleExpL > 0 ) && ( hEffL >> scaleExpL ) < 2 ) scaleExpL--;
556
557 /* downscale */
558 if( scaleExpL > 0 )
559 {
560 uint32 iL;
561 w1L = wEffL >> 1;
562 h1L = hEffL >> 1;
563 if( bufPtrA == NULL ) bbs_ERROR1( "%s:\nPreallocated buffer is needed", fNameL );
564 bbs_UInt8Arr_size( cpA, bufPtrA, w1L * h1L );
565 bim_downscaleBy2( bufPtrA->arrPtrE, srcL + yMinL * w0L + xMinL, w0L, wEffL, hEffL );
566 for( iL = 1; iL < scaleExpL; iL++ )
567 {
568 bim_downscaleBy2( bufPtrA->arrPtrE, bufPtrA->arrPtrE, w1L, w1L, h1L );
569 w1L >>= 1;
570 h1L >>= 1;
571 }
572
573 /* adjust inverted cordinates */
574 txL -= ( xMinL << 16 );
575 tyL -= ( yMinL << 16 );
576 mxxL >>= scaleExpL;
577 mxyL >>= scaleExpL;
578 myxL >>= scaleExpL;
579 myyL >>= scaleExpL;
580 txL >>= scaleExpL;
581 tyL >>= scaleExpL;
582 srcL = bufPtrA->arrPtrE;
583 }
584
585 downScaledL = TRUE;
586 }
587 }
588
589 /* if not downscaled and src and dst images are identcal then copy srcImage into buffer */
590 if( !downScaledL && dstImagePtrA == srcImagePtrA )
591 {
592 uint32 iL;
593 uint32 srcSizeL = srcImageWidthA * srcImageHeightA;
594 if( bufPtrA == NULL ) bbs_ERROR1( "%s:\nPreallocated buffer is needed", fNameL );
595 bbs_UInt8Arr_size( cpA, bufPtrA, srcSizeL );
596 for( iL = 0; iL < srcSizeL; iL++ ) bufPtrA->arrPtrE[ iL ] = srcImagePtrA[ iL ];
597 srcL = bufPtrA->arrPtrE;
598 }
599
600 /* compute destination image */
601
602 /* bounds check (dst image fully inside src image? -> fast algorithm) */
603 {
604 int32 xL, yL;
605 int32 wbL = w1L - 1;
606 int32 hbL = h1L - 1;
607
608 xL = txL >> 16;
609 yL = tyL >> 16;
610 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL );
611
612 xL = ( txL + mxxL * ( int32 )( dstWidthA - 1 ) ) >> 16;
613 yL = ( tyL + myxL * ( int32 )( dstWidthA - 1 ) ) >> 16;
614 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL );
615
616 xL = ( txL + mxyL * ( int32 )( dstHeightA - 1 ) ) >> 16;
617 yL = ( tyL + myyL * ( int32 )( dstHeightA - 1 ) ) >> 16;
618 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL );
619
620 xL = ( txL + mxyL * ( int32 )( dstHeightA - 1 ) + mxxL * ( int32 )( dstWidthA - 1 ) ) >> 16;
621 yL = ( tyL + myyL * ( int32 )( dstHeightA - 1 ) + myxL * ( int32 )( dstWidthA - 1 ) ) >> 16;
622 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL );
623 }
624
625 if( boundsOkL )
626 {
627 int32 iL, jL;
628 for( jL = 0; jL < ( int32 )dstHeightA; jL++ )
629 {
630 /* 16.16 */
631 int32 xL = txL + mxyL * jL;
632 int32 yL = tyL + myyL * jL;
633 for( iL = 0; iL < ( int32 )dstWidthA; iL++ )
634 {
635 /* nearest whole position */
636 *dstL++ = srcL[ ( ( ( yL >> 15 ) + 1 ) >> 1 ) * w1L + ( ( ( xL >> 15 ) + 1 ) >> 1 ) ];
637 xL += mxxL;
638 yL += myxL;
639 }
640 }
641 }
642 else
643 {
644 int32 iL, jL;
645 for( jL = 0; jL < ( int32 )dstHeightA; jL++ )
646 {
647 /* 16.16 */
648 int32 xL = txL + mxyL * jL;
649 int32 yL = tyL + myyL * jL;
650 for( iL = 0; iL < ( int32 )dstWidthA; iL++ )
651 {
652 /* nearest whole position */
653 int32 x0L = ( ( xL >> 15 ) + 1 ) >> 1;
654 int32 y0L = ( ( yL >> 15 ) + 1 ) >> 1;
655 xL += mxxL;
656 yL += myxL;
657
658 if( y0L < 0 )
659 {
660 if( x0L < 0 )
661 {
662 *dstL++ = srcL[ 0 ];
663 }
664 else if( x0L >= ( int32 )w1L - 1 )
665 {
666 *dstL++ = srcL[ w1L - 1 ];
667 }
668 else
669 {
670 *dstL++ = srcL[ x0L ];
671 }
672 }
673 else if( y0L >= ( int32 )h1L - 1 )
674 {
675 if( x0L < 0 )
676 {
677 *dstL++ = srcL[ ( h1L - 1 ) * w1L ];
678 }
679 else if( x0L >= ( int32 )w1L - 1 )
680 {
681 *dstL++ = srcL[ ( h1L * w1L ) - 1 ];
682 }
683 else
684 {
685 *dstL++ = srcL[ ( h1L - 1 ) * w1L + x0L ];
686 }
687 }
688 else
689 {
690 if( x0L < 0 )
691 {
692 *dstL++ = srcL[ y0L * w1L ];
693 }
694 else if( x0L >= ( int32 )w1L - 1 )
695 {
696 *dstL++ = srcL[ ( y0L + 1 ) * w1L - 1 ];
697 }
698 else
699 {
700 *dstL++ = srcL[ y0L * w1L + x0L ];
701 }
702 }
703 }
704 }
705 }
706 }
707
708 /* ------------------------------------------------------------------------- */
709
bim_filterWarp(struct bbs_Context * cpA,uint8 * dstImagePtrA,const uint8 * srcImagePtrA,uint32 srcImageWidthA,uint32 srcImageHeightA,const struct bts_Int16Vec2D * offsPtrA,const struct bts_Flt16Alt2D * altPtrA,uint32 dstWidthA,uint32 dstHeightA,struct bbs_UInt8Arr * bufPtrA,uint32 scaleThresholdA,flag interpolateA)710 void bim_filterWarp( struct bbs_Context* cpA,
711 uint8* dstImagePtrA,
712 const uint8* srcImagePtrA,
713 uint32 srcImageWidthA,
714 uint32 srcImageHeightA,
715 const struct bts_Int16Vec2D* offsPtrA,
716 const struct bts_Flt16Alt2D* altPtrA,
717 uint32 dstWidthA,
718 uint32 dstHeightA,
719 struct bbs_UInt8Arr* bufPtrA,
720 uint32 scaleThresholdA,
721 flag interpolateA )
722 {
723 if( interpolateA )
724 {
725 bim_filterWarpInterpolation( cpA, dstImagePtrA, srcImagePtrA, srcImageWidthA, srcImageHeightA, offsPtrA, altPtrA, dstWidthA, dstHeightA, bufPtrA, scaleThresholdA );
726 }
727 else
728 {
729 bim_filterWarpPixelReplication( cpA, dstImagePtrA, srcImagePtrA, srcImageWidthA, srcImageHeightA, offsPtrA, altPtrA, dstWidthA, dstHeightA, bufPtrA, scaleThresholdA );
730 }
731 }
732
733 /* ------------------------------------------------------------------------- */
734
735