Reg. Insert Image in DXF Document

Oct 10, 2013 at 7:52 AM
Hi Everyone,

Is it possible to insert any image(.bmp,.jpeg etc. ) in the DXF Docuement ?
Coordinator
Oct 12, 2013 at 7:22 PM
Yes, you can use the Image entity for this. In the TestDxfDocument you will find an example on how to do it, take a look at the WriteImage method. Here you have a piece of code:
ImageDef imageDef = new ImageDef("myImage.jpg");
Image image = new Image(imageDef, Vector3.Zero);
DxfDocument dxf = new DxfDocument();
dxf.AddEntity(image);
Daniel
Jun 25, 2014 at 3:20 AM
Hi, Thanks for your excellent work.
In my Autocad, it just display region with name of file.
It does not display image.
Thanks
Jun 25, 2014 at 4:25 AM
Now, I know why.
I must set the full directory for image file.
Thanks
Coordinator
Jun 25, 2014 at 3:26 PM
Actually the dxf permits the use of both relative and absolute paths, but for unknown reasons, sometimes, it complains when relative paths are passed to the dxf. I guess this is a bug with AutoCad, in any case, reloading the external references should fix the problem.

Daniel
Aug 25, 2015 at 11:44 AM
Hi,

Do you plan to add support for embeding images in DXF files (if that is technically possible).

I would like to create Image from Stream eg.:
var stream = new System.IO.MemoryStream(bytes);
var imageDef1 = new ImageDef(stream);
var image1 = new Image(imageDef1, Vector3.Zero, 0, 0);
Coordinator
Aug 25, 2015 at 5:38 PM
The dxf specification of the Image entity only supports externally referenced bitmaps, it is not possible to embed them.

