脚本专家 发表于 2026-6-11 09:00:01

Python批量修改图片DPI:基于Pillow实现批量脚本与参数解读

学术投稿、期刊论文对图片DPI有严格要求,多数期刊要求300dpi甚至600dpi,而ArcGIS截图、屏幕截图默认仅为72或96dpi。手动逐张修改费时费力,PS动作批量处理也常卡顿。本文提供一个纯Python批量修改图片DPI的解决方案,基于Pillow库实现,支持JPG/PNG/TIFF等格式,并详解参数含义与踩坑点。

一、DPI与像素的关系
DPI(Dots Per Inch)是打印分辨率标识,修改DPI不会改变图片的像素尺寸,只影响打印时的物理尺寸(物理尺寸 = 像素尺寸 / DPI)。例如,一张3000×2400像素的图,设置为300dpi时打印尺寸为10×8英寸;若设为600dpi则打印尺寸缩小为5×4英寸,但像素不变。因此,仅修改DPI元数据不会改变文件体积,仅改变打印/出版属性。

二、核心实现:单图片DPI修改
Pillow的Image.save()方法直接支持dpi参数,几行代码即可完成:


from PIL import Image

with Image.open('input.jpg') as img:
    img.save('output.jpg', dpi=(600, 600), quality=95)


参数说明:
- dpi:元组(x, y),建议x和y相同。对于JPG,设置dpi即可写入EXIF元数据;PNG也支持dpi元数据(部分读取器可能忽略)。
- quality(仅JPG):1-100整数,推荐95,在文件大小和画质间平衡较好。
- subsampling=0:在JPG保存时禁用4:2:0色度子采样,可避免文字边缘模糊,适合插图。

三、批量处理脚本(带错误处理与格式过滤)
以下脚本遍历输入文件夹,自动跳过非图片文件,支持JPG/JPEG/PNG,批量修改DPI并保持原文件名输出到目标文件夹:


from PIL import Image
import os

INPUT_FOLDER = r".\input"   # 原图存放路径
OUTPUT_FOLDER = r".\output"   # 输出路径
TARGET_DPI = (600, 600)      # 目标DPI
os.makedirs(OUTPUT_FOLDER, exist_ok=True)

extensions = ('.png', '.jpg', '.jpeg')
count_ok = count_skip = 0

for filename in os.listdir(INPUT_FOLDER):
    filepath = os.path.join(INPUT_FOLDER, filename)
    if not os.path.isfile(filepath):
      continue
    ext = os.path.splitext(filename).lower()
    if ext not in extensions:
      count_skip += 1
      continue
    try:
      with Image.open(filepath) as img:
            params = {'dpi': TARGET_DPI}
            if ext in ('.jpg', '.jpeg'):
                params['quality'] = 95
                params['subsampling'] = 0
            img.save(os.path.join(OUTPUT_FOLDER, filename), **params)
            count_ok += 1
    except Exception as e:
      count_skip += 1
      print(f'处理失败: {filename} | {e}')

print(f'成功: {count_ok} 张,跳过: {count_skip} 个')


四、使用步骤
1. 安装Pillow:pip install Pillow
2. 在脚本同级目录新建input和output文件夹。
3. 将待处理图片放入input文件夹,运行脚本。
4. 处理后的图片出现在output文件夹,右键属性→详细信息可查看DPI变化。

五、常见踩坑与解决办法
1. JPG保存后变糊:未设置quality或过低,请显式设为95,并添加subsampling=0。
2. 文件扩展名大小写:.JPG等大写后缀,脚本中使用.lower()转换即可。
3. 图片被其他程序占用(如PS打开):关闭占用程序再运行。
4. TIFF格式支持:在extensions元组中添加('.tiff', '.tif'),Pillow可处理TIFF DPI元数据。

六、高级扩展:两种DPI修改模式
除了仅修改元数据,有时需要同时重采样像素以保持打印物理尺寸一致。以下区分两种模式并提供函数实现。

模式1:仅修改DPI元数据(不改变像素尺寸)
适用于已有像素足够大、只需更新打印标识的场景。注意:PNG保存时可能丢失dpi,可转为JPEG或TIFF。


def batch_set_dpi_metadata(input_dir, output_dir, target_dpi=300, extensions=('.jpg', '.jpeg', '.png', '.tiff', '.bmp')):
    import os
    from PIL import Image
    os.makedirs(output_dir, exist_ok=True)
    for fname in os.listdir(input_dir):
      if not fname.lower().endswith(extensions):
            continue
      src = os.path.join(input_dir, fname)
      dst = os.path.join(output_dir, fname)
      with Image.open(src) as img:
            if img.format == 'PNG' and dst.lower().endswith('.png'):
                dst = os.path.splitext(dst) + '.jpg'
                img = img.convert('RGB')
            img.save(dst, dpi=(target_dpi, target_dpi))


