shinestacker 1.5.4__py3-none-any.whl → 1.6.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of shinestacker might be problematic. Click here for more details.
- shinestacker/_version.py +1 -1
- shinestacker/algorithms/multilayer.py +1 -1
- shinestacker/algorithms/stack.py +17 -9
- shinestacker/app/args_parser_opts.py +4 -0
- shinestacker/app/gui_utils.py +10 -2
- shinestacker/app/main.py +8 -3
- shinestacker/app/project.py +7 -3
- shinestacker/app/retouch.py +8 -1
- shinestacker/app/settings_dialog.py +171 -0
- shinestacker/config/app_config.py +30 -0
- shinestacker/config/constants.py +3 -0
- shinestacker/config/gui_constants.py +4 -2
- shinestacker/config/settings.py +110 -0
- shinestacker/core/core_utils.py +3 -12
- shinestacker/core/logging.py +3 -2
- shinestacker/gui/action_config.py +6 -5
- shinestacker/gui/action_config_dialog.py +17 -74
- shinestacker/gui/config_dialog.py +78 -0
- shinestacker/gui/main_window.py +6 -6
- shinestacker/gui/menu_manager.py +2 -0
- shinestacker/gui/new_project.py +2 -1
- shinestacker/gui/project_controller.py +8 -6
- shinestacker/gui/project_model.py +16 -1
- shinestacker/gui/recent_file_manager.py +3 -21
- shinestacker/retouch/base_filter.py +1 -1
- shinestacker/retouch/display_manager.py +48 -7
- shinestacker/retouch/image_editor_ui.py +27 -36
- shinestacker/retouch/image_view_status.py +4 -1
- shinestacker/retouch/image_viewer.py +17 -9
- shinestacker/retouch/io_gui_handler.py +96 -44
- shinestacker/retouch/io_threads.py +78 -0
- shinestacker/retouch/layer_collection.py +12 -0
- shinestacker/retouch/overlaid_view.py +13 -5
- shinestacker/retouch/paint_area_manager.py +30 -0
- shinestacker/retouch/sidebyside_view.py +32 -16
- shinestacker/retouch/transformation_manager.py +1 -3
- shinestacker/retouch/undo_manager.py +15 -13
- shinestacker/retouch/view_strategy.py +79 -26
- {shinestacker-1.5.4.dist-info → shinestacker-1.6.1.dist-info}/METADATA +1 -1
- {shinestacker-1.5.4.dist-info → shinestacker-1.6.1.dist-info}/RECORD +44 -39
- shinestacker/retouch/io_manager.py +0 -69
- {shinestacker-1.5.4.dist-info → shinestacker-1.6.1.dist-info}/WHEEL +0 -0
- {shinestacker-1.5.4.dist-info → shinestacker-1.6.1.dist-info}/entry_points.txt +0 -0
- {shinestacker-1.5.4.dist-info → shinestacker-1.6.1.dist-info}/licenses/LICENSE +0 -0
- {shinestacker-1.5.4.dist-info → shinestacker-1.6.1.dist-info}/top_level.txt +0 -0
|
@@ -6,13 +6,10 @@ from .. config.gui_constants import gui_constants
|
|
|
6
6
|
class UndoManager(QObject):
|
|
7
7
|
stack_changed = Signal(bool, str, bool, str)
|
|
8
8
|
|
|
9
|
-
def __init__(self, transformation_manager):
|
|
9
|
+
def __init__(self, transformation_manager, paint_area_manager):
|
|
10
10
|
super().__init__()
|
|
11
11
|
self.transformation_manager = transformation_manager
|
|
12
|
-
self.
|
|
13
|
-
self.y_start = None
|
|
14
|
-
self.x_end = None
|
|
15
|
-
self.y_end = None
|
|
12
|
+
self.paint_area_manager = paint_area_manager
|
|
16
13
|
self.undo_stack = None
|
|
17
14
|
self.redo_stack = None
|
|
18
15
|
self.reset()
|
|
@@ -24,22 +21,25 @@ class UndoManager(QObject):
|
|
|
24
21
|
self.stack_changed.emit(False, "", False, "")
|
|
25
22
|
|
|
26
23
|
def reset_undo_area(self):
|
|
27
|
-
self.
|
|
28
|
-
self.x_start = self.y_start = gui_constants.MAX_UNDO_SIZE
|
|
24
|
+
self.paint_area_manager.reset()
|
|
29
25
|
|
|
30
26
|
def extend_undo_area(self, x_start, y_start, x_end, y_end):
|
|
31
|
-
self.x_start
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
self.
|
|
27
|
+
self.paint_area_manager.extend(x_start, y_start, x_end, y_end)
|
|
28
|
+
|
|
29
|
+
def paint_area(self):
|
|
30
|
+
return self.paint_area_manager.area()
|
|
31
|
+
|
|
32
|
+
def set_paint_area(self, x_start, y_start, x_end, y_end):
|
|
33
|
+
self.paint_area_manager.set_area(x_start, y_start, x_end, y_end)
|
|
35
34
|
|
|
36
35
|
def save_undo_state(self, layer, description):
|
|
37
36
|
if layer is None:
|
|
38
37
|
return
|
|
39
38
|
self.redo_stack = []
|
|
39
|
+
x_start, y_start, x_end, y_end = self.paint_area()
|
|
40
40
|
undo_state = {
|
|
41
|
-
'master': layer[
|
|
42
|
-
'area': (
|
|
41
|
+
'master': layer[y_start:y_end, x_start:x_end].copy(),
|
|
42
|
+
'area': (x_start, y_start, x_end, y_end),
|
|
43
43
|
'description': description
|
|
44
44
|
}
|
|
45
45
|
if len(self.undo_stack) >= gui_constants.MAX_UNDO_SIZE:
|
|
@@ -54,6 +54,7 @@ class UndoManager(QObject):
|
|
|
54
54
|
return False
|
|
55
55
|
undo_state = self.undo_stack.pop()
|
|
56
56
|
x_start, y_start, x_end, y_end = undo_state['area']
|
|
57
|
+
self.set_paint_area(x_start, y_start, x_end, y_end)
|
|
57
58
|
redo_state = {
|
|
58
59
|
'master': layer[y_start:y_end, x_start:x_end].copy(),
|
|
59
60
|
'area': (x_start, y_start, x_end, y_end),
|
|
@@ -80,6 +81,7 @@ class UndoManager(QObject):
|
|
|
80
81
|
return False
|
|
81
82
|
redo_state = self.redo_stack.pop()
|
|
82
83
|
x_start, y_start, x_end, y_end = redo_state['area']
|
|
84
|
+
self.set_paint_area(x_start, y_start, x_end, y_end)
|
|
83
85
|
undo_state = {
|
|
84
86
|
'master': layer[y_start:y_end, x_start:x_end].copy(),
|
|
85
87
|
'area': (x_start, y_start, x_end, y_end),
|
|
@@ -9,6 +9,7 @@ from PySide6.QtWidgets import (
|
|
|
9
9
|
QGraphicsEllipseItem, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem,
|
|
10
10
|
QGraphicsItemGroup, QGraphicsPathItem)
|
|
11
11
|
from .. config.gui_constants import gui_constants
|
|
12
|
+
from .. config.app_config import AppConfig
|
|
12
13
|
from .layer_collection import LayerCollectionHandler
|
|
13
14
|
from .brush_gradient import create_default_brush_gradient
|
|
14
15
|
from .brush_preview import BrushPreviewItem
|
|
@@ -78,10 +79,9 @@ class BrushCursor(QGraphicsItemGroup):
|
|
|
78
79
|
|
|
79
80
|
class ViewSignals:
|
|
80
81
|
temp_view_requested = Signal(bool)
|
|
81
|
-
|
|
82
|
-
brush_operation_continued = Signal(QPoint)
|
|
83
|
-
brush_operation_ended = Signal()
|
|
82
|
+
end_copy_brush_area_requested = Signal()
|
|
84
83
|
brush_size_change_requested = Signal(int) # +1 or -1
|
|
84
|
+
needs_update_requested = Signal()
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
class ImageGraphicsViewBase(QGraphicsView):
|
|
@@ -102,9 +102,12 @@ class ImageGraphicsViewBase(QGraphicsView):
|
|
|
102
102
|
|
|
103
103
|
|
|
104
104
|
class ViewStrategy(LayerCollectionHandler):
|
|
105
|
-
def __init__(self, layer_collection, status):
|
|
105
|
+
def __init__(self, layer_collection, status, brush_tool, paint_area_manager):
|
|
106
106
|
LayerCollectionHandler.__init__(self, layer_collection)
|
|
107
107
|
self.status = status
|
|
108
|
+
self.brush_tool = brush_tool
|
|
109
|
+
self.paint_area_manager = paint_area_manager
|
|
110
|
+
self.mask_layer = None
|
|
108
111
|
self.brush = None
|
|
109
112
|
self.brush_cursor = None
|
|
110
113
|
self.brush_preview = BrushPreviewItem(layer_collection)
|
|
@@ -121,6 +124,8 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
121
124
|
self.last_mouse_pos = None
|
|
122
125
|
self.last_update_time = QTime.currentTime()
|
|
123
126
|
self.last_color_update_time = 0
|
|
127
|
+
self.last_cursor_update_time = 0
|
|
128
|
+
self.enable_paint = True
|
|
124
129
|
|
|
125
130
|
@abstractmethod
|
|
126
131
|
def create_pixmaps(self):
|
|
@@ -245,6 +250,8 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
245
250
|
|
|
246
251
|
def set_cursor_style(self, style):
|
|
247
252
|
self.cursor_style = style
|
|
253
|
+
if style != 'simple' and self.brush_cursor:
|
|
254
|
+
self.brush_cursor.setBrush(Qt.NoBrush)
|
|
248
255
|
if style == 'preview':
|
|
249
256
|
self.show_brush_preview()
|
|
250
257
|
self.update_brush_cursor()
|
|
@@ -270,6 +277,25 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
270
277
|
view.verticalScrollBar().setValue(self.status.v_scroll)
|
|
271
278
|
self.arrange_images()
|
|
272
279
|
|
|
280
|
+
def update_master_display_area(self):
|
|
281
|
+
if self.empty():
|
|
282
|
+
return
|
|
283
|
+
x_start, y_start, x_end, y_end = self.paint_area_manager.area()
|
|
284
|
+
dirty_region = self.master_layer()[y_start:y_end, x_start:x_end]
|
|
285
|
+
qimage = self.numpy_to_qimage(dirty_region)
|
|
286
|
+
if not qimage:
|
|
287
|
+
return
|
|
288
|
+
pixmap = QPixmap.fromImage(qimage)
|
|
289
|
+
master_pixmap_item = self.get_master_pixmap()
|
|
290
|
+
current_pixmap = master_pixmap_item.pixmap()
|
|
291
|
+
if current_pixmap.isNull():
|
|
292
|
+
self.update_master_display()
|
|
293
|
+
return
|
|
294
|
+
painter = QPainter(current_pixmap)
|
|
295
|
+
painter.drawPixmap(x_start, y_start, pixmap)
|
|
296
|
+
painter.end()
|
|
297
|
+
master_pixmap_item.setPixmap(current_pixmap)
|
|
298
|
+
|
|
273
299
|
def update_master_display(self):
|
|
274
300
|
self.update_view_display(
|
|
275
301
|
self.master_layer(),
|
|
@@ -283,7 +309,7 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
283
309
|
self.update_view_display(
|
|
284
310
|
self.current_layer(),
|
|
285
311
|
self.get_current_pixmap(),
|
|
286
|
-
self.
|
|
312
|
+
self.get_current_scene(),
|
|
287
313
|
self.get_current_view())
|
|
288
314
|
|
|
289
315
|
def update_cursor_pen_width(self):
|
|
@@ -694,18 +720,60 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
694
720
|
self.status.set_scroll(view.horizontalScrollBar().value(),
|
|
695
721
|
view.verticalScrollBar().value())
|
|
696
722
|
|
|
723
|
+
def copy_brush_area_to_master(self, view_pos):
|
|
724
|
+
if self.layer_stack() is None or self.number_of_layers() == 0:
|
|
725
|
+
return
|
|
726
|
+
area = self.brush_tool.apply_brush_operation(
|
|
727
|
+
self.master_layer_copy(),
|
|
728
|
+
self.current_layer(),
|
|
729
|
+
self.master_layer(), self.mask_layer,
|
|
730
|
+
view_pos)
|
|
731
|
+
self.paint_area_manager.extend(*area)
|
|
732
|
+
|
|
733
|
+
def begin_copy_brush_area(self, pos):
|
|
734
|
+
self.mask_layer = self.blank_layer().copy()
|
|
735
|
+
self.copy_master_layer()
|
|
736
|
+
self.paint_area_manager.reset()
|
|
737
|
+
self.copy_brush_area_to_master(pos)
|
|
738
|
+
self.needs_update_requested.emit()
|
|
739
|
+
|
|
740
|
+
def continue_copy_brush_area(self, pos):
|
|
741
|
+
self.copy_brush_area_to_master(pos)
|
|
742
|
+
self.needs_update_requested.emit()
|
|
743
|
+
|
|
744
|
+
def mouse_press_event(self, event):
|
|
745
|
+
if self.empty():
|
|
746
|
+
return
|
|
747
|
+
if self.enable_paint and event.button() & Qt.LeftButton and self.has_master_layer():
|
|
748
|
+
if self.space_pressed:
|
|
749
|
+
self.scrolling = True
|
|
750
|
+
self.last_mouse_pos = event.position()
|
|
751
|
+
self.setCursor(Qt.ClosedHandCursor)
|
|
752
|
+
else:
|
|
753
|
+
self.last_brush_pos = event.position()
|
|
754
|
+
self.begin_copy_brush_area(event.position().toPoint())
|
|
755
|
+
self.dragging = True
|
|
756
|
+
if not self.scrolling:
|
|
757
|
+
self.show_brush_cursor()
|
|
758
|
+
|
|
697
759
|
def mouse_move_event(self, event):
|
|
698
760
|
if self.empty():
|
|
699
761
|
return
|
|
762
|
+
current_time = time.time() * 1000 # ms
|
|
763
|
+
cursor_update_interval = AppConfig.get('cursor_update_time')
|
|
764
|
+
if current_time - self.last_cursor_update_time < cursor_update_interval:
|
|
765
|
+
return
|
|
766
|
+
self.last_cursor_update_time = current_time
|
|
700
767
|
position = event.position()
|
|
701
768
|
brush_size = self.brush.size
|
|
702
769
|
if not self.space_pressed:
|
|
703
770
|
self.update_brush_cursor()
|
|
704
|
-
if self.dragging and event.buttons() & Qt.LeftButton:
|
|
771
|
+
if self.enable_paint and self.dragging and event.buttons() & Qt.LeftButton:
|
|
705
772
|
current_time = QTime.currentTime()
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
773
|
+
paint_refresh_time = AppConfig.get('paint_refresh_time')
|
|
774
|
+
if self.last_update_time.msecsTo(current_time) >= paint_refresh_time:
|
|
775
|
+
min_step = AppConfig.get('min_mouse_step_brush_fraction')
|
|
776
|
+
min_step = brush_size * min_step * self.zoom_factor()
|
|
709
777
|
x, y = position.x(), position.y()
|
|
710
778
|
xp, yp = self.last_brush_pos.x(), self.last_brush_pos.y()
|
|
711
779
|
distance = math.sqrt((x - xp)**2 + (y - yp)**2)
|
|
@@ -716,7 +784,7 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
716
784
|
for i in range(0, n_steps + 1):
|
|
717
785
|
pos = QPoint(self.last_brush_pos.x() + i * delta_x,
|
|
718
786
|
self.last_brush_pos.y() + i * delta_y)
|
|
719
|
-
self.
|
|
787
|
+
self.continue_copy_brush_area(pos)
|
|
720
788
|
self.last_brush_pos = position
|
|
721
789
|
self.last_update_time = current_time
|
|
722
790
|
if self.scrolling and event.buttons() & Qt.LeftButton:
|
|
@@ -728,21 +796,6 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
728
796
|
self.last_mouse_pos = position
|
|
729
797
|
self.scroll_view(master_view, delta.x(), delta.y())
|
|
730
798
|
|
|
731
|
-
def mouse_press_event(self, event):
|
|
732
|
-
if self.empty():
|
|
733
|
-
return
|
|
734
|
-
if event.button() == Qt.LeftButton and self.has_master_layer():
|
|
735
|
-
if self.space_pressed:
|
|
736
|
-
self.scrolling = True
|
|
737
|
-
self.last_mouse_pos = event.position()
|
|
738
|
-
self.setCursor(Qt.ClosedHandCursor)
|
|
739
|
-
else:
|
|
740
|
-
self.last_brush_pos = event.position()
|
|
741
|
-
self.brush_operation_started.emit(event.position().toPoint())
|
|
742
|
-
self.dragging = True
|
|
743
|
-
if not self.scrolling:
|
|
744
|
-
self.show_brush_cursor()
|
|
745
|
-
|
|
746
799
|
def mouse_release_event(self, event):
|
|
747
800
|
if self.empty():
|
|
748
801
|
return
|
|
@@ -759,4 +812,4 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
759
812
|
self.last_mouse_pos = None
|
|
760
813
|
elif self.dragging:
|
|
761
814
|
self.dragging = False
|
|
762
|
-
self.
|
|
815
|
+
self.end_copy_brush_area_requested.emit()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
shinestacker/__init__.py,sha256=uq2fjAw2z_6TpH3mOcWFZ98GoEPRsNhTAK8N0MMm_e8,448
|
|
2
|
-
shinestacker/_version.py,sha256=
|
|
2
|
+
shinestacker/_version.py,sha256=DH87PU9LcZeI_uvttoH-lyhGyb55UShgeFtsG2qIZgE,21
|
|
3
3
|
shinestacker/algorithms/__init__.py,sha256=1FwVJ3w9GGbFFkjYJRUedTvcdE4j0ieSgaH9RC9iCY4,877
|
|
4
4
|
shinestacker/algorithms/align.py,sha256=mb44u-YxZI1TTSHz81nRpX_2c8awlOhnGrK0LyfTQeQ,33543
|
|
5
5
|
shinestacker/algorithms/align_auto.py,sha256=pJetw6zZEWQLouzcelkI8gD4cPiOp887ePXzVbm0E6Q,3800
|
|
@@ -9,54 +9,58 @@ shinestacker/algorithms/base_stack_algo.py,sha256=RzxvLDHqxqhnAl83u2onjvfsRea1qG
|
|
|
9
9
|
shinestacker/algorithms/denoise.py,sha256=GL3Z4_6MHxSa7Wo4ZzQECZS87tHBFqO0sIVF_jPuYQU,426
|
|
10
10
|
shinestacker/algorithms/depth_map.py,sha256=nRBrZQWbdUqFOtYMEQx9UNdnybrBTeAOr1eV91FlN8U,5611
|
|
11
11
|
shinestacker/algorithms/exif.py,sha256=SM4ZDDe8hCJ3xY6053FNndOiwzEStzdp0WrXurlcHVc,9429
|
|
12
|
-
shinestacker/algorithms/multilayer.py,sha256=
|
|
12
|
+
shinestacker/algorithms/multilayer.py,sha256=EEMDr2NlCU9DCFO5ykbBrY-2q9oBUD0-ctm7x0IXU5U,9911
|
|
13
13
|
shinestacker/algorithms/noise_detection.py,sha256=myUiLKYC3Ph62j28upUd_7rZum_JpqyxiN33nZN35zE,9346
|
|
14
14
|
shinestacker/algorithms/pyramid.py,sha256=Z7tlp8Hh3ploAXJCr0VNe33d8H9GNrlqHXq_LapgRwo,8205
|
|
15
15
|
shinestacker/algorithms/pyramid_auto.py,sha256=fl_jXNYLWsBiX0M0UghzCLqai0SGXlmKYHU7Z9SUYSo,6173
|
|
16
16
|
shinestacker/algorithms/pyramid_tiles.py,sha256=ZBWIeifkDOIVFF4SCyspRZHSj6K_1P3dk4WLmuo53RU,12213
|
|
17
17
|
shinestacker/algorithms/sharpen.py,sha256=h7PMJBYxucg194Usp_6pvItPUMFYbT-ebAc_-7XBFUw,949
|
|
18
|
-
shinestacker/algorithms/stack.py,sha256=
|
|
18
|
+
shinestacker/algorithms/stack.py,sha256=p9bLCbMjDMm7rX_FRfgXRTEJAj3GhNPOCvwePE9hVmc,5549
|
|
19
19
|
shinestacker/algorithms/stack_framework.py,sha256=OMrjD5dKquHQXhM7TfLRExDsqN1n938WWhGAfkPYLZM,13883
|
|
20
20
|
shinestacker/algorithms/utils.py,sha256=l6GJpEXpzDr_ml9Not03a1_F7wYvPwn8JkEWDuNwL9o,12116
|
|
21
21
|
shinestacker/algorithms/vignetting.py,sha256=gJOv-FN3GnTgaVn70W_6d-qbw3WmqinDiO9oL053cus,10351
|
|
22
22
|
shinestacker/algorithms/white_balance.py,sha256=PMKsBtxOSn5aRr_Gkx1StHS4eN6kBN2EhNnhg4UG24g,501
|
|
23
23
|
shinestacker/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
24
|
shinestacker/app/about_dialog.py,sha256=pkH7nnxUP8yc0D3vRGd1jRb5cwi1nDVbQRk_OC9yLk8,4144
|
|
25
|
-
shinestacker/app/args_parser_opts.py,sha256=
|
|
26
|
-
shinestacker/app/gui_utils.py,sha256=
|
|
25
|
+
shinestacker/app/args_parser_opts.py,sha256=c6IUXOI0SJIFckPWPXYnwmBmdNnOcrtvU5S8hUDU_AQ,979
|
|
26
|
+
shinestacker/app/gui_utils.py,sha256=EGZejp0XZXRLVa_Wd_2VYAwK3oe9hMSoZzNgT7NUNRw,2986
|
|
27
27
|
shinestacker/app/help_menu.py,sha256=g8lKG_xZmXtNQaC3SIRzyROKVWva_PLEgZsQWh6zUcQ,499
|
|
28
|
-
shinestacker/app/main.py,sha256=
|
|
28
|
+
shinestacker/app/main.py,sha256=OQwPJvhrsAThv9kmiqtX7CX-smfwXdFXagQmGsQdmuU,11258
|
|
29
29
|
shinestacker/app/open_frames.py,sha256=bsu32iJSYJQLe_tQQbvAU5DuMDVX6MRuNdE7B5lojZc,1488
|
|
30
|
-
shinestacker/app/project.py,sha256=
|
|
31
|
-
shinestacker/app/retouch.py,sha256=
|
|
30
|
+
shinestacker/app/project.py,sha256=jn4LlMTMxrJeAyQQrR5nVS4Di1rOrjiOJ8LOg0CZbwE,3045
|
|
31
|
+
shinestacker/app/retouch.py,sha256=fyk74fgpeoBqY1mRJiXWf1hRzSeG7xXFx4V-Sphr3Kg,3069
|
|
32
|
+
shinestacker/app/settings_dialog.py,sha256=0P3nqqZEiTIFgidW1_e3Q_zE7NbAouNsuj-yNsU41vk,8192
|
|
32
33
|
shinestacker/config/__init__.py,sha256=aXxi-LmAvXd0daIFrVnTHE5OCaYeK1uf1BKMr7oaXQs,197
|
|
34
|
+
shinestacker/config/app_config.py,sha256=rM1Rndk1GDa5c0AhcVNEN9zSAzxPZixzQYfjODbJUwE,771
|
|
33
35
|
shinestacker/config/config.py,sha256=eBko2D3ADhLTIm9X6hB_a_WsIjwgfE-qmBVkhP1XSvc,1636
|
|
34
|
-
shinestacker/config/constants.py,sha256=
|
|
35
|
-
shinestacker/config/gui_constants.py,sha256=
|
|
36
|
+
shinestacker/config/constants.py,sha256=Z7QjaklrYYsPjTX68Tjyh_wCOuYyQPBR8dnYrZfNwA8,8376
|
|
37
|
+
shinestacker/config/gui_constants.py,sha256=PNxzwmVEppJ2mV_vwp68NhWzJOEitVy1Pk9SwSmRsho,2882
|
|
38
|
+
shinestacker/config/settings.py,sha256=4p4r6wKOCbttzfH9tyHQSTd-iv-GfgCd1LxI3C7WIjU,3861
|
|
36
39
|
shinestacker/core/__init__.py,sha256=IUEIx6SQ3DygDEHN3_E6uKpHjHtUa4a_U_1dLd_8yEU,484
|
|
37
40
|
shinestacker/core/colors.py,sha256=kr_tJA1iRsdck2JaYDb2lS-codZ4Ty9gdu3kHfiWvuM,1340
|
|
38
|
-
shinestacker/core/core_utils.py,sha256=
|
|
41
|
+
shinestacker/core/core_utils.py,sha256=wmpu9_idDRe866JFEylMvGPJRT8lSVhikK9PljcbPSI,1392
|
|
39
42
|
shinestacker/core/exceptions.py,sha256=2-noG-ORAGdvDhL8jBQFs0xxZS4fI6UIkMqrWekgk2c,1618
|
|
40
43
|
shinestacker/core/framework.py,sha256=QaTfnzEUHwzlbyFG7KzeyteckTSWHWEEJE4d5Tc8H18,11015
|
|
41
|
-
shinestacker/core/logging.py,sha256=
|
|
44
|
+
shinestacker/core/logging.py,sha256=T-ZTGYjN2n2_5Vu2mBJ2id9qj1c9NA79OD2H2w-W0nM,3096
|
|
42
45
|
shinestacker/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
|
-
shinestacker/gui/action_config.py,sha256=
|
|
44
|
-
shinestacker/gui/action_config_dialog.py,sha256=
|
|
46
|
+
shinestacker/gui/action_config.py,sha256=Xv7SGbhPl1F_dUnU04VBt_E-wIItnN_q6QuhU_d9GfI,25929
|
|
47
|
+
shinestacker/gui/action_config_dialog.py,sha256=QN95FiVPYL6uin2sYO5F7tq6G5rBWh9yRkeTVvwKrwU,38341
|
|
45
48
|
shinestacker/gui/base_form_dialog.py,sha256=KAUQNtmJazttmOIe4E4pFifbtvcByTAhtCmcIYeA4UE,766
|
|
46
49
|
shinestacker/gui/colors.py,sha256=-HaFprDuzRSKjXoZfX1rdOuvawQAkazqdgLBEiZcFII,1476
|
|
50
|
+
shinestacker/gui/config_dialog.py,sha256=yt3nvh0HPHQuCn3AFlzlIHUJnnxcz-Rrw3W3jS9ZYiE,3447
|
|
47
51
|
shinestacker/gui/flow_layout.py,sha256=3yBU_z7VtvHKpx1H97CHVd81eq9pe1Dcja2EZBGGKcI,3791
|
|
48
52
|
shinestacker/gui/folder_file_selection.py,sha256=IYWfZQFkoD5iO7zJ7BxVVDP9F3Dc0EXLILAhL4q-Cb8,4117
|
|
49
53
|
shinestacker/gui/gui_images.py,sha256=k39DpdsxcmYoRdHNNZj6OpFAas0GOHS4JSG542wfheg,5728
|
|
50
54
|
shinestacker/gui/gui_logging.py,sha256=kiZcrC2AFYCWgPZo0O5SKw-E5cFrezwf4anS3HjPuNw,8168
|
|
51
55
|
shinestacker/gui/gui_run.py,sha256=zr7x4BVmM0n_ZRsSEaJVVKvHSWHuwhftgkUvgeg90gU,15767
|
|
52
|
-
shinestacker/gui/main_window.py,sha256=
|
|
53
|
-
shinestacker/gui/menu_manager.py,sha256=
|
|
54
|
-
shinestacker/gui/new_project.py,sha256=
|
|
55
|
-
shinestacker/gui/project_controller.py,sha256=
|
|
56
|
+
shinestacker/gui/main_window.py,sha256=0G-ZjSVKY_rCK_DmstRn3wxOdvS5i3Ba3FBR2ijxpe0,25220
|
|
57
|
+
shinestacker/gui/menu_manager.py,sha256=q4m3cBSxUR68gexpwfIROVRKJ86zp-XPZVrohh1PfQU,11786
|
|
58
|
+
shinestacker/gui/new_project.py,sha256=XMv1ttYrkuqaN9629anXtVSn1bxosgyJpxSFPjlVryU,16437
|
|
59
|
+
shinestacker/gui/project_controller.py,sha256=MYv8QJNXUdc7r1K5D6LnBbds9YalCKSAo_CaO6b0TO8,16636
|
|
56
60
|
shinestacker/gui/project_converter.py,sha256=Gmna0HwbvACcXiX74TaQYumif8ZV8sZ2APLTMM-L1mU,7436
|
|
57
61
|
shinestacker/gui/project_editor.py,sha256=lSgQ42IoaobHs-NQQWT88Qhg5l7nu5ejxAO5VgIupr8,25498
|
|
58
|
-
shinestacker/gui/project_model.py,sha256=
|
|
59
|
-
shinestacker/gui/recent_file_manager.py,sha256=
|
|
62
|
+
shinestacker/gui/project_model.py,sha256=9dId8N-np4YHDpz_wO20Mvd06np3YKlej-0TMWaA_WE,4833
|
|
63
|
+
shinestacker/gui/recent_file_manager.py,sha256=010bciuirKLiVCfOAKs0uFlB3iUjHNBlPX_9K2vH5j0,2916
|
|
60
64
|
shinestacker/gui/select_path_widget.py,sha256=HSwgSr702w5Et4c-6nkRXnIpm1KFqKJetAF5xQNa5zI,1017
|
|
61
65
|
shinestacker/gui/sys_mon.py,sha256=zU41YYVeqQ1-v6oGIh2_BFzQWq87keN-398Wdm59-Nk,3526
|
|
62
66
|
shinestacker/gui/tab_widget.py,sha256=VgRmuktWXCgbXbV7c1Tho0--W5_EmmzXPfzRZgwhGfg,2965
|
|
@@ -71,35 +75,36 @@ shinestacker/gui/img/forward-button-icon.png,sha256=lNw86T4TOEd_uokHYF8myGSGUXzd
|
|
|
71
75
|
shinestacker/gui/img/play-button-round-icon.png,sha256=9j6Ks9mOGa-2cXyRFpimepAAvSaHzqJKBfxShRb4_dE,4595
|
|
72
76
|
shinestacker/gui/img/plus-round-line-icon.png,sha256=LS068Hlu-CeBvJuB3dwwdJg1lZq6D5MUIv53lu1yKJA,7534
|
|
73
77
|
shinestacker/retouch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
74
|
-
shinestacker/retouch/base_filter.py,sha256=
|
|
78
|
+
shinestacker/retouch/base_filter.py,sha256=ObrAcwZv9YJbIhWMHcryHEEj41oAk9hfHmE4phEd1gE,11263
|
|
75
79
|
shinestacker/retouch/brush.py,sha256=dzD2FzSpBIPdJRmTZobcrQ1FrVd3tF__ZPnUplNE72s,357
|
|
76
80
|
shinestacker/retouch/brush_gradient.py,sha256=F5SFhyzl8YTMqjJU3jK8BrIlLCYLUvITd5wz3cQE4xk,1453
|
|
77
81
|
shinestacker/retouch/brush_preview.py,sha256=cOFVMCbEsgR_alzmr_-LLghtGU_unrE-hAjLHcvrZAY,5484
|
|
78
82
|
shinestacker/retouch/brush_tool.py,sha256=8uVncTA375uC3Nhp2YM0eZjpOR-nN47i2eGjN8tJzOU,8714
|
|
79
83
|
shinestacker/retouch/denoise_filter.py,sha256=UpNKbFs7uArdglEej8AUHan7oCVYV5E7HNzkovj7XMQ,571
|
|
80
|
-
shinestacker/retouch/display_manager.py,sha256=
|
|
84
|
+
shinestacker/retouch/display_manager.py,sha256=fTZTGbvmX5DXagexuvbNgOF5GiH2Vv-stLUQQwoglp8,10181
|
|
81
85
|
shinestacker/retouch/exif_data.py,sha256=LF-fRXW-reMq-xJ_QRE5j8DC2LVGKIlC6MR3QbC1cdg,1896
|
|
82
86
|
shinestacker/retouch/file_loader.py,sha256=z02-A8_uDZxayI1NFTxT2GVUvEBWStchX9hlN1o5-0U,4784
|
|
83
87
|
shinestacker/retouch/filter_manager.py,sha256=tOGIWj5HjViL1-iXHkd91X-sZ1c1G531pDmLO0x6zx0,866
|
|
84
88
|
shinestacker/retouch/icon_container.py,sha256=6gw1HO1bC2FrdB4dc_iH81DQuLjzuvRGksZ2hKLT9yA,585
|
|
85
|
-
shinestacker/retouch/image_editor_ui.py,sha256
|
|
86
|
-
shinestacker/retouch/image_view_status.py,sha256=
|
|
87
|
-
shinestacker/retouch/image_viewer.py,sha256=
|
|
88
|
-
shinestacker/retouch/io_gui_handler.py,sha256=
|
|
89
|
-
shinestacker/retouch/
|
|
90
|
-
shinestacker/retouch/layer_collection.py,sha256=
|
|
91
|
-
shinestacker/retouch/overlaid_view.py,sha256=
|
|
89
|
+
shinestacker/retouch/image_editor_ui.py,sha256=r2S4Fgyi3xQi2XeqlVYTUxZ9YlPZe2rMaIpvIak8Aog,33181
|
|
90
|
+
shinestacker/retouch/image_view_status.py,sha256=2rWi2ugdyjMhWCtRJkwOnb7-tCtVfnGfCY_54qpZhwM,1970
|
|
91
|
+
shinestacker/retouch/image_viewer.py,sha256=xf1vYZRPb9ClCQbqrqAFhPubdqIIpku7DgcY8O5bvYU,4694
|
|
92
|
+
shinestacker/retouch/io_gui_handler.py,sha256=tyHMmR6_uE_IEI-CIcJibVhupxarKYHzX2fuhnesHaI,14616
|
|
93
|
+
shinestacker/retouch/io_threads.py,sha256=r0X4it2PfwnmiAU7eStniIfcHhPvuaqdqf5VlnvjZ-4,2832
|
|
94
|
+
shinestacker/retouch/layer_collection.py,sha256=xx8INSLCXIeTQn_nxfCo4QljAmQK1qukSYO1Zk4rqqo,6183
|
|
95
|
+
shinestacker/retouch/overlaid_view.py,sha256=QTTdegUWs99YBZZPlIRdPI5O80U3t_c3HnyegbRqNbA,7029
|
|
96
|
+
shinestacker/retouch/paint_area_manager.py,sha256=ilK6uQT7lzNyvdc8uNv4xTHHHAbk5hGEClJRNmiA4P8,894
|
|
92
97
|
shinestacker/retouch/shortcuts_help.py,sha256=BFWTT5QvodqMhqa_9LI25hZqjICfckgyWG4fGrGzvnM,4283
|
|
93
|
-
shinestacker/retouch/sidebyside_view.py,sha256=
|
|
94
|
-
shinestacker/retouch/transformation_manager.py,sha256=
|
|
95
|
-
shinestacker/retouch/undo_manager.py,sha256=
|
|
98
|
+
shinestacker/retouch/sidebyside_view.py,sha256=4sNa_IUMbNH18iECO7eDO9S_ls3v2ENwP1AWrBFhofI,18907
|
|
99
|
+
shinestacker/retouch/transformation_manager.py,sha256=QFYCL-l9V6qlhw3y7tcs0saWWClNPsh7F9pTBkfPbRU,1711
|
|
100
|
+
shinestacker/retouch/undo_manager.py,sha256=J4hEAnv9bKLQ0N1wllWswjJBhgRgasCnBoMT5LEw-dM,4453
|
|
96
101
|
shinestacker/retouch/unsharp_mask_filter.py,sha256=Iapc8UmSVpj3V0LcJq_38P5qerRqTevMynbbk5Rk6iE,3634
|
|
97
|
-
shinestacker/retouch/view_strategy.py,sha256=
|
|
102
|
+
shinestacker/retouch/view_strategy.py,sha256=jZxB_vX3_0notH0ClxKkLzbdtx4is3vQiYoIP-sDv3M,30216
|
|
98
103
|
shinestacker/retouch/vignetting_filter.py,sha256=JhFr6OVIripQzSJrZEG4lxq7wBsmpofLqJQ-aP2bKw8,3789
|
|
99
104
|
shinestacker/retouch/white_balance_filter.py,sha256=UaH4yxG3fU4vPutBAkV5oTXIQyUTN09x0uTywAzv3sY,8286
|
|
100
|
-
shinestacker-1.
|
|
101
|
-
shinestacker-1.
|
|
102
|
-
shinestacker-1.
|
|
103
|
-
shinestacker-1.
|
|
104
|
-
shinestacker-1.
|
|
105
|
-
shinestacker-1.
|
|
105
|
+
shinestacker-1.6.1.dist-info/licenses/LICENSE,sha256=pWgb-bBdsU2Gd2kwAXxketnm5W_2u8_fIeWEgojfrxs,7651
|
|
106
|
+
shinestacker-1.6.1.dist-info/METADATA,sha256=9sevPHbXS-yaj-wYc-42q28V34PNOdnPlntqNzlsgOo,6978
|
|
107
|
+
shinestacker-1.6.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
108
|
+
shinestacker-1.6.1.dist-info/entry_points.txt,sha256=SY6g1LqtMmp23q1DGwLUDT_dhLX9iss8DvWkiWLyo_4,166
|
|
109
|
+
shinestacker-1.6.1.dist-info/top_level.txt,sha256=MhijwnBVX5psfsyX8JZjqp3SYiWPsKe69f3Gnyze4Fw,13
|
|
110
|
+
shinestacker-1.6.1.dist-info/RECORD,,
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# pylint: disable=E1101, C0114, C0115, C0116, E0611, W0718, R0903
|
|
2
|
-
import traceback
|
|
3
|
-
import cv2
|
|
4
|
-
from PySide6.QtCore import QThread, Signal
|
|
5
|
-
from .. algorithms.utils import read_img, validate_image, get_img_metadata
|
|
6
|
-
from .. algorithms.exif import get_exif, write_image_with_exif_data
|
|
7
|
-
from .. algorithms.multilayer import write_multilayer_tiff_from_images
|
|
8
|
-
from .layer_collection import LayerCollectionHandler
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class FileMultilayerSaver(QThread):
|
|
12
|
-
finished = Signal()
|
|
13
|
-
error = Signal(str)
|
|
14
|
-
|
|
15
|
-
def __init__(self, images_dict, path, exif_path=None):
|
|
16
|
-
super().__init__()
|
|
17
|
-
self.images_dict = images_dict
|
|
18
|
-
self.path = path
|
|
19
|
-
self.exif_path = exif_path
|
|
20
|
-
|
|
21
|
-
def run(self):
|
|
22
|
-
try:
|
|
23
|
-
write_multilayer_tiff_from_images(
|
|
24
|
-
self.images_dict, self.path, exif_path=self.exif_path)
|
|
25
|
-
self.finished.emit()
|
|
26
|
-
except Exception as e:
|
|
27
|
-
traceback.print_tb(e.__traceback__)
|
|
28
|
-
self.error.emit(str(e))
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class IOManager(LayerCollectionHandler):
|
|
32
|
-
def __init__(self, layer_collection):
|
|
33
|
-
super().__init__(layer_collection)
|
|
34
|
-
self.exif_path = ''
|
|
35
|
-
self.exif_data = None
|
|
36
|
-
|
|
37
|
-
def import_frames(self, file_paths):
|
|
38
|
-
stack = []
|
|
39
|
-
labels = []
|
|
40
|
-
master = None
|
|
41
|
-
shape, dtype = get_img_metadata(self.master_layer())
|
|
42
|
-
for path in file_paths:
|
|
43
|
-
try:
|
|
44
|
-
label = path.split("/")[-1].split(".")[0]
|
|
45
|
-
img = cv2.cvtColor(read_img(path), cv2.COLOR_BGR2RGB)
|
|
46
|
-
if shape is not None and dtype is not None:
|
|
47
|
-
validate_image(img, shape, dtype)
|
|
48
|
-
else:
|
|
49
|
-
shape, dtype = get_img_metadata(img)
|
|
50
|
-
label_x = label
|
|
51
|
-
i = 0
|
|
52
|
-
while label_x in labels:
|
|
53
|
-
i += 1
|
|
54
|
-
label_x = f"{label} ({i})"
|
|
55
|
-
labels.append(label_x)
|
|
56
|
-
stack.append(img)
|
|
57
|
-
if master is None:
|
|
58
|
-
master = img.copy()
|
|
59
|
-
except Exception as e:
|
|
60
|
-
raise RuntimeError(f"Error loading file: {path}.\n{str(e)}") from e
|
|
61
|
-
return stack, labels, master
|
|
62
|
-
|
|
63
|
-
def save_master(self, path):
|
|
64
|
-
img = cv2.cvtColor(self.master_layer(), cv2.COLOR_RGB2BGR)
|
|
65
|
-
write_image_with_exif_data(self.exif_data, img, path)
|
|
66
|
-
|
|
67
|
-
def set_exif_data(self, path):
|
|
68
|
-
self.exif_path = path
|
|
69
|
-
self.exif_data = get_exif(path)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|