jde*_*aan 3 .net encode image wmf bitmap
有很多将wmf转换为位图的示例: 可靠的.wmf/wmf到基于像素的图像转换
但我需要反向操作.我不寻找矢量化器.我只是想在wmf文件中嵌入一张图片,而不必担心wmf格式的位和字节.我最好在C#中使用.NET的解决方案.
我首先想到这会做的工作:
using (Image img = Image.FromFile (path)) {
img.Save (myStream, System.Drawing.Imaging.ImageFormat.Wmf);
}
Run Code Online (Sandbox Code Playgroud)
但是这在运行时抱怨编码器为空.在哪里/如何构建这样的编码器?我不需要复杂的,只需将图像包装成wmf.对WMF支持的格式有一些要求吗?我想支持png和bmp但是还支持gif吗?
以下是问题的完整答案,包括我的修改.文森特的回答是完全正确的.只缺少一些定义和一个枚举.这就是为什么我在这里发布"干净"的工作代码,希望它对其他人有用.
[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;
}
Run Code Online (Sandbox Code Playgroud)
从这里:
当您使用Save方法将图形图像另存为Windows图元文件格式(WMF)或增强型图元文件格式(EMF)文件时,生成的文件将另存为可移植网络图形(PNG)文件.出现此问题的原因是.NET Framework的GDI +组件没有可用于将文件另存为.wmf或.emf文件的编码器.
但我想你已经走了那么远:)
这里有人在FileStream中放置一个位图.
metafileStream = MakeMetafileStream(gdiBitmap);
Run Code Online (Sandbox Code Playgroud)
使用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;
}
Run Code Online (Sandbox Code Playgroud)
有趣的东西.但至于编码器的事情......
这里从MS黄文雄登载非托管的方法:
[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);
}
Run Code Online (Sandbox Code Playgroud)
希望这会让你到那里:)
jdehaan发布的改进版本(对他和文森特的称赞)
[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;
}
Run Code Online (Sandbox Code Playgroud)
这个不会留下临时文件,也避免将_bufferSize复制到临时文件,然后将其复制到另一个缓冲区.再次感谢你们.