Spaces:
Sleeping
Sleeping
File size: 6,502 Bytes
21ad2d2 63d6aa2 bfad80e 7b78620 63d6aa2 5f9c588 63d6aa2 4566ace 63d6aa2 4566ace 833d8f3 4566ace e4a053f 5f9c588 5f21c94 33474d5 2207c89 5f9c588 d05a7d7 5f9c588 d05a7d7 33474d5 d05a7d7 5f21c94 cb516ca 4566ace 6a375fe 33474d5 f6491d9 2207c89 f6491d9 5f9c588 33474d5 5f9c588 415de37 5f21c94 33474d5 2207c89 fe6eaae 415de37 c7a0bf4 415de37 4566ace 5f21c94 5f9c588 33474d5 5f9c588 5f21c94 67c1381 d05a7d7 5f9c588 2207c89 4566ace d05a7d7 5f9c588 d05a7d7 4566ace d05a7d7 4566ace d05a7d7 fe6eaae d05a7d7 fe6eaae 33474d5 4566ace 2207c89 4566ace 2207c89 2f7b803 2207c89 4e9d611 415de37 4e9d611 2f7b803 2207c89 2f7b803 4e9d611 415de37 4e9d611 2f7b803 4e9d611 2f7b803 4e9d611 | 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 | import streamlit as st
from PIL import Image, ImageEnhance
from io import BytesIO
import zipfile
import os
from fpdf import FPDF
import hashlib
st.set_page_config(page_title="Smart Doc Scanner", layout="wide")
def resize_image(img, max_height=600):
if img.height > max_height:
ratio = max_height / img.height
return img.resize((int(img.width * ratio), max_height), Image.Resampling.LANCZOS)
return img
def crop_sliders(img, key):
w, h = img.size
state = st.session_state
for name, val in zip(["left", "top", "right", "bottom"], [0, 0, w, h]):
state.setdefault(f"{key}_{name}", val)
col1, col2 = st.columns(2)
with col1:
st.session_state[f"{key}_left"] = st.slider("Crop Left", 0, w - 10, st.session_state[f"{key}_left"], key=f"{key}_left_slider")
st.session_state[f"{key}_right"] = st.slider("Crop Right", st.session_state[f"{key}_left"] + 10, w, st.session_state[f"{key}_right"], key=f"{key}_right_slider")
with col2:
st.session_state[f"{key}_top"] = st.slider("Crop Top", 0, h - 10, st.session_state[f"{key}_top"], key=f"{key}_top_slider")
st.session_state[f"{key}_bottom"] = st.slider("Crop Bottom", st.session_state[f"{key}_top"] + 10, h, st.session_state[f"{key}_bottom"], key=f"{key}_bottom_slider")
return (
st.session_state[f"{key}_left"],
st.session_state[f"{key}_top"],
st.session_state[f"{key}_right"],
st.session_state[f"{key}_bottom"]
)
st.title("📄 Smart ID & Document Scanner")
uploaded_files = st.file_uploader("📤 Upload Images", type=["png", "jpg", "jpeg"], accept_multiple_files=True)
if uploaded_files:
mode = st.radio("Mode", ["Normal Mode", "Advanced Mode (Edit Each)"])
processed_images = []
file_names = []
for file in uploaded_files:
file_bytes = file.getvalue()
hash_key = hashlib.md5(file_bytes).hexdigest()
key = f"img_{hash_key}"
st.markdown(f"---\n### 🖼️ {file.name}")
original = Image.open(BytesIO(file_bytes)).convert("RGB")
# Init session state
if f"original_{key}" not in st.session_state:
st.session_state[f"original_{key}"] = original
st.session_state[f"enhance_{key}"] = False
st.session_state[f"filename_{key}"] = file.name.rsplit(".", 1)[0]
w, h = original.size
st.session_state[f"{key}_left"] = 0
st.session_state[f"{key}_top"] = 0
st.session_state[f"{key}_right"] = w
st.session_state[f"{key}_bottom"] = h
st.session_state[f"angle_{key}"] = 0
# ✅ NORMAL MODE HANDLING
if mode == "Normal Mode":
st.image(resize_image(original), use_container_width=True)
processed_images.append(original)
file_names.append(st.session_state[f"filename_{key}"])
continue
# ADVANCED MODE
col1, col2 = st.columns([1, 1.5])
with col1:
if st.button("🔁 Reset", key=f"reset_{key}"):
st.session_state[f"angle_{key}"] = 0
st.session_state[f"enhance_{key}"] = False
w, h = original.size
st.session_state[f"{key}_left"] = 0
st.session_state[f"{key}_top"] = 0
st.session_state[f"{key}_right"] = w
st.session_state[f"{key}_bottom"] = h
angle = st.slider("🌀 Rotate", -180, 180, value=st.session_state[f"angle_{key}"], key=f"angle_{key}_slider")
st.session_state[f"angle_{key}"] = angle
st.checkbox("✨ Enhance", key=f"enhance_{key}")
left, top, right, bottom = crop_sliders(original, key)
st.text_input("📁 Rename this file", value=st.session_state[f"filename_{key}"], key=f"filename_{key}_input")
with col2:
angle = st.session_state[f"angle_{key}"]
enhance = st.session_state[f"enhance_{key}"]
img = st.session_state[f"original_{key}"].crop((left, top, right, bottom))
img = resize_image(img)
if enhance:
img = ImageEnhance.Contrast(img).enhance(1.5)
img = ImageEnhance.Sharpness(img).enhance(2.0)
if angle != 0:
img = img.rotate(angle, expand=True)
st.image(img, caption=f"🎯 Live Preview ({angle}°)", use_container_width=True)
if st.button("✅ Save This Image", key=f"save_{key}"):
st.session_state[f"final_{key}"] = img.copy()
st.success("Saved for export!")
final_img = st.session_state.get(f"final_{key}", original)
filename = st.session_state.get(f"filename_{key}", file.name.rsplit(".", 1)[0])
processed_images.append(final_img)
file_names.append(filename)
# --- EXPORT SECTION ---
st.markdown("### 🧾 Export Options")
# ZIP layout
zip_col1, zip_col2 = st.columns([1, 2])
with zip_col1:
if st.button("📦 Generate ZIP"):
zip_buffer = BytesIO()
with zipfile.ZipFile(zip_buffer, "w") as zipf:
for name, img in zip(file_names, processed_images):
buffer = BytesIO()
img.save(buffer, format="PNG")
zipf.writestr(f"{name}.png", buffer.getvalue())
zip_buffer.seek(0)
st.session_state["zip_file"] = zip_buffer
with zip_col2:
if "zip_file" in st.session_state:
st.download_button("⬇️ Download ZIP", st.session_state["zip_file"], "images.zip", mime="application/zip", key="zip_dl")
# PDF layout
pdf_col1, pdf_col2 = st.columns([1, 2])
with pdf_col1:
if st.button("📄 Generate PDF"):
pdf = FPDF()
tmp_paths = []
for name, img in zip(file_names, processed_images):
path = f"/tmp/{name}.jpg"
img.save(path, "JPEG")
pdf.add_page()
pdf.image(path, x=10, y=10, w=190)
tmp_paths.append(path)
out_path = "/tmp/final.pdf"
pdf.output(out_path)
with open(out_path, "rb") as f:
st.session_state["pdf_file"] = f.read()
for p in tmp_paths + [out_path]:
os.remove(p)
with pdf_col2:
if "pdf_file" in st.session_state:
st.download_button("⬇️ Download PDF", st.session_state["pdf_file"], "scanned.pdf", mime="application/pdf", key="pdf_dl")
|