1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-04 18:06:22 +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

@ -348,10 +348,6 @@ is
deferred class Window;
---Purpose: Defines a window.
---Category: Classes
deferred class PixMap;
---Purpose: Defines a pixmap(bitmap)
---Category: Classes
deferred class GraphicDevice;
---Purpose: Defines a physical graphic device allowing to

View File

@ -1,92 +0,0 @@
-- Created on: 1999-10-14
-- Created by: VKH
-- Copyright (c) 1999 Matra Datavision
-- Copyright (c) 1999-2012 OPEN CASCADE SAS
--
-- The content of this file is subject to the Open CASCADE Technology Public
-- License Version 6.5 (the "License"). You may not use the content of this file
-- except in compliance with the License. Please obtain a copy of the License
-- at http://www.opencascade.org and read it completely before using this file.
--
-- The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-- main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
--
-- The Original Code and all software distributed under the License is
-- distributed on an "AS IS" basis, without warranty of any kind, and the
-- Initial Developer hereby disclaims all such warranties, including without
-- limitation, any warranties of merchantability, fitness for a particular
-- purpose or non-infringement. Please see the License for the specific terms
-- and conditions governing the rights and limitations under the License.
-- Updated: GG IMP100701 Add the "depth" field and method
-- to the pixmap object.
deferred class PixMap from Aspect
inherits
TShared from MMgt
---Purpose: This class allows the definition of a pixmap(bitmap)
uses
Handle from Aspect,
Color from Quantity
raises
PixmapDefinitionError from Aspect,
PixmapError from Aspect
is
Initialize ( aWidth, anHeight : Integer from Standard;
aDepth : Integer from Standard );
---Level: Public
---Purpose: Initializes the datas of a pixmap with a pixel size
-- <aWidth>,<anHeight> and depth.
Destroy ( me : mutable )
raises PixmapError from Aspect is deferred;
---Level: Advanced
---Purpose: Destroy the pixmap
---Category: Methods to modify the class definition
Dump ( me ; aFilename : CString from Standard;
aGammaValue: Real from Standard = 1.0 )
returns Boolean
raises PixmapError from Aspect is deferred;
---Level: Advanced
---Purpose:
-- Dumps the Bitmap to an image file with
-- an optional gamma correction value
-- and returns TRUE if the dump occurs normaly.
---Trigger: Raises if pixmap is not defined properly
PixelColor ( me : in;
theX, theY : in Integer from Standard )
returns Color from Quantity is deferred;
---Purpose:
-- Returns the pixel color.
----------------------------
-- Category: Inquire methods
----------------------------
PixmapID ( me ) returns Handle from Aspect
is deferred;
---Level: Advanced
---Purpose: Returns the ID of the just created pixmap
---Category: Inquire methods
Size ( me ; aWidth, anHeight : out Integer from Standard )
is static;
---Level: Public
---Purpose: Returns the allocated pixmap's size in PIXEL
---Category: Inquire methods
Depth ( me ) returns Integer from Standard
is static;
---Level: Public
---Purpose: Returns the allocated pixmap's depth (planes number)
---Category: Inquire methods
fields
myWidth : Integer from Standard is protected;
myHeight : Integer from Standard is protected;
myDepth : Integer from Standard is protected;
end PixMap;

View File

@ -1,52 +0,0 @@
// Created on: 1999-10-14
// Created by: VKH
// Copyright (c) 1999 Matra Datavision
// Copyright (c) 1999-2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
// Updated GG IMP100701 Add the "depth" field and method
// to the pixmap object.
//-Version
#include <Aspect_PixMap.ixx>
//-Constructor
////////////////////////////////////////////////////////////////////
Aspect_PixMap::Aspect_PixMap ( const Standard_Integer aWidth,
const Standard_Integer anHeight,
const Standard_Integer aDepth )
{
myWidth = aWidth;
myHeight = anHeight;
myDepth = aDepth;
}
////////////////////////////////////////////////////////////
void Aspect_PixMap::Size ( Standard_Integer &aWidth,
Standard_Integer &anHeight ) const {
aWidth = myWidth;
anHeight = myHeight;
}
////////////////////////////////////////////////////////////
Standard_Integer Aspect_PixMap::Depth () const {
return myDepth;
}

View File

@ -42,7 +42,6 @@ uses
TypeOfResize from Aspect,
FillMethod from Aspect,
Handle from Aspect,
PixMap from Aspect,
Ratio from Quantity,
Parameter from Quantity,
NameOfColor from Quantity,
@ -208,12 +207,6 @@ is
-- or the area is out of the Window.
raises WindowError from Aspect is deferred;
ToPixMap ( me )
returns PixMap from Aspect
---Level : Public
---Purpose : dump the full contents of the window to a pixmap.
is deferred;
Load ( me ; aFilename : CString from Standard) returns Boolean
---Level: Advanced
---Purpose: Loads the XWD file to this Window.

View File

@ -34,7 +34,7 @@
#include <Draw_Interpretor.hxx>
#include <Draw_Appli.hxx>
#include <TCollection_AsciiString.hxx>
#include <Image_PixMap.hxx>
#include <Image_AlienPixMap.hxx>
extern Draw_Interpretor theCommands;
extern Standard_Boolean Draw_VirtualWindows;
@ -717,39 +717,44 @@ Standard_Boolean Draw_Window::Save (const char* theFileName) const
}
}
// find the image
XImage* pximage = XGetImage (Draw_WindowDisplay, GetDrawable(),
0, 0, winAttr.width, winAttr.height,
AllPlanes, ZPixmap);
if (pximage == NULL)
XVisualInfo aVInfo;
if (XMatchVisualInfo (Draw_WindowDisplay, Draw_WindowScreen, 32, TrueColor, &aVInfo) == 0
&& XMatchVisualInfo (Draw_WindowDisplay, Draw_WindowScreen, 24, TrueColor, &aVInfo) == 0)
{
std::cerr << "24-bit TrueColor visual is not supported by server!\n";
return Standard_False;
}
if (winAttr.visual->c_class == TrueColor)
Image_AlienPixMap anImage;
bool isBigEndian = Image_PixMap::IsBigEndianHost();
const Standard_Size aSizeRowBytes = Standard_Size(winAttr.width) * 4;
if (!anImage.InitTrash (isBigEndian ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgBGR32,
Standard_Size(winAttr.width), Standard_Size(winAttr.height), aSizeRowBytes))
{
Standard_Byte* aDataPtr = (Standard_Byte* )pximage->data;
Handle(Image_PixMap) anImagePixMap = new Image_PixMap (aDataPtr,
pximage->width, pximage->height,
pximage->bytes_per_line,
pximage->bits_per_pixel,
Standard_True);
// destroy the image
XDestroyImage (pximage);
// save the image
return anImagePixMap->Dump (theFileName);
}
else
{
std::cerr << "Visual Type not supported!";
// destroy the image
XDestroyImage (pximage);
return Standard_False;
}
anImage.SetTopDown (true);
XImage* anXImage = XCreateImage (Draw_WindowDisplay, aVInfo.visual,
32, ZPixmap, 0, (char* )anImage.ChangeData(), winAttr.width, winAttr.height, 32, int(aSizeRowBytes));
anXImage->bitmap_bit_order = anXImage->byte_order = (isBigEndian ? MSBFirst : LSBFirst);
if (XGetSubImage (Draw_WindowDisplay, GetDrawable(),
0, 0, winAttr.width, winAttr.height,
AllPlanes, ZPixmap, anXImage, 0, 0) == NULL)
{
anXImage->data = NULL;
XDestroyImage (anXImage);
return Standard_False;
}
// destroy the image
anXImage->data = NULL;
XDestroyImage (anXImage);
// save the image
return anImage.Save (theFileName);
}
//=======================================================================
//function : ProcessEvent
//purpose :
@ -1700,63 +1705,44 @@ void DrawWindow::Clear()
/*--------------------------------------------------------*\
| SaveBitmap
\*--------------------------------------------------------*/
static Standard_Boolean SaveBitmap (HBITMAP theHBitmap,
static Standard_Boolean SaveBitmap (HBITMAP theHBitmap,
const char* theFileName)
{
// 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;
}
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 Standard_False;
}
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;
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;
}
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;
ReleaseDC (NULL, aDC);
return isSuccess;
return isSuccess && anImage.Save (theFileName);
}
/*--------------------------------------------------------*\

View File

@ -53,3 +53,4 @@ Graphic3d_AspectText3d.cxx
Graphic3d_WNTGraphicDevice.cxx
Graphic3d_NameOfFont.hxx
Graphic3d_PtrFrameBuffer.hxx
Graphic3d_BufferType.hxx

View File

@ -329,6 +329,7 @@ is
---------------------------
imported PrimitiveArray;
imported BufferType;
imported CBitFields20;
---Purpose: Defines the C structure

View File

@ -1,4 +1,4 @@
// Copyright (c) 1999-2012 OPEN CASCADE SAS
// Copyright (c) 2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
@ -15,15 +15,15 @@
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#ifndef _Image_HPrivateImage_HeaderFile
#define _Image_HPrivateImage_HeaderFile
#ifndef _Graphic3d_BufferType_H__
#define _Graphic3d_BufferType_H__
#include <NCollection_Handle.hxx>
//! Define buffers available for dump
typedef enum
{
Graphic3d_BT_RGB, //!< color buffer without alpha component
Graphic3d_BT_RGBA, //!< color buffer
Graphic3d_BT_Depth //!< depth buffer
} Graphic3d_BufferType;
// This typedef shadows the private image storage class
// Currently FreeImagePlus is used
class fipImage;
typedef NCollection_Handle<fipImage> Image_HPrivateImage;
#endif /*_Image_HPrivateImage_HeaderFile*/
#endif // _Graphic3d_BufferType_H__

View File

@ -71,6 +71,7 @@ uses
PlaneAngle from Quantity,
AlienImage from AlienImage,
PixMap from Image,
Array1OfEdge from Aspect,
CLayer2d from Aspect,
@ -93,7 +94,7 @@ uses
CPlane from Graphic3d,
CStructure from Graphic3d,
CView from Graphic3d,
CRawBufferData from Image,
BufferType from Graphic3d,
Structure from Graphic3d,
TextPath from Graphic3d,
TypeOfComposition from Graphic3d,
@ -1008,8 +1009,9 @@ is
---Purpose: Change offscreen FBO viewport.
BufferDump( me : mutable;
view : CView from Graphic3d;
buffer : in out CRawBufferData from Image )
theCView : CView from Graphic3d;
theImage : in out PixMap from Image;
theBufferType : BufferType from Graphic3d )
returns Boolean from Standard
is deferred;
---Purpose: Dump active rendering buffer into specified memory buffer.

View File

@ -6,5 +6,11 @@ Image_PixelAddress.cxx
Image_PixelAddress.hxx
Image.edl
Image_CMPLRS.edl
Image_CRawBufferData.hxx
Image_HPrivateImage.hxx
Image_PixMap.hxx
Image_PixMap.cxx
Image_PixMapData.hxx
Image_Color.hxx
Image_AlienPixMap.hxx
Image_AlienPixMap.cxx
Image_Diff.hxx
Image_Diff.cxx

View File

@ -88,18 +88,16 @@ is
IndexPixel from Aspect,
IndexPixelMapHasher );
class PixMap;
---Purpose: Aspect_PixMap implementation.
-----------------------------
---Category: Imported types:
-----------------------------
imported PixelAddress;
imported HPrivateImage;
imported CRawBufferData;
imported PixMap;
imported AlienPixMap;
imported PixMap_Handle;
imported AlienPixMap_Handle;
imported Diff;
-----------------------------
---Category: The Enumerations
@ -132,12 +130,7 @@ is
---Purpose: Type of dithering method.
enumeration TypeOfImage is TOI_ColorImage,
TOI_PseudoColorImage,
TOI_RGB,
TOI_RGBA,
TOI_RGBF,
TOI_RGBAF,
TOI_FLOAT
TOI_PseudoColorImage
end TypeOfImage ;
Zoom ( aImage : mutable Image from Image ;

View File

@ -0,0 +1,516 @@
// Created on: 2010-09-16
// Created by: KGV
// Copyright (c) 2010-2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_FREEIMAGE
#include <FreeImage.h>
#ifdef _MSC_VER
#pragma comment( lib, "FreeImage.lib" )
#endif
#endif
#include <Image_AlienPixMap.hxx>
#include <gp.hxx>
#include <TCollection_AsciiString.hxx>
#include <fstream>
#ifdef HAVE_FREEIMAGE
namespace
{
static Image_PixMap::ImgFormat convertFromFreeFormat (FREE_IMAGE_TYPE theFormatFI,
FREE_IMAGE_COLOR_TYPE theColorTypeFI,
unsigned theBitsPerPixel)
{
switch (theFormatFI)
{
case FIT_RGBF: return Image_PixMap::ImgRGBF;
case FIT_RGBAF: return Image_PixMap::ImgRGBAF;
case FIT_FLOAT: return Image_PixMap::ImgGrayF;
case FIT_BITMAP:
{
switch (theColorTypeFI)
{
case FIC_MINISBLACK:
{
return Image_PixMap::ImgGray;
}
case FIC_RGB:
{
if (Image_PixMap::IsBigEndianHost())
{
return (theBitsPerPixel == 32) ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgRGB;
}
else
{
return (theBitsPerPixel == 32) ? Image_PixMap::ImgBGR32 : Image_PixMap::ImgBGR;
}
}
case FIC_RGBALPHA:
{
return Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
}
default:
return Image_PixMap::ImgUNKNOWN;
}
}
default:
return Image_PixMap::ImgUNKNOWN;
}
}
static FREE_IMAGE_TYPE convertToFreeFormat (Image_PixMap::ImgFormat theFormat)
{
switch (theFormat)
{
case Image_PixMap::ImgGrayF:
return FIT_FLOAT;
case Image_PixMap::ImgRGBAF:
return FIT_RGBAF;
case Image_PixMap::ImgRGBF:
return FIT_RGBF;
case Image_PixMap::ImgRGBA:
case Image_PixMap::ImgBGRA:
case Image_PixMap::ImgRGB32:
case Image_PixMap::ImgBGR32:
case Image_PixMap::ImgRGB:
case Image_PixMap::ImgBGR:
case Image_PixMap::ImgGray:
return FIT_BITMAP;
default:
return FIT_UNKNOWN;
}
}
};
#endif
IMPLEMENT_STANDARD_HANDLE (Image_AlienPixMap, Image_PixMap)
IMPLEMENT_STANDARD_RTTIEXT(Image_AlienPixMap, Image_PixMap)
// =======================================================================
// function : Image_AlienPixMap
// purpose :
// =======================================================================
Image_AlienPixMap::Image_AlienPixMap()
: myLibImage (NULL)
{
SetTopDown (false);
}
// =======================================================================
// function : ~Image_AlienPixMap
// purpose :
// =======================================================================
Image_AlienPixMap::~Image_AlienPixMap()
{
Clear();
}
// =======================================================================
// function : InitWrapper
// purpose :
// =======================================================================
bool Image_AlienPixMap::InitWrapper (ImgFormat thePixelFormat,
Standard_Byte* theDataPtr,
const Standard_Size theSizeX,
const Standard_Size theSizeY,
const Standard_Size theSizeRowBytes)
{
Clear();
return false;
}
// =======================================================================
// function : InitTrash
// purpose :
// =======================================================================
bool Image_AlienPixMap::InitTrash (ImgFormat thePixelFormat,
const Standard_Size theSizeX,
const Standard_Size theSizeY,
const Standard_Size theSizeRowBytes)
{
Clear();
#ifdef HAVE_FREEIMAGE
FREE_IMAGE_TYPE aFormatFI = convertToFreeFormat (thePixelFormat);
int aBitsPerPixel = (int )Image_PixMap::SizePixelBytes (thePixelFormat) * 8;
if (aFormatFI == FIT_UNKNOWN)
{
aFormatFI = FIT_BITMAP;
aBitsPerPixel = 24;
}
FIBITMAP* anImage = FreeImage_AllocateT (aFormatFI, (int )theSizeX, (int )theSizeY, aBitsPerPixel);
Image_PixMap::ImgFormat aFormat = convertFromFreeFormat (FreeImage_GetImageType (anImage),
FreeImage_GetColorType (anImage),
FreeImage_GetBPP (anImage));
if (thePixelFormat == Image_PixMap::ImgBGR32
|| thePixelFormat == Image_PixMap::ImgRGB32)
{
//FreeImage_SetTransparent (anImage, FALSE);
aFormat = (aFormat == Image_PixMap::ImgBGRA) ? Image_PixMap::ImgBGR32 : Image_PixMap::ImgRGB32;
}
Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
SetTopDown (false);
// assign image after wrapper initialization (virtual Clear() called inside)
myLibImage = anImage;
return true;
#else
return Image_PixMap::InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes);
#endif
}
// =======================================================================
// function : Clear
// purpose :
// =======================================================================
bool Image_AlienPixMap::InitCopy (const Image_PixMap& theCopy)
{
if (&theCopy == this)
{
// self-copying disallowed
return false;
}
if (!InitTrash (theCopy.Format(), theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
{
return false;
}
if (myImgFormat == theCopy.Format())
{
if (myData.mySizeRowBytes == theCopy.SizeRowBytes()
&& myData.myTopToDown == theCopy.TopDownInc())
{
// copy with one call
memcpy (myData.myDataPtr, theCopy.Data(), theCopy.SizeBytes());
return true;
}
// copy row-by-row
const Standard_Size aRowSizeBytes = (myData.mySizeRowBytes > theCopy.SizeRowBytes())
? theCopy.SizeRowBytes() : myData.mySizeRowBytes;
for (Standard_Size aRow = 0; aRow < myData.mySizeY; ++aRow)
{
memcpy (ChangeRow (aRow), theCopy.Row (aRow), aRowSizeBytes);
}
return true;
}
// pixel format conversion required
Clear();
return false;
}
// =======================================================================
// function : Clear
// purpose :
// =======================================================================
void Image_AlienPixMap::Clear (ImgFormat thePixelFormat)
{
Image_PixMap::Clear (thePixelFormat);
#ifdef HAVE_FREEIMAGE
if (myLibImage != NULL)
{
FreeImage_Unload (myLibImage);
myLibImage = NULL;
}
#endif
}
// =======================================================================
// function : Load
// purpose :
// =======================================================================
bool Image_AlienPixMap::Load (const TCollection_AsciiString& theImagePath)
{
Clear();
#ifdef HAVE_FREEIMAGE
FREE_IMAGE_FORMAT aFIF = FreeImage_GetFileType (theImagePath.ToCString(), 0);
if (aFIF == FIF_UNKNOWN)
{
// no signature? try to guess the file format from the file extension
aFIF = FreeImage_GetFIFFromFilename (theImagePath.ToCString());
}
if ((aFIF == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading (aFIF))
{
// unsupported image format
return false;
}
int aLoadFlags = 0;
if (aFIF == FIF_GIF)
{
// 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading
aLoadFlags = GIF_PLAYBACK;
}
else if (aFIF == FIF_ICO)
{
// convert to 32bpp and create an alpha channel from the AND-mask when loading
aLoadFlags = ICO_MAKEALPHA;
}
FIBITMAP* anImage = FreeImage_Load (aFIF, theImagePath.ToCString(), aLoadFlags);
if (anImage == NULL)
{
return false;
}
Image_PixMap::ImgFormat aFormat = convertFromFreeFormat (FreeImage_GetImageType (anImage),
FreeImage_GetColorType (anImage),
FreeImage_GetBPP (anImage));
if (aFormat == Image_PixMap::ImgUNKNOWN)
{
//anImage = FreeImage_ConvertTo24Bits (anImage);
return false;
}
Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
SetTopDown (false);
// assign image after wrapper initialization (virtual Clear() called inside)
myLibImage = anImage;
return true;
#else
return false;
#endif
}
// =======================================================================
// function : savePPM
// purpose :
// =======================================================================
bool Image_AlienPixMap::savePPM (const TCollection_AsciiString& theFileName) const
{
if (IsEmpty())
{
return false;
}
// Open file
FILE* aFile = fopen (theFileName.ToCString(), "wb");
if (aFile == NULL)
{
return false;
}
// Write header
fprintf (aFile, "P6\n%d %d\n255\n", (int )SizeX(), (int )SizeY());
fprintf (aFile, "# Image stored by OpenCASCADE framework in linear RGB colorspace\n");
// Write pixel data
Quantity_Color aColor;
Quantity_Parameter aDummy;
Standard_Byte aByte;
for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
{
for (Standard_Size aCol = 0; aCol < SizeY(); ++aCol)
{
// extremely SLOW but universal (implemented for all supported pixel formats)
aColor = PixelColor (aCol, aRow, aDummy);
aByte = Standard_Byte(aColor.Red() * 255.0); fwrite (&aByte, 1, 1, aFile);
aByte = Standard_Byte(aColor.Green() * 255.0); fwrite (&aByte, 1, 1, aFile);
aByte = Standard_Byte(aColor.Blue() * 255.0); fwrite (&aByte, 1, 1, aFile);
}
}
// Close file
fclose (aFile);
return true;
}
// =======================================================================
// function : Save
// purpose :
// =======================================================================
bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
{
#ifdef HAVE_FREEIMAGE
if (myLibImage == NULL)
{
return false;
}
FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilename (theFileName.ToCString());
if (anImageFormat == FIF_UNKNOWN)
{
std::cerr << "Image_PixMap, image format doesn't supported!\n";
return false;
}
if (IsTopDown())
{
FreeImage_FlipVertical (myLibImage);
SetTopDown (false);
}
// FreeImage doesn't provide flexible format convertion API
// so we should perform multiple convertions in some cases!
Standard_Boolean isCopied = Standard_False;
FIBITMAP* anImageToDump = myLibImage;
switch (anImageFormat)
{
case FIF_PNG:
case FIF_BMP:
{
if (Format() == Image_PixMap::ImgBGR32
|| Format() == Image_PixMap::ImgRGB32)
{
// stupid FreeImage treats reserved byte as alpha if some bytes not set to 0xFF
Image_PixMapData<Image_ColorRGB32>& aData = Image_PixMap::EditData<Image_ColorRGB32>();
for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
{
for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol)
{
aData.ChangeValue (aRow, aCol).a_() = 0xFF;
}
}
}
else if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
{
anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
}
break;
}
case FIF_GIF:
{
FIBITMAP* aTmpBitmap = myLibImage;
if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
{
aTmpBitmap = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
if (aTmpBitmap == NULL)
{
return false;
}
}
if (FreeImage_GetBPP (aTmpBitmap) != 24)
{
FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (aTmpBitmap);
if (aTmpBitmap != myLibImage)
{
FreeImage_Unload (aTmpBitmap);
}
if (aTmpBitmap24 == NULL)
{
return false;
}
aTmpBitmap = aTmpBitmap24;
}
// need convertion to image with pallete (requires 24bit bitmap)
anImageToDump = FreeImage_ColorQuantize (aTmpBitmap, FIQ_NNQUANT);
if (aTmpBitmap != myLibImage)
{
FreeImage_Unload (aTmpBitmap);
}
break;
}
case FIF_EXR:
{
if (Format() == Image_PixMap::ImgGray)
{
anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_FLOAT);
}
else if (Format() == Image_PixMap::ImgRGBA
|| Format() == Image_PixMap::ImgBGRA)
{
anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBAF);
}
else
{
FREE_IMAGE_TYPE aImgTypeFI = FreeImage_GetImageType (myLibImage);
if (aImgTypeFI != FIT_RGBF
&& aImgTypeFI != FIT_RGBAF
&& aImgTypeFI != FIT_FLOAT)
{
anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBF);
}
}
break;
}
default:
{
if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
{
anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
if (anImageToDump == NULL)
{
return false;
}
}
if (FreeImage_GetBPP (anImageToDump) != 24)
{
FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (anImageToDump);
if (anImageToDump != myLibImage)
{
FreeImage_Unload (anImageToDump);
}
if (aTmpBitmap24 == NULL)
{
return false;
}
anImageToDump = aTmpBitmap24;
}
break;
}
}
if (anImageToDump == NULL)
{
return false;
}
bool isSaved = (FreeImage_Save (anImageFormat, anImageToDump, theFileName.ToCString()) != FALSE);
if (anImageToDump != myLibImage)
{
FreeImage_Unload (anImageToDump);
}
return isSaved;
#else
const Standard_Integer aLen = theFileName.Length();
if ((aLen >= 4) && (theFileName.Value (aLen - 3) == '.')
&& TCollection_AsciiString::ISSIMILAR (theFileName.SubString (aLen - 2, aLen), "ppm"))
{
return savePPM (theFileName);
}
std::cerr << "Image_PixMap, no image library available! Image saved in PPM format.\n";
return savePPM (theFileName);
#endif
}
// =======================================================================
// function : AdjustGamma
// purpose :
// =======================================================================
Standard_EXPORT bool Image_AlienPixMap::AdjustGamma (const Standard_Real theGammaCorr)
{
#ifdef HAVE_FREEIMAGE
return FreeImage_AdjustGamma (myLibImage, theGammaCorr) != FALSE;
#else
return false;
#endif
}

