GDI+ includes a built-in decoder for EMF but it does not include a built-in encoder (see https://msdn.microsoft.com/en-us/library/bb882579(v=vs.110).aspx). Consequently, you can read an EMF, but not write it. Atleast, not through GDI+. If you use the Metafile.Save method (which is the natutal thing to do) then you will actually save a PNG and loose the vector graphics.

GDI+ includes a built-in decoder for EMF but it does not include a built-in encoder (see https://msdn.microsoft.com/en-us/library/bb882579(v=vs.110).aspx). Consequently, you can read an EMF, but not write it. Atleast, not through GDI+. If you use the Metafile.Save method (which is the natutal thing to do) then you will actually save a PNG and loose the vector graphics.

Save a Metafile

To save a Metafile object as an EMF file and preserve the vector graphics then you will need to jump through some hoops. Here is the boilerplate code:

[System.Runtime.InteropServices.DllImport("gdi32")] public static extern int GetEnhMetaFileBits( int hemf, int cbBuffer, byte[] lpbBuffer);

// caller remains owner of stream and metafile static void saveMetafile(Stream stream, Metafile metafile) { // get the GDI handle int enhMetafileHandle = metafile.GetHenhmetafile().ToInt32();

// get required buffer size int bufferSize = GetEnhMetaFileBits(enhMetafileHandle, 0, null);

// create buffer byte[] buffer = new byte[bufferSize];

// get metafile data if (GetEnhMetaFileBits(enhMetafileHandle, bufferSize, buffer) <= 0) { throw new System.ApplicationException("GetEnhMetaFileBits failed"); }

// write metafile data to stream stream.Write(buffer, 0, bufferSize); }

Render a PDF page to an EMF file

Our PDF rasterizer component lets you render to an EMF file. Here is the code that renders a PDF page to an EMF:

using (FileStream pdfFile = new FileStream( "in.pdf", FileMode.Open, FileAccess.Read)) { // get the first PDF page Document document = new Document(pdfFile); Page page = document.Pages[0];

Metafile metafile = createMetafile(page);

... }

This code uses the following helper function:

// caller becomes owner of returned Metafile static Metafile createMetafile(Page page) { Metafile metafile = null;

using (Graphics graphics = Graphics.FromHwndInternal(IntPtr.Zero))
{ System.IntPtr hdc = graphics.GetHdc(); metafile = new Metafile( hdc, new System.Drawing.RectangleF( 0, 0, (float)page.Width, (float)page.Height), MetafileFrameUnit.Point); graphics.ReleaseHdc(hdc); }

using (Graphics metafileGraphics = Graphics.FromImage(metafile))
{ // for some reason the metafile header and metafile graphics // may have different resolutions // adjust for this using a scale transform MetafileHeader metafileHeader = metafile.GetMetafileHeader(); metafileGraphics.ScaleTransform( metafileHeader.DpiX / metafileGraphics.DpiX, metafileHeader.DpiY / metafileGraphics.DpiY);

// PDF graphics are in points; this corresponds to 72 DPI
// adjust for the difference with the metaGraphics resolution
metafileGraphics.ScaleTransform(
  metafileGraphics.DpiX / 72f,
  metafileGraphics.DpiY / 72f);

page.Draw(metafileGraphics);

} return metafile; }

I borrowed the piece that adjust for the difference in resolution between the metafileGraphics and metafileHeader from Nicholas Piasecki's blog (unfortunately it isn't available online anymore).

Using the saveMetafile method above, you can now save this to an EMF file as follows:

using (FileStream emfFile = new FileStream( "out.emf", FileMode.Create, FileAccess.Write)) { saveMetafile(emfFile, metafile); }

if (null != metafile) metafile.Dispose();

If you open the EMF file in the Windows viewer, you can zoom in to the maximum level and see that the vector graphics are preserved: