shinestacker 1.3.0__py3-none-any.whl → 1.4.0__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.

Files changed (50) hide show
  1. shinestacker/_version.py +1 -1
  2. shinestacker/algorithms/align.py +229 -41
  3. shinestacker/algorithms/align_auto.py +15 -3
  4. shinestacker/algorithms/align_parallel.py +81 -25
  5. shinestacker/algorithms/balance.py +23 -13
  6. shinestacker/algorithms/base_stack_algo.py +14 -20
  7. shinestacker/algorithms/depth_map.py +9 -14
  8. shinestacker/algorithms/noise_detection.py +3 -1
  9. shinestacker/algorithms/pyramid.py +8 -22
  10. shinestacker/algorithms/pyramid_auto.py +5 -14
  11. shinestacker/algorithms/pyramid_tiles.py +18 -20
  12. shinestacker/algorithms/stack_framework.py +1 -1
  13. shinestacker/algorithms/utils.py +37 -10
  14. shinestacker/algorithms/vignetting.py +2 -0
  15. shinestacker/app/gui_utils.py +10 -0
  16. shinestacker/app/main.py +3 -1
  17. shinestacker/app/project.py +3 -1
  18. shinestacker/app/retouch.py +3 -1
  19. shinestacker/config/gui_constants.py +2 -2
  20. shinestacker/core/core_utils.py +10 -1
  21. shinestacker/gui/action_config.py +172 -7
  22. shinestacker/gui/action_config_dialog.py +443 -452
  23. shinestacker/gui/colors.py +1 -0
  24. shinestacker/gui/folder_file_selection.py +5 -0
  25. shinestacker/gui/gui_run.py +2 -2
  26. shinestacker/gui/main_window.py +18 -9
  27. shinestacker/gui/menu_manager.py +26 -2
  28. shinestacker/gui/new_project.py +5 -5
  29. shinestacker/gui/project_controller.py +4 -0
  30. shinestacker/gui/project_editor.py +6 -4
  31. shinestacker/gui/recent_file_manager.py +93 -0
  32. shinestacker/gui/sys_mon.py +24 -23
  33. shinestacker/retouch/base_filter.py +5 -5
  34. shinestacker/retouch/brush_preview.py +3 -0
  35. shinestacker/retouch/brush_tool.py +11 -11
  36. shinestacker/retouch/display_manager.py +21 -37
  37. shinestacker/retouch/image_editor_ui.py +129 -71
  38. shinestacker/retouch/image_view_status.py +61 -0
  39. shinestacker/retouch/image_viewer.py +89 -431
  40. shinestacker/retouch/io_gui_handler.py +12 -2
  41. shinestacker/retouch/overlaid_view.py +212 -0
  42. shinestacker/retouch/shortcuts_help.py +13 -3
  43. shinestacker/retouch/sidebyside_view.py +479 -0
  44. shinestacker/retouch/view_strategy.py +466 -0
  45. {shinestacker-1.3.0.dist-info → shinestacker-1.4.0.dist-info}/METADATA +1 -1
  46. {shinestacker-1.3.0.dist-info → shinestacker-1.4.0.dist-info}/RECORD +50 -45
  47. {shinestacker-1.3.0.dist-info → shinestacker-1.4.0.dist-info}/WHEEL +0 -0
  48. {shinestacker-1.3.0.dist-info → shinestacker-1.4.0.dist-info}/entry_points.txt +0 -0
  49. {shinestacker-1.3.0.dist-info → shinestacker-1.4.0.dist-info}/licenses/LICENSE +0 -0
  50. {shinestacker-1.3.0.dist-info → shinestacker-1.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,466 @@
1
+ # pylint: disable=C0114, C0115, C0116, E0611, R0904, R0903, R0902, E1101, R0914
2
+ import math
3
+ from abc import abstractmethod
4
+ import numpy as np
5
+ from PySide6.QtCore import Qt, QPointF, QTime, QPoint, Signal
6
+ from PySide6.QtGui import QImage, QPainter, QColor, QBrush, QPen, QCursor
7
+ from PySide6.QtWidgets import (
8
+ QGraphicsEllipseItem, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem)
9
+ from .. config.gui_constants import gui_constants
10
+ from .layer_collection import LayerCollectionHandler
11
+ from .brush_gradient import create_default_brush_gradient
12
+ from .brush_preview import BrushPreviewItem
13
+
14
+
15
+ class ViewSignals:
16
+ temp_view_requested = Signal(bool)
17
+ brush_operation_started = Signal(QPoint)
18
+ brush_operation_continued = Signal(QPoint)
19
+ brush_operation_ended = Signal()
20
+ brush_size_change_requested = Signal(int) # +1 or -1
21
+
22
+
23
+ class ImageGraphicsViewBase(QGraphicsView):
24
+ def __init__(self, parent=None):
25
+ super().__init__(parent)
26
+ self.setTransformationAnchor(QGraphicsView.AnchorViewCenter)
27
+ self.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
28
+ self.setInteractive(False)
29
+ self.grabGesture(Qt.PinchGesture)
30
+ self.grabGesture(Qt.PanGesture)
31
+ self.setMouseTracking(True)
32
+ self.setDragMode(QGraphicsView.NoDrag)
33
+ self.setRenderHint(QPainter.Antialiasing)
34
+ self.setRenderHint(QPainter.SmoothPixmapTransform)
35
+ self.setCursor(Qt.BlankCursor)
36
+
37
+
38
+ class ViewStrategy(LayerCollectionHandler):
39
+ def __init__(self, layer_collection, status):
40
+ LayerCollectionHandler.__init__(self, layer_collection)
41
+ self.display_manager = None
42
+ self.status = status
43
+ self.brush = None
44
+ self.brush_cursor = None
45
+ self.display_manager = None
46
+ self.brush_preview = BrushPreviewItem(layer_collection)
47
+ self.cursor_style = gui_constants.DEFAULT_CURSOR_STYLE
48
+ self.allow_cursor_preview = True
49
+ self.control_pressed = False
50
+ self.space_pressed = False
51
+ self.gesture_active = False
52
+ self.pinch_center_view = None
53
+ self.pinch_center_scene = None
54
+ self.pinch_start_scale = None
55
+ self.last_scroll_pos = None
56
+ self.scrolling = False
57
+ self.dragging = False
58
+ self.last_brush_pos = None
59
+ self.last_mouse_pos = None
60
+ self.last_update_time = QTime.currentTime()
61
+
62
+ @abstractmethod
63
+ def create_pixmaps(self):
64
+ pass
65
+
66
+ @abstractmethod
67
+ def set_master_image(self, qimage):
68
+ pass
69
+
70
+ @abstractmethod
71
+ def set_current_image(self, qimage):
72
+ pass
73
+
74
+ @abstractmethod
75
+ def update_master_display(self):
76
+ pass
77
+
78
+ @abstractmethod
79
+ def update_current_display(self):
80
+ pass
81
+
82
+ @abstractmethod
83
+ def get_master_view(self):
84
+ pass
85
+
86
+ @abstractmethod
87
+ def get_master_scene(self):
88
+ pass
89
+
90
+ @abstractmethod
91
+ def get_views(self):
92
+ pass
93
+
94
+ @abstractmethod
95
+ def get_scenes(self):
96
+ pass
97
+
98
+ @abstractmethod
99
+ def get_pixmaps(self):
100
+ pass
101
+
102
+ @abstractmethod
103
+ def get_master_pixmap(self):
104
+ pass
105
+
106
+ def show_master(self):
107
+ pass
108
+
109
+ def show_current(self):
110
+ pass
111
+
112
+ def set_allow_cursor_preview(self, state):
113
+ self.allow_cursor_preview = state
114
+
115
+ def zoom_factor(self):
116
+ return self.status.zoom_factor
117
+
118
+ def set_zoom_factor(self, zoom_factor):
119
+ self.status.set_zoom_factor(zoom_factor)
120
+
121
+ def get_current_scale(self):
122
+ return self.get_master_view().transform().m11()
123
+
124
+ def min_scale(self):
125
+ return self.status.min_scale
126
+
127
+ def max_scale(self):
128
+ return self.status.max_scale
129
+
130
+ def set_min_scale(self, scale):
131
+ self.status.set_min_scale(scale)
132
+
133
+ def set_max_scale(self, scale):
134
+ self.status.set_max_scale(scale)
135
+
136
+ def empty(self):
137
+ return self.status.empty()
138
+
139
+ def set_brush(self, brush):
140
+ self.brush = brush
141
+
142
+ def set_preview_brush(self, brush):
143
+ self.brush_preview.brush = brush
144
+
145
+ def set_display_manager(self, dm):
146
+ self.display_manager = dm
147
+
148
+ def set_cursor_style(self, style):
149
+ self.cursor_style = style
150
+ if self.brush_cursor:
151
+ self.update_brush_cursor()
152
+
153
+ def get_cursor_style(self):
154
+ return self.cursor_style
155
+
156
+ def handle_key_press_event(self, _event):
157
+ return
158
+
159
+ def handle_key_release_event(self, _event):
160
+ return
161
+
162
+ def clear_image(self):
163
+ for scene in self.get_scenes():
164
+ scene.clear()
165
+ self.create_pixmaps()
166
+ self.status.clear()
167
+ self.setup_brush_cursor()
168
+ self.brush_preview = BrushPreviewItem(self.layer_collection)
169
+ self.get_master_scene().addItem(self.brush_preview)
170
+ self.setCursor(Qt.ArrowCursor)
171
+ if self.brush_cursor:
172
+ self.brush_cursor.hide()
173
+
174
+ def set_master_image_np(self, img):
175
+ self.set_master_image(self.numpy_to_qimage(img))
176
+
177
+ def numpy_to_qimage(self, array):
178
+ if array is None:
179
+ return None
180
+ if array.dtype == np.uint16:
181
+ array = np.right_shift(array, 8).astype(np.uint8)
182
+ if array.ndim == 2:
183
+ height, width = array.shape
184
+ return QImage(memoryview(array), width, height, width, QImage.Format_Grayscale8)
185
+ if array.ndim == 3:
186
+ height, width, _ = array.shape
187
+ if not array.flags['C_CONTIGUOUS']:
188
+ array = np.ascontiguousarray(array)
189
+ return QImage(memoryview(array), width, height, 3 * width, QImage.Format_RGB888)
190
+ return QImage()
191
+
192
+ def create_scene(self, view):
193
+ scene = QGraphicsScene()
194
+ view.setScene(scene)
195
+ scene.setBackgroundBrush(QBrush(QColor(120, 120, 120)))
196
+ return scene
197
+
198
+ def create_pixmap(self, scene):
199
+ pixmap_item = QGraphicsPixmapItem()
200
+ scene.addItem(pixmap_item)
201
+ return pixmap_item
202
+
203
+ def refresh_display(self):
204
+ self.update_brush_cursor()
205
+ for scene in self.get_scenes():
206
+ scene.update()
207
+
208
+ def zoom_in(self):
209
+ if self.empty():
210
+ return
211
+ master_view = self.get_master_view()
212
+ old_center = master_view.mapToScene(master_view.viewport().rect().center())
213
+ current_scale = self.get_current_scale()
214
+ new_scale = current_scale * gui_constants.ZOOM_IN_FACTOR
215
+ if new_scale <= self.max_scale():
216
+ for view in self.get_views():
217
+ view.scale(gui_constants.ZOOM_IN_FACTOR, gui_constants.ZOOM_IN_FACTOR)
218
+ self.set_zoom_factor(new_scale)
219
+ master_view.centerOn(old_center)
220
+ self.update_brush_cursor()
221
+
222
+ def zoom_out(self):
223
+ if self.empty():
224
+ return
225
+ master_view = self.get_master_view()
226
+ old_center = master_view.mapToScene(master_view.viewport().rect().center())
227
+ current_scale = self.get_current_scale()
228
+ new_scale = current_scale * gui_constants.ZOOM_OUT_FACTOR
229
+ if new_scale >= self.min_scale():
230
+ for view in self.get_views():
231
+ view.scale(gui_constants.ZOOM_OUT_FACTOR, gui_constants.ZOOM_OUT_FACTOR)
232
+ self.set_zoom_factor(new_scale)
233
+ master_view.centerOn(old_center)
234
+ self.update_brush_cursor()
235
+
236
+ def reset_zoom(self):
237
+ if self.empty():
238
+ return
239
+ self.pinch_start_scale = 1.0
240
+ self.last_scroll_pos = QPointF()
241
+ self.gesture_active = False
242
+ self.pinch_center_view = None
243
+ self.pinch_center_scene = None
244
+ for pixmap, view in self.get_pixmaps().items():
245
+ view.fitInView(pixmap, Qt.KeepAspectRatio)
246
+ self.set_zoom_factor(self.get_current_scale())
247
+ self.set_zoom_factor(max(self.min_scale(), min(self.max_scale(), self.zoom_factor())))
248
+ for view in self.get_views():
249
+ view.resetTransform()
250
+ view.scale(self.zoom_factor(), self.zoom_factor())
251
+ self.update_brush_cursor()
252
+
253
+ def actual_size(self):
254
+ if self.empty():
255
+ return
256
+ self.set_zoom_factor(max(self.min_scale(), min(self.max_scale(), 1.0)))
257
+ for view in self.get_views():
258
+ view.resetTransform()
259
+ view.scale(self.zoom_factor(), self.zoom_factor())
260
+ self.update_brush_cursor()
261
+
262
+ def setup_outline_style(self):
263
+ self.brush_cursor.setPen(QPen(QColor(*gui_constants.BRUSH_COLORS['pen']),
264
+ gui_constants.BRUSH_LINE_WIDTH / self.zoom_factor()))
265
+ self.brush_cursor.setBrush(Qt.NoBrush)
266
+
267
+ def setup_simple_brush_style(self, center_x, center_y, radius):
268
+ gradient = create_default_brush_gradient(center_x, center_y, radius, self.brush)
269
+ self.brush_cursor.setPen(QPen(QColor(*gui_constants.BRUSH_COLORS['pen']),
270
+ gui_constants.BRUSH_LINE_WIDTH / self.zoom_factor()))
271
+ self.brush_cursor.setBrush(QBrush(gradient))
272
+
273
+ def setup_brush_cursor(self):
274
+ if not self.brush:
275
+ return
276
+ scene = self.get_master_scene()
277
+ for item in scene.items():
278
+ if isinstance(item, QGraphicsEllipseItem) and item != self.brush_preview:
279
+ scene.removeItem(item)
280
+ pen = QPen(QColor(*gui_constants.BRUSH_COLORS['pen']), 1)
281
+ brush = QBrush(QColor(*gui_constants.BRUSH_COLORS['cursor_inner']))
282
+ self.brush_cursor = scene.addEllipse(
283
+ 0, 0, self.brush.size, self.brush.size, pen, brush)
284
+ self.brush_cursor.setZValue(1000)
285
+ self.brush_cursor.hide()
286
+
287
+ def update_brush_cursor(self):
288
+ if self.empty():
289
+ return
290
+ if not self.brush_cursor or not self.isVisible():
291
+ return
292
+ master_view = self.get_master_view()
293
+ mouse_pos = master_view.mapFromGlobal(QCursor.pos())
294
+ if not master_view.rect().contains(mouse_pos):
295
+ self.brush_cursor.hide()
296
+ return
297
+ scene_pos = master_view.mapToScene(mouse_pos)
298
+ size = self.brush.size
299
+ radius = size / 2
300
+ self.brush_cursor.setRect(scene_pos.x() - radius, scene_pos.y() - radius, size, size)
301
+ allow_cursor_preview = self.display_manager.allow_cursor_preview()
302
+ if self.cursor_style == 'preview' and allow_cursor_preview:
303
+ self.setup_outline_style()
304
+ self.brush_cursor.hide()
305
+ pos = QCursor.pos()
306
+ if isinstance(pos, QPointF):
307
+ scene_pos = pos
308
+ else:
309
+ cursor_pos = master_view.mapFromGlobal(pos)
310
+ scene_pos = master_view.mapToScene(cursor_pos)
311
+ self.brush_preview.update(scene_pos, int(size))
312
+ else:
313
+ self.brush_preview.hide()
314
+ if self.cursor_style == 'outline' or not allow_cursor_preview:
315
+ self.setup_outline_style()
316
+ else:
317
+ self.setup_simple_brush_style(scene_pos.x(), scene_pos.y(), radius)
318
+ if not self.brush_cursor.isVisible():
319
+ self.brush_cursor.show()
320
+
321
+ def position_on_image(self, pos):
322
+ master_view = self.get_master_view()
323
+ pixmap = self.get_master_pixmap()
324
+ scene_pos = master_view.mapToScene(pos)
325
+ item_pos = pixmap.mapFromScene(scene_pos)
326
+ return item_pos
327
+
328
+ def get_visible_image_region(self):
329
+ if self.empty():
330
+ return None
331
+ master_view = self.get_master_view()
332
+ master_pixmap = self.get_master_pixmap()
333
+ pixmap = self.get_master_pixmap()
334
+ view_rect = master_view.viewport().rect()
335
+ scene_rect = master_view.mapToScene(view_rect).boundingRect()
336
+ image_rect = master_pixmap.mapFromScene(scene_rect).boundingRect().toRect()
337
+ return image_rect.intersected(pixmap.boundingRect().toRect())
338
+
339
+ def get_visible_image_portion(self):
340
+ if self.has_no_master_layer():
341
+ return None
342
+ visible_rect = self.get_visible_image_region()
343
+ if not visible_rect:
344
+ return self.master_layer()
345
+ x, y = int(visible_rect.x()), int(visible_rect.y())
346
+ w, h = int(visible_rect.width()), int(visible_rect.height())
347
+ master_img = self.master_layer()
348
+ return master_img[y:y + h, x:x + w], (x, y, w, h)
349
+
350
+ def map_to_scene(self, pos):
351
+ return self.get_master_view().mapToScene(pos)
352
+
353
+ # pylint: disable=C0103
354
+ def keyPressEvent(self, event):
355
+ if self.empty():
356
+ return
357
+ master_view = self.get_master_view()
358
+ if event.key() == Qt.Key_Space and not self.scrolling:
359
+ self.space_pressed = True
360
+ master_view.setCursor(Qt.OpenHandCursor)
361
+ if self.brush_cursor:
362
+ self.brush_cursor.hide()
363
+ self.handle_key_press_event(event)
364
+ if event.key() == Qt.Key_Control and not self.scrolling:
365
+ self.control_pressed = True
366
+ super().keyPressEvent(event)
367
+
368
+ def keyReleaseEvent(self, event):
369
+ if self.empty():
370
+ return
371
+ master_view = self.get_master_view()
372
+ self.update_brush_cursor()
373
+ if event.key() == Qt.Key_Space:
374
+ self.space_pressed = False
375
+ if not self.scrolling:
376
+ master_view.setCursor(Qt.BlankCursor)
377
+ if self.brush_cursor:
378
+ self.brush_cursor.show()
379
+ self.handle_key_release_event(event)
380
+ if event.key() == Qt.Key_Control:
381
+ self.control_pressed = False
382
+ super().keyReleaseEvent(event)
383
+
384
+ def leaveEvent(self, event):
385
+ if not self.empty():
386
+ self.get_master_view().setCursor(Qt.ArrowCursor)
387
+ if self.brush_cursor:
388
+ self.brush_cursor.hide()
389
+ super().leaveEvent(event)
390
+ # pylint: enable=C0103
391
+
392
+ def mouse_move_event(self, event):
393
+ if self.empty():
394
+ return
395
+ position = event.position()
396
+ brush_size = self.brush.size
397
+ if not self.space_pressed:
398
+ self.update_brush_cursor()
399
+ if self.dragging and event.buttons() & Qt.LeftButton:
400
+ current_time = QTime.currentTime()
401
+ if self.last_update_time.msecsTo(current_time) >= gui_constants.PAINT_REFRESH_TIMER:
402
+ min_step = brush_size * \
403
+ gui_constants.MIN_MOUSE_STEP_BRUSH_FRACTION * self.zoom_factor()
404
+ x, y = position.x(), position.y()
405
+ xp, yp = self.last_brush_pos.x(), self.last_brush_pos.y()
406
+ distance = math.sqrt((x - xp)**2 + (y - yp)**2)
407
+ n_steps = int(float(distance) / min_step)
408
+ if n_steps > 0:
409
+ delta_x = (position.x() - self.last_brush_pos.x()) / n_steps
410
+ delta_y = (position.y() - self.last_brush_pos.y()) / n_steps
411
+ for i in range(0, n_steps + 1):
412
+ pos = QPoint(self.last_brush_pos.x() + i * delta_x,
413
+ self.last_brush_pos.y() + i * delta_y)
414
+ self.brush_operation_continued.emit(pos)
415
+ self.last_brush_pos = position
416
+ self.last_update_time = current_time
417
+ if self.scrolling and event.buttons() & Qt.LeftButton:
418
+ master_view = self.get_master_view()
419
+ if self.space_pressed:
420
+ master_view.setCursor(Qt.ClosedHandCursor)
421
+ if self.brush_cursor:
422
+ self.brush_cursor.hide()
423
+ delta = position - self.last_mouse_pos
424
+ self.last_mouse_pos = position
425
+ self.scroll_view(master_view, delta.x(), delta.y())
426
+
427
+ def scroll_view(self, view, delta_x, delta_y):
428
+ view.horizontalScrollBar().setValue(
429
+ view.horizontalScrollBar().value() - delta_x)
430
+ view.verticalScrollBar().setValue(
431
+ view.verticalScrollBar().value() - delta_y)
432
+
433
+ def mouse_press_event(self, event):
434
+ if self.empty():
435
+ return
436
+ if event.button() == Qt.LeftButton and self.has_master_layer():
437
+ if self.space_pressed:
438
+ self.scrolling = True
439
+ self.last_mouse_pos = event.position()
440
+ self.setCursor(Qt.ClosedHandCursor)
441
+ else:
442
+ self.last_brush_pos = event.position()
443
+ self.brush_operation_started.emit(event.position().toPoint())
444
+ self.dragging = True
445
+ if self.brush_cursor:
446
+ self.brush_cursor.show()
447
+
448
+ def mouse_release_event(self, event):
449
+ if self.empty():
450
+ return
451
+ master_view = self.get_master_view()
452
+ if self.space_pressed:
453
+ master_view.setCursor(Qt.OpenHandCursor)
454
+ if self.brush_cursor:
455
+ self.brush_cursor.hide()
456
+ else:
457
+ master_view.setCursor(Qt.BlankCursor)
458
+ if self.brush_cursor:
459
+ self.brush_cursor.show()
460
+ if event.button() == Qt.LeftButton:
461
+ if self.scrolling:
462
+ self.scrolling = False
463
+ self.last_mouse_pos = None
464
+ elif self.dragging:
465
+ self.dragging = False
466
+ self.brush_operation_ended.emit()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shinestacker
3
- Version: 1.3.0
3
+ Version: 1.4.0
4
4
  Summary: ShineStacker
5
5
  Author-email: Luca Lista <luka.lista@gmail.com>
6
6
  License-Expression: LGPL-3.0
@@ -1,62 +1,63 @@
1
1
  shinestacker/__init__.py,sha256=uq2fjAw2z_6TpH3mOcWFZ98GoEPRsNhTAK8N0MMm_e8,448
2
- shinestacker/_version.py,sha256=tP8c5-8yPCRUk61qFQy1AQFkbfy99N-tga3OUiJT1MA,21
2
+ shinestacker/_version.py,sha256=R4yO1-T_1mGmXG30xDxIA44z6cxCh-PK6l33V9MTqxk,21
3
3
  shinestacker/algorithms/__init__.py,sha256=1FwVJ3w9GGbFFkjYJRUedTvcdE4j0ieSgaH9RC9iCY4,877
4
- shinestacker/algorithms/align.py,sha256=tVgLzn0vV9sIrFj4fZezBYHxhK2o_xrjCm8k55OoAYQ,23514
5
- shinestacker/algorithms/align_auto.py,sha256=wIv9iSOhzxdQiPo0GG1Dv9WSLgFGjCJM7I2uqMl-cGc,3093
6
- shinestacker/algorithms/align_parallel.py,sha256=3tGhrSr9IPz8fv0FUW-AAq9-e3BEJadwS9DYTZm-Sgo,14812
7
- shinestacker/algorithms/balance.py,sha256=KJ8eXWYyqRVQa7_iZWQhZZ9BfO4wNve5nhZxunK7B5k,23583
8
- shinestacker/algorithms/base_stack_algo.py,sha256=jiqckBGQnP536OPfTW0Kzfawcpk1L-bByhCjoyQyBGw,2841
4
+ shinestacker/algorithms/align.py,sha256=mb44u-YxZI1TTSHz81nRpX_2c8awlOhnGrK0LyfTQeQ,33543
5
+ shinestacker/algorithms/align_auto.py,sha256=pJetw6zZEWQLouzcelkI8gD4cPiOp887ePXzVbm0E6Q,3800
6
+ shinestacker/algorithms/align_parallel.py,sha256=5ru4HDcUObLNDP8bPUgsgwpLyflpcyVA16pPqHpYZfs,17671
7
+ shinestacker/algorithms/balance.py,sha256=aoqnc1u5A2C3R7fKaOoKnzudRiOT8GRIu4LEP-uzyZQ,24053
8
+ shinestacker/algorithms/base_stack_algo.py,sha256=RzxvLDHqxqhnAl83u2onjvfsRea1qGK_blbh2Vo0kxA,2670
9
9
  shinestacker/algorithms/denoise.py,sha256=GL3Z4_6MHxSa7Wo4ZzQECZS87tHBFqO0sIVF_jPuYQU,426
10
- shinestacker/algorithms/depth_map.py,sha256=m0_Qm8FLDeSWyQEMNx29PzXp_VFGar7gY3jWxq_10t8,5713
10
+ shinestacker/algorithms/depth_map.py,sha256=nRBrZQWbdUqFOtYMEQx9UNdnybrBTeAOr1eV91FlN8U,5611
11
11
  shinestacker/algorithms/exif.py,sha256=SM4ZDDe8hCJ3xY6053FNndOiwzEStzdp0WrXurlcHVc,9429
12
12
  shinestacker/algorithms/multilayer.py,sha256=WlB4L5oY9qra3w7Qahg-tqO6S_s3pMB_LmGR8PPR_7w,9904
13
- shinestacker/algorithms/noise_detection.py,sha256=KSdMDER5GNOCTD6DIAbjJvRDFvrVorul3xr5maXtCh8,9298
14
- shinestacker/algorithms/pyramid.py,sha256=drGLeGRQ2_QMmbpOFaFI7kSOSuvraOcsWJNTXbBUT6k,8838
15
- shinestacker/algorithms/pyramid_auto.py,sha256=TxIkOrzS2i9Dz994L_YYeL4CNRRjTWkygGL8KDjDuWo,6602
16
- shinestacker/algorithms/pyramid_tiles.py,sha256=mjmvJil0olQJSUWDMR5Hkuu1PbI_TomTUZi8lsC10cU,12356
13
+ shinestacker/algorithms/noise_detection.py,sha256=myUiLKYC3Ph62j28upUd_7rZum_JpqyxiN33nZN35zE,9346
14
+ shinestacker/algorithms/pyramid.py,sha256=Z7tlp8Hh3ploAXJCr0VNe33d8H9GNrlqHXq_LapgRwo,8205
15
+ shinestacker/algorithms/pyramid_auto.py,sha256=fl_jXNYLWsBiX0M0UghzCLqai0SGXlmKYHU7Z9SUYSo,6173
16
+ shinestacker/algorithms/pyramid_tiles.py,sha256=ZBWIeifkDOIVFF4SCyspRZHSj6K_1P3dk4WLmuo53RU,12213
17
17
  shinestacker/algorithms/sharpen.py,sha256=h7PMJBYxucg194Usp_6pvItPUMFYbT-ebAc_-7XBFUw,949
18
18
  shinestacker/algorithms/stack.py,sha256=V9YX0CbNWrgAo7_uti64rmmuwU6RsRcjDoBpsES4aSE,5137
19
- shinestacker/algorithms/stack_framework.py,sha256=L5fXv07CuO4gHBBnoHS6U9ajWB-nDYCKBroutAQzd2U,13890
20
- shinestacker/algorithms/utils.py,sha256=jImR2XF73gsLRZMic0kv8cyCuO2Zq21tX4kUhaTcfzI,11301
21
- shinestacker/algorithms/vignetting.py,sha256=MwhsTqmNMc6GdQl_Bbuyo8IUQPn1OoeGcWj1L6Jjybc,10274
19
+ shinestacker/algorithms/stack_framework.py,sha256=OMrjD5dKquHQXhM7TfLRExDsqN1n938WWhGAfkPYLZM,13883
20
+ shinestacker/algorithms/utils.py,sha256=l6GJpEXpzDr_ml9Not03a1_F7wYvPwn8JkEWDuNwL9o,12116
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/gui_utils.py,sha256=08TrCj2gFGsNsF6hG7ySO2y7wcQakM5PzERkeplqNFs,2344
25
+ shinestacker/app/gui_utils.py,sha256=fSpkwPXTON_l676UHdAnJNrGq7BPbSlPOiHpOF_LZaI,2519
26
26
  shinestacker/app/help_menu.py,sha256=g8lKG_xZmXtNQaC3SIRzyROKVWva_PLEgZsQWh6zUcQ,499
27
- shinestacker/app/main.py,sha256=VPZx_qcmFc1YmWicFjKcfQrH1br0VR5ZGuE64nsD3n0,10414
27
+ shinestacker/app/main.py,sha256=XdWYUm1ed1q7aPghxgaFwWJVNijCvZZ_WG0fux8Nisc,10459
28
28
  shinestacker/app/open_frames.py,sha256=bsu32iJSYJQLe_tQQbvAU5DuMDVX6MRuNdE7B5lojZc,1488
29
- shinestacker/app/project.py,sha256=W0u715LZne_PNJvg9msSy27ybIjgDXiEAQdJ7_6BjYI,2774
30
- shinestacker/app/retouch.py,sha256=ZQ-nRKnHo6xurcP34RNqaAWkmuGBjJ5jE05hTQ_ycis,2482
29
+ shinestacker/app/project.py,sha256=oopOiqU6bOK1cQdpot88z49KbKrlB-LAz_q4-8Iui0U,2819
30
+ shinestacker/app/retouch.py,sha256=dpSozNWSxL6wIO0SMjoviDbXZbbfRN_rVLjeL324c54,2527
31
31
  shinestacker/config/__init__.py,sha256=aXxi-LmAvXd0daIFrVnTHE5OCaYeK1uf1BKMr7oaXQs,197
32
32
  shinestacker/config/config.py,sha256=eBko2D3ADhLTIm9X6hB_a_WsIjwgfE-qmBVkhP1XSvc,1636
33
33
  shinestacker/config/constants.py,sha256=EEdr7pZg4JpbIjUWaP7kJQfTuBB85FN739myDNAfn8A,8301
34
- shinestacker/config/gui_constants.py,sha256=i2dHeGRnY-Wc3dVjpIEKNNxEQYhfn18IEUcvl96r89I,2575
34
+ shinestacker/config/gui_constants.py,sha256=7oZtBaeUxzU7WmbcR7yvQVlzQyRUaIMRcxY3SrKRGOk,2589
35
35
  shinestacker/core/__init__.py,sha256=IUEIx6SQ3DygDEHN3_E6uKpHjHtUa4a_U_1dLd_8yEU,484
36
36
  shinestacker/core/colors.py,sha256=kr_tJA1iRsdck2JaYDb2lS-codZ4Ty9gdu3kHfiWvuM,1340
37
- shinestacker/core/core_utils.py,sha256=BlHbvQmDQXSONNkDx0zq_xiDTsfrS0N7r1DBTUPm8CE,1523
37
+ shinestacker/core/core_utils.py,sha256=1LYj19Dfc9jZN9-4dlf1paximDH5WZYa7DXvKr7R7QY,1719
38
38
  shinestacker/core/exceptions.py,sha256=2-noG-ORAGdvDhL8jBQFs0xxZS4fI6UIkMqrWekgk2c,1618
39
39
  shinestacker/core/framework.py,sha256=QaTfnzEUHwzlbyFG7KzeyteckTSWHWEEJE4d5Tc8H18,11015
40
40
  shinestacker/core/logging.py,sha256=9SuSSy9Usbh7zqmLYMqkmy-VBkOJW000lwqAR0XQs30,3067
41
41
  shinestacker/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
- shinestacker/gui/action_config.py,sha256=BhKssL0xHPdNkE5hDkBy7Uw5rZOLZ8PU8hz-Nt_CdwA,19038
43
- shinestacker/gui/action_config_dialog.py,sha256=SbYL1fxyI-N5Pt_vgkNtJw1s2f-3gd9LlfLnxw4qtDI,41894
42
+ shinestacker/gui/action_config.py,sha256=HeDbRy3YSl9IldLZBCdXj7eWIfTTHmUqC_AW9LJU2Pk,25859
43
+ shinestacker/gui/action_config_dialog.py,sha256=Jp0LVhE0gdz70ve47LCL5N2sSLuj8_arZb4xL50_pkk,41101
44
44
  shinestacker/gui/base_form_dialog.py,sha256=KAUQNtmJazttmOIe4E4pFifbtvcByTAhtCmcIYeA4UE,766
45
- shinestacker/gui/colors.py,sha256=m0pQQ-uvtIN1xmb_-N06BvC7pZYZZnq59ZSEJwutHuk,1432
45
+ shinestacker/gui/colors.py,sha256=-HaFprDuzRSKjXoZfX1rdOuvawQAkazqdgLBEiZcFII,1476
46
46
  shinestacker/gui/flow_layout.py,sha256=3yBU_z7VtvHKpx1H97CHVd81eq9pe1Dcja2EZBGGKcI,3791
47
- shinestacker/gui/folder_file_selection.py,sha256=V6Pdu6EtQpBzCmh_yTibJ75by6Nf-4YHgAAWWTYl-VA,3966
47
+ shinestacker/gui/folder_file_selection.py,sha256=IYWfZQFkoD5iO7zJ7BxVVDP9F3Dc0EXLILAhL4q-Cb8,4117
48
48
  shinestacker/gui/gui_images.py,sha256=k39DpdsxcmYoRdHNNZj6OpFAas0GOHS4JSG542wfheg,5728
49
49
  shinestacker/gui/gui_logging.py,sha256=kiZcrC2AFYCWgPZo0O5SKw-E5cFrezwf4anS3HjPuNw,8168
50
- shinestacker/gui/gui_run.py,sha256=MQPE7muBPw3KTrGDsg-MBcC6nNFYuvvojfXfq84kR8o,15759
51
- shinestacker/gui/main_window.py,sha256=GUrGhZerYXCMwMeB2K51oSHaJAgtMTPj6AfOgkkmwoc,24521
52
- shinestacker/gui/menu_manager.py,sha256=ZsND0e-vM263-6unwKUtYAtLbb4YgvIQabh5lCiT2ow,10179
53
- shinestacker/gui/new_project.py,sha256=Gwg57Ze3D5AQeTCbuI2oNLMqrDnpFRIfNOfWAbO3nUk,16145
54
- shinestacker/gui/project_controller.py,sha256=hvSNGrQM-yDHH3e132oouxBtgRv7mUG7lrigUl21BsA,16043
50
+ shinestacker/gui/gui_run.py,sha256=zr7x4BVmM0n_ZRsSEaJVVKvHSWHuwhftgkUvgeg90gU,15767
51
+ shinestacker/gui/main_window.py,sha256=5k_9TiZT9idKCmovUFYpUTSEQQj-DMQrlyq9dAgY1MU,24800
52
+ shinestacker/gui/menu_manager.py,sha256=b5Cxh6uddOlio8i7fRISbGDJI-oe0ds6LIF5dWM7leI,11263
53
+ shinestacker/gui/new_project.py,sha256=VSUaq1xm9CR0gimKHRKfCdQOQ-ErE1sxGmu6x14nlAQ,16113
54
+ shinestacker/gui/project_controller.py,sha256=W4sbBGEPVtfF9F1rC-6Y0oKLq_y94HuFBvZRj87xNKQ,16272
55
55
  shinestacker/gui/project_converter.py,sha256=Gmna0HwbvACcXiX74TaQYumif8ZV8sZ2APLTMM-L1mU,7436
56
- shinestacker/gui/project_editor.py,sha256=j7bBH4u5g6CO8Mv541ceDrs7GKsWZ-eVKpCPTKF6zVY,25368
56
+ shinestacker/gui/project_editor.py,sha256=lSgQ42IoaobHs-NQQWT88Qhg5l7nu5ejxAO5VgIupr8,25498
57
57
  shinestacker/gui/project_model.py,sha256=eRUmH3QmRzDtPtZoxgT6amKzN8_5XzwjHgEJeL-_JOE,4263
58
+ shinestacker/gui/recent_file_manager.py,sha256=FtatDGUqwmXXchepZdA0YRNzqCRS9Qp4EL9R9Wsg5qE,3731
58
59
  shinestacker/gui/select_path_widget.py,sha256=HSwgSr702w5Et4c-6nkRXnIpm1KFqKJetAF5xQNa5zI,1017
59
- shinestacker/gui/sys_mon.py,sha256=h_Mg99bceXPSX_oK8t_IuRJoSsVo3uthcTnwe8tOYhM,3378
60
+ shinestacker/gui/sys_mon.py,sha256=zU41YYVeqQ1-v6oGIh2_BFzQWq87keN-398Wdm59-Nk,3526
60
61
  shinestacker/gui/tab_widget.py,sha256=VgRmuktWXCgbXbV7c1Tho0--W5_EmmzXPfzRZgwhGfg,2965
61
62
  shinestacker/gui/time_progress_bar.py,sha256=7_sllrQgayjRh__mwJ0-4lghXIakuRAx8wWucJ6olYs,3028
62
63
  shinestacker/gui/ico/focus_stack_bkg.png,sha256=Q86TgqvKEi_IzKI8m6aZB2a3T40UkDtexf2PdeBM9XE,163151
@@ -69,30 +70,34 @@ shinestacker/gui/img/forward-button-icon.png,sha256=lNw86T4TOEd_uokHYF8myGSGUXzd
69
70
  shinestacker/gui/img/play-button-round-icon.png,sha256=9j6Ks9mOGa-2cXyRFpimepAAvSaHzqJKBfxShRb4_dE,4595
70
71
  shinestacker/gui/img/plus-round-line-icon.png,sha256=LS068Hlu-CeBvJuB3dwwdJg1lZq6D5MUIv53lu1yKJA,7534
71
72
  shinestacker/retouch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
- shinestacker/retouch/base_filter.py,sha256=7UfuhZV3wEZefQbExVIHJ6IqKnXlMF2MelxswTMaqOo,10356
73
+ shinestacker/retouch/base_filter.py,sha256=l8sdqKJ8OS2EEwMVVF8DLLLqE_kvYudQ_nUBo_GnC-0,10346
73
74
  shinestacker/retouch/brush.py,sha256=dzD2FzSpBIPdJRmTZobcrQ1FrVd3tF__ZPnUplNE72s,357
74
75
  shinestacker/retouch/brush_gradient.py,sha256=F5SFhyzl8YTMqjJU3jK8BrIlLCYLUvITd5wz3cQE4xk,1453
75
- shinestacker/retouch/brush_preview.py,sha256=QKD3pL7n7YJbIibinUFYKv7lkyq_AWLpt6oyqnltrwQ,4893
76
- shinestacker/retouch/brush_tool.py,sha256=nxnEuvTioPNw1WeWsT20X1zl-LNZ8i-1ExOcihikEjk,8618
76
+ shinestacker/retouch/brush_preview.py,sha256=V-6yRH-paXOEC9bTCJ1NiE6xkTPUiJQGo1N61MMG1AI,4969
77
+ shinestacker/retouch/brush_tool.py,sha256=8uVncTA375uC3Nhp2YM0eZjpOR-nN47i2eGjN8tJzOU,8714
77
78
  shinestacker/retouch/denoise_filter.py,sha256=TDUHzhRKlKvCa3D5SCYCZKTpjcl81kGwmONsgSDtO1k,440
78
- shinestacker/retouch/display_manager.py,sha256=XPbOBmoYc_jNA791WkWkOSaFHb0ztCZechl2p2KSlwQ,9597
79
+ shinestacker/retouch/display_manager.py,sha256=9HKCU8HFs3OyenEa2sk1FanaRCWpmPt77x6G4JfhJ-c,8888
79
80
  shinestacker/retouch/exif_data.py,sha256=LF-fRXW-reMq-xJ_QRE5j8DC2LVGKIlC6MR3QbC1cdg,1896
80
81
  shinestacker/retouch/file_loader.py,sha256=z02-A8_uDZxayI1NFTxT2GVUvEBWStchX9hlN1o5-0U,4784
81
82
  shinestacker/retouch/filter_manager.py,sha256=SdYIZkZBUvuB6wDG0moGWav5sfEvIcB9ioUJR5wJFts,388
82
83
  shinestacker/retouch/icon_container.py,sha256=6gw1HO1bC2FrdB4dc_iH81DQuLjzuvRGksZ2hKLT9yA,585
83
- shinestacker/retouch/image_editor_ui.py,sha256=eYOHR_ihekQ7bWZUk7jXqNDpi5WYOAyTgvi3_QxnmTE,29914
84
- shinestacker/retouch/image_viewer.py,sha256=3ebrLHTDtGd_EbIT2nNFRUjH836rblmmK7jZ62YcJ2U,19564
85
- shinestacker/retouch/io_gui_handler.py,sha256=pT-49uP0GROMOjZ70LoMLgXHnqSDq8ieAlAKGw0t1TM,11418
84
+ shinestacker/retouch/image_editor_ui.py,sha256=Y7gzbgkWa3ehQ9dUahiY4TGoQPkwI00BHTGwobdm8L4,32442
85
+ shinestacker/retouch/image_view_status.py,sha256=8M1IA0T2cATWhOx1Zv0K9u8yMkujSnWLqy5zlEEy5c4,1745
86
+ shinestacker/retouch/image_viewer.py,sha256=TV4RsEGQC4nhpfS7MCjQDd-ASojcVZpbcFKbi-TuDhQ,4187
87
+ shinestacker/retouch/io_gui_handler.py,sha256=Upt8VWwDUrB-UnqCI54SQQwfR4w9kfznCdRL2UwupWQ,12010
86
88
  shinestacker/retouch/io_manager.py,sha256=JUAA--AK0mVa1PTErJTnBFjaXIle5Qs7Ow0Wkd8at0o,2437
87
89
  shinestacker/retouch/layer_collection.py,sha256=Q7zoCYRn__jYkfrEC2lY1uKHWfOUbsJ27xaYHIoKVxo,5730
88
- shinestacker/retouch/shortcuts_help.py,sha256=-beAkhxVia-wyuYMiAn2uQZxnUdSNadmZM77EdReoOk,3789
90
+ shinestacker/retouch/overlaid_view.py,sha256=J4r9DqHzhPrPgJ2IUGuAB26UGxkr2Kf50NUo_NM6w98,8468
91
+ shinestacker/retouch/shortcuts_help.py,sha256=EDxwR7MZwUC9NHLjvqAlh5iEHT9g3g8Tzl18VUGErI4,4130
92
+ shinestacker/retouch/sidebyside_view.py,sha256=tS50VzmTc0Iqf9k3fIbQ3jeIIkDyOO_6TJoNiGg7pLI,19423
89
93
  shinestacker/retouch/undo_manager.py,sha256=_ekbcOLcPbQLY7t-o8wf-b1uA6OPY9rRyLM-KqMlQRo,3257
90
94
  shinestacker/retouch/unsharp_mask_filter.py,sha256=uFnth8fpZFGhdIgJCnS8x5v6lBQgJ3hX0CBke9pFXeM,3510
95
+ shinestacker/retouch/view_strategy.py,sha256=DjBXWsrJJPU4UmdHIeqy_AI6ltDWHBr-RRaFwwYwc04,17061
91
96
  shinestacker/retouch/vignetting_filter.py,sha256=MA97rQkSL0D-Nh-n2L4AiPR064RoTROkvza4tw84g9U,3658
92
97
  shinestacker/retouch/white_balance_filter.py,sha256=glMBYlmrF-i_OrB3sGUpjZE6X4FQdyLC4GBy2bWtaFc,6056
93
- shinestacker-1.3.0.dist-info/licenses/LICENSE,sha256=pWgb-bBdsU2Gd2kwAXxketnm5W_2u8_fIeWEgojfrxs,7651
94
- shinestacker-1.3.0.dist-info/METADATA,sha256=lJFdzbmkUcsMTN05Lyivq-uM3-IuKUyi-PEfR8JptyA,6972
95
- shinestacker-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
96
- shinestacker-1.3.0.dist-info/entry_points.txt,sha256=SY6g1LqtMmp23q1DGwLUDT_dhLX9iss8DvWkiWLyo_4,166
97
- shinestacker-1.3.0.dist-info/top_level.txt,sha256=MhijwnBVX5psfsyX8JZjqp3SYiWPsKe69f3Gnyze4Fw,13
98
- shinestacker-1.3.0.dist-info/RECORD,,
98
+ shinestacker-1.4.0.dist-info/licenses/LICENSE,sha256=pWgb-bBdsU2Gd2kwAXxketnm5W_2u8_fIeWEgojfrxs,7651
99
+ shinestacker-1.4.0.dist-info/METADATA,sha256=gqcYTHpTNsHmYEUz76mZzWXREe3d0D_iVmfesRQsyM0,6972
100
+ shinestacker-1.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
101
+ shinestacker-1.4.0.dist-info/entry_points.txt,sha256=SY6g1LqtMmp23q1DGwLUDT_dhLX9iss8DvWkiWLyo_4,166
102
+ shinestacker-1.4.0.dist-info/top_level.txt,sha256=MhijwnBVX5psfsyX8JZjqp3SYiWPsKe69f3Gnyze4Fw,13
103
+ shinestacker-1.4.0.dist-info/RECORD,,