View File

@ -0,0 +1,96 @@
// Created on: 2012-07-18
// Created by: Kirill GAVRILOV
// Copyright (c) 2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#ifndef _Image_AlienPixMap_H__
#define _Image_AlienPixMap_H__
#include <Image_PixMap.hxx>
#include <Image_TypeOfImage.hxx>
class TCollection_AsciiString;
struct FIBITMAP;
//! Image class that support file reading/writing operations using auxiliary image library.
//! Notice that supported images format could be limited.
class Image_AlienPixMap : public Image_PixMap
{
public:
//! Empty constructor.
Standard_EXPORT Image_AlienPixMap();
//! Destructor
Standard_EXPORT virtual ~Image_AlienPixMap();
//! Read image data from file.
Standard_EXPORT bool Load (const TCollection_AsciiString& theFileName);
//! Write image data to file using file extension to determine compression format.
Standard_EXPORT bool Save (const TCollection_AsciiString& theFileName);
//! Initialize image plane with required dimensions.
//! thePixelFormat - if specified pixel format doesn't supported by image library
//! than nearest supported will be used instead!
//! theSizeRowBytes - may be ignored by this class and required alignemnt will be used instead!
Standard_EXPORT virtual bool InitTrash (ImgFormat thePixelFormat,
const Standard_Size theSizeX,
const Standard_Size theSizeY,
const Standard_Size theSizeRowBytes = 0);
//! Initialize by copying data.
Standard_EXPORT virtual bool InitCopy (const Image_PixMap& theCopy);
//! Method correctly deallocate internal buffer.
Standard_EXPORT virtual void Clear (ImgFormat thePixelFormat = ImgGray);
//! Performs gamma correction on image.
//! theGamma - gamma value to use; a value of 1.0 leaves the image alone
Standard_EXPORT bool AdjustGamma (const Standard_Real theGammaCorr);
private:
FIBITMAP* myLibImage;
private:
//! Copying allowed only within Handles
Image_AlienPixMap (const Image_AlienPixMap& );
Image_AlienPixMap& operator= (const Image_AlienPixMap& );
//! Wrapper initialization is disallowed for this class (will return false in any case)!
//! Use only copying and allocation initializers.
Standard_EXPORT virtual bool InitWrapper (ImgFormat thePixelFormat,
Standard_Byte* theDataPtr,
const Standard_Size theSizeX,
const Standard_Size theSizeY,
const Standard_Size theSizeRowBytes);
//! Built-in PPM export
Standard_EXPORT bool savePPM (const TCollection_AsciiString& theFileName) const;
public:
DEFINE_STANDARD_RTTI(Image_AlienPixMap) // Type definition
};
DEFINE_STANDARD_HANDLE(Image_AlienPixMap, Image_PixMap)
#endif // _Image_AlienPixMap_H__

View File

@ -1,30 +0,0 @@
// Copyright (c) 1999-2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#ifndef _Image_CRawBufferData_HeaderFile
#define _Image_CRawBufferData_HeaderFile
#include <InterfaceGraphic_RawBufferData.hxx>
typedef TRawBufferData Image_CRawBufferData;
#if defined(__cplusplus) || defined(c_plusplus)
#include <Standard_Type.hxx>
const Handle(Standard_Type)& TYPE(Image_CRawBufferData);
#endif
#endif /*_Image_CRawBufferData_HeaderFile*/

543
src/Image/Image_Color.hxx Normal file
View File

@ -0,0 +1,543 @@
// Created on: 2012-07-18
// Created by: Kirill GAVRILOV
// Copyright (c) 2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#ifndef _Image_Color_H__
#define _Image_Color_H__
#include <Standard.hxx>
//! POD structure for packed RGB color value (3 bytes)
struct Image_ColorRGB
{
//! Returns the number of components.
static Standard_Integer Length()
{
return 3;
}
public: // access methods
//! Alias to 1st component (red intensity).
Standard_Byte r() const { return v[0]; }
//! Alias to 2nd component (green intensity).
Standard_Byte g() const { return v[1]; }
//! Alias to 3rd component (blue intensity).
Standard_Byte b() const { return v[2]; }
//! Alias to 1st component (red intensity).
Standard_Byte& r() { return v[0]; }
//! Alias to 2nd component (green intensity).
Standard_Byte& g() { return v[1]; }
//! Alias to 3rd component (blue intensity).
Standard_Byte& b() { return v[2]; }
public:
Standard_Byte v[3];
};
//! POD structure for packed RGB color value (4 bytes with extra byte for alignment)
struct Image_ColorRGB32
{
//! Returns the number of components.
static Standard_Integer Length()
{
return 3;
}
//! Alias to 1st component (red intensity).
Standard_Byte r() const { return v[0]; }
//! Alias to 2nd component (green intensity).
Standard_Byte g() const { return v[1]; }
//! Alias to 3rd component (blue intensity).
Standard_Byte b() const { return v[2]; }
//! Alias to 4th component (dummy).
Standard_Byte a_() const { return v[3]; }
//! Alias to 1st component (red intensity).
Standard_Byte& r() { return v[0]; }
//! Alias to 2nd component (green intensity).
Standard_Byte& g() { return v[1]; }
//! Alias to 3rd component (blue intensity).
Standard_Byte& b() { return v[2]; }
//! Alias to 4th component (dummy).
Standard_Byte& a_() { return v[3]; }
public:
Standard_Byte v[4];
};
//! POD structure for packed RGBA color value (4 bytes)
struct Image_ColorRGBA
{
//! Returns the number of components.
static Standard_Integer Length()
{
return 4;
}
//! Alias to 1st component (red intensity).
Standard_Byte r() const { return v[0]; }
//! Alias to 2nd component (green intensity).
Standard_Byte g() const { return v[1]; }
//! Alias to 3rd component (blue intensity).
Standard_Byte b() const { return v[2]; }
//! Alias to 4th component (alpha value).
Standard_Byte a() const { return v[3]; }
//! Alias to 1st component (red intensity).
Standard_Byte& r() { return v[0]; }
//! Alias to 2nd component (green intensity).
Standard_Byte& g() { return v[1]; }
//! Alias to 3rd component (blue intensity).
Standard_Byte& b() { return v[2]; }
//! Alias to 4th component (alpha value).
Standard_Byte& a() { return v[3]; }
public:
Standard_Byte v[4];
};
//! POD structure for packed BGR color value (3 bytes)
struct Image_ColorBGR
{
//! Returns the number of components.
static Standard_Integer Length()
{
return 3;
}
//! Alias to 3rd component (red intensity).
Standard_Byte r() const { return v[2]; }
//! Alias to 2nd component (green intensity).
Standard_Byte g() const { return v[1]; }
//! Alias to 1st component (blue intensity).
Standard_Byte b() const { return v[0]; }
//! Alias to 3rd component (red intensity).
Standard_Byte& r() { return v[2]; }
//! Alias to 2nd component (green intensity).
Standard_Byte& g() { return v[1]; }
//! Alias to 1st component (blue intensity).
Standard_Byte& b() { return v[0]; }
public:
Standard_Byte v[3];
};
//! POD structure for packed BGR color value (4 bytes with extra byte for alignment)
struct Image_ColorBGR32
{
//! Returns the number of components.
static Standard_Integer Length()
{
return 3;
}
//! Alias to 3rd component (red intensity).
Standard_Byte r() const { return v[2]; }
//! Alias to 2nd component (green intensity).
Standard_Byte g() const { return v[1]; }
//! Alias to 1st component (blue intensity).
Standard_Byte b() const { return v[0]; }
//! Alias to 4th component (dummy).
Standard_Byte a_() const { return v[3]; }
//! Alias to 3rd component (red intensity).
Standard_Byte& r() { return v[2]; }
//! Alias to 2nd component (green intensity).
Standard_Byte& g() { return v[1]; }
//! Alias to 1st component (blue intensity).
Standard_Byte& b() { return v[0]; }
//! Alias to 4th component (dummy).
Standard_Byte& a_() { return v[3]; }
public:
Standard_Byte v[4];
};
//! POD structure for packed BGRA color value (4 bytes)
struct Image_ColorBGRA
{
//! Returns the number of components.
static Standard_Integer Length()
{
return 4;
}
//! Alias to 3rd component (red intensity).
Standard_Byte r() const { return v[2]; }
//! Alias to 2nd component (green intensity).
Standard_Byte g() const { return v[1]; }
//! Alias to 1st component (blue intensity).
Standard_Byte b() const { return v[0]; }
//! Alias to 4th component (alpha value).
Standard_Byte a() const { return v[3]; }
//! Alias to 3rd component (red intensity).
Standard_Byte& r() { return v[2]; }
//! Alias to 2nd component (green intensity).
Standard_Byte& g() { return v[1]; }
//! Alias to 1st component (blue intensity).
Standard_Byte& b() { return v[0]; }
//! Alias to 4th component (alpha value).
Standard_Byte& a() { return v[3]; }
public:
Standard_Byte v[4];
};
//! POD structure for packed float RGB color value (3 floats)
struct Image_ColorRGBF
{
//! Returns the number of components.
static Standard_Integer Length()
{
return 3;
}
//! Alias to 1st component (red intensity).
Standard_ShortReal r() const { return v[0]; }
//! Alias to 2nd component (green intensity).
Standard_ShortReal g() const { return v[1]; }
//! Alias to 3rd component (blue intensity).
Standard_ShortReal b() const { return v[2]; }
//! Alias to 1st component (red intensity).
Standard_ShortReal& r() { return v[0]; }
//! Alias to 2nd component (green intensity).
Standard_ShortReal& g() { return v[1]; }
//! Alias to 3rd component (blue intensity).
Standard_ShortReal& b() { return v[2]; }
public:
Standard_ShortReal v[3];
};
//! POD structure for packed BGR float color value (3 floats)
struct Image_ColorBGRF
{
//! Returns the number of components.
static Standard_Integer Length()
{
return 3;
}
//! Alias to 3rd component (red intensity).
Standard_ShortReal r() const { return v[2]; }
//! Alias to 2nd component (green intensity).
Standard_ShortReal g() const { return v[1]; }
//! Alias to 1st component (blue intensity).
Standard_ShortReal b() const { return v[0]; }
//! Alias to 3rd component (red intensity).
Standard_ShortReal& r() { return v[2]; }
//! Alias to 2nd component (green intensity).
Standard_ShortReal& g() { return v[1]; }
//! Alias to 1st component (blue intensity).
Standard_ShortReal& b() { return v[0]; }
public:
Standard_ShortReal v[3];
};
//! POD structure for packed RGBA color value (4 floats)
struct Image_ColorRGBAF
{
//! Returns the number of components.
static Standard_Integer Length()
{
return 4;
}
//! Alias to 1st component (red intensity).
Standard_ShortReal r() const { return v[0]; }
//! Alias to 2nd component (green intensity).
Standard_ShortReal g() const { return v[1]; }
//! Alias to 3rd component (blue intensity).
Standard_ShortReal b() const { return v[2]; }
//! Alias to 4th component (alpha value).
Standard_ShortReal a() const { return v[3]; }
//! Alias to 1st component (red intensity).
Standard_ShortReal& r() { return v[0]; }
//! Alias to 2nd component (green intensity).
Standard_ShortReal& g() { return v[1]; }
//! Alias to 3rd component (blue intensity).
Standard_ShortReal& b() { return v[2]; }
//! Alias to 4th component (alpha value).
Standard_ShortReal& a() { return v[3]; }
public:
Standard_ShortReal v[4];
};
//! POD structure for packed float BGRA color value (4 floats)
struct Image_ColorBGRAF
{
//! Returns the number of components.
static Standard_Integer Length()
{
return 4;
}
//! Alias to 3rd component (red intensity).
Standard_ShortReal r() const { return v[2]; }
//! Alias to 2nd component (green intensity).
Standard_ShortReal g() const { return v[1]; }
//! Alias to 1st component (blue intensity).
Standard_ShortReal b() const { return v[0]; }
//! Alias to 4th component (alpha value).
Standard_ShortReal a() const { return v[3]; }
//! Alias to 3rd component (red intensity).
Standard_ShortReal& r() { return v[2]; }
//! Alias to 2nd component (green intensity).
Standard_ShortReal& g() { return v[1]; }
//! Alias to 1st component (blue intensity).
Standard_ShortReal& b() { return v[0]; }
//! Alias to 4th component (alpha value).
Standard_ShortReal& a() { return v[3]; }
public:
Standard_ShortReal v[4];
};
//! Addition operator
template<typename ColorType_t>
inline ColorType_t Image_ColorSumm3 (const ColorType_t& theA, const ColorType_t& theB)
{
ColorType_t aRes = { theA.v[0] + theB.v[0],
theA.v[1] + theB.v[1],
theA.v[2] + theB.v[2] };
return aRes;
}
inline Image_ColorRGB operator+ (const Image_ColorRGB& theA, const Image_ColorRGB& theB)
{
return Image_ColorSumm3 (theA, theB);
}
inline Image_ColorBGR operator+ (const Image_ColorBGR& theA, const Image_ColorBGR& theB)
{
return Image_ColorSumm3 (theA, theB);
}
inline Image_ColorRGBF operator+ (const Image_ColorRGBF& theA, const Image_ColorRGBF& theB)
{
return Image_ColorSumm3 (theA, theB);
}
inline Image_ColorBGRF operator+ (const Image_ColorBGRF& theA, const Image_ColorBGRF& theB)
{
return Image_ColorSumm3 (theA, theB);
}
template<typename ColorType_t>
inline ColorType_t Image_ColorSumm4 (const ColorType_t& theA, const ColorType_t& theB)
{
ColorType_t aRes = { theA.v[0] + theB.v[0],
theA.v[1] + theB.v[1],
theA.v[2] + theB.v[2],
theA.v[3] + theB.v[3] };
return aRes;
}
inline Image_ColorRGBA operator+ (const Image_ColorRGBA& theA, const Image_ColorRGBA& theB)
{
return Image_ColorSumm4 (theA, theB);
}
inline Image_ColorBGRA operator+ (const Image_ColorBGRA& theA, const Image_ColorBGRA& theB)
{
return Image_ColorSumm4 (theA, theB);
}
inline Image_ColorRGB32 operator+ (const Image_ColorRGB32& theA, const Image_ColorRGB32& theB)
{
return Image_ColorSumm4 (theA, theB);
}
inline Image_ColorBGR32 operator+ (const Image_ColorBGR32& theA, const Image_ColorBGR32& theB)
{
return Image_ColorSumm4 (theA, theB);
}
inline Image_ColorRGBAF operator+ (const Image_ColorRGBAF& theA, const Image_ColorRGBAF& theB)
{
return Image_ColorSumm4 (theA, theB);
}
inline Image_ColorBGRAF operator+ (const Image_ColorBGRAF& theA, const Image_ColorBGRAF& theB)
{
return Image_ColorSumm4 (theA, theB);
}
//! Subtraction operator
template<typename ColorType_t>
inline ColorType_t Image_ColorSub3 (const ColorType_t& theA, const ColorType_t& theB)
{
ColorType_t aRes = { theA.v[0] - theB.v[0],
theA.v[1] - theB.v[1],
theA.v[2] - theB.v[2] };
return aRes;
}
inline Image_ColorRGB operator- (const Image_ColorRGB& theA, const Image_ColorRGB& theB)
{
return Image_ColorSub3 (theA, theB);
}
inline Image_ColorBGR operator- (const Image_ColorBGR& theA, const Image_ColorBGR& theB)
{
return Image_ColorSub3 (theA, theB);
}
inline Image_ColorRGBF operator- (const Image_ColorRGBF& theA, const Image_ColorRGBF& theB)
{
return Image_ColorSub3 (theA, theB);
}
inline Image_ColorBGRF operator- (const Image_ColorBGRF& theA, const Image_ColorBGRF& theB)
{
return Image_ColorSub3 (theA, theB);
}
template<typename ColorType_t>
inline ColorType_t Image_ColorSub4 (const ColorType_t& theA, const ColorType_t& theB)
{
ColorType_t aRes = { theA.v[0] - theB.v[0],
theA.v[1] - theB.v[1],
theA.v[2] - theB.v[2],
theA.v[3] - theB.v[3] };
return aRes;
}
inline Image_ColorRGBA operator- (const Image_ColorRGBA& theA, const Image_ColorRGBA& theB)
{
return Image_ColorSub4 (theA, theB);
}
inline Image_ColorBGRA operator- (const Image_ColorBGRA& theA, const Image_ColorBGRA& theB)
{
return Image_ColorSub4 (theA, theB);
}
inline Image_ColorRGB32 operator- (const Image_ColorRGB32& theA, const Image_ColorRGB32& theB)
{
return Image_ColorSub4 (theA, theB);
}
inline Image_ColorBGR32 operator- (const Image_ColorBGR32& theA, const Image_ColorBGR32& theB)
{
return Image_ColorSub4 (theA, theB);
}
inline Image_ColorRGBAF operator- (const Image_ColorRGBAF& theA, const Image_ColorRGBAF& theB)
{
return Image_ColorSub4 (theA, theB);
}
inline Image_ColorBGRAF operator- (const Image_ColorBGRAF& theA, const Image_ColorBGRAF& theB)
{
return Image_ColorSub4 (theA, theB);
}
#endif // _Image_Color_H__

