深度解析

如何将 BMP 转换为 JPG、PNG 和 WebP:实用指南

koboshiCo-founder
·4 分钟阅读
如何将 BMP 转换为 JPG、PNG 和 WebP:实用指南
概述

BMP 易于读取却占空间巨大。本指南覆盖本地操作系统工具、命令行工作流以及五种语言的代码转换,帮你把 BMP 高效转成 JPG、PNG 或 WebP。

一张 1920 × 1080 的 24 位 BMP 接近 6 MB。同一张图以质量 90 保存为 JPEG,通常不到 500 KB。二者相差近十倍,这正是 BMP 仍出没于老式扫描仪、医疗软件和 Windows 内部组件,却通常需要转换后才能派上用场的原因。

BMP 的核心优势就是简单。要做好转换,需要知道这种简单性什么时候是优势,什么时候是短板,以及哪种目标格式才真正适合当前任务。

BMP 为什么还在

BMP 用极小的头部开销存储像素。没有霍夫曼表、没有 DEFLATE 状态机、没有色度子采样。对于嵌入式系统、遗留 Windows 工具,以及"读取头部、复制字节"即可搞定的场景,这种简单性确实是优势。

把它挤出日常使用的也是同样的缺点:

  • 没有有效压缩。 未压缩 BMP 体积巨大。RLE 变体存在,但很少能赢过现代编解码器。
  • 没有可靠的 Alpha 通道。 32 位 BMP 的 Alpha 字节在不同工具间支持不一致。
  • 自底向上的行序。 大多数 BMP 从图像底部向上存储行,这对期望自上而下数据的处理流程会增加一个小转换步骤。
  • 没有元数据生态。 经典头部不支持 EXIF、ICC 配置文件,也没有动画。

用于归档或兼容性,BMP 没问题。用于网页、邮件、移动端或追求存储效率的场景,它就得换成别的格式。

选择正确的输出格式

在运行命令或写代码之前,先确定你最看重什么。

目标格式适用场景取舍
JPG照片、预览、任何屏幕展示有损,但文件极小
PNG图形、截图、需要透明度的内容无损,照片比 JPG 大
WebP现代网页、应用、任何在意带宽的场景比 JPG/PNG 更小,浏览器支持广泛

如果你要转换一份带文字和图表的扫描文档,PNG 能保持边缘锐利。如果转换来自旧设备的照片,JPG 或 WebP 更合适。用于网页分发,WebP 通常在体积上胜出。

我们的浏览器端 BMP 转 JPGBMP 转 PNGBMP 转 WebP 转换器可以本地处理这三种情况——文件不会离开你的设备。

在 Windows 上转换

画图

  1. 用画图打开 BMP。
  2. 选择文件 > 另存为
  3. 选择 JPEG 图片PNG 图片WebP 图像
  4. 保存。

画图只能应付单张图片。没有质量调节,也支持不了批量处理,所以不适合整个文件夹。

PowerShell(ImageMagick)

从官网安装 ImageMagick 后:

magick input.bmp output.jpg
magick input.bmp output.png
magick input.bmp output.webp

批量转换某个文件夹:

Get-ChildItem *.bmp | ForEach-Object {
    magick $_.FullName ($_.BaseName + ".jpg")
}

不借助外部工具的 PowerShell

Windows 10 和 11 内置 .NET 图像栈。这种方式支持 BMP 转 JPG 和 PNG,但 WebP 需要额外库:

Add-Type -AssemblyName System.Drawing
$img = [System.Drawing.Image]::FromFile("input.bmp")
$img.Save("output.jpg", [System.Drawing.Imaging.ImageFormat]::Jpeg)
$img.Dispose()

在 macOS 上转换

预览

  1. 用预览打开 BMP。
  2. 选择文件 > 导出
  3. 从格式下拉框中选择目标格式。
  4. 如需输出 JPEG,可调整质量。

预览快速且私密,但和画图一样只能单文件处理。

终端使用 sips

sips 内置于 macOS,支持 BMP、JPEG、PNG 和 TIFF:

sips -s format jpeg input.bmp --out output.jpg
sips -s format png input.bmp --out output.png

WebP 需要 ImageMagick 或 Homebrew 的 webp 包提供的 cwebp

brew install webp

# cwebp 不能直接读取 BMP,先转成 PNG
sips -s format png input.bmp --out temp.png
cwebp temp.png -o output.webp
rm temp.png

批量 shell 循环

for f in *.bmp; do
    sips -s format jpeg "$f" --out "${f%.bmp}.jpg"
done

在 Linux 上转换

ImageMagick

sudo apt install imagemagick

magick input.bmp output.jpg
magick input.bmp output.png
magick input.bmp output.webp

调整 JPEG 质量:

magick input.bmp -quality 90 output.jpg

批量转换

for f in *.bmp; do
    magick "$f" "${f%.bmp}.jpg"
done

如果你只需要最小的 WebP 输出,直接用 cwebp

for f in *.bmp; do
    cwebp -q 85 "$f" -o "${f%.bmp}.webp"
