1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00

0028876: Tests, Image_Diff - the image difference is unavailable for test case bugs vis bug28205_1

Quantity_ColorRGBA - added method SetValues().
Image_PixMap::PixelColor() now returns Quantity_ColorRGBA instead of Quantity_Color.
Image_PixMap::SetPixelColor() now takes Quantity_ColorRGBA instead of NCollection_Vec4<float>.

Image_Diff has been improved to support Image_Format_Gray.
Image_Diff::SaveDiffImage() now saves image difference
in Image_Format_Gray format to reduce size of image file.

Image_Diff now uses TColStd_HPackedMapOfInteger instead of
TColStd_MapOfInteger with manual memory allocation.
This commit is contained in:
kgv 2017-07-03 12:27:08 +03:00 committed by bugmaster
parent 4679d975dc
commit e958a649c6
13 changed files with 510 additions and 393 deletions

View File

@ -1252,6 +1252,7 @@ In most cases this change should be transparent, however applications implementi
* Enumeration *Image_PixMap::ImgFormat*, previously declared as nested enumeration within class *Image_PixMap*, has been moved to global namespace as *Image_Format* following OCCT coding rules. * Enumeration *Image_PixMap::ImgFormat*, previously declared as nested enumeration within class *Image_PixMap*, has been moved to global namespace as *Image_Format* following OCCT coding rules.
The enumeration values have suffix Image_Format_ and preserve previous name scheme for easy renaming of old values - e.g. Image_PixMap::ImgGray become Image_Format_Gray. The enumeration values have suffix Image_Format_ and preserve previous name scheme for easy renaming of old values - e.g. Image_PixMap::ImgGray become Image_Format_Gray.
Old definitions are preserved as depreacated aliases to the new ones; Old definitions are preserved as depreacated aliases to the new ones;
* Methods *Image_PixMap::PixelColor()* and *Image_PixMap::SetPixelColor()* now take/return Quantity_ColorRGBA instead of Quantity_Color/NCollection_Vec4.
* The method BOPAlgo_Builder::Origins() returns BOPCol_DataMapOfShapeListOfShape instead of BOPCol_DataMapOfShapeShape. * The method BOPAlgo_Builder::Origins() returns BOPCol_DataMapOfShapeListOfShape instead of BOPCol_DataMapOfShapeShape.
* The methods BOPDS_DS::IsToSort(const Handle(BOPDS_CommonBlock)&, Standard_Integer&) and BOPDS_DS::SortPaveBlocks(const Handle(BOPDS_CommonBlock)&) have been removed. The sorting is now performed during the addition of the Pave Blocks into Common Block. * The methods BOPDS_DS::IsToSort(const Handle(BOPDS_CommonBlock)&, Standard_Integer&) and BOPDS_DS::SortPaveBlocks(const Handle(BOPDS_CommonBlock)&) have been removed. The sorting is now performed during the addition of the Pave Blocks into Common Block.
* The methods BOPAlgo_Tools::MakeBlocks() and BOPAlgo_Tools::MakeBlocksCnx() have been replaced with the single template method BOPAlgo_Tools::MakeBlocks(). The chains of connected elements are now stored into the list of list instead of data map. * The methods BOPAlgo_Tools::MakeBlocks() and BOPAlgo_Tools::MakeBlocksCnx() have been replaced with the single template method BOPAlgo_Tools::MakeBlocks(). The chains of connected elements are now stored into the list of list instead of data map.

View File

@ -90,21 +90,15 @@ Handle(TColStd_HArray1OfByte) Graphic3d_MarkerImage::GetBitMapArray (const Stand
{ {
for (Standard_Integer aColumn = 0; aColumn < aWidth; aColumn++) for (Standard_Integer aColumn = 0; aColumn < aWidth; aColumn++)
{ {
Standard_Real anAlphaValue; const Quantity_ColorRGBA aColor = myImage->PixelColor (aColumn, aRow);
Quantity_Color aColor = myImage->PixelColor (aColumn, aRow, anAlphaValue);
Standard_Boolean aBitOn = Standard_False; Standard_Boolean aBitOn = Standard_False;
if (myImage->Format() == Image_Format_Gray)
if (myImage->Format() == Image_Format_Alpha)
{ {
aBitOn = anAlphaValue > theAlphaValue; aBitOn = aColor.GetRGB().Red() > theAlphaValue;
} }
else if (myImage->Format() == Image_Format_Gray) else //if (myImage->Format() == Image_Format_Alpha)
{ {
aBitOn = aColor.Red() > theAlphaValue; aBitOn = aColor.Alpha() > theAlphaValue;
}
else
{
aBitOn = anAlphaValue > theAlphaValue;
} }
Standard_Integer anIndex = aNumOfBytesInRow * aRow + aColumn / 8; Standard_Integer anIndex = aNumOfBytesInRow * aRow + aColumn / 8;
@ -179,14 +173,13 @@ const Handle(Image_PixMap)& Graphic3d_MarkerImage::GetImageAlpha()
myImageAlpha = new Image_PixMap(); myImageAlpha = new Image_PixMap();
myImageAlpha->InitZero (Image_Format_Alpha, myImage->Width(), myImage->Height()); myImageAlpha->InitZero (Image_Format_Alpha, myImage->Width(), myImage->Height());
myImageAlpha->SetTopDown (Standard_False); myImageAlpha->SetTopDown (Standard_False);
Standard_Real anAlpha;
for (Standard_Size aRowIter = 0; aRowIter < myImage->Height(); aRowIter++) for (Standard_Size aRowIter = 0; aRowIter < myImage->Height(); aRowIter++)
{ {
Standard_Byte* anImageRow = myImageAlpha->ChangeRow (aRowIter); Standard_Byte* anImageRow = myImageAlpha->ChangeRow (aRowIter);
for (Standard_Size aColumnIter = 0; aColumnIter < myImage->Width(); aColumnIter++) for (Standard_Size aColumnIter = 0; aColumnIter < myImage->Width(); aColumnIter++)
{ {
myImage->PixelColor ((Standard_Integer)aColumnIter, (Standard_Integer)aRowIter, anAlpha); const Quantity_ColorRGBA aColor = myImage->PixelColor ((Standard_Integer)aColumnIter, (Standard_Integer)aRowIter);
anImageRow[aColumnIter] = Standard_Byte (255.0 * anAlpha); anImageRow[aColumnIter] = Standard_Byte (255.0 * aColor.Alpha());
} }
} }
} }

View File

@ -349,18 +349,16 @@ bool Image_AlienPixMap::savePPM (const TCollection_AsciiString& theFileName) con
fprintf (aFile, "# Image stored by OpenCASCADE framework in linear RGB colorspace\n"); fprintf (aFile, "# Image stored by OpenCASCADE framework in linear RGB colorspace\n");
// Write pixel data // Write pixel data
Quantity_Color aColor;
Standard_Real aDummy;
Standard_Byte aByte; Standard_Byte aByte;
for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow) for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
{ {
for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol) for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol)
{ {
// extremely SLOW but universal (implemented for all supported pixel formats) // extremely SLOW but universal (implemented for all supported pixel formats)
aColor = PixelColor ((Standard_Integer )aCol, (Standard_Integer )aRow, aDummy); const Quantity_ColorRGBA aColor = PixelColor ((Standard_Integer )aCol, (Standard_Integer )aRow);
aByte = Standard_Byte(aColor.Red() * 255.0); fwrite (&aByte, 1, 1, aFile); aByte = Standard_Byte(aColor.GetRGB().Red() * 255.0); fwrite (&aByte, 1, 1, aFile);
aByte = Standard_Byte(aColor.Green() * 255.0); fwrite (&aByte, 1, 1, aFile); aByte = Standard_Byte(aColor.GetRGB().Green() * 255.0); fwrite (&aByte, 1, 1, aFile);
aByte = Standard_Byte(aColor.Blue() * 255.0); fwrite (&aByte, 1, 1, aFile); aByte = Standard_Byte(aColor.GetRGB().Blue() * 255.0); fwrite (&aByte, 1, 1, aFile);
} }
} }

View File

