When loading Raster Image: Runtime.Exception: 'eFileAccessErr'

When loading Raster Image: Runtime.Exception: 'eFileAccessErr'

BKSpurgeon
Collaborator Collaborator
1,216 Views
2 Replies
Message 1 of 3

When loading Raster Image: Runtime.Exception: 'eFileAccessErr'

BKSpurgeon
Collaborator
Collaborator

Hi there

 

  • I am wanting to add a raster image to an AutoCAD drawing programmatically.
  • The source for this image is from the internet. Taken from a Google Chart API. Basically I want to add a QR code to an autocad drawing. This QR code, when read with a mobile phone, points to an internet link. As stated before, this QR Code was created with the Google Charts API.
  • But for some reason, it always fails when it comes to this line:

 

                    acRasterDefNew.SourceFileName = strFileName;

 

  • When the file source is a local file source it works perfectly, but when the source is from the internet, it seems to fail.
  • It worked perfectly in AutoCAD 2016, but when I updated to AutoCAD 2019, using the latest ObjectARX dlls, it seems to fail.

 

Assistance much appreciated.

 

Here is some sample code:

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace RasterImageTest
{
    public class Commands
    {
        [CommandMethod("RasterTest")]
        public void RasterTest()
        {
            // Get the current database and start a transaction
            Database acCurDb;
            acCurDb = Application.DocumentManager.MdiActiveDocument.Database;

            using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
            {
                // Define the name and image to use
                string strImgName = "WorldMap";

                // string strFileName = "C:\\AutoCAD\\Sample\\VBA\\WorldMap.TIF";
                string strFileName = "http://chart.apis.google.com/chart?cht=qr&chs=500x500&chl=https%3A%2F%2Fpanel%2Dstatus%2Eherokuapp%2Ecom%2Fpanels%2F51%2Fedit_errors";
                string strFileNameEscaped = @"http://chart.apis.google.com/chart?cht=qr&chs=500x500&chl=https%3A%2F%2Fpanel%2Dstatus%2Eherokuapp%2Ecom%2Fpanels%2F51%2Fedit_errors";

                RasterImageDef acRasterDef;
                bool bRasterDefCreated = false;
                ObjectId acImgDefId;

                // Get the image dictionary
                ObjectId acImgDctID = RasterImageDef.GetImageDictionary(acCurDb);

                // Check to see if the dictionary does not exist, it not then create it
                if (acImgDctID.IsNull)
                {
                    acImgDctID = RasterImageDef.CreateImageDictionary(acCurDb);
                }

                // Open the image dictionary
                DBDictionary acImgDict = acTrans.GetObject(acImgDctID, OpenMode.ForRead) as DBDictionary;

                // Check to see if the image definition already exists
                if (acImgDict.Contains(strImgName))
                {
                    acImgDefId = acImgDict.GetAt(strImgName);

                    acRasterDef = acTrans.GetObject(acImgDefId, OpenMode.ForWrite) as RasterImageDef;
                }
                else
                {
                    // Create a raster image definition
                    RasterImageDef acRasterDefNew = new RasterImageDef();

                    // Set the source for the image file
                    acRasterDefNew.SourceFileName = strFileName;
                    // acRasterDefNew.SourceFileName = strFileNameEscaped;

                    // Load the image into memory
                    acRasterDefNew.Load();

                    // Add the image definition to the dictionary
                    acImgDict.UpgradeOpen();
                    acImgDefId = acImgDict.SetAt(strImgName, acRasterDefNew);

                    acTrans.AddNewlyCreatedDBObject(acRasterDefNew, true);

                    acRasterDef = acRasterDefNew;

                    bRasterDefCreated = true;
                }

                // Open the Block table for read
                BlockTable acBlkTbl;
                acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;

                // Open the Block table record Model space for write
                BlockTableRecord acBlkTblRec;
                acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
                                                OpenMode.ForWrite) as BlockTableRecord;

                // Create the new image and assign it the image definition
                using (RasterImage acRaster = new RasterImage())
                {
                    acRaster.ImageDefId = acImgDefId;

                    // 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
                    Vector3d width;
                    Vector3d height;

                    // Check to see if the measurement is set to English (Imperial) or Metric units
                    if (acCurDb.Measurement == MeasurementValue.English)
                    {
                        width = new Vector3d((acRasterDef.ResolutionMMPerPixel.X * acRaster.ImageWidth) / 25.4, 0, 0);
                        height = new Vector3d(0, (acRasterDef.ResolutionMMPerPixel.Y * acRaster.ImageHeight) / 25.4, 0);
                    }
                    else
                    {
                        width = new Vector3d(acRasterDef.ResolutionMMPerPixel.X * acRaster.ImageWidth, 0, 0);
                        height = new Vector3d(0, acRasterDef.ResolutionMMPerPixel.Y * acRaster.ImageHeight, 0);
                    }

                    // Define the position for the image 
                    Point3d insPt = new Point3d(5.0, 5.0, 0.0);

                    // Define and assign a coordinate system for the image's orientation
                    CoordinateSystem3d coordinateSystem = new 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
                    acBlkTblRec.AppendEntity(acRaster);
                    acTrans.AddNewlyCreatedDBObject(acRaster, true);

                    // Connect the raster definition and image together so the definition
                    // does not appear as "unreferenced" in the External References palette.
                    RasterImage.EnableReactors(true);
                    acRaster.AssociateRasterDef(acRasterDef);

                    if (bRasterDefCreated)
                    {
                        acRasterDef.Dispose();
                    }
                }

                // Save the new object to the database
                acTrans.Commit();

                // Dispose of the transaction
            }
        }
    }
}

 

0 Likes
Accepted solutions (2)
1,217 Views
2 Replies
Replies (2)
Message 2 of 3

norman.yuan
Mentor
Mentor
Accepted solution

I believe the SourceFileName should be a valid file name of the OS (Windows) file system, bot an URL indicating where you can find the file (not to mention, how to get it from that URL).

 

So, if the image is generated (and made available) by an online process, you'll need to DOWNLOAD it to your computer. You probably need to use System.Net.WebClient to doanload it and save it (with proper file name) to somewhere in the computer.

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 3 of 3

BKSpurgeon
Collaborator
Collaborator
Accepted solution

I did as  you suggested and it worked perfectly.

 

It used to work directly from a URL beforehand.

 

anyways here is the work around:

 

                            string localFileSource = getLocalFileSource(url, drawingType, info.PanelNo);
                            // Set the source for the image file
                            acRasterDefNew.SourceFileName = localFileSource;


// And here is the method:


private static string getLocalFileSource(string url, GetDrawingType drawingType, string panelNo)
        {   
            string pathToNewFolder = System.IO.Path.Combine(drawingType.FolderPathToPanelsDirectory, QRCodeFolderName);
            System.IO.DirectoryInfo directory = System.IO.Directory.CreateDirectory(pathToNewFolder);

            string qrCodeImageName = System.IO.Path.Combine(directory.FullName, panelNo );

            System.Net.WebClient webClient = new System.Net.WebClient();
            webClient.DownloadFile(url, qrCodeImageName);

            return qrCodeImageName;
        }


0 Likes