shinestacker 1.5.2__tar.gz → 1.5.3__tar.gz

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 (151) hide show
  1. {shinestacker-1.5.2 → shinestacker-1.5.3}/CHANGELOG.md +12 -0
  2. {shinestacker-1.5.2/src/shinestacker.egg-info → shinestacker-1.5.3}/PKG-INFO +1 -1
  3. shinestacker-1.5.3/src/shinestacker/_version.py +1 -0
  4. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/app/main.py +1 -1
  5. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/app/project.py +1 -1
  6. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/app/retouch.py +1 -1
  7. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/config/gui_constants.py +1 -1
  8. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/sidebyside_view.py +18 -0
  9. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/view_strategy.py +70 -6
  10. {shinestacker-1.5.2 → shinestacker-1.5.3/src/shinestacker.egg-info}/PKG-INFO +1 -1
  11. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker.egg-info/SOURCES.txt +1 -1
  12. shinestacker-1.5.2/src/shinestacker/_version.py +0 -1
  13. {shinestacker-1.5.2 → shinestacker-1.5.3}/.coveragerc +0 -0
  14. {shinestacker-1.5.2 → shinestacker-1.5.3}/.flake8 +0 -0
  15. {shinestacker-1.5.2 → shinestacker-1.5.3}/.github/workflows/ci-multiplatform.yml +0 -0
  16. {shinestacker-1.5.2 → shinestacker-1.5.3}/.github/workflows/pylint.yml +0 -0
  17. {shinestacker-1.5.2 → shinestacker-1.5.3}/.github/workflows/pypi-publish.yml +0 -0
  18. {shinestacker-1.5.2 → shinestacker-1.5.3}/.github/workflows/release.yml +0 -0
  19. {shinestacker-1.5.2 → shinestacker-1.5.3}/.gitignore +0 -0
  20. {shinestacker-1.5.2 → shinestacker-1.5.3}/.pylintrc +0 -0
  21. {shinestacker-1.5.2 → shinestacker-1.5.3}/.readthedocs.yaml +0 -0
  22. {shinestacker-1.5.2 → shinestacker-1.5.3}/LICENSE +0 -0
  23. {shinestacker-1.5.2 → shinestacker-1.5.3}/MANIFEST.in +0 -0
  24. {shinestacker-1.5.2 → shinestacker-1.5.3}/README.md +0 -0
  25. {shinestacker-1.5.2 → shinestacker-1.5.3}/THIRD_PARTY_LICENSES.txt +0 -0
  26. {shinestacker-1.5.2 → shinestacker-1.5.3}/docs/alignment.md +0 -0
  27. {shinestacker-1.5.2 → shinestacker-1.5.3}/docs/api.md +0 -0
  28. {shinestacker-1.5.2 → shinestacker-1.5.3}/docs/balancing.md +0 -0
  29. {shinestacker-1.5.2 → shinestacker-1.5.3}/docs/conf.py +0 -0
  30. {shinestacker-1.5.2 → shinestacker-1.5.3}/docs/focus_stacking.md +0 -0
  31. {shinestacker-1.5.2 → shinestacker-1.5.3}/docs/gui.md +0 -0
  32. {shinestacker-1.5.2 → shinestacker-1.5.3}/docs/index.md +0 -0
  33. {shinestacker-1.5.2 → shinestacker-1.5.3}/docs/job.md +0 -0
  34. {shinestacker-1.5.2 → shinestacker-1.5.3}/docs/main.md +0 -0
  35. {shinestacker-1.5.2 → shinestacker-1.5.3}/docs/multilayer.md +0 -0
  36. {shinestacker-1.5.2 → shinestacker-1.5.3}/docs/noise.md +0 -0
  37. {shinestacker-1.5.2 → shinestacker-1.5.3}/docs/requirements.txt +0 -0
  38. {shinestacker-1.5.2 → shinestacker-1.5.3}/docs/vignetting.md +0 -0
  39. {shinestacker-1.5.2 → shinestacker-1.5.3}/img/coffee.gif +0 -0
  40. {shinestacker-1.5.2 → shinestacker-1.5.3}/img/coffee_stack.jpg +0 -0
  41. {shinestacker-1.5.2 → shinestacker-1.5.3}/img/extreme-vignetting.jpg +0 -0
  42. {shinestacker-1.5.2 → shinestacker-1.5.3}/img/flies.gif +0 -0
  43. {shinestacker-1.5.2 → shinestacker-1.5.3}/img/flies_stack.jpg +0 -0
  44. {shinestacker-1.5.2 → shinestacker-1.5.3}/img/flow-diagram.png +0 -0
  45. {shinestacker-1.5.2 → shinestacker-1.5.3}/img/gui-finder.png +0 -0
  46. {shinestacker-1.5.2 → shinestacker-1.5.3}/img/gui-project-new.png +0 -0
  47. {shinestacker-1.5.2 → shinestacker-1.5.3}/img/gui-project-run.png +0 -0
  48. {shinestacker-1.5.2 → shinestacker-1.5.3}/img/gui-retouch.png +0 -0
  49. {shinestacker-1.5.2 → shinestacker-1.5.3}/index.html +0 -0
  50. {shinestacker-1.5.2 → shinestacker-1.5.3}/pyproject.toml +0 -0
  51. {shinestacker-1.5.2 → shinestacker-1.5.3}/requirements.txt +0 -0
  52. {shinestacker-1.5.2 → shinestacker-1.5.3}/scripts/build_release.py +0 -0
  53. {shinestacker-1.5.2 → shinestacker-1.5.3}/scripts/git-rev-list.sh +0 -0
  54. {shinestacker-1.5.2 → shinestacker-1.5.3}/scripts/validate-tomli.py +0 -0
  55. {shinestacker-1.5.2 → shinestacker-1.5.3}/setup.cfg +0 -0
  56. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/__init__.py +0 -0
  57. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/__init__.py +0 -0
  58. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/align.py +0 -0
  59. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/align_auto.py +0 -0
  60. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/align_parallel.py +0 -0
  61. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/balance.py +0 -0
  62. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/base_stack_algo.py +0 -0
  63. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/denoise.py +0 -0
  64. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/depth_map.py +0 -0
  65. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/exif.py +0 -0
  66. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/multilayer.py +0 -0
  67. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/noise_detection.py +0 -0
  68. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/pyramid.py +0 -0
  69. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/pyramid_auto.py +0 -0
  70. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/pyramid_tiles.py +0 -0
  71. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/sharpen.py +0 -0
  72. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/stack.py +0 -0
  73. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/stack_framework.py +0 -0
  74. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/utils.py +0 -0
  75. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/vignetting.py +0 -0
  76. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/algorithms/white_balance.py +0 -0
  77. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/app/__init__.py +0 -0
  78. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/app/about_dialog.py +0 -0
  79. /shinestacker-1.5.2/src/shinestacker/app/args.py → /shinestacker-1.5.3/src/shinestacker/app/args_parser_opts.py +0 -0
  80. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/app/gui_utils.py +0 -0
  81. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/app/help_menu.py +0 -0
  82. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/app/open_frames.py +0 -0
  83. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/config/__init__.py +0 -0
  84. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/config/config.py +0 -0
  85. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/config/constants.py +0 -0
  86. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/core/__init__.py +0 -0
  87. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/core/colors.py +0 -0
  88. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/core/core_utils.py +0 -0
  89. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/core/exceptions.py +0 -0
  90. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/core/framework.py +0 -0
  91. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/core/logging.py +0 -0
  92. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/__init__.py +0 -0
  93. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/action_config.py +0 -0
  94. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/action_config_dialog.py +0 -0
  95. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/base_form_dialog.py +0 -0
  96. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/colors.py +0 -0
  97. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/flow_layout.py +0 -0
  98. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/folder_file_selection.py +0 -0
  99. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/gui_images.py +0 -0
  100. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/gui_logging.py +0 -0
  101. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/gui_run.py +0 -0
  102. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/ico/focus_stack_bkg.png +0 -0
  103. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/ico/shinestacker.icns +0 -0
  104. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/ico/shinestacker.ico +0 -0
  105. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/ico/shinestacker.png +0 -0
  106. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/ico/shinestacker.svg +0 -0
  107. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/img/close-round-line-icon.png +0 -0
  108. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/img/forward-button-icon.png +0 -0
  109. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/img/play-button-round-icon.png +0 -0
  110. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/img/plus-round-line-icon.png +0 -0
  111. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/main_window.py +0 -0
  112. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/menu_manager.py +0 -0
  113. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/new_project.py +0 -0
  114. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/project_controller.py +0 -0
  115. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/project_converter.py +0 -0
  116. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/project_editor.py +0 -0
  117. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/project_model.py +0 -0
  118. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/recent_file_manager.py +0 -0
  119. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/select_path_widget.py +0 -0
  120. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/sys_mon.py +0 -0
  121. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/tab_widget.py +0 -0
  122. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/gui/time_progress_bar.py +0 -0
  123. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/__init__.py +0 -0
  124. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/base_filter.py +0 -0
  125. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/brush.py +0 -0
  126. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/brush_gradient.py +0 -0
  127. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/brush_preview.py +0 -0
  128. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/brush_tool.py +0 -0
  129. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/denoise_filter.py +0 -0
  130. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/display_manager.py +0 -0
  131. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/exif_data.py +0 -0
  132. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/file_loader.py +0 -0
  133. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/filter_manager.py +0 -0
  134. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/icon_container.py +0 -0
  135. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/image_editor_ui.py +0 -0
  136. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/image_view_status.py +0 -0
  137. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/image_viewer.py +0 -0
  138. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/io_gui_handler.py +0 -0
  139. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/io_manager.py +0 -0
  140. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/layer_collection.py +0 -0
  141. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/overlaid_view.py +0 -0
  142. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/shortcuts_help.py +0 -0
  143. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/transformation_manager.py +0 -0
  144. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/undo_manager.py +0 -0
  145. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/unsharp_mask_filter.py +0 -0
  146. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/vignetting_filter.py +0 -0
  147. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker/retouch/white_balance_filter.py +0 -0
  148. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker.egg-info/dependency_links.txt +0 -0
  149. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker.egg-info/entry_points.txt +0 -0
  150. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker.egg-info/requires.txt +0 -0
  151. {shinestacker-1.5.2 → shinestacker-1.5.3}/src/shinestacker.egg-info/top_level.txt +0 -0
