Implemented new method to provide access to alpha value in image.
Implemented new vreadpixel Draw Harness command to read
specified pixel value from 3D view.
vdump command - added result checks
Corrected misprint
TypeOfImage from Image,
HPrivateImage from Image,
CRawBufferData from Image,
- Color from Quantity
+ Color from Quantity,
+ Parameter from Quantity
raises
PixmapDefinitionError from Aspect,
-- Note that this function convert input theY coordinate
-- to count off from top of an image (while in memory it stored
-- upside-down).
+
+ PixelColor ( me : in;
+ theX, theY : in Integer from Standard;
+ theAlpha : out Parameter from Quantity )
+ returns Color from Quantity;
+ ---Purpose:
+ -- Returns the pixel color. This function is relatively slow,
+ -- use AccessBuffer() instead for stream operations.
+ -- theAlpha argument is set to color intensity (0 - transparent, 1 - opaque)
+ -- Note that this function convert input theY coordinate
+ -- to count off from top of an image (while in memory it stored
+ -- upside-down).
+
fields
myImage : HPrivateImage from Image is protected;
end PixMap;
}
Quantity_Color getPixelColor (const Standard_Integer theCol,
- const Standard_Integer theRow) const
+ const Standard_Integer theRow,
+ Quantity_Parameter& theAlpha) const
{
RGBQuad_t* aPixel = (RGBQuad_t* )&getScanLine (theRow)[theCol * myBytesPerPixel];
+ theAlpha = (myBytesPerPixel > 3) ? (Standard_Real (aPixel->rgbReserved) / 255.0) : 1.0;
return Quantity_Color (Standard_Real (aPixel->rgbRed) / 255.0,
Standard_Real (aPixel->rgbGreen) / 255.0,
Standard_Real (aPixel->rgbBlue) / 255.0,
#endif
}
+// =======================================================================
+// function : PixelColor
+// purpose :
+// =======================================================================
Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
const Standard_Integer theY) const
+{
+ Quantity_Parameter aDummy;
+ return PixelColor (theX, theY, aDummy);
+}
+
+// =======================================================================
+// function : PixelColor
+// purpose :
+// =======================================================================
+Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
+ const Standard_Integer theY,
+ Quantity_Parameter& theAlpha) const
{
Standard_Integer aScanlineId = myImage->getHeight() - theY - 1;
- if (theX < 0 || theX >= (unsigned int)myImage->getWidth() ||
- theY < 0 || theY >= (unsigned int)myImage->getHeight())
+ if (theX < 0 || (unsigned int )theX >= (unsigned int )myImage->getWidth() ||
+ theY < 0 || (unsigned int )theY >= (unsigned int )myImage->getHeight())
{
+ theAlpha = 0.0; // transparent
return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
}
#ifdef HAVE_FREEIMAGE
{
RGBQUAD aValue; memset (&aValue, 0, sizeof(aValue));
myImage->getPixelColor (theX, aScanlineId, &aValue);
+ theAlpha = (myImage->getColorType() == FIC_RGBALPHA) ? (Standard_Real (aValue.rgbReserved) / 255.0) : 1.0;
return Quantity_Color (Standard_Real (aValue.rgbRed) / 255.0,
Standard_Real (aValue.rgbGreen) / 255.0,
Standard_Real (aValue.rgbBlue) / 255.0,
{
float* aScanLine = (float* )myImage->getScanLine (aScanlineId);
Quantity_Parameter aValue = Quantity_Parameter (aScanLine[theX]);
+ theAlpha = 1.0; // opaque
return Quantity_Color (aValue, aValue, aValue, Quantity_TOC_RGB);
}
case FIT_RGBF:
{
FIRGBF* aScanLine = (FIRGBF* )myImage->getScanLine (aScanlineId);
FIRGBF* aPixel = &aScanLine[theX];
+ theAlpha = 1.0; // opaque
return Quantity_Color (Quantity_Parameter (aPixel->red),
Quantity_Parameter (aPixel->green),
Quantity_Parameter (aPixel->blue),
{
FIRGBAF* aScanLine = (FIRGBAF* )myImage->getScanLine (aScanlineId);
FIRGBAF* aPixel = &aScanLine[theX];
+ theAlpha = aPixel->alpha;
return Quantity_Color (Quantity_Parameter (aPixel->red),
Quantity_Parameter (aPixel->green),
Quantity_Parameter (aPixel->blue),
default:
{
// not supported image type
+ theAlpha = 0.0; // transparent
return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
}
}
}
#else
- return myImage->getPixelColor (theX, aScanlineId);
+ return myImage->getPixelColor (theX, aScanlineId, theAlpha);
#endif
}
Graphic3d_CView* cView = (Graphic3d_CView* )MyView->CView();
Graphic3d_PtrFrameBuffer aFBOPtr = NULL;
Graphic3d_PtrFrameBuffer aPrevFBOPtr = (Graphic3d_PtrFrameBuffer )cView->ptrFBO;
+ Standard_Integer aFBOVPSizeX (theWidth), aFBOVPSizeY (theHeight), aFBOSizeXMax (0), aFBOSizeYMax (0);
Standard_Integer aPrevFBOVPSizeX (0), aPrevFBOVPSizeY (0), aPrevFBOSizeXMax (0), aPrevFBOSizeYMax (0);
if (aPrevFBOPtr != NULL)
{
MyView->FBOGetDimensions (aPrevFBOPtr,
aPrevFBOVPSizeX, aPrevFBOVPSizeY,
aPrevFBOSizeXMax, aPrevFBOSizeYMax);
- if (theWidth <= aPrevFBOSizeXMax && theHeight <= aPrevFBOSizeYMax)
+ if (aFBOVPSizeX <= aPrevFBOSizeXMax && aFBOVPSizeY <= aPrevFBOSizeYMax)
{
- MyView->FBOChangeViewport (aPrevFBOPtr, theWidth, theHeight);
+ MyView->FBOChangeViewport (aPrevFBOPtr, aFBOVPSizeX, aFBOVPSizeY);
aFBOPtr = aPrevFBOPtr;
}
}
if (aFBOPtr == NULL)
{
// Try to create hardware accelerated buffer
- aFBOPtr = MyView->FBOCreate (theWidth, theHeight);
+ aFBOPtr = MyView->FBOCreate (aFBOVPSizeX, aFBOVPSizeY);
+ if (aFBOPtr != NULL)
+ {
+ MyView->FBOGetDimensions (aFBOPtr,
+ aFBOVPSizeX, aFBOVPSizeY,
+ aFBOSizeXMax, aFBOSizeYMax);
+ // reduce viewport in case of hardware limits
+ if (aFBOVPSizeX > aFBOSizeXMax) aFBOVPSizeX = aFBOSizeXMax;
+ if (aFBOVPSizeY > aFBOSizeYMax) aFBOVPSizeY = aFBOSizeYMax;
+ MyView->FBOChangeViewport (aFBOPtr, aFBOVPSizeX, aFBOVPSizeY);
+ }
}
cView->ptrFBO = aFBOPtr;
// technically we can reduce existing viewport...
// but currently allow only dumping the window itself
- if (theWidth != aWinWidth || theHeight != aWinHeight)
+ if (aFBOVPSizeX != aWinWidth || aFBOVPSizeY != aWinHeight)
{
return Handle(Image_PixMap)();
}
//szv: calculate expansion
Umin = PUmin; Vmin = PVmin; Umax = PUmax; Vmax = PVmax;
Standard_Real oldWidth = (PUmax - PUmin), oldHeight = (PVmax - PVmin);
- Standard_Real newWidth = (oldHeight * theWidth) / theHeight;
+ Standard_Real newWidth = (oldHeight * aFBOVPSizeX) / aFBOVPSizeY;
if (newWidth < oldWidth)
{
- Standard_Real newHeight = (oldWidth * theHeight) / theWidth;
+ Standard_Real newHeight = (oldWidth * aFBOVPSizeY) / aFBOVPSizeX;
// Expand height
Standard_Real delta = 0.5 * (newHeight - oldHeight);
Vmin = PVmin - delta;
// allocate image buffer for dumping
Image_CRawBufferData aRawBuffer;
- Handle(Image_PixMap) anImageBitmap = new Image_PixMap (theWidth, theHeight, theBufferType);
+ Handle(Image_PixMap) anImageBitmap = new Image_PixMap (aFBOVPSizeX, aFBOVPSizeY, theBufferType);
anImageBitmap->AccessBuffer (aRawBuffer);
if (!MyView->BufferDump (aRawBuffer))
{
Handle(AIS_InteractiveContext) IC;
Handle(V3d_View) view;
GetCtxAndView (IC, view);
- if (!view.IsNull())
+ if (view.IsNull())
{
- if (aWidth > 0 && aHeight > 0)
- {
- return view->ToPixMap (aWidth, aHeight, aBufferType)->Dump (argv[1]) ? 0 : 1;
- }
- else
+ di << "Cannot find an active viewer/view\n";
+ return 1;
+ }
+
+ if (aWidth <= 0 || aHeight <= 0)
+ {
+ if (!view->Dump (argv[1], aBufferType))
{
- return view->Dump (argv[1], aBufferType) ? 0 : 1;
+ di << "Dumping failed!\n";
+ return 1;
}
+ return 0;
}
- else
+
+ Handle(Image_PixMap) aPixMap = view->ToPixMap (aWidth, aHeight, aBufferType);
+ if (aPixMap.IsNull())
+ {
+ di << "Dumping failed!\n";
+ return 1;
+ }
+
+ Image_CRawBufferData aRawBuffer;
+ aPixMap->AccessBuffer (aRawBuffer);
+ if (aRawBuffer.widthPx != aWidth || aRawBuffer.heightPx != aHeight)
+ {
+ std::cout << "Warning! Dumped dimensions " << aRawBuffer.widthPx << "x" << aRawBuffer.heightPx
+ << " are lesser than requested " << aWidth << "x" << aHeight << "\n";
+ }
+ if (!aPixMap->Dump (argv[1]))
{
- di << "Cannot find an active viewer/view" << "\n";
+ di << "Saving image failed!\n";
return 1;
}
+ return 0;
}
return 0;
}
+// ==============================================================================
+// function : VReadPixel
+// purpose :
+// ==============================================================================
+static int VReadPixel (Draw_Interpretor& theDI,
+ Standard_Integer theArgNb,
+ const char** theArgVec)
+{
+ // get the active view
+ Handle(V3d_View) aView = ViewerTest::CurrentView();
+ if (aView.IsNull())
+ {
+ std::cerr << "No active view. Please call vinit.\n";
+ return 1;
+ }
+ else if (theArgNb < 3)
+ {
+ std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
+ return 1;
+ }
+
+ Image_TypeOfImage aBufferType = Image_TOI_RGBA;
+ Standard_Integer aWidth, aHeight;
+ aView->Window()->Size (aWidth, aHeight);
+ const Standard_Integer anX = atoi (theArgVec[1]);
+ const Standard_Integer anY = atoi (theArgVec[2]);
+ if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
+ {
+ std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
+ return 1;
+ }
+
+ Standard_Boolean toShowName = Standard_False;
+ Standard_Boolean toShowHls = Standard_False;
+ for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
+ {
+ TCollection_AsciiString aParam (theArgVec[anIter]);
+ if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("rgb")))
+ {
+ aBufferType = Image_TOI_RGB;
+ }
+ else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("hls")))
+ {
+ aBufferType = Image_TOI_RGB;
+ toShowHls = Standard_True;
+ }
+ else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("rgbf")))
+ {
+ aBufferType = Image_TOI_RGBF;
+ }
+ else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("rgba")))
+ {
+ aBufferType = Image_TOI_RGBA;
+ }
+ else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("rgbaf")))
+ {
+ aBufferType = Image_TOI_RGBAF;
+ }
+ else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("depth")))
+ {
+ aBufferType = Image_TOI_FLOAT;
+ }
+ else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("name")))
+ {
+ toShowName = Standard_True;
+ }
+ }
+
+ Handle(Image_PixMap) anImage = aView->ToPixMap (aWidth, aHeight, aBufferType);
+ if (anImage.IsNull())
+ {
+ std::cerr << "Image dump failed\n";
+ return 1;
+ }
+
+ Quantity_Parameter anAlpha;
+ Quantity_Color aColor = anImage->PixelColor (anX, anY, anAlpha);
+ if (toShowName)
+ {
+ if (aBufferType == Image_TOI_RGBA
+ || aBufferType == Image_TOI_RGBAF)
+ {
+ theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha << "\n";
+ }
+ else
+ {
+ theDI << Quantity_Color::StringName (aColor.Name()) << "\n";
+ }
+ }
+ else
+ {
+ switch (aBufferType)
+ {
+ default:
+ case Image_TOI_RGB:
+ case Image_TOI_RGBF:
+ {
+ if (toShowHls)
+ {
+ theDI << aColor.Hue() << " " << aColor.Light() << " " << aColor.Saturation() << "\n";
+ }
+ else
+ {
+ theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << "\n";
+ }
+ break;
+ }
+ case Image_TOI_RGBA:
+ case Image_TOI_RGBAF:
+ {
+ theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha << "\n";
+ break;
+ }
+ case Image_TOI_FLOAT:
+ {
+ theDI << aColor.Red() << "\n";
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
//=======================================================================
//function : ViewerCommands
//purpose :
"vmemgpu [f]: print system-dependent GPU memory information if available;"
" with f option returns free memory in bytes",
__FILE__, VMemGpu, group);
+ theCommands.Add ("vreadpixel",
+ "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
+ " : Read pixel value for active view",
+ __FILE__, VReadPixel, group);
}