Spaces:
Running
Running
import streamlit as st | |
from PIL import Image, ImageEnhance, ImageFilter, ImageOps, ImageDraw | |
import numpy as np | |
import io | |
# App Title | |
st.title("Advanced Image Editor") | |
# File Uploader | |
uploaded_file = st.file_uploader("Upload an image", type=["jpg", "jpeg", "png"]) | |
if uploaded_file: | |
# Load image | |
img = Image.open(uploaded_file).convert("RGBA") | |
st.image(img, caption="Original Image", use_container_width=True) | |
# Sidebar Options | |
st.sidebar.title("Editing Options") | |
# Crop Tool | |
st.sidebar.header("Crop") | |
crop_left = st.sidebar.slider("Crop Left (%)", 0, 50, 0) | |
crop_top = st.sidebar.slider("Crop Top (%)", 0, 50, 0) | |
crop_right = st.sidebar.slider("Crop Right (%)", 0, 50, 0) | |
crop_bottom = st.sidebar.slider("Crop Bottom (%)", 0, 50, 0) | |
left = int(crop_left * img.width / 100) | |
top = int(crop_top * img.height / 100) | |
right = img.width - int(crop_right * img.width / 100) | |
bottom = img.height - int(crop_bottom * img.height / 100) | |
img_cropped = img.crop((left, top, right, bottom)) | |
# Rotation Tool | |
st.sidebar.header("Rotation") | |
rotation = st.sidebar.slider("Rotate (°)", 0, 360, 0) | |
img_rotated = img_cropped.rotate(rotation, expand=True) | |
# Background Color Change | |
st.sidebar.header("Background Color") | |
bg_color = st.sidebar.color_picker("Pick a Background Color", "#FFFFFF") | |
bg_layer = Image.new("RGBA", img_rotated.size, bg_color) | |
img_with_bg = Image.alpha_composite(bg_layer, img_rotated) | |
# Ensure RGBA transparency | |
if img_with_bg.mode != "RGBA": | |
img_with_bg = img_with_bg.convert("RGBA") | |
# Filters | |
st.sidebar.header("Filters") | |
filters = st.sidebar.selectbox("Choose a filter", ["None", "Grayscale", "Sepia", "Negative", "Blur", "Contour", "Detail", "Emboss"]) | |
if filters == "Grayscale": | |
img_filtered = img_with_bg.convert("L").convert("RGBA") | |
elif filters == "Sepia": | |
sepia_filter = np.array(img_with_bg)[:, :, :3] | |
sepia = np.dot(sepia_filter, [0.393, 0.769, 0.189]).clip(0, 255).astype("uint8") | |
img_filtered = Image.fromarray(sepia).convert("RGBA") | |
elif filters == "Negative": | |
img_filtered = ImageOps.invert(img_with_bg.convert("RGB")).convert("RGBA") | |
elif filters == "Blur": | |
img_filtered = img_with_bg.filter(ImageFilter.BLUR) | |
elif filters == "Contour": | |
img_filtered = img_with_bg.filter(ImageFilter.CONTOUR) | |
elif filters == "Detail": | |
img_filtered = img_with_bg.filter(ImageFilter.DETAIL) | |
elif filters == "Emboss": | |
img_filtered = img_with_bg.filter(ImageFilter.EMBOSS) | |
else: | |
img_filtered = img_with_bg | |
# Adjustments | |
st.sidebar.header("Adjustments") | |
brightness = st.sidebar.slider("Brightness", 0.5, 2.0, 1.0) | |
contrast = st.sidebar.slider("Contrast", 0.5, 2.0, 1.0) | |
sharpness = st.sidebar.slider("Sharpness", 0.5, 2.0, 1.0) | |
saturation = st.sidebar.slider("Saturation", 0.5, 2.0, 1.0) | |
img_final = ImageEnhance.Brightness(img_filtered).enhance(brightness) | |
img_final = ImageEnhance.Contrast(img_final).enhance(contrast) | |
img_final = ImageEnhance.Sharpness(img_final).enhance(sharpness) | |
img_final = ImageEnhance.Color(img_final).enhance(saturation) | |
# Resize Tool | |
st.sidebar.header("Resize") | |
new_width = st.sidebar.slider("Width", 50, img_final.width, img_final.width) | |
new_height = st.sidebar.slider("Height", 50, img_final.height, img_final.height) | |
img_resized = img_final.resize((new_width, new_height)) | |
# Convert RGBA to RGB for JPEG format | |
img_resized_rgb = img_resized.convert("RGB") | |
# Display Final Image | |
st.image(img_resized, caption="Edited Image", use_container_width=True) | |
# Download Button | |
st.sidebar.header("Download") | |
buffer = io.BytesIO() | |
img_resized_rgb.save(buffer, format="JPEG") | |
st.sidebar.download_button("Download Edited Image", buffer.getvalue(), file_name="edited_image.jpg", mime="image/jpeg") | |
else: | |
st.info("Please upload an image to start editing.") | |