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

如何将ImageMagick convert的-gravity与-extent转为Python/PIL实现

将ImageMagick的convert命令转换为PIL脚本:实现-gravity center和-extent 200x200功能

问题背景

我正在尝试将使用ImageMagick的convert命令的Shell脚本转换为Python/PIL脚本。

原Shell脚本如下:

convert \
    -resize 25% \
    +repage \
    -background white
    -quality 95 \
    -flatten \
    -gravity center \
    -extent 200x200 \
        img_a.png img_b.jpg

我已完成部分转换,代码如下:

# Paths
img_a_png_filepath = '/foo/bar/img_a.png'
img_a_name = Path(img_a_png_filepath).stem
img_b_name = f'{img_a_name}.jpg'
img_b_jpg_filepath = f'/foo/bar/{img_b_name}'
# Converting to JPEG    
img_a_png = Image.open(img_a_png_filepath)
# -background white
white_bg = Image.new('RGBA',img_a_png.size ,(255, 255, 255, 255))
white_bg.paste(img_a_png, (0, 0), img_a_png)
white_bg = white_bg.convert('RGB')
white_bg.save(img_b_name, 'JPEG')
# -resize 25%
img_b_jpg = Image.open(img_b_jpg_filepath)
img_b_jpg = img_b_jpg.resize((img_b_jpg.size[0]*0.25, img_b_jpg.size[0]*0.25))
img_b_jpg.save(img_b_name, 'JPEG')

我猜测原脚本通过-gravity center和-extent 200x200实现居中裁剪,但不知道如何在PIL中实现这两个参数的功能,请求帮助。


解决方案

首先明确:ImageMagick的-gravity center+-extent 200x200不是单纯裁剪,而是将缩放后的图像居中放置在200x200的白色画布上——如果缩放后图像尺寸小于200x200,就补白;如果大于,则居中裁剪到200x200。

另外你当前的代码有冗余(无需存成JPEG再重新打开),可以优化流程一步完成所有操作:

完整代码

from PIL import Image
from pathlib import Path

# 路径处理
img_a_png_filepath = '/foo/bar/img_a.png'
img_a_name = Path(img_a_png_filepath).stem
img_b_jpg_filepath = f'/foo/bar/{img_a_name}.jpg'

# 打开原图并处理
with Image.open(img_a_png_filepath) as img:
    # 1. 按25%缩放(用整数运算避免尺寸小数,LANCZOS滤镜保证缩放质量)
    width, height = img.size
    scaled_size = (int(width * 0.25), int(height * 0.25))
    scaled_img = img.resize(scaled_size, Image.Resampling.LANCZOS)

    # 2. 替换透明背景为白色(对应-flatten和-background white)
    if img.mode in ('RGBA', 'LA'):
        white_bg = Image.new('RGB', scaled_size, (255, 255, 255))
        white_bg.paste(scaled_img, mask=scaled_img.split()[-1])
        scaled_img = white_bg
    else:
        scaled_img = scaled_img.convert('RGB')

    # 3. 实现-gravity center + -extent 200x200
    target_w, target_h = 200, 200
    final_img = Image.new('RGB', (target_w, target_h), (255, 255, 255))

    if scaled_img.width > target_w or scaled_img.height > target_h:
        # 图像过大,居中裁剪到目标尺寸
        crop_left = (scaled_img.width - target_w) // 2
        crop_top = (scaled_img.height - target_h) // 2
        cropped_img = scaled_img.crop((crop_left, crop_top, crop_left + target_w, crop_top + target_h))
        final_img.paste(cropped_img, (0, 0))
    else:
        # 图像过小,计算居中偏移量后粘贴
        offset_x = (target_w - scaled_img.width) // 2
        offset_y = (target_h - scaled_img.height) // 2
        final_img.paste(scaled_img, (offset_x, offset_y))

    # 4. 保存为JPEG,对应-quality 95
    final_img.save(img_b_jpg_filepath, 'JPEG', quality=95)

关键步骤说明

  • 缩放处理:使用Image.Resampling.LANCZOS滤镜匹配ImageMagick默认的高质量缩放,同时用整数运算避免尺寸出现小数问题。
  • 背景替换:针对带透明通道的图像,通过paste的mask参数保留原图像的透明区域,实现-flatten的效果。
  • 居中+Extent逻辑:
    • 若缩放后图像大于200x200:计算居中裁剪坐标,裁剪后直接覆盖到目标画布。
    • 若缩放后图像小于200x200:计算中心偏移量,将图像粘贴到画布中心,周围自动补白。
  • 保存参数:save时指定quality=95,对应ImageMagick的-quality 95。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 11:01:01