#include "AtilDefs.h"
#include "Image.h"
#include "RgbModel.h"
#include "RgbPaletteModel.h"
#include <PngCustomProperties.h>
#include "BitonalModel.h"
#include "atilformats.h"
#include "JFIFFormatCodec.h"
#include "TiffFormatCodec.h"
#include "TiffCustomProperties.h"
#include "BmpFormatCodec.h"
#include "FileSpecifier.h"
#include "FileWriteDescriptor.h"
#include "FileReadDescriptor.h"
#include "RowProviderInterface.h"
#include <adsmigr.h>
#include <adsdef.h>
#include <acedads.h>
#include <acutads.h>
#include <acgs.h>
#include <gs.h>
#pragma comment (lib ,"AdImaging.lib")
#pragma comment (lib ,"AdIntImgServices.lib")
using namespace std;
class CRhRhImgServicesScreenshot
{
public:
enum eScreenshotFormatType
{
kJPG,
kPNG,
kTIF,
kBMP
};
public:
CRhRhImgServicesScreenshot(void);
virtual ~CRhRhImgServicesScreenshot() ;
int getCVPort();
Atil::DataModel* colorSpace(char*& pRGBData, int colorDepth, int paletteSize);
Atil::Image* constructAtilImg(char* pRGBData, unsigned long bufferSize, unsigned long rowBytes, unsigned long xSize, unsigned long ySize, int colorDepth, int paletteSize);
bool writeImageFile(Atil::Image* pImageSource, eScreenshotFormatType formatType, wchar_t const* pFileName);
bool snapGSView(eScreenshotFormatType fmt, AcGsView* pView, int width, int height, double& fieldWidth, double& fieldHeight, AcGePoint3d& position, AcGePoint3d& target, AcGeVector3d& upVector, const TCHAR* imagePath);
bool getTempImgFile(TCHAR* fileName);
bool RecordViewDetails(eScreenshotFormatType fmt, double& fieldWidth, double& fieldHeight, AcGePoint3d& position, AcGePoint3d& target, AcGeVector3d& upVector, const TCHAR* imagePath);
static void test();
} ;
int CRhRhImgServicesScreenshot::getCVPort()
{
struct resbuf rb;
ads_getvar(_T("CVPORT"), &rb);
return rb.resval.rint;
}
Atil::DataModel* CRhRhImgServicesScreenshot::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(static_cast<unsigned char>(palette[i + 2]), static_cast<unsigned char>(palette[i + 1]), static_cast<unsigned char>(palette[i]), 255);
}
pPM->setEntries(0, 256, (Atil::RgbColor*)&space);
}
else
pDm = new Atil::RgbModel(32);
_ASSERT(NULL != pDm);
return pDm;
}
Atil::Image* CRhRhImgServicesScreenshot::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 <= 0) || (ySize <= 0))
{
return NULL;
}
Atil::Image* pImg = NULL;
Atil::Size size(xSize, ySize);
// construct the Atil::Image object
if (pRGBData)
{
// Check the buffer for size and definition
if (bufferSize)
{
if (!rowBytes)
{
return NULL;
}
// did they allocate enough?
if (rowBytes * ySize > bufferSize)
{
return NULL;
}
}
else
{
return NULL;
}
Atil::DataModel* pM = colorSpace(pRGBData, colorDepth, paletteSize);
_ASSERT(NULL != pM);
if (NULL == pM)
return NULL;
try
{
// BEWARE: pRGBData may be moved in colorSpace
pImg = new Atil::Image(pRGBData, bufferSize, rowBytes, size, pM);
}
catch (Atil::ATILException* pExpCon)
{
// image construction failure
delete pExpCon;
delete pM;
pImg = NULL;
_ASSERT(FALSE);
return NULL;
}
delete pM;
}
else
{
Atil::RgbModel rgbM(32);
Atil::RgbGrayModel gM;
Atil::ImagePixel initialColor(colorDepth == 32 ? Atil::DataModelAttributes::kRgba : Atil::DataModelAttributes::kGray);
initialColor.setToZero();
try
{
pImg = new Atil::Image(size, colorDepth == 32 ? &rgbM : &gM, initialColor);
}
catch (Atil::ATILException* pExpCon)
{
// image construction failure
delete pExpCon;
pImg = NULL;
_ASSERT(FALSE);
return NULL;
}
}
_ASSERT(NULL != pImg);
return pImg;
}
bool CRhRhImgServicesScreenshot::writeImageFile(Atil::Image* pImageSource, eScreenshotFormatType 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;
}
}
//TB141111 this was missing:
int iRet = pFWD->writeImageFrame(pPipe);
delete pFWD;
pFWD = NULL;
return true;
}
bool CRhRhImgServicesScreenshot::snapGSView(eScreenshotFormatType fmt, 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]);
std::auto_ptr<char> apCharBuffer = std::auto_ptr<char>(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
std::auto_ptr<Atil::Image> autodeleter = std::auto_ptr<Atil::Image>(pImage);
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, fmt, 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 CRhRhImgServicesScreenshot::getTempImgFile(TCHAR* fileName)
{
// Here we create a temp bmp file as a transitional file
TCHAR tempDic[MAX_PATH];
::memset(tempDic, 0, MAX_PATH);
DWORD nRetSize = ::GetTempPath(MAX_PATH, tempDic);
if (nRetSize > MAX_PATH || nRetSize == 0)
{
const TCHAR* tempStr = _T("C:\\temp");
if (wcscpy_s(tempDic, tempStr) != 0)
{
return false;
}
if (::PathFileExists(tempStr) == FALSE && ::CreateDirectory(tempStr, NULL) == FALSE)
{
return false;
}
}
// create the temp file whose prefix is "img"
if (::GetTempFileName(tempDic, _T("tmp"), 0, fileName) == 0)
{
return false;
}
// now split the filepath into its individual components
TCHAR drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];
_tsplitpath(fileName, drive, dir, fname, ext);
_stprintf(fileName, _T("%s%s%s.bmp"), drive, dir, fname);
return true;
}
// by Fenton Webb, DevTech, 1/30/2013
// screen shoots the view details as a BMP
bool CRhRhImgServicesScreenshot::RecordViewDetails(eScreenshotFormatType fmt, double& fieldWidth, double& fieldHeight, AcGePoint3d& position, AcGePoint3d& target, AcGeVector3d& upVector, const TCHAR* imagePath)
{
int iVP = getCVPort();
// Compute the viewport dimensions.
int nLeft, nBottom, nRight, nTop;
int iImageWidth, iImageHeight;
acgsGetViewportInfo(iVP, nLeft, nBottom, nRight, nTop);
iImageWidth = nRight - nLeft + 1;
iImageHeight = nTop - nBottom + 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 autoBuff = std::auto_ptr(new char[nBufferSize]);
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);
resbuf cvport;
acedGetVar(L"CVPORT", &cvport);
AcGsView* pView = acgsGetCurrent3dAcGsView(cvport.resval.rint);
// if not
if (NULL == pView)
{
// then we must be in 2D wireframe mode, so use acgsGetScreenShot
//std::auto_ptr autoScreenShot(acgsGetScreenShot(iVP));
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(pSnapshotData), nBufferSize, nBytesPerRow, w, h, 32, 0);
pImage = constructAtilImg(reinterpret_cast<char*>(pSnapshotData),
nBufferSize, nBytesPerRow, w, h, 32, 0);
//std::auto_ptr autodeleter = std::auto_ptr(pImage); // auto_ptr now owns the image
std::auto_ptr<Atil::Image> autodeleter = std::auto_ptr<Atil::Image>(pImage);
if (!writeImageFile(pImage, fmt, imagePath))
{
acutPrintf(_T("\nFailed to write image file %s"), imagePath);
return false;
}
else
acutPrintf(_T("\nSuccessfully written %s"), imagePath);
}
return true;
}
else
{
return snapGSView(fmt, pView, iImageWidth, iImageHeight, fieldHeight, fieldWidth, position, target, upVector, imagePath);
}
}
能否写个复制粘贴到剪切板功能
最新发布