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 
bim_UInt8Image_init(struct bbs_Context * cpA,struct bim_UInt8Image * ptrA)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 
bim_UInt8Image_create(struct bbs_Context * cpA,struct bim_UInt8Image * ptrA,uint32 widthA,uint32 heightA,struct bbs_MemSeg * mspA)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 
bim_UInt8Image_exit(struct bbs_Context * cpA,struct bim_UInt8Image * ptrA)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 
bim_UInt8Image_copy(struct bbs_Context * cpA,struct bim_UInt8Image * ptrA,const struct bim_UInt8Image * srcPtrA)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 
bim_UInt8Image_equal(struct bbs_Context * cpA,const struct bim_UInt8Image * ptrA,const struct bim_UInt8Image * srcPtrA)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 
bim_UInt8Image_checkSum(struct bbs_Context * cpA,const struct bim_UInt8Image * ptrA)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 
bim_UInt8Image_assignExternalImage(struct bbs_Context * cpA,struct bim_UInt8Image * ptrA,struct bim_UInt8Image * srcPtrA)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 
bim_UInt8Image_size(struct bbs_Context * cpA,struct bim_UInt8Image * ptrA,uint32 widthA,uint32 heightA)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 
bim_UInt8Image_memSize(struct bbs_Context * cpA,const struct bim_UInt8Image * ptrA)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 
bim_UInt8Image_memWrite(struct bbs_Context * cpA,const struct bim_UInt8Image * ptrA,uint16 * memPtrA)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 
bim_UInt8Image_memRead(struct bbs_Context * cpA,struct bim_UInt8Image * ptrA,const uint16 * memPtrA,struct bbs_MemSeg * mspA)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 
bim_UInt8Image_setAllPixels(struct bbs_Context * cpA,struct bim_UInt8Image * ptrA,uint8 valueA)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 */
bim_UInt8Image_copySection(struct bbs_Context * cpA,struct bim_UInt8Image * ptrA,const struct bim_UInt8Image * srcPtrA,const struct bts_Int16Rect * sectionPtrA)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 */
bim_UInt8Image_warpOffs(struct bbs_Context * cpA,struct bim_UInt8Image * ptrA,const struct bim_UInt8Image * srcPtrA,int32 xOffsA,int32 yOffsA,const struct bts_Flt16Alt2D * altPtrA,int32 resultWidthA,int32 resultHeightA)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 
bim_UInt8Image_warp(struct bbs_Context * cpA,struct bim_UInt8Image * ptrA,const struct bim_UInt8Image * srcPtrA,const struct bts_Flt16Alt2D * altPtrA,int32 resultWidthA,int32 resultHeightA)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