
系列:图像处理算法入门
期数:第004期 / 共144期
日期:2026-08-13
关键词:图像格式、JPEG、PNG、TIFF、BMP、有损压缩、无损压缩、EXIF、文件大小
难度:⭐⭐☆☆☆(需少量OpenCV/Pillow基础)
一、前言
上期我们理解了"图像是矩阵"这一核心认知。但同一张图像存成不同文件,大小、质量、用途却千差万别。本文将系统拆解图像处理中最常见的 JPEG、PNG、TIFF、BMP 四种格式:它们各自如何编码?什么时候该用谁?有损与无损的本质区别是什么?文末提供完整可运行的代码实验,用实测数据回答这些问题。
二、四种格式核心特性速查
| 格式 | 压缩方式 | 是否支持透明 | 典型文件大小 | 最佳适用场景 | 主要缺点 |
|---|---|---|---|---|---|
| BMP | 通常无压缩 | 否 | 很大 | Windows 原生位图、嵌入式系统 | 无压缩导致体积大,网络传输不友好 |
| PNG | 无损压缩(DEFLATE) | 是 | 中等 | 截图、图标、线条图、需要透明的图像 | 不适合照片,文件通常比 JPEG 大 |
| JPEG | 有损压缩(DCT) | 否 | 很小 | 照片、自然图像、网页展示 | 有损压缩会产生块效应,不适合反复编辑 |
| TIFF | 灵活(无损/有损/未压缩) | 是 | 大 | 印刷、医学影像、科研、多页文档 | 兼容性和体积问题,不适合网页 |
一句话记忆:照片选 JPEG,截图/图标选 PNG,印刷/科研选 TIFF,原生/兼容选 BMP。
三、有损压缩 vs 无损压缩
3.1 无损压缩
无损压缩的核心特征是:解压后的数据与原始数据完全一致,没有任何信息损失。
- 原理:利用数据的统计冗余进行编码(如行程编码、霍夫曼编码、LZW、DEFLATE)。
- 优点:可反复保存编辑而不损失质量。
- 代表格式:PNG、TIFF(无损模式)、GIF、BMP(未压缩时)。
3.2 有损压缩
有损压缩通过丢弃人眼不敏感的信息来换取更小的文件体积。
- 原理:通常基于变换编码(如 JPEG 的 DCT 离散余弦变换)+ 量化 + 熵编码。
- 优点:文件体积极小,适合网络传输和存储。
- 缺点:每次重新保存都会损失质量,不适合反复编辑;在硬边、文字、线条上容易产生块效应(Blocking Artifacts)。
- 代表格式:JPEG、WebP(有损模式)、HEIC。
3.3 关键认知:压缩≠质量差
JPEG 的"有损"是可控的。质量参数(Quality)越高,丢弃的信息越少,文件越大。高质量 JPEG(Q=95+)在日常视觉上几乎与无损无异,但体积远小于 PNG。
四、JPEG 压缩原理简述
JPEG 的压缩流程是理解有损压缩的经典案例:
原始 RGB 图像
↓ 颜色空间转换:RGB → YCbCr
↓ 色度下采样(4:2:0 或 4:2:2)
↓ 分块:8×8 像素块
↓ 离散余弦变换(DCT):空域 → 频域
↓ 量化:高频信息粗量化,低频信息细量化
↓ 熵编码(Huffman / Arithmetic)
↓ 压缩后的 JPEG 文件
为什么 JPEG 适合照片? 照片通常具有丰富的细节和渐变,高频信息对人眼不重要,量化后损失不易察觉。而截图、文字、图标含有大量硬边和纯色块,JPEG 会在边缘处产生明显的马赛克块效应。
五、PNG 压缩原理简述
PNG 使用 DEFLATE 算法(LZ77 + 霍夫曼编码)进行无损压缩:
原始图像
↓ 滤波(Filter):预测每个像素的值,生成残差
↓ DEFLATE 压缩残差数据
↓ 压缩后的 PNG 文件
PNG 支持 Alpha 通道透明,是网页图标、Logo、UI 切图的首选。但对于照片类图像,PNG 的压缩率通常不如 JPEG,文件会明显更大。
六、代码实践
实验一:同一图像存为不同格式,对比文件大小
import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 创建测试图像(包含渐变、几何图形、文字、细线)
def create_test_image(size=(512, 512)):
h, w = size
img = np.zeros((h, w, 3), dtype=np.uint8)
y, x = np.ogrid[:h, :w]
img[:, :, 0] = (255 * x / w).astype(np.uint8)
img[:, :, 1] = (255 * y / h).astype(np.uint8)
img[:, :, 2] = (255 * (1 - x / w)).astype(np.uint8)
cv2.circle(img, (w // 4, h // 4), 60, (255, 255, 255), -1)
cv2.circle(img, (w // 4, h // 4), 60, (0, 0, 0), 3)
cv2.rectangle(img, (w * 3 // 4 - 50, h // 4 - 50),
(w * 3 // 4 + 50, h // 4 + 50), (255, 255, 0), -1)
cv2.putText(img, "FORMAT TEST", (w // 8, h * 3 // 4),
cv2.FONT_HERSHEY_SIMPLEX, 1.2, (255, 255, 255), 3)
for i in range(0, h, 16):
cv2.line(img, (0, i), (w // 4, i), (255, 255, 255), 1)
return img
img = create_test_image()
format_configs = [
("BMP", "test.bmp", []),
("PNG", "test.png", [cv2.IMWRITE_PNG_COMPRESSION, 6]),
("TIFF", "test.tiff", []),
("JPEG-95", "test_95.jpg", [cv2.IMWRITE_JPEG_QUALITY, 95]),
("JPEG-85", "test_85.jpg", [cv2.IMWRITE_JPEG_QUALITY, 85]),
("JPEG-50", "test_50.jpg", [cv2.IMWRITE_JPEG_QUALITY, 50]),
]
results = []
for name, filename, params in format_configs:
path = f"code/output/004_format_files/{filename}"
cv2.imwrite(path, img, params)
size_kb = os.path.getsize(path) / 1024
results.append((name, size_kb))
print(f"{name:12s}: {size_kb:8.2f} KB")
实测结果(512×512 测试图):
| 格式 | 文件大小 |
|---|---|
| BMP | 768.05 KB |
| PNG | 13.70 KB |
| TIFF | 53.65 KB |
| JPEG Q=95 | 47.71 KB |
| JPEG Q=85 | 28.77 KB |
| JPEG Q=50 | 16.56 KB |
观察:BMP 因为无压缩体积最大;PNG 无损压缩效果极好;JPEG 通过质量参数可以灵活控制体积。
实验二:JPEG 质量参数对图像质量的影响
img = create_test_image()
qualities = [10, 30, 50, 70, 85, 95, 100]
for q in qualities:
path = f"code/output/004_format_files/jpeg_q{q}.jpg"
cv2.imwrite(path, img, [cv2.IMWRITE_JPEG_QUALITY, q])
size_kb = os.path.getsize(path) / 1024
compressed = cv2.imread(path)
mse = np.mean((img.astype(np.float32) - compressed.astype(np.float32)) ** 2)
print(f"Quality={q:3d}: {size_kb:7.2f} KB, MSE={mse:8.2f}")
实测数据:
| Quality | 文件大小 (KB) | MSE |
|---|---|---|
| 10 | 8.58 | 195.28 |
| 30 | 13.25 | 117.95 |
| 50 | 16.56 | 98.39 |
| 70 | 22.55 | 78.51 |
| 85 | 28.77 | 68.67 |
| 95 | 47.71 | 64.26 |
| 100 | 90.94 | 63.58 |
结论:Quality 从 10 提升到 85 时,文件大小和质量都有显著改善;但 95→100 的体积增长接近一倍,质量提升却非常有限。日常照片推荐使用 Q=80~95。
实验三:有损 vs 无损的视觉差异
img = create_test_image()
cv2.imwrite("code/output/004_format_files/lossless.png", img)
cv2.imwrite("code/output/004_format_files/lossy_30.jpg", img,
[cv2.IMWRITE_JPEG_QUALITY, 30])
img_png = cv2.imread("code/output/004_format_files/lossless.png")
img_jpg = cv2.imread("code/output/004_format_files/lossy_30.jpg")
diff = np.abs(img.astype(np.float32) - img_jpg.astype(np.float32)).astype(np.uint8)
关键观察:
- 整体视觉:Q=30 的 JPEG 仍能辨识内容,但色彩过渡出现分块。
- 局部放大:文字边缘和细线条处出现明显的 8×8 块效应。
- 误差图:差异主要集中在高频细节区域(边缘、文字、细线)。
实验四:用 Pillow 读取图像元数据(EXIF)
from PIL import Image
img = Image.open("code/output/004_format_files/test_exif.jpg")
print(f"尺寸: {img.size}")
print(f"格式: {img.format}")
print(f"模式: {img.mode}")
exif = img._getexif() or {}
for tag_id, value in exif.items():
print(f"Tag {tag_id}: {value}")
输出示例:
尺寸: (512, 512)
格式: JPEG
模式: RGB
文件大小: 33.22 KB
(本文件未包含额外 EXIF 元数据)
EXIF 是什么? Exchangeable Image File Format,记录拍摄参数(时间、相机型号、光圈、ISO、GPS 位置等)。手机/相机拍摄的照片通常包含丰富的 EXIF 信息,是图像处理中重要的元数据来源。
七、常见问题与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 网页图片加载慢 | 图片格式选择不当或质量过高 | 照片用 JPEG Q=80~85,图标/截图用 PNG,必要时用 WebP |
| JPEG 反复保存后变模糊 | 每次保存都进行有损压缩 | 编辑过程中使用 PNG/TIFF/PSD 等无损格式,最终输出再用 JPEG |
| PNG 照片文件太大 | PNG 对照片压缩率低 | 照片优先使用 JPEG 或 WebP |
| 需要透明背景 | JPEG/BMP 不支持 Alpha 通道 | 使用 PNG 或 TIFF |
| 读取图像后颜色偏蓝 | OpenCV 默认 BGR 顺序 | 用 cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 转换 |
| 需要打印输出 | 屏幕显示与印刷色彩空间不同 | 使用 TIFF + CMYK 或至少 300 DPI 的 PNG/JPEG |
八、相关产品推荐
移动端 App
| 产品 | 平台 | 与本期内容的关联 | 适合场景 |
|---|---|---|---|
| VSCO | iOS / Android | 导出时可选 JPEG 质量,支持 PNG 保存 | 移动端照片编辑与导出 |
| Snapseed | iOS / Android | 保存时可查看文件格式与压缩选项 | 日常照片精修 |
| 扫描全能王 | iOS / Android | 文档扫描后可选 JPEG/PDF,自动优化压缩比 | 文档数字化 |
专业级工具
| 产品 | 平台 | 与本期内容的关联 | 适合场景 |
|---|---|---|---|
| Adobe Photoshop | Win / macOS | 支持 8/16bit、多种格式导出、Alpha 通道、图层 | 专业图像编辑 |
| Capture One | Win / macOS | RAW 处理后可导出 TIFF/JPEG,精细控制质量 | 商业摄影后期 |
| ImageMagick | 跨平台 / 命令行 | 批量格式转换、质量调整、元数据处理 | 批量图像处理 |
| XnConvert | 跨平台 | 可视化批量格式转换,支持 500+ 格式 | 格式批量转换 |
九、扩展练习
- 格式转换实验:找一张 1920×1080 的真实照片,分别保存为 BMP、PNG、JPEG Q=70/85/95,记录文件大小并计算压缩比。
- 重复保存测试:将一张 JPEG 图片反复打开并保存 10 次(每次 Q=85),观察图像质量变化并计算每次保存后的 MSE。
- 透明度实验:创建一张带有透明通道的 RGBA 图像,分别保存为 PNG 和 BMP/TIFF,比较文件大小和透明度保留情况。
十、知识总结
| 概念 | 核心要点 | 一句话记忆 |
|---|---|---|
| BMP | 无压缩位图,文件大 | 简单直接但笨重 |
| PNG | 无损压缩,支持透明 | 截图图标首选 |
| JPEG | 有损压缩,质量可调 | 照片网络首选 |
| TIFF | 灵活格式,无损/多页/浮点 | 科研印刷首选 |
| 有损压缩 | 丢弃信息换体积 | 不可逆,质量参数决定损失 |
| 无损压缩 | 完全保留信息 | 可反复编辑 |
| EXIF | 图像元数据标准 | 记录拍摄参数的"身份证" |
十一、下节预告
第005期:颜色空间入门:RGB/HSV/CMYK/Lab,将深入理解图像颜色空间,掌握各空间的转换原理与应用场景,并用代码实现 RGB 与 HSV 的互转。
本期核心结论:图像格式的选择是"质量-体积-功能"的权衡。照片选 JPEG,截图/透明选 PNG,科研印刷选 TIFF,原生兼容选 BMP。理解有损与无损的本质,是后续图像存储、传输、处理决策的基础。
觉得有用的话,点赞收藏不迷路,我们下期见!

451

被折叠的 条评论
为什么被折叠?



