shinestacker 0.3.0__py3-none-any.whl → 0.3.2__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 (43) hide show
  1. shinestacker/__init__.py +6 -6
  2. shinestacker/_version.py +1 -1
  3. shinestacker/algorithms/balance.py +6 -7
  4. shinestacker/algorithms/noise_detection.py +2 -0
  5. shinestacker/algorithms/utils.py +4 -0
  6. shinestacker/algorithms/white_balance.py +13 -0
  7. shinestacker/app/open_frames.py +6 -4
  8. shinestacker/config/__init__.py +2 -1
  9. shinestacker/config/config.py +1 -0
  10. shinestacker/config/constants.py +1 -0
  11. shinestacker/config/gui_constants.py +1 -0
  12. shinestacker/core/__init__.py +4 -3
  13. shinestacker/core/colors.py +1 -0
  14. shinestacker/core/core_utils.py +6 -6
  15. shinestacker/core/exceptions.py +1 -0
  16. shinestacker/core/framework.py +2 -1
  17. shinestacker/gui/action_config.py +47 -42
  18. shinestacker/gui/actions_window.py +8 -5
  19. shinestacker/gui/new_project.py +1 -0
  20. shinestacker/retouch/brush_gradient.py +20 -0
  21. shinestacker/retouch/brush_preview.py +10 -14
  22. shinestacker/retouch/brush_tool.py +164 -0
  23. shinestacker/retouch/denoise_filter.py +56 -0
  24. shinestacker/retouch/display_manager.py +177 -0
  25. shinestacker/retouch/exif_data.py +2 -1
  26. shinestacker/retouch/filter_base.py +114 -0
  27. shinestacker/retouch/filter_manager.py +14 -0
  28. shinestacker/retouch/image_editor.py +108 -543
  29. shinestacker/retouch/image_editor_ui.py +42 -75
  30. shinestacker/retouch/image_filters.py +27 -423
  31. shinestacker/retouch/image_viewer.py +31 -31
  32. shinestacker/retouch/io_gui_handler.py +208 -0
  33. shinestacker/retouch/io_manager.py +53 -0
  34. shinestacker/retouch/layer_collection.py +118 -0
  35. shinestacker/retouch/unsharp_mask_filter.py +84 -0
  36. shinestacker/retouch/white_balance_filter.py +111 -0
  37. {shinestacker-0.3.0.dist-info → shinestacker-0.3.2.dist-info}/METADATA +3 -2
  38. {shinestacker-0.3.0.dist-info → shinestacker-0.3.2.dist-info}/RECORD +42 -31
  39. shinestacker/retouch/brush_controller.py +0 -57
  40. {shinestacker-0.3.0.dist-info → shinestacker-0.3.2.dist-info}/WHEEL +0 -0
  41. {shinestacker-0.3.0.dist-info → shinestacker-0.3.2.dist-info}/entry_points.txt +0 -0
  42. {shinestacker-0.3.0.dist-info → shinestacker-0.3.2.dist-info}/licenses/LICENSE +0 -0
  43. {shinestacker-0.3.0.dist-info → shinestacker-0.3.2.dist-info}/top_level.txt +0 -0
@@ -1,48 +1,49 @@
1
- shinestacker/__init__.py,sha256=sxG9J11a6Qpu_VcqsARRqGSPByHtDvQqR5ozWYjHfZU,387
2
- shinestacker/_version.py,sha256=gTggO06fb2c9XKEwlQYUSPlUfy82yVlM9pzLMOUqVcY,21
1
+ shinestacker/__init__.py,sha256=35QgHh92rTqveh8kp-4T-iWPOVFKmBAtfmSE7Ytl4k0,416
2
+ shinestacker/_version.py,sha256=64UBVh2KX7E-WVG4ZyY1dUiW9jGXZloWZk1N9nEUC2k,21
3
3
  shinestacker/algorithms/__init__.py,sha256=X9nwToaB13GAACoaE-K0o9R1Jt7g9xSzeJI8Ra2GcL8,722
4
4
  shinestacker/algorithms/align.py,sha256=As7MIfjoJc_1vJ058iwP7b_PnDnfYsBQ1JNZ4GX5ZU4,16529