526
src/Image/Image_Diff.cxx Normal file
View File

@ -0,0 +1,526 @@
// Created on: 2012-07-10
// Created by: VRO
// Copyright (c) 2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#include <Image_Diff.hxx>
#include <Image_AlienPixMap.hxx>
#include <TColStd_MapIteratorOfMapOfInteger.hxx>
#include <cstdlib>
IMPLEMENT_STANDARD_HANDLE (Image_Diff, Standard_Transient)
IMPLEMENT_STANDARD_RTTIEXT(Image_Diff, Standard_Transient)
//! Dot squared for difference of two colors
inline Standard_Integer dotSquared (const Image_ColorRGB& theColor)
{
// explicitly convert to integer
const Standard_Integer r = theColor.r();
const Standard_Integer g = theColor.g();
const Standard_Integer b = theColor.b();
return r * r + g * g + b * b;
}
//! @return true if pixel is black
inline bool isBlack (const Image_ColorRGB& theColor)
{
return theColor.r() == 0
&& theColor.g() == 0
&& theColor.b() == 0;
}
//! Converts a pixel position (row, column) to one integer value
inline Standard_Size pixel2Int (const Standard_Size aRow,
const Standard_Size aCol)
{
return aCol + (aRow << 15);
}
//! Converts an integer value to pixel coordinates (row, column)
inline void int2Pixel (const Standard_Size theValue,
Standard_Size& theRow,
Standard_Size& theCol)
{
theRow = (theValue >> 15);
theCol = theValue - (theRow << 15);
}
namespace
{
static const Standard_Size NEIGHBOR_PIXELS_NB = 8;
struct
{
Standard_Integer row_inc;
Standard_Integer col_inc;
inline Standard_Size pixel2Int (const Standard_Size theRowCenter,
const Standard_Size theColCenter) const
{
return ::pixel2Int (theRowCenter + Standard_Size(row_inc),
theColCenter + Standard_Size(col_inc));
}
inline bool isBlack (const Image_PixMapData<Image_ColorRGB>& theData,
const Standard_Size theRowCenter,
const Standard_Size theColCenter) const
{
return ::isBlack (theData.Value (theRowCenter + Standard_Size(row_inc),
theColCenter + Standard_Size(col_inc)));
}
}
static const NEIGHBOR_PIXELS[NEIGHBOR_PIXELS_NB] =
{
{-1, -1}, {-1, 0}, {-1, 1},
{ 0, -1}, { 0, 1},
{ 1, -1}, { 1, 0}, { 1, 1}
};
static bool isSupportedFormat (const Image_PixMap::ImgFormat theFormat)
{
return theFormat == Image_PixMap::ImgRGB
|| theFormat == Image_PixMap::ImgBGR
|| theFormat == Image_PixMap::ImgRGB32
|| theFormat == Image_PixMap::ImgBGR32
|| theFormat == Image_PixMap::ImgRGBA
|| theFormat == Image_PixMap::ImgBGRA;
}
};
// =======================================================================
// function : Image_Diff
// purpose :
// =======================================================================
Image_Diff::Image_Diff()
: myColorTolerance (0.0),
myIsBorderFilterOn (Standard_False)
{
//
}
// =======================================================================
// function : ~Image_Diff
// purpose :
// =======================================================================
Image_Diff::~Image_Diff()
{
releaseGroupsOfDiffPixels();
}
// =======================================================================
// function : Init
// purpose :
// =======================================================================
Standard_Boolean Image_Diff::Init (const Handle(Image_PixMap)& theImageRef,
const Handle(Image_PixMap)& theImageNew,
const Standard_Boolean theToBlackWhite)
{
myImageRef.Nullify();
myImageNew.Nullify();
myDiffPixels.Clear();
releaseGroupsOfDiffPixels();
if (theImageRef.IsNull() || theImageNew.IsNull()
|| theImageRef->IsEmpty() || theImageNew->IsEmpty()
|| theImageRef->SizeX() != theImageNew->SizeX()
|| theImageRef->SizeY() != theImageNew->SizeY()
|| theImageRef->Format() != theImageNew->Format())
{
std::cerr << "Images has different format or dimensions\n";
return Standard_False;
}
else if (!isSupportedFormat (theImageRef->Format()))
{
std::cerr << "Images has unsupported pixel format\n";
return Standard_False;
}
else if (theImageRef->SizeX() >= 0xFFFF
|| theImageRef->SizeY() >= 0xFFFF)
{
std::cerr << "Image too large\n";
return Standard_False;
}
myImageRef = theImageRef;
myImageNew = theImageNew;
if (theToBlackWhite)
{
// Convert the images to white/black
const Image_ColorRGB aWhite = {{255, 255, 255}};
Image_PixMapData<Image_ColorRGB>& aDataRef = myImageRef->EditData<Image_ColorRGB>();
Image_PixMapData<Image_ColorRGB>& aDataNew = myImageNew->EditData<Image_ColorRGB>();
for (Standard_Size aRow = 0; aRow < aDataRef.SizeY(); ++aRow)
{
for (Standard_Size aCol = 0; aCol < aDataRef.SizeY(); ++aCol)
{
Image_ColorRGB& aPixel1 = aDataRef.ChangeValue (aRow, aCol);
Image_ColorRGB& aPixel2 = aDataNew.ChangeValue (aRow, aCol);
if (!isBlack (aPixel1))
{
aPixel1 = aWhite;
}
if (!isBlack (aPixel2))
{
aPixel2 = aWhite;
}
}
}
}
return Standard_True;
}
// =======================================================================
// function : Init
// purpose :
// =======================================================================
Standard_Boolean Image_Diff::Init (const TCollection_AsciiString& theImgPathRef,
const TCollection_AsciiString& theImgPathNew,
const Standard_Boolean theToBlackWhite)
{
Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
if (!anImgRef->Load (theImgPathRef)
|| !anImgNew->Load (theImgPathNew))
{
std::cerr << "Failed to load image(s) file(s)\n";
return Standard_False;
}
return Init (anImgRef, anImgNew, theToBlackWhite);
}
// =======================================================================
// function : SetColorTolerance
// purpose :
// =======================================================================
void Image_Diff::SetColorTolerance (const Standard_Real theTolerance)
{
myColorTolerance = theTolerance;
}
// =======================================================================
// function : ColorTolerance
// purpose :
// =======================================================================
Standard_Real Image_Diff::ColorTolerance() const
{
return myColorTolerance;
}
// =======================================================================
// function : SetBorderFilterOn
// purpose :
// =======================================================================
void Image_Diff::SetBorderFilterOn (const Standard_Boolean theToIgnore)
{
myIsBorderFilterOn = theToIgnore;
}
// =======================================================================
// function : IsBorderFilterOn
// purpose :
// =======================================================================
Standard_Boolean Image_Diff::IsBorderFilterOn() const
{
return myIsBorderFilterOn;
}
// =======================================================================
// function : Compare
// purpose :
// =======================================================================
Standard_Integer Image_Diff::Compare()
{
// Number of different pixels (by color)
Standard_Integer aNbDiffColors = 0;
myDiffPixels.Clear();
if (myImageRef.IsNull() || myImageNew.IsNull())
{
return -1;
}
// Tolerance of comparison operation for color
// Maximum difference between colors (white - black) = 100%
Image_ColorRGB aDiff = {{255, 255, 255}};
const Standard_Integer aMaxDiffColor = dotSquared (aDiff);
const Standard_Integer aDiffThreshold = Standard_Integer(Standard_Real(aMaxDiffColor) * myColorTolerance);
// we don't care about RGB/BGR/RGBA/BGRA/RGB32/BGR32 differences
// because we just compute summ of r g b components
const Image_PixMapData<Image_ColorRGB>& aDataRef = myImageRef->ReadData<Image_ColorRGB>();
const Image_PixMapData<Image_ColorRGB>& aDataNew = myImageNew->ReadData<Image_ColorRGB>();
// compare colors of each pixel
for (Standard_Size aRow = 0; aRow < myImageRef->SizeY(); ++aRow)
{
for (Standard_Size aCol = 0; aCol < myImageRef->SizeX(); ++aCol)
{
aDiff = aDataNew.Value (aRow, aCol) - aDataRef.Value (aRow, aCol);
if (dotSquared (aDiff) > aDiffThreshold)
{
const Standard_Size aValue = pixel2Int (aRow, aCol);
myDiffPixels.Append (aValue);
++aNbDiffColors;
}
}
}
// take into account a border effect
if (myIsBorderFilterOn && myDiffPixels.Length() > 0)
{
aNbDiffColors = ignoreBorderEffect();
}
return aNbDiffColors;
}
// =======================================================================
// function : SaveDiffImage
// purpose :
// =======================================================================
Standard_Boolean Image_Diff::SaveDiffImage (Image_PixMap& theDiffImage) const
{
if (myImageRef.IsNull() || myImageNew.IsNull())
{
return Standard_False;
}
if (theDiffImage.IsEmpty()
|| theDiffImage.SizeX() != myImageRef->SizeX()
|| theDiffImage.SizeY() != myImageRef->SizeY()
|| !isSupportedFormat (theDiffImage.Format()))
{
if (!theDiffImage.InitTrash (Image_PixMap::ImgRGB, myImageRef->SizeX(), myImageRef->SizeY()))
{
return Standard_False;
}
}
Standard_Size aRow, aCol;
const Image_ColorRGB aWhite = {{255, 255, 255}};
Image_PixMapData<Image_ColorRGB>& aDataOut = theDiffImage.EditData<Image_ColorRGB>();
// initialize black image for dump
memset (theDiffImage.ChangeData(), 0, theDiffImage.SizeBytes());
if (myGroupsOfDiffPixels.IsEmpty())
{
if (myIsBorderFilterOn)
{
return Standard_True;
}
for (Standard_Integer aPixelId = 0; aPixelId < myDiffPixels.Length(); ++aPixelId)
{
const Standard_Size aValue = myDiffPixels.Value (aPixelId);
int2Pixel (aValue, aRow, aCol);
aDataOut.ChangeValue (aRow, aCol) = aWhite;
}
return Standard_True;
}
Standard_Integer aGroupId = 1;
for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next(), ++aGroupId)
{
if (myLinearGroups.Contains (aGroupId))
{
continue; // skip linear groups
}
const TColStd_MapOfInteger* aGroup = aGrIter.Value();
for (TColStd_MapIteratorOfMapOfInteger aPixelIter(*aGroup);
aPixelIter.More(); aPixelIter.Next())
{
int2Pixel (aPixelIter.Key(), aRow, aCol);
aDataOut.ChangeValue (aRow, aCol) = aWhite;
}
}
return Standard_True;
}
// =======================================================================
// function : SaveDiffImage
// purpose :
// =======================================================================
Standard_Boolean Image_Diff::SaveDiffImage (const TCollection_AsciiString& theDiffPath) const
{
if (myImageRef.IsNull() || myImageNew.IsNull() || theDiffPath.IsEmpty())
{
return Standard_False;
}
Image_AlienPixMap aDiff;
if (!aDiff.InitTrash (Image_PixMap::ImgRGB, myImageRef->SizeX(), myImageRef->SizeY())
|| !SaveDiffImage (aDiff))
{
return Standard_False;
}
// save image
return aDiff.Save (theDiffPath);
}
// =======================================================================
// function : ignoreBorderEffect
// purpose :
// =======================================================================
Standard_Integer Image_Diff::ignoreBorderEffect()
{
if (myImageRef.IsNull() || myImageNew.IsNull())
{
return 0;
}
const Image_PixMapData<Image_ColorRGB>& aDataRef = myImageRef->ReadData<Image_ColorRGB>();
// allocate groups of different pixels
releaseGroupsOfDiffPixels();
// Find a different area (a set of close to each other pixels which colors differ in both images).
// It filters alone pixels with different color.
Standard_Size aRow1, aCol1, aRow2, aCol2;
Standard_Integer aLen1 = (myDiffPixels.Length() > 0) ? (myDiffPixels.Length() - 1) : 0;
for (Standard_Integer aPixelId1 = 0; aPixelId1 < aLen1; ++aPixelId1)
{
const Standard_Size aValue1 = myDiffPixels.Value (aPixelId1);
int2Pixel (aValue1, aRow1, aCol1);
// Check other pixels in the list looking for a neighbour of this one
for (Standard_Integer aPixelId2 = aPixelId1 + 1; aPixelId2 < myDiffPixels.Length(); ++aPixelId2)
{
const Standard_Size aValue2 = myDiffPixels.Value (aPixelId2);
int2Pixel (aValue2, aRow2, aCol2);
if (std::abs (ptrdiff_t (aCol1 - aCol2)) <= 1 &&
std::abs (ptrdiff_t (aRow1 - aRow2)) <= 1)
{
// A neighbour is found. Create a new group and add both pixels.
if (myGroupsOfDiffPixels.IsEmpty())
{
TColStd_MapOfInteger* aGroup = new TColStd_MapOfInteger();
aGroup->Add (aValue1);
aGroup->Add (aValue2);
myGroupsOfDiffPixels.Append (aGroup);
}
else
{
// Find a group the pixels belong to.
Standard_Boolean isFound = Standard_False;
for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next())
{
TColStd_MapOfInteger*& aGroup = aGrIter.ChangeValue();
if (aGroup->Contains (aValue1))
{
aGroup->Add (aValue2);
isFound = Standard_True;
break;
}
}
if (!isFound)
{
// Create a new group
TColStd_MapOfInteger* aGroup = new TColStd_MapOfInteger();
aGroup->Add (aValue1);
aGroup->Add (aValue2);
myGroupsOfDiffPixels.Append (aGroup);
}
}
}
}
}
// filter linear groups which represent border of a solid shape
Standard_Integer aGroupId = 1;
for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next(), ++aGroupId)
{
Standard_Integer aNeighboursNb = 0;
Standard_Boolean isLine = Standard_True;
const TColStd_MapOfInteger* aGroup = aGrIter.Value();
for (TColStd_MapIteratorOfMapOfInteger aPixelIter (*aGroup); aPixelIter.More(); aPixelIter.Next())
{
int2Pixel (aPixelIter.Key(), aRow1, aCol1);
aNeighboursNb = 0;
// pixels of a line have only 1 or 2 neighbour pixels inside the same group
// check all neighbour pixels on presence in the group
for (Standard_Size aNgbrIter = 0; aNgbrIter < NEIGHBOR_PIXELS_NB; ++aNgbrIter)
{
if (aGroup->Contains (NEIGHBOR_PIXELS[aNgbrIter].pixel2Int (aRow1, aCol1)))
{
++aNeighboursNb;
}
}
if (aNeighboursNb > 2)
{
isLine = Standard_False;
break;
}
} // for pixels inside group...
if (isLine)
{
// Test a pixel of the linear group on belonging to a solid shape.
// Consider neighbour pixels of the last pixel of the linear group in the 1st image.
// If the pixel has greater than 1 not black neighbour pixel, it is a border of a shape.
// Otherwise, it may be a topological edge, for example.
aNeighboursNb = 0;
for (Standard_Size aNgbrIter = 0; aNgbrIter < NEIGHBOR_PIXELS_NB; ++aNgbrIter)
{
if (!NEIGHBOR_PIXELS[aNgbrIter].isBlack (aDataRef, aRow1, aCol1))
{
++aNeighboursNb;
}
}
if (aNeighboursNb > 1)
{
myLinearGroups.Add (aGroupId);
}
}
} // for groups...
// number of different groups of pixels (except linear groups)
Standard_Integer aNbDiffColors = 0;
aGroupId = 1;
for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next(), ++aGroupId)
{
if (!myLinearGroups.Contains (aGroupId))
++aNbDiffColors;
}
return aNbDiffColors;
}
// =======================================================================
// function : releaseGroupsOfDiffPixels
// purpose :
// =======================================================================
void Image_Diff::releaseGroupsOfDiffPixels()
{
for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next())
{
TColStd_MapOfInteger*& aGroup = aGrIter.ChangeValue();
delete aGroup;
}
myGroupsOfDiffPixels.Clear();
myLinearGroups.Clear();
}

