diff -r 000000000000 -r 3da2a79470a7 testtoolsconn/stat/desktop/source/lib/src/cstatimageverify.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testtoolsconn/stat/desktop/source/lib/src/cstatimageverify.cpp Mon Mar 08 15:04:18 2010 +0800 @@ -0,0 +1,678 @@ +/* +* Copyright (c) 2005-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: +* +*/ + + + + +#include "stdafx.h" +#include +#include "CSTATImageVerify.h" + +//---------------------------------------------------------------------------- +//standard constructor +CSTATImageVerify::CSTATImageVerify(CSTATLogFile *pLog) +: iImageCount(0), margin(0), lastrefimageloaded(0), pLogFile(pLog), + m_pDib(NULL), m_pDib2(NULL), m_pDibBits(NULL), m_pDibBits2(NULL), + m_pBIH(NULL), m_pBIH2(NULL), m_pPalette(NULL), m_pPalette2(NULL), + m_dwDibSize(0), m_dwDibSize2(0), m_nPaletteEntries(0), m_nPaletteEntries2(0) +{ +} + +//---------------------------------------------------------------------------- +//destructor +CSTATImageVerify::~CSTATImageVerify() +{ + if (m_pDib) + { + delete [] m_pDib; + m_pDib = NULL; + } + + if (m_pDib2) + { + delete [] m_pDib2; + m_pDib2 = NULL; + } +} + +//---------------------------------------------------------------------------- + +//image verification function (loading + blitting) +int CSTATImageVerify::VerifyImage(CString& lastscreenshot) +{ + TCHAR buffer[70]; + _stprintf(buffer, _T("User set margin of error (percentage) : %ld"), margin); + + pLogFile->Set(START_VERIFICATION, buffer); + + // make sure we've got at least 1 image left + if(ImagesRemaining()) + { + if(LoadRefImage()) + pLogFile->Set(REFIMAGELOAD_OK, refimagearray[lastrefimageloaded++].completefilenamepath); + else + return pLogFile->Set(REFIMAGELOAD_FAILURE); + + Sleep(500); + + if(LoadNewImage(lastscreenshot)) + pLogFile->Set(NEWIMAGELOAD_OK); + else + return pLogFile->Set(NEWIMAGELOAD_FAILURE); + } + else + return pLogFile->Set(REFIMAGELOAD_FAILURE_LIMIT); //run out of reference images + + //compare images and decide if difference is greater than margin value set earlier + + // If we have not data we can't draw. + if (!m_pDib2) + return pLogFile->Set(VERIFICATION_FAILURE); + + //set width and height of images + int nWidth = m_pBIH2 -> biWidth; + int nHeight = m_pBIH2 -> biHeight; + + HDC hdc, hMaskDC, hImageDC; + HBITMAP hMaskBitmap, hImageBitmap; + + hdc = GetDC(NULL); + + //--------------------- + + hMaskDC = CreateCompatibleDC(hdc); + hImageDC = CreateCompatibleDC(hdc); + + hMaskBitmap = CreateCompatibleBitmap(hdc, nWidth, nHeight); + + SelectObject(hMaskDC, hMaskBitmap); + SetTextColor(hMaskDC, RGB(0, 0, 255)); + + //--------------------- + + hImageBitmap = CreateCompatibleBitmap(hdc, nWidth, nHeight); + + // release the object now we're finished with it + ReleaseDC(NULL, hdc); + + SelectObject(hImageDC, hImageBitmap); + SetTextColor(hImageDC, RGB(0, 0, 255)); + + //--------------------- + + //set MaskBitmap pixel data to that of the original DIB + SetDIBits(hMaskDC, hMaskBitmap, 0L, nHeight, m_pDibBits, (BITMAPINFO *)m_pBIH, (DWORD)DIB_RGB_COLORS); + + //create a new DIB using second image data + SetDIBits(hImageDC, hImageBitmap, 0L, nHeight, m_pDibBits2, (BITMAPINFO *)m_pBIH2, (DWORD)DIB_RGB_COLORS); + + //XOR new image with original image (so new pic on top of pic 2) + BitBlt(hMaskDC, 0, 0, nWidth, nHeight, hImageDC, 0, 0, SRCINVERT); + + //*************************************************** + + //now work on percentage difference in images + + //need to use 'new' otherwise you get a stack overflow with anything big like this (1MB+) + COLORREF (*pixelcoord) [480]; + pixelcoord = new COLORREF [640][480]; + if (!pixelcoord) + return pLogFile->Set(VERIFICATION_FAILURE); + + int x, y, myheight, mywidth; + float totalpixelarea; + + x = 0; + y = 0; + int difference = 0; + float finalpercentage = 0; + totalpixelarea = 0; + myheight = 0; + mywidth = 0; + + mywidth = m_pBIH -> biWidth; + myheight = m_pBIH -> biHeight; + + // convert total to float for later % calculation + totalpixelarea = (float)(mywidth * myheight); + + //initialisation + for(y = 0; y < 480; y++) + { + //go across picture left to right at each line + for(x = 0; x < 640; x++) + { + //get colorref value from coordinates + pixelcoord[x][y] = 0; + } + } + + //check pixels - start at line 0 + for(y = 0; y < myheight; y++) + { + //go across picture left to right at each line + for(x = 0; x < mywidth; x++) + { + //get colorref value from coordinates + pixelcoord[x][y] = GetPixel(hMaskDC, x, y); + + //if not a black pixel then increment counter + if(pixelcoord[x][y] != 0) + { + difference++; + } + } + } + + // release resources + delete [] pixelcoord; + DeleteDC(hMaskDC); + DeleteDC(hImageDC); + DeleteObject(hMaskBitmap); + DeleteObject(hImageBitmap); + + if (m_pDib) + { + delete [] m_pDib; + m_pDib = NULL; + } + + if (m_pDib2) + { + delete [] m_pDib2; + m_pDib2 = NULL; + } + + //now calculate percentage of pic that is not black + finalpercentage = ((difference / totalpixelarea) * 100); + + // write conversion info to file + + + CString cBuffer; + cBuffer.Format(_T("Margin %ld : Difference %f"), margin, finalpercentage); + pLogFile->Set(cBuffer); + + if(finalpercentage > margin) + return pLogFile->Set(VERIFICATION_FAILURE); + + return pLogFile->Set(VERIFICATION_PASS); +} + + +//---------------------------------------------------------------------------- +//image loading for current new image +bool CSTATImageVerify::LoadNewImage(CString& newimage) +{ + CFile cf; + + // Attempt to open the Dib file for reading. + if(!cf.Open(newimage, CFile::modeRead)) + return false; + + // Get the size of the file and store + // in a local variable. Subtract the + // size of the BITMAPFILEHEADER structure + // since we won't keep that in memory. + DWORD dwDibSize; + dwDibSize = cf.GetLength() - sizeof( BITMAPFILEHEADER ); + + // Attempt to allocate the Dib memory. + unsigned char *pDib; + pDib = new unsigned char [dwDibSize]; + if(!pDib) + { + cf.Close(); + return false; + } + + BITMAPFILEHEADER BFH; + + // Read in the Dib header and data. + try + { + // Did we read in the entire BITMAPFILEHEADER? + if( cf.Read( &BFH, sizeof( BITMAPFILEHEADER ) ) + != sizeof( BITMAPFILEHEADER ) || + + // Is the type 'MB'? + BFH.bfType != 'MB' || + + // Did we read in the remaining data? + cf.Read( pDib, dwDibSize ) != dwDibSize ) + { + + // Delete the memory if we had any + // errors and return FALSE. + delete [] pDib; + cf.Close(); + return false; + } + } + + // If we catch an exception, delete the + // exception, the temporary Dib memory, + // and return FALSE. + catch( CFileException *e ) + { + e->Delete(); + delete [] pDib; + cf.Close(); + return( FALSE ); + } + + // If we got to this point, the Dib has been + // loaded. If a Dib was already loaded into + // this class, we must now delete it. + if (m_pDib2) + { + delete [] m_pDib2; + m_pDib2 = NULL; + } + + // Store the local Dib data pointer and + // Dib size variables in the class member + // variables. + m_pDib2 = pDib; + m_dwDibSize2 = dwDibSize; + + // Pointer our BITMAPINFOHEADER and RGBQUAD + // variables to the correct place in the Dib data. + m_pBIH2 = (BITMAPINFOHEADER *) m_pDib2; + m_pPalette2 = + (RGBQUAD *) &m_pDib2[sizeof(BITMAPINFOHEADER)]; + + // Calculate the number of palette entries. + m_nPaletteEntries = 1 << m_pBIH2->biBitCount; + if( m_pBIH2->biBitCount > 8 ) + m_nPaletteEntries = 0; + else if( m_pBIH2->biClrUsed != 0 ) + m_nPaletteEntries = m_pBIH2->biClrUsed; + + // Point m_pDib2Bits to the actual Dib bits data. + m_pDibBits2 = + &m_pDib2[sizeof(BITMAPINFOHEADER)+ + m_nPaletteEntries*sizeof(RGBQUAD)]; + + // If we have a valid palette, delete it. + if( m_Palette.GetSafeHandle() != NULL ) + m_Palette.DeleteObject(); + + // If there are palette entries, we'll need + // to create a LOGPALETTE then create the + // CPalette palette. + if( m_nPaletteEntries != 0 ) + { + // Allocate the LOGPALETTE structure. + LOGPALETTE *pLogPal = (LOGPALETTE *) new char [sizeof(LOGPALETTE) + m_nPaletteEntries*sizeof(PALETTEENTRY)]; + if (pLogPal) + { + // Set the LOGPALETTE to version 0x300 + // and store the number of palette + // entries. + pLogPal->palVersion = 0x300; + pLogPal->palNumEntries = (WORD)m_nPaletteEntries; + + // Store the RGB values into each + // PALETTEENTRY element. + for( int i=0; ipalPalEntry[i].peRed = + m_pPalette2[i].rgbRed; + pLogPal->palPalEntry[i].peGreen = + m_pPalette2[i].rgbGreen; + pLogPal->palPalEntry[i].peBlue = + m_pPalette2[i].rgbBlue; + } + + // Create the CPalette object and + // delete the LOGPALETTE memory. + m_Palette.CreatePalette( pLogPal ); + delete [] pLogPal; + } + else + return false; + } + + cf.Close(); + + return true; +} + +//---------------------------------------------------------------------------- +//image loading for current reference image +bool CSTATImageVerify::LoadRefImage() +{ + CFile cf; + if( !cf.Open(refimagearray[lastrefimageloaded].completefilenamepath, CFile::modeRead ) ) + return false; + + // Get the size of the file and store + // in a local variable. Subtract the + // size of the BITMAPFILEHEADER structure + // since we won't keep that in memory. + DWORD dwDibSize; + dwDibSize = cf.GetLength() - sizeof( BITMAPFILEHEADER ); + + // Attempt to allocate the Dib memory. + unsigned char *pDib; + pDib = new unsigned char [dwDibSize]; + if(!pDib) + { + cf.Close(); + return false; + } + + BITMAPFILEHEADER BFH; + + // Read in the Dib header and data. + try + { + + // Did we read in the entire BITMAPFILEHEADER? + if( cf.Read( &BFH, sizeof( BITMAPFILEHEADER ) ) + != sizeof( BITMAPFILEHEADER ) || + + // Is the type 'MB'? + BFH.bfType != 'MB' || + + // Did we read in the remaining data? + cf.Read( pDib, dwDibSize ) != dwDibSize ) + { + + // Delete the memory if we had any + // errors and return FALSE. + delete [] pDib; + cf.Close(); + return false; + } + } + + // If we catch an exception, delete the + // exception, the temporary Dib memory, + // and return FALSE. + catch( CFileException *e ) + { + e->Delete(); + delete [] pDib; + cf.Close(); + return false; + } + + // If we got to this point, the Dib has been + // loaded. If a Dib was already loaded into + // this class, we must now delete it. + if(m_pDib) + { + delete m_pDib; + m_pDib = NULL; + } + + // Store the local Dib data pointer and + // Dib size variables in the class member + // variables. + m_pDib = pDib; + m_dwDibSize = dwDibSize; + + // Pointer our BITMAPINFOHEADER and RGBQUAD + // variables to the correct place in the Dib data. + m_pBIH = (BITMAPINFOHEADER *) m_pDib; + m_pPalette = + (RGBQUAD *) &m_pDib[sizeof(BITMAPINFOHEADER)]; + + // Calculate the number of palette entries. + m_nPaletteEntries = 1 << m_pBIH->biBitCount; + if( m_pBIH->biBitCount > 8 ) + m_nPaletteEntries = 0; + else if( m_pBIH->biClrUsed != 0 ) + m_nPaletteEntries = m_pBIH->biClrUsed; + + // Point m_pDibBits to the actual Dib bits data. + m_pDibBits = + &m_pDib[sizeof(BITMAPINFOHEADER)+ + m_nPaletteEntries*sizeof(RGBQUAD)]; + + // If we have a valid palette, delete it. + if (m_Palette.GetSafeHandle()) + m_Palette.DeleteObject(); + + // If there are palette entries, we'll need + // to create a LOGPALETTE then create the + // CPalette palette. + if( m_nPaletteEntries != 0 ) + { + // Allocate the LOGPALETTE structure. + LOGPALETTE *pLogPal = (LOGPALETTE *) new char + [sizeof(LOGPALETTE)+ + m_nPaletteEntries*sizeof(PALETTEENTRY)]; + + if(pLogPal) + { + + // Set the LOGPALETTE to version 0x300 + // and store the number of palette + // entries. + pLogPal->palVersion = 0x300; + pLogPal->palNumEntries = (WORD)m_nPaletteEntries; + + // Store the RGB values into each + // PALETTEENTRY element. + for( int i=0; ipalPalEntry[i].peRed = + m_pPalette[i].rgbRed; + pLogPal->palPalEntry[i].peGreen = + m_pPalette[i].rgbGreen; + pLogPal->palPalEntry[i].peBlue = + m_pPalette[i].rgbBlue; + } + + // Create the CPalette object and + // delete the LOGPALETTE memory. + m_Palette.CreatePalette( pLogPal ); + delete [] pLogPal; + } + else + return false; + } + + cf.Close(); + + return true; +} + +//---------------------------------------------------------------------------- +int CSTATImageVerify::EnableVerification(int fudge) +{ + // temp variable + FILETIME creationtime; + creationtime.dwLowDateTime = 0; + creationtime.dwHighDateTime = 0; + + // initialise settings + iImageCount = 0; + lastrefimageloaded = 0; + margin = fudge; + + // check limits + if (margin < 0) + margin = 0; + if (margin > 100) + margin = 100; + + // populate our array with images + CFileFind refimagefinder; + if (refimagefinder.FindFile(referenceimagedir + _T("\\*.bmp"), 0)) + { + int i = 0; + int iMoreFiles = true; + for (i=0;i