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_BasicEm/Math.h"
     20 #include "b_BasicEm/Functions.h"
     21 #include "b_ImageEm/UInt8Image.h"
     22 
     23 /* ------------------------------------------------------------------------- */
     24 
     25 /* ========================================================================= */
     26 /*                                                                           */
     27 /* ---- \ghd{ auxiliary functions } ---------------------------------------- */
     28 /*                                                                           */
     29 /* ========================================================================= */
     30 
     31 /* ------------------------------------------------------------------------- */
     32 
     33 /* ========================================================================= */
     34 /*                                                                           */
     35 /* ---- \ghd{ constructor / destructor } ----------------------------------- */
     36 /*                                                                           */
     37 /* ========================================================================= */
     38 
     39 /* ------------------------------------------------------------------------- */
     40 
     41 void bim_UInt8Image_init( struct bbs_Context* cpA,
     42 						  struct bim_UInt8Image* ptrA )
     43 {
     44 	bbs_UInt8Arr_init( cpA, &ptrA->arrE );
     45 	ptrA->widthE = 0;
     46 	ptrA->heightE = 0;
     47 }
     48 
     49 /* ------------------------------------------------------------------------- */
     50 
     51 void bim_UInt8Image_create( struct bbs_Context* cpA,
     52 						    struct bim_UInt8Image* ptrA,
     53 						    uint32 widthA,
     54 							uint32 heightA,
     55  					        struct bbs_MemSeg* mspA )
     56 {
     57 	if( bbs_Context_error( cpA ) ) return;
     58 	if( ptrA->arrE.arrPtrE != 0 )
     59 	{
     60 		bim_UInt8Image_size( cpA, ptrA, widthA, heightA );
     61 	}
     62 	else
     63 	{
     64 		bbs_UInt8Arr_create( cpA, &ptrA->arrE, widthA * heightA, mspA );
     65 		ptrA->widthE  = widthA;
     66 		ptrA->heightE = heightA;
     67 	}
     68 }
     69 /* ------------------------------------------------------------------------- */
     70 
     71 void bim_UInt8Image_exit( struct bbs_Context* cpA,
     72 						  struct bim_UInt8Image* ptrA )
     73 {
     74 	bbs_UInt8Arr_exit( cpA, &ptrA->arrE );
     75 	ptrA->widthE = 0;
     76 	ptrA->heightE = 0;
     77 }
     78 
     79 /* ------------------------------------------------------------------------- */
     80 
     81 /* ========================================================================= */
     82 /*                                                                           */
     83 /* ---- \ghd{ operators } -------------------------------------------------- */
     84 /*                                                                           */
     85 /* ========================================================================= */
     86 
     87 /* ------------------------------------------------------------------------- */
     88 
     89 void bim_UInt8Image_copy( struct bbs_Context* cpA,
     90 						  struct bim_UInt8Image* ptrA,
     91 						  const struct bim_UInt8Image* srcPtrA )
     92 {
     93 #ifdef DEBUG1
     94 	if( ptrA->arrE.sizeE < srcPtrA->arrE.sizeE )
     95 	{
     96 		bbs_ERROR0( "void bim_UInt8Image_copy( struct bim_UInt8Image*, const struct bim_UInt8Image* ):\n"
     97 				   "Unsufficient allocated memory in destination image" );
     98 		return;
     99 	}
    100 #endif
    101 	ptrA->widthE = srcPtrA->widthE;
    102 	ptrA->heightE = srcPtrA->heightE;
    103 	bbs_UInt8Arr_copy( cpA, &ptrA->arrE, &srcPtrA->arrE );
    104 }
    105 
    106 /* ------------------------------------------------------------------------- */
    107 
    108 flag bim_UInt8Image_equal( struct bbs_Context* cpA,
    109 						   const struct bim_UInt8Image* ptrA,
    110 						   const struct bim_UInt8Image* srcPtrA )
    111 {
    112 	if( ptrA->widthE != srcPtrA->widthE ) return FALSE;
    113 	if( ptrA->heightE != srcPtrA->heightE ) return FALSE;
    114 	return bbs_UInt8Arr_equal( cpA, &ptrA->arrE, &srcPtrA->arrE );
    115 }
    116 
    117 /* ------------------------------------------------------------------------- */
    118 
    119 /* ========================================================================= */
    120 /*                                                                           */
    121 /* ---- \ghd{ query functions } -------------------------------------------- */
    122 /*                                                                           */
    123 /* ========================================================================= */
    124 
    125 /* ------------------------------------------------------------------------- */
    126 
    127 uint32 bim_UInt8Image_checkSum( struct bbs_Context* cpA,
    128 							    const struct bim_UInt8Image* ptrA )
    129 {
    130 	uint32 sumL =0 ;
    131 	uint32 iL;
    132 	uint32 sizeL = ptrA->arrE.sizeE;
    133 	const uint8* ptrL = ptrA->arrE.arrPtrE;
    134 	for( iL =0; iL < sizeL; iL++ )
    135 	{
    136 		sumL += *ptrL++;
    137 	}
    138 	return sumL;
    139 }
    140 
    141 /* ------------------------------------------------------------------------- */
    142 
    143 /* ========================================================================= */
    144 /*                                                                           */
    145 /* ---- \ghd{ modify functions } ------------------------------------------- */
    146 /*                                                                           */
    147 /* ========================================================================= */
    148 
    149 /* ------------------------------------------------------------------------- */
    150 
    151 void bim_UInt8Image_assignExternalImage( struct bbs_Context* cpA,
    152 										 struct bim_UInt8Image* ptrA,
    153 										 struct bim_UInt8Image* srcPtrA )
    154 {
    155 	struct bbs_MemSeg sharedSegL = bbs_MemSeg_createShared( cpA, srcPtrA->arrE.arrPtrE, ( srcPtrA->widthE * srcPtrA->heightE ) / 2 );
    156 
    157 	if( ptrA->arrE.arrPtrE != 0 )
    158 	{
    159 		bbs_ERROR0( "void bim_UInt8Image_assignExternalImage( ... ): image was already created once" );
    160 		return;
    161 	}
    162 
    163 	bim_UInt8Image_create( cpA, ptrA,
    164 					       srcPtrA->widthE,
    165 						   srcPtrA->heightE,
    166 						   &sharedSegL );
    167 }
    168 
    169 /* ------------------------------------------------------------------------- */
    170 
    171 void bim_UInt8Image_size( struct bbs_Context* cpA,
    172 						  struct bim_UInt8Image* ptrA,
    173 						  uint32 widthA,
    174 						  uint32 heightA )
    175 {
    176 	if( ptrA->arrE.allocatedSizeE < widthA * heightA )
    177 	{
    178 		bbs_ERROR0( "void bim_UInt8Image_size( struct bim_UInt8Image*, uint32 sizeA ):\n"
    179 				   "Unsufficient allocated memory" );
    180 		return;
    181 	}
    182 	bbs_UInt8Arr_size( cpA, &ptrA->arrE, widthA * heightA );
    183 	ptrA->widthE  = widthA;
    184 	ptrA->heightE = heightA;
    185 }
    186 
    187 /* ------------------------------------------------------------------------- */
    188 
    189 /* ========================================================================= */
    190 /*                                                                           */
    191 /* ---- \ghd{ I/O } -------------------------------------------------------- */
    192 /*                                                                           */
    193 /* ========================================================================= */
    194 
    195 /* ------------------------------------------------------------------------- */
    196 
    197 uint32 bim_UInt8Image_memSize( struct bbs_Context* cpA,
    198 							   const struct bim_UInt8Image* ptrA )
    199 {
    200 	return  bbs_SIZEOF16( uint32 )
    201 		  + bbs_SIZEOF16( uint32 ) /* version */
    202 		  + bbs_SIZEOF16( ptrA->widthE )
    203 		  + bbs_SIZEOF16( ptrA->heightE )
    204 		  + bbs_UInt8Arr_memSize( cpA, &ptrA->arrE );
    205 }
    206 
    207 /* ------------------------------------------------------------------------- */
    208 
    209 uint32 bim_UInt8Image_memWrite( struct bbs_Context* cpA,
    210 							    const struct bim_UInt8Image* ptrA,
    211 								uint16* memPtrA )
    212 {
    213 	uint32 memSizeL = bim_UInt8Image_memSize( cpA, ptrA );
    214 	memPtrA += bbs_memWrite32( &memSizeL, memPtrA );
    215 	memPtrA += bbs_memWriteUInt32( bim_UINT8_IMAGE_VERSION, memPtrA );
    216 	memPtrA += bbs_memWrite32( &ptrA->widthE, memPtrA );
    217 	memPtrA += bbs_memWrite32( &ptrA->heightE, memPtrA );
    218 	bbs_UInt8Arr_memWrite( cpA, &ptrA->arrE, memPtrA );
    219 	return memSizeL;
    220 }
    221 
    222 /* ------------------------------------------------------------------------- */
    223 
    224 uint32 bim_UInt8Image_memRead( struct bbs_Context* cpA,
    225 							   struct bim_UInt8Image* ptrA,
    226 							   const uint16* memPtrA,
    227  					           struct bbs_MemSeg* mspA )
    228 {
    229 	uint32 memSizeL, versionL, widthL, heightL;
    230 	if( bbs_Context_error( cpA ) ) return 0;
    231 	memPtrA += bbs_memRead32( &memSizeL, memPtrA );
    232 	memPtrA += bbs_memReadVersion32( cpA, &versionL, bim_UINT8_IMAGE_VERSION, memPtrA );
    233 	memPtrA += bbs_memRead32( &widthL, memPtrA );
    234 	memPtrA += bbs_memRead32( &heightL, memPtrA );
    235 
    236 	ptrA->widthE  = widthL;
    237 	ptrA->heightE = heightL;
    238 	bbs_UInt8Arr_memRead( cpA, &ptrA->arrE, memPtrA, mspA );
    239 
    240 	if( memSizeL != bim_UInt8Image_memSize( cpA, ptrA ) )
    241 	{
    242 		bbs_ERR0( bbs_ERR_CORRUPT_DATA, "uint32 bim_UInt8Image_memRead( const struct bim_UInt8Image* ptrA, const void* memPtrA ):\n"
    243                    "size mismatch" );
    244 		return 0;
    245 	}
    246 	return memSizeL;
    247 }
    248 
    249 /* ------------------------------------------------------------------------- */
    250 
    251 /* ========================================================================= */
    252 /*                                                                           */
    253 /* ---- \ghd{ exec functions } --------------------------------------------- */
    254 /*                                                                           */
    255 /* ========================================================================= */
    256 
    257 /* ------------------------------------------------------------------------- */
    258 
    259 void bim_UInt8Image_setAllPixels( struct bbs_Context* cpA,
    260 								  struct bim_UInt8Image* ptrA,
    261 								  uint8 valueA )
    262 {
    263 	long iL;
    264 	uint8* ptrL = ptrA->arrE.arrPtrE;
    265 	for( iL = ptrA->widthE * ptrA->heightE; iL > 0; iL-- )
    266 	{
    267 		*ptrL++ = valueA;
    268 	}
    269 }
    270 
    271 /* ------------------------------------------------------------------------- */
    272 
    273 /**
    274 			|				|				|				|
    275 			|	(loop x1)	|	(loop x2)	|	(loop x3)	|
    276 			o------------->-o------------>--o------------->-o
    277 			|				|				|				|
    278 			|				|				|				|
    279 			|				|				|				|
    280 			|				|				|				|
    281 	( sectionL->x1E, sectionL->y1E )		|				|
    282 ---------o-	R-------------------------------|----------------
    283 		 |	|				|				|				|
    284 		 |	|				|				|				|
    285 		 |	|				|				|				|
    286 		 |	|				|				|				|
    287    (loop y1)|				|				|				|
    288 		 |	|				|				|				|
    289 		 V	|				|				|				|
    290 		 |	|				|( 0, 0 )		|				|		X
    291 ---------o------------------I------------------------------------------------->
    292 		 |	|				|				|				|
    293 		 |	|				|				|				|
    294 		 |	|				|				|				|
    295 		 |	|				|				|				|
    296 		 |	|				|				|				|
    297    (loop y2)|				|				|				|
    298 		 |	|				|				|				|
    299 		 |	|				|				|				|
    300 		 |	|				|				|				|
    301 		 V	|				|				|				|
    302 		 |	|				|				|				|
    303 ---------o------------------|---------------I				|
    304 		 |	|				|		( srcPtrA->widthE, srcPtrA->heightE )
    305 		 |	|				|								|
    306 		 |	|				|								|
    307 		 |	|				|								|
    308 		 |	|				|								|
    309 		 |	|				|								|
    310    (loop y3)|				|								|
    311 		 |	|				|								|
    312 		 |	|				|								|
    313 		 V	|				|								|
    314 		 |	|				|								|
    315 ---------o--------------------------------------------------R
    316 							|				( sectionL->x2E, sectionL->y2E )
    317 							|
    318 						  Y	|
    319 							|
    320 							|
    321 							V
    322 
    323   To understand how the algorithm work refer to the diagram above.
    324   The image boundaries are indicated by letter "I" ( 0, 0 ) to ( srcPtrA->widthE, srcPtrA->heightE )
    325   The rectangle boundaries are indicated by letter "R" ( sectionPtrA->x1E, sectionPtrA->y1E ) to ( sectionPtrA->x2E, sectionPtrA->y2E )
    326 
    327   In the above example the intersection of the image and the rectange is
    328   ( 0, 0 ), ( srcPtrA->widthE, srcPtrA->heightE )
    329 
    330   The size of the destination image is always ( ( sectionL->x2E, sectionL->y2E ) - ( sectionL->x1E, sectionL->y1E ) )
    331 
    332   All coordinates are assumed to be relative to the original image.
    333 
    334   1. parse all pixels in "loop y1"
    335 	1.a. parse all pixels in "loop x1"
    336 	1.b. parse all pixels in "loop x2"
    337 	1.c. parse all pixels in "loop x3"
    338   2. parse all pixels in "loop y2"
    339 	2.a. parse all pixels in "loop x1"
    340 	2.b. parse all pixels in "loop x2"
    341 	2.c. parse all pixels in "loop x3"
    342   3. parse all pixels in "loop y3"
    343 	3.a. parse all pixels in "loop x1"
    344 	3.b. parse all pixels in "loop x2"
    345 	3.c. parse all pixels in "loop x3"
    346 
    347 */
    348 
    349 /** copies a section of given image */
    350 void bim_UInt8Image_copySection( struct bbs_Context* cpA,
    351 								 struct bim_UInt8Image* ptrA,
    352 								 const struct bim_UInt8Image* srcPtrA,
    353 								 const struct bts_Int16Rect* sectionPtrA )
    354 {
    355 
    356 	uint8* srcPixelPtrL;
    357 	uint8* dstPixelPtrL;
    358 	int32 yIndexL;
    359 	int32 xIndexL;
    360 
    361 	struct bts_Int16Rect srcImageSubSectionL;
    362 	struct bts_Int16Rect sectionL;
    363 
    364 	/* make sure that the rectangle passed is correct, in case the x2 < x1 or y2 < y1, swap them */
    365 	sectionL.x1E = bbs_min( sectionPtrA->x1E, sectionPtrA->x2E );
    366 	sectionL.x2E = bbs_max( sectionPtrA->x1E, sectionPtrA->x2E );
    367 	sectionL.y1E = bbs_min( sectionPtrA->y1E, sectionPtrA->y2E );
    368 	sectionL.y2E = bbs_max( sectionPtrA->y1E, sectionPtrA->y2E );
    369 
    370 	/* find the intersection betweem the rectangle and the image, the image always starts at 0,0 */
    371 	srcImageSubSectionL.x1E = bbs_max( 0, sectionL.x1E );
    372 	srcImageSubSectionL.y1E = bbs_max( 0, sectionL.y1E );
    373 	srcImageSubSectionL.x2E = bbs_min( ( int32 ) srcPtrA->widthE, sectionL.x2E );
    374 	srcImageSubSectionL.y2E = bbs_min( ( int32 ) srcPtrA->heightE, sectionL.y2E );
    375 
    376 	/* If the image and the rectangle do not intersect in X direction, set the intersecting rectangle to the image coordinates */
    377 	if( srcImageSubSectionL.x2E < srcImageSubSectionL.x1E )
    378 	{
    379 		srcImageSubSectionL.x1E = 0;
    380 		srcImageSubSectionL.x2E = srcPtrA->widthE;
    381 	}
    382 	/* do the same as above in the Y direction */
    383 	if( srcImageSubSectionL.y2E < srcImageSubSectionL.y1E )
    384 	{
    385 		srcImageSubSectionL.y1E = 0;
    386 		srcImageSubSectionL.y2E = srcPtrA->heightE;
    387 	}
    388 
    389 	/* set size, and allocate required memory for the destination image if required */
    390 	bim_UInt8Image_size( cpA, ptrA, sectionL.x2E - sectionL.x1E, sectionL.y2E - sectionL.y1E );
    391 
    392 	/* get the pointer to the destination image */
    393 	dstPixelPtrL = ptrA->arrE.arrPtrE;
    394 
    395 	/* 1. parse all pixels in "loop y1" */
    396 	for( yIndexL = sectionL.y1E; yIndexL < srcImageSubSectionL.y1E && yIndexL < sectionL.y2E; yIndexL++ )
    397 	{
    398 		/* move to the first pixel that needs to be copied. */
    399 		srcPixelPtrL = srcPtrA->arrE.arrPtrE;
    400 
    401 		/* 1.a. parse all pixels in "loop x1" */
    402 		for( xIndexL = sectionL.x1E; xIndexL < srcImageSubSectionL.x1E && xIndexL < sectionL.x2E; xIndexL++ )
    403 		{
    404 			*dstPixelPtrL++ = *srcPixelPtrL;
    405 		}
    406 		/* 1.b. parse all pixels in "loop x2" */
    407 		for( ; xIndexL < srcImageSubSectionL.x2E && xIndexL < sectionL.x2E; xIndexL++ )
    408 		{
    409 			*dstPixelPtrL++ = *srcPixelPtrL++;
    410 		}
    411 		srcPixelPtrL--;
    412 		/* 1.c. parse all pixels in "loop x3" */
    413 		for( ; xIndexL < sectionL.x2E; xIndexL++ )
    414 		{
    415 			*dstPixelPtrL++ = *srcPixelPtrL;
    416 		}
    417 	}
    418 	/* 2. parse all pixels in "loop y2" */
    419 	for( ; yIndexL < srcImageSubSectionL.y2E && yIndexL < sectionL.y2E; yIndexL++ )
    420 	{
    421 		/* move to the first pixel that needs to be copied. */
    422 		srcPixelPtrL = srcPtrA->arrE.arrPtrE + yIndexL * srcPtrA->widthE + srcImageSubSectionL.x1E;
    423 
    424 		/* 2.a. parse all pixels in "loop x1" */
    425 		for( xIndexL = sectionL.x1E; xIndexL < srcImageSubSectionL.x1E && xIndexL < sectionL.x2E; xIndexL++ )
    426 		{
    427 			*dstPixelPtrL++ = *srcPixelPtrL;
    428 		}
    429 		/* 2.b. parse all pixels in "loop x2" */
    430 		for( ; xIndexL < srcImageSubSectionL.x2E && xIndexL < sectionL.x2E; xIndexL++ )
    431 		{
    432 			*dstPixelPtrL++ = *srcPixelPtrL++;
    433 		}
    434 		srcPixelPtrL--;
    435 		/* 2.c. parse all pixels in "loop x3" */
    436 		for( ; xIndexL < sectionL.x2E; xIndexL++ )
    437 		{
    438 			*dstPixelPtrL++ = *srcPixelPtrL;
    439 		}
    440 	}
    441 	/* 3. parse all pixels in "loop y3" */
    442 	for( ; yIndexL < sectionL.y2E; yIndexL++ )
    443 	{
    444 		srcPixelPtrL = srcPtrA->arrE.arrPtrE + ( srcImageSubSectionL.y2E - 1 ) * srcPtrA->widthE + srcImageSubSectionL.x1E;
    445 
    446 		/* 3.a. parse all pixels in "loop x1" */
    447 		for( xIndexL = sectionL.x1E; xIndexL < srcImageSubSectionL.x1E && xIndexL < sectionL.x2E; xIndexL++ )
    448 		{
    449 			*dstPixelPtrL++ = *srcPixelPtrL;
    450 		}
    451 		/* 3.b. parse all pixels in "loop x3" */
    452 		for( ; xIndexL < srcImageSubSectionL.x2E && xIndexL < sectionL.x2E; xIndexL++ )
    453 		{
    454 			*dstPixelPtrL++ = *srcPixelPtrL++;
    455 		}
    456 		srcPixelPtrL--;
    457 		/* 3.c. parse all pixels in "loop x3" */
    458 		for( ; xIndexL < sectionL.x2E; xIndexL++ )
    459 		{
    460 			*dstPixelPtrL++ = *srcPixelPtrL;
    461 		}
    462 	}
    463 
    464 }
    465 
    466 /* ------------------------------------------------------------------------- */
    467 
    468 /**
    469 
    470 
    471 		M-------------------------------------------------------M
    472 		|				|						|				|
    473 		|				|						|				|
    474 		|				|						|				|
    475 		|				|						|				|
    476 		|	region x0y0	|		region x1y0		|	region x2y0	|
    477 		|				|						|				|
    478 		|				|						|				|
    479 		|				|						|				|
    480 		|---------------I-----------------------I---------------|
    481 		|				|						|				|
    482 		|				|						|				|
    483 		|				|						|				|
    484 		|				|						|				|
    485 		|				|						|				|
    486 		|				|						|				|
    487 		|	region x0y1	|		region x1y1		|	region x2y1	|
    488 		|				|						|				|
    489 		|				|						|				|
    490 		|				|						|				|
    491 		|				|						|				|
    492 		|				|						|				|
    493 		|				|						|				|
    494 		|				|						|				|
    495 		|---------------I-----------------------I---------------|
    496 		|				|						|				|
    497 		|				|						|				|
    498 		|				|						|				|
    499 		|				|						|				|
    500 		|	region x0y2	|		region x1y2		|	region x2y2	|
    501 		|				|						|				|
    502 		|				|						|				|
    503 		|				|						|				|
    504 		M-------------------------------------------------------M
    505 
    506 
    507   To see how the code is organized. Refer to the diagram above.
    508   Assume the original image after applying the tranzformations(translation, rotation and scaling) is "O"
    509 	(boundaries of the image are shown above bounded by the letter 'O').
    510   This image is being Warped to the area "M" (boundaries of this area are bounded by the letter 'M').
    511 
    512 	Refer to the source code below to point to the loop that maps pixels in the particular region.
    513 
    514  */
    515 
    516 /** applies affine linear warping to pixels positions of imageA before copying the into *ptrA */
    517 void bim_UInt8Image_warpOffs( struct bbs_Context* cpA,
    518 						  struct bim_UInt8Image* ptrA,
    519 						  const struct bim_UInt8Image* srcPtrA,
    520 						  int32 xOffsA,
    521 						  int32 yOffsA,
    522 						  const struct bts_Flt16Alt2D* altPtrA,
    523 			              int32 resultWidthA,
    524 			              int32 resultHeightA )
    525 {
    526 	long srcWidthL = srcPtrA->widthE;
    527 	long srcHeightL = srcPtrA->heightE;
    528 
    529 	struct bts_Flt16Alt2D invAlt2DL;
    530 
    531 	uint8* dstPtrL;
    532 	const uint8* ulPtrL = srcPtrA->arrE.arrPtrE;
    533 	const uint8* urPtrL = ulPtrL + srcWidthL - 1;
    534 	const uint8* llPtrL = ulPtrL + ( srcHeightL - 1 ) * srcWidthL;
    535 	const uint8* lrPtrL = llPtrL + srcWidthL - 1;
    536 
    537 	uint32 iL, jL;
    538 	int32 shiftL;
    539 
    540 	const uint16 bbpL = 16;
    541 	int32 maxInt32Value8bbpL  = 0x7FFFFFFF;
    542 
    543 	/* The bbp for all these variables is the same as bbpL */
    544 	int32 mxxL;
    545 	int32 mxyL;
    546 	int32 myxL;
    547 	int32 myyL;
    548 
    549 	int32 txL;
    550 	int32 tyL;
    551 
    552 	int32 xL;
    553 	int32 yL;
    554 
    555 	bim_UInt8Image_size( cpA, ptrA, resultWidthA, resultHeightA );
    556 	dstPtrL = ptrA->arrE.arrPtrE;
    557 
    558 	/* compute inverse */
    559 	invAlt2DL = bts_Flt16Alt2D_inverted( altPtrA );
    560 
    561 	if( srcWidthL == 0 || srcHeightL == 0 )
    562 	{
    563 		bim_UInt8Image_size( cpA, ptrA, srcWidthL, srcHeightL );
    564 		bbs_ERROR2( "Size of output image is %d/%d", srcWidthL, srcHeightL );
    565 		return;
    566 	}
    567 
    568 	/* align Matrix and Vector to 8 bits bbp */
    569 	shiftL = invAlt2DL.matE.bbpE - bbpL;
    570 	if( shiftL >= 0 )
    571 	{
    572 		mxxL = invAlt2DL.matE.xxE >> shiftL;
    573 		mxyL = invAlt2DL.matE.xyE >> shiftL;
    574 		myxL = invAlt2DL.matE.yxE >> shiftL;
    575 		myyL = invAlt2DL.matE.yyE >> shiftL;
    576 	}
    577 	else
    578 	{
    579 		/* Check for overflow since we are left shifting. */
    580 		maxInt32Value8bbpL >>= -shiftL;
    581 		if( invAlt2DL.matE.xxE > maxInt32Value8bbpL ||
    582 			invAlt2DL.matE.xyE > maxInt32Value8bbpL ||
    583 			invAlt2DL.matE.yxE > maxInt32Value8bbpL ||
    584 			invAlt2DL.matE.yyE > maxInt32Value8bbpL )
    585 		{
    586 			/* Overflow error */
    587 			bbs_ERROR5( "The values in the transformation matrix cause overflow during bitshift\n%d, %d,\n%d, %d\n"
    588 						"The maximum allowed value is %d",
    589 						invAlt2DL.matE.xxE >> invAlt2DL.matE.bbpE,
    590 						invAlt2DL.matE.xyE >> invAlt2DL.matE.bbpE,
    591 						invAlt2DL.matE.yxE >> invAlt2DL.matE.bbpE,
    592 						invAlt2DL.matE.yyE >> invAlt2DL.matE.bbpE,
    593 						maxInt32Value8bbpL >> ( bbpL - ( -shiftL ) ) );
    594 			return;
    595 		}
    596 
    597 		mxxL = invAlt2DL.matE.xxE << -shiftL;
    598 		mxyL = invAlt2DL.matE.xyE << -shiftL;
    599 		myxL = invAlt2DL.matE.yxE << -shiftL;
    600 		myyL = invAlt2DL.matE.yyE << -shiftL;
    601 		maxInt32Value8bbpL <<= -shiftL;
    602 	}
    603 
    604 	/* invAlt2DL.matE.bbpE = bbpL; nonsense! */
    605 
    606 	shiftL = invAlt2DL.vecE.bbpE - bbpL;
    607 	if( shiftL >= 0 )
    608 	{
    609 		txL  = invAlt2DL.vecE.xE >> shiftL;
    610 		tyL  = invAlt2DL.vecE.yE >> shiftL;
    611 	}
    612 	else
    613 	{
    614 		/* Check for overflow since we are left shifting. */
    615 		maxInt32Value8bbpL >>= -shiftL;
    616 		if(	invAlt2DL.vecE.xE  > maxInt32Value8bbpL ||
    617 			invAlt2DL.vecE.yE  > maxInt32Value8bbpL )
    618 		{
    619 			/* Overflow error */
    620 			bbs_ERROR3( "The values in the vector cause overflow during bitshift\n%d, %d,\n"
    621 						"The maximum allowed value is %d",
    622 						invAlt2DL.vecE.xE >> invAlt2DL.vecE.bbpE,
    623 						invAlt2DL.vecE.yE >> invAlt2DL.vecE.bbpE,
    624 						maxInt32Value8bbpL >> ( bbpL - ( -shiftL ) ) );
    625 			return;
    626 		}
    627 		txL  = invAlt2DL.vecE.xE << -shiftL;
    628 		tyL  = invAlt2DL.vecE.yE << -shiftL;
    629 		maxInt32Value8bbpL <<= -shiftL;
    630 	}
    631 
    632 	/* invAlt2DL.vecE.bbpE = bbpL; nonsense! */
    633 
    634 	/* adjust offset */
    635 	txL += xOffsA << bbpL;
    636 	tyL += yOffsA << bbpL;
    637 
    638 	/* For each destination pixel find the correspoding source pixel by applying the inverse transformation */
    639 	for( jL = 0; jL < ptrA->heightE; jL++ )
    640 	{
    641 		xL = txL + mxyL * jL;
    642 		yL = tyL + myyL * jL;
    643 		for( iL = 0; iL < ptrA->widthE; iL++ )
    644 		{
    645 			const uint16 bbpLby2L = bbpL / 2;
    646 			const int32 oneL = 0x00000001 << bbpLby2L;
    647 			const int32 fractionOnlyL = 0xFFFFFFFF >> ( 32 - bbpL );
    648 
    649 			/* The bbp for all these variables is the same as bbpLby2L */
    650 			int32 f2xL;
    651 			int32 f2yL;
    652 			int32 f1xL;
    653 			int32 f1yL;
    654 
    655 			/* always whole numbers with a bbp of 0 */
    656 			int32 kL;
    657 			int32 lL;
    658 
    659 			/* The bbpE for these variables is bbpLby2L */
    660 			int32 valL;
    661 
    662 			/* Get the whole numbers only and make the bbp 0. */
    663 			kL = xL >> bbpL;
    664 			lL = yL >> bbpL;
    665 
    666 			/* fraction of destination pixel in the next source pixel */
    667 			f2xL = ( xL & fractionOnlyL ) >> bbpLby2L;
    668 			f2yL = ( yL & fractionOnlyL ) >> bbpLby2L;
    669 			/* fraction of destination pixel in the current source pixel */
    670 			f1xL = oneL - f2xL;
    671 			f1yL = oneL - f2yL;
    672 
    673 			/* increment values for next loop */
    674 			xL += mxxL;
    675 			yL += myxL;
    676 
    677 			if( lL < 0 )
    678 			{
    679 				if( kL < 0 )
    680 				{
    681 					/* handle all pixels in region x0y0 */
    682 					*dstPtrL++ = *ulPtrL;
    683 				}
    684 				else if( kL >= srcWidthL - 1 )
    685 				{
    686 					/* handle all pixels in region x2y0 */
    687 					*dstPtrL++ = *urPtrL;
    688 				}
    689 				else
    690 				{
    691 					/* handle all pixels in region x1y0 */
    692 					/* The bbp has shifted left by bbpLby2L */
    693 					valL =  *( ulPtrL + kL ) * f1xL + *( ulPtrL + kL + 1 ) * f2xL;
    694 					*dstPtrL++ = valL >> bbpLby2L;
    695 				}
    696 			} /* if( lL < 0 ) */
    697 			else if( lL >= srcHeightL - 1 )
    698 			{
    699 				if( kL < 0 )
    700 				{
    701 					/* handle all pixels in region x0y2 */
    702 					*dstPtrL++ = *llPtrL;
    703 				}
    704 				else if( kL >= srcWidthL - 1 )
    705 				{
    706 					/* handle all pixels in region x2y2 */
    707 					*dstPtrL++ = *lrPtrL;
    708 				}
    709 				else
    710 				{
    711 					/* handle all pixels in region x1y2 */
    712 					/* The bbp has shifted left by bbpLby2L */
    713 					valL =   *( llPtrL + kL ) * f1xL + *( llPtrL +  kL + 1 ) * f2xL;
    714 					*dstPtrL++ = valL >> bbpLby2L;
    715 				}
    716 			} /* if( lL >= srcHeightL - 1 ) */
    717 			else
    718 			{
    719 				const uint8* ptr1L;
    720 				const uint8* ptr2L;
    721 
    722 				ptr1L = ulPtrL + lL * srcWidthL;
    723 				/* point to the pixel in the same column */
    724 				ptr2L = ptr1L + srcWidthL;
    725 				if( kL < 0 )
    726 				{
    727 					/* handle all pixels in region x0y1 */
    728 					/* The bbp has shifted left by bbpLby2L */
    729 					valL = *ptr1L * f1yL + *ptr2L * f2yL ;
    730 					*dstPtrL++ = valL >> bbpLby2L;
    731 				}
    732 				else if( kL >= srcWidthL - 1 )
    733 				{
    734 					/* handle all pixels in region x2y1 */
    735 					/* The bbp has shifted left by bbpLby2L */
    736 					valL =  *( ptr1L + srcWidthL - 1 ) * f1yL + *( ptr2L  + srcWidthL - 1 ) * f2yL;
    737 					*dstPtrL++ = valL >> bbpLby2L;
    738 				}
    739 				else
    740 				{
    741 					/* assuming that bbpL = bbpLby2 * 2 */
    742 					/* The bbp for these variables is bbpLby2L */
    743 					int32 v1L;
    744 					int32 v2L;
    745 					/* The bbp for these variables is bbpL */
    746 					const int32 halfL = 0x00000001 << ( bbpL - 1 );
    747 
    748 					/* handle all pixels in region x1y1 */
    749 					/* The bbp has shifted left by bbpLby2L */
    750 					v1L = *( ptr1L + kL ) * f1xL + *( ptr1L + kL + 1 ) * f2xL;
    751 					v2L = *( ptr2L + kL ) * f1xL + *( ptr2L + kL + 1 ) * f2xL;
    752 					/* The bbp has shifted left again by bbpLby2L */
    753 					/* adding the half to round off the resulting value */
    754 					valL = v1L * f1yL + v2L * f2yL + halfL;
    755 					*dstPtrL++ = valL >> bbpL;
    756 				}
    757 			}
    758 		} /* iL loop */
    759 	} /* jL loop */
    760 
    761 }
    762 
    763 /* ------------------------------------------------------------------------- */
    764 
    765 void bim_UInt8Image_warp( struct bbs_Context* cpA,
    766 						  struct bim_UInt8Image* ptrA,
    767 						  const struct bim_UInt8Image* srcPtrA,
    768 						  const struct bts_Flt16Alt2D* altPtrA,
    769 			              int32 resultWidthA,
    770 			              int32 resultHeightA )
    771 {
    772 	bim_UInt8Image_warpOffs( cpA, ptrA, srcPtrA, 0, 0, altPtrA, resultWidthA, resultHeightA );
    773 }
    774 
    775 /* ========================================================================= */
    776 
    777 
    778