shinestacker 0.2.0.post1.dev1__tar.gz → 0.2.2__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 (179) hide show
  1. shinestacker-0.2.2/.coverage +0 -0
  2. shinestacker-0.2.2/.coveragerc +5 -0
  3. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/.github/workflows/ci-multiplatform.yml +9 -3
  4. {shinestacker-0.2.0.post1.dev1/sandbox → shinestacker-0.2.2/.github/workflows}/pypi-publish.yml +1 -1
  5. shinestacker-0.2.2/.readthedocs.yaml +22 -0
  6. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/CHANGELOG.md +20 -0
  7. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/PKG-INFO +10 -5
  8. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/README.md +7 -4
  9. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/docs/alignment.md +3 -1
  10. shinestacker-0.2.2/docs/api.md +10 -0
  11. shinestacker-0.2.2/docs/conf.py +42 -0
  12. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/docs/gui.md +5 -5
  13. shinestacker-0.2.2/docs/index.md +22 -0
  14. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/docs/job.md +2 -2
  15. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/docs/main.md +13 -10
  16. shinestacker-0.2.2/docs/requirements.txt +3 -0
  17. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/pyproject.toml +4 -0
  18. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/scripts/build_release.py +2 -8
  19. shinestacker-0.2.2/src/shinestacker/__init__.py +16 -0
  20. shinestacker-0.2.2/src/shinestacker/_version.py +1 -0
  21. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/algorithms/__init__.py +5 -0
  22. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/algorithms/align.py +0 -1
  23. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/algorithms/core_utils.py +1 -1
  24. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/app/main.py +1 -7
  25. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/app/project.py +2 -2
  26. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/app/retouch.py +3 -2
  27. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/config/__init__.py +2 -0
  28. shinestacker-0.2.2/src/shinestacker/core/__init__.py +11 -0
  29. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/main_window.py +3 -0
  30. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/new_project.py +1 -7
  31. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/project_editor.py +0 -4
  32. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/retouch/exif_data.py +1 -7
  33. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/retouch/image_editor.py +0 -2
  34. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/retouch/shortcuts_help.py +1 -7
  35. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker.egg-info/PKG-INFO +10 -5
  36. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker.egg-info/SOURCES.txt +17 -6
  37. shinestacker-0.2.2/tests/test_0002_config.py +60 -0
  38. shinestacker-0.2.2/tests/test_0006_exceptions.py +99 -0
  39. shinestacker-0.2.2/tests/test_0011_core_utils.py +105 -0
  40. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_0020_noise_detection.py +5 -4
  41. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_0030_align.py +17 -5
  42. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_0032_align_methods.py +11 -3
  43. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_0040_balance.py +6 -6
  44. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_0050_align_balance.py +4 -4
  45. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_0060_stack.py +4 -4
  46. shinestacker-0.2.2/tests/test_0061_depth_map.py +84 -0
  47. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_0070_multilayer.py +23 -9
  48. shinestacker-0.2.2/tests/test_0080_exif.py +220 -0
  49. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_0090_vignetting.py +4 -2
  50. shinestacker-0.2.2/tests/test_0091_vignetting_algo.py +127 -0
  51. shinestacker-0.2.0.post1.dev1/sandbox/test_alignment_multiple.py +0 -124
  52. shinestacker-0.2.0.post1.dev1/src/shinestacker/__init__.py +0 -3
  53. shinestacker-0.2.0.post1.dev1/src/shinestacker/_version.py +0 -1
  54. shinestacker-0.2.0.post1.dev1/src/shinestacker/core/__init__.py +0 -5
  55. shinestacker-0.2.0.post1.dev1/tests/test_0080_exif.py +0 -90
  56. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/.flake8 +0 -0
  57. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/.github/workflows/release.yml +0 -0
  58. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/.gitignore +0 -0
  59. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/LICENSE +0 -0
  60. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/docs/balancing.md +0 -0
  61. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/docs/focus_stacking.md +0 -0
  62. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/docs/multilayer.md +0 -0
  63. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/docs/noise.md +0 -0
  64. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/docs/vignetting.md +0 -0
  65. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/balance-only.fsp +0 -0
  66. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/complete-project.fsp +0 -0
  67. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/focus-stack-1.ipynb +0 -0
  68. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/focus-stack-2.ipynb +0 -0
  69. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-jpg/0000.jpg +0 -0
  70. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-jpg/0001.jpg +0 -0
  71. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-jpg/0002.jpg +0 -0
  72. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-jpg/0003.jpg +0 -0
  73. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-jpg/0004.jpg +0 -0
  74. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-jpg/0005.jpg +0 -0
  75. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-noise/0001.jpg +0 -0
  76. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-noise/0002.jpg +0 -0
  77. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-noise/0003.jpg +0 -0
  78. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-noise/0004.jpg +0 -0
  79. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-noise/0005.jpg +0 -0
  80. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-noise/0006.jpg +0 -0
  81. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-tif/0000.tif +0 -0
  82. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-tif/0001.tif +0 -0
  83. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-tif/0002.tif +0 -0
  84. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-tif/0003.tif +0 -0
  85. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-tif/0004.tif +0 -0
  86. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-tif/0005.tif +0 -0
  87. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-vignetted/vig-0000.jpg +0 -0
  88. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-vignetted/vig-0001.jpg +0 -0
  89. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-vignetted/vig-0002.jpg +0 -0
  90. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/input/img-vignetted/vig-0003.jpg +0 -0
  91. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/stack-comparison.fsp +0 -0
  92. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/stack-from-frames.fsp +0 -0
  93. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/examples/vignetting.fsp +0 -0
  94. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/img/flies.gif +0 -0
  95. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/img/flies_stack.jpg +0 -0
  96. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/img/flow-diagram.png +0 -0
  97. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/img/gui-finder.png +0 -0
  98. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/img/gui-project-new.png +0 -0
  99. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/img/gui-project-run.png +0 -0
  100. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/img/gui-retouch.png +0 -0
  101. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/scripts/validate-tomli.py +0 -0
  102. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/setup.cfg +0 -0
  103. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/algorithms/balance.py +0 -0
  104. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/algorithms/depth_map.py +0 -0
  105. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/algorithms/exif.py +0 -0
  106. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/algorithms/multilayer.py +0 -0
  107. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/algorithms/noise_detection.py +0 -0
  108. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/algorithms/pyramid.py +0 -0
  109. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/algorithms/stack.py +0 -0
  110. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/algorithms/stack_framework.py +0 -0
  111. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/algorithms/utils.py +0 -0
  112. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/algorithms/vignetting.py +0 -0
  113. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/app/__init__.py +0 -0
  114. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/app/about_dialog.py +0 -0
  115. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/app/app_config.py +0 -0
  116. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/app/gui_utils.py +0 -0
  117. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/app/help_menu.py +0 -0
  118. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/app/open_frames.py +0 -0
  119. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/config/config.py +0 -0
  120. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/config/constants.py +0 -0
  121. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/config/gui_constants.py +0 -0
  122. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/core/colors.py +0 -0
  123. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/core/core_utils.py +0 -0
  124. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/core/exceptions.py +0 -0
  125. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/core/framework.py +0 -0
  126. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/core/logging.py +0 -0
  127. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/__init__.py +0 -0
  128. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/action_config.py +0 -0
  129. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/actions_window.py +0 -0
  130. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/colors.py +0 -0
  131. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/gui_images.py +0 -0
  132. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/gui_logging.py +0 -0
  133. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/gui_run.py +0 -0
  134. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2/src/shinestacker/gui}/ico/focus_stack_bkg.png +0 -0
  135. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2/src/shinestacker/gui}/ico/shinestacker.icns +0 -0
  136. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2/src/shinestacker/gui}/ico/shinestacker.ico +0 -0
  137. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2/src/shinestacker/gui}/ico/shinestacker.png +0 -0
  138. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/img/close-round-line-icon.png +0 -0
  139. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/img/forward-button-icon.png +0 -0
  140. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/img/play-button-round-icon.png +0 -0
  141. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/img/plus-round-line-icon.png +0 -0
  142. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/project_converter.py +0 -0
  143. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/gui/project_model.py +0 -0
  144. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/retouch/__init__.py +0 -0
  145. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/retouch/brush.py +0 -0
  146. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/retouch/brush_controller.py +0 -0
  147. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/retouch/brush_preview.py +0 -0
  148. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/retouch/file_loader.py +0 -0
  149. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/retouch/image_editor_ui.py +0 -0
  150. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/retouch/image_viewer.py +0 -0
  151. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker/retouch/undo_manager.py +0 -0
  152. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker.egg-info/dependency_links.txt +0 -0
  153. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker.egg-info/entry_points.txt +0 -0
  154. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker.egg-info/requires.txt +0 -0
  155. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/src/shinestacker.egg-info/top_level.txt +0 -0
  156. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test-align-balance.ipynb +0 -0
  157. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test-align.ipynb +0 -0
  158. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test-balance.ipynb +0 -0
  159. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test-exif.ipynb +0 -0
  160. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test-job.ipynb +0 -0
  161. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test-logging.ipynb +0 -0
  162. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test-multilayer.ipynb +0 -0
  163. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test-noise-detection.ipynb +0 -0
  164. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test-stack.ipynb +0 -0
  165. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test-vignetting.ipynb +0 -0
  166. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_0000_logging.py +0 -0
  167. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_0001_colors.py +0 -0
  168. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_0005_make_test_img.py +0 -0
  169. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_0010_job.py +0 -0
  170. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_0031_align_precision.py +0 -0
  171. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_1000_brush_mask.py +0 -0
  172. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_1010_gui.py +0 -0
  173. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_1020_gui_images.py +0 -0
  174. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_1030_gui_logging.py +0 -0
  175. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_1040_action_config.py +0 -0
  176. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_1050_project_converter.py +0 -0
  177. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_1060_gui_run.py +0 -0
  178. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_1070_project_editor.py +0 -0
  179. {shinestacker-0.2.0.post1.dev1 → shinestacker-0.2.2}/tests/test_1080_actions_window.py +0 -0
