shinestacker 0.3.0__tar.gz → 0.3.1__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.
- {shinestacker-0.3.0 → shinestacker-0.3.1}/CHANGELOG.md +21 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/PKG-INFO +1 -1
- {shinestacker-0.3.0 → shinestacker-0.3.1}/docs/gui.md +3 -6
- {shinestacker-0.3.0 → shinestacker-0.3.1}/docs/main.md +2 -2
- shinestacker-0.3.1/src/shinestacker/_version.py +1 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/utils.py +4 -0
- shinestacker-0.3.1/src/shinestacker/algorithms/white_balance.py +13 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/new_project.py +1 -0
- shinestacker-0.3.1/src/shinestacker/retouch/brush_gradient.py +20 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/retouch/brush_preview.py +11 -14
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/retouch/image_editor.py +93 -202
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/retouch/image_editor_ui.py +15 -8
- shinestacker-0.3.1/src/shinestacker/retouch/image_filters.py +391 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/retouch/image_viewer.py +13 -21
- shinestacker-0.3.1/src/shinestacker/retouch/io_manager.py +57 -0
- shinestacker-0.3.1/src/shinestacker/retouch/layer_collection.py +54 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker.egg-info/PKG-INFO +1 -1
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker.egg-info/SOURCES.txt +6 -0
- shinestacker-0.3.1/tests/test_0053_white_balance.py +37 -0
- shinestacker-0.3.1/tests/test_0100_layer_collection.py +66 -0
- shinestacker-0.3.0/src/shinestacker/_version.py +0 -1
- shinestacker-0.3.0/src/shinestacker/retouch/image_filters.py +0 -463
- {shinestacker-0.3.0 → shinestacker-0.3.1}/.coverage +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/.coveragerc +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/.flake8 +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/.github/workflows/ci-multiplatform.yml +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/.github/workflows/pypi-publish.yml +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/.github/workflows/release.yml +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/.gitignore +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/.readthedocs.yaml +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/LICENSE +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/README.md +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/docs/alignment.md +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/docs/api.md +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/docs/balancing.md +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/docs/conf.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/docs/focus_stacking.md +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/docs/index.md +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/docs/job.md +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/docs/multilayer.md +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/docs/noise.md +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/docs/requirements.txt +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/docs/vignetting.md +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/balance-only.fsp +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/complete-project.fsp +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/focus-stack-1.ipynb +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/focus-stack-2.ipynb +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-jpg/0000.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-jpg/0001.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-jpg/0002.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-jpg/0003.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-jpg/0004.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-jpg/0005.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-noise/0001.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-noise/0002.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-noise/0003.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-noise/0004.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-noise/0005.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-noise/0006.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-tif/0000.tif +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-tif/0001.tif +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-tif/0002.tif +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-tif/0003.tif +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-tif/0004.tif +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-tif/0005.tif +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-vignetted/vig-0000.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-vignetted/vig-0001.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-vignetted/vig-0002.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/input/img-vignetted/vig-0003.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/stack-comparison.fsp +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/stack-from-frames.fsp +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/examples/vignetting.fsp +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/img/extreme-vignetting.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/img/flies.gif +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/img/flies_stack.jpg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/img/flow-diagram.png +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/img/gui-finder.png +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/img/gui-project-new.png +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/img/gui-project-run.png +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/img/gui-retouch.png +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/pyproject.toml +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/scripts/build_release.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/scripts/validate-tomli.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/setup.cfg +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/__init__.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/__init__.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/align.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/balance.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/core_utils.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/denoise.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/depth_map.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/exif.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/multilayer.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/noise_detection.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/pyramid.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/sharpen.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/stack.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/stack_framework.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/algorithms/vignetting.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/app/__init__.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/app/about_dialog.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/app/app_config.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/app/gui_utils.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/app/help_menu.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/app/main.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/app/open_frames.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/app/project.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/app/retouch.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/config/__init__.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/config/config.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/config/constants.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/config/gui_constants.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/core/__init__.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/core/colors.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/core/core_utils.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/core/exceptions.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/core/framework.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/core/logging.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/__init__.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/action_config.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/actions_window.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/colors.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/gui_images.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/gui_logging.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/gui_run.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/ico/focus_stack_bkg.png +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/ico/shinestacker.icns +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/ico/shinestacker.ico +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/ico/shinestacker.png +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/img/close-round-line-icon.png +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/img/forward-button-icon.png +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/img/play-button-round-icon.png +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/img/plus-round-line-icon.png +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/main_window.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/project_converter.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/project_editor.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/gui/project_model.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/retouch/__init__.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/retouch/brush.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/retouch/brush_controller.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/retouch/exif_data.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/retouch/file_loader.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/retouch/shortcuts_help.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker/retouch/undo_manager.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker.egg-info/dependency_links.txt +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker.egg-info/entry_points.txt +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker.egg-info/requires.txt +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/src/shinestacker.egg-info/top_level.txt +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test-align-balance.ipynb +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test-align.ipynb +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test-balance.ipynb +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test-exif.ipynb +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test-job.ipynb +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test-logging.ipynb +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test-multilayer.ipynb +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test-noise-detection.ipynb +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test-stack.ipynb +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test-vignetting.ipynb +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0000_logging.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0001_colors.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0002_config.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0005_make_test_img.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0006_exceptions.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0010_job.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0011_core_utils.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0020_noise_detection.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0030_align.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0031_align_precision.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0032_align_methods.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0040_balance.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0050_align_balance.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0051_denoise.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0052_sharpen.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0060_stack.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0061_depth_map.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0070_multilayer.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0080_exif.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0090_vignetting.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_0091_vignetting_algo.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_1000_brush_mask.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_1010_gui.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_1020_gui_images.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_1030_gui_logging.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_1040_action_config.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_1050_project_converter.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_1060_gui_run.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_1070_project_editor.py +0 -0
- {shinestacker-0.3.0 → shinestacker-0.3.1}/tests/test_1080_actions_window.py +0 -0
|
@@ -4,6 +4,27 @@ This page reports the main releases only and the main changes therein.
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## [v0.3.1] - 2025-08-12
|
|
8
|
+
**Fixes and code refactoring**
|
|
9
|
+
|
|
10
|
+
### Changes
|
|
11
|
+
|
|
12
|
+
* some GUI fixes
|
|
13
|
+
* some code refactoring and cleanup
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## [v0.3.0] - 2025-08-11
|
|
18
|
+
**Filters added to retouch GUI**
|
|
19
|
+
|
|
20
|
+
### Changes
|
|
21
|
+
|
|
22
|
+
* added filters for sharpening, denoise and white balance
|
|
23
|
+
* updated documentation
|
|
24
|
+
* some bug fixes
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
7
28
|
## [v0.2.2] - 2025-07-28
|
|
8
29
|
**More stability and improved tests**
|
|
9
30
|
|
|
@@ -99,7 +99,9 @@ Adjust in the top toolbar:
|
|
|
99
99
|
3. **Verify**:
|
|
100
100
|
- Toggle master view (`M`) to check results
|
|
101
101
|
- Compare before/after with `L`/`M` toggle
|
|
102
|
-
|
|
102
|
+
4. **Filters**:
|
|
103
|
+
- Improve the final image with sharpening, denoise and color balance
|
|
104
|
+
5. **Export**:
|
|
103
105
|
- ✅ Final image: Single TIFF/JPEG
|
|
104
106
|
- 🗂️ Editable: Multilayer TIFF (large)
|
|
105
107
|
|
|
@@ -123,9 +125,4 @@ See help menu for complete list of shortcuts.
|
|
|
123
125
|
**EXIF metadata**:
|
|
124
126
|
* EXIF data can be imported from source images and saved with final file.
|
|
125
127
|
|
|
126
|
-
## Final retouch
|
|
127
|
-
|
|
128
|
-
The final retouch, including color and luminosity balance, sharpness enhancement and
|
|
129
|
-
so on can be applied with your favorite image processing application, like [GIMP](https://www.gimp.org/)
|
|
130
|
-
or other.
|
|
131
128
|
|
|
@@ -94,7 +94,7 @@ job.run()
|
|
|
94
94
|
## Requirements
|
|
95
95
|
|
|
96
96
|
* Python: 3.12 (3.13 may not work due to garbage collection issues)
|
|
97
|
-
* RAM: 16GB+ recommended for >15 images
|
|
97
|
+
* RAM: 16GB+ recommended for >15 images at 20Mpx resolution
|
|
98
98
|
|
|
99
99
|
## Dependencies
|
|
100
100
|
|
|
@@ -116,6 +116,6 @@ pip install ipywidgets
|
|
|
116
116
|
|
|
117
117
|
| Issue | Workaround |
|
|
118
118
|
|----------|----------------|
|
|
119
|
-
| Balance modes ```HSV```/```HLS```
|
|
119
|
+
| Balance modes ```HSV```/```HLS``` don't support 16-bit images | convert to 8-bit or use ```RGB``` or luminosity |
|
|
120
120
|
| PNG support untested | Convert to TIFF/JPEG first |
|
|
121
121
|
| GUI tests limited | Report bugs as GitHub issuse |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '0.3.1'
|
|
@@ -47,10 +47,14 @@ def img_bw(img):
|
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def get_img_metadata(img):
|
|
50
|
+
if img is None:
|
|
51
|
+
return None, None
|
|
50
52
|
return img.shape[:2], img.dtype
|
|
51
53
|
|
|
52
54
|
|
|
53
55
|
def validate_image(img, expected_shape=None, expected_dtype=None):
|
|
56
|
+
if img is None:
|
|
57
|
+
raise RuntimeError("Image is None")
|
|
54
58
|
shape, dtype = get_img_metadata(img)
|
|
55
59
|
if expected_shape and shape[:2] != expected_shape[:2]:
|
|
56
60
|
raise ShapeError(expected_shape, shape)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def white_balance_from_rgb(img, target_rgb):
|
|
5
|
+
img_float = img.astype(np.float64)
|
|
6
|
+
target_bgr = (target_rgb[2], target_rgb[1], target_rgb[0])
|
|
7
|
+
target_gray = sum(target_bgr) / 3.0
|
|
8
|
+
scales = [target_gray / val if val != 0 else 1.0 for val in target_bgr]
|
|
9
|
+
for c in range(3):
|
|
10
|
+
img_float[..., c] *= scales[c]
|
|
11
|
+
max_val = np.iinfo(img.dtype).max
|
|
12
|
+
img_float = np.clip(img_float, 0, max_val)
|
|
13
|
+
return img_float.astype(img.dtype)
|
|
@@ -85,6 +85,7 @@ class NewProjectDialog(QDialog):
|
|
|
85
85
|
bunch_overlap_range = gui_constants.NEW_PROJECT_BUNCH_OVERLAP
|
|
86
86
|
self.bunch_overlap.setRange(bunch_overlap_range['min'], bunch_overlap_range['max'])
|
|
87
87
|
self.bunch_overlap.setValue(constants.DEFAULT_OVERLAP)
|
|
88
|
+
self.update_bunch_options(gui_constants.NEW_PROJECT_BUNCH_STACK)
|
|
88
89
|
self.focus_stack_pyramid = QCheckBox()
|
|
89
90
|
self.focus_stack_pyramid.setChecked(gui_constants.NEW_PROJECT_FOCUS_STACK_PYRAMID)
|
|
90
91
|
self.focus_stack_depth_map = QCheckBox()
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from PySide6.QtGui import QRadialGradient
|
|
2
|
+
from PySide6.QtGui import QColor
|
|
3
|
+
from .. config.gui_constants import gui_constants
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def create_brush_gradient(center_x, center_y, radius, hardness, inner_color=None, outer_color=None, opacity=100):
|
|
7
|
+
gradient = QRadialGradient(center_x, center_y, float(radius))
|
|
8
|
+
inner = inner_color if inner_color is not None else QColor(*gui_constants.BRUSH_COLORS['inner'])
|
|
9
|
+
outer = outer_color if outer_color is not None else QColor(*gui_constants.BRUSH_COLORS['gradient_end'])
|
|
10
|
+
inner_with_opacity = QColor(inner)
|
|
11
|
+
inner_with_opacity.setAlpha(int(float(inner.alpha()) * float(opacity) / 100.0))
|
|
12
|
+
if hardness < 100:
|
|
13
|
+
hardness_normalized = float(hardness) / 100.0
|
|
14
|
+
gradient.setColorAt(0.0, inner_with_opacity)
|
|
15
|
+
gradient.setColorAt(hardness_normalized, inner_with_opacity)
|
|
16
|
+
gradient.setColorAt(1.0, outer)
|
|
17
|
+
else:
|
|
18
|
+
gradient.setColorAt(0.0, inner_with_opacity)
|
|
19
|
+
gradient.setColorAt(1.0, inner_with_opacity)
|
|
20
|
+
return gradient
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
from PySide6.QtWidgets import QGraphicsPixmapItem
|
|
3
|
-
from PySide6.QtCore import Qt
|
|
3
|
+
from PySide6.QtCore import Qt
|
|
4
4
|
from PySide6.QtGui import QPixmap, QPainter, QImage
|
|
5
5
|
|
|
6
6
|
|
|
@@ -42,6 +42,8 @@ def create_brush_mask(size, hardness_percent, opacity_percent):
|
|
|
42
42
|
class BrushPreviewItem(QGraphicsPixmapItem):
|
|
43
43
|
def __init__(self):
|
|
44
44
|
super().__init__()
|
|
45
|
+
self.layer_collection = None
|
|
46
|
+
self.brush = None
|
|
45
47
|
self.setVisible(False)
|
|
46
48
|
self.setZValue(500)
|
|
47
49
|
self.setTransformationMode(Qt.SmoothTransformation)
|
|
@@ -68,31 +70,26 @@ class BrushPreviewItem(QGraphicsPixmapItem):
|
|
|
68
70
|
else:
|
|
69
71
|
raise Exception("Bitmas is neither 8 bit nor 16, but of type " + area.dtype)
|
|
70
72
|
|
|
71
|
-
def update(self,
|
|
73
|
+
def update(self, scene_pos, size):
|
|
72
74
|
try:
|
|
73
|
-
if
|
|
75
|
+
if self.layer_collection.layer_stack is None or size <= 0:
|
|
74
76
|
self.hide()
|
|
75
77
|
return
|
|
76
78
|
radius = size // 2
|
|
77
|
-
if isinstance(pos, QPointF):
|
|
78
|
-
scene_pos = pos
|
|
79
|
-
else:
|
|
80
|
-
cursor_pos = editor.image_viewer.mapFromGlobal(pos)
|
|
81
|
-
scene_pos = editor.image_viewer.mapToScene(cursor_pos)
|
|
82
79
|
x = int(scene_pos.x() - radius + 0.5)
|
|
83
80
|
y = int(scene_pos.y() - radius)
|
|
84
81
|
w = h = size
|
|
85
|
-
if
|
|
82
|
+
if not self.layer_collection.valid_current_layer_idx():
|
|
86
83
|
self.hide()
|
|
87
84
|
return
|
|
88
|
-
layer_area = self.get_layer_area(
|
|
89
|
-
master_area = self.get_layer_area(
|
|
85
|
+
layer_area = self.get_layer_area(self.layer_collection.current_layer(), x, y, w, h)
|
|
86
|
+
master_area = self.get_layer_area(self.layer_collection.master_layer, x, y, w, h)
|
|
90
87
|
if layer_area is None or master_area is None:
|
|
91
88
|
self.hide()
|
|
92
89
|
return
|
|
93
|
-
height, width =
|
|
94
|
-
full_mask = create_brush_mask(size=size, hardness_percent=
|
|
95
|
-
opacity_percent=
|
|
90
|
+
height, width = self.layer_collection.current_layer().shape[:2]
|
|
91
|
+
full_mask = create_brush_mask(size=size, hardness_percent=self.brush.hardness,
|
|
92
|
+
opacity_percent=self.brush.opacity)[:, :, np.newaxis]
|
|
96
93
|
mask_x_start = max(0, -x) if x < 0 else 0
|
|
97
94
|
mask_y_start = max(0, -y) if y < 0 else 0
|
|
98
95
|
mask_x_end = size - (max(0, (x + w) - width)) if (x + w) > width else size
|