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:
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@@ -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;
|
||||
|
@@ -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 ************************************//
|
||||
|
Reference in New Issue
Block a user