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
+++ /dev/null
--- 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;
+++ /dev/null
-// 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;
-}
-
TypeOfResize from Aspect,
FillMethod from Aspect,
Handle from Aspect,
- PixMap from Aspect,
Ratio from Quantity,
Parameter from Quantity,
NameOfColor from Quantity,
-- 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.
#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;
}
}
- // 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);
+ return Standard_False;
}
- else
+ 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)
{
- std::cerr << "Visual Type not supported!";
- // destroy the image
- XDestroyImage (pximage);
+ 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
/*--------------------------------------------------------*\
| SaveBitmap
\*--------------------------------------------------------*/
-static Standard_Boolean SaveBitmap (HBITMAP theHBitmap,
+static Standard_Boolean SaveBitmap (HBITMAP theHBitmap,
const char* theFileName)
{
- // Copy data from HBITMAP
+ // Get informations about the bitmap
BITMAP aBitmap;
+ if (GetObject (theHBitmap, sizeof(BITMAP), (LPSTR )&aBitmap) == 0)
+ {
+ return Standard_False;
+ }
- // 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 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);
}
/*--------------------------------------------------------*\
Graphic3d_WNTGraphicDevice.cxx
Graphic3d_NameOfFont.hxx
Graphic3d_PtrFrameBuffer.hxx
+Graphic3d_BufferType.hxx
---------------------------
imported PrimitiveArray;
+ imported BufferType;
imported CBitFields20;
---Purpose: Defines the C structure
--- /dev/null
+// 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 _Graphic3d_BufferType_H__
+#define _Graphic3d_BufferType_H__
+
+//! 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;
+
+#endif // _Graphic3d_BufferType_H__
PlaneAngle from Quantity,
AlienImage from AlienImage,
+ PixMap from Image,
Array1OfEdge from Aspect,
CLayer2d from Aspect,
CPlane from Graphic3d,
CStructure from Graphic3d,
CView from Graphic3d,
- CRawBufferData from Image,
+ BufferType from Graphic3d,
Structure from Graphic3d,
TextPath from Graphic3d,
TypeOfComposition from Graphic3d,
---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.
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
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
---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 ;
--- /dev/null
+// 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
+}
--- /dev/null
+// 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__
+++ /dev/null
-// 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*/
--- /dev/null
+// 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__
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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__
+++ /dev/null
-// 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_HPrivateImage_HeaderFile
-#define _Image_HPrivateImage_HeaderFile
-
-#include <NCollection_Handle.hxx>
-
-// This typedef shadows the private image storage class
-// Currently FreeImagePlus is used
-
-class fipImage;
-typedef NCollection_Handle<fipImage> Image_HPrivateImage;
-
-#endif /*_Image_HPrivateImage_HeaderFile*/
+++ /dev/null
--- 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;
-// 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
// 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);
- }
+ return (TypePtr ) _mm_malloc (theBytesCount, theAlign);
+#endif
+}
- private:
+inline void MemFreeAligned (void* thePtrAligned)
+{
+#if defined(_MSC_VER)
+ _aligned_free (thePtrAligned);
+#else
+ _mm_free (thePtrAligned);
+#endif
+}
- Standard_Byte* myDataPtr;
- Standard_Integer mySizeX;
- Standard_Integer mySizeY;
- Standard_Integer myBytesPerLine;
- Standard_Integer myBytesPerPixel;
+IMPLEMENT_STANDARD_HANDLE (Image_PixMap, Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap, Standard_Transient)
- };
-#endif
+// =======================================================================
+// function : Image_PixMap
+// purpose :
+// =======================================================================
+Image_PixMap::Image_PixMap()
+: myImgFormat (Image_PixMap::ImgGray),
+ myIsOwnPointer (true)
+{
+ memset (&myData, 0, sizeof(myData));
+ myData.mySizeBPP = 1;
+ myData.myTopToDown = 1;
+ setFormat (Image_PixMap::ImgGray);
+}
-#include <gp.hxx>
-#include <TCollection_AsciiString.hxx>
+// =======================================================================
+// function : ~Image_PixMap
+// purpose :
+// =======================================================================
+Image_PixMap::~Image_PixMap()
+{
+ Clear();
+}
-//=======================================================================
-//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()
+Standard_Size Image_PixMap::SizePixelBytes (const Image_PixMap::ImgFormat thePixelFormat)
{
-#ifdef HAVE_FREEIMAGE
- FREE_IMAGE_TYPE aFIType = FIT_UNKNOWN;
- int aBitsPerPixel = 0;
- switch (theType)
+ switch (thePixelFormat)
{
- 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:
+ 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:
- aFIType = FIT_BITMAP;
- aBitsPerPixel = 24;
- break;
- }
- myImage = new fipImage (aFIType, theWidth, theHeight, aBitsPerPixel);
-#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;
+ return 1;
}
- myImage = new fipImage (theWidth, theHeight, 0, aBytesPerPixel);
- //
-#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())
+// =======================================================================
+// function : setFormat
+// purpose :
+// =======================================================================
+void Image_PixMap::setFormat (Image_PixMap::ImgFormat thePixelFormat)
{
-#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
+ myImgFormat = thePixelFormat;
+ myData.mySizeBPP = SizePixelBytes (myImgFormat);
}
-//=======================================================================
-//function : Destroy
-//purpose :
-//=======================================================================
-void Image_PixMap::Destroy()
+// =======================================================================
+// function : setTopDown
+// purpose :
+// =======================================================================
+void Image_PixMap::setTopDown()
{
- myImage = Image_HPrivateImage();
+ myData.myTopRowPtr = ((myData.myTopToDown == 1 || myData.myDataPtr == NULL)
+ ? myData.myDataPtr : (myData.myDataPtr + myData.mySizeRowBytes * (myData.mySizeY - 1)));
}
-//=======================================================================
-//function : Dump
-//purpose :
-//=======================================================================
-Standard_Boolean Image_PixMap::Dump (const Standard_CString theFilename,
- const Standard_Real theGammaCorr) const
+// =======================================================================
+// 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)
{
-#ifdef HAVE_FREEIMAGE
- FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilename (theFilename);
- if (anImageFormat == FIF_UNKNOWN)
+ Clear (thePixelFormat);
+ if ((theSizeX == 0) || (theSizeY == 0) || (theDataPtr == NULL))
{
- std::cerr << "Image_PixMap, image format doesn't supported!\n";
- return Standard_False;
+ return false;
}
+ myData.mySizeX = theSizeX;
+ myData.mySizeY = theSizeY;
+ myData.mySizeRowBytes = (theSizeRowBytes != 0) ? theSizeRowBytes : (theSizeX * myData.mySizeBPP);
+ myData.myDataPtr = theDataPtr;
+ myIsOwnPointer = false;
+ setTopDown();
+ return true;
+}
- Standard_Boolean isCopied = Standard_False;
- Image_HPrivateImage anImageToDump = myImage;
- if (Abs (theGammaCorr - 1.0) > gp::Resolution())
+// =======================================================================
+// 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))
{
- if (!isCopied)
- {
- isCopied = Standard_True;
- anImageToDump = new fipImage (*myImage);
- }
- anImageToDump->adjustGamma (theGammaCorr);
+ return false;
}
-
- switch (anImageFormat)
+ myData.mySizeX = theSizeX;
+ myData.mySizeY = theSizeY;
+ myData.mySizeRowBytes = myData.mySizeX * myData.mySizeBPP;
+ if (theSizeRowBytes > myData.mySizeRowBytes)
{
- 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;
+ // use argument only if it greater
+ myData.mySizeRowBytes = theSizeRowBytes;
}
- return anImageToDump->save (theFilename);
-#else
- return myImage->savePPM (theFilename);
-#endif
+ myData.myDataPtr = MemAllocAligned<Standard_Byte*> (SizeBytes());
+ myIsOwnPointer = true;
+ setTopDown();
+ return myData.myDataPtr != NULL;
}
-Aspect_Handle Image_PixMap::PixmapID() const
+// =======================================================================
+// 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)
{
- return Aspect_Handle();
+ if (!InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes))
+ {
+ return false;
+ }
+ memset (myData.myDataPtr, (int )theValue, SizeBytes());
+ return true;
}
-void Image_PixMap::AccessBuffer (Image_CRawBufferData& theBuffer) const
+// =======================================================================
+// function : InitCopy
+// purpose :
+// =======================================================================
+bool Image_PixMap::InitCopy (const Image_PixMap& theCopy)
{
- theBuffer.widthPx = myImage->getWidth();
- theBuffer.heightPx = myImage->getHeight();
-#ifdef HAVE_FREEIMAGE
- theBuffer.rowAligmentBytes = 4; // 32 bits according to FreeImage documentation
- switch (myImage->getImageType())
+ if (&theCopy == this)
{
- 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;
+ // self-copying disallowed
+ return false;
}
- theBuffer.dataPtr = myImage->accessPixels();
-#else
- theBuffer.rowAligmentBytes = myImage->getMaxRowAligmentBytes();
- theBuffer.format = (myImage->getBytesPerPixel() == 4) ? TBGRA : TBGR;
- theBuffer.type = TUByte;
- theBuffer.dataPtr = myImage->getData();
-#endif
+ 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 : PixelColor
+// function : Clear
// purpose :
// =======================================================================
-Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
- const Standard_Integer theY) const
+void Image_PixMap::Clear (Image_PixMap::ImgFormat thePixelFormat)
{
- Quantity_Parameter aDummy;
- return PixelColor (theX, theY, aDummy);
+ 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;
}
// =======================================================================
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)
- {
- 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 (myImgFormat)
{
- switch (myImage->getImageType())
+ case ImgGrayF:
+ {
+ 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:
{
- 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 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
}
--- /dev/null
+// 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__
--- /dev/null
+// 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__
InterfaceGraphic_cPrintf.cxx
InterfaceGraphic_Palette.c
InterfaceGraphic_PrimitiveArray.hxx
-InterfaceGraphic_RawBufferData.hxx
InterfaceGraphic_telem.hxx
InterfaceGraphic_degeneration.hxx
InterfaceGraphic_tgl_all.hxx
+++ /dev/null
-// 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 */
#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>
#include <Graphic3d_Array2OfVertex.hxx>
#include <Graphic3d_Array2OfVertexN.hxx>
#include <Graphic3d_Array2OfVertexNT.hxx>
+#include <Graphic3d_BufferType.hxx>
#include <NCollection_DataMap.hxx>
class TColStd_Array1OfInteger;
class Aspect_Array1OfEdge;
class TCollection_ExtendedString;
class AlienImage_AlienImage;
+class Image_PixMap;
class TColStd_HArray1OfReal;
class Handle(OpenGl_View);
class Handle(OpenGl_Workspace);
//! 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>
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)
-{
- switch (theTFormat)
- {
- 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;
- }
-}
-
-static inline GLenum TTypeToGLEnum (const TRawBufferDataType theTType)
+inline bool getDataFormat (const Image_PixMap& theData,
+ GLenum& thePixelFormat,
+ GLenum& theDataType)
{
- switch (theTType)
+ thePixelFormat = GL_RGB;
+ theDataType = GL_UNSIGNED_BYTE;
+ switch (theData.Format())
{
- case TUByte: return GL_UNSIGNED_BYTE;
- case TFloat: return GL_FLOAT;
- 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;
}
}
-Standard_Boolean OpenGl_GraphicDriver::BufferDump (const Graphic3d_CView& ACView, Image_CRawBufferData& theBuffer)
+Standard_Boolean OpenGl_GraphicDriver::BufferDump (const Graphic3d_CView& theCView,
+ Image_PixMap& theImage,
+ const Graphic3d_BufferType& theBufferType)
{
- 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
{
GLint anAlignBack = 1;
glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack);
- if (theBuffer.rowAligmentBytes == 0)
+ 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
{
- theBuffer.rowAligmentBytes = 1;
+ // read pixels
+ glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
+ theImage.SetTopDown (false); // image bottom-up in OpenGL
}
- glPixelStorei (GL_PACK_ALIGNMENT, theBuffer.rowAligmentBytes);
- // 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
{
#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>
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.
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; }
#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>
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;
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());
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;
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;
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)
di << "Usage : " << argv[0] << " [3d|2d]" << "\n";
return 1;
}
- Handle (Aspect_Window) QAAISWindow;
+ Handle(Xw_Window) QAAISWindow;
Standard_Boolean is3d = 1;
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;
}
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;
}
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);
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]);
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;
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;
}
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)
Plotter from Graphic3d,
Window from Aspect,
PixMap from Image,
- TypeOfImage from Image,
+ BufferType from Graphic3d,
Background from Aspect,
GradientBackground from Aspect,
PlotterDriver from PlotMgt,
---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
-- 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
-- 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 )
#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>
#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);
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();
// but currently allow only dumping the window itself
if (aFBOVPSizeX != aWinWidth || aFBOVPSizeY != aWinHeight)
{
- return Handle(Image_PixMap)();
+ return Standard_False;
}
}
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)
MyView->FBOChangeViewport (aPrevFBOPtr, aPrevFBOVPSizeX, aPrevFBOVPSizeY);
}
cView->ptrFBO = aPrevFBOPtr;
- return anImageBitmap;
+ return isSuccess;
}
#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
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;
}
}
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;
#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>
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);
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);
// 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
{
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]);
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")))
{
}
}
- 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";
}
switch (aBufferType)
{
default:
- case Image_TOI_RGB:
- case Image_TOI_RGBF:
+ case Graphic3d_BT_RGB:
{
if (toShowHls)
{
}
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;
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 :
"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);
}
ColorScale from Aspect,
PrintAlgo from Aspect,
- CRawBufferData from Image,
-
+ BufferType from Graphic3d,
CBitFields8 from Graphic3d,
CView from Graphic3d,
GraphicDriver from Graphic3d,
FontAspect from OSD,
AsciiString from TCollection,
ExtendedString from TCollection,
- CGraduatedTrihedron from Graphic3d
+ CGraduatedTrihedron from Graphic3d,
+
+ PixMap from Image
raises
TransformError from Visual3d,
---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
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
#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
} // 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;
-
- 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;
+ 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;
- // 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;
}
//***//
hNewBmp = hBmp;
}
- retVal = DumpBitmapToFile (gDev, NULL,
- hNewBmp, fName);
+ retVal = DumpBitmapToFile (hNewBmp, fName);
} // end __try
__finally {
if (hNewBmp != NULL && newBmp) DeleteObject (hNewBmp);
---Keywords: Bitmap, Pixmap
inherits
- PixMap from Aspect
+ Transient from Standard
uses
Handle from Aspect,
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;
#include <WNT_Window.hxx>
-extern int DumpBitmapToFile( Handle(WNT_GraphicDevice)&, HDC, HBITMAP, char* );
+extern int DumpBitmapToFile (HBITMAP, const char* );
#include <WNT_GraphicDevice.hxx>
}
///////////////////////////////////////////////////////////////////////////////////////
-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 );
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;
}
////////////////////////////////////////////////////////////
-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);
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);
}
////////////////////////////////////////////////////////////
TypeOfResize from Aspect,
FillMethod from Aspect,
GradientFillMethod from Aspect,
- PixMap from Aspect,
+ PixMap from Image,
NameOfColor from Quantity,
Color from Quantity,
Parameter from Quantity,
-- 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;
#include <WNT_Window.ixx>
-#include <Image_PixMap.hxx>
+#include <Image_AlienPixMap.hxx>
#include <Aspect_Convert.hxx>
#include <stdio.h>
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 ***********************************//
} // 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
+ // Get informations about the bitmap
BITMAP aBitmap;
+ if (GetObject (theHBitmap, sizeof(BITMAP), (LPSTR )&aBitmap) == 0)
+ {
+ return Standard_False;
+ }
- // Get informations about the bitmap
- GetObject (theHBitmap, sizeof(BITMAP), (LPSTR )&aBitmap);
- Standard_Integer aWidth = aBitmap.bmWidth;
- Standard_Integer aHeight = aBitmap.bmHeight;
+ 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;
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 ************************************//
---Keywords: Bitmap, Pixmap, X11
inherits
- PixMap from Aspect
+ Transient from Standard
uses
Handle from Aspect,
Color from Quantity,
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;
#define xTRACE 1
+#include <TCollection_AsciiString.hxx>
+#include <Image_AlienPixMap.hxx>
+
#include <errno.h>
#include <stdio.h>
#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* );
//////////////////////////////////////////////////////////////////////////////////////////
-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();
}
}
-
////////////////////////////////////////////////////////////
-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)
+ if (winAttr.visual->c_class != TrueColor)
{
+ std::cerr << "Visual Type not supported!";
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, theGammaValue);
+ return Standard_False;
}
- else
+ 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)
{
- std::cerr << "Visual Type not supported!";
- // destroy the image
- XDestroyImage (pximage);
+ 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);
}
////////////////////////////////////////////////////////////
Handle from Aspect,
FillMethod from Aspect,
GradientFillMethod from Aspect,
- PixMap from Aspect,
+ PixMap from Image,
NameOfColor from Quantity,
Parameter from Quantity,
Ratio from Quantity,
-- 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;
#include <Xw_Cextern.hxx>
//}
#include <Aspect_Convert.hxx>
-#include <Image_PixMap.hxx>
+#include <Image_AlienPixMap.hxx>
#include <Xw_Extension.h>
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;
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 {
# 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
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