Enhance video editing controls: add Shift+scroll functionality to expand/contract crop uniformly and implement adjust_crop_size_uniform method
This commit is contained in:
@@ -4025,7 +4025,7 @@ class VideoEditor:
|
|||||||
# Force immediate display update to recalculate previous/next points and arrows
|
# Force immediate display update to recalculate previous/next points and arrows
|
||||||
self.display_current_frame()
|
self.display_current_frame()
|
||||||
|
|
||||||
# Handle scroll wheel: Ctrl+scroll -> zoom; plain scroll -> seek ±1 frame (independent of multiplier)
|
# Handle scroll wheel: Ctrl+scroll -> zoom; Shift+scroll -> expand/contract crop; plain scroll -> seek ±1 frame
|
||||||
if event == cv2.EVENT_MOUSEWHEEL:
|
if event == cv2.EVENT_MOUSEWHEEL:
|
||||||
if flags & cv2.EVENT_FLAG_CTRLKEY:
|
if flags & cv2.EVENT_FLAG_CTRLKEY:
|
||||||
if flags > 0: # Scroll up -> zoom in
|
if flags > 0: # Scroll up -> zoom in
|
||||||
@@ -4033,6 +4033,12 @@ class VideoEditor:
|
|||||||
else: # Scroll down -> zoom out
|
else: # Scroll down -> zoom out
|
||||||
self.zoom_factor = max(self.MIN_ZOOM, self.zoom_factor - self.ZOOM_INCREMENT)
|
self.zoom_factor = max(self.MIN_ZOOM, self.zoom_factor - self.ZOOM_INCREMENT)
|
||||||
self.clear_transformation_cache()
|
self.clear_transformation_cache()
|
||||||
|
elif flags & cv2.EVENT_FLAG_SHIFTKEY:
|
||||||
|
# Shift+scroll -> expand/contract crop uniformly
|
||||||
|
if flags > 0: # Scroll up -> expand
|
||||||
|
self.adjust_crop_size_uniform(expand=True)
|
||||||
|
else: # Scroll down -> contract
|
||||||
|
self.adjust_crop_size_uniform(expand=False)
|
||||||
else:
|
else:
|
||||||
if not self.is_image_mode:
|
if not self.is_image_mode:
|
||||||
direction = 1 if flags > 0 else -1
|
direction = 1 if flags > 0 else -1
|
||||||
@@ -4265,6 +4271,45 @@ class VideoEditor:
|
|||||||
self.clear_transformation_cache()
|
self.clear_transformation_cache()
|
||||||
self.save_state() # Save state when crop is adjusted
|
self.save_state() # Save state when crop is adjusted
|
||||||
|
|
||||||
|
def adjust_crop_size_uniform(self, expand: bool, amount: int = None):
|
||||||
|
"""Expand or contract crop uniformly in all directions
|
||||||
|
expand=False: expand (like uppercase HJKL)
|
||||||
|
expand=True: contract (like lowercase hjkl)
|
||||||
|
"""
|
||||||
|
if amount is None:
|
||||||
|
amount = self.crop_size_step
|
||||||
|
if not self.crop_rect:
|
||||||
|
center_x = self.frame_width // 2
|
||||||
|
center_y = self.frame_height // 2
|
||||||
|
default_size = min(self.frame_width, self.frame_height) // 4
|
||||||
|
self.crop_rect = (
|
||||||
|
center_x - default_size // 2,
|
||||||
|
center_y - default_size // 2,
|
||||||
|
default_size,
|
||||||
|
default_size
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
x, y, w, h = self.crop_rect
|
||||||
|
|
||||||
|
if not expand: # expand=False means expand
|
||||||
|
# Expand uniformly from center
|
||||||
|
new_x = max(0, x - amount)
|
||||||
|
new_y = max(0, y - amount)
|
||||||
|
new_w = min(self.frame_width - new_x, w + (x - new_x) + amount)
|
||||||
|
new_h = min(self.frame_height - new_y, h + (y - new_y) + amount)
|
||||||
|
else: # expand=True means contract
|
||||||
|
# Contract uniformly toward center
|
||||||
|
contract_amount = min(amount, (w - 10) // 2, (h - 10) // 2)
|
||||||
|
new_x = x + contract_amount
|
||||||
|
new_y = y + contract_amount
|
||||||
|
new_w = max(10, w - contract_amount * 2)
|
||||||
|
new_h = max(10, h - contract_amount * 2)
|
||||||
|
|
||||||
|
self.crop_rect = (new_x, new_y, new_w, new_h)
|
||||||
|
self.clear_transformation_cache()
|
||||||
|
self.save_state()
|
||||||
|
|
||||||
def render_video(self, output_path: str):
|
def render_video(self, output_path: str):
|
||||||
"""Render video or save image with current edits applied"""
|
"""Render video or save image with current edits applied"""
|
||||||
if self.is_image_mode:
|
if self.is_image_mode:
|
||||||
|
|||||||
Reference in New Issue
Block a user