实现根据json布局进行图层叠加

This commit is contained in:
cyborvirtue 2025-05-22 10:50:10 +08:00
parent 08ae3b6623
commit b2bcb6616c
4 changed files with 197 additions and 0 deletions

View File

@ -0,0 +1,197 @@
"""
测试文件从JSON配置文件创建PSD文件
支持通过配置文件精确控制图层位置和属性
"""
import json
from psd_tools import PSDImage
from PIL import Image
from psd_tools.constants import Compression
import os
from typing import List, Tuple
# 导入PixelLayer类用于从PIL图像创建图层
from psd_tools.api.layers import PixelLayer
def create_psd_from_config(config_file: str) -> None:
"""
从JSON配置文件创建PSD文件
参数:
config_file: JSON配置文件路径
"""
# 确保配置文件存在
if not os.path.exists(config_file):
raise FileNotFoundError(f"配置文件不存在: {config_file}")
# 读取JSON配置文件
with open(config_file, 'r', encoding='utf-8') as f:
config = json.load(f)
try:
# 1. 从配置创建PSD文件
canvas = config['canvas']
psd = PSDImage.new(
canvas['mode'],
(canvas['width'], canvas['height'])
)
# 2. 根据配置添加图层
for layer_config in config['layers']:
# 打开图片
image = Image.open(layer_config['image_path'])
# 获取位置信息
position = layer_config['position']
left = position['left']
top = position['top']
# 创建图层
layer = PixelLayer.frompil(
image,
psd,
layer_config['name'],
top,
left,
Compression.RLE
)
# 设置图层可见性
layer.visible = layer_config.get('visible', True)
psd.append(layer)
# 3. 确保所有图层都是可见的
for layer in psd:
if not layer.visible:
print(f"图层 {layer.name} 不可见,正在设置为可见")
layer.visible = True
# 4. 生成合成图像并更新PSD文件的图像数据
composite_image = psd.composite(force=True)
psd._record.image_data.set_data(
[channel.tobytes() for channel in composite_image.split()],
psd._record.header
)
# 5. 保存PSD文件
output_config = config['output']
output_path = output_config['path']
# 确保输出目录存在
os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)
psd.save(output_path)
print(f"PSD文件已成功创建保存在: {output_path}")
# 6. 生成预览(如果配置中启用)
if output_config.get('generate_preview', False):
preview_path = os.path.splitext(output_path)[0] + "_预览.png"
composite_image.save(preview_path)
print(f"预览已保存在: {preview_path}")
# 7. 验证PSD文件结构
saved_psd = PSDImage.open(output_path)
print(f"PSD文件信息: {saved_psd}")
print(f"图层数量: {len(saved_psd)}")
for i, layer in enumerate(saved_psd):
print(f"图层 {i}: {layer.name}, 位置: ({layer.left}, {layer.top}), 大小: {layer.width}x{layer.height}")
except Exception as e:
print(f"创建PSD文件时出错: {e}")
def create_psd_from_images(
image_paths: List[str],
output_path: str,
canvas_size: Tuple[int, int] = (1000, 800),
mode: str = 'RGB'
) -> None:
"""
从图片列表创建PSD文件将图片从底到顶堆叠保留原有功能
参数:
image_paths: 图片路径列表
output_path: 保存PSD文件的路径
canvas_size: PSD画布大小格式为(宽度, 高度)
mode: PSD文件的颜色模式
"""
# 确保输出目录存在
os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)
try:
# 1. 创建一个新的PSD文件
psd = PSDImage.new(mode, canvas_size)
# 2. 打开并添加每个图片作为图层
for i, img_path in enumerate(image_paths):
# 打开图片
image = Image.open(img_path)
# 计算居中位置
left = (canvas_size[0] - image.width) // 2
top = (canvas_size[1] - image.height) // 2
# 根据图片文件名创建图层名称
layer_name = f"layer {i+1} - {os.path.basename(img_path)}"
# 创建并添加图层
layer = PixelLayer.frompil(image, psd, layer_name, top, left, Compression.RLE)
# 确保图层可见
layer.visible = True
psd.append(layer)
# 确保所有图层都是可见的
for layer in psd:
if not layer.visible:
print(f"图层 {layer.name} 不可见,正在设置为可见")
layer.visible = True
# 生成合成图像
composite_image = psd.composite(force=True)
# 更新PSD文件的图像数据
psd._record.image_data.set_data([channel.tobytes() for channel in composite_image.split()], psd._record.header)
# 3. 保存PSD文件
psd.save(output_path)
print(f"PSD文件已成功创建保存在: {output_path}")
# 4. 生成并保存预览
preview_path = os.path.splitext(output_path)[0] + "_预览.png"
composite_image.save(preview_path)
print(f"预览已保存在: {preview_path}")
# 5. 验证PSD文件结构
saved_psd = PSDImage.open(output_path)
print(f"PSD文件信息: {saved_psd}")
print(f"图层数量: {len(saved_psd)}")
for i, layer in enumerate(saved_psd):
print(f"图层 {i}: {layer.name}, 位置: ({layer.left}, {layer.top}), 大小: {layer.width}x{layer.height}")
except Exception as e:
print(f"创建PSD文件时出错: {e}")
if __name__ == "__main__":
# 方法1: 使用JSON配置文件
print("=== 使用JSON配置文件创建PSD ===")
create_psd_from_config('../configs/example.json')
print("\n" + "="*50 + "\n")
# 方法2: 使用原有的图片列表方法(保留兼容性)
print("=== 使用图片列表创建PSD居中布局===")
image_list = [
'../images/background.jpg', # 底层图片
'../images/nankai.jpg', # 中间图片
'../images/aaai.png', # 顶层图片
# 可以根据需要添加更多图片
]
create_psd_from_images(
image_paths=image_list,
output_path='../outputs/combined_output.psd'
)