Click here to Skip to main content
15,439,556 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi there,
Short version of the question:
Is there any way to create a GraphicsPath from an EMF (or similar) file?


Long version of the question:

I have a method which arranges the position of images, before they are drawn, such that they do not overlap. At present, each image is assigned a RectangleF which matches the size and current location of the image. If two rectangles overlap, one of them is moved (eg up), so that they do not overlap. Once arranging has taken place, the images are drawn onto the 'canvas'.
(These images which get arranged are saved to the hard disc as EMF files.)
I need to change from using rectangles to using GraphicsPaths, so that this auto arranging is much 'tighter'. I can't figure out how to generate a graphics path from an EMF file or metafile though...
is there any way to create a graphics path from an EMF file?

Thanks!
Lee
Posted
Updated 2-Nov-10 13:29pm
v2

I have done something similar before. In my case, I created a converter to convert records from WMF, EMF, and EMF+ metafiles to vector graphics objects.

There is no GDI+ method or set of methods to turn a metafile into a graphics path. I found that I had to use Graphics.EnumerateMetafile(), and in the callback I manually extracted the data from each record and interpreted each record type individually. It was quite a bit of work but the results were very good.

There are 3 different metafile formats:

  • WMF: from the 16-bit windows days - doesn't support curves (bezier, cardinal, etc) and various other GDI features
  • EMF: GDI32's metafile format. Supports curves and (almost) everything else GDI allows
  • EMF+: GDI+'s metafile format. GDI+ drawing records are entirely different in format than normal EMF records, but allow a lot more features.

At the time I wrote my code, all I had to go on for WMF and EMF were the MSDN docs, which were kind of confusing at times, and EMF+ was not documented at all (although there were unofficial docs for some of what I needed). I spent a lot of time reverse-engineering the format.

These days, thanks to MS's open protocol specifications initiative, you should have everything you need, in an easier format:

WMF format documentation[^]

EMF format documentation[^]

EMF+ format documentation[^]
 
Share this answer
 
v3
Comments
Lee Reid 3-Nov-10 6:20am     CRLF
Hey! thanks for your reply :) I've tried to get the EnumerateMetafile method going, by copying the example given on the MS website http://msdn.microsoft.com/en-us/library/ms142060.aspx It doesn't seem to even use the callback method they've given (e.g. can add the line "throw new Exception()" into the callback method and nothing happens). I also had a good look at the documentation - 306 pages!! this really does seem like a nightmare/reinventing the wheel. Is there any chance that your converter, or something like it, is accessible anywhere?
J. Dunlap 3-Nov-10 15:02pm     CRLF
I had originally written the converter as a product, which had some sales back then but is a niche project and I doubt I will get anything more from it as it currently stands. I would be willing to send you the source for reference purposes. Just send me a private email and we can discuss. As for the issue of it not enumerating the metafile, I noticed that if the Graphics object you are using to enumerate the metafile is a screen Graphics and is not currently showing on the screen, the metafile will not be enumerated at all. The solution for this is to use a 1x1 Bitmap and create a Graphics from that. Also, I believe I found it to work better when passing in metafile.PhysicalDimension as the size when enumerating. Here is an example: <pre lang="cs">Bitmap bmp = new Bitmap(1,1); Graphics g = Graphics.FromImage(bmp); g.EnumerateMetafile( metafile, new Point(0,0), new System.Drawing.Rectangle(new Point(0,0),mf.PhysicalDimension.ToSize()), GraphicsUnit.Pixel, WmfMetaProc);</pre>
James Binkley 22-Feb-17 11:05am     CRLF
J.Dunlap, I am in the process of writing code to replay an EMF. I must write custom code to do this because I am rendering onto a custom canvas (not a DC). In other words, I will need to enumerate the EMF, manually extract each record, interpret, and then take appropriate corresponding action. I may find your code useful as a reference. Please let me know if you are willing to share. Thank you! -james
J. Dunlap 3-Nov-10 15:03pm    
Hmm, that didn't come out looking very good, but you get the idea.
**Disclaimer**
I do not know if this will lead to a solution to your problem.
************************************************************

There is a MetaFile class which has a PropertyItems collection.

The PropertyItem class has properties for Len (length of the array of values), Type (describes what the array contains) and Value (the actual array).

Whether a PropertyItem can be deciphered to provide information to build a GraphicsPath I have no idea but, if all else fails, it might be worth looking at.
 
Share this answer
 
v2
Comments
Lee Reid 2-Nov-10 21:25pm     CRLF
Hi Henry, thanks for your reply. Your suggestions sounded quite likely to work, but the propertyItems collection returns a System.NotImplementedException when you try to access it (e.g. pic.PropertyItems.ToString()). The propertyIDList is empty, and tags are null. :s I would be dismayed if this, which I'm sure should be very simple, would require me to write my own class to open the emf, but it's starting to look like it

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900