@ -14,120 +14,88 @@
// commercial license or contractual agreement. // commercial license or contractual agreement.
#include <Image_Diff.hxx> #include <Image_Diff.hxx>
#include <Image_AlienPixMap.hxx>
#include <TColStd_MapIteratorOfMapOfInteger.hxx> #include <Image_AlienPixMap.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
#include <cstdlib> #include <cstdlib>
IMPLEMENT_STANDARD_RTTIEXT(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_ColorXXX24& theColor)
{
// explicitly convert to integer
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_ColorXXX24& theColor)
{
return theColor.v[0] == 0
&& theColor.v[1] == 0
&& theColor.v[2] == 0;
}
//! Converts a pixel position (row, column) to one integer value
inline Standard_Size pixel2Int (const Standard_Size aRow,
const Standard_Size aCol)
{
return aCol + (aRow << 15);
}
//! Converts an integer value to pixel coordinates (row, column)
inline void int2Pixel (const Standard_Size theValue,
Standard_Size& theRow,
Standard_Size& theCol)
{
theRow = (theValue >> 15);
theCol = theValue - (theRow << 15);
}
namespace namespace
{ {
inline ptrdiff_t getAbs (const ptrdiff_t theValue) //! POD structure for packed RGB color value (3 bytes)
struct Image_ColorXXX24
{ {
return theValue >= 0 ? theValue : -theValue; Standard_Byte v[3];
} typedef Standard_Byte ComponentType_t; //!< Component type
static Standard_Integer Length() { return 3; } //!< Returns the number of components
static const Standard_Size NEIGHBOR_PIXELS_NB = 8;
static struct
{
Standard_Integer row_inc;
Standard_Integer col_inc;
inline Standard_Size pixel2Int (const Standard_Size theRowCenter,
const Standard_Size theColCenter) const
{
return ::pixel2Int (theRowCenter + Standard_Size(row_inc),
theColCenter + Standard_Size(col_inc));
}
inline bool isBlack (const Image_PixMap& theData,
const Standard_Size theRowCenter,
const Standard_Size theColCenter) const
{
return ::isBlack (theData.Value<Image_ColorXXX24> (theRowCenter + Standard_Size(row_inc),
theColCenter + Standard_Size(col_inc)));
}
inline bool isValid (const Image_PixMap& theData,
const Standard_Size theRowCenter,
const Standard_Size theColCenter) const
{
const Standard_Size aRow = theRowCenter + Standard_Size(row_inc);
const Standard_Size aCol = theColCenter + Standard_Size(col_inc);
return aRow < theData.SizeX() // this unsigned math checks Standard_Size(-1) at-once
&& aCol < theData.SizeY();
}
}
const NEIGHBOR_PIXELS[NEIGHBOR_PIXELS_NB] =
{
{-1, -1}, {-1, 0}, {-1, 1},
{ 0, -1}, { 0, 1},
{ 1, -1}, { 1, 0}, { 1, 1}
}; };
static bool isSupportedFormat (const Image_Format theFormat) static Image_ColorXXX24 operator- (const Image_ColorXXX24& theA,
const Image_ColorXXX24& theB)
{ {
return theFormat == Image_Format_RGB return Image_ColorSub3 (theA, theB);
|| theFormat == Image_Format_BGR
|| theFormat == Image_Format_RGB32
|| theFormat == Image_Format_BGR32
|| theFormat == Image_Format_RGBA
|| theFormat == Image_Format_BGRA;
} }
} // anonymous namespace //! Dot squared for difference of two colors
static Standard_Integer dotSquared (const Image_ColorXXX24& theColor)
{
// explicitly convert to integer
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;
}
//! Number of neighbor pixels.
static const Standard_Size Image_Diff_NbOfNeighborPixels = 8;
//! List of neighbor pixels (offsets).
static const int Image_Diff_NEIGHBOR_PIXELS[Image_Diff_NbOfNeighborPixels][2] =
{
{-1, -1}, {0, -1}, {1, -1},
{-1, 0}, {1, 0},
{-1, 1}, {0, 1}, {1, 1}
};
//! @return true if pixel is black
static bool isBlackPixel (const Image_PixMap& theData, Standard_Size theY, Standard_Size theX)
{
switch (theData.Format())
{
case Image_Format_Gray:
case Image_Format_Alpha:
{
return theData.Value<unsigned char> (theY, theX) == 0;
}
case Image_Format_RGB:
case Image_Format_BGR:
case Image_Format_RGB32:
case Image_Format_BGR32:
case Image_Format_RGBA:
case Image_Format_BGRA:
{
const Image_ColorXXX24& aColor = theData.Value<Image_ColorXXX24> (theY, theX);
return aColor.v[0] == 0
&& aColor.v[1] == 0
&& aColor.v[2] == 0;
}
default:
{
const Quantity_ColorRGBA aPixelRgba = theData.PixelColor ((int)theY, (int)theX);
const NCollection_Vec4<float>& aPixel = aPixelRgba;
return aPixel.r() == 0.0f
&& aPixel.g() == 0.0f
&& aPixel.b() == 0.0f;
}
}
}
}
// ======================================================================= // =======================================================================
// function : Image_Diff // function : Image_Diff
@ -167,56 +135,26 @@ Standard_Boolean Image_Diff::Init (const Handle(Image_PixMap)& theImageRef,
|| theImageRef->SizeY() != theImageNew->SizeY() || theImageRef->SizeY() != theImageNew->SizeY()
|| theImageRef->Format() != theImageNew->Format()) || theImageRef->Format() != theImageNew->Format())
{ {
#ifdef OCCT_DEBUG Message::DefaultMessenger()->Send ("Error: Images have different format or dimensions", Message_Fail);
std::cerr << "Images has different format or dimensions\n";
#endif
return Standard_False;
}
else if (!isSupportedFormat (theImageRef->Format()))
{
#ifdef OCCT_DEBUG
std::cerr << "Images has unsupported pixel format\n";
#endif
return Standard_False; return Standard_False;
} }
else if (theImageRef->SizeX() >= 0xFFFF else if (theImageRef->SizeX() >= 0xFFFF
|| theImageRef->SizeY() >= 0xFFFF) || theImageRef->SizeY() >= 0xFFFF)
{ {
#ifdef OCCT_DEBUG Message::DefaultMessenger()->Send ("Error: Images are too large", Message_Fail);
std::cerr << "Image too large\n";
#endif
return Standard_False; return Standard_False;
} }
myImageRef = theImageRef; myImageRef = theImageRef;
myImageNew = theImageNew; myImageNew = theImageNew;
if (theToBlackWhite) if (theToBlackWhite)
{ {
// Convert the images to white/black Image_PixMap::ToBlackWhite (*myImageRef);
const Image_ColorXXX24 aWhite = {{255, 255, 255}}; Image_PixMap::ToBlackWhite (*myImageNew);
for (Standard_Size aRow = 0; aRow < myImageRef->SizeY(); ++aRow)
{
for (Standard_Size aCol = 0; aCol < myImageRef->SizeX(); ++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;
}
}
}
} }
return Standard_True; return Standard_True;
} }
// ======================================================================= // =======================================================================
// function : Init // function : Init
// purpose : // purpose :
@ -230,50 +168,12 @@ Standard_Boolean Image_Diff::Init (const TCollection_AsciiString& theImgPathRef,
if (!anImgRef->Load (theImgPathRef) if (!anImgRef->Load (theImgPathRef)
|| !anImgNew->Load (theImgPathNew)) || !anImgNew->Load (theImgPathNew))
{ {
#ifdef OCCT_DEBUG Message::DefaultMessenger()->Send ("Error: Failed to load image(s) file(s)", Message_Fail);
std::cerr << "Failed to load image(s) file(s)\n";
#endif
return Standard_False; return Standard_False;
} }
return Init (anImgRef, anImgNew, theToBlackWhite); return Init (anImgRef, anImgNew, theToBlackWhite);
} }
// =======================================================================
// function : SetColorTolerance
// purpose :
// =======================================================================
void Image_Diff::SetColorTolerance (const Standard_Real theTolerance)
{
myColorTolerance = theTolerance;
}
// =======================================================================
// function : ColorTolerance
// purpose :
// =======================================================================
Standard_Real Image_Diff::ColorTolerance() const
{
return myColorTolerance;
}
// =======================================================================
// function : SetBorderFilterOn
// purpose :
// =======================================================================
void Image_Diff::SetBorderFilterOn (const Standard_Boolean theToIgnore)
{
myIsBorderFilterOn = theToIgnore;
}
// =======================================================================
// function : IsBorderFilterOn
// purpose :
// =======================================================================
Standard_Boolean Image_Diff::IsBorderFilterOn() const
{
return myIsBorderFilterOn;
}
// ======================================================================= // =======================================================================
// function : Compare // function : Compare
// purpose : // purpose :
@ -289,38 +189,94 @@ Standard_Integer Image_Diff::Compare()
return -1; return -1;
} }
// first check if images are exactly teh same // first check if images are exactly the same
if (! memcmp (myImageNew->Data(), myImageRef->Data(), myImageRef->SizeBytes())) if (myImageNew->SizeBytes() == myImageRef->SizeBytes()
&& memcmp (myImageNew->Data(), myImageRef->Data(), myImageRef->SizeBytes()) == 0)
{ {
return 0; return 0;
} }
// Tolerance of comparison operation for color switch (myImageRef->Format())
// Maximum difference between colors (white - black) = 100%
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
// compare colors of each pixel
for (Standard_Size aRow = 0; aRow < myImageRef->SizeY(); ++aRow)
{ {
for (Standard_Size aCol = 0; aCol < myImageRef->SizeX(); ++aCol) case Image_Format_Gray:
case Image_Format_Alpha:
{ {
aDiff = myImageNew->Value<Image_ColorXXX24> (aRow, aCol) - myImageRef->Value<Image_ColorXXX24> (aRow, aCol); // Tolerance of comparison operation for color
if (dotSquared (aDiff) > aDiffThreshold) Standard_Integer aDiff = 255;
const Standard_Real aMaxDiffColor = aDiff * aDiff;
const Standard_Integer aDiffThreshold = Standard_Integer(aMaxDiffColor * myColorTolerance);
for (Standard_Size aRow = 0; aRow < myImageRef->SizeY(); ++aRow)
{ {
const Standard_Size aValue = pixel2Int (aRow, aCol); for (Standard_Size aCol = 0; aCol < myImageRef->SizeX(); ++aCol)
myDiffPixels.Append (aValue); {
++aNbDiffColors; aDiff = Standard_Integer(myImageNew->Value<unsigned char> (aRow, aCol)) - Standard_Integer(myImageRef->Value<unsigned char> (aRow, aCol));
if (aDiff * aDiff > aDiffThreshold)
{
myDiffPixels.Append (PackXY ((uint16_t)aCol, (uint16_t)aRow));
++aNbDiffColors;
}
}
} }
break;
}
case Image_Format_RGB:
case Image_Format_BGR:
case Image_Format_RGB32:
case Image_Format_BGR32:
case Image_Format_RGBA:
case Image_Format_BGRA:
{
// Tolerance of comparison operation for color
// Maximum difference between colors (white - black) = 100%
Image_ColorXXX24 aDiff = {{255, 255, 255}};
const Standard_Real aMaxDiffColor = dotSquared (aDiff);
const Standard_Integer aDiffThreshold = Standard_Integer(aMaxDiffColor * myColorTolerance);
// we don't care about RGB/BGR/RGBA/BGRA/RGB32/BGR32 differences
// because we just compute summ of r g b components
for (Standard_Size aRow = 0; aRow < myImageRef->SizeY(); ++aRow)
{
for (Standard_Size aCol = 0; aCol < myImageRef->SizeX(); ++aCol)
{
aDiff = myImageNew->Value<Image_ColorXXX24> (aRow, aCol) - myImageRef->Value<Image_ColorXXX24> (aRow, aCol);
if (dotSquared (aDiff) > aDiffThreshold)
{
myDiffPixels.Append (PackXY ((uint16_t)aCol, (uint16_t)aRow));
++aNbDiffColors;
}
}
}
break;
}
default:
{
// Tolerance of comparison operation for color
// Maximum difference between colors (white - black) = 100%
NCollection_Vec3<float> aDiff (1.0f, 1.0f, 1.0f);
const Standard_Real aMaxDiffColor = aDiff.SquareModulus();
const Standard_Integer aDiffThreshold = Standard_Integer(aMaxDiffColor * myColorTolerance);
for (Standard_Size aRow = 0; aRow < myImageRef->SizeY(); ++aRow)
{
for (Standard_Size aCol = 0; aCol < myImageRef->SizeX(); ++aCol)
{
const Quantity_ColorRGBA aPixel1Rgba = myImageRef->PixelColor (Standard_Integer(aCol), Standard_Integer(aRow));
const Quantity_ColorRGBA aPixel2Rgba = myImageNew->PixelColor (Standard_Integer(aCol), Standard_Integer(aRow));
const NCollection_Vec3<float>& aPixel1 = aPixel1Rgba.GetRGB();
const NCollection_Vec3<float>& aPixel2 = aPixel2Rgba.GetRGB();
aDiff = aPixel2 - aPixel1;
if (aDiff.SquareModulus() > aDiffThreshold)
{
myDiffPixels.Append (PackXY ((uint16_t)aCol, (uint16_t)aRow));
++aNbDiffColors;
}
}
}
break;
} }
} }
// take into account a border effect // take into account a border effect
if (myIsBorderFilterOn && myDiffPixels.Length() > 0) if (myIsBorderFilterOn && !myDiffPixels.IsEmpty())
{ {
aNbDiffColors = ignoreBorderEffect(); aNbDiffColors = ignoreBorderEffect();
} }
@ -341,17 +297,16 @@ Standard_Boolean Image_Diff::SaveDiffImage (Image_PixMap& theDiffImage) const
if (theDiffImage.IsEmpty() if (theDiffImage.IsEmpty()
|| theDiffImage.SizeX() != myImageRef->SizeX() || theDiffImage.SizeX() != myImageRef->SizeX()
|| theDiffImage.SizeY() != myImageRef->SizeY() || theDiffImage.SizeY() != myImageRef->SizeY())
|| !isSupportedFormat (theDiffImage.Format()))
{ {
if (!theDiffImage.InitTrash (Image_Format_RGB, myImageRef->SizeX(), myImageRef->SizeY())) if (!theDiffImage.InitTrash (Image_Format_Gray, myImageRef->SizeX(), myImageRef->SizeY()))
{ {
return Standard_False; return Standard_False;
} }
} }
Standard_Size aRow, aCol; const Image_ColorXXX24 aWhite24 = {{255, 255, 255}};
const Image_ColorXXX24 aWhite = {{255, 255, 255}}; const Quantity_ColorRGBA aWhiteRgba (1.0f, 1.0f, 1.0f, 1.0f);
// initialize black image for dump // initialize black image for dump
memset (theDiffImage.ChangeData(), 0, theDiffImage.SizeBytes()); memset (theDiffImage.ChangeData(), 0, theDiffImage.SizeBytes());
@ -362,30 +317,86 @@ Standard_Boolean Image_Diff::SaveDiffImage (Image_PixMap& theDiffImage) const
return Standard_True; return Standard_True;
} }
for (Standard_Integer aPixelId = 0; aPixelId < myDiffPixels.Length(); ++aPixelId) switch (theDiffImage.Format())
{ {
const Standard_Size aValue = myDiffPixels.Value (aPixelId); case Image_Format_Gray:
int2Pixel (aValue, aRow, aCol); case Image_Format_Alpha:
theDiffImage.ChangeValue<Image_ColorXXX24> (aRow, aCol) = aWhite; {
for (NCollection_Vector<Standard_Integer>::Iterator aPixelIter (myDiffPixels); aPixelIter.More(); aPixelIter.Next())
{
theDiffImage.ChangeValue<unsigned char> (UnpackY(aPixelIter.Value()), UnpackX(aPixelIter.Value())) = 255;
}
break;
}
case Image_Format_RGB:
case Image_Format_BGR:
case Image_Format_RGB32:
case Image_Format_BGR32:
case Image_Format_RGBA:
case Image_Format_BGRA:
{
for (NCollection_Vector<Standard_Integer>::Iterator aPixelIter (myDiffPixels); aPixelIter.More(); aPixelIter.Next())
{
theDiffImage.ChangeValue<Image_ColorXXX24> (UnpackY(aPixelIter.Value()), UnpackX(aPixelIter.Value())) = aWhite24;
}
break;
}
default:
{
for (NCollection_Vector<Standard_Integer>::Iterator aPixelIter (myDiffPixels); aPixelIter.More(); aPixelIter.Next())
{
theDiffImage.SetPixelColor (UnpackX(aPixelIter.Value()), UnpackY(aPixelIter.Value()), aWhiteRgba);
}
break;
}
} }
return Standard_True; return Standard_True;
} }
Standard_Integer aGroupId = 1; Standard_Integer aGroupId = 1;
for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next(), ++aGroupId) for (NCollection_List<Handle(TColStd_HPackedMapOfInteger)>::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next(), ++aGroupId)
{ {
if (myLinearGroups.Contains (aGroupId)) if (myLinearGroups.Contains (aGroupId))
{ {
continue; // skip linear groups continue; // skip linear groups
} }
const TColStd_MapOfInteger* aGroup = aGrIter.Value(); const Handle(TColStd_HPackedMapOfInteger)& aGroup = aGrIter.Value();
for (TColStd_MapIteratorOfMapOfInteger aPixelIter(*aGroup); switch (theDiffImage.Format())
aPixelIter.More(); aPixelIter.Next())
{ {
int2Pixel (aPixelIter.Key(), aRow, aCol); case Image_Format_Gray:
theDiffImage.ChangeValue<Image_ColorXXX24> (aRow, aCol) = aWhite; case Image_Format_Alpha:
{
for (TColStd_MapIteratorOfPackedMapOfInteger aPixelIter (aGroup->Map()); aPixelIter.More(); aPixelIter.Next())
{
Standard_Integer aDiffPixel (aPixelIter.Key());
theDiffImage.ChangeValue<unsigned char> (UnpackY(aDiffPixel), UnpackX(aDiffPixel)) = 255;
}
break;
}
case Image_Format_RGB:
case Image_Format_BGR:
case Image_Format_RGB32:
case Image_Format_BGR32:
case Image_Format_RGBA:
case Image_Format_BGRA:
{
for (TColStd_MapIteratorOfPackedMapOfInteger aPixelIter (aGroup->Map()); aPixelIter.More(); aPixelIter.Next())
{
Standard_Integer aDiffPixel (aPixelIter.Key());
theDiffImage.ChangeValue<Image_ColorXXX24> (UnpackY(aDiffPixel), UnpackX(aDiffPixel)) = aWhite24;
}
break;
}
default:
{
for (TColStd_MapIteratorOfPackedMapOfInteger aPixelIter (aGroup->Map()); aPixelIter.More(); aPixelIter.Next())
{
Standard_Integer aDiffPixel (aPixelIter.Key());
theDiffImage.SetPixelColor (UnpackX(aDiffPixel), UnpackY(aDiffPixel), aWhiteRgba);
}
break;
}
} }
} }
@ -404,7 +415,7 @@ Standard_Boolean Image_Diff::SaveDiffImage (const TCollection_AsciiString& theDi
} }
Image_AlienPixMap aDiff; Image_AlienPixMap aDiff;
if (!aDiff.InitTrash (Image_Format_RGB, myImageRef->SizeX(), myImageRef->SizeY()) if (!aDiff.InitTrash (Image_Format_Gray, myImageRef->SizeX(), myImageRef->SizeY())
|| !SaveDiffImage (aDiff)) || !SaveDiffImage (aDiff))
{ {
return Standard_False; return Standard_False;
@ -430,39 +441,36 @@ Standard_Integer Image_Diff::ignoreBorderEffect()
// Find a different area (a set of close to each other pixels which colors differ in both images). // Find a different area (a set of close to each other pixels which colors differ in both images).
// It filters alone pixels with different color. // It filters alone pixels with different color.
Standard_Size aRow1 = 0, aCol1 = 0, aRow2, aCol2; const Standard_Integer aLen1 = !myDiffPixels.IsEmpty() ? (myDiffPixels.Length() - 1) : 0;
Standard_Integer aLen1 = (myDiffPixels.Length() > 0) ? (myDiffPixels.Length() - 1) : 0;
for (Standard_Integer aPixelId1 = 0; aPixelId1 < aLen1; ++aPixelId1) for (Standard_Integer aPixelId1 = 0; aPixelId1 < aLen1; ++aPixelId1)
{ {
const Standard_Size aValue1 = myDiffPixels.Value (aPixelId1); Standard_Integer aValue1 = myDiffPixels.Value (aPixelId1);
int2Pixel (aValue1, aRow1, aCol1);
// Check other pixels in the list looking for a neighbour of this one // Check other pixels in the list looking for a neighbour of this one
for (Standard_Integer aPixelId2 = aPixelId1 + 1; aPixelId2 < myDiffPixels.Length(); ++aPixelId2) for (Standard_Integer aPixelId2 = aPixelId1 + 1; aPixelId2 < myDiffPixels.Length(); ++aPixelId2)
{ {
const Standard_Size aValue2 = myDiffPixels.Value (aPixelId2); Standard_Integer aValue2 = myDiffPixels.Value (aPixelId2);
int2Pixel (aValue2, aRow2, aCol2); if (Abs (Standard_Integer(UnpackX(aValue1)) - Standard_Integer(UnpackX(aValue2))) <= 1
if (getAbs (ptrdiff_t (aCol1 - aCol2)) <= 1 && && Abs (Standard_Integer(UnpackY(aValue1)) - Standard_Integer(UnpackY(aValue2))) <= 1)
getAbs (ptrdiff_t (aRow1 - aRow2)) <= 1)
{ {
// A neighbour is found. Create a new group and add both pixels. // A neighbour is found. Create a new group and add both pixels.
if (myGroupsOfDiffPixels.IsEmpty()) if (myGroupsOfDiffPixels.IsEmpty())
{ {
TColStd_MapOfInteger* aGroup = new TColStd_MapOfInteger(); Handle(TColStd_HPackedMapOfInteger) aGroup = new TColStd_HPackedMapOfInteger();
aGroup->Add ((Standard_Integer)aValue1); aGroup->ChangeMap().Add (aValue1);
aGroup->Add ((Standard_Integer)aValue2); aGroup->ChangeMap().Add (aValue2);
myGroupsOfDiffPixels.Append (aGroup); myGroupsOfDiffPixels.Append (aGroup);
} }
else else
{ {
// Find a group the pixels belong to. // Find a group the pixels belong to.
Standard_Boolean isFound = Standard_False; Standard_Boolean isFound = Standard_False;
for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next()) for (NCollection_List<Handle(TColStd_HPackedMapOfInteger)>::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next())
{ {
TColStd_MapOfInteger*& aGroup = aGrIter.ChangeValue(); const Handle(TColStd_HPackedMapOfInteger)& aGroup = aGrIter.ChangeValue();
if (aGroup->Contains ((Standard_Integer)aValue1)) if (aGroup->Map().Contains (aValue1))
{ {
aGroup->Add ((Standard_Integer)aValue2); aGroup->ChangeMap().Add (aValue2);
isFound = Standard_True; isFound = Standard_True;
break; break;
} }
@ -471,9 +479,9 @@ Standard_Integer Image_Diff::ignoreBorderEffect()
if (!isFound) if (!isFound)
{ {
// Create a new group // Create a new group
TColStd_MapOfInteger* aGroup = new TColStd_MapOfInteger(); Handle(TColStd_HPackedMapOfInteger) aGroup = new TColStd_HPackedMapOfInteger();
aGroup->Add ((Standard_Integer)aValue1); aGroup->ChangeMap().Add (aValue1);
aGroup->Add ((Standard_Integer)aValue2); aGroup->ChangeMap().Add (aValue2);
myGroupsOfDiffPixels.Append (aGroup); myGroupsOfDiffPixels.Append (aGroup);
} }
} }
@ -483,22 +491,31 @@ Standard_Integer Image_Diff::ignoreBorderEffect()
// filter linear groups which represent border of a solid shape // filter linear groups which represent border of a solid shape
Standard_Integer aGroupId = 1; Standard_Integer aGroupId = 1;
for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next(), ++aGroupId) for (NCollection_List<Handle(TColStd_HPackedMapOfInteger)>::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next(), ++aGroupId)
{ {
Standard_Integer aNeighboursNb = 0; Standard_Integer aNeighboursNb = 0;
Standard_Boolean isLine = Standard_True; Standard_Boolean isLine = Standard_True;
const TColStd_MapOfInteger* aGroup = aGrIter.Value(); const Handle(TColStd_HPackedMapOfInteger)& aGroup = aGrIter.Value();
for (TColStd_MapIteratorOfMapOfInteger aPixelIter (*aGroup); aPixelIter.More(); aPixelIter.Next()) if (aGroup->Map().IsEmpty())
{ {
int2Pixel (aPixelIter.Key(), aRow1, aCol1); continue;
}
Standard_Integer aDiffPixel = 0;
for (TColStd_MapIteratorOfPackedMapOfInteger aPixelIter (aGroup->Map()); aPixelIter.More(); aPixelIter.Next())
{
aDiffPixel = aPixelIter.Key();
aNeighboursNb = 0; aNeighboursNb = 0;
// pixels of a line have only 1 or 2 neighbour pixels inside the same group // pixels of a line have only 1 or 2 neighbour pixels inside the same group
// check all neighbour pixels on presence in the group // check all neighbour pixels on presence in the group
for (Standard_Size aNgbrIter = 0; aNgbrIter < NEIGHBOR_PIXELS_NB; ++aNgbrIter) for (Standard_Size aNgbrIter = 0; aNgbrIter < Image_Diff_NbOfNeighborPixels; ++aNgbrIter)
{ {
if (NEIGHBOR_PIXELS[aNgbrIter].isValid (*myImageRef, aRow1, aCol1) Standard_Integer anX = UnpackX(aDiffPixel) + Image_Diff_NEIGHBOR_PIXELS[aNgbrIter][0];
&& aGroup->Contains ((Standard_Integer)NEIGHBOR_PIXELS[aNgbrIter].pixel2Int (aRow1, aCol1))) Standard_Integer anY = UnpackY(aDiffPixel) + Image_Diff_NEIGHBOR_PIXELS[aNgbrIter][1];
if (Standard_Size(anX) < myImageRef->SizeX() // this unsigned math checks Standard_Size(-1) at-once
&& Standard_Size(anY) < myImageRef->SizeY()
&& aGroup->Map().Contains (PackXY((uint16_t)anX, (uint16_t)anY)))
{ {
++aNeighboursNb; ++aNeighboursNb;
} }
@ -509,7 +526,7 @@ Standard_Integer Image_Diff::ignoreBorderEffect()
isLine = Standard_False; isLine = Standard_False;
break; break;
} }
} // for pixels inside group... }
if (isLine) if (isLine)
{ {
@ -518,10 +535,13 @@ Standard_Integer Image_Diff::ignoreBorderEffect()
// If the pixel has greater than 1 not black neighbour pixel, it is a border of a shape. // If the pixel has greater than 1 not black neighbour pixel, it is a border of a shape.
// Otherwise, it may be a topological edge, for example. // Otherwise, it may be a topological edge, for example.
aNeighboursNb = 0; aNeighboursNb = 0;
for (Standard_Size aNgbrIter = 0; aNgbrIter < NEIGHBOR_PIXELS_NB; ++aNgbrIter) for (Standard_Size aNgbrIter = 0; aNgbrIter < Image_Diff_NbOfNeighborPixels; ++aNgbrIter)
{ {
if ( NEIGHBOR_PIXELS[aNgbrIter].isValid (*myImageRef, aRow1, aCol1) Standard_Integer anX = UnpackX(aDiffPixel) + Image_Diff_NEIGHBOR_PIXELS[aNgbrIter][0];
&& !NEIGHBOR_PIXELS[aNgbrIter].isBlack (*myImageRef, aRow1, aCol1)) Standard_Integer anY = UnpackY(aDiffPixel) + Image_Diff_NEIGHBOR_PIXELS[aNgbrIter][1];
if (Standard_Size(anX) < myImageRef->SizeX() // this unsigned math checks Standard_Size(-1) at-once
&& Standard_Size(anY) < myImageRef->SizeY()
&& !isBlackPixel (*myImageRef, Standard_Size(anY), Standard_Size(anX)))
{ {
++aNeighboursNb; ++aNeighboursNb;
} }
@ -532,15 +552,17 @@ Standard_Integer Image_Diff::ignoreBorderEffect()
myLinearGroups.Add (aGroupId); myLinearGroups.Add (aGroupId);
} }
} }
} // for groups... }
// number of different groups of pixels (except linear groups) // number of different groups of pixels (except linear groups)
Standard_Integer aNbDiffColors = 0; Standard_Integer aNbDiffColors = 0;
aGroupId = 1; aGroupId = 1;
for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next(), ++aGroupId) for (NCollection_List<Handle(TColStd_HPackedMapOfInteger)>::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next(), ++aGroupId)
{ {
if (!myLinearGroups.Contains (aGroupId)) if (!myLinearGroups.Contains (aGroupId))
{
++aNbDiffColors; ++aNbDiffColors;
}
} }
return aNbDiffColors; return aNbDiffColors;
@ -552,11 +574,6 @@ Standard_Integer Image_Diff::ignoreBorderEffect()
// ======================================================================= // =======================================================================
void Image_Diff::releaseGroupsOfDiffPixels() void Image_Diff::releaseGroupsOfDiffPixels()
{ {
for (ListOfMapOfInteger::Iterator aGrIter (myGroupsOfDiffPixels); aGrIter.More(); aGrIter.Next())
{
TColStd_MapOfInteger*& aGroup = aGrIter.ChangeValue();
delete aGroup;
}
myGroupsOfDiffPixels.Clear(); myGroupsOfDiffPixels.Clear();
myLinearGroups.Clear(); myLinearGroups.Clear();
} }

View File

@ -18,7 +18,7 @@
#include <Image_PixMap.hxx> #include <Image_PixMap.hxx>
#include <TCollection_AsciiString.hxx> #include <TCollection_AsciiString.hxx>
#include <TColStd_MapOfInteger.hxx> #include <TColStd_HPackedMapOfInteger.hxx>
#include <NCollection_List.hxx> #include <NCollection_List.hxx>
#include <NCollection_Vector.hxx> #include <NCollection_Vector.hxx>
@ -81,10 +81,10 @@ public:
//! Color tolerance for equality check. Should be within range 0..1: //! Color tolerance for equality check. Should be within range 0..1:
//! Corresponds to a difference between white and black colors (maximum difference). //! Corresponds to a difference between white and black colors (maximum difference).
//! By default, the tolerance is equal to 0 thus equality check will return false for any different colors. //! By default, the tolerance is equal to 0 thus equality check will return false for any different colors.
Standard_EXPORT void SetColorTolerance (const Standard_Real theTolerance); void SetColorTolerance (const Standard_Real theTolerance) { myColorTolerance = theTolerance; }
//! Color tolerance for equality check. //! Color tolerance for equality check.
Standard_EXPORT Standard_Real ColorTolerance() const; Standard_Real ColorTolerance() const { return myColorTolerance; }
//! Sets taking into account (ignoring) a "border effect" on comparison of images. //! Sets taking into account (ignoring) a "border effect" on comparison of images.
//! The border effect is caused by a border of shaded shapes in the viewer 3d. //! The border effect is caused by a border of shaded shapes in the viewer 3d.
@ -92,10 +92,10 @@ public:
//! Therefore, they deflect light differently according to implementation of a video card driver. //! Therefore, they deflect light differently according to implementation of a video card driver.
//! This flag allows to detect such a "border" area and skip it from comparison of images. //! This flag allows to detect such a "border" area and skip it from comparison of images.
//! Filter turned OFF by default. //! Filter turned OFF by default.
Standard_EXPORT void SetBorderFilterOn (const Standard_Boolean theToIgnore); void SetBorderFilterOn (const Standard_Boolean theToIgnore) { myIsBorderFilterOn = theToIgnore; }
//! Returns a flag of taking into account (ignoring) a border effect in comparison of images. //! Returns a flag of taking into account (ignoring) a border effect in comparison of images.
Standard_EXPORT Standard_Boolean IsBorderFilterOn() const; Standard_Boolean IsBorderFilterOn() const { return myIsBorderFilterOn; }
//! Compares two images. It returns a number of different pixels (or groups of pixels). //! Compares two images. It returns a number of different pixels (or groups of pixels).
//! It returns -1 if algorithm not initialized before. //! It returns -1 if algorithm not initialized before.
@ -117,15 +117,38 @@ protected:
protected: protected:
typedef NCollection_List<TColStd_MapOfInteger* > ListOfMapOfInteger; //! Map two pixel coordinates to 32-bit integer
static Standard_Integer PackXY (uint16_t theX, uint16_t theY)
{
return Standard_Integer((unsigned int)theY |
((unsigned int)theX << 16));
}
//! Get pixel X coordinate from 32-bit packed integer
static uint16_t UnpackX (Standard_Integer theXY)
{
return (uint16_t)(((unsigned int)theXY & 0xffff0000) >> 16);
}
//! Get pixel Y coordinate from 32-bit packed integer
static uint16_t UnpackY (Standard_Integer theXY)
{
return (uint16_t)((unsigned int)theXY & 0xffff);
}
protected:
Handle(Image_PixMap) myImageRef; //!< reference image to compare (from) Handle(Image_PixMap) myImageRef; //!< reference image to compare (from)
Handle(Image_PixMap) myImageNew; //!< new image to compare (to) Handle(Image_PixMap) myImageNew; //!< new image to compare (to)
Standard_Real myColorTolerance; //!< tolerance for equality check (0..1, 0 - any not equal, 1 - opposite colors) Standard_Real myColorTolerance; //!< tolerance for equality check (0..1, 0 - any not equal, 1 - opposite colors)
Standard_Boolean myIsBorderFilterOn; //!< perform algorithm with border effect filter Standard_Boolean myIsBorderFilterOn; //!< perform algorithm with border effect filter
ListOfMapOfInteger myGroupsOfDiffPixels;
NCollection_Vector<Standard_Size> myDiffPixels; //!< different pixels (position packed into integer) //! coordinates of different pixels, packed in one int using 16-bit integers to save memory
TColStd_MapOfInteger myLinearGroups; NCollection_Vector<Standard_Integer> myDiffPixels;
TColStd_PackedMapOfInteger myLinearGroups;
NCollection_List<Handle(TColStd_HPackedMapOfInteger)>
myGroupsOfDiffPixels;
public: public:

View File

@ -191,16 +191,14 @@ void Image_PixMap::Clear()
// function : PixelColor // function : PixelColor
// purpose : // purpose :
// ======================================================================= // =======================================================================
Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX, Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX,
const Standard_Integer theY, const Standard_Integer theY) const
Standard_Real& theAlpha) const
{ {
if (IsEmpty() if (IsEmpty()
|| theX < 0 || (Standard_Size )theX >= SizeX() || theX < 0 || (Standard_Size )theX >= SizeX()
|| theY < 0 || (Standard_Size )theY >= SizeY()) || theY < 0 || (Standard_Size )theY >= SizeY())
{ {
theAlpha = 0.0; // transparent return Quantity_ColorRGBA (0.0f, 0.0f, 0.0f, 0.0f); // transparent
return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
} }
switch (myImgFormat) switch (myImgFormat)
@ -208,86 +206,72 @@ Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
case Image_Format_GrayF: case Image_Format_GrayF:
{ {
const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX); const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
theAlpha = 1.0; // opaque return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel, aPixel, aPixel, 1.0f)); // opaque
return Quantity_Color (aPixel, aPixel, aPixel, Quantity_TOC_RGB);
} }
case Image_Format_AlphaF: case Image_Format_AlphaF:
{ {
const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX); const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
theAlpha = aPixel; return Quantity_ColorRGBA (NCollection_Vec4<float> (1.0f, 1.0f, 1.0f, aPixel));
return Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB);
} }
case Image_Format_RGBAF: case Image_Format_RGBAF:
{ {
const Image_ColorRGBAF& aPixel = Value<Image_ColorRGBAF> (theY, theX); const Image_ColorRGBAF& aPixel = Value<Image_ColorRGBAF> (theY, theX);
theAlpha = aPixel.a(); return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), aPixel.a()));
return Quantity_Color (aPixel.r(), aPixel.g(), aPixel.b(), Quantity_TOC_RGB);
} }
case Image_Format_BGRAF: case Image_Format_BGRAF:
{ {
const Image_ColorBGRAF& aPixel = Value<Image_ColorBGRAF> (theY, theX); const Image_ColorBGRAF& aPixel = Value<Image_ColorBGRAF> (theY, theX);
theAlpha = aPixel.a(); return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), aPixel.a()));
return Quantity_Color (aPixel.r(), aPixel.g(), aPixel.b(), Quantity_TOC_RGB);
} }
case Image_Format_RGBF: case Image_Format_RGBF:
{ {
const Image_ColorRGBF& aPixel = Value<Image_ColorRGBF> (theY, theX); const Image_ColorRGBF& aPixel = Value<Image_ColorRGBF> (theY, theX);
theAlpha = 1.0; // opaque return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), 1.0f)); // opaque
return Quantity_Color (aPixel.r(), aPixel.g(), aPixel.b(), Quantity_TOC_RGB);
} }
case Image_Format_BGRF: case Image_Format_BGRF:
{ {
const Image_ColorBGRF& aPixel = Value<Image_ColorBGRF> (theY, theX); const Image_ColorBGRF& aPixel = Value<Image_ColorBGRF> (theY, theX);
theAlpha = 1.0; // opaque return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), 1.0f)); // opaque
return Quantity_Color (aPixel.r(), aPixel.g(), aPixel.b(), Quantity_TOC_RGB);
} }
case Image_Format_RGBA: case Image_Format_RGBA:
{ {
const Image_ColorRGBA& aPixel = Value<Image_ColorRGBA> (theY, theX); const Image_ColorRGBA& aPixel = Value<Image_ColorRGBA> (theY, theX);
theAlpha = Standard_Real (aPixel.a()) / 255.0; return Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, float(aPixel.a()) / 255.0f);
return Quantity_Color (Standard_Real (aPixel.r()) / 255.0, Standard_Real (aPixel.g()) / 255.0, Standard_Real (aPixel.b()) / 255.0, Quantity_TOC_RGB);
} }
case Image_Format_BGRA: case Image_Format_BGRA:
{ {
const Image_ColorBGRA& aPixel = Value<Image_ColorBGRA> (theY, theX); const Image_ColorBGRA& aPixel = Value<Image_ColorBGRA> (theY, theX);
theAlpha = Standard_Real (aPixel.a()) / 255.0; return Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, float(aPixel.a()) / 255.0f);
return Quantity_Color (Standard_Real (aPixel.r()) / 255.0, Standard_Real (aPixel.g()) / 255.0, Standard_Real (aPixel.b() / 255.0), Quantity_TOC_RGB);
} }
case Image_Format_RGB32: case Image_Format_RGB32:
{ {
const Image_ColorRGB32& aPixel = Value<Image_ColorRGB32> (theY, theX); const Image_ColorRGB32& aPixel = Value<Image_ColorRGB32> (theY, theX);
theAlpha = 1.0; // opaque return Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f); // opaque
return Quantity_Color (Standard_Real (aPixel.r()) / 255.0, Standard_Real (aPixel.g()) / 255.0, Standard_Real (aPixel.b()) / 255.0, Quantity_TOC_RGB);
} }
case Image_Format_BGR32: case Image_Format_BGR32:
{ {
const Image_ColorBGR32& aPixel = Value<Image_ColorBGR32> (theY, theX); const Image_ColorBGR32& aPixel = Value<Image_ColorBGR32> (theY, theX);
theAlpha = 1.0; // opaque return Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f); // opaque
return Quantity_Color (Standard_Real (aPixel.r()) / 255.0, Standard_Real (aPixel.g()) / 255.0, Standard_Real (aPixel.b()) / 255.0, Quantity_TOC_RGB);
} }
case Image_Format_RGB: case Image_Format_RGB:
{ {
const Image_ColorRGB& aPixel = Value<Image_ColorRGB> (theY, theX); const Image_ColorRGB& aPixel = Value<Image_ColorRGB> (theY, theX);
theAlpha = 1.0; // opaque return Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f); // opaque
return Quantity_Color (Standard_Real (aPixel.r()) / 255.0, Standard_Real (aPixel.g()) / 255.0, Standard_Real (aPixel.b()) / 255.0, Quantity_TOC_RGB);
} }
case Image_Format_BGR: case Image_Format_BGR:
{ {
const Image_ColorBGR& aPixel = Value<Image_ColorBGR> (theY, theX); const Image_ColorBGR& aPixel = Value<Image_ColorBGR> (theY, theX);
theAlpha = 1.0; // opaque return Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f); // opaque
return Quantity_Color (Standard_Real (aPixel.r()) / 255.0, Standard_Real (aPixel.g()) / 255.0, Standard_Real (aPixel.b()) / 255.0, Quantity_TOC_RGB);
} }
case Image_Format_Gray: case Image_Format_Gray:
{ {
const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX); const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
theAlpha = 1.0; // opaque return Quantity_ColorRGBA (float(aPixel) / 255.0f, float(aPixel) / 255.0f, float(aPixel) / 255.0f, 1.0f); // opaque
return Quantity_Color (Standard_Real (aPixel) / 255.0, Standard_Real (aPixel) / 255.0, Standard_Real (aPixel) / 255.0, Quantity_TOC_RGB);
} }
case Image_Format_Alpha: case Image_Format_Alpha:
{ {
const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX); const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
theAlpha = Standard_Real (aPixel) / 255.0; return Quantity_ColorRGBA (1.0f, 1.0f, 1.0f, float(aPixel) / 255.0f);
return Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB);
} }
case Image_Format_UNKNOWN: case Image_Format_UNKNOWN:
{ {
@ -296,8 +280,7 @@ Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
} }
// unsupported image type // unsupported image type
theAlpha = 0.0; // transparent return Quantity_ColorRGBA (0.0f, 0.0f, 0.0f, 0.0f); // transparent
return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
} }
// ======================================================================= // =======================================================================
@ -306,7 +289,7 @@ Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
// ======================================================================= // =======================================================================
void Image_PixMap::SetPixelColor (const Standard_Integer theX, void Image_PixMap::SetPixelColor (const Standard_Integer theX,
const Standard_Integer theY, const Standard_Integer theY,
const NCollection_Vec4<float>& theColor) const Quantity_ColorRGBA& theColor)
{ {
if (IsEmpty() if (IsEmpty()
|| theX < 0 || Standard_Size(theX) >= SizeX() || theX < 0 || Standard_Size(theX) >= SizeX()
@ -315,112 +298,113 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
return; return;
} }
const NCollection_Vec4<float>& aColor = theColor;
switch (myImgFormat) switch (myImgFormat)
{ {
case Image_Format_GrayF: case Image_Format_GrayF:
{ {
ChangeValue<Standard_ShortReal> (theY, theX) = theColor.r(); ChangeValue<Standard_ShortReal> (theY, theX) = aColor.r();
return; return;
} }
case Image_Format_AlphaF: case Image_Format_AlphaF:
{ {
ChangeValue<Standard_ShortReal> (theY, theX) = theColor.a(); ChangeValue<Standard_ShortReal> (theY, theX) = aColor.a();
return; return;
} }
case Image_Format_RGBAF: case Image_Format_RGBAF:
{ {
Image_ColorRGBAF& aPixel = ChangeValue<Image_ColorRGBAF> (theY, theX); Image_ColorRGBAF& aPixel = ChangeValue<Image_ColorRGBAF> (theY, theX);
aPixel.r() = theColor.r(); aPixel.r() = aColor.r();
aPixel.g() = theColor.g(); aPixel.g() = aColor.g();
aPixel.b() = theColor.b(); aPixel.b() = aColor.b();
aPixel.a() = theColor.a(); aPixel.a() = aColor.a();
return; return;
} }
case Image_Format_BGRAF: case Image_Format_BGRAF:
{ {
Image_ColorBGRAF& aPixel = ChangeValue<Image_ColorBGRAF> (theY, theX); Image_ColorBGRAF& aPixel = ChangeValue<Image_ColorBGRAF> (theY, theX);
aPixel.r() = theColor.r(); aPixel.r() = aColor.r();
aPixel.g() = theColor.g(); aPixel.g() = aColor.g();
aPixel.b() = theColor.b(); aPixel.b() = aColor.b();
aPixel.a() = theColor.a(); aPixel.a() = aColor.a();
return; return;
} }
case Image_Format_RGBF: case Image_Format_RGBF:
{ {
Image_ColorRGBF& aPixel = ChangeValue<Image_ColorRGBF> (theY, theX); Image_ColorRGBF& aPixel = ChangeValue<Image_ColorRGBF> (theY, theX);
aPixel.r() = theColor.r(); aPixel.r() = aColor.r();
aPixel.g() = theColor.g(); aPixel.g() = aColor.g();
aPixel.b() = theColor.b(); aPixel.b() = aColor.b();
return; return;
} }
case Image_Format_BGRF: case Image_Format_BGRF:
{ {
Image_ColorBGRF& aPixel = ChangeValue<Image_ColorBGRF> (theY, theX); Image_ColorBGRF& aPixel = ChangeValue<Image_ColorBGRF> (theY, theX);
aPixel.r() = theColor.r(); aPixel.r() = aColor.r();
aPixel.g() = theColor.g(); aPixel.g() = aColor.g();
aPixel.b() = theColor.b(); aPixel.b() = aColor.b();
return; return;
} }
case Image_Format_RGBA: case Image_Format_RGBA:
{ {
Image_ColorRGBA& aPixel = ChangeValue<Image_ColorRGBA> (theY, theX); Image_ColorRGBA& aPixel = ChangeValue<Image_ColorRGBA> (theY, theX);
aPixel.r() = Standard_Byte(theColor.r() * 255.0f); aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
aPixel.g() = Standard_Byte(theColor.g() * 255.0f); aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
aPixel.b() = Standard_Byte(theColor.b() * 255.0f); aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
aPixel.a() = Standard_Byte(theColor.a() * 255.0f); aPixel.a() = Standard_Byte(aColor.a() * 255.0f);
return; return;
} }
case Image_Format_BGRA: case Image_Format_BGRA:
{ {
Image_ColorBGRA& aPixel = ChangeValue<Image_ColorBGRA> (theY, theX); Image_ColorBGRA& aPixel = ChangeValue<Image_ColorBGRA> (theY, theX);
aPixel.r() = Standard_Byte(theColor.r() * 255.0f); aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
aPixel.g() = Standard_Byte(theColor.g() * 255.0f); aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
aPixel.b() = Standard_Byte(theColor.b() * 255.0f); aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
aPixel.a() = Standard_Byte(theColor.a() * 255.0f); aPixel.a() = Standard_Byte(aColor.a() * 255.0f);
return; return;
} }
case Image_Format_RGB32: case Image_Format_RGB32:
{ {
Image_ColorRGB32& aPixel = ChangeValue<Image_ColorRGB32> (theY, theX); Image_ColorRGB32& aPixel = ChangeValue<Image_ColorRGB32> (theY, theX);
aPixel.r() = Standard_Byte(theColor.r() * 255.0f); aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
aPixel.g() = Standard_Byte(theColor.g() * 255.0f); aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
aPixel.b() = Standard_Byte(theColor.b() * 255.0f); aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
aPixel.a_() = 255; aPixel.a_() = 255;
return; return;
} }
case Image_Format_BGR32: case Image_Format_BGR32:
{ {
Image_ColorBGR32& aPixel = ChangeValue<Image_ColorBGR32> (theY, theX); Image_ColorBGR32& aPixel = ChangeValue<Image_ColorBGR32> (theY, theX);
aPixel.r() = Standard_Byte(theColor.r() * 255.0f); aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
aPixel.g() = Standard_Byte(theColor.g() * 255.0f); aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
aPixel.b() = Standard_Byte(theColor.b() * 255.0f); aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
aPixel.a_() = 255; aPixel.a_() = 255;
return; return;
} }
case Image_Format_RGB: case Image_Format_RGB:
{ {
Image_ColorRGB& aPixel = ChangeValue<Image_ColorRGB> (theY, theX); Image_ColorRGB& aPixel = ChangeValue<Image_ColorRGB> (theY, theX);
aPixel.r() = Standard_Byte(theColor.r() * 255.0f); aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
aPixel.g() = Standard_Byte(theColor.g() * 255.0f); aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
aPixel.b() = Standard_Byte(theColor.b() * 255.0f); aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
return; return;
} }
case Image_Format_BGR: case Image_Format_BGR:
{ {
Image_ColorBGR& aPixel = ChangeValue<Image_ColorBGR> (theY, theX); Image_ColorBGR& aPixel = ChangeValue<Image_ColorBGR> (theY, theX);
aPixel.r() = Standard_Byte(theColor.r() * 255.0f); aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
aPixel.g() = Standard_Byte(theColor.g() * 255.0f); aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
aPixel.b() = Standard_Byte(theColor.b() * 255.0f); aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
return; return;
} }
case Image_Format_Gray: case Image_Format_Gray:
{ {
ChangeValue<Standard_Byte> (theY, theX) = Standard_Byte(theColor.r() * 255.0f); ChangeValue<Standard_Byte> (theY, theX) = Standard_Byte(aColor.r() * 255.0f);
return; return;
} }
case Image_Format_Alpha: case Image_Format_Alpha:
{ {
ChangeValue<Standard_Byte> (theY, theX) = Standard_Byte(theColor.a() * 255.0f); ChangeValue<Standard_Byte> (theY, theX) = Standard_Byte(aColor.a() * 255.0f);
return; return;
} }
case Image_Format_UNKNOWN: case Image_Format_UNKNOWN:
@ -499,3 +483,72 @@ bool Image_PixMap::SwapRgbaBgra (Image_PixMap& theImage)
default: return false; default: return false;
} }
} }
// =======================================================================
// function : ToBlackWhite
// purpose :
// =======================================================================
void Image_PixMap::ToBlackWhite (Image_PixMap& theImage)
{
switch (theImage.Format())
{
case Image_Format_Gray:
case Image_Format_Alpha:
{
for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
{
for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
{
unsigned char& aPixel = theImage.ChangeValue<unsigned char> (aRow, aCol);
if (aPixel != 0)
{
aPixel = 255;
}
}
}
break;
}
case Image_Format_RGB:
case Image_Format_BGR:
case Image_Format_RGB32:
case Image_Format_BGR32:
case Image_Format_RGBA:
case Image_Format_BGRA:
{
const NCollection_Vec3<unsigned char> aWhite24 (255, 255, 255);
for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
{
for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
{
NCollection_Vec3<unsigned char>& aPixel = theImage.ChangeValue< NCollection_Vec3<unsigned char> > (aRow, aCol);
if (aPixel[0] != 0
|| aPixel[1] != 0
|| aPixel[2] != 0)
{
aPixel = aWhite24;
}
}
}
break;
}
default:
{
const Quantity_ColorRGBA aWhiteRgba (1.0f, 1.0f, 1.0f, 1.0f);
for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
{
for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
{
const Quantity_ColorRGBA aPixelRgba = theImage.PixelColor (Standard_Integer(aCol), Standard_Integer(aRow));
const NCollection_Vec4<float>& aPixel = aPixelRgba;
if (aPixel[0] != 0.0f
|| aPixel[1] != 0.0f
|| aPixel[2] != 0.0f)
{
theImage.SetPixelColor (int(aCol), int(aRow), aWhiteRgba);
}
}
}
break;
}
}
}

