Merge remote-tracking branch 'origin/xhy_PSD' into wxq_llm
This commit is contained in:
commit
dfc357f2bb
21
README.md
21
README.md
@ -20,4 +20,23 @@
|
|||||||
python generate_layout.py
|
python generate_layout.py
|
||||||
```
|
```
|
||||||
- 该脚本会自动调用 DeepSeek API 生成 React 组件代码,并将其保存到指定路径。
|
- 该脚本会自动调用 DeepSeek API 生成 React 组件代码,并将其保存到指定路径。
|
||||||
默认为``output/generated_code.jsx``,可以根据需要修改。
|
默认为``output/generated_code.jsx``,可以根据需要修改。
|
||||||
|
|
||||||
|
## 图层叠加和PSD导出部分
|
||||||
|
### 功能组件
|
||||||
|
- **图层合成**:根据生成的布局配置,将各个图层叠加在一起,生成完整的海报图像。
|
||||||
|
- **PSD导出**:将合成的海报图像保存为标准的PSD格式,同时保留各个图层的独立性,方便后续编辑。
|
||||||
|
### 如何调用
|
||||||
|
1. **环境准备**:
|
||||||
|
```bash
|
||||||
|
conda create -n ai_service python=3.8
|
||||||
|
conda activate ai_service
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
2. **运行脚本**:
|
||||||
|
```bash
|
||||||
|
python export_psd.py #简单生成
|
||||||
|
python export_psd_from_json.py #从json文件加载布局并生成
|
||||||
|
python PSD_test.py #在run_pipline.py中的调用方法
|
||||||
|
```
|
||||||
|
该脚本会自动调用图层合成模块生成完整海报图像,并将其保存为标准PSD格式。
|
40
configs/example.json
Normal file
40
configs/example.json
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"canvas": {
|
||||||
|
"width": 1000,
|
||||||
|
"height": 800,
|
||||||
|
"mode": "RGB"
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"image_path": "../images/background.jpg",
|
||||||
|
"name": "background",
|
||||||
|
"position": {
|
||||||
|
"left": 0,
|
||||||
|
"top": 0
|
||||||
|
},
|
||||||
|
"visible": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"image_path": "../images/nankai.jpg",
|
||||||
|
"name": "middle",
|
||||||
|
"position": {
|
||||||
|
"left": 100,
|
||||||
|
"top": 100
|
||||||
|
},
|
||||||
|
"visible": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"image_path": "../images/aaai.png",
|
||||||
|
"name": "top",
|
||||||
|
"position": {
|
||||||
|
"left": 200,
|
||||||
|
"top": 200
|
||||||
|
},
|
||||||
|
"visible": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"output": {
|
||||||
|
"path": "../outputs/configured_output.psd",
|
||||||
|
"generate_preview": true
|
||||||
|
}
|
||||||
|
}
|
BIN
outputs/.DS_Store
vendored
Normal file
BIN
outputs/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
outputs/combined_output.psd
Normal file
BIN
outputs/combined_output.psd
Normal file
Binary file not shown.
BIN
outputs/combined_output_预览.png
Normal file
BIN
outputs/combined_output_预览.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 69 KiB |
14
scripts/PSD_test1.py
Normal file
14
scripts/PSD_test1.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from export_psd import create_psd_from_images
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
image_list = [
|
||||||
|
'../images/background.jpg',
|
||||||
|
'../images/nankai.jpg',
|
||||||
|
'../images/aaai.png',
|
||||||
|
# Add more images as needed
|
||||||
|
]
|
||||||
|
|
||||||
|
create_psd_from_images(
|
||||||
|
image_paths=image_list,
|
||||||
|
output_path='../outputs/combined_output.psd'
|
||||||
|
)
|
100
scripts/export_psd.py
Normal file
100
scripts/export_psd.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
"""
|
||||||
|
测试文件:从多个图片创建PSD文件
|
||||||
|
将图片列表作为输入,从底到顶添加为PSD图层,并将图片居中放置
|
||||||
|
"""
|
||||||
|
|
||||||
|
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_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__":
|
||||||
|
# 示例用法
|
||||||
|
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'
|
||||||
|
)
|
197
scripts/export_psd_from_json.py
Normal file
197
scripts/export_psd_from_json.py
Normal 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'
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user