Кто-нибудь из вас знает/имеет пример с кодом импорта изображения с диска в файл 2013.dwg? Что я делаю не так/есть ли другое решение? Могу ли я, возможно, избежать сохранения на диск и напрямую передать массив байтов для сохранения в виде изображения в чертеже AUTOCAD / BRICSCAD? (2013/2018 .dwg) Изображение должно быть вставлено, XRef недостаточно.
Я сделал следующее, чтобы сначала получить изображение:
public ScreenshotInfo MakeScreenShot(_AcWnd.Window pWindow, string pFilePath, int pTopCutOff, int pBottomCutoff, int pLeftCutoff, int pRightCutoff ) {
Point windowLocation = pWindow.GetLocation();
Size windowSize = pWindow.GetSize();
windowLocation.X += pLeftCutoff;
windowLocation.Y += pTopCutOff;
windowSize.Height -= pTopCutOff + pBottomCutoff;
windowSize.Width -= pLeftCutoff + pRightCutoff;
using (Bitmap bitmap = new Bitmap(windowSize.Width, windowSize.Height, PixelFormat.Format32bppArgb)) {
using (Graphics graphics = Graphics.FromImage(bitmap)) {
graphics.CopyFromScreen(windowLocation.X, windowLocation.Y, 0, 0, windowSize, CopyPixelOperation.SourceCopy);
bitmap.Save(pFilePath, ImageFormat.Png);
}
}
return new ScreenshotInfo(pFilePath, windowSize.Width, windowSize.Height);
}
Как только изображение будет сохранено на диске, я хочу вставить его в dwg:
public void AttachRasterImage(string pImageName, string pFilePath) {
m_communicator.BCUtils.WriteLine("Attach image: " + pFilePath);
// Get the current database and start a transaction
_AcDb.Database database = m_communicator.BCUtils.MdiActiveDocument.Database;
using (_AcDb.Transaction transaction = database.TransactionManager.StartTransaction()) {
// Define the name and image to use
string imageName = pImageName;
string filePath = pFilePath;
_AcDb.RasterImageDef rasterImageDef;
bool rasterDefCreated = false;
_AcDb.ObjectId imageObjectId;
// Get the image dictionary
_AcDb.ObjectId imageDirectoryObjectId = _AcDb.RasterImageDef.GetImageDictionary(database);
// Check to see if the dictionary does not exist, if not then create it
if (imageDirectoryObjectId.IsNull) {
imageDirectoryObjectId = _AcDb.RasterImageDef.CreateImageDictionary(database);
}
// Open the image dictionary
_AcDb.DBDictionary dbImageDictionary = transaction.GetObject(imageDirectoryObjectId, _AcDb.OpenMode.ForRead) as _AcDb.DBDictionary;
// Check to see if the image definition already exists
if (dbImageDictionary.Contains(imageName)) {
imageObjectId = dbImageDictionary.GetAt(imageName);
rasterImageDef = transaction.GetObject(imageObjectId, _AcDb.OpenMode.ForWrite) as _AcDb.RasterImageDef;
}
else {
// Create a raster image definition
_AcDb.RasterImageDef acRasterDefNew = new _AcDb.RasterImageDef();
// Set the source for the image file
acRasterDefNew.SourceFileName = filePath;
m_communicator.BCUtils.WriteLine("SFN: " + acRasterDefNew.SourceFileName);
// Load the image into memory
acRasterDefNew.Load();
// Add the image definition to the dictionary
dbImageDictionary.UpgradeOpen();
imageObjectId = dbImageDictionary.SetAt(imageName, acRasterDefNew);
transaction.AddNewlyCreatedDBObject(acRasterDefNew, true);
rasterImageDef = acRasterDefNew;
rasterDefCreated = true;
}
// Open the Block table for read
using (_AcDb.BlockTable blockTable = transaction.GetObject(database.BlockTableId, _AcDb.OpenMode.ForRead) as _AcDb.BlockTable)
using (_AcDb.BlockTableRecord blockTableRecord = transaction.GetObject(blockTable[_AcDb.BlockTableRecord.ModelSpace], _AcDb.OpenMode.ForWrite) as _AcDb.BlockTableRecord)
using (_AcDb.RasterImage acRaster = new _AcDb.RasterImage()) {
acRaster.ImageDefId = imageObjectId;
// Use ImageWidth and ImageHeight to get the size of the image in pixels (1024 x 768).
// Use ResolutionMMPerPixel to determine the number of millimeters in a pixel so you
// can convert the size of the drawing into other units or millimeters based on the
// drawing units used in the current drawing.
// Define the width and height of the image
_AcGe.Vector3d width;
_AcGe.Vector3d height;
// Check to see if the measurement is set to English (Imperial) or Metric units
if (database.Measurement == _AcDb.MeasurementValue.English) {
width = new _AcGe.Vector3d((rasterImageDef.ResolutionMMPerPixel.X * acRaster.ImageWidth) / 25.4, 0, 0);
height = new _AcGe.Vector3d(0, (rasterImageDef.ResolutionMMPerPixel.Y * acRaster.ImageHeight) / 25.4, 0);
}
else {
width = new _AcGe.Vector3d(rasterImageDef.ResolutionMMPerPixel.X * acRaster.ImageWidth, 0, 0);
height = new _AcGe.Vector3d(0, rasterImageDef.ResolutionMMPerPixel.Y * acRaster.ImageHeight, 0);
}
// Define the position for the image
_AcGe.Point3d insPt = new _AcGe.Point3d(5.0, 5.0, 0.0);
// Define and assign a coordinate system for the image's orientation
_AcGe.CoordinateSystem3d coordinateSystem = new _AcGe.CoordinateSystem3d(insPt, width * 2, height * 2);
acRaster.Orientation = coordinateSystem;
// Set the rotation angle for the image
acRaster.Rotation = 0;
// Add the new object to the block table record and the transaction
blockTableRecord.AppendEntity(acRaster);
transaction.AddNewlyCreatedDBObject(acRaster, true);
// Connect the raster definition and image together so the definition
// does not appear as "unreferenced" in the External References palette.
_AcDb.RasterImage.EnableReactors(true);
acRaster.AssociateRasterDef(rasterImageDef);
if (rasterDefCreated) {
rasterImageDef.Dispose();
}
}
transaction.Commit();
}
}
Проблема возникает, когда программа достигает:
acRasterDefNew.Load();
Текст ошибки: System.AccessViolationException: «Попытка чтения или записи в защищенную память. Это часто указывает на то, что другая память повреждена».
Я не понимаю, почему возникает эта ошибка. Согласно @Hans Passant, изображение больше не должно быть заблокировано.