scmpvtltd/Image_Enhancer
0
1import io2from typing import Optional3 4import streamlit as st5from PIL import Image, ImageEnhance, ImageFilter, ImageOps6 7st.set_page_config(page_title="Image Editor", page_icon="🖼️", layout="wide")8 9# ---------------------------10# Helpers11# ---------------------------12def load_image(file) -> Image.Image:13 img = Image.open(file)14 # Respect EXIF orientation & normalize to RGB15 img = ImageOps.exif_transpose(img).convert("RGB")16 return img17 18def apply_filters(19 img: Image.Image,20 grayscale: bool,21 chosen_filter: str,22 gauss_radius: float,23 brightness: float,24 contrast: float,25 color_sat: float,26) -> Image.Image:27 out = img.copy()28 29 # Grayscale first30 if grayscale:31 out = ImageOps.grayscale(out).convert("RGB")32 33 # Filters34 if chosen_filter == "Blur":35 out = out.filter(ImageFilter.BLUR)36 elif chosen_filter == "Sharpen":37 out = out.filter(ImageFilter.SHARPEN)38 elif chosen_filter == "Edge Enhance":39 out = out.filter(ImageFilter.EDGE_ENHANCE)40 elif chosen_filter == "Emboss":41 out = out.filter(ImageFilter.EMBOSS)42 elif chosen_filter == "Find Edges":43 out = out.filter(ImageFilter.FIND_EDGES)44 elif chosen_filter == "Contour":45 out = out.filter(ImageFilter.CONTOUR)46 elif chosen_filter == "Detail":47 out = out.filter(ImageFilter.DETAIL)48 elif chosen_filter == "Smooth":49 out = out.filter(ImageFilter.SMOOTH)50 elif chosen_filter == "Gaussian Blur (radius)":51 out = out.filter(ImageFilter.GaussianBlur(radius=gauss_radius))52 # "None" does nothing53 54 # Adjustments55 if brightness != 1.0:56 out = ImageEnhance.Brightness(out).enhance(brightness)57 if contrast != 1.0:58 out = ImageEnhance.Contrast(out).enhance(contrast)59 if color_sat != 1.0:60 out = ImageEnhance.Color(out).enhance(color_sat)61 62 return out63 64def to_bytes(img: Image.Image, fmt: str, quality: int = 95) -> bytes:65 buf = io.BytesIO()66 save_kwargs = {}67 if fmt.upper() == "JPEG":68 save_kwargs["quality"] = quality69 save_kwargs["optimize"] = True70 img.save(buf, format=fmt.upper(), **save_kwargs)71 return buf.getvalue()72 73# ---------------------------74# UI75# ---------------------------76st.title("🖼️ Image Editor (Streamlit)")77st.caption("Upload → edit (filters, grayscale, brightness/contrast/saturation) → download")78 79with st.sidebar:80 st.header("Controls")81 82 filter_name = st.selectbox(83 "Filter",84 [85 "None",86 "Blur",87 "Sharpen",88 "Edge Enhance",89 "Emboss",90 "Find Edges",91 "Contour",92 "Detail",93 "Smooth",94 "Gaussian Blur (radius)",95 ],96 index=0,97 )98 gauss_radius = 0.099 if filter_name == "Gaussian Blur (radius)":100 gauss_radius = st.slider("Gaussian radius", 0.0, 20.0, 2.0, 0.1)101 102 grayscale = st.checkbox("Grayscale", value=False)103 104 st.subheader("Adjustments")105 brightness = st.slider("Brightness", 0.0, 3.0, 1.0, 0.05)106 contrast = st.slider("Contrast", 0.0, 3.0, 1.0, 0.05)107 color_sat = st.slider("Saturation", 0.0, 3.0, 1.0, 0.05)108 109 st.subheader("Preview")110 preview_width = st.slider("Preview width (px)", 300, 1200, 700, 10)111 112 st.subheader("Download settings")113 out_format = st.selectbox("Format", ["PNG", "JPEG", "WEBP"], index=0)114 jpg_quality = 95115 if out_format == "JPEG":116 jpg_quality = st.slider("JPEG quality", 60, 100, 95, 1)117 118uploaded = st.file_uploader(119 "Upload image(s)",120 type=["png", "jpg", "jpeg", "webp"],121 accept_multiple_files=True,122)123 124if not uploaded:125 st.info("Upload one or more images to begin.")126 st.stop()127 128# choose image to edit (crash-proof)129uploaded = st.file_uploader(130 "Upload image(s)",131 type=["png", "jpg", "jpeg", "webp"],132 accept_multiple_files=True,133)134 135if not uploaded:136 st.info("Upload one or more images to begin.")137 st.stop()138 139file_names = [f.name for f in uploaded]140active_name = st.selectbox("Select image to edit", file_names, index=0, key="select_img")141 142# Be safe if Streamlit reruns and the list changes143active_file = next((f for f in uploaded if f.name == active_name), None)144if active_file is None:145 st.warning("File list refreshed—please reselect the image.")146 st.stop()147 148# process149orig = load_image(active_file)150edited = apply_filters(151 orig,152 grayscale=grayscale,153 chosen_filter=filter_name,154 gauss_radius=gauss_radius,155 brightness=brightness,156 contrast=contrast,157 color_sat=color_sat,158)159 160# preview161c1, c2 = st.columns(2, gap="large")162with c1:163 st.markdown("**Original**")164 st.image(orig, use_column_width=False, width=preview_width)165with c2:166 st.markdown("**Edited**")167 st.image(edited, use_column_width=False, width=preview_width)168 169# download170st.divider()171out_bytes = to_bytes(edited, out_format, quality=jpg_quality)172dl_name = f"{active_name.rsplit('.', 1)[0]}_edited.{out_format.lower()}"173st.download_button(174 "⬇️ Download edited image",175 data=out_bytes,176 file_name=dl_name,177 mime=f"image/{'jpeg' if out_format=='JPEG' else out_format.lower()}",178)179 180 