Initial commit (generated by auto-git)
This commit is contained in:
31
cleanup.php
Normal file
31
cleanup.php
Normal 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
193
image_to_3d.py
Normal 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
37
secure_upload.php
Normal 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"]);
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user