python对图片的颜色操作相关

1.更换图片的颜色,包括 jpg   png    gif   svg

#--------------jpg,png替换--------------
from PIL import Image , ImageSequence
import numpy as np
from scipy.ndimage import binary_erosion, binary_dilation
#--------------svg替换--------------
import re
from xml.dom import minidom
import cssutils


#---------------------------------------------jpg,png替换---------------------------------------------

def change_color_jpg_png(image_path, output_path,target_color, new_color):
    """
    高精度颜色替换,保持边缘清晰
    
    参数:
        image_path: 输入图片路径
        target_color: 要替换的目标颜色 (R,G,B)
        new_color: 新的颜色 (R,G,B)
        tolerance: 颜色匹配容差 (0-100)
        output_path: 输出图片路径
    """
    # 打开图片并确保是RGBA模式
    img = Image.open(image_path)
    if img.mode != 'RGBA':
        img = img.convert('RGBA')
    
    img_array = np.array(img)

    target = np.array(target_color)
    newc = np.array(new_color)

    for element in img_array:
        for colorItem in element:
                if(((255 - colorItem[0]) < 3) and colorItem[1] == target[1] and colorItem[2] == target[2]):
                     colorItem[0] = newc[0]
                     colorItem[1] = newc[1]
                     colorItem[2] = newc[2]
                else:
                    a = abs(255 - colorItem[0])
                    b = abs(255 - colorItem[1])
                    c = abs(255 - colorItem[2])
                    if((a < 5) and (b > 50)  and (c > 50)):
                        colorItem[0] = newc[0]
                        colorItem[1] = newc[1]
                        colorItem[2] = newc[2]
    
    # 保存结果
    result_img = Image.fromarray(img_array)
    result_img.save(output_path, quality=100)
    print(f"处理完成,结果保存到: {output_path}")



#---------------------------------------------svg替换---------------------------------------------

def replace_in_svg(image_path, output_path,o_color,n_color):
    """
    替换 SVG 文件中的内容
    
    参数:
        image_path: 输入的 SVG 文件路径
        output_file: 输出的 SVG 文件路径
    """
    replacements = {
        'colors': {
            f'{o_color}': f'{n_color}',  # 红色替换为绿色
            # 'rgb(254,36,67)': 'rgb(119,230,28)',
        },
    }
    # 读取 SVG 文件
    with open(image_path, 'r', encoding='utf-8') as f:
        svg_content = f.read()
    
    # 解析 XML
    doc = minidom.parseString(svg_content)
    
    # 颜色替换
    if 'colors' in replacements:
        for old_color, new_color in replacements['colors'].items():
            svg_content = replace_colors(svg_content, old_color, new_color)
    
    # 保存修改后的 SVG
    with open(output_path, 'w', encoding='utf-8') as f:
        f.write(svg_content)
    
    print(f"SVG 内容已替换并保存到 {output_path}")

def replace_colors(svg_content, old_color, new_color):
    """替换 SVG 中的颜色值"""
    # 支持 hex, rgb(), rgba(), 颜色名称等多种格式
    color_patterns = [
        (re.compile(f'fill="{old_color}"'), f'fill="{new_color}"'),
        (re.compile(f'stroke="{old_color}"'), f'stroke="{new_color}"'),
        (re.compile(f'fill:{old_color}(;|!important)'), f'fill:{new_color}\\1'),
        (re.compile(f'stroke:{old_color}(;|!important)'), f'stroke:{new_color}\\1'),
        (re.compile(f'stop-color="{old_color}"'), f'stop-color="{new_color}"'),
        (re.compile(f'flood-color="{old_color}"'), f'flood-color="{new_color}"'),
    ]
    
    for pattern, replacement in color_patterns:
        svg_content = pattern.sub(replacement, svg_content)
    
    return svg_content



#---------------------------------------------gif替换---------------------------------------------


def replace_gif_color(image_path, output_path, target_color, new_color):
    """
    替换 GIF 文件中的颜色
    
    参数:
        image_path: 输入 GIF 文件路径
        output_path: 输出 GIF 文件路径
        color_mapping: 颜色映射字典 {旧颜色: 新颜色},颜色格式为 (R,G,B) 或 (R,G,B,A)
    """
    # 打开 GIF 文件
    gif = Image.open(image_path)
    
    # 获取 GIF 的调色板模式信息
    palette = gif.getpalette()

    # 处理每一帧
    frames = []
    durations = []
    for frame in ImageSequence.Iterator(gif):
        # 转换为 RGBA 以处理透明度
        frame_rgba = frame.convert('RGBA')
        frame_array = np.array(frame_rgba)

        target = np.array(target_color)
        newc = np.array(new_color)

        for element in frame_array:
            for colorItem in element:
                    if(((255 - colorItem[0]) < 3) and colorItem[1] == target[1] and colorItem[2] == target[2]):
                        colorItem[0] = newc[0]
                        colorItem[1] = newc[1]
                        colorItem[2] = newc[2]
                    else:
                        a = abs(255 - colorItem[0])
                        b = abs(255 - colorItem[1])
                        c = abs(255 - colorItem[2])
                        if((a < 5) and (b > 50)  and (c > 50)):
                            colorItem[0] = newc[0]
                            colorItem[1] = newc[1]
                            colorItem[2] = newc[2]
        
        # 转换回 PIL 图像
        new_frame = Image.fromarray(frame_array)

        frames.append(new_frame)
        durations.append(frame.info.get('duration', 100))  # 默认 100ms

    # 保存 GIF
    frames[0].save(
        output_path,
        save_all=True,
        append_images=frames[1:],
        duration=durations,
        loop=0,  # 无限循环
        disposal=2,  # 恢复背景
        optimize=True
    )
    
    print(f"GIF 颜色已替换并保存到 {output_path}")

