From ca0c0b11ac5e755e38f090084635855584034059 Mon Sep 17 00:00:00 2001 From: kgv Date: Fri, 4 Apr 2014 09:15:40 +0400 Subject: [PATCH] 0024534: Improve design of Image_PixMap class 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. --- src/Image/Image_AlienPixMap.cxx | 18 ++- src/Image/Image_AlienPixMap.hxx | 2 +- src/Image/Image_Diff.cxx | 71 ++++++----- src/Image/Image_PixMap.cxx | 83 +++++-------- src/Image/Image_PixMap.hxx | 66 +++++----- src/Image/Image_PixMapData.hxx | 102 ++++++++++------ src/MeshVS/MeshVS_NodalColorPrsBuilder.cxx | 7 +- src/NCollection/FILES | 1 + src/NCollection/NCollection_Buffer.hxx | 135 +++++++++++++++++++++ src/OpenGl/OpenGl_AspectMarker.cxx | 10 +- src/OpenGl/OpenGl_View_2.cxx | 3 +- src/QABugs/QABugs_19.cxx | 3 +- 12 files changed, 313 insertions(+), 188 deletions(-) create mode 100644 src/NCollection/NCollection_Buffer.hxx diff --git a/src/Image/Image_AlienPixMap.cxx b/src/Image/Image_AlienPixMap.cxx index 298b7f3fe3..fb92dfefbc 100644 --- a/src/Image/Image_AlienPixMap.cxx +++ b/src/Image/Image_AlienPixMap.cxx @@ -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& aData = Image_PixMap::EditData(); 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; } } } diff --git a/src/Image/Image_AlienPixMap.hxx b/src/Image/Image_AlienPixMap.hxx index a7de5dd57d..7976ac5962 100644 --- a/src/Image/Image_AlienPixMap.hxx +++ b/src/Image/Image_AlienPixMap.hxx @@ -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 diff --git a/src/Image/Image_Diff.cxx b/src/Image/Image_Diff.cxx index 2e78644e6a..81eca33026 100644 --- a/src/Image/Image_Diff.cxx +++ b/src/Image/Image_Diff.cxx @@ -23,22 +23,36 @@ 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& 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 (theRowCenter + Standard_Size(row_inc), + theColCenter + Standard_Size(col_inc))); } - inline bool isValid (const Image_PixMapData& 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& aDataRef = myImageRef->EditData(); - Image_PixMapData& aDataNew = myImageNew->EditData(); - 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 (aRow, aCol); if (!isBlack (aPixel1)) { aPixel1 = aWhite; } + Image_ColorXXX24& aPixel2 = myImageNew->ChangeValue (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& aDataRef = myImageRef->ReadData(); - const Image_PixMapData& aDataNew = myImageNew->ReadData(); // 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 (aRow, aCol) - myImageRef->Value (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& aDataOut = theDiffImage.EditData(); + 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 (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 (aRow, aCol) = aWhite; } } @@ -401,8 +410,6 @@ Standard_Integer Image_Diff::ignoreBorderEffect() return 0; } - const Image_PixMapData& aDataRef = myImageRef->ReadData(); - // 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; } diff --git a/src/Image/Image_PixMap.cxx b/src/Image/Image_PixMap.cxx index 1f451388af..4297b021c2 100644 --- a/src/Image/Image_PixMap.cxx +++ b/src/Image/Image_PixMap.cxx @@ -14,7 +14,7 @@ // commercial license or contractual agreement. #include -#include +#include 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); diff --git a/src/Image/Image_PixMap.hxx b/src/Image/Image_PixMap.hxx index ea831dfc29..fe64ff3db3 100644 --- a/src/Image/Image_PixMap.hxx +++ b/src/Image/Image_PixMap.hxx @@ -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 - inline Image_PixMapData& EditData() - { - return *(Image_PixMapData* )&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 - inline const Image_PixMapData& ReadData() const + inline const ColorType_t& Value (const Standard_Size theRow, + const Standard_Size theCol) const { - return *(Image_PixMapData* )&myData; + return *reinterpret_cast(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 - 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* )&myData)->Value (theRow, theCol); + return *reinterpret_cast(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 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: diff --git a/src/Image/Image_PixMapData.hxx b/src/Image/Image_PixMapData.hxx index b9d1089093..155ee61d97 100644 --- a/src/Image/Image_PixMapData.hxx +++ b/src/Image/Image_PixMapData.hxx @@ -17,48 +17,74 @@ #define _Image_PixMapData_H__ #include +#include -//! POD template structure to access image buffer -template -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 Handle(Image_PixMapData); + #endif // _Image_PixMapData_H__ diff --git a/src/MeshVS/MeshVS_NodalColorPrsBuilder.cxx b/src/MeshVS/MeshVS_NodalColorPrsBuilder.cxx index 78f0491948..9609098744 100644 --- a/src/MeshVS/MeshVS_NodalColorPrsBuilder.cxx +++ b/src/MeshVS/MeshVS_NodalColorPrsBuilder.cxx @@ -695,11 +695,10 @@ Handle(Graphic3d_Texture2D) MeshVS_NodalColorPrsBuilder::CreateTexture() const } anImage->SetTopDown (false); - Image_PixMapData& aData = anImage->EditData(); 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 (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 (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 (1, aCol) = anInvalidColor; } // create texture diff --git a/src/NCollection/FILES b/src/NCollection/FILES index dba4e4dec4..f5c0d3af7e 100755 --- a/src/NCollection/FILES +++ b/src/NCollection/FILES @@ -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 index 0000000000..eeb09a517d --- /dev/null +++ b/src/NCollection/NCollection_Buffer.hxx @@ -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 +#include + +//! 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 Handle(NCollection_Buffer); + +#endif // _NCollection_Buffer_HeaderFile diff --git a/src/OpenGl/OpenGl_AspectMarker.cxx b/src/OpenGl/OpenGl_AspectMarker.cxx index b294421971..5ea558972e 100644 --- a/src/OpenGl/OpenGl_AspectMarker.cxx +++ b/src/OpenGl/OpenGl_AspectMarker.cxx @@ -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& aDataBGRA = anImage->EditData(); - Image_PixMapData& aDataGray = anImageA->EditData(); // 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 (aDiffX + aRow, aDiffY + aCol) = aColor32; + anImageA->ChangeValue (aDiffX + aRow, aDiffY + aCol) = 255; } } } diff --git a/src/OpenGl/OpenGl_View_2.cxx b/src/OpenGl/OpenGl_View_2.cxx index a53e7a433c..5110e24b4d 100644 --- a/src/OpenGl/OpenGl_View_2.cxx +++ b/src/OpenGl/OpenGl_View_2.cxx @@ -859,14 +859,13 @@ void OpenGl_View::CreateBackgroundTexture (const Standard_CString theFilePath, } anImage.SetTopDown (false); - Image_PixMapData& aDataNew = anImage.EditData(); 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 (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()); diff --git a/src/QABugs/QABugs_19.cxx b/src/QABugs/QABugs_19.cxx index 6abcf8525d..3329b9bb09 100755 --- a/src/QABugs/QABugs_19.cxx +++ b/src/QABugs/QABugs_19.cxx @@ -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& anImageData = anImage->EditData(); for (Standard_Integer aRow = 0; aRow < 8; ++aRow) { for (Standard_Integer aCol = 0; aCol < 8; ++aCol) { - anImageData.ChangeValue (aRow, aCol) = aBitmap[aRow]; + anImage->ChangeValue (aRow, aCol) = aBitmap[aRow]; } } } -- 2.39.5