View File

@ -45,6 +45,9 @@ public:
//! - Image_Format_RGBAF / Image_Format_BGRAF //! - Image_Format_RGBAF / Image_Format_BGRAF
Standard_EXPORT static bool SwapRgbaBgra (Image_PixMap& theImage); Standard_EXPORT static bool SwapRgbaBgra (Image_PixMap& theImage);
//! Convert image to Black/White.
Standard_EXPORT static void ToBlackWhite (Image_PixMap& theImage);
public: // high-level API public: // high-level API
Image_Format Format() const { return myImgFormat; } Image_Format Format() const { return myImgFormat; }
@ -102,45 +105,23 @@ public: // high-level API
//! @param theX column index from left //! @param theX column index from left
//! @param theY row index from top //! @param theY row index from top
//! @return the pixel color //! @return the pixel color
inline Quantity_Color PixelColor (const Standard_Integer theX, Standard_EXPORT Quantity_ColorRGBA PixelColor (const Standard_Integer theX,
const Standard_Integer theY) const const Standard_Integer theY) const;
{
Standard_Real aDummy;
return PixelColor (theX, theY, aDummy);
}
//! Returns the pixel color. This function is relatively slow.
//! theAlpha argument is set to color intensity (0 - transparent, 1 - opaque)
//! Beware that this method takes coordinates in opposite order in contrast to ::Value() and ::ChangeValue().
Standard_EXPORT Quantity_Color PixelColor (const Standard_Integer theX,
const Standard_Integer theY,
Standard_Real& theAlpha) const;
//! Sets the pixel color. This function is relatively slow. //! Sets the pixel color. This function is relatively slow.
//! Beware that this method takes coordinates in opposite order in contrast to ::Value() and ::ChangeValue(). //! Beware that this method takes coordinates in opposite order in contrast to ::Value() and ::ChangeValue().
void SetPixelColor (const Standard_Integer theX, void SetPixelColor (const Standard_Integer theX,
const Standard_Integer theY, const Standard_Integer theY,
const Quantity_ColorRGBA& theColor) const Quantity_Color& theColor)
{ {
const NCollection_Vec4<float> aColor = theColor; SetPixelColor (theX, theY, Quantity_ColorRGBA (theColor, 1.0f));
SetPixelColor (theX, theY, aColor);
}
//! Sets the pixel color. This function is relatively slow.
//! Beware that this method takes coordinates in opposite order in contrast to ::Value() and ::ChangeValue().
void SetPixelColor(const Standard_Integer theX,
const Standard_Integer theY,
const Quantity_Color& theColor)
{
const NCollection_Vec3<float> aColor = theColor;
SetPixelColor (theX, theY, NCollection_Vec4<float> (aColor, 1.0f));
} }
//! Sets the pixel color. This function is relatively slow. //! Sets the pixel color. This function is relatively slow.
//! Beware that this method takes coordinates in opposite order in contrast to ::Value() and ::ChangeValue(). //! Beware that this method takes coordinates in opposite order in contrast to ::Value() and ::ChangeValue().
Standard_EXPORT void SetPixelColor (const Standard_Integer theX, Standard_EXPORT void SetPixelColor (const Standard_Integer theX,
const Standard_Integer theY, const Standard_Integer theY,
const NCollection_Vec4<float>& theColor); const Quantity_ColorRGBA& theColor);
//! Initialize image plane as wrapper over alien data. //! Initialize image plane as wrapper over alien data.
//! Data will not be copied! Notice that caller should ensure //! Data will not be copied! Notice that caller should ensure

