Как импортировать изображение в .dwg 2013/2018 с помощью С#?

Кто-нибудь из вас знает/имеет пример с кодом импорта изображения с диска в файл 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, изображение больше не должно быть заблокировано.


person Marian Baňas    schedule 04.12.2020    source источник