#include <Standard_Atomic.hxx>
#include <TColStd_HArray1OfByte.hxx>
+#include "Graphic3d_MarkerImage.pxx"
+
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_MarkerImage,Standard_Transient)
namespace
{
static volatile Standard_Integer THE_MARKER_IMAGE_COUNTER = 0;
-}
+ //! Returns a parameters for the marker of the specified type and scale.
+ static void getMarkerBitMapParam (const Aspect_TypeOfMarker theMarkerType,
+ const Standard_ShortReal theScale,
+ Standard_Integer& theWidth,
+ Standard_Integer& theHeight,
+ Standard_Integer& theOffset,
+ Standard_Integer& theNumOfBytes)
+ {
+ const Standard_Integer aType = Standard_Integer(theMarkerType > Aspect_TOM_O
+ ? Aspect_TOM_O
+ : theMarkerType);
+ const Standard_Real anIndex = (Standard_Real)(TEL_NO_OF_SIZES - 1) * (theScale - (Standard_Real)TEL_PM_START_SIZE)
+ / (Standard_Real)(TEL_PM_END_SIZE - TEL_PM_START_SIZE);
+ Standard_Integer anId = (Standard_Integer)(anIndex + 0.5);
+ if (anId < 0)
+ {
+ anId = 0;
+ }
+ else if (anId >= TEL_NO_OF_SIZES)
+ {
+ anId = TEL_NO_OF_SIZES - 1;
+ }
+
+ theWidth = (Standard_Integer)arrPMFontInfo[aType][anId].width;
+ theHeight = (Standard_Integer)arrPMFontInfo[aType][anId].height;
+ theOffset = arrPMFontInfo[aType][anId].offset;
+ const Standard_Integer aNumOfBytesInRow = theWidth / 8 + (theWidth % 8 ? 1 : 0);
+ theNumOfBytes = theHeight * aNumOfBytesInRow;
+ }
+
+ //! Merge two image pixmap into one. Used for creating image for following markers:
+ //! Aspect_TOM_O_POINT, Aspect_TOM_O_PLUS, Aspect_TOM_O_STAR, Aspect_TOM_O_X, Aspect_TOM_RING1, Aspect_TOM_RING2, Aspect_TOM_RING3
+ static Handle(Image_PixMap) mergeImages (const Handle(Image_PixMap)& theImage1,
+ const Handle(Image_PixMap)& theImage2)
+ {
+ if (theImage1.IsNull() && theImage2.IsNull())
+ {
+ return Handle(Image_PixMap)();
+ }
+
+ Handle(Image_PixMap) aResultImage = new Image_PixMap();
+
+ Standard_Integer aWidth1 = 0, aHeight1 = 0;
+ if (!theImage1.IsNull())
+ {
+ aWidth1 = (Standard_Integer )theImage1->Width();
+ aHeight1 = (Standard_Integer )theImage1->Height();
+ }
+
+ Standard_Integer aWidth2 = 0, aHeight2 = 0;
+ if (!theImage2.IsNull())
+ {
+ aWidth2 = (Standard_Integer )theImage2->Width();
+ aHeight2 = (Standard_Integer )theImage2->Height();
+ }
+
+ const Standard_Integer aMaxWidth = Max (aWidth1, aWidth2);
+ const Standard_Integer aMaxHeight = Max (aHeight1, aHeight2);
+ const Standard_Integer aSize = Max (aMaxWidth, aMaxHeight);
+ aResultImage->InitZero (Image_Format_Alpha, aSize, aSize);
+
+ if (!theImage1.IsNull())
+ {
+ const Standard_Integer aXOffset1 = Abs (aWidth1 - aMaxWidth) / 2;
+ const Standard_Integer anYOffset1 = Abs (aHeight1 - aMaxHeight) / 2;
+ for (Standard_Integer anY = 0; anY < aHeight1; anY++)
+ {
+ Standard_Byte* anImageLine = theImage1->ChangeRow (anY);
+ Standard_Byte* aResultImageLine = aResultImage->ChangeRow (anYOffset1 + anY);
+ for (Standard_Integer aX = 0; aX < aWidth1; aX++)
+ {
+ aResultImageLine[aXOffset1 + aX] |= anImageLine[aX];
+ }
+ }
+ }
+
+ if (!theImage2.IsNull())
+ {
+ const Standard_Integer aXOffset2 = Abs (aWidth2 - aMaxWidth) / 2;
+ const Standard_Integer anYOffset2 = Abs (aHeight2 - aMaxHeight) / 2;
+ for (Standard_Integer anY = 0; anY < aHeight2; anY++)
+ {
+ Standard_Byte* anImageLine = theImage2->ChangeRow (anY);
+ Standard_Byte* aResultImageLine = aResultImage->ChangeRow (anYOffset2 + anY);
+ for (Standard_Integer aX = 0; aX < aWidth2; aX++)
+ {
+ aResultImageLine[aXOffset2 + aX] |= anImageLine[aX];
+ }
+ }
+ }
+
+ return aResultImage;
+ }
+
+ //! Draw inner point as filled rectangle
+ static Handle(TColStd_HArray1OfByte) fillPointBitmap (const Standard_Integer theSize)
+ {
+ const Standard_Integer aNbBytes = (theSize / 8 + (theSize % 8 ? 1 : 0)) * theSize;
+ Handle(TColStd_HArray1OfByte) aBitMap = new TColStd_HArray1OfByte (0, aNbBytes - 1);
+ for (Standard_Integer anIter = 0; anIter < aBitMap->Length(); ++anIter)
+ {
+ aBitMap->SetValue (anIter, 255);
+ }
+ return aBitMap;
+ }
+
+ //! Returns a marker image for the marker of the specified type and scale.
+ static Handle(Graphic3d_MarkerImage) getTextureImage (const Aspect_TypeOfMarker theMarkerType,
+ const Standard_ShortReal theScale)
+ {
+ Standard_Integer aWidth = 0, aHeight = 0, anOffset = 0, aNbBytes = 0;
+ getMarkerBitMapParam (theMarkerType, theScale, aWidth, aHeight, anOffset, aNbBytes);
+
+ Handle(TColStd_HArray1OfByte) aBitMap = new TColStd_HArray1OfByte (0, aNbBytes - 1);
+ for (Standard_Integer anIter = 0; anIter < aNbBytes; ++anIter)
+ {
+ aBitMap->ChangeValue (anIter) = Graphic3d_MarkerImage_myMarkerRaster[anOffset + anIter];
+ }
+
+ Handle(Graphic3d_MarkerImage) aTexture = new Graphic3d_MarkerImage (aBitMap, aWidth, aHeight);
+ return aTexture;
+ }
+}
// =======================================================================
// function : Graphic3d_MarkerImage
// purpose :
// =======================================================================
-Graphic3d_MarkerImage::Graphic3d_MarkerImage (const Handle(Image_PixMap)& theImage)
+Graphic3d_MarkerImage::Graphic3d_MarkerImage (const Handle(Image_PixMap)& theImage,
+ const Handle(Image_PixMap)& theImageAlpha)
: myImage (theImage),
+ myImageAlpha (theImageAlpha),
myMargin (1),
myWidth ((Standard_Integer )theImage->Width()),
myHeight ((Standard_Integer )theImage->Height())
myImageAlphaId = TCollection_AsciiString ("Graphic3d_MarkerImageAlpha_")
+ TCollection_AsciiString (THE_MARKER_IMAGE_COUNTER);
+
+ if (!theImageAlpha.IsNull())
+ {
+ if (theImageAlpha->Format() != Image_Format_Alpha
+ && theImageAlpha->Format() != Image_Format_Gray)
+ {
+ throw Standard_ProgramError ("Graphic3d_MarkerImage, wrong color format of alpha image");
+ }
+ if (theImageAlpha->SizeX() != theImage->SizeX()
+ || theImageAlpha->SizeY() != theImage->SizeY())
+ {
+ throw Standard_ProgramError ("Graphic3d_MarkerImage, wrong dimensions of alpha image");
+ }
+ }
}
// =======================================================================
// purpose :
// =======================================================================
Graphic3d_MarkerImage::Graphic3d_MarkerImage (const Handle(TColStd_HArray1OfByte)& theBitMap,
- const Standard_Integer& theWidth,
- const Standard_Integer& theHeight)
+ const Standard_Integer theWidth,
+ const Standard_Integer theHeight)
: myBitMap (theBitMap),
myMargin (1),
myWidth (theWidth),
+ TCollection_AsciiString (THE_MARKER_IMAGE_COUNTER);
}
+// =======================================================================
+// function : IsColoredImage
+// purpose :
+// =======================================================================
+bool Graphic3d_MarkerImage::IsColoredImage() const
+{
+ return !myImage.IsNull()
+ && myImage->Format() != Image_Format_Alpha
+ && myImage->Format() != Image_Format_Gray;
+}
+
// =======================================================================
// function : GetBitMapArray
// purpose :
// =======================================================================
-Handle(TColStd_HArray1OfByte) Graphic3d_MarkerImage::GetBitMapArray (const Standard_Real& theAlphaValue) const
+Handle(TColStd_HArray1OfByte) Graphic3d_MarkerImage::GetBitMapArray (const Standard_Real theAlphaValue,
+ const Standard_Boolean theIsTopDown) const
{
- if (!myBitMap.IsNull())
+ if (!myBitMap.IsNull()
+ || myImage.IsNull())
{
return myBitMap;
}
- Handle(TColStd_HArray1OfByte) aBitMap;
- if (myImage.IsNull())
- {
- return aBitMap;
- }
-
const Standard_Integer aNumOfBytesInRow = (Standard_Integer )(myImage->Width() / 8) + (myImage->Width() % 8 ? 1 : 0);
const Standard_Integer aNumOfBytes = (Standard_Integer )(aNumOfBytesInRow * myImage->Height());
const Standard_Integer aHeight = (Standard_Integer )myImage->Height();
const Standard_Integer aWidth = (Standard_Integer )myImage->Width();
- aBitMap = new TColStd_HArray1OfByte (0, aNumOfBytes - 1);
+ Handle(TColStd_HArray1OfByte) aBitMap = new TColStd_HArray1OfByte (0, aNumOfBytes - 1);
aBitMap->Init (0);
for (Standard_Integer aRow = 0; aRow < aHeight; aRow++)
{
+ const Standard_Integer aResRow = !theIsTopDown ? (aHeight - aRow - 1) : aRow;
for (Standard_Integer aColumn = 0; aColumn < aWidth; aColumn++)
{
const Quantity_ColorRGBA aColor = myImage->PixelColor (aColumn, aRow);
aBitOn = aColor.Alpha() > theAlphaValue;
}
- Standard_Integer anIndex = aNumOfBytesInRow * aRow + aColumn / 8;
+ Standard_Integer anIndex = aNumOfBytesInRow * aResRow + aColumn / 8;
aBitMap->SetValue (anIndex, (Standard_Byte)(aBitMap->Value (anIndex) +
(aBitOn ? (0x80 >> (aColumn % 8)) : 0)));
}
// =======================================================================
const Handle(Image_PixMap)& Graphic3d_MarkerImage::GetImage()
{
- if (!myImage.IsNull())
- {
- return myImage;
- }
-
- if (myBitMap.IsNull())
+ if (!myImage.IsNull()
+ || myBitMap.IsNull())
{
return myImage;
}
theWidth = myWidth;
theHeight = myHeight;
}
+
+// =======================================================================
+// function : GetMarkerImage
+// purpose :
+// =======================================================================
+Handle(Graphic3d_MarkerImage) Graphic3d_MarkerImage::StandardMarker (const Aspect_TypeOfMarker theMarkerType,
+ const Standard_ShortReal theScale,
+ const Graphic3d_Vec4& theColor)
+{
+ switch (theMarkerType)
+ {
+ case Aspect_TOM_O_POINT:
+ case Aspect_TOM_O_PLUS:
+ case Aspect_TOM_O_STAR:
+ case Aspect_TOM_O_X:
+ {
+ // For this type of markers we merge two base bitmaps into one
+ // For example Aspect_TOM_O_PLUS = Aspect_TOM_O + Aspect_TOM_PLUS
+ Handle(Graphic3d_MarkerImage) aMarkerImage1 = getTextureImage (Aspect_TOM_O, theScale);
+ Handle(Graphic3d_MarkerImage) aMarkerImage2;
+ if (theMarkerType == Aspect_TOM_O_POINT)
+ {
+ // draw inner point as filled rectangle
+ const Standard_Integer aSize = theScale > 7 ? 7 : (Standard_Integer)(theScale + 0.5F);
+ Handle(TColStd_HArray1OfByte) aBitMap = fillPointBitmap (aSize);
+ aMarkerImage2 = new Graphic3d_MarkerImage (aBitMap, aSize, aSize);
+ }
+ else
+ {
+ aMarkerImage2 = getTextureImage (Aspect_TypeOfMarker(theMarkerType - Aspect_TOM_O_POINT), theScale);
+ }
+ Handle(Image_PixMap) anImage = mergeImages (aMarkerImage1->GetImage(), aMarkerImage2->GetImage());
+ Handle(Graphic3d_MarkerImage) aNewMarkerImage = new Graphic3d_MarkerImage (anImage);
+ return aNewMarkerImage;
+ }
+ case Aspect_TOM_RING1:
+ case Aspect_TOM_RING2:
+ case Aspect_TOM_RING3:
+ {
+ const Standard_ShortReal aDelta = 0.1f;
+ Standard_ShortReal aScale = theScale;
+ Standard_ShortReal aLimit = 0.0f;
+ if (theMarkerType == Aspect_TOM_RING1)
+ {
+ aLimit = aScale * 0.2f;
+ }
+ else if (theMarkerType == Aspect_TOM_RING2)
+ {
+ aLimit = aScale * 0.5f;
+ }
+ else if (theMarkerType == Aspect_TOM_RING3)
+ {
+ aLimit = aScale * 0.8f;
+ }
+
+ Handle(Image_PixMap) anImage;
+ for (; aScale > aLimit && aScale >= 1.0f; aScale -= aDelta)
+ {
+ anImage = mergeImages (anImage, getTextureImage (Aspect_TOM_O, aScale)->GetImage());
+ }
+ Handle(Graphic3d_MarkerImage) aNewMarkerImage = new Graphic3d_MarkerImage (anImage);
+ return aNewMarkerImage;
+ }
+ case Aspect_TOM_BALL:
+ {
+ Standard_Integer aWidth = 0, aHeight = 0, anOffset = 0, aNbBytes = 0;
+ Standard_ShortReal aScale = theScale;
+ getMarkerBitMapParam (Aspect_TOM_O, aScale, aWidth, aHeight, anOffset, aNbBytes);
+
+ NCollection_Vec4<Standard_Real> aColor (theColor);
+
+ const Standard_Integer aSize = Max (aWidth + 2, aHeight + 2); // includes extra margin
+ Handle(Image_PixMap) anImage = new Image_PixMap();
+ Handle(Image_PixMap) anImageA = new Image_PixMap();
+ anImage ->InitZero (Image_Format_RGBA, aSize, aSize);
+ anImageA->InitZero (Image_Format_Alpha, aSize, aSize);
+
+ // we draw a set of circles
+ Image_ColorRGBA aColor32;
+ aColor32.a() = 255;
+ Standard_Real aHLS[3];
+ const Standard_ShortReal aDelta = 0.1f;
+ while (aScale >= 1.0f)
+ {
+ Quantity_Color::RgbHls (aColor.r(), aColor.g(), aColor.b(), aHLS[0], aHLS[1], aHLS[2]);
+ aHLS[2] *= 0.95; // 5% saturation change
+ Quantity_Color::HlsRgb (aHLS[0], aHLS[1], aHLS[2], aColor.r(), aColor.g(), aColor.b());
+ aColor32.r() = Standard_Byte (255.0 * aColor.r());
+ aColor32.g() = Standard_Byte (255.0 * aColor.g());
+ aColor32.b() = Standard_Byte (255.0 * aColor.b());
+
+ const Handle(Graphic3d_MarkerImage) aMarker = getTextureImage (Aspect_TOM_O, aScale);
+ const Handle(Image_PixMap)& aCircle = aMarker->GetImage();
+
+ 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);
+ for (Standard_Size aCol = 0; aCol < aCircle->SizeX(); ++aCol)
+ {
+ if (aRowData[aCol] != 0)
+ {
+ anImage->ChangeValue<Image_ColorRGBA>(aDiffX + aRow, aDiffY + aCol) = aColor32;
+ anImageA->ChangeValue<Standard_Byte> (aDiffX + aRow, aDiffY + aCol) = 255;
+ }
+ }
+ }
+ aScale -= aDelta;
+ }
+ Handle(Graphic3d_MarkerImage) aNewMarkerImage = new Graphic3d_MarkerImage (anImage, anImageA);
+ return aNewMarkerImage;
+ }
+ default:
+ {
+ return getTextureImage (theMarkerType, theScale);
+ }
+ }
+}