Convertir une image en WMF with.NET Je ne sais pas.

il y a beaucoup d'exemples de conversion d'un wmf en bitmap comme: fiable .WMF / wmf en Pixel conversion d'image

Mais j'ai besoin de l'opération inverse. Je ne cherche pas un vectorisateur. Je veux juste intégrer une image à l'intérieur d'un fichier wmf sans avoir à se soucier des bits et des octets du format wmf. J'ai besoin d'une solution pour .NET de préférence en C#.

j'ai d'abord pensé que cela ferait l'affaire:

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

mais cela se plaint à l'exécution que l'encodeur est nul. Où / Comment puis-je construire un tel encodeur? Je n'ai pas besoin d'un complexe, juste un qui enveloppe une image dans un wmf. Y a-t-il des exigences sur les formats pris en charge dans WMF? Je suppose que png et bmp sont pris en charge, mais gif est-il également pris en charge?

3
demandé sur Community 2011-03-11 11:47:06

4 réponses

à Partir de ici :

Lorsque vous utilisez la méthode save pour Enregistrer un image graphique en tant que Métafile Windows Format (WMF) ou Métafile amélioré Format (EMF) de fichier, le fichier résultant est enregistré comme un réseau Portable Le fichier graphique (PNG) à la place. Ce le comportement se produit parce que le GDI+ composante du cadre. net pas un codeur que vous pouvez utiliser pour sauvegarder les fichiers sous .wmf ou .les fichiers emf.

Mais je suppose que vous avez déjà loin :)

Ici quelqu'un est en train de mettre une image bitmap dans un FileStream.

metafileStream = MakeMetafileStream(gdiBitmap);

avec MakeMetafileStream () étant:

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

intéressant. Mais comme pour le codeur chose...

ici Peter Huang du MS a affiché cette approche non gérée:

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

J'espère que ça vous aidera il y a:)

4
répondu Vincent Vancalbergh 2011-03-11 09:08:12

Voici la réponse complète à la question, y compris mes modifications. La réponse de Vincent est tout à fait correcte. Seules quelques définitions et un enum manquaient. C'est pourquoi je poste ici le "nettoyer" le code de travail dans l'espoir qu'il peut être utile pour quelqu'un d'autre.

        [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;
        }
5
répondu jdehaan 2011-03-15 08:42:29

une version améliorée de ce que jdehaan posté (kudos btw à lui et 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;
    }

celui-ci ne laisse pas de fichiers temp derrière et évite aussi de copier _bufferSize dans un fichier temp pour ensuite le copier dans un autre buffer. Merci encore les gars.

2
répondu ILIA BROUDNO 2014-12-04 01:44:37

voici un Win32 GDI+ exemple qui a fonctionné pour moi (crédit à 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);
0
répondu Pierre 2016-05-07 23:31:41