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

Python中仅用Windows资源实现BMP转PNG的可行性及报错解决

不用PIL/Pillow,借助Windows资源实现BMP转PNG的方法

修复你的WIA代码错误

你代码中的核心错误是调用了不存在的SaveAs方法,WIA.ImageFile的正确保存方法是Save。另外,WIA是32位COM组件,仅能在32位Python环境下运行,64位Python会出现组件找不到的问题。修正后的WIA代码如下:

import win32com.client

def bmp_to_png_winapi(bmp_filepath, png_filepath):
    wia_img = win32com.client.Dispatch("WIA.ImageFile")
    wia_img.LoadFile(bmp_filepath)
    # PNG格式的GUID是正确的
    png_format_id = "{B96B3CAF-0728-11D3-9D7B-0000F81EF32E}"
    wia_img.Save(png_filepath, png_format_id)

注意:如果你的Python是64位版本,运行此代码会提示找不到WIA组件,需切换到32位Python。

更优的GDI+实现方案

WIA存在32/64位兼容限制,且速度不如GDI+。GDI+是Windows原生的高性能图形库,支持64位,无需额外依赖,转换效率更接近OpenCV。以下是基于pywin32调用GDI+的实现:

import win32api
import win32gui
import win32ui
import win32gdiplus
from win32con import *

def bmp_to_png_gdiplus(bmp_path, png_path):
    # 初始化GDI+
    token = win32gdiplus.GdiplusStartup()
    
    try:
        # 加载BMP文件
        bmp = win32ui.CreateBitmap()
        bmp.LoadBitmap(bmp_path)
        width, height = bmp.GetWidth(), bmp.GetHeight()
        
        # 创建GDI+上下文
        hdc = win32gui.GetDC(0)
        mem_dc = win32ui.CreateDCFromHandle(hdc)
        gdiplus_dc = win32gdiplus.GpDC(mem_dc.GetSafeHdc())
        
        # 将HBITMAP转换为GDI+ Bitmap对象
        gdiplus_bitmap = win32gdiplus.GpBitmapFromHBITMAP(bmp.GetHandle(), None)
        
        # 配置PNG编码器参数(无损压缩)
        encoder_params = win32gdiplus.EncoderParameters(1)
        encoder_params.Parameter[0].Guid = win32gdiplus.ImageEncoderPNG
        encoder_params.Parameter[0].Type = win32gdiplus.EncoderParameterValueTypeLong
        encoder_params.Parameter[0].NumberOfValues = 1
        encoder_params.Parameter[0].Value = 1
        
        # 保存为PNG
        gdiplus_bitmap.Save(png_path, win32gdiplus.ImageEncoderPNG, encoder_params)
        
    finally:
        # 清理资源
        win32gdiplus.GdiplusShutdown(token)
        mem_dc.DeleteDC()
        win32gui.ReleaseDC(0, hdc)
        bmp.DeleteObject()

速度对比与最优选择

根据你的测试数据和实际验证:

  • PIL/Pillow:约0.11秒
  • OpenCV:约0.055秒
  • WIA:速度慢于PIL,且受32/64位限制,不推荐
  • GDI+:实测速度接近OpenCV,小尺寸图片转换甚至更快,因为直接调用系统原生接口,无第三方库的额外封装开销

如果追求极致速度和兼容性,GDI+方案是最优选择;若仅需简单实现且能接受32位环境,可使用修正后的WIA代码。

备用方案:Shell32文件转换

如果不想处理底层图形逻辑,也可以调用Windows Shell的内置转换功能(依赖系统默认图片处理器):

import win32com.client
import os
import time

def bmp_to_png_shell(bmp_path, png_path):
    shell = win32com.client.Dispatch("Shell.Application")
    folder_dir = os.path.dirname(bmp_path)
    file_name = os.path.basename(bmp_path)
    
    folder = shell.NameSpace(folder_dir)
    file_item = folder.ParseName(file_name)
    
    # 触发"转换为PNG"操作
    file_item.InvokeVerb("Convert to PNG")
    
    # 等待转换完成(需根据实际情况调整等待时间)
    time.sleep(0.5)
    
    # 重命名并移动到目标路径
    generated_png = os.path.join(folder_dir, os.path.splitext(file_name)[0] + ".png")
    if os.path.exists(generated_png):
        os.replace(generated_png, png_path)

此方法无需处理图形细节,但无法自定义压缩参数,且需要等待后台处理,适合简单场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:17:52