Spaces:
Running
Running
Update generation.html
Browse files- generation.html +47 -30
generation.html
CHANGED
|
@@ -26,6 +26,20 @@
|
|
| 26 |
backdrop-filter: blur(8px);
|
| 27 |
background-color: rgba(255, 255, 255, 0.7);
|
| 28 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
</style>
|
| 30 |
</head>
|
| 31 |
<body class="page-bg min-h-screen flex items-center justify-center p-4">
|
|
@@ -369,7 +383,7 @@
|
|
| 369 |
alert("Please generate an image first.");
|
| 370 |
return;
|
| 371 |
}
|
| 372 |
-
|
| 373 |
let resultContainer = document.getElementById("lookalike-results");
|
| 374 |
if (!resultContainer) {
|
| 375 |
resultContainer = document.createElement("div");
|
|
@@ -377,12 +391,13 @@
|
|
| 377 |
resultContainer.className = "mt-6 grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4";
|
| 378 |
document.body.appendChild(resultContainer);
|
| 379 |
}
|
| 380 |
-
|
| 381 |
-
|
|
|
|
| 382 |
// 1. Convert current image to base64
|
| 383 |
const imageBlob = await fetch(currentImageUrl).then(r => r.blob());
|
| 384 |
const base64Data = await toBase64(imageBlob);
|
| 385 |
-
|
| 386 |
// 2. Upload to Lenso
|
| 387 |
let uploadResp = await fetch("https://lenso.ai/api/hugging-upload", {
|
| 388 |
method: "POST",
|
|
@@ -395,7 +410,7 @@
|
|
| 395 |
if (!uploadResp.ok) throw new Error("Upload failed");
|
| 396 |
const uploadData = await uploadResp.json();
|
| 397 |
const searchId = uploadData.id;
|
| 398 |
-
|
| 399 |
// 3. Perform face search
|
| 400 |
let searchResp = await fetch("https://lenso.ai/api/hugging-search", {
|
| 401 |
method: "POST",
|
|
@@ -410,31 +425,24 @@
|
|
| 410 |
});
|
| 411 |
if (!searchResp.ok) throw new Error("Search failed");
|
| 412 |
const result = await searchResp.json();
|
| 413 |
-
|
| 414 |
-
// 4. Create placeholders with spinner for each result
|
| 415 |
-
const placeholders = result.results.map(r => {
|
| 416 |
-
const wrapper = document.createElement("div");
|
| 417 |
-
wrapper.className = "m-2 text-center";
|
| 418 |
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 422 |
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
return { wrapper, data: r };
|
| 426 |
-
});
|
| 427 |
-
|
| 428 |
-
// 5. Load images one by one
|
| 429 |
-
for (const item of placeholders) {
|
| 430 |
try {
|
| 431 |
-
const resp = await fetch(
|
| 432 |
const blob = await resp.blob();
|
| 433 |
|
| 434 |
-
//
|
| 435 |
let formData = new FormData();
|
| 436 |
formData.append("file", blob, "input.webp");
|
| 437 |
-
|
| 438 |
const cleanResp = await fetch("https://nowatermark.p.rapidapi.com/dewatermark", {
|
| 439 |
method: "POST",
|
| 440 |
headers: {
|
|
@@ -445,27 +453,36 @@
|
|
| 445 |
});
|
| 446 |
|
| 447 |
if (!cleanResp.ok) {
|
| 448 |
-
console.warn("Skipping image, dewatermark failed:",
|
| 449 |
-
item.wrapper.innerHTML = ""; // Remove spinner
|
| 450 |
continue;
|
| 451 |
}
|
| 452 |
|
| 453 |
const finalBlob = await cleanResp.blob();
|
| 454 |
const imgUrl = URL.createObjectURL(finalBlob);
|
| 455 |
|
| 456 |
-
// Replace spinner with
|
| 457 |
-
|
| 458 |
const img = document.createElement("img");
|
| 459 |
img.src = imgUrl;
|
| 460 |
img.className = "w-40 h-40 object-cover rounded-md shadow-md";
|
| 461 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 462 |
|
| 463 |
} catch (err) {
|
| 464 |
console.warn("Error processing one result:", err);
|
| 465 |
-
item.wrapper.innerHTML = ""; // Remove spinner if error
|
| 466 |
}
|
| 467 |
}
|
| 468 |
-
|
|
|
|
|
|
|
|
|
|
| 469 |
} catch (err) {
|
| 470 |
console.error("Face search error:", err);
|
| 471 |
alert("Something went wrong during face search.");
|
|
|
|
| 26 |
backdrop-filter: blur(8px);
|
| 27 |
background-color: rgba(255, 255, 255, 0.7);
|
| 28 |
}
|
| 29 |
+
.spinner {
|
| 30 |
+
border: 4px solid rgba(0,0,0,0.1);
|
| 31 |
+
border-left-color: #4facfe;
|
| 32 |
+
border-radius: 50%;
|
| 33 |
+
width: 40px;
|
| 34 |
+
height: 40px;
|
| 35 |
+
animation: spin 1s linear infinite;
|
| 36 |
+
margin: auto;
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
@keyframes spin {
|
| 40 |
+
to { transform: rotate(360deg); }
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
</style>
|
| 44 |
</head>
|
| 45 |
<body class="page-bg min-h-screen flex items-center justify-center p-4">
|
|
|
|
| 383 |
alert("Please generate an image first.");
|
| 384 |
return;
|
| 385 |
}
|
| 386 |
+
|
| 387 |
let resultContainer = document.getElementById("lookalike-results");
|
| 388 |
if (!resultContainer) {
|
| 389 |
resultContainer = document.createElement("div");
|
|
|
|
| 391 |
resultContainer.className = "mt-6 grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4";
|
| 392 |
document.body.appendChild(resultContainer);
|
| 393 |
}
|
| 394 |
+
|
| 395 |
+
resultContainer.innerHTML = ""; // Clear old results
|
| 396 |
+
|
| 397 |
// 1. Convert current image to base64
|
| 398 |
const imageBlob = await fetch(currentImageUrl).then(r => r.blob());
|
| 399 |
const base64Data = await toBase64(imageBlob);
|
| 400 |
+
|
| 401 |
// 2. Upload to Lenso
|
| 402 |
let uploadResp = await fetch("https://lenso.ai/api/hugging-upload", {
|
| 403 |
method: "POST",
|
|
|
|
| 410 |
if (!uploadResp.ok) throw new Error("Upload failed");
|
| 411 |
const uploadData = await uploadResp.json();
|
| 412 |
const searchId = uploadData.id;
|
| 413 |
+
|
| 414 |
// 3. Perform face search
|
| 415 |
let searchResp = await fetch("https://lenso.ai/api/hugging-search", {
|
| 416 |
method: "POST",
|
|
|
|
| 425 |
});
|
| 426 |
if (!searchResp.ok) throw new Error("Search failed");
|
| 427 |
const result = await searchResp.json();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 428 |
|
| 429 |
+
// 4. Create single spinner in first position
|
| 430 |
+
let spinnerWrapper = document.createElement("div");
|
| 431 |
+
spinnerWrapper.className = "m-2 flex justify-center items-center";
|
| 432 |
+
const spinner = document.createElement("div");
|
| 433 |
+
spinner.className = "spinner"; // CSS circular spinner
|
| 434 |
+
spinnerWrapper.appendChild(spinner);
|
| 435 |
+
resultContainer.appendChild(spinnerWrapper);
|
| 436 |
|
| 437 |
+
// 5. Process results sequentially
|
| 438 |
+
for (const r of result.results) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 439 |
try {
|
| 440 |
+
const resp = await fetch(r.proxyUrl);
|
| 441 |
const blob = await resp.blob();
|
| 442 |
|
| 443 |
+
// Dewatermark
|
| 444 |
let formData = new FormData();
|
| 445 |
formData.append("file", blob, "input.webp");
|
|
|
|
| 446 |
const cleanResp = await fetch("https://nowatermark.p.rapidapi.com/dewatermark", {
|
| 447 |
method: "POST",
|
| 448 |
headers: {
|
|
|
|
| 453 |
});
|
| 454 |
|
| 455 |
if (!cleanResp.ok) {
|
| 456 |
+
console.warn("Skipping image, dewatermark failed:", r);
|
|
|
|
| 457 |
continue;
|
| 458 |
}
|
| 459 |
|
| 460 |
const finalBlob = await cleanResp.blob();
|
| 461 |
const imgUrl = URL.createObjectURL(finalBlob);
|
| 462 |
|
| 463 |
+
// Replace spinner with loaded image
|
| 464 |
+
spinnerWrapper.innerHTML = "";
|
| 465 |
const img = document.createElement("img");
|
| 466 |
img.src = imgUrl;
|
| 467 |
img.className = "w-40 h-40 object-cover rounded-md shadow-md";
|
| 468 |
+
spinnerWrapper.appendChild(img);
|
| 469 |
+
|
| 470 |
+
// Move spinner to next grid position
|
| 471 |
+
spinnerWrapper = document.createElement("div");
|
| 472 |
+
spinnerWrapper.className = "m-2 flex justify-center items-center";
|
| 473 |
+
const newSpinner = document.createElement("div");
|
| 474 |
+
newSpinner.className = "spinner";
|
| 475 |
+
spinnerWrapper.appendChild(newSpinner);
|
| 476 |
+
resultContainer.appendChild(spinnerWrapper);
|
| 477 |
|
| 478 |
} catch (err) {
|
| 479 |
console.warn("Error processing one result:", err);
|
|
|
|
| 480 |
}
|
| 481 |
}
|
| 482 |
+
|
| 483 |
+
// Remove the last spinner after all images are done
|
| 484 |
+
spinnerWrapper.remove();
|
| 485 |
+
|
| 486 |
} catch (err) {
|
| 487 |
console.error("Face search error:", err);
|
| 488 |
alert("Something went wrong during face search.");
|