netDxf icon indicating copy to clipboard operation
netDxf copied to clipboard

Ignore missing images

Open dsn27 opened this issue 2 years ago • 4 comments

Hebel.zip

Hi.

The attached DXF file will throw an error when loading. I guess this is because the referenced JPG is missing.

Is there a way to ignore this error and load the DXF anyway?

E.g. LibreCAD will open the file without a problem.

Thanks in advance, Michel

System.Collections.Generic.KeyNotFoundException
  HResult=0x80131577
  Message=The given key '18A' was not present in the dictionary.
  Source=System.Private.CoreLib
  StackTrace:
   at System.ThrowHelper.ThrowKeyNotFoundException[T](T key) in /_/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs:line 194
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key) in /_/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs:line 181
   at netDxf.IO.DxfReader.PostProcesses() in C:\Users\1\Source\Repos\netDxf\netDxf\IO\DxfReader.cs:line 10939
   at netDxf.IO.DxfReader.Read(Stream stream, IEnumerable`1 supportFolders) in C:\Users\1\Source\Repos\netDxf\netDxf\IO\DxfReader.cs:line 312
   at netDxf.DxfDocument.Load(String file, IEnumerable`1 supportFolders) in C:\Users\1\Source\Repos\netDxf\netDxf\DxfDocument.cs:line 529
   at TestDxfDocument.Program.Test(String file, String output) in C:\Users\1\Source\Repos\netDxf\TestDxfDocument\Program.cs:line 5147
   at TestDxfDocument.Program.Main() in C:\Users\1\Source\Repos\netDxf\TestDxfDocument\Program.cs:line 33

dsn27 avatar Jan 14 '22 10:01 dsn27

The root of your problem lies on a badly formatted DXF, it lacks the IMAGEDEF_REACTOR object information. At the moment I am cleaning some of the internal data structures that are not necessary, and this is one of them. The IMAGEDEF_REACTOR holds two handles that link the IMAGEDEF object with the IMAGE entity, but since the IMAGE already stores the handle to the IMAGEDEF, it is unnecessary. I am handling this in a different way when the entities are added to the document.

When I finish cleaning up this, the issue should resolve itself, and also recover the IMAGE entity since your file only lacks the IMAGEDEF_REACTOR, the important data, the IMAGE and IMAGEDEF, are there.

haplokuon avatar Jan 18 '22 15:01 haplokuon

Hi, Any news on that particular issue? I am trying to implement a fix to the dxflib in cpp for cloudcompare and I've been struggling for a while now... I'm trying to write the simpliest file and just referencing a simple image.. And I've got a couple of questions On line 180 in the DxfWriter, your a creating a dictionnary, is that really necessary? https://github.com/haplokuon/netDxf/blob/master/netDxf/IO/DxfWriter.cs#L180 Same thing for the images classes https://github.com/haplokuon/netDxf/blob/master/netDxf/IO/DxfWriter.cs#L289 Same thing for the xData https://github.com/haplokuon/netDxf/blob/master/netDxf/IO/DxfWriter.cs#L4191

I've been trying really hard, but man that is complicated! Is there any good reference for .dxf exports procedures somewhere, autodesk is lacking. My first time working with c# and your code is really easy to read and follow!

dagata-mining avatar Apr 04 '22 01:04 dagata-mining

This gonna take a while.

Reading the official DXF documentation is like trying to understand a manual by just reading its table of contents. You can take a look at the ARX documentation, perhaps it will throw you some light into the inner workings of the AutoCAD internal data structure.

About the subject of the first post:

Yes, I already solved that in one of the latest commits. Keep in mind that the IMAGEDEF_REACTOR needs to be present in the DXF. I just don't need it because I am handling the references in a different way. I am creating it when the file is saved, but when loading a DXF I do not care about it. That is why, the file that the other user posted now works even if it was not properly written.

About the OBJECTS section:

My knowledge of this DXF section is purely empirical by reading other DXF files and mimicking its structure. I have not tried other combinations, I know this way it works. So, I would say yes it is required. You can always try to avoid some of the steps, who knows...

Basically, what you have first is a dictionary, called named object dictionary in the DXF documentation, that holds a list of handles to other dictionaries that hold more handles to other dictionaries,... until you find the data you seek as one of the known Objects. The number of steps can vary. I guess the main purpose of OBJECTS section is to have a generic way for plugins to store its data. But AutoCAD uses it too for its own crap, what the hell the MLine style is doing here, it is a known piece of data not some random plugin information. Conceptually, it is the same as any other style stored in the TABLE section where it should belong. Same thing can be said about the Image definition, all very messy.

In the case you are pointing to, you will have something like: namedObjectDictionary (holds a handle to) -> imageDefDictionary (holds a handle to) -> imageDef object (holds a handle to) -> imageDefReactor (holds a handle to the image entity)

Be very careful with the handles, usually, if you don't get them right AutoCAD may blow up. If you ask me, by no reason an application should crash when loading an external file no matter how badly broken it is, and this happens a lot with AutoCAD when loading badly written DXFs, specially when the file contains broken handles.

About the CLASSES section:

It seems that there is something fishy with this section. If the classes section is left empty and the DXF document contains images, AutoCAD start complaining about some unknown object types. It looks like that there is something buggy with it, because it only happens when the first loaded file is the DXF in question, it is like AutoCAD fails to load some class types at the start and the images will not appear. I do not know if this behavior is common across all AutoCAD versions.

These are the error messages: Unknown object type IMAGE ignored Unknown object type WIPEOUT ignored Unknown object type RASTERVARIABLES ignored Unknown object type IMAGEDEF_REACTOR ignored Unknown object type IMAGEDEF ignored

The classes section seems to be a placeholder for AutoCAD external plugins to register its own classes, but these known classes should be always registered by default, they belong to the internal AutoCAD functionality. To play it safe I am writing some basic classes with the default values, but it seems that writing just one is enough to force AutoCAD to properly run and register those unknown types. So, if you want to simplify it, you can just write the default raster variable class "this.WriteRasterVariablesClass(1);", it seems that this does the trick.

About the extended data information (XData):

This is a way to add additional information to DXF objects. The Express Tools of AutoCAD have a couple commands to manipulate extended data for entities. If you want to implement this, yes, it is needed to store the XData associated with the IMAGE entity. AutoCAD even stores important information as extended data, and without it, the entity or table will not be properly created. This is the case of hatches with a gradient pattern, text styles, dimensions, block records, layers, these are the one that come to my mind at the moment.

haplokuon avatar Apr 09 '22 01:04 haplokuon

Wow, thanks for the great explanation, makes more sense, but still pretty hard to implement on my side, after a couple of hours/days spent on it. So I've decided to build an object json writter in CloudCompare and a json reader in netDXF to read and then write save in .dxf as a subprocess. I know there are some API possibilities between C# and C++ and writting json files is not optimal but it does the job. Again, many thanks for the library and the help!

dagata-mining avatar Apr 11 '22 15:04 dagata-mining