Daniel
Aug 21 at 7:02 AM
Edited Aug 21 at 7:54 AM
haplokuon wrote:
Yes, you can use the Image entity for this. In the TestDxfDocument you will find an example on how to do it, take a look at the WriteImage method. Here you have a piece of code:
``` ImageDef imageDef = new ImageDef("myImage.jpg");
Image image = new Image(imageDef, Vector3.Zero);
DxfDocument dxf = new DxfDocument();
dxf.AddEntity(image);
Daniel
Hello,when I use
            ImageDefinition imageDef1 = new ImageDefinition("img\\image01.jpg");
            Image image1 = new Image(imageDef1, Vector3.Zero, 100, 100);
I notice that the Image method always need two double to set the image's width and height,but in my test,the width and height must equal the resolution ratio of the image.Just like
            ImageDefinition imageDefinition = new ImageDefinition("img\\image01.jpg");            
            Image image = new Image(imageDefinition, Vector3.Zero, imageDefinition.Width, imageDefinition.Height);
Otherwise,the image in dxf file do not show properly.How can I resize the image?
Thanks
Aug 22 at 8:45 AM
Edited Aug 22 at 8:47 AM
oh,after search this discussions deeply,I find it . Image can be added in a block in a insert.Then use the insert.scale to resize the image.
Coordinator
Aug 22 at 3:25 PM
Edited Aug 22 at 10:53 PM
The dimensions (width and height) of an Image entity are not restricted to the same proportions of the original bitmap. So if you set the width and height to 100, 100; and the aspect ratio of the image is not 1, the resulting Image will be stretched in one of the dimensions. In your second example you are setting the size of the Image to be the same as the size of the ImageDefinition, this way, obviously, the resulting Image will maintain the same proportions, but remember the width and height of an Image entity are defined in drawing units while the ImageDefinition width and height are in pixels.

You need to consider the aspect ratio of original image if you want to maintain the same proportions. Imagine you have a bitmap of (WxH) 100x50 pixels, if you want to create an Image entity from that bitmap with a width of, for example, 500; and you want to keep the aspect ratio of the Image entity the same as the bitmap, the height of the Image will have to be Image.Width(ImageDefinition.Height/ImageDefinition.Width), 500(50/100)=250 for this example.

Later, if you need to resize the Image, just change its width and height values, there is no need to create a block. Multiplying the width and height of the Image by the same value will achieve the same thing as an uniform scale.

Daniel
Aug 23 at 1:20 AM
Edited Aug 23 at 1:31 AM
Thanks for your reply,but I have tried in the way you said before ,it seems not work.
The image file I used is the "image.jpg" in TestDxfDocument folder in your source code,it's 260x260 pixels.And the code I used to test is the sample "WriteImage()" in your code.I made a little change to test.In my test,the img/image01.jpg and img/image02.jpg are both copies of "image.jpg" in TestDxfDocument folder.Here it is:
private static void WriteImage()
        {
            ImageDefinition imageDefinition = new ImageDefinition("img\\image01.jpg");
            Image image = new Image(imageDefinition, Vector3.Zero, 360, 360);

            XData xdata1 = new XData(new ApplicationRegistry("netDxf"));
            xdata1.XDataRecord.Add(new XDataRecord(XDataCode.String, "xData image position"));
            xdata1.XDataRecord.Add(XDataRecord.OpenControlString);
            xdata1.XDataRecord.Add(new XDataRecord(XDataCode.WorldSpacePositionX, image.Position.X));
            xdata1.XDataRecord.Add(new XDataRecord(XDataCode.WorldSpacePositionY, image.Position.Y));
            xdata1.XDataRecord.Add(new XDataRecord(XDataCode.WorldSpacePositionZ, image.Position.Z));
            xdata1.XDataRecord.Add(XDataRecord.CloseControlString);
            //image.XData.Add(xdata1);

            //image.Normal = new Vector3(1, 1, 1);
            //image.Rotation = 30;

            // you can pass a name that must be unique for the image definiton, by default it will use the file name without the extension
            ImageDefinition imageDef2 = new ImageDefinition("img\\image02.jpg", "MyImage");
            Image image2 = new Image(imageDef2, new Vector3(0, 500, 0), 100, 100);
            Image image3 = new Image(imageDef2, new Vector3(500, 500, 0), 100, 100);

            // clipping boundary definition in local coordinates
            ClippingBoundary clip = new ClippingBoundary(100, 100, 500, 300);
            image.ClippingBoundary = clip;
            // set to null to restore the default clipping boundary (full image)
            image.ClippingBoundary = null;

            // images can be part of a block definition
            Block block = new Block("ImageBlock");
            block.Entities.Add(image2);
            block.Entities.Add(image3);
            Insert insert = new Insert(block, new Vector3(0, 100, 0));

            DxfDocument dxf = new DxfDocument();

            dxf.AddEntity(image);
            //dxf.AddEntity(image2);
            //dxf.AddEntity(image3);
            dxf.AddEntity(insert);

            dxf.Save("image.dxf");
            dxf = DxfDocument.Load("image.dxf");
            dxf.DrawingVariables.AcadVer = DxfVersion.AutoCad2010;
            dxf.Save("test.dxf");

            //dxf.RemoveEntity(image2);
            //dxf.Save("image2.dxf");
            //dxf.RemoveEntity(image3);
            //dxf.RemoveEntity(image);
            //dxf.Save("image3.dxf");
        }
Then the dxf file shows this way(Click here to see the screenshot.).Why? Did I do something wrong?
However,when I set the size of the Image to be the same as the size of the ImageDefinition, and create a block to resize, it displays properly.
PS:I am a Chinese, if there is something wrong in my expression in English, pardon me.
Aug 23 at 8:19 AM
Edited Aug 23 at 8:24 AM
Another question...
I want to insert a dxf file to another, Just like this two topics.
https://netdxf.codeplex.com/discussions/644807
https://netdxf.codeplex.com/discussions/640893
I tried the code provided by theboss691 in the second topic.But it doesn't works very well. I don't know how to fix it...
Here is the screenshot.
http://imgur.com/WGzyFHN
Coordinator
Aug 24 at 6:23 PM
About the Image entity, there is a problem with the clipping boundaries that I will fix for the next update. Even when the Clipping property is set to false the image is shown as it is being clipped by its boundary. At the moment you can create a block and scale it, as you have been doing it.

About your other issue with the change changing its font, remember that any element that is referenced by other entities like: layers, linetypes, text styles (this is your case), blocks,... will not override the values of the destination drawing. Imagine that you have a TextStyle with name "MyStyle" that points to a font named "arial.ttf" in your first drawing; and you have another TextStyle with the same name "MyStyle" that points to a font "tahoma.ttf" in your second drawing. When you create a block from the second drawing and then you insert it into the first, the TextStyle of the second drawing will not override the properties of the TextStyle of the first drawing. So, the text of the second drawing will change its font from "tahoma.ttf" to "arial.ttf". This is intended, you cannot have two different styles with the same name in the same drawing, and one must prevail over the other. Without more information, I guess this is what is happening to you.

The same thing will happen with layers, for example, if you have two layers with the same name with different colors, the color of the layer of the destination drawing will prevail over the color of the layer of the source drawing. Be careful with block names it can radically change the appearance of your drawing.

Don't worry about your English, it is not my mother tongue either.

Daniel
Aug 25 at 4:21 AM
Edited Aug 28 at 8:57 AM
Thanks a lot for your detailed explanation.
When you create a block from the second drawing and then you insert it into the first, the TextStyle of the second drawing will not override the properties of the TextStyle of the first drawing.
Just use your example, what I want to do is to make the TextStyle of the second drawing override the properties of the TextStyle of the first drawing.

Let me make it more clear what I want to get: I have a few dxf files provided by others, for example A1.dxf, A2.dxf,A3.dxf....... These files are created by AutoCAD.
Now I need to insert them into one dxf life and keep their appearance unchanged.The code I used is ,for example, var bolck =Block.load(A1.dxf);var insert = new block(block,position).

How can I solve it? It will be very helpful if you can provide some sample code.

I have solved this problem by load those dxf files and save them in a specific font.
Aug 28 at 9:01 AM
Edited Aug 28 at 9:22 AM
Well , another problem showed up. When I use "Block.load(xxx.dxf)",some dxf files will raise the Expection :"The following characters \<>/?":;*|,=` are not supported for table object names."
How did this happen?
Coordinator
Sep 4 at 3:54 PM
Sorry for the delay but I was unavailable.

When joining different drawings you need to solve all naming conflicts between TableObjects of the drawings, as there cannot be two of the same name. How you solve it is up to you. You can do several things:
  1. Make sure that there are no conflicts between the drawings, obviously.
  2. Use first the drawing with the TableObject that you want to keep, all other entities added will inherit the TableObject properties of the first drawing, when two of the same name appears.
  3. Load the drawings into different documents and change the name of the TableObject, you cannot do this with reserved TableObjects, like the Layer "0" or the TextStyle "Standard" they must always be present.
  4. Load the drawings into different drawings and assign a new TableObject like a TextStyle. You can get all references of a particular TextStyle with:
    dxf.TextStyles.GetReferences("styleName").
    Once the reference count is zero you can safely delete the TableObject, as long as it is not one of the reserved ones.
About your second issue. AutoCad does not allow those characters as part of any TableObject name, but it has its exceptions. I took care of the ones I know, but since Autodesk is so kind of not properly document its own stuff, I have to rely on trial and error. Without the problematic dxf I cannot tell you what exactly is wrong and make a fix for it. Keep in mind that the official dxf documentation is awful, to say the least, it leaves too many things undocumented.

Daniel