done

用代码转换

如果你需要在应用、流水线或后端服务里转换图片,直接调用库通常比调用 ImageMagick 命令更简洁。

TypeScript / Node.js

使用 sharp。它支持 BMP 输入,并可输出 JPG、PNG 和 WebP。

import sharp from "sharp"

async function convertBmp(
  input: string,
  output: string,
  format: "jpg" | "png" | "webp"
) {
  await sharp(input)
    .toFormat(format, format === "jpg" ? { quality: 90 } : undefined)
    .toFile(output)
}

await convertBmp("input.bmp", "output.jpg", "jpg")
await convertBmp("input.bmp", "output.png", "png")
await convertBmp("input.bmp", "output.webp", "webp")

在浏览器里无法运行 sharp,我们的 BMP 转 WebP 转换器使用 WebAssembly 在客户端完成解码和编码。

PHP

如果启用了 GD 扩展,PHP 内置了图像函数。

<?php

function bmpToJpg(string $input, string $output, int $quality = 90): void {
    $image = imagecreatefrombmp($input);
    imagejpeg($image, $output, $quality);
    imagedestroy($image);
}

function bmpToPng(string $input, string $output): void {
    $image = imagecreatefrombmp($input);
    imagepng($image, $output);
    imagedestroy($image);
}

function bmpToWebp(string $input, string $output, int $quality = 90): void {
    $image = imagecreatefrombmp($input);
    imagewebp($image, $output, $quality);
    imagedestroy($image);
}

bmpToJpg("input.bmp", "output.jpg");
bmpToPng("input.bmp", "output.png");
bmpToWebp("input.bmp", "output.webp");

Go

Go 标准库本身不读 BMP,但 golang.org/x/image/bmp 包可以。输出使用 image/jpegimage/pnggolang.org/x/image/webp

package main

import (
	"image/jpeg"
	"image/png"
	"os"

	"golang.org/x/image/bmp"
	"golang.org/x/image/webp"
)

func bmpToJpg(input, output string, quality int) error {
	f, err := os.Open(input)
	if err != nil {
		return err
	}
	defer f.Close()

	img, err := bmp.Decode(f)
	if err != nil {
		return err
	}

	out, err := os.Create(output)
	if err != nil {
		return err
	}
	defer out.Close()

	return jpeg.Encode(out, img, &jpeg.Options{Quality: quality})
}

PNG 和 WebP 用同样的模式,分别调用 png.Encodewebp.Encode

Java

Java 的 ImageIO 原生支持读取 BMP。输出 WebP 需要额外库,例如 webp-imageiocwebp 绑定。

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class BmpConverter {
    public static void bmpToJpg(String input, String output, float quality) throws IOException {
        BufferedImage image = ImageIO.read(new File(input));
        File out = new File(output);
        ImageIO.write(image, "jpg", out);
    }

    public static void bmpToPng(String input, String output) throws IOException {
        BufferedImage image = ImageIO.read(new File(input));
        File out = new File(output);
        ImageIO.write(image, "png", out);
    }
}

如需更精细地控制 JPEG 质量,使用 JPEGImageWriteParam API。

Python

配合 Pillow,Python 是转换 BMP 最省事的选择。

from PIL import Image

with Image.open("input.bmp") as img:
    img.convert("RGB").save("output.jpg", quality=90)

with Image.open("input.bmp") as img:
    img.save("output.png")

with Image.open("input.bmp") as img:
    img.save("output.webp", quality=90)

如果需要保留透明度输出为 PNG,不要强制转 RGB:

with Image.open("input.bmp") as img:
    img.save("output.png")

常见陷阱

  • 索引色 BMP。 8 位或更低位的 BMP 使用调色板。如果没有显式转换,某些解码器返回的是调色板索引而非 RGB 值。在 Pillow 中,保存为 JPEG 或 WebP 前用 img.convert("RGB") 可解决。
  • 自底向上方向。 大多数库会自动处理,但如果你手写 BMP 解码器,要记住正高度字段表示行自下而上存储。
  • JPEG 默认质量。 许多工具默认 75–80。用于全屏观看的照片,90 更安全;用于缩略图,70–80 足够。
  • WebP 兼容性。 WebP 浏览器支持很好,但在某些旧版桌面图片查看器中仍可能无法打开。如果目标是 Windows 原生应用,PNG 或 JPG 更安全。

不同场景该用什么

  • 遗留归档: 保留原始 BMP。存储便宜,丢失原始版本不划算。
  • 网页上传: 转换为 WebP。如果需要兜底格式,再保留一份 JPG。
  • 印刷或编辑工作流: PNG 保持无损,避免压缩伪影。
  • 邮件和即时通讯: JPG 是最安全的通用格式。

如果你想快速转换,又懒得安装软件、敲命令或上传文件,可以直接用我们的 BMP 转 JPGBMP 转 PNGBMP 转 WebP 转换器。所有处理都在浏览器内完成,文件自始至终留在你的机器上。

更多推荐阅读