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/APhImage.h"
22#include "b_ImageEm/ComplexImage.h"
23
24/* ------------------------------------------------------------------------- */
25
26/* ========================================================================= */
27/*                                                                           */
28/* ---- \ghd{ auxiliary functions } ---------------------------------------- */
29/*                                                                           */
30/* ========================================================================= */
31
32/* ------------------------------------------------------------------------- */
33
34/* ========================================================================= */
35/*                                                                           */
36/* ---- \ghd{ constructor / destructor } ----------------------------------- */
37/*                                                                           */
38/* ========================================================================= */
39
40/* ------------------------------------------------------------------------- */
41
42void bim_APhImage_init( struct bbs_Context* cpA,
43					    struct bim_APhImage* ptrA )
44{
45	bbs_APhArr_init( cpA, &ptrA->arrE );
46	ptrA->widthE = 0;
47	ptrA->heightE = 0;
48}
49
50/* ------------------------------------------------------------------------- */
51
52void bim_APhImage_create( struct bbs_Context* cpA,
53						  struct bim_APhImage* ptrA,
54						  uint32 widthA,
55						  uint32 heightA,
56 					      struct bbs_MemSeg* mspA )
57{
58	if( bbs_Context_error( cpA ) ) return;
59	if( ptrA->arrE.arrPtrE != 0 )
60	{
61		bim_APhImage_size( cpA, ptrA, widthA, heightA );
62	}
63	else
64	{
65		bbs_APhArr_create( cpA, &ptrA->arrE, widthA * heightA, mspA );
66		ptrA->widthE  = widthA;
67		ptrA->heightE = heightA;
68	}
69}
70
71/* ------------------------------------------------------------------------- */
72
73void bim_APhImage_exit( struct bbs_Context* cpA,
74					    struct bim_APhImage* ptrA )
75{
76	bbs_APhArr_exit( cpA, &ptrA->arrE );
77	ptrA->widthE = 0;
78	ptrA->heightE = 0;
79}
80
81/* ------------------------------------------------------------------------- */
82
83/* ========================================================================= */
84/*                                                                           */
85/* ---- \ghd{ operators } -------------------------------------------------- */
86/*                                                                           */
87/* ========================================================================= */
88
89/* ------------------------------------------------------------------------- */
90
91void bim_APhImage_copy( struct bbs_Context* cpA,
92					    struct bim_APhImage* ptrA,
93						const struct bim_APhImage* srcPtrA )
94{
95#ifdef DEBUG1
96	if( ptrA->arrE.allocatedSizeE < srcPtrA->arrE.allocatedSizeE )
97	{
98		bbs_ERROR0( "void bim_APhImage_copy( struct bim_APhImage*, uint32 sizeA ):\n"
99				   "Unsufficient allocated memory" );
100		return;
101	}
102#endif
103	ptrA->widthE = srcPtrA->widthE;
104	ptrA->heightE = srcPtrA->heightE;
105	bbs_APhArr_copy( cpA, &ptrA->arrE, &srcPtrA->arrE );
106}
107
108/* ------------------------------------------------------------------------- */
109
110flag bim_APhImage_equal( struct bbs_Context* cpA,
111						 const struct bim_APhImage* ptrA,
112						 const struct bim_APhImage* srcPtrA )
113{
114	if( ptrA->widthE != srcPtrA->widthE ) return FALSE;
115	if( ptrA->heightE != srcPtrA->heightE ) return FALSE;
116	return bbs_APhArr_equal( cpA, &ptrA->arrE, &srcPtrA->arrE );
117}
118
119/* ------------------------------------------------------------------------- */
120
121/* ========================================================================= */
122/*                                                                           */
123/* ---- \ghd{ query functions } -------------------------------------------- */
124/*                                                                           */
125/* ========================================================================= */
126
127/* ------------------------------------------------------------------------- */
128
129/* ========================================================================= */
130/*                                                                           */
131/* ---- \ghd{ modify functions } ------------------------------------------- */
132/*                                                                           */
133/* ========================================================================= */
134
135/* ------------------------------------------------------------------------- */
136
137void bim_APhImage_size( struct bbs_Context* cpA,
138					    struct bim_APhImage* ptrA,
139						uint32 widthA,
140						uint32 heightA )
141{
142#ifdef DEBUG1
143	if( ptrA->arrE.allocatedSizeE < widthA * heightA )
144	{
145		bbs_ERROR0( "void bim_APhImage_size( struct bim_APhImage*, uint32 sizeA ):\n"
146				   "Unsufficient allocated memory" );
147		return;
148	}
149#endif
150	ptrA->widthE  = widthA;
151	ptrA->heightE = heightA;
152	bbs_APhArr_size( cpA, &ptrA->arrE, widthA * heightA );
153}
154
155/* ------------------------------------------------------------------------- */
156
157/* ========================================================================= */
158/*                                                                           */
159/* ---- \ghd{ I/O } -------------------------------------------------------- */
160/*                                                                           */
161/* ========================================================================= */
162
163/* ------------------------------------------------------------------------- */
164
165uint32 bim_APhImage_memSize( struct bbs_Context* cpA,
166							 const struct bim_APhImage* ptrA )
167{
168	return  bbs_SIZEOF16( uint32 )
169		  + bbs_SIZEOF16( uint32 ) /* version */
170		  + bbs_SIZEOF16( ptrA->widthE )
171		  + bbs_SIZEOF16( ptrA->heightE )
172		  + bbs_APhArr_memSize( cpA, &ptrA->arrE );
173}
174
175/* ------------------------------------------------------------------------- */
176
177uint32 bim_APhImage_memWrite( struct bbs_Context* cpA,
178							  const struct bim_APhImage* ptrA,
179							  uint16* memPtrA )
180{
181	uint32 memSizeL = bim_APhImage_memSize( cpA, ptrA );
182	memPtrA += bbs_memWrite32( &memSizeL, memPtrA );
183	memPtrA += bbs_memWriteUInt32( bim_APH_IMAGE_VERSION, memPtrA );
184	memPtrA += bbs_memWrite32( &ptrA->widthE, memPtrA );
185	memPtrA += bbs_memWrite32( &ptrA->heightE, memPtrA );
186	bbs_APhArr_memWrite( cpA, &ptrA->arrE, memPtrA );
187	return memSizeL;
188}
189
190/* ------------------------------------------------------------------------- */
191
192uint32 bim_APhImage_memRead( struct bbs_Context* cpA,
193							 struct bim_APhImage* ptrA,
194							 const uint16* memPtrA,
195 					         struct bbs_MemSeg* mspA )
196{
197	uint32 memSizeL, widthL, heightL, versionL;
198	if( bbs_Context_error( cpA ) ) return 0;
199	memPtrA += bbs_memRead32( &memSizeL, memPtrA );
200	memPtrA += bbs_memReadVersion32( cpA, &versionL, bim_APH_IMAGE_VERSION, memPtrA );
201	memPtrA += bbs_memRead32( &widthL, memPtrA );
202	memPtrA += bbs_memRead32( &heightL, memPtrA );
203
204	ptrA->widthE  = widthL;
205	ptrA->heightE = heightL;
206	bbs_APhArr_memRead( cpA, &ptrA->arrE, memPtrA, mspA );
207
208	if( memSizeL != bim_APhImage_memSize( cpA, ptrA ) )
209	{
210		bbs_ERR0( bbs_ERR_CORRUPT_DATA, "uint32 bim_APhImage_memRead( const struct bim_APhImage*, const void* ):\n"
211                   "size mismatch" );
212		return 0;
213	}
214	return memSizeL;
215}
216
217/* ------------------------------------------------------------------------- */
218
219/* ========================================================================= */
220/*                                                                           */
221/* ---- \ghd{ exec functions } --------------------------------------------- */
222/*                                                                           */
223/* ========================================================================= */
224
225/* ------------------------------------------------------------------------- */
226
227void bim_APhImage_setAllPixels( struct bbs_Context* cpA,
228							    struct bim_APhImage* ptrA,
229								struct bbs_APh valueA )
230{
231	long iL;
232	struct bbs_APh* ptrL = ptrA->arrE.arrPtrE;
233	for( iL = ptrA->widthE * ptrA->heightE; iL > 0; iL-- )
234	{
235		*ptrL++ = valueA;
236	}
237}
238
239/* ------------------------------------------------------------------------- */
240
241/**
242			|				|				|				|
243			|	(loop x1)	|	(loop x2)	|	(loop x3)	|
244			o------------->-o------------>--o------------->-o
245			|				|				|				|
246			|				|				|				|
247			|				|				|				|
248			|				|				|				|
249	( sectionL->x1E, sectionL->y1E )		|				|
250---------o-	R-------------------------------|----------------
251		 |	|				|				|				|
252		 |	|				|				|				|
253		 |	|				|				|				|
254		 |	|				|				|				|
255   (loop y1)|				|				|				|
256		 |	|				|				|				|
257		 V	|				|				|				|
258		 |	|				|( 0, 0 )		|				|		X
259---------o------------------I------------------------------------------------->
260		 |	|				|				|				|
261		 |	|				|				|				|
262		 |	|				|				|				|
263		 |	|				|				|				|
264		 |	|				|				|				|
265   (loop y2)|				|				|				|
266		 |	|				|				|				|
267		 |	|				|				|				|
268		 |	|				|				|				|
269		 V	|				|				|				|
270		 |	|				|				|				|
271---------o------------------|---------------I				|
272		 |	|				|		( srcPtrA->widthE, srcPtrA->heightE )
273		 |	|				|								|
274		 |	|				|								|
275		 |	|				|								|
276		 |	|				|								|
277		 |	|				|								|
278   (loop y3)|				|								|
279		 |	|				|								|
280		 |	|				|								|
281		 V	|				|								|
282		 |	|				|								|
283---------o--------------------------------------------------R
284							|				( sectionL->x2E, sectionL->y2E )
285							|
286						  Y	|
287							|
288							|
289							V
290
291  To understand how the algorithm work refer to the diagram above.
292  The image boundaries are indicated by letter "I" ( 0, 0 ) to ( srcPtrA->widthE, srcPtrA->heightE )
293  The rectangle boundaries are indicated by letter "R" ( sectionPtrA->x1E, sectionPtrA->y1E ) to ( sectionPtrA->x2E, sectionPtrA->y2E )
294
295  In the above example the intersection of the image and the rectange is
296  ( 0, 0 ), ( srcPtrA->widthE, srcPtrA->heightE )
297
298  The size of the destination image is always ( ( sectionL->x2E, sectionL->y2E ) - ( sectionL->x1E, sectionL->y1E ) )
299
300  All coordinates are assumed to be relative to the original image.
301
302  1. parse all pixels in "loop y1"
303	1.a. parse all pixels in "loop x1"
304	1.b. parse all pixels in "loop x2"
305	1.c. parse all pixels in "loop x3"
306  2. parse all pixels in "loop y2"
307	2.a. parse all pixels in "loop x1"
308	2.b. parse all pixels in "loop x2"
309	2.c. parse all pixels in "loop x3"
310  3. parse all pixels in "loop y3"
311	3.a. parse all pixels in "loop x1"
312	3.b. parse all pixels in "loop x2"
313	3.c. parse all pixels in "loop x3"
314
315*/
316
317/** copies a section of given image */
318void bim_APhImage_copySection( struct bbs_Context* cpA,
319							   struct bim_APhImage* ptrA,
320								   const struct bim_APhImage* srcPtrA,
321								   const struct bts_Int16Rect* sectionPtrA )
322{
323
324	struct bbs_APh* srcPixelPtrL;
325	struct bbs_APh* dstPixelPtrL;
326	int32 yIndexL;
327	int32 xIndexL;
328
329	struct bts_Int16Rect srcImageSubSectionL;
330	struct bts_Int16Rect sectionL;
331
332	/* make sure that the rectangle passed is correct, in case the x2 < x1 or y2 < y1, swap them */
333	sectionL.x1E = bbs_min( sectionPtrA->x1E, sectionPtrA->x2E );
334	sectionL.x2E = bbs_max( sectionPtrA->x1E, sectionPtrA->x2E );
335	sectionL.y1E = bbs_min( sectionPtrA->y1E, sectionPtrA->y2E );
336	sectionL.y2E = bbs_max( sectionPtrA->y1E, sectionPtrA->y2E );
337
338	/* find the intersection betweem the rectangle and the image, the image always starts at 0,0 */
339	srcImageSubSectionL.x1E = bbs_max( 0, sectionL.x1E );
340	srcImageSubSectionL.y1E = bbs_max( 0, sectionL.y1E );
341	srcImageSubSectionL.x2E = bbs_min( ( int32 ) srcPtrA->widthE, sectionL.x2E );
342	srcImageSubSectionL.y2E = bbs_min( ( int32 ) srcPtrA->heightE, sectionL.y2E );
343
344	/* If the image and the rectangle do not intersect in X direction, set the intersecting rectangle to the image coordinates */
345	if( srcImageSubSectionL.x2E < srcImageSubSectionL.x1E )
346	{
347		srcImageSubSectionL.x1E = 0;
348		srcImageSubSectionL.x2E = srcPtrA->widthE;
349	}
350	/* do the same as above in the Y direction */
351	if( srcImageSubSectionL.y2E < srcImageSubSectionL.y1E )
352	{
353		srcImageSubSectionL.y1E = 0;
354		srcImageSubSectionL.y2E = srcPtrA->heightE;
355	}
356
357	/* set size, and allocate required memory for the destination image if required */
358	bim_APhImage_size( cpA, ptrA, sectionL.x2E - sectionL.x1E, sectionL.y2E - sectionL.y1E );
359
360	/* get the pointer to the destination image */
361	dstPixelPtrL = ptrA->arrE.arrPtrE;
362
363	/* 1. parse all pixels in "loop y1" */
364	for( yIndexL = sectionL.y1E; yIndexL < srcImageSubSectionL.y1E && yIndexL < sectionL.y2E; yIndexL++ )
365	{
366		/* move to the first pixel that needs to be copied. */
367		srcPixelPtrL = srcPtrA->arrE.arrPtrE;
368
369		/* 1.a. parse all pixels in "loop x1" */
370		for( xIndexL = sectionL.x1E; xIndexL < srcImageSubSectionL.x1E && xIndexL < sectionL.x2E; xIndexL++ )
371		{
372			*dstPixelPtrL++ = *srcPixelPtrL;
373		}
374		/* 1.b. parse all pixels in "loop x2" */
375		for( ; xIndexL < srcImageSubSectionL.x2E && xIndexL < sectionL.x2E; xIndexL++ )
376		{
377			*dstPixelPtrL++ = *srcPixelPtrL++;
378		}
379		srcPixelPtrL--;
380		/* 1.c. parse all pixels in "loop x3" */
381		for( ; xIndexL < sectionL.x2E; xIndexL++ )
382		{
383			*dstPixelPtrL++ = *srcPixelPtrL;
384		}
385	}
386	/* 2. parse all pixels in "loop y2" */
387	for( ; yIndexL < srcImageSubSectionL.y2E && yIndexL < sectionL.y2E; yIndexL++ )
388	{
389		/* move to the first pixel that needs to be copied. */
390		srcPixelPtrL = srcPtrA->arrE.arrPtrE + yIndexL * srcPtrA->widthE + srcImageSubSectionL.x1E;
391
392		/* 2.a. parse all pixels in "loop x1" */
393		for( xIndexL = sectionL.x1E; xIndexL < srcImageSubSectionL.x1E && xIndexL < sectionL.x2E; xIndexL++ )
394		{
395			*dstPixelPtrL++ = *srcPixelPtrL;
396		}
397		/* 2.b. parse all pixels in "loop x2" */
398		for( ; xIndexL < srcImageSubSectionL.x2E && xIndexL < sectionL.x2E; xIndexL++ )
399		{
400			*dstPixelPtrL++ = *srcPixelPtrL++;
401		}
402		srcPixelPtrL--;
403		/* 2.c. parse all pixels in "loop x3" */
404		for( ; xIndexL < sectionL.x2E; xIndexL++ )
405		{
406			*dstPixelPtrL++ = *srcPixelPtrL;
407		}
408	}
409	/* 3. parse all pixels in "loop y3" */
410	for( ; yIndexL < sectionL.y2E; yIndexL++ )
411	{
412		srcPixelPtrL = srcPtrA->arrE.arrPtrE + ( srcImageSubSectionL.y2E - 1 ) * srcPtrA->widthE + srcImageSubSectionL.x1E;
413
414		/* 3.a. parse all pixels in "loop x1" */
415		for( xIndexL = sectionL.x1E; xIndexL < srcImageSubSectionL.x1E && xIndexL < sectionL.x2E; xIndexL++ )
416		{
417			*dstPixelPtrL++ = *srcPixelPtrL;
418		}
419		/* 3.b. parse all pixels in "loop x3" */
420		for( ; xIndexL < srcImageSubSectionL.x2E && xIndexL < sectionL.x2E; xIndexL++ )
421		{
422			*dstPixelPtrL++ = *srcPixelPtrL++;
423		}
424		srcPixelPtrL--;
425		/* 3.c. parse all pixels in "loop x3" */
426		for( ; xIndexL < sectionL.x2E; xIndexL++ )
427		{
428			*dstPixelPtrL++ = *srcPixelPtrL;
429		}
430	}
431
432}
433
434/* ------------------------------------------------------------------------- */
435
436void bim_APhImage_importComplex( struct bbs_Context* cpA,
437								 struct bim_APhImage* dstPtrA,
438								 const struct bim_ComplexImage* srcPtrA )
439{
440	long iL;
441	struct bbs_APh* dstL;
442	const struct bbs_Complex* srcL;
443	bim_APhImage_size( cpA, dstPtrA, srcPtrA->widthE, srcPtrA->heightE );
444	dstL = dstPtrA->arrE.arrPtrE;
445	srcL = srcPtrA->arrE.arrPtrE;
446	for( iL = srcPtrA->widthE * srcPtrA->heightE; iL > 0; iL-- )
447	{
448		bbs_APh_importComplex( dstL++, srcL++ );
449	}
450}
451
452/* ------------------------------------------------------------------------- */
453
454/* ========================================================================= */
455
456
457