135
src/Image/Image_Diff.hxx Normal file
View File

@ -0,0 +1,135 @@
// Created on: 2012-07-10
// Created by: VRO
// Copyright (c) 2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#ifndef _Image_Diff_H__
#define _Image_Diff_H__
#include <Image_PixMap.hxx>
#include <TCollection_AsciiString.hxx>
#include <TColStd_MapOfInteger.hxx>
#include <NCollection_List.hxx>
#include <NCollection_Vector.hxx>
//! This class compares two images pixel-by-pixel.
//! It uses the following methods to ignore the difference between images:
//! - Black/White comparison. It makes the images 2-colored before the comparison.
//! - Equality with tolerance. Colors of two pixels are considered the same if the
//! differnce of their color is less than a tolerance.
//! - Border filter. The algorithm ignores alone independent pixels,
//! which are different on both images, ignores the "border effect" -
//! the difference caused by triangles located at angle about 0 or 90 degrees to the user.
//!
//! Border filter ignores a difference in implementation of
//! anti-aliasing and other effects on boundary of a shape.
//! The triangles of a boundary zone are usually located so that their normals point aside the user
//! (about 90 degree between the normal and the direction to the user's eye).
//! Deflection of the light for such a triangle depends on implementation of the video driver.
//! In order to skip this difference the following algorithm is used:
//! a) "Different" pixels are groupped and checked on "one-pixel width line".
//! indeed, the pixels may represent not a line, but any curve.
//! But the width of this curve should be not more than a pixel.
//! This group of pixels become a candidate to be ignored because of boundary effect.
//! b) The group of pixels is checked on belonging to a "shape".
//! Neighbour pixels are checked from the reference image.
//! This test confirms a fact that the group of pixels belongs to a shape and
//! represent a boundary of the shape.
//! In this case the whole group of pixels is ignored (considered as same).
//! Otherwise, the group of pixels may represent a geometrical curve in the viewer 3D
//! and should be considered as "different".
class Image_Diff : public Standard_Transient
{
public:
//! An empty constructor. Init() should be called for initialization.
Standard_EXPORT Image_Diff();
//! Desctructor.
Standard_EXPORT virtual ~Image_Diff();
//! Initialize algorithm by two images.
//! @return false if images has different or unsupported pixel format.
Standard_EXPORT Standard_Boolean Init (const Handle(Image_PixMap)& theImageRef,
const Handle(Image_PixMap)& theImageNew,
const Standard_Boolean theToBlackWhite = Standard_False);
//! Initialize algorithm by two images (will be loaded from files).
//! @return false if images couldn't be opened or their format is unsupported.
Standard_EXPORT Standard_Boolean Init (const TCollection_AsciiString& theImgPathRef,
const TCollection_AsciiString& theImgPathNew,
const Standard_Boolean theToBlackWhite = Standard_False);
//! Color tolerance for equality check. Should be within range 0..1:
//! Corresponds to a difference between white and black colors (maximum difference).
//! By default, the tolerance is equal to 0 thus equality check will return false for any different colors.
Standard_EXPORT void SetColorTolerance (const Standard_Real theTolerance);
//! Color tolerance for equality check.
Standard_EXPORT Standard_Real ColorTolerance() const;
//! Sets taking into account (ignoring) a "border effect" on comparison of images.
//! The border effect is caused by a border of shaded shapes in the viewer 3d.
//! Triangles of this area are located at about 0 or 90 degrees to the user.
//! Therefore, they deflect light differently according to implementation of a video card driver.
//! This flag allows to detect such a "border" area and skip it from comparison of images.
//! Filter turned OFF by default.
Standard_EXPORT void SetBorderFilterOn (const Standard_Boolean theToIgnore);
//! Returns a flag of taking into account (ignoring) a border effect in comparison of images.
Standard_EXPORT Standard_Boolean IsBorderFilterOn() const;
//! Compares two images. It returns a number of different pixels (or groups of pixels).
//! It returns -1 if algorithm not initialized before.
Standard_EXPORT Standard_Integer Compare();
//! Saves a difference between two images as white pixels on black backgroud.
Standard_EXPORT Standard_Boolean SaveDiffImage (Image_PixMap& theDiffImage) const;
//! Saves a difference between two images as white pixels on black backgroud.
Standard_EXPORT Standard_Boolean SaveDiffImage (const TCollection_AsciiString& theDiffPath) const;
protected:
//! Perform border filter algorithm.
Standard_EXPORT Standard_Integer ignoreBorderEffect();
//! Release dynamically allocated memory.
Standard_EXPORT void releaseGroupsOfDiffPixels();
protected:
typedef NCollection_List<TColStd_MapOfInteger* > ListOfMapOfInteger;
Handle(Image_PixMap) myImageRef; //!< reference image to compare (from)
Handle(Image_PixMap) myImageNew; //!< new image to compare (to)
Standard_Real myColorTolerance; //!< tolerance for equality check (0..1, 0 - any not equal, 1 - opposite colors)
Standard_Boolean myIsBorderFilterOn; //!< perform algorithm with border effect filter
ListOfMapOfInteger myGroupsOfDiffPixels;
NCollection_Vector<Standard_Size> myDiffPixels; //!< different pixels (position packed into integer)
TColStd_MapOfInteger myLinearGroups;
public:
DEFINE_STANDARD_RTTI(Image_Diff) // Type definition
};
DEFINE_STANDARD_HANDLE(Image_Diff, Standard_Transient)
#endif // _Image_Diff_H__

View File

@ -1,147 +0,0 @@
-- Created on: 2010-09-16
-- Created by: KGV
-- Copyright (c) 2010-2012 OPEN CASCADE SAS
--
-- The content of this file is subject to the Open CASCADE Technology Public
-- License Version 6.5 (the "License"). You may not use the content of this file
-- except in compliance with the License. Please obtain a copy of the License
-- at http://www.opencascade.org and read it completely before using this file.
--
-- The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-- main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
--
-- The Original Code and all software distributed under the License is
-- distributed on an "AS IS" basis, without warranty of any kind, and the
-- Initial Developer hereby disclaims all such warranties, including without
-- limitation, any warranties of merchantability, fitness for a particular
-- purpose or non-infringement. Please see the License for the specific terms
-- and conditions governing the rights and limitations under the License.
class PixMap from Image
---Version:
---Purpose: This class defines a system-independent bitmap
---Keywords: Bitmap, Pixmap
inherits
PixMap from Aspect
uses
Handle from Aspect,
TypeOfImage from Image,
HPrivateImage from Image,
CRawBufferData from Image,
Color from Quantity,
Parameter from Quantity
raises
PixmapDefinitionError from Aspect,
PixmapError from Aspect
is
Create ( theWidth, theHeight : Integer from Standard;
theType : TypeOfImage from Image )
returns mutable PixMap from Image
raises PixmapDefinitionError from Aspect;
---Level: Public
---Purpose:
-- Allocate the bitmap with requested dimensions.
-- Allowed image types:
-- - Image_TOI_RGB (color image, 1 byte per component);
-- - Image_TOI_RGBA (color image with alpha channel);
-- - Image_TOI_RGBF (color image, 1 float per component);
-- - Image_TOI_RGBAF (color image with alpha channel);
-- - Image_TOI_FLOAT (grey image, 1 float per pixel).
Create ( theDataPtr : PByte from Standard;
theWidth, theHeight : Integer from Standard;
thePitch : Integer from Standard;
theBitsPerPixel : Integer from Standard;
theIsTopDown : Boolean from Standard )
returns mutable PixMap from Image
raises PixmapDefinitionError from Aspect;
---Level: Public
---Purpose:
-- Create a bitmap by copying an existing buffer.
---------------------------------------------------
-- Category: Methods to modify the class definition
---------------------------------------------------
Destroy ( me : mutable )
---Level: Advanced
---Purpose:
-- Destroies the Bitmap
---C++: alias ~
---Trigger: Raises if Bitmap is not defined properly
raises PixmapError from Aspect is virtual;
Dump ( me;
theFilename : CString from Standard;
theGammaCorr : Real from Standard = 1.0 )
returns Boolean from Standard
---Level: Advanced
---Purpose:
-- Dumps the Bitmap to an image file with
-- an optional gamma correction value
-- and returns TRUE if the dump occurs normaly.
raises PixmapError from Aspect is virtual;
----------------------------
-- Category: Inquire methods
----------------------------
PixmapID ( me ) returns Handle from Aspect is virtual;
---Level: Advanced
---Purpose:
-- Returns NULL handle
---Category: Inquire methods
----------------------------
-- Category: Access methods
----------------------------
AccessBuffer ( me : in;
theBufferInfo : in out CRawBufferData from Image )
is static;
---Purpose:
-- Fill the structure for low-level access to the bitmap data.
-- It is up to you to interpret these bytes correctly!
-- Important notice: image stored upside-down in the memory,
-- first image row is an last scanline in
-- the memory buffer.
-- If image was created with type Image_TOI_FLOAT buffer
-- format will be set to TDepthComponent. You can override
-- this field with another one-channel buffer format because
-- it useless for bitmap definition.
PixelColor ( me : in;
theX, theY : in Integer from Standard )
returns Color from Quantity
is virtual;
---Purpose:
-- Returns the pixel color. This function is relatively slow,
-- use AccessBuffer() instead for stream operations.
-- Note that this function convert input theY coordinate
-- to count off from top of an image (while in memory it stored
-- upside-down).
PixelColor ( me : in;
theX, theY : in Integer from Standard;
theAlpha : out Parameter from Quantity )
returns Color from Quantity;
---Purpose:
-- Returns the pixel color. This function is relatively slow,
-- use AccessBuffer() instead for stream operations.
-- theAlpha argument is set to color intensity (0 - transparent, 1 - opaque)
-- Note that this function convert input theY coordinate
-- to count off from top of an image (while in memory it stored
-- upside-down).
fields
myImage : HPrivateImage from Image is protected;
end PixMap;

View File

