Cela n'est pas possible dans GDI + en utilisant un métafichier WMF, mais avec EMF Plus. Vous pouvez convertir à EMF Plus à la source, ou à la volée avec une méthode GDI + mal documentée (voir ci-dessous). GDI (pas GDI +) rend le fichier WMF sans utiliser le compositing de l'objet GDI + Graphics sous-jacent, il s'agit simplement d'une énumération des appels GDI directs. See this question for more, but all answers say about the same thing.
Si vous pouvez convertir le fichier en EMF Plus, cela utilisera les méthodes GDI + pour rendre le contenu et utiliser la composition GDI +, y compris l'anti-aliasing. Si vous utilisez déjà WPF, vous pouvez également envisager d'exporter vers XPS que WPF peut rendre anti-aliasé.
Si vous ne pouvez pas convertir à la source, vous pouvez appeler une méthode GDI + à partir de C#, mais ce n'est pas élégant. Vous devez avoir accès aux poignées natives utilisées par les classes 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);
Vous utilisez ce code similaire avec les éléments suivants:
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");
}
}
Here's a working example for LinqPad. Il convertit un fichier WMF (drawing.wmf) en un métafichier EMF Plus et l'affiche dans le panneau des résultats.
fichier WMF dans Paint:
converti EMF + fichier dans Paint:
Par souci d'exhaustivité, la méthode GdipConvertToEmfPlus
ci-dessus fait partie de ce qu'on appelle le "flat API "de GDI +. Son but original était de ne servir que les classes GDI + C++. L'API C++ qui utilise cette méthode est appelée Metafile.ConvertToEmfPlus
.
Comment est-ce que cela concerne WPF? 'Graphics' provient de' System.Drawing', 'Metafile' provient de' System.Drawing.Image', les deux espaces de noms de WinForms. – Clemens
Je l'utilise dans une application WPF, mais oui, probablement pas lié. Je vais mettre à jour les tags. – Macke