You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何调用Windows自带画图软件将BMP转换为单色位图?

调用Windows画图软件转换BMP为单色位图的方案

一、核心实现:调用画图程序并自动完成转换

Windows自带的画图程序(mspaint.exe)没有直接的命令行转换参数,需要通过UI模拟操作实现。以下提供两种可行方式:

方式1:SendKeys模拟按键操作(简单但依赖系统环境)

通过启动画图程序,模拟键盘操作完成打开、另存为单色位图的流程,适合快速实现但稳定性受窗口状态、系统语言影响:

using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;

public void ConvertBmpWithPaint(string inputPath, string outputPath)
{
    // 启动画图并打开目标图片
    var paintProcess = Process.Start("mspaint.exe", $"\"{inputPath}\"");
    paintProcess.WaitForInputIdle();
    Thread.Sleep(1000); // 等待图片加载完成,可根据实际调整

    // 模拟Alt+F打开文件菜单
    SendKeys.SendWait("%F");
    Thread.Sleep(200);
    // 选择"另存为"
    SendKeys.SendWait("S");
    Thread.Sleep(200);
    // 选择"单色位图"(中文系统快捷键为M,英文系统需改为对应按键)
    SendKeys.SendWait("M");
    Thread.Sleep(500);
    // 输入保存路径
    SendKeys.SendWait($"\"{outputPath}\"");
    Thread.Sleep(200);
    // 确认保存
    SendKeys.SendWait("{ENTER}");
    Thread.Sleep(200);
    // 覆盖已有文件则按Y确认
    SendKeys.SendWait("Y");
    Thread.Sleep(200);

    // 关闭画图程序
    paintProcess.CloseMainWindow();
    paintProcess.WaitForExit();
}

方式2:UI Automation控件定位(更稳定)

通过Windows UI Automation库定位画图程序的控件,模拟点击操作,不依赖按键,适配性更强:

using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Automation;

public void ConvertBmpWithPaintAutomation(string inputPath, string outputPath)
{
    var paintProcess = Process.Start("mspaint.exe", $"\"{inputPath}\"");
    paintProcess.WaitForInputIdle();
    Thread.Sleep(1000);

    // 获取画图主窗口
    var mainWindow = AutomationElement.FromHandle(paintProcess.MainWindowHandle);

    // 打开文件菜单
    var fileMenu = mainWindow.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, "文件"));
    fileMenu?.GetCurrentPattern(InvokePattern.Pattern)?.Invoke();
    Thread.Sleep(200);

    // 点击"另存为"
    var saveAsMenu = mainWindow.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, "另存为"));
    saveAsMenu?.GetCurrentPattern(InvokePattern.Pattern)?.Invoke();
    Thread.Sleep(500);

    // 选择"单色位图"格式
    var monoOption = mainWindow.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, "单色位图"));
    monoOption?.GetCurrentPattern(InvokePattern.Pattern)?.Invoke();
    Thread.Sleep(500);

    // 在保存对话框输入路径并确认
    var saveDialog = mainWindow.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.ClassNameProperty, "#32770"));
    if (saveDialog != null)
    {
        // 输入保存路径
        var pathInput = saveDialog.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
        (pathInput?.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern)?.SetValue(outputPath);
        Thread.Sleep(200);

        // 点击保存按钮
        var saveBtn = saveDialog.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, "保存"));
        saveBtn?.GetCurrentPattern(InvokePattern.Pattern)?.Invoke();
        Thread.Sleep(200);

        // 处理覆盖提示
        var overwriteDialog = AutomationElement.FromHandle(paintProcess.MainWindowHandle).FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, "确认另存为"));
        var yesBtn = overwriteDialog?.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, "是"));
        yesBtn?.GetCurrentPattern(InvokePattern.Pattern)?.Invoke();
        Thread.Sleep(200);
    }

    // 关闭画图
    paintProcess.CloseMainWindow();
    paintProcess.WaitForExit();
}

二、替代方案:修复自定义1bpp转换代码

调用外部程序存在不稳定风险,更优方案是修复你现有代码的格式问题。画图保存的单色位图符合打印机要求的核心原因是:正确的黑白调色板、扫描线字节对齐、标准DPI设置。以下是修复后的转换代码:

using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

public static Bitmap ConvertToValid1Bit(Bitmap input)
{
    int width = input.Width;
    int height = input.Height;

    // 创建1bpp索引位图
    Bitmap output = new Bitmap(width, height, PixelFormat.Format1bppIndexed);

    // 设置标准黑白调色板
    ColorPalette palette = output.Palette;
    palette.Entries[0] = Color.Black;
    palette.Entries[1] = Color.White;
    output.Palette = palette;

    // 锁定图像数据
    BitmapData inputData = input.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
    BitmapData outputData = output.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);

    try
    {
        int inputStride = inputData.Stride;
        int outputStride = outputData.Stride;
        IntPtr inputScan = inputData.Scan0;
        IntPtr outputScan = outputData.Scan0;

        // 逐行处理图像
        for (int y = 0; y < height; y++)
        {
            byte[] inputLine = new byte[inputStride];
            byte[] outputLine = new byte[outputStride];
            Marshal.Copy(inputScan, inputLine, 0, inputStride);
            Marshal.Copy(outputScan, outputLine, 0, outputStride);

            for (int x = 0; x < width; x++)
            {
                // 计算灰度值
                byte r = inputLine[x * 3 + 2];
                byte g = inputLine[x * 3 + 1];
                byte b = inputLine[x * 3 + 0];
                int gray = (int)(r * 0.299 + g * 0.587 + b * 0.114);

                // 阈值转黑白,写入对应位
                int bitPos = x % 8;
                int bytePos = x / 8;
                if (gray > 127)
                {
                    outputLine[bytePos] |= (byte)(0x80 >> bitPos);
                }
                else
                {
                    outputLine[bytePos] &= (byte)~(0x80 >> bitPos);
                }
            }

            Marshal.Copy(outputLine, 0, outputScan, outputStride);
            inputScan += inputStride;
            outputScan += outputStride;
        }
    }
    finally
    {
        input.UnlockBits(inputData);
        output.UnlockBits(outputData);
    }

    // 设置打印机兼容的DPI(例如300DPI)
    output.SetResolution(300, 300);
    return output;
}

内容的提问来源于stack exchange,提问作者Wenbin Geng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 20:17:04