Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-06-13 08:30:33

0001 // Created on: 2012-07-10
0002 // Created by: VRO
0003 // Copyright (c) 2012-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef Image_Diff_HeaderFile
0017 #define Image_Diff_HeaderFile
0018 
0019 #include <Image_PixMap.hxx>
0020 #include <TCollection_AsciiString.hxx>
0021 #include <TColStd_HPackedMapOfInteger.hxx>
0022 #include <NCollection_List.hxx>
0023 #include <NCollection_Vector.hxx>
0024 
0025 //! This class compares two images pixel-by-pixel.
0026 //! It uses the following methods to ignore the difference between images:
0027 //!  - Black/White comparison. It makes the images 2-colored before the comparison.
0028 //!  - Equality with tolerance. Colors of two pixels are considered the same if the
0029 //!    difference of their color is less than a tolerance.
0030 //!  - Border filter. The algorithm ignores alone independent pixels,
0031 //!    which are different on both images, ignores the "border effect" -
0032 //!    the difference caused by triangles located at angle about 0 or 90 degrees to the user.
0033 //!
0034 //! Border filter ignores a difference in implementation of
0035 //! anti-aliasing and other effects on boundary of a shape.
0036 //! The triangles of a boundary zone are usually located so that their normals point aside the user
0037 //! (about 90 degree between the normal and the direction to the user's eye).
0038 //! Deflection of the light for such a triangle depends on implementation of the video driver.
0039 //! In order to skip this difference the following algorithm is used:
0040 //!  a) "Different" pixels are grouped and checked on "one-pixel width line".
0041 //!     indeed, the pixels may represent not a line, but any curve.
0042 //!     But the width of this curve should be not more than a pixel.
0043 //!     This group of pixels become a candidate to be ignored because of boundary effect.
0044 //!  b) The group of pixels is checked on belonging to a "shape".
0045 //!     Neighbour pixels are checked from the reference image.
0046 //!     This test confirms a fact that the group of pixels belongs to a shape and
0047 //!     represent a boundary of the shape.
0048 //!     In this case the whole group of pixels is ignored (considered as same).
0049 //!     Otherwise, the group of pixels may represent a geometrical curve in the viewer 3D
0050 //!     and should be considered as "different".
0051 //!
0052 //! References:
0053 //!     1. http://pdiff.sourceforge.net/ypg01.pdf
0054 //!     2. http://pdiff.sourceforge.net/metric.html
0055 //!     3. http://www.cs.ucf.edu/~sumant/publications/sig99.pdf
0056 //!     4. http://www.worldscientific.com/worldscibooks/10.1142/2641#t=toc (there is a list of
0057 //!     articles and books in PDF format)
0058 
0059 class Image_Diff : public Standard_Transient
0060 {
0061 
0062 public:
0063   //! An empty constructor. Init() should be called for initialization.
0064   Standard_EXPORT Image_Diff();
0065 
0066   //! Destructor.
0067   Standard_EXPORT virtual ~Image_Diff();
0068 
0069   //! Initialize algorithm by two images.
0070   //! @return false if images has different or unsupported pixel format.
0071   Standard_EXPORT Standard_Boolean Init(const Handle(Image_PixMap)& theImageRef,
0072                                         const Handle(Image_PixMap)& theImageNew,
0073                                         const Standard_Boolean theToBlackWhite = Standard_False);
0074 
0075   //! Initialize algorithm by two images (will be loaded from files).
0076   //! @return false if images couldn't be opened or their format is unsupported.
0077   Standard_EXPORT Standard_Boolean Init(const TCollection_AsciiString& theImgPathRef,
0078                                         const TCollection_AsciiString& theImgPathNew,
0079                                         const Standard_Boolean theToBlackWhite = Standard_False);
0080 
0081   //! Color tolerance for equality check. Should be within range 0..1:
0082   //! Corresponds to a difference between white and black colors (maximum difference).
0083   //! By default, the tolerance is equal to 0 thus equality check will return false for any
0084   //! different colors.
0085   void SetColorTolerance(const Standard_Real theTolerance) { myColorTolerance = theTolerance; }
0086 
0087   //! Color tolerance for equality check.
0088   Standard_Real ColorTolerance() const { return myColorTolerance; }
0089 
0090   //! Sets taking into account (ignoring) a "border effect" on comparison of images.
0091   //! The border effect is caused by a border of shaded shapes in the viewer 3d.
0092   //! Triangles of this area are located at about 0 or 90 degrees to the user.
0093   //! Therefore, they deflect light differently according to implementation of a video card driver.
0094   //! This flag allows to detect such a "border" area and skip it from comparison of images.
0095   //! Filter turned OFF by default.
0096   void SetBorderFilterOn(const Standard_Boolean theToIgnore) { myIsBorderFilterOn = theToIgnore; }
0097 
0098   //! Returns a flag of taking into account (ignoring) a border effect in comparison of images.
0099   Standard_Boolean IsBorderFilterOn() const { return myIsBorderFilterOn; }
0100 
0101   //! Compares two images. It returns a number of different pixels (or groups of pixels).
0102   //! It returns -1 if algorithm not initialized before.
0103   Standard_EXPORT Standard_Integer Compare();
0104 
0105   //! Saves a difference between two images as white pixels on black background.
0106   Standard_EXPORT Standard_Boolean SaveDiffImage(Image_PixMap& theDiffImage) const;
0107 
0108   //! Saves a difference between two images as white pixels on black background.
0109   Standard_EXPORT Standard_Boolean SaveDiffImage(const TCollection_AsciiString& theDiffPath) const;
0110 
0111 protected:
0112   //! Perform border filter algorithm.
0113   Standard_EXPORT Standard_Integer ignoreBorderEffect();
0114 
0115   //! Release dynamically allocated memory.
0116   Standard_EXPORT void releaseGroupsOfDiffPixels();
0117 
0118 protected:
0119   //! Map two pixel coordinates to 32-bit integer
0120   static Standard_Integer PackXY(uint16_t theX, uint16_t theY)
0121   {
0122     return Standard_Integer((unsigned int)theY | ((unsigned int)theX << 16));
0123   }
0124 
0125   //! Get pixel X coordinate from 32-bit packed integer
0126   static uint16_t UnpackX(Standard_Integer theXY)
0127   {
0128     return (uint16_t)(((unsigned int)theXY & 0xffff0000) >> 16);
0129   }
0130 
0131   //! Get pixel Y coordinate from 32-bit packed integer
0132   static uint16_t UnpackY(Standard_Integer theXY)
0133   {
0134     return (uint16_t)((unsigned int)theXY & 0xffff);
0135   }
0136 
0137 protected:
0138   Handle(Image_PixMap) myImageRef;    //!< reference image to compare (from)
0139   Handle(Image_PixMap) myImageNew;    //!< new       image to compare (to)
0140                                       // clang-format off
0141   Standard_Real                     myColorTolerance;     //!< tolerance for equality check (0..1, 0 - any not equal, 1 - opposite colors)
0142 
0143   Standard_Boolean                  myIsBorderFilterOn;   //!< perform algorithm with border effect filter
0144                                       // clang-format on
0145 
0146   //! coordinates of different pixels, packed in one int using 16-bit integers to save memory
0147   NCollection_Vector<Standard_Integer>                  myDiffPixels;
0148   TColStd_PackedMapOfInteger                            myLinearGroups;
0149   NCollection_List<Handle(TColStd_HPackedMapOfInteger)> myGroupsOfDiffPixels;
0150 
0151 public:
0152   DEFINE_STANDARD_RTTIEXT(Image_Diff, Standard_Transient) // Type definition
0153 };
0154 
0155 DEFINE_STANDARD_HANDLE(Image_Diff, Standard_Transient)
0156 
0157 #endif // _Image_Diff_H__