Add brightness and contrast controls

This commit is contained in:
2025-09-04 15:15:05 +02:00
parent cd89bbf4e4
commit d739e40862

View File

@@ -83,6 +83,10 @@ class VideoEditor:
# Rotation settings # Rotation settings
self.rotation_angle = 0 # 0, 90, 180, 270 degrees self.rotation_angle = 0 # 0, 90, 180, 270 degrees
# Brightness and contrast settings
self.brightness = 0 # -100 to 100
self.contrast = 1.0 # 0.1 to 3.0
# Cut points # Cut points
self.cut_start_frame = None self.cut_start_frame = None
self.cut_end_frame = None self.cut_end_frame = None
@@ -121,12 +125,14 @@ class VideoEditor:
self.playback_speed = 1.0 self.playback_speed = 1.0
self.current_display_frame = None self.current_display_frame = None
# Reset crop, zoom, rotation, and cut settings for new video # Reset crop, zoom, rotation, brightness/contrast, and cut settings for new video
self.crop_rect = None self.crop_rect = None
self.crop_history = [] self.crop_history = []
self.zoom_factor = 1.0 self.zoom_factor = 1.0
self.zoom_center = None self.zoom_center = None
self.rotation_angle = 0 self.rotation_angle = 0
self.brightness = 0
self.contrast = 1.0
self.cut_start_frame = None self.cut_start_frame = None
self.cut_end_frame = None self.cut_end_frame = None
self.display_offset = [0, 0] self.display_offset = [0, 0]
@@ -198,21 +204,24 @@ class VideoEditor:
return self.load_current_frame() return self.load_current_frame()
def apply_crop_zoom_and_rotation(self, frame): def apply_crop_zoom_and_rotation(self, frame):
"""Apply current crop, zoom, and rotation settings to frame""" """Apply current crop, zoom, rotation, and brightness/contrast settings to frame"""
if frame is None: if frame is None:
return None return None
processed_frame = frame.copy() processed_frame = frame.copy()
# Apply crop first # Apply brightness/contrast first (to original frame for best quality)
processed_frame = self.apply_brightness_contrast(processed_frame)
# Apply crop
if self.crop_rect: if self.crop_rect:
x, y, w, h = self.crop_rect x, y, w, h = self.crop_rect
x, y, w, h = int(x), int(y), int(w), int(h) x, y, w, h = int(x), int(y), int(w), int(h)
# Ensure crop is within frame bounds # Ensure crop is within frame bounds
x = max(0, min(x, frame.shape[1] - 1)) x = max(0, min(x, processed_frame.shape[1] - 1))
y = max(0, min(y, frame.shape[0] - 1)) y = max(0, min(y, processed_frame.shape[0] - 1))
w = min(w, frame.shape[1] - x) w = min(w, processed_frame.shape[1] - x)
h = min(h, frame.shape[0] - y) h = min(h, processed_frame.shape[0] - y)
if w > 0 and h > 0: if w > 0 and h > 0:
processed_frame = processed_frame[y:y+h, x:x+w] processed_frame = processed_frame[y:y+h, x:x+w]
@@ -254,6 +263,26 @@ class VideoEditor:
"""Rotate video 90 degrees clockwise""" """Rotate video 90 degrees clockwise"""
self.rotation_angle = (self.rotation_angle + 90) % 360 self.rotation_angle = (self.rotation_angle + 90) % 360
def apply_brightness_contrast(self, frame):
"""Apply brightness and contrast adjustments to frame"""
if self.brightness == 0 and self.contrast == 1.0:
return frame
# Convert brightness from -100/100 range to -255/255 range
brightness_value = self.brightness * 2.55
# Apply brightness and contrast: new_pixel = contrast * old_pixel + brightness
adjusted = cv2.convertScaleAbs(frame, alpha=self.contrast, beta=brightness_value)
return adjusted
def adjust_brightness(self, delta: int):
"""Adjust brightness by delta (-100 to 100)"""
self.brightness = max(-100, min(100, self.brightness + delta))
def adjust_contrast(self, delta: float):
"""Adjust contrast by delta (0.1 to 3.0)"""
self.contrast = max(0.1, min(3.0, self.contrast + delta))
def draw_timeline(self, frame): def draw_timeline(self, frame):
"""Draw timeline at the bottom of the frame""" """Draw timeline at the bottom of the frame"""
height, width = frame.shape[:2] height, width = frame.shape[:2]
@@ -370,7 +399,9 @@ class VideoEditor:
# Add info overlay # Add info overlay
rotation_text = f" | Rotation: {self.rotation_angle}°" if self.rotation_angle != 0 else "" rotation_text = f" | Rotation: {self.rotation_angle}°" if self.rotation_angle != 0 else ""
info_text = f"Frame: {self.current_frame}/{self.total_frames} | Speed: {self.playback_speed:.1f}x | Zoom: {self.zoom_factor:.1f}x{rotation_text} | {'Playing' if self.is_playing else 'Paused'}" brightness_text = f" | Brightness: {self.brightness}" if self.brightness != 0 else ""
contrast_text = f" | Contrast: {self.contrast:.1f}" if self.contrast != 1.0 else ""
info_text = f"Frame: {self.current_frame}/{self.total_frames} | Speed: {self.playback_speed:.1f}x | Zoom: {self.zoom_factor:.1f}x{rotation_text}{brightness_text}{contrast_text} | {'Playing' if self.is_playing else 'Paused'}"
cv2.putText(canvas, info_text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2) cv2.putText(canvas, info_text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
cv2.putText(canvas, info_text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 0), 1) cv2.putText(canvas, info_text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 0), 1)
@@ -648,6 +679,9 @@ class VideoEditor:
else: else:
return None return None
# Apply brightness and contrast
frame = self.apply_brightness_contrast(frame)
# Apply rotation # Apply rotation
if self.rotation_angle != 0: if self.rotation_angle != 0:
frame = self.apply_rotation(frame) frame = self.apply_rotation(frame)
@@ -682,6 +716,8 @@ class VideoEditor:
print(" Shift+A/D: Seek backward/forward (10 frames)") print(" Shift+A/D: Seek backward/forward (10 frames)")
print(" Ctrl+A/D: Seek backward/forward (60 frames)") print(" Ctrl+A/D: Seek backward/forward (60 frames)")
print(" W/S: Increase/Decrease speed") print(" W/S: Increase/Decrease speed")
print(" E/Shift+E: Increase/Decrease brightness")
print(" R/Shift+R: Increase/Decrease contrast")
print(" -: Rotate clockwise 90°") print(" -: Rotate clockwise 90°")
print(" Shift+Click+Drag: Select crop area") print(" Shift+Click+Drag: Select crop area")
print(" U: Undo crop") print(" U: Undo crop")
@@ -740,6 +776,22 @@ class VideoEditor:
self.playback_speed = min(self.MAX_PLAYBACK_SPEED, self.playback_speed + self.SPEED_INCREMENT) self.playback_speed = min(self.MAX_PLAYBACK_SPEED, self.playback_speed + self.SPEED_INCREMENT)
elif key == ord('s'): elif key == ord('s'):
self.playback_speed = max(self.MIN_PLAYBACK_SPEED, self.playback_speed - self.SPEED_INCREMENT) self.playback_speed = max(self.MIN_PLAYBACK_SPEED, self.playback_speed - self.SPEED_INCREMENT)
elif key == ord('e') or key == ord('E'):
# Brightness adjustment: E (increase), Shift+E (decrease)
if key == ord('E'):
self.adjust_brightness(-5)
print(f"Brightness: {self.brightness}")
else:
self.adjust_brightness(5)
print(f"Brightness: {self.brightness}")
elif key == ord('r') or key == ord('R'):
# Contrast adjustment: R (increase), Shift+R (decrease)
if key == ord('R'):
self.adjust_contrast(-0.1)
print(f"Contrast: {self.contrast:.1f}")
else:
self.adjust_contrast(0.1)
print(f"Contrast: {self.contrast:.1f}")
elif key == ord('u'): elif key == ord('u'):
self.undo_crop() self.undo_crop()
elif key == ord('c'): elif key == ord('c'):