0024534: Improve design of Image_PixMap class
authorkgv <kgv@opencascade.com>
Fri, 4 Apr 2014 05:15:40 +0000 (09:15 +0400)
committerabv <abv@opencascade.com>
Thu, 10 Apr 2014 15:49:50 +0000 (19:49 +0400)
Remove template methods Image_PixMap::EditData(), ::ReadData().
Add template method Image_PixMap::ChangeValue().
Remove redundant parameter for Image_PixMap::Clear() method.

Make Image_PixMapData non-template class. Introduce NCollection_Buffer.

12 files changed:
src/Image/Image_AlienPixMap.cxx
src/Image/Image_AlienPixMap.hxx
src/Image/Image_Diff.cxx
src/Image/Image_PixMap.cxx
src/Image/Image_PixMap.hxx
src/Image/Image_PixMapData.hxx
src/MeshVS/MeshVS_NodalColorPrsBuilder.cxx
src/NCollection/FILES
src/NCollection/NCollection_Buffer.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_AspectMarker.cxx
src/OpenGl/OpenGl_View_2.cxx
src/QABugs/QABugs_19.cxx

index 298b7f3..fb92dfe 100644 (file)
@@ -201,18 +201,17 @@ bool Image_AlienPixMap::InitCopy (const Image_PixMap& theCopy)
 
   if (myImgFormat == theCopy.Format())
   {
-    if (myData.mySizeRowBytes == theCopy.SizeRowBytes()
-     && myData.myTopToDown    == theCopy.TopDownInc())
+    if (SizeRowBytes() == theCopy.SizeRowBytes()
+     && TopDownInc()   == theCopy.TopDownInc())
     {
       // copy with one call
-      memcpy (myData.myDataPtr, theCopy.Data(), theCopy.SizeBytes());
+      memcpy (ChangeData(), theCopy.Data(), std::min (SizeBytes(), 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)
+    const Standard_Size aRowSizeBytes = std::min (SizeRowBytes(), theCopy.SizeRowBytes());
+    for (Standard_Size aRow = 0; aRow < myData.SizeY; ++aRow)
     {
       memcpy (ChangeRow (aRow), theCopy.Row (aRow), aRowSizeBytes);
     }
@@ -228,9 +227,9 @@ bool Image_AlienPixMap::InitCopy (const Image_PixMap& theCopy)
 // function : Clear
 // purpose  :
 // =======================================================================
-void Image_AlienPixMap::Clear (ImgFormat thePixelFormat)
+void Image_AlienPixMap::Clear()
 {
-  Image_PixMap::Clear (thePixelFormat);
+  Image_PixMap::Clear();
 #ifdef HAVE_FREEIMAGE
   if (myLibImage != NULL)
   {
@@ -383,12 +382,11 @@ bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
        || 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;
+            myData.ChangeValue (aRow, aCol)[3] = 0xFF;
           }
         }
       }
index a7de5dd..7976ac5 100644 (file)
@@ -61,7 +61,7 @@ public:
   Standard_EXPORT virtual bool InitCopy (const Image_PixMap& theCopy);
 
   //! Method correctly deallocate internal buffer.
-  Standard_EXPORT virtual void Clear (ImgFormat thePixelFormat = ImgGray);
+  Standard_EXPORT virtual void Clear();
 
   //! Performs gamma correction on image.
   //! theGamma - gamma value to use; a value of 1.0 leaves the image alone
index 2e78644..81eca33 100644 (file)
 IMPLEMENT_STANDARD_HANDLE (Image_Diff, Standard_Transient)
 IMPLEMENT_STANDARD_RTTIEXT(Image_Diff, Standard_Transient)
 
+//! POD structure for packed RGB color value (3 bytes)
+struct Image_ColorXXX24
+{
+  Standard_Byte v[3];
+  typedef Standard_Byte ComponentType_t;         //!< Component type
+  static Standard_Integer Length() { return 3; } //!< Returns the number of components
+};
+
+inline Image_ColorXXX24 operator- (const Image_ColorXXX24& theA,
+                                   const Image_ColorXXX24& theB)
+{
+  return Image_ColorSub3 (theA, theB);
+}
+
 //! Dot squared for difference of two colors
-inline Standard_Integer dotSquared (const Image_ColorRGB& theColor)
+inline Standard_Integer dotSquared (const Image_ColorXXX24& theColor)
 {
   // explicitly convert to integer
-  const Standard_Integer r = theColor.r();
-  const Standard_Integer g = theColor.g();
-  const Standard_Integer b = theColor.b();
+  const Standard_Integer r = theColor.v[0];
+  const Standard_Integer g = theColor.v[1];
+  const Standard_Integer b = theColor.v[2];
   return r * r + g * g + b * b;
 }
 
 //! @return true if pixel is black
-inline bool isBlack (const Image_ColorRGB& theColor)
+inline bool isBlack (const Image_ColorXXX24& theColor)
 {
-  return theColor.r() == 0
-      && theColor.g() == 0
-      && theColor.b() == 0;
+  return theColor.v[0] == 0
+      && theColor.v[1] == 0
+      && theColor.v[2] == 0;
 }
 
 //! Converts a pixel position (row, column) to one integer value
@@ -78,15 +92,15 @@ namespace
                           theColCenter + Standard_Size(col_inc));
     }
 
