• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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