| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* ---- includes ----------------------------------------------------------- */ |
| |
| #include "b_ImageEm/Functions.h" |
| |
| /* ---- related objects --------------------------------------------------- */ |
| |
| /* ---- typedefs ----------------------------------------------------------- */ |
| |
| /* ---- constants ---------------------------------------------------------- */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ external functions } ----------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /** downscale by factor 2 (dstPtrA and srcPtrA may be identical) */ |
| void bim_downscaleBy2( uint8* dstPtrA, |
| const uint8* srcPtrA, |
| uint32 srcWidthA, |
| uint32 effWidthA, |
| uint32 effHeightA ) |
| { |
| uint32 wsL = srcWidthA; |
| uint32 w0L = effWidthA; |
| uint32 h0L = effHeightA; |
| uint32 w1L = w0L >> 1; |
| uint32 h1L = h0L >> 1; |
| |
| const uint8* srcL = srcPtrA; |
| uint8* dstL = dstPtrA; |
| |
| uint32 iL, jL; |
| for( jL = 0; jL < h1L; jL++ ) |
| { |
| for( iL = 0; iL < w1L; iL++ ) |
| { |
| *dstL = ( ( uint32 )srcL[ 0 ] + srcL[ 1 ] + srcL[ wsL ] + srcL[ wsL + 1 ] + 2 ) >> 2; |
| dstL++; |
| srcL += 2; |
| } |
| srcL += ( wsL - w1L ) * 2; |
| } |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bim_filterWarpInterpolation( struct bbs_Context* cpA, |
| uint8* dstImagePtrA, |
| const uint8* srcImagePtrA, |
| uint32 srcImageWidthA, |
| uint32 srcImageHeightA, |
| const struct bts_Int16Vec2D* offsPtrA, |
| const struct bts_Flt16Alt2D* altPtrA, |
| uint32 dstWidthA, |
| uint32 dstHeightA, |
| struct bbs_UInt8Arr* bufPtrA, |
| uint32 scaleThresholdA ) |
| { |
| bbs_DEF_fNameL( "bim_filterWarpInterpolation" ) |
| |
| uint32 w0L = srcImageWidthA; |
| uint32 h0L = srcImageHeightA; |
| |
| const uint8* srcL = srcImagePtrA; |
| uint8* dstL = dstImagePtrA; |
| |
| uint32 w1L = w0L; |
| uint32 h1L = h0L; |
| |
| /* 16.16 */ |
| uint32 scaleThrL = scaleThresholdA; |
| struct bts_Flt16Alt2D invAltL; |
| |
| /* matrix variables */ |
| int32 mxxL, mxyL, myxL, myyL, txL, tyL; |
| |
| flag downScaledL = FALSE; |
| flag boundsOkL = TRUE; |
| |
| if( w0L == 0 || h0L == 0 || bts_Flt16Mat2D_det( &altPtrA->matE ) == 0 ) |
| { |
| uint32 iL; |
| for( iL = 0; iL < dstWidthA * dstHeightA; iL++ ) dstImagePtrA[ iL ] = 0; |
| return; |
| } |
| |
| /* compute inverse ALT */ |
| invAltL = bts_Flt16Alt2D_inverted( altPtrA ); |
| |
| /* fixed point ALT 16.16 */ |
| if( invAltL.matE.bbpE <= 16 ) |
| { |
| uint32 shlL = 16 - invAltL.matE.bbpE; |
| mxxL = invAltL.matE.xxE << shlL; |
| mxyL = invAltL.matE.xyE << shlL; |
| myxL = invAltL.matE.yxE << shlL; |
| myyL = invAltL.matE.yyE << shlL; |
| } |
| else |
| { |
| uint32 shrL = invAltL.matE.bbpE - 16; |
| mxxL = ( ( invAltL.matE.xxE >> ( shrL - 1 ) ) + 1 ) >> 1; |
| mxyL = ( ( invAltL.matE.xyE >> ( shrL - 1 ) ) + 1 ) >> 1; |
| myxL = ( ( invAltL.matE.yxE >> ( shrL - 1 ) ) + 1 ) >> 1; |
| myyL = ( ( invAltL.matE.yyE >> ( shrL - 1 ) ) + 1 ) >> 1; |
| } |
| |
| if( invAltL.vecE.bbpE <= 16 ) |
| { |
| uint32 shlL = 16 - invAltL.vecE.bbpE; |
| txL = invAltL.vecE.xE << shlL; |
| tyL = invAltL.vecE.yE << shlL; |
| } |
| else |
| { |
| uint32 shrL = invAltL.vecE.bbpE - 16; |
| txL = ( ( invAltL.vecE.xE >> ( shrL - 1 ) ) + 1 ) >> 1; |
| tyL = ( ( invAltL.vecE.yE >> ( shrL - 1 ) ) + 1 ) >> 1; |
| } |
| |
| /* add offset */ |
| txL += ( int32 )offsPtrA->xE << 16; |
| tyL += ( int32 )offsPtrA->yE << 16; |
| |
| if( scaleThresholdA > 0 ) |
| { |
| /* compute downscale exponent */ |
| uint32 axxL = ( mxxL >= 0 ) ? mxxL : -mxxL; |
| uint32 axyL = ( mxyL >= 0 ) ? mxyL : -mxyL; |
| uint32 ayxL = ( myxL >= 0 ) ? myxL : -myxL; |
| uint32 ayyL = ( myyL >= 0 ) ? myyL : -myyL; |
| |
| uint32 a1L = ( axxL > ayxL ) ? axxL : ayxL; |
| uint32 a2L = ( axyL > ayyL ) ? axyL : ayyL; |
| |
| uint32 invScaleL = ( a1L < a2L ) ? a1L : a2L; |
| uint32 scaleExpL = 0; |
| while( ( invScaleL >> scaleExpL ) > scaleThrL ) scaleExpL++; |
| while( ( scaleExpL > 0 ) && ( w0L >> scaleExpL ) < 2 ) scaleExpL--; |
| while( ( scaleExpL > 0 ) && ( h0L >> scaleExpL ) < 2 ) scaleExpL--; |
| |
| /* downscale image */ |
| if( scaleExpL > 0 ) |
| { |
| /* down sampling is limited to the effective area of the original image */ |
| |
| /* compute effective area by mapping all corners of the dst rectangle */ |
| int32 xMinL = 0x7FFFFFFF; |
| int32 yMinL = 0x7FFFFFFF; |
| int32 xMaxL = 0x80000000; |
| int32 yMaxL = 0x80000000; |
| uint32 wEffL, hEffL; |
| |
| { |
| int32 xL, yL; |
| xL = txL; |
| yL = tyL; |
| xMinL = xL < xMinL ? xL : xMinL; |
| yMinL = yL < yMinL ? yL : yMinL; |
| xMaxL = xL > xMaxL ? xL : xMaxL; |
| yMaxL = yL > yMaxL ? yL : yMaxL; |
| xL = txL + mxxL * ( int32 )dstWidthA + mxyL * ( int32 )dstHeightA; |
| yL = tyL + myxL * ( int32 )dstWidthA + myyL * ( int32 )dstHeightA; |
| xMinL = xL < xMinL ? xL : xMinL; |
| yMinL = yL < yMinL ? yL : yMinL; |
| xMaxL = xL > xMaxL ? xL : xMaxL; |
| yMaxL = yL > yMaxL ? yL : yMaxL; |
| xL = txL + mxyL * ( int32 )dstHeightA; |
| yL = tyL + myyL * ( int32 )dstHeightA; |
| xMinL = xL < xMinL ? xL : xMinL; |
| yMinL = yL < yMinL ? yL : yMinL; |
| xMaxL = xL > xMaxL ? xL : xMaxL; |
| yMaxL = yL > yMaxL ? yL : yMaxL; |
| xL = txL + mxxL * ( int32 )dstWidthA; |
| yL = tyL + myxL * ( int32 )dstWidthA; |
| xMinL = xL < xMinL ? xL : xMinL; |
| yMinL = yL < yMinL ? yL : yMinL; |
| xMaxL = xL > xMaxL ? xL : xMaxL; |
| yMaxL = yL > yMaxL ? yL : yMaxL; |
| } |
| |
| xMaxL = ( xMaxL >> 16 ) + 2; |
| yMaxL = ( yMaxL >> 16 ) + 2; |
| xMinL >>= 16; |
| yMinL >>= 16; |
| |
| /* ensre effective area stays within original frame */ |
| xMinL = 0 > xMinL ? 0 : xMinL; |
| yMinL = 0 > yMinL ? 0 : yMinL; |
| xMinL = ( int32 )w0L < xMinL ? w0L : xMinL; |
| yMinL = ( int32 )h0L < yMinL ? h0L : yMinL; |
| xMaxL = 0 > xMaxL ? 0 : xMaxL; |
| yMaxL = 0 > yMaxL ? 0 : yMaxL; |
| xMaxL = ( int32 )w0L < xMaxL ? w0L : xMaxL; |
| yMaxL = ( int32 )h0L < yMaxL ? h0L : yMaxL; |
| |
| wEffL = xMaxL - xMinL; |
| hEffL = yMaxL - yMinL; |
| |
| /* ensure downscaling does not reduce image to 0 */ |
| while( ( scaleExpL > 0 ) && ( wEffL >> scaleExpL ) < 2 ) scaleExpL--; |
| while( ( scaleExpL > 0 ) && ( hEffL >> scaleExpL ) < 2 ) scaleExpL--; |
| |
| /* downscale */ |
| if( scaleExpL > 0 ) |
| { |
| uint32 iL; |
| w1L = wEffL >> 1; |
| h1L = hEffL >> 1; |
| if( bufPtrA == NULL ) bbs_ERROR1( "%s:\nPreallocated buffer is needed", fNameL ); |
| bbs_UInt8Arr_size( cpA, bufPtrA, w1L * h1L ); |
| bim_downscaleBy2( bufPtrA->arrPtrE, srcL + yMinL * w0L + xMinL, w0L, wEffL, hEffL ); |
| for( iL = 1; iL < scaleExpL; iL++ ) |
| { |
| bim_downscaleBy2( bufPtrA->arrPtrE, bufPtrA->arrPtrE, w1L, w1L, h1L ); |
| w1L >>= 1; |
| h1L >>= 1; |
| } |
| |
| /* adjust inverted cordinates */ |
| txL -= ( xMinL << 16 ); |
| tyL -= ( yMinL << 16 ); |
| mxxL >>= scaleExpL; |
| mxyL >>= scaleExpL; |
| myxL >>= scaleExpL; |
| myyL >>= scaleExpL; |
| txL >>= scaleExpL; |
| tyL >>= scaleExpL; |
| srcL = bufPtrA->arrPtrE; |
| } |
| |
| downScaledL = TRUE; |
| } |
| } |
| |
| /* if not downscaled and src and dst images are identcal then copy srcImage into buffer */ |
| if( !downScaledL && dstImagePtrA == srcImagePtrA ) |
| { |
| uint32 iL; |
| uint32 srcSizeL = srcImageWidthA * srcImageHeightA; |
| if( bufPtrA == NULL ) bbs_ERROR1( "%s:\nPreallocated buffer is needed", fNameL ); |
| bbs_UInt8Arr_size( cpA, bufPtrA, srcSizeL ); |
| for( iL = 0; iL < srcSizeL; iL++ ) bufPtrA->arrPtrE[ iL ] = srcImagePtrA[ iL ]; |
| srcL = bufPtrA->arrPtrE; |
| } |
| |
| /* compute destination image */ |
| |
| /* bounds check (dst image fully inside src image? -> fast algorithm) */ |
| { |
| int32 xL, yL; |
| int32 wbL = w1L - 1; |
| int32 hbL = h1L - 1; |
| |
| xL = txL >> 16; |
| yL = tyL >> 16; |
| boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); |
| |
| xL = ( txL + mxxL * ( int32 )( dstWidthA - 1 ) ) >> 16; |
| yL = ( tyL + myxL * ( int32 )( dstWidthA - 1 ) ) >> 16; |
| boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); |
| |
| xL = ( txL + mxyL * ( int32 )( dstHeightA - 1 ) ) >> 16; |
| yL = ( tyL + myyL * ( int32 )( dstHeightA - 1 ) ) >> 16; |
| boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); |
| |
| xL = ( txL + mxyL * ( int32 )( dstHeightA - 1 ) + mxxL * ( int32 )( dstWidthA - 1 ) ) >> 16; |
| yL = ( tyL + myyL * ( int32 )( dstHeightA - 1 ) + myxL * ( int32 )( dstWidthA - 1 ) ) >> 16; |
| boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); |
| } |
| |
| if( boundsOkL ) |
| { |
| int32 iL, jL; |
| for( jL = 0; jL < ( int32 )dstHeightA; jL++ ) |
| { |
| /* 16.16 */ |
| int32 xL = txL + mxyL * jL; |
| int32 yL = tyL + myyL * jL; |
| for( iL = 0; iL < ( int32 )dstWidthA; iL++ ) |
| { |
| int32 x0L = xL >> 16; |
| int32 y0L = yL >> 16; |
| uint32 xf2L = xL & 0x0FFFF; |
| uint32 yf2L = yL & 0x0FFFF; |
| uint32 xf1L = 0x10000 - xf2L; |
| uint32 yf1L = 0x10000 - yf2L; |
| |
| xL += mxxL; |
| yL += myxL; |
| |
| { |
| uint32 idxL = y0L * w1L + x0L; |
| uint32 v1L = ( ( uint32 )srcL[ idxL ] * xf1L + ( uint32 )srcL[ idxL + 1 ] * xf2L + 0x0800 ) >> 12; |
| uint32 v2L = ( ( uint32 )srcL[ idxL + w1L ] * xf1L + ( uint32 )srcL[ idxL + w1L + 1 ] * xf2L + 0x0800 ) >> 12; |
| *dstL++ = ( v1L * yf1L + v2L * yf2L + 0x080000 ) >> 20; |
| } |
| } |
| } |
| } |
| else |
| { |
| int32 iL, jL; |
| for( jL = 0; jL < ( int32 )dstHeightA; jL++ ) |
| { |
| /* 16.16 */ |
| int32 xL = txL + mxyL * jL; |
| int32 yL = tyL + myyL * jL; |
| for( iL = 0; iL < ( int32 )dstWidthA; iL++ ) |
| { |
| int32 x0L = xL >> 16; |
| int32 y0L = yL >> 16; |
| uint32 xf2L = xL & 0x0FFFF; |
| uint32 yf2L = yL & 0x0FFFF; |
| uint32 xf1L = 0x10000 - xf2L; |
| uint32 yf1L = 0x10000 - yf2L; |
| |
| xL += mxxL; |
| yL += myxL; |
| |
| if( y0L < 0 ) |
| { |
| if( x0L < 0 ) |
| { |
| *dstL++ = srcL[ 0 ]; |
| } |
| else if( x0L >= ( int32 )w1L - 1 ) |
| { |
| *dstL++ = srcL[ w1L - 1 ]; |
| } |
| else |
| { |
| *dstL++ = ( ( uint32 )srcL[ x0L ] * xf1L + ( uint32 )srcL[ x0L + 1 ] * xf2L + 0x08000 ) >> 16; |
| } |
| } |
| else if( y0L >= ( int32 )h1L - 1 ) |
| { |
| if( x0L < 0 ) |
| { |
| *dstL++ = srcL[ ( h1L - 1 ) * w1L ]; |
| } |
| else if( x0L >= ( int32 )w1L - 1 ) |
| { |
| *dstL++ = srcL[ ( h1L * w1L ) - 1 ]; |
| } |
| else |
| { |
| uint32 idxL = ( h1L - 1 ) * w1L + x0L; |
| *dstL++ = ( ( uint32 )srcL[ idxL ] * xf1L + ( uint32 )srcL[ idxL + 1 ] * xf2L + 0x08000 ) >> 16; |
| } |
| } |
| else |
| { |
| if( x0L < 0 ) |
| { |
| uint32 idxL = y0L * w1L; |
| *dstL++ = ( ( uint32 )srcL[ idxL ] * yf1L + ( uint32 )srcL[ idxL + w1L ] * yf2L + 0x08000 ) >> 16; |
| } |
| else if( x0L >= ( int32 )w1L - 1 ) |
| { |
| uint32 idxL = ( y0L + 1 ) * w1L - 1; |
| *dstL++ = ( ( uint32 )srcL[ idxL ] * yf1L + ( uint32 )srcL[ idxL + w1L ] * yf2L + 0x08000 ) >> 16; |
| } |
| else |
| { |
| uint32 idxL = y0L * w1L + x0L; |
| uint32 v1L = ( ( uint32 )srcL[ idxL ] * xf1L + ( uint32 )srcL[ idxL + 1 ] * xf2L + 0x0800 ) >> 12; |
| uint32 v2L = ( ( uint32 )srcL[ idxL + w1L ] * xf1L + ( uint32 )srcL[ idxL + w1L + 1 ] * xf2L + 0x0800 ) >> 12; |
| *dstL++ = ( v1L * yf1L + v2L * yf2L + 0x080000 ) >> 20; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bim_filterWarpPixelReplication( struct bbs_Context* cpA, |
| uint8* dstImagePtrA, |
| const uint8* srcImagePtrA, |
| uint32 srcImageWidthA, |
| uint32 srcImageHeightA, |
| const struct bts_Int16Vec2D* offsPtrA, |
| const struct bts_Flt16Alt2D* altPtrA, |
| uint32 dstWidthA, |
| uint32 dstHeightA, |
| struct bbs_UInt8Arr* bufPtrA, |
| uint32 scaleThresholdA ) |
| { |
| bbs_DEF_fNameL( "bim_filterWarpPixelReplication" ) |
| |
| uint32 w0L = srcImageWidthA; |
| uint32 h0L = srcImageHeightA; |
| |
| const uint8* srcL = srcImagePtrA; |
| uint8* dstL = dstImagePtrA; |
| |
| uint32 w1L = w0L; |
| uint32 h1L = h0L; |
| |
| /* 16.16 */ |
| uint32 scaleThrL = scaleThresholdA; |
| struct bts_Flt16Alt2D invAltL; |
| |
| /* matrix variables */ |
| int32 mxxL, mxyL, myxL, myyL, txL, tyL; |
| |
| flag downScaledL = FALSE; |
| flag boundsOkL = TRUE; |
| |
| if( w0L == 0 || h0L == 0 || bts_Flt16Mat2D_det( &altPtrA->matE ) == 0 ) |
| { |
| uint32 iL; |
| for( iL = 0; iL < dstWidthA * dstHeightA; iL++ ) dstImagePtrA[ iL ] = 0; |
| return; |
| } |
| |
| /* compute inverse ALT */ |
| invAltL = bts_Flt16Alt2D_inverted( altPtrA ); |
| |
| /* fixed point ALT 16.16 */ |
| if( invAltL.matE.bbpE <= 16 ) |
| { |
| uint32 shlL = 16 - invAltL.matE.bbpE; |
| mxxL = invAltL.matE.xxE << shlL; |
| mxyL = invAltL.matE.xyE << shlL; |
| myxL = invAltL.matE.yxE << shlL; |
| myyL = invAltL.matE.yyE << shlL; |
| } |
| else |
| { |
| uint32 shrL = invAltL.matE.bbpE - 16; |
| mxxL = ( ( invAltL.matE.xxE >> ( shrL - 1 ) ) + 1 ) >> 1; |
| mxyL = ( ( invAltL.matE.xyE >> ( shrL - 1 ) ) + 1 ) >> 1; |
| myxL = ( ( invAltL.matE.yxE >> ( shrL - 1 ) ) + 1 ) >> 1; |
| myyL = ( ( invAltL.matE.yyE >> ( shrL - 1 ) ) + 1 ) >> 1; |
| } |
| |
| if( invAltL.vecE.bbpE <= 16 ) |
| { |
| uint32 shlL = 16 - invAltL.vecE.bbpE; |
| txL = invAltL.vecE.xE << shlL; |
| tyL = invAltL.vecE.yE << shlL; |
| } |
| else |
| { |
| uint32 shrL = invAltL.vecE.bbpE - 16; |
| txL = ( ( invAltL.vecE.xE >> ( shrL - 1 ) ) + 1 ) >> 1; |
| tyL = ( ( invAltL.vecE.yE >> ( shrL - 1 ) ) + 1 ) >> 1; |
| } |
| |
| /* add offset */ |
| txL += ( int32 )offsPtrA->xE << 16; |
| tyL += ( int32 )offsPtrA->yE << 16; |
| |
| if( scaleThresholdA > 0 ) |
| { |
| /* compute downscale exponent */ |
| uint32 axxL = ( mxxL >= 0 ) ? mxxL : -mxxL; |
| uint32 axyL = ( mxyL >= 0 ) ? mxyL : -mxyL; |
| uint32 ayxL = ( myxL >= 0 ) ? myxL : -myxL; |
| uint32 ayyL = ( myyL >= 0 ) ? myyL : -myyL; |
| |
| uint32 a1L = ( axxL > ayxL ) ? axxL : ayxL; |
| uint32 a2L = ( axyL > ayyL ) ? axyL : ayyL; |
| |
| uint32 invScaleL = ( a1L < a2L ) ? a1L : a2L; |
| uint32 scaleExpL = 0; |
| while( ( invScaleL >> scaleExpL ) > scaleThrL ) scaleExpL++; |
| while( ( scaleExpL > 0 ) && ( w0L >> scaleExpL ) < 2 ) scaleExpL--; |
| while( ( scaleExpL > 0 ) && ( h0L >> scaleExpL ) < 2 ) scaleExpL--; |
| |
| /* downscale image */ |
| if( scaleExpL > 0 ) |
| { |
| /* down sampling is limited to the effective area of the original image */ |
| |
| /* compute effective area by mapping all corners of the dst rectangle */ |
| int32 xMinL = 0x7FFFFFFF; |
| int32 yMinL = 0x7FFFFFFF; |
| int32 xMaxL = 0x80000000; |
| int32 yMaxL = 0x80000000; |
| uint32 wEffL, hEffL; |
| |
| { |
| int32 xL, yL; |
| xL = txL; |
| yL = tyL; |
| xMinL = xL < xMinL ? xL : xMinL; |
| yMinL = yL < yMinL ? yL : yMinL; |
| xMaxL = xL > xMaxL ? xL : xMaxL; |
| yMaxL = yL > yMaxL ? yL : yMaxL; |
| xL = txL + mxxL * ( int32 )dstWidthA + mxyL * ( int32 )dstHeightA; |
| yL = tyL + myxL * ( int32 )dstWidthA + myyL * ( int32 )dstHeightA; |
| xMinL = xL < xMinL ? xL : xMinL; |
| yMinL = yL < yMinL ? yL : yMinL; |
| xMaxL = xL > xMaxL ? xL : xMaxL; |
| yMaxL = yL > yMaxL ? yL : yMaxL; |
| xL = txL + mxyL * ( int32 )dstHeightA; |
| yL = tyL + myyL * ( int32 )dstHeightA; |
| xMinL = xL < xMinL ? xL : xMinL; |
| yMinL = yL < yMinL ? yL : yMinL; |
| xMaxL = xL > xMaxL ? xL : xMaxL; |
| yMaxL = yL > yMaxL ? yL : yMaxL; |
| xL = txL + mxxL * ( int32 )dstWidthA; |
| yL = tyL + myxL * ( int32 )dstWidthA; |
| xMinL = xL < xMinL ? xL : xMinL; |
| yMinL = yL < yMinL ? yL : yMinL; |
| xMaxL = xL > xMaxL ? xL : xMaxL; |
| yMaxL = yL > yMaxL ? yL : yMaxL; |
| } |
| |
| xMaxL = ( xMaxL >> 16 ) + 2; |
| yMaxL = ( yMaxL >> 16 ) + 2; |
| xMinL >>= 16; |
| yMinL >>= 16; |
| |
| /* ensre effective area stays within original frame */ |
| xMinL = 0 > xMinL ? 0 : xMinL; |
| yMinL = 0 > yMinL ? 0 : yMinL; |
| xMinL = ( int32 )w0L < xMinL ? w0L : xMinL; |
| yMinL = ( int32 )h0L < yMinL ? h0L : yMinL; |
| xMaxL = 0 > xMaxL ? 0 : xMaxL; |
| yMaxL = 0 > yMaxL ? 0 : yMaxL; |
| xMaxL = ( int32 )w0L < xMaxL ? w0L : xMaxL; |
| yMaxL = ( int32 )h0L < yMaxL ? h0L : yMaxL; |
| |
| wEffL = xMaxL - xMinL; |
| hEffL = yMaxL - yMinL; |
| |
| /* ensure downscaling does not reduce image to 0 */ |
| while( ( scaleExpL > 0 ) && ( wEffL >> scaleExpL ) < 2 ) scaleExpL--; |
| while( ( scaleExpL > 0 ) && ( hEffL >> scaleExpL ) < 2 ) scaleExpL--; |
| |
| /* downscale */ |
| if( scaleExpL > 0 ) |
| { |
| uint32 iL; |
| w1L = wEffL >> 1; |
| h1L = hEffL >> 1; |
| if( bufPtrA == NULL ) bbs_ERROR1( "%s:\nPreallocated buffer is needed", fNameL ); |
| bbs_UInt8Arr_size( cpA, bufPtrA, w1L * h1L ); |
| bim_downscaleBy2( bufPtrA->arrPtrE, srcL + yMinL * w0L + xMinL, w0L, wEffL, hEffL ); |
| for( iL = 1; iL < scaleExpL; iL++ ) |
| { |
| bim_downscaleBy2( bufPtrA->arrPtrE, bufPtrA->arrPtrE, w1L, w1L, h1L ); |
| w1L >>= 1; |
| h1L >>= 1; |
| } |
| |
| /* adjust inverted cordinates */ |
| txL -= ( xMinL << 16 ); |
| tyL -= ( yMinL << 16 ); |
| mxxL >>= scaleExpL; |
| mxyL >>= scaleExpL; |
| myxL >>= scaleExpL; |
| myyL >>= scaleExpL; |
| txL >>= scaleExpL; |
| tyL >>= scaleExpL; |
| srcL = bufPtrA->arrPtrE; |
| } |
| |
| downScaledL = TRUE; |
| } |
| } |
| |
| /* if not downscaled and src and dst images are identcal then copy srcImage into buffer */ |
| if( !downScaledL && dstImagePtrA == srcImagePtrA ) |
| { |
| uint32 iL; |
| uint32 srcSizeL = srcImageWidthA * srcImageHeightA; |
| if( bufPtrA == NULL ) bbs_ERROR1( "%s:\nPreallocated buffer is needed", fNameL ); |
| bbs_UInt8Arr_size( cpA, bufPtrA, srcSizeL ); |
| for( iL = 0; iL < srcSizeL; iL++ ) bufPtrA->arrPtrE[ iL ] = srcImagePtrA[ iL ]; |
| srcL = bufPtrA->arrPtrE; |
| } |
| |
| /* compute destination image */ |
| |
| /* bounds check (dst image fully inside src image? -> fast algorithm) */ |
| { |
| int32 xL, yL; |
| int32 wbL = w1L - 1; |
| int32 hbL = h1L - 1; |
| |
| xL = txL >> 16; |
| yL = tyL >> 16; |
| boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); |
| |
| xL = ( txL + mxxL * ( int32 )( dstWidthA - 1 ) ) >> 16; |
| yL = ( tyL + myxL * ( int32 )( dstWidthA - 1 ) ) >> 16; |
| boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); |
| |
| xL = ( txL + mxyL * ( int32 )( dstHeightA - 1 ) ) >> 16; |
| yL = ( tyL + myyL * ( int32 )( dstHeightA - 1 ) ) >> 16; |
| boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); |
| |
| xL = ( txL + mxyL * ( int32 )( dstHeightA - 1 ) + mxxL * ( int32 )( dstWidthA - 1 ) ) >> 16; |
| yL = ( tyL + myyL * ( int32 )( dstHeightA - 1 ) + myxL * ( int32 )( dstWidthA - 1 ) ) >> 16; |
| boundsOkL = boundsOkL && ( xL >= 0 && xL < wbL && yL >= 0 && yL < hbL ); |
| } |
| |
| if( boundsOkL ) |
| { |
| int32 iL, jL; |
| for( jL = 0; jL < ( int32 )dstHeightA; jL++ ) |
| { |
| /* 16.16 */ |
| int32 xL = txL + mxyL * jL; |
| int32 yL = tyL + myyL * jL; |
| for( iL = 0; iL < ( int32 )dstWidthA; iL++ ) |
| { |
| /* nearest whole position */ |
| *dstL++ = srcL[ ( ( ( yL >> 15 ) + 1 ) >> 1 ) * w1L + ( ( ( xL >> 15 ) + 1 ) >> 1 ) ]; |
| xL += mxxL; |
| yL += myxL; |
| } |
| } |
| } |
| else |
| { |
| int32 iL, jL; |
| for( jL = 0; jL < ( int32 )dstHeightA; jL++ ) |
| { |
| /* 16.16 */ |
| int32 xL = txL + mxyL * jL; |
| int32 yL = tyL + myyL * jL; |
| for( iL = 0; iL < ( int32 )dstWidthA; iL++ ) |
| { |
| /* nearest whole position */ |
| int32 x0L = ( ( xL >> 15 ) + 1 ) >> 1; |
| int32 y0L = ( ( yL >> 15 ) + 1 ) >> 1; |
| xL += mxxL; |
| yL += myxL; |
| |
| if( y0L < 0 ) |
| { |
| if( x0L < 0 ) |
| { |
| *dstL++ = srcL[ 0 ]; |
| } |
| else if( x0L >= ( int32 )w1L - 1 ) |
| { |
| *dstL++ = srcL[ w1L - 1 ]; |
| } |
| else |
| { |
| *dstL++ = srcL[ x0L ]; |
| } |
| } |
| else if( y0L >= ( int32 )h1L - 1 ) |
| { |
| if( x0L < 0 ) |
| { |
| *dstL++ = srcL[ ( h1L - 1 ) * w1L ]; |
| } |
| else if( x0L >= ( int32 )w1L - 1 ) |
| { |
| *dstL++ = srcL[ ( h1L * w1L ) - 1 ]; |
| } |
| else |
| { |
| *dstL++ = srcL[ ( h1L - 1 ) * w1L + x0L ]; |
| } |
| } |
| else |
| { |
| if( x0L < 0 ) |
| { |
| *dstL++ = srcL[ y0L * w1L ]; |
| } |
| else if( x0L >= ( int32 )w1L - 1 ) |
| { |
| *dstL++ = srcL[ ( y0L + 1 ) * w1L - 1 ]; |
| } |
| else |
| { |
| *dstL++ = srcL[ y0L * w1L + x0L ]; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bim_filterWarp( struct bbs_Context* cpA, |
| uint8* dstImagePtrA, |
| const uint8* srcImagePtrA, |
| uint32 srcImageWidthA, |
| uint32 srcImageHeightA, |
| const struct bts_Int16Vec2D* offsPtrA, |
| const struct bts_Flt16Alt2D* altPtrA, |
| uint32 dstWidthA, |
| uint32 dstHeightA, |
| struct bbs_UInt8Arr* bufPtrA, |
| uint32 scaleThresholdA, |
| flag interpolateA ) |
| { |
| if( interpolateA ) |
| { |
| bim_filterWarpInterpolation( cpA, dstImagePtrA, srcImagePtrA, srcImageWidthA, srcImageHeightA, offsPtrA, altPtrA, dstWidthA, dstHeightA, bufPtrA, scaleThresholdA ); |
| } |
| else |
| { |
| bim_filterWarpPixelReplication( cpA, dstImagePtrA, srcImagePtrA, srcImageWidthA, srcImageHeightA, offsPtrA, altPtrA, dstWidthA, dstHeightA, bufPtrA, scaleThresholdA ); |
| } |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |