Initial commit (generated by auto-git)

This commit is contained in:
2025-06-02 07:28:49 +02:00
commit a98a06f712
4 changed files with 262 additions and 0 deletions

1
README.md Normal file
View File

@@ -0,0 +1 @@
# Projekt in image_to_3d

31
cleanup.php Normal file
View File

@@ -0,0 +1,31 @@
<?php
// cleanup.php
$PASSWORD = "YOUR_PASSWORD";
$target_dir = __DIR__ . "/";
if (!isset($_POST['password']) || $_POST['password'] !== $PASSWORD) {
http_response_code(403);
echo json_encode(["error" => "Wrong password"]);
exit;
}
if (!isset($_POST['filename'])) {
http_response_code(400);
echo json_encode(["error" => "No filename"]);
exit;
}
$file = basename($_POST['filename']);
$file_path = $target_dir . $file;
if (is_file($file_path) && preg_match('/\.(png|jpg|jpeg)$/i', $file)) {
if (unlink($file_path)) {
echo json_encode(["success" => true]);
} else {
http_response_code(500);
echo json_encode(["error" => "Could not delete file"]);
}
} else {
http_response_code(404);
echo json_encode(["error" => "File not found or wrong extension"]);
}
?>

193
image_to_3d.py Normal file
View File

@@ -0,0 +1,193 @@
import sys
import os
os.environ["SYNEXA_API_KEY"] = "YOUR_SYNEXA_API_KEY"
import tempfile
import requests
import synexa
from PIL import Image
UPLOAD_URL = "https://yourwebsite.com/yourtmpimagefolder/secure_upload.php"
CLEANUP_URL = "https://yourwebsite.com/yourtmpimagefolder/cleanup.php"
UPLOAD_PASSWORD = "YOUR_PASSWORD_AS_DEFINED_IN_PHP"
BASE_URL = "https://www.victorgiers.com/generate3d"
MODEL_NAME = "tencent/hunyuan3d-2"
TIMEOUT = 180 # seconds
ALLOWED_EXTENSIONS = (".jpg", ".jpeg", ".png")
def is_native_image(filename):
ext = os.path.splitext(filename)[1].lower()
return ext in ALLOWED_EXTENSIONS
def convert_to_png(src_path):
img = Image.open(src_path)
fd, tmp_path = tempfile.mkstemp(suffix=".png")
os.close(fd)
img.save(tmp_path, "PNG")
return tmp_path
def upload_image(image_path):
with open(image_path, 'rb') as f:
files = {'file': (os.path.basename(image_path), f)}
data = {'password': UPLOAD_PASSWORD}
r = requests.post(UPLOAD_URL, files=files, data=data)
try:
resp = r.json()
except Exception as e:
print(f"[UPLOAD] Fehler: {e}")
return None
if "url" in resp:
return resp["url"]
else:
print(f"[UPLOAD] Fehler: {resp}")
return None
def cleanup_remote_file(filename):
data = {'password': UPLOAD_PASSWORD, 'filename': filename}
try:
r = requests.post(CLEANUP_URL, data=data)
if r.status_code == 200 and r.json().get("success"):
print(f"[CLEANUP] Remote Datei gelöscht: {filename}")
return True
else:
print(f"[CLEANUP] Fehler beim Löschen: {r.text}")
return False
except Exception as e:
print(f"[CLEANUP] Fehler: {e}")
return False
def notify(title, message):
# macOS Notification über osascript
os.system(f'''osascript -e 'display notification "{message}" with title "{title}"' ''')
def process_image(img_path):
orig_name = os.path.basename(img_path)
orig_dir = os.path.dirname(os.path.abspath(img_path))
temp_files = []
try:
# 1. Konvertieren falls nötig
if is_native_image(img_path):
upload_path = img_path
upload_name = orig_name
else:
upload_path = convert_to_png(img_path)
temp_files.append(upload_path)
upload_name = os.path.basename(upload_path)
print(f"Konvertiert zu PNG: {upload_path}")
# 2. Upload
url = upload_image(upload_path)
if not url:
msg = f"Upload von {upload_name} fehlgeschlagen."
print(msg)
notify("3D-Konvertierung Fehler", msg)
return None
print(f"Upload erfolgreich: {url}")
# 3. Synexa: Model run
base_name, ext = os.path.splitext(upload_name)
if not upload_name.lower().endswith(ALLOWED_EXTENSIONS):
msg = f"Bild {upload_name} ist kein PNG/JPG/JPEG auf dem Server, überspringe Synexa."
print(msg)
cleanup_remote_file(upload_name)
notify("3D-Konvertierung Fehler", msg)
return None
image_url = f"{BASE_URL}/{upload_name}"
output_filename = os.path.join(orig_dir, f"{base_name}.glb")
print(f"→ Sende an Synexa: {image_url}")
try:
response_list = synexa.run(
MODEL_NAME,
input={
"seed": 1234,
"image": image_url,
"steps": 5,
"caption": "",
"shape_only": False,
"guidance_scale": 5.5,
"multiple_views": [],
"check_box_rembg": True,
"octree_resolution": "256"
},
wait=TIMEOUT
)
except Exception as e:
msg = f"⚠️ Model run failed for {upload_name}: {e}"
print(msg)
cleanup_remote_file(upload_name)
notify("3D-Konvertierung Fehler", msg)
return None
# 4. Find .glb
textured_url = None
for fo in response_list:
url = getattr(fo, "url", "")
if url.endswith("textured_mesh.glb"):
textured_url = url
break
if not textured_url:
msg = f"⚠️ No textured_mesh.glb found in response for {upload_name}"
print(msg)
cleanup_remote_file(upload_name)
notify("3D-Konvertierung Fehler", msg)
return None
# 5. Download
print(f"↓ Downloading textured mesh → {output_filename}")
try:
dl = requests.get(textured_url, timeout=TIMEOUT)
dl.raise_for_status()
with open(output_filename, "wb") as out_file:
out_file.write(dl.content)
msg = f"3D-Modell gespeichert: {output_filename}"
print(f"✅ {msg}")
notify("3D-Konvertierung Erfolgreich", msg)
except Exception as e:
msg = f"⚠️ Download failed for {upload_name}: {e}"
print(msg)
notify("3D-Konvertierung Fehler", msg)
# 6. Remote Cleanup
cleanup_remote_file(upload_name)
# 7. Lokale temp-Dateien löschen
for tfile in temp_files:
try:
os.remove(tfile)
print(f"[CLEANUP] Lokale temporäre Datei gelöscht: {tfile}")
except Exception as e:
print(f"[CLEANUP] Fehler beim lokalen Löschen: {e}")
return output_filename
except Exception as e:
msg = f"Allgemeiner Fehler bei {img_path}: {e}"
print(msg)
notify("3D-Konvertierung Fehler", msg)
return None
def main():
if len(sys.argv) < 2:
notify("3D-Konvertierung Fehler", "Keine Bilddateien angegeben!")
print("Verwendung: python image_to_3d.py <image1> [image2 ...]")
sys.exit(1)
all_outputs = []
for img_path in sys.argv[1:]:
print(f"\nBearbeite: {img_path}")
result = process_image(img_path)
if result:
all_outputs.append(result)
# Sammel-Notification am Ende
if all_outputs:
notify("3D-Konvertierung", f"Fertig! {len(all_outputs)} Modell(e) gespeichert.")
else:
notify("3D-Konvertierung", "Keine 3D-Modelle erzeugt.")
if __name__ == "__main__":
main()

37
secure_upload.php Normal file
View File

@@ -0,0 +1,37 @@
<?php
// secure_upload.php
$PASSWORD = "YOUR_PASSWORD"; // Sicheren Wert setzen!
$target_dir = __DIR__ . "/"; // Speichert im gleichen Ordner
// Passwort prüfen
if (!isset($_POST['password']) || $_POST['password'] !== $PASSWORD) {
http_response_code(403);
echo json_encode(["error" => "Wrong password"]);
exit;
}
if (!isset($_FILES["file"])) {
http_response_code(400);
echo json_encode(["error" => "No file uploaded"]);
exit;
}
$target_file = $target_dir . basename($_FILES["file"]["name"]);
// Optional: Dateityp prüfen (nur Bilder)
$allowed = ['jpg', 'jpeg', 'png'];
$ext = strtolower(pathinfo($target_file, PATHINFO_EXTENSION));
if (!in_array($ext, $allowed)) {
http_response_code(400);
echo json_encode(["error" => "Invalid file type"]);
exit;
}
if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_file)) {
echo json_encode(["success" => true, "url" => "https://www.victorgiers.com/generate3d/" . basename($_FILES["file"]["name"])]);
} else {
http_response_code(500);
echo json_encode(["error" => "Failed to move uploaded file"]);
}
?>