Это невозможно в GDI + с использованием метафайла WMF, но с EMF Plus. Вы можете конвертировать в EMF Plus у источника или «на лету» с плохо документированным методом GDI + (см. Ниже).
GDI (не GDI +) отображает WMF-файл без использования какого-либо композиционного объекта GDI + Graphics, лежащего в основе его, это просто перечисление прямых вызовов GDI. See this question for more, but all answers say about the same thing.
Если вы можете конвертировать файл в EMF Plus, это будет использовать методы GDI + для рендеринга контента и использовать GDI + compositing, включая сглаживание. Если вы уже используете WPF, вы также можете рассмотреть возможность экспорта в XPS, который WPF может отображать сглаженными.
Если вы не можете преобразовать исходный код, вы можете вызвать метод GDI + с C#, но он не изящный. Вы должны иметь доступ к нативным ручкам, используемых классы 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);
Вы бы использовать это с кодом, подобным следующем:
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. Он преобразует WMF-файл (drawing.wmf) в метафайл файла EMF Plus и отображает его на панели результатов.
WMF файл в Paint:
Старинное EMF + файл в Paint:
Для полноты картины выше GdipConvertToEmfPlus
метод является частью того, что известно как "flat API "GDI +. Его первоначальная цель состояла в том, чтобы обслуживать только классы GDI + C++. C++ API, который использует этот метод, называется Metafile.ConvertToEmfPlus
.
Как это связано с WPF? 'Graphics' - это' System.Drawing', 'Metafile' - это' System.Drawing.Image', оба пространства имен WinForms. – Clemens
Я использую его в WPF-приложении, но да, возможно, не связан. Я обновлю теги. – Macke