5
- shinestacker/algorithms/balance.py,sha256=UOmyUPJVBswUYWvYIB8WdlfTAxUAahZrnxQUSrYJ3I4,15649
5
+ shinestacker/algorithms/balance.py,sha256=wFVfKzZTwHlvqqJ6Fd8CsUQKkz7I9Dw7uP98esJ-_K0,15640
6
6
  shinestacker/algorithms/core_utils.py,sha256=3mvJVDDfzMOboP724iM_5WT-pLFFoGAhwcXsQN8dBYo,552
7
7
  shinestacker/algorithms/denoise.py,sha256=C59la4DEh6uPZIDgmaZIqgxdxDYBxXRxgQBLLBvSlBA,374
8
8
  shinestacker/algorithms/depth_map.py,sha256=hx6yyCjLKiu3Wi5uZFXiixEfOBxfieNQ9xH9cp5zD0Y,7844
9
9
  shinestacker/algorithms/exif.py,sha256=VS3qbLRVlbZ8_z8hYgGVV4BSmwWzR0reN_G0XV3hzAI,9364
10
10
  shinestacker/algorithms/multilayer.py,sha256=Fm-WZqH4DAEOAyC0QpPaMH3VaG5cEPX9rqKsAyWpELs,8694
11
- shinestacker/algorithms/noise_detection.py,sha256=ra4mkprxPcb5WqHsOdKFUflAmIJ4_nQegYv1EhwH7ts,8280
11
+ shinestacker/algorithms/noise_detection.py,sha256=GMX5_Pd24tL-aSt28ad94wsCiCOBXYXc3Sf4IySbxfo,8362
12
12
  shinestacker/algorithms/pyramid.py,sha256=iUbgRI0p0uzEXcZetAm3hgzwiXhF4mIaNxYMUUpJFeE,8589
13
13
  shinestacker/algorithms/sharpen.py,sha256=KtTDIytJW7z4Oj-E1FcxKvhzz27xLX2CCSwJAG_QRUY,911
14
14
  shinestacker/algorithms/stack.py,sha256=EZm2SIuoh8c7hgySB2tQGydKYQjJa2hEqR8YNzIeRuQ,5194
15
15
  shinestacker/algorithms/stack_framework.py,sha256=aJBjkQFxiPNjnsnZyoF8lXKR17tm0rTO7puEu_ZvASU,10928
16
- shinestacker/algorithms/utils.py,sha256=TV3NaGe6_2JTgGdFe4kKNzgihjt6vcK-SLy-HHnbts0,2054
16
+ shinestacker/algorithms/utils.py,sha256=Z81_tHTjzH_8oJ44UmgukHtm1Wbbm8g3YTCy4jBYrWo,2164
17
17
  shinestacker/algorithms/vignetting.py,sha256=EiD4O8GJPGOqByjDAfFj-de4cb64Qf685RujqlBgvX0,6774
18
+ shinestacker/algorithms/white_balance.py,sha256=AN33zegS8hMJK7I-7UZVmjaOg5PXy9wTnDei12EnPWg,470
18
19
  shinestacker/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
20
  shinestacker/app/about_dialog.py,sha256=G_2hRQFpo96q0H8z02fMZ0Jl_2-PpnwNxqISY7Xn5Kg,885
20
21
  shinestacker/app/app_config.py,sha256=tQ1JBTG2gtHO1UbJYJjjYUBCakmtZpafvMUTHb5OyUo,1117
21
22
  shinestacker/app/gui_utils.py,sha256=C5ehbYyoIcBweFTfdQcjsILAcWpMPrVLMbYz0ZM-EcM,1571
22
23
  shinestacker/app/help_menu.py,sha256=ofFhZMPTz7lQ-_rsu30yAxbLA-Zq_kkRGXxPMukaG08,476
23
24
  shinestacker/app/main.py,sha256=insz1oxeDlZQWNKo7DGaLmRrc8PZVD7brPRrWE1SWvk,6894