@@ -2,6 +2,18 @@
2
2
 
3
3
  This page reports the main releases only and the main changes therein.
4
4
 
5
+ ## [v1.5.3] - 2025-09-21
6
+ **Bug fixes**
7
+
8
+ ### Fixed
9
+ - fixed brush preview visiblity in cursor style transitions
10
+ - fixed relative import in main app scripts
11
+
12
+ ### Changed
13
+ - implemenrted cursor dynamic color based on background image luminosity
14
+
15
+ ---
16
+
5
17
  ## [v1.5.2] - 2025-09-21
6
18
  **Bug fixes**
7
19
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shinestacker
3
- Version: 1.5.2
3
+ Version: 1.5.3
4
4
  Summary: ShineStacker
5
5
  Author-email: Luca Lista <luka.lista@gmail.com>
6
6
  License-Expression: LGPL-3.0
@@ -0,0 +1 @@
1
+ __version__ = '1.5.3'
@@ -20,7 +20,7 @@ from shinestacker.app.gui_utils import (
20
20
  disable_macos_special_menu_items, fill_app_menu, set_css_style)
21
21
  from shinestacker.app.help_menu import add_help_action
22
22
  from shinestacker.app.open_frames import open_frames
23
- from .args import add_project_arguments, add_retouch_arguments
23
+ from shinestacker.app.args_parser_opts import add_project_arguments, add_retouch_arguments
24
24
 
