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/UInt16ByteImage.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_UInt16ByteImage_init( struct bbs_Context* cpA,
42							   struct bim_UInt16ByteImage* ptrA )
43{
44	bbs_UInt16Arr_init( cpA, &ptrA->arrE );
45	ptrA->widthE = 0;
46	ptrA->heightE = 0;
47}
48
49/* ------------------------------------------------------------------------- */
50
51void bim_UInt16ByteImage_exit( struct bbs_Context* cpA,
52							   struct bim_UInt16ByteImage* ptrA )
53{
54	bbs_UInt16Arr_exit( cpA, &ptrA->arrE );
55	ptrA->widthE = 0;
56	ptrA->heightE = 0;
57}
58
59/* ------------------------------------------------------------------------- */
60
61/* ========================================================================= */
62/*                                                                           */
63/* ---- \ghd{ operators } -------------------------------------------------- */
64/*                                                                           */
65/* ========================================================================= */
66
67/* ------------------------------------------------------------------------- */
68
69void bim_UInt16ByteImage_copy( struct bbs_Context* cpA,
70							   struct bim_UInt16ByteImage* ptrA,
71							   const struct bim_UInt16ByteImage* srcPtrA )
72{
73#ifdef DEBUG1
74	if( ptrA->arrE.sizeE < srcPtrA->arrE.sizeE )
75	{
76		bbs_ERROR0( "void bim_UInt16ByteImage_copy( struct bim_UInt16ByteImage*, const struct bim_UInt16ByteImage* ):\n"
77				   "Unsufficient allocated memory in destination image" );
78		return;
79	}
80#endif
81	ptrA->widthE = srcPtrA->widthE;
82	ptrA->heightE = srcPtrA->heightE;
83	bbs_UInt16Arr_copy( cpA, &ptrA->arrE, &srcPtrA->arrE );
84}
85
86/* ------------------------------------------------------------------------- */
87
88flag bim_UInt16ByteImage_equal( struct bbs_Context* cpA,
89							    const struct bim_UInt16ByteImage* ptrA,
90								const struct bim_UInt16ByteImage* srcPtrA )
91{
92	if( ptrA->widthE != srcPtrA->widthE ) return FALSE;
93	if( ptrA->heightE != srcPtrA->heightE ) return FALSE;
94	return bbs_UInt16Arr_equal( cpA, &ptrA->arrE, &srcPtrA->arrE );
95}
96
97/* ------------------------------------------------------------------------- */
98
99/* ========================================================================= */
100/*                                                                           */
101/* ---- \ghd{ query functions } -------------------------------------------- */
102/*                                                                           */
103/* ========================================================================= */
104
105/* ------------------------------------------------------------------------- */
106
107uint32 bim_UInt16ByteImage_checkSum( struct bbs_Context* cpA,
108									 const struct bim_UInt16ByteImage* ptrA )
109{
110	uint32 sumL =0 ;
111	uint32 iL;
112	uint32 sizeL = ptrA->arrE.sizeE;
113	const uint16* ptrL = ptrA->arrE.arrPtrE;
114	for( iL =0; iL < sizeL; iL++ )
115	{
116		sumL += *ptrL++;
117	}
118	return sumL;
119}
120
121/* ------------------------------------------------------------------------- */
122
123/* ========================================================================= */
124/*                                                                           */
125/* ---- \ghd{ modify functions } ------------------------------------------- */
126/*                                                                           */
127/* ========================================================================= */
128
129/* ------------------------------------------------------------------------- */
130
131void bim_UInt16ByteImage_create( struct bbs_Context* cpA,
132								 struct bim_UInt16ByteImage* ptrA,
133						         uint32 widthA,
134							     uint32 heightA,
135 					             struct bbs_MemSeg* mspA )
136{
137	if( bbs_Context_error( cpA ) ) return;
138	if( widthA & 1 )
139	{
140		bbs_ERROR0( "bim_UInt16ByteImage_create( .... ): width of image must be even" );
141		return;
142	}
143
144	if( ptrA->arrE.arrPtrE != 0 )
145	{
146		bim_UInt16ByteImage_size( cpA, ptrA, widthA, heightA );
147	}
148	else
149	{
150		bbs_UInt16Arr_create( cpA, &ptrA->arrE, ( widthA * heightA ) >> 1, mspA );
151		ptrA->widthE  = widthA;
152		ptrA->heightE = heightA;
153	}
154}
155
156/* ------------------------------------------------------------------------- */
157
158void bim_UInt16ByteImage_assignExternalImage( struct bbs_Context* cpA,
159											  struct bim_UInt16ByteImage* ptrA,
160											  struct bim_UInt16ByteImage* srcPtrA )
161{
162	struct bbs_MemSeg sharedSegL = bbs_MemSeg_createShared( cpA, srcPtrA->arrE.arrPtrE, ( srcPtrA->widthE * srcPtrA->heightE ) / 2 );
163
164	if( ptrA->arrE.arrPtrE != 0 )
165	{
166		bbs_ERROR0( "void bim_UInt16ByteImage_assignExternalImage( ... ): image was already created once" );
167		return;
168	}
169
170	bim_UInt16ByteImage_create( cpA, ptrA,
171					            srcPtrA->widthE,
172						        srcPtrA->heightE,
173						        &sharedSegL );
174}
175
176/* ------------------------------------------------------------------------- */
177
178void bim_UInt16ByteImage_size( struct bbs_Context* cpA,
179							   struct bim_UInt16ByteImage* ptrA,
180							   uint32 widthA, uint32 heightA )
181{
182	if( widthA & 1 )
183	{
184		bbs_ERROR0( "bim_UInt16ByteImage_size( .... ): width of image must be even" );
185		return;
186	}
187
188	if( ptrA->arrE.allocatedSizeE < ( ( widthA * heightA ) >> 1 ) )
189	{
190		bbs_ERROR0( "void bim_UInt16ByteImage_size( struct bim_UInt16ByteImage*, uint32 sizeA ):\n"
191				   "Unsufficient allocated memory" );
192		return;
193	}
194	bbs_UInt16Arr_size( cpA, &ptrA->arrE, ( widthA * heightA ) >> 1 );
195	ptrA->widthE  = widthA;
196	ptrA->heightE = heightA;
197}
198
199/* ------------------------------------------------------------------------- */
200
201/* ========================================================================= */
202/*                                                                           */
203/* ---- \ghd{ I/O } -------------------------------------------------------- */
204/*                                                                           */
205/* ========================================================================= */
206
207/* ------------------------------------------------------------------------- */
208
209uint32 bim_UInt16ByteImage_memSize( struct bbs_Context* cpA,
210								    const struct bim_UInt16ByteImage* ptrA )
211{
212	return  bbs_SIZEOF16( uint32 )
213		  + bbs_SIZEOF16( uint32 ) /* version */
214		  + bbs_SIZEOF16( ptrA->widthE )
215		  + bbs_SIZEOF16( ptrA->heightE )
216		  + bbs_UInt16Arr_memSize( cpA, &ptrA->arrE );
217}
218
219/* ------------------------------------------------------------------------- */
220
221uint32 bim_UInt16ByteImage_memWrite( struct bbs_Context* cpA,
222									 const struct bim_UInt16ByteImage* ptrA,
223									 uint16* memPtrA )
224{
225	uint32 memSizeL = bim_UInt16ByteImage_memSize( cpA, ptrA );
226	memPtrA += bbs_memWrite32( &memSizeL, memPtrA );
227	memPtrA += bbs_memWriteUInt32( bim_UINT16_IMAGE_VERSION, memPtrA );
228	memPtrA += bbs_memWrite32( &ptrA->widthE, memPtrA );
229	memPtrA += bbs_memWrite32( &ptrA->heightE, memPtrA );
230	bbs_UInt16Arr_memWrite( cpA, &ptrA->arrE, memPtrA );
231	return memSizeL;
232}
233
234/* ------------------------------------------------------------------------- */
235
236uint32 bim_UInt16ByteImage_memRead( struct bbs_Context* cpA,
237								    struct bim_UInt16ByteImage* ptrA,
238							   const uint16* memPtrA,
239 					           struct bbs_MemSeg* mspA )
240{
241	uint32 memSizeL, versionL, widthL, heightL;
242	if( bbs_Context_error( cpA ) ) return 0;
243	memPtrA += bbs_memRead32( &memSizeL, memPtrA );
244	memPtrA += bbs_memReadVersion32( cpA, &versionL, bim_UINT16_IMAGE_VERSION, memPtrA );
245	memPtrA += bbs_memRead32( &widthL, memPtrA );
246	memPtrA += bbs_memRead32( &heightL, memPtrA );
247
248	ptrA->widthE  = widthL;
249	ptrA->heightE = heightL;
250	bbs_UInt16Arr_memRead( cpA, &ptrA->arrE, memPtrA, mspA );
251
252	if( memSizeL != bim_UInt16ByteImage_memSize( cpA, ptrA ) )
253	{
254		bbs_ERR0( bbs_ERR_CORRUPT_DATA, "uint32 bim_UInt16ByteImage_memRead( const struct bim_UInt16ByteImage* ptrA, const void* memPtrA ):\n"
255                   "size mismatch" );
256		return 0;
257	}
258	return memSizeL;
259}
260
261/* ------------------------------------------------------------------------- */
262
263/* ========================================================================= */
264/*                                                                           */
265/* ---- \ghd{ exec functions } --------------------------------------------- */
266/*                                                                           */
267/* ========================================================================= */
268
269/* ------------------------------------------------------------------------- */
270
271void bim_UInt16ByteImage_setAllPixels( struct bbs_Context* cpA,
272									   struct bim_UInt16ByteImage* ptrA,
273									   uint16 valueA )
274{
275	long iL;
276	uint16* ptrL = ptrA->arrE.arrPtrE;
277	uint16 fillL = ( valueA & 0x0FF ) | ( ( valueA & 0x0FF ) << 8 );
278	for( iL = ptrA->arrE.sizeE; iL > 0; iL-- )
279	{
280		*ptrL++ = fillL;
281	}
282}
283
284/* ------------------------------------------------------------------------- */
285
286/**
287		M-------------------------------------------------------M
288		|				|						|				|
289		|				|						|				|
290		|				|						|				|
291		|				|						|				|
292		|	region x0y0	|		region x1y0		|	region x2y0	|
293		|				|						|				|
294		|				|						|				|
295		|				|						|				|
296		|---------------I-----------------------I---------------|
297		|				|						|				|
298		|				|						|				|
299		|				|						|				|
300		|				|						|				|
301		|				|						|				|
302		|				|						|				|
303		|	region x0y1	|		region x1y1		|	region x2y1	|
304		|				|						|				|
305		|				|						|				|
306		|				|						|				|
307		|				|						|				|
308		|				|						|				|
309		|				|						|				|
310		|				|						|				|
311		|---------------I-----------------------I---------------|
312		|				|						|				|
313		|				|						|				|
314		|				|						|				|
315		|				|						|				|
316		|	region x0y2	|		region x1y2		|	region x2y2	|
317		|				|						|				|
318		|				|						|				|
319		|				|						|				|
320		M-------------------------------------------------------M
321
322
323  To see how the code is organized. Refer to the diagram above.
324  Assume the original image after applying the tranzformations(translation, rotation and scaling) is "O"
325	(boundaries of the image are shown above bounded by the letter 'O').
326  This image is being Warped to the area "M" (boundaries of this area are bounded by the letter 'M').
327
328  Refer to the source code below to point to the loop that maps pixels in the particular region.
329*/
330
331/** applies affine linear warping to pixels positions of imageA before copying the into *ptrA */
332void bim_UInt16ByteImage_warp( struct bbs_Context* cpA,
333							   struct bim_UInt16ByteImage* ptrA,
334						       const struct bim_UInt16ByteImage* srcPtrA,
335						       const struct bts_Flt16Alt2D* altPtrA,
336			                   int32 resultWidthA,
337			                   int32 resultHeightA )
338{
339	long srcWidthL = srcPtrA->widthE;
340	long srcHeightL = srcPtrA->heightE;
341	long halfSrcWidthL = srcWidthL >> 1;
342
343	struct bts_Flt16Alt2D invAlt2DL;
344
345	uint16* dstPtrL;
346	const uint16* ulPtrL = srcPtrA->arrE.arrPtrE;
347	const uint16* urPtrL = ulPtrL + halfSrcWidthL - 1;
348	const uint16* llPtrL = ulPtrL + ( srcHeightL - 1 ) * halfSrcWidthL;
349	const uint16* lrPtrL = llPtrL + halfSrcWidthL - 1;
350
351	uint32 iL, jL;
352	int32 shiftL;
353
354	const uint16 bbpL = 16;
355	int32 maxInt32Value8bbpL  = 0x7FFFFFFF;
356
357	/* The bbp for all these variables is the same as bbpL */
358	int32 mxxL;
359	int32 mxyL;
360	int32 myxL;
361	int32 myyL;
362
363	int32 txL;
364	int32 tyL;
365
366	int32 xL;
367	int32 yL;
368
369	bim_UInt16ByteImage_size( cpA, ptrA, resultWidthA, resultHeightA );
370	dstPtrL = ptrA->arrE.arrPtrE;
371
372	/* compute inverse */
373	invAlt2DL = bts_Flt16Alt2D_inverted( altPtrA );
374
375	if( srcWidthL == 0 || srcHeightL == 0 )
376	{
377		bim_UInt16ByteImage_size( cpA, ptrA, srcWidthL, srcHeightL );
378		bbs_ERROR2( "Size of output image is %d/%d", srcWidthL, srcHeightL );
379		return;
380	}
381
382	/* align Matrix and Vector to 8 bits bbp */
383	shiftL = invAlt2DL.matE.bbpE - bbpL;
384	if( shiftL >= 0 )
385	{
386		mxxL = ( int32 )invAlt2DL.matE.xxE >> shiftL;
387		mxyL = ( int32 )invAlt2DL.matE.xyE >> shiftL;
388		myxL = ( int32 )invAlt2DL.matE.yxE >> shiftL;
389		myyL = ( int32 )invAlt2DL.matE.yyE >> shiftL;
390	}
391	else
392	{
393		/* Check for overflow since we are left shifting. */
394		maxInt32Value8bbpL >>= -shiftL;
395		if( invAlt2DL.matE.xxE > maxInt32Value8bbpL ||
396			invAlt2DL.matE.xyE > maxInt32Value8bbpL ||
397			invAlt2DL.matE.yxE > maxInt32Value8bbpL ||
398			invAlt2DL.matE.yyE > maxInt32Value8bbpL )
399		{
400			/* Overflow error */
401			bbs_ERROR5( "The values in the transformation matrix cause overflow during bitshift\n%d, %d,\n%d, %d\n"
402						"The maximum allowed value is %d",
403						invAlt2DL.matE.xxE >> invAlt2DL.matE.bbpE,
404						invAlt2DL.matE.xyE >> invAlt2DL.matE.bbpE,
405						invAlt2DL.matE.yxE >> invAlt2DL.matE.bbpE,
406						invAlt2DL.matE.yyE >> invAlt2DL.matE.bbpE,
407						maxInt32Value8bbpL >> ( bbpL - ( -shiftL ) ) );
408			return;
409		}
410
411		mxxL = ( int32 )invAlt2DL.matE.xxE << -shiftL;
412		mxyL = ( int32 )invAlt2DL.matE.xyE << -shiftL;
413		myxL = ( int32 )invAlt2DL.matE.yxE << -shiftL;
414		myyL = ( int32 )invAlt2DL.matE.yyE << -shiftL;
415		maxInt32Value8bbpL <<= -shiftL;
416	}
417	invAlt2DL.matE.bbpE = bbpL;
418
419	shiftL = invAlt2DL.vecE.bbpE - bbpL;
420	if( shiftL >= 0 )
421	{
422		txL  = ( int32 )invAlt2DL.vecE.xE >> shiftL;
423		tyL  = ( int32 )invAlt2DL.vecE.yE >> shiftL;
424	}
425	else
426	{
427		/* Check for overflow since we are left shifting. */
428		maxInt32Value8bbpL >>= -shiftL;
429		if(	invAlt2DL.vecE.xE  > maxInt32Value8bbpL ||
430			invAlt2DL.vecE.yE  > maxInt32Value8bbpL )
431		{
432			/* Overflow error */
433			bbs_ERROR3( "The values in the vector cause overflow during bitshift\n%d, %d,\n"
434						"The maximum allowed value is %d",
435						invAlt2DL.vecE.xE >> invAlt2DL.vecE.bbpE,
436						invAlt2DL.vecE.yE >> invAlt2DL.vecE.bbpE,
437						maxInt32Value8bbpL >> ( bbpL - ( -shiftL ) ) );
438			return;
439		}
440		txL  = ( int32 )invAlt2DL.vecE.xE << -shiftL;
441		tyL  = ( int32 )invAlt2DL.vecE.yE << -shiftL;
442		maxInt32Value8bbpL <<= -shiftL;
443	}
444	invAlt2DL.vecE.bbpE = bbpL;
445
446	/* For each destination pixel find the correspoding source pixel by applying the inverse transformation */
447	for( jL = 0; jL < ptrA->heightE; jL++ )
448	{
449		xL = txL + mxyL * jL;
450		yL = tyL + myyL * jL;
451		for( iL = 0; iL < ptrA->widthE; iL++ )
452		{
453			const uint16 bbpLby2L = bbpL / 2;
454			const int32 oneL = ( int32 )0x00000001 << bbpLby2L;
455			const int32 fractionOnlyL = 0xFFFFFFFF >> ( 32 - bbpL );
456			uint16 dstPixelL;
457
458			/* The bbp for all these variables is the same as bbpLby2L */
459			int32 f2xL;
460			int32 f2yL;
461			int32 f1xL;
462			int32 f1yL;
463
464			/* always whole numbers with a bbp of 0 */
465			int32 kL, khL;
466			int32 lL;
467
468			flag kEvenL;
469
470			/* The bbpE for these variables is bbpLby2L */
471			int32 valL;
472
473			/* Get the whole numbers only and make the bbp 0. */
474			kL = xL >> bbpL;
475			lL = yL >> bbpL;
476
477			khL = kL >> 1;
478			kEvenL = !( kL & 1 );
479
480			/* fraction of destination pixel in the next source pixel */
481			f2xL = ( xL & fractionOnlyL ) >> bbpLby2L;
482			f2yL = ( yL & fractionOnlyL ) >> bbpLby2L;
483			/* fraction of destination pixel in the current source pixel */
484			f1xL = oneL - f2xL;
485			f1yL = oneL - f2yL;
486
487			/* increment values for next loop */
488			xL += mxxL;
489			yL += myxL;
490
491			if( lL < 0 )
492			{
493				if( kL < 0 )
494				{
495					/* handle all pixels in region x0y0 */
496					dstPixelL = *ulPtrL & 0x0FF;
497				}
498				else if( kL >= srcWidthL - 1 )
499				{
500					/* handle all pixels in region x2y0 */
501					dstPixelL = *urPtrL >> 8;
502				}
503				else
504				{
505					/* handle all pixels in region x1y0 */
506					/* The bbp has shifted left by bbpLby2L */
507					if( kEvenL )
508					{
509						uint16 srcL = *( ulPtrL + khL );
510						valL = f1xL * ( srcL & 0x00FF )  +  f2xL * ( srcL >> 8 );
511					}
512					else
513					{
514						valL =  f1xL * ( *( ulPtrL + khL ) >> 8 ) + f2xL * ( *( ulPtrL + khL + 1 ) & 0x0FF );
515					}
516					dstPixelL = valL >> bbpLby2L;
517				}
518			} /* if( lL < 0 ) */
519			else if( lL >= srcHeightL - 1 )
520			{
521				if( kL < 0 )
522				{
523					/* handle all pixels in region x0y2 */
524					dstPixelL = *llPtrL & 0x0FF;
525				}
526				else if( kL >= srcWidthL - 1 )
527				{
528					/* handle all pixels in region x2y2 */
529					dstPixelL = *lrPtrL >> 8;
530				}
531				else
532				{
533					/* handle all pixels in region x1y2 */
534					/* The bbp has shifted left by bbpLby2L */
535					if( kEvenL )
536					{
537						uint16 srcL = *( llPtrL + khL );
538						valL = f1xL * ( srcL & 0x00FF ) + f2xL * ( srcL >> 8 );
539					}
540					else
541					{
542						valL =  f1xL * ( *( llPtrL + khL ) >> 8 ) + f2xL * ( *( llPtrL + khL + 1 ) & 0x0FF );
543					}
544
545					dstPixelL = valL >> bbpLby2L;
546				}
547			} /* if( lL >= srcHeightL - 1 ) */
548			else
549			{
550				const uint16* ptr1L;
551				const uint16* ptr2L;
552
553				ptr1L = ulPtrL + lL * halfSrcWidthL;
554				/* point to the pixel in the same column */
555				ptr2L = ptr1L + halfSrcWidthL;
556				if( kL < 0 )
557				{
558					/* handle all pixels in region x0y1 */
559					valL =  f1yL * ( *ptr1L & 0x0FF ) + f2yL * ( *ptr2L & 0x0FF );
560					dstPixelL = valL >> bbpLby2L;
561				}
562				else if( kL >= srcWidthL - 1 )
563				{
564					/* handle all pixels in region x2y1 */
565					valL = f1yL * ( *( ptr1L + halfSrcWidthL - 1 ) >> 8 ) +
566						   f2yL * ( *( ptr2L + halfSrcWidthL - 1 ) >> 8 );
567					dstPixelL = valL >> bbpLby2L;
568				}
569				else
570				{
571					/* assuming that bbpL = bbpLby2 * 2 */
572					/* The bbp for these variables is bbpL */
573					int32 v1L;
574					int32 v2L;
575					const int32 halfL = ( int32 )0x00000001 << ( bbpL - 1 );
576
577					/* handle all pixels in region x1y1 */
578					if( kEvenL )
579					{
580						#ifdef HW_BIG_ENDIAN
581							/* Our images are in byte order for big & little endian  so when using a
582                                                           16bit ptr our bytes will be swapped on big endian hardware shift and mask*/
583							v1L = f1xL * ( *( ptr1L + khL ) >> 8 ) + f2xL * ( *( ptr1L + khL ) & 0x0FF );
584							v2L = f1xL * ( *( ptr2L + khL ) >> 8 ) + f2xL * ( *( ptr2L + khL ) & 0x0FF );
585						#else
586							v1L = f1xL * ( *( ptr1L + khL ) & 0x0FF ) + f2xL * ( *( ptr1L + khL ) >> 8 );
587							v2L = f1xL * ( *( ptr2L + khL ) & 0x0FF ) + f2xL * ( *( ptr2L + khL ) >> 8 );
588						#endif
589					}
590					else
591					{
592						#ifdef HW_BIG_ENDIAN
593							v1L = f1xL * ( *( ptr1L + khL ) & 0x0FF ) + f2xL * ( *( ptr1L + khL + 1 ) >> 8 );
594							v2L = f1xL * ( *( ptr2L + khL ) & 0x0FF ) + f2xL * ( *( ptr2L + khL + 1 ) >> 8 );
595						#else
596							v1L = f1xL * ( *( ptr1L + khL ) >> 8 ) + f2xL * ( *( ptr1L + khL + 1 ) & 0x0FF );
597							v2L = f1xL * ( *( ptr2L + khL ) >> 8 ) + f2xL * ( *( ptr2L + khL + 1 ) & 0x0FF );
598						#endif
599					}
600					/* adding the half to round off the resulting value */
601					valL = v1L * f1yL + v2L * f2yL + halfL;
602					dstPixelL = valL >> bbpL;
603				}
604			}
605
606			if( iL & 1 )
607			{
608				#ifdef HW_BIG_ENDIAN
609					*dstPtrL |= dstPixelL & 0x0FF;
610				#else
611					*dstPtrL |= dstPixelL << 8;
612				#endif
613				dstPtrL++;
614			}
615			else
616			{
617				#ifdef HW_BIG_ENDIAN
618					*dstPtrL = dstPixelL << 8;
619				#else
620					*dstPtrL = dstPixelL & 0x0FF;
621				#endif
622			}
623
624		} /* iL loop */
625	} /* jL loop */
626
627}
628
629/* ------------------------------------------------------------------------- */
630
631#ifndef HW_TMS320C5x /* 16bit architecture excluded */
632
633void bim_UInt16ByteImage_warp8( struct bbs_Context* cpA,
634							    struct bim_UInt16ByteImage* ptrA,
635							    const struct bim_UInt16ByteImage* srcPtrA,
636							    const struct bts_Flt16Alt2D* altPtrA,
637							    int32 resultWidthA,
638							    int32 resultHeightA )
639{
640	long srcWidthL = srcPtrA->widthE;
641	long srcHeightL = srcPtrA->heightE;
642
643	struct bts_Flt16Alt2D invAlt2DL;
644
645	uint8* dstPtrL;
646	const uint8* ulPtrL = ( const uint8* )srcPtrA->arrE.arrPtrE;
647	const uint8* urPtrL = ulPtrL + srcWidthL - 1;
648	const uint8* llPtrL = ulPtrL + ( srcHeightL - 1 ) * srcWidthL;
649	const uint8* lrPtrL = llPtrL + srcWidthL - 1;
650
651	uint32 iL, jL;
652	int32 shiftL;
653
654	const uint16 bbpL = 16;
655	int32 maxInt32Value8bbpL  = 0x7FFFFFFF;
656
657	/* The bbp for all these variables is the same as bbpL */
658	int32 mxxL;
659	int32 mxyL;
660	int32 myxL;
661	int32 myyL;
662
663	int32 txL;
664	int32 tyL;
665
666	int32 xL;
667	int32 yL;
668
669	bim_UInt16ByteImage_size( cpA, ptrA, resultWidthA, resultHeightA );
670	dstPtrL = ( uint8* )ptrA->arrE.arrPtrE;
671
672	/* compute inverse */
673	invAlt2DL = bts_Flt16Alt2D_inverted( altPtrA );
674
675	if( srcWidthL == 0 || srcHeightL == 0 )
676	{
677		bbs_ERROR2( "Size of output image is %d/%d", srcWidthL, srcHeightL );
678		return;
679	}
680
681	/* align Matrix and Vector to 8 bits bbp */
682	shiftL = invAlt2DL.matE.bbpE - bbpL;
683	if( shiftL >= 0 )
684	{
685		mxxL = ( int32 )invAlt2DL.matE.xxE >> shiftL;
686		mxyL = ( int32 )invAlt2DL.matE.xyE >> shiftL;
687		myxL = ( int32 )invAlt2DL.matE.yxE >> shiftL;
688		myyL = ( int32 )invAlt2DL.matE.yyE >> shiftL;
689	}
690	else
691	{
692		/* Check for overflow since we are left shifting. */
693		maxInt32Value8bbpL >>= -shiftL;
694		if( invAlt2DL.matE.xxE > maxInt32Value8bbpL ||
695			invAlt2DL.matE.xyE > maxInt32Value8bbpL ||
696			invAlt2DL.matE.yxE > maxInt32Value8bbpL ||
697			invAlt2DL.matE.yyE > maxInt32Value8bbpL )
698		{
699			/* Overflow error */
700			bbs_ERROR5( "The values in the transformation matrix cause overflow during bitshift\n%d, %d,\n%d, %d\n"
701						"The maximum allowed value is %d",
702						( int32 )invAlt2DL.matE.xxE >> invAlt2DL.matE.bbpE,
703						( int32 )invAlt2DL.matE.xyE >> invAlt2DL.matE.bbpE,
704						( int32 )invAlt2DL.matE.yxE >> invAlt2DL.matE.bbpE,
705						( int32 )invAlt2DL.matE.yyE >> invAlt2DL.matE.bbpE,
706						maxInt32Value8bbpL >> ( bbpL - ( -shiftL ) ) );
707			return;
708		}
709
710		mxxL = ( int32 )invAlt2DL.matE.xxE << -shiftL;
711		mxyL = ( int32 )invAlt2DL.matE.xyE << -shiftL;
712		myxL = ( int32 )invAlt2DL.matE.yxE << -shiftL;
713		myyL = ( int32 )invAlt2DL.matE.yyE << -shiftL;
714		maxInt32Value8bbpL <<= -shiftL;
715	}
716	invAlt2DL.matE.bbpE = bbpL;
717
718	shiftL = invAlt2DL.vecE.bbpE - bbpL;
719	if( shiftL >= 0 )
720	{
721		txL  = ( int32 )invAlt2DL.vecE.xE >> shiftL;
722		tyL  = ( int32 )invAlt2DL.vecE.yE >> shiftL;
723	}
724	else
725	{
726		/* Check for overflow since we are left shifting. */
727		maxInt32Value8bbpL >>= -shiftL;
728		if(	invAlt2DL.vecE.xE  > maxInt32Value8bbpL ||
729			invAlt2DL.vecE.yE  > maxInt32Value8bbpL )
730		{
731			/* Overflow error */
732			bbs_ERROR3( "The values in the vector cause overflow during bitshift\n%d, %d,\n"
733						"The maximum allowed value is %d",
734						invAlt2DL.vecE.xE >> invAlt2DL.vecE.bbpE,
735						invAlt2DL.vecE.yE >> invAlt2DL.vecE.bbpE,
736						maxInt32Value8bbpL >> ( bbpL - ( -shiftL ) ) );
737			return;
738		}
739		txL  = ( int32 )invAlt2DL.vecE.xE << -shiftL;
740		tyL  = ( int32 )invAlt2DL.vecE.yE << -shiftL;
741		maxInt32Value8bbpL <<= -shiftL;
742	}
743	invAlt2DL.vecE.bbpE = bbpL;
744
745	/* For each destination pixel find the correspoding source pixel by applying the inverse transformation */
746	for( jL = 0; jL < ptrA->heightE; jL++ )
747	{
748		xL = txL + mxyL * jL;
749		yL = tyL + myyL * jL;
750		for( iL = 0; iL < ptrA->widthE; iL++ )
751		{
752			const uint16 bbpLby2L = bbpL / 2;
753			const int32 oneL = ( int32 )0x00000001 << bbpLby2L;
754			const int32 fractionOnlyL = 0xFFFFFFFF >> ( 32 - bbpL );
755
756			/* The bbp for all these variables is the same as bbpLby2L */
757			int32 f2xL;
758			int32 f2yL;
759			int32 f1xL;
760			int32 f1yL;
761
762			/* always whole numbers with a bbp of 0 */
763			int32 kL;
764			int32 lL;
765
766			/* The bbpE for these variables is bbpLby2L */
767			int32 valL;
768
769			/* Get the whole numbers only and make the bbp 0. */
770			kL = xL >> bbpL;
771			lL = yL >> bbpL;
772
773			/* fraction of destination pixel in the next source pixel */
774			f2xL = ( xL & fractionOnlyL ) >> bbpLby2L;
775			f2yL = ( yL & fractionOnlyL ) >> bbpLby2L;
776			/* fraction of destination pixel in the current source pixel */
777			f1xL = oneL - f2xL;
778			f1yL = oneL - f2yL;
779
780			/* increment values for next loop */
781			xL += mxxL;
782			yL += myxL;
783
784			if( lL < 0 )
785			{
786				if( kL < 0 )
787				{
788					/* handle all pixels in region x0y0 */
789					*dstPtrL++ = *ulPtrL;
790				}
791				else if( kL >= srcWidthL - 1 )
792				{
793					/* handle all pixels in region x2y0 */
794					*dstPtrL++ = *urPtrL;
795				}
796				else
797				{
798					/* handle all pixels in region x1y0 */
799					/* The bbp has shifted left by bbpLby2L */
800					valL =  *( ulPtrL + kL ) * f1xL + *( ulPtrL + kL + 1 ) * f2xL;
801					*dstPtrL++ = valL >> bbpLby2L;
802				}
803			} /* if( lL < 0 ) */
804			else if( lL >= srcHeightL - 1 )
805			{
806				if( kL < 0 )
807				{
808					/* handle all pixels in region x0y2 */
809					*dstPtrL++ = *llPtrL;
810				}
811				else if( kL >= srcWidthL - 1 )
812				{
813					/* handle all pixels in region x2y2 */
814					*dstPtrL++ = *lrPtrL;
815				}
816				else
817				{
818					/* handle all pixels in region x1y2 */
819					/* The bbp has shifted left by bbpLby2L */
820					valL =   *( llPtrL + kL ) * f1xL + *( llPtrL +  kL + 1 ) * f2xL;
821					*dstPtrL++ = valL >> bbpLby2L;
822				}
823			} /* if( lL >= srcHeightL - 1 ) */
824			else
825			{
826				const uint8* ptr1L;
827				const uint8* ptr2L;
828
829				ptr1L = ulPtrL + lL * srcWidthL;
830				/* point to the pixel in the same column */
831				ptr2L = ptr1L + srcWidthL;
832				if( kL < 0 )
833				{
834					/* handle all pixels in region x0y1 */
835					/* The bbp has shifted left by bbpLby2L */
836					valL = *ptr1L * f1yL + *ptr2L * f2yL ;
837					*dstPtrL++ = valL >> bbpLby2L;
838				}
839				else if( kL >= srcWidthL - 1 )
840				{
841					/* handle all pixels in region x2y1 */
842					/* The bbp has shifted left by bbpLby2L */
843					valL =  *( ptr1L + srcWidthL - 1 ) * f1yL + *( ptr2L  + srcWidthL - 1 ) * f2yL;
844					*dstPtrL++ = valL >> bbpLby2L;
845				}
846				else
847				{
848					/* assuming that bbpL = bbpLby2 * 2 */
849					/* The bbp for these variables is bbpLby2L */
850					int32 v1L;
851					int32 v2L;
852					/* The bbp for these variables is bbpL */
853					const int32 halfL = ( int32 )0x00000001 << ( bbpL - 1 );
854
855					/* handle all pixels in region x1y1 */
856					/* The bbp has shifted left by bbpLby2L */
857					v1L = *( ptr1L + kL ) * f1xL + *( ptr1L + kL + 1 ) * f2xL;
858					v2L = *( ptr2L + kL ) * f1xL + *( ptr2L + kL + 1 ) * f2xL;
859					/* The bbp has shifted left again by bbpLby2L */
860					/* adding the half to round off the resulting value */
861					valL = v1L * f1yL + v2L * f2yL + halfL;
862					*dstPtrL++ = valL >> bbpL;
863				}
864			}
865		} /* iL loop */
866	} /* jL loop */
867
868}
869
870#endif
871
872/* ------------------------------------------------------------------------- */
873
874/* ========================================================================= */
875
876
877