--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/htiui/HtiServicePlugins/HtiScreenshotServicePlugin/src/HtiTextRcg.cpp Tue Feb 02 00:17:27 2010 +0200
@@ -0,0 +1,956 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Text recognition algorithm implementation.
+*
+*/
+
+
+#include "HtiTextRcg.h"
+#include <AknUtils.h>
+#include <HTILogging.h>
+
+const static TInt KDefaultStrategy = EHintEdge;
+
+TInt CompareTPoint(const TPoint& aP1,const TPoint& aP2)
+ {
+ //this functions is used only to avoid equal points when creating FGA or BGA
+ //so only equality of points is important, order doesnt matter
+ if ( aP1.iY == aP2.iY )
+ return aP1.iX - aP2.iX;
+ return aP1.iY - aP2.iY;
+ }
+
+CHtiTextRcg::CHtiTextRcg()
+ {
+ iAvgDiffMin = KDefaultAvgDiffMin;
+ //minimal SS for foreground, with plain color should be 0
+ iFgSSMin = KDefaultFgSSMin;
+ iFgAvgDiffMin = KDefaultFgAvgDiffMin;
+
+ iFGAAmount = KDefaultFGAAmount;
+ iBGAAmount = KDefaultBGAAmount;
+
+ SetHint(KDefaultStrategy);
+ }
+
+CHtiTextRcg::~CHtiTextRcg()
+ {
+ iFGASet.Close();
+ iBGASet.Close();
+ }
+
+void CHtiTextRcg::SetHint(TInt aHint)
+ {
+ //selects strategy and algorithm parameters
+ switch ( aHint )
+ {
+ case EHintEdge:
+ {
+ //AA strategy
+ iCurrentStrategy = EHintEdge;
+ }
+ break;
+ case EHintNone:
+ default:
+ {
+ //default strategy
+ iCurrentStrategy = EHintNone;
+ }
+ }
+ }
+
+
+TBool CHtiTextRcg::RecognizeTextL(CFbsBitmap* aScreenshot,
+ const TDesC& aText,
+ const CFont* aFont,
+ TRect& aResult)
+ {
+HTI_LOG_FUNC_IN("RecognizeTextL");
+ TInt returnValue = KWorstCase;
+
+ CFbsBitmap* gray = ColorDownL(aScreenshot);
+ CleanupStack::PushL(gray);
+
+ switch ( iCurrentStrategy )
+ {
+ case EHintEdge:
+ {
+ returnValue = RecognizeAAL(gray,aText, aFont, aResult);
+ }
+ break;
+ case EHintNone:
+ default:
+ {
+ returnValue = RecognizeBinL(gray,aText, aFont, aResult);
+ }
+ }
+
+ CleanupStack::PopAndDestroy(gray);
+HTI_LOG_FUNC_OUT("RecognizeTextL");
+ return returnValue < KSuccessThresold;
+ }
+
+TInt CHtiTextRcg::RecognizeBinL(CFbsBitmap* aScreenshot,
+ const TDesC& aText,
+ const CFont* aFont,
+ TRect& aResult)
+{
+ HTI_LOG_FUNC_IN("RecognizeBinL");
+ CFbsBitmap* searchFirstLetter = GetTextBitmapL(aText, aFont, 1);
+ CleanupStack::PushL(searchFirstLetter);
+ HTI_LOG_FORMAT("pattern size w %d", searchFirstLetter->SizeInPixels().iWidth);
+ HTI_LOG_FORMAT("pattern size h %d", searchFirstLetter->SizeInPixels().iHeight);
+
+ if ( !AnalyzePatternL(searchFirstLetter) )
+ {
+ CleanupStack::PopAndDestroy(searchFirstLetter);
+ return KWorstCase;
+ }
+ CFbsBitmap* searchText = GetTextBitmapL(aText, aFont);
+ CleanupStack::PushL(searchText);
+
+ //search range (0,0) - (reg.Size() - searchText.SizeInPixels)
+ TPoint end(aScreenshot->SizeInPixels().iWidth, aScreenshot->SizeInPixels().iHeight);
+ end -= searchText->SizeInPixels();
+ end += TPoint(1,1);
+
+ //search itself
+ for ( TPoint p( 0, 0 ); p.iY < end.iY; p.iY++ )
+ {
+ for ( p.iX = 0; p.iX < end.iX; p.iX++ )
+ {
+ TInt t = ImageDiffBinSampleL(aScreenshot, p, searchFirstLetter);
+ if ( t == 0 )
+ {
+ //check full word
+ TInt wordD = ImageDiffBinFullL(aScreenshot, p, searchText);
+ if ( wordD == 0 )
+ {
+ aResult.iTl.iX = p.iX;
+ aResult.iTl.iY = p.iY;
+ aResult.SetSize(searchText->SizeInPixels());
+ CleanupStack::PopAndDestroy(searchText);
+ CleanupStack::PopAndDestroy(searchFirstLetter);
+ HTI_LOG_FUNC_OUT("RecognizeBinL");
+ return 0;
+ }
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(searchText);
+ CleanupStack::PopAndDestroy(searchFirstLetter);
+
+ HTI_LOG_FUNC_OUT("RecognizeBinL");
+ return KWorstCase;
+}
+
+
+TInt CHtiTextRcg::RecognizeAAL(CFbsBitmap* aScreenshot,
+ const TDesC& aText,
+ const CFont* aFont,
+ TRect& aResult)
+{
+ HTI_LOG_FUNC_IN("RecognizeAAL");
+ CFbsBitmap* searchFirstLetter = GetTextBitmapL(aText, aFont, 1);
+ CleanupStack::PushL(searchFirstLetter);
+ if ( !AnalyzePatternL(searchFirstLetter) )
+ {
+ CleanupStack::PopAndDestroy(searchFirstLetter);
+ return KWorstCase;
+ }
+
+ CFbsBitmap* searchText = GetTextBitmapL(aText, aFont);
+ CleanupStack::PushL(searchText);
+
+
+ //search range (0,0) - (reg.Size() - searchText.SizeInPixels)
+ TPoint end(aScreenshot->SizeInPixels().iWidth, aScreenshot->SizeInPixels().iHeight);
+ end -= searchText->SizeInPixels();
+ end += TPoint(1,1);
+
+ //search itself
+ TInt min = KSuccessThresold;
+ TInt wordMin = KSuccessThresold;
+
+ for ( TPoint p( 0, 0 ); p.iY < end.iY; p.iY++ )
+ {
+ for ( p.iX = 0; p.iX < end.iX; p.iX++ )
+ {
+ TInt t = ImageDiffAASampleL(aScreenshot, p, searchFirstLetter);
+ if ( t < min )
+ {
+ //check full word
+ TInt wordD = ImageDiffAAFullL(aScreenshot, p, searchText);
+ if ( wordD < wordMin )
+ {
+ wordMin = wordD;
+ min = t;
+ aResult.iTl.iX = p.iX;
+ aResult.iTl.iY = p.iY;
+ aResult.SetSize(searchText->SizeInPixels());
+ if ( wordMin == 0 )
+ {
+ CleanupStack::PopAndDestroy(searchText);
+ CleanupStack::PopAndDestroy(searchFirstLetter);
+ HTI_LOG_FUNC_OUT("RecognizeAAL");
+ return 0;
+ }
+ }
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy(searchText);
+ CleanupStack::PopAndDestroy(searchFirstLetter);
+
+ HTI_LOG_FUNC_OUT("RecognizeAAL");
+
+ return wordMin;
+}
+
+TBool CHtiTextRcg::AnalyzePatternL(CFbsBitmap * aPattern)
+{
+ HTI_LOG_FUNC_IN("AnalyzePatternL");
+ if ( aPattern->SizeInPixels().iWidth == 0 ||
+ aPattern->SizeInPixels().iHeight == 0 )
+ {
+ return EFalse;
+ }
+ //points are selected as follow
+ //take pair of FG-BG points which located next to each other
+ MinMax(aPattern,
+ iMaskFgColor, //min, black font
+ iMaskBgColor);//max, white bg
+
+ if ( iMaskFgColor == iMaskBgColor ) //pattern is empty
+ {
+ return EFalse;
+ }
+
+ TLinearOrder<TPoint> pointOrder(CompareTPoint);
+ TSize borders = aPattern->SizeInPixels();
+ iFGASet.Reset();
+ iBGASet.Reset();
+
+ TBitmapUtil bmpIterator(aPattern);
+ //lock bitmap
+ bmpIterator.Begin( TPoint(0,0));
+
+ //first take center lines and find take at least two pairs
+ //vertical1
+ TPoint startPoint(borders.iWidth/2, 0);
+ bmpIterator.SetPos(startPoint);
+
+ TInt lastColor = bmpIterator.GetPixel()&0xff;
+ TInt lastColorPos = 0;
+ bmpIterator.IncYPos();
+ TInt i=1;
+ TInt found = 0;
+
+ while ( found < 2 && i < borders.iHeight )
+ {
+ TInt c = bmpIterator.GetPixel()&0xff;
+
+ if ( lastColor != c )
+ {
+ if ( c == iMaskFgColor )
+ {
+ iFGASet.InsertInOrder(TPoint(startPoint.iX, i), pointOrder);
+ iBGASet.InsertInOrder(TPoint(startPoint.iX, lastColorPos), pointOrder);
+ lastColor = c;
+ lastColorPos = i;
+ ++found;
+ }
+ else if ( c == iMaskBgColor )
+ {
+ iBGASet.InsertInOrder(TPoint(startPoint.iX, i), pointOrder);
+ iFGASet.InsertInOrder(TPoint(startPoint.iX, lastColorPos), pointOrder);
+ lastColor = c;
+ lastColorPos = i;
+ ++found;
+ }
+ }
+ else
+ {
+ lastColorPos = i;
+ }
+
+ ++i;
+ bmpIterator.IncYPos();
+ }
+
+ //horizontal1
+ startPoint.SetXY(0,borders.iHeight/2);
+ bmpIterator.SetPos(startPoint);
+ lastColor = bmpIterator.GetPixel()&0xff;
+ bmpIterator.IncXPos();
+ i=1;
+ found = 0;
+ lastColorPos = 0;
+
+ while ( found < 2 && i < borders.iWidth )
+ {
+ TInt c = bmpIterator.GetPixel()&0xff;
+
+ if ( lastColor != c )
+ {
+ if ( c == iMaskFgColor )
+ {
+ iFGASet.InsertInOrder(TPoint(i, startPoint.iY), pointOrder);
+ iBGASet.InsertInOrder(TPoint(lastColorPos, startPoint.iY), pointOrder);
+ lastColor = c;
+ lastColorPos = i;
+ ++found;
+ }
+ else if ( c == iMaskBgColor )
+ {
+ iBGASet.InsertInOrder(TPoint(i, startPoint.iY), pointOrder);
+ iFGASet.InsertInOrder(TPoint(lastColorPos, startPoint.iY), pointOrder);
+ lastColor = c;
+ lastColorPos = i;
+ ++found;
+ }
+ }
+ else
+ {
+ lastColorPos = i;
+ }
+ ++i;
+ bmpIterator.IncXPos();
+ }
+
+ //unlock bitmap
+ bmpIterator.End();
+
+ iFGAAmount = iFGASet.Count();
+ iBGAAmount = iBGASet.Count();
+
+ HTI_LOG_FUNC_OUT("AnalyzePatternL");
+ return ETrue;
+
+}
+
+TInt CHtiTextRcg::ImageDiffAASampleL(CFbsBitmap * aBitmap1, TPoint aOrigin1,
+ CFbsBitmap * aBitmap2)
+ {
+
+ if (iFGASet.Count()==0 || iBGASet.Count()==0)
+ return KWorstCase;
+
+ TSize aSize = aBitmap2->SizeInPixels();
+
+ //straight average difference
+ TBitmapUtil bmpIterator1(aBitmap1);
+ TBitmapUtil bmpIterator2(aBitmap2);
+
+ bmpIterator1.Begin( aOrigin1 );
+
+ //1. check FGA points are equal
+ bmpIterator1.SetPos( aOrigin1 + iFGASet[0]);
+ iTestFgColor = bmpIterator1.GetPixel()&0xff;
+
+ for ( TInt i = 1; i < iFGAAmount;++i )
+ {
+ bmpIterator1.SetPos( aOrigin1 + iFGASet[i]);
+ TInt c = bmpIterator1.GetPixel()&0xff;
+ if ( Abs(c-iTestFgColor) > iFgAvgDiffMin )
+ {
+ bmpIterator2.End();
+ bmpIterator1.End();
+ return KWorstCase;
+ }
+ }
+ // if we are here all FGA points are equal to colorFGA
+ //2. check that avg BGA point value is not equal to colorFGA
+ iTestBgColor = 0;
+ for ( TInt i = 0; i < iBGAAmount; ++i )
+ {
+ bmpIterator1.SetPos( aOrigin1 + iBGASet[i]);
+ iTestBgColor += bmpIterator1.GetPixel()&0xff;
+ }
+ iTestBgColor /= iBGAAmount;
+ //if difference is too small leave with false
+ if ( Abs(iTestBgColor-iTestFgColor) < iAvgDiffMin )
+ {
+ bmpIterator2.End();
+ bmpIterator1.End();
+ return KWorstCase;
+ }
+
+ //all checking based on FGA and BGA are correct, chance to have match
+ //3. calculate sum of diff between colorFGA and ALL FG points
+ bmpIterator1.End();
+ bmpIterator1.Begin( aOrigin1 );
+ bmpIterator2.Begin( TPoint(0,0), bmpIterator1 );
+
+ TInt nofF = 0;
+ TInt sum = 0;
+ TBool iterFlag = EFalse;
+
+ TInt rowDelta = 2;
+ TInt columnDelta = 1;
+
+ TBool intellFlagBG;
+ iTestNormCoef = (Abs(iMaskFgColor-iMaskBgColor)<<KNormCoefAcc)/Abs(iTestFgColor-iTestBgColor);
+
+ for ( TInt i = 0; i < aSize.iHeight; i += rowDelta )
+ {
+ intellFlagBG = EFalse;
+ for ( TInt j = 0; j < aSize.iWidth; j += columnDelta )
+ {
+ TInt c1 = (bmpIterator1.GetPixel())&0xff;
+ TInt c2 = (bmpIterator2.GetPixel())&0xff;
+
+ if ( c2 != iMaskBgColor ) // if foreground
+ {
+ if ( c2 == iMaskFgColor ) //should be "pure" FG
+ {
+ if ( Abs( c1 - iTestFgColor ) > iFgAvgDiffMin )
+ {
+ bmpIterator2.End();
+ bmpIterator1.End();
+ return KWorstCase;
+ }
+ intellFlagBG = ETrue;
+ }
+ else if ( intellFlagBG ) // AA pixels
+ {
+ //calculate diff. in relative diff in aa pixel
+ //in mask and searh image
+ //based on assumtion that aa pixels color
+ // relative to fg color should correlate
+ TInt normD = (Abs(c1-iTestFgColor)*iTestNormCoef)>>KNormCoefAcc;
+ sum += Abs(Abs(iMaskFgColor-c2) - normD );
+
+ ++nofF;
+ intellFlagBG = EFalse;
+
+ }
+ }
+ for ( TInt l = 0; l < columnDelta; l++ )
+ {
+ if ( iterFlag )
+ {
+ bmpIterator1.DecXPos();
+ bmpIterator2.DecXPos();
+ }
+ else
+ {
+ bmpIterator1.IncXPos();
+ bmpIterator2.IncXPos();
+ }
+ }
+ }
+
+ for ( int k = 0; k < rowDelta; k++ )
+ {
+ bmpIterator1.IncYPos();
+ bmpIterator2.IncYPos();
+ }
+ for ( int l = 0; l < columnDelta; l++ )
+ {
+ if ( iterFlag )
+ {
+ bmpIterator1.IncXPos();
+ bmpIterator2.IncXPos();
+ }
+ else
+ {
+ bmpIterator1.DecXPos();
+ bmpIterator2.DecXPos();
+ }
+ }
+ iterFlag = !iterFlag;
+ }
+
+
+ bmpIterator2.End();
+ bmpIterator1.End();
+
+ if ( nofF == 0 )
+ {
+ return 0;
+ }
+ return sum / nofF;
+ }
+
+
+TInt CHtiTextRcg::ImageDiffAAFullL(CFbsBitmap * aBitmap1, TPoint aOrigin1,
+ CFbsBitmap * aBitmap2)
+ {
+ TSize aSize = aBitmap2->SizeInPixels();
+ //straight average difference
+ TBitmapUtil bmpIterator1(aBitmap1);
+ TBitmapUtil bmpIterator2(aBitmap2);
+
+ bmpIterator1.Begin( aOrigin1 );
+ bmpIterator2.Begin( TPoint(0,0), bmpIterator1 );
+
+ TInt nofF = 0;
+ TInt sumF = 0;
+ TBool intellFlagBG;
+ TBool iterFlag = EFalse;
+ TInt rowDelta = 2;
+ TInt columnDelta = 1;
+
+ for ( TInt i = 0; i < aSize.iHeight; i += rowDelta )
+ {
+ intellFlagBG = EFalse;
+ for ( TInt j = 0; j < aSize.iWidth; j += columnDelta )
+ {
+ TInt c1 = ( bmpIterator1.GetPixel() ) & 0xff;
+ TInt c2 = ( bmpIterator2.GetPixel() ) & 0xff;
+
+ if ( c2 != iMaskBgColor ) // if foreground
+ {
+ if ( c2 == iMaskFgColor ) //should be pure FG
+ {
+ if ( Abs(c1 - iTestFgColor) > iFgAvgDiffMin )
+ {
+ bmpIterator2.End();
+ bmpIterator1.End();
+ return KWorstCase;
+ }
+ intellFlagBG = ETrue;
+ }
+ else if ( intellFlagBG ) // AA pixels
+ {
+ //calculate diff. in relative diff in aa pixel
+ //in mask and searh image
+ //based on assumtion that aa pixels color
+ // relative to fg color should correlate
+ TInt normD = (Abs(c1-iTestFgColor)*iTestNormCoef)>>KNormCoefAcc;
+ sumF += Abs(Abs(iMaskFgColor-c2) - normD );
+
+ ++nofF;
+ intellFlagBG = EFalse;
+ }
+ }
+ for ( TInt l = 0; l < columnDelta; l++ )
+ {
+ if ( iterFlag )
+ {
+ bmpIterator1.DecXPos();
+ bmpIterator2.DecXPos();
+ }
+ else
+ {
+ bmpIterator1.IncXPos();
+ bmpIterator2.IncXPos();
+ }
+ }
+ }
+
+ for ( TInt k = 0; k < rowDelta; k++ )
+ {
+ bmpIterator1.IncYPos();
+ bmpIterator2.IncYPos();
+ }
+ for ( TInt l = 0; l < columnDelta; l++ )
+ {
+ if ( iterFlag )
+ {
+ bmpIterator1.IncXPos();
+ bmpIterator2.IncXPos();
+ }
+ else
+ {
+ bmpIterator1.DecXPos();
+ bmpIterator2.DecXPos();
+ }
+ }
+ iterFlag = !iterFlag;
+ }
+ bmpIterator2.End();
+ bmpIterator1.End();
+
+ if ( nofF == 0 )
+ return 0;
+
+ return sumF/nofF;
+ }
+
+TInt CHtiTextRcg::ImageDiffBinSampleL(CFbsBitmap * aBitmap1, TPoint aOrigin1,
+ CFbsBitmap * aBitmap2)
+ {
+ TSize aSize = aBitmap2->SizeInPixels();
+ if ( iFGASet.Count() == 0 || iBGASet.Count() == 0 )
+ return KWorstCase;
+
+ //straight average difference
+ TBitmapUtil bmpIterator1(aBitmap1);
+ TBitmapUtil bmpIterator2(aBitmap2);
+
+ bmpIterator1.Begin( aOrigin1 );
+
+ //1. check FGA points are equal
+ bmpIterator1.SetPos( aOrigin1 + iFGASet[0]);
+ TInt colorFGA = bmpIterator1.GetPixel()&0xff;
+
+ for ( TInt i = 1; i < iFGAAmount; ++i )
+ {
+ bmpIterator1.SetPos( aOrigin1 + iFGASet[i] );
+ TInt c = bmpIterator1.GetPixel()&0xff;
+ if ( c != colorFGA )
+ {
+ bmpIterator2.End();
+ bmpIterator1.End();
+ return KWorstCase;
+ }
+ }
+ // if we are here all FGA points are equal to colorFGA
+ //2. check that avg BGA point value is not equal to colorFGA
+ TInt avgColorBGA = 0;
+ for ( TInt i = 0; i < iBGAAmount; ++i )
+ {
+ bmpIterator1.SetPos( aOrigin1 + iBGASet[i] );
+ avgColorBGA += bmpIterator1.GetPixel() & 0xff;
+ }
+ avgColorBGA /= iBGAAmount;
+ //if difference is too small leave with false
+ if ( Abs(avgColorBGA-colorFGA) < iAvgDiffMin )
+ {
+ bmpIterator2.End();
+ bmpIterator1.End();
+ return KWorstCase;
+ }
+
+ //all checking based on FGA and BGA are correct, chance to have math
+ //3. calculate sum of diff between colorFGA and ALL FG points
+ bmpIterator1.End();
+ bmpIterator1.Begin( aOrigin1 );
+ bmpIterator2.Begin( TPoint(0,0), bmpIterator1 );
+
+ TBool iterFlag = EFalse;
+
+ TInt rowDelta = 1;
+ TInt columnDelta = 1;
+
+ for ( TInt i = 0; i < aSize.iHeight; i += rowDelta )
+ {
+ for ( TInt j = 0; j < aSize.iWidth; j += columnDelta )
+ {
+ TInt c1 = ( bmpIterator1.GetPixel() ) & 0xff;
+ TInt c2 = ( bmpIterator2.GetPixel() ) & 0xff;
+
+ if ( c2 == iMaskFgColor ) // if foreground
+ {
+ if ( colorFGA != c1 )
+ {
+ bmpIterator2.End();
+ bmpIterator1.End();
+ return KWorstCase;
+ }
+ }
+ for ( TInt l = 0; l < columnDelta; l++ )
+ {
+ if ( iterFlag )
+ {
+ bmpIterator1.DecXPos();
+ bmpIterator2.DecXPos();
+ }
+ else
+ {
+ bmpIterator1.IncXPos();
+ bmpIterator2.IncXPos();
+ }
+ }
+ }
+
+ for ( TInt k = 0; k < rowDelta; k++ )
+ {
+ bmpIterator1.IncYPos();
+ bmpIterator2.IncYPos();
+ }
+ for ( TInt l = 0; l < columnDelta; l++ )
+ {
+ if ( iterFlag )
+ {
+ bmpIterator1.IncXPos();
+ bmpIterator2.IncXPos();
+ }
+ else
+ {
+ bmpIterator1.DecXPos();
+ bmpIterator2.DecXPos();
+ }
+ }
+ iterFlag = !iterFlag;
+ }
+
+
+ bmpIterator2.End();
+ bmpIterator1.End();
+
+ return 0;
+ }
+
+TInt CHtiTextRcg::ImageDiffBinFullL(CFbsBitmap * aBitmap1, TPoint aOrigin1,
+ CFbsBitmap * aBitmap2)
+ {
+ TSize aSize = aBitmap2->SizeInPixels();
+ //straight average difference
+ TBitmapUtil bmpIterator1(aBitmap1);
+ TBitmapUtil bmpIterator2(aBitmap2);
+
+ bmpIterator1.Begin( aOrigin1 );
+ bmpIterator2.Begin( TPoint(0,0), bmpIterator1 );
+
+ //TInt nofF = 0;
+ TInt nofB = 0;
+
+ TInt sumB = 0;
+ //TInt sumF = 0;
+ TBool intellFlagBG;
+ TBool iterFlag = EFalse;
+ TInt rowDelta = 1;
+ TInt columnDelta = 1;
+ TInt fgColor = -1;
+ for ( TInt i = 0; i < aSize.iHeight; i += rowDelta )
+ {
+ intellFlagBG = EFalse;
+ for ( TInt j = 0; j < aSize.iWidth; j += columnDelta )
+ {
+ TInt c1 = ( bmpIterator1.GetPixel() ) & 0xff;
+ TInt c2 = ( bmpIterator2.GetPixel() ) & 0xff;
+
+ if ( c2 == iMaskFgColor ) // if FG
+ {
+ if ( c1 != fgColor )
+ {
+ if ( fgColor != -1 )
+ {
+ //failed
+ bmpIterator2.End();
+ bmpIterator1.End();
+ return KWorstCase;
+ }
+ else
+ {
+ fgColor = c1; //init fgColor
+ }
+ }
+ intellFlagBG = ETrue;
+ }
+ else if ( c2 == iMaskBgColor && intellFlagBG )
+ {
+ sumB += c1;
+ ++nofB;
+ intellFlagBG = EFalse;
+ }
+ for ( TInt l = 0; l < columnDelta; l++ )
+ {
+ if ( iterFlag )
+ {
+ bmpIterator1.DecXPos();
+ bmpIterator2.DecXPos();
+ }
+ else
+ {
+ bmpIterator1.IncXPos();
+ bmpIterator2.IncXPos();
+ }
+ }
+ }
+
+ for ( TInt k = 0; k < rowDelta; k++ )
+ {
+ bmpIterator1.IncYPos();
+ bmpIterator2.IncYPos();
+ }
+ for ( TInt l = 0; l < columnDelta; l++ )
+ {
+ if ( iterFlag )
+ {
+ bmpIterator1.IncXPos();
+ bmpIterator2.IncXPos();
+ }
+ else
+ {
+ bmpIterator1.DecXPos();
+ bmpIterator2.DecXPos();
+ }
+ }
+ iterFlag = !iterFlag;
+ }
+ bmpIterator2.End();
+ bmpIterator1.End();
+
+ if ( nofB == 0 ) //something wrong, should be some BG
+ return KWorstCase;
+
+ TInt avgB = sumB / ( nofB );
+
+ if ( Abs( fgColor - avgB ) < iAvgDiffMin )
+ {
+ return KWorstCase;
+ }
+
+ return 0;
+ }
+
+void CHtiTextRcg::MinMax(CFbsBitmap * aBitmap, TInt& aMin, TInt& aMax)
+ {
+ //straight average difference
+ TSize aSize = aBitmap->SizeInPixels();
+ TBitmapUtil bmpIterator(aBitmap);
+
+ bmpIterator.Begin( TPoint(0,0) );
+
+ aMin = KMaxTInt;
+ aMax = -1;
+ for ( TInt i = 0; i < aSize.iHeight; ++i )
+ {
+ for ( TInt j = 0; j < aSize.iWidth; ++j )
+ {
+ TInt c = ( bmpIterator.GetPixel() ) & 0xff;
+
+ if ( c < aMin )
+ {
+ aMin = c;
+ }
+ else if ( c > aMax )
+ {
+ aMax = c;
+ }
+
+ if ( i & 1 )
+ {
+ bmpIterator.DecXPos();
+ }
+ else
+ {
+ bmpIterator.IncXPos();
+ }
+ }
+ bmpIterator.IncYPos();
+
+ if ( i & 1 )
+ {
+ bmpIterator.IncXPos();
+ }
+ else
+ {
+ bmpIterator.DecXPos();
+ }
+ }
+
+ bmpIterator.End();
+ }
+
+CFbsBitmap* CHtiTextRcg::ColorDownL( CFbsBitmap * aBitmap )
+ {
+ TSize bmpSize = aBitmap->SizeInPixels();
+ CFbsBitmap* result = new ( ELeave ) CFbsBitmap();
+ User::LeaveIfError( result->Create( bmpSize, EGray256 ) );
+
+ TBitmapUtil srcBmpIterator( aBitmap );
+ TBitmapUtil resultBmpIterator( result );
+
+ srcBmpIterator.Begin( TPoint( 0, 0 ) );
+ resultBmpIterator.Begin( TPoint( 0, 0 ), srcBmpIterator );
+
+ TPoint point( 0, 0 );
+ for ( point.iY = 0; point.iY < bmpSize.iHeight; ++point.iY )
+ {
+ point.iX = 0;
+ srcBmpIterator.SetPos( point );
+ resultBmpIterator.SetPos( point );
+ for ( ; point.iX < bmpSize.iWidth; ++point.iX )
+ {
+ TUint32 c = srcBmpIterator.GetPixel();
+ TRgb col( c );
+ resultBmpIterator.SetPixel( col.Gray256() );
+ srcBmpIterator.IncXPos();
+ resultBmpIterator.IncXPos();
+ }
+ }
+
+ resultBmpIterator.End();
+ srcBmpIterator.End();
+
+ return result;
+ }
+
+CFbsBitmap* CHtiTextRcg::GetTextBitmapL( const TDesC& aText,
+ const CFont* fontUsed,
+ const TInt aLength )
+ {
+ return GetTextBitmapL( aText, fontUsed, KRgbBlack, KRgbWhite,
+ EGray256, aLength );
+ }
+
+
+
+CFbsBitmap* CHtiTextRcg::GetTextBitmapL( const TDesC& aText,
+ const CFont* fontUsed,
+ TRgb aForeground,
+ TRgb aBackground,
+ TDisplayMode aDisplayMode,
+ const TInt aLength )
+{
+ HTI_LOG_FUNC_IN( "CHtiTextRcg::GetTextBitmapL" )
+ // Measure the text to get needed bitmap size and baseline point
+ CFont::TMeasureTextOutput output;
+ TInt reqWidth = fontUsed->MeasureText( aText, NULL, &output );
+ reqWidth = Max( reqWidth, output.iBounds.Width() );
+
+ // If only partial text requested, calculate new width but keep the
+ // height (and baseline) as it needs to be the same as for the full text
+ // for the text recognition to work.
+ if ( aLength < aText.Length() )
+ {
+ CFont::TMeasureTextOutput partialOutput;
+ reqWidth = fontUsed->MeasureText( aText.Left( aLength ), NULL,
+ &partialOutput );
+ reqWidth = Max( reqWidth, partialOutput.iBounds.Width() );
+ }
+
+ TSize bmpSize( reqWidth, output.iBounds.Height() );
+ HTI_LOG_FORMAT( "Bitmap width = %d", bmpSize.iWidth );
+ HTI_LOG_FORMAT( "Bitmap height = %d", bmpSize.iHeight );
+
+ // Create the bitmap
+ CFbsBitmap* result = new ( ELeave ) CFbsBitmap();
+ User::LeaveIfError( result->Create( bmpSize, aDisplayMode ) );
+
+ CFbsBitGc* bitmapContext = NULL;
+ CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL( result );
+ CleanupStack::PushL( bitmapDevice );
+ User::LeaveIfError( bitmapDevice->CreateContext( bitmapContext ) );
+ CleanupStack::PushL( bitmapContext );
+ bitmapContext->SetBrushColor( aBackground );
+ bitmapContext->Clear();
+ bitmapContext->UseFont( fontUsed );
+ bitmapContext->SetPenColor( aForeground );
+
+ // Set the baseline point and draw the text
+ TPoint pos( 0, bmpSize.iHeight - output.iBounds.iBr.iY );
+ HTI_LOG_FORMAT( "Baseline Y = %d", pos.iY );
+ if ( aLength < aText.Length() )
+ {
+ bitmapContext->DrawText( aText.Left( aLength ), pos );
+ }
+ else
+ {
+ bitmapContext->DrawText( aText, pos );
+ }
+
+ CleanupStack::PopAndDestroy( 2 );
+ HTI_LOG_FUNC_OUT( "CHtiTextRcg::GetTextBitmapL" )
+ return result;
+}
+
+
+// End of file