C++程序  |  877行  |  27.01 KB

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* ---- includes ----------------------------------------------------------- */

#include "b_BasicEm/Math.h"
#include "b_BasicEm/Functions.h"
#include "b_ImageEm/UInt16ByteImage.h"

/* ------------------------------------------------------------------------- */

/* ========================================================================= */
/*                                                                           */
/* ---- \ghd{ auxiliary functions } ---------------------------------------- */
/*                                                                           */
/* ========================================================================= */

/* ------------------------------------------------------------------------- */

/* ========================================================================= */
/*                                                                           */
/* ---- \ghd{ constructor / destructor } ----------------------------------- */
/*                                                                           */
/* ========================================================================= */

/* ------------------------------------------------------------------------- */

void bim_UInt16ByteImage_init( struct bbs_Context* cpA,
							   struct bim_UInt16ByteImage* ptrA )
{
	bbs_UInt16Arr_init( cpA, &ptrA->arrE );
	ptrA->widthE = 0;
	ptrA->heightE = 0;
}

/* ------------------------------------------------------------------------- */

void bim_UInt16ByteImage_exit( struct bbs_Context* cpA,
							   struct bim_UInt16ByteImage* ptrA )
{
	bbs_UInt16Arr_exit( cpA, &ptrA->arrE );
	ptrA->widthE = 0;
	ptrA->heightE = 0;	
}

/* ------------------------------------------------------------------------- */

/* ========================================================================= */
/*                                                                           */
/* ---- \ghd{ operators } -------------------------------------------------- */
/*                                                                           */
/* ========================================================================= */

/* ------------------------------------------------------------------------- */

void bim_UInt16ByteImage_copy( struct bbs_Context* cpA,
							   struct bim_UInt16ByteImage* ptrA, 
							   const struct bim_UInt16ByteImage* srcPtrA )
{
#ifdef DEBUG1
	if( ptrA->arrE.sizeE < srcPtrA->arrE.sizeE )
	{
		bbs_ERROR0( "void bim_UInt16ByteImage_copy( struct bim_UInt16ByteImage*, const struct bim_UInt16ByteImage* ):\n"
				   "Unsufficient allocated memory in destination image" );		
		return;
	}
#endif
	ptrA->widthE = srcPtrA->widthE;
	ptrA->heightE = srcPtrA->heightE;
	bbs_UInt16Arr_copy( cpA, &ptrA->arrE, &srcPtrA->arrE );
}

/* ------------------------------------------------------------------------- */

flag bim_UInt16ByteImage_equal( struct bbs_Context* cpA,
							    const struct bim_UInt16ByteImage* ptrA, 
								const struct bim_UInt16ByteImage* srcPtrA )
{
	if( ptrA->widthE != srcPtrA->widthE ) return FALSE;
	if( ptrA->heightE != srcPtrA->heightE ) return FALSE;
	return bbs_UInt16Arr_equal( cpA, &ptrA->arrE, &srcPtrA->arrE );
}

/* ------------------------------------------------------------------------- */

/* ========================================================================= */
/*                                                                           */
/* ---- \ghd{ query functions } -------------------------------------------- */
/*                                                                           */
/* ========================================================================= */

/* ------------------------------------------------------------------------- */

uint32 bim_UInt16ByteImage_checkSum( struct bbs_Context* cpA,
									 const struct bim_UInt16ByteImage* ptrA )
{
	uint32 sumL =0 ;
	uint32 iL;
	uint32 sizeL = ptrA->arrE.sizeE;
	const uint16* ptrL = ptrA->arrE.arrPtrE;
	for( iL =0; iL < sizeL; iL++ )
	{
		sumL += *ptrL++;
	}
	return sumL;
}

/* ------------------------------------------------------------------------- */

/* ========================================================================= */
/*                                                                           */
/* ---- \ghd{ modify functions } ------------------------------------------- */
/*                                                                           */
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
	
void bim_UInt16ByteImage_create( struct bbs_Context* cpA,
								 struct bim_UInt16ByteImage* ptrA, 
						         uint32 widthA, 
							     uint32 heightA,
 					             struct bbs_MemSeg* mspA )
{
	if( bbs_Context_error( cpA ) ) return;
	if( widthA & 1 )
	{
		bbs_ERROR0( "bim_UInt16ByteImage_create( .... ): width of image must be even" );
		return;
	}