24
- shinestacker/app/open_frames.py,sha256=uqUihAkP1K2p4bQ8LAQK02XwVddkRJUPy_vzwUgI8jc,1356
25
+ shinestacker/app/open_frames.py,sha256=B66j1MhghMwQYqVJNuC0d7yWGuuWtM2ANOpW86PpRoI,1431
25
26
  shinestacker/app/project.py,sha256=xtuA8SRoWINpHcLTApBL3RYRd0ADrczrAaq_xtT3cZI,3234
26
27
  shinestacker/app/retouch.py,sha256=6Sa3ngUqj_Wn5gZBJNZeM-JxeGvXWmJZAa2Jj99t-xk,3012
27
- shinestacker/config/__init__.py,sha256=gMotpjZz5KyGdytdHhudCVlSKONw8kqMYNRACmlWUw0,172
28
- shinestacker/config/config.py,sha256=Vif1_-zFZQhI6KW1CAX3Yt-cgwXMJ7YDwDJrzoGVE48,1459
29
- shinestacker/config/constants.py,sha256=yOt1L7LiJyBPrGezIW-Vx_1I4r1Os0rPibfqroN30nk,5724
30
- shinestacker/config/gui_constants.py,sha256=PtizNIsLHM_P_GdkrhsSVZuuS5abxOETXozu5eSRt9w,2440
31
- shinestacker/core/__init__.py,sha256=tZOPV21QOxH6bEZG21fLxIdGNu9UbbwkFWHgSJkReRk,459
32
- shinestacker/core/colors.py,sha256=f4_iaNgDYpHfLaoooCsltDxem5fI950GPZlw2lFPqYM,1330
33
- shinestacker/core/core_utils.py,sha256=EkDJY8g3zLdAqT9hTRZ2_jh3jo8GMF2L6ZBINyG6L6Y,1398
34
- shinestacker/core/exceptions.py,sha256=TzguZ88XxjgbPs5jMFdrXV2cQRkl5mFfXZin9GRMSRY,1555
35
- shinestacker/core/framework.py,sha256=7N7awCefwT-SUsUE97eM9DBCCbNnrHk1Yab-DGE5iNI,6871
28
+ shinestacker/config/__init__.py,sha256=aXxi-LmAvXd0daIFrVnTHE5OCaYeK1uf1BKMr7oaXQs,197
29
+ shinestacker/config/config.py,sha256=BmcY79Ng3bN7HvYK7DzkGlrk2kTfV5R4gKTln87tfWs,1539
30
+ shinestacker/config/constants.py,sha256=79bOcE44MZ0WuAVPjDwwhvNrsQTlHGyIOwmqwlLOfMU,5776
31
+ shinestacker/config/gui_constants.py,sha256=002r96jtxV4Acel7q5NgECrcsDJzW-kOStEHqam-5Gg,2492
32
+ shinestacker/core/__init__.py,sha256=IUEIx6SQ3DygDEHN3_E6uKpHjHtUa4a_U_1dLd_8yEU,484
33
+ shinestacker/core/colors.py,sha256=HqelUiEAwsS9lS0Z4zA1NE-pgg8CuSl17FjnQ_M5srY,1368
34
+ shinestacker/core/core_utils.py,sha256=DI6kriZSXkLF87Df8B8jG0BCvUBM7u16r1n-5QC5EY0,1428
35
+ shinestacker/core/exceptions.py,sha256=XZWlnwXh-SGKvxxk61oLKOgQudtoH5bIX7RM0WnxNgI,1593
36
+ shinestacker/core/framework.py,sha256=Nh_fF-y1WcJQpycCEsgYjtQUq0idkFa04KWzZuo5lK0,6907
36
37
  shinestacker/core/logging.py,sha256=YkKqCduU9FVYCBi26izHKmjyxlGMbwwpYbfn9AY1KeI,3155
37
38
  shinestacker/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- shinestacker/gui/action_config.py,sha256=v-BWr-en11nyp0bFKoPqUQnVfSv9Ov14KW7oEaVJ9I8,47690