View File

@ -57,6 +57,14 @@ public:
v[1] = theY; v[1] = theY;
} }
//! Assign new values to the vector.
void SetValues (const Element_t theX,
const Element_t theY)
{
v[0] = theX;
v[1] = theY;
}
//! Alias to 1st component as X coordinate in XY. //! Alias to 1st component as X coordinate in XY.
Element_t x() const { return v[0]; } Element_t x() const { return v[0]; }

View File

@ -73,6 +73,16 @@ public:
v[2] = Element_t(0); v[2] = Element_t(0);
} }
//! Assign new values to the vector.
void SetValues (const Element_t theX,
const Element_t theY,
const Element_t theZ)
{
v[0] = theX;
v[1] = theY;
v[2] = theZ;
}
//! Alias to 1st component as X coordinate in XYZ. //! Alias to 1st component as X coordinate in XYZ.
Element_t x() const { return v[0]; } Element_t x() const { return v[0]; }

View File

@ -80,6 +80,18 @@ public:
v[3] = theAlpha; v[3] = theAlpha;
} }
//! Assign new values to the vector.
void SetValues (const Element_t theX,
const Element_t theY,
const Element_t theZ,
const Element_t theW)
{
v[0] = theX;
v[1] = theY;
v[2] = theZ;
v[3] = theW;
}
//! Alias to 1st component as X coordinate in XYZW. //! Alias to 1st component as X coordinate in XYZW.
Element_t x() const { return v[0]; } Element_t x() const { return v[0]; }

