top of page

Detaching Images from AutoCAD files

Liability has been a topic in my office over the last year. Clients and contractors that we are associating with do not always have the technological means to access a Revit model. And not all of our projects are in Revit. More often they would like information sent out in AutoCAD DWG format. How do we protect the company's liability when we are sending out documents to the contractors or the owner of the project? Our answer was to remove ours and any sub-consultants logos from the file before sending them out.


In a typical AutoCAD project, there is a titleblock external reference that is linked into all of the sheets in the project. Within the titleblock file, all the logos are linked into that file in the correct location so that the documents look professional. Before binding the files to be sent out to the logos are removed from the titleblock before all external references are bound. That sounds all well and good for a typical AutoCAD provided all the users that are archiving the files communicate.


In the Revit environment, all sheets are using a shared definition of a titleblock with graphic parameters toggled on or off and individual parameters filled in to get the correct data on sheets. Revit's environment has some similarities to how an AutoCAD project is set up. When the sheets are exported to DWG format, those similarities go away. For each exported sheet the titleblock is exported as a unique definition of the block showing whatever graphics were toggled on including the embedded logos. All parameters whether at the project or sheet level are separate pieces of text. They are nowhere near the equivalent of what you see in an AutoCAD project.


So how do we handle the logos in this environment?

  • The deleting from an external reference option is a nonexistent option since the titleblocks are unique.

  • Some may suggest just deleting the image files that are linked into each of the Sheets, but that results in each file's External Reference manager showing the images as not found. That still leaves outstanding references that our client's CAD Management system throws errors on. We would then have to go through each sheet and remove the broken links. That isn't much of a time saver.

  • You may suggest creating a script and a scripting tool like AutoScript, but the error handling for detaching images is poor and you could not be sure if the files with no images had no images or were locked because they both would throw the same results.

My solution for this was to create an AutoCAD Command that would modify the database and remove the images directly from each file without opening the file directly. This allows 20+ DWG files to be modified in under a minute because the software doesn't have to actively open the file. I also sprinkled in some command line notes so that I could see how all of this progressed and which files contained images at a glance.




public class DetachImage
    {
        private static Editor _commandLine;
        private static Transaction _transaction;

        [CommandMethod("MultiDocDetachImages")]
        public void MultiDocDetachImages()
        {
            _commandLine = CADApplication.DocumentManager.MdiActiveDocument.Editor;

            if (TargetDialog.ShowDialog() != DialogResult.OK) 
                return;
            foreach (var file in TargetDialog.FileNames)
            {
                try
                {
                    using (var database = new Database(false, true))
                    {
                        database.ReadDwgFile(file, FileOpenMode.OpenForReadAndAllShare, true, null);
                        _commandLine.WriteMessage("\n"+file+" has been opened.");
                        PurgeImageReferences(database);
                        database.SaveAs(file, DwgVersion.Current);
                        _commandLine.WriteMessage("\n" + file + " has saved.");
                        _commandLine.WriteMessage("\n---------------------------------------------------------------");
                    }
                }
                catch (System.Exception ex)
                {
                    _commandLine.WriteMessage($"\n{file}: {ex.Message}");
                }
            }
        }
        private static void PurgeImageReferences(Database database)
        {
            var imageDictionaryId = GetImageDictionaryId(database);
            using (_transaction = database.TransactionManager.StartTransaction())
            {
                var imageDictionary = (DBDictionary)_transaction.GetObject(imageDictionaryId, OpenMode.ForRead);
                foreach (var image in ObjectIds(imageDictionary))
                {
                    var dbObject = _transaction.GetObject(image.Value, OpenMode.ForWrite);
                    if (dbObject != null)
                    {
                        dbObject.UpgradeOpen();
                        dbObject.Erase();
                        _commandLine.WriteMessage("\n" + image.Key + " has been removed");
                    }
                }
                _transaction.Commit();
            }
        }

        private static ObjectId GetImageDictionaryId(Database database)
        {
            var imageDictionaryId = RasterImageDef.GetImageDictionary(database);
            if (!imageDictionaryId.IsNull) 
                return imageDictionaryId;
            throw new System.Exception("No Images Attached");
        }

        private static Dictionary<string, ObjectId> ObjectIds(DBDictionary imageDictionary)
        {
            var dictionary = new Dictionary<string, ObjectId>();
            foreach (var imageDictionaryEntry in imageDictionary)
            {
                var imageId = imageDictionaryEntry.Value;
                var imageDefinition = (RasterImageDef)_transaction.GetObject(imageId, OpenMode.ForRead);
                var imageName = imageDefinition.SourceFileName;
                dictionary.Add(imageName, imageId);
            }
            return dictionary;
        }

        private static readonly OpenFileDialog TargetDialog = new OpenFileDialog
        {
            InitialDirectory = "c:\\",
            Filter = @"DWG Files (*.dwg)|*.dwg",
            FilterIndex = 2,
            RestoreDirectory = true,
            Multiselect = true,
            Title = @"Select CAD files to update"
        };
    }

24 views0 comments

Recent Posts

See All
bottom of page