Python案例如何用Pillow制作缩略图

wen python案例 2

本文目录导读:

Python案例如何用Pillow制作缩略图

  1. 基础安装
  2. 最简单的缩略图制作
  3. 固定尺寸裁剪缩略图
  4. 批量处理缩略图
  5. 添加水印的缩略图
  6. 命令行工具版本
  7. 高级功能:自适应正方形缩略图
  8. 使用建议

我来详细讲解如何使用Pillow库制作缩略图,包含多个实用案例。

基础安装

pip install Pillow

最简单的缩略图制作

from PIL import Image
def create_thumbnail(input_path, output_path, size=(150, 150)):
    """
    制作缩略图
    :param input_path: 输入图片路径
    :param output_path: 输出图片路径
    :param size: 缩略图大小 (宽, 高)
    """
    # 打开图片
    image = Image.open(input_path)
    # 使用thumbnail方法(保持原比例)
    image.thumbnail(size, Image.Resampling.LANCZOS)
    # 保存缩略图
    image.save(output_path, "JPEG", quality=85)
    print(f"缩略图已保存至: {output_path}")
# 使用示例
create_thumbnail("input.jpg", "thumbnail.jpg")

固定尺寸裁剪缩略图

from PIL import Image
def create_fixed_thumbnail(input_path, output_path, size=(200, 200)):
    """
    创建固定尺寸的缩略图,超出部分裁剪
    """
    image = Image.open(input_path)
    # 计算裁剪区域
    image_ratio = image.width / image.height
    target_ratio = size[0] / size[1]
    if image_ratio > target_ratio:
        # 图片太宽,裁剪左右
        new_width = int(image.height * target_ratio)
        left = (image.width - new_width) // 2
        box = (left, 0, left + new_width, image.height)
    else:
        # 图片太高,裁剪上下
        new_height = int(image.width / target_ratio)
        top = (image.height - new_height) // 2
        box = (0, top, image.width, top + new_height)
    # 裁剪并调整大小
    image = image.crop(box)
    image.thumbnail(size, Image.Resampling.LANCZOS)
    # 保存
    image.save(output_path, "JPEG", quality=95)
    print(f"固定尺寸缩略图已保存: {output_path}")
# 使用示例
create_fixed_thumbnail("input.jpg", "fixed_thumb.jpg")

批量处理缩略图

import os
from PIL import Image
from pathlib import Path
def batch_create_thumbnails(input_dir, output_dir, size=(150, 150), suffix="_thumb"):
    """
    批量处理文件夹中的所有图片
    """
    # 创建输出目录
    Path(output_dir).mkdir(parents=True, exist_ok=True)
    # 支持的图片格式
    supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.webp']
    processed_count = 0
    for filename in os.listdir(input_dir):
        file_ext = os.path.splitext(filename)[1].lower()
        if file_ext in supported_formats:
            # 构建路径
            input_path = os.path.join(input_dir, filename)
            output_filename = f"{os.path.splitext(filename)[0]}{suffix}{file_ext}"
            output_path = os.path.join(output_dir, output_filename)
            try:
                # 处理图片
                with Image.open(input_path) as img:
                    img.thumbnail(size, Image.Resampling.LANCZOS)
                    # 根据原格式保存
                    if file_ext in ['.jpg', '.jpeg']:
                        img.save(output_path, "JPEG", quality=85)
                    elif file_ext == '.png':
                        img.save(output_path, "PNG")
                    elif file_ext == '.gif':
                        img.save(output_path, "GIF")
                    else:
                        img.save(output_path)
                    processed_count += 1
                    print(f"处理完成: {filename} -> {output_filename}")
            except Exception as e:
                print(f"处理 {filename} 时出错: {e}")
    print(f"\n批量处理完成! 共处理 {processed_count} 张图片")
# 使用示例
batch_create_thumbnails("original_images", "thumbnails", size=(200, 200))

添加水印的缩略图

