Hi,
Yes, this is possible, here is the minimal code that I used to test it now.
First, let's define a custom entity.
class ImageWorldDraw : public AcDbEntity
{
public :
ACRX_DECLARE_MEMBERS(ImageWorldDraw);
ImageWorldDraw();
~ImageWorldDraw();
virtual Adesk::Boolean subWorldDraw(AcGiWorldDraw*);
virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* filer);
virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* filer) const;
virtual void saveAs(AcGiWorldDraw* mode, AcDb::SaveType st);
private:
std::unique_ptr<AcGiPixelBGRA32[]> m_imageSourceData;
};
Now, let's implement the custom entity.
ACRX_DXF_DEFINE_MEMBERS(ImageWorldDraw, AcDbEntity,
AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent,
0, IMAGE_WORLD_DRAW, ImgSamp);
ImageWorldDraw::ImageWorldDraw()
{
}
ImageWorldDraw::~ImageWorldDraw()
{
}
Adesk::Boolean ImageWorldDraw::subWorldDraw(AcGiWorldDraw* mode)
{
const int imageWidth = 100;
const int imageHeight = 200;
const int imageSize = imageWidth * imageHeight;
if (!m_imageSourceData)
{
m_imageSourceData = std::make_unique<AcGiPixelBGRA32[]>(imageSize);
for (int i = 0; i < imageSize; ++i)
{
m_imageSourceData[i].setRGBA((i % imageWidth) * 255 / imageWidth,
(i / imageWidth) * 255 / imageHeight,
128,
255);
}
}
AcGiImageBGRA32 imageSource(imageWidth, imageHeight, m_imageSourceData.get());
AcGePoint3d position(4.0, 5.0, 6.0);
Adesk::UInt32 width = 200;
Adesk::UInt32 height = 400;
AcGeVector3d u(width, 0.0, 0.0);
AcGeVector3d v(0.0, height, 0.0);
AcGiGeometry::TransparencyMode transparencyMode = AcGiGeometry::kTransparencyOff;
return mode->rawGeometry()->image(imageSource, position, u, v, transparencyMode);
}
Acad::ErrorStatus ImageWorldDraw::dwgInFields(AcDbDwgFiler* filer)
{
assertWriteEnabled();
Acad::ErrorStatus es = AcDbEntity::dwgInFields(filer);
if (es != Acad::eOk)
return es;
Adesk::UInt32 width, height;
filer->readUInt32(&width);
filer->readUInt32(&height);
const size_t imageSize = width * height;
if (imageSize > 0)
{
m_imageSourceData = std::make_unique<AcGiPixelBGRA32[]>(imageSize);
for (size_t i = 0; i < imageSize; ++i)
{
filer->readBytes(&m_imageSourceData[i], sizeof(AcGiPixelBGRA32));
}
}
return filer->filerStatus();
}
Acad::ErrorStatus ImageWorldDraw::dwgOutFields(AcDbDwgFiler* filer) const
{
Acad::ErrorStatus es = AcDbEntity::dwgOutFields(filer);
if (es != Acad::eOk)
return es;
Adesk::UInt32 width = 100;
Adesk::UInt32 height = 200;
filer->writeUInt32(width);
filer->writeUInt32(height);
const size_t imageSize = width * height;
if (imageSize > 0 && m_imageSourceData)
{
for (size_t i = 0; i < imageSize; ++i)
{
filer->writeBytes(&m_imageSourceData[i], sizeof(AcGiPixelBGRA32));
}
}
return filer->filerStatus();
}
void ImageWorldDraw::saveAs(AcGiWorldDraw* mode, AcDb::SaveType st)
{
if (st == AcDb::SaveType::k2018Save)
{
AcGePoint3d position(4.0, 5.0, 6.0);
Adesk::UInt32 width = 100;
Adesk::UInt32 height = 200;
AcGeVector3d u(width, 0.0, 0.0);
AcGeVector3d v(0.0, height, 0.0);
AcGiGeometry::TransparencyMode transparencyMode = AcGiGeometry::kTransparencyOff;
if (m_imageSourceData)
{
AcGiImageBGRA32 imageSource(width, height, m_imageSourceData.get());
mode->rawGeometry()->image(imageSource, position, u, v, transparencyMode);
}
}
}
Now, write the driver code to call over custom entity -
void imageTest() {
ImageWorldDraw* pImageWorldDraw = new ImageWorldDraw;
AcDbObjectId imageOID;
Acad::ErrorStatus es = postToDatabase(pImageWorldDraw, imageOID);
if (es != Acad::eOk) {
acutPrintf(_T("\nFailed to post the image to the database"));
delete pImageWorldDraw;
return;
}
pImageWorldDraw->close();}
Compile everything, load the DBX, and run the command imagetest
. You should see a gradient image. Save the drawing in the 2018 format.
Close AutoCAD.
Do not load the DBX; simply open the drawing. You should see something similar.
Note: The image pixel data is being stored in a buffer, which will increase the size of the drawing.
