Alibrown commited on
Commit
914bd5e
·
verified ·
1 Parent(s): ab13b5f

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +158 -0
app.py ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py - Streamlit für Hugging Face Spaces
2
+ import os
3
+ import tempfile
4
+ import streamlit as st
5
+ from PIL import Image
6
+ import io
7
+ import numpy as np # Immer noch nützlich, falls wir mal Arrays brauchen
8
+
9
+ # ----------------------------------------------------
10
+ # 🚨 KRITISCHE FIXES FÜR DEN PERMISSION ERROR (beibehalten)
11
+ # Zwingt Streamlit, seine temporären/Konfigurationsdateien
12
+ # in den beschreibbaren /tmp-Bereich zu schreiben.
13
+ # ----------------------------------------------------
14
+ TEMP_STREAMLIT_HOME = os.path.join(tempfile.gettempdir(), "st_config_workaround")
15
+ os.makedirs(TEMP_STREAMLIT_HOME, exist_ok=True)
16
+ os.environ["STREAMLIT_HOME"] = TEMP_STREAMLIT_HOME
17
+ os.environ["STREAMLIT_GATHER_USAGE_STATS"] = "false"
18
+ CONFIG_PATH = os.path.join(TEMP_STREAMLIT_HOME, "config.toml")
19
+ CONFIG_CONTENT = """
20
+ [browser]
21
+ gatherUsageStats = false
22
+
23
+ [server]
24
+ headless = true
25
+ port = 7860
26
+ enableCORS = false
27
+ """
28
+ with open(CONFIG_PATH, "w") as f:
29
+ f.write(CONFIG_CONTENT)
30
+
31
+ # --- Bildverarbeitungsfunktionen ---
32
+
33
+ def stack_horizontal(img1, img2):
34
+ """Stapelt zwei Bilder horizontal nebeneinander."""
35
+ # Wandelt in RGB um, um die Transparenz in diesem Modus zu ignorieren
36
+ img1 = img1.convert("RGB")
37
+ img2 = img2.convert("RGB")
38
+
39
+ h1, h2 = img1.size[1], img2.size[1]
40
+ if h1 != h2:
41
+ w2_new = int(img2.size[0] * h1 / h2)
42
+ img2 = img2.resize((w2_new, h1), Image.Resampling.LANCZOS)
43
+
44
+ total_width = img1.size[0] + img2.size[0]
45
+ total_height = img1.size[1]
46
+
47
+ stacked_img = Image.new('RGB', (total_width, total_height))
48
+ stacked_img.paste(img1, (0, 0))
49
+ stacked_img.paste(img2, (img1.size[0], 0))
50
+
51
+ return stacked_img
52
+
53
+ def blend_images_cpu(img1, img2, alpha):
54
+ """Blendet zwei Bilder mit Alpha-Faktor."""
55
+ # Konvertiert in RGBA, um Transparenz beim Blenden zu unterstützen
56
+ img1 = img1.convert("RGBA")
57
+ img2 = img2.convert("RGBA")
58
+
59
+ if img1.size != img2.size:
60
+ img2 = img2.resize(img1.size, Image.Resampling.LANCZOS)
61
+
62
+ blended = Image.blend(img1, img2, alpha)
63
+ return blended.convert("RGB") # Rückgabe als RGB für Konsistenz im UI, wenn nicht transparent sein muss
64
+
65
+ def overlay_image(background_img, overlay_img, x_pos, y_pos, scale_factor):
66
+ """
67
+ Überlagert ein freigestelltes Bild (overlay_img, muss RGBA sein)
68
+ auf ein Hintergrundbild (background_img).
69
+ Position und Skalierung sind einstellbar.
70
+ """
71
+ # Hintergrundbild immer als RGBA behandeln, um Alpha-Kanal zu ermöglichen
72
+ background = background_img.convert("RGBA")
73
+
74
+ # Overlay-Bild muss RGBA haben, um Transparenz zu unterstützen
75
+ overlay = overlay_img.convert("RGBA")
76
+
77
+ # Skalierung anwenden
78
+ new_width = int(overlay.width * scale_factor)
79
+ new_height = int(overlay.height * scale_factor)
80
+ overlay = overlay.resize((new_width, new_height), Image.Resampling.LANCZOS)
81
+
82
+ # Erstelle ein leeres Bild mit der Größe des Hintergrundbildes im RGBA-Modus
83
+ # und paste das Hintergrundbild hinein
84
+ result = Image.new("RGBA", background.size)
85
+ result.paste(background, (0, 0)) # Füge das Hintergrundbild ein
86
+
87
+ # Überlagere das zweite Bild (Katze) an der gewünschten Position
88
+ # Die paste-Methode von Pillow verwendet den Alpha-Kanal des "mask"-Arguments,
89
+ # wenn das überlagernde Bild einen Alpha-Kanal hat und als Maske übergeben wird.
90
+ result.paste(overlay, (x_pos, y_pos), overlay) # 'overlay' als Maske verwenden
91
+
92
+ return result.convert("RGB") # Rückgabe als RGB für die Anzeige
93
+
94
+
95
+ # --- Streamlit UI ---
96
+ st.set_page_config(page_title="Image Transformer", layout="wide")
97
+
98
+ st.title("🖼️ CPU Image Transformer (Blend, Stack, Overlay)")
99
+ st.markdown("**Blend** (überblenden), **Stack** (aneinanderreihen) oder **Overlay** (Katze auf Toilette 😎) - Reine CPU-Operation")
100
+
101
+ col1, col2 = st.columns(2)
102
+
103
+ with col1:
104
+ st.subheader("Eingabe & Steuerung")
105
+ img1_file = st.file_uploader("Bild 1 (Basisbild / Hintergrund)", type=["png", "jpg", "jpeg", "webp"])
106
+ img2_file = st.file_uploader("Bild 2 (Zusatzbild / Overlay)", type=["png", "jpg", "jpeg", "webp"])
107
+
108
+ method = st.selectbox("Transformationsmethode", ["Blend", "Stack Horizontal", "Overlay (Position & Scale)"])
109
+
110
+ # Blending-Faktor (nur bei Blend relevant)
111
+ alpha = st.slider("Blending-Faktor (Alpha, nur bei 'Blend' aktiv)", 0.0, 1.0, 0.5, 0.05, disabled=(method != "Blend"))
112
+
113
+ # Overlay-Parameter (nur bei Overlay relevant)
114
+ with st.expander("Overlay-Optionen", expanded=(method == "Overlay (Position & Scale)")):
115
+ x_pos = st.slider("X-Position des Overlays", 0, 1000, 0, 10, disabled=(method != "Overlay (Position & Scale)"))
116
+ y_pos = st.slider("Y-Position des Overlays", 0, 1000, 0, 10, disabled=(method != "Overlay (Position & Scale)"))
117
+ scale_factor = st.slider("Skalierung des Overlays", 0.1, 3.0, 1.0, 0.1, disabled=(method != "Overlay (Position & Scale)"))
118
+ st.info("Für 'Overlay' sollte Bild 2 ein freigestelltes PNG mit Transparenz sein!")
119
+
120
+ process_btn = st.button("🚀 Verarbeiten", type="primary")
121
+
122
+ with col2:
123
+ st.subheader("Resultat")
124
+ result_placeholder = st.empty()
125
+
126
+ # Verarbeitung
127
+ if process_btn:
128
+ if img1_file and img2_file:
129
+ with st.spinner("Verarbeite..."):
130
+ try:
131
+ img1 = Image.open(img1_file)
132
+ img2 = Image.open(img2_file)
133
+
134
+ result = None
135
+ if method == "Blend":
136
+ result = blend_images_cpu(img1, img2, alpha)
137
+ elif method == "Stack Horizontal":
138
+ result = stack_horizontal(img1, img2)
139
+ elif method == "Overlay (Position & Scale)":
140
+ # Hier ist es wichtig, dass img2 (Katze) einen Alpha-Kanal hat
141
+ result = overlay_image(img1, img2, x_pos, y_pos, scale_factor)
142
+
143
+ if result:
144
+ result_placeholder.image(result, use_container_width=True)
145
+
146
+ # Download-Button
147
+ buf = io.BytesIO()
148
+ result.save(buf, format="PNG") # PNG für Transparenz bei Overlay
149
+ st.download_button(
150
+ label="💾 Download Resultat",
151
+ data=buf.getvalue(),
152
+ file_name=f"result_{method.lower().replace(' ', '_')}.png",
153
+ mime="image/png"
154
+ )
155
+ except Exception as e:
156
+ st.error(f"Fehler: {e}")
157
+ else:
158
+ st.warning("⚠️ Bitte beide Bilder hochladen!")