Come abilitare l’anti-aliasing quando si esegue il rendering di WMF in BitMap in C # / WPF / WinForms?

Perché le linee ecc non saranno anti-aliasate quando si fa questo?

using (var myGraphics = Graphics.FromImage(bitmap)) { myGraphics.CompositingQuality = CompositingQuality.HighQuality; myGraphics.SmoothingMode = SmoothingMode.HighQuality; myGraphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; myGraphics.Clear(backgroundColor); myGraphics.EnumerateMetafile(m_metafile, new Point(0, 0), m_metafileDelegate); } 

La funzione delegato ha questo aspetto:

 private bool MetafileCallback(EmfPlusRecordType recordType, int flags, int dataSize, IntPtr data, PlayRecordCallback callbackData) { byte[] dataArray = null; if (data != IntPtr.Zero) { // Copy the unmanaged record to a managed byte buffer // that can be used by PlayRecord. dataArray = new byte[dataSize]; Marshal.Copy(data, dataArray, 0, dataSize); } m_metafile.PlayRecord(recordType, flags, dataSize, dataArray); return true; } 

Devo eseguire l’override di PlayRecord per un tipo specifico per ottenere l’anti-aliasing qui?

I WMF provengono da AutoCAD, se questo è un aiuto.

    Questo non è ansible in GDI + utilizzando un metafile WMF, ma è con EMF Plus. È ansible convertire in EMF Plus all’origine o al volo con un metodo GDI + scarsamente documentato (vedere di seguito).

    GDI (non GDI +) esegue il rendering del file WMF senza utilizzare alcun compositing dell’object GDI + Graphics sottostante, è solo un’enumerazione delle chiamate GDI dirette. Vedi questa domanda per ulteriori informazioni, ma tutte le risposte dicono della stessa cosa .

    Se è ansible convertire il file in EMF Plus, verranno utilizzati i metodi GDI + per il rendering del contenuto e verrà utilizzato il compositing GDI + incluso l’anti-aliasing. Se stai già utilizzando WPF, potresti anche prendere in considerazione l’esportazione in XPS che WPF può rendere antialiasing.

    Se non riesci a convertire all’origine, puoi chiamare un metodo GDI + da C #, ma non è elegante. È necessario avere accesso agli handle nativi utilizzati dalle classi System.Drawing:

     [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)] internal static extern int GdipConvertToEmfPlus(HandleRef graphics, HandleRef metafile, out Boolean conversionSuccess, EmfType emfType, [MarshalAsAttribute(UnmanagedType.LPWStr)] String description, out IntPtr convertedMetafile); 

    Lo useresti con un codice simile al seguente:

     using (var graphics = Graphics.FromImage(bmp)) using (var metafile = Metafile.FromFile(@"drawing.wmf")) using (var imageAttr = new ImageAttributes()) { graphics.SmoothingMode = SmoothingMode.AntiAlias; graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; var metafileHandleField = typeof(Metafile).GetField("nativeImage", BindingFlags.Instance | BindingFlags.NonPublic); var imageAttributesHandleField = typeof(ImageAttributes).GetField("nativeImageAttributes", BindingFlags.Instance | BindingFlags.NonPublic); var graphicsHandleProperty = typeof(Graphics).GetProperty("NativeGraphics", BindingFlags.Instance | BindingFlags.NonPublic); var setNativeImage = typeof(Image).GetMethod("SetNativeImage", BindingFlags.Instance | BindingFlags.NonPublic); IntPtr mf = (IntPtr)metafileHandleField.GetValue(metafile); IntPtr ia = (IntPtr)imageAttributesHandleField.GetValue(imageAttr); IntPtr g = (IntPtr)graphicsHandleProperty.GetValue(graphics); Boolean isSuccess; IntPtr emfPlusHandle; var status = GdipConvertToEmfPlus(new HandleRef(graphics, g), new HandleRef(metafile, mf), out isSuccess, EmfType.EmfPlusOnly, "", out emfPlusHandle); if (status != 0) { throw new Exception("Can't convert"); } using (var emfPlus = (Metafile)System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject(typeof(Metafile))) { setNativeImage.Invoke(emfPlus, new object[] { emfPlusHandle }); // use EnumerateMetafile on emfPlus as per your example code or save it: emfPlus.Save(@"drawing.emf"); } } 

    Ecco un esempio funzionante per LinqPad . Converte un file WMF (drawing.wmf) in un metafile EMF Plus e lo visualizza nel pannello dei risultati.

    File WMF in Paint: File WMF senza anti-aliasing

    File EMF + convertito in Paint: EMF + file con anti-aliasing


    Per completezza, il metodo GdipConvertToEmfPlus sopra fa parte della cosiddetta ” API piatta ” di GDI +. Il suo scopo originale era di servire solo le classi GDI + C ++. L’API C ++ che utilizza questo metodo si chiama Metafile.ConvertToEmfPlus .