	if( ptrA->arrE.arrPtrE != 0 )
	{
		bim_UInt16ByteImage_size( cpA, ptrA, widthA, heightA );
	}
	else
	{
		bbs_UInt16Arr_create( cpA, &ptrA->arrE, ( widthA * heightA ) >> 1, mspA );
		ptrA->widthE  = widthA;
		ptrA->heightE = heightA;
	}
}

/* ------------------------------------------------------------------------- */

void bim_UInt16ByteImage_assignExternalImage( struct bbs_Context* cpA,
											  struct bim_UInt16ByteImage* ptrA, 
											  struct bim_UInt16ByteImage* srcPtrA )
{
	struct bbs_MemSeg sharedSegL = bbs_MemSeg_createShared( cpA, srcPtrA->arrE.arrPtrE, ( srcPtrA->widthE * srcPtrA->heightE ) / 2 );

	if( ptrA->arrE.arrPtrE != 0 )
	{
		bbs_ERROR0( "void bim_UInt16ByteImage_assignExternalImage( ... ): image was already created once" );
		return;
	}

	bim_UInt16ByteImage_create( cpA, ptrA, 
					            srcPtrA->widthE, 
						        srcPtrA->heightE,
						        &sharedSegL );
}

/* ------------------------------------------------------------------------- */
	
void bim_UInt16ByteImage_size( struct bbs_Context* cpA,
							   struct bim_UInt16ByteImage* ptrA, 
							   uint32 widthA, uint32 heightA )
{
	if( widthA & 1 )
	{
		bbs_ERROR0( "bim_UInt16ByteImage_size( .... ): width of image must be even" );
		return;
	}

	if( ptrA->arrE.allocatedSizeE < ( ( widthA * heightA ) >> 1 ) )
	{
		bbs_ERROR0( "void bim_UInt16ByteImage_size( struct bim_UInt16ByteImage*, uint32 sizeA ):\n"
				   "Unsufficient allocated memory" );
		return;
	}
	bbs_UInt16Arr_size( cpA, &ptrA->arrE, ( widthA * heightA ) >> 1 );
	ptrA->widthE  = widthA;
	ptrA->heightE = heightA;
}

/* ------------------------------------------------------------------------- */
	
/* ========================================================================= */
/*                                                                           */
/* ---- \ghd{ I/O } -------------------------------------------------------- */
/*                                                                           */
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
	
uint32 bim_UInt16ByteImage_memSize( struct bbs_Context* cpA,
								    const struct bim_UInt16ByteImage* ptrA )
{
	return  bbs_SIZEOF16( uint32 )
		  + bbs_SIZEOF16( uint32 ) /* version */
		  + bbs_SIZEOF16( ptrA->widthE ) 
		  + bbs_SIZEOF16( ptrA->heightE )
		  + bbs_UInt16Arr_memSize( cpA, &ptrA->arrE ); 
}

/* ------------------------------------------------------------------------- */
	
uint32 bim_UInt16ByteImage_memWrite( struct bbs_Context* cpA,
									 const struct bim_UInt16ByteImage* ptrA, 
									 uint16* memPtrA )
{
	uint32 memSizeL = bim_UInt16ByteImage_memSize( cpA, ptrA );
	memPtrA += bbs_memWrite32( &memSizeL, memPtrA );
	memPtrA += bbs_memWriteUInt32( bim_UINT16_IMAGE_VERSION, memPtrA );
	memPtrA += bbs_memWrite32( &ptrA->widthE, memPtrA );
	memPtrA += bbs_memWrite32( &ptrA->heightE, memPtrA );
	bbs_UInt16Arr_memWrite( cpA, &ptrA->arrE, memPtrA );
	return memSizeL;
}

/* ------------------------------------------------------------------------- */
	
uint32 bim_UInt16ByteImage_memRead( struct bbs_Context* cpA,
								    struct bim_UInt16ByteImage* ptrA, 
							   const uint16* memPtrA,
 					           struct bbs_MemSeg* mspA )
{
	uint32 memSizeL, versionL, widthL, heightL;
	if( bbs_Context_error( cpA ) ) return 0;
	memPtrA += bbs_memRead32( &memSizeL, memPtrA );
	memPtrA += bbs_memReadVersion32( cpA, &versionL, bim_UINT16_IMAGE_VERSION, memPtrA );
	memPtrA += bbs_memRead32( &widthL, memPtrA );
	memPtrA += bbs_memRead32( &heightL, memPtrA );

