Python案例如何用Pillow转换色彩模式

wen python案例 2

本文目录导读:

Python案例如何用Pillow转换色彩模式

  1. 基础色彩模式转换
  2. 完整的转换案例
  3. 批量转换工具
  4. 特殊转换处理
  5. 模式转换实用工具
  6. 实用函数集合
  7. 常用模式转换说明

我来为您介绍使用Pillow库转换色彩模式的完整案例。

基础色彩模式转换

from PIL import Image
import os
# 打开图片
img = Image.open('example.jpg')
# 打印当前模式
print(f"原始模式: {img.mode}")
# 转换为不同色彩模式
img_rgb = img.convert('RGB')
img_rgba = img.convert('RGBA')
img_gray = img.convert('L')  # 灰度图
img_cmyk = img.convert('CMYK')
img_hsv = img.convert('HSV')
# 保存转换后的图片
img_rgb.save('output_rgb.jpg')
img_gray.save('output_gray.jpg')

完整的转换案例

from PIL import Image
import numpy as np
def convert_color_mode(input_path, output_path, target_mode='L'):
    """
    转换图片色彩模式
    参数:
        input_path: 输入图片路径
        output_path: 输出图片路径
        target_mode: 目标模式 (L, RGB, RGBA, CMYK, HSV)
    """
    try:
        # 打开图片
        img = Image.open(input_path)
        print(f"原图信息:")
        print(f"  模式: {img.mode}")
        print(f"  大小: {img.size}")
        print(f"  格式: {img.format}")
        # 模式映射说明
        mode_desc = {
            '1': '1位像素,黑和白',
            'L': '8位像素,灰度',
            'P': '8位像素,使用调色板',
            'RGB': '3x8位像素,真彩色',
            'RGBA': '4x8位像素,带透明度',
            'CMYK': '4x8位像素,分色',
            'HSV': '3x8位像素,色相、饱和度、明度'
        }
        print(f"\n目标模式: {target_mode} - {mode_desc.get(target_mode, '未知模式')}")
        # 转换模式
        converted_img = img.convert(target_mode)
        # 保存结果
        converted_img.save(output_path)
        print(f"\n转换后信息:")
        print(f"  模式: {converted_img.mode}")
        print(f"  大小: {converted_img.size}")
        print(f"  保存到: {output_path}")
        return converted_img
    except Exception as e:
        print(f"转换失败: {e}")
        return None
# 使用示例
convert_color_mode('input.jpg', 'output_grayscale.jpg', 'L')
convert_color_mode('input.jpg', 'output_rgba.png', 'RGBA')

批量转换工具

import os
from PIL import Image
class ColorModeConverter:
    """色彩模式批量转换工具"""
    def __init__(self):
        self.supported_modes = ['L', 'RGB', 'RGBA', 'CMYK', 'HSV']
        self.mode_desc = {
            '1': '黑白',
            'L': '灰度',
            'RGB': '真彩色',
            'RGBA': '带透明度',
            'CMYK': 'CMYK印刷色',
            'HSV': 'HSV色彩空间'
        }
    def convert_single(self, input_path, output_path, target_mode='RGB', 
                      quality=95, show_info=True):
        """转换单个文件"""
        if target_mode not in self.supported_modes:
            raise ValueError(f"不支持的模式: {target_mode}")
        img = Image.open(input_path)
        if show_info:
            print(f"转换: {os.path.basename(input_path)}")
            print(f"  原始模式: {img.mode} -> 目标模式: {target_mode}")
        converted = img.convert(target_mode)
        # 根据输出格式调整保存参数
        save_params = {}
        if output_path.lower().endswith(('.jpg', '.jpeg')):
            save_params['quality'] = quality
        elif output_path.lower().endswith('.png'):
            save_params['compress_level'] = 3
        converted.save(output_path, **save_params)
        if show_info:
            print(f"  保存到: {output_path}\n")
        return converted
    def batch_convert(self, input_dir, output_dir, target_mode='RGB', 
                     extensions=['.jpg', '.jpeg', '.png', '.bmp']):
        """批量转换目录下的所有图片"""
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        files = [f for f in os.listdir(input_dir) 
                if os.path.splitext(f)[1].lower() in extensions]
        print(f"找到 {len(files)} 个图片文件")
        print(f"目标模式: {target_mode} ({self.mode_desc.get(target_mode, '')})\n")
        for file in files:
            input_path = os.path.join(input_dir, file)
            # 生成输出文件名
            name, ext = os.path.splitext(file)
            if target_mode == 'RGBA' and ext == '.jpg':
                ext = '.png'  # JPG不支持透明度
            output_path = os.path.join(output_dir, f"{name}_{target_mode}{ext}")
            try:
                self.convert_single(input_path, output_path, target_mode)
            except Exception as e:
                print(f"转换失败: {file} - {e}\n")
