Home | History | Annotate | Download | only in b_ImageEm
      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) */
     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 
     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 
    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 
    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