Add brightness and contrast controls
This commit is contained in:
@@ -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'):
|
||||||
|
Reference in New Issue
Block a user