25
25
 
26
26
  class SelectionDialog(QDialog):
@@ -17,7 +17,7 @@ from shinestacker.gui.main_window import MainWindow
17
17
  from shinestacker.app.gui_utils import (
18
18
  disable_macos_special_menu_items, fill_app_menu, set_css_style)
19
19
  from shinestacker.app.help_menu import add_help_action
20
- from .args import add_project_arguments
20
+ from shinestacker.app.args_parser_opts import add_project_arguments
21
21
 
22
22
 
23
23
  class ProjectApp(MainWindow):
@@ -13,7 +13,7 @@ from shinestacker.app.gui_utils import (
13
13
  disable_macos_special_menu_items, fill_app_menu, set_css_style)
14
14
  from shinestacker.app.help_menu import add_help_action
15
15
  from shinestacker.app.open_frames import open_frames
16
- from .args import add_retouch_arguments
16
+ from shinestacker.app.args_parser_opts import add_retouch_arguments
17
17
 
18
18
 
19
19
  class RetouchApp(ImageEditorUI):
@@ -26,7 +26,7 @@ class _GuiConstants:
26
26
  'outer': (255, 0, 0, 200),
27
27
  'inner': (255, 0, 0, 150),
28
28
  'gradient_end': (255, 0, 0, 0),
29
- 'pen': (255, 0, 0, 200),
29
+ 'pen': (255, 255, 255, 200),
30
30
  'preview': (255, 180, 180),