39
- shinestacker/gui/actions_window.py,sha256=DTMyi2WTugJxqliD6QdKcui_nhtaq0Pq-0SHuLBJGh0,13136
39
+ shinestacker/gui/action_config.py,sha256=YuKNd61XyxlUrd3H96e-9t6a_gLZQ-B7ZslQOtdWPHI,48410
40
+ shinestacker/gui/actions_window.py,sha256=cj_-Okc0wIbV6S_KqycaFsX3BEM32cCSxCrNHUZLpFI,13442
40
41
  shinestacker/gui/colors.py,sha256=Af4ccwKfiElzA2poyx2QSU2xvxOdA5fFz0Y2YIqTj9Y,1292
41
42
  shinestacker/gui/gui_images.py,sha256=3HySCrldbYhUyxO0B1ckC2TLVg5nq94bBXjqsQzCyCA,5546
42
43
  shinestacker/gui/gui_logging.py,sha256=sN82OsGhMcZdgFMY4z-VbUYiRIsReN-ICaxi31M1J6E,8147
43
44
  shinestacker/gui/gui_run.py,sha256=LpBi1V91NrJpVpgS098lSgLtiege0aqcWIGwSbB8cL4,15701
44
45
  shinestacker/gui/main_window.py,sha256=KtMe6Hm74xk-lP3qcUsWAw0dzT7CynpdbZA_H651XN0,27203
45
- shinestacker/gui/new_project.py,sha256=kGTt8zf24w5o8wUOc0QgXVDbvi4XcM4ia0CZftUImOc,7002
46
+ shinestacker/gui/new_project.py,sha256=0bcFg8iB8yxSom0itiO1f9bIcKrCAEgT8aSgUUKyomQ,7075
46
47
  shinestacker/gui/project_converter.py,sha256=d66pbBzaBgANpudJLW0tGUSfSy0PXNhs1M6R2o_Fd5E,7390
47
48
  shinestacker/gui/project_editor.py,sha256=s0IU3l3xO_JGovazOHhKkT1rraUWNVzyAua1dsUqJyg,21657
48
49
  shinestacker/gui/project_model.py,sha256=buzpxppLuoNWao7M2_FOPVpCBex2WgEcvqyq9dxvrz8,4524
@@ -56,19 +57,29 @@ shinestacker/gui/img/play-button-round-icon.png,sha256=9j6Ks9mOGa-2cXyRFpimepAAv
56
57
  shinestacker/gui/img/plus-round-line-icon.png,sha256=LS068Hlu-CeBvJuB3dwwdJg1lZq6D5MUIv53lu1yKJA,7534
57
58
  shinestacker/retouch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
59
  shinestacker/retouch/brush.py,sha256=49YNdZp1dbfowh6HmLfxuHKz7Py9wkFQsN9-pH38P7Q,319
59
- shinestacker/retouch/brush_controller.py,sha256=R_pWs7Cf_5sC07TkkqqHnX3L_vV5j9CP8S3TkoxYbvs,2945
60
- shinestacker/retouch/brush_preview.py,sha256=ePyoZPdSY4ytK4uXV-eByQgfsqvhHJqXpleycSxshDg,5247
61
- shinestacker/retouch/exif_data.py,sha256=cYl0ZAAEOmimh2O0REtY0fU_1Y_4uIUtk9orpVLyQKY,2234
60
+ shinestacker/retouch/brush_gradient.py,sha256=b7vEnluGkdUVXn7AIECEhQUh1OYbBFIv2UbW8exBRWg,1014
61
+ shinestacker/retouch/brush_preview.py,sha256=uqhO1VpCs6lYLy-HT0QR-Sy8-KivnJnR03YSHJD_p0Y,4946
62
+ shinestacker/retouch/brush_tool.py,sha256=e1o2OMtnFD_H6Dj0hkxHO0nR97pF4axCfEiBj0L8CP4,7989
63
+ shinestacker/retouch/denoise_filter.py,sha256=RCviO8rk0ygcA9jfbG7n3fDX6xwloQH7u92fExX_NeE,2168
64
+ shinestacker/retouch/display_manager.py,sha256=resqj_fDMZE8i7Bi8k4eO9s771qbqXB5uXuI5SdItqI,7031
65
+ shinestacker/retouch/exif_data.py,sha256=VLo-vQu89QlbHZisE9vcWCKk0YhHdOMOJDvWuER6phQ,2256
62
66
  shinestacker/retouch/file_loader.py,sha256=TbPjiD9Vv-i3LCsPVcumYJ2DxgnLmQA6xYCiLCqbEcg,4565
63
- shinestacker/retouch/image_editor.py,sha256=j-IMm8vWrUgI8XROWgGWDpeQ2HKK5MgrC_BPIr4uijI,28461
64
- shinestacker/retouch/image_editor_ui.py,sha256=-N_ZSuzC6AjDgf0t04un-WStBQcH3c3-C-6uJjHsXCw,16723
65
- shinestacker/retouch/image_filters.py,sha256=un1CxlMdfzlBEQ1x7RHPLrb5iDsyUihDYel2uyk40qA,19129
66
- shinestacker/retouch/image_viewer.py,sha256=5t7JRNoNwSgS7btn7zWmSXPPzXvZKbWBiZMm-YA7Xhg,14827
67
+ shinestacker/retouch/filter_base.py,sha256=GYpUnGl-RAWx7dLGAiTMkqYOetVCEnFzr97Tl2SyESg,4106
68
+ shinestacker/retouch/filter_manager.py,sha256=IrzLYh1LiIeBYO-lzHcPZVv4FRJqGntZTv8hO6KlsV4,415
69
+ shinestacker/retouch/image_editor.py,sha256=0xO_HPQruRjF0gRdsWPIOZjNPj0ma6y6MvN_mqvkFIQ,10506
70
+ shinestacker/retouch/image_editor_ui.py,sha256=6Capd2uOBi-Zd7f9v4pFkxBqNFtvrFdHKW2d4Rf4Tio,15548
71
+ shinestacker/retouch/image_filters.py,sha256=Pi3TMUdav1IDwckdnnJYaY6fABqFfCFRvjVyoMg3rGM,2803
72
+ shinestacker/retouch/image_viewer.py,sha256=tvL4n7Sx4qr2XIPsRpjC93zD8fYtT-gYStKeMy8xuTU,14654
73
+ shinestacker/retouch/io_gui_handler.py,sha256=FFUp3TKJKur_jcO3jtWdOPkAMR8-uIQ3O649y8S0F_A,8721
74
+ shinestacker/retouch/io_manager.py,sha256=Z-ScRSnD8YobqgRiHpjIISyHRjZr_OceMfXv7tU4Sq0,2066
75
+ shinestacker/retouch/layer_collection.py,sha256=usG1fObcQil-lq8ot7w1BtgJ_rBM8p6pE319NXUzkOY,4881
67
76
  shinestacker/retouch/shortcuts_help.py,sha256=iYwD7YGV2epNDwOBVDc99zqB9bbxLR_IUtanMJ-abPQ,3749
68
77
  shinestacker/retouch/undo_manager.py,sha256=5jWPsaERSh7TuWV5EbvqL6EsRS88Ct6VmM7FHxYzufs,3042
