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")