如何使用GdipConvertToEmfPlus将WMF转换为EMF +而不会丢失四分之三的图像?

时间:2016-06-28 08:48:46

标签: c# system.drawing autocad metafile wmf

将WMF转换为EMF +以获得抗锯齿渲染后,转换为EMF +后仅包含WMF的左上象限。

使用EnumerateMetafile绘制WMF(转换前)有效,但没有反别名,这就是我在这里开枪。

为什么四分之三的图片在转换时丢失了?

WMF由AutoCAD LT和32640x14586像素大小生成,单位/英寸= 1632.

EMF中的记录类型(转换后)是:

EmfMin
Header
SetAntiAliasMode
SetPixelOffsetMode
SetTextRenderingHint
MultiplyWorldTransform
Save
MultiplyWorldTransform
SetWorldTransform
BeginContainerNoParams
SetAntiAliasMode
SetPixelOffsetMode
SetTextRenderingHint
SetPageTransform
SetWorldTransform
SetWorldTransform
SetWorldTransform
SetWorldTransform
SetWorldTransform
Object
Object
DrawPath
...
SetClipRegion
EndContainer
Restore
SetWorldTransform
EndOfFile
EmfEof

我尝试在元文件回调中跳过SetPageTransform和SetClipRegion,并且之前也缩放图形,但没有任何帮助。

我会看看我是否可以分享原始的WMF进行检查。

通过此问题了解如何进行转换: How to enable anti-aliasing when rendering WMF to BitMap in C#/WPF/WinForms?

1 个答案:

答案 0 :(得分:0)

所以,我不得不将SetWorldTransform记录的矩阵缩放0.75,那么一切都好吗?

这就是我的EnumerateMetafile调用代码与周围代码的对比,如果有其他人发生这种情况。

graphics.EnumerateMetafile(emfPlusMetaFile, new PointF(0, 0),
    (recordType, flags, dataSize, data, callbackData) =>
    {
        var dataArray = GetDataArray(data, dataSize);
        AdjustWorldTransformScale(recordType, dataArray, 0.75f);
        emfPlusMetaFile.PlayRecord(recordType, flags, dataSize, dataArray);
        return true;
    }
);


private static void AdjustWorldTransformScale(EmfPlusRecordType recordType, byte[] dataArray, float wtfScale)
{
    if (recordType == EmfPlusRecordType.SetWorldTransform)
    {
        using (var stream = new MemoryStream(dataArray))
        using (var reader = new BinaryReader(stream))
        using (var writer = new BinaryWriter(stream))
        {
            var m11 = reader.ReadSingle();
            var m12 = reader.ReadSingle();
            var m21 = reader.ReadSingle();
            var m22 = reader.ReadSingle();

            stream.Position = 0;

            writer.Write(m11*wtfScale);
            writer.Write(m12*wtfScale);
            writer.Write(m21*wtfScale);
            writer.Write(m22*wtfScale);                
        }
    }
}

private static byte[] GetDataArray(IntPtr data, int dataSize)
{
    if (data == IntPtr.Zero) return null;

    // Copy the unmanaged record to a managed byte buffer that can be used by PlayRecord.
    var dataArray = new byte[dataSize];
    Marshal.Copy(data, dataArray, 0, dataSize);
    return dataArray;
}

(缩放参数的命名是有意的。)