# 使用示例
converter = ColorModeConverter()
# 单个文件转换
converter.convert_single('input.jpg', 'output_rgb.jpg', 'RGB')
converter.convert_single('input.png', 'output_gray.jpg', 'L')
# 批量转换
converter.batch_convert('images/', 'converted/', 'L')

特殊转换处理

from PIL import Image
import numpy as np
def create_transparent_background(input_path, output_path):
    """创建透明背景(RGBA模式)"""
    img = Image.open(input_path)
    # 转换为RGBA模式
    rgba_img = img.convert('RGBA')
    # 获取像素数据
    datas = rgba_img.getdata()
    # 替换白色背景为透明
    new_data = []
    for item in datas:
        # 如果像素接近白色(RGB值都大于240)
        if item[0] > 240 and item[1] > 240 and item[2] > 240:
            new_data.append((255, 255, 255, 0))  # 设置为透明
        else:
            new_data.append(item)
    rgba_img.putdata(new_data)
    rgba_img.save(output_path, 'PNG')
    print(f"透明背景图片已保存到: {output_path}")
def convert_to_indexed_color(input_path, output_path, colors=256):
    """转换为索引颜色模式"""
    img = Image.open(input_path)
    # 先转换为RGB
    if img.mode != 'RGB':
        img = img.convert('RGB')
    # 量化减色
    img_quantized = img.quantize(colors=colors)
    # 转换为调色板模式
    img_palette = img_quantized.convert('P')
    img_palette.save(output_path, optimize=True)
    print(f"索引颜色图片 ({colors}色) 已保存到: {output_path}")
def convert_for_special_use(input_path, output_path):
    """针对特殊用途的转换"""
    img = Image.open(input_path)
    print("特殊用途转换:")
    # 1. 网页使用 - RGB优化
    web_img = img.convert('RGB')
    web_img.save('web_' + output_path, optimize=True, quality=85)
    print("  网页优化: web_" + output_path)
    # 2. 灰度打印 - 高质量灰度
    gray_img = img.convert('L')
    gray_img.save('print_' + output_path, dpi=(300, 300))
    print("  打印优化: print_" + output_path)
    # 3. 图标使用 - 索引色
    icon_img = img.resize((64, 64)).convert('RGB')
    icon_quantized = icon_img.quantize(colors=16)
    icon_quantized.save('icon_' + output_path)
    print("  图标优化: icon_" + output_path)
# 使用示例
create_transparent_background('logo.jpg', 'logo_transparent.png')
convert_to_indexed_color('photo.jpg', 'photo_indexed.png', colors=64)
convert_for_special_use('photo.jpg', 'output.png')

模式转换实用工具

from PIL import Image
def get_color_mode_info(image_path):
    """获取图片色彩模式信息"""
    img = Image.open(image_path)
    info = {
        'path': image_path,
        'mode': img.mode,
        'size': img.size,
        'bands': img.getbands(),
        'format': img.format,
        'bits_per_pixel': len(img.getbands()) * 8 if img.mode != '1' else 1
    }
    return info
