Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C#/WPF/WinForms中将WMF渲染为位图时,如何启用抗锯齿?_C#_System.drawing_Metafile_Wmf_.emf - Fatal编程技术网

在C#/WPF/WinForms中将WMF渲染为位图时,如何启用抗锯齿?

在C#/WPF/WinForms中将WMF渲染为位图时,如何启用抗锯齿?,c#,system.drawing,metafile,wmf,.emf,C#,System.drawing,Metafile,Wmf,.emf,为什么执行此操作时不会对线等进行抗锯齿处理 using (var myGraphics = Graphics.FromImage(bitmap)) { myGraphics.CompositingQuality = CompositingQuality.HighQuality; myGraphics.SmoothingMode = SmoothingMode.HighQuality; myGraphics.TextRenderingHint = TextRenderingHint.AntiAli

为什么执行此操作时不会对线等进行抗锯齿处理

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);
}
委托函数如下所示:

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;
}
我是否需要覆盖特定类型的PlayRecord以在此处获得抗锯齿


WMF来自AutoCAD,如果有帮助的话。

这在GDI+中不可能使用WMF图元文件,但在EMF Plus中是这样的。您可以在源代码处转换为EMF Plus,也可以使用文档不完整的GDI+方法动态转换(见下文)

GDI(不是GDI+)渲染WMF文件,而不使用其底层GDI+图形对象的任何合成,它只是直接GDI调用的枚举

如果可以将文件转换为EMF Plus,则将使用GDI+方法呈现内容,并使用GDI+合成(包括抗锯齿)。如果您已经使用WPF,您也可以考虑导出到XPS,WPF可以呈现反锯齿。 如果无法在源代码处进行转换,可以从C#调用GDI+方法,但这并不优雅。您需要有权访问系统使用的本机句柄。绘图类:

[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");
    }
}
。它将WMF文件(drawing.WMF)转换为EMF Plus图元文件,并将其显示在结果面板中

绘画中的WMF文件:

在Paint中转换的EMF+文件:



为了完整起见,上面的
gdipconverttoemplus
方法是GDI+的“”的一部分。它的最初目的是只为GDI+C++类服务。使用这种方法的C++ API被调用.< /p>这与WPF有关?code>Graphics来自
System.Drawing
Metafile
来自
System.Drawing.Image
,都是WinForms的名称空间。我正在WPF应用程序中使用它,但是的,可能不相关。我会更新标签的。谢谢!对于WMF(AutoCAD LT)的源代码,我真的做不了太多,所以在这种情况下,有一点本地性是可以的。我会尝试一下,如果它能工作,我会回来的,这看起来是应该的(考虑到我有限的WMF/EMF/GDI+经验)。(我想GDI函数会支持一些全局“AntiAlias”标志,但我刚刚错过了哪一个。)。(这个,g)应该是(图形,g),对吗?然后我得到issucess=true,但图元文件构造函数失败,出现“generic error System.Runtime.InteropServices.ExternalException(0x80004005):GDI+中发生了一个generic error”。此外,imageAttr似乎根本没有被使用?没错,代码还没有准备好使用,并且假设您可能有ImageAttributes,而您可能没有。您是否有可以共享的WMF来重现问题?更新代码以提供工作示例。使用图元文件构造函数时出现一些问题,因此我们需要以一种非常粗糙但有效的方式直接调用
SetNativeHandle
。谢谢!非常感谢!SetNativeHandle成功了。我真的需要深入研究一下它是如何工作的。(顺便说一句,您的代码中没有使用imageAttribute/ia,它可以通过删除所有相关调用来正常工作。)(另外,感谢您向我介绍LinqPad;-)