#---------------------------------------------jpg,png替换 ,渐变---------------------------------------------

def change_color_jpg_png_slowly(image_path, output_path,target_color, new_color):
    """
    高精度颜色替换,保持边缘清晰
    
    参数:
        image_path: 输入图片路径
        target_color: 要替换的目标颜色 (R,G,B)
        new_color: 新的颜色 (R,G,B)
        tolerance: 颜色匹配容差 (0-100)
        output_path: 输出图片路径
    """
    # 打开图片并确保是RGBA模式
    img = Image.open(image_path)
    if img.mode != 'RGBA':
        img = img.convert('RGBA')
    
    img_array = np.array(img)

    target = np.array(target_color)
    newc = np.array(new_color)

    for element in img_array:
        for colorItem in element:
            if(colorItem[0] > 250 and colorItem[1] > 250 and colorItem[2] > 250):
                continue
            
            if(colorItem[0] < target[0]):
                colorItem[0] = max(min(int(newc[0] + (colorItem[0] - target[0])),255),0)
            else:
                colorItem[0] = max(min(int(newc[0] + (colorItem[0] - target[0])),255),0)

            if(colorItem[1] < target[1]):
                colorItem[1] = max(min(int(newc[1] + (colorItem[1] - target[1])),255),0)
            else:
                colorItem[1] = max(min(int(newc[1] + (colorItem[1] - target[1])),255),0)
    
    # 保存结果
    result_img = Image.fromarray(img_array)
    result_img.save(output_path, quality=100)
    print(f"处理完成,结果保存到: {output_path}")

2.获取图片颜色

from PIL import Image
import numpy as np
from collections import Counter

def get_all_argb_values(image_path, output_mode='unique', top_colors=10):
    """
    获取图片中所有像素的ARGB值
    
    参数:
        image_path: 图片路径
        output_mode: 输出模式 ('all'所有像素/'unique'唯一值/'top'最常见颜色)
        top_colors: 当output_mode='top'时,指定显示的最常见颜色数量
        
    返回:
        根据output_mode返回不同的ARGB值集合
    """
    # 打开图片并转换为RGBA模式
    try:
        img = Image.open(image_path).convert('RGBA')
    except Exception as e:
        print(f"无法打开图片: {e}")
        return None
    
    # 将图像数据转换为numpy数组
    img_array = np.array(img)
    
    # 获取所有像素的ARGB值 (形状: [height, width, 4])
    argb_values = img_array.reshape(-1, 4)  # 展平为二维数组 [pixel_count, 4]
    
    # 根据输出模式返回不同结果
    if output_mode == 'all':
        return argb_values.tolist()  # 返回所有像素的ARGB值
        
    elif output_mode == 'unique':
        # 返回唯一的ARGB值
        unique_colors = np.unique(argb_values, axis=0)
        return unique_colors.tolist()
        
    elif output_mode == 'top':
        # 返回最常见的top_colors种颜色及其出现次数
        # 将ARGB元组作为字典键
        color_counts = Counter(tuple(color) for color in argb_values)
        return color_counts.most_common(top_colors)
        
    else:
        raise ValueError("output_mode参数必须是'all'、'unique'或'top'")

def save_argb_values_to_file(argb_data, output_file):
    """将ARGB数据保存到文本文件"""
    with open(output_file, 'w') as f:
        if isinstance(argb_data[0], tuple):  # top模式数据
            for color, count in argb_data:
                f.write(f"ARGB{color}: {count}次\n")
        else:  # all或unique模式数据
            for color in argb_data:
                f.write(f"ARGB{tuple(color)}\n")
    print(f"ARGB值已保存到 {output_file}")

def display_color_palette(argb_data, palette_size=400):
    """显示颜色调色板"""
    from PIL import ImageDraw
    
    if isinstance(argb_data[0], tuple):  # top模式数据
        colors = [color for color, _ in argb_data]
    else:  # all或unique模式数据
        colors = [tuple(color) for color in argb_data]
    
    # 创建调色板图像
    cols = 10
    rows = (len(colors) // cols) + 1
    swatch_size = palette_size // cols
    palette = Image.new('RGBA', (cols*swatch_size, rows*swatch_size))
    draw = ImageDraw.Draw(palette)
    
    for i, color in enumerate(colors):
        x = (i % cols) * swatch_size
        y = (i // cols) * swatch_size
        draw.rectangle([x, y, x+swatch_size, y+swatch_size], fill=color)
    
    palette.show()
    return palette

# 使用示例
if __name__ == "__main__":
    # 配置参数
    image_path = '/Users/veepai005/Documents/personal_bg_light.png'  # 替换为你的图片路径
    output_mode = 'top'        # 'all''unique''top'
    top_colors = 20            # 当output_mode='top'时有效
    output_file = '/Users/veepai005/Documents/buy_flow.txt'
    
    # 获取ARGB值
    argb_data = get_all_argb_values(image_path, output_mode, top_colors)
    
    if argb_data:
        # 打印部分结果
        print(f"找到 {len(argb_data)} 个ARGB值(模式: {output_mode})")
        if output_mode == 'top':
            for i, (color, count) in enumerate(argb_data[:10], 1):
                print(f"{i}. ARGB{color}: {count}次")
        else:
            print("前5个ARGB值:", argb_data[:10])
        
        # 保存到文件
        save_argb_values_to_file(argb_data, output_file)
        
        # 显示颜色调色板(仅当颜色数量<=100时)
        if len(argb_data) <= 100:
            display_color_palette(argb_data)
        else:
            print("颜色过多,不显示调色板")

 

   

posted @ 2025-08-12 11:31  呢哇哦比较  阅读(18)  评论(0)    收藏  举报