@ -1,6 +1,6 @@
// Created on: 2010-09-16
// Created by: KGV
// Copyright (c) 2010-2012 OPEN CASCADE SAS
// Created on: 2012-07-18
// Created by: Kirill GAVRILOV
// Copyright (c) 2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
@ -17,414 +17,209 @@
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <Image_PixMap.hxx>
#ifndef _MSC_VER
#include <mm_malloc.h>
#endif
#ifdef HAVE_FREEIMAGE
#include <FreeImagePlus.h>
#include <Image_PixMap.ixx>
/* OCC22216 NOTE: linker dependency can be switched off by undefining macro */
#ifdef _MSC_VER
#pragma comment( lib, "FreeImage.lib" )
#pragma comment( lib, "FreeImagePlus.lib" )
#endif
template<typename TypePtr>
inline TypePtr MemAllocAligned (const Standard_Size& theBytesCount,
const Standard_Size& theAlign = 16)
{
#if defined(_MSC_VER)
return (TypePtr )_aligned_malloc (theBytesCount, theAlign);
#else
#include <Image_PixMap.ixx>
#include <fstream>
#if (defined(BYTE_ORDER) && BYTE_ORDER==BIG_ENDIAN) || \
(defined(__BYTE_ORDER) && __BYTE_ORDER==__BIG_ENDIAN) || \
defined(__BIG_ENDIAN__)
#define THE_BIGENDIAN
#endif
// dummy class which can only dump to PPM format
class fipImage
{
public:
typedef struct tagRGBQuad {
#ifndef THE_BIGENDIAN
Standard_Byte rgbBlue;
Standard_Byte rgbGreen;
Standard_Byte rgbRed;
#else
Standard_Byte rgbRed;
Standard_Byte rgbGreen;
Standard_Byte rgbBlue;
#endif
Standard_Byte rgbReserved;
} RGBQuad_t;
public:
fipImage()
: myDataPtr(NULL),
mySizeX(0),
mySizeY(0),
myBytesPerLine(0),
myBytesPerPixel(3)
{
//
}
fipImage (const Standard_Integer theSizeX, const Standard_Integer theSizeY,
const Standard_Integer theBytesPerLine = 0, const Standard_Integer theBytesPerPixel = 3)
: myDataPtr(NULL),
mySizeX (theSizeX),
mySizeY (theSizeY),
myBytesPerLine (theBytesPerLine),
myBytesPerPixel (theBytesPerPixel)
{
if (myBytesPerLine == 0)
{
myBytesPerLine = mySizeX * myBytesPerPixel;
}
myDataPtr = new Standard_Byte[myBytesPerLine * mySizeY];
}
~fipImage()
{
delete[] myDataPtr;
}
Standard_Integer getHeight() const
{
return mySizeY;
}
Standard_Integer getWidth() const
{
return mySizeX;
}
Standard_Integer getBytesPerPixel() const
{
return myBytesPerPixel;
}
Standard_Integer getBytesPerLine() const
{
return myBytesPerLine;
}
Standard_Byte* getData() const
{
return myDataPtr;
}
Standard_Byte* getScanLine (const Standard_Integer theRow) const
{
return &myDataPtr[theRow * myBytesPerLine];
}
Quantity_Color getPixelColor (const Standard_Integer theCol,
const Standard_Integer theRow,
Quantity_Parameter& theAlpha) const
{
RGBQuad_t* aPixel = (RGBQuad_t* )&getScanLine (theRow)[theCol * myBytesPerPixel];
theAlpha = (myBytesPerPixel > 3) ? (Standard_Real (aPixel->rgbReserved) / 255.0) : 1.0;
return Quantity_Color (Standard_Real (aPixel->rgbRed) / 255.0,
Standard_Real (aPixel->rgbGreen) / 255.0,
Standard_Real (aPixel->rgbBlue) / 255.0,
Quantity_TOC_RGB);
}
Standard_Boolean savePPM (const Standard_CString theFileName) const
{
// Open file
FILE* pFile = fopen (theFileName, "wb");
if (pFile == NULL)
{
return Standard_False;
}
// Write header
fprintf (pFile, "P6\n%d %d\n255\n", mySizeX, mySizeY);
// Write pixel data
Standard_Byte* aScanLine;
RGBQuad_t* aPixel;
// image stored upside-down
for (Standard_Integer aRow = mySizeY - 1; aRow >= 0; --aRow)
{
aScanLine = getScanLine (aRow);
for (Standard_Integer aCol = 0; aCol < mySizeX; ++aCol)
{
aPixel = (RGBQuad_t* )&aScanLine[aCol * myBytesPerPixel];
fwrite (&aPixel->rgbRed, 1, 1, pFile);
fwrite (&aPixel->rgbGreen, 1, 1, pFile);
fwrite (&aPixel->rgbBlue, 1, 1, pFile);
}
}
// Close file
fclose (pFile);
return Standard_True;
}
Standard_Integer getMaxRowAligmentBytes() const
{
Standard_Integer aDeltaBytes = myBytesPerLine - myBytesPerPixel * mySizeX;
for (Standard_Integer anAligment = 16; anAligment > 1; anAligment /= 2)
{
if (isRowAlignedTo (anAligment, aDeltaBytes))
{
return anAligment;
}
}
return 1;
}
private:
Standard_Boolean isRowAlignedTo (const Standard_Integer theAligmentBytes,
const Standard_Integer theDeltaBytes) const
{
return (theDeltaBytes < theAligmentBytes) &&
((myBytesPerLine % theAligmentBytes) == 0);
}
private:
Standard_Byte* myDataPtr;
Standard_Integer mySizeX;
Standard_Integer mySizeY;
Standard_Integer myBytesPerLine;
Standard_Integer myBytesPerPixel;
};
return (TypePtr ) _mm_malloc (theBytesCount, theAlign);
#endif
}
#include <gp.hxx>
#include <TCollection_AsciiString.hxx>
//=======================================================================
//function : Image_PixMap
//purpose :
//=======================================================================
Image_PixMap::Image_PixMap (const Standard_Integer theWidth,
const Standard_Integer theHeight,
const Image_TypeOfImage theType)
: Aspect_PixMap (theWidth, theHeight, 1),
myImage()
inline void MemFreeAligned (void* thePtrAligned)
{
#ifdef HAVE_FREEIMAGE
FREE_IMAGE_TYPE aFIType = FIT_UNKNOWN;
int aBitsPerPixel = 0;
switch (theType)
{
case Image_TOI_RGBA:
aFIType = FIT_BITMAP;
aBitsPerPixel = 32;
break;
case Image_TOI_RGBF:
aFIType = FIT_RGBF;
aBitsPerPixel = 96;
break;
case Image_TOI_RGBAF:
aFIType = FIT_RGBAF;
aBitsPerPixel = 128;
break;
case Image_TOI_FLOAT:
aFIType = FIT_FLOAT;
aBitsPerPixel = 32;
break;
case Image_TOI_RGB:
default:
aFIType = FIT_BITMAP;
aBitsPerPixel = 24;
break;
}
myImage = new fipImage (aFIType, theWidth, theHeight, aBitsPerPixel);
#if defined(_MSC_VER)
_aligned_free (thePtrAligned);
#else
Standard_Integer aBytesPerPixel = 0;
switch (theType)
{
case Image_TOI_RGBAF:
std::cerr << "Float formats not supported\n";
case Image_TOI_RGBA:
aBytesPerPixel = 4;
break;
case Image_TOI_RGBF:
case Image_TOI_FLOAT:
std::cerr << "Float formats not supported\n";
case Image_TOI_RGB:
default:
aBytesPerPixel = 3;
break;
}
myImage = new fipImage (theWidth, theHeight, 0, aBytesPerPixel);
//
_mm_free (thePtrAligned);
#endif
}
//=======================================================================
//function : Image_PixMap
//purpose :
//=======================================================================
Image_PixMap::Image_PixMap (const Standard_PByte theDataPtr,
const Standard_Integer theWidth, const Standard_Integer theHeight,
const Standard_Integer thePitch, const Standard_Integer theBitsPerPixel,
const Standard_Boolean theIsTopDown)
: Aspect_PixMap (theWidth, theHeight, 1),
myImage (new fipImage())
{
#ifdef HAVE_FREEIMAGE
*myImage = FreeImage_ConvertFromRawBits (theDataPtr,
theWidth, theHeight,
thePitch, theBitsPerPixel,
0, 0, 0,
theIsTopDown);
if (theBitsPerPixel != 24)
{
myImage->convertTo24Bits();
}
#else
myImage = new fipImage (theWidth, theHeight, thePitch, theBitsPerPixel / 8);
Standard_Integer aRowStart = !theIsTopDown ? 0 : (theHeight - 1);
Standard_Integer aRowDelta = !theIsTopDown ? 1 : -1;
for (Standard_Integer aRowFrom (aRowStart), aRowTo (0);
aRowFrom >= 0 && aRowFrom < theHeight;
aRowFrom += aRowDelta, ++aRowTo)
{
memcpy (myImage->getScanLine (aRowTo),
&theDataPtr[aRowFrom * thePitch],
myImage->getBytesPerLine());
}
#endif
}
//=======================================================================
//function : Destroy
//purpose :
//=======================================================================
void Image_PixMap::Destroy()
{
myImage = Image_HPrivateImage();
}
//=======================================================================
//function : Dump
//purpose :
//=======================================================================
Standard_Boolean Image_PixMap::Dump (const Standard_CString theFilename,
const Standard_Real theGammaCorr) const
{
#ifdef HAVE_FREEIMAGE
FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilename (theFilename);
if (anImageFormat == FIF_UNKNOWN)
{
std::cerr << "Image_PixMap, image format doesn't supported!\n";
return Standard_False;
}
Standard_Boolean isCopied = Standard_False;
Image_HPrivateImage anImageToDump = myImage;
if (Abs (theGammaCorr - 1.0) > gp::Resolution())
{
if (!isCopied)
{
isCopied = Standard_True;
anImageToDump = new fipImage (*myImage);
}
anImageToDump->adjustGamma (theGammaCorr);
}
switch (anImageFormat)
{
case FIF_GIF:
if (!isCopied)
{
isCopied = Standard_True;
anImageToDump = new fipImage (*myImage);
}
// need convertion to image with pallete
anImageToDump->colorQuantize (FIQ_NNQUANT);
break;
case FIF_EXR:
if (myImage->getImageType() == FIT_BITMAP)
{
if (!isCopied)
{
isCopied = Standard_True;
anImageToDump = new fipImage (*myImage);
}
anImageToDump->convertToType (FIT_RGBF);
}
break;
default:
if (myImage->getImageType() != FIT_BITMAP)
{
if (!isCopied)
{
isCopied = Standard_True;
anImageToDump = new fipImage (*myImage);
}
anImageToDump->convertToType (FIT_BITMAP);
}
break;
}
return anImageToDump->save (theFilename);
#else
return myImage->savePPM (theFilename);
#endif
}
Aspect_Handle Image_PixMap::PixmapID() const
{
return Aspect_Handle();
}
void Image_PixMap::AccessBuffer (Image_CRawBufferData& theBuffer) const
{
theBuffer.widthPx = myImage->getWidth();
theBuffer.heightPx = myImage->getHeight();
#ifdef HAVE_FREEIMAGE
theBuffer.rowAligmentBytes = 4; // 32 bits according to FreeImage documentation
switch (myImage->getImageType())
{
case FIT_FLOAT:
theBuffer.format = TDepthComponent;
theBuffer.type = TFloat;
break;
case FIT_RGBF:
theBuffer.format = TRGB;
theBuffer.type = TFloat;
break;
case FIT_RGBAF:
theBuffer.format = TRGBA;
theBuffer.type = TFloat;
break;
case FIT_BITMAP:
default:
#if defined(FREEIMAGE_BIGENDIAN)
theBuffer.format = (myImage->getColorType() == FIC_RGBALPHA) ? TRGBA : TRGB;
#else
theBuffer.format = (myImage->getColorType() == FIC_RGBALPHA) ? TBGRA : TBGR;
#endif
theBuffer.type = TUByte;
break;
}
theBuffer.dataPtr = myImage->accessPixels();
#else
theBuffer.rowAligmentBytes = myImage->getMaxRowAligmentBytes();
theBuffer.format = (myImage->getBytesPerPixel() == 4) ? TBGRA : TBGR;
theBuffer.type = TUByte;
theBuffer.dataPtr = myImage->getData();
#endif
}
IMPLEMENT_STANDARD_HANDLE (Image_PixMap, Standard_Transient)
IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap, Standard_Transient)
// =======================================================================
// function : PixelColor
// function : Image_PixMap
// purpose :
// =======================================================================
Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
const Standard_Integer theY) const
Image_PixMap::Image_PixMap()
: myImgFormat (Image_PixMap::ImgGray),
myIsOwnPointer (true)
{
Quantity_Parameter aDummy;
return PixelColor (theX, theY, aDummy);
memset (&myData, 0, sizeof(myData));
myData.mySizeBPP = 1;
myData.myTopToDown = 1;
setFormat (Image_PixMap::ImgGray);
}
// =======================================================================
// function : ~Image_PixMap
// purpose :
// =======================================================================
Image_PixMap::~Image_PixMap()
{
Clear();
}
Standard_Size Image_PixMap::SizePixelBytes (const Image_PixMap::ImgFormat thePixelFormat)
{
switch (thePixelFormat)
{
case ImgGrayF:
return sizeof(float);
case ImgRGBAF:
case ImgBGRAF:
return sizeof(float) * 4;
case ImgRGBF:
case ImgBGRF:
return sizeof(float) * 3;
case ImgRGBA:
case ImgBGRA:
return 4;
case ImgRGB32:
case ImgBGR32:
return 4;
case ImgRGB:
case ImgBGR:
return 3;
case ImgGray:
default:
return 1;
}
}
// =======================================================================
// function : setFormat
// purpose :
// =======================================================================
void Image_PixMap::setFormat (Image_PixMap::ImgFormat thePixelFormat)
{
myImgFormat = thePixelFormat;
myData.mySizeBPP = SizePixelBytes (myImgFormat);
}
// =======================================================================
// function : setTopDown
// purpose :
// =======================================================================
void Image_PixMap::setTopDown()
{
myData.myTopRowPtr = ((myData.myTopToDown == 1 || myData.myDataPtr == NULL)
? myData.myDataPtr : (myData.myDataPtr + myData.mySizeRowBytes * (myData.mySizeY - 1)));
}
// =======================================================================
// function : InitWrapper
// purpose :
// =======================================================================
bool Image_PixMap::InitWrapper (Image_PixMap::ImgFormat thePixelFormat,
Standard_Byte* theDataPtr,
const Standard_Size theSizeX,
const Standard_Size theSizeY,
const Standard_Size theSizeRowBytes)
{
Clear (thePixelFormat);
if ((theSizeX == 0) || (theSizeY == 0) || (theDataPtr == NULL))
{
return false;
}
myData.mySizeX = theSizeX;
myData.mySizeY = theSizeY;
myData.mySizeRowBytes = (theSizeRowBytes != 0) ? theSizeRowBytes : (theSizeX * myData.mySizeBPP);
myData.myDataPtr = theDataPtr;
myIsOwnPointer = false;
setTopDown();
return true;
}
// =======================================================================
// function : InitTrash
// purpose :
// =======================================================================
bool Image_PixMap::InitTrash (Image_PixMap::ImgFormat thePixelFormat,
const Standard_Size theSizeX,
const Standard_Size theSizeY,
const Standard_Size theSizeRowBytes)
{
Clear (thePixelFormat);
if ((theSizeX == 0) || (theSizeY == 0))
{
return false;
}
myData.mySizeX = theSizeX;
myData.mySizeY = theSizeY;
myData.mySizeRowBytes = myData.mySizeX * myData.mySizeBPP;
if (theSizeRowBytes > myData.mySizeRowBytes)
{
// use argument only if it greater
myData.mySizeRowBytes = theSizeRowBytes;
}
myData.myDataPtr = MemAllocAligned<Standard_Byte*> (SizeBytes());
myIsOwnPointer = true;
setTopDown();
return myData.myDataPtr != NULL;
}
// =======================================================================
// function : InitZero
// purpose :
// =======================================================================
bool Image_PixMap::InitZero (Image_PixMap::ImgFormat thePixelFormat,
const Standard_Size theSizeX,
const Standard_Size theSizeY,
const Standard_Size theSizeRowBytes,
const Standard_Byte theValue)
{
if (!InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes))
{
return false;
}
memset (myData.myDataPtr, (int )theValue, SizeBytes());
return true;
}
// =======================================================================
// function : InitCopy
// purpose :
// =======================================================================
bool Image_PixMap::InitCopy (const Image_PixMap& theCopy)
{
if (&theCopy == this)
{
// self-copying disallowed
return false;
}
if (InitTrash (theCopy.myImgFormat, theCopy.myData.mySizeX, theCopy.myData.mySizeY, theCopy.myData.mySizeRowBytes))
{
memcpy (myData.myDataPtr, theCopy.myData.myDataPtr, theCopy.SizeBytes());
return true;
}
return false;
}
// =======================================================================
// function : Clear
// purpose :
// =======================================================================
void Image_PixMap::Clear (Image_PixMap::ImgFormat thePixelFormat)
{
if (myIsOwnPointer && (myData.myDataPtr != NULL))
{
MemFreeAligned (myData.myDataPtr);
}
myData.myDataPtr = myData.myTopRowPtr = NULL;
myIsOwnPointer = true;
myData.mySizeX = myData.mySizeY = myData.mySizeRowBytes = 0;
setFormat (thePixelFormat);
myData.myTopToDown = 1;
}
// =======================================================================
@ -435,64 +230,130 @@ Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
const Standard_Integer theY,
Quantity_Parameter& theAlpha) const
{
Standard_Integer aScanlineId = myImage->getHeight() - theY - 1;
if (theX < 0 || (unsigned int )theX >= (unsigned int )myImage->getWidth() ||
theY < 0 || (unsigned int )theY >= (unsigned int )myImage->getHeight())
if (IsEmpty() ||
theX < 0 || (Standard_Size )theX >= myData.mySizeX ||
theY < 0 || (Standard_Size )theY >= myData.mySizeY)
{
theAlpha = 0.0; // transparent
return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
}
#ifdef HAVE_FREEIMAGE
else if (myImage->getImageType() == FIT_BITMAP)
switch (myImgFormat)
{
RGBQUAD aValue; memset (&aValue, 0, sizeof(aValue));
myImage->getPixelColor (theX, aScanlineId, &aValue);
theAlpha = (myImage->getColorType() == FIC_RGBALPHA) ? (Standard_Real (aValue.rgbReserved) / 255.0) : 1.0;
return Quantity_Color (Standard_Real (aValue.rgbRed) / 255.0,
Standard_Real (aValue.rgbGreen) / 255.0,
Standard_Real (aValue.rgbBlue) / 255.0,
Quantity_TOC_RGB);
}
else
{
switch (myImage->getImageType())
case ImgGrayF:
{
case FIT_FLOAT:
{
float* aScanLine = (float* )myImage->getScanLine (aScanlineId);
Quantity_Parameter aValue = Quantity_Parameter (aScanLine[theX]);
theAlpha = 1.0; // opaque
return Quantity_Color (aValue, aValue, aValue, Quantity_TOC_RGB);
}
case FIT_RGBF:
{
FIRGBF* aScanLine = (FIRGBF* )myImage->getScanLine (aScanlineId);
FIRGBF* aPixel = &aScanLine[theX];
theAlpha = 1.0; // opaque
return Quantity_Color (Quantity_Parameter (aPixel->red),
Quantity_Parameter (aPixel->green),
Quantity_Parameter (aPixel->blue),
Quantity_TOC_RGB);
}
case FIT_RGBAF:
{
FIRGBAF* aScanLine = (FIRGBAF* )myImage->getScanLine (aScanlineId);
FIRGBAF* aPixel = &aScanLine[theX];
theAlpha = aPixel->alpha;
return Quantity_Color (Quantity_Parameter (aPixel->red),
Quantity_Parameter (aPixel->green),
Quantity_Parameter (aPixel->blue),
Quantity_TOC_RGB);
}
default:
{
// not supported image type
theAlpha = 0.0; // transparent
return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
}
const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
theAlpha = 1.0; // opaque
return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel)),
Quantity_Parameter (Standard_Real (aPixel)),
Quantity_Parameter (Standard_Real (aPixel)),
Quantity_TOC_RGB);
break;
}
case ImgRGBAF:
{
const Image_ColorRGBAF& aPixel = Value<Image_ColorRGBAF> (theY, theX);
theAlpha = aPixel.a();
return Quantity_Color (Quantity_Parameter (aPixel.r()),
Quantity_Parameter (aPixel.g()),
Quantity_Parameter (aPixel.b()),
Quantity_TOC_RGB);
}
case ImgBGRAF:
{
const Image_ColorBGRAF& aPixel = Value<Image_ColorBGRAF> (theY, theX);
theAlpha = aPixel.a();
return Quantity_Color (Quantity_Parameter (aPixel.r()),
Quantity_Parameter (aPixel.g()),
Quantity_Parameter (aPixel.b()),
Quantity_TOC_RGB);
}
case ImgRGBF:
{
const Image_ColorRGBF& aPixel = Value<Image_ColorRGBF> (theY, theX);
theAlpha = 1.0; // opaque
return Quantity_Color (Quantity_Parameter (aPixel.r()),
Quantity_Parameter (aPixel.g()),
Quantity_Parameter (aPixel.b()),
Quantity_TOC_RGB);
}
case ImgBGRF:
{
const Image_ColorBGRF& aPixel = Value<Image_ColorBGRF> (theY, theX);
theAlpha = 1.0; // opaque
return Quantity_Color (Quantity_Parameter (aPixel.r()),
Quantity_Parameter (aPixel.g()),
Quantity_Parameter (aPixel.b()),
Quantity_TOC_RGB);
}
case ImgRGBA:
{
const Image_ColorRGBA& aPixel = Value<Image_ColorRGBA> (theY, theX);
theAlpha = Standard_Real (aPixel.a()) / 255.0;
return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
Quantity_TOC_RGB);
}
case ImgBGRA:
{
const Image_ColorBGRA& aPixel = Value<Image_ColorBGRA> (theY, theX);
theAlpha = Standard_Real (aPixel.a()) / 255.0;
return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
Quantity_TOC_RGB);
}
case ImgRGB32:
{
const Image_ColorRGB32& aPixel = Value<Image_ColorRGB32> (theY, theX);
theAlpha = 1.0; // opaque
return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
Quantity_TOC_RGB);
}
case ImgBGR32:
{
const Image_ColorBGR32& aPixel = Value<Image_ColorBGR32> (theY, theX);
theAlpha = 1.0; // opaque
return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
Quantity_TOC_RGB);
}
case ImgRGB:
{
const Image_ColorRGB& aPixel = Value<Image_ColorRGB> (theY, theX);
theAlpha = 1.0; // opaque
return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
Quantity_TOC_RGB);
}
case ImgBGR:
{
const Image_ColorBGR& aPixel = Value<Image_ColorBGR> (theY, theX);
theAlpha = 1.0; // opaque
return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
Quantity_TOC_RGB);
}
case ImgGray:
{
const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
theAlpha = 1.0; // opaque
return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel) / 255.0),
Quantity_Parameter (Standard_Real (aPixel) / 255.0),
Quantity_Parameter (Standard_Real (aPixel) / 255.0),
Quantity_TOC_RGB);
}
default:
{
// not supported image type
theAlpha = 0.0; // transparent
return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
}
}
#else
return myImage->getPixelColor (theX, aScanlineId, theAlpha);
#endif
}

294
src/Image/Image_PixMap.hxx Normal file
View File

@ -0,0 +1,294 @@
// Created on: 2012-07-18
// Created by: Kirill GAVRILOV
// Copyright (c) 2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#ifndef _Image_PixMap_H__
#define _Image_PixMap_H__
#include <Image_PixMapData.hxx>
#include <Standard_Transient.hxx>
#include <Quantity_Color.hxx>
//! Class represents packed image plane.
class Image_PixMap : public Standard_Transient
{
public:
//! This enumeration define packed image plane formats
typedef enum tagFormat {
ImgUNKNOWN = 0, //!< unsupported or unknown format
ImgGray = 1, //!< 1 byte per pixel
ImgRGB, //!< 3 bytes packed RGB image plane
ImgBGR, //!< same as RGB but with different components order
ImgRGB32, //!< 4 bytes packed RGB image plane (1 extra byte for alignment, may have undefined value)
ImgBGR32, //!< same as RGB but with different components order
ImgRGBA, //!< 4 bytes packed RGBA image plane
ImgBGRA, //!< same as RGBA but with different components order
ImgGrayF, //!< 1 float (4-bytes) per pixel (1-component plane)
ImgRGBF, //!< 3 floats (12-bytes) RGB image plane
ImgBGRF, //!< same as RGBF but with different components order
ImgRGBAF, //!< 4 floats (16-bytes) RGBA image plane
ImgBGRAF, //!< same as RGBAF but with different components order
} ImgFormat;
//! Determine Big-Endian at runtime
static inline bool IsBigEndianHost()
{
union { int myInt; char myChar[sizeof(int)]; } aUnion;
aUnion.myInt = 1;
return !aUnion.myChar[0];
}
public: // high-level API
inline ImgFormat Format() const
{
return myImgFormat;
}
//! @return image width in pixels
inline Standard_Size Width() const
{
return myData.mySizeX;
}
//! @return image height in pixels
inline Standard_Size Height() const
{
return myData.mySizeY;
}
//! @return image width in pixels
inline Standard_Size SizeX() const
{
return myData.mySizeX;
}
//! @return image height in pixels
inline Standard_Size SizeY() const
{
return myData.mySizeY;
}
//! @return width / height.
inline Standard_Real Ratio() const
{
return (myData.mySizeY > 0) ? (Standard_Real(myData.mySizeX) / Standard_Real(myData.mySizeY)) : 1.0;
}
//! @return true if data is NULL.
bool IsEmpty() const
{
return myData.myDataPtr == NULL;
}
//! Empty constructor. Initialize the NULL image plane.
Standard_EXPORT Image_PixMap();
//! Destructor
Standard_EXPORT virtual ~Image_PixMap();
//! Returns the pixel color. This function is relatively slow.
//! @param theX - column index from left
//! @param theY - row index from top
//! @return the pixel color
inline Quantity_Color PixelColor (const Standard_Integer theX,
const Standard_Integer theY) const
{
Quantity_Parameter aDummy;
return PixelColor (theX, theY, aDummy);
}
//! Returns the pixel color. This function is relatively slow.
//! theAlpha argument is set to color intensity (0 - transparent, 1 - opaque)
Standard_EXPORT Quantity_Color PixelColor (const Standard_Integer theX,
const Standard_Integer theY,
Quantity_Parameter& theAlpha) const;
//! Initialize image plane as wrapper over alien data.
//! Data will not be copied! Notice that caller should ensure
//! that data pointer will not be released during this wrapper lifetime.
//! You may call InitCopy() to perform data copying.
Standard_EXPORT virtual bool InitWrapper (ImgFormat thePixelFormat,
Standard_Byte* theDataPtr,
const Standard_Size theSizeX,
const Standard_Size theSizeY,
const Standard_Size theSizeRowBytes = 0);
//! Initialize image plane with required dimensions.
//! Memory will be left uninitialized (performance trick).
Standard_EXPORT virtual bool InitTrash (ImgFormat thePixelFormat,
const Standard_Size theSizeX,
const Standard_Size theSizeY,
const Standard_Size theSizeRowBytes = 0);
//! Initialize by copying data.
//! If you want to copy alien data you should create wrapper using InitWrapper() before.
Standard_EXPORT virtual bool InitCopy (const Image_PixMap& theCopy);
//! Initialize image plane with required dimensions.
//! Buffer will be zeroed (black color for most formats).
Standard_EXPORT bool InitZero (ImgFormat thePixelFormat,
const Standard_Size theSizeX,
const Standard_Size theSizeY,
const Standard_Size theSizeRowBytes = 0,
const Standard_Byte theValue = 0);
//! Method correctly deallocate internal buffer.
Standard_EXPORT virtual void Clear (ImgFormat thePixelFormat = ImgGray);
public: // low-level API for batch-processing (pixels reading / comparison / modification)
//! Returns true if image data stored from Top to the Down (default).
//! Some external APIs can return bottom-up data instead
//! (topmost scanlines starts from the bottom in memory).
//! Notice that access methods within this class automatically
//! convert input row-index to apply this flag!
//! You should use this flag only if interconnect with alien APIs and buffers.
//! @return true if image data is top-down.
inline bool IsTopDown() const
{
return myData.myTopToDown == 1;
}
//! Setup scanlines order in memory - top-down or bottom-up.
//! Drawers should explicitly specify this value if current state IsTopDown() was ignored!
//! @param theIsTopDown - top-down flag.
inline void SetTopDown (bool theIsTopDown)
{
myData.myTopToDown = (theIsTopDown ? 1 : Standard_Size(-1));
setTopDown();
}
//! Returns +1 if scanlines ordered in Top->Down order in memory and -1 otherwise.
//! @return scanline increment for Top->Down iteration
inline Standard_Size TopDownInc() const
{
return myData.myTopToDown;
}
//! @return data pointer for low-level operations (copying entire buffer, parsing with extra tools etc.).
inline const Standard_Byte* Data() const
{
return myData.myDataPtr;
}
//! @return data pointer for low-level operations (copying entire buffer, parsing with extra tools etc.).
inline Standard_Byte* ChangeData()
{
return myData.myDataPtr;
}
//! @return data pointer to requested row (first column).
inline const Standard_Byte* Row (const Standard_Size theRow) const
{
return myData.Row (theRow);
}
//! @return data pointer to requested row (first column).
inline Standard_Byte* ChangeRow (const Standard_Size theRow)
{
return myData.ChangeRow (theRow);
}
//! @return bytes reserved for one pixel (may include extra bytes for alignment).
inline Standard_Size SizePixelBytes() const
{
return myData.mySizeBPP;
}
//! @return bytes reserved for one pixel (may include extra bytes for alignment).
static Standard_Size SizePixelBytes (const Image_PixMap::ImgFormat thePixelFormat);
//! @return bytes reserved per row.
//! Could be larger than needed to store packed row (extra bytes for alignment etc.).
inline Standard_Size SizeRowBytes() const
{
return myData.mySizeRowBytes;
}
//! @return the extra bytes in the row.
inline Standard_Size RowExtraBytes() const
{
return myData.mySizeRowBytes - myData.mySizeX * myData.mySizeBPP;
}
//! Compute the maximal row alignment for current row size.
//! @return maximal row alignment in bytes (up to 16 bytes).
inline Standard_Size MaxRowAligmentBytes() const
{
return myData.MaxRowAligmentBytes();
}
inline Standard_Size SizeBytes() const
{
return myData.SizeBytes();
}
//! Access image buffer for write/read operations with specified color type.
template <typename ColorType_t>
inline Image_PixMapData<ColorType_t>& EditData()
{
return *(Image_PixMapData<ColorType_t>* )&myData;
}
//! Access image buffer for read operations with specified color type.
template <typename ColorType_t>
inline const Image_PixMapData<ColorType_t>& ReadData() const
{
return *(Image_PixMapData<ColorType_t>* )&myData;
}
//! Access image pixel with specified color type.
template <typename ColorType_t>
inline const ColorType_t& Value (const Standard_Size theRow,
const Standard_Size theCol) const
{
return ((Image_PixMapData<ColorType_t>* )&myData)->Value (theRow, theCol);
}
protected:
//! Setup pixel format
Standard_EXPORT void setFormat (ImgFormat thePixelFormat);
//! Auxiliary method to setup myTopRowPtr
Standard_EXPORT void setTopDown();
protected:
Image_PixMapData<Standard_Byte> myData;
ImgFormat myImgFormat; //!< pixel format
bool myIsOwnPointer; //!< if data was allocated by this class - flag is true
private:
//! Copying allowed only within Handles
Image_PixMap (const Image_PixMap& );
Image_PixMap& operator= (const Image_PixMap& );
public:
DEFINE_STANDARD_RTTI(Image_PixMap) // Type definition
};
DEFINE_STANDARD_HANDLE(Image_PixMap, Standard_Transient)
#endif // _Image_PixMap_H__