Binary file
@@ -0,0 +1,5 @@
1
+ [run]
2
+ omit =
3
+ src/shinestacker/gui/*
4
+ src/shinestacker/app/*
5
+ src/shinestacker/retouch/*
@@ -30,10 +30,16 @@ jobs:
30
30
 
31
31
  - name: Install dependencies
32
32
  run: |
33
- python -m pip install --upgrade pip setuptools
33
+ python -m pip install --upgrade pip setuptools pytest-cov
34
34
  pip install -e .[dev]
35
35
 
36
36
  - name: Run non-GUI tests (test_00*.py)
37
- working-directory: tests
38
37
  run: >
39
- python3 -c "import glob, pytest, sys; sys.exit(pytest.main(glob.glob('test_00*.py') + ['-v', '--disable-warnings']))"
38
+ python3 -c "import glob, pytest, sys; sys.exit(pytest.main(glob.glob('tests/test_00*.py') + ['-v', '--disable-warnings', '--cov=shinestacker', '--cov-report=xml']))"
39
+
40
+ - name: Upload coverage to Codecov
41
+ if: matrix.os == 'ubuntu-latest'
42
+ uses: codecov/codecov-action@v5
43
+ with:
44
+ token: ${{ secrets.CODECOV_TOKEN }}
45
+ slug: lucalista/shinestacker
@@ -10,7 +10,7 @@ jobs:
10
10
  runs-on: ubuntu-latest
11
11
 
12
12
  permissions:
13
- id-token: write # Needed for trusted publishing (if you prefer)
13
+ id-token: write
14
14
  contents: read
15
15
 
16
16
  steps:
@@ -0,0 +1,22 @@
1
+ # Read the Docs configuration file
2
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3
+
4
+ # Required
5
+ version: 2
6
+
7
+ # Set the OS, Python version, and other tools you might need
8
+ build:
9
+ os: ubuntu-24.04
10
+ tools:
11
+ python: "3.12"
12
+
13
+ # Build documentation in the "docs/" directory with Sphinx
14
+ sphinx:
15
+ configuration: docs/conf.py
16
+
17
+ # Optionally, but recommended,
18
+ # declare the Python requirements required to build your documentation
19
+ # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
20
+ python:
21
+ install:
22
+ - requirements: docs/requirements.txt
@@ -4,6 +4,26 @@ This page reports the main releases only and the main changes therein.
4
4
 
5
5
  ---
6
6
 
7
+ ## [v0.2.2] - 2025-07-28
8
+ **More stability and improved tests**
9
+
10
+ ### Changes
11
+
12
+ * improved test suite and enhanced test coverage
13
+ * updated documentation
14
+ * some stability improvements
15
+
16
+ ---
17
+
18
+ ## [v0.2.1] - 2025-07-27
19
+ **Icon location fix**
20
+
21
+ ### Changes
22
+
23
+ * icon location fixed, compatibly with PyPI and bundle release build
24
+
25
+ ---
26
+
7
27
  ## [v0.2.0] - 2025-07-27
8
28
  **Stability improvements and new package name**
9
29
 
@@ -1,9 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shinestacker
3
- Version: 0.2.0.post1.dev1
3
+ Version: 0.2.2
4
4
  Summary: ShineStacker
5
5
  Author-email: Luca Lista <luka.lista@gmail.com>
6
6
  License-Expression: LGPL-3.0
7
+ Project-URL: Homepage, https://github.com/lucalista/shinestacker
8
+ Project-URL: Documentation, https://shinestacker.readthedocs.io/
7
9
  Classifier: Programming Language :: Python :: 3
8
10
  Classifier: Operating System :: OS Independent
9
11
  Requires-Python: >=3.12
@@ -30,17 +32,20 @@ Dynamic: license-file
30
32
  # Shine Stacker Processing Framework
31
33
 
32
34
  [![CI multiplatform](https://github.com/lucalista/shinestacker/actions/workflows/ci-multiplatform.yml/badge.svg)](https://github.com/lucalista/shinestacker/actions/workflows/ci-multiplatform.yml)
35
+ [![PyPI version](https://badge.fury.io/py/shinestacker.svg)](https://pypi.org/project/shinestacker/)
36
+ [![Python Versions](https://img.shields.io/pypi/pyversions/shinestacker)](https://pypi.org/project/shinestacker/)
37
+ [![codecov](https://codecov.io/github/lucalista/shinestacker/graph/badge.svg?token=Y5NKW6VH5G)](https://codecov.io/github/lucalista/shinestacker)
33
38
 
34
- <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flies.gif' width="400"> <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flies_stack.jpg' width="400">
39
+ <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flies.gif' width="400" referrerpolicy="no-referrer"> <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flies_stack.jpg' width="400" referrerpolicy="no-referrer">
35
40
 
36
- ## Documentation
41
+ # Documentation
37
42
 
38
43
  📖 [Main documentation](https://github.com/lucalista/shinestacker/blob/main/docs/main.md) • 📝 [Changelog](https://github.com/lucalista/shinestacker/blob/main/CHANGELOG.md)
39
44
 
40
45
 
41
- # Credits:
46
+ # Credits
42
47
 
43
- The main pyramid stack algorithm was inspired by the [Laplacian pyramids method](https://github.com/sjawhar/focus-stacking) implementation by Sami Jawhar. The latest implementation was rewritten from the original code that was used under permission of the author for initial versions of this package.
48
+ The main pyramid stack algorithm was initially inspired by the [Laplacian pyramids method](https://github.com/sjawhar/focus-stacking) implementation by Sami Jawhar that was used under permission of the author for initial versions of this package. The implementation in the latest releases was rewritten from the original code.
44
49
 
45
50
  # Resources
46
51
 
@@ -1,17 +1,20 @@
1
1
  # Shine Stacker Processing Framework
2
2
 
3
3
  [![CI multiplatform](https://github.com/lucalista/shinestacker/actions/workflows/ci-multiplatform.yml/badge.svg)](https://github.com/lucalista/shinestacker/actions/workflows/ci-multiplatform.yml)
4
+ [![PyPI version](https://badge.fury.io/py/shinestacker.svg)](https://pypi.org/project/shinestacker/)
5
+ [![Python Versions](https://img.shields.io/pypi/pyversions/shinestacker)](https://pypi.org/project/shinestacker/)
6
+ [![codecov](https://codecov.io/github/lucalista/shinestacker/graph/badge.svg?token=Y5NKW6VH5G)](https://codecov.io/github/lucalista/shinestacker)
4
7
 
5
- <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flies.gif' width="400"> <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flies_stack.jpg' width="400">
8
+ <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flies.gif' width="400" referrerpolicy="no-referrer"> <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flies_stack.jpg' width="400" referrerpolicy="no-referrer">
6
9
 
7
- ## Documentation
10
+ # Documentation
8
11
 
9
12
  📖 [Main documentation](https://github.com/lucalista/shinestacker/blob/main/docs/main.md) • 📝 [Changelog](https://github.com/lucalista/shinestacker/blob/main/CHANGELOG.md)
10
13
 
11
14
 
12
- # Credits:
15
+ # Credits
13
16
 
14
- The main pyramid stack algorithm was inspired by the [Laplacian pyramids method](https://github.com/sjawhar/focus-stacking) implementation by Sami Jawhar. The latest implementation was rewritten from the original code that was used under permission of the author for initial versions of this package.
17
+ The main pyramid stack algorithm was initially inspired by the [Laplacian pyramids method](https://github.com/sjawhar/focus-stacking) implementation by Sami Jawhar that was used under permission of the author for initial versions of this package. The implementation in the latest releases was rewritten from the original code.
15
18
 
16
19
  # Resources
17
20
 
@@ -1,4 +1,6 @@
1
- # Alignment and registration: scale, tanslation and rotation correction, or full perspective correction
1
+ # Alignment and registration
2
+
3
+ Automatically align, scale, tanslate and rotate or apply full perspective correction.
2
4
 
3
5
  ```python
4
6
  job.add_action(Actions("align", [AlignFrames(*options)])
@@ -0,0 +1,10 @@
1
+ # API Reference
2
+
3
+ ```{toctree}
4
+ :maxdepth: 2
5
+ :caption: API Modules
6
+
7
+ _autosummary/shinestacker.config
8
+ _autosummary/shinestacker.core
9
+ _autosummary/shinestacker.algorithms
10
+ ```
@@ -0,0 +1,42 @@
1
+ import os
2
+ import sys
3
+ sys.path.insert(0, os.path.abspath('../src'))
4
+
5
+ project = 'Shine Stacker'
6
+ author = 'Luca Lista'
7
+ html_title = "Shine Stacker Documentation"
8
+
9
+ extensions = [
10
+ 'myst_parser',
11
+ 'sphinx.ext.mathjax',
12
+ ]
13
+
14
+ myst_enable_extensions = [
15
+ "dollarmath",
16
+ "amsmath",
17
+ ]
18
+
19
+ source_suffix = {
20
+ '.rst': 'restructuredtext',
21
+ '.md': 'markdown',
22
+ }
23
+
24
+ master_doc = 'index'
25
+
26
+ html_theme = 'furo'
27
+
28
+ extensions = [
29
+ 'myst_parser',
30
+ 'sphinx.ext.autodoc',
31
+ 'sphinx.ext.napoleon',
32
+ 'sphinx.ext.autosummary',
33
+ ]
34
+
35
+ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '**/.ipynb_checkpoints']
36
+
37
+ autosummary_generate = True
38
+ autodoc_default_options = {
39
+ 'members': True,
40
+ 'undoc-members': True,
41
+ 'show-inheritance': True,
42
+ }
@@ -20,7 +20,7 @@ noisy pixel masking.
20
20
 
21
21
  * If the app is dowloaded from the [releases page](https://github.com/lucalista/focusstack/releases), after the ```zip``` archive is uncompressed, just double-click the app icon.
22
22
 
23
- <img src='../img/gui-finder.png' width="300">
23
+ <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/gui-finder.png' width="300" referrerpolicy="no-referrer">
24
24
 
25
25
  **Platform Tip**: Windows apps are inside `/focusstack/`, macOS/Linux apps are directly in the uncompressed folder.
26
26
 
@@ -35,7 +35,7 @@ Switching from *Project* to *Retouch* can be done from the *FocusStack* main men
35
35
 
36
36
  When the app starts, it proposes to create a new project.
37
37
 
38
- <img src='../img/gui-project-new.png' width="600">
38
+ <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/gui-project-new.png' width="600" referrerpolicy="no-referrer">
39
39
 
40
40
  ### Creating Projects
41
41
  1. Select source folder (JPEG/TIFF 8/16-bit)
@@ -44,7 +44,7 @@ When the app starts, it proposes to create a new project.
44
44
  - Real-time logs & progress bar
45
45
  - Thumbnail previews for each stage
46
46
 
47
- <img src='../img/flow-diagram.png' width="900" alt="FocusStack workflow: Source images → Alignment → Balancing → Stacking">
47
+ <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flow-diagram.png' width="900" alt="FocusStack workflow: Source images → Alignment → Balancing → Stacking" referrerpolicy="no-referrer">
48
48
 
49
49
  > **Large Set Tip**: For 100+ images:
50
50
  > - Split into 10-15 image "bunches"
@@ -63,7 +63,7 @@ Some actions can be combined in order to produce a single intermediate output (a
63
63
 
64
64
  It is possible to run a single job, or all jobs within a project.
65
65
 
66
- <img src='../img/gui-project-run.png' width="600">
66
+ <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/gui-project-run.png' width="600" referrerpolicy="no-referrer">
67
67
 
68
68
  ### Project Run Tabs
69
69
 
@@ -75,7 +75,7 @@ When the job finishes, a *Retouch* button is enabled, which opens the output ima
75
75
 
76
76
  ## Retouch area
77
77
 
78
- <img src='../img/gui-retouch.png' width="600">
78
+ <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/gui-retouch.png' width="600" referrerpolicy="no-referrer">
79
79
 
80
80
  ### Brush Properties
81
81
  Adjust in the top toolbar:
@@ -0,0 +1,22 @@
1
+ # Shine Stacker
2
+
3
+ ## Focus Stacking Processing Framework and GUI
4
+
5
+ [![CI multiplatform](https://github.com/lucalista/shinestacker/actions/workflows/ci-multiplatform.yml/badge.svg)](https://github.com/lucalista/shinestacker/actions/workflows/ci-multiplatform.yml)
6
+ [![PyPI version](https://badge.fury.io/py/shinestacker.svg)](https://pypi.org/project/shinestacker/)
7
+ [![Python Versions](https://img.shields.io/pypi/pyversions/shinestacker)](https://pypi.org/project/shinestacker/)
8
+ [![codecov](https://codecov.io/github/lucalista/shinestacker/graph/badge.svg?token=Y5NKW6VH5G)](https://codecov.io/github/lucalista/shinestacker)
9
+
10
+ ```{toctree}
11
+ :maxdepth: 2
12
+ :caption: Content
13
+
14
+ main.md
15
+ gui.md
16
+ job.md
17
+ alignment.md
18
+ balancing.md
19
+ focus_stacking.md
20
+ multilayer.md
21
+ noise.md
22
+ vignetting.md
@@ -1,4 +1,4 @@
1
- # Job creation
1
+ # Job creation and action scheduling
2
2
 
3
3
  Create a job, then schedule the desired actions in a job, then run the job.
4
4
 
@@ -13,7 +13,7 @@ Arguments are:
13
13
  * ```callbacks``` (optional, default: ```None```): dictionary of callback functions for internal use. If equal to ```'tqdm'```, a progress bar is shown in either text mode or jupyter notebook.
14
14
  * ```enabled``` (optional, default: ```True```): allows to switch on and off all actions within a job.
15
15
 
16
- # Schedule multiple actions based on a reference image: align and/or balance images
16
+ ## Schedule multiple actions based on a reference image: align and/or balance images
17
17
 
18
18
  The class ```CombinedActions``` runs multiple actions on each of the frames appearing in a path.
19
19
 
@@ -1,8 +1,11 @@
1
1
  # Shine Stacker Processing Framework
2
2
 
3
3
  [![CI multiplatform](https://github.com/lucalista/shinestacker/actions/workflows/ci-multiplatform.yml/badge.svg)](https://github.com/lucalista/shinestacker/actions/workflows/ci-multiplatform.yml)
4
+ [![PyPI version](https://badge.fury.io/py/shinestacker.svg)](https://pypi.org/project/shinestacker/)
5
+ [![Python Versions](https://img.shields.io/pypi/pyversions/shinestacker)](https://pypi.org/project/shinestacker/)
6
+ [![codecov](https://codecov.io/github/lucalista/shinestacker/graph/badge.svg?token=Y5NKW6VH5G)](https://codecov.io/github/lucalista/shinestacker)
4
7
 
5
- <img src='../img/flies.gif' width="400"> <img src='../img/flies_stack.jpg' width="400">
8
+ <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flies.gif' width="400"> <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flies_stack.jpg' width="400">
6
9
 
7
10
  > **Professional focus stacking** for microscopy, macro photography, and computational imaging
8
11
 
@@ -76,14 +79,14 @@ job.run()
76
79
 
77
80
  ## Documentation Highlights
78
81
  ### Core Processing
79
- - [Graphical User Interface](../docs/gui.md)
80
- - [Image alignment](../docs/alignment.md)
81
- - [Luminosity and color balancing](../docs/balancing.md)
82
- - [Stacking algorithms](../docs/focus_stacking.md)
82
+ - [Graphical User Interface](gui.md)
83
+ - [Image alignment](alignment.md)
84
+ - [Luminosity and color balancing](balancing.md)
85
+ - [Stacking algorithms](focus_stacking.md)
83
86
  ### Advanced Modules
84
- - [Noisy pixel masking](../docs/noise.md)
85
- - [Vignetting correction](../docs/vignetting.md)
86
- - [Multilayer image](../docs/multilayer.md)
87
+ - [Noisy pixel masking](noise.md)
88
+ - [Vignetting correction](vignetting.md)
89
+ - [Multilayer image](multilayer.md)
87
90
 
88
91
  ## Requirements
89
92
 
@@ -96,12 +99,12 @@ job.run()
96
99
  ```bash
97
100
  pip install imagecodecs matplotlib numpy opencv-python pillow psdtags scipy setuptools-scm tifffile tqdm
98
101
  ```
99
- # GUI support
102
+ ## GUI support
100
103
  ```bash
101
104
  pip install argparse PySide6 jsonpickle webbrowser
102
105
  ```
103
106
 
104
- # Jupyter support
107
+ ## Jupyter support
105
108
  ```bash
106
109
  pip install ipywidgets
107
110
  ```
@@ -0,0 +1,3 @@
1
+ sphinx
2
+ myst-parser
3
+ furo
@@ -33,6 +33,10 @@ dependencies = [
33
33
  "setuptools-scm"
34
34
  ]
35
35
 
36
+ [project.urls]
37
+ Homepage = "https://github.com/lucalista/shinestacker"
38
+ Documentation = "https://shinestacker.readthedocs.io/"
39
+
36
40
  [project.optional-dependencies]
37
41
  dev = [
38
42
  "pytest",
@@ -20,20 +20,14 @@ pyinstaller_cmd = ["pyinstaller", "--onedir", f"--name={app_name}", "--paths=src
20
20
  f"--distpath=dist/{package_dir}", f"--collect-all={project_name}",
21
21
  "--collect-data=imagecodecs", "--collect-submodules=imagecodecs", "--copy-metadata=imagecodecs"]
22
22
  if sys_name == 'darwin':
23
- pyinstaller_cmd += ["--windowed", "--icon=ico/shinestacker.icns"]
23
+ pyinstaller_cmd += ["--windowed", "--icon=src/shinestacker/gui/ico/shinestacker.icns"]
24
24
  elif sys_name == 'windows':
25
- pyinstaller_cmd += ["--windowed", "--icon=ico/shinestacker.ico"]
25
+ pyinstaller_cmd += ["--windowed", "--icon=src/shinestacker/gui/ico/shinestacker.ico"]
26
26
  pyinstaller_cmd += ["src/shinestacker/app/main.py"]
27
27
 
28
28
  print(" ".join(pyinstaller_cmd))
29
29
  subprocess.run(pyinstaller_cmd, check=True)
30
30
 
31
- ico_dir = project_root / "ico"
32
- target_ico = dist_dir / package_dir / "ico"
33
- if target_ico.exists():
34
- shutil.rmtree(target_ico)
35
- shutil.copytree(ico_dir, target_ico)
36
-
37
31
  examples_dir = project_root / "examples"
38
32
  target_examples = dist_dir / package_dir / "examples"
39
33
  target_examples.mkdir(exist_ok=True)
@@ -0,0 +1,16 @@
1
+ # flake8: noqa F401 F403
2
+ from ._version import __version__
3
+ from . import config
4
+ from . import core
5
+ from . import algorithms
6
+ from .config import __all__
7
+ from .core import __all__
8
+ from .algorithms import __all__
9
+ from .config import *
10
+ from .core import *
11
+ from .algorithms import *
12
+
13
+ __all__ = ['__version__']
14
+ #__all__ += config.__all__
15
+ #__all__ += core.__all__
16
+ #__all__ += algorithms.__all__
@@ -0,0 +1 @@
1
+ __version__ = '0.2.2'
@@ -12,3 +12,8 @@ from .vignetting import Vignetting
12
12
  import logging
13
13
  logger = logging.getLogger(__name__)
14
14
  logger.addHandler(logging.NullHandler())
15
+
16
+ __all__ = [
17
+ 'StackJob', 'CombinedActions', 'AlignFrames', 'BalanceFrames', 'FocusStackBunch', 'FocusStack',
18
+ 'DepthMapStack', 'PyramidStack', 'MultiLayer', 'NoiseDetection', 'MaskNoise', 'Vignetting'
19
+ ]
@@ -62,7 +62,6 @@ def get_good_matches(des_0, des_1, matching_config=None):
62
62
 
63
63
 
64
64
  def validate_align_config(detector, descriptor, match_method):
65
- print(detector, descriptor, match_method)
66
65
  if descriptor == constants.DESCRIPTOR_SIFT and match_method == constants.MATCHING_NORM_HAMMING:
67
66
  raise ValueError("Descriptor SIFT requires matching method KNN")
68
67
  if detector == constants.DETECTOR_ORB and descriptor == constants.DESCRIPTOR_AKAZE and \
@@ -1,5 +1,5 @@
1
1
  import os
2
- from config.config import config
2
+ from ..config.config import config
3
3
 
4
4
  if not config.DISABLE_TQDM:
5
5
  from tqdm import tqdm
@@ -12,7 +12,6 @@ from shinestacker.config.config import config
12
12
  config.init(DISABLE_TQDM=True, COMBINED_APP=True, DONT_USE_NATIVE_MENU=True)
13
13
  from shinestacker.config.constants import constants
14
14
  from shinestacker.core.logging import setup_logging
15
- from shinestacker.core.core_utils import get_app_base_path
16
15
  from shinestacker.gui.main_window import MainWindow
17
16
  from shinestacker.retouch.image_editor_ui import ImageEditorUI
18
17
  from shinestacker.app.gui_utils import disable_macos_special_menu_items
@@ -138,12 +137,7 @@ expert options are visible by default.
138
137
  app.setAttribute(Qt.AA_DontUseNativeMenuBar)
139
138
  else:
140
139
  disable_macos_special_menu_items()
141
- icon_path = f'{get_app_base_path()}'
142
- if os.path.exists(f'{icon_path}/ico'):
143
- icon_path = f'{icon_path}/ico'
144
- else:
145
- icon_path = f'{icon_path}/../ico'
146
- icon_path = f'{icon_path}/shinestacker.png'
140
+ icon_path = f"{os.path.dirname(__file__)}/../gui/ico/shinestacker.png"
147
141
  app.setWindowIcon(QIcon(icon_path))
148
142
  main_app = MainApp()
149
143
  app.main_app = main_app
@@ -12,7 +12,6 @@ from shinestacker.config.config import config
12
12
  config.init(DISABLE_TQDM=True, DONT_USE_NATIVE_MENU=True)
13
13
  from shinestacker.config.constants import constants
14
14
  from shinestacker.core.logging import setup_logging
15
- from shinestacker.core.core_utils import get_app_base_path
16
15
  from shinestacker.gui.main_window import MainWindow
17
16
  from shinestacker.app.gui_utils import disable_macos_special_menu_items
18
17
  from shinestacker.app.help_menu import add_help_action
@@ -73,7 +72,8 @@ expert options are visible by default.
73
72
  app.setAttribute(Qt.AA_DontUseNativeMenuBar)
74
73
  else:
75
74
  disable_macos_special_menu_items()
76
- app.setWindowIcon(QIcon(f'{get_app_base_path()}/ico/shinestacker.png'))
75
+ icon_path = f"{os.path.dirname(__file__)}/../gui/ico/shinestacker.png"
76
+ app.setWindowIcon(QIcon(icon_path))
77
77
  window = ProjectApp()
78
78
  if args['expert']:
79
79
  window.set_expert_options()
@@ -1,3 +1,4 @@
1
+ import os
1
2
  import sys
2
3
  import argparse
3
4
  from PySide6.QtWidgets import QApplication, QMenu
@@ -5,7 +6,6 @@ from PySide6.QtGui import QIcon, QAction
5
6
  from PySide6.QtCore import Qt, QEvent
6
7
  from shinestacker.config.config import config
7
8
  config.init(DISABLE_TQDM=True, DONT_USE_NATIVE_MENU=True)
8
- from shinestacker.core.core_utils import get_app_base_path
9
9
  from shinestacker.config.config import config
10
10
  from shinestacker.config.constants import constants
11
11
  from shinestacker.retouch.image_editor_ui import ImageEditorUI
@@ -70,7 +70,8 @@ Multiple directories can be specified separated by ';'.
70
70
  app.setAttribute(Qt.AA_DontUseNativeMenuBar)
71
71
  else:
72
72
  disable_macos_special_menu_items()
73
- app.setWindowIcon(QIcon(f'{get_app_base_path()}/ico/shinestacker.png'))
73
+ icon_path = f"{os.path.dirname(__file__)}/../gui/ico/shinestacker.png"
74
+ app.setWindowIcon(QIcon(icon_path))
74
75
  editor = RetouchApp()
75
76
  app.editor = editor
76
77
  editor.show()
@@ -2,3 +2,5 @@
2
2
  from .config import config
3
3
  from .constants import constants
4
4
  from .gui_constants import gui_constants
5
+
6
+ __all__ = ['config', 'constants', 'gui_constants']
@@ -0,0 +1,11 @@
1
+ # flake8: noqa F401
2
+ from .logging import setup_logging
3
+ from .exceptions import (FocusStackError, InvalidOptionError, ImageLoadError, ImageSaveError, AlignmentError,
4
+ BitDepthError, ShapeError, RunStopException)
5
+ from .framework import Job
6
+
7
+ __all__ = [
8
+ 'setup_logging',
9
+ 'FocusStackError', 'InvalidOptionError', 'ImageLoadError', 'ImageSaveError',
10
+ 'AlignmentError','BitDepthError', 'ShapeError', 'RunStopException',
11
+ 'Job']
@@ -414,6 +414,9 @@ class MainWindow(ActionsWindow, LogManager):
414
414
  menu.addAction(self.job_retouch_path_action)
415
415
  menu.exec(event.globalPos())
416
416
 
417
+ def get_icon(self, icon):
418
+ return QIcon(os.path.join(self.script_dir, f"img/{icon}.png"))
419
+
417
420
  def get_retouch_path(self, job):
418
421
  frames_path = [get_action_output_path(action)[0]
419
422
  for action in job.sub_actions if action.type_name == constants.ACTION_COMBO]
@@ -6,7 +6,6 @@ from PySide6.QtGui import QIcon
6
6
  from PySide6.QtCore import Qt
7
7
  from .. config.gui_constants import gui_constants
8
8
  from .. config.constants import constants
9
- from .. core.core_utils import get_app_base_path
10
9
 
11
10
 
12
11
  class NewProjectDialog(QDialog):
@@ -39,12 +38,7 @@ class NewProjectDialog(QDialog):
39
38
  self.layout.addRow(label)
40
39
 
41
40
  def create_form(self):
42
- icon_path = f'{get_app_base_path()}'
43
- if os.path.exists(f'{icon_path}/ico'):
44
- icon_path = f'{icon_path}/ico'
45
- else:
46
- icon_path = f'{icon_path}/../ico'
47
- icon_path = f'{icon_path}/shinestacker.png'
41
+ icon_path = f"{os.path.dirname(__file__)}/ico/shinestacker.png"
48
42
  app_icon = QIcon(icon_path)
49
43
  icon_pixmap = app_icon.pixmap(128, 128)
50
44
  icon_label = QLabel()
@@ -1,7 +1,6 @@
1
1
  import os
2
2
  from dataclasses import dataclass
3
3
  from PySide6.QtWidgets import QMainWindow, QListWidget, QMessageBox, QDialog, QListWidgetItem, QLabel
4
- from PySide6.QtGui import QIcon
5
4
  from PySide6.QtCore import Qt
6
5
  from .. config.constants import constants
7
6
  from .colors import ColorPalette
@@ -328,9 +327,6 @@ class ProjectEditor(QMainWindow):
328
327
  label = QLabel(html_text)
329
328
  widget_list.setItemWidget(item, label)
330
329
 
331
- def get_icon(self, icon):
332
- return QIcon(os.path.join(self.script_dir, f"img/{icon}.png"))
333
-
334
330
  def add_action_CombinedActions(self):
335
331
  self.add_action(constants.ACTION_COMBO)
336
332
 
@@ -3,7 +3,6 @@ from PIL.TiffImagePlugin import IFDRational
3
3
  from PySide6.QtWidgets import QFormLayout, QHBoxLayout, QPushButton, QDialog, QLabel
4
4
  from PySide6.QtGui import QIcon
5
5
  from PySide6.QtCore import Qt
6
- from .. core.core_utils import get_app_base_path
7
6
  from .. algorithms.exif import exif_dict
8
7
 
9
8
 
@@ -32,12 +31,7 @@ class ExifData(QDialog):
32
31
  self.layout.addRow(label)
33
32
 
34
33
  def create_form(self):
35
- icon_path = f'{get_app_base_path()}'
36
- if os.path.exists(f'{icon_path}/ico'):
37
- icon_path = f'{icon_path}/ico'
38
- else:
39
- icon_path = f'{icon_path}/../ico'
40
- icon_path = f'{icon_path}/shinestacker.png'
34
+ icon_path = f"{os.path.dirname(__file__)}/../gui/ico/shinestacker.png"
41
35
  app_icon = QIcon(icon_path)
42
36
  icon_pixmap = app_icon.pixmap(128, 128)
43
37
  icon_label = QLabel()
@@ -364,8 +364,6 @@ class ImageEditor(QMainWindow):
364
364
  QMessageBox.critical(self, "Save Error", f"Could not save file: {str(e)}")
365
365
 
366
366
  def select_exif_path(self):
367
- if self.current_stack is None:
368
- return
369
367
  path, _ = QFileDialog.getOpenFileName(None, "Select file with exif data")
370
368
  if path:
371
369
  self.exif_path = path
@@ -3,7 +3,6 @@ from PySide6.QtWidgets import (QFormLayout, QHBoxLayout, QPushButton, QDialog,
3
3
  QLabel, QVBoxLayout, QWidget)
4
4
  from PySide6.QtGui import QIcon
5
5
  from PySide6.QtCore import Qt
6
- from .. core.core_utils import get_app_base_path
7
6
 
8
7
 
9
8
  class ShortcutsHelp(QDialog):
@@ -44,12 +43,7 @@ class ShortcutsHelp(QDialog):
44
43
  layout.addRow(label)
45
44
 
46
45
  def create_form(self, left_layout, right_layout):
47
- icon_path = f'{get_app_base_path()}'
48
- if os.path.exists(f'{icon_path}/ico'):
49
- icon_path = f'{icon_path}/ico'
50
- else:
51
- icon_path = f'{icon_path}/../ico'
52
- icon_path = f'{icon_path}/shinestacker.png'
46
+ icon_path = f"{os.path.dirname(__file__)}/../gui/ico/shinestacker.png"
53
47
  app_icon = QIcon(icon_path)
54
48
  icon_pixmap = app_icon.pixmap(128, 128)
55
49
  icon_label = QLabel()