There are plenty of examples of converting a wmf into a bitmap like: Reliable .wmf/wmf to Pixel based image conversion
But I need the reverse operation. I do not look for a vectorizer. I just want to embed a picture inside a wmf file without having to bother about the bits and bytes of the wmf format. I need a solution for .NET preferably in C#.
I first thought this would do the job:
using (Image img = Image.FromFile (path)) {
img.Save (myStream, System.Drawing.Imaging.ImageFormat.Wmf);
}
But this complains at runtime that the encoder is null. Where/How can I build such an encoder? I do not need a complicated one, just one that wraps an image into a wmf. Are there some requirements on the supported formats in WMF? I suppose png and bmp are supported but is gif also supported?
Here is the full answer to the question including my modifications. Vincent's answer is fully correct. Only some definitions and one enum were missing. That is why I post here the "clean" working code in the hope it can be useful for someone else.
[Flags]
private enum EmfToWmfBitsFlags {
EmfToWmfBitsFlagsDefault = 0x00000000,
EmfToWmfBitsFlagsEmbedEmf = 0x00000001,
EmfToWmfBitsFlagsIncludePlaceable = 0x00000002,
EmfToWmfBitsFlagsNoXORClip = 0x00000004
}
private static int MM_ISOTROPIC = 7;
private static int MM_ANISOTROPIC = 8;
[DllImport ("gdiplus.dll")]
private static extern uint GdipEmfToWmfBits (IntPtr _hEmf, uint _bufferSize,
byte[] _buffer, int _mappingMode, EmfToWmfBitsFlags _flags);
[DllImport ("gdi32.dll")]
private static extern IntPtr SetMetaFileBitsEx (uint _bufferSize,
byte[] _buffer);
[DllImport ("gdi32.dll")]
private static extern IntPtr CopyMetaFile (IntPtr hWmf,
string filename);
[DllImport ("gdi32.dll")]
private static extern bool DeleteMetaFile (IntPtr hWmf);
[DllImport ("gdi32.dll")]
private static extern bool DeleteEnhMetaFile (IntPtr hEmf);
private static MemoryStream MakeMetafileStream (Bitmap image)
{
Metafile metafile = null;
using (Graphics g = Graphics.FromImage (image)) {
IntPtr hDC = g.GetHdc ();
metafile = new Metafile (hDC, EmfType.EmfOnly);
g.ReleaseHdc (hDC);
}
using (Graphics g = Graphics.FromImage (metafile)) {
g.DrawImage (image, 0, 0);
}
IntPtr _hEmf = metafile.GetHenhmetafile ();
uint _bufferSize = GdipEmfToWmfBits (_hEmf, 0, null, MM_ANISOTROPIC,
EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
byte[] _buffer = new byte[_bufferSize];
GdipEmfToWmfBits (_hEmf, _bufferSize, _buffer, MM_ANISOTROPIC,
EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
IntPtr hmf = SetMetaFileBitsEx (_bufferSize, _buffer);
string tempfile = Path.GetTempFileName ();
CopyMetaFile (hmf, tempfile);
DeleteMetaFile (hmf);
DeleteEnhMetaFile (_hEmf);
var stream = new MemoryStream ();
byte[] data = File.ReadAllBytes (tempfile);
//File.Delete (tempfile);
int count = data.Length;
stream.Write (data, 0, count);
return stream;
}