Skip to content

Commit c88f043

Browse files
committed
зеркалирование отрабатывает правильно
1 parent bc02df2 commit c88f043

File tree

1 file changed

+60
-32
lines changed

1 file changed

+60
-32
lines changed

editor.py

Lines changed: 60 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -156,23 +156,24 @@ def _get_transformed_image_cached(self, zoom_level, scale, rotation, flip_h, fli
156156
else:
157157
return Image.new("RGBA", (10, 10), (255, 0, 0, 128))
158158

159-
# ПРИМЕНЯЕМ МАСШТАБ К ОРИГИНАЛЬНОМУ ИЗОБРАЖЕНИЮ
159+
# ПРАВИЛЬНЫЙ ПОРЯДОК ТРАНСФОРМАЦИЙ:
160+
# 1. Масштаб элемента
160161
if scale != 1.0:
161162
new_width = max(1, int(img.width * scale))
162163
new_height = max(1, int(img.height * scale))
163164
img = img.resize((new_width, new_height), Image.LANCZOS)
164165

165-
# Отражение (применяется после масштабирования)
166+
# 2. Отражение
166167
if flip_h:
167168
img = img.transpose(Image.FLIP_LEFT_RIGHT)
168169
if flip_v:
169170
img = img.transpose(Image.FLIP_TOP_BOTTOM)
170171

171-
# Поворот
172+
# 3. Поворот
172173
if rotation != 0:
173174
img = img.rotate(rotation, expand=True, resample=Image.BICUBIC)
174175

175-
# Масштаб зума (для отображения в редакторе)
176+
# 4. Зум для отображения (только для редактора)
176177
if zoom_level != 1.0:
177178
final_width = max(1, int(img.width * zoom_level))
178179
final_height = max(1, int(img.height * zoom_level))
@@ -182,6 +183,9 @@ def _get_transformed_image_cached(self, zoom_level, scale, rotation, flip_h, fli
182183

183184
def _get_transformed_image(self, zoom_level=1.0):
184185
"""Получает трансформированное изображение для заданного уровня зума"""
186+
logger.debug(f"Getting transformed image: scale={self.scale}, rotation={self.rotation}, "
187+
f"flip_h={self.flip_horizontal}, flip_v={self.flip_vertical}, zoom={zoom_level}")
188+
185189
# Для GIF сначала обновляем текущий кадр
186190
if self.is_gif and self.gif_frames:
187191
self._update_gif_frame()
@@ -210,23 +214,24 @@ def _get_transformed_image(self, zoom_level=1.0):
210214
else:
211215
img = self._original_image.copy()
212216

213-
# ПРИМЕНЯЕМ МАСШТАБ К ОРИГИНАЛЬНОМУ ИЗОБРАЖЕНИЮ
217+
# ПРАВИЛЬНЫЙ ПОРЯДОК ТРАНСФОРМАЦИЙ:
218+
# 1. Масштаб элемента
214219
if self.scale != 1.0:
215220
new_width = max(1, int(img.width * self.scale))
216221
new_height = max(1, int(img.height * self.scale))
217222
img = img.resize((new_width, new_height), Image.LANCZOS)
218223

219-
# Отражение (применяется после масштабирования)
224+
# 2. Отражение
220225
if self.flip_horizontal:
221226
img = img.transpose(Image.FLIP_LEFT_RIGHT)
222227
if self.flip_vertical:
223228
img = img.transpose(Image.FLIP_TOP_BOTTOM)
224229

225-
# Поворот
230+
# 3. Поворот
226231
if self.rotation != 0:
227232
img = img.rotate(self.rotation, expand=True, resample=Image.BICUBIC)
228233

229-
# Масштаб зума (для отображения в редакторе)
234+
# 4. Зум для отображения (только для редактора)
230235
if zoom_level != 1.0:
231236
final_width = max(1, int(img.width * zoom_level))
232237
final_height = max(1, int(img.height * zoom_level))
@@ -256,6 +261,10 @@ def clear_cache(self):
256261
"""Очищает кэш изображений"""
257262
self._get_transformed_image_cached.cache_clear()
258263
self._zoom_cache.clear()
264+
265+
# Также очищаем Tkinter PhotoImage кэш
266+
if hasattr(self, '_tk_images'):
267+
self._tk_images.clear()
259268

260269
class ModelEditor(tk.Toplevel):
261270
def __init__(self, master, on_save=None, device='По умолчанию', noise_gate_threshold=0.01, sensitivity=1.0, thresholds=None, current_slot=None):
@@ -1131,20 +1140,20 @@ def _create_preview_for_export(self, temp_dir, preview_path):
11311140
try:
11321141
img = Image.open(ci.image_path).convert("RGBA")
11331142

1134-
# Применяем трансформации
1143+
# Применяем трансформации в ПРАВИЛЬНОМ ПОРЯДКЕ (как в редакторе)
11351144
if ci.scale != 1.0:
11361145
new_width = max(1, int(img.width * ci.scale))
11371146
new_height = max(1, int(img.height * ci.scale))
11381147
img = img.resize((new_width, new_height), Image.LANCZOS)
11391148

1140-
if ci.rotation != 0:
1141-
img = img.rotate(ci.rotation, expand=True, resample=Image.BICUBIC)
1142-
11431149
if ci.flip_horizontal:
11441150
img = img.transpose(Image.FLIP_LEFT_RIGHT)
11451151
if ci.flip_vertical:
11461152
img = img.transpose(Image.FLIP_TOP_BOTTOM)
11471153

1154+
if ci.rotation != 0:
1155+
img = img.rotate(ci.rotation, expand=True, resample=Image.BICUBIC)
1156+
11481157
px = center_x - img.size[0] // 2 + int(ci.x)
11491158
py = center_y - img.size[1] // 2 + int(ci.y)
11501159

@@ -1297,16 +1306,20 @@ def _fast_render_canvas(self, level=0.0, mode="none"):
12971306
scaled_width = int(self.canvas_width * self.zoom_level)
12981307
scaled_height = int(self.canvas_height * self.zoom_level)
12991308

1309+
# Убедитесь, что scaled_width и scaled_height не отрицательные
1310+
scaled_width = max(10, scaled_width)
1311+
scaled_height = max(10, scaled_height)
1312+
13001313
center_x = canvas_width // 2 + self.offset_x
13011314
center_y = canvas_height // 2 + self.offset_y
13021315

13031316
canvas_x1 = center_x - scaled_width // 2
13041317
canvas_y1 = center_y - scaled_height // 2
13051318

1306-
# Рисуем фон холста
1319+
# Рисуем фон холста с учетом границ
13071320
self.canvas.create_rectangle(
1308-
canvas_x1, canvas_y1,
1309-
canvas_x1 + scaled_width, canvas_y1 + scaled_height,
1321+
max(0, canvas_x1), max(0, canvas_y1),
1322+
min(canvas_width, canvas_x1 + scaled_width), min(canvas_height, canvas_y1 + scaled_height),
13101323
outline="#666", width=2, fill="#333"
13111324
)
13121325

@@ -1341,11 +1354,15 @@ def _fast_render_canvas(self, level=0.0, mode="none"):
13411354
continue
13421355

13431356
# Рассчитываем позицию на холсте
1344-
img_center_x = scaled_width // 2
1345-
img_center_y = scaled_height // 2
1357+
center_x_scaled = scaled_width // 2
1358+
center_y_scaled = scaled_height // 2
13461359

1347-
pos_x = canvas_x1 + img_center_x - img.width // 2 + int(ci.x * self.zoom_level)
1348-
pos_y = canvas_x1 + img_center_y - img.height // 2 + int(ci.y * self.zoom_level)
1360+
# Координаты относительно центра с учетом зума
1361+
offset_x = int(ci.x * self.zoom_level)
1362+
offset_y = int(ci.y * self.zoom_level)
1363+
1364+
pos_x = canvas_x1 + center_x_scaled - img.width // 2 + offset_x
1365+
pos_y = canvas_y1 + center_y_scaled - img.height // 2 + offset_y
13491366

13501367
# Используем кэшированные PhotoImage, но для GIF не кэшируем
13511368
if ci.is_gif:
@@ -1840,6 +1857,8 @@ def on_mirror_change(self):
18401857
ci.flip_vertical = self.flip_v_var.get()
18411858
ci.clear_cache() # Очищаем кэш
18421859

1860+
# Очищаем кэш редактора
1861+
self._photo_images.clear()
18431862
self._canvas_cache_valid = False
18441863
self.redraw_canvas()
18451864
self.save_to_history("Изменение отражения")
@@ -1853,6 +1872,8 @@ def on_visible_change(self):
18531872
ci.visible = self.visible_var.get()
18541873
ci.clear_cache() # Очищаем кэш
18551874

1875+
# Очищаем кэш редактора
1876+
self._photo_images.clear()
18561877
self._canvas_cache_valid = False
18571878
self.redraw_canvas()
18581879
self.save_to_history("Изменение видимости")
@@ -2444,19 +2465,20 @@ def create_preview(self):
24442465
try:
24452466
img = Image.open(ci.image_path).convert("RGBA")
24462467

2447-
# Применяем масштаб ПЕРВЫМ (как в рендерере)
2468+
# ПРАВИЛЬНЫЙ ПОРЯДОК ТРАНСФОРМАЦИЙ (такой же как в редакторе):
2469+
# 1. Масштаб элемента
24482470
if ci.scale != 1.0:
24492471
new_width = max(1, int(img.width * ci.scale))
24502472
new_height = max(1, int(img.height * ci.scale))
24512473
img = img.resize((new_width, new_height), Image.LANCZOS)
24522474

2453-
# Затем отражение
2475+
# 2. Отражение
24542476
if ci.flip_horizontal:
24552477
img = img.transpose(Image.FLIP_LEFT_RIGHT)
24562478
if ci.flip_vertical:
24572479
img = img.transpose(Image.FLIP_TOP_BOTTOM)
24582480

2459-
# Затем поворот
2481+
# 3. Поворот
24602482
if ci.rotation != 0:
24612483
img = img.rotate(ci.rotation, expand=True, resample=Image.BICUBIC)
24622484

@@ -2637,14 +2659,17 @@ def apply_props(self):
26372659
ci.flip_horizontal = self.flip_h_var.get()
26382660
ci.flip_vertical = self.flip_v_var.get()
26392661

2640-
# Очищаем кэш
2662+
# Очищаем кэш изображения
26412663
ci.clear_cache()
26422664

2665+
# Очищаем кэш редактора
2666+
self._photo_images.clear()
2667+
self._canvas_cache_valid = False
2668+
26432669
self._save_tree_state()
26442670
self.tree_state["preserve_selection"] = True
26452671

26462672
self.refresh_tree()
2647-
self._canvas_cache_valid = False
26482673
self.redraw_canvas()
26492674
self.last_autosave = time.time()
26502675

@@ -2843,22 +2868,25 @@ def on_canvas_mouse_down(self, event):
28432868
continue
28442869

28452870
# Позиция элемента
2846-
img_center_x = scaled_width // 2
2847-
img_center_y = scaled_height // 2
2871+
center_x_scaled = scaled_width // 2
2872+
center_y_scaled = scaled_height // 2
2873+
2874+
offset_x = int(ci.x * self.zoom_level)
2875+
offset_y = int(ci.y * self.zoom_level)
28482876

2849-
pos_x = img_center_x - img.width // 2 + int(ci.x * self.zoom_level)
2850-
pos_y = img_center_y - img.height // 2 + int(ci.y * self.zoom_level)
2877+
pos_x = canvas_x1 + center_x_scaled - img.width // 2 + offset_x
2878+
pos_y = canvas_y1 + center_y_scaled - img.height // 2 + offset_y
28512879

28522880
# Проверяем попадание
2853-
if (pos_x <= event.x - canvas_x1 <= pos_x + img.width and
2854-
pos_y <= event.y - canvas_y1 <= pos_y + img.height):
2881+
if (pos_x <= event.x <= pos_x + img.width and
2882+
pos_y <= event.y <= pos_y + img.height):
28552883

28562884
# Проверяем прозрачность пикселя
28572885
try:
28582886
is_opaque = False
28592887
if img.mode == 'RGBA':
2860-
pixel_x = int((event.x - canvas_x1) - pos_x)
2861-
pixel_y = int((event.y - canvas_y1) - pos_y)
2888+
pixel_x = int(event.x - pos_x)
2889+
pixel_y = int(event.y - pos_y)
28622890

28632891
if 0 <= pixel_x < img.width and 0 <= pixel_y < img.height:
28642892
pixel = img.getpixel((pixel_x, pixel_y))

0 commit comments

Comments
 (0)