View File

@ -0,0 +1,113 @@
// Created on: 2012-07-18
// Created by: Kirill GAVRILOV
// Copyright (c) 2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#ifndef _Image_PixMapData_H__
#define _Image_PixMapData_H__
#include <Image_Color.hxx>
//! POD template structure to access image buffer
template<typename ColorType_t>
struct Image_PixMapData
{
//! @return data pointer for low-level operations (copying entire buffer, parsing with extra tools etc.).
inline const ColorType_t* Data() const
{
return (const ColorType_t* )myDataPtr;
}
//! @return data pointer for low-level operations (copying entire buffer, parsing with extra tools etc.).
inline ColorType_t* ChangeData()
{
return (ColorType_t* )myDataPtr;
}
//! @return data pointer to requested row (first column).
inline const ColorType_t* Row (const Standard_Size theRow) const
{
return (ColorType_t* )(myTopRowPtr + mySizeRowBytes * theRow * myTopToDown);
}
//! @return data pointer to requested row (first column).
inline ColorType_t* ChangeRow (const Standard_Size theRow)
{
return (ColorType_t* )(myTopRowPtr + mySizeRowBytes * theRow * myTopToDown);
}
//! @return data pointer to requested position.
inline const ColorType_t& Value (const Standard_Size theRow,
const Standard_Size theCol) const
{
return *(const ColorType_t* )(myTopRowPtr + mySizeRowBytes * theRow * myTopToDown + mySizeBPP * theCol);
}
//! @return data pointer to requested position.
inline ColorType_t& ChangeValue (const Standard_Size theRow,
const Standard_Size theCol)
{
return *(ColorType_t* )(myTopRowPtr + mySizeRowBytes * theRow * myTopToDown + mySizeBPP * theCol);
}
//! Compute the maximal row alignment for current row size.
//! @return maximal row alignment in bytes (up to 16 bytes).
inline Standard_Size MaxRowAligmentBytes() const
{
Standard_Size anAlignment = 2;
for (; anAlignment <= 16; anAlignment <<= 1)
{
if ((mySizeRowBytes % anAlignment) != 0 || (Standard_Size(myDataPtr) % anAlignment) != 0)
{
return (anAlignment >> 1);
}
}
return anAlignment;
}
//! @return bytes allocated for the whole image plane.
inline Standard_Size SizeBytes() const
{
return mySizeRowBytes * mySizeY;
}
//! @return image width in pixels
inline Standard_Size SizeX() const
{
return mySizeX;
}
//! @return image height in pixels
inline Standard_Size SizeY() const
{
return mySizeY;
}
public:
Standard_Byte* myDataPtr; //!< pointer to the data
Standard_Byte* myTopRowPtr; //!< pointer to the topmost row (depending on scanlines order in memory)
Standard_Size mySizeBPP; //!< bytes per pixel
Standard_Size mySizeX; //!< width in pixels
Standard_Size mySizeY; //!< height in pixels
Standard_Size mySizeRowBytes; //!< number of bytes per line (in most cases equal to 3 * sizeX)
Standard_Size myTopToDown; //!< image scanlines direction in memory from Top to the Down
};
#endif // _Image_PixMapData_H__

View File

@ -11,7 +11,6 @@ InterfaceGraphic_wntio.hxx
InterfaceGraphic_cPrintf.cxx
InterfaceGraphic_Palette.c
InterfaceGraphic_PrimitiveArray.hxx
InterfaceGraphic_RawBufferData.hxx
InterfaceGraphic_telem.hxx
InterfaceGraphic_degeneration.hxx
InterfaceGraphic_tgl_all.hxx

View File

@ -1,54 +0,0 @@
// Copyright (c) 1991-1999 Matra Datavision
// Copyright (c) 1999-2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#ifndef INTERFACEGRAPHIC_RawBufferData_H
#define INTERFACEGRAPHIC_RawBufferData_H
#include <Standard.hxx>
// Most items are from GLenum, but values not equal!
typedef enum
{
TRGB,
TBGR,
TRGBA,
TBGRA,
TDepthComponent,
TRed,
TGreen,
TBlue,
TAlpha,
} TRawBufferDataFormat;
typedef enum
{
TUByte,
TFloat,
} TRawBufferDataType;
struct TRawBufferData
{
Standard_Integer widthPx;
Standard_Integer heightPx;
Standard_Integer rowAligmentBytes;
TRawBufferDataFormat format;
TRawBufferDataType type;
Standard_Address dataPtr;
};
#endif /* INTERFACEGRAPHIC_RawBufferData_H */

View File

@ -32,7 +32,6 @@
#include <Quantity_PlaneAngle.hxx>
#include <Quantity_NameOfColor.hxx>
#include <Handle_AlienImage_AlienImage.hxx>
#include <Image_CRawBufferData.hxx>
#include <Aspect_Display.hxx>
#include <Aspect_GradientFillMethod.hxx>
@ -69,6 +68,7 @@
#include <Graphic3d_Array2OfVertex.hxx>
#include <Graphic3d_Array2OfVertexN.hxx>
#include <Graphic3d_Array2OfVertexNT.hxx>
#include <Graphic3d_BufferType.hxx>
#include <NCollection_DataMap.hxx>
class TColStd_Array1OfInteger;
@ -82,6 +82,7 @@ class Graphic3d_Vertex;
class Aspect_Array1OfEdge;
class TCollection_ExtendedString;
class AlienImage_AlienImage;
class Image_PixMap;
class TColStd_HArray1OfReal;
class Handle(OpenGl_View);
class Handle(OpenGl_Workspace);
@ -262,7 +263,9 @@ public:
//! Remove offscreen FBO <br>
Standard_EXPORT void FBORelease (const Graphic3d_CView& view, Graphic3d_PtrFrameBuffer& fboPtr);
//! Dump active rendering buffer into specified memory buffer. <br>
Standard_EXPORT Standard_Boolean BufferDump (const Graphic3d_CView& view, Image_CRawBufferData& buffer);
Standard_EXPORT Standard_Boolean BufferDump (const Graphic3d_CView& theCView,
Image_PixMap& theImage,
const Graphic3d_BufferType& theBufferType);
Standard_EXPORT void SetGLLightEnabled (const Graphic3d_CView& view,const Standard_Boolean isEnabled) const;
Standard_EXPORT Standard_Boolean IsGLLightEnabled (const Graphic3d_CView& view) const;
//! Clear visualization data in graphical driver and stop <br>

View File