69
- shinestacker-0.3.0.dist-info/licenses/LICENSE,sha256=cBN0P3F6BWFkfOabkhuTxwJnK1B0v50jmmzZJjGGous,80
70
- shinestacker-0.3.0.dist-info/METADATA,sha256=lqCr530LfhBtToLsuwCNx2LUN37n0pq4QMDgI4LbETE,4219
71
- shinestacker-0.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
72
- shinestacker-0.3.0.dist-info/entry_points.txt,sha256=SY6g1LqtMmp23q1DGwLUDT_dhLX9iss8DvWkiWLyo_4,166
73
- shinestacker-0.3.0.dist-info/top_level.txt,sha256=MhijwnBVX5psfsyX8JZjqp3SYiWPsKe69f3Gnyze4Fw,13
74
- shinestacker-0.3.0.dist-info/RECORD,,
78
+ shinestacker/retouch/unsharp_mask_filter.py,sha256=3lvV4H5uGTMXPT2Q41SXqi7wUVOuau1dn7CBbT7wzNk,3646
79
+ shinestacker/retouch/white_balance_filter.py,sha256=h3TxwQ2uN_3tzVU22kr-5A6IeDzrJ1JpBd0jpHuuDvU,5011
80
+ shinestacker-0.3.2.dist-info/licenses/LICENSE,sha256=cBN0P3F6BWFkfOabkhuTxwJnK1B0v50jmmzZJjGGous,80
81
+ shinestacker-0.3.2.dist-info/METADATA,sha256=tzNHac7NHKCwXhjd-pRKsY9q6e9t-_7qiv5O_eKs4lM,4505
82
+ shinestacker-0.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
83
+ shinestacker-0.3.2.dist-info/entry_points.txt,sha256=SY6g1LqtMmp23q1DGwLUDT_dhLX9iss8DvWkiWLyo_4,166
84
+ shinestacker-0.3.2.dist-info/top_level.txt,sha256=MhijwnBVX5psfsyX8JZjqp3SYiWPsKe69f3Gnyze4Fw,13
85
+ shinestacker-0.3.2.dist-info/RECORD,,
@@ -1,57 +0,0 @@
1
- import numpy as np
2
- from .. config.constants import constants
3
- from .brush_preview import create_brush_mask
4
-
5
-
6
- class BrushController:
7
- def __init__(self, brush):
8
- self._brush_mask_cache = {}
9
- self.brush = brush
10
-
11
- def apply_brush_operation(self, master_layer, source_layer, dest_layer, mask_layer, view_pos, image_viewer):
12
- if master_layer is None or source_layer is None:
13
- return False
14
- if dest_layer is None:
15
- dest_layer = master_layer
16
- scene_pos = image_viewer.mapToScene(view_pos)
17
- x_center = int(round(scene_pos.x()))
18
- y_center = int(round(scene_pos.y()))
19
- radius = int(round(self.brush.size // 2))
20
- h, w = master_layer.shape[:2]
21
- x_start, x_end = max(0, x_center - radius), min(w, x_center + radius + 1)
22
- y_start, y_end = max(0, y_center - radius), min(h, y_center + radius + 1)
23
- if x_start >= x_end or y_start >= y_end:
24
- return 0, 0, 0, 0
25
- mask = self.get_brush_mask(radius)
26
- if mask is None:
27
- return 0, 0, 0, 0
28
- master_area = master_layer[y_start:y_end, x_start:x_end]
29
- source_area = source_layer[y_start:y_end, x_start:x_end]
30
- dest_area = dest_layer[y_start:y_end, x_start:x_end]
31
- mask_layer_area = mask_layer[y_start:y_end, x_start:x_end]
32
- mask_area = mask[y_start - (y_center - radius):y_end - (y_center - radius), x_start - (x_center - radius):x_end - (x_center - radius)]
33
- mask_layer_area[:] = np.clip(mask_layer_area + mask_area * self.brush.flow / 100.0, 0.0, 1.0) # np.maximum(mask_layer_area, mask_area)
34
- self.apply_mask(master_area, source_area, mask_layer_area, dest_area)
35
- return x_start, y_start, x_end, y_end
36
-
37
- def get_brush_mask(self, radius):
38
- mask_key = (radius, self.brush.hardness)
39
- if mask_key not in self._brush_mask_cache.keys():
40
- full_mask = create_brush_mask(size=radius * 2 + 1, hardness_percent=self.brush.hardness,
41
- opacity_percent=self.brush.opacity)
42
- self._brush_mask_cache[mask_key] = full_mask
43
- return self._brush_mask_cache[mask_key]
44
-
45
- def apply_mask(self, master_area, source_area, mask_area, dest_area):
46
- opacity_factor = float(self.brush.opacity) / 100.0
47
- effective_mask = np.clip(mask_area * opacity_factor, 0, 1)
48
- dtype = master_area.dtype
49
- max_px_value = constants.MAX_UINT16 if dtype == np.uint16 else constants.MAX_UINT8
50
- if master_area.ndim == 3:
51
- dest_area[:] = np.clip(master_area * (1 - effective_mask[..., np.newaxis]) + source_area * # noqa
52
- effective_mask[..., np.newaxis], 0, max_px_value).astype(dtype)
53
- else:
54
- dest_area[:] = np.clip(master_area * (1 - effective_mask) + source_area * effective_mask, 0, max_px_value).astype(dtype)
55
-
56
- def clear_cache(self):
57
- self._brush_mask_cache.clear()