31
31
  'cursor_inner': (255, 0, 0, 120),
32
32
  'preview_inner': (255, 255, 255, 150)
@@ -1,4 +1,5 @@
1
1
  # pylint: disable=C0114, C0115, C0116, R0904, R0915, E0611, R0902, R0911, R0914, E1003
2
+ import time
2
3
  from PySide6.QtCore import Qt, Signal, QEvent, QRectF
3
4
  from PySide6.QtGui import QCursor
4
5
  from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QFrame
@@ -58,6 +59,7 @@ class DoubleViewBase(ViewStrategy, QWidget, ViewSignals):
58
59
  self.current_view.setFocusPolicy(Qt.NoFocus)
59
60
  self.master_view.setFocusPolicy(Qt.NoFocus)
60
61
  self.current_brush_cursor = None
62
+ self.last_color_update_time_current = 0
61
63
 
62
64
  def setup_layout(self):
63
65
  raise NotImplementedError("Subclasses must implement setup_layout")
@@ -311,9 +313,11 @@ class DoubleViewBase(ViewStrategy, QWidget, ViewSignals):
311
313
  radius = size / 2
312
314
  self.current_brush_cursor.setRect(
313
315
  scene_pos.x() - radius, scene_pos.y() - radius, size, size)
316
+ self.update_current_cursor_color()
314
317
  self.current_brush_cursor.show()
315
318
  self.brush_cursor.setRect(
316
319
  scene_pos.x() - radius, scene_pos.y() - radius, size, size)
320
+ self.update_master_cursor_color()
317
321
  self.brush_cursor.show()
318
322
  else:
319
323
  self.brush_cursor.hide()
@@ -321,6 +325,19 @@ class DoubleViewBase(ViewStrategy, QWidget, ViewSignals):
321
325
  self.master_view.setCursor(Qt.ArrowCursor)
322
326
  self.current_view.setCursor(Qt.ArrowCursor)
323
327
 
328
+ def update_current_cursor_color(self):
329
+ self.update_cursor_color_based_on_background(
330
+ self.current_brush_cursor, self.current_layer(),
331
+ self.get_visible_current_image_region, self.get_current_pixmap,
332
+ self.update_color_time_current)
333
+
334
+ def update_color_time_current(self):
335
+ current_time = time.time()
336
+ if current_time - self.last_color_update_time_current < 0.2:
337
+ return False
338
+ self.last_color_update_time_current = current_time
339
+ return True
340
+
324
341
  def handle_master_mouse_press(self, event):