from PIL import Image, ImageDraw, ImageFont
def create_thumb_with_watermark(input_path, output_path, size=(200, 200), 
                                watermark_text="预览", font_size=20):
    """
    创建带水印的缩略图
    """
    image = Image.open(input_path)
    # 创建缩略图
    image.thumbnail(size, Image.Resampling.LANCZOS)
    # 创建水印
    watermark = Image.new('RGBA', image.size, (0, 0, 0, 0))
    draw = ImageDraw.Draw(watermark)
    # 设置字体
    try:
        font = ImageFont.truetype("arial.ttf", font_size)
    except:
        font = ImageFont.load_default()
    # 计算水印位置(居中)
    text_bbox = draw.textbbox((0, 0), watermark_text, font=font)
    text_width = text_bbox[2] - text_bbox[0]
    text_height = text_bbox[3] - text_bbox[1]
    x = (image.width - text_width) // 2
    y = (image.height - text_height) // 2
    # 绘制半透明水印
    draw.text((x, y), watermark_text, fill=(255, 255, 255, 128), font=font)
    # 合并图片
    result = Image.alpha_composite(image.convert('RGBA'), watermark)
    # 保存
    result = result.convert('RGB')
    result.save(output_path, "JPEG", quality=85)
    print(f"带水印缩略图已保存: {output_path}")
# 使用示例
create_thumb_with_watermark("input.jpg", "watermarked_thumb.jpg")

命令行工具版本

import argparse
from PIL import Image
import sys
def main():
    parser = argparse.ArgumentParser(description='图片缩略图制作工具')
    parser.add_argument('input', help='输入图片路径')
    parser.add_argument('-o', '--output', default='thumbnail.jpg', 
                       help='输出图片路径 (默认: thumbnail.jpg)')
    parser.add_argument('-s', '--size', type=int, nargs=2, 
                       default=[200, 200], metavar=('WIDTH', 'HEIGHT'),
                       help='缩略图尺寸 (默认: 200 200)')
    parser.add_argument('-q', '--quality', type=int, default=85,
                       help='图片质量 1-100 (默认: 85)')
    parser.add_argument('-k', '--keep-ratio', action='store_true',
                       help='保持原始比例')
    args = parser.parse_args()
    try:
        with Image.open(args.input) as img:
            if args.keep_ratio:
                img.thumbnail(tuple(args.size), Image.Resampling.LANCZOS)
            else:
                img = img.resize(tuple(args.size), Image.Resampling.LANCZOS)
            img.save(args.output, "JPEG", quality=args.quality)
            print(f"缩略图已保存至: {args.output}")
    except FileNotFoundError:
        print(f"错误: 找不到文件 {args.input}")
        sys.exit(1)
    except Exception as e:
        print(f"错误: {e}")
        sys.exit(1)
if __name__ == "__main__":
    main()

高级功能:自适应正方形缩略图

from PIL import Image
import math
def create_smart_square_thumb(input_path, output_path, size=200):
    """
    智能裁剪为正方形缩略图,保留最重要的内容
    """
    image = Image.open(input_path)
    # 计算裁剪区域(基于边缘检测的中心裁剪)
    width, height = image.size
    if width > height:
        # 横图:裁剪中间部分
        left = (width - height) // 2
        top = 0
        right = left + height
        bottom = height
    else:
        # 竖图:裁剪中间部分
        left = 0
        top = (height - width) // 2
        right = width
        bottom = top + width
    # 裁剪为正方形
    square_img = image.crop((left, top, right, bottom))
    # 调整为指定大小
    result = square_img.resize((size, size), Image.Resampling.LANCZOS)
    # 保存
    result.save(output_path, "JPEG", quality=95)
    print(f"智能缩略图已保存: {output_path}")
# 使用示例
create_smart_square_thumb("input.jpg", "smart_thumb.jpg")

使用建议

  1. quality参数:JPG格式推荐85-95之间,平衡文件大小和画质
  2. Resampling.LANCZOS:高质量的缩放算法,适合缩略图
  3. 内存管理:处理大图片时使用with语句自动释放资源
  4. 格式选择:透明背景用PNG,照片用JPG,动图用GIF
  5. 批量处理:注意处理异常,避免一个文件出错中断全部

这些案例涵盖了缩略图制作的常见场景,你可以根据实际需求选择合适的方案。

抱歉,评论功能暂时关闭!