0023272: Image comparison algorithm
authorkgv <kgv@opencascade.com>
Mon, 10 Sep 2012 10:30:46 +0000 (14:30 +0400)
committerkgv <kgv@opencascade.com>
Mon, 10 Sep 2012 10:30:46 +0000 (14:30 +0400)
A new class Image_Diff for comparison of images
and a draw-command "diffimage", which compares 2 images.

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

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

ToPixMap methods now retrieve Image_PixMap as argument.

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

Eliminated Aspect <-> Image cyclic dependency

Fixed GIF dump in case of BGR32 image format

43 files changed:
src/Aspect/Aspect.cdl
src/Aspect/Aspect_PixMap.cdl [deleted file]
src/Aspect/Aspect_PixMap.cxx [deleted file]
src/Aspect/Aspect_Window.cdl
src/Draw/Draw_Window.cxx
src/Graphic3d/FILES
src/Graphic3d/Graphic3d.cdl
src/Graphic3d/Graphic3d_BufferType.hxx [moved from src/Image/Image_HPrivateImage.hxx with 71% similarity]
src/Graphic3d/Graphic3d_GraphicDriver.cdl
src/Image/FILES
src/Image/Image.cdl
src/Image/Image_AlienPixMap.cxx [new file with mode: 0644]
src/Image/Image_AlienPixMap.hxx [new file with mode: 0644]
src/Image/Image_CRawBufferData.hxx [deleted file]
src/Image/Image_Color.hxx [new file with mode: 0644]
src/Image/Image_Diff.cxx [new file with mode: 0644]
src/Image/Image_Diff.hxx [new file with mode: 0644]
src/Image/Image_PixMap.cdl [deleted file]
src/Image/Image_PixMap.cxx
src/Image/Image_PixMap.hxx [new file with mode: 0644]
src/Image/Image_PixMapData.hxx [new file with mode: 0644]
src/InterfaceGraphic/FILES
src/InterfaceGraphic/InterfaceGraphic_RawBufferData.hxx [deleted file]
src/OpenGl/OpenGl_GraphicDriver.hxx
src/OpenGl/OpenGl_GraphicDriver_7.cxx
src/OpenGl/OpenGl_Workspace.hxx
src/QADraw/QADraw.cxx
src/V3d/V3d_View.cdl
src/V3d/V3d_View.cxx
src/ViewerTest/ViewerTest.cxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
src/Visual3d/Visual3d_View.cdl
src/Visual3d/Visual3d_View.cxx
src/WNT/WNT_ImageProcessor.cxx
src/WNT/WNT_PixMap.cdl
src/WNT/WNT_PixMap.cxx
src/WNT/WNT_Window.cdl
src/WNT/WNT_Window.cxx
src/Xw/Xw_PixMap.cdl
src/Xw/Xw_PixMap.cxx
src/Xw/Xw_Window.cdl
src/Xw/Xw_Window.cxx
src/Xw/Xw_save_image.cxx

index 509cb07..39d2891 100755 (executable)
@@ -348,10 +348,6 @@ is
         deferred class Window;
         ---Purpose: Defines a window.
         ---Category: Classes
-
-        deferred class PixMap;
-        ---Purpose: Defines a pixmap(bitmap)
-        ---Category: Classes
         
         deferred class GraphicDevice;
         ---Purpose: Defines a physical graphic device allowing to
diff --git a/src/Aspect/Aspect_PixMap.cdl b/src/Aspect/Aspect_PixMap.cdl
deleted file mode 100755 (executable)
index a95d3c3..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
--- Created on: 1999-10-14
--- Created by: VKH
--- Copyright (c) 1999 Matra Datavision
--- Copyright (c) 1999-2012 OPEN CASCADE SAS
---
--- The content of this file is subject to the Open CASCADE Technology Public
--- License Version 6.5 (the "License"). You may not use the content of this file
--- except in compliance with the License. Please obtain a copy of the License
--- at http://www.opencascade.org and read it completely before using this file.
---
--- The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
--- main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
---
--- The Original Code and all software distributed under the License is
--- distributed on an "AS IS" basis, without warranty of any kind, and the
--- Initial Developer hereby disclaims all such warranties, including without
--- limitation, any warranties of merchantability, fitness for a particular
--- purpose or non-infringement. Please see the License for the specific terms
--- and conditions governing the rights and limitations under the License.
-
--- Updated:    GG IMP100701 Add the "depth" field and method
---              to the pixmap object.
-
-
-deferred class PixMap from Aspect
-inherits
-    TShared from MMgt
-    ---Purpose: This class allows the definition of a pixmap(bitmap)
-
-uses
-    Handle                from Aspect,
-    Color                 from Quantity
-
-raises
-    PixmapDefinitionError      from Aspect,
-    PixmapError           from Aspect
-is
-    Initialize ( aWidth, anHeight : Integer from Standard;
-                 aDepth           : Integer from Standard );
-    ---Level: Public
-    ---Purpose: Initializes the datas of a pixmap with a pixel size
-    -- <aWidth>,<anHeight> and depth.
-
-    Destroy ( me : mutable )
-    raises PixmapError from Aspect is deferred;
-    ---Level: Advanced
-    ---Purpose: Destroy the pixmap
-    ---Category: Methods to modify the class definition
-
-    Dump ( me ; aFilename : CString from Standard;
-           aGammaValue: Real from Standard = 1.0 )
-    returns Boolean
-    raises PixmapError from Aspect is deferred;
-    ---Level: Advanced
-    ---Purpose:
-    -- Dumps the Bitmap to an image file with
-    -- an optional gamma correction value
-    -- and returns TRUE if the dump occurs normaly.
-    ---Trigger: Raises if pixmap is not defined properly
-
-    PixelColor ( me         : in;
-                 theX, theY : in Integer from Standard )
-    returns Color from Quantity is deferred;
-    ---Purpose:
-    -- Returns the pixel color.
-
-         ----------------------------
-    -- Category: Inquire methods
-    ----------------------------
-
-    PixmapID ( me ) returns Handle from Aspect
-    is deferred;
-    ---Level: Advanced
-    ---Purpose: Returns the ID of the just created pixmap
-    ---Category: Inquire methods
-
-    Size ( me ; aWidth, anHeight : out Integer from Standard )
-    is static;
-    ---Level: Public
-    ---Purpose: Returns the allocated pixmap's size in PIXEL
-    ---Category: Inquire methods
-
-    Depth ( me ) returns Integer from Standard
-    is static;
-    ---Level: Public
-    ---Purpose: Returns the allocated pixmap's depth (planes number)
-    ---Category: Inquire methods
-fields
-    myWidth  : Integer from Standard is protected;
-    myHeight : Integer from Standard is protected;
-    myDepth     : Integer from Standard is protected;
-end PixMap;
diff --git a/src/Aspect/Aspect_PixMap.cxx b/src/Aspect/Aspect_PixMap.cxx
deleted file mode 100755 (executable)
index ea1cd94..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-// Created on: 1999-10-14
-// Created by: VKH
-// Copyright (c) 1999 Matra Datavision
-// Copyright (c) 1999-2012 OPEN CASCADE SAS
-//
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
-//
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
-//
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
-
-
-// Updated     GG IMP100701 Add the "depth" field and method
-//             to the pixmap object.
-
-
-//-Version
-
-#include <Aspect_PixMap.ixx>
-
-//-Constructor
-////////////////////////////////////////////////////////////////////
-Aspect_PixMap::Aspect_PixMap ( const Standard_Integer aWidth,
-                               const Standard_Integer anHeight,
-                              const Standard_Integer aDepth )
-{
-  myWidth = aWidth;
-  myHeight = anHeight;
-  myDepth = aDepth;
-}
-
-////////////////////////////////////////////////////////////
-void Aspect_PixMap::Size ( Standard_Integer &aWidth,
-                  Standard_Integer &anHeight ) const {
-  aWidth = myWidth;
-  anHeight = myHeight;
-}
-
-////////////////////////////////////////////////////////////
-Standard_Integer Aspect_PixMap::Depth () const { 
-  return myDepth;
-}
-
index 859836b..f939cbd 100755 (executable)
@@ -42,7 +42,6 @@ uses
         TypeOfResize       from Aspect,
         FillMethod         from Aspect,
         Handle             from Aspect,
-        PixMap             from Aspect,
         Ratio              from Quantity,
         Parameter          from Quantity,
         NameOfColor        from Quantity,
@@ -208,12 +207,6 @@ is
         --          or the area is out of the Window.
         raises WindowError from Aspect is deferred;
 
-        ToPixMap ( me )
-        returns PixMap from Aspect
-        ---Level   : Public
-        ---Purpose : dump the full contents of the window to a pixmap.
-        is deferred;
-
         Load ( me ; aFilename : CString from Standard) returns Boolean
         ---Level: Advanced
         ---Purpose: Loads the XWD file to this Window.
index 0a7c0d0..03a6a78 100755 (executable)
@@ -34,7 +34,7 @@
 #include <Draw_Interpretor.hxx>
 #include <Draw_Appli.hxx>
 #include <TCollection_AsciiString.hxx>
-#include <Image_PixMap.hxx>
+#include <Image_AlienPixMap.hxx>
 
 extern Draw_Interpretor theCommands;
 extern Standard_Boolean Draw_VirtualWindows;
@@ -717,38 +717,43 @@ Standard_Boolean Draw_Window::Save (const char* theFileName) const
     }
   }
 
-  // find the image
-  XImage* pximage = XGetImage (Draw_WindowDisplay, GetDrawable(),
-                               0, 0, winAttr.width, winAttr.height,
-                               AllPlanes, ZPixmap);
-  if (pximage == NULL)
+  XVisualInfo aVInfo;
+  if (XMatchVisualInfo (Draw_WindowDisplay, Draw_WindowScreen, 32, TrueColor, &aVInfo) == 0
+   && XMatchVisualInfo (Draw_WindowDisplay, Draw_WindowScreen, 24, TrueColor, &aVInfo) == 0)
   {
+    std::cerr << "24-bit TrueColor visual is not supported by server!\n";
     return Standard_False;
   }
 
-  if (winAttr.visual->c_class == TrueColor)
+  Image_AlienPixMap anImage;
+  bool isBigEndian = Image_PixMap::IsBigEndianHost();
+  const Standard_Size aSizeRowBytes = Standard_Size(winAttr.width) * 4;
+  if (!anImage.InitTrash (isBigEndian ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgBGR32,
+                          Standard_Size(winAttr.width), Standard_Size(winAttr.height), aSizeRowBytes))
   {
-    Standard_Byte* aDataPtr = (Standard_Byte* )pximage->data;
-    Handle(Image_PixMap) anImagePixMap = new Image_PixMap (aDataPtr,
-                                                           pximage->width, pximage->height,
-                                                           pximage->bytes_per_line,
-                                                           pximage->bits_per_pixel,
-                                                           Standard_True);
-    // destroy the image
-    XDestroyImage (pximage);
-
-    // save the image
-    return anImagePixMap->Dump (theFileName);
+    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
@@ -1700,63 +1705,44 @@ void DrawWindow::Clear()
 /*--------------------------------------------------------*\
 |  SaveBitmap
 \*--------------------------------------------------------*/
-static Standard_Boolean SaveBitmap (HBITMAP theHBitmap,
+static Standard_Boolean SaveBitmap (HBITMAP     theHBitmap,
                                     const char* theFileName)
 {
-  // Copy data from HBITMAP
+  // 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);
 }
 
 /*--------------------------------------------------------*\
index b985933..e095fa2 100755 (executable)
@@ -53,3 +53,4 @@ Graphic3d_AspectText3d.cxx
 Graphic3d_WNTGraphicDevice.cxx
 Graphic3d_NameOfFont.hxx
 Graphic3d_PtrFrameBuffer.hxx
+Graphic3d_BufferType.hxx
index 843f369..03e54b6 100755 (executable)
@@ -329,6 +329,7 @@ is
     ---------------------------
 
     imported PrimitiveArray;
+    imported BufferType;
 
     imported CBitFields20;
     ---Purpose: Defines the C structure
similarity index 71%
rename from src/Image/Image_HPrivateImage.hxx
rename to src/Graphic3d/Graphic3d_BufferType.hxx
index 702f83d..40c225c 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (c) 1999-2012 OPEN CASCADE SAS
+// Copyright (c) 2012 OPEN CASCADE SAS
 //
 // The content of this file is subject to the Open CASCADE Technology Public
 // License Version 6.5 (the "License"). You may not use the content of this file
 // purpose or non-infringement. Please see the License for the specific terms
 // and conditions governing the rights and limitations under the License.
 
-#ifndef _Image_HPrivateImage_HeaderFile
-#define _Image_HPrivateImage_HeaderFile
+#ifndef _Graphic3d_BufferType_H__
+#define _Graphic3d_BufferType_H__
 
-#include <NCollection_Handle.hxx>
+//! Define buffers available for dump
+typedef enum
+{
+  Graphic3d_BT_RGB,   //!< color buffer without alpha component
+  Graphic3d_BT_RGBA,  //!< color buffer
+  Graphic3d_BT_Depth  //!< depth buffer
+} Graphic3d_BufferType;
 
-// This typedef shadows the private image storage class
-// Currently FreeImagePlus is used
-
-class fipImage;
-typedef NCollection_Handle<fipImage> Image_HPrivateImage;
-
-#endif /*_Image_HPrivateImage_HeaderFile*/
+#endif // _Graphic3d_BufferType_H__
index 7d5cf4a..446ab36 100755 (executable)
@@ -71,6 +71,7 @@ uses
     PlaneAngle          from Quantity,
 
     AlienImage          from AlienImage,
+    PixMap              from Image,
 
     Array1OfEdge        from Aspect,
     CLayer2d            from Aspect,
@@ -93,7 +94,7 @@ uses
     CPlane              from Graphic3d,
     CStructure          from Graphic3d,
     CView               from Graphic3d,
-    CRawBufferData      from Image,
+    BufferType          from Graphic3d,
     Structure           from Graphic3d,
     TextPath            from Graphic3d,
     TypeOfComposition   from Graphic3d,
@@ -1008,8 +1009,9 @@ is
     ---Purpose: Change offscreen FBO viewport.
 
         BufferDump( me            : mutable;
-                    view          : CView from Graphic3d;
-                    buffer        : in out CRawBufferData from Image )
+                    theCView      : CView from Graphic3d;
+                    theImage      : in out PixMap from Image;
+                    theBufferType : BufferType from Graphic3d )
                    returns Boolean from Standard
     is deferred;
     ---Purpose: Dump active rendering buffer into specified memory buffer.
index 5b70dab..84ca817 100755 (executable)
@@ -6,5 +6,11 @@ Image_PixelAddress.cxx
 Image_PixelAddress.hxx
 Image.edl
 Image_CMPLRS.edl
-Image_CRawBufferData.hxx
-Image_HPrivateImage.hxx
+Image_PixMap.hxx
+Image_PixMap.cxx
+Image_PixMapData.hxx
+Image_Color.hxx
+Image_AlienPixMap.hxx
+Image_AlienPixMap.cxx
+Image_Diff.hxx
+Image_Diff.cxx
index 5be5645..a34e05e 100755 (executable)
@@ -88,18 +88,16 @@ is
                                    IndexPixel from Aspect,
                                    IndexPixelMapHasher );
 
-    class PixMap;
-    ---Purpose: Aspect_PixMap implementation.
-
         -----------------------------
        ---Category: Imported types:
         -----------------------------
 
        imported PixelAddress;
-
-    imported HPrivateImage;
-
-    imported CRawBufferData;
+       imported PixMap;
+       imported AlienPixMap;
+       imported PixMap_Handle;
+       imported AlienPixMap_Handle;
+       imported Diff;
 
         -----------------------------
         ---Category: The Enumerations
@@ -132,12 +130,7 @@ is
        ---Purpose: Type of dithering method.
     
     enumeration TypeOfImage is TOI_ColorImage,