325
342
  self.setFocus()
326
343
  self.mouse_press_event(event)
@@ -425,6 +442,7 @@ class DoubleViewBase(ViewStrategy, QWidget, ViewSignals):
425
442
  scene_pos.x() - radius, scene_pos.y() - radius,
426
443
  size, size)
427
444
  if self.brush_cursor.isVisible():
445
+ self.update_current_cursor_color()
428
446
  self.current_brush_cursor.show()
429
447
  else:
430
448
  self.current_brush_cursor.hide()
@@ -1,5 +1,6 @@
1
1
  # pylint: disable=C0114, C0115, C0116, E0611, R0904, R0903, R0902, E1101, R0914, R0913, R0917
2
2
  import math
3
+ import time
3
4
  from abc import abstractmethod
4
5
  import numpy as np
5
6
  from PySide6.QtCore import Qt, QPointF, QTime, QPoint, Signal, QRectF
@@ -116,6 +117,7 @@ class ViewStrategy(LayerCollectionHandler):
116
117
  self.last_brush_pos = None
117
118
  self.last_mouse_pos = None
118
119
  self.last_update_time = QTime.currentTime()
120
+ self.last_color_update_time = 0
119
121
 
120
122
  @abstractmethod
121
123
  def create_pixmaps(self):
@@ -236,6 +238,8 @@ class ViewStrategy(LayerCollectionHandler):
236
238
 
237
239
  def set_cursor_style(self, style):
238
240
  self.cursor_style = style
241
+ if style == 'preview':
242
+ self.show_brush_preview()
239
243
  self.update_brush_cursor()
240
244
 
241
245
  def get_cursor_style(self):
@@ -402,9 +406,12 @@ class ViewStrategy(LayerCollectionHandler):
402
406
  self.update_cursor_pen_width()
403
407
 
404
408
  def setup_simple_brush_style(self, center_x, center_y, radius):
409
+ if self.brush_cursor:
410
+ pen = self.brush_cursor.pen()
411
+ else:
412
+ pen = QPen(QColor(*gui_constants.BRUSH_COLORS['pen']), self.current_line_width())
405
413
  gradient = create_default_brush_gradient(center_x, center_y, radius, self.brush)
406
- self.brush_cursor.setPen(QPen(QColor(*gui_constants.BRUSH_COLORS['pen']),
407
- self.current_line_width()))
414
+ self.brush_cursor.setPen(pen)
408
415
  self.brush_cursor.setBrush(QBrush(gradient))
409
416
 
410
417
  def create_circle(self, scene, line_style=Qt.SolidLine):
@@ -469,10 +476,58 @@ class ViewStrategy(LayerCollectionHandler):
469
476
  self.brush_preview.update(scene_pos, int(size))
470
477
  else:
471
478
  self.hide_brush_preview()
472
- if self.cursor_style != 'outline':
473
- self.setup_simple_brush_style(scene_pos.x(), scene_pos.y(), radius)
479
+ self.update_master_cursor_color()
480
+ if self.cursor_style == 'brush':
481
+ self.setup_simple_brush_style(scene_pos.x(), scene_pos.y(), radius)
474
482
  self.show_brush_cursor()
475
483
 