	ptrA->widthE  = widthL;
	ptrA->heightE = heightL;
	bbs_UInt16Arr_memRead( cpA, &ptrA->arrE, memPtrA, mspA );

	if( memSizeL != bim_UInt16ByteImage_memSize( cpA, ptrA ) )
	{
		bbs_ERR0( bbs_ERR_CORRUPT_DATA, "uint32 bim_UInt16ByteImage_memRead( const struct bim_UInt16ByteImage* ptrA, const void* memPtrA ):\n"
                   "size mismatch" ); 
		return 0;
	}
	return memSizeL;
}

/* ------------------------------------------------------------------------- */
	
/* ========================================================================= */
/*                                                                           */
/* ---- \ghd{ exec functions } --------------------------------------------- */
/*                                                                           */
/* ========================================================================= */

/* ------------------------------------------------------------------------- */

void bim_UInt16ByteImage_setAllPixels( struct bbs_Context* cpA,
									   struct bim_UInt16ByteImage* ptrA, 
									   uint16 valueA )
{
	long iL;
	uint16* ptrL = ptrA->arrE.arrPtrE;
	uint16 fillL = ( valueA & 0x0FF ) | ( ( valueA & 0x0FF ) << 8 );
	for( iL = ptrA->arrE.sizeE; iL > 0; iL-- )
	{
		*ptrL++ = fillL;
	}
}

/* ------------------------------------------------------------------------- */

/**
		M-------------------------------------------------------M
		|				|						|				|
		|				|						|				|
		|				|						|				|
		|				|						|				|
		|	region x0y0	|		region x1y0		|	region x2y0	|
		|				|						|				|
		|				|						|				|
		|				|						|				|
		|---------------I-----------------------I---------------|
		|				|						|				|
		|				|						|				|
		|				|						|				|
		|				|						|				|
		|				|						|				|
		|				|						|				|
		|	region x0y1	|		region x1y1		|	region x2y1	|
		|				|						|				|
		|				|						|				|
		|				|						|				|
		|				|						|				|
		|				|						|				|
		|				|						|				|
		|				|						|				|
		|---------------I-----------------------I---------------|
		|				|						|				|
		|				|						|				|
		|				|						|				|
		|				|						|				|
		|	region x0y2	|		region x1y2		|	region x2y2	|
		|				|						|				|
		|				|						|				|
		|				|						|				|
		M-------------------------------------------------------M


  To see how the code is organized. Refer to the diagram above.
  Assume the original image after applying the tranzformations(translation, rotation and scaling) is "O" 
	(boundaries of the image are shown above bounded by the letter 'O').
  This image is being Warped to the area "M" (boundaries of this area are bounded by the letter 'M').
  
  Refer to the source code below to point to the loop that maps pixels in the particular region.
*/