-                TOI_PseudoColorImage,
-                TOI_RGB,
-                TOI_RGBA,
-                TOI_RGBF,
-                TOI_RGBAF,
-                TOI_FLOAT
+                TOI_PseudoColorImage
     end TypeOfImage ;
 
     Zoom     ( aImage         : mutable Image from Image ;
diff --git a/src/Image/Image_AlienPixMap.cxx b/src/Image/Image_AlienPixMap.cxx
new file mode 100644 (file)
index 0000000..ee5d5cb
--- /dev/null
@@ -0,0 +1,516 @@
+// Created on: 2010-09-16
+// Created by: KGV
+// Copyright (c) 2010-2012 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
+//
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
+#ifdef HAVE_CONFIG_H
+  #include <config.h>
+#endif
+
+#ifdef HAVE_FREEIMAGE
+  #include <FreeImage.h>
+
+  #ifdef _MSC_VER
+    #pragma comment( lib, "FreeImage.lib" )
+  #endif
+#endif
+
+#include <Image_AlienPixMap.hxx>
+#include <gp.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <fstream>
+
+#ifdef HAVE_FREEIMAGE
+namespace
+{
+  static Image_PixMap::ImgFormat convertFromFreeFormat (FREE_IMAGE_TYPE       theFormatFI,
+                                                        FREE_IMAGE_COLOR_TYPE theColorTypeFI,
+                                                        unsigned              theBitsPerPixel)
+  {
+    switch (theFormatFI)
+    {
+      case FIT_RGBF:   return Image_PixMap::ImgRGBF;
+      case FIT_RGBAF:  return Image_PixMap::ImgRGBAF;
+      case FIT_FLOAT:  return Image_PixMap::ImgGrayF;
+      case FIT_BITMAP:
+      {
+        switch (theColorTypeFI)
+        {
+          case FIC_MINISBLACK:
+          {
+            return Image_PixMap::ImgGray;
+          }
+          case FIC_RGB:
+          {
+            if (Image_PixMap::IsBigEndianHost())
+            {
+              return (theBitsPerPixel == 32) ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgRGB;
+            }
+            else
+            {
+              return (theBitsPerPixel == 32) ? Image_PixMap::ImgBGR32 : Image_PixMap::ImgBGR;
+            }
+          }
+          case FIC_RGBALPHA:
+          {
+            return Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
+          }
+          default:
+            return Image_PixMap::ImgUNKNOWN;
+        }
+      }
+      default:
+        return Image_PixMap::ImgUNKNOWN;
+    }
+  }
+
+  static FREE_IMAGE_TYPE convertToFreeFormat (Image_PixMap::ImgFormat theFormat)
+  {
+    switch (theFormat)
+    {
+      case Image_PixMap::ImgGrayF:
+        return FIT_FLOAT;
+      case Image_PixMap::ImgRGBAF:
+        return FIT_RGBAF;
+      case Image_PixMap::ImgRGBF:
+        return FIT_RGBF;
+      case Image_PixMap::ImgRGBA:
+      case Image_PixMap::ImgBGRA:
+      case Image_PixMap::ImgRGB32:
+      case Image_PixMap::ImgBGR32:
+      case Image_PixMap::ImgRGB:
+      case Image_PixMap::ImgBGR:
+      case Image_PixMap::ImgGray:
+        return FIT_BITMAP;
+      default:
+        return FIT_UNKNOWN;
+    }
+  }
+};
+#endif
+
+IMPLEMENT_STANDARD_HANDLE (Image_AlienPixMap, Image_PixMap)
+IMPLEMENT_STANDARD_RTTIEXT(Image_AlienPixMap, Image_PixMap)
+
+// =======================================================================
+// function : Image_AlienPixMap
+// purpose  :
+// =======================================================================
+Image_AlienPixMap::Image_AlienPixMap()
+: myLibImage (NULL)
+{
+  SetTopDown (false);
+}
+
+// =======================================================================
+// function : ~Image_AlienPixMap
+// purpose  :
+// =======================================================================
+Image_AlienPixMap::~Image_AlienPixMap()
+{
+  Clear();
+}
+
+// =======================================================================
+// function : InitWrapper
+// purpose  :
+// =======================================================================
+bool Image_AlienPixMap::InitWrapper (ImgFormat            thePixelFormat,
+                                     Standard_Byte*       theDataPtr,
+                                     const Standard_Size  theSizeX,
+                                     const Standard_Size  theSizeY,
+                                     const Standard_Size  theSizeRowBytes)
+{
+  Clear();
+  return false;
+}
+
+// =======================================================================
+// function : InitTrash
+// purpose  :
+// =======================================================================
+bool Image_AlienPixMap::InitTrash (ImgFormat           thePixelFormat,
+                                   const Standard_Size theSizeX,
+                                   const Standard_Size theSizeY,
+                                   const Standard_Size theSizeRowBytes)
+{
+  Clear();
+#ifdef HAVE_FREEIMAGE
+  FREE_IMAGE_TYPE aFormatFI = convertToFreeFormat (thePixelFormat);
+  int aBitsPerPixel = (int )Image_PixMap::SizePixelBytes (thePixelFormat) * 8;
+  if (aFormatFI == FIT_UNKNOWN)
+  {
+    aFormatFI     = FIT_BITMAP;
+    aBitsPerPixel = 24;
+  }
+
+  FIBITMAP* anImage = FreeImage_AllocateT (aFormatFI, (int )theSizeX, (int )theSizeY, aBitsPerPixel);
+  Image_PixMap::ImgFormat aFormat = convertFromFreeFormat (FreeImage_GetImageType (anImage),
+                                                           FreeImage_GetColorType (anImage),
+                                                           FreeImage_GetBPP (anImage));
+  if (thePixelFormat == Image_PixMap::ImgBGR32
+   || thePixelFormat == Image_PixMap::ImgRGB32)
+  {
+    //FreeImage_SetTransparent (anImage, FALSE);
+    aFormat = (aFormat == Image_PixMap::ImgBGRA) ? Image_PixMap::ImgBGR32 : Image_PixMap::ImgRGB32;
+  }
+
+  Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
+                             FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
+  SetTopDown (false);
+
+  // assign image after wrapper initialization (virtual Clear() called inside)
+  myLibImage = anImage;
+  return true;
+#else
+  return Image_PixMap::InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes);
+#endif
+}
+
+// =======================================================================
+// function : Clear
+// purpose  :
+// =======================================================================
+bool Image_AlienPixMap::InitCopy (const Image_PixMap& theCopy)
+{
+  if (&theCopy == this)
+  {
+    // self-copying disallowed
+    return false;
+  }
+  if (!InitTrash (theCopy.Format(), theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
+  {
+    return false;
+  }
+
+  if (myImgFormat == theCopy.Format())
+  {
+    if (myData.mySizeRowBytes == theCopy.SizeRowBytes()
+     && myData.myTopToDown    == theCopy.TopDownInc())
+    {
+      // copy with one call
+      memcpy (myData.myDataPtr, theCopy.Data(), theCopy.SizeBytes());
+      return true;
+    }
+
+    // copy row-by-row
+    const Standard_Size aRowSizeBytes = (myData.mySizeRowBytes > theCopy.SizeRowBytes())
+                                      ? theCopy.SizeRowBytes() : myData.mySizeRowBytes;
+    for (Standard_Size aRow = 0; aRow < myData.mySizeY; ++aRow)
+    {
+      memcpy (ChangeRow (aRow), theCopy.Row (aRow), aRowSizeBytes);
+    }
+    return true;
+  }
+
+  // pixel format conversion required
+  Clear();
+  return false;
+}
+
+// =======================================================================
+// function : Clear
+// purpose  :
+// =======================================================================
+void Image_AlienPixMap::Clear (ImgFormat thePixelFormat)
+{
+  Image_PixMap::Clear (thePixelFormat);
+#ifdef HAVE_FREEIMAGE
+  if (myLibImage != NULL)
+  {
+    FreeImage_Unload (myLibImage);
+    myLibImage = NULL;
+  }
+#endif
+}
+
+// =======================================================================
+// function : Load
+// purpose  :
+// =======================================================================
+bool Image_AlienPixMap::Load (const TCollection_AsciiString& theImagePath)
+{
+  Clear();
+#ifdef HAVE_FREEIMAGE
+
+  FREE_IMAGE_FORMAT aFIF = FreeImage_GetFileType (theImagePath.ToCString(), 0);
+  if (aFIF == FIF_UNKNOWN)
+  {
+    // no signature? try to guess the file format from the file extension
+    aFIF = FreeImage_GetFIFFromFilename (theImagePath.ToCString());
+  }
+  if ((aFIF == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading (aFIF))
+  {
+    // unsupported image format
+    return false;
+  }
+
+  int aLoadFlags = 0;
+  if (aFIF == FIF_GIF)
+  {
+    // 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading
+    aLoadFlags = GIF_PLAYBACK;
+  }
+  else if (aFIF == FIF_ICO)
+  {
+    // convert to 32bpp and create an alpha channel from the AND-mask when loading
+    aLoadFlags = ICO_MAKEALPHA;
+  }
+
+  FIBITMAP* anImage = FreeImage_Load (aFIF, theImagePath.ToCString(), aLoadFlags);
+  if (anImage == NULL)
+  {
+    return false;
+  }
+
+  Image_PixMap::ImgFormat aFormat = convertFromFreeFormat (FreeImage_GetImageType (anImage),
+                                                           FreeImage_GetColorType (anImage),
+                                                           FreeImage_GetBPP (anImage));
+  if (aFormat == Image_PixMap::ImgUNKNOWN)
+  {
+    //anImage = FreeImage_ConvertTo24Bits (anImage);
+    return false;
+  }
+
+  Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
+                             FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
+  SetTopDown (false);
+
+  // assign image after wrapper initialization (virtual Clear() called inside)
+  myLibImage = anImage;
+  return true;
+#else
+  return false;
+#endif
+}
+
+// =======================================================================
+// function : savePPM
+// purpose  :
+// =======================================================================
+bool Image_AlienPixMap::savePPM (const TCollection_AsciiString& theFileName) const
+{
+  if (IsEmpty())
+  {
+    return false;
+  }
+
+  // Open file
+  FILE* aFile = fopen (theFileName.ToCString(), "wb");
+  if (aFile == NULL)
+  {
+    return false;
+  }
+
+  // Write header
+  fprintf (aFile, "P6\n%d %d\n255\n", (int )SizeX(), (int )SizeY());
+  fprintf (aFile, "# Image stored by OpenCASCADE framework in linear RGB colorspace\n");
+
+  // Write pixel data
+  Quantity_Color aColor;
+  Quantity_Parameter aDummy;
+  Standard_Byte aByte;
+  for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
+  {
+    for (Standard_Size aCol = 0; aCol < SizeY(); ++aCol)
+    {
+      // extremely SLOW but universal (implemented for all supported pixel formats)
+      aColor = PixelColor (aCol, aRow, aDummy);
+      aByte = Standard_Byte(aColor.Red() * 255.0);   fwrite (&aByte, 1, 1, aFile);
+      aByte = Standard_Byte(aColor.Green() * 255.0); fwrite (&aByte, 1, 1, aFile);
+      aByte = Standard_Byte(aColor.Blue() * 255.0);  fwrite (&aByte, 1, 1, aFile);
+    }
+  }
+
+  // Close file
+  fclose (aFile);
+  return true;
+}
+
+// =======================================================================
+// function : Save
+// purpose  :
+// =======================================================================
+bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
+{
+#ifdef HAVE_FREEIMAGE
+  if (myLibImage == NULL)
+  {
+    return false;
+  }
+
+  FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilename (theFileName.ToCString());
+  if (anImageFormat == FIF_UNKNOWN)
+  {
+    std::cerr << "Image_PixMap, image format doesn't supported!\n";
+    return false;
+  }
+
+  if (IsTopDown())
+  {
+    FreeImage_FlipVertical (myLibImage);
+    SetTopDown (false);
+  }
+
+  // FreeImage doesn't provide flexible format convertion API
+  // so we should perform multiple convertions in some cases!
+  Standard_Boolean isCopied = Standard_False;
+  FIBITMAP* anImageToDump = myLibImage;
+  switch (anImageFormat)
+  {
+    case FIF_PNG:
+    case FIF_BMP:
+    {
+      if (Format() == Image_PixMap::ImgBGR32
+       || Format() == Image_PixMap::ImgRGB32)
+      {
+        // stupid FreeImage treats reserved byte as alpha if some bytes not set to 0xFF
+        Image_PixMapData<Image_ColorRGB32>& aData = Image_PixMap::EditData<Image_ColorRGB32>();
+        for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
+        {
+          for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol)
+          {
+            aData.ChangeValue (aRow, aCol).a_() = 0xFF;
+          }
+        }
+      }
+      else if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
+      {
+        anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
+      }
+      break;
+    }
+    case FIF_GIF:
+    {
+      FIBITMAP* aTmpBitmap = myLibImage;
+      if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
+      {
+        aTmpBitmap = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
+        if (aTmpBitmap == NULL)
+        {
+          return false;
+        }
+      }
+
+      if (FreeImage_GetBPP (aTmpBitmap) != 24)
+      {
+        FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (aTmpBitmap);
+        if (aTmpBitmap != myLibImage)
+        {
+          FreeImage_Unload (aTmpBitmap);
+        }
+        if (aTmpBitmap24 == NULL)
+        {
+          return false;
+        }
+        aTmpBitmap = aTmpBitmap24;
+      }
+
+      // need convertion to image with pallete (requires 24bit bitmap)
+      anImageToDump = FreeImage_ColorQuantize (aTmpBitmap, FIQ_NNQUANT);
+      if (aTmpBitmap != myLibImage)
+      {
+        FreeImage_Unload (aTmpBitmap);
+      }
+      break;
+    }
+    case FIF_EXR:
+    {
+      if (Format() == Image_PixMap::ImgGray)
+      {
+        anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_FLOAT);
+      }
+      else if (Format() == Image_PixMap::ImgRGBA
+            || Format() == Image_PixMap::ImgBGRA)
+      {
+        anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBAF);
+      }
+      else
+      {
+        FREE_IMAGE_TYPE aImgTypeFI = FreeImage_GetImageType (myLibImage);
+        if (aImgTypeFI != FIT_RGBF
+         && aImgTypeFI != FIT_RGBAF
+         && aImgTypeFI != FIT_FLOAT)
+        {
+          anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBF);
+        }
+      }
+      break;
+    }
+    default:
+    {
+      if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
+      {
+        anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
+        if (anImageToDump == NULL)
+        {
+          return false;
+        }
+      }
+
+      if (FreeImage_GetBPP (anImageToDump) != 24)
+      {
+        FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (anImageToDump);
+        if (anImageToDump != myLibImage)
+        {
+          FreeImage_Unload (anImageToDump);
+        }
+        if (aTmpBitmap24 == NULL)
+        {
+          return false;
+        }
+        anImageToDump = aTmpBitmap24;
+      }
+      break;
+    }
+  }
+
+  if (anImageToDump == NULL)
+  {
+    return false;
+  }
+
+  bool isSaved = (FreeImage_Save (anImageFormat, anImageToDump, theFileName.ToCString()) != FALSE);
+  if (anImageToDump != myLibImage)
+  {
+    FreeImage_Unload (anImageToDump);
+  }
+  return isSaved;
+#else
+  const Standard_Integer aLen = theFileName.Length();
+  if ((aLen >= 4) && (theFileName.Value (aLen - 3) == '.')
+   && TCollection_AsciiString::ISSIMILAR (theFileName.SubString (aLen - 2, aLen), "ppm"))
+  {
+    return savePPM (theFileName);
+  }
+  std::cerr << "Image_PixMap, no image library available! Image saved in PPM format.\n";
+  return savePPM (theFileName);
+#endif
+}
+
+// =======================================================================
+// function : AdjustGamma
+// purpose  :
+// =======================================================================
+Standard_EXPORT bool Image_AlienPixMap::AdjustGamma (const Standard_Real theGammaCorr)
+{
+#ifdef HAVE_FREEIMAGE
+  return FreeImage_AdjustGamma (myLibImage, theGammaCorr) != FALSE;
+#else
+  return false;
+#endif
+}
diff --git a/src/Image/Image_AlienPixMap.hxx b/src/Image/Image_AlienPixMap.hxx
new file mode 100644 (file)
index 0000000..85045b2
--- /dev/null
@@ -0,0 +1,96 @@
+// Created on: 2012-07-18
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2012 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
+//
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
+#ifndef _Image_AlienPixMap_H__
+#define _Image_AlienPixMap_H__
+
+#include <Image_PixMap.hxx>
+#include <Image_TypeOfImage.hxx>
+
+class TCollection_AsciiString;
+struct FIBITMAP;
+
+//! Image class that support file reading/writing operations using auxiliary image library.
+//! Notice that supported images format could be limited.
+class Image_AlienPixMap : public Image_PixMap
+{
+
+public:
+
+  //! Empty constructor.
+  Standard_EXPORT Image_AlienPixMap();
+
+  //! Destructor
+  Standard_EXPORT virtual ~Image_AlienPixMap();
+
+  //! Read image data from file.
+  Standard_EXPORT bool Load (const TCollection_AsciiString& theFileName);
+
+  //! Write image data to file using file extension to determine compression format.
+  Standard_EXPORT bool Save (const TCollection_AsciiString& theFileName);
+
+  //! Initialize image plane with required dimensions.
+  //! thePixelFormat - if specified pixel format doesn't supported by image library
+  //!                  than nearest supported will be used instead!
+  //! theSizeRowBytes - may be ignored by this class and required alignemnt will be used instead!
+  Standard_EXPORT virtual bool InitTrash (ImgFormat           thePixelFormat,
+                                          const Standard_Size theSizeX,
+                                          const Standard_Size theSizeY,
+                                          const Standard_Size theSizeRowBytes = 0);
+
+  //! Initialize by copying data.
+  Standard_EXPORT virtual bool InitCopy (const Image_PixMap& theCopy);
+
+  //! Method correctly deallocate internal buffer.
+  Standard_EXPORT virtual void Clear (ImgFormat thePixelFormat = ImgGray);
+
+  //! Performs gamma correction on image.
+  //! theGamma - gamma value to use; a value of 1.0 leaves the image alone
+  Standard_EXPORT bool AdjustGamma (const Standard_Real theGammaCorr);
+
+private:
+
+  FIBITMAP* myLibImage;
+
+private:
+
+  //! Copying allowed only within Handles
+  Image_AlienPixMap            (const Image_AlienPixMap& );
+  Image_AlienPixMap& operator= (const Image_AlienPixMap& );
+
+  //! Wrapper initialization is disallowed for this class (will return false in any case)!
+  //! Use only copying and allocation initializers.
+  Standard_EXPORT virtual bool InitWrapper (ImgFormat           thePixelFormat,
+                                            Standard_Byte*      theDataPtr,
+                                            const Standard_Size theSizeX,
+                                            const Standard_Size theSizeY,
+                                            const Standard_Size theSizeRowBytes);
+
+  //! Built-in PPM export
+  Standard_EXPORT bool savePPM (const TCollection_AsciiString& theFileName) const;
+
+public:
+
+  DEFINE_STANDARD_RTTI(Image_AlienPixMap) // Type definition
+
+};
+
+DEFINE_STANDARD_HANDLE(Image_AlienPixMap, Image_PixMap)
+
+#endif // _Image_AlienPixMap_H__
diff --git a/src/Image/Image_CRawBufferData.hxx b/src/Image/Image_CRawBufferData.hxx
deleted file mode 100644 (file)
index 48c137a..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 1999-2012 OPEN CASCADE SAS
-//
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
-//
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
-//
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
-
-#ifndef _Image_CRawBufferData_HeaderFile
-#define _Image_CRawBufferData_HeaderFile
-
-#include <InterfaceGraphic_RawBufferData.hxx>
-
-typedef TRawBufferData Image_CRawBufferData;
-
-#if defined(__cplusplus) || defined(c_plusplus)
-  #include <Standard_Type.hxx>
-  const Handle(Standard_Type)& TYPE(Image_CRawBufferData);
-#endif
-
-#endif /*_Image_CRawBufferData_HeaderFile*/
diff --git a/src/Image/Image_Color.hxx b/src/Image/Image_Color.hxx
new file mode 100644 (file)
index 0000000..ef58a57
--- /dev/null
@@ -0,0 +1,543 @@
+// Created on: 2012-07-18
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2012 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
+//
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
+#ifndef _Image_Color_H__
+#define _Image_Color_H__
+
+#include <Standard.hxx>
+
+//! POD structure for packed RGB color value (3 bytes)
+struct Image_ColorRGB
+{
+
+  //! Returns the number of components.
+  static Standard_Integer Length()
+  {
+    return 3;
+  }
+
+public: // access methods
+
+  //! Alias to 1st component (red intensity).
+  Standard_Byte r() const { return v[0]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_Byte g() const { return v[1]; }
+
+  //! Alias to 3rd component (blue intensity).
+  Standard_Byte b() const { return v[2]; }
+
+  //! Alias to 1st component (red intensity).
+  Standard_Byte& r() { return v[0]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_Byte& g() { return v[1]; }
+
+  //! Alias to 3rd component (blue intensity).
+  Standard_Byte& b() { return v[2]; }
+
+public:
+
+  Standard_Byte v[3];
+
+};
+
+//! POD structure for packed RGB color value (4 bytes with extra byte for alignment)
+struct Image_ColorRGB32
+{
+
+  //! Returns the number of components.
+  static Standard_Integer Length()
+  {
+    return 3;
+  }
+
+  //! Alias to 1st component (red intensity).
+  Standard_Byte r() const { return v[0]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_Byte g() const { return v[1]; }
+
+  //! Alias to 3rd component (blue intensity).
+  Standard_Byte b() const { return v[2]; }
+
+  //! Alias to 4th component (dummy).
+  Standard_Byte a_() const { return v[3]; }
+
+  //! Alias to 1st component (red intensity).
+  Standard_Byte& r() { return v[0]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_Byte& g() { return v[1]; }
+
+  //! Alias to 3rd component (blue intensity).
+  Standard_Byte& b() { return v[2]; }
+
+  //! Alias to 4th component (dummy).
+  Standard_Byte& a_() { return v[3]; }
+
+public:
+
+  Standard_Byte v[4];
+
+};
+
+//! POD structure for packed RGBA color value (4 bytes)
+struct Image_ColorRGBA
+{
+
+  //! Returns the number of components.
+  static Standard_Integer Length()
+  {
+    return 4;
+  }
+
+  //! Alias to 1st component (red intensity).
+  Standard_Byte r() const { return v[0]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_Byte g() const { return v[1]; }
+
+  //! Alias to 3rd component (blue intensity).
+  Standard_Byte b() const { return v[2]; }
+
+  //! Alias to 4th component (alpha value).
+  Standard_Byte a() const { return v[3]; }
+
+  //! Alias to 1st component (red intensity).
+  Standard_Byte& r() { return v[0]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_Byte& g() { return v[1]; }
+
+  //! Alias to 3rd component (blue intensity).
+  Standard_Byte& b() { return v[2]; }
+
+  //! Alias to 4th component (alpha value).
+  Standard_Byte& a() { return v[3]; }
+
+public:
+
+  Standard_Byte v[4];
+
+};
+
+//! POD structure for packed BGR color value (3 bytes)
+struct Image_ColorBGR
+{
+
+  //! Returns the number of components.
+  static Standard_Integer Length()
+  {
+    return 3;
+  }
+
+  //! Alias to 3rd component (red intensity).
+  Standard_Byte r() const { return v[2]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_Byte g() const { return v[1]; }
+
+  //! Alias to 1st component (blue intensity).
+  Standard_Byte b() const { return v[0]; }
+
+  //! Alias to 3rd component (red intensity).
+  Standard_Byte& r() { return v[2]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_Byte& g() { return v[1]; }
+
+  //! Alias to 1st component (blue intensity).
+  Standard_Byte& b() { return v[0]; }
+
+public:
+
+  Standard_Byte v[3];
+
+};
+
+//! POD structure for packed BGR color value (4 bytes with extra byte for alignment)
+struct Image_ColorBGR32
+{
+
+  //! Returns the number of components.
+  static Standard_Integer Length()
+  {
+    return 3;
+  }
+
+  //! Alias to 3rd component (red intensity).
+  Standard_Byte r() const { return v[2]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_Byte g() const { return v[1]; }
+
+  //! Alias to 1st component (blue intensity).
+  Standard_Byte b() const { return v[0]; }
+
+  //! Alias to 4th component (dummy).
+  Standard_Byte a_() const { return v[3]; }
+
+  //! Alias to 3rd component (red intensity).
+  Standard_Byte& r() { return v[2]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_Byte& g() { return v[1]; }
+
+  //! Alias to 1st component (blue intensity).
+  Standard_Byte& b() { return v[0]; }
+
+  //! Alias to 4th component (dummy).
+  Standard_Byte& a_() { return v[3]; }
+
+public:
+
+  Standard_Byte v[4];
+
+};
+
+//! POD structure for packed BGRA color value (4 bytes)
+struct Image_ColorBGRA
+{
+
+  //! Returns the number of components.
+  static Standard_Integer Length()
+  {
+    return 4;
+  }
+
+  //! Alias to 3rd component (red intensity).
+  Standard_Byte r() const { return v[2]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_Byte g() const { return v[1]; }
+
+  //! Alias to 1st component (blue intensity).
+  Standard_Byte b() const { return v[0]; }
+
+  //! Alias to 4th component (alpha value).
+  Standard_Byte a() const { return v[3]; }
+
+  //! Alias to 3rd component (red intensity).
+  Standard_Byte& r() { return v[2]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_Byte& g() { return v[1]; }
+
+  //! Alias to 1st component (blue intensity).
+  Standard_Byte& b() { return v[0]; }
+
+  //! Alias to 4th component (alpha value).
+  Standard_Byte& a() { return v[3]; }
+
+public:
+
+  Standard_Byte v[4];
+
+};
+
+//! POD structure for packed float RGB color value (3 floats)
+struct Image_ColorRGBF
+{
+
+  //! Returns the number of components.
+  static Standard_Integer Length()
+  {
+    return 3;
+  }
+
+  //! Alias to 1st component (red intensity).
+  Standard_ShortReal r() const { return v[0]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_ShortReal g() const { return v[1]; }
+
+  //! Alias to 3rd component (blue intensity).
+  Standard_ShortReal b() const { return v[2]; }
+
+  //! Alias to 1st component (red intensity).
+  Standard_ShortReal& r() { return v[0]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_ShortReal& g() { return v[1]; }
+
+  //! Alias to 3rd component (blue intensity).
+  Standard_ShortReal& b() { return v[2]; }
+
+public:
+
+  Standard_ShortReal v[3];
+
+};
+
+//! POD structure for packed BGR float color value (3 floats)
+struct Image_ColorBGRF
+{
+
+  //! Returns the number of components.
+  static Standard_Integer Length()
+  {
+    return 3;
+  }
+
+  //! Alias to 3rd component (red intensity).
+  Standard_ShortReal r() const { return v[2]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_ShortReal g() const { return v[1]; }
+
+  //! Alias to 1st component (blue intensity).
+  Standard_ShortReal b() const { return v[0]; }
+
+  //! Alias to 3rd component (red intensity).
+  Standard_ShortReal& r() { return v[2]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_ShortReal& g() { return v[1]; }
+
+  //! Alias to 1st component (blue intensity).
+  Standard_ShortReal& b() { return v[0]; }
+
+public:
+
+  Standard_ShortReal v[3];
+
+};
+
+//! POD structure for packed RGBA color value (4 floats)
+struct Image_ColorRGBAF
+{
+
+  //! Returns the number of components.
+  static Standard_Integer Length()
+  {
+    return 4;
+  }
+
+  //! Alias to 1st component (red intensity).
+  Standard_ShortReal r() const { return v[0]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_ShortReal g() const { return v[1]; }
+
+  //! Alias to 3rd component (blue intensity).
+  Standard_ShortReal b() const { return v[2]; }
+
+  //! Alias to 4th component (alpha value).
+  Standard_ShortReal a() const { return v[3]; }
+
+  //! Alias to 1st component (red intensity).
+  Standard_ShortReal& r() { return v[0]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_ShortReal& g() { return v[1]; }
+
+  //! Alias to 3rd component (blue intensity).
+  Standard_ShortReal& b() { return v[2]; }
+
+  //! Alias to 4th component (alpha value).
+  Standard_ShortReal& a() { return v[3]; }
+
+public:
+
+  Standard_ShortReal v[4];
+
+};
+
+//! POD structure for packed float BGRA color value (4 floats)
+struct Image_ColorBGRAF
+{
+
+  //! Returns the number of components.
+  static Standard_Integer Length()
+  {
+    return 4;
+  }
+
+  //! Alias to 3rd component (red intensity).
+  Standard_ShortReal r() const { return v[2]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_ShortReal g() const { return v[1]; }
+
+  //! Alias to 1st component (blue intensity).
+  Standard_ShortReal b() const { return v[0]; }
+
+  //! Alias to 4th component (alpha value).
+  Standard_ShortReal a() const { return v[3]; }
+
+  //! Alias to 3rd component (red intensity).
+  Standard_ShortReal& r() { return v[2]; }
+
+  //! Alias to 2nd component (green intensity).
+  Standard_ShortReal& g() { return v[1]; }
+
+  //! Alias to 1st component (blue intensity).
+  Standard_ShortReal& b() { return v[0]; }
+
+  //! Alias to 4th component (alpha value).
+  Standard_ShortReal& a() { return v[3]; }
+
+public:
+
+  Standard_ShortReal v[4];
+
+};
+
+//! Addition operator
+template<typename ColorType_t>
+inline ColorType_t Image_ColorSumm3 (const ColorType_t& theA, const ColorType_t& theB)
+{
+  ColorType_t aRes = { theA.v[0] + theB.v[0],
+                       theA.v[1] + theB.v[1],
+                       theA.v[2] + theB.v[2] };
+  return aRes;
+}
+
+inline Image_ColorRGB operator+ (const Image_ColorRGB& theA, const Image_ColorRGB& theB)
+{
+  return Image_ColorSumm3 (theA, theB);
+}
+
+inline Image_ColorBGR operator+ (const Image_ColorBGR& theA, const Image_ColorBGR& theB)
+{
+  return Image_ColorSumm3 (theA, theB);
+}
+
+inline Image_ColorRGBF operator+ (const Image_ColorRGBF& theA, const Image_ColorRGBF& theB)
+{
+  return Image_ColorSumm3 (theA, theB);
+}
+
+inline Image_ColorBGRF operator+ (const Image_ColorBGRF& theA, const Image_ColorBGRF& theB)
+{
+  return Image_ColorSumm3 (theA, theB);
+}
+
+template<typename ColorType_t>
+inline ColorType_t Image_ColorSumm4 (const ColorType_t& theA, const ColorType_t& theB)
+{
+  ColorType_t aRes = { theA.v[0] + theB.v[0],
+                       theA.v[1] + theB.v[1],
+                       theA.v[2] + theB.v[2],
+                       theA.v[3] + theB.v[3] };
+  return aRes;
+}
+
+inline Image_ColorRGBA operator+ (const Image_ColorRGBA& theA, const Image_ColorRGBA& theB)
+{
+  return Image_ColorSumm4 (theA, theB);
+}
+
+inline Image_ColorBGRA operator+ (const Image_ColorBGRA& theA, const Image_ColorBGRA& theB)
+{
+  return Image_ColorSumm4 (theA, theB);
+}
+
+inline Image_ColorRGB32 operator+ (const Image_ColorRGB32& theA, const Image_ColorRGB32& theB)
+{
+  return Image_ColorSumm4 (theA, theB);
+}
+
+inline Image_ColorBGR32 operator+ (const Image_ColorBGR32& theA, const Image_ColorBGR32& theB)
+{
+  return Image_ColorSumm4 (theA, theB);
+}
+
+inline Image_ColorRGBAF operator+ (const Image_ColorRGBAF& theA, const Image_ColorRGBAF& theB)
+{
+  return Image_ColorSumm4 (theA, theB);
+}
+
+inline Image_ColorBGRAF operator+ (const Image_ColorBGRAF& theA, const Image_ColorBGRAF& theB)
+{
+  return Image_ColorSumm4 (theA, theB);
+}
+
+//! Subtraction operator
+template<typename ColorType_t>
+inline ColorType_t Image_ColorSub3 (const ColorType_t& theA, const ColorType_t& theB)
+{
+  ColorType_t aRes = { theA.v[0] - theB.v[0],
+                       theA.v[1] - theB.v[1],
+                       theA.v[2] - theB.v[2] };
+  return aRes;
+}
+
+inline Image_ColorRGB operator- (const Image_ColorRGB& theA, const Image_ColorRGB& theB)
+{
+  return Image_ColorSub3 (theA, theB);
+}
+
+inline Image_ColorBGR operator- (const Image_ColorBGR& theA, const Image_ColorBGR& theB)
+{
+  return Image_ColorSub3 (theA, theB);
+}
+
+inline Image_ColorRGBF operator- (const Image_ColorRGBF& theA, const Image_ColorRGBF& theB)
+{
+  return Image_ColorSub3 (theA, theB);
+}
+
+inline Image_ColorBGRF operator- (const Image_ColorBGRF& theA, const Image_ColorBGRF& theB)
+{
+  return Image_ColorSub3 (theA, theB);
+}
+
+template<typename ColorType_t>
+inline ColorType_t Image_ColorSub4 (const ColorType_t& theA, const ColorType_t& theB)
+{
+  ColorType_t aRes = { theA.v[0] - theB.v[0],
+                       theA.v[1] - theB.v[1],
+                       theA.v[2] - theB.v[2],
+                       theA.v[3] - theB.v[3] };
+  return aRes;
+}
+
+inline Image_ColorRGBA operator- (const Image_ColorRGBA& theA, const Image_ColorRGBA& theB)
+{
+  return Image_ColorSub4 (theA, theB);
+}
+
+inline Image_ColorBGRA operator- (const Image_ColorBGRA& theA, const Image_ColorBGRA& theB)
+{
+  return Image_ColorSub4 (theA, theB);
+}
+
+inline Image_ColorRGB32 operator- (const Image_ColorRGB32& theA, const Image_ColorRGB32& theB)
+{
+  return Image_ColorSub4 (theA, theB);
+}
+
+inline Image_ColorBGR32 operator- (const Image_ColorBGR32& theA, const Image_ColorBGR32& theB)
+{
+  return Image_ColorSub4 (theA, theB);
+}
+
+inline Image_ColorRGBAF operator- (const Image_ColorRGBAF& theA, const Image_ColorRGBAF& theB)
+{
+  return Image_ColorSub4 (theA, theB);
+}
+
+inline Image_ColorBGRAF operator- (const Image_ColorBGRAF& theA, const Image_ColorBGRAF& theB)
+{
+  return Image_ColorSub4 (theA, theB);
+}
+
+#endif // _Image_Color_H__
diff --git a/src/Image/Image_Diff.cxx b/src/Image/Image_Diff.cxx
new file mode 100644 (file)
index 0000000..5b28f18
--- /dev/null
@@ -0,0 +1,526 @@
+// Created on: 2012-07-10
+// Created by: VRO
+// Copyright (c) 2012 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
+//
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
+#include <Image_Diff.hxx>
+#include <Image_AlienPixMap.hxx>
+
+#include <TColStd_MapIteratorOfMapOfInteger.hxx>
+
+#include <cstdlib>
+
+IMPLEMENT_STANDARD_HANDLE (Image_Diff, Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT(Image_Diff, Standard_Transient)
+
+//! Dot squared for difference of two colors
+inline Standard_Integer dotSquared (const Image_ColorRGB& theColor)
+{
+  // explicitly convert to integer
+  const Standard_Integer r = theColor.r();
+  const Standard_Integer g = theColor.g();
+  const Standard_Integer b = theColor.b();
+  return r * r + g * g + b * b;
+}
+
+//! @return true if pixel is black
+inline bool isBlack (const Image_ColorRGB& theColor)
+{
+  return theColor.r() == 0
+      && theColor.g() == 0
+      && theColor.b() == 0;
+}
+
+//! Converts a pixel position (row, column) to one integer value
+inline Standard_Size pixel2Int (const Standard_Size aRow,
+                                const Standard_Size aCol)
+{
+  return aCol + (aRow << 15);
+}
+
+//! Converts an integer value to pixel coordinates (row, column)
+inline void int2Pixel (const Standard_Size theValue,
+                       Standard_Size&      theRow,
+                       Standard_Size&      theCol)
+{
+  theRow = (theValue >> 15);
+  theCol = theValue - (theRow << 15);
+}
+
+namespace
+{
+  static const Standard_Size NEIGHBOR_PIXELS_NB = 8;
+  struct
+  {
+    Standard_Integer row_inc;
+    Standard_Integer col_inc;
+
+    inline Standard_Size pixel2Int (const Standard_Size theRowCenter,
+                                    const Standard_Size theColCenter) const
+    {
+      return ::pixel2Int (theRowCenter + Standard_Size(row_inc),
+                          theColCenter + Standard_Size(col_inc));
+    }
+
+    inline bool isBlack (const Image_PixMapData<Image_ColorRGB>& theData,
+                         const Standard_Size theRowCenter,
+                         const Standard_Size theColCenter) const
+    {
+      return ::isBlack (theData.Value (theRowCenter + Standard_Size(row_inc),
+                                       theColCenter + Standard_Size(col_inc)));
+    }
+  }
+  static const NEIGHBOR_PIXELS[NEIGHBOR_PIXELS_NB] =
+  {
+    {-1, -1}, {-1,  0}, {-1,  1},
+    { 0, -1},           { 0,  1},
+    { 1, -1}, { 1,  0}, { 1,  1}
+  };
+
+  static bool isSupportedFormat (const Image_PixMap::ImgFormat theFormat)
+  {
+    return theFormat == Image_PixMap::ImgRGB
+        || theFormat == Image_PixMap::ImgBGR
+        || theFormat == Image_PixMap::ImgRGB32
+        || theFormat == Image_PixMap::ImgBGR32
+        || theFormat == Image_PixMap::ImgRGBA
+        || theFormat == Image_PixMap::ImgBGRA;
+  }
+};
+
+// =======================================================================
+// function : Image_Diff
+// purpose  :
+// =======================================================================
+Image_Diff::Image_Diff()
+: myColorTolerance (0.0),
+  myIsBorderFilterOn (Standard_False)
+{
+  //
+}
+
+// =======================================================================
+// function : ~Image_Diff
+// purpose  :
+// =======================================================================
+Image_Diff::~Image_Diff()
+{
+  releaseGroupsOfDiffPixels();
+}
+
+// =======================================================================
+// function : Init
+// purpose  :
+// =======================================================================
+Standard_Boolean Image_Diff::Init (const Handle(Image_PixMap)& theImageRef,
+                                   const Handle(Image_PixMap)& theImageNew,
+                                   const Standard_Boolean      theToBlackWhite)
+{
+  myImageRef.Nullify();
+  myImageNew.Nullify();
+  myDiffPixels.Clear();
+  releaseGroupsOfDiffPixels();
+  if (theImageRef.IsNull()   || theImageNew.IsNull()
+   || theImageRef->IsEmpty() || theImageNew->IsEmpty()
+   || theImageRef->SizeX()   != theImageNew->SizeX()
+   || theImageRef->SizeY()   != theImageNew->SizeY()
+   || theImageRef->Format()  != theImageNew->Format())
+  {
+    std::cerr << "Images has different format or dimensions\n";
+    return Standard_False;
+  }
+  else if (!isSupportedFormat (theImageRef->Format()))
+  {
+    std::cerr << "Images has unsupported pixel format\n";
+    return Standard_False;
+  }
+  else if (theImageRef->SizeX() >= 0xFFFF
+        || theImageRef->SizeY() >= 0xFFFF)
+  {
+    std::cerr << "Image too large\n";
+    return Standard_False;
+  }
+
+  myImageRef = theImageRef;
+  myImageNew = theImageNew;
+
+  if (theToBlackWhite)
+  {
+    // Convert the images to white/black
+    const Image_ColorRGB aWhite = {{255, 255, 255}};
+    Image_PixMapData<Image_ColorRGB>& aDataRef = myImageRef->EditData<Image_ColorRGB>();
+    Image_PixMapData<Image_ColorRGB>& aDataNew = myImageNew->EditData<Image_ColorRGB>();
+    for (Standard_Size aRow = 0; aRow < aDataRef.SizeY(); ++aRow)
+    {
+      for (Standard_Size aCol = 0; aCol < aDataRef.SizeY(); ++aCol)
+      {
+        Image_ColorRGB& aPixel1 = aDataRef.ChangeValue (aRow, aCol);
+        Image_ColorRGB& aPixel2 = aDataNew.ChangeValue (aRow, aCol);
+        if (!isBlack (aPixel1))
+        {
+          aPixel1 = aWhite;
+        }
+        if (!isBlack (aPixel2))
+        {
+          aPixel2 = aWhite;
+        }
+      }
+    }
+  }
+
+  return Standard_True;
+}
+
+
+// =======================================================================
+// function : Init
+// purpose  :
+// =======================================================================
+Standard_Boolean Image_Diff::Init (const TCollection_AsciiString& theImgPathRef,
+                                   const TCollection_AsciiString& theImgPathNew,
+                                   const Standard_Boolean         theToBlackWhite)
+{
+  Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
+  Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
+  if (!anImgRef->Load (theImgPathRef)
+   || !anImgNew->Load (theImgPathNew))
+  {
+    std::cerr << "Failed to load image(s) file(s)\n";
+    return Standard_False;
+  }
+  return Init (anImgRef, anImgNew, theToBlackWhite);
+}
+
+// =======================================================================
+// function : SetColorTolerance
+// purpose  :
+// =======================================================================
+void Image_Diff::SetColorTolerance (const Standard_Real theTolerance)
+{
+  myColorTolerance = theTolerance;
+}
+
+// =======================================================================
+// function : ColorTolerance
+// purpose  :
+// =======================================================================
+Standard_Real Image_Diff::ColorTolerance() const
+{
+  return myColorTolerance;
+}
+
+// =======================================================================
+// function : SetBorderFilterOn
+// purpose  :
+// =======================================================================
+void Image_Diff::SetBorderFilterOn (const Standard_Boolean theToIgnore)
+{
+  myIsBorderFilterOn = theToIgnore;
+}
+
+// =======================================================================
+// function : IsBorderFilterOn
+// purpose  :
+// =======================================================================
+Standard_Boolean Image_Diff::IsBorderFilterOn() const
+{
+  return myIsBorderFilterOn;
+}
+
+// =======================================================================
+// function : Compare
+// purpose  :
+// =======================================================================
+Standard_Integer Image_Diff::Compare()
+{
+  // Number of different pixels (by color)
+  Standard_Integer aNbDiffColors = 0;
+  myDiffPixels.Clear();
+
+  if (myImageRef.IsNull() || myImageNew.IsNull())
+  {
+    return -1;
+  }
+
+  // Tolerance of comparison operation for color
+  // Maximum difference between colors (white - black) = 100%
+  Image_ColorRGB aDiff = {{255, 255, 255}};
+  const Standard_Integer aMaxDiffColor  = dotSquared (aDiff);
+  const Standard_Integer aDiffThreshold = Standard_Integer(Standard_Real(aMaxDiffColor) * myColorTolerance);
+
+  // we don't care about RGB/BGR/RGBA/BGRA/RGB32/BGR32 differences
+  // because we just compute summ of r g b components
+  const Image_PixMapData<Image_ColorRGB>& aDataRef = myImageRef->ReadData<Image_ColorRGB>();
+  const Image_PixMapData<Image_ColorRGB>& aDataNew = myImageNew->ReadData<Image_ColorRGB>();
+
+  // compare colors of each pixel
+  for (Standard_Size aRow = 0; aRow < myImageRef->SizeY(); ++aRow)
+  {
+    for (Standard_Size aCol = 0; aCol < myImageRef->SizeX(); ++aCol)
+    {
+      aDiff = aDataNew.Value (aRow, aCol) - aDataRef.Value (aRow, aCol);
+      if (dotSquared (aDiff) > aDiffThreshold)
+      {
+        const Standard_Size aValue = pixel2Int (aRow, aCol);
+        myDiffPixels.Append (aValue);
+        ++aNbDiffColors;
+      }
+    }
+  }
+
+  // take into account a border effect
+  if (myIsBorderFilterOn && myDiffPixels.Length() > 0)
+  {
+    aNbDiffColors = ignoreBorderEffect();
+  }
+
+  return aNbDiffColors;
+}
+
+// =======================================================================
+// function : SaveDiffImage
+// purpose  :
+// =======================================================================
+Standard_Boolean Image_Diff::SaveDiffImage (Image_PixMap& theDiffImage) const
+{
+  if (myImageRef.IsNull() || myImageNew.IsNull())
+  {
+    return Standard_False;
+  }
+
+  if (theDiffImage.IsEmpty()
+   || theDiffImage.SizeX() != myImageRef->SizeX()
+   || theDiffImage.SizeY() != myImageRef->SizeY()
+   || !isSupportedFormat (theDiffImage.Format()))
+  {
+    if (!theDiffImage.InitTrash (Image_PixMap::ImgRGB, myImageRef->SizeX(), myImageRef->SizeY()))
+    {
+      return Standard_False;
+    }
+  }
+
+  Standard_Size aRow, aCol;
+  const Image_ColorRGB aWhite = {{255, 255, 255}};
+  Image_PixMapData<Image_ColorRGB>& aDataOut = theDiffImage.EditData<Image_ColorRGB>();
+
+  // initialize black image for dump
+  memset (theDiffImage.ChangeData(), 0, theDiffImage.SizeBytes());
+  if (myGroupsOfDiffPixels.IsEmpty())
+  {
+    if (myIsBorderFilterOn)
+    {
+      return Standard_True;
+    }
+
+    for (Standard_Integer aPixelId = 0; aPixelId < myDiffPixels.Length(); ++aPixelId)
+    {
+      const Standard_Size aValue = myDiffPixels.Value (aPixelId);
+      int2Pixel (aValue, aRow, aCol);
+      aDataOut.ChangeValue (aRow, aCol) = aWhite;
+    }
+
+    return Standard_True;
+  }
+
+  Standard_Integer aGroupId = 1;
+  for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next(), ++aGroupId)
+  {
+    if (myLinearGroups.Contains (aGroupId))
+    {
+      continue; // skip linear groups
+    }
+
+    const TColStd_MapOfInteger* aGroup = aGrIter.Value();
+    for (TColStd_MapIteratorOfMapOfInteger aPixelIter(*aGroup);
+         aPixelIter.More(); aPixelIter.Next())
+    {
+      int2Pixel (aPixelIter.Key(), aRow, aCol);
+      aDataOut.ChangeValue (aRow, aCol) = aWhite;
+    }
+  }
+
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SaveDiffImage
+// purpose  :
+// =======================================================================
+Standard_Boolean Image_Diff::SaveDiffImage (const TCollection_AsciiString& theDiffPath) const
+{
+  if (myImageRef.IsNull() || myImageNew.IsNull() || theDiffPath.IsEmpty())
+  {
+    return Standard_False;
+  }
+
+  Image_AlienPixMap aDiff;
+  if (!aDiff.InitTrash (Image_PixMap::ImgRGB, myImageRef->SizeX(), myImageRef->SizeY())
+   || !SaveDiffImage (aDiff))
+  {
+    return Standard_False;
+  }
+
+  // save image
+  return aDiff.Save (theDiffPath);
+}
+
+// =======================================================================
+// function : ignoreBorderEffect
+// purpose  :
+// =======================================================================
+Standard_Integer Image_Diff::ignoreBorderEffect()
+{
+  if (myImageRef.IsNull() || myImageNew.IsNull())
+  {
+    return 0;
+  }
+
+  const Image_PixMapData<Image_ColorRGB>& aDataRef = myImageRef->ReadData<Image_ColorRGB>();
+
+  // allocate groups of different pixels
+  releaseGroupsOfDiffPixels();
+
+  // Find a different area (a set of close to each other pixels which colors differ in both images).
+  // It filters alone pixels with different color.
+  Standard_Size aRow1, aCol1, aRow2, aCol2;
+  Standard_Integer aLen1 = (myDiffPixels.Length() > 0) ? (myDiffPixels.Length() - 1) : 0;
+  for (Standard_Integer aPixelId1 = 0; aPixelId1 < aLen1; ++aPixelId1)
+  {
+    const Standard_Size aValue1 = myDiffPixels.Value (aPixelId1);
+    int2Pixel (aValue1, aRow1, aCol1);
+
+    // Check other pixels in the list looking for a neighbour of this one
+    for (Standard_Integer aPixelId2 = aPixelId1 + 1; aPixelId2 < myDiffPixels.Length(); ++aPixelId2)
+    {
+      const Standard_Size aValue2 = myDiffPixels.Value (aPixelId2);
+      int2Pixel (aValue2, aRow2, aCol2);
+      if (std::abs (ptrdiff_t (aCol1 - aCol2)) <= 1 &&
+          std::abs (ptrdiff_t (aRow1 - aRow2)) <= 1)
+      {
+        // A neighbour is found. Create a new group and add both pixels.
+        if (myGroupsOfDiffPixels.IsEmpty())
+        {
+          TColStd_MapOfInteger* aGroup = new TColStd_MapOfInteger();
+          aGroup->Add (aValue1);
+          aGroup->Add (aValue2);
+          myGroupsOfDiffPixels.Append (aGroup);
+        }
+        else
+        {
+          // Find a group the pixels belong to.
+          Standard_Boolean isFound = Standard_False;
+          for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next())
+          {
+            TColStd_MapOfInteger*& aGroup = aGrIter.ChangeValue();
+            if (aGroup->Contains (aValue1))
+            {
+              aGroup->Add (aValue2);
+              isFound = Standard_True;
+              break;
+            }
+          }
+
+          if (!isFound)
+          {
+            // Create a new group
+            TColStd_MapOfInteger* aGroup = new TColStd_MapOfInteger();
+            aGroup->Add (aValue1);
+            aGroup->Add (aValue2);
+            myGroupsOfDiffPixels.Append (aGroup);
+          }
+        }
+      }
+    }
+  }
+
+  // filter linear groups which represent border of a solid shape
+  Standard_Integer aGroupId = 1;
+  for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next(), ++aGroupId)
+  {
+    Standard_Integer aNeighboursNb = 0;
+    Standard_Boolean isLine = Standard_True;
+    const TColStd_MapOfInteger* aGroup = aGrIter.Value();
+    for (TColStd_MapIteratorOfMapOfInteger aPixelIter (*aGroup); aPixelIter.More(); aPixelIter.Next())
+    {
+      int2Pixel (aPixelIter.Key(), aRow1, aCol1);
+      aNeighboursNb = 0;
+
+      // pixels of a line have only 1 or 2 neighbour pixels inside the same group
+      // check all neighbour pixels on presence in the group
+      for (Standard_Size aNgbrIter = 0; aNgbrIter < NEIGHBOR_PIXELS_NB; ++aNgbrIter)
+      {
+        if (aGroup->Contains (NEIGHBOR_PIXELS[aNgbrIter].pixel2Int (aRow1, aCol1)))
+        {
+          ++aNeighboursNb;
+        }
+      }
+
+      if (aNeighboursNb > 2)
+      {
+        isLine = Standard_False;
+        break;
+      }
+    } // for pixels inside group...
+
+    if (isLine)
+    {
+      // Test a pixel of the linear group on belonging to a solid shape.
+      // Consider neighbour pixels of the last pixel of the linear group in the 1st image.
+      // If the pixel has greater than 1 not black neighbour pixel, it is a border of a shape.
+      // Otherwise, it may be a topological edge, for example.
+      aNeighboursNb = 0;
+      for (Standard_Size aNgbrIter = 0; aNgbrIter < NEIGHBOR_PIXELS_NB; ++aNgbrIter)
+      {
+        if (!NEIGHBOR_PIXELS[aNgbrIter].isBlack (aDataRef, aRow1, aCol1))
+        {
+          ++aNeighboursNb;
+        }
+      }
+
+      if (aNeighboursNb > 1)
+      {
+        myLinearGroups.Add (aGroupId);
+      }
+    }
+  } // for groups...
+
+  // number of different groups of pixels (except linear groups)
+  Standard_Integer aNbDiffColors = 0;
+  aGroupId = 1;
+  for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next(), ++aGroupId)
+  {
+    if (!myLinearGroups.Contains (aGroupId))
+      ++aNbDiffColors;
+  }
+
+  return aNbDiffColors;
+}
+
+// =======================================================================
+// function : releaseGroupsOfDiffPixels
+// purpose  :
+// =======================================================================
+void Image_Diff::releaseGroupsOfDiffPixels()
+{
+  for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next())
+  {
+    TColStd_MapOfInteger*& aGroup = aGrIter.ChangeValue();
+    delete aGroup;
+  }
+  myGroupsOfDiffPixels.Clear();
+  myLinearGroups.Clear();
+}
diff --git a/src/Image/Image_Diff.hxx b/src/Image/Image_Diff.hxx
new file mode 100644 (file)
index 0000000..1f1541c
--- /dev/null
@@ -0,0 +1,135 @@
+// Created on: 2012-07-10
+// Created by: VRO
+// Copyright (c) 2012 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
+//
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
+#ifndef _Image_Diff_H__
+#define _Image_Diff_H__
+
+#include <Image_PixMap.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <TColStd_MapOfInteger.hxx>
+#include <NCollection_List.hxx>
+#include <NCollection_Vector.hxx>
+
+//! This class compares two images pixel-by-pixel.
+//! It uses the following methods to ignore the difference between images:
+//!  - Black/White comparison. It makes the images 2-colored before the comparison.
+//!  - Equality with tolerance. Colors of two pixels are considered the same if the
+//!    differnce of their color is less than a tolerance.
+//!  - Border filter. The algorithm ignores alone independent pixels,
+//!    which are different on both images, ignores the "border effect" -
+//!    the difference caused by triangles located at angle about 0 or 90 degrees to the user.
+//!
+//! Border filter ignores a difference in implementation of
+//! anti-aliasing and other effects on boundary of a shape.
+//! The triangles of a boundary zone are usually located so that their normals point aside the user
+//! (about 90 degree between the normal and the direction to the user's eye).
+//! Deflection of the light for such a triangle depends on implementation of the video driver.
+//! In order to skip this difference the following algorithm is used:
+//!  a) "Different" pixels are groupped and checked on "one-pixel width line".
+//!     indeed, the pixels may represent not a line, but any curve.
+//!     But the width of this curve should be not more than a pixel.
+//!     This group of pixels become a candidate to be ignored because of boundary effect.
+//!  b) The group of pixels is checked on belonging to a "shape".
+//!     Neighbour pixels are checked from the reference image.
+//!     This test confirms a fact that the group of pixels belongs to a shape and
+//!     represent a boundary of the shape.
+//!     In this case the whole group of pixels is ignored (considered as same).
+//!     Otherwise, the group of pixels may represent a geometrical curve in the viewer 3D
+//!     and should be considered as "different".
+class Image_Diff : public Standard_Transient
+{
+
+public:
+
+  //! An empty constructor. Init() should be called for initialization.
+  Standard_EXPORT Image_Diff();
+
+  //! Desctructor.
+  Standard_EXPORT virtual ~Image_Diff();
+
+  //! Initialize algorithm by two images.
+  //! @return false if images has different or unsupported pixel format.
+  Standard_EXPORT Standard_Boolean Init (const Handle(Image_PixMap)& theImageRef,
+                                         const Handle(Image_PixMap)& theImageNew,
+                                         const Standard_Boolean      theToBlackWhite = Standard_False);
+
+  //! Initialize algorithm by two images (will be loaded from files).
+  //! @return false if images couldn't be opened or their format is unsupported.
+  Standard_EXPORT Standard_Boolean Init (const TCollection_AsciiString& theImgPathRef,
+                                         const TCollection_AsciiString& theImgPathNew,
+                                         const Standard_Boolean         theToBlackWhite = Standard_False);
+
+  //! Color tolerance for equality check. Should be within range 0..1:
+  //! Corresponds to a difference between white and black colors (maximum difference).
+  //! By default, the tolerance is equal to 0 thus equality check will return false for any different colors.
+  Standard_EXPORT void SetColorTolerance (const Standard_Real theTolerance);
+
+  //! Color tolerance for equality check.
+  Standard_EXPORT Standard_Real ColorTolerance() const;
+
+  //! Sets taking into account (ignoring) a "border effect" on comparison of images.
+  //! The border effect is caused by a border of shaded shapes in the viewer 3d.
+  //! Triangles of this area are located at about 0 or 90 degrees to the user.
+  //! Therefore, they deflect light differently according to implementation of a video card driver.
+  //! This flag allows to detect such a "border" area and skip it from comparison of images.
+  //! Filter turned OFF by default.
+  Standard_EXPORT void SetBorderFilterOn (const Standard_Boolean theToIgnore);
+
+  //! Returns a flag of taking into account (ignoring) a border effect in comparison of images.
+  Standard_EXPORT Standard_Boolean IsBorderFilterOn() const;
+
+  //! Compares two images. It returns a number of different pixels (or groups of pixels).
+  //! It returns -1 if algorithm not initialized before.
+  Standard_EXPORT Standard_Integer Compare();
+
+  //! Saves a difference between two images as white pixels on black backgroud.
+  Standard_EXPORT Standard_Boolean SaveDiffImage (Image_PixMap& theDiffImage) const;
+
+  //! Saves a difference between two images as white pixels on black backgroud.
+  Standard_EXPORT Standard_Boolean SaveDiffImage (const TCollection_AsciiString& theDiffPath) const;
+
+protected:
+
+  //! Perform border filter algorithm.
+  Standard_EXPORT Standard_Integer ignoreBorderEffect();
+
+  //! Release dynamically allocated memory.
+  Standard_EXPORT void releaseGroupsOfDiffPixels();
+
+protected:
+
+  typedef NCollection_List<TColStd_MapOfInteger* > ListOfMapOfInteger;
+
+  Handle(Image_PixMap)              myImageRef;           //!< reference image to compare (from)
+  Handle(Image_PixMap)              myImageNew;           //!< new       image to compare (to)
+  Standard_Real                     myColorTolerance;     //!< tolerance for equality check (0..1, 0 - any not equal, 1 - opposite colors)
+  Standard_Boolean                  myIsBorderFilterOn;   //!< perform algorithm with border effect filter
+  ListOfMapOfInteger                myGroupsOfDiffPixels;
+  NCollection_Vector<Standard_Size> myDiffPixels;         //!< different pixels (position packed into integer)
+  TColStd_MapOfInteger              myLinearGroups;
+
+public:
+
+  DEFINE_STANDARD_RTTI(Image_Diff) // Type definition
+
+};
+
+DEFINE_STANDARD_HANDLE(Image_Diff, Standard_Transient)
+
+#endif // _Image_Diff_H__
diff --git a/src/Image/Image_PixMap.cdl b/src/Image/Image_PixMap.cdl
deleted file mode 100644 (file)
index ad528f3..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
--- Created on: 2010-09-16
--- Created by: KGV
--- Copyright (c) 2010-2012 OPEN CASCADE SAS
---
--- The content of this file is subject to the Open CASCADE Technology Public
--- License Version 6.5 (the "License"). You may not use the content of this file
--- except in compliance with the License. Please obtain a copy of the License
--- at http://www.opencascade.org and read it completely before using this file.
---
--- The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
--- main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
---
--- The Original Code and all software distributed under the License is
--- distributed on an "AS IS" basis, without warranty of any kind, and the
--- Initial Developer hereby disclaims all such warranties, including without
--- limitation, any warranties of merchantability, fitness for a particular
--- purpose or non-infringement. Please see the License for the specific terms
--- and conditions governing the rights and limitations under the License.
-
-
-class PixMap from Image
-
-       ---Version:
-
-       ---Purpose: This class defines a system-independent bitmap
-
-       ---Keywords: Bitmap, Pixmap
-
-inherits
-    PixMap         from Aspect
-
-uses
-    Handle         from Aspect,
-    TypeOfImage    from Image,
-    HPrivateImage  from Image,
-    CRawBufferData from Image,
-    Color          from Quantity,
-    Parameter      from Quantity
-
-raises
-    PixmapDefinitionError  from Aspect,
-    PixmapError            from Aspect
-
-is
-
-    Create ( theWidth, theHeight : Integer from Standard;
-             theType             : TypeOfImage from Image )
-    returns mutable PixMap from Image
-    raises PixmapDefinitionError from Aspect;
-    ---Level: Public
-    ---Purpose:
-    -- Allocate the bitmap with requested dimensions.
-    -- Allowed image types:
-    --  - Image_TOI_RGB (color image, 1 byte per component);
-    --  - Image_TOI_RGBA (color image with alpha channel);
-    --  - Image_TOI_RGBF (color image, 1 float per component);
-    --  - Image_TOI_RGBAF (color image with alpha channel);
-    --  - Image_TOI_FLOAT (grey image, 1 float per pixel).
-
-    Create ( theDataPtr          : PByte from Standard;
-             theWidth, theHeight : Integer from Standard;
-             thePitch            : Integer from Standard;
-             theBitsPerPixel     : Integer from Standard;
-             theIsTopDown        : Boolean from Standard )
-    returns mutable PixMap from Image
-    raises PixmapDefinitionError from Aspect;
-    ---Level: Public
-    ---Purpose:
-    -- Create a bitmap by copying an existing buffer.
-
-    ---------------------------------------------------
-    -- Category: Methods to modify the class definition
-    ---------------------------------------------------
-
-    Destroy ( me : mutable )
-    ---Level: Advanced
-    ---Purpose:
-    -- Destroies the Bitmap
-    ---C++: alias ~
-    ---Trigger: Raises if Bitmap is not defined properly
-    raises PixmapError from Aspect is virtual;
-
-    Dump ( me;
-           theFilename  : CString from Standard;
-           theGammaCorr : Real from Standard = 1.0 )
-    returns Boolean from Standard
-    ---Level: Advanced
-    ---Purpose:
-    -- Dumps the Bitmap to an image file with
-    -- an optional gamma correction value
-    -- and returns TRUE if the dump occurs normaly.
-    raises PixmapError from Aspect is virtual;
-
-    ----------------------------
-    -- Category: Inquire methods
-    ----------------------------
-
-    PixmapID ( me ) returns Handle from Aspect is virtual;
-    ---Level: Advanced
-    ---Purpose:
-    -- Returns NULL handle
-    ---Category: Inquire methods
-
-    ----------------------------
-    -- Category: Access methods
-    ----------------------------
-
-    AccessBuffer ( me            : in;
-                   theBufferInfo : in out CRawBufferData from Image )
-    is static;
-    ---Purpose:
-    -- Fill the structure for low-level access to the bitmap data.
-    -- It is up to you to interpret these bytes correctly!
-    -- Important notice: image stored upside-down in the memory,
-    --                   first image row is an last scanline in
-    --                   the memory buffer.
-    -- If image was created with type Image_TOI_FLOAT buffer
-    -- format will be set to TDepthComponent. You can override
-    -- this field with another one-channel buffer format because
-    -- it useless for bitmap definition.
-
-    PixelColor ( me         : in;
-                 theX, theY : in Integer from Standard )
-    returns Color from Quantity
-    is virtual;
-    ---Purpose:
-    -- Returns the pixel color. This function is relatively slow,
-    -- use AccessBuffer() instead for stream operations.
-    -- Note that this function convert input theY coordinate
-    -- to count off from top of an image (while in memory it stored
-    -- upside-down).
-
-    PixelColor ( me         : in;
-                 theX, theY : in  Integer   from Standard;
-                 theAlpha   : out Parameter from Quantity )
-    returns Color from Quantity;
-    ---Purpose:
-    -- Returns the pixel color. This function is relatively slow,
-    -- use AccessBuffer() instead for stream operations.
-    -- theAlpha argument is set to color intensity (0 - transparent, 1 - opaque)
-    -- Note that this function convert input theY coordinate
-    -- to count off from top of an image (while in memory it stored
-    -- upside-down).
-
-fields
-    myImage : HPrivateImage from Image is protected;
-end PixMap;
index 3065861..14b3f2a 100644 (file)
@@ -1,6 +1,6 @@
-// Created on: 2010-09-16
-// Created by: KGV
-// Copyright (c) 2010-2012 OPEN CASCADE SAS
+// Created on: 2012-07-18
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2012 OPEN CASCADE SAS
 //
 // The content of this file is subject to the Open CASCADE Technology Public
 // License Version 6.5 (the "License"). You may not use the content of this file
 // 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;
 }
 
 // =======================================================================
@@ -435,64 +230,130 @@ Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
                                          const Standard_Integer theY,
                                          Quantity_Parameter&    theAlpha) const
 {
-  Standard_Integer aScanlineId = myImage->getHeight() - theY - 1;
-  if (theX < 0 || (unsigned int )theX >= (unsigned int )myImage->getWidth() ||
-      theY < 0 || (unsigned int )theY >= (unsigned int )myImage->getHeight())
+  if (IsEmpty() ||
+      theX < 0 || (Standard_Size )theX >= myData.mySizeX ||
+      theY < 0 || (Standard_Size )theY >= myData.mySizeY)
   {
     theAlpha = 0.0; // transparent
     return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
   }
-#ifdef HAVE_FREEIMAGE
-  else if (myImage->getImageType() == FIT_BITMAP)
-  {
-    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
 }
diff --git a/src/Image/Image_PixMap.hxx b/src/Image/Image_PixMap.hxx
new file mode 100644 (file)
index 0000000..e0d2a41
--- /dev/null
@@ -0,0 +1,294 @@
+// Created on: 2012-07-18
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2012 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
+//
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
+#ifndef _Image_PixMap_H__
+#define _Image_PixMap_H__
+
+#include <Image_PixMapData.hxx>
+#include <Standard_Transient.hxx>
+#include <Quantity_Color.hxx>
+
+//! Class represents packed image plane.
+class Image_PixMap : public Standard_Transient
+{
+
+public:
+
+  //! This enumeration define packed image plane formats
+  typedef enum tagFormat {
+      ImgUNKNOWN = 0, //!< unsupported or unknown format
+      ImgGray    = 1, //!< 1 byte per pixel
+      ImgRGB,         //!< 3 bytes packed RGB image plane
+      ImgBGR,         //!< same as RGB but with different components order
+      ImgRGB32,       //!< 4 bytes packed RGB image plane (1 extra byte for alignment, may have undefined value)
+      ImgBGR32,       //!< same as RGB but with different components order
+      ImgRGBA,        //!< 4 bytes packed RGBA image plane
+      ImgBGRA,        //!< same as RGBA but with different components order
+      ImgGrayF,       //!< 1 float  (4-bytes) per pixel (1-component plane)
+      ImgRGBF,        //!< 3 floats (12-bytes) RGB image plane
+      ImgBGRF,        //!< same as RGBF but with different components order
+      ImgRGBAF,       //!< 4 floats (16-bytes) RGBA image plane
+      ImgBGRAF,       //!< same as RGBAF but with different components order
+  } ImgFormat;
+
+  //! Determine Big-Endian at runtime
+  static inline bool IsBigEndianHost()
+  {
+    union { int myInt; char myChar[sizeof(int)]; } aUnion;
+    aUnion.myInt = 1;
+    return !aUnion.myChar[0];
+  }
+
+public: // high-level API
+
+  inline ImgFormat Format() const
+  {
+    return myImgFormat;
+  }
+
+  //! @return image width in pixels
+  inline Standard_Size Width() const
+  {
+    return myData.mySizeX;
+  }
+
+  //! @return image height in pixels
+  inline Standard_Size Height() const
+  {
+    return myData.mySizeY;
+  }
+
+  //! @return image width in pixels
+  inline Standard_Size SizeX() const
+  {
+    return myData.mySizeX;
+  }
+
+  //! @return image height in pixels
+  inline Standard_Size SizeY() const
+  {
+    return myData.mySizeY;
+  }
+
+  //! @return width / height.
+  inline Standard_Real Ratio() const
+  {
+    return (myData.mySizeY > 0) ? (Standard_Real(myData.mySizeX) / Standard_Real(myData.mySizeY)) : 1.0;
+  }
+
+  //! @return true if data is NULL.
+  bool IsEmpty() const
+  {
+    return myData.myDataPtr == NULL;
+  }
+
+  //! Empty constructor. Initialize the NULL image plane.
+  Standard_EXPORT Image_PixMap();
+
+  //! Destructor
+  Standard_EXPORT virtual ~Image_PixMap();
+
+  //! Returns the pixel color. This function is relatively slow.
+  //! @param theX - column index from left
+  //! @param theY - row    index from top
+  //! @return the pixel color
+  inline Quantity_Color PixelColor (const Standard_Integer theX,
+                                    const Standard_Integer theY) const
+  {
+    Quantity_Parameter aDummy;
+    return PixelColor (theX, theY, aDummy);
+  }
+
+  //! Returns the pixel color. This function is relatively slow.
+  //! theAlpha argument is set to color intensity (0 - transparent, 1 - opaque)
+  Standard_EXPORT Quantity_Color PixelColor (const Standard_Integer theX,
+                                             const Standard_Integer theY,
+                                             Quantity_Parameter&    theAlpha) const;
+
+  //! Initialize image plane as wrapper over alien data.
+  //! Data will not be copied! Notice that caller should ensure
+  //! that data pointer will not be released during this wrapper lifetime.
+  //! You may call InitCopy() to perform data copying.
+  Standard_EXPORT virtual bool InitWrapper (ImgFormat            thePixelFormat,
+                                            Standard_Byte*       theDataPtr,
+                                            const Standard_Size  theSizeX,
+                                            const Standard_Size  theSizeY,
+                                            const Standard_Size  theSizeRowBytes = 0);
+
+  //! Initialize image plane with required dimensions.
+  //! Memory will be left uninitialized (performance trick).
+  Standard_EXPORT virtual bool InitTrash (ImgFormat           thePixelFormat,
+                                          const Standard_Size theSizeX,
+                                          const Standard_Size theSizeY,
+                                          const Standard_Size theSizeRowBytes = 0);
+
+  //! Initialize by copying data.
+  //! If you want to copy alien data you should create wrapper using InitWrapper() before.
+  Standard_EXPORT virtual bool InitCopy (const Image_PixMap& theCopy);
+
+  //! Initialize image plane with required dimensions.
+  //! Buffer will be zeroed (black color for most formats).
+  Standard_EXPORT bool InitZero (ImgFormat           thePixelFormat,
+                                 const Standard_Size theSizeX,
+                                 const Standard_Size theSizeY,
+                                 const Standard_Size theSizeRowBytes = 0,
+                                 const Standard_Byte theValue = 0);
+
+  //! Method correctly deallocate internal buffer.
+  Standard_EXPORT virtual void Clear (ImgFormat thePixelFormat = ImgGray);
+
+public: // low-level API for batch-processing (pixels reading / comparison / modification)
+
+  //! Returns true if image data stored from Top to the Down (default).
+  //! Some external APIs can return bottom-up data instead
+  //! (topmost scanlines starts from the bottom in memory).
+  //! Notice that access methods within this class automatically
+  //! convert input row-index to apply this flag!
+  //! You should use this flag only if interconnect with alien APIs and buffers.
+  //! @return true if image data is top-down.
+  inline bool IsTopDown() const
+  {
+    return myData.myTopToDown == 1;
+  }
+
+  //! Setup scanlines order in memory - top-down or bottom-up.
+  //! Drawers should explicitly specify this value if current state IsTopDown() was ignored!
+  //! @param theIsTopDown - top-down flag.
+  inline void SetTopDown (bool theIsTopDown)
+  {
+    myData.myTopToDown = (theIsTopDown ? 1 : Standard_Size(-1));
+    setTopDown();
+  }
+
+  //! Returns +1 if scanlines ordered in Top->Down order in memory and -1 otherwise.
+  //! @return scanline increment for Top->Down iteration
+  inline Standard_Size TopDownInc() const
+  {
+    return myData.myTopToDown;
+  }
+
+  //! @return data pointer for low-level operations (copying entire buffer, parsing with extra tools etc.).
+  inline const Standard_Byte* Data() const
+  {
+    return myData.myDataPtr;
+  }
+
+  //! @return data pointer for low-level operations (copying entire buffer, parsing with extra tools etc.).
+  inline Standard_Byte* ChangeData()
+  {
+    return myData.myDataPtr;
+  }
+
+  //! @return data pointer to requested row (first column).
+  inline const Standard_Byte* Row (const Standard_Size theRow) const
+  {
+    return myData.Row (theRow);
+  }
+
+  //! @return data pointer to requested row (first column).
+  inline Standard_Byte* ChangeRow (const Standard_Size theRow)
+  {
+    return myData.ChangeRow (theRow);
+  }
+
+  //! @return bytes reserved for one pixel (may include extra bytes for alignment).
+  inline Standard_Size SizePixelBytes() const
+  {
+    return myData.mySizeBPP;
+  }
+
+  //! @return bytes reserved for one pixel (may include extra bytes for alignment).
+  static Standard_Size SizePixelBytes (const Image_PixMap::ImgFormat thePixelFormat);
+
+  //! @return bytes reserved per row.
+  //! Could be larger than needed to store packed row (extra bytes for alignment etc.).
+  inline Standard_Size SizeRowBytes() const
+  {
+    return myData.mySizeRowBytes;
+  }
+
+  //! @return the extra bytes in the row.
+  inline Standard_Size RowExtraBytes() const
+  {
+    return myData.mySizeRowBytes - myData.mySizeX * myData.mySizeBPP;
+  }
+
+  //! Compute the maximal row alignment for current row size.
+  //! @return maximal row alignment in bytes (up to 16 bytes).
+  inline Standard_Size MaxRowAligmentBytes() const
+  {
+    return myData.MaxRowAligmentBytes();
+  }
+
+  inline Standard_Size SizeBytes() const
+  {
+    return myData.SizeBytes();
+  }
+
+  //! Access image buffer for write/read operations with specified color type.
+  template <typename ColorType_t>
+  inline Image_PixMapData<ColorType_t>& EditData()
+  {
+    return *(Image_PixMapData<ColorType_t>* )&myData;
+  }
+
+  //! Access image buffer for read operations with specified color type.
+  template <typename ColorType_t>
+  inline const Image_PixMapData<ColorType_t>& ReadData() const
+  {
+    return *(Image_PixMapData<ColorType_t>* )&myData;
+  }
+
+  //! Access image pixel with specified color type.
+  template <typename ColorType_t>
+  inline const ColorType_t& Value (const Standard_Size theRow,
+                                   const Standard_Size theCol) const
+  {
+    return ((Image_PixMapData<ColorType_t>* )&myData)->Value (theRow, theCol);
+  }
+
+protected:
+
+  //! Setup pixel format
+  Standard_EXPORT void setFormat (ImgFormat thePixelFormat);
+
+  //! Auxiliary method to setup myTopRowPtr
+  Standard_EXPORT void setTopDown();
+
+protected:
+
+  Image_PixMapData<Standard_Byte> myData;
+  ImgFormat                       myImgFormat;    //!< pixel format
+  bool                            myIsOwnPointer; //!< if data was allocated by this class - flag is true
+
+private:
+
+  //! Copying allowed only within Handles
+  Image_PixMap            (const Image_PixMap& );
+  Image_PixMap& operator= (const Image_PixMap& );
+
+public:
+
+  DEFINE_STANDARD_RTTI(Image_PixMap) // Type definition
+
+};
+
+DEFINE_STANDARD_HANDLE(Image_PixMap, Standard_Transient)
+
+#endif // _Image_PixMap_H__
diff --git a/src/Image/Image_PixMapData.hxx b/src/Image/Image_PixMapData.hxx
new file mode 100644 (file)
index 0000000..f0ee720
--- /dev/null
@@ -0,0 +1,113 @@
+// Created on: 2012-07-18
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2012 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
+//
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
+#ifndef _Image_PixMapData_H__
+#define _Image_PixMapData_H__
+
+#include <Image_Color.hxx>
+
+//! POD template structure to access image buffer
+template<typename ColorType_t>
+struct Image_PixMapData
+{
+
+  //! @return data pointer for low-level operations (copying entire buffer, parsing with extra tools etc.).
+  inline const ColorType_t* Data() const
+  {
+    return (const ColorType_t* )myDataPtr;
+  }
+
+  //! @return data pointer for low-level operations (copying entire buffer, parsing with extra tools etc.).
+  inline ColorType_t* ChangeData()
+  {
+    return (ColorType_t* )myDataPtr;
+  }
+
+  //! @return data pointer to requested row (first column).
+  inline const ColorType_t* Row (const Standard_Size theRow) const
+  {
+    return (ColorType_t* )(myTopRowPtr + mySizeRowBytes * theRow * myTopToDown);
+  }
+
+  //! @return data pointer to requested row (first column).
+  inline ColorType_t* ChangeRow (const Standard_Size theRow)
+  {
+    return (ColorType_t* )(myTopRowPtr + mySizeRowBytes * theRow * myTopToDown);
+  }
+
+  //! @return data pointer to requested position.
+  inline const ColorType_t& Value (const Standard_Size theRow,
+                                   const Standard_Size theCol) const
+  {
+    return *(const ColorType_t* )(myTopRowPtr + mySizeRowBytes * theRow * myTopToDown + mySizeBPP * theCol);
+  }
+
+  //! @return data pointer to requested position.
+  inline ColorType_t& ChangeValue (const Standard_Size theRow,
+                                   const Standard_Size theCol)
+  {
+    return *(ColorType_t* )(myTopRowPtr + mySizeRowBytes * theRow * myTopToDown + mySizeBPP * theCol);
+  }
+
+  //! Compute the maximal row alignment for current row size.
+  //! @return maximal row alignment in bytes (up to 16 bytes).
+  inline Standard_Size MaxRowAligmentBytes() const
+  {
+    Standard_Size anAlignment = 2;
+    for (; anAlignment <= 16; anAlignment <<= 1)
+    {
+      if ((mySizeRowBytes % anAlignment) != 0 || (Standard_Size(myDataPtr) % anAlignment) != 0)
+      {
+        return (anAlignment >> 1);
+      }
+    }
+    return anAlignment;
+  }
+
+  //! @return bytes allocated for the whole image plane.
+  inline Standard_Size SizeBytes() const
+  {
+    return mySizeRowBytes * mySizeY;
+  }
+
+  //! @return image width in pixels
+  inline Standard_Size SizeX() const
+  {
+    return mySizeX;
+  }
+
+  //! @return image height in pixels
+  inline Standard_Size SizeY() const
+  {
+    return mySizeY;
+  }
+
+public:
+
+  Standard_Byte* myDataPtr;      //!< pointer to the data
+  Standard_Byte* myTopRowPtr;    //!< pointer to the topmost row (depending on scanlines order in memory)
+  Standard_Size  mySizeBPP;      //!< bytes per pixel
+  Standard_Size  mySizeX;        //!< width  in pixels
+  Standard_Size  mySizeY;        //!< height in pixels
+  Standard_Size  mySizeRowBytes; //!< number of bytes per line (in most cases equal to 3 * sizeX)
+  Standard_Size  myTopToDown;    //!< image scanlines direction in memory from Top to the Down
+
+};
+
+#endif // _Image_PixMapData_H__
index da7204e..93ca56a 100755 (executable)
@@ -11,7 +11,6 @@ InterfaceGraphic_wntio.hxx
 InterfaceGraphic_cPrintf.cxx
 InterfaceGraphic_Palette.c
 InterfaceGraphic_PrimitiveArray.hxx
-InterfaceGraphic_RawBufferData.hxx
 InterfaceGraphic_telem.hxx
 InterfaceGraphic_degeneration.hxx
 InterfaceGraphic_tgl_all.hxx
diff --git a/src/InterfaceGraphic/InterfaceGraphic_RawBufferData.hxx b/src/InterfaceGraphic/InterfaceGraphic_RawBufferData.hxx
deleted file mode 100644 (file)
index bff620e..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 1991-1999 Matra Datavision
-// Copyright (c) 1999-2012 OPEN CASCADE SAS
-//
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
-//
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
-//
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
-
-#ifndef INTERFACEGRAPHIC_RawBufferData_H
-#define INTERFACEGRAPHIC_RawBufferData_H
-
-#include <Standard.hxx>
-
-// Most items are from GLenum, but values not equal!
-typedef enum
-{
-  TRGB,
-  TBGR,
-  TRGBA,
-  TBGRA,
-  TDepthComponent,
-  TRed,
-  TGreen,
-  TBlue,
-  TAlpha,
-} TRawBufferDataFormat;
-
-typedef enum
-{
-  TUByte,
-  TFloat,
-} TRawBufferDataType;
-
-struct TRawBufferData
-{
-  Standard_Integer widthPx;
-  Standard_Integer heightPx;
-  Standard_Integer rowAligmentBytes;
-  TRawBufferDataFormat format;
-  TRawBufferDataType type;
-  Standard_Address dataPtr;
-};
-
-#endif /* INTERFACEGRAPHIC_RawBufferData_H */
index 01f02b9..b704436 100644 (file)
@@ -32,7 +32,6 @@
 #include <Quantity_PlaneAngle.hxx>
 #include <Quantity_NameOfColor.hxx>
 #include <Handle_AlienImage_AlienImage.hxx>
-#include <Image_CRawBufferData.hxx>
 
 #include <Aspect_Display.hxx>
 #include <Aspect_GradientFillMethod.hxx>
@@ -69,6 +68,7 @@
 #include <Graphic3d_Array2OfVertex.hxx>
 #include <Graphic3d_Array2OfVertexN.hxx>
 #include <Graphic3d_Array2OfVertexNT.hxx>
+#include <Graphic3d_BufferType.hxx>
 #include <NCollection_DataMap.hxx>
 
 class TColStd_Array1OfInteger;
@@ -82,6 +82,7 @@ class Graphic3d_Vertex;
 class Aspect_Array1OfEdge;
 class TCollection_ExtendedString;
 class AlienImage_AlienImage;
+class Image_PixMap;
 class TColStd_HArray1OfReal;
 class Handle(OpenGl_View);
 class Handle(OpenGl_Workspace);
@@ -262,7 +263,9 @@ public:
   //! Remove offscreen FBO <br>
   Standard_EXPORT void FBORelease (const Graphic3d_CView& view, Graphic3d_PtrFrameBuffer& fboPtr);
   //! Dump active rendering buffer into specified memory buffer. <br>
-  Standard_EXPORT Standard_Boolean BufferDump (const Graphic3d_CView& view, Image_CRawBufferData& buffer);
+  Standard_EXPORT Standard_Boolean BufferDump (const Graphic3d_CView&      theCView,
+                                               Image_PixMap&               theImage,
+                                               const Graphic3d_BufferType& theBufferType);
   Standard_EXPORT void SetGLLightEnabled (const Graphic3d_CView& view,const Standard_Boolean isEnabled) const;
   Standard_EXPORT Standard_Boolean IsGLLightEnabled (const Graphic3d_CView& view) const;
   //! Clear visualization data in graphical driver and stop <br>
index d67a84f..b7e6414 100755 (executable)
@@ -284,72 +284,88 @@ void OpenGl_GraphicDriver::FBOChangeViewport (const Graphic3d_CView& ,
   aFrameBuffer->ChangeViewport (theWidth, theHeight);
 }
 
-// OpenGL 1.2 stuff
-#ifndef GL_BGR
-  #define GL_BGR  0x80E0
-#endif
-#ifndef GL_BGRA
-  #define GL_BGRA 0x80E1
-#endif
-
-static inline GLenum TFormatToGLEnum (const TRawBufferDataFormat theTFormat)
-{
-  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
   {
@@ -361,19 +377,30 @@ Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer *theFBOPtr, Im
 
   GLint anAlignBack = 1;
   glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack);
-  if (theBuffer.rowAligmentBytes == 0)
+  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
   {
index b927c46..6e9d569 100644 (file)
@@ -33,7 +33,7 @@
 #include <Aspect_Handle.hxx>
 #include <Aspect_PrintAlgo.hxx>
 #include <Graphic3d_PtrFrameBuffer.hxx>
-#include <Image_CRawBufferData.hxx>
+#include <Graphic3d_BufferType.hxx>
 
 #include <InterfaceGraphic_Graphic3d.hxx>
 #include <InterfaceGraphic_Visual3d.hxx>
@@ -53,6 +53,7 @@ class OpenGl_AspectMarker;
 class OpenGl_AspectText;
 class OpenGl_FrameBuffer;
 class OpenGl_Structure;
+class Image_PixMap;
 
 //! Reprepsents window with GL context.
 //! Provides methods to render primitives and maintan GL state.
@@ -127,7 +128,9 @@ public:
 
   Graphic3d_PtrFrameBuffer FBOCreate (const Standard_Integer theWidth, const Standard_Integer theHeight);
   void FBORelease (Graphic3d_PtrFrameBuffer theFBOPtr);
-  Standard_Boolean BufferDump (OpenGl_FrameBuffer *theFBOPtr, Image_CRawBufferData& theBuffer);
+  Standard_Boolean BufferDump (OpenGl_FrameBuffer*         theFBOPtr,
+                               Image_PixMap&               theImage,
+                               const Graphic3d_BufferType& theBufferType);
 
   void UseTransparency (const Standard_Boolean theFlag);
   Standard_Boolean& UseZBuffer()   { return myUseZBuffer; }
index 022a3cc..cd0c279 100755 (executable)
@@ -25,7 +25,7 @@
 #include <QADraw.hxx>
 #include <QADraw_DataMapOfAsciiStringOfAddress.hxx>
 #include <Draw_Interpretor.hxx>
-#include <Image_PixMap.hxx>
+#include <Image_AlienPixMap.hxx>
 #include <V3d_View.hxx>
 #include <ViewerTest.hxx>
 #include <ViewerTest_EventManager.hxx>
@@ -426,19 +426,18 @@ static Standard_Integer QAvzfit(Draw_Interpretor& di, Standard_Integer /*argc*/,
   return 0;
 }
 
-Handle(TColStd_HSequenceOfReal) GetColorOfPixel (const Handle(Aspect_PixMap) theImage,
+Handle(TColStd_HSequenceOfReal) GetColorOfPixel (const Image_PixMap&    theImage,
                                                  const Standard_Integer theCoordinateX,
                                                  const Standard_Integer theCoordinateY,
                                                  const Standard_Integer theRadius)
 {
   Handle(TColStd_HSequenceOfReal) aSeq = new TColStd_HSequenceOfReal();
-  if (theImage.IsNull()) {
+  if (theImage.IsEmpty()) {
     std::cerr << "The image is null.\n";
     return aSeq;
   }
-  Standard_Integer aWidth = 0;
-  Standard_Integer anHeight = 0;
-  theImage->Size (aWidth, anHeight);
+  Standard_Integer aWidth   = (Standard_Integer )theImage.SizeX();
+  Standard_Integer anHeight = (Standard_Integer )theImage.SizeY();
 
   Quantity_Color aColorTmp;
   for (Standard_Integer anXIter = theCoordinateX - theRadius;
@@ -456,7 +455,7 @@ Handle(TColStd_HSequenceOfReal) GetColorOfPixel (const Handle(Aspect_PixMap) the
         continue;
       }
       // Image_PixMap stores image upside-down in memory!
-      aColorTmp = theImage->PixelColor (anXIter, anYIter);
+      aColorTmp = theImage.PixelColor (anXIter, anYIter);
       aSeq->Append (aColorTmp.Red());
       aSeq->Append (aColorTmp.Green());
       aSeq->Append (aColorTmp.Blue());
@@ -482,8 +481,8 @@ static Standard_Integer QAAISGetPixelColor (Draw_Interpretor& di, Standard_Integ
   Standard_Integer QAAISXWindowSize_X = 0;
   Standard_Integer QAAISXWindowSize_Y = 0;
   QAAISWindow->Size(QAAISXWindowSize_X, QAAISXWindowSize_Y);
-  Standard_ShortReal QAAISCoordinateX = atoi (argv [1]);
-  Standard_ShortReal QAAISCoordinateY = atoi (argv [2]);
+  Standard_ShortReal QAAISCoordinateX = atof (argv [1]);
+  Standard_ShortReal QAAISCoordinateY = atof (argv [2]);
 
   Standard_ShortReal QAAISColorRED_V = 0;
   Standard_ShortReal QAAISColorGRN_V = 0;
@@ -504,9 +503,9 @@ static Standard_Integer QAAISGetPixelColor (Draw_Interpretor& di, Standard_Integ
     aRadius=0;
   }
 
-  Handle(TColStd_HSequenceOfReal) aSeq = GetColorOfPixel (QAAISView->ToPixMap (QAAISXWindowSize_X, QAAISXWindowSize_Y, Image_TOI_RGB),
-                                                          QAAISCoordinateX, QAAISCoordinateY,
-                                                          aRadius);
+  Image_PixMap anImage;
+  QAAISView->ToPixMap (anImage, QAAISXWindowSize_X, QAAISXWindowSize_Y);
+  Handle(TColStd_HSequenceOfReal) aSeq = GetColorOfPixel (anImage, QAAISCoordinateX, QAAISCoordinateY, aRadius);
   cout << "Length = " << aSeq->Length() << endl;
 
   Standard_Boolean IsNotEqual = Standard_True;
@@ -696,6 +695,7 @@ static Standard_Integer QAAISGetViewCharac (Draw_Interpretor& di, Standard_Integ
   di << "Proj on X : " << QAAISViewProjX << "; on Y: " << QAAISViewProjY << "; on Z: " << QAAISViewProjZ << "\n";
   di << "Up on X : " << QAAISViewUpX << "; on Y: " << QAAISViewUpY << "; on Z: " << QAAISViewUpZ << "\n";
   di << "At on X : " << QAAISViewAtX << "; on Y: " << QAAISViewAtY << "; on Z: " << QAAISViewAtZ << "\n";
+  return 0;
 }
 
 static Standard_Integer QAAISSetViewCharac (Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
@@ -737,7 +737,7 @@ static Standard_Integer QAAISGetColorCoord (Draw_Interpretor& di, Standard_Integ
     di << "Usage : " << argv[0] << " [3d|2d]" << "\n";
     return 1;
   }
-  Handle (Aspect_Window) QAAISWindow;
+  Handle(Xw_Window) QAAISWindow;
 
   Standard_Boolean is3d = 1;
 
@@ -748,7 +748,7 @@ static Standard_Integer QAAISGetColorCoord (Draw_Interpretor& di, Standard_Integ
       di << "You must initialize AISViewer before this command." << "\n";
       return 1;
     }
-    QAAISWindow = QAAIS_MainView -> V3d_View::Window ();
+    QAAISWindow = Handle(Xw_Window)::DownCast (QAAIS_MainView->V3d_View::Window());
     is3d = 1;
   }
 
@@ -758,7 +758,7 @@ static Standard_Integer QAAISGetColorCoord (Draw_Interpretor& di, Standard_Integ
       di << "You must initialize AIS 2D Viewer before this command." << "\n";
       return 1;
     }
-    QAAISWindow = V->Driver()->Window();
+    QAAISWindow = Handle(Xw_Window)::DownCast (V->Driver()->Window());
     is3d = 0;
   }
 
@@ -795,19 +795,20 @@ static Standard_Integer QAAISGetColorCoord (Draw_Interpretor& di, Standard_Integ
   const char **argvvv = (const char **) bufff;
   while ( is3d ? ViewerMainLoop (argccc, argvvv) : ViewerMainLoop2d (argccc, argvvv)) {
     Handle(TColStd_HSequenceOfReal) aSeq;
+    Image_PixMap anImage;
     if(is3d)
     {
       ViewerTest::GetMousePosition (QAAIS_MousePoint_X, QAAIS_MousePoint_Y);
       Handle (V3d_View) QAAIS_MainView = ViewerTest::CurrentView();
-      aSeq = GetColorOfPixel (QAAIS_MainView->ToPixMap (QAAIS_WindowSize_X, QAAIS_WindowSize_Y, Image_TOI_RGB),
-                              QAAIS_MousePoint_X, QAAIS_MousePoint_Y, 0);
+      QAAIS_MainView->ToPixMap (anImage, QAAIS_WindowSize_X, QAAIS_WindowSize_Y);
     }
     else
     {
       Viewer2dTest::GetMousePosition (QAAIS_MousePoint_X, QAAIS_MousePoint_Y);
-      aSeq = GetColorOfPixel (QAAISWindow->ToPixMap(),
-                              QAAIS_MousePoint_X, QAAIS_MousePoint_Y, 0);
+      QAAISWindow->ToPixMap (anImage);
     }
+    aSeq = GetColorOfPixel (anImage, QAAIS_MousePoint_X, QAAIS_MousePoint_Y, 0);
+
     QAAIS_ColorRED = aSeq->Value(1);
     QAAIS_ColorGRN = aSeq->Value(2);
     QAAIS_ColorBLU = aSeq->Value(3);
@@ -869,8 +870,13 @@ static int QAAISGetPixelColor2d (Draw_Interpretor& di, Standard_Integer argc, co
     di << "You must initialize AIS 2D Viewer before this command." << "\n";
     return 1;
   }
+
   // Get Color
-  Handle(Aspect_Window) QAAISWindow = V->Driver()->Window();
+  #if (defined(_WIN32) || defined(__WIN32__))
+    Handle(WNT_Window) QAAISWindow = Handle(WNT_Window)::DownCast (V->Driver()->Window());
+  #else
+    Handle(Xw_Window)  QAAISWindow = Handle(Xw_Window )::DownCast (V->Driver()->Window());
+  #endif
 
   Standard_ShortReal aCoordinateX = atoi(argv[1]);
   Standard_ShortReal aCoordinateY = atoi(argv[2]);
@@ -895,9 +901,9 @@ static int QAAISGetPixelColor2d (Draw_Interpretor& di, Standard_Integer argc, co
     aRadius=0;
   }
 
-  Handle(TColStd_HSequenceOfReal) aSeq = GetColorOfPixel (QAAISWindow->ToPixMap(),
-                                                          aCoordinateX, aCoordinateY,
-                                                          aRadius);
+  Image_PixMap anImage;
+  QAAISWindow->ToPixMap (anImage);
+  Handle(TColStd_HSequenceOfReal) aSeq = GetColorOfPixel (anImage, aCoordinateX, aCoordinateY, aRadius);
 
   Standard_Boolean IsNotEqual = Standard_True;
   Standard_Integer i;
@@ -1041,7 +1047,7 @@ static int V2dPan (Draw_Interpretor& di, int argc, const char ** argv)
     di << "use 'v2dinit' command before " << argv[0] << "\n";
     return -1;
   }
-  Viewer2dTest::CurrentView()->Pan(atof(argv[1]), atof(argv[2]));
+  Viewer2dTest::CurrentView()->Pan(atoi(argv[1]), atoi(argv[2]));
   return 0;
 }
 
@@ -1242,6 +1248,7 @@ static int QA2dGetIndexes (Draw_Interpretor& di, int /*argc*/, const char ** arg
   di << "Available font  indexes are " << aFontMin << " - " << aFontMax << "\n";
   aWindowDriver->ColorBoundIndexs(aColorMin, aColorMax);
   di << "Available color indexes are " << aColorMin << " - " << aColorMax << "\n";
+  return 0;
 }
 
 #if ! defined(WNT)
index 6bcbaa4..5406978 100755 (executable)
@@ -125,7 +125,7 @@ uses
         Plotter                           from Graphic3d,
         Window                            from Aspect,
         PixMap                            from Image,
-        TypeOfImage                       from Image,
+        BufferType                        from Graphic3d,
         Background                        from Aspect,
         GradientBackground                from Aspect,
         PlotterDriver                     from PlotMgt,
@@ -1590,8 +1590,8 @@ is
         ---Purpose: dump the view
 
         Dump ( me: mutable;
-               theFile: CString from Standard;
-               theBufferType : TypeOfImage from Image = Image_TOI_RGB )
+               theFile       : CString from Standard;
+               theBufferType : BufferType from Graphic3d = Graphic3d_BT_RGB )
     returns Boolean from Standard;
         ---Level: Public
         ---Purpose: dump the full contents of the view at the same
@@ -1600,9 +1600,9 @@ is
         --          Returns FALSE when the dump has failed
 
         Dump ( me: mutable;
-               theFile   : CString from Standard;
-               theFormat : FormatOfSheetPaper from Aspect;
-               theBufferType : TypeOfImage from Image = Image_TOI_RGB )
+               theFile       : CString from Standard;
+               theFormat     : FormatOfSheetPaper from Aspect;
+               theBufferType : BufferType from Graphic3d = Graphic3d_BT_RGB )
     returns Boolean from Standard;
         ---Level: Public
         ---Purpose: dump the full contents of the view with a
@@ -1653,16 +1653,18 @@ is
     --  Warning: Works only under Windows.
 
         ToPixMap ( me : mutable;
+                   theImage  : in out PixMap from Image;
                    theWidth  : Integer from Standard;
                    theHeight : Integer from Standard;
-                   theBufferType : TypeOfImage from Image = Image_TOI_RGB;
+                   theBufferType : BufferType from Graphic3d = Graphic3d_BT_RGB;
                    theForceCentered : Boolean from Standard = Standard_True )
-        returns PixMap from Image;
+        returns Boolean from Standard;
         ---Level   : Public
         ---Purpose : dump the full contents of the view
         --        to a pixmap of pixel size <theWidth>*<theHeight> and
         --        buffer type <theBufferType>. If <theForceCentered> is true
         --        view scene will be centered.
+        --       Pixmap will be automatically (re)allocated when needed.
 
     SetProjModel( me : mutable;
         amOdel: TypeOfProjectionModel from V3d = V3d_TPM_SCREEN )
index fab3967..a6b0e52 100755 (executable)
@@ -158,7 +158,7 @@ To solve the problem (for lack of a better solution) I make 2 passes.
 #include <Graphic3d_MapIteratorOfMapOfStructure.hxx>
 #include <Graphic3d_MapOfStructure.hxx>
 #include <Graphic3d_TextureEnv.hxx>
-#include <Image_PixMap.hxx>
+#include <Image_AlienPixMap.hxx>
 #include <V3d.hxx>
 #include <V3d_View.ixx>
 #include <Viewer_BadValue.hxx>
@@ -3482,22 +3482,20 @@ void V3d_View::ScreenCopy (const Handle(PlotMgt_PlotterDriver)& aPlotterDriver,
 #include <Visual3d_Layer.hxx>
 
 ////////////////////////////////////////////////////////////////
-Standard_Boolean V3d_View::Dump (const Standard_CString theFile,
-                                 const Image_TypeOfImage theBufferType)
+Standard_Boolean V3d_View::Dump (const Standard_CString      theFile,
+                                 const Graphic3d_BufferType& theBufferType)
 {
   Standard_Integer aWinWidth, aWinHeight;
   MyWindow->Size (aWinWidth, aWinHeight);
-
-  Handle(Aspect_PixMap) aPixMap = ToPixMap (aWinWidth, aWinHeight, theBufferType);
-  return !aPixMap.IsNull() && aPixMap->Dump (theFile);
+  Image_AlienPixMap anImage;
+  return ToPixMap (anImage, aWinWidth, aWinHeight, theBufferType) && anImage.Save (theFile);
 }
 
 ////////////////////////////////////////////////////////////////
-Standard_Boolean V3d_View::Dump (const Standard_CString theFile,
+Standard_Boolean V3d_View::Dump (const Standard_CString          theFile,
                                  const Aspect_FormatOfSheetPaper theFormat,
-                                 const Image_TypeOfImage theBufferType)
+                                 const Graphic3d_BufferType&     theBufferType)
 {
-  Standard_Boolean isDone = Standard_False;
   // convert Aspect_FormatOfSheetPaper size to pixel ...
   Quantity_Length anSPWidth, anSPHeight;
   Aspect::ValuesOfFOSP (theFormat, anSPWidth, anSPHeight);
@@ -3511,22 +3509,25 @@ Standard_Boolean V3d_View::Dump (const Standard_CString theFile,
   Quantity_Factor aScale = Min (anSPWidth / aWinWidth, anSPHeight / aWinHeight);
   aPixelWidth  = Standard_Integer (aPixelWidth  * aScale);
   aPixelHeight = Standard_Integer (aPixelHeight * aScale);
+
+  Image_AlienPixMap anImage;
+  ToPixMap (anImage, aPixelWidth, aPixelHeight, theBufferType);
+  OSD_Environment anEnvGamma ("CSF_GAMMA_CORRECTION");
+  TCollection_AsciiString strGamma (anEnvGamma.Value());
+  if (!anImage.IsEmpty() && !strGamma.IsEmpty())
   {
-    Handle(Aspect_PixMap) aBitmap = ToPixMap (aPixelWidth, aPixelHeight, theBufferType);
-    Standard_Real aGammaValue = 1.0;
-    OSD_Environment anEnvGamma ("CSF_GAMMA_CORRECTION");
-    TCollection_AsciiString strGamma (anEnvGamma.Value());
-    if (!strGamma.IsEmpty()) aGammaValue = strGamma.RealValue();
-    isDone = !aBitmap.IsNull() && aBitmap->Dump (theFile, aGammaValue);
+    Standard_Real aGammaValue = strGamma.RealValue();
+    anImage.AdjustGamma (aGammaValue);
   }
-  return isDone;
+  return anImage.Save (theFile);
 }
 
 ////////////////////////////////////////////////////////////////
-Handle(Image_PixMap) V3d_View::ToPixMap (const Standard_Integer  theWidth,
-                                         const Standard_Integer  theHeight,
-                                         const Image_TypeOfImage theBufferType,
-                                         const Standard_Boolean  theIsForceCentred)
+Standard_Boolean V3d_View::ToPixMap (Image_PixMap&               theImage,
+                                     const Standard_Integer      theWidth,
+                                     const Standard_Integer      theHeight,
+                                     const Graphic3d_BufferType& theBufferType,
+                                     const Standard_Boolean      theIsForceCentred)
 {
   // always prefer hardware accelerated offscreen buffer
   Graphic3d_CView* cView = (Graphic3d_CView* )MyView->CView();
@@ -3575,7 +3576,7 @@ Handle(Image_PixMap) V3d_View::ToPixMap (const Standard_Integer  theWidth,
     // but currently allow only dumping the window itself
     if (aFBOVPSizeX != aWinWidth || aFBOVPSizeY != aWinHeight)
     {
-      return Handle(Image_PixMap)();
+      return Standard_False;
     }
   }
 
@@ -3625,15 +3626,25 @@ Handle(Image_PixMap) V3d_View::ToPixMap (const Standard_Integer  theWidth,
   MyViewMapping = prevMapping;
   MyView->SetViewMapping (prevMapping);
 
+  Standard_Boolean isSuccess = Standard_True;
+
   // allocate image buffer for dumping
-  Image_CRawBufferData aRawBuffer;
-  Handle(Image_PixMap) anImageBitmap = new Image_PixMap (aFBOVPSizeX, aFBOVPSizeY, theBufferType);
-  anImageBitmap->AccessBuffer (aRawBuffer);
-  if (!MyView->BufferDump (aRawBuffer))
+  if (theImage.IsEmpty()
+   || (Standard_Size )aFBOVPSizeX != theImage.SizeX()
+   || (Standard_Size )aFBOVPSizeY != theImage.SizeY())
   {
-    // dump is failed!
-    anImageBitmap = Handle(Image_PixMap)();
+    bool isBigEndian = Image_PixMap::IsBigEndianHost();
+    Image_PixMap::ImgFormat aFormat = Image_PixMap::ImgUNKNOWN;
+    switch (theBufferType)
+    {
+      case Graphic3d_BT_RGB:   aFormat = isBigEndian ? Image_PixMap::ImgRGB  : Image_PixMap::ImgBGR;  break;
+      case Graphic3d_BT_RGBA:  aFormat = isBigEndian ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA; break;
+      case Graphic3d_BT_Depth: aFormat = Image_PixMap::ImgGrayF; break;
+    }
+
+    isSuccess = isSuccess && theImage.InitZero (aFormat, aFBOVPSizeX, aFBOVPSizeY);
   }
+  isSuccess = isSuccess && MyView->BufferDump (theImage, theBufferType);
 
   // FBO now useless, free resources
   if (aFBOPtr != aPrevFBOPtr)
@@ -3645,5 +3656,5 @@ Handle(Image_PixMap) V3d_View::ToPixMap (const Standard_Integer  theWidth,
     MyView->FBOChangeViewport (aPrevFBOPtr, aPrevFBOVPSizeX, aPrevFBOVPSizeY);
   }
   cView->ptrFBO = aPrevFBOPtr;
-  return anImageBitmap;
+  return isSuccess;
 }
index 148208c..d017497 100755 (executable)
@@ -54,7 +54,7 @@
 #include <AIS_ListIteratorOfListOfInteractive.hxx>
 #include <Aspect_InteriorStyle.hxx>
 #include <Graphic3d_AspectFillArea3d.hxx>
-#include <Image_PixMap.hxx>
+#include <Image_AlienPixMap.hxx>
 #include <Prs3d_ShadingAspect.hxx>
 
 #ifdef HAVE_CONFIG_H
@@ -833,22 +833,21 @@ static Standard_Integer VDump (Draw_Interpretor& di, Standard_Integer argc, cons
     return 1;
   }
 
-  Image_TypeOfImage aBufferType = Image_TOI_RGB;
-
+  Graphic3d_BufferType aBufferType = Graphic3d_BT_RGB;
   if (argc > 2)
   {
     TCollection_AsciiString aBuffTypeStr (argv[2]);
     if (TCollection_AsciiString::ISSIMILAR (aBuffTypeStr, TCollection_AsciiString ("rgb")))
     {
-      aBufferType = Image_TOI_RGB;
+      aBufferType = Graphic3d_BT_RGB;
     }
     else if (TCollection_AsciiString::ISSIMILAR (aBuffTypeStr, TCollection_AsciiString ("rgba")))
     {
-      aBufferType = Image_TOI_RGBA;
+      aBufferType = Graphic3d_BT_RGBA;
     }
     else if (TCollection_AsciiString::ISSIMILAR (aBuffTypeStr, TCollection_AsciiString ("depth")))
     {
-      aBufferType = Image_TOI_FLOAT;
+      aBufferType = Graphic3d_BT_Depth;
     }
   }
 
@@ -874,21 +873,20 @@ static Standard_Integer VDump (Draw_Interpretor& di, Standard_Integer argc, cons
     return 0;
   }
 
-  Handle(Image_PixMap) aPixMap = view->ToPixMap (aWidth, aHeight, aBufferType);
-  if (aPixMap.IsNull())
+  Image_AlienPixMap aPixMap;
+  if (!view->ToPixMap (aPixMap, aWidth, aHeight, aBufferType))
   {
     di << "Dumping failed!\n";
     return 1;
   }
 
-  Image_CRawBufferData aRawBuffer;
-  aPixMap->AccessBuffer (aRawBuffer);
-  if (aRawBuffer.widthPx != aWidth || aRawBuffer.heightPx != aHeight)
+  if (aPixMap.SizeX() != Standard_Size(aWidth)
+   || aPixMap.SizeY() != Standard_Size(aHeight))
   {
-    std::cout << "Warning! Dumped dimensions " << aRawBuffer.widthPx << "x" << aRawBuffer.heightPx
-              << " are lesser than requested " << aWidth             << "x" << aHeight << "\n";
+    std::cout << "Warning! Dumped dimensions " << aPixMap.SizeX() << "x" << aPixMap.SizeY()
+              << " are lesser than requested " << aWidth          << "x" << aHeight << "\n";
   }
-  if (!aPixMap->Dump (argv[1]))
+  if (!aPixMap.Save (argv[1]))
   {
     di << "Saving image failed!\n";
     return 1;
index d634c02..c7ac0b9 100755 (executable)
 #include <Draw.hxx>
 #include <Draw_Appli.hxx>
 #include <Aspect_PrintAlgo.hxx>
-#include <Image_PixMap.hxx>
+#include <Image_AlienPixMap.hxx>
 #include <OSD_Timer.hxx>
 #include <TColStd_SequenceOfInteger.hxx>
 #include <Visual3d_LayerItem.hxx>
 #include <V3d_LayerMgr.hxx>
 #include <V3d_LayerMgrPointer.hxx>
 #include <Aspect_TypeOfLine.hxx>
+#include <Image_Diff.hxx>
 
 #ifdef WNT
 #undef DrawText
 #endif
 
 #include <Visual3d_Layer.hxx>
+#include <cstdlib>
 
 #ifndef WNT
 #include <Graphic3d_GraphicDevice.hxx>
@@ -2151,10 +2153,8 @@ static int VPrintView (Draw_Interpretor& di, Standard_Integer argc,
   if (aMode != 0 && aMode != 1)
     aMode = 0;
 
-  Image_CRawBufferData aRawBuffer;
-  HDC anDC = CreateCompatibleDC(0);
-
   // define compatible bitmap
+  HDC anDC = CreateCompatibleDC(0);
   BITMAPINFO aBitmapData;
   memset (&aBitmapData, 0, sizeof (BITMAPINFOHEADER));
   aBitmapData.bmiHeader.biSize          = sizeof (BITMAPINFOHEADER);
@@ -2170,12 +2170,13 @@ static int VPrintView (Draw_Interpretor& di, Standard_Integer argc,
   aBitmapData.bmiHeader.biSizeImage     = 0;
 
   // Create Device Independent Bitmap
+  void* aBitsOut = NULL;
   HBITMAP aMemoryBitmap = CreateDIBSection (anDC, &aBitmapData, DIB_RGB_COLORS,
-                                            &aRawBuffer.dataPtr, NULL, 0);
+                                            &aBitsOut, NULL, 0);
   HGDIOBJ anOldBitmap   = SelectObject(anDC, aMemoryBitmap);
 
   Standard_Boolean isSaved = Standard_False, isPrinted = Standard_False;
-  if (aRawBuffer.dataPtr != 0)
+  if (aBitsOut != NULL)
   {    
     if (aMode == 0)
       isPrinted = aView->Print(anDC,1,1,0,Aspect_PA_STRETCH);
@@ -2185,11 +2186,13 @@ static int VPrintView (Draw_Interpretor& di, Standard_Integer argc,
     // succesfully printed into an intermediate buffer
     if (isPrinted)
     {
-      Handle(Image_PixMap) anImageBitmap =
-                         new Image_PixMap ((Standard_PByte)aRawBuffer.dataPtr,
-                                           aWidth, aHeight,
-                                           aWidth*3 + aWidth%4, 24, 0);
-      isSaved = anImageBitmap->Dump(aFileName.ToCString());
+      Image_PixMap aWrapper;
+      aWrapper.InitWrapper (Image_PixMap::ImgBGR, (Standard_Byte* )aBitsOut, aWidth, aHeight, aWidth * 3 + aWidth % 4);
+      aWrapper.SetTopDown (false);
+
+      Image_AlienPixMap anImageBitmap;
+      anImageBitmap.InitCopy (aWrapper);
+      isSaved = anImageBitmap.Save (aFileName);
     }
     else
     {
@@ -2898,7 +2901,9 @@ static int VReadPixel (Draw_Interpretor& theDI,
     return 1;
   }
 
-  Image_TypeOfImage aBufferType = Image_TOI_RGBA;
+  Image_PixMap::ImgFormat aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
+  Graphic3d_BufferType    aBufferType = Graphic3d_BT_RGBA;
+
   Standard_Integer aWidth, aHeight;
   aView->Window()->Size (aWidth, aHeight);
   const Standard_Integer anX = atoi (theArgVec[1]);
@@ -2916,28 +2921,34 @@ static int VReadPixel (Draw_Interpretor& theDI,
     TCollection_AsciiString aParam (theArgVec[anIter]);
     if (TCollection_AsciiString::ISSIMILAR      (aParam, TCollection_AsciiString ("rgb")))
     {
-      aBufferType = Image_TOI_RGB;
+      aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
+      aBufferType = Graphic3d_BT_RGB;
     }
     else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("hls")))
     {
-      aBufferType = Image_TOI_RGB;
+      aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
+      aBufferType = Graphic3d_BT_RGB;
       toShowHls   = Standard_True;
     }
     else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("rgbf")))
     {
-      aBufferType = Image_TOI_RGBF;
+      aFormat     = Image_PixMap::ImgRGBF;
+      aBufferType = Graphic3d_BT_RGB;
     }
     else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("rgba")))
     {
-      aBufferType = Image_TOI_RGBA;
+      aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
+      aBufferType = Graphic3d_BT_RGBA;
     }
     else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("rgbaf")))
     {
-      aBufferType = Image_TOI_RGBAF;
+      aFormat     = Image_PixMap::ImgRGBAF;
+      aBufferType = Graphic3d_BT_RGBA;
     }
     else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("depth")))
     {
-      aBufferType = Image_TOI_FLOAT;
+      aFormat     = Image_PixMap::ImgGrayF;
+      aBufferType = Graphic3d_BT_Depth;
     }
     else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("name")))
     {
@@ -2945,19 +2956,23 @@ static int VReadPixel (Draw_Interpretor& theDI,
     }
   }
 
-  Handle(Image_PixMap) anImage = aView->ToPixMap (aWidth, aHeight, aBufferType);
-  if (anImage.IsNull())
+  Image_PixMap anImage;
+  if (!anImage.InitTrash (aFormat, aWidth, aHeight))
+  {
+    std::cerr << "Image allocation failed\n";
+    return 1;
+  }
+  else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
   {
     std::cerr << "Image dump failed\n";
     return 1;
   }
 
   Quantity_Parameter anAlpha;
-  Quantity_Color aColor = anImage->PixelColor (anX, anY, anAlpha);
+  Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
   if (toShowName)
   {
-    if (aBufferType == Image_TOI_RGBA
-     || aBufferType == Image_TOI_RGBAF)
+    if (aBufferType == Graphic3d_BT_RGBA)
     {
       theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha << "\n";
     }
@@ -2971,8 +2986,7 @@ static int VReadPixel (Draw_Interpretor& theDI,
     switch (aBufferType)
     {
       default:
-      case Image_TOI_RGB:
-      case Image_TOI_RGBF:
+      case Graphic3d_BT_RGB:
       {
         if (toShowHls)
         {
@@ -2984,13 +2998,12 @@ static int VReadPixel (Draw_Interpretor& theDI,
         }
         break;
       }
-      case Image_TOI_RGBA:
-      case Image_TOI_RGBAF:
+      case Graphic3d_BT_RGBA:
       {
         theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha << "\n";
         break;
       }
-      case Image_TOI_FLOAT:
+      case Graphic3d_BT_Depth:
       {
         theDI << aColor.Red() << "\n";
         break;
@@ -3001,6 +3014,57 @@ static int VReadPixel (Draw_Interpretor& theDI,
   return 0;
 }
 
+//==============================================================================
+//function : VDiffImage
+//purpose  : The draw-command compares two images.
+//==============================================================================
+
+static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
+{
+  if (theArgNb < 6)
+  {
+    theDI << "Not enough arguments.\n";
+    return 1;
+  }
+
+  // image file names
+  const char* anImgPathRef = theArgVec[1];
+  const char* anImgPathNew = theArgVec[2];
+
+  // get string tolerance and check its validity
+  Standard_Real aTolColor = atof (theArgVec[3]);
+  if (aTolColor < 0.0)
+    aTolColor = 0.0;
+  if (aTolColor > 1.0)
+    aTolColor = 1.0;
+
+  Standard_Boolean toBlackWhite     = (atoi (theArgVec[4]) == 1);
+  Standard_Boolean isBorderFilterOn = (atoi (theArgVec[5]) == 1);
+
+  // image file of difference
+  const char* aDiffImagePath = (theArgNb >= 7) ? theArgVec[6] : NULL;
+
+  // compare the images
+  Image_Diff aComparer;
+  if (!aComparer.Init (anImgPathRef, anImgPathNew, toBlackWhite))
+  {
+    return 1;
+  }
+
+  aComparer.SetColorTolerance (aTolColor);
+  aComparer.SetBorderFilterOn (isBorderFilterOn);
+  Standard_Integer aDiffColorsNb = aComparer.Compare();
+  theDI << aDiffColorsNb << "\n";
+
+  // save image of difference
+  if (aDiffImagePath != NULL)
+  {
+    aComparer.SaveDiffImage (aDiffImagePath);
+  }
+
+  return 0;
+}
+
 //=======================================================================
 //function : ViewerCommands
 //purpose  :
@@ -3131,4 +3195,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
     " : Read pixel value for active view",
     __FILE__, VReadPixel, group);
+  theCommands.Add("diffimage",
+    "diffimage     : diffimage imageFile1 imageFile2 toleranceOfColor(0..1) blackWhite(1|0) borderFilter(1|0) [diffImageFile]",
+    __FILE__, VDiffImage, group);
 }
index 0f6b6cb..48e5864 100755 (executable)
@@ -87,8 +87,7 @@ uses
     ColorScale              from Aspect,
     PrintAlgo               from Aspect,
 
-    CRawBufferData          from Image,
-
+    BufferType              from Graphic3d,
     CBitFields8             from Graphic3d,
     CView                   from Graphic3d,
     GraphicDriver           from Graphic3d,
@@ -121,7 +120,9 @@ uses
     FontAspect              from OSD,
     AsciiString             from TCollection,
     ExtendedString          from TCollection,
-    CGraduatedTrihedron     from Graphic3d
+    CGraduatedTrihedron     from Graphic3d,
+
+    PixMap                  from Image
 
 raises
     TransformError          from Visual3d,
@@ -1238,7 +1239,8 @@ is
         ---Purpose: Change offscreen FBO viewport.
 
         BufferDump( me            : mutable;
-                    buffer        : in out CRawBufferData from Image )
+                    theImage      : in out PixMap from Image;
+                    theBufferType : BufferType from Graphic3d )
                    returns Boolean from Standard
         is static;
         ---Level: Public
index 7e2c5e2..a53786b 100755 (executable)
@@ -4277,9 +4277,10 @@ void Visual3d_View::FBOChangeViewport(Graphic3d_PtrFrameBuffer& theFBOPtr,
                                      theWidth, theHeight );
 }
 
-Standard_Boolean Visual3d_View::BufferDump (Image_CRawBufferData& theBuffer)
+Standard_Boolean Visual3d_View::BufferDump (Image_PixMap&               theImage,
+                                            const Graphic3d_BufferType& theBufferType)
 {
-  return MyGraphicDriver->BufferDump( MyCView, theBuffer);
+  return MyGraphicDriver->BufferDump (MyCView, theImage, theBufferType);
 }
 
 void Visual3d_View::EnableGLLight( const Standard_Boolean enable ) const
index 119a7b0..662eca3 100755 (executable)
@@ -43,7 +43,8 @@
 #include <Quantity_Color.hxx>
 #include <WNT_GraphicDevice.hxx>
 #include <WNT_TypeOfImage.hxx>
-#include <Image_PixMap.hxx>
+#include <Image_AlienPixMap.hxx>
+#include <TCollection_AsciiString.hxx>
 
 //***//
 #define I_SUCCESS Standard_True
@@ -285,64 +286,45 @@ int __WNT_API SaveWindowToFile (
 
 }  // end SaveWindowToFile
 
-int DumpBitmapToFile (Handle(WNT_GraphicDevice)& , HDC ,
-                      HBITMAP theHBitmap,
-                      char* theFileName)
+int DumpBitmapToFile (HBITMAP     theHBitmap,
+                      const char* theFileName)
 {
-  // Copy data from HBITMAP
+  // get informations about the bitmap
   BITMAP aBitmap;
+  if (GetObject (theHBitmap, sizeof(BITMAP), &aBitmap) == 0)
+  {
+    return I_ERROR;
+  }
 
-  // Get informations about the bitmap
-  GetObject (theHBitmap, sizeof(BITMAP), (LPSTR )&aBitmap);
-  Standard_Integer aWidth  = aBitmap.bmWidth;
-  Standard_Integer aHeight = aBitmap.bmHeight;
+  Image_AlienPixMap anImage;
+  const Standard_Size aSizeRowBytes = Standard_Size(aBitmap.bmWidth) * 4;
+  if (!anImage.InitTrash (Image_PixMap::ImgBGR32, Standard_Size(aBitmap.bmWidth), Standard_Size(aBitmap.bmHeight), aSizeRowBytes))
+  {
+    return I_ERROR;
+  }
+  anImage.SetTopDown (false);
 
   // Setup image data
   BITMAPINFOHEADER aBitmapInfo;
   memset (&aBitmapInfo, 0, sizeof(BITMAPINFOHEADER));
-  aBitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
-  aBitmapInfo.biWidth = aWidth;
-  aBitmapInfo.biHeight = aHeight; // positive means bottom-up!
-  aBitmapInfo.biPlanes = 1;
-  aBitmapInfo.biBitCount = 32;
+  aBitmapInfo.biSize        = sizeof(BITMAPINFOHEADER);
+  aBitmapInfo.biWidth       = aBitmap.bmWidth;
+  aBitmapInfo.biHeight      = aBitmap.bmHeight; // positive means bottom-up!
+  aBitmapInfo.biPlanes      = 1;
+  aBitmapInfo.biBitCount    = 32; // use 32bit for automatic word-alignment per row
   aBitmapInfo.biCompression = BI_RGB;
 
-  Standard_Integer aBytesPerLine = aWidth * 4;
-  Standard_Byte* aDataPtr = new Standard_Byte[aBytesPerLine * aHeight];
-
   // Copy the pixels
   HDC aDC = GetDC (NULL);
-  Standard_Boolean isSuccess
-    = GetDIBits (aDC,             // handle to DC
-                 theHBitmap,      // handle to bitmap
-                 0,               // first scan line to set
-                 aHeight,         // number of scan lines to copy
-                 aDataPtr,        // array for bitmap bits
-                 (LPBITMAPINFO )&aBitmapInfo, // bitmap data info
-                 DIB_RGB_COLORS   // RGB
-                 ) != 0;
-
-  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;
 }
 
 //***//
@@ -401,8 +383,7 @@ int SaveBitmapToFile (Handle(WNT_GraphicDevice)& gDev,
       hNewBmp = hBmp;
     }
 
-    retVal = DumpBitmapToFile (gDev, NULL,
-                               hNewBmp, fName);
+    retVal = DumpBitmapToFile (hNewBmp, fName);
   }  // end __try
   __finally {
     if (hNewBmp != NULL && newBmp) DeleteObject (hNewBmp);
index 32e7028..ea84798 100755 (executable)
@@ -30,7 +30,7 @@ class PixMap from WNT
     ---Keywords: Bitmap, Pixmap
 
 inherits
-    PixMap                from Aspect
+    Transient             from Standard
 
 uses
     Handle                from Aspect,
@@ -99,7 +99,10 @@ is
     returns Integer from Standard is private;
 
 fields
-    myDC       : Handle from Aspect is protected;
-    myBitmap   : Handle from Aspect is protected;
-    myWND      : Window from Aspect;
+    myDC     : Handle from Aspect is protected;
+    myBitmap : Handle from Aspect is protected;
+    myWND    : Window from Aspect;
+    myWidth  : Integer from Standard is protected;
+    myHeight : Integer from Standard is protected;
+    myDepth     : Integer from Standard is protected;
 end PixMap;
index 78e887c..8140d37 100755 (executable)
@@ -31,7 +31,7 @@
 
 #include <WNT_Window.hxx>
 
-extern int DumpBitmapToFile( Handle(WNT_GraphicDevice)&, HDC, HBITMAP, char* );
+extern int DumpBitmapToFile (HBITMAP, const char* );
 
 #include <WNT_GraphicDevice.hxx>
 
@@ -50,15 +50,16 @@ Standard_Integer WNT_PixMap::PreferedDepth(
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////
-WNT_PixMap::WNT_PixMap ( const Handle(Aspect_Window)& aWindow,
-                         const Standard_Integer aWidth,
-                         const Standard_Integer anHeight,
-                         const Standard_Integer aCDepth ) :
-Aspect_PixMap(aWidth, anHeight, PreferedDepth(aWindow, aCDepth))
+WNT_PixMap::WNT_PixMap (const Handle(Aspect_Window)& theWindow,
+                        const Standard_Integer       theWidth,
+                        const Standard_Integer       theHeight,
+                        const Standard_Integer       theDepth)
+: myWND    (theWindow),
+  myWidth  (theWidth),
+  myHeight (theHeight),
+  myDepth  (PreferedDepth (theWindow, theDepth))
 {
-  myWND = aWindow;
-
-  const Handle(WNT_Window)& hWindow = Handle(WNT_Window)::DownCast(aWindow);
+  const Handle(WNT_Window)& hWindow = Handle(WNT_Window)::DownCast(theWindow);
   HDC hdc = GetDC ( (HWND)(hWindow->HWindow()) );
   HDC hdcMem = CreateCompatibleDC ( hdc );
   ReleaseDC ( (HWND)(hWindow->HWindow()), hdc );
@@ -80,8 +81,8 @@ Aspect_PixMap(aWidth, anHeight, PreferedDepth(aWindow, aCDepth))
   ZeroMemory (  pBmi, sizeBmi  );
 
   pBmi->bmiHeader.biSize          = sizeof (BITMAPINFOHEADER); //sizeBmi
-  pBmi->bmiHeader.biWidth         = aWidth;
-  pBmi->bmiHeader.biHeight        = anHeight;
+  pBmi->bmiHeader.biWidth         = myWidth;
+  pBmi->bmiHeader.biHeight        = myHeight;
   pBmi->bmiHeader.biPlanes        = 1;
   pBmi->bmiHeader.biBitCount      = myDepth; //WIL001: was 24
   pBmi->bmiHeader.biCompression   = BI_RGB;
@@ -127,8 +128,8 @@ void WNT_PixMap::Destroy ()
 }
 
 ////////////////////////////////////////////////////////////
-Standard_Boolean WNT_PixMap::Dump ( const Standard_CString aFilename,
-                                   const Standard_Real aGammaValue ) const
+Standard_Boolean WNT_PixMap::Dump (const Standard_CString theFilename,
+                                   const Standard_Real    theGammaValue) const
 {
   // *** gamma correction must be implemented also on WNT system ...
   const Handle(WNT_Window) hWindow = Handle(WNT_Window)::DownCast(myWND);
@@ -138,7 +139,7 @@ Standard_Boolean WNT_PixMap::Dump ( const Standard_CString aFilename,
   if ( dev.IsNull() ) return Standard_False;
   //Aspect_PixmapError::Raise ( "WNT_GraphicDevice is NULL" );
 
-  return DumpBitmapToFile ( dev, (HDC)myDC, (HBITMAP)myBitmap, (Standard_PCharacter)aFilename );
+  return DumpBitmapToFile ((HBITMAP)myBitmap, theFilename);
 }
 
 ////////////////////////////////////////////////////////////
index 0a53f41..b1ae092 100755 (executable)
@@ -47,7 +47,7 @@ class Window from WNT inherits Window from Aspect
     TypeOfResize       from Aspect,
     FillMethod         from Aspect,
     GradientFillMethod from Aspect,
-    PixMap             from Aspect,
+    PixMap             from Image,
     NameOfColor        from Quantity,
     Color              from Quantity,
     Parameter          from Quantity,
@@ -354,8 +354,8 @@ class Window from WNT inherits Window from Aspect
        --          or the area is out of the Window.
      raises WindowError from Aspect is virtual;
 
-    ToPixMap ( me )
-    returns PixMap from Aspect
+    ToPixMap ( me ; theImage : in out PixMap from Image )
+    returns Boolean
     ---Level   : Public
     ---Purpose : dump the full contents of the window to a pixmap.
     is virtual;
index 5da184d..134e1e6 100755 (executable)
@@ -27,7 +27,7 @@
 
 #include <WNT_Window.ixx>
 
-#include <Image_PixMap.hxx>
+#include <Image_AlienPixMap.hxx>
 #include <Aspect_Convert.hxx>
 
 #include <stdio.h>
@@ -733,7 +733,16 @@ void WNT_Window :: RestoreArea (
 Standard_Boolean WNT_Window::Dump (const Standard_CString theFilename,
                                    const Standard_Real theGammaValue) const
 {
-  return ToPixMap()->Dump (theFilename, theGammaValue);
+  Image_AlienPixMap anImg;
+  if (!ToPixMap (anImg) || anImg.IsEmpty())
+  {
+    return Standard_False;
+  }
+  if (Abs (theGammaValue - 1.0) > 0.001)
+  {
+    anImg.AdjustGamma (theGammaValue);
+  }
+  return anImg.Save (theFilename);
 }  // end WNT_Window :: Dump
 //***//
 //*************************** DumpArea ***********************************//
@@ -753,61 +762,50 @@ Standard_Boolean WNT_Window::DumpArea (const Standard_CString theFilename,
 }  // end WNT_Window :: DumpArea
 //***//
 
-static Handle(Image_PixMap) ConvertBitmap (HBITMAP theHBitmap)
+static Standard_Boolean ConvertBitmap (HBITMAP       theHBitmap,
+                                       Image_PixMap& thePixMap)
 {
-  Handle(Image_PixMap) anImagePixMap;
-  // Copy data from HBITMAP
+  // 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;
@@ -825,13 +823,13 @@ Handle(Aspect_PixMap) WNT_Window::ToPixMap() const
   HBITMAP anHBitmapOld = (HBITMAP )SelectObject (aMemDC, anHBitmapDump);
   BitBlt (aMemDC, 0, 0, aWidth, aHeight, aSrcDC, 0, 0, SRCCOPY);
 
-  Handle(Image_PixMap) anImagePixMap = ConvertBitmap (anHBitmapDump);
+  Standard_Boolean isSuccess = ConvertBitmap (anHBitmapDump, thePixMap);
 
   // Free objects
   DeleteObject (SelectObject (aMemDC, anHBitmapOld));
   DeleteDC (aMemDC);
 
-  return anImagePixMap;
+  return isSuccess;
 }
 
 //****************************** Load ************************************//
index e76abb6..799339a 100755 (executable)
@@ -30,7 +30,7 @@ class PixMap from Xw
     ---Keywords: Bitmap, Pixmap, X11
 
 inherits
-    PixMap                from Aspect
+    Transient             from Standard
 uses
     Handle                from Aspect,
     Color                 from Quantity,
@@ -97,4 +97,7 @@ is
 fields
     myPixmap : Handle from Aspect is protected;
     myWindow : Window from Xw;
+    myWidth  : Integer from Standard is protected;
+    myHeight : Integer from Standard is protected;
+    myDepth     : Integer from Standard is protected;
 end PixMap;
index e9035cf..7512f42 100755 (executable)
@@ -28,6 +28,9 @@
 
 #define xTRACE 1
 
+#include <TCollection_AsciiString.hxx>
+#include <Image_AlienPixMap.hxx>
+
 #include <errno.h>
 #include <stdio.h>
 
@@ -36,9 +39,6 @@
 #include <Xw_Window.hxx>
 #include <Xw_Extension.h>
 
-#include <TCollection_AsciiString.hxx>
-#include <Image_PixMap.hxx>
-
 XW_STATUS Xw_save_xwd_image ( void*, void*, char* );
 XW_STATUS Xw_save_bmp_image ( void*, void*, char* );
 XW_STATUS Xw_save_gif_image ( void*, void*, char* );
@@ -63,15 +63,15 @@ Standard_Integer Xw_PixMap::PreferedDepth(
 
 
 //////////////////////////////////////////////////////////////////////////////////////////
-Xw_PixMap::Xw_PixMap ( const Handle(Aspect_Window)& aWindow,
-                       const Standard_Integer aWidth,
-                       const Standard_Integer anHeight,
-                      const Standard_Integer aDepth ) :
-       Aspect_PixMap(aWidth, anHeight, PreferedDepth(aWindow, aDepth))
+Xw_PixMap::Xw_PixMap (const Handle(Aspect_Window)& theWindow,
+                      const Standard_Integer       theWidth,
+                      const Standard_Integer       theHeight,
+                                 const Standard_Integer       theDepth)
+: myWindow (Handle(Xw_Window)::DownCast(theWindow)),
+  myWidth  (theWidth),
+  myHeight (theHeight),
+  myDepth  (PreferedDepth (theWindow, theDepth))
 {
-
-  myWindow = Handle(Xw_Window)::DownCast(aWindow);
-
   XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*) myWindow->ExtendedWindow();
 
   Xw_print_error();
@@ -99,46 +99,54 @@ Xw_PixMap::Destroy ()
   }
 }
 
-
 ////////////////////////////////////////////////////////////
-Standard_Boolean Xw_PixMap::Dump (const Standard_CString theFilename,
-                                  const Standard_Real theGammaValue) const
+Standard_Boolean Xw_PixMap::Dump (const Standard_CString theFileName,
+                                  const Standard_Real    theGammaValue) const
 {
   // the attributes
   XWindowAttributes winAttr;
   XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*) myWindow->ExtendedWindow();
   XGetWindowAttributes (_DISPLAY, _WINDOW, &winAttr);
-
-  // find the image
-  XImage* pximage = XGetImage (_DISPLAY, myPixmap,
-                               0, 0, myWidth, myHeight,
-                               AllPlanes, ZPixmap);
-  if (pximage == NULL)
+  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);
 }
 
 ////////////////////////////////////////////////////////////
index b5ce738..282bded 100755 (executable)
@@ -49,7 +49,7 @@ uses
     Handle             from Aspect,
     FillMethod         from Aspect,
     GradientFillMethod from Aspect,
-    PixMap             from Aspect,
+    PixMap             from Image,
     NameOfColor        from Quantity,
     Parameter          from Quantity,
     Ratio              from Quantity,
@@ -330,8 +330,8 @@ is
     --      or the area is out of the Window.
     raises WindowError from Aspect is virtual;
 
-    ToPixMap ( me )
-    returns PixMap from Aspect
+    ToPixMap ( me ; theImage : in out PixMap from Image )
+    returns Boolean
     ---Level   : Public
     ---Purpose : dump the full contents of the window to a pixmap.
     is virtual;
index 584c24b..a1065ba 100755 (executable)
@@ -77,7 +77,7 @@
 #include <Xw_Cextern.hxx>
 //}
 #include <Aspect_Convert.hxx>
-#include <Image_PixMap.hxx>
+#include <Image_AlienPixMap.hxx>
 
 #include <Xw_Extension.h>
 
@@ -862,15 +862,14 @@ Standard_Boolean Xw_Window::DumpArea (const Standard_CString theFilename,
   return Standard_Boolean(aStatus);
 }
 
-Handle(Aspect_PixMap) Xw_Window::ToPixMap() const
+Standard_Boolean Xw_Window::ToPixMap (Image_PixMap& thePixMap) const
 {
-  Handle(Image_PixMap) anImagePixMap;
   int aDummy, aWidth, aHeight;
   XW_WINDOWSTATE state = Xw_get_window_position (MyExtendedWindow,
                                                  &aDummy, &aDummy, &aWidth, &aHeight);
   if (state == XW_WS_UNKNOWN)
   {
-    return anImagePixMap;
+    return Standard_False;
   }
 
   XW_EXT_IMAGEDATA* pimage = NULL;
@@ -895,22 +894,27 @@ Handle(Aspect_PixMap) Xw_Window::ToPixMap() const
 
   if (pimage == NULL)
   {
-    return anImagePixMap;
+    return Standard_False;
   }
 
   XImage* pximage = (pimage->zximage) ? pimage->zximage : pimage->pximage;
   XW_EXT_WINDOW* pwindow = (XW_EXT_WINDOW* )MyExtendedWindow;
-  if (pwindow->pcolormap->visual->c_class == TrueColor)
+  if (pwindow->pcolormap->visual->c_class != TrueColor)
   {
-    Standard_Byte* aDataPtr = (Standard_Byte* )pximage->data;
-    anImagePixMap = new Image_PixMap (aDataPtr,
-                                      pximage->width, pximage->height,
-                                      pximage->bytes_per_line,
-                                      pximage->bits_per_pixel,
-                                      Standard_True);
+    return Standard_False;
   }
+
+  const bool isBigEndian = (pximage->byte_order == MSBFirst);
+  Image_PixMap::ImgFormat aFormat = (pximage->bits_per_pixel == 32)
+                                  ? (isBigEndian ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgBGR32)
+                                  : (isBigEndian ? Image_PixMap::ImgRGB   : Image_PixMap::ImgBGR);
+  Image_PixMap aWrapper;
+  aWrapper.InitWrapper (aFormat, (Standard_Byte* )pximage->data, pximage->width, pximage->height, pximage->bytes_per_line);
+  aWrapper.SetTopDown (true);
+
+  Standard_Boolean isSuccess = thePixMap.InitCopy (aWrapper);
   Xw_close_image (pimage);
-  return anImagePixMap;
+  return isSuccess;
 }
 
 Standard_Boolean Xw_Window::Load (const Standard_CString aFilename) const {
index a317e10..f759c3c 100755 (executable)
 # include <config.h>
 #endif
 
+#include <Image_AlienPixMap.hxx>
+#include <TCollection_AsciiString.hxx>
+
 #include <Xw_Extension.h>
 #ifdef HAVE_STRINGS_H
 # include <strings.h>
 #endif
 
-#include <Image_PixMap.hxx>
-
 #ifdef XW_PROTOTYPE
 XW_STATUS Xw_save_image_adv (Display *aDisplay,Window aWindow,XWindowAttributes aWinAttr,XImage *aPximage,Colormap aColormap,int aNcolors,char *filename)
 #else
@@ -54,22 +55,22 @@ int ncolors;
 char *filename;
 #endif /*XW_PROTOTYPE*/
 {
-  if (aWinAttr.visual->c_class == TrueColor)
-  {
-    Standard_Byte* aDataPtr = (Standard_Byte* )aPximage->data;
-    Handle(Image_PixMap) anImagePixMap = new Image_PixMap (aDataPtr,
-                                                           aPximage->width, aPximage->height,
-                                                           aPximage->bytes_per_line,
-                                                           aPximage->bits_per_pixel,
-                                                           Standard_True);
-    // save the image
-    return anImagePixMap->Dump (filename) ? XW_SUCCESS : XW_ERROR;
-  }
-  else
+  if (aWinAttr.visual->c_class != TrueColor)
   {
     std::cerr << "Visual Type not supported!";
-    return XW_SUCCESS;
+    return XW_ERROR;
   }
+
+  const bool isBigEndian = (aPximage->byte_order == MSBFirst);
+  Image_PixMap::ImgFormat aFormat = (aPximage->bits_per_pixel == 32)
+                                  ? (isBigEndian ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgBGR32)
+                                  : (isBigEndian ? Image_PixMap::ImgRGB   : Image_PixMap::ImgBGR);
+  Image_PixMap aWrapper;
+  aWrapper.InitWrapper (aFormat, (Standard_Byte* )aPximage->data, aPximage->width, aPximage->height, aPximage->bytes_per_line);
+  aWrapper.SetTopDown (true);
+
+  Image_AlienPixMap anAlienImage;
+  return (anAlienImage.InitCopy (aWrapper) && anAlienImage.Save (filename)) ? XW_SUCCESS : XW_ERROR;
 }
 
 #ifdef XW_PROTOTYPE