484
+ def update_color_time(self):
485
+ current_time = time.time()
486
+ if current_time - self.last_color_update_time < 0.2:
487
+ return False
488
+ self.last_color_update_time = current_time
489
+ return True
490
+
491
+ def update_master_cursor_color(self):
492
+ self.update_cursor_color_based_on_background(
493
+ self.brush_cursor, self.master_layer(),
494
+ self.get_visible_image_region, self.get_master_pixmap,
495
+ self.update_color_time)
496
+
497
+ def update_cursor_color_based_on_background(
498
+ self, cursor, layer,
499
+ visible_region, get_pixmap, update_timer):
500
+ if not update_timer():
501
+ return
502
+ cursor_rect = cursor.rect()
503
+ image_region = visible_region()
504
+ if image_region and cursor_rect.intersects(image_region):
505
+ intersect_rect = cursor_rect.intersected(image_region)
506
+ top_left = get_pixmap().mapFromScene(intersect_rect.topLeft())
507
+ bottom_right = get_pixmap().mapFromScene(intersect_rect.bottomRight())
508
+ x1, y1 = max(0, int(top_left.x())), max(0, int(top_left.y()))
509
+ x2, y2 = min(layer.shape[1], int(bottom_right.x())), \
510
+ min(layer.shape[0], int(bottom_right.y()))
511
+ if x2 > x1 and y2 > y1:
512
+ region = layer[y1:y2, x1:x2]
513
+ if region.size > 10000:
514
+ step = int(math.sqrt(region.size / 100))
515
+ region = region[::step, ::step]
516
+ if region.ndim == 3:
517
+ luminosity = np.dot(region[..., :3], [0.299, 0.587, 0.114])
518
+ avg_luminosity = np.mean(luminosity)
519
+ else:
520
+ avg_luminosity = np.mean(region)
521
+ if region.dtype == np.uint16:
522
+ avg_luminosity /= 256.0
523
+ if avg_luminosity < 128:
524
+ new_color = QColor(255, 255, 255)
525
+ else:
526
+ new_color = QColor(0, 0, 0)
527
+ current_pen = cursor.pen()
528
+ current_pen.setColor(new_color)
529
+ cursor.setPen(current_pen)
530
+
476
531
  def position_on_image(self, pos):
477
532
  master_view = self.get_master_view()
478
533
  pixmap = self.get_master_pixmap()
@@ -485,11 +540,20 @@ class ViewStrategy(LayerCollectionHandler):
485
540
  return None
486
541
  master_view = self.get_master_view()
487
542
  master_pixmap = self.get_master_pixmap()
488
- pixmap = self.get_master_pixmap()
489
543
  view_rect = master_view.viewport().rect()
490
544
  scene_rect = master_view.mapToScene(view_rect).boundingRect()
491
545
  image_rect = master_pixmap.mapFromScene(scene_rect).boundingRect().toRect()
492
- return image_rect.intersected(pixmap.boundingRect().toRect())
546
+ return image_rect.intersected(master_pixmap.boundingRect().toRect())
547
+
548
+ def get_visible_current_image_region(self):
549
+ if self.empty():
550
+ return None
551
+ current_view = self.get_current_view()
552
+ current_pixmap = self.get_current_pixmap()
553
+ view_rect = current_view.viewport().rect()
554
+ scene_rect = current_view.mapToScene(view_rect).boundingRect()
555
+ image_rect = current_pixmap.mapFromScene(scene_rect).boundingRect().toRect()
556
+ return image_rect.intersected(current_pixmap.boundingRect().toRect())
493
557
 
494
558
  def get_visible_image_portion(self):
495
559
  if self.has_no_master_layer():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shinestacker
3
- Version: 1.5.2
3
+ Version: 1.5.3
4
4
  Summary: ShineStacker
5
5
  Author-email: Luca Lista <luka.lista@gmail.com>
6
6
  License-Expression: LGPL-3.0
@@ -71,7 +71,7 @@ src/shinestacker/algorithms/vignetting.py
71
71
  src/shinestacker/algorithms/white_balance.py
72
72
  src/shinestacker/app/__init__.py
73
73
  src/shinestacker/app/about_dialog.py
74
- src/shinestacker/app/args.py
74
+ src/shinestacker/app/args_parser_opts.py
75
75
  src/shinestacker/app/gui_utils.py
76
76
  src/shinestacker/app/help_menu.py
77
77
  src/shinestacker/app/main.py
@@ -1 +0,0 @@
1
- __version__ = '1.5.2'
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes