Refactor coordinate mapping in VideoEditor for improved zoom and rotation handling
This commit enhances the _map_original_to_screen and _map_screen_to_original methods by clarifying the calculations for zoom and rotation. It introduces new variables for better readability and ensures accurate mapping of coordinates, including adjustments for display offsets. The changes streamline the processing of frame dimensions and improve the overall functionality of the video editing experience.
This commit is contained in:
@@ -1201,14 +1201,18 @@ class VideoEditor:
|
||||
|
||||
def _map_original_to_screen(self, ox, oy):
|
||||
"""Map a point in original frame coords to canvas screen coords."""
|
||||
cx, cy, cw, ch = self._get_effective_crop_rect_for_frame(getattr(self, 'current_frame', 0))
|
||||
frame_number = getattr(self, 'current_frame', 0)
|
||||
cx, cy, cw, ch = self._get_effective_crop_rect_for_frame(frame_number)
|
||||
# Relative to effective crop
|
||||
px = ox - cx
|
||||
py = oy - cy
|
||||
angle = self.rotation_angle
|
||||
# Dimensions after rotation
|
||||
if angle in (90, 270):
|
||||
rotated_w, rotated_h = ch, cw
|
||||
else:
|
||||
rotated_w, rotated_h = cw, ch
|
||||
# Forward rotation mapping
|
||||
if angle == 90:
|
||||
rx, ry = py, rotated_w - px
|
||||
elif angle == 180:
|
||||
@@ -1217,51 +1221,68 @@ class VideoEditor:
|
||||
rx, ry = rotated_h - py, px
|
||||
else:
|
||||
rx, ry = px, py
|
||||
# Zoom
|
||||
zx = rx * self.zoom_factor
|
||||
zy = ry * self.zoom_factor
|
||||
base_w, base_h = rotated_w, rotated_h
|
||||
disp_w = int(base_w * self.zoom_factor)
|
||||
disp_h = int(base_h * self.zoom_factor)
|
||||
# Apply display offset cropping in zoomed space
|
||||
new_w = int(rotated_w * self.zoom_factor)
|
||||
new_h = int(rotated_h * self.zoom_factor)
|
||||
offx_max = max(0, new_w - self.window_width)
|
||||
offy_max = max(0, new_h - self.window_height)
|
||||
offx = max(0, min(int(self.display_offset[0]), offx_max))
|
||||
offy = max(0, min(int(self.display_offset[1]), offy_max))
|
||||
inframe_x = zx - offx
|
||||
inframe_y = zy - offy
|
||||
# Size of processed_frame from apply_crop_zoom_and_rotation
|
||||
base_w = new_w if new_w <= self.window_width else self.window_width
|
||||
base_h = new_h if new_h <= self.window_height else self.window_height
|
||||
# Final scale and canvas placement
|
||||
available_height = self.window_height - (0 if self.is_image_mode else self.TIMELINE_HEIGHT)
|
||||
scale = min(self.window_width / max(1, disp_w), available_height / max(1, disp_h))
|
||||
if scale < 1.0:
|
||||
final_w = int(disp_w * scale)
|
||||
final_h = int(disp_h * scale)
|
||||
else:
|
||||
final_w = disp_w
|
||||
final_h = disp_h
|
||||
scale = 1.0
|
||||
start_x = (self.window_width - final_w) // 2
|
||||
start_y = (available_height - final_h) // 2
|
||||
sx = int(round(start_x + zx * scale))
|
||||
sy = int(round(start_y + zy * scale))
|
||||
scale = min(self.window_width / max(1, base_w), available_height / max(1, base_h))
|
||||
final_w = int(base_w * scale)
|
||||
final_h = int(base_h * scale)
|
||||
start_x_canvas = (self.window_width - final_w) // 2
|
||||
start_y_canvas = (available_height - final_h) // 2
|
||||
sx = int(round(start_x_canvas + inframe_x * scale))
|
||||
sy = int(round(start_y_canvas + inframe_y * scale))
|
||||
return sx, sy
|
||||
|
||||
def _map_screen_to_original(self, sx, sy):
|
||||
"""Map a point on canvas screen coords back to original frame coords."""
|
||||
cx, cy, cw, ch = self._get_effective_crop_rect_for_frame(getattr(self, 'current_frame', 0))
|
||||
frame_number = getattr(self, 'current_frame', 0)
|
||||
cx, cy, cw, ch = self._get_effective_crop_rect_for_frame(frame_number)
|
||||
angle = self.rotation_angle
|
||||
# Dimensions after rotation
|
||||
if angle in (90, 270):
|
||||
rotated_w, rotated_h = ch, cw
|
||||
else:
|
||||
rotated_w, rotated_h = cw, ch
|
||||
disp_w = int(rotated_w * self.zoom_factor)
|
||||
disp_h = int(rotated_h * self.zoom_factor)
|
||||
# Zoomed dimensions and base processed dimensions (after window cropping)
|
||||
new_w = int(rotated_w * self.zoom_factor)
|
||||
new_h = int(rotated_h * self.zoom_factor)
|
||||
base_w = new_w if new_w <= self.window_width else self.window_width
|
||||
base_h = new_h if new_h <= self.window_height else self.window_height
|
||||
# Final scaling used in display
|
||||
available_height = self.window_height - (0 if self.is_image_mode else self.TIMELINE_HEIGHT)
|
||||
scale = min(self.window_width / max(1, disp_w), available_height / max(1, disp_h))
|
||||
if scale < 1.0:
|
||||
final_w = int(disp_w * scale)
|
||||
final_h = int(disp_h * scale)
|
||||
else:
|
||||
final_w = disp_w
|
||||
final_h = disp_h
|
||||
scale = 1.0
|
||||
start_x = (self.window_width - final_w) // 2
|
||||
start_y = (available_height - final_h) // 2
|
||||
zx = (sx - start_x) / max(1e-6, scale)
|
||||
zy = (sy - start_y) / max(1e-6, scale)
|
||||
scale = min(self.window_width / max(1, base_w), available_height / max(1, base_h))
|
||||
final_w = int(base_w * scale)
|
||||
final_h = int(base_h * scale)
|
||||
start_x_canvas = (self.window_width - final_w) // 2
|
||||
start_y_canvas = (available_height - final_h) // 2
|
||||
# Back to processed (zoomed+cropped) space
|
||||
zx = (sx - start_x_canvas) / max(1e-6, scale)
|
||||
zy = (sy - start_y_canvas) / max(1e-6, scale)
|
||||
# Add display offset in zoomed space
|
||||
offx_max = max(0, new_w - self.window_width)
|
||||
offy_max = max(0, new_h - self.window_height)
|
||||
offx = max(0, min(int(self.display_offset[0]), offx_max))
|
||||
offy = max(0, min(int(self.display_offset[1]), offy_max))
|
||||
zx += offx
|
||||
zy += offy
|
||||
# Reverse zoom
|
||||
rx = zx / max(1e-6, self.zoom_factor)
|
||||
ry = zy / max(1e-6, self.zoom_factor)
|
||||
# Reverse rotation
|
||||
if angle == 90:
|
||||
px, py = rotated_w - ry, rx
|
||||
elif angle == 180:
|
||||
@@ -1270,6 +1291,7 @@ class VideoEditor:
|
||||
px, py = ry, rotated_h - rx
|
||||
else:
|
||||
px, py = rx, ry
|
||||
# Back to original frame
|
||||
ox = px + cx
|
||||
oy = py + cy
|
||||
ox = max(0, min(int(round(ox)), self.frame_width - 1))
|
||||
|
Reference in New Issue
Block a user