1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

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.
This commit is contained in:
kgv
2014-04-04 09:15:40 +04:00
committed by abv
parent 927513c009
commit ca0c0b11ac
12 changed files with 315 additions and 190 deletions

View 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;
}
}
}

View 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

View File

@@ -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<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;
}

View 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);

View 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();
}
//! 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;
return myData.Size();
}
//! 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
{
return ((Image_PixMapData<ColorType_t>* )&myData)->Value (theRow, theCol);
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 ColorType_t& ChangeValue (const Standard_Size theRow,
const Standard_Size 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:

View File

@@ -17,48 +17,74 @@
#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__

View 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

View File

@@ -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

View File

@@ -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

View 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;
}
}
}

View 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());

View File

@@ -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];
}
}
}