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