def convert_all_modes(input_path, output_dir):
    """转换所有支持的色彩模式并保存"""
    import os
    os.makedirs(output_dir, exist_ok=True)
    img = Image.open(input_path)
    base_name = os.path.splitext(os.path.basename(input_path))[0]
    modes = {
        '1': ('black_white', 'png'),
        'L': ('grayscale', 'jpg'),
        'P': ('palette', 'png'),
        'RGB': ('rgb', 'jpg'),
        'RGBA': ('rgba', 'png'),
        'CMYK': ('cmyk', 'jpg')
    }
    for mode, (suffix, ext) in modes.items():
        try:
            converted = img.convert(mode)
            output_path = os.path.join(output_dir, f"{base_name}_{suffix}.{ext}")
            converted.save(output_path)
            print(f"✓ {mode} -> {output_path}")
        except Exception as e:
            print(f"✗ {mode} -> 转换失败: {e}")
# 使用示例
info = get_color_mode_info('photo.jpg')
print("图片信息:", info)
convert_all_modes('photo.jpg', 'color_modes/')

实用函数集合

from PIL import Image
def convert_mode_safe(img, target_mode, fallback_mode='RGB'):
    """
    安全的模式转换,带fallback
    参数:
        img: PIL Image对象
        target_mode: 目标模式
        fallback_mode: 转换失败时的备选模式
    """
    try:
        return img.convert(target_mode)
    except Exception as e:
        print(f"转换为 {target_mode} 失败: {e}")
        print(f"回退到 {fallback_mode}")
        return img.convert(fallback_mode)
def optimize_for_web(input_path, output_path, max_width=1920, quality=85):
    """优化为网页使用的图片"""
    img = Image.open(input_path)
    # 调整大小
    if img.width > max_width:
        ratio = max_width / img.width
        new_size = (max_width, int(img.height * ratio))
        img = img.resize(new_size, Image.Resampling.LANCZOS)
    # 转换为RGB(去除透明度)
    img = img.convert('RGB')
    # 保存为优化后的JPEG
    img.save(output_path, 'JPEG', optimize=True, quality=quality)
    print(f"网页优化图片: {output_path}")
def batch_convert_for_display(input_dir, output_dir, target_mode='RGB', 
                              max_size=(1920, 1080)):
    """批量转换图片为显示优化格式"""
    import os
    from glob import glob
    os.makedirs(output_dir, exist_ok=True)
    # 支持的图片格式
    extensions = ['*.jpg', '*.jpeg', '*.png', '*.bmp', '*.tiff']
    files = []
    for ext in extensions:
        files.extend(glob(os.path.join(input_dir, ext)))
    for file_path in files:
        try:
            img = Image.open(file_path)
            # 调整大小
            img.thumbnail(max_size, Image.Resampling.LANCZOS)
            # 转换模式
            img = img.convert(target_mode)
            # 生成输出路径
            filename = os.path.basename(file_path)
            name, _ = os.path.splitext(filename)
            output_path = os.path.join(output_dir, f"{name}_display.jpg")
            # 保存
            img.save(output_path, 'JPEG', quality=92, optimize=True)
            print(f"✓ {filename} -> {output_path}")
        except Exception as e:
            print(f"✗ {file_path}: {e}")
# 使用示例
optimize_for_web('large_photo.jpg', 'web_photo.jpg')
batch_convert_for_display('photos/', 'display_photos/')

常用模式转换说明

源模式 目标模式 注意事项
RGB L 直接转换,丢失颜色信息
RGB RGBA 添加alpha通道(不透明)
RGBA RGB 去除alpha通道,背景变白
RGB CMYK 颜色空间转换,可能色差
L RGB 灰度转彩色(仍然是灰色)
P RGB 调色板展开为真彩色

这些案例涵盖了日常使用Pillow进行色彩模式转换的常见场景,根据您的具体需求选择合适的函数使用即可。

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