/** applies affine linear warping to pixels positions of imageA before copying the into *ptrA */
void bim_UInt16ByteImage_warp( struct bbs_Context* cpA,
							   struct bim_UInt16ByteImage* ptrA, 
						       const struct bim_UInt16ByteImage* srcPtrA, 
						       const struct bts_Flt16Alt2D* altPtrA,
			                   int32 resultWidthA,
			                   int32 resultHeightA )
{
	long srcWidthL = srcPtrA->widthE;
	long srcHeightL = srcPtrA->heightE;
	long halfSrcWidthL = srcWidthL >> 1;
	
	struct bts_Flt16Alt2D invAlt2DL;
	
	uint16* dstPtrL;
	const uint16* ulPtrL = srcPtrA->arrE.arrPtrE;
	const uint16* urPtrL = ulPtrL + halfSrcWidthL - 1;
	const uint16* llPtrL = ulPtrL + ( srcHeightL - 1 ) * halfSrcWidthL;
	const uint16* lrPtrL = llPtrL + halfSrcWidthL - 1;
	
	uint32 iL, jL;
	int32 shiftL;

	const uint16 bbpL = 16;
	int32 maxInt32Value8bbpL  = 0x7FFFFFFF;

	/* The bbp for all these variables is the same as bbpL */
	int32 mxxL;
	int32 mxyL;
	int32 myxL;
	int32 myyL;

	int32 txL;
	int32 tyL;

	int32 xL;
	int32 yL;

	bim_UInt16ByteImage_size( cpA, ptrA, resultWidthA, resultHeightA );
	dstPtrL = ptrA->arrE.arrPtrE;
	
	/* compute inverse */
	invAlt2DL = bts_Flt16Alt2D_inverted( altPtrA );
	
	if( srcWidthL == 0 || srcHeightL == 0 )
	{
		bim_UInt16ByteImage_size( cpA, ptrA, srcWidthL, srcHeightL );
		bbs_ERROR2( "Size of output image is %d/%d", srcWidthL, srcHeightL );
		return;
	}

	/* align Matrix and Vector to 8 bits bbp */
	shiftL = invAlt2DL.matE.bbpE - bbpL;
	if( shiftL >= 0 )
	{
		mxxL = ( int32 )invAlt2DL.matE.xxE >> shiftL;
		mxyL = ( int32 )invAlt2DL.matE.xyE >> shiftL;
		myxL = ( int32 )invAlt2DL.matE.yxE >> shiftL;
		myyL = ( int32 )invAlt2DL.matE.yyE >> shiftL;
	}
	else
	{
		/* Check for overflow since we are left shifting. */
		maxInt32Value8bbpL >>= -shiftL;
		if( invAlt2DL.matE.xxE > maxInt32Value8bbpL ||
			invAlt2DL.matE.xyE > maxInt32Value8bbpL ||
			invAlt2DL.matE.yxE > maxInt32Value8bbpL ||
			invAlt2DL.matE.yyE > maxInt32Value8bbpL )
		{
			/* Overflow error */
			bbs_ERROR5( "The values in the transformation matrix cause overflow during bitshift\n%d, %d,\n%d, %d\n"
						"The maximum allowed value is %d", 
						invAlt2DL.matE.xxE >> invAlt2DL.matE.bbpE,
						invAlt2DL.matE.xyE >> invAlt2DL.matE.bbpE,
						invAlt2DL.matE.yxE >> invAlt2DL.matE.bbpE,
						invAlt2DL.matE.yyE >> invAlt2DL.matE.bbpE,
						maxInt32Value8bbpL >> ( bbpL - ( -shiftL ) ) );
			return;
		}

		mxxL = ( int32 )invAlt2DL.matE.xxE << -shiftL;
		mxyL = ( int32 )invAlt2DL.matE.xyE << -shiftL;
		myxL = ( int32 )invAlt2DL.matE.yxE << -shiftL;
		myyL = ( int32 )invAlt2DL.matE.yyE << -shiftL;
		maxInt32Value8bbpL <<= -shiftL;
	}
	invAlt2DL.matE.bbpE = bbpL;

	shiftL = invAlt2DL.vecE.bbpE - bbpL;
	if( shiftL >= 0 )
	{
		txL  = ( int32 )invAlt2DL.vecE.xE >> shiftL;
		tyL  = ( int32 )invAlt2DL.vecE.yE >> shiftL;
	}
	else
	{
		/* Check for overflow since we are left shifting. */
		maxInt32Value8bbpL >>= -shiftL;
		if(	invAlt2DL.vecE.xE  > maxInt32Value8bbpL ||
			invAlt2DL.vecE.yE  > maxInt32Value8bbpL )
		{
			/* Overflow error */
			bbs_ERROR3( "The values in the vector cause overflow during bitshift\n%d, %d,\n"
						"The maximum allowed value is %d", 
						invAlt2DL.vecE.xE >> invAlt2DL.vecE.bbpE,
						invAlt2DL.vecE.yE >> invAlt2DL.vecE.bbpE,
						maxInt32Value8bbpL >> ( bbpL - ( -shiftL ) ) );
			return;
		}
		txL  = ( int32 )invAlt2DL.vecE.xE << -shiftL;
		tyL  = ( int32 )invAlt2DL.vecE.yE << -shiftL;
		maxInt32Value8bbpL <<= -shiftL;
	}
	invAlt2DL.vecE.bbpE = bbpL;

	/* For each destination pixel find the correspoding source pixel by applying the inverse transformation */
	for( jL = 0; jL < ptrA->heightE; jL++ )
	{
		xL = txL + mxyL * jL;
		yL = tyL + myyL * jL;
		for( iL = 0; iL < ptrA->widthE; iL++ )
		{
			const uint16 bbpLby2L = bbpL / 2;
			const int32 oneL = ( int32 )0x00000001 << bbpLby2L;
			const int32 fractionOnlyL = 0xFFFFFFFF >> ( 32 - bbpL );
			uint16 dstPixelL;

			/* The bbp for all these variables is the same as bbpLby2L */
			int32 f2xL;
			int32 f2yL;
			int32 f1xL;
			int32 f1yL;

			/* always whole numbers with a bbp of 0 */
			int32 kL, khL;
			int32 lL;

			flag kEvenL;

			/* The bbpE for these variables is bbpLby2L */
			int32 valL;

			/* Get the whole numbers only and make the bbp 0. */
			kL = xL >> bbpL;
			lL = yL >> bbpL;

			khL = kL >> 1;
			kEvenL = !( kL & 1 );

			/* fraction of destination pixel in the next source pixel */
			f2xL = ( xL & fractionOnlyL ) >> bbpLby2L;
			f2yL = ( yL & fractionOnlyL ) >> bbpLby2L;
			/* fraction of destination pixel in the current source pixel */
			f1xL = oneL - f2xL;
			f1yL = oneL - f2yL;

			/* increment values for next loop */
			xL += mxxL;
			yL += myxL;

			if( lL < 0 )
			{
				if( kL < 0 )
				{
					/* handle all pixels in region x0y0 */
					dstPixelL = *ulPtrL & 0x0FF;
				}
				else if( kL >= srcWidthL - 1 )
				{
					/* handle all pixels in region x2y0 */
					dstPixelL = *urPtrL >> 8;
				}
				else
				{
					/* handle all pixels in region x1y0 */
					/* The bbp has shifted left by bbpLby2L */
					if( kEvenL )
					{
						uint16 srcL = *( ulPtrL + khL );
						valL = f1xL * ( srcL & 0x00FF )  +  f2xL * ( srcL >> 8 );
					}
					else
					{
						valL =  f1xL * ( *( ulPtrL + khL ) >> 8 ) + f2xL * ( *( ulPtrL + khL + 1 ) & 0x0FF );
					}
					dstPixelL = valL >> bbpLby2L;
				}
			} /* if( lL < 0 ) */
			else if( lL >= srcHeightL - 1 )
			{
				if( kL < 0 )
				{
					/* handle all pixels in region x0y2 */
					dstPixelL = *llPtrL & 0x0FF;
				}
				else if( kL >= srcWidthL - 1 )
				{
					/* handle all pixels in region x2y2 */
					dstPixelL = *lrPtrL >> 8;
				}
				else
				{
					/* handle all pixels in region x1y2 */
					/* The bbp has shifted left by bbpLby2L */
					if( kEvenL )
					{
						uint16 srcL = *( llPtrL + khL );
						valL = f1xL * ( srcL & 0x00FF ) + f2xL * ( srcL >> 8 );
					}
					else
					{
						valL =  f1xL * ( *( llPtrL + khL ) >> 8 ) + f2xL * ( *( llPtrL + khL + 1 ) & 0x0FF );
					}

					dstPixelL = valL >> bbpLby2L;
				}
			} /* if( lL >= srcHeightL - 1 ) */
			else
			{
				const uint16* ptr1L;
				const uint16* ptr2L;

				ptr1L = ulPtrL + lL * halfSrcWidthL;
				/* point to the pixel in the same column */
				ptr2L = ptr1L + halfSrcWidthL;
				if( kL < 0 )
				{
					/* handle all pixels in region x0y1 */
					valL =  f1yL * ( *ptr1L & 0x0FF ) + f2yL * ( *ptr2L & 0x0FF );
					dstPixelL = valL >> bbpLby2L;
				}
				else if( kL >= srcWidthL - 1 )
				{
					/* handle all pixels in region x2y1 */
					valL = f1yL * ( *( ptr1L + halfSrcWidthL - 1 ) >> 8 ) + 
						   f2yL * ( *( ptr2L + halfSrcWidthL - 1 ) >> 8 );
					dstPixelL = valL >> bbpLby2L;
				}
				else
				{
					/* assuming that bbpL = bbpLby2 * 2 */
					/* The bbp for these variables is bbpL */
					int32 v1L;
					int32 v2L;
					const int32 halfL = ( int32 )0x00000001 << ( bbpL - 1 );
	
					/* handle all pixels in region x1y1 */
					if( kEvenL )
					{
						#ifdef HW_BIG_ENDIAN
							/* Our images are in byte order for big & little endian  so when using a
                                                           16bit ptr our bytes will be swapped on big endian hardware shift and mask*/
							v1L = f1xL * ( *( ptr1L + khL ) >> 8 ) + f2xL * ( *( ptr1L + khL ) & 0x0FF );
							v2L = f1xL * ( *( ptr2L + khL ) >> 8 ) + f2xL * ( *( ptr2L + khL ) & 0x0FF );
						#else
							v1L = f1xL * ( *( ptr1L + khL ) & 0x0FF ) + f2xL * ( *( ptr1L + khL ) >> 8 );
							v2L = f1xL * ( *( ptr2L + khL ) & 0x0FF ) + f2xL * ( *( ptr2L + khL ) >> 8 );
						#endif
					}
					else
					{
						#ifdef HW_BIG_ENDIAN
							v1L = f1xL * ( *( ptr1L + khL ) & 0x0FF ) + f2xL * ( *( ptr1L + khL + 1 ) >> 8 );
							v2L = f1xL * ( *( ptr2L + khL ) & 0x0FF ) + f2xL * ( *( ptr2L + khL + 1 ) >> 8 );
						#else					
							v1L = f1xL * ( *( ptr1L + khL ) >> 8 ) + f2xL * ( *( ptr1L + khL + 1 ) & 0x0FF );
							v2L = f1xL * ( *( ptr2L + khL ) >> 8 ) + f2xL * ( *( ptr2L + khL + 1 ) & 0x0FF );
						#endif
					}
					/* adding the half to round off the resulting value */
					valL = v1L * f1yL + v2L * f2yL + halfL;
					dstPixelL = valL >> bbpL;
				}
			}

			if( iL & 1 )
			{
				#ifdef HW_BIG_ENDIAN
					*dstPtrL |= dstPixelL & 0x0FF;
				#else			
					*dstPtrL |= dstPixelL << 8;
				#endif
				dstPtrL++;
			}
			else
			{
				#ifdef HW_BIG_ENDIAN
					*dstPtrL = dstPixelL << 8;
				#else			
					*dstPtrL = dstPixelL & 0x0FF;
				#endif
			}

		} /* iL loop */
	} /* jL loop */

}

