| | from PIL.ImageQt import ImageQt
|
| | from PyQt5 import QtCore
|
| | from PyQt5.QtCore import QSize, Qt, QUrl
|
| | from PyQt5.QtGui import (
|
| | QDesktopServices,
|
| | QPixmap,
|
| | )
|
| | from PyQt5.QtWidgets import (
|
| | QApplication,
|
| | QHBoxLayout,
|
| | QLabel,
|
| | QPushButton,
|
| | QSizePolicy,
|
| | QTextEdit,
|
| | QToolButton,
|
| | QVBoxLayout,
|
| | QWidget,
|
| | )
|
| |
|
| | from app_settings import AppSettings
|
| | from constants import DEVICE
|
| | from frontend.gui.image_generator_worker import ImageGeneratorWorker
|
| |
|
| |
|
| | class ImageLabel(QLabel):
|
| | """Defines a simple QLabel widget"""
|
| |
|
| | changed = QtCore.pyqtSignal()
|
| |
|
| | def __init__(self, text: str):
|
| | super().__init__(text)
|
| | self.setAlignment(Qt.AlignCenter)
|
| | self.resize(512, 512)
|
| | self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
|
| | self.sizeHint = QSize(512, 512)
|
| | self.setAcceptDrops(False)
|
| |
|
| | def show_image(self, pixmap: QPixmap = None):
|
| | """Updates the widget pixamp"""
|
| | if pixmap == None or pixmap.isNull():
|
| | return
|
| | self.current_pixmap = pixmap
|
| | self.changed.emit()
|
| |
|
| |
|
| | image_width = self.current_pixmap.width()
|
| | image_height = self.current_pixmap.height()
|
| | if image_width > 512 or image_height > 512:
|
| | new_width = 512 if image_width > 512 else image_width
|
| | new_height = 512 if image_height > 512 else image_height
|
| | self.setPixmap(
|
| | self.current_pixmap.scaled(
|
| | new_width,
|
| | new_height,
|
| | Qt.KeepAspectRatio,
|
| | )
|
| | )
|
| | else:
|
| | self.setPixmap(self.current_pixmap)
|
| |
|
| |
|
| | class BaseWidget(QWidget):
|
| | def __init__(self, config: AppSettings, parent):
|
| | super().__init__()
|
| | self.config = config
|
| | self.gen_images = []
|
| | self.image_index = 0
|
| | self.config = config
|
| | self.parent = parent
|
| |
|
| |
|
| | self.prev_btn = QToolButton()
|
| | self.prev_btn.setText("<")
|
| | self.prev_btn.clicked.connect(self.on_show_previous_image)
|
| | self.img = ImageLabel("<<Image>>")
|
| | self.next_btn = QToolButton()
|
| | self.next_btn.setText(">")
|
| | self.next_btn.clicked.connect(self.on_show_next_image)
|
| | self.prompt = QTextEdit()
|
| | self.prompt.setPlaceholderText("A fantasy landscape")
|
| | self.prompt.setAcceptRichText(False)
|
| | self.prompt.setFixedHeight(40)
|
| | self.neg_prompt = QTextEdit()
|
| | self.neg_prompt.setPlaceholderText("")
|
| | self.neg_prompt.setAcceptRichText(False)
|
| | self.neg_prompt_label = QLabel("Negative prompt (Set guidance scale > 1.0):")
|
| | self.neg_prompt.setFixedHeight(35)
|
| | self.neg_prompt.setEnabled(False)
|
| | self.generate = QPushButton("Generate")
|
| | self.generate.clicked.connect(self.generate_click)
|
| | self.browse_results = QPushButton("...")
|
| | self.browse_results.setFixedWidth(30)
|
| | self.browse_results.clicked.connect(self.on_open_results_folder)
|
| | self.browse_results.setToolTip("Open output folder")
|
| |
|
| |
|
| | ilayout = QHBoxLayout()
|
| | ilayout.addWidget(self.prev_btn)
|
| | ilayout.addWidget(self.img)
|
| | ilayout.addWidget(self.next_btn)
|
| |
|
| |
|
| | hlayout = QHBoxLayout()
|
| | hlayout.addWidget(self.neg_prompt)
|
| | hlayout.addWidget(self.generate)
|
| | hlayout.addWidget(self.browse_results)
|
| |
|
| |
|
| | vlayout = QVBoxLayout()
|
| | vlayout.addLayout(ilayout)
|
| |
|
| | vlayout.addWidget(self.prompt)
|
| | vlayout.addWidget(self.neg_prompt_label)
|
| | vlayout.addLayout(hlayout)
|
| | self.setLayout(vlayout)
|
| |
|
| | self.parent.settings_changed.connect(self.on_settings_changed)
|
| |
|
| | def generate_image(self):
|
| | self.parent.prepare_generation_settings(self.config)
|
| | self.config.settings.lcm_diffusion_setting.prompt = self.prompt.toPlainText()
|
| | self.config.settings.lcm_diffusion_setting.negative_prompt = (
|
| | self.neg_prompt.toPlainText()
|
| | )
|
| | images = self.parent.context.generate_text_to_image(
|
| | self.config.settings,
|
| | self.config.reshape_required,
|
| | DEVICE,
|
| | )
|
| | self.parent.context.save_images(
|
| | images,
|
| | self.config.settings,
|
| | )
|
| | self.prepare_images(images)
|
| | self.after_generation()
|
| |
|
| | def prepare_images(self, images):
|
| | """Prepares the generated images to be displayed in the Qt widget"""
|
| | self.image_index = 0
|
| | self.gen_images = []
|
| | for img in images:
|
| | im = ImageQt(img).copy()
|
| | pixmap = QPixmap.fromImage(im)
|
| | self.gen_images.append(pixmap)
|
| |
|
| | if len(self.gen_images) > 1:
|
| | self.next_btn.setEnabled(True)
|
| | self.prev_btn.setEnabled(False)
|
| | else:
|
| | self.next_btn.setEnabled(False)
|
| | self.prev_btn.setEnabled(False)
|
| |
|
| | self.img.show_image(pixmap=self.gen_images[0])
|
| |
|
| | def on_show_next_image(self):
|
| | if self.image_index != len(self.gen_images) - 1 and len(self.gen_images) > 0:
|
| | self.prev_btn.setEnabled(True)
|
| | self.image_index += 1
|
| | self.img.show_image(pixmap=self.gen_images[self.image_index])
|
| | if self.image_index == len(self.gen_images) - 1:
|
| | self.next_btn.setEnabled(False)
|
| |
|
| | def on_show_previous_image(self):
|
| | if self.image_index != 0:
|
| | self.next_btn.setEnabled(True)
|
| | self.image_index -= 1
|
| | self.img.show_image(pixmap=self.gen_images[self.image_index])
|
| | if self.image_index == 0:
|
| | self.prev_btn.setEnabled(False)
|
| |
|
| | def on_open_results_folder(self):
|
| | QDesktopServices.openUrl(
|
| | QUrl.fromLocalFile(self.config.settings.generated_images.path)
|
| | )
|
| |
|
| | def generate_click(self):
|
| | self.img.setText("Please wait...")
|
| | self.before_generation()
|
| | worker = ImageGeneratorWorker(self.generate_image)
|
| | self.parent.threadpool.start(worker)
|
| |
|
| | def before_generation(self):
|
| | """Call this function before running a generation task"""
|
| | self.img.setEnabled(False)
|
| | self.generate.setEnabled(False)
|
| | self.browse_results.setEnabled(False)
|
| |
|
| | def after_generation(self):
|
| | """Call this function after running a generation task"""
|
| | self.img.setEnabled(True)
|
| | self.generate.setEnabled(True)
|
| | self.browse_results.setEnabled(True)
|
| | self.parent.store_dimension_settings()
|
| |
|
| | def on_settings_changed(self):
|
| | self.neg_prompt.setEnabled(
|
| | self.config.settings.lcm_diffusion_setting.use_openvino
|
| | or self.config.settings.lcm_diffusion_setting.use_lcm_lora
|
| | )
|
| |
|