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
41void 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
51void 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
71void 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
89void 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
108flag 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
127uint32 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
151void 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
171void 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
197uint32 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
209uint32 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
224uint32 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
259void 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 */
350void 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 */
517void 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
765void 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