By Fenton Webb
Issue
- How to capture the screen shot of a Viewport to save it to an image file?
- Is it possible to temporarily display an image over the Viewport or alter the Viewport display?
Solution
There are two AcGs functions in ObjectARX SDK that can be used to get the screen shot of the specified Viewport in AutoCAD and also to set an image to be displayed in a specified Viewport.
The functions are:
- acgsGetScreenShot()
- acgsDisplayImage()
The function acgsGetScreenShot() will get you the pointer to an AcGsScreenShot object for the specified viewport number. When in TILEMODE 1, just specify the Viewport that you are interested in or just specify “0” to get the entire ModelSpace (and same is the case with PaperSpace). Similarly just specify the Viewport number you are interested in if the TILEMODE is 0 (i.e. in PaperSpace). Also if you specify viewport number of 1 in TILEMODE 0 then you will get only the entities that exist in the PaperSpace.
You can get the image data using the method getScanline() of the AcGsScreenShot class. Using this you can fill in an array of truecolor long words which essentially will be the ARBG data. This data can be used to create an image file. You can use the ATIL SDK to create a bitmap or JPG easily from the image data.
The function acgsDisplayImage() on the other hand takes an array of truecolor long words and displays the image at the specified location on a specified Viewport. The image will stay till a redraw is called.
This function can be used to:
- Show a temporary external image quickly.
- Blank the entire view port temporarily.
- Change the colors of the Viewport. Say inverting the colors of the Viewport.
Note:The acgsGetScreenShot() does not get you the shaded or rendered view.
Here’s some code which shows how to use the functions, to use the Atil libs you need to link with the headers and libs in the Atil folder of the ObjectARX SDK:
// by Fenton Webb, DevTech, 1/30/2013
<p style="margin: 0px"><!--EndFragment-->// screen shoots the view details as a BMP</p> </font></font></span> <p style="margin: 0px"><font face="Consolas"><span style="color:"><font color="#0000ff"><font style="font-size: 8pt">bool</font></font></span><font style="font-size: 8pt"><font color="#000000"> </font><span style="color:"><font color="#010001">R</font></span><span style="color:"><font color="#010001">ecordViewDetails</font></span><font color="#000000">(</font><span style="color:"><font color="#0000ff">double</font></span><font color="#000000"> &</font><span style="color:"><font color="#010001">fieldWidth</font></span><font color="#000000">, </font><span style="color:"><font color="#0000ff">double</font></span><font color="#000000"> &</font><span style="color:"><font color="#010001">fieldHeight</font></span><font color="#000000">, </font><span style="color:"><font color="#010001">AcGePoint3d</font></span><font color="#000000"> &</font><span style="color:"><font color="#010001">position</font></span><font color="#000000">, </font><span style="color:"><font color="#010001">AcGePoint3d</font></span><font color="#000000"> &</font><span style="color:"><font color="#010001">target</font></span><font color="#000000">, </font><span style="color:"><font color="#010001">AcGeVector3d</font></span><font color="#000000"> &</font><span style="color:"><font color="#010001">upVector</font></span><font color="#000000">, </font><span style="color:"><font color="#0000ff">const</font></span><font color="#000000"> </font><span style="color:"><font color="#010001">TCHAR</font></span><font color="#000000"> *</font><span style="color:"><font color="#010001">imagePath</font></span><font color="#000000">)</font></font></font></p> <p style="margin: 0px"><font face="Consolas"><font style="font-size: 8pt" color="#000000">{</font></font></p> <p style="margin: 0px"><font face="Consolas"><font color="#000000"><font style="font-size: 8pt">  </font></font><font style="font-size: 8pt"><span style="color:"><font color="#0000ff">int</font></span><font color="#000000"> </font><span style="color:"><font color="#010001">iVP</font></span><font color="#000000"> = </font><span style="color:"><font color="#010001">getCVPort</font></span><font color="#000000">();</font></font></font></p> <p style="margin: 0px"><font face="Consolas"><font style="font-size: 8pt" color="#000000"> </font></font></p> <p style="margin: 0px"><font face="Consolas"><font color="#000000"><font style="font-size: 8pt">  </font></font><span style="color:"><font style="font-size: 8pt" color="#008000">// Compute the viewport dimensions.</font></span></font></p> <p style="margin: 0px"><font face="Consolas"><font color="#000000"><font style="font-size: 8pt">  </font></font><font style="font-size: 8pt"><span style="color:"><font color="#0000ff">int</font></span><font color="#000000"> </font><span style="color:"><font color="#010001">nLeft</font></span><font color="#000000">, </font><span style="color:"><font color="#010001">nBottom</font></span><font color="#000000">, </font><span style="color:"><font color="#010001">nRight</font></span><font color="#000000">, </font><span style="color:"><font color="#010001">nTop</font></span><font color="#000000">;</font></font></font></p> <p style="margin: 0px"><font face="Consolas"><font color="#000000"><font style="font-size: 8pt">  </font></font><font style="font-size: 8pt"><span style="color:"><font color="#0000ff">int</font></span><font color="#000000"> </font><span style="color:"><font color="#010001">iImageWidth</font></span><font color="#000000">, </font><span style="color:"><font color="#010001">iImageHeight</font></span><font color="#000000">;</font></font></font></p> <p style="margin: 0px"><font face="Consolas"><font color="#000000"><font style="font-size: 8pt">  </font></font><font style="font-size: 8pt"><span style="color:"><font color="#010001">acgsGetViewportInfo</font></span><font color="#000000"> (</font><span style="color:"><font color="#010001">iVP</font></span><font color="#000000">, </font><span style="color:"><font color="#010001">nLeft</font></span><font color="#000000">, </font><span style="color:"><font color="#010001">nBottom</font></span><font color="#000000">, </font><span style="color:"><font color="#010001">nRight</font></span><font color="#000000">, </font><span style="color:"><font color="#010001">nTop</font></span><font color="#000000">);</font></font></font></p> <p style="margin: 0px"><font face="Consolas"><font style="font-size: 8pt" color="#000000"> </font></font></p> <p style="margin: 0px"><font face="Consolas"><font color="#000000"><font style="font-size: 8pt">  </font></font><font style="font-size: 8pt"><span style="color:"><font color="#010001">iImageWidth</font></span><font color="#000000">  = </font><span style="color:"><font color="#010001">nRight</font></span><font color="#000000"> - </font><span style="color:"><font color="#010001">nLeft</font></span><font color="#000000"> + 1;</font></font></font></p> <p style="margin: 0px"><font face="Consolas"><font color="#000000"><font style="font-size: 8pt">  </font></font><font style="font-size: 8pt"><span style="color:"><font color="#010001">iImageHeight</font></span><font color="#000000"> = </font><span style="color:"><font color="#010001">nTop</font></span><font color="#000000"> - </font><span style="color:"><font color="#010001">nBottom</font></span><font color="#0000
00″> + 1;
Atil::Size size(iImageWidth, iImageHeight);
int nBytesPerRow = Atil::DataModel::bytesPerRow(iImageWidth,
Atil::DataModelAttributes::k32);
unsigned long nBufferSize = iImageHeight * nBytesPerRow;
// Create an ATIL image for accepting the rendered image.
std::auto_ptr<char> autoBuff = std::auto_ptr<char>(new char[nBufferSize]);
char pSnapshotData = autoBuff.get();
Atil::Image * pImage = NULL;
// see if there is a GS view created
AcGsView *pView = acgsGetGsView(iVP, false);
// if not
if (NULL == pView)
{
// then we must be in 2D wireframe mode, so use acgsGetScreenShot
std::auto_ptr<AcGsScreenShot> autoScreenShot(acgsGetScreenShot(iVP));
AcGsScreenShot screenShot = autoScreenShot.get(); // auto_ptr still owns the pointer.
if (screenShot)
{
int w = 0, h = 0, d = 0;
screenShot->getSize(w, h, d);
char* pBufTemp = pSnapshotData;
for (int row = 0; row < h; row++)
{
memcpy(pBufTemp, screenShot->getScanline(0, row), nBytesPerRow);
// convert from RGBA to BGRA
char* pColor = pBufTemp;
for (int i = 0; i < w; i++) // Slow but it works
{
char temp = pColor;
*pColor = *(pColor + 2);
*(pColor + 2) = temp;
pColor += 4;
}
pBufTemp += nBytesPerRow;
}
pImage = constructAtilImg(reinterpret_cast<char>(pSnapshotData),
nBufferSize, nBytesPerRow, w, h, 32, 0);
std::auto_ptr<Atil::Image> autodeleter = std::auto_ptr<Atil::Image>(pImage); // auto_ptr now owns the image
if (!writeImageFile(pImage, kBMP, imagePath))
{
acutPrintf(_T("nFailed to write image file %s"), imagePath);
return false;
}
else
acutPrintf(_T("nSuccessfully written %s"), imagePath);
}
return true;
}
else
{
return snapGSView(pView, iImageWidth, iImageHeight, fieldHeight,
fieldWidth, position, target, upVector, imagePath);
}
}
bool snapGSView(AcGsView *pView, int width, int height, double &fieldWidth, double &fieldHeight, AcGePoint3d &position, AcGePoint3d &target, AcGeVector3d &upVector, const TCHAR *imagePath) { Atil::Size size(width, height); int nBytesPerRow = Atil::DataModel::bytesPerRow(width, Atil::DataModelAttributes::k32); unsigned long nBufferSize = height * nBytesPerRow; // Create an ATIL image for accepting the rendered image. std::auto_ptr apCharBuffer = std::auto_ptr(new char[nBufferSize]); char *pSnapshotData = apCharBuffer.get(); // auto_ptr still owns the buffer. // in shaded mode (from GS) Atil::Image * pImage = NULL; pImage = constructAtilImg(pSnapshotData, nBufferSize, nBytesPerRow, width, height, 32, 0); std::auto_ptr autodeleter = std::auto_ptr(pImage); // auto_ptr now owns the image pView->getSnapShot(pImage, AcGsDCPoint(0, 0)); // add a temp image to invert the image. do we have a better way to turn an image around? Atil::Image imgTempForInverted(pImage->read(pImage->size(), Atil::Offset(0, 0), Atil::kBottomUpLeftRight)); *pImage = imgTempForInverted; if (!writeImageFile(pImage, kBMP, imagePath)) { acutPrintf(_T("nFailed to write image file %s"), imagePath); return false; } else acutPrintf(_T("nSuccessfully written %s"), imagePath); // record the view data fieldHeight = pView->fieldHeight(); fieldWidth = pView->fieldWidth(); position = pView->position(); target = pView->target(); upVector = pView->upVector(); return true; }
bool writeImageFile (Atil::Image pImageSource, eFormatType formatType, wchar_t const *pFileName) { _ASSERT(NULL != pImageSource); if(NULL == pImageSource) return false; _ASSERT(pImageSource->isValid()); if(!pImageSource->isValid()) return false; if(PathFileExists(pFileName)) DeleteFile(pFileName); /if(PathFileExists(pFileName)) { if(IsFileReadOnly(pFileName)) { RemoveReadonlyAttribute(pFileName); DeleteFile(pFileName); } }/ if(PathFileExists(pFileName)) return false; Atil::RowProviderInterface pPipe = pImageSource->read(pImageSource->size(), Atil::Offset(0,0)); ASSERTE(NULL != pPipe); if(!pPipe) return false; Atil::FileWriteDescriptor *pFWD = NULL; Atil::ImageFormatCodec *pCodec = NULL; if (formatType == kJPG) pCodec = new JfifFormatCodec(); else if (formatType == kPNG) pCodec = new PngFormatCodec(); else if (formatType == kTIF) pCodec = new TiffFormatCodec(); else if (formatType == kBMP) pCodec = new BmpFormatCodec(); _ASSERTE(NULL != pCodec); if(NULL == pCodec) return false; if(!Atil::FileWriteDescriptor::isCompatibleFormatCodec(pCodec, &(pPipe->dataModel()), pPipe->size())) { delete pCodec; return false; } pFWD = new Atil::FileWriteDescriptor(pCodec); _ASSERTE(NULL != pFWD); #ifdef UNICODE #ifndef _ADESK_MAC Atil::FileSpecifier fs(Atil::StringBuffer((lstrlen(pFileName) + 1) * sizeof(TCHAR), (const Atil::Byte ) pFileName, Atil::StringBuffer::kUTF_16), Atil::FileSpecifier::kFilePath); #else Atil::FileSpecifier fs(Atil::StringBuffer((lstrlen(pFileName) + 1) * sizeof(TCHAR), (const Atil::Byte *) pFileName, Atil::StringBuffer::kUTF_32), Atil::FileSpecifier::kFilePath); #endif #else Atil::FileSpecifier fs(Atil::StringBuffer(lstrlen(pFileName) + 1, (const Atil::Byte *) pFileName, Atil::StringBuffer::kASCII), Atil::FileSpecifier::kFilePath); #endif if (!pFWD->setFileSpecifier(fs)) return false; pFWD->createImageFrame(pPipe->dataModel(), pPipe->size()); if (formatType == kPNG) { Atil::FormatCodecPropertyInterface pProp = pFWD->getProperty(Atil::FormatCodecPropertyInterface::kCompression); if (pProp != NULL) { PngCompression* pPngComp = (PngCompression)(pProp); if ( pPngComp != NULL ) { // Why not compress all we can? pPngComp->selectCompression(PngCompressionType::kHigh); pFWD->setProperty(pPngComp); } delete pProp; pProp = NULL; } } else if (formatType == kTIF) { Atil::FormatCodecPropertyInterface pProp = pFWD->getProperty(Atil::FormatCodecPropertyInterface::kCompression); if (pProp != NULL) { TiffCompression* pComp = (TiffCompression)(pProp); if ( pComp != NULL ) { // G4 is only valid for 1 bit images. if ( pComp->selectCompression(TiffCompressionType::kCCITT_FAX4) == false ) { // So if that fails, resort to LZW now that it is patent free if ( pComp->selectCompression(TiffCompressionType::kLZW) == false ) { // If that fails (and is shouldn't, be) then set none. pComp->selectCompression(TiffCompressionType::kNone); } } pFWD->setProperty(pComp); } delete pProp; pProp = NULL; } } // get the current vp int getCVPort() { struct resbuf rb; ads_getvar(_T("CVPORT"), &rb); return rb.resval.rint; } Atil::DataModel colorSpace (char *&pRGBData, int colorDepth, int paletteSize) { _ASSERT(NULL != pRGBData); // Setup a color space, with palette if needed Atil::DataModel *pDm = NULL; if (colorDepth == 8) { Atil::RgbColor space[256]; Atil::RgbPaletteModel *pPM = new Atil::RgbPaletteModel(); _ASSERT(NULL != pPM); if(!pPM) return NULL; pDm = pPM; char *palette = pRGBData; pRGBData += paletteSize; for (int i = 0; i < paletteSize; i += 4) space[i / 4] = Atil::RgbColor(palette[i+2],palette[i+1],palette[i], 255); pPM->setEntries(0, 256, (Atil::RgbColor *)&space); } else pDm = new Atil::RgbModel(32); _ASSERT(NULL != pDm); return pDm; } Atil::Image *constructAtilImg(char *pRGBData, unsigned long bufferSize, unsigned long rowBytes, unsigned long xSize, unsigned long ySize, int colorDepth, int paletteSize) { if ((8 != colorDepth) && (32 != colorDepth)) { return NULL; } if (paletteSize)
{ if ((paletteSize < 0) || (paletteSize > 255)) { return NULL; } } if ((xSize

Leave a Reply to sudarshan d.Cancel reply