You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

WMF文件转C# Bitmap出现拉伸失真问题求助(可修改C++/C#两端代码)

WMF文件转C# Bitmap出现拉伸失真问题求助(可修改C++/C#两端代码)

你好,我之前处理过类似的WMF/EMF缩放失真问题,这种拉伸问题几乎肯定是因为你在C#代码里硬编码了固定宽高,没有尊重元文件本身的原生比例和分辨率信息。结合你两边都能修改代码的情况,给你几个可落地的解决方案:


方案1:C#端读取WMF原始尺寸,按比例绘制(改动最小,优先尝试)

WMF是矢量格式,自带物理尺寸和DPI信息,直接硬写width/height会强制扭曲它的原生比例。我们可以先读取WMF的原始参数,计算出匹配的像素尺寸后再绘制:

using (var wmf = new Metafile(path))
{
    // 获取WMF的原生DPI和物理尺寸(单位:0.01毫米)
    float nativeDpiX = wmf.HorizontalResolution;
    float nativeDpiY = wmf.VerticalResolution;
    
    // 转换逻辑:1英寸=25.4毫米,将物理尺寸转成匹配原生DPI的像素
    int targetWidth = (int)Math.Round(wmf.Width * nativeDpiX / (25.4f * 100f));
    int targetHeight = (int)Math.Round(wmf.Height * nativeDpiY / (25.4f * 100f));

    using (var bitmap = new Bitmap(targetWidth, targetHeight))
    {
        using (var g = Graphics.FromImage(bitmap))
        {
            // 开启高质量绘制选项,提升最终BMP清晰度
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
            g.Clear(Color.White); // 可选:设置背景色避免透明区域异常

            // 按原生比例绘制,无拉伸
            g.DrawImage(wmf, new Rectangle(0, 0, targetWidth, targetHeight));

            var bmpPath = path.Replace("wmf", "bmp");
            bitmap.Save(bmpPath, System.Drawing.Imaging.ImageFormat.Bmp);
            
            // 插入Excel时也用计算后的尺寸,避免二次拉伸
            chartSheet.Pictures.AddPicture(bitmap, chartSheet.Cells[cell], 0, 0, targetWidth, targetHeight);
        }
    }
}

方案2:C#端直接使用WMF/EMF,跳过BMP转换(最优解,若场景允许)

如果你的C#场景(比如Excel的Pictures.AddPicture)支持直接插入矢量元文件,完全不用转BMP——矢量图本身不会有拉伸失真问题,还能保持缩放清晰度:

// 直接插入WMF到Excel,使用原生尺寸
var pic = chartSheet.Pictures.AddPicture(
    filename: path,
    linkToFile: false,
    saveWithDocument: true,
    left: chartSheet.Cells[cell].Left,
    top: chartSheet.Cells[cell].Top,
    width: Type.Missing, // 传Type.Missing让Excel自动使用WMF原生宽度
    height: Type.Missing // 传Type.Missing让Excel自动使用WMF原生高度
);

方案3:C++端优化元文件生成,保证尺寸信息准确

你当前用CopyMetaFile直接复制元文件,可能原始的hMFDist本身的边界信息不完整。如果生成EMF,建议用增强型元文件API,确保写入准确的边界数据:

// 替换原有的CopyMetaFile逻辑,生成带准确边界的EMF
CString distChartMeta = _T("DistChartMeta.emf");
RECT rcBounds = {0};

// 先读取原始元文件的边界信息
METAFILEPICT* mfp = (METAFILEPICT*)GlobalLock(GetMetaFileBitsEx(hMFDist, 0, NULL, 0));
if (mfp != nullptr)
{
    // 提取原始元文件的尺寸作为边界
    rcBounds.right = mfp->mfxExt;
    rcBounds.bottom = mfp->mfyExt;
    GlobalUnlock(mfp);
}
else
{
    // 兜底:设置默认边界(如果无法读取原始信息)
    SetRect(&rcBounds, 0, 0, 1000, 800);
}

// 创建带准确边界的增强型元文件DC
HDC hdcEnh = CreateEnhMetaFile(
    NULL, 
    _T(temp + distChartMeta), 
    &rcBounds, 
    _T("Your App Name") // 可选:元文件的描述信息
);

if (hdcEnh != nullptr)
{
    // 将原始元文件回放至增强型元文件DC
    PlayMetaFile(hdcEnh, hMFDist);
    // 关闭DC并获取增强型元文件句柄
    HMETAFILE hMFEnh = CloseEnhMetaFile(hdcEnh);
    if (hMFEnh != nullptr)
    {
        // 保存增强型元文件
        CopyEnhMetaFile(hMFEnh, _T(temp + distChartMeta));
        DeleteMetaFile(hMFEnh);
    }
}

这样生成的EMF会包含完整的尺寸元数据,C#读取时能正确识别原生比例,不会出现拉伸。


额外排查小技巧

  1. 用Windows自带的画图打开原始WMF,查看「属性」里的宽高比,对比你C#中硬编码的width/height比例是否一致——如果比例不同,必然会拉伸。
  2. MetaEdit这类工具打开WMF/EMF,检查它的METAFILEPICT结构中的mfxExt/mfyExt值,确认尺寸信息是否正确。

如果还有问题,可以补充原始WMF的尺寸属性信息,我再帮你细化方案!

火山引擎 最新活动