1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-09-08 14:17:06 +03:00

0023272: Image comparison algorithm

A new class Image_Diff for comparison of images
and a draw-command "diffimage", which compares 2 images.

Image_PixMap redesigned to provide interface for low-level image operations.
New Image_AlienPixMap class now intended for Save/Load functionality.

Aspect_PixMap class dropped.
Xw_PixMap and WNT_PixMap classes now do not inherit from Aspect_PixMap and deprecated.

ToPixMap methods now retrieve Image_PixMap as argument.

Conflicts:
src/ViewerTest/ViewerTest.cxx
Remarks applied
Fix compilation (correct merging error)

Eliminated Aspect <-> Image cyclic dependency

Fixed GIF dump in case of BGR32 image format
This commit is contained in:
kgv
2012-09-10 14:30:46 +04:00
parent 567148d8f4
commit 692613e554
43 changed files with 3095 additions and 1289 deletions

View File

@@ -43,7 +43,8 @@
#include <Quantity_Color.hxx>
#include <WNT_GraphicDevice.hxx>
#include <WNT_TypeOfImage.hxx>
#include <Image_PixMap.hxx>
#include <Image_AlienPixMap.hxx>
#include <TCollection_AsciiString.hxx>
//***//
#define I_SUCCESS Standard_True
@@ -285,64 +286,45 @@ int __WNT_API SaveWindowToFile (
} // end SaveWindowToFile
int DumpBitmapToFile (Handle(WNT_GraphicDevice)& , HDC ,
HBITMAP theHBitmap,
char* theFileName)
int DumpBitmapToFile (HBITMAP theHBitmap,
const char* theFileName)
{
// Copy data from HBITMAP
// get informations about the bitmap
BITMAP aBitmap;
if (GetObject (theHBitmap, sizeof(BITMAP), &aBitmap) == 0)
{
return I_ERROR;
}
// Get informations about the bitmap
GetObject (theHBitmap, sizeof(BITMAP), (LPSTR )&aBitmap);
Standard_Integer aWidth = aBitmap.bmWidth;
Standard_Integer aHeight = aBitmap.bmHeight;
Image_AlienPixMap anImage;
const Standard_Size aSizeRowBytes = Standard_Size(aBitmap.bmWidth) * 4;
if (!anImage.InitTrash (Image_PixMap::ImgBGR32, Standard_Size(aBitmap.bmWidth), Standard_Size(aBitmap.bmHeight), aSizeRowBytes))
{
return I_ERROR;
}
anImage.SetTopDown (false);
// Setup image data
BITMAPINFOHEADER aBitmapInfo;
memset (&aBitmapInfo, 0, sizeof(BITMAPINFOHEADER));
aBitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
aBitmapInfo.biWidth = aWidth;
aBitmapInfo.biHeight = aHeight; // positive means bottom-up!
aBitmapInfo.biPlanes = 1;
aBitmapInfo.biBitCount = 32;
aBitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
aBitmapInfo.biWidth = aBitmap.bmWidth;
aBitmapInfo.biHeight = aBitmap.bmHeight; // positive means bottom-up!
aBitmapInfo.biPlanes = 1;
aBitmapInfo.biBitCount = 32; // use 32bit for automatic word-alignment per row
aBitmapInfo.biCompression = BI_RGB;
Standard_Integer aBytesPerLine = aWidth * 4;
Standard_Byte* aDataPtr = new Standard_Byte[aBytesPerLine * aHeight];
// Copy the pixels
HDC aDC = GetDC (NULL);
Standard_Boolean isSuccess
= GetDIBits (aDC, // handle to DC
theHBitmap, // handle to bitmap
0, // first scan line to set
aHeight, // number of scan lines to copy
aDataPtr, // array for bitmap bits
(LPBITMAPINFO )&aBitmapInfo, // bitmap data info
DIB_RGB_COLORS // RGB
) != 0;
Standard_Boolean isSuccess = GetDIBits (aDC, theHBitmap,
0, // first scan line to set
aBitmap.bmHeight, // number of scan lines to copy
anImage.ChangeData(), // array for bitmap bits
(LPBITMAPINFO )&aBitmapInfo, // bitmap data info
DIB_RGB_COLORS) != 0;
if (isSuccess)
{
Handle(Image_PixMap) anImagePixMap = new Image_PixMap (aDataPtr,
aWidth, aHeight,
aBytesPerLine,
aBitmapInfo.biBitCount,
Standard_False); // bottom-up!
// Release dump memory here
delete[] aDataPtr;
// save the image
anImagePixMap->Dump (theFileName);
}
else
{
// Release dump memory
delete[] aDataPtr;
}
ReleaseDC (NULL, aDC);
return isSuccess ? I_SUCCESS : I_ERROR;
return (isSuccess && anImage.Save (theFileName)) ? I_SUCCESS : I_ERROR;
}
//***//
@@ -401,8 +383,7 @@ int SaveBitmapToFile (Handle(WNT_GraphicDevice)& gDev,
hNewBmp = hBmp;
}
retVal = DumpBitmapToFile (gDev, NULL,
hNewBmp, fName);
retVal = DumpBitmapToFile (hNewBmp, fName);
} // end __try
__finally {
if (hNewBmp != NULL && newBmp) DeleteObject (hNewBmp);

View File

@@ -30,7 +30,7 @@ class PixMap from WNT
---Keywords: Bitmap, Pixmap
inherits
PixMap from Aspect
Transient from Standard
uses
Handle from Aspect,
@@ -99,7 +99,10 @@ is
returns Integer from Standard is private;
fields
myDC : Handle from Aspect is protected;
myBitmap : Handle from Aspect is protected;
myWND : Window from Aspect;
myDC : Handle from Aspect is protected;
myBitmap : Handle from Aspect is protected;
myWND : Window from Aspect;
myWidth : Integer from Standard is protected;
myHeight : Integer from Standard is protected;
myDepth : Integer from Standard is protected;
end PixMap;

View File

@@ -31,7 +31,7 @@
#include <WNT_Window.hxx>
extern int DumpBitmapToFile( Handle(WNT_GraphicDevice)&, HDC, HBITMAP, char* );
extern int DumpBitmapToFile (HBITMAP, const char* );
#include <WNT_GraphicDevice.hxx>
@@ -50,15 +50,16 @@ Standard_Integer WNT_PixMap::PreferedDepth(
}
///////////////////////////////////////////////////////////////////////////////////////
WNT_PixMap::WNT_PixMap ( const Handle(Aspect_Window)& aWindow,
const Standard_Integer aWidth,
const Standard_Integer anHeight,
const Standard_Integer aCDepth ) :
Aspect_PixMap(aWidth, anHeight, PreferedDepth(aWindow, aCDepth))
WNT_PixMap::WNT_PixMap (const Handle(Aspect_Window)& theWindow,
const Standard_Integer theWidth,
const Standard_Integer theHeight,
const Standard_Integer theDepth)
: myWND (theWindow),
myWidth (theWidth),
myHeight (theHeight),
myDepth (PreferedDepth (theWindow, theDepth))
{
myWND = aWindow;
const Handle(WNT_Window)& hWindow = Handle(WNT_Window)::DownCast(aWindow);
const Handle(WNT_Window)& hWindow = Handle(WNT_Window)::DownCast(theWindow);
HDC hdc = GetDC ( (HWND)(hWindow->HWindow()) );
HDC hdcMem = CreateCompatibleDC ( hdc );
ReleaseDC ( (HWND)(hWindow->HWindow()), hdc );
@@ -80,8 +81,8 @@ Aspect_PixMap(aWidth, anHeight, PreferedDepth(aWindow, aCDepth))
ZeroMemory ( pBmi, sizeBmi );
pBmi->bmiHeader.biSize = sizeof (BITMAPINFOHEADER); //sizeBmi
pBmi->bmiHeader.biWidth = aWidth;
pBmi->bmiHeader.biHeight = anHeight;
pBmi->bmiHeader.biWidth = myWidth;
pBmi->bmiHeader.biHeight = myHeight;
pBmi->bmiHeader.biPlanes = 1;
pBmi->bmiHeader.biBitCount = myDepth; //WIL001: was 24
pBmi->bmiHeader.biCompression = BI_RGB;
@@ -127,8 +128,8 @@ void WNT_PixMap::Destroy ()
}
////////////////////////////////////////////////////////////
Standard_Boolean WNT_PixMap::Dump ( const Standard_CString aFilename,
const Standard_Real aGammaValue ) const
Standard_Boolean WNT_PixMap::Dump (const Standard_CString theFilename,
const Standard_Real theGammaValue) const
{
// *** gamma correction must be implemented also on WNT system ...
const Handle(WNT_Window) hWindow = Handle(WNT_Window)::DownCast(myWND);
@@ -138,7 +139,7 @@ Standard_Boolean WNT_PixMap::Dump ( const Standard_CString aFilename,
if ( dev.IsNull() ) return Standard_False;
//Aspect_PixmapError::Raise ( "WNT_GraphicDevice is NULL" );
return DumpBitmapToFile ( dev, (HDC)myDC, (HBITMAP)myBitmap, (Standard_PCharacter)aFilename );
return DumpBitmapToFile ((HBITMAP)myBitmap, theFilename);
}
////////////////////////////////////////////////////////////

View File

@@ -47,7 +47,7 @@ class Window from WNT inherits Window from Aspect
TypeOfResize from Aspect,
FillMethod from Aspect,
GradientFillMethod from Aspect,
PixMap from Aspect,
PixMap from Image,
NameOfColor from Quantity,
Color from Quantity,
Parameter from Quantity,
@@ -354,8 +354,8 @@ class Window from WNT inherits Window from Aspect
-- or the area is out of the Window.
raises WindowError from Aspect is virtual;
ToPixMap ( me )
returns PixMap from Aspect
ToPixMap ( me ; theImage : in out PixMap from Image )
returns Boolean
---Level : Public
---Purpose : dump the full contents of the window to a pixmap.
is virtual;

View File

@@ -27,7 +27,7 @@
#include <WNT_Window.ixx>
#include <Image_PixMap.hxx>
#include <Image_AlienPixMap.hxx>
#include <Aspect_Convert.hxx>
#include <stdio.h>
@@ -733,7 +733,16 @@ void WNT_Window :: RestoreArea (
Standard_Boolean WNT_Window::Dump (const Standard_CString theFilename,
const Standard_Real theGammaValue) const
{
return ToPixMap()->Dump (theFilename, theGammaValue);
Image_AlienPixMap anImg;
if (!ToPixMap (anImg) || anImg.IsEmpty())
{
return Standard_False;
}
if (Abs (theGammaValue - 1.0) > 0.001)
{
anImg.AdjustGamma (theGammaValue);
}
return anImg.Save (theFilename);
} // end WNT_Window :: Dump
//***//
//*************************** DumpArea ***********************************//
@@ -753,61 +762,50 @@ Standard_Boolean WNT_Window::DumpArea (const Standard_CString theFilename,
} // end WNT_Window :: DumpArea
//***//
static Handle(Image_PixMap) ConvertBitmap (HBITMAP theHBitmap)
static Standard_Boolean ConvertBitmap (HBITMAP theHBitmap,
Image_PixMap& thePixMap)
{
Handle(Image_PixMap) anImagePixMap;
// Copy data from HBITMAP
BITMAP aBitmap;
// Get informations about the bitmap
GetObject (theHBitmap, sizeof(BITMAP), (LPSTR )&aBitmap);
Standard_Integer aWidth = aBitmap.bmWidth;
Standard_Integer aHeight = aBitmap.bmHeight;
BITMAP aBitmap;
if (GetObject (theHBitmap, sizeof(BITMAP), (LPSTR )&aBitmap) == 0)
{
return Standard_False;
}
const Standard_Size aSizeRowBytes = Standard_Size(aBitmap.bmWidth) * 4;
if (!thePixMap.InitTrash (Image_PixMap::ImgBGR32, Standard_Size(aBitmap.bmWidth), Standard_Size(aBitmap.bmHeight), aSizeRowBytes))
{
return Standard_False;
}
thePixMap.SetTopDown (false);
// Setup image data
BITMAPINFOHEADER aBitmapInfo;
memset (&aBitmapInfo, 0, sizeof(BITMAPINFOHEADER));
aBitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
aBitmapInfo.biWidth = aWidth;
aBitmapInfo.biHeight = aHeight; // positive means bottom-up!
aBitmapInfo.biPlanes = 1;
aBitmapInfo.biBitCount = 32;
aBitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
aBitmapInfo.biWidth = aBitmap.bmWidth;
aBitmapInfo.biHeight = aBitmap.bmHeight; // positive means bottom-up!
aBitmapInfo.biPlanes = 1;
aBitmapInfo.biBitCount = 32; // use 32bit for automatic word-alignment per row
aBitmapInfo.biCompression = BI_RGB;
Standard_Integer aBytesPerLine = aWidth * 4;
Standard_Byte* aDataPtr = new Standard_Byte[aBytesPerLine * aHeight];
// Copy the pixels
HDC aDC = GetDC (NULL);
Standard_Boolean isSuccess
= GetDIBits (aDC, // handle to DC
theHBitmap, // handle to bitmap
0, // first scan line to set
aHeight, // number of scan lines to copy
aDataPtr, // array for bitmap bits
(LPBITMAPINFO )&aBitmapInfo, // bitmap data info
DIB_RGB_COLORS // RGB
) != 0;
if (isSuccess)
{
anImagePixMap = new Image_PixMap (aDataPtr,
aWidth, aHeight,
aBytesPerLine,
aBitmapInfo.biBitCount,
Standard_False); // bottom-up!
}
// Release dump memory
delete[] aDataPtr;
Standard_Boolean isSuccess = GetDIBits (aDC, theHBitmap,
0, // first scan line to set
aBitmap.bmHeight, // number of scan lines to copy
thePixMap.ChangeData(), // array for bitmap bits
(LPBITMAPINFO )&aBitmapInfo, // bitmap data info
DIB_RGB_COLORS) != 0;
ReleaseDC (NULL, aDC);
return anImagePixMap;
return isSuccess;
}
Handle(Aspect_PixMap) WNT_Window::ToPixMap() const
Standard_Boolean WNT_Window::ToPixMap (Image_PixMap& thePixMap) const
{
if (myDoubleBuffer && myHPixmap)
{
return ConvertBitmap ((HBITMAP )myHPixmap);
return ConvertBitmap ((HBITMAP )myHPixmap, thePixMap);
}
RECT aRect;
@@ -825,13 +823,13 @@ Handle(Aspect_PixMap) WNT_Window::ToPixMap() const
HBITMAP anHBitmapOld = (HBITMAP )SelectObject (aMemDC, anHBitmapDump);
BitBlt (aMemDC, 0, 0, aWidth, aHeight, aSrcDC, 0, 0, SRCCOPY);
Handle(Image_PixMap) anImagePixMap = ConvertBitmap (anHBitmapDump);
Standard_Boolean isSuccess = ConvertBitmap (anHBitmapDump, thePixMap);
// Free objects
DeleteObject (SelectObject (aMemDC, anHBitmapOld));
DeleteDC (aMemDC);
return anImagePixMap;
return isSuccess;
}
//****************************** Load ************************************//