View File

@ -26,10 +26,32 @@ public:
Quantity_ColorRGBA() : myAlpha (1.0f) {} Quantity_ColorRGBA() : myAlpha (1.0f) {}
//! Creates the color with specified RGB value. //! Creates the color with specified RGB value.
explicit Quantity_ColorRGBA (const Quantity_Color& theRgb) : myRgb (theRgb), myAlpha (1.0f) {} explicit Quantity_ColorRGBA (const Quantity_Color& theRgb)
: myRgb (theRgb), myAlpha (1.0f)
{}
//! Creates the color with specified RGBA values.
Quantity_ColorRGBA (const Quantity_Color& theRgb, float theAlpha)
: myRgb (theRgb), myAlpha (theAlpha)
{}
//! Creates the color from RGBA vector. //! Creates the color from RGBA vector.
explicit Quantity_ColorRGBA (const NCollection_Vec4<float>& theRgba) : myRgb (theRgba.rgb()), myAlpha (theRgba.a()) {} explicit Quantity_ColorRGBA (const NCollection_Vec4<float>& theRgba)
: myRgb (theRgba.rgb()), myAlpha (theRgba.a())
{}
//! Creates the color from RGBA values.
Quantity_ColorRGBA (float theRed, float theGreen, float theBlue, float theAlpha)
: myRgb (theRed, theGreen, theBlue, Quantity_TOC_RGB),
myAlpha (theAlpha)
{}
//! Assign new values to the color.
void SetValues (float theRed, float theGreen, float theBlue, float theAlpha)
{
myRgb.SetValues (theRed, theGreen, theBlue, Quantity_TOC_RGB);
myAlpha = theAlpha;
}
//! Return RGB color value. //! Return RGB color value.
const Quantity_Color& GetRGB() const { return myRgb; } const Quantity_Color& GetRGB() const { return myRgb; }
@ -71,8 +93,8 @@ public:
private: private:
static void __testSize3() { Standard_STATIC_ASSERT (sizeof(float) * 3 == sizeof(Quantity_Color)); } static void myTestSize3() { Standard_STATIC_ASSERT (sizeof(float) * 3 == sizeof(Quantity_Color)); }
static void __testSize4() { Standard_STATIC_ASSERT (sizeof(float) * 4 == sizeof(Quantity_ColorRGBA)); } static void myTestSize4() { Standard_STATIC_ASSERT (sizeof(float) * 4 == sizeof(Quantity_ColorRGBA)); }
private: private:

