import streamlit as st from PIL import Image, ImageOps import io from streamlit_drawable_canvas import st_canvas # Set Streamlit page configuration st.set_page_config(page_title="Image Transformer", page_icon="🖼️", layout="wide") # Sidebar for navigation and options st.sidebar.title("Transformation Options") operation = st.sidebar.radio( "Choose an operation to perform:", ("Mirror", "Resize", "Crop", "Rotate", "Black/White", "Pixelate", "Compress") ) # Main title for the app st.title("Image Manipulation with Generative AI") st.write("Upload an image and apply transformations based on your selection") # Upload image uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "png", "jpeg"]) if uploaded_file is not None: # Load the image image = Image.open(uploaded_file) # Create two columns for displaying images col1, col3 = st.columns([1, 1]) # Create a middle column for the "Apply" button col2 = st.empty() # This will hold the button # Show the original image (smaller size) in the first column with col1: st.image(image, caption="Original Image", use_column_width=False, width=250) # Variables to store slider values or manual inputs new_width = None new_height = None crop_values = None angle = None pixel_size = None quality = None # Display sliders/input fields based on operation, but only apply when the button is pressed if operation == "Resize": st.write("Resize Image:") new_width = st.number_input("Width (in px)", min_value=50, max_value=2000, value=image.width) new_height = st.number_input("Height (in px)", min_value=50, max_value=2000, value=image.height) elif operation == "Crop": st.write("Crop Image:") st.write("Draw a rectangle on the image to crop it.") canvas_result = st_canvas( stroke_width=1, stroke_color="#FF0000", background_image=image, update_streamlit=True, height=image.height, width=image.width, drawing_mode="rect", key="crop_canvas" ) if canvas_result.json_data is not None: try: # Get the rectangle from the canvas rect = canvas_result.json_data["objects"][0] left = int(rect["left"]) top = int(rect["top"]) width = int(rect["width"]) height = int(rect["height"]) crop_values = (left, top, left + width, top + height) except IndexError: st.write("No rectangle drawn yet.") elif operation == "Rotate": angle = st.number_input("Rotate Image clockwise (in degrees)", min_value=0, max_value=360, value=0) elif operation == "Pixelate": pixel_size = st.number_input("Pixelate Size (larger number = more pixelation)", min_value=1, max_value=50, value=10) elif operation == "Compress": quality = st.number_input("Image Quality (Compression)", min_value=10, max_value=100, value=80) # Apply button with dynamic label based on the operation apply_button_label = f"Apply {operation}" if col2.button(apply_button_label): # Only generate the output when the "Apply" button is clicked with col3: # Mirror Operation if operation == "Mirror": mirrored_image = ImageOps.mirror(image) st.image(mirrored_image, caption=" ", use_column_width=False, width=250) # Download button for mirrored image buffered = io.BytesIO() mirrored_image.save(buffered, format="PNG") st.download_button("Download Image", data=buffered.getvalue(), file_name="mirrored_image.png", mime="image/png") # Resize Operation elif operation == "Resize" and new_width and new_height: resized_image = image.resize((new_width, new_height), Image.LANCZOS) st.image(resized_image, caption=" ", use_column_width=False, width=250) # Download button for resized image buffered = io.BytesIO() resized_image.save(buffered, format="PNG") st.download_button("Download Image", data=buffered.getvalue(), file_name="resized_image.png", mime="image/png") # Crop Operation elif operation == "Crop" and crop_values: cropped_image = image.crop(crop_values) st.image(cropped_image, caption=" ", use_column_width=False, width=250) # Download button for cropped image buffered = io.BytesIO() cropped_image.save(buffered, format="PNG") st.download_button("Download Image", data=buffered.getvalue(), file_name="cropped_image.png", mime="image/png") # Rotate Operation elif operation == "Rotate" and angle is not None: rotated_image = image.rotate(-angle) # Negative to rotate clockwise st.image(rotated_image, caption=" ", use_column_width=False, width=250) # Download button for rotated image buffered = io.BytesIO() rotated_image.save(buffered, format="PNG") st.download_button("Download Image", data=buffered.getvalue(), file_name="rotated_image.png", mime="image/png") # Black/White Operation elif operation == "Black/White": bw_image = image.convert("L") st.image(bw_image, caption=" ", use_column_width=False, width=250) # Download button for black-and-white image buffered = io.BytesIO() bw_image.save(buffered, format="PNG") st.download_button("Download Image", data=buffered.getvalue(), file_name="bw_image.png", mime="image/png") # Pixelate Operation elif operation == "Pixelate" and pixel_size: small = image.resize((image.width // pixel_size, image.height // pixel_size), Image.NEAREST) pixelated_image = small.resize((image.width, image.height), Image.NEAREST) st.image(pixelated_image, caption=" ", use_column_width=False, width=250) # Download button for pixelated image buffered = io.BytesIO() pixelated_image.save(buffered, format="PNG") st.download_button("Download Image", data=buffered.getvalue(), file_name="pixelated_image.png", mime="image/png") # Compress Operation elif operation == "Compress" and quality: # Save the image with the specified quality buffered = io.BytesIO() image.save(buffered, format="JPEG", quality=quality) st.image(image, caption=" ", use_column_width=False, width=250) # Download button for compressed image st.download_button("Download Image", data=buffered.getvalue(), file_name="compressed_image.jpeg", mime="image/jpeg")