有很多将wmf转换为位图的示例,如: Reliable .wmf/wmf to Pixel based image conversion
但我需要反向操作。我不寻找矢量化器。我只是想在wmf文件中嵌入一张图片,而不必担心wmf格式的位和字节。我最好在C#中使用.NET的解决方案。
我首先想到这会做的工作:
using (Image img = Image.FromFile (path)) {
img.Save (myStream, System.Drawing.Imaging.ImageFormat.Wmf);
}
但是这在运行时抱怨编码器为空。在哪里/如何构建这样的编码器?我不需要复杂的,只需将图像包装成wmf。对WMF支持的格式有一些要求吗?我想支持png和bmp但是还支持gif吗?
答案 0 :(得分:6)
以下是问题的完整答案,包括我的修改。文森特的回答是完全正确的。只缺少一些定义和一个枚举。这就是为什么我在这里发布“干净”的工作代码,希望它对其他人有用。
[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;
}
答案 1 :(得分:5)
来自here:
使用Save方法保存时 图形图像作为Windows图元文件 格式(WMF)或增强型图元文件 格式化(EMF)文件,生成的文件 保存为便携式网络 而是图形(PNG)文件。这个 行为发生的原因是GDI + .NET Framework的组件 没有可以使用的编码器 将文件保存为.wmf或.emf文件。
但我猜你已经走得那么远了。)
Here有人在FileStream中放置位图。
metafileStream = MakeMetafileStream(gdiBitmap);
使用MakeMetafileStream():
private static MemoryStream MakeMetafileStream(Bitmap image)
{
Graphics graphics = null;
Metafile metafile= null;
var stream = new MemoryStream();
try
{
using (graphics = Graphics.FromImage(image))
{
var hdc = graphics.GetHdc();
metafile= new Metafile(stream, hdc);
graphics.ReleaseHdc(hdc);
}
using (graphics = Graphics.FromImage(metafile))
{ graphics.DrawImage(image, 0, 0); }
}
finally
{
if (graphics != null)
{ graphics.Dispose(); }
if (metafile!= null)
{ metafile.Dispose(); }
}
return stream;
}
有趣的东西。 但至于编码器的事情......
Here来自MS的Peter Huang发布了这种不受管理的方法:
[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 void button4_Click(object sender, System.EventArgs e)
{
Graphics g= this.CreateGraphics();
IntPtr hDC = g.GetHdc();
Metafile mf = new Metafile(hDC,EmfType.EmfOnly);
g.ReleaseHdc(hDC);
g.Dispose();
g=Graphics.FromImage(mf);
//Pen p = new Pen(Color.White,5);
g.DrawArc(Pens.Black,0,0,200,200,0,360);
//g.DrawImage(Bitmap.FromFile(@"c:\temp\test.bmp"),0,0);
g.Dispose();
IntPtr _hEmf= mf.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);
CopyMetaFile(hmf, "C:\\ConvertedMetafile.wmf");
DeleteMetaFile(hmf);
DeleteEnhMetaFile(_hEmf);
}
希望这能让你到达那里:)
答案 2 :(得分:5)
jdehaan发布的改进版本(对他和Vincent赞不绝口)
[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);
public static MemoryStream MakeMetafileStream(System.Drawing.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);
DeleteEnhMetaFile(_hEmf);
var stream = new MemoryStream();
stream.Write(_buffer, 0, (int)_bufferSize);
stream.Seek(0, 0);
return stream;
}
这个文件不会留下临时文件,也避免将_bufferSize复制到临时文件,然后再将其复制到另一个缓冲区。 再次感谢你们。
答案 3 :(得分:0)
这是一个适合我的Win32 GDI +示例(归功于http://www.codeproject.com/Articles/6879/How-to-use-GDI-to-save-image-in-WMF-EXIF-or-EMF-fo)
Bitmap *image;
image = Bitmap::FromFile(L"in.jpg"); // read in the JPG
HDC hdc = GetDC(hwnd); // parent window
Metafile *metafile = new Metafile(L"out.wmf", hdc);
Graphics *graphics = new Graphics(metafile);
graphics->DrawImage(image, 0, 0, image->GetWidth(), image->GetHeight());
delete graphics; delete metafile; delete image;
ReleaseDC(hwnd, hdc);