| | import gradio as gr |
| | import numpy as np |
| | from PIL import Image |
| |
|
| |
|
| | def apply_photoshop_color_balance_with_controls( |
| | image_pil, cyan_shift, magenta_shift, yellow_shift, brightness, contrast |
| | ): |
| | |
| | if image_pil is None: |
| | return None |
| |
|
| | |
| | image_rgb = np.array(image_pil.convert("RGB")).astype(np.float32) / 255.0 |
| | R0, G0, B0 = image_rgb[..., 0], image_rgb[..., 1], image_rgb[..., 2] |
| |
|
| | |
| | valid_mask = np.any(image_rgb > 0.05, axis=-1) |
| |
|
| | |
| | orig_lum = 0.299 * R0 + 0.587 * G0 + 0.114 * B0 |
| |
|
| | |
| | C = 1 - R0 |
| | M = 1 - G0 |
| | Y = 1 - B0 |
| |
|
| | |
| | delta_C = cyan_shift / 100.0 |
| | delta_M = magenta_shift / 100.0 |
| | delta_Y = yellow_shift / 100.0 |
| |
|
| | |
| | C[valid_mask] = np.clip(C[valid_mask] + delta_C, 0, 1) |
| | M[valid_mask] = np.clip(M[valid_mask] + delta_M, 0, 1) |
| | Y[valid_mask] = np.clip(Y[valid_mask] + delta_Y, 0, 1) |
| |
|
| | |
| | R = 1 - C |
| | G = 1 - M |
| | B = 1 - Y |
| |
|
| | |
| | new_lum = 0.299 * R + 0.587 * G + 0.114 * B |
| | gain = np.ones_like(new_lum) |
| | gain[valid_mask] = (orig_lum[valid_mask] + 1e-5) / (new_lum[valid_mask] + 1e-5) |
| |
|
| | R = np.clip(R * gain, 0, 1) |
| | G = np.clip(G * gain, 0, 1) |
| | B = np.clip(B * gain, 0, 1) |
| |
|
| | |
| | result = np.stack([R, G, B], axis=-1) |
| |
|
| | |
| | brightness_shift = brightness / 250.0 |
| | result = np.clip(result + brightness_shift, 0, 1) |
| |
|
| | |
| | contrast_factor = 1.0 + (contrast / 250.0) |
| | result = np.clip((result - 0.5) * contrast_factor + 0.5, 0, 1) |
| |
|
| | return Image.fromarray((result * 255).astype(np.uint8)) |
| |
|
| | show_sliders = False |
| | share = False |
| |
|
| | iface = gr.Interface( |
| | fn=apply_photoshop_color_balance_with_controls, |
| | inputs=[ |
| | gr.Image(type="pil", label="Upload Image"), |
| | gr.Slider(-100, 100, value=37, label="Red–Cyan", visible=show_sliders), |
| | gr.Slider(-100, 100, value=-20, label="Green-Magenta", visible=show_sliders), |
| | gr.Slider(-100, 100, value=-10, label="Blue-Yellow", visible=show_sliders), |
| | gr.Slider(-100, 100, value=-25, label="Brightness", visible=show_sliders), |
| | gr.Slider(-100, 100, value=34, label="Contrast", visible=show_sliders), |
| | ], |
| | live=True, |
| | outputs=gr.Image(type="pil", label="Processed Image"), |
| | title="Image Color Balancer with CMY + Brightness/Contrast", |
| | description="Apply Photoshop-like CMY color shifts in shadows. Optionally adjust brightness and contrast.", |
| | ) |
| |
|
| |
|
| | if __name__ == "__main__": |
| | iface.launch(share=share) |
| |
|