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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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 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