/* ------------------------------------------------------------------------- */

#ifndef HW_TMS320C5x /* 16bit architecture excluded */

void bim_UInt16ByteImage_warp8( struct bbs_Context* cpA,
							    struct bim_UInt16ByteImage* ptrA, 
							    const struct bim_UInt16ByteImage* srcPtrA, 
							    const struct bts_Flt16Alt2D* altPtrA,
							    int32 resultWidthA,
							    int32 resultHeightA )
{
	long srcWidthL = srcPtrA->widthE;
	long srcHeightL = srcPtrA->heightE;
	
	struct bts_Flt16Alt2D invAlt2DL;
	
	uint8* dstPtrL;
	const uint8* ulPtrL = ( const uint8* )srcPtrA->arrE.arrPtrE;
	const uint8* urPtrL = ulPtrL + srcWidthL - 1;
	const uint8* llPtrL = ulPtrL + ( srcHeightL - 1 ) * srcWidthL;
	const uint8* lrPtrL = llPtrL + srcWidthL - 1;
	
	uint32 iL, jL;
	int32 shiftL;

	const uint16 bbpL = 16;
	int32 maxInt32Value8bbpL  = 0x7FFFFFFF;

	/* The bbp for all these variables is the same as bbpL */
	int32 mxxL;
	int32 mxyL;
	int32 myxL;
	int32 myyL;

	int32 txL;
	int32 tyL;

	int32 xL;
	int32 yL;

	bim_UInt16ByteImage_size( cpA, ptrA, resultWidthA, resultHeightA );
	dstPtrL = ( uint8* )ptrA->arrE.arrPtrE;
	
	/* compute inverse */
	invAlt2DL = bts_Flt16Alt2D_inverted( altPtrA );
	
	if( srcWidthL == 0 || srcHeightL == 0 )
	{
		bbs_ERROR2( "Size of output image is %d/%d", srcWidthL, srcHeightL );
		return;
	}

	/* align Matrix and Vector to 8 bits bbp */
	shiftL = invAlt2DL.matE.bbpE - bbpL;
	if( shiftL >= 0 )
	{
		mxxL = ( int32 )invAlt2DL.matE.xxE >> shiftL;
		mxyL = ( int32 )invAlt2DL.matE.xyE >> shiftL;
		myxL = ( int32 )invAlt2DL.matE.yxE >> shiftL;
		myyL = ( int32 )invAlt2DL.matE.yyE >> shiftL;
	}
	else
	{
		/* Check for overflow since we are left shifting. */
		maxInt32Value8bbpL >>= -shiftL;
		if( invAlt2DL.matE.xxE > maxInt32Value8bbpL ||
			invAlt2DL.matE.xyE > maxInt32Value8bbpL ||
			invAlt2DL.matE.yxE > maxInt32Value8bbpL ||
			invAlt2DL.matE.yyE > maxInt32Value8bbpL )
		{
			/* Overflow error */
			bbs_ERROR5( "The values in the transformation matrix cause overflow during bitshift\n%d, %d,\n%d, %d\n"
						"The maximum allowed value is %d", 
						( int32 )invAlt2DL.matE.xxE >> invAlt2DL.matE.bbpE,
						( int32 )invAlt2DL.matE.xyE >> invAlt2DL.matE.bbpE,
						( int32 )invAlt2DL.matE.yxE >> invAlt2DL.matE.bbpE,
						( int32 )invAlt2DL.matE.yyE >> invAlt2DL.matE.bbpE,
						maxInt32Value8bbpL >> ( bbpL - ( -shiftL ) ) );
			return;
		}

		mxxL = ( int32 )invAlt2DL.matE.xxE << -shiftL;
		mxyL = ( int32 )invAlt2DL.matE.xyE << -shiftL;
		myxL = ( int32 )invAlt2DL.matE.yxE << -shiftL;
		myyL = ( int32 )invAlt2DL.matE.yyE << -shiftL;
		maxInt32Value8bbpL <<= -shiftL;
	}
	invAlt2DL.matE.bbpE = bbpL;

	shiftL = invAlt2DL.vecE.bbpE - bbpL;
	if( shiftL >= 0 )
	{
		txL  = ( int32 )invAlt2DL.vecE.xE >> shiftL;
		tyL  = ( int32 )invAlt2DL.vecE.yE >> shiftL;
	}
	else
	{
		/* Check for overflow since we are left shifting. */
		maxInt32Value8bbpL >>= -shiftL;
		if(	invAlt2DL.vecE.xE  > maxInt32Value8bbpL ||
			invAlt2DL.vecE.yE  > maxInt32Value8bbpL )
		{
			/* Overflow error */
			bbs_ERROR3( "The values in the vector cause overflow during bitshift\n%d, %d,\n"
						"The maximum allowed value is %d", 
						invAlt2DL.vecE.xE >> invAlt2DL.vecE.bbpE,
						invAlt2DL.vecE.yE >> invAlt2DL.vecE.bbpE,
						maxInt32Value8bbpL >> ( bbpL - ( -shiftL ) ) );
			return;
		}
		txL  = ( int32 )invAlt2DL.vecE.xE << -shiftL;
		tyL  = ( int32 )invAlt2DL.vecE.yE << -shiftL;
		maxInt32Value8bbpL <<= -shiftL;
	}
	invAlt2DL.vecE.bbpE = bbpL;

	/* For each destination pixel find the correspoding source pixel by applying the inverse transformation */
	for( jL = 0; jL < ptrA->heightE; jL++ )
	{
		xL = txL + mxyL * jL;
		yL = tyL + myyL * jL;
		for( iL = 0; iL < ptrA->widthE; iL++ )
		{
			const uint16 bbpLby2L = bbpL / 2;
			const int32 oneL = ( int32 )0x00000001 << bbpLby2L;
			const int32 fractionOnlyL = 0xFFFFFFFF >> ( 32 - bbpL );

			/* The bbp for all these variables is the same as bbpLby2L */
			int32 f2xL;
			int32 f2yL;
			int32 f1xL;
			int32 f1yL;

			/* always whole numbers with a bbp of 0 */
			int32 kL;
			int32 lL;

			/* The bbpE for these variables is bbpLby2L */
			int32 valL;

			/* Get the whole numbers only and make the bbp 0. */
			kL = xL >> bbpL;
			lL = yL >> bbpL;

			/* fraction of destination pixel in the next source pixel */
			f2xL = ( xL & fractionOnlyL ) >> bbpLby2L;
			f2yL = ( yL & fractionOnlyL ) >> bbpLby2L;
			/* fraction of destination pixel in the current source pixel */
			f1xL = oneL - f2xL;
			f1yL = oneL - f2yL;

			/* increment values for next loop */
			xL += mxxL;
			yL += myxL;

			if( lL < 0 )
			{
				if( kL < 0 )
				{
					/* handle all pixels in region x0y0 */
					*dstPtrL++ = *ulPtrL;
				}
				else if( kL >= srcWidthL - 1 )
				{
					/* handle all pixels in region x2y0 */
					*dstPtrL++ = *urPtrL;
				}
				else
				{
					/* handle all pixels in region x1y0 */
					/* The bbp has shifted left by bbpLby2L */
					valL =  *( ulPtrL + kL ) * f1xL + *( ulPtrL + kL + 1 ) * f2xL;
					*dstPtrL++ = valL >> bbpLby2L;
				}
			} /* if( lL < 0 ) */
			else if( lL >= srcHeightL - 1 )
			{
				if( kL < 0 )
				{
					/* handle all pixels in region x0y2 */
					*dstPtrL++ = *llPtrL;
				}
				else if( kL >= srcWidthL - 1 )
				{
					/* handle all pixels in region x2y2 */
					*dstPtrL++ = *lrPtrL;
				}
				else
				{
					/* handle all pixels in region x1y2 */
					/* The bbp has shifted left by bbpLby2L */
					valL =   *( llPtrL + kL ) * f1xL + *( llPtrL +  kL + 1 ) * f2xL;
					*dstPtrL++ = valL >> bbpLby2L;
				}
			} /* if( lL >= srcHeightL - 1 ) */
			else
			{
				const uint8* ptr1L;
				const uint8* ptr2L;

				ptr1L = ulPtrL + lL * srcWidthL;
				/* point to the pixel in the same column */
				ptr2L = ptr1L + srcWidthL;
				if( kL < 0 )
				{
					/* handle all pixels in region x0y1 */
					/* The bbp has shifted left by bbpLby2L */
					valL = *ptr1L * f1yL + *ptr2L * f2yL ;
					*dstPtrL++ = valL >> bbpLby2L;
				}
				else if( kL >= srcWidthL - 1 )
				{
					/* handle all pixels in region x2y1 */
					/* The bbp has shifted left by bbpLby2L */
					valL =  *( ptr1L + srcWidthL - 1 ) * f1yL + *( ptr2L  + srcWidthL - 1 ) * f2yL;
					*dstPtrL++ = valL >> bbpLby2L;
				}
				else
				{
					/* assuming that bbpL = bbpLby2 * 2 */
					/* The bbp for these variables is bbpLby2L */
					int32 v1L;
					int32 v2L;
					/* The bbp for these variables is bbpL */
					const int32 halfL = ( int32 )0x00000001 << ( bbpL - 1 );
	
					/* handle all pixels in region x1y1 */
					/* The bbp has shifted left by bbpLby2L */
					v1L = *( ptr1L + kL ) * f1xL + *( ptr1L + kL + 1 ) * f2xL;
					v2L = *( ptr2L + kL ) * f1xL + *( ptr2L + kL + 1 ) * f2xL;
					/* The bbp has shifted left again by bbpLby2L */
					/* adding the half to round off the resulting value */
					valL = v1L * f1yL + v2L * f2yL + halfL;
					*dstPtrL++ = valL >> bbpL;
				}
			}
		} /* iL loop */
	} /* jL loop */

}

#endif

/* ------------------------------------------------------------------------- */

/* ========================================================================= */