net img how .net image bitmap encode wmf

img - Convierte una imagen en WMF con.NET?



system drawing image vb net (4)

Desde aquí :

Cuando utiliza el método Guardar para guardar una imagen gráfica como un formato de metarchivo de Windows (WMF) o un archivo de formato de metarchivo mejorado (EMF), el archivo resultante se guarda como un archivo de gráficos de red portátiles (PNG). Este comportamiento se produce porque el componente GDI + de .NET Framework no tiene un codificador que puede usar para guardar archivos como archivos .wmf o .emf.

Pero supongo que ya has llegado tan lejos :)

Aquí alguien está poniendo un mapa de bits en un FileStream.

metafileStream = MakeMetafileStream(gdiBitmap);

con MakeMetafileStream () siendo:

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; }

Cosas interesantes. Pero en cuanto a la cosa del codificador ...

Aquí Peter Huang de MS publicó este enfoque no gestionado:

[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); }

Espero que esto te lleve allí :)

Hay muchos ejemplos de cómo convertir un archivo wmf en un mapa de bits, por ejemplo: conversión confiable de imágenes .wmf / wmf a píxel.

Pero necesito la operación inversa. No busco un vectorizador. Solo quiero insertar una imagen dentro de un archivo wmf sin tener que preocuparme por los bits y bytes del formato wmf. Necesito una solución para .NET preferiblemente en C #.

Primero pensé que esto haría el trabajo:

using (Image img = Image.FromFile (path)) { img.Save (myStream, System.Drawing.Imaging.ImageFormat.Wmf); }

Pero esto se queja en tiempo de ejecución de que el codificador es nulo. ¿Dónde / Cómo puedo construir tal codificador? No necesito uno complicado, solo uno que envuelve una imagen en un wmf. ¿Hay algunos requisitos en los formatos compatibles en WMF? Supongo que png y bmp son compatibles pero también es compatible con gif?


Aquí está la respuesta completa a la pregunta, incluidas mis modificaciones. La respuesta de Vincent es completamente correcta. Solo faltaban algunas definiciones y una enumeración. Es por eso que publico aquí el código de trabajo "limpio" con la esperanza de que pueda ser útil para otra persona.

[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; }


Una versión mejorada de lo que jdehaan publicó (felicitaciones por él y 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; }

Este no deja archivos temporales atrás y también evita copiar _bufferSize a un archivo temporal solo para luego copiarlo a otro buffer. Gracias de nuevo chicos.


Aquí hay un ejemplo de Win32 GDI + que funcionó para mí (crédito a 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);