模式2:按目标DPI重采样图像(改变像素尺寸)
若原图像素过小,仅改DPI会导致打印物理尺寸过小,需按公式“新像素 = 原像素 × (目标DPI / 原始DPI)”进行缩放。此处使用LANCZOS高质量重采样。


def batch_resize_by_dpi(input_dir, output_dir, target_dpi=300):
    import os
    from PIL import Image
    os.makedirs(output_dir, exist_ok=True)
    for fname in os.listdir(input_dir):
      if not fname.lower().endswith(('.jpg', '.jpeg', '.png', '.tiff')):
            continue
      src = os.path.join(input_dir, fname)
      dst = os.path.join(output_dir, fname)
      with Image.open(src) as img:
            src_dpi = img.info.get('dpi', (72, 72))
            if src_dpi == target_dpi:
                img.save(dst)
                continue
            ratio = target_dpi / src_dpi
            new_size = (int(img.width * ratio), int(img.height * ratio))
            resized = img.resize(new_size, Image.Resampling.LANCZOS)
            resized.save(dst, dpi=(target_dpi, target_dpi))


七、终极方案:通过piexif直接修改JPEG的EXIF DPI标签
有些期刊要求精确写入EXIF中的XResolution/YResolution,使用piexif库可绕过Pillow的封装,更可靠。


import os, piexif
from PIL import Image

def batch_set_dpi_exif(input_dir, output_dir, target_dpi=300):
    os.makedirs(output_dir, exist_ok=True)
    for fname in os.listdir(input_dir):
      if not fname.lower().endswith(('.jpg', '.jpeg')):
            continue
      src = os.path.join(input_dir, fname)
      dst = os.path.join(output_dir, fname)
      img = Image.open(src)
      try:
            exif = piexif.load(img.info.get('exif', b''))
      except:
            exif = {'0th': {}, 'Exif': {}, 'GPS': {}, '1st': {}}
      exif['0th'] = (target_dpi, 1)
      exif['0th'] = (target_dpi, 1)
      exif['0th'] = 2
      exif_bytes = piexif.dump(exif)
      img.save(dst, exif=exif_bytes)


总结:本文提供的Python脚本可直接用于学术投稿前的DPI批量修改,核心在于Pillow的save方法。根据需求选择仅改元数据或重采样,JPEG注意quality和subsampling参数,PNG建议转JPEG以保留DPI信息。实测处理几百张图片仅需数秒,显著提升效率。

热心网友5 发表于 2026-6-11 09:10:00

Re: Python批量修改图片DPI:基于Pillow实现批量脚本与参数解读

感谢分享!这个批量脚本对需要处理学术论文配图的人太实用了。我之前手动用PS一张张改DPI,遇到几十张图真是崩溃。尤其你提到的 `subsampling=0` 和 `quality=95` 组合避免文字模糊,这个细节很关键,很多批量处理工具默认会压缩画质。 想请教一下:对于PNG图片改DPI后转成JPG保存,会不会因为色彩空间或透明通道造成意外?如果原图带透明背景(比如科研示意图),转JPG会丢失透明信息,有没有保留PNG格式但写入DPI元数据的更稳妥做法?

热心网友2 发表于 2026-6-21 09:00:01

Re: Python批量修改图片DPI:基于Pillow实现批量脚本与参数解读

非常实用的分享!平时投稿修图确实经常遇到DPI不达标的问题,之前我都是手动一张张用PS改,效率很低。你这个脚本思路很清晰,而且把两种模式(只改元数据和重采样)都讲明白了,尤其是 `subsampling=0` 这个参数,确实能有效避免文字边缘模糊,很多教程里都不会提到这个坑。另外,用 `lower()` 处理大小写和错误处理的 try-except 也很贴心,适合批量跑图时快速定位问题。准备收藏下来,下次处理论文配图直接用了,感谢!

热心网友3 发表于 2026-6-21 11:20:00

Re: Python批量修改图片DPI:基于Pillow实现批量脚本与参数解读

感谢分享,非常实用的方案。之前用PS动作批量处理,偶尔会卡在格式兼容上,这个纯Python脚本确实简洁高效。特别注意到你提到了 `subsampling=0` 防止文字模糊,这个细节很关键,很多批量工具都不处理。另外,脚本里对PNG转RGB再存JPG的兜底处理也很贴心。 刚试跑了一下,JPG和PNG的DPI都成功改成600了,只有一张TIF因为路径里带了中文编码报错,加个 `errors='ignore'` 应该就能解决。总之是好东西,收藏了!
页: [1]
查看完整版本: Python批量修改图片DPI:基于Pillow实现批量脚本与参数解读