-    inline bool isBlack (const Image_PixMapData<Image_ColorRGB>& theData,
+    inline bool isBlack (const Image_PixMap& theData,
                          const Standard_Size theRowCenter,
                          const Standard_Size theColCenter) const
     {
-      return ::isBlack (theData.Value (theRowCenter + Standard_Size(row_inc),
-                                       theColCenter + Standard_Size(col_inc)));
+      return ::isBlack (theData.Value<Image_ColorXXX24> (theRowCenter + Standard_Size(row_inc),
+                                                         theColCenter + Standard_Size(col_inc)));
     }
 
-    inline bool isValid (const Image_PixMapData<Image_ColorRGB>& theData,
+    inline bool isValid (const Image_PixMap& theData,
                          const Standard_Size theRowCenter,
                          const Standard_Size theColCenter) const
     {
@@ -173,19 +187,17 @@ Standard_Boolean Image_Diff::Init (const Handle(Image_PixMap)& theImageRef,
   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)
+    const Image_ColorXXX24 aWhite = {{255, 255, 255}};
+    for (Standard_Size aRow = 0; aRow < myImageRef->SizeY(); ++aRow)
     {
-      for (Standard_Size aCol = 0; aCol < aDataRef.SizeY(); ++aCol)
+      for (Standard_Size aCol = 0; aCol < myImageRef->SizeX(); ++aCol)
       {
-        Image_ColorRGB& aPixel1 = aDataRef.ChangeValue (aRow, aCol);
-        Image_ColorRGB& aPixel2 = aDataNew.ChangeValue (aRow, aCol);
+        Image_ColorXXX24& aPixel1 = myImageRef->ChangeValue<Image_ColorXXX24> (aRow, aCol);
         if (!isBlack (aPixel1))
         {
           aPixel1 = aWhite;
         }
+        Image_ColorXXX24& aPixel2 = myImageNew->ChangeValue<Image_ColorXXX24> (aRow, aCol);
         if (!isBlack (aPixel2))
         {
           aPixel2 = aWhite;
@@ -270,21 +282,19 @@ Standard_Integer Image_Diff::Compare()
 
   // Tolerance of comparison operation for color
   // Maximum difference between colors (white - black) = 100%
-  Image_ColorRGB aDiff = {{255, 255, 255}};
+  Image_ColorXXX24 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);
+      aDiff = myImageNew->Value<Image_ColorXXX24> (aRow, aCol) - myImageRef->Value<Image_ColorXXX24> (aRow, aCol);
       if (dotSquared (aDiff) > aDiffThreshold)
       {
         const Standard_Size aValue = pixel2Int (aRow, aCol);
@@ -326,8 +336,7 @@ Standard_Boolean Image_Diff::SaveDiffImage (Image_PixMap& theDiffImage) const
   }
 
   Standard_Size aRow, aCol;
-  const Image_ColorRGB aWhite = {{255, 255, 255}};
-  Image_PixMapData<Image_ColorRGB>& aDataOut = theDiffImage.EditData<Image_ColorRGB>();
+  const Image_ColorXXX24 aWhite = {{255, 255, 255}};
 
   // initialize black image for dump
   memset (theDiffImage.ChangeData(), 0, theDiffImage.SizeBytes());
@@ -342,7 +351,7 @@ Standard_Boolean Image_Diff::SaveDiffImage (Image_PixMap& theDiffImage) const
     {
       const Standard_Size aValue = myDiffPixels.Value (aPixelId);
       int2Pixel (aValue, aRow, aCol);
-      aDataOut.ChangeValue (aRow, aCol) = aWhite;
+      theDiffImage.ChangeValue<Image_ColorXXX24> (aRow, aCol) = aWhite;
     }
 
     return Standard_True;
@@ -361,7 +370,7 @@ Standard_Boolean Image_Diff::SaveDiffImage (Image_PixMap& theDiffImage) const
          aPixelIter.More(); aPixelIter.Next())
     {
       int2Pixel (aPixelIter.Key(), aRow, aCol);
-      aDataOut.ChangeValue (aRow, aCol) = aWhite;
+      theDiffImage.ChangeValue<Image_ColorXXX24> (aRow, aCol) = aWhite;
     }
   }
 
@@ -401,8 +410,6 @@ Standard_Integer Image_Diff::ignoreBorderEffect()
     return 0;
   }
 
-  const Image_PixMapData<Image_ColorRGB>& aDataRef = myImageRef->ReadData<Image_ColorRGB>();
-
   // allocate groups of different pixels
   releaseGroupsOfDiffPixels();
 
@@ -475,7 +482,7 @@ Standard_Integer Image_Diff::ignoreBorderEffect()
       // check all neighbour pixels on presence in the group
       for (Standard_Size aNgbrIter = 0; aNgbrIter < NEIGHBOR_PIXELS_NB; ++aNgbrIter)
       {
-        if (NEIGHBOR_PIXELS[aNgbrIter].isValid (aDataRef, aRow1, aCol1)
+        if (NEIGHBOR_PIXELS[aNgbrIter].isValid (*myImageRef, aRow1, aCol1)
          && aGroup->Contains ((Standard_Integer)NEIGHBOR_PIXELS[aNgbrIter].pixel2Int (aRow1, aCol1)))
         {
           ++aNeighboursNb;
@@ -498,8 +505,8 @@ Standard_Integer Image_Diff::ignoreBorderEffect()
       aNeighboursNb = 0;
       for (Standard_Size aNgbrIter = 0; aNgbrIter < NEIGHBOR_PIXELS_NB; ++aNgbrIter)
       {
-        if ( NEIGHBOR_PIXELS[aNgbrIter].isValid (aDataRef, aRow1, aCol1)
-         && !NEIGHBOR_PIXELS[aNgbrIter].isBlack (aDataRef, aRow1, aCol1))
+        if ( NEIGHBOR_PIXELS[aNgbrIter].isValid (*myImageRef, aRow1, aCol1)
+         && !NEIGHBOR_PIXELS[aNgbrIter].isBlack (*myImageRef, aRow1, aCol1))
         {
           ++aNeighboursNb;
         }
index 1f45138..4297b02 100644 (file)
@@ -14,7 +14,7 @@
 // commercial license or contractual agreement.
 
 #include <Image_PixMap.hxx>
-#include <Standard.hxx>
+#include <NCollection_AlignedAllocator.hxx>
 
 IMPLEMENT_STANDARD_HANDLE (Image_PixMap, Standard_Transient)
 IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap, Standard_Transient)
@@ -24,13 +24,9 @@ IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap, Standard_Transient)
 // purpose  :
 // =======================================================================
 Image_PixMap::Image_PixMap()
-: myImgFormat (Image_PixMap::ImgGray),
-  myIsOwnPointer (true)
+: myImgFormat (Image_PixMap::ImgGray)
 {
-  memset (&myData, 0, sizeof(myData));
-  myData.mySizeBPP   = 1;
-  myData.myTopToDown = Standard_Size(-1);
-  setFormat (Image_PixMap::ImgGray);
+  //
 }
 
 // =======================================================================
@@ -75,18 +71,7 @@ Standard_Size Image_PixMap::SizePixelBytes (const Image_PixMap::ImgFormat thePix
 // =======================================================================
 void Image_PixMap::setFormat (Image_PixMap::ImgFormat thePixelFormat)
 {
-  myImgFormat      = thePixelFormat;
-  myData.mySizeBPP = SizePixelBytes (myImgFormat);
-}
-
-// =======================================================================
-// function : setTopDown
-// purpose  :
-// =======================================================================
-void Image_PixMap::setTopDown()
-{
-  myData.myTopRowPtr = ((myData.myTopToDown == 1 || myData.myDataPtr == NULL)
-                     ? myData.myDataPtr : (myData.myDataPtr + myData.mySizeRowBytes * (myData.mySizeY - 1)));
+  myImgFormat = thePixelFormat;
 }
 
 // =======================================================================
@@ -99,17 +84,16 @@ bool Image_PixMap::InitWrapper (Image_PixMap::ImgFormat thePixelFormat,
                                 const Standard_Size     theSizeY,
                                 const Standard_Size     theSizeRowBytes)
 {
-  Clear (thePixelFormat);
+  Clear();
+  myImgFormat = thePixelFormat;
   if ((theSizeX == 0) || (theSizeY == 0) || (theDataPtr == NULL))
   {
     return false;
   }
-  myData.mySizeX        = theSizeX;
-  myData.mySizeY        = theSizeY;
-  myData.mySizeRowBytes = (theSizeRowBytes != 0) ? theSizeRowBytes : (theSizeX * myData.mySizeBPP);
-  myData.myDataPtr      = theDataPtr;
-  myIsOwnPointer = false;
-  setTopDown();
+
+  Handle(NCollection_BaseAllocator) anEmptyAlloc;
+  myData.Init (anEmptyAlloc, Image_PixMap::SizePixelBytes (thePixelFormat),
+               theSizeX, theSizeY, theSizeRowBytes, theDataPtr);
   return true;
 }
 
@@ -122,23 +106,19 @@ bool Image_PixMap::InitTrash (Image_PixMap::ImgFormat thePixelFormat,
                               const Standard_Size     theSizeY,
                               const Standard_Size     theSizeRowBytes)
 {
-  Clear (thePixelFormat);
+  Clear();
+  myImgFormat = thePixelFormat;
   if ((theSizeX == 0) || (theSizeY == 0))
   {
     return false;
   }
-  myData.mySizeX        = theSizeX;
-  myData.mySizeY        = theSizeY;
-  myData.mySizeRowBytes = myData.mySizeX * myData.mySizeBPP;
-  if (theSizeRowBytes > myData.mySizeRowBytes)
-  {
-    // use argument only if it greater
-    myData.mySizeRowBytes = theSizeRowBytes;
-  }
-  myData.myDataPtr = (Standard_Byte* )Standard::AllocateAligned (SizeBytes(), 16);
-  myIsOwnPointer   = true;
-  setTopDown();
-  return myData.myDataPtr != NULL;
+
+  // use argument only if it greater
+  const Standard_Size aSizeRowBytes = std::max (theSizeRowBytes, theSizeX * SizePixelBytes (thePixelFormat));
+  Handle(NCollection_BaseAllocator) anAlloc = new NCollection_AlignedAllocator (16);
+  myData.Init (anAlloc, Image_PixMap::SizePixelBytes (thePixelFormat),
+               theSizeX, theSizeY, aSizeRowBytes, NULL);
+  return !myData.IsEmpty();
 }
 
 // =======================================================================
@@ -155,7 +135,7 @@ bool Image_PixMap::InitZero (Image_PixMap::ImgFormat thePixelFormat,
   {
     return false;
   }
-  memset (myData.myDataPtr, (int )theValue, SizeBytes());
+  memset (myData.ChangeData(), (int )theValue, SizeBytes());
   return true;
 }
 
@@ -170,9 +150,9 @@ bool Image_PixMap::InitCopy (const Image_PixMap& theCopy)
     // self-copying disallowed
     return false;
   }
-  if (InitTrash (theCopy.myImgFormat, theCopy.myData.mySizeX, theCopy.myData.mySizeY, theCopy.myData.mySizeRowBytes))
+  if (InitTrash (theCopy.myImgFormat, theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
   {
-    memcpy (myData.myDataPtr, theCopy.myData.myDataPtr, theCopy.SizeBytes());
+    memcpy (myData.ChangeData(), theCopy.myData.Data(), theCopy.SizeBytes());
     return true;
   }
   return false;
@@ -182,16 +162,11 @@ bool Image_PixMap::InitCopy (const Image_PixMap& theCopy)
 // function : Clear
 // purpose  :
 // =======================================================================
-void Image_PixMap::Clear (Image_PixMap::ImgFormat thePixelFormat)
+void Image_PixMap::Clear()
 {
-  if (myIsOwnPointer && (myData.myDataPtr != NULL))
-  {
-    Standard::FreeAligned (myData.myDataPtr);
-  }
-  myData.myDataPtr = myData.myTopRowPtr = NULL;
-  myIsOwnPointer = true;
-  myData.mySizeX = myData.mySizeY = myData.mySizeRowBytes = 0;
-  setFormat (thePixelFormat);
+  Handle(NCollection_BaseAllocator) anEmptyAlloc;
+  myData.Init (anEmptyAlloc, Image_PixMap::SizePixelBytes (myImgFormat),
+               0, 0, 0, NULL);
 }
 
 // =======================================================================
@@ -202,9 +177,9 @@ Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
                                          const Standard_Integer theY,
                                          Quantity_Parameter&    theAlpha) const
 {
-  if (IsEmpty() ||
-      theX < 0 || (Standard_Size )theX >= myData.mySizeX ||
-      theY < 0 || (Standard_Size )theY >= myData.mySizeY)
+  if (IsEmpty()
+   || theX < 0 || (Standard_Size )theX >= SizeX()
+   || theY < 0 || (Standard_Size )theY >= SizeY())
   {
     theAlpha = 0.0; // transparent
     return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
index ea831df..fe64ff3 100644 (file)
@@ -62,37 +62,37 @@ public: // high-level API
   //! @return image width in pixels
   inline Standard_Size Width() const
   {
-    return myData.mySizeX;
+    return myData.SizeX;
   }
 
   //! @return image height in pixels
   inline Standard_Size Height() const
   {
-    return myData.mySizeY;
+    return myData.SizeY;
   }
 
   //! @return image width in pixels
   inline Standard_Size SizeX() const
   {
-    return myData.mySizeX;
+    return myData.SizeX;
   }
 
   //! @return image height in pixels
   inline Standard_Size SizeY() const
   {
-    return myData.mySizeY;
+    return myData.SizeY;
   }
 
   //! @return width / height.
   inline Standard_Real Ratio() const
   {
-    return (myData.mySizeY > 0) ? (Standard_Real(myData.mySizeX) / Standard_Real(myData.mySizeY)) : 1.0;
+    return (SizeY() > 0) ? (Standard_Real(SizeX()) / Standard_Real(SizeY())) : 1.0;
   }
 
   //! @return true if data is NULL.
   bool IsEmpty() const
   {
-    return myData.myDataPtr == NULL;
+    return myData.IsEmpty();
   }
 
   //! Empty constructor. Initialize the NULL image plane.
@@ -148,9 +148,9 @@ public: // high-level API
                                  const Standard_Byte theValue = 0);
 
   //! Method correctly deallocate internal buffer.
-  Standard_EXPORT virtual void Clear (ImgFormat thePixelFormat = ImgGray);
+  Standard_EXPORT virtual void Clear();
 
-public: // low-level API for batch-processing (pixels reading / comparison / modification)
+public: //! @name low-level API for batch-processing (pixels reading / comparison / modification)
 
   //! Returns TRUE if image data is stored from Top to the Down.
   //! By default Bottom Up order is used instead
@@ -163,7 +163,7 @@ public: // low-level API for batch-processing (pixels reading / comparison / mod
   //! @return true if image data is top-down
   inline bool IsTopDown() const
   {
-    return myData.myTopToDown == 1;
+    return myData.TopToDown == 1;
   }
 
   //! Setup scanlines order in memory - top-down or bottom-up.
@@ -171,27 +171,26 @@ public: // low-level API for batch-processing (pixels reading / comparison / mod
   //! @param theIsTopDown top-down flag
   inline void SetTopDown (const bool theIsTopDown)
   {
-    myData.myTopToDown = (theIsTopDown ? 1 : Standard_Size(-1));
-    setTopDown();
+    myData.SetTopDown (theIsTopDown);
   }
 
   //! 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 myData.TopToDown;
   }
 
   //! @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 myData.Data();
   }
 
   //! @return data pointer for low-level operations (copying entire buffer, parsing with extra tools etc.).
   inline Standard_Byte* ChangeData()
   {
-    return myData.myDataPtr;
+    return myData.ChangeData();
   }
 
   //! @return data pointer to requested row (first column).
@@ -209,7 +208,7 @@ public: // low-level API for batch-processing (pixels reading / comparison / mod
   //! @return bytes reserved for one pixel (may include extra bytes for alignment).
   inline Standard_Size SizePixelBytes() const
   {
-    return myData.mySizeBPP;
+    return myData.SizeBPP;
   }
 
   //! @return bytes reserved for one pixel (may include extra bytes for alignment).
@@ -219,13 +218,13 @@ public: // low-level API for batch-processing (pixels reading / comparison / mod
   //! Could be larger than needed to store packed row (extra bytes for alignment etc.).
   inline Standard_Size SizeRowBytes() const
   {
-    return myData.mySizeRowBytes;
+    return myData.SizeRowBytes;
   }
 
   //! @return the extra bytes in the row.
   inline Standard_Size RowExtraBytes() const
   {
-    return myData.mySizeRowBytes - myData.mySizeX * myData.mySizeBPP;
+    return SizeRowBytes() - SizeX() * SizePixelBytes();
   }
 
   //! Compute the maximal row alignment for current row size.
@@ -235,31 +234,28 @@ public: // low-level API for batch-processing (pixels reading / comparison / mod
     return myData.MaxRowAligmentBytes();
   }
 
+  //! @return buffer size
   inline Standard_Size SizeBytes() const
   {
-    return myData.SizeBytes();
+    return myData.Size();
   }
 
-  //! 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.
+  //! Access image pixel with specified color type.
+  //! This method does not perform any type checks - use on own risk (check Format() before)!
   template <typename ColorType_t>
-  inline const Image_PixMapData<ColorType_t>& ReadData() const
+  inline const ColorType_t& Value (const Standard_Size theRow,
+                                   const Standard_Size theCol) const
   {
-    return *(Image_PixMapData<ColorType_t>* )&myData;
+    return *reinterpret_cast<const ColorType_t*>(myData.Value (theRow, theCol));
   }
 
   //! Access image pixel with specified color type.
+  //! This method does not perform any type checks - use on own risk (check Format() before)!
   template <typename ColorType_t>
-  inline const ColorType_t& Value (const Standard_Size theRow,
-                                   const Standard_Size theCol) const
+  inline ColorType_t& ChangeValue (const Standard_Size theRow,
+                                   const Standard_Size theCol)
   {
-    return ((Image_PixMapData<ColorType_t>* )&myData)->Value (theRow, theCol);
+    return *reinterpret_cast<ColorType_t* >(myData.ChangeValue (theRow, theCol));
   }
 
 protected:
@@ -267,14 +263,10 @@ 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
+  Image_PixMapData myData;      //!< data buffer
+  ImgFormat        myImgFormat; //!< pixel format
 
 private:
 
index b9d1089..155ee61 100644 (file)
 #define _Image_PixMapData_H__
 
 #include <Image_Color.hxx>
+#include <NCollection_Buffer.hxx>
 
-//! POD template structure to access image buffer
-template<typename ColorType_t>
-struct Image_PixMapData
+//! Structure to manage image buffer.
+class Image_PixMapData : public NCollection_Buffer
 {
+public:
 
-  //! @return data pointer for low-level operations (copying entire buffer, parsing with extra tools etc.).
-  inline const ColorType_t* Data() const
+  //! Empty constructor.
+  Image_PixMapData()
+  : NCollection_Buffer (Handle(NCollection_BaseAllocator)()),
+    myTopRowPtr  (NULL),
+    SizeBPP      (0),
+    SizeX        (0),
+    SizeY        (0),
+    SizeRowBytes (0),
+    TopToDown    (Standard_Size(-1))
   {
-    return (const ColorType_t* )myDataPtr;
+    //
   }
 
-  //! @return data pointer for low-level operations (copying entire buffer, parsing with extra tools etc.).
-  inline ColorType_t* ChangeData()
+  //! Initializer.
+  void Init (const Handle(NCollection_BaseAllocator)& theAlloc,
+             const Standard_Size                      theSizeBPP,
+             const Standard_Size                      theSizeX,
+             const Standard_Size                      theSizeY,
+             const Standard_Size                      theSizeRowBytes,
+             Standard_Byte*                           theDataPtr)
   {
-    return (ColorType_t* )myDataPtr;
+    SetAllocator (theAlloc); // will free old data as well
+
+    myData       = theDataPtr;
+    myTopRowPtr  = NULL;
+    SizeBPP      = theSizeBPP;
+    SizeX        = theSizeX;
+    SizeY        = theSizeY;
+    SizeRowBytes = theSizeRowBytes != 0 ? theSizeRowBytes : (theSizeX * theSizeBPP);
+    mySize       = SizeRowBytes * SizeY;
+    if (myData == NULL)
+    {
+      Allocate (mySize);
+    }
+    SetTopDown (TopToDown == 1);
   }
 
   //! @return data pointer to requested row (first column).
-  inline const ColorType_t* Row (const Standard_Size theRow) const
+  inline const Standard_Byte* Row (const Standard_Size theRow) const
   {
-    return (ColorType_t* )(myTopRowPtr + mySizeRowBytes * theRow * myTopToDown);
+    return myTopRowPtr + SizeRowBytes * theRow * TopToDown;
   }
 
   //! @return data pointer to requested row (first column).
-  inline ColorType_t* ChangeRow (const Standard_Size theRow)
+  inline Standard_Byte* ChangeRow (const Standard_Size theRow)
   {
-    return (ColorType_t* )(myTopRowPtr + mySizeRowBytes * theRow * myTopToDown);
+    return myTopRowPtr + SizeRowBytes * theRow * TopToDown;
   }
 
   //! @return data pointer to requested position.
-  inline const ColorType_t& Value (const Standard_Size theRow,
-                                   const Standard_Size theCol) const
+  inline const Standard_Byte* Value (const Standard_Size theRow,
+                                     const Standard_Size theCol) const
   {
-    return *(const ColorType_t* )(myTopRowPtr + mySizeRowBytes * theRow * myTopToDown + mySizeBPP * theCol);
+    return myTopRowPtr + SizeRowBytes * theRow * TopToDown + SizeBPP * theCol;
   }
 
   //! @return data pointer to requested position.
-  inline ColorType_t& ChangeValue (const Standard_Size theRow,
-                                   const Standard_Size theCol)
+  inline Standard_Byte* ChangeValue (const Standard_Size theRow,
+                                     const Standard_Size theCol)
   {
-    return *(ColorType_t* )(myTopRowPtr + mySizeRowBytes * theRow * myTopToDown + mySizeBPP * theCol);
+    return myTopRowPtr + SizeRowBytes * theRow * TopToDown + SizeBPP * theCol;
   }
 
   //! Compute the maximal row alignment for current row size.
@@ -68,7 +94,7 @@ struct Image_PixMapData
     Standard_Size anAlignment = 2;
     for (; anAlignment <= 16; anAlignment <<= 1)
     {
-      if ((mySizeRowBytes % anAlignment) != 0 || (Standard_Size(myDataPtr) % anAlignment) != 0)
+      if ((SizeRowBytes % anAlignment) != 0 || (Standard_Size(myData) % anAlignment) != 0)
       {
         return (anAlignment >> 1);
       }
@@ -76,34 +102,30 @@ struct Image_PixMapData
     return anAlignment;
   }
 
-  //! @return bytes allocated for the whole image plane.
-  inline Standard_Size SizeBytes() const
+  //! 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 (const bool theIsTopDown)
   {
-    return mySizeRowBytes * mySizeY;
+    TopToDown   = (theIsTopDown ? 1 : Standard_Size(-1));
+    myTopRowPtr = ((TopToDown == 1 || myData == NULL)
+                ? myData : (myData + SizeRowBytes * (SizeY - 1)));
   }
 
-  //! @return image width in pixels
-  inline Standard_Size SizeX() const
-  {
-    return mySizeX;
-  }
+protected:
 
-  //! @return image height in pixels
-  inline Standard_Size SizeY() const
-  {
-    return mySizeY;
-  }
+  Standard_Byte* myTopRowPtr;  //!< pointer to the topmost row (depending on scanlines order in memory)
 
 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
+  Standard_Size  SizeBPP;      //!< bytes per pixel
+  Standard_Size  SizeX;        //!< width  in pixels
+  Standard_Size  SizeY;        //!< height in pixels
+  Standard_Size  SizeRowBytes; //!< number of bytes per line (in most cases equal to 3 * sizeX)
+  Standard_Size  TopToDown;    //!< image scanlines direction in memory from Top to the Down
 
 };
 
+typedef NCollection_Handle<Image_PixMapData> Handle(Image_PixMapData);
+
 #endif // _Image_PixMapData_H__
index 78f0491..9609098 100644 (file)
@@ -695,11 +695,10 @@ Handle(Graphic3d_Texture2D) MeshVS_NodalColorPrsBuilder::CreateTexture() const
   }
 
   anImage->SetTopDown (false);
-  Image_PixMapData<Image_ColorRGBA>& aData = anImage->EditData<Image_ColorRGBA>();
   for (Standard_Size aCol = 0; aCol < Standard_Size(aColorsNb); ++aCol)
   {
     const Quantity_Color& aSrcColor = myTextureColorMap.Value (Standard_Integer(aCol) + 1);
-    Image_ColorRGBA& aColor = aData.ChangeValue (0, aCol);
+    Image_ColorRGBA& aColor = anImage->ChangeValue<Image_ColorRGBA> (0, aCol);
     aColor.r() = Standard_Byte(255.0 * aSrcColor.Red());
     aColor.g() = Standard_Byte(255.0 * aSrcColor.Green());
     aColor.b() = Standard_Byte(255.0 * aSrcColor.Blue());
@@ -719,7 +718,7 @@ Handle(Graphic3d_Texture2D) MeshVS_NodalColorPrsBuilder::CreateTexture() const
   // fill second row
   for (Standard_Size aCol = (Standard_Size )aColorsNb; aCol < anImage->SizeX(); ++aCol)
   {
-    aData.ChangeValue (0, aCol) = aLastColor;
+    anImage->ChangeValue<Image_ColorRGBA> (0, aCol) = aLastColor;
   }
 
   const Image_ColorRGBA anInvalidColor =
@@ -731,7 +730,7 @@ Handle(Graphic3d_Texture2D) MeshVS_NodalColorPrsBuilder::CreateTexture() const
   }};
   for (Standard_Size aCol = 0; aCol < anImage->SizeX(); ++aCol)
   {
-    aData.ChangeValue (1, aCol) = anInvalidColor;
+    anImage->ChangeValue<Image_ColorRGBA> (1, aCol) = anInvalidColor;
   }
 
   // create texture
index dba4e4d..f5c0d3a 100755 (executable)
@@ -91,6 +91,7 @@ NCollection_Haft.h
 NCollection_DefaultHasher.hxx
 NCollection_DefineAlloc.hxx
 
+NCollection_Buffer.hxx
 NCollection_Vec2.hxx
 NCollection_Vec3.hxx
 NCollection_Vec4.hxx
diff --git a/src/NCollection/NCollection_Buffer.hxx b/src/NCollection/NCollection_Buffer.hxx
new file mode 100644 (file)
index 0000000..eeb09a5
--- /dev/null
@@ -0,0 +1,135 @@
+// Created on: 2014-04-01
+// Created by: Kirill Gavrilov
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _NCollection_Buffer_HeaderFile
+#define _NCollection_Buffer_HeaderFile
+
+#include <NCollection_BaseAllocator.hxx>
+#include <NCollection_Handle.hxx>
+
+//! Low-level buffer object.
+class NCollection_Buffer
+{
+
+public:
+
+  //! Default constructor.
+  //! When theData is NULL but theSize is not 0 than buffer of specified size will be allocated.
+  //! @param theAlloc memory allocator
+  //! @param theSize  buffer size
+  //! @param theData  buffer data allocated by theAlloc
+  NCollection_Buffer (const Handle(NCollection_BaseAllocator)& theAlloc,
+                      const Standard_Size                      theSize = 0,
+                      Standard_Byte*                           theData = NULL)
+  : myData (NULL),
+    mySize (0),
+    myAllocator (theAlloc)
+  {
+    if (theData != NULL)
+    {
+      myData = theData;
+      mySize = theSize;
+    }
+    else
+    {
+      Allocate (theSize);
+    }
+  }
+
+  //! Destructor.
+  virtual ~NCollection_Buffer()
+  {
+    Free();
+  }
+
+  //! @return buffer data
+  const Standard_Byte* Data() const
+  {
+    return myData;
+  }
+
+  //! @return buffer data
+  Standard_Byte* ChangeData()
+  {
+    return myData;
+  }
+
+  //! @return true if buffer is not allocated
+  bool IsEmpty() const
+  {
+    return myData == NULL;
+  }
+
+  //! Return buffer length in bytes.
+  Standard_Size Size() const
+  {
+    return mySize;
+  }
+
+  //! @return buffer allocator
+  const Handle(NCollection_BaseAllocator)& Allocator() const
+  {
+    return myAllocator;
+  }
+
+  //! Assign new buffer allocator with de-allocation of buffer.
+  void SetAllocator (const Handle(NCollection_BaseAllocator)& theAlloc)
+  {
+    Free();
+    myAllocator = theAlloc;
+  }
+
+  //! Allocate the buffer.
+  //! @param theSize buffer length in bytes
+  bool Allocate (const Standard_Size theSize)
+  {
+    Free();
+    mySize = theSize;
+    if (theSize != 0
+    || !myAllocator.IsNull())
+    {
+      myData = (Standard_Byte* )myAllocator->Allocate (theSize);
+    }
+
+    if (myData == NULL)
+    {
+      mySize = 0;
+      return false;
+    }
+    return true;
+  }
+
+  //! De-allocate buffer.
+  void Free()
+  {
+    if (!myAllocator.IsNull())
+    {
+      myAllocator->Free (myData);
+    }
+    myData = NULL;
+    mySize = 0;
+  }
+
+protected:
+
+  Standard_Byte*                    myData;      //!< data pointer
+  Standard_Size                     mySize;      //!< buffer length in bytes
+  Handle(NCollection_BaseAllocator) myAllocator; //!< buffer allocator
+
+};
+
+typedef NCollection_Handle<NCollection_Buffer> Handle(NCollection_Buffer);
+
+#endif // _NCollection_Buffer_HeaderFile
index b294421..5ea5589 100644 (file)
@@ -1710,8 +1710,6 @@ void OpenGl_AspectMarker::Resources::BuildSprites (const Handle(OpenGl_Workspace
           anImageA = new Image_PixMap();
           anImage ->InitZero (Image_PixMap::ImgBGRA, aSize, aSize);
           anImageA->InitZero (Image_PixMap::ImgGray, aSize, aSize);
-          Image_PixMapData<Image_ColorBGRA>& aDataBGRA = anImage->EditData<Image_ColorBGRA>();
-          Image_PixMapData<Standard_Byte>&   aDataGray = anImageA->EditData<Standard_Byte>();
 
           // we draw a set of circles
           Image_ColorBGRA aColor32;
@@ -1729,8 +1727,8 @@ void OpenGl_AspectMarker::Resources::BuildSprites (const Handle(OpenGl_Workspace
             const Handle(Graphic3d_MarkerImage) aMarker = GetTextureImage (Aspect_TOM_O, aScale);
             const Handle(Image_PixMap)& aCircle = aMarker->GetImage();
 
-            const Standard_Size aDiffX = (aDataBGRA.SizeX() - aCircle->SizeX()) / 2;
-            const Standard_Size aDiffY = (aDataBGRA.SizeY() - aCircle->SizeY()) / 2;
+            const Standard_Size aDiffX = (anImage->SizeX() - aCircle->SizeX()) / 2;
+            const Standard_Size aDiffY = (anImage->SizeY() - aCircle->SizeY()) / 2;
             for (Standard_Size aRow = 0; aRow < aCircle->SizeY(); ++aRow)
             {
               const Standard_Byte* aRowData = aCircle->Row (aRow);
@@ -1738,8 +1736,8 @@ void OpenGl_AspectMarker::Resources::BuildSprites (const Handle(OpenGl_Workspace
               {
                 if (aRowData[aCol] != 0)
                 {
-                  aDataBGRA.ChangeValue (aDiffX + aRow, aDiffY + aCol) = aColor32;
-                  aDataGray.ChangeValue (aDiffX + aRow, aDiffY + aCol) = 255;
+                  anImage ->ChangeValue<Image_ColorBGRA> (aDiffX + aRow, aDiffY + aCol) = aColor32;
+                  anImageA->ChangeValue<Standard_Byte>   (aDiffX + aRow, aDiffY + aCol) = 255;
                 }
               }
             }
index a53e7a4..5110e24 100644 (file)
@@ -859,14 +859,13 @@ void OpenGl_View::CreateBackgroundTexture (const Standard_CString  theFilePath,
     }
 
     anImage.SetTopDown (false);
-    Image_PixMapData<Image_ColorRGB>& aDataNew = anImage.EditData<Image_ColorRGB>();
     Quantity_Color aSrcColor;
     for (Standard_Size aRow = 0; aRow < anImage.SizeY(); ++aRow)
     {
       for (Standard_Size aCol = 0; aCol < anImage.SizeX(); ++aCol)
       {
         aSrcColor = anImageLoaded.PixelColor ((Standard_Integer )aCol, (Standard_Integer )aRow);
-        Image_ColorRGB& aColor = aDataNew.ChangeValue (aRow, aCol);
+        Image_ColorRGB& aColor = anImage.ChangeValue<Image_ColorRGB> (aRow, aCol);
         aColor.r() = Standard_Byte(255.0 * aSrcColor.Red());
         aColor.g() = Standard_Byte(255.0 * aSrcColor.Green());
         aColor.b() = Standard_Byte(255.0 * aSrcColor.Blue());
index 6abcf85..3329b9b 100755 (executable)
@@ -1771,12 +1771,11 @@ static Standard_Integer OCC24622 (Draw_Interpretor& /*theDi*/, Standard_Integer
   else if (aTextureTypeArg == "2D")
   {
     anImage->InitTrash (Image_PixMap::ImgRGB, 8, 8);
-    Image_PixMapData<Image_ColorRGB>& anImageData = anImage->EditData<Image_ColorRGB>();
     for (Standard_Integer aRow = 0; aRow < 8; ++aRow)
     {
       for (Standard_Integer aCol = 0; aCol < 8; ++aCol)
       {
-        anImageData.ChangeValue (aRow, aCol) = aBitmap[aRow];
+        anImage->ChangeValue<Image_ColorRGB> (aRow, aCol) = aBitmap[aRow];
       }
     }
   }