any2any / app.py
namelessai's picture
fix yet another type error
18f5767 verified
Raw
History Blame Contribute Delete
4.11 kB
import io
from pathlib import Path
from PIL import Image
import gradio as gr
# Optional support for extra formats requires plugins:
# - JPEG2000: built-in via Pillow
# - AVIF: install 'pillow-avif-plugin'
# - HEIF/HEIC: install 'pillow-heif'
# Supported formats and their default options
offered_formats = [
"JPEG", "JPEG2000", "PNG", "BMP", "TIFF", "WEBP", "AVIF", "HEIF"
]
# Map formats to save kwargs defaults
format_options = {
"JPEG": {"quality": 85, "optimize": True},
"JPEG2000": {"quality_layers": [25, 50, 75], "codec": "jp2"},
"PNG": {"compress_level": 6, "optimize": True},
"BMP": {},
"TIFF": {"compression": "tiff_deflate"},
"WEBP": {"quality": 80, "lossless": False},
"AVIF": {"quality": 50, "speed": 4},
"HEIF": {"quality": 50, "subsampling": "4:2:0"}
}
def convert_image(
img_file, output_format,
quality, compress_level,
jpeg2000_layers, avif_speed,
subsampling, professional_lossless
):
# img_file is a filesystem path (string)
img_path = Path(img_file)
img_bytes = img_path.read_bytes()
# Load image and convert to RGB
image = Image.open(io.BytesIO(img_bytes)).convert("RGB")
# Prepare save kwargs
fmt = output_format
save_kwargs = {}
if professional_lossless:
# Force true lossless: use PNG
fmt = "PNG"
save_kwargs.update({"compress_level": 9, "optimize": True})
else:
# Base defaults for chosen format
save_kwargs.update(format_options.get(fmt, {}))
# Overrides per-format
if fmt == "JPEG":
save_kwargs["quality"] = quality
elif fmt == "WEBP":
save_kwargs["quality"] = quality
save_kwargs["lossless"] = False
elif fmt == "PNG":
save_kwargs["compress_level"] = compress_level
save_kwargs["optimize"] = True
elif fmt == "JPEG2000":
save_kwargs["quality_layers"] = [int(l) for l in jpeg2000_layers.split(",")]
elif fmt == "AVIF":
save_kwargs["quality"] = quality
save_kwargs["speed"] = avif_speed
elif fmt == "HEIF":
save_kwargs["quality"] = quality
save_kwargs["subsampling"] = subsampling
# Save into a bytes buffer
buf = io.BytesIO()
image.save(buf, format=fmt, **save_kwargs)
buf.seek(0)
# Return bytes along with a filename
filename = f"converted_image.{fmt.lower()}"
return (buf.getvalue(), filename)
def build_app():
with gr.Blocks() as demo:
gr.Markdown("# Advanced Image Converter")
with gr.Row():
# Use 'filepath' so Gradio returns a local file path string
inp = gr.File(label="Upload Image", file_types=["image"], type="filepath")
out = gr.File(label="Download Converted")
with gr.Row():
fmt = gr.Dropdown(offered_formats, value="PNG", label="Output Format")
with gr.Row():
quality = gr.Slider(1, 100, value=85, step=1,
label="Quality (JPEG/AVIF/HEIF/WEBP)")
compress = gr.Slider(0, 9, value=6, step=1,
label="PNG Compress Level")
with gr.Row():
jpeg2000_layers = gr.Textbox(value="25,50,75",
label="JPEG2000 Quality Layers (comma-separated)")
avif_speed = gr.Slider(0, 8, value=4, step=1, label="AVIF Speed")
subsample = gr.Dropdown(["4:4:4", "4:2:2", "4:2:0"], value="4:2:0",
label="HEIF Subsampling")
professional = gr.Checkbox(label="Professional Lossless Mode",
info="Force highest-quality lossless conversion as optimized PNG")
convert_btn = gr.Button("Convert")
convert_btn.click(
fn=convert_image,
inputs=[inp, fmt, quality, compress,
jpeg2000_layers, avif_speed,
subsample, professional],
outputs=out
)
return demo
if __name__ == "__main__":
app = build_app()
app.launch()