Skip to content

Latest commit

 

History

History
133 lines (114 loc) · 5.12 KB

File metadata and controls

133 lines (114 loc) · 5.12 KB
Error in user YAML: (<unknown>): found a tab character that violate indentation while scanning a plain scalar at line 3 column 3
---
- oeasy Python 0655
- 这是 oeasy 系统化 Python 教程,从基础一步步讲,扎实、完整、不跳步。愿意花时间学,就能真正学会。
- 本教程同步发布在: 
	- 个人网站: `https://oeasy.org` 
	- 蓝桥云课: `https://www.lanqiao.cn/courses/3584` 
	- GitHub: `https://github.com/overmind1980/oeasy-python-tutorial` 
	- Gitee: `https://gitee.com/overmind1980/oeasypython` 
---
import argparse
from PIL import Image
import os

class PixelArtConverter:
    def __init__(self, input_path, output_path, crop_region=None, color_count=16, block_size=8):
        """
        初始化像素艺术转换器
        :param input_path: 输入图片路径
        :param output_path: 输出图片路径
        :param crop_region: 裁剪区域,格式为(x1, y1, x2, y2),None表示不裁剪
        :param color_count: 色彩数量,范围2-256
        :param block_size: 像素块大小
        """
        self.input_path = input_path
        self.output_path = output_path
        self.crop_region = crop_region
        self.color_count = max(2, min(color_count, 256))  # 限制在2-256之间
        self.block_size = max(1, block_size)  # 确保至少为1
        self.image = None

    def load_image(self):
        """加载并预处理图片"""
        if not os.path.exists(self.input_path):
            raise FileNotFoundError(f"输入文件不存在: {self.input_path}")

        # 打开图片并转换为RGB模式(处理透明通道)
        self.image = Image.open(self.input_path)
        if self.image.mode in ('RGBA', 'LA'):
            background = Image.new(self.image.mode[:-1], self.image.size, (255, 255, 255))
            background.paste(self.image, self.image.split()[-1])
            self.image = background
        self.image = self.image.convert('RGB')

    def crop_image(self):
        """裁剪图片"""
        if self.crop_region and self.image:
            x1, y1, x2, y2 = self.crop_region
            # 确保裁剪区域有效
            width, height = self.image.size
            x1 = max(0, min(x1, width))
            y1 = max(0, min(y1, height))
            x2 = max(x1 + 1, min(x2, width))
            y2 = max(y1 + 1, min(y2, height))
            self.image = self.image.crop((x1, y1, x2, y2))

    def convert_to_pixel_art(self):
        """将图片转换为像素风格"""
        if not self.image:
            raise ValueError("未加载图片,请先调用load_image()")

        width, height = self.image.size

        # 计算缩小后的尺寸
        small_width = width // self.block_size
        small_height = height // self.block_size

        # 缩小图片(创建像素块效果)
        img_small = self.image.resize((small_width, small_height), Image.NEAREST)

        # 放大回原始尺寸
        img_pixel = img_small.resize((width, height), Image.NEAREST)

        # 减少色彩数量
        img_quantized = img_pixel.quantize(colors=self.color_count)

        # 转换回RGB模式以保存为JPG
        self.image = img_quantized.convert('RGB')

    def save_image(self):
        """保存处理后的图片"""
        if self.image:
            # 创建输出目录(如果需要)
            output_dir = os.path.dirname(self.output_path)
            if output_dir and not os.path.exists(output_dir):
                os.makedirs(output_dir)
            self.image.save(self.output_path, 'JPEG', quality=95)
            print(f"图片已保存至: {self.output_path}")

    def process(self):
        """执行完整处理流程"""
        try:
            self.load_image()
            print(f"加载图片成功: {self.input_path}")
            print(f"原始尺寸: {self.image.size[0]}x{self.image.size[1]}")

            self.crop_image()
            if self.crop_region:
                print(f"裁剪后尺寸: {self.image.size[0]}x{self.image.size[1]}")

            self.convert_to_pixel_art()
            print(f"像素风格转换完成: {self.color_count}种颜色, {self.block_size}x{self.block_size}像素块")

            self.save_image()
            return True
        except Exception as e:
            print(f"处理失败: {str(e)}")
            return False

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='JPG图片裁剪与像素风格转换工具')
    parser.add_argument('--input', required=True, help='输入JPG图片路径')
    parser.add_argument('--output', required=True, help='输出JPG图片路径')
    parser.add_argument('--crop', nargs=4, type=int, help='裁剪区域坐标 (x1 y1 x2 y2),如 --crop 100 100 500 500')
    parser.add_argument('--colors', type=int, default=16, help='色彩数量 (2-256),默认16')
    parser.add_argument('--block-size', type=int, default=8, help='像素块大小 (正整数),默认8')

    args = parser.parse_args()

    # 创建转换器实例并处理图片
    converter = PixelArtConverter(
        input_path=args.input,
        output_path=args.output,
        crop_region=args.crop,
        color_count=args.colors,
        block_size=args.block_size
    )
    converter.process()

  • 本文来自 oeasy Python 系统教程。
  • 想完整、扎实学 Python,
  • 搜索 oeasy 即可。