@ -284,72 +284,88 @@ void OpenGl_GraphicDriver::FBOChangeViewport (const Graphic3d_CView& ,
aFrameBuffer->ChangeViewport (theWidth, theHeight);
}
// OpenGL 1.2 stuff
#ifndef GL_BGR
#define GL_BGR 0x80E0
#endif
#ifndef GL_BGRA
#define GL_BGRA 0x80E1
#endif
static inline GLenum TFormatToGLEnum (const TRawBufferDataFormat theTFormat)
inline bool getDataFormat (const Image_PixMap& theData,
GLenum& thePixelFormat,
GLenum& theDataType)
{
switch (theTFormat)
thePixelFormat = GL_RGB;
theDataType = GL_UNSIGNED_BYTE;
switch (theData.Format())
{
case TRGB: return GL_RGB;
case TBGR: return GL_BGR;
case TRGBA: return GL_RGBA;
case TBGRA: return GL_BGRA;
case TDepthComponent: return GL_DEPTH_COMPONENT;
case TRed: return GL_RED;
case TGreen: return GL_GREEN;
case TBlue: return GL_BLUE;
case TAlpha: return GL_ALPHA;
default: return 0;
case Image_PixMap::ImgGray:
thePixelFormat = GL_DEPTH_COMPONENT;
theDataType = GL_UNSIGNED_BYTE;
return true;
case Image_PixMap::ImgRGB:
thePixelFormat = GL_RGB;
theDataType = GL_UNSIGNED_BYTE;
return true;
case Image_PixMap::ImgBGR:
thePixelFormat = GL_BGR;
theDataType = GL_UNSIGNED_BYTE;
return true;
case Image_PixMap::ImgRGBA:
case Image_PixMap::ImgRGB32:
thePixelFormat = GL_RGBA;
theDataType = GL_UNSIGNED_BYTE;
return true;
case Image_PixMap::ImgBGRA:
case Image_PixMap::ImgBGR32:
thePixelFormat = GL_BGRA;
theDataType = GL_UNSIGNED_BYTE;
return true;
case Image_PixMap::ImgGrayF:
thePixelFormat = GL_DEPTH_COMPONENT;
theDataType = GL_FLOAT;
return true;
case Image_PixMap::ImgRGBF:
thePixelFormat = GL_RGB;
theDataType = GL_FLOAT;
return true;
case Image_PixMap::ImgBGRF:
thePixelFormat = GL_BGR;
theDataType = GL_FLOAT;
return true;
case Image_PixMap::ImgRGBAF:
thePixelFormat = GL_RGBA;
theDataType = GL_FLOAT;
return true;
case Image_PixMap::ImgBGRAF:
thePixelFormat = GL_BGRA;
theDataType = GL_FLOAT;
return true;
default:
return false;
}
}
static inline GLenum TTypeToGLEnum (const TRawBufferDataType theTType)
Standard_Boolean OpenGl_GraphicDriver::BufferDump (const Graphic3d_CView& theCView,
Image_PixMap& theImage,
const Graphic3d_BufferType& theBufferType)
{
switch (theTType)
{
case TUByte: return GL_UNSIGNED_BYTE;
case TFloat: return GL_FLOAT;
default: return 0;
}
}
Standard_Boolean OpenGl_GraphicDriver::BufferDump (const Graphic3d_CView& ACView, Image_CRawBufferData& theBuffer)
{
const OpenGl_CView *aCView = (const OpenGl_CView *)ACView.ptrView;
if (aCView)
return aCView->WS->BufferDump((OpenGl_FrameBuffer *)ACView.ptrFBO,theBuffer);
const OpenGl_CView* aCView = (const OpenGl_CView* )theCView.ptrView;
return (aCView != NULL) && aCView->WS->BufferDump ((OpenGl_FrameBuffer* )theCView.ptrFBO, theImage, theBufferType);
return Standard_False;
}
Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer *theFBOPtr, Image_CRawBufferData& theBuffer)
Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer* theFBOPtr,
Image_PixMap& theImage,
const Graphic3d_BufferType& theBufferType)
{
GLenum aFormat = TFormatToGLEnum (theBuffer.format);
GLenum aType = TTypeToGLEnum (theBuffer.type);
// safe checks
if (aFormat == 0 || aType == 0 ||
theBuffer.widthPx == 0 || theBuffer.heightPx == 0 ||
theBuffer.dataPtr == NULL)
GLenum aFormat, aType;
if (theImage.IsEmpty()
|| !getDataFormat (theImage, aFormat, aType)
|| ((theBufferType == Graphic3d_BT_Depth) && (aFormat != GL_DEPTH_COMPONENT))
|| !Activate())
{
return Standard_False;
}
// activate OpenGL context
if (!Activate())
return Standard_False;
// bind FBO if used
OpenGl_FrameBuffer* aFrameBuffer = theFBOPtr;
GLint aReadBufferPrev = GL_BACK;
if (aFrameBuffer != NULL && aFrameBuffer->IsValid())
if (theFBOPtr != NULL && theFBOPtr->IsValid())
{
aFrameBuffer->BindBuffer (GetGlContext());
theFBOPtr->BindBuffer (GetGlContext());
}
else
{
@ -361,19 +377,30 @@ Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer *theFBOPtr, Im
GLint anAlignBack = 1;
glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack);
if (theBuffer.rowAligmentBytes == 0)
{
theBuffer.rowAligmentBytes = 1;
}
glPixelStorei (GL_PACK_ALIGNMENT, theBuffer.rowAligmentBytes);
GLint anExtraBytes = (GLint )theImage.RowExtraBytes();
GLint anAligment = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
if (anExtraBytes >= anAligment)
{
// copy row by row
for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
{
glReadPixels (0, GLint(aRow), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
}
}
else
{
// read pixels
glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
theImage.SetTopDown (false); // image bottom-up in OpenGL
}
// read pixels
glReadPixels (0, 0, theBuffer.widthPx, theBuffer.heightPx, aFormat, aType, (GLvoid* )theBuffer.dataPtr);
glPixelStorei (GL_PACK_ALIGNMENT, anAlignBack);
if (aFrameBuffer != NULL && aFrameBuffer->IsValid())
if (theFBOPtr != NULL && theFBOPtr->IsValid())
{
aFrameBuffer->UnbindBuffer (GetGlContext());
theFBOPtr->UnbindBuffer (GetGlContext());
}
else
{

View File

@ -33,7 +33,7 @@
#include <Aspect_Handle.hxx>
#include <Aspect_PrintAlgo.hxx>
#include <Graphic3d_PtrFrameBuffer.hxx>
#include <Image_CRawBufferData.hxx>
#include <Graphic3d_BufferType.hxx>
#include <InterfaceGraphic_Graphic3d.hxx>
#include <InterfaceGraphic_Visual3d.hxx>
@ -53,6 +53,7 @@ class OpenGl_AspectMarker;
class OpenGl_AspectText;
class OpenGl_FrameBuffer;
class OpenGl_Structure;
class Image_PixMap;
//! Reprepsents window with GL context.
//! Provides methods to render primitives and maintan GL state.
@ -127,7 +128,9 @@ public:
Graphic3d_PtrFrameBuffer FBOCreate (const Standard_Integer theWidth, const Standard_Integer theHeight);
void FBORelease (Graphic3d_PtrFrameBuffer theFBOPtr);
Standard_Boolean BufferDump (OpenGl_FrameBuffer *theFBOPtr, Image_CRawBufferData& theBuffer);
Standard_Boolean BufferDump (OpenGl_FrameBuffer* theFBOPtr,
Image_PixMap& theImage,
const Graphic3d_BufferType& theBufferType);
void UseTransparency (const Standard_Boolean theFlag);
Standard_Boolean& UseZBuffer() { return myUseZBuffer; }

View File

@ -25,7 +25,7 @@
#include <QADraw.hxx>
#include <QADraw_DataMapOfAsciiStringOfAddress.hxx>
#include <Draw_Interpretor.hxx>
#include <Image_PixMap.hxx>
#include <Image_AlienPixMap.hxx>
#include <V3d_View.hxx>
#include <ViewerTest.hxx>
#include <ViewerTest_EventManager.hxx>
@ -426,19 +426,18 @@ static Standard_Integer QAvzfit(Draw_Interpretor& di, Standard_Integer /*argc*/,
return 0;
}
Handle(TColStd_HSequenceOfReal) GetColorOfPixel (const Handle(Aspect_PixMap) theImage,
Handle(TColStd_HSequenceOfReal) GetColorOfPixel (const Image_PixMap& theImage,
const Standard_Integer theCoordinateX,
const Standard_Integer theCoordinateY,
const Standard_Integer theRadius)
{
Handle(TColStd_HSequenceOfReal) aSeq = new TColStd_HSequenceOfReal();
if (theImage.IsNull()) {
if (theImage.IsEmpty()) {
std::cerr << "The image is null.\n";
return aSeq;
}
Standard_Integer aWidth = 0;
Standard_Integer anHeight = 0;
theImage->Size (aWidth, anHeight);
Standard_Integer aWidth = (Standard_Integer )theImage.SizeX();
Standard_Integer anHeight = (Standard_Integer )theImage.SizeY();
Quantity_Color aColorTmp;
for (Standard_Integer anXIter = theCoordinateX - theRadius;
@ -456,7 +455,7 @@ Handle(TColStd_HSequenceOfReal) GetColorOfPixel (const Handle(Aspect_PixMap) the
continue;
}
// Image_PixMap stores image upside-down in memory!
aColorTmp = theImage->PixelColor (anXIter, anYIter);
aColorTmp = theImage.PixelColor (anXIter, anYIter);
aSeq->Append (aColorTmp.Red());
aSeq->Append (aColorTmp.Green());
aSeq->Append (aColorTmp.Blue());
@ -482,8 +481,8 @@ static Standard_Integer QAAISGetPixelColor (Draw_Interpretor& di, Standard_Integ
Standard_Integer QAAISXWindowSize_X = 0;
Standard_Integer QAAISXWindowSize_Y = 0;
QAAISWindow->Size(QAAISXWindowSize_X, QAAISXWindowSize_Y);
Standard_ShortReal QAAISCoordinateX = atoi (argv [1]);
Standard_ShortReal QAAISCoordinateY = atoi (argv [2]);
Standard_ShortReal QAAISCoordinateX = atof (argv [1]);
Standard_ShortReal QAAISCoordinateY = atof (argv [2]);
Standard_ShortReal QAAISColorRED_V = 0;
Standard_ShortReal QAAISColorGRN_V = 0;
@ -504,9 +503,9 @@ static Standard_Integer QAAISGetPixelColor (Draw_Interpretor& di, Standard_Integ
aRadius=0;
}
Handle(TColStd_HSequenceOfReal) aSeq = GetColorOfPixel (QAAISView->ToPixMap (QAAISXWindowSize_X, QAAISXWindowSize_Y, Image_TOI_RGB),
QAAISCoordinateX, QAAISCoordinateY,
aRadius);
Image_PixMap anImage;
QAAISView->ToPixMap (anImage, QAAISXWindowSize_X, QAAISXWindowSize_Y);
Handle(TColStd_HSequenceOfReal) aSeq = GetColorOfPixel (anImage, QAAISCoordinateX, QAAISCoordinateY, aRadius);
cout << "Length = " << aSeq->Length() << endl;
Standard_Boolean IsNotEqual = Standard_True;
@ -696,6 +695,7 @@ static Standard_Integer QAAISGetViewCharac (Draw_Interpretor& di, Standard_Integ
di << "Proj on X : " << QAAISViewProjX << "; on Y: " << QAAISViewProjY << "; on Z: " << QAAISViewProjZ << "\n";
di << "Up on X : " << QAAISViewUpX << "; on Y: " << QAAISViewUpY << "; on Z: " << QAAISViewUpZ << "\n";
di << "At on X : " << QAAISViewAtX << "; on Y: " << QAAISViewAtY << "; on Z: " << QAAISViewAtZ << "\n";
return 0;
}
static Standard_Integer QAAISSetViewCharac (Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
@ -737,7 +737,7 @@ static Standard_Integer QAAISGetColorCoord (Draw_Interpretor& di, Standard_Integ
di << "Usage : " << argv[0] << " [3d|2d]" << "\n";
return 1;
}
Handle (Aspect_Window) QAAISWindow;
Handle(Xw_Window) QAAISWindow;
Standard_Boolean is3d = 1;
@ -748,7 +748,7 @@ static Standard_Integer QAAISGetColorCoord (Draw_Interpretor& di, Standard_Integ
di << "You must initialize AISViewer before this command." << "\n";
return 1;
}
QAAISWindow = QAAIS_MainView -> V3d_View::Window ();
QAAISWindow = Handle(Xw_Window)::DownCast (QAAIS_MainView->V3d_View::Window());
is3d = 1;
}
@ -758,7 +758,7 @@ static Standard_Integer QAAISGetColorCoord (Draw_Interpretor& di, Standard_Integ
di << "You must initialize AIS 2D Viewer before this command." << "\n";
return 1;
}
QAAISWindow = V->Driver()->Window();
QAAISWindow = Handle(Xw_Window)::DownCast (V->Driver()->Window());
is3d = 0;
}
@ -795,19 +795,20 @@ static Standard_Integer QAAISGetColorCoord (Draw_Interpretor& di, Standard_Integ
const char **argvvv = (const char **) bufff;
while ( is3d ? ViewerMainLoop (argccc, argvvv) : ViewerMainLoop2d (argccc, argvvv)) {
Handle(TColStd_HSequenceOfReal) aSeq;
Image_PixMap anImage;
if(is3d)
{
ViewerTest::GetMousePosition (QAAIS_MousePoint_X, QAAIS_MousePoint_Y);
Handle (V3d_View) QAAIS_MainView = ViewerTest::CurrentView();
aSeq = GetColorOfPixel (QAAIS_MainView->ToPixMap (QAAIS_WindowSize_X, QAAIS_WindowSize_Y, Image_TOI_RGB),
QAAIS_MousePoint_X, QAAIS_MousePoint_Y, 0);
QAAIS_MainView->ToPixMap (anImage, QAAIS_WindowSize_X, QAAIS_WindowSize_Y);
}
else
{
Viewer2dTest::GetMousePosition (QAAIS_MousePoint_X, QAAIS_MousePoint_Y);
aSeq = GetColorOfPixel (QAAISWindow->ToPixMap(),
QAAIS_MousePoint_X, QAAIS_MousePoint_Y, 0);
QAAISWindow->ToPixMap (anImage);
}
aSeq = GetColorOfPixel (anImage, QAAIS_MousePoint_X, QAAIS_MousePoint_Y, 0);
QAAIS_ColorRED = aSeq->Value(1);
QAAIS_ColorGRN = aSeq->Value(2);
QAAIS_ColorBLU = aSeq->Value(3);
@ -869,8 +870,13 @@ static int QAAISGetPixelColor2d (Draw_Interpretor& di, Standard_Integer argc, co
di << "You must initialize AIS 2D Viewer before this command." << "\n";
return 1;
}
// Get Color
Handle(Aspect_Window) QAAISWindow = V->Driver()->Window();
#if (defined(_WIN32) || defined(__WIN32__))
Handle(WNT_Window) QAAISWindow = Handle(WNT_Window)::DownCast (V->Driver()->Window());
#else
Handle(Xw_Window) QAAISWindow = Handle(Xw_Window )::DownCast (V->Driver()->Window());
#endif
Standard_ShortReal aCoordinateX = atoi(argv[1]);
Standard_ShortReal aCoordinateY = atoi(argv[2]);
@ -895,9 +901,9 @@ static int QAAISGetPixelColor2d (Draw_Interpretor& di, Standard_Integer argc, co
aRadius=0;
}
Handle(TColStd_HSequenceOfReal) aSeq = GetColorOfPixel (QAAISWindow->ToPixMap(),
aCoordinateX, aCoordinateY,
aRadius);
Image_PixMap anImage;
QAAISWindow->ToPixMap (anImage);
Handle(TColStd_HSequenceOfReal) aSeq = GetColorOfPixel (anImage, aCoordinateX, aCoordinateY, aRadius);
Standard_Boolean IsNotEqual = Standard_True;
Standard_Integer i;
@ -1041,7 +1047,7 @@ static int V2dPan (Draw_Interpretor& di, int argc, const char ** argv)
di << "use 'v2dinit' command before " << argv[0] << "\n";
return -1;
}
Viewer2dTest::CurrentView()->Pan(atof(argv[1]), atof(argv[2]));
Viewer2dTest::CurrentView()->Pan(atoi(argv[1]), atoi(argv[2]));
return 0;
}
@ -1242,6 +1248,7 @@ static int QA2dGetIndexes (Draw_Interpretor& di, int /*argc*/, const char ** arg
di << "Available font indexes are " << aFontMin << " - " << aFontMax << "\n";
aWindowDriver->ColorBoundIndexs(aColorMin, aColorMax);
di << "Available color indexes are " << aColorMin << " - " << aColorMax << "\n";
return 0;
}
#if ! defined(WNT)

View File

@ -125,7 +125,7 @@ uses
Plotter from Graphic3d,
Window from Aspect,
PixMap from Image,
TypeOfImage from Image,
BufferType from Graphic3d,
Background from Aspect,
GradientBackground from Aspect,
PlotterDriver from PlotMgt,
@ -1590,8 +1590,8 @@ is
---Purpose: dump the view
Dump ( me: mutable;
theFile: CString from Standard;
theBufferType : TypeOfImage from Image = Image_TOI_RGB )
theFile : CString from Standard;
theBufferType : BufferType from Graphic3d = Graphic3d_BT_RGB )
returns Boolean from Standard;
---Level: Public
---Purpose: dump the full contents of the view at the same
@ -1600,9 +1600,9 @@ is
-- Returns FALSE when the dump has failed
Dump ( me: mutable;
theFile : CString from Standard;
theFormat : FormatOfSheetPaper from Aspect;
theBufferType : TypeOfImage from Image = Image_TOI_RGB )
theFile : CString from Standard;
theFormat : FormatOfSheetPaper from Aspect;
theBufferType : BufferType from Graphic3d = Graphic3d_BT_RGB )
returns Boolean from Standard;
---Level: Public
---Purpose: dump the full contents of the view with a
@ -1653,16 +1653,18 @@ is
-- Warning: Works only under Windows.
ToPixMap ( me : mutable;
theImage : in out PixMap from Image;
theWidth : Integer from Standard;
theHeight : Integer from Standard;
theBufferType : TypeOfImage from Image = Image_TOI_RGB;
theBufferType : BufferType from Graphic3d = Graphic3d_BT_RGB;
theForceCentered : Boolean from Standard = Standard_True )
returns PixMap from Image;
returns Boolean from Standard;
---Level : Public
---Purpose : dump the full contents of the view
-- to a pixmap of pixel size <theWidth>*<theHeight> and
-- buffer type <theBufferType>. If <theForceCentered> is true
-- view scene will be centered.
-- Pixmap will be automatically (re)allocated when needed.
SetProjModel( me : mutable;
amOdel: TypeOfProjectionModel from V3d = V3d_TPM_SCREEN )

View File

@ -158,7 +158,7 @@ To solve the problem (for lack of a better solution) I make 2 passes.
#include <Graphic3d_MapIteratorOfMapOfStructure.hxx>
#include <Graphic3d_MapOfStructure.hxx>
#include <Graphic3d_TextureEnv.hxx>
#include <Image_PixMap.hxx>
#include <Image_AlienPixMap.hxx>
#include <V3d.hxx>
#include <V3d_View.ixx>
#include <Viewer_BadValue.hxx>
@ -3482,22 +3482,20 @@ void V3d_View::ScreenCopy (const Handle(PlotMgt_PlotterDriver)& aPlotterDriver,
#include <Visual3d_Layer.hxx>
////////////////////////////////////////////////////////////////
Standard_Boolean V3d_View::Dump (const Standard_CString theFile,
const Image_TypeOfImage theBufferType)
Standard_Boolean V3d_View::Dump (const Standard_CString theFile,
const Graphic3d_BufferType& theBufferType)
{
Standard_Integer aWinWidth, aWinHeight;
MyWindow->Size (aWinWidth, aWinHeight);
Handle(Aspect_PixMap) aPixMap = ToPixMap (aWinWidth, aWinHeight, theBufferType);
return !aPixMap.IsNull() && aPixMap->Dump (theFile);
Image_AlienPixMap anImage;
return ToPixMap (anImage, aWinWidth, aWinHeight, theBufferType) && anImage.Save (theFile);
}
////////////////////////////////////////////////////////////////
Standard_Boolean V3d_View::Dump (const Standard_CString theFile,
Standard_Boolean V3d_View::Dump (const Standard_CString theFile,
const Aspect_FormatOfSheetPaper theFormat,
const Image_TypeOfImage theBufferType)
const Graphic3d_BufferType& theBufferType)
{
Standard_Boolean isDone = Standard_False;
// convert Aspect_FormatOfSheetPaper size to pixel ...
Quantity_Length anSPWidth, anSPHeight;
Aspect::ValuesOfFOSP (theFormat, anSPWidth, anSPHeight);
@ -3511,22 +3509,25 @@ Standard_Boolean V3d_View::Dump (const Standard_CString theFile,
Quantity_Factor aScale = Min (anSPWidth / aWinWidth, anSPHeight / aWinHeight);
aPixelWidth = Standard_Integer (aPixelWidth * aScale);
aPixelHeight = Standard_Integer (aPixelHeight * aScale);
Image_AlienPixMap anImage;
ToPixMap (anImage, aPixelWidth, aPixelHeight, theBufferType);
OSD_Environment anEnvGamma ("CSF_GAMMA_CORRECTION");
TCollection_AsciiString strGamma (anEnvGamma.Value());
if (!anImage.IsEmpty() && !strGamma.IsEmpty())
{
Handle(Aspect_PixMap) aBitmap = ToPixMap (aPixelWidth, aPixelHeight, theBufferType);
Standard_Real aGammaValue = 1.0;
OSD_Environment anEnvGamma ("CSF_GAMMA_CORRECTION");
TCollection_AsciiString strGamma (anEnvGamma.Value());
if (!strGamma.IsEmpty()) aGammaValue = strGamma.RealValue();
isDone = !aBitmap.IsNull() && aBitmap->Dump (theFile, aGammaValue);
Standard_Real aGammaValue = strGamma.RealValue();
anImage.AdjustGamma (aGammaValue);
}
return isDone;
return anImage.Save (theFile);
}
////////////////////////////////////////////////////////////////
Handle(Image_PixMap) V3d_View::ToPixMap (const Standard_Integer theWidth,
const Standard_Integer theHeight,
const Image_TypeOfImage theBufferType,
const Standard_Boolean theIsForceCentred)
Standard_Boolean V3d_View::ToPixMap (Image_PixMap& theImage,
const Standard_Integer theWidth,
const Standard_Integer theHeight,
const Graphic3d_BufferType& theBufferType,
const Standard_Boolean theIsForceCentred)
{
// always prefer hardware accelerated offscreen buffer
Graphic3d_CView* cView = (Graphic3d_CView* )MyView->CView();
@ -3575,7 +3576,7 @@ Handle(Image_PixMap) V3d_View::ToPixMap (const Standard_Integer theWidth,
// but currently allow only dumping the window itself
if (aFBOVPSizeX != aWinWidth || aFBOVPSizeY != aWinHeight)
{
return Handle(Image_PixMap)();
return Standard_False;
}
}
@ -3625,15 +3626,25 @@ Handle(Image_PixMap) V3d_View::ToPixMap (const Standard_Integer theWidth,
MyViewMapping = prevMapping;
MyView->SetViewMapping (prevMapping);
Standard_Boolean isSuccess = Standard_True;
// allocate image buffer for dumping
Image_CRawBufferData aRawBuffer;
Handle(Image_PixMap) anImageBitmap = new Image_PixMap (aFBOVPSizeX, aFBOVPSizeY, theBufferType);
anImageBitmap->AccessBuffer (aRawBuffer);
if (!MyView->BufferDump (aRawBuffer))
if (theImage.IsEmpty()
|| (Standard_Size )aFBOVPSizeX != theImage.SizeX()
|| (Standard_Size )aFBOVPSizeY != theImage.SizeY())
{
// dump is failed!
anImageBitmap = Handle(Image_PixMap)();
bool isBigEndian = Image_PixMap::IsBigEndianHost();
Image_PixMap::ImgFormat aFormat = Image_PixMap::ImgUNKNOWN;
switch (theBufferType)
{
case Graphic3d_BT_RGB: aFormat = isBigEndian ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR; break;
case Graphic3d_BT_RGBA: aFormat = isBigEndian ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA; break;
case Graphic3d_BT_Depth: aFormat = Image_PixMap::ImgGrayF; break;
}
isSuccess = isSuccess && theImage.InitZero (aFormat, aFBOVPSizeX, aFBOVPSizeY);
}
isSuccess = isSuccess && MyView->BufferDump (theImage, theBufferType);
// FBO now useless, free resources
if (aFBOPtr != aPrevFBOPtr)
@ -3645,5 +3656,5 @@ Handle(Image_PixMap) V3d_View::ToPixMap (const Standard_Integer theWidth,
MyView->FBOChangeViewport (aPrevFBOPtr, aPrevFBOVPSizeX, aPrevFBOVPSizeY);
}
cView->ptrFBO = aPrevFBOPtr;
return anImageBitmap;
return isSuccess;
}

View File

@ -54,7 +54,7 @@
#include <AIS_ListIteratorOfListOfInteractive.hxx>
#include <Aspect_InteriorStyle.hxx>
#include <Graphic3d_AspectFillArea3d.hxx>
#include <Image_PixMap.hxx>
#include <Image_AlienPixMap.hxx>
#include <Prs3d_ShadingAspect.hxx>
#ifdef HAVE_CONFIG_H
@ -833,22 +833,21 @@ static Standard_Integer VDump (Draw_Interpretor& di, Standard_Integer argc, cons
return 1;
}
Image_TypeOfImage aBufferType = Image_TOI_RGB;
Graphic3d_BufferType aBufferType = Graphic3d_BT_RGB;
if (argc > 2)
{
TCollection_AsciiString aBuffTypeStr (argv[2]);
if (TCollection_AsciiString::ISSIMILAR (aBuffTypeStr, TCollection_AsciiString ("rgb")))
{
aBufferType = Image_TOI_RGB;
aBufferType = Graphic3d_BT_RGB;
}
else if (TCollection_AsciiString::ISSIMILAR (aBuffTypeStr, TCollection_AsciiString ("rgba")))
{
aBufferType = Image_TOI_RGBA;
aBufferType = Graphic3d_BT_RGBA;
}
else if (TCollection_AsciiString::ISSIMILAR (aBuffTypeStr, TCollection_AsciiString ("depth")))
{
aBufferType = Image_TOI_FLOAT;
aBufferType = Graphic3d_BT_Depth;
}
}
@ -874,21 +873,20 @@ static Standard_Integer VDump (Draw_Interpretor& di, Standard_Integer argc, cons
return 0;
}
Handle(Image_PixMap) aPixMap = view->ToPixMap (aWidth, aHeight, aBufferType);
if (aPixMap.IsNull())
Image_AlienPixMap aPixMap;
if (!view->ToPixMap (aPixMap, aWidth, aHeight, aBufferType))
{
di << "Dumping failed!\n";
return 1;
}
Image_CRawBufferData aRawBuffer;
aPixMap->AccessBuffer (aRawBuffer);
if (aRawBuffer.widthPx != aWidth || aRawBuffer.heightPx != aHeight)
if (aPixMap.SizeX() != Standard_Size(aWidth)
|| aPixMap.SizeY() != Standard_Size(aHeight))
{
std::cout << "Warning! Dumped dimensions " << aRawBuffer.widthPx << "x" << aRawBuffer.heightPx
<< " are lesser than requested " << aWidth << "x" << aHeight << "\n";
std::cout << "Warning! Dumped dimensions " << aPixMap.SizeX() << "x" << aPixMap.SizeY()
<< " are lesser than requested " << aWidth << "x" << aHeight << "\n";
}
if (!aPixMap->Dump (argv[1]))
if (!aPixMap.Save (argv[1]))
{
di << "Saving image failed!\n";
return 1;

View File

@ -45,19 +45,21 @@
#include <Draw.hxx>
#include <Draw_Appli.hxx>
#include <Aspect_PrintAlgo.hxx>
#include <Image_PixMap.hxx>
#include <Image_AlienPixMap.hxx>
#include <OSD_Timer.hxx>
#include <TColStd_SequenceOfInteger.hxx>
#include <Visual3d_LayerItem.hxx>
#include <V3d_LayerMgr.hxx>
#include <V3d_LayerMgrPointer.hxx>
#include <Aspect_TypeOfLine.hxx>
#include <Image_Diff.hxx>
#ifdef WNT
#undef DrawText
#endif
#include <Visual3d_Layer.hxx>
#include <cstdlib>
#ifndef WNT
#include <Graphic3d_GraphicDevice.hxx>
@ -2151,10 +2153,8 @@ static int VPrintView (Draw_Interpretor& di, Standard_Integer argc,
if (aMode != 0 && aMode != 1)
aMode = 0;
Image_CRawBufferData aRawBuffer;
HDC anDC = CreateCompatibleDC(0);
// define compatible bitmap
HDC anDC = CreateCompatibleDC(0);
BITMAPINFO aBitmapData;
memset (&aBitmapData, 0, sizeof (BITMAPINFOHEADER));
aBitmapData.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
@ -2170,12 +2170,13 @@ static int VPrintView (Draw_Interpretor& di, Standard_Integer argc,
aBitmapData.bmiHeader.biSizeImage = 0;
// Create Device Independent Bitmap
void* aBitsOut = NULL;
HBITMAP aMemoryBitmap = CreateDIBSection (anDC, &aBitmapData, DIB_RGB_COLORS,
&aRawBuffer.dataPtr, NULL, 0);
&aBitsOut, NULL, 0);
HGDIOBJ anOldBitmap = SelectObject(anDC, aMemoryBitmap);
Standard_Boolean isSaved = Standard_False, isPrinted = Standard_False;
if (aRawBuffer.dataPtr != 0)
if (aBitsOut != NULL)
{
if (aMode == 0)
isPrinted = aView->Print(anDC,1,1,0,Aspect_PA_STRETCH);
@ -2185,11 +2186,13 @@ static int VPrintView (Draw_Interpretor& di, Standard_Integer argc,
// succesfully printed into an intermediate buffer
if (isPrinted)
{
Handle(Image_PixMap) anImageBitmap =
new Image_PixMap ((Standard_PByte)aRawBuffer.dataPtr,
aWidth, aHeight,
aWidth*3 + aWidth%4, 24, 0);
isSaved = anImageBitmap->Dump(aFileName.ToCString());
Image_PixMap aWrapper;
aWrapper.InitWrapper (Image_PixMap::ImgBGR, (Standard_Byte* )aBitsOut, aWidth, aHeight, aWidth * 3 + aWidth % 4);
aWrapper.SetTopDown (false);
Image_AlienPixMap anImageBitmap;
anImageBitmap.InitCopy (aWrapper);
isSaved = anImageBitmap.Save (aFileName);
}
else
{
@ -2898,7 +2901,9 @@ static int VReadPixel (Draw_Interpretor& theDI,
return 1;
}
Image_TypeOfImage aBufferType = Image_TOI_RGBA;
Image_PixMap::ImgFormat aFormat = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
Standard_Integer aWidth, aHeight;
aView->Window()->Size (aWidth, aHeight);
const Standard_Integer anX = atoi (theArgVec[1]);
@ -2916,28 +2921,34 @@ static int VReadPixel (Draw_Interpretor& theDI,
TCollection_AsciiString aParam (theArgVec[anIter]);
if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("rgb")))
{
aBufferType = Image_TOI_RGB;
aFormat = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
aBufferType = Graphic3d_BT_RGB;
}
else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("hls")))
{
aBufferType = Image_TOI_RGB;
aFormat = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
aBufferType = Graphic3d_BT_RGB;
toShowHls = Standard_True;
}
else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("rgbf")))
{
aBufferType = Image_TOI_RGBF;
aFormat = Image_PixMap::ImgRGBF;
aBufferType = Graphic3d_BT_RGB;
}
else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("rgba")))
{
aBufferType = Image_TOI_RGBA;
aFormat = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
aBufferType = Graphic3d_BT_RGBA;
}
else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("rgbaf")))
{
aBufferType = Image_TOI_RGBAF;
aFormat = Image_PixMap::ImgRGBAF;
aBufferType = Graphic3d_BT_RGBA;
}
else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("depth")))
{
aBufferType = Image_TOI_FLOAT;
aFormat = Image_PixMap::ImgGrayF;
aBufferType = Graphic3d_BT_Depth;
}
else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("name")))
{
@ -2945,19 +2956,23 @@ static int VReadPixel (Draw_Interpretor& theDI,
}
}
Handle(Image_PixMap) anImage = aView->ToPixMap (aWidth, aHeight, aBufferType);
if (anImage.IsNull())
Image_PixMap anImage;
if (!anImage.InitTrash (aFormat, aWidth, aHeight))
{
std::cerr << "Image allocation failed\n";
return 1;
}
else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
{
std::cerr << "Image dump failed\n";
return 1;
}
Quantity_Parameter anAlpha;
Quantity_Color aColor = anImage->PixelColor (anX, anY, anAlpha);
Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
if (toShowName)
{
if (aBufferType == Image_TOI_RGBA
|| aBufferType == Image_TOI_RGBAF)
if (aBufferType == Graphic3d_BT_RGBA)
{
theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha << "\n";
}
@ -2971,8 +2986,7 @@ static int VReadPixel (Draw_Interpretor& theDI,
switch (aBufferType)
{
default:
case Image_TOI_RGB:
case Image_TOI_RGBF:
case Graphic3d_BT_RGB:
{
if (toShowHls)
{
@ -2984,13 +2998,12 @@ static int VReadPixel (Draw_Interpretor& theDI,
}
break;
}
case Image_TOI_RGBA:
case Image_TOI_RGBAF:
case Graphic3d_BT_RGBA:
{
theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha << "\n";
break;
}
case Image_TOI_FLOAT:
case Graphic3d_BT_Depth:
{
theDI << aColor.Red() << "\n";
break;
@ -3001,6 +3014,57 @@ static int VReadPixel (Draw_Interpretor& theDI,
return 0;
}
//==============================================================================
//function : VDiffImage
//purpose : The draw-command compares two images.
//==============================================================================
static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
{
if (theArgNb < 6)
{
theDI << "Not enough arguments.\n";
return 1;
}
// image file names
const char* anImgPathRef = theArgVec[1];
const char* anImgPathNew = theArgVec[2];
// get string tolerance and check its validity
Standard_Real aTolColor = atof (theArgVec[3]);
if (aTolColor < 0.0)
aTolColor = 0.0;
if (aTolColor > 1.0)
aTolColor = 1.0;
Standard_Boolean toBlackWhite = (atoi (theArgVec[4]) == 1);
Standard_Boolean isBorderFilterOn = (atoi (theArgVec[5]) == 1);
// image file of difference
const char* aDiffImagePath = (theArgNb >= 7) ? theArgVec[6] : NULL;
// compare the images
Image_Diff aComparer;
if (!aComparer.Init (anImgPathRef, anImgPathNew, toBlackWhite))
{
return 1;
}
aComparer.SetColorTolerance (aTolColor);
aComparer.SetBorderFilterOn (isBorderFilterOn);
Standard_Integer aDiffColorsNb = aComparer.Compare();
theDI << aDiffColorsNb << "\n";
// save image of difference
if (aDiffImagePath != NULL)
{
aComparer.SaveDiffImage (aDiffImagePath);
}
return 0;
}
//=======================================================================
//function : ViewerCommands
//purpose :
@ -3131,4 +3195,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
"vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
" : Read pixel value for active view",
__FILE__, VReadPixel, group);
theCommands.Add("diffimage",
"diffimage : diffimage imageFile1 imageFile2 toleranceOfColor(0..1) blackWhite(1|0) borderFilter(1|0) [diffImageFile]",
__FILE__, VDiffImage, group);
}

View File

@ -87,8 +87,7 @@ uses
ColorScale from Aspect,
PrintAlgo from Aspect,
CRawBufferData from Image,
BufferType from Graphic3d,
CBitFields8 from Graphic3d,
CView from Graphic3d,
GraphicDriver from Graphic3d,
@ -121,7 +120,9 @@ uses
FontAspect from OSD,
AsciiString from TCollection,
ExtendedString from TCollection,
CGraduatedTrihedron from Graphic3d
CGraduatedTrihedron from Graphic3d,
PixMap from Image
raises
TransformError from Visual3d,
@ -1238,7 +1239,8 @@ is
---Purpose: Change offscreen FBO viewport.
BufferDump( me : mutable;
buffer : in out CRawBufferData from Image )
theImage : in out PixMap from Image;
theBufferType : BufferType from Graphic3d )
returns Boolean from Standard
is static;
---Level: Public

View File

@ -4277,9 +4277,10 @@ void Visual3d_View::FBOChangeViewport(Graphic3d_PtrFrameBuffer& theFBOPtr,
theWidth, theHeight );
}
Standard_Boolean Visual3d_View::BufferDump (Image_CRawBufferData& theBuffer)
Standard_Boolean Visual3d_View::BufferDump (Image_PixMap& theImage,
const Graphic3d_BufferType& theBufferType)
{
return MyGraphicDriver->BufferDump( MyCView, theBuffer);
return MyGraphicDriver->BufferDump (MyCView, theImage, theBufferType);
}
void Visual3d_View::EnableGLLight( const Standard_Boolean enable ) const

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 ************************************//

View File

@ -30,7 +30,7 @@ class PixMap from Xw
---Keywords: Bitmap, Pixmap, X11
inherits
PixMap from Aspect
Transient from Standard
uses
Handle from Aspect,
Color from Quantity,
@ -97,4 +97,7 @@ is
fields
myPixmap : Handle from Aspect is protected;
myWindow : Window from Xw;
myWidth : Integer from Standard is protected;
myHeight : Integer from Standard is protected;
myDepth : Integer from Standard is protected;
end PixMap;

View File

@ -28,6 +28,9 @@
#define xTRACE 1
#include <TCollection_AsciiString.hxx>
#include <Image_AlienPixMap.hxx>
#include <errno.h>
#include <stdio.h>
@ -36,9 +39,6 @@
#include <Xw_Window.hxx>
#include <Xw_Extension.h>
#include <TCollection_AsciiString.hxx>
#include <Image_PixMap.hxx>
XW_STATUS Xw_save_xwd_image ( void*, void*, char* );
XW_STATUS Xw_save_bmp_image ( void*, void*, char* );
XW_STATUS Xw_save_gif_image ( void*, void*, char* );
@ -63,15 +63,15 @@ Standard_Integer Xw_PixMap::PreferedDepth(
//////////////////////////////////////////////////////////////////////////////////////////
Xw_PixMap::Xw_PixMap ( const Handle(Aspect_Window)& aWindow,
const Standard_Integer aWidth,
const Standard_Integer anHeight,
const Standard_Integer aDepth ) :
Aspect_PixMap(aWidth, anHeight, PreferedDepth(aWindow, aDepth))
Xw_PixMap::Xw_PixMap (const Handle(Aspect_Window)& theWindow,
const Standard_Integer theWidth,
const Standard_Integer theHeight,
const Standard_Integer theDepth)
: myWindow (Handle(Xw_Window)::DownCast(theWindow)),
myWidth (theWidth),
myHeight (theHeight),
myDepth (PreferedDepth (theWindow, theDepth))
{
myWindow = Handle(Xw_Window)::DownCast(aWindow);
XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*) myWindow->ExtendedWindow();
Xw_print_error();
@ -99,46 +99,54 @@ Xw_PixMap::Destroy ()
}
}
////////////////////////////////////////////////////////////
Standard_Boolean Xw_PixMap::Dump (const Standard_CString theFilename,
const Standard_Real theGammaValue) const
Standard_Boolean Xw_PixMap::Dump (const Standard_CString theFileName,
const Standard_Real theGammaValue) const
{
// the attributes
XWindowAttributes winAttr;
XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*) myWindow->ExtendedWindow();
XGetWindowAttributes (_DISPLAY, _WINDOW, &winAttr);
// find the image
XImage* pximage = XGetImage (_DISPLAY, myPixmap,
0, 0, myWidth, myHeight,
AllPlanes, ZPixmap);
if (pximage == NULL)
{
return Standard_False;
}
if (winAttr.visual->c_class == TrueColor)
{
Standard_Byte* aDataPtr = (Standard_Byte* )pximage->data;
Handle(Image_PixMap) anImagePixMap = new Image_PixMap (aDataPtr,
pximage->width, pximage->height,
pximage->bytes_per_line,
pximage->bits_per_pixel,
Standard_True);
// destroy the image
XDestroyImage (pximage);
// save the image
return anImagePixMap->Dump (theFilename, theGammaValue);
}
else
if (winAttr.visual->c_class != TrueColor)
{
std::cerr << "Visual Type not supported!";
// destroy the image
XDestroyImage (pximage);
return Standard_False;
}
Image_AlienPixMap anImage;
bool isBigEndian = Image_PixMap::IsBigEndianHost();
const Standard_Size aSizeRowBytes = Standard_Size(winAttr.width) * 4;
if (!anImage.InitTrash (isBigEndian ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgBGR32,
Standard_Size(winAttr.width), Standard_Size(winAttr.height), aSizeRowBytes))
{
return Standard_False;
}
anImage.SetTopDown (true);
XImage* anXImage = XCreateImage (_DISPLAY, winAttr.visual,
32, ZPixmap, 0, (char* )anImage.ChangeData(), winAttr.width, winAttr.height, 32, int(aSizeRowBytes));
anXImage->bitmap_bit_order = anXImage->byte_order = (isBigEndian ? MSBFirst : LSBFirst);
if (XGetSubImage (_DISPLAY, myPixmap,
0, 0, winAttr.width, winAttr.height,
AllPlanes, ZPixmap, anXImage, 0, 0) == NULL)
{
anXImage->data = NULL;
XDestroyImage (anXImage);
return Standard_False;
}
// destroy the image
anXImage->data = NULL;
XDestroyImage (anXImage);
// save the image
if (Abs (theGammaValue - 1.0) > 0.001)
{
anImage.AdjustGamma (theGammaValue);
}
// save the image
return anImage.Save (theFileName);
}
////////////////////////////////////////////////////////////

View File

@ -49,7 +49,7 @@ uses
Handle from Aspect,
FillMethod from Aspect,
GradientFillMethod from Aspect,
PixMap from Aspect,
PixMap from Image,
NameOfColor from Quantity,
Parameter from Quantity,
Ratio from Quantity,
@ -330,8 +330,8 @@ is
-- 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

@ -77,7 +77,7 @@
#include <Xw_Cextern.hxx>
//}
#include <Aspect_Convert.hxx>
#include <Image_PixMap.hxx>
#include <Image_AlienPixMap.hxx>
#include <Xw_Extension.h>
@ -862,15 +862,14 @@ Standard_Boolean Xw_Window::DumpArea (const Standard_CString theFilename,
return Standard_Boolean(aStatus);
}
Handle(Aspect_PixMap) Xw_Window::ToPixMap() const
Standard_Boolean Xw_Window::ToPixMap (Image_PixMap& thePixMap) const
{
Handle(Image_PixMap) anImagePixMap;
int aDummy, aWidth, aHeight;
XW_WINDOWSTATE state = Xw_get_window_position (MyExtendedWindow,
&aDummy, &aDummy, &aWidth, &aHeight);
if (state == XW_WS_UNKNOWN)
{
return anImagePixMap;
return Standard_False;
}
XW_EXT_IMAGEDATA* pimage = NULL;
@ -895,22 +894,27 @@ Handle(Aspect_PixMap) Xw_Window::ToPixMap() const
if (pimage == NULL)
{
return anImagePixMap;
return Standard_False;
}
XImage* pximage = (pimage->zximage) ? pimage->zximage : pimage->pximage;
XW_EXT_WINDOW* pwindow = (XW_EXT_WINDOW* )MyExtendedWindow;
if (pwindow->pcolormap->visual->c_class == TrueColor)
if (pwindow->pcolormap->visual->c_class != TrueColor)
{
Standard_Byte* aDataPtr = (Standard_Byte* )pximage->data;
anImagePixMap = new Image_PixMap (aDataPtr,
pximage->width, pximage->height,
pximage->bytes_per_line,
pximage->bits_per_pixel,
Standard_True);
return Standard_False;
}
const bool isBigEndian = (pximage->byte_order == MSBFirst);
Image_PixMap::ImgFormat aFormat = (pximage->bits_per_pixel == 32)
? (isBigEndian ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgBGR32)
: (isBigEndian ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR);
Image_PixMap aWrapper;
aWrapper.InitWrapper (aFormat, (Standard_Byte* )pximage->data, pximage->width, pximage->height, pximage->bytes_per_line);
aWrapper.SetTopDown (true);
Standard_Boolean isSuccess = thePixMap.InitCopy (aWrapper);
Xw_close_image (pimage);
return anImagePixMap;
return isSuccess;
}
Standard_Boolean Xw_Window::Load (const Standard_CString aFilename) const {

View File

@ -34,13 +34,14 @@
# include <config.h>
#endif
#include <Image_AlienPixMap.hxx>
#include <TCollection_AsciiString.hxx>
#include <Xw_Extension.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <Image_PixMap.hxx>
#ifdef XW_PROTOTYPE
XW_STATUS Xw_save_image_adv (Display *aDisplay,Window aWindow,XWindowAttributes aWinAttr,XImage *aPximage,Colormap aColormap,int aNcolors,char *filename)
#else
@ -54,22 +55,22 @@ int ncolors;
char *filename;
#endif /*XW_PROTOTYPE*/
{
if (aWinAttr.visual->c_class == TrueColor)
{
Standard_Byte* aDataPtr = (Standard_Byte* )aPximage->data;
Handle(Image_PixMap) anImagePixMap = new Image_PixMap (aDataPtr,
aPximage->width, aPximage->height,
aPximage->bytes_per_line,
aPximage->bits_per_pixel,
Standard_True);
// save the image
return anImagePixMap->Dump (filename) ? XW_SUCCESS : XW_ERROR;
}
else
if (aWinAttr.visual->c_class != TrueColor)
{
std::cerr << "Visual Type not supported!";
return XW_SUCCESS;
return XW_ERROR;
}
const bool isBigEndian = (aPximage->byte_order == MSBFirst);
Image_PixMap::ImgFormat aFormat = (aPximage->bits_per_pixel == 32)
? (isBigEndian ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgBGR32)
: (isBigEndian ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR);
Image_PixMap aWrapper;
aWrapper.InitWrapper (aFormat, (Standard_Byte* )aPximage->data, aPximage->width, aPximage->height, aPximage->bytes_per_line);
aWrapper.SetTopDown (true);
Image_AlienPixMap anAlienImage;
return (anAlienImage.InitCopy (aWrapper) && anAlienImage.Save (filename)) ? XW_SUCCESS : XW_ERROR;
}
#ifdef XW_PROTOTYPE