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_ImageEm/Functions.h" 20 21/* ---- related objects --------------------------------------------------- */ 22 23/* ---- typedefs ----------------------------------------------------------- */ 24 25/* ---- constants ---------------------------------------------------------- */ 26 27/* ------------------------------------------------------------------------- */ 28 29/* ========================================================================= */ 30/* */ 31/* ---- \ghd{ external functions } ----------------------------------------- */ 32/* */ 33/* ========================================================================= */ 34 35/* ------------------------------------------------------------------------- */ 36 37/** downscale by factor 2 (dstPtrA and srcPtrA may be identical) */ 38void bim_downscaleBy2( uint8* dstPtrA, 39 const uint8* srcPtrA, 40 uint32 srcWidthA, 41 uint32 effWidthA, 42 uint32 effHeightA ) 43{ 44 uint32 wsL = srcWidthA; 45 uint32 w0L = effWidthA; 46 uint32 h0L = effHeightA; 47 uint32 w1L = w0L >> 1; 48 uint32 h1L = h0L >> 1; 49 50 const uint8* srcL = srcPtrA; 51 uint8* dstL = dstPtrA; 52 53 uint32 iL, jL; 54 for( jL = 0; jL < h1L; jL++ ) 55 { 56 for( iL = 0; iL < w1L; iL++ ) 57 { 58 *dstL = ( ( uint32 )srcL[ 0 ] + srcL[ 1 ] + srcL[ wsL ] + srcL[ wsL + 1 ] + 2 ) >> 2; 59 dstL++; 60 srcL += 2; 61 } 62 srcL += ( wsL - w1L ) * 2; 63 } 64} 65 66/* ------------------------------------------------------------------------- */ 67 68void bim_filterWarpInterpolation( struct bbs_Context* cpA, 69 uint8* dstImagePtrA, 70 const uint8* srcImagePtrA, 71 uint32 srcImageWidthA, 72 uint32 srcImageHeightA, 73 const struct bts_Int16Vec2D* offsPtrA, 74 const struct bts_Flt16Alt2D* altPtrA, 75 uint32 dstWidthA, 76 uint32 dstHeightA, 77 struct bbs_UInt8Arr* bufPtrA, 78 uint32 scaleThresholdA ) 79{ 80 bbs_DEF_fNameL( "bim_filterWarpInterpolation" ) 81 82 uint32 w0L = srcImageWidthA; 83 uint32 h0L = srcImageHeightA; 84 85 const uint8* srcL = srcImagePtrA; 86 uint8* dstL = dstImagePtrA; 87 88 uint32 w1L = w0L; 89 uint32 h1L = h0L; 90 91 /* 16.16 */ 92 uint32 scaleThrL = scaleThresholdA; 93 struct bts_Flt16Alt2D invAltL; 94 95 /* matrix variables */ 96 int32 mxxL, mxyL, myxL, myyL, txL, tyL; 97 98 flag downScaledL = FALSE; 99 flag boundsOkL = TRUE; 100 101 if( w0L == 0 || h0L == 0 || bts_Flt16Mat2D_det( &altPtrA->matE ) == 0 ) 102 { 103 uint32 iL; 104 for( iL = 0; iL < dstWidthA * dstHeightA; iL++ ) dstImagePtrA[ iL ] = 0; 105 return; 106 } 107 108 /* compute inverse ALT */ 109 invAltL = bts_Flt16Alt2D_inverted( altPtrA ); 110 111 /* fixed point ALT 16.16 */ 112 if( invAltL.matE.bbpE <= 16 ) 113 { 114 uint32 shlL = 16 - invAltL.matE.bbpE; 115 mxxL = invAltL.matE.xxE << shlL; 116 mxyL = invAltL.matE.xyE << shlL; 117 myxL = invAltL.matE.yxE << shlL; 118 myyL = invAltL.matE.yyE << shlL; 119 } 120 else 121 { 122 uint32 shrL = invAltL.matE.bbpE - 16; 123 mxxL = ( ( invAltL.matE.xxE >> ( shrL - 1 ) ) + 1 ) >> 1; 124 mxyL = ( ( invAltL.matE.xyE >> ( shrL - 1 ) ) + 1 ) >> 1; 125 myxL = ( ( invAltL.matE.yxE >> ( shrL - 1 ) ) + 1 ) >> 1; 126 myyL = ( ( invAltL.matE.yyE >> ( shrL - 1 ) ) + 1 ) >> 1; 127 } 128 129 if( invAltL.vecE.bbpE <= 16 ) 130 { 131 uint32 shlL = 16 - invAltL.vecE.bbpE; 132 txL = invAltL.vecE.xE << shlL; 133 tyL = invAltL.vecE.yE << shlL; 134 } 135 else 136 { 137 uint32 shrL = invAltL.vecE.bbpE - 16; 138 txL = ( ( invAltL.vecE.xE >> ( shrL - 1 ) ) + 1 ) >> 1; 139 tyL = ( ( invAltL.vecE.yE >> ( shrL - 1 ) ) + 1 ) >> 1; 140 } 141 142 /* add offset */ 143 txL += ( int32 )offsPtrA->xE << 16; 144 tyL += ( int32 )offsPtrA->yE << 16; 145 146 if( scaleThresholdA > 0 ) 147 { 148 /* compute downscale exponent */ 149 uint32 axxL = ( mxxL >= 0 ) ? mxxL : -mxxL; 150 uint32 axyL = ( mxyL >= 0 ) ? mxyL : -mxyL; 151 uint32 ayxL = ( myxL >= 0 ) ? myxL : -myxL; 152 uint32 ayyL = ( myyL >= 0 ) ? myyL : -myyL; 153 154 uint32 a1L = ( axxL > ayxL ) ? axxL : ayxL; 155 uint32 a2L = ( axyL > ayyL ) ? axyL : ayyL; 156 157 uint32 invScaleL = ( a1L < a2L ) ? a1L : a2L; 158 uint32 scaleExpL = 0; 159 while( ( invScaleL >> scaleExpL ) > scaleThrL ) scaleExpL++; 160 while( ( scaleExpL > 0 ) && ( w0L >> scaleExpL ) < 2 ) scaleExpL--; 161 while( ( scaleExpL > 0 ) && ( h0L >> scaleExpL ) < 2 ) scaleExpL--; 162 163 /* downscale image */ 164 if( scaleExpL > 0 ) 165 { 166 /* down sampling is limited to the effective area of the original image */ 167 168 /* compute effective area by mapping all corners of the dst rectangle */ 169 int32 xMinL = 0x7FFFFFFF; 170 int32 yMinL = 0x7FFFFFFF; 171 int32 xMaxL = 0x80000000; 172 int32 yMaxL = 0x80000000; 173 uint32 wEffL, hEffL; 174 175 { 176 int32 xL, yL; 177 xL = txL; 178 yL = tyL; 179 xMinL = xL < xMinL ? xL : xMinL; 180 yMinL = yL < yMinL ? yL : yMinL; 181 xMaxL = xL > xMaxL ? xL : xMaxL; 182 yMaxL = yL > yMaxL ? yL : yMaxL; 183 xL = txL + mxxL * ( int32 )dstWidthA + mxyL * ( int32 )dstHeightA; 184 yL = tyL + myxL * ( int32 )dstWidthA + myyL * ( int32 )dstHeightA; 185 xMinL = xL < xMinL ? xL : xMinL; 186 yMinL = yL < yMinL ? yL : yMinL; 187 xMaxL = xL > xMaxL ? xL : xMaxL; 188 yMaxL = yL > yMaxL ? yL : yMaxL; 189 xL = txL + mxyL * ( int32 )dstHeightA; 190 yL = tyL + myyL * ( int32 )dstHeightA; 191 xMinL = xL < xMinL ? xL : xMinL; 192 yMinL = yL < yMinL ? yL : yMinL; 193 xMaxL = xL > xMaxL ? xL : xMaxL; 194 yMaxL = yL > yMaxL ? yL : yMaxL; 195 xL = txL + mxxL * ( int32 )dstWidthA; 196 yL = tyL + myxL * ( int32 )dstWidthA; 197 xMinL = xL < xMinL ? xL : xMinL; 198 yMinL = yL < yMinL ? yL : yMinL; 199 xMaxL = xL > xMaxL ? xL : xMaxL; 200 yMaxL = yL > yMaxL ? yL : yMaxL; 201 } 202 203 xMaxL = ( xMaxL >> 16 ) + 2; 204 yMaxL = ( yMaxL >> 16 ) + 2; 205 xMinL >>= 16; 206 yMinL >>= 16; 207 208 /* ensre effective area stays within original frame */ 209 xMinL = 0 > xMinL ? 0 : xMinL; 210 yMinL = 0 > yMinL ? 0 : yMinL; 211 xMinL = ( int32 )w0L < xMinL ? w0L : xMinL; 212 yMinL = ( int32 )h0L < yMinL ? h0L : yMinL; 213 xMaxL = 0 > xMaxL ? 0 : xMaxL; 214 yMaxL = 0 > yMaxL ? 0 : yMaxL; 215 xMaxL = ( int32 )w0L < xMaxL ? w0L : xMaxL; 216 yMaxL = ( int32 )h0L < yMaxL ? h0L : yMaxL; 217 218 wEffL = xMaxL - xMinL; 219 hEffL = yMaxL - yMinL; 220 221 /* ensure downscaling does not reduce image to 0 */ 222 while( ( scaleExpL > 0 ) && ( wEffL >> scaleExpL ) < 2 ) scaleExpL--; 223 while( ( scaleExpL > 0 ) && ( hEffL >> scaleExpL ) < 2 ) scaleExpL--; 224 225 /* downscale */ 226 if( scaleExpL > 0 ) 227 { 228 uint32 iL; 229 w1L = wEffL >> 1; 230 h1L = hEffL >> 1; 231 if( bufPtrA == NULL ) bbs_ERROR1( "%s:\nPreallocated buffer is needed", fNameL ); 232 bbs_UInt8Arr_size( cpA, bufPtrA, w1L * h1L ); 233 bim_downscaleBy2( bufPtrA->arrPtrE, srcL + yMinL * w0L + xMinL, w0L, wEffL, hEffL ); 234 for( iL = 1; iL < scaleExpL; iL++ ) 235 { 236 bim_downscaleBy2( bufPtrA->arrPtrE, bufPtrA->arrPtrE, w1L, w1L, h1L ); 237 w1L >>= 1; 238 h1L >>= 1; 239 } 240 241 /* adjust inverted cordinates */ 242 txL -= ( xMinL << 16 ); 243 tyL -= ( yMinL << 16 ); 244 mxxL >>= scaleExpL; 245 mxyL >>= scaleExpL; 246 myxL >>= scaleExpL; 247 myyL >>= scaleExpL; 248 txL >>= scaleExpL; 249 tyL >>= scaleExpL; 250 srcL = bufPtrA->arrPtrE; 251 } 252 253 downScaledL = TRUE; 254 } 255 } 256 257 /* if not downscaled and src and dst images are identcal then copy srcImage into buffer */ 258 if( !downScaledL && dstImagePtrA == srcImagePtrA ) 259 { 260 uint32 iL; 261 uint32 srcSizeL = srcImageWidthA * srcImageHeightA; 262 if( bufPtrA == NULL ) bbs_ERROR1( "%s:\nPreallocated buffer is needed", fNameL ); 263 bbs_UInt8Arr_size( cpA, bufPtrA, srcSizeL ); 264 for( iL = 0; iL < srcSizeL; iL++ ) bufPtrA->arrPtrE[ iL ] = srcImagePtrA[ iL ]; 265 srcL = bufPtrA->arrPtrE; 266 } 267 268 /* compute destination image */ 269 270 /* bounds check (dst image fully inside src image? -> fast algorithm) */ 271 { 272 int32 xL, yL; 273 int32 wbL = w1L - 1; 274 int32 hbL = h1L - 1; 275 276 xL = txL >> 16; 277 yL = tyL >> 16; 278 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); 279 280 xL = ( txL + mxxL * ( int32 )( dstWidthA - 1 ) ) >> 16; 281 yL = ( tyL + myxL * ( int32 )( dstWidthA - 1 ) ) >> 16; 282 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); 283 284 xL = ( txL + mxyL * ( int32 )( dstHeightA - 1 ) ) >> 16; 285 yL = ( tyL + myyL * ( int32 )( dstHeightA - 1 ) ) >> 16; 286 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); 287 288 xL = ( txL + mxyL * ( int32 )( dstHeightA - 1 ) + mxxL * ( int32 )( dstWidthA - 1 ) ) >> 16; 289 yL = ( tyL + myyL * ( int32 )( dstHeightA - 1 ) + myxL * ( int32 )( dstWidthA - 1 ) ) >> 16; 290 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); 291 } 292 293 if( boundsOkL ) 294 { 295 int32 iL, jL; 296 for( jL = 0; jL < ( int32 )dstHeightA; jL++ ) 297 { 298 /* 16.16 */ 299 int32 xL = txL + mxyL * jL; 300 int32 yL = tyL + myyL * jL; 301 for( iL = 0; iL < ( int32 )dstWidthA; iL++ ) 302 { 303 int32 x0L = xL >> 16; 304 int32 y0L = yL >> 16; 305 uint32 xf2L = xL & 0x0FFFF; 306 uint32 yf2L = yL & 0x0FFFF; 307 uint32 xf1L = 0x10000 - xf2L; 308 uint32 yf1L = 0x10000 - yf2L; 309 310 xL += mxxL; 311 yL += myxL; 312 313 { 314 uint32 idxL = y0L * w1L + x0L; 315 uint32 v1L = ( ( uint32 )srcL[ idxL ] * xf1L + ( uint32 )srcL[ idxL + 1 ] * xf2L + 0x0800 ) >> 12; 316 uint32 v2L = ( ( uint32 )srcL[ idxL + w1L ] * xf1L + ( uint32 )srcL[ idxL + w1L + 1 ] * xf2L + 0x0800 ) >> 12; 317 *dstL++ = ( v1L * yf1L + v2L * yf2L + 0x080000 ) >> 20; 318 } 319 } 320 } 321 } 322 else 323 { 324 int32 iL, jL; 325 for( jL = 0; jL < ( int32 )dstHeightA; jL++ ) 326 { 327 /* 16.16 */ 328 int32 xL = txL + mxyL * jL; 329 int32 yL = tyL + myyL * jL; 330 for( iL = 0; iL < ( int32 )dstWidthA; iL++ ) 331 { 332 int32 x0L = xL >> 16; 333 int32 y0L = yL >> 16; 334 uint32 xf2L = xL & 0x0FFFF; 335 uint32 yf2L = yL & 0x0FFFF; 336 uint32 xf1L = 0x10000 - xf2L; 337 uint32 yf1L = 0x10000 - yf2L; 338 339 xL += mxxL; 340 yL += myxL; 341 342 if( y0L < 0 ) 343 { 344 if( x0L < 0 ) 345 { 346 *dstL++ = srcL[ 0 ]; 347 } 348 else if( x0L >= ( int32 )w1L - 1 ) 349 { 350 *dstL++ = srcL[ w1L - 1 ]; 351 } 352 else 353 { 354 *dstL++ = ( ( uint32 )srcL[ x0L ] * xf1L + ( uint32 )srcL[ x0L + 1 ] * xf2L + 0x08000 ) >> 16; 355 } 356 } 357 else if( y0L >= ( int32 )h1L - 1 ) 358 { 359 if( x0L < 0 ) 360 { 361 *dstL++ = srcL[ ( h1L - 1 ) * w1L ]; 362 } 363 else if( x0L >= ( int32 )w1L - 1 ) 364 { 365 *dstL++ = srcL[ ( h1L * w1L ) - 1 ]; 366 } 367 else 368 { 369 uint32 idxL = ( h1L - 1 ) * w1L + x0L; 370 *dstL++ = ( ( uint32 )srcL[ idxL ] * xf1L + ( uint32 )srcL[ idxL + 1 ] * xf2L + 0x08000 ) >> 16; 371 } 372 } 373 else 374 { 375 if( x0L < 0 ) 376 { 377 uint32 idxL = y0L * w1L; 378 *dstL++ = ( ( uint32 )srcL[ idxL ] * yf1L + ( uint32 )srcL[ idxL + w1L ] * yf2L + 0x08000 ) >> 16; 379 } 380 else if( x0L >= ( int32 )w1L - 1 ) 381 { 382 uint32 idxL = ( y0L + 1 ) * w1L - 1; 383 *dstL++ = ( ( uint32 )srcL[ idxL ] * yf1L + ( uint32 )srcL[ idxL + w1L ] * yf2L + 0x08000 ) >> 16; 384 } 385 else 386 { 387 uint32 idxL = y0L * w1L + x0L; 388 uint32 v1L = ( ( uint32 )srcL[ idxL ] * xf1L + ( uint32 )srcL[ idxL + 1 ] * xf2L + 0x0800 ) >> 12; 389 uint32 v2L = ( ( uint32 )srcL[ idxL + w1L ] * xf1L + ( uint32 )srcL[ idxL + w1L + 1 ] * xf2L + 0x0800 ) >> 12; 390 *dstL++ = ( v1L * yf1L + v2L * yf2L + 0x080000 ) >> 20; 391 } 392 } 393 } 394 } 395 } 396} 397 398/* ------------------------------------------------------------------------- */ 399 400void bim_filterWarpPixelReplication( struct bbs_Context* cpA, 401 uint8* dstImagePtrA, 402 const uint8* srcImagePtrA, 403 uint32 srcImageWidthA, 404 uint32 srcImageHeightA, 405 const struct bts_Int16Vec2D* offsPtrA, 406 const struct bts_Flt16Alt2D* altPtrA, 407 uint32 dstWidthA, 408 uint32 dstHeightA, 409 struct bbs_UInt8Arr* bufPtrA, 410 uint32 scaleThresholdA ) 411{ 412 bbs_DEF_fNameL( "bim_filterWarpPixelReplication" ) 413 414 uint32 w0L = srcImageWidthA; 415 uint32 h0L = srcImageHeightA; 416 417 const uint8* srcL = srcImagePtrA; 418 uint8* dstL = dstImagePtrA; 419 420 uint32 w1L = w0L; 421 uint32 h1L = h0L; 422 423 /* 16.16 */ 424 uint32 scaleThrL = scaleThresholdA; 425 struct bts_Flt16Alt2D invAltL; 426 427 /* matrix variables */ 428 int32 mxxL, mxyL, myxL, myyL, txL, tyL; 429 430 flag downScaledL = FALSE; 431 flag boundsOkL = TRUE; 432 433 if( w0L == 0 || h0L == 0 || bts_Flt16Mat2D_det( &altPtrA->matE ) == 0 ) 434 { 435 uint32 iL; 436 for( iL = 0; iL < dstWidthA * dstHeightA; iL++ ) dstImagePtrA[ iL ] = 0; 437 return; 438 } 439 440 /* compute inverse ALT */ 441 invAltL = bts_Flt16Alt2D_inverted( altPtrA ); 442 443 /* fixed point ALT 16.16 */ 444 if( invAltL.matE.bbpE <= 16 ) 445 { 446 uint32 shlL = 16 - invAltL.matE.bbpE; 447 mxxL = invAltL.matE.xxE << shlL; 448 mxyL = invAltL.matE.xyE << shlL; 449 myxL = invAltL.matE.yxE << shlL; 450 myyL = invAltL.matE.yyE << shlL; 451 } 452 else 453 { 454 uint32 shrL = invAltL.matE.bbpE - 16; 455 mxxL = ( ( invAltL.matE.xxE >> ( shrL - 1 ) ) + 1 ) >> 1; 456 mxyL = ( ( invAltL.matE.xyE >> ( shrL - 1 ) ) + 1 ) >> 1; 457 myxL = ( ( invAltL.matE.yxE >> ( shrL - 1 ) ) + 1 ) >> 1; 458 myyL = ( ( invAltL.matE.yyE >> ( shrL - 1 ) ) + 1 ) >> 1; 459 } 460 461 if( invAltL.vecE.bbpE <= 16 ) 462 { 463 uint32 shlL = 16 - invAltL.vecE.bbpE; 464 txL = invAltL.vecE.xE << shlL; 465 tyL = invAltL.vecE.yE << shlL; 466 } 467 else 468 { 469 uint32 shrL = invAltL.vecE.bbpE - 16; 470 txL = ( ( invAltL.vecE.xE >> ( shrL - 1 ) ) + 1 ) >> 1; 471 tyL = ( ( invAltL.vecE.yE >> ( shrL - 1 ) ) + 1 ) >> 1; 472 } 473 474 /* add offset */ 475 txL += ( int32 )offsPtrA->xE << 16; 476 tyL += ( int32 )offsPtrA->yE << 16; 477 478 if( scaleThresholdA > 0 ) 479 { 480 /* compute downscale exponent */ 481 uint32 axxL = ( mxxL >= 0 ) ? mxxL : -mxxL; 482 uint32 axyL = ( mxyL >= 0 ) ? mxyL : -mxyL; 483 uint32 ayxL = ( myxL >= 0 ) ? myxL : -myxL; 484 uint32 ayyL = ( myyL >= 0 ) ? myyL : -myyL; 485 486 uint32 a1L = ( axxL > ayxL ) ? axxL : ayxL; 487 uint32 a2L = ( axyL > ayyL ) ? axyL : ayyL; 488 489 uint32 invScaleL = ( a1L < a2L ) ? a1L : a2L; 490 uint32 scaleExpL = 0; 491 while( ( invScaleL >> scaleExpL ) > scaleThrL ) scaleExpL++; 492 while( ( scaleExpL > 0 ) && ( w0L >> scaleExpL ) < 2 ) scaleExpL--; 493 while( ( scaleExpL > 0 ) && ( h0L >> scaleExpL ) < 2 ) scaleExpL--; 494 495 /* downscale image */ 496 if( scaleExpL > 0 ) 497 { 498 /* down sampling is limited to the effective area of the original image */ 499 500 /* compute effective area by mapping all corners of the dst rectangle */ 501 int32 xMinL = 0x7FFFFFFF; 502 int32 yMinL = 0x7FFFFFFF; 503 int32 xMaxL = 0x80000000; 504 int32 yMaxL = 0x80000000; 505 uint32 wEffL, hEffL; 506 507 { 508 int32 xL, yL; 509 xL = txL; 510 yL = tyL; 511 xMinL = xL < xMinL ? xL : xMinL; 512 yMinL = yL < yMinL ? yL : yMinL; 513 xMaxL = xL > xMaxL ? xL : xMaxL; 514 yMaxL = yL > yMaxL ? yL : yMaxL; 515 xL = txL + mxxL * ( int32 )dstWidthA + mxyL * ( int32 )dstHeightA; 516 yL = tyL + myxL * ( int32 )dstWidthA + myyL * ( int32 )dstHeightA; 517 xMinL = xL < xMinL ? xL : xMinL; 518 yMinL = yL < yMinL ? yL : yMinL; 519 xMaxL = xL > xMaxL ? xL : xMaxL; 520 yMaxL = yL > yMaxL ? yL : yMaxL; 521 xL = txL + mxyL * ( int32 )dstHeightA; 522 yL = tyL + myyL * ( int32 )dstHeightA; 523 xMinL = xL < xMinL ? xL : xMinL; 524 yMinL = yL < yMinL ? yL : yMinL; 525 xMaxL = xL > xMaxL ? xL : xMaxL; 526 yMaxL = yL > yMaxL ? yL : yMaxL; 527 xL = txL + mxxL * ( int32 )dstWidthA; 528 yL = tyL + myxL * ( int32 )dstWidthA; 529 xMinL = xL < xMinL ? xL : xMinL; 530 yMinL = yL < yMinL ? yL : yMinL; 531 xMaxL = xL > xMaxL ? xL : xMaxL; 532 yMaxL = yL > yMaxL ? yL : yMaxL; 533 } 534 535 xMaxL = ( xMaxL >> 16 ) + 2; 536 yMaxL = ( yMaxL >> 16 ) + 2; 537 xMinL >>= 16; 538 yMinL >>= 16; 539 540 /* ensre effective area stays within original frame */ 541 xMinL = 0 > xMinL ? 0 : xMinL; 542 yMinL = 0 > yMinL ? 0 : yMinL; 543 xMinL = ( int32 )w0L < xMinL ? w0L : xMinL; 544 yMinL = ( int32 )h0L < yMinL ? h0L : yMinL; 545 xMaxL = 0 > xMaxL ? 0 : xMaxL; 546 yMaxL = 0 > yMaxL ? 0 : yMaxL; 547 xMaxL = ( int32 )w0L < xMaxL ? w0L : xMaxL; 548 yMaxL = ( int32 )h0L < yMaxL ? h0L : yMaxL; 549 550 wEffL = xMaxL - xMinL; 551 hEffL = yMaxL - yMinL; 552 553 /* ensure downscaling does not reduce image to 0 */ 554 while( ( scaleExpL > 0 ) && ( wEffL >> scaleExpL ) < 2 ) scaleExpL--; 555 while( ( scaleExpL > 0 ) && ( hEffL >> scaleExpL ) < 2 ) scaleExpL--; 556 557 /* downscale */ 558 if( scaleExpL > 0 ) 559 { 560 uint32 iL; 561 w1L = wEffL >> 1; 562 h1L = hEffL >> 1; 563 if( bufPtrA == NULL ) bbs_ERROR1( "%s:\nPreallocated buffer is needed", fNameL ); 564 bbs_UInt8Arr_size( cpA, bufPtrA, w1L * h1L ); 565 bim_downscaleBy2( bufPtrA->arrPtrE, srcL + yMinL * w0L + xMinL, w0L, wEffL, hEffL ); 566 for( iL = 1; iL < scaleExpL; iL++ ) 567 { 568 bim_downscaleBy2( bufPtrA->arrPtrE, bufPtrA->arrPtrE, w1L, w1L, h1L ); 569 w1L >>= 1; 570 h1L >>= 1; 571 } 572 573 /* adjust inverted cordinates */ 574 txL -= ( xMinL << 16 ); 575 tyL -= ( yMinL << 16 ); 576 mxxL >>= scaleExpL; 577 mxyL >>= scaleExpL; 578 myxL >>= scaleExpL; 579 myyL >>= scaleExpL; 580 txL >>= scaleExpL; 581 tyL >>= scaleExpL; 582 srcL = bufPtrA->arrPtrE; 583 } 584 585 downScaledL = TRUE; 586 } 587 } 588 589 /* if not downscaled and src and dst images are identcal then copy srcImage into buffer */ 590 if( !downScaledL && dstImagePtrA == srcImagePtrA ) 591 { 592 uint32 iL; 593 uint32 srcSizeL = srcImageWidthA * srcImageHeightA; 594 if( bufPtrA == NULL ) bbs_ERROR1( "%s:\nPreallocated buffer is needed", fNameL ); 595 bbs_UInt8Arr_size( cpA, bufPtrA, srcSizeL ); 596 for( iL = 0; iL < srcSizeL; iL++ ) bufPtrA->arrPtrE[ iL ] = srcImagePtrA[ iL ]; 597 srcL = bufPtrA->arrPtrE; 598 } 599 600 /* compute destination image */ 601 602 /* bounds check (dst image fully inside src image? -> fast algorithm) */ 603 { 604 int32 xL, yL; 605 int32 wbL = w1L - 1; 606 int32 hbL = h1L - 1; 607 608 xL = txL >> 16; 609 yL = tyL >> 16; 610 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); 611 612 xL = ( txL + mxxL * ( int32 )( dstWidthA - 1 ) ) >> 16; 613 yL = ( tyL + myxL * ( int32 )( dstWidthA - 1 ) ) >> 16; 614 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); 615 616 xL = ( txL + mxyL * ( int32 )( dstHeightA - 1 ) ) >> 16; 617 yL = ( tyL + myyL * ( int32 )( dstHeightA - 1 ) ) >> 16; 618 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); 619 620 xL = ( txL + mxyL * ( int32 )( dstHeightA - 1 ) + mxxL * ( int32 )( dstWidthA - 1 ) ) >> 16; 621 yL = ( tyL + myyL * ( int32 )( dstHeightA - 1 ) + myxL * ( int32 )( dstWidthA - 1 ) ) >> 16; 622 boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); 623 } 624 625 if( boundsOkL ) 626 { 627 int32 iL, jL; 628 for( jL = 0; jL < ( int32 )dstHeightA; jL++ ) 629 { 630 /* 16.16 */ 631 int32 xL = txL + mxyL * jL; 632 int32 yL = tyL + myyL * jL; 633 for( iL = 0; iL < ( int32 )dstWidthA; iL++ ) 634 { 635 /* nearest whole position */ 636 *dstL++ = srcL[ ( ( ( yL >> 15 ) + 1 ) >> 1 ) * w1L + ( ( ( xL >> 15 ) + 1 ) >> 1 ) ]; 637 xL += mxxL; 638 yL += myxL; 639 } 640 } 641 } 642 else 643 { 644 int32 iL, jL; 645 for( jL = 0; jL < ( int32 )dstHeightA; jL++ ) 646 { 647 /* 16.16 */ 648 int32 xL = txL + mxyL * jL; 649 int32 yL = tyL + myyL * jL; 650 for( iL = 0; iL < ( int32 )dstWidthA; iL++ ) 651 { 652 /* nearest whole position */ 653 int32 x0L = ( ( xL >> 15 ) + 1 ) >> 1; 654 int32 y0L = ( ( yL >> 15 ) + 1 ) >> 1; 655 xL += mxxL; 656 yL += myxL; 657 658 if( y0L < 0 ) 659 { 660 if( x0L < 0 ) 661 { 662 *dstL++ = srcL[ 0 ]; 663 } 664 else if( x0L >= ( int32 )w1L - 1 ) 665 { 666 *dstL++ = srcL[ w1L - 1 ]; 667 } 668 else 669 { 670 *dstL++ = srcL[ x0L ]; 671 } 672 } 673 else if( y0L >= ( int32 )h1L - 1 ) 674 { 675 if( x0L < 0 ) 676 { 677 *dstL++ = srcL[ ( h1L - 1 ) * w1L ]; 678 } 679 else if( x0L >= ( int32 )w1L - 1 ) 680 { 681 *dstL++ = srcL[ ( h1L * w1L ) - 1 ]; 682 } 683 else 684 { 685 *dstL++ = srcL[ ( h1L - 1 ) * w1L + x0L ]; 686 } 687 } 688 else 689 { 690 if( x0L < 0 ) 691 { 692 *dstL++ = srcL[ y0L * w1L ]; 693 } 694 else if( x0L >= ( int32 )w1L - 1 ) 695 { 696 *dstL++ = srcL[ ( y0L + 1 ) * w1L - 1 ]; 697 } 698 else 699 { 700 *dstL++ = srcL[ y0L * w1L + x0L ]; 701 } 702 } 703 } 704 } 705 } 706} 707 708/* ------------------------------------------------------------------------- */ 709 710void bim_filterWarp( struct bbs_Context* cpA, 711 uint8* dstImagePtrA, 712 const uint8* srcImagePtrA, 713 uint32 srcImageWidthA, 714 uint32 srcImageHeightA, 715 const struct bts_Int16Vec2D* offsPtrA, 716 const struct bts_Flt16Alt2D* altPtrA, 717 uint32 dstWidthA, 718 uint32 dstHeightA, 719 struct bbs_UInt8Arr* bufPtrA, 720 uint32 scaleThresholdA, 721 flag interpolateA ) 722{ 723 if( interpolateA ) 724 { 725 bim_filterWarpInterpolation( cpA, dstImagePtrA, srcImagePtrA, srcImageWidthA, srcImageHeightA, offsPtrA, altPtrA, dstWidthA, dstHeightA, bufPtrA, scaleThresholdA ); 726 } 727 else 728 { 729 bim_filterWarpPixelReplication( cpA, dstImagePtrA, srcImagePtrA, srcImageWidthA, srcImageHeightA, offsPtrA, altPtrA, dstWidthA, dstHeightA, bufPtrA, scaleThresholdA ); 730 } 731} 732 733/* ------------------------------------------------------------------------- */ 734 735