Add a description of what you changed

This commit is contained in:
SS-snap
2024-10-07 16:05:55 +08:00
parent d70e6055f5
commit ac93688009
25 changed files with 94 additions and 71 deletions
+32 -26
View File
@@ -1,85 +1,91 @@
# 文件路径: ComfyUI/custom_nodes/ComfyUI-Snap_Processing/Snap_canvas.py
from PyQt5.QtCore import QEventLoop
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QApplication, QMessageBox
from PyQt5.QtGui import QImage
import time
import os
import random
import torch
from PIL import Image
import numpy as np
from io import BytesIO
from .ui.canvas_window import CanvasWindow
class PyQtCanvasNode:
@staticmethod
def INPUT_TYPES():
return {
"required": {
"image": ("IMAGE",), # Required image input
"image": ("IMAGE",), # 必需的图像输入
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
}
}
RETURN_TYPES = ("IMAGE", "INT", "STRING") # Added "STRING" to the return types
RETURN_TYPES = ("IMAGE", "INT", "STRING", "INT", "INT", "FLOAT") # IMAGE, seed, path, x, y, scale_factor
RETURN_NAMES = ("image", "seed", "string", "X", "Y", "factor")
FUNCTION = "activate_pyqt"
CATEGORY = "Snap Processing"
def activate_pyqt(self, image, seed):
try:
# Use the user-provided seed value
# 使用用户提供的种子值
print(f"Received seed: {seed}")
# Convert tensor to QImage
# 将张量转换为 QImage
qimage = self.tensor_to_qimage(image)
print("Converted tensor to QImage")
# Run PyQt GUI and block the main thread until the user finishes
modified_image = self.run_pyqt_gui(qimage)
# 运行 PyQt GUI 并阻塞主线程,直到用户完成操作
modified_image, x, y, scale_factor = self.run_pyqt_gui(qimage)
print("PyQt GUI closed")
# Convert the modified QImage to a NumPy array
# 将修改后的 QImage 转换为 NumPy 数组
numpy_array = self.qimage_to_numpy(modified_image)
print("Converted QImage to NumPy array")
# Define the save directory
save_directory = os.path.join(os.getcwd(), "ComfyUI", "custom_nodes", "ComfyUI-Snap_Processing", "save")
save_directory = os.path.join(os.getcwd(), "canvas")
# 如果目录不存在,则创建该目录
if not os.path.exists(save_directory):
os.makedirs(save_directory)
# Create a unique file name using the seed and current timestamp
timestamp = int(time.time())
png_image_filename = f"output_image_seed{seed}_{timestamp}.png"
# 使用固定文件名 'output.png'
png_image_filename = "output.png"
png_image_path = os.path.join(save_directory, png_image_filename)
# 保存图像
self.numpy_to_png(numpy_array, png_image_path)
print(f"Saved image to {png_image_path}")
print(f"已将图像保存到 {png_image_path}")
# Get the absolute path for consistency
absolute_png_image_path = os.path.abspath(png_image_path)
# Return the modified image, seed, and the file path
return (self.qimage_to_tensor(modified_image), seed, absolute_png_image_path)
# 返回修改后的图像和其他参数
return (self.qimage_to_tensor(modified_image), seed, png_image_path, x, y, scale_factor)
except Exception as e:
print(f"Error in activate_pyqt: {e}")
print(f"激活 PyQt 时出错: {e}")
raise e
def run_pyqt_gui(self, input_image):
try:
app = QApplication.instance()
if app is None:
app = QApplication([]) # Create the global application
app = QApplication([]) # 创建全局应用程序
# Always create a new CanvasWindow instance
# 始终创建一个新的 CanvasWindow 实例
dialog = CanvasWindow(input_image)
dialog.save_signal.connect(self.on_save)
dialog.close_signal.connect(self.on_close)
print("PyQt CanvasWindow shown")
dialog.exec_() # Block until the dialog is closed
dialog.exec_() # 阻塞,直到对话框关闭
print("Dialog closed")
modified_image = dialog.get_modified_image()
dialog.deleteLater() # Ensure the window is properly destroyed
x = dialog.get_top_left_x()
y = dialog.get_top_left_y()
scale_factor = dialog.get_scale_factor()
dialog.deleteLater() # 确保窗口被正确销毁
print("CanvasWindow deleted")
return modified_image
return modified_image, x, y, scale_factor
except Exception as e:
print(f"Error in run_pyqt_gui: {e}")
raise e
+1 -1
View File
@@ -44,7 +44,7 @@ class Snapload:
def _resolve_path(image) -> Path:
# 如果未提供图像路径,则使用默认路径
if not image:
default_path = Path("ComfyUI/custom_nodes/ComfyUI-Snap_Processing/save/output.png").resolve()
default_path = Path("custom_nodes/ComfyUI-Snap_Processing/save/output.png").resolve()
else:
default_path = Path(folder_paths.get_annotated_filepath(image)).resolve()
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.
+61 -44
View File
@@ -1,3 +1,5 @@
# 文件路径: ComfyUI/custom_nodes/ComfyUI-Snap_Processing/ui/canvas_window.py
import os
import sys
import time
@@ -6,7 +8,7 @@ from PyQt5.QtWidgets import (
QGraphicsView, QGraphicsScene, QGraphicsPixmapItem, QGraphicsItem, QMessageBox
)
from PyQt5.QtGui import QPixmap, QImage, QColor, QPainter, QTransform, QPen
from PyQt5.QtCore import pyqtSignal, Qt, QRectF
from PyQt5.QtCore import pyqtSignal, Qt, QRectF, QPointF
class CanvasWindow(QDialog):
@@ -22,6 +24,10 @@ class CanvasWindow(QDialog):
self.canvas_height = canvas_height
self.modified_image = None
self.top_left_x = 0
self.top_left_y = 0
self.scale_factor = 1.0 # 初始缩放倍数
self.scene = QGraphicsScene()
self.view = QGraphicsView(self.scene)
self.view.setStyleSheet("border: 1px solid black;")
@@ -39,10 +45,9 @@ class CanvasWindow(QDialog):
self.scene.addItem(self.canvas_pixmap_item)
# 添加可调整大小和可旋转的输入图像
scaled_pixmap = QPixmap.fromImage(self.input_image).scaled(
self.canvas_width, self.canvas_height, Qt.KeepAspectRatio, Qt.SmoothTransformation
)
self.input_pixmap_item = ResizablePixmapItem(scaled_pixmap, self.canvas_width, self.canvas_height)
# 直接显示原始尺寸,不进行适应画布
original_pixmap = QPixmap.fromImage(self.input_image)
self.input_pixmap_item = ResizablePixmapItem(original_pixmap, self.canvas_width, self.canvas_height)
self.scene.addItem(self.input_pixmap_item)
# 设置旋转锚点为图像中心
@@ -63,6 +68,14 @@ class CanvasWindow(QDialog):
rotate_button = QPushButton("旋转", self)
rotate_button.clicked.connect(self.rotate_image)
scale_label = QLineEdit(self)
scale_label.setPlaceholderText("缩放倍数")
scale_label.setFixedWidth(100)
self.scale_input = scale_label
scale_button = QPushButton("缩放", self)
scale_button.clicked.connect(self.scale_image)
self.canvas_width_input = QLineEdit(self)
self.canvas_width_input.setPlaceholderText("画布宽度")
self.canvas_width_input.setText(str(self.canvas_width))
@@ -80,6 +93,8 @@ class CanvasWindow(QDialog):
hbox.addWidget(size_button)
hbox.addWidget(self.rotate_input)
hbox.addWidget(rotate_button)
hbox.addWidget(self.scale_input)
hbox.addWidget(scale_button)
vbox = QVBoxLayout()
vbox.addWidget(self.view)
@@ -92,10 +107,10 @@ class CanvasWindow(QDialog):
self.view.setSceneRect(0, 0, self.canvas_width, self.canvas_height)
# 设置窗口最小大小
self.setMinimumSize(400, 300)
self.setMinimumSize(600, 400)
def add_canvas_border(self):
"""添加画布边界线以可视化画布边缘"""
"""添加画布边界线以可视化画布边缘,但不包含在输出中"""
pen = QPen(QColor('red'))
pen.setWidth(2)
border_rect = QRectF(0, 0, self.canvas_width, self.canvas_height)
@@ -130,13 +145,13 @@ class CanvasWindow(QDialog):
self.modified_image = image
# 保存路径
save_directory = os.path.join(os.getcwd(), "ComfyUI", "custom_nodes", "ComfyUI-Snap_Processing", "save")
# 获取图像左上角的坐标
top_left_point = self.input_pixmap_item.mapToScene(0, 0)
self.top_left_x = int(top_left_point.x())
self.top_left_y = int(top_left_point.y())
timestamp = int(time.time() * 1000)
save_path = os.path.join(save_directory, f"output_{timestamp}.png")
image.save(save_path)
self.save_signal.emit()
# 获取缩放倍数
self.scale_factor = self.input_pixmap_item.get_current_scale()
def closeEvent(self, event):
self.close_signal.emit()
@@ -178,15 +193,37 @@ class CanvasWindow(QDialog):
self.input_pixmap_item.rotate_pixmap(angle)
def scale_image(self):
try:
scale_factor = float(self.scale_input.text())
if scale_factor <= 0:
raise ValueError
except ValueError:
QMessageBox.warning(self, "输入错误", "缩放倍数必须是一个正数。")
return
self.input_pixmap_item.scale_pixmap(scale_factor)
def get_modified_image(self):
return self.modified_image
def get_top_left_x(self):
return self.top_left_x
def get_top_left_y(self):
return self.top_left_y
def get_scale_factor(self):
return self.scale_factor
class ResizablePixmapItem(QGraphicsPixmapItem):
def __init__(self, pixmap, canvas_width, canvas_height):
super().__init__(pixmap)
self.canvas_width = canvas_width
self.canvas_height = canvas_height
self.original_pixmap = pixmap.copy() # 保持原始图像的副本
self.original_size = pixmap.size()
self.setFlags(
QGraphicsItem.ItemIsSelectable |
QGraphicsItem.ItemIsMovable |
@@ -290,38 +327,18 @@ class ResizablePixmapItem(QGraphicsPixmapItem):
self.update()
def rotate_pixmap(self, angle):
"""根据输入角度旋转图像"""
"""根据输入角度旋转图像,并保持旋转锚点为中心"""
self.current_rotation = (self.current_rotation + angle) % 360
self.setRotation(self.current_rotation)
def scale_pixmap(self, scale_factor):
"""手动设置缩放倍数"""
if scale_factor <= 0:
return
if self.min_scale <= scale_factor <= self.max_scale:
self.current_scale = scale_factor
self.setScale(self.current_scale)
self.update()
# 示例用法
def run_pyqt_gui(input_image_path, canvas_width=512, canvas_height=512):
app = QApplication(sys.argv)
input_image = QImage(input_image_path)
if input_image.isNull():
QMessageBox.critical(None, "加载失败", "无法加载图像。请检查图像路径是否正确。")
sys.exit(1)
dialog = CanvasWindow(input_image, canvas_width, canvas_height)
dialog.show() # 使用 show 而不是 exec_ 以避免阻塞
# 运行应用程序的事件循环
app.exec_()
modified_image = dialog.get_modified_image()
if modified_image:
save_directory = os.path.join(os.getcwd(), "ComfyUI", "custom_nodes", "Comfyui-Snap_Processing", "save")
timestamp = int(time.time() * 1000)
save_path = os.path.join(save_directory, f"modified_output_{timestamp}.png")
modified_image.save(save_path)
else:
QMessageBox.information(None, "信息", "没有修改后的图像可用。")
if __name__ == "__main__":
# 替换为您实际的图像路径
image_path = "path_to_your_image.png" # 请替换为实际图像路径
run_pyqt_gui(image_path)
def get_current_scale(self):
return self.current_scale