View File

@ -840,7 +840,7 @@ namespace
|| aDepth >= ShortRealLast()) || aDepth >= ShortRealLast())
{ {
myImage->SetPixelColor (Standard_Integer(aColIter), Standard_Integer(aRowIter), myImage->SetPixelColor (Standard_Integer(aColIter), Standard_Integer(aRowIter),
NCollection_Vec4<float> (0.0f, 0.0f, 0.0f, 1.0f)); Quantity_ColorRGBA (0.0f, 0.0f, 0.0f, 1.0f));
continue; continue;
} }
@ -850,7 +850,7 @@ namespace
aNormDepth = 1.0f - aNormDepth; aNormDepth = 1.0f - aNormDepth;
} }
myImage->SetPixelColor (Standard_Integer(aColIter), Standard_Integer(aRowIter), myImage->SetPixelColor (Standard_Integer(aColIter), Standard_Integer(aRowIter),
NCollection_Vec4<float> (aNormDepth, aNormDepth, aNormDepth, 1.0f)); Quantity_ColorRGBA (aNormDepth, aNormDepth, aNormDepth, 1.0f));
} }
} }
} }
@ -878,13 +878,13 @@ namespace
if (thePicked < 1 if (thePicked < 1
|| thePicked > myMainSel->NbPicked()) || thePicked > myMainSel->NbPicked())
{ {
myImage->SetPixelColor (theCol, theRow, NCollection_Vec4<float> (0.0f, 0.0f, 0.0f, 1.0f)); myImage->SetPixelColor (theCol, theRow, Quantity_ColorRGBA (0.0f, 0.0f, 0.0f, 1.0f));
return; return;
} }
const SelectMgr_SortCriterion& aSortCriterion = myMainSel->PickedData (thePicked); const SelectMgr_SortCriterion& aSortCriterion = myMainSel->PickedData (thePicked);
const float aDepth = float(aSortCriterion.Depth); const float aDepth = float(aSortCriterion.Depth);
myImage->SetPixelColor (theCol, theRow, NCollection_Vec4<float> (aDepth, aDepth, aDepth, 1.0f)); myImage->SetPixelColor (theCol, theRow, Quantity_ColorRGBA (aDepth, aDepth, aDepth, 1.0f));
} }
}; };

View File

@ -5848,17 +5848,16 @@ static int VReadPixel (Draw_Interpretor& theDI,
return 1; return 1;
} }
Standard_Real anAlpha; Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
if (toShowName) if (toShowName)
{ {
if (aBufferType == Graphic3d_BT_RGBA) if (aBufferType == Graphic3d_BT_RGBA)
{ {
theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha; theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
} }
else else
{ {
theDI << Quantity_Color::StringName (aColor.Name()); theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
} }
} }
else else
@ -5870,22 +5869,22 @@ static int VReadPixel (Draw_Interpretor& theDI,
{ {
if (toShowHls) if (toShowHls)
{ {
theDI << aColor.Hue() << " " << aColor.Light() << " " << aColor.Saturation(); theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
} }
else else
{ {
theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue(); theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
} }
break; break;
} }
case Graphic3d_BT_RGBA: case Graphic3d_BT_RGBA:
{ {
theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha; theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
break; break;
} }
case Graphic3d_BT_Depth: case Graphic3d_BT_Depth:
{ {
theDI << aColor.Red(); theDI << aColor.GetRGB().Red();
break; break;
} }
} }