dialogs
This commit is contained in:
parent
296d1ef7d4
commit
cc0ee4dde1
43
jezyki-skryptowe/image-editor/DialogsPanel.py
Normal file
43
jezyki-skryptowe/image-editor/DialogsPanel.py
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
from PyQt6.QtWidgets import QFileDialog, QWidget, QToolBar, QVBoxLayout, QPushButton
|
||||||
|
from PyQt6.QtGui import QIcon
|
||||||
|
from PyQt6.QtCore import pyqtSignal
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from dialogs import DIALOGS
|
||||||
|
|
||||||
|
DIALOG_PROPERTY = "dialog"
|
||||||
|
|
||||||
|
class DialogsPanel(QWidget):
|
||||||
|
result_ready = pyqtSignal(np.ndarray)
|
||||||
|
|
||||||
|
def __init__(self, image_manager):
|
||||||
|
super().__init__()
|
||||||
|
self.mgr = image_manager
|
||||||
|
self.dialog_buttons = []
|
||||||
|
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
for DIALOG in DIALOGS:
|
||||||
|
btn = QPushButton(DIALOG.dialog_name(), self)
|
||||||
|
btn.setProperty(DIALOG_PROPERTY, DIALOG)
|
||||||
|
btn.clicked.connect(self.open_dialog)
|
||||||
|
|
||||||
|
self.dialog_buttons.append(btn)
|
||||||
|
layout.addWidget(btn)
|
||||||
|
|
||||||
|
|
||||||
|
def open_dialog(self):
|
||||||
|
dialog_factory = self.sender().property(DIALOG_PROPERTY)
|
||||||
|
self.dialog = dialog_factory(self.mgr.image())
|
||||||
|
self.dialog.result_ready().connect(lambda img : self.result_ready.emit(img))
|
||||||
|
self.dialog.accepted.connect(self.on_accepted)
|
||||||
|
self.dialog.rejected.connect(self.on_rejected)
|
||||||
|
self.dialog.exec()
|
||||||
|
|
||||||
|
def on_accepted(self):
|
||||||
|
self.mgr.update(self.dialog.last_processed)
|
||||||
|
self.dialog = None
|
||||||
|
|
||||||
|
def on_rejected(self):
|
||||||
|
self.mgr.refresh()
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
import abc
|
|
||||||
from ImageProcessingWorker import ImageProcessingWorker
|
|
||||||
|
|
||||||
from PyQt6.QtWidgets import QApplication, QLabel, QVBoxLayout, QHBoxLayout, QPushButton, QWidget, QFileDialog, QSlider, QLineEdit, QDialog
|
|
||||||
from PyQt6.QtGui import QPixmap, QImage, QColor, QPainter, QPen
|
|
||||||
from PyQt6.QtCore import Qt, QPoint, QThread
|
|
||||||
|
|
||||||
|
|
||||||
class ImageParameterDialog(QDialog):
|
|
||||||
|
|
||||||
def __init__(self, hsv_image):
|
|
||||||
self._hsv_image = hsv_image
|
|
||||||
self.setup_worker()
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
def setup_worker(self):
|
|
||||||
self.worker = ImageProcessingWorker(self._hsv_image, self.process_image)
|
|
||||||
self.update_values_signal = self.worker.update_values
|
|
||||||
self.update_values_signal.connect(self.worker.process_image)
|
|
||||||
|
|
||||||
self.worker.start()
|
|
||||||
|
|
||||||
|
|
||||||
# @abc.abstractmethod
|
|
||||||
def process_image(self,hsv_image, values):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def result_ready(self):
|
|
||||||
return self.worker.result_ready
|
|
||||||
|
|
||||||
def send_to_process(self, values):
|
|
||||||
self.update_values_signal.emit(values)
|
|
||||||
|
|
@ -35,11 +35,41 @@ class ImageProcessingWorker(QThread):
|
||||||
|
|
||||||
img = self.image.copy()
|
img = self.image.copy()
|
||||||
processed_image = self.process_function(img, values)
|
processed_image = self.process_function(img, values)
|
||||||
processed_image = processed_image.astype('uint8')
|
postprocessed_image = self.postprocess(processed_image)
|
||||||
rgb_image = cv2.cvtColor(processed_image, cv2.COLOR_HSV2RGB)
|
|
||||||
|
|
||||||
self.result_ready.emit(rgb_image)
|
self.result_ready.emit(postprocessed_image)
|
||||||
|
|
||||||
|
def postprocess(self, processed_image):
|
||||||
|
return processed_image
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.queue(None)
|
self.queue(None)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
|
|
||||||
|
class RGBImageProcessingWorker(ImageProcessingWorker):
|
||||||
|
def __init__(self, image, process_function):
|
||||||
|
img = image.astype('float32')
|
||||||
|
super().__init__(img, process_function)
|
||||||
|
|
||||||
|
def postprocess(self, processed_image):
|
||||||
|
return processed_image.astype('uint8')
|
||||||
|
|
||||||
|
|
||||||
|
class HSVImageProcessingWorker(ImageProcessingWorker):
|
||||||
|
def __init__(self, image, process_function):
|
||||||
|
img = cv2.cvtColor(image, cv2.COLOR_RGB2HSV).astype('float32')
|
||||||
|
super().__init__(img, process_function)
|
||||||
|
|
||||||
|
def postprocess(self, processed_image):
|
||||||
|
processed_image = processed_image.astype('uint8')
|
||||||
|
return cv2.cvtColor(processed_image, cv2.COLOR_HSV2RGB)
|
||||||
|
|
||||||
|
class HLSImageProcessingWorker(ImageProcessingWorker):
|
||||||
|
def __init__(self, image, process_function):
|
||||||
|
img = cv2.cvtColor(image, cv2.COLOR_RGB2HLS).astype('float32')
|
||||||
|
super().__init__(img, process_function)
|
||||||
|
|
||||||
|
def postprocess(self, processed_image):
|
||||||
|
processed_image = processed_image.astype('uint8')
|
||||||
|
return cv2.cvtColor(processed_image, cv2.COLOR_HLS2RGB)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ from PyQt6.QtWidgets import QApplication, QLabel, QVBoxLayout, QHBoxLayout, QPus
|
||||||
from PyQt6.QtGui import QPixmap, QImage, QColor, QPainter, QPen
|
from PyQt6.QtGui import QPixmap, QImage, QColor, QPainter, QPen
|
||||||
from PyQt6.QtCore import Qt, QPoint, QThread
|
from PyQt6.QtCore import Qt, QPoint, QThread
|
||||||
|
|
||||||
from ImageParameterDialog import ImageParameterDialog
|
from .ImageParameterDialog import ImageParameterDialog
|
||||||
|
|
||||||
|
|
||||||
class HCLDialog(ImageParameterDialog):
|
class HCLDialog(ImageParameterDialog):
|
||||||
|
|
@ -70,3 +70,7 @@ class HCLDialog(ImageParameterDialog):
|
||||||
|
|
||||||
|
|
||||||
return hsv_image
|
return hsv_image
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def dialog_name(cls):
|
||||||
|
return "Hue-Chroma-Lightness"
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
import abc
|
||||||
|
|
||||||
|
from PyQt6.QtWidgets import QWidget, QDialog, QDialogButtonBox
|
||||||
|
from PyQt6.QtGui import QPixmap, QImage, QColor, QPainter, QPen
|
||||||
|
from PyQt6.QtCore import Qt, QPoint, QThread
|
||||||
|
|
||||||
|
|
||||||
|
class ImageParameterDialog(QDialog):
|
||||||
|
|
||||||
|
def __init__(self, image, worker_factory):
|
||||||
|
super().__init__()
|
||||||
|
self._image = image
|
||||||
|
self.last_processed = image
|
||||||
|
self.worker_factory = worker_factory
|
||||||
|
self.setup_worker()
|
||||||
|
|
||||||
|
self.button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
|
||||||
|
self.button_box.accepted.connect(self.accept)
|
||||||
|
self.button_box.rejected.connect(self.reject)
|
||||||
|
|
||||||
|
def setup_worker(self):
|
||||||
|
self.worker = self.worker_factory(self._image, self.process_image)
|
||||||
|
self.worker.result_ready.connect(self._update_last_processed)
|
||||||
|
self.update_values_signal = self.worker.update_values
|
||||||
|
self.update_values_signal.connect(self.worker.process_image)
|
||||||
|
|
||||||
|
self.worker.start()
|
||||||
|
|
||||||
|
def _update_last_processed(self, new_image):
|
||||||
|
self.last_processed = new_image
|
||||||
|
|
||||||
|
def _on_accepted(self):
|
||||||
|
self.worker.stop()
|
||||||
|
self.accept()
|
||||||
|
|
||||||
|
|
||||||
|
# @abc.abstractmethod
|
||||||
|
def process_image(self,image, values):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def result_ready(self):
|
||||||
|
return self.worker.result_ready
|
||||||
|
|
||||||
|
def send_to_process(self, values):
|
||||||
|
self.update_values_signal.emit(values)
|
||||||
|
|
||||||
|
def set_accept_enable(self, value):
|
||||||
|
self.button_box.button(QDialogButtonBox.StandardButton.Ok).setEnabled(value)
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def dialog_name(cls):
|
||||||
|
return cls.__name__
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def dialog_icon(cls):
|
||||||
|
return None
|
||||||
137
jezyki-skryptowe/image-editor/dialogs/ResizeDialog.py
Normal file
137
jezyki-skryptowe/image-editor/dialogs/ResizeDialog.py
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
import ImageProcessingWorker
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import cv2
|
||||||
|
|
||||||
|
from PyQt6.QtWidgets import (QApplication, QLabel, QVBoxLayout, QHBoxLayout, QPushButton, QWidget, QFileDialog, QSlider,
|
||||||
|
QLineEdit, QDialog, QCheckBox, QComboBox)
|
||||||
|
from PyQt6.QtGui import QPixmap, QImage, QColor, QPainter, QPen, QIntValidator
|
||||||
|
from PyQt6.QtCore import Qt, QPoint, QThread
|
||||||
|
|
||||||
|
from .ImageParameterDialog import ImageParameterDialog
|
||||||
|
|
||||||
|
|
||||||
|
INTERPOLATION_MAP = {
|
||||||
|
"Nearest": cv2.INTER_NEAREST,
|
||||||
|
"Linear": cv2.INTER_LINEAR,
|
||||||
|
"Area": cv2.INTER_AREA,
|
||||||
|
"Cubic": cv2.INTER_CUBIC,
|
||||||
|
"Lanczos4": cv2.INTER_LANCZOS4
|
||||||
|
}
|
||||||
|
|
||||||
|
class ResizeDialog(ImageParameterDialog):
|
||||||
|
def __init__(self, image):
|
||||||
|
super().__init__(image, ImageProcessingWorker.ImageProcessingWorker)
|
||||||
|
|
||||||
|
self.original_height, self.original_width, _ = image.shape
|
||||||
|
|
||||||
|
|
||||||
|
self.setWindowTitle("Resizing")
|
||||||
|
self.layout = QVBoxLayout()
|
||||||
|
|
||||||
|
# Width input
|
||||||
|
self.width_label = QLabel("Width:")
|
||||||
|
self.width_field = QLineEdit()
|
||||||
|
self.width_field.setPlaceholderText("Enter width")
|
||||||
|
self.width_field.setText(str(self.original_width))
|
||||||
|
self.width_field.setValidator(QIntValidator(1, 10000))
|
||||||
|
self.width_field.textEdited.connect(self.width_changed)
|
||||||
|
|
||||||
|
# Height input
|
||||||
|
self.height_label = QLabel("Height:")
|
||||||
|
self.height_field = QLineEdit()
|
||||||
|
self.height_field.setPlaceholderText("Enter height")
|
||||||
|
self.height_field.setText(str(self.original_height))
|
||||||
|
self.height_field.setValidator(QIntValidator(1, 10000))
|
||||||
|
self.height_field.textEdited.connect(self.height_changed)
|
||||||
|
|
||||||
|
# Auto-scaling checkbox
|
||||||
|
self.auto_scale_checkbox = QCheckBox("Auto-scale")
|
||||||
|
self.auto_scale_checkbox.setChecked(True)
|
||||||
|
self.auto_scale_checkbox.stateChanged.connect(self.toggle_auto_scale)
|
||||||
|
|
||||||
|
# Interpolation method dropdown
|
||||||
|
self.interpolation_label = QLabel("Interpolation Method:")
|
||||||
|
self.interpolation_dropdown = QComboBox()
|
||||||
|
self.interpolation_dropdown.addItems(list(INTERPOLATION_MAP.keys()))
|
||||||
|
self.interpolation_dropdown.currentIndexChanged.connect(self.update)
|
||||||
|
# Layout for input fields
|
||||||
|
input_layout = QHBoxLayout()
|
||||||
|
input_layout.addWidget(self.width_label)
|
||||||
|
input_layout.addWidget(self.width_field)
|
||||||
|
input_layout.addWidget(self.height_label)
|
||||||
|
input_layout.addWidget(self.height_field)
|
||||||
|
|
||||||
|
self.layout.addLayout(input_layout)
|
||||||
|
self.layout.addWidget(self.auto_scale_checkbox)
|
||||||
|
self.layout.addWidget(self.interpolation_label)
|
||||||
|
self.layout.addWidget(self.interpolation_dropdown)
|
||||||
|
|
||||||
|
self.layout.addWidget(self.button_box)
|
||||||
|
|
||||||
|
self.setLayout(self.layout)
|
||||||
|
|
||||||
|
self.toggle_auto_scale() # Initially disable the width and height fields
|
||||||
|
|
||||||
|
def toggle_auto_scale(self):
|
||||||
|
if self.auto_scale_checkbox.isChecked():
|
||||||
|
self.adjust_height()
|
||||||
|
|
||||||
|
|
||||||
|
def adjust_height(self):
|
||||||
|
if self.auto_scale_checkbox.isChecked():
|
||||||
|
try:
|
||||||
|
width = int(self.width_field.text())
|
||||||
|
height = int((width / self.original_width) * self.original_height)
|
||||||
|
self.height_field.setText(str(height))
|
||||||
|
except ValueError:
|
||||||
|
self.height_field.clear()
|
||||||
|
|
||||||
|
def adjust_width(self):
|
||||||
|
if self.auto_scale_checkbox.isChecked():
|
||||||
|
try:
|
||||||
|
height = int(self.height_field.text())
|
||||||
|
width = int((height / self.original_height) * self.original_width)
|
||||||
|
self.width_field.setText(str(width))
|
||||||
|
except ValueError:
|
||||||
|
self.width_field.clear()
|
||||||
|
|
||||||
|
def height_changed(self):
|
||||||
|
self.adjust_width()
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def width_changed(self):
|
||||||
|
self.adjust_height()
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
width = self.width_field.text()
|
||||||
|
height = self.height_field.text()
|
||||||
|
if (not width or not height):
|
||||||
|
self.set_accept_enable(False)
|
||||||
|
return
|
||||||
|
self.send_to_process({
|
||||||
|
'width': int(width),
|
||||||
|
'height': int(height),
|
||||||
|
'auto_scale': self.auto_scale_checkbox.isChecked(),
|
||||||
|
'interpolation': self.interpolation_dropdown.currentText()
|
||||||
|
})
|
||||||
|
|
||||||
|
def process_image(self, image, values):
|
||||||
|
if values['width'] == 0 or values['height'] == 0:
|
||||||
|
return image
|
||||||
|
|
||||||
|
interpolation = INTERPOLATION_MAP[values['interpolation']]
|
||||||
|
try:
|
||||||
|
resized_image = cv2.resize(image, (values['width'], values['height']), interpolation=interpolation)
|
||||||
|
except:
|
||||||
|
self.set_accept_enable(False)
|
||||||
|
return image
|
||||||
|
self.set_accept_enable(True)
|
||||||
|
return resized_image
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def dialog_name(cls):
|
||||||
|
return "Resize"
|
||||||
8
jezyki-skryptowe/image-editor/dialogs/__init__.py
Normal file
8
jezyki-skryptowe/image-editor/dialogs/__init__.py
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
from .HCLDialog import HCLDialog
|
||||||
|
from .ResizeDialog import ResizeDialog
|
||||||
|
|
||||||
|
|
||||||
|
DIALOGS = [
|
||||||
|
HCLDialog,
|
||||||
|
ResizeDialog
|
||||||
|
]
|
||||||
|
|
@ -7,62 +7,34 @@ import numpy as np
|
||||||
|
|
||||||
from ImageCanvas import ImageCanvas
|
from ImageCanvas import ImageCanvas
|
||||||
from ImageProcessingWorker import ImageProcessingWorker
|
from ImageProcessingWorker import ImageProcessingWorker
|
||||||
from HueDialog import HueDialog
|
from ImageManager import ImageManager
|
||||||
|
from ImageManagePanel import ImageManagePanel
|
||||||
def process_image_function(image, values):
|
from DialogsPanel import DialogsPanel
|
||||||
saturation = values.get('saturation', 0.0)
|
|
||||||
contrast = values.get('contrast', 1.0)
|
|
||||||
brightness = values.get('brightness', 0)
|
|
||||||
|
|
||||||
|
|
||||||
# Adjust saturation
|
|
||||||
hsv_image[:, :, 1] += saturation * 255
|
|
||||||
hsv_image[:, :, 1] = np.clip(hsv_image[:, :, 1], 0, 255)
|
|
||||||
|
|
||||||
# Adjust brightness and contrast
|
|
||||||
hsv_image[:, :, 2] = np.clip(hsv_image[:, :, 2] * contrast + brightness, 0, 255)
|
|
||||||
|
|
||||||
|
|
||||||
return rgb_image
|
|
||||||
|
|
||||||
|
|
||||||
class ImageEditor(QWidget):
|
class ImageEditor(QWidget):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
|
||||||
self.setWindowTitle("Image Editor")
|
self.setWindowTitle("Image Editor")
|
||||||
self.setGeometry(100, 100, 800, 600)
|
self.setGeometry(100, 100, 800, 600)
|
||||||
|
|
||||||
self.canvas = ImageCanvas()
|
self.canvas = ImageCanvas()
|
||||||
|
|
||||||
# self.image_label = QLabel()
|
self.img_manager = ImageManagePanel()
|
||||||
# self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
self.img_manager.on_update.connect(self.display_image)
|
||||||
|
self.img_manager.on_close.connect(lambda : self.canvas.clear())
|
||||||
|
|
||||||
self.open_button = QPushButton("Open Image")
|
self.dialogs_panel = DialogsPanel(self.img_manager.mgr)
|
||||||
self.open_button.clicked.connect(self.open_image)
|
self.dialogs_panel.result_ready.connect(self.display_image)
|
||||||
|
|
||||||
self.save_button = QPushButton("Save Image")
|
|
||||||
self.save_button.clicked.connect(self.save_image)
|
|
||||||
|
|
||||||
self.hcl_button = QPushButton("Hue-Chroma-Lightness")
|
|
||||||
self.hcl_button.clicked.connect(self.open_hcl)
|
|
||||||
|
|
||||||
|
|
||||||
self.resolution_label = QLabel("Resolution:")
|
|
||||||
self.width_input = QLineEdit()
|
|
||||||
self.height_input = QLineEdit()
|
|
||||||
|
|
||||||
self.aspect_ratio_label = QLabel("Aspect Ratio:")
|
|
||||||
self.aspect_ratio_input = QLineEdit()
|
|
||||||
|
|
||||||
|
|
||||||
main_layout = QHBoxLayout()
|
main_layout = QHBoxLayout()
|
||||||
|
|
||||||
side_panel = QVBoxLayout()
|
side_panel = QVBoxLayout()
|
||||||
|
|
||||||
side_panel.addWidget(self.open_button)
|
side_panel.addWidget(self.img_manager, 1)
|
||||||
side_panel.addWidget(self.save_button)
|
side_panel.addWidget(self.dialogs_panel, 9)
|
||||||
side_panel.addWidget(self.hcl_button)
|
|
||||||
|
|
||||||
preview_panel = QVBoxLayout()
|
preview_panel = QVBoxLayout()
|
||||||
preview_panel.addWidget(self.canvas)
|
preview_panel.addWidget(self.canvas)
|
||||||
|
|
@ -75,55 +47,15 @@ class ImageEditor(QWidget):
|
||||||
self.setLayout(main_layout)
|
self.setLayout(main_layout)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def open_image(self):
|
|
||||||
file_name, _ = QFileDialog.getOpenFileName(self, "Open Image File", "", "Image Files (*.jpg *.jpeg *.png)")
|
|
||||||
if file_name:
|
|
||||||
self.image = cv2.imread(file_name)
|
|
||||||
self.image = cv2.cvtColor(self.image, cv2.COLOR_BGR2RGB)
|
|
||||||
|
|
||||||
self.image_as_hsv = cv2.cvtColor(self.image, cv2.COLOR_RGB2HSV).astype('float32')
|
|
||||||
|
|
||||||
self.display_image(self.image, first_load=True)
|
|
||||||
|
|
||||||
def display_image(self, image, first_load = False):
|
def display_image(self, image, first_load = False):
|
||||||
height, width, channel = image.shape
|
height, width, channel = image.shape
|
||||||
bytes_per_line = 3 * width
|
bytes_per_line = 3 * width
|
||||||
q_image = QPixmap.fromImage(QImage(image.data, width, height, bytes_per_line, QImage.Format.Format_RGB888))
|
|
||||||
self.canvas.updatePixmap(QImage(image.data, width, height, bytes_per_line, QImage.Format.Format_RGB888))
|
self.canvas.updatePixmap(QImage(image.data, width, height, bytes_per_line, QImage.Format.Format_RGB888))
|
||||||
|
|
||||||
if first_load:
|
if first_load:
|
||||||
self.canvas.reset()
|
self.canvas.reset()
|
||||||
|
|
||||||
def save_image(self):
|
|
||||||
file_name, _ = QFileDialog.getSaveFileName(self, "Save Image File", "", "Image Files (*.jpg *.png)")
|
|
||||||
if file_name and hasattr(self, 'image'):
|
|
||||||
cv2.imwrite(file_name, cv2.cvtColor(self.image, cv2.COLOR_RGB2BGR))
|
|
||||||
|
|
||||||
def open_hcl(self):
|
|
||||||
self.dialog = HueDialog(self.image_as_hsv)
|
|
||||||
self.dialog.result_ready().connect(self.display_image)
|
|
||||||
self.dialog.exec()
|
|
||||||
|
|
||||||
|
|
||||||
def update_image(self):
|
|
||||||
print(self.saturation_slider.value(), self.contrast_slider.value(), self.brightness_slider.value())
|
|
||||||
if self.image_as_hsv is not None:
|
|
||||||
if self.worker is None:
|
|
||||||
self.setup_worker()
|
|
||||||
|
|
||||||
values = {
|
|
||||||
'saturation': self.saturation_slider.value() / 100.0,
|
|
||||||
'contrast': self.contrast_slider.value() / 100.0,
|
|
||||||
'brightness': self.brightness_slider.value()
|
|
||||||
}
|
|
||||||
self.update_values_signal.emit(values) # Emit new values to the worker
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user