Spaces:
Sleeping
Sleeping
File size: 6,828 Bytes
71aee75 9c007e5 71aee75 9c007e5 25b025f 9c007e5 25b025f 9c007e5 25b025f 9c007e5 25b025f 9c007e5 25b025f 9c007e5 25b025f 9c007e5 71aee75 9c007e5 71aee75 25b025f 9c007e5 71aee75 9c007e5 71aee75 9c007e5 71aee75 9c007e5 71aee75 9c007e5 71aee75 25b025f 9c007e5 25b025f 9c007e5 25b025f 9c007e5 25b025f 9c007e5 25b025f 9c007e5 25b025f 9c007e5 25b025f 9c007e5 25b025f 9c007e5 25b025f 9c007e5 25b025f 9c007e5 25b025f 9c007e5 71aee75 9c007e5 71aee75 9c007e5 25b025f 9c007e5 71aee75 9c007e5 71aee75 9c007e5 71aee75 9c007e5 71aee75 9c007e5 71aee75 9c007e5 71aee75 9c007e5 71aee75 9c007e5 71aee75 9c007e5 71aee75 25b025f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | import gradio as gr
from PIL import Image
import io
import time
import tempfile
from pathlib import Path
import zipfile
def compress_image(file, quality=75, format_type="webp"):
"""Simple image compression function"""
if file is None:
return None, "Please upload an image"
try:
# Open image
img = Image.open(file.name)
original_size = Path(file.name).stat().st_size / 1024
# Compress to selected format
output = io.BytesIO()
if format_type == "webp":
img.save(output, format='WEBP', quality=quality, method=4)
extension = ".webp"
elif format_type == "jpeg":
if img.mode in ('RGBA', 'LA', 'P'):
# Convert to RGB for JPEG
rgb_img = Image.new('RGB', img.size, (255, 255, 255))
rgb_img.paste(img, mask=img.split()[-1] if img.mode == 'RGBA' else None)
img = rgb_img
img.save(output, format='JPEG', quality=quality, optimize=True)
extension = ".jpg"
else: # png
img.save(output, format='PNG', optimize=True)
extension = ".png"
output.seek(0)
compressed_size = len(output.getvalue()) / 1024
saved_percent = (1 - compressed_size / original_size) * 100
# Save to temp file for download
temp_path = tempfile.NamedTemporaryFile(delete=False, suffix=extension)
temp_path.write(output.getvalue())
temp_path.close()
info = f"""✅ Success!
Original: {original_size:.1f} KB
Compressed: {compressed_size:.1f} KB
Saved: {saved_percent:.1f}%
Format: {format_type.upper()}
Quality: {quality}"""
return temp_path.name, info
except Exception as e:
return None, f"❌ Error: {str(e)}"
def compress_batch(files, quality=75, format_type="webp"):
"""Batch compression"""
if not files:
return None, "Please upload files"
compressed_paths = []
total_saved = 0
with tempfile.TemporaryDirectory() as temp_dir:
for file in files:
try:
img = Image.open(file.name)
original_size = Path(file.name).stat().st_size / 1024
output = io.BytesIO()
if format_type == "webp":
img.save(output, format='WEBP', quality=quality)
ext = ".webp"
elif format_type == "jpeg":
if img.mode in ('RGBA', 'LA', 'P'):
rgb_img = Image.new('RGB', img.size, (255, 255, 255))
rgb_img.paste(img, mask=img.split()[-1] if img.mode == 'RGBA' else None)
img = rgb_img
img.save(output, format='JPEG', quality=quality)
ext = ".jpg"
else:
img.save(output, format='PNG', optimize=True)
ext = ".png"
output.seek(0)
compressed_size = len(output.getvalue()) / 1024
saved = (1 - compressed_size / original_size) * 100
total_saved += saved
# Save file
temp_file = Path(temp_dir) / f"compressed_{Path(file.name).stem}{ext}"
with open(temp_file, 'wb') as f:
f.write(output.getvalue())
compressed_paths.append(temp_file)
except Exception as e:
print(f"Error: {e}")
if not compressed_paths:
return None, "No files could be compressed"
# Create ZIP
zip_path = Path(temp_dir) / "compressed_images.zip"
with zipfile.ZipFile(zip_path, 'w') as zipf:
for path in compressed_paths:
zipf.write(path, path.name)
# Copy to persistent location
final_zip = Path("/tmp") / f"batch_{int(time.time())}.zip"
import shutil
shutil.copy(zip_path, final_zip)
avg_saved = total_saved / len(compressed_paths)
info = f"✅ Compressed {len(compressed_paths)} files\nAverage saving: {avg_saved:.1f}%"
return str(final_zip), info
# Create interface
with gr.Blocks(title="Image Compressor", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# 🚀 Image Compressor
**Simple, fast, and private - all processing happens in your browser!**
### Features:
- Compress JPEG, PNG, WebP
- Batch processing with ZIP download
- Adjustable quality
- No uploads to server
""")
with gr.Tabs():
with gr.TabItem("Single Image"):
with gr.Row():
with gr.Column():
input_file = gr.File(label="Upload Image", file_types=["image"])
format_choice = gr.Radio(
choices=["webp", "jpeg", "png"],
value="webp",
label="Output Format"
)
quality_slider = gr.Slider(
minimum=30,
maximum=100,
value=75,
label="Quality (higher = better quality, larger file)"
)
compress_btn = gr.Button("Compress", variant="primary")
with gr.Column():
output_file = gr.File(label="Download Compressed Image")
info_text = gr.Textbox(label="Results", lines=8)
with gr.TabItem("Batch Processing"):
batch_files = gr.File(
label="Upload Multiple Images",
file_types=["image"],
file_count="multiple"
)
batch_format = gr.Radio(
choices=["webp", "jpeg", "png"],
value="webp",
label="Output Format"
)
batch_quality = gr.Slider(
minimum=30,
maximum=100,
value=75,
label="Quality"
)
batch_btn = gr.Button("Compress All", variant="primary")
batch_output = gr.File(label="Download ZIP")
batch_info = gr.Textbox(label="Results", lines=5)
# Connect functions
compress_btn.click(
compress_image,
inputs=[input_file, quality_slider, format_choice],
outputs=[output_file, info_text]
)
batch_btn.click(
compress_batch,
inputs=[batch_files, batch_quality, batch_format],
outputs=[batch_output, batch_info]
)
# Launch
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860) |