gaur3009 commited on
Commit
a81f61e
·
verified ·
1 Parent(s): 6a2a63a

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +106 -11
index.html CHANGED
@@ -279,6 +279,19 @@
279
  border-radius: 20px;
280
  font-size: 0.8rem;
281
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  </style>
283
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
284
  </head>
@@ -310,7 +323,7 @@
310
 
311
  <div class="form-group">
312
  <label for="negativePrompt">Negative Prompt</label>
313
- <input type="text" id="negativePrompt" value="blurry, distorted" placeholder="Things to avoid in the result">
314
  </div>
315
 
316
  <div class="form-group">
@@ -323,9 +336,18 @@
323
  <input type="range" id="steps" min="5" max="50" value="20">
324
  </div>
325
 
 
 
 
 
 
326
  <button class="btn" id="runEdit">
327
  <i class="fas fa-magic"></i> Apply Edits
328
  </button>
 
 
 
 
329
  </div>
330
 
331
  <div class="panel">
@@ -377,6 +399,10 @@
377
  <i class="fas fa-check-circle"></i>
378
  <p>More steps (20-30) generally improve quality but take longer to process</p>
379
  </div>
 
 
 
 
380
  </div>
381
 
382
  <div class="footer">
@@ -408,10 +434,15 @@
408
  const scaleValue = document.getElementById('scaleValue');
409
  const stepsInput = document.getElementById('steps');
410
  const stepsValue = document.getElementById('stepsValue');
 
 
 
 
411
 
412
  // Set initial slider values
413
  scaleValue.textContent = guidanceScaleInput.value;
414
  stepsValue.textContent = stepsInput.value;
 
415
 
416
  // Event listeners for sliders
417
  guidanceScaleInput.addEventListener('input', () => {
@@ -422,6 +453,10 @@
422
  stepsValue.textContent = stepsInput.value;
423
  });
424
 
 
 
 
 
425
  // File selection
426
  browseBtn.addEventListener('click', () => {
427
  imageUpload.click();
@@ -472,11 +507,65 @@
472
  // Clear previous result
473
  resultImage.style.display = 'none';
474
  resultPlaceholder.style.display = 'block';
 
 
 
475
  };
476
 
477
  reader.readAsDataURL(file);
478
  }
479
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
480
  // Run the edit process
481
  runEditBtn.addEventListener('click', async () => {
482
  // Validate inputs
@@ -493,33 +582,40 @@
493
  // Show loading indicator
494
  runEditBtn.disabled = true;
495
  loadingIndicator.style.display = 'block';
 
496
 
497
  try {
 
 
 
 
498
  // Create FormData
499
  const formData = new FormData();
500
-
501
- // Convert data URL to blob
502
- const blob = await fetch(originalImage.src).then(r => r.blob());
503
- formData.append('image', blob, 'image.png');
504
-
505
- // Add other parameters
506
  formData.append('prompt', promptInput.value);
507
  formData.append('negative_prompt', negativePromptInput.value);
508
  formData.append('guidance_scale', guidanceScaleInput.value);
509
  formData.append('steps', stepsInput.value);
510
 
511
  // Make request to Hugging Face API
512
- const response = await fetch('https://multimodalart-cosxl.hf.space/run/run_edit', {
513
  method: 'POST',
514
  body: formData
515
  });
516
 
517
  if (!response.ok) {
518
- throw new Error(`API request failed with status ${response.status}`);
 
519
  }
520
 
521
  // Get the result image
522
  const resultBlob = await response.blob();
 
 
 
 
 
 
523
  const resultUrl = URL.createObjectURL(resultBlob);
524
 
525
  // Display result
@@ -528,8 +624,7 @@
528
  resultPlaceholder.style.display = 'none';
529
 
530
  } catch (error) {
531
- console.error('Error processing image:', error);
532
- alert('Error processing image. Please try again.');
533
  } finally {
534
  // Hide loading indicator
535
  runEditBtn.disabled = false;
 
279
  border-radius: 20px;
280
  font-size: 0.8rem;
281
  }
282
+
283
+ .error-box {
284
+ display: none;
285
+ background: rgba(200, 0, 0, 0.2);
286
+ border: 1px solid rgba(255, 0, 0, 0.3);
287
+ border-radius: 8px;
288
+ padding: 15px;
289
+ margin-top: 20px;
290
+ font-family: monospace;
291
+ font-size: 0.9rem;
292
+ max-height: 200px;
293
+ overflow-y: auto;
294
+ }
295
  </style>
296
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
297
  </head>
 
323
 
324
  <div class="form-group">
325
  <label for="negativePrompt">Negative Prompt</label>
326
+ <input type="text" id="negativePrompt" value="blurry, distorted, low quality, artifacts" placeholder="Things to avoid in the result">
327
  </div>
328
 
329
  <div class="form-group">
 
336
  <input type="range" id="steps" min="5" max="50" value="20">
337
  </div>
338
 
339
+ <div class="form-group">
340
+ <label for="quality">Image Quality: <span id="qualityValue">85%</span></label>
341
+ <input type="range" id="quality" min="50" max="95" step="5" value="85">
342
+ </div>
343
+
344
  <button class="btn" id="runEdit">
345
  <i class="fas fa-magic"></i> Apply Edits
346
  </button>
347
+
348
+ <div class="error-box" id="errorBox">
349
+ <pre id="errorDetails"></pre>
350
+ </div>
351
  </div>
352
 
353
  <div class="panel">
 
399
  <i class="fas fa-check-circle"></i>
400
  <p>More steps (20-30) generally improve quality but take longer to process</p>
401
  </div>
402
+ <div class="tip">
403
+ <i class="fas fa-check-circle"></i>
404
+ <p>Reduce image quality to 80% for faster processing with minimal quality loss</p>
405
+ </div>
406
  </div>
407
 
408
  <div class="footer">
 
434
  const scaleValue = document.getElementById('scaleValue');
435
  const stepsInput = document.getElementById('steps');
436
  const stepsValue = document.getElementById('stepsValue');
437
+ const qualityInput = document.getElementById('quality');
438
+ const qualityValue = document.getElementById('qualityValue');
439
+ const errorBox = document.getElementById('errorBox');
440
+ const errorDetails = document.getElementById('errorDetails');
441
 
442
  // Set initial slider values
443
  scaleValue.textContent = guidanceScaleInput.value;
444
  stepsValue.textContent = stepsInput.value;
445
+ qualityValue.textContent = qualityInput.value + '%';
446
 
447
  // Event listeners for sliders
448
  guidanceScaleInput.addEventListener('input', () => {
 
453
  stepsValue.textContent = stepsInput.value;
454
  });
455
 
456
+ qualityInput.addEventListener('input', () => {
457
+ qualityValue.textContent = qualityInput.value + '%';
458
+ });
459
+
460
  // File selection
461
  browseBtn.addEventListener('click', () => {
462
  imageUpload.click();
 
507
  // Clear previous result
508
  resultImage.style.display = 'none';
509
  resultPlaceholder.style.display = 'block';
510
+
511
+ // Hide any previous errors
512
+ errorBox.style.display = 'none';
513
  };
514
 
515
  reader.readAsDataURL(file);
516
  }
517
 
518
+ // Function to compress image
519
+ async function compressImage(imageSrc, quality) {
520
+ return new Promise((resolve, reject) => {
521
+ const img = new Image();
522
+ img.crossOrigin = 'Anonymous';
523
+ img.src = imageSrc;
524
+
525
+ img.onload = () => {
526
+ const canvas = document.createElement('canvas');
527
+ const ctx = canvas.getContext('2d');
528
+
529
+ // Calculate new dimensions to max 1024px
530
+ let width = img.width;
531
+ let height = img.height;
532
+ const maxDimension = 1024;
533
+
534
+ if (width > maxDimension || height > maxDimension) {
535
+ const ratio = Math.min(maxDimension / width, maxDimension / height);
536
+ width = Math.floor(width * ratio);
537
+ height = Math.floor(height * ratio);
538
+ }
539
+
540
+ canvas.width = width;
541
+ canvas.height = height;
542
+
543
+ // Draw image on canvas
544
+ ctx.drawImage(img, 0, 0, width, height);
545
+
546
+ // Convert to blob with specified quality
547
+ canvas.toBlob(blob => {
548
+ if (!blob) {
549
+ reject(new Error('Image compression failed'));
550
+ return;
551
+ }
552
+ resolve(blob);
553
+ }, 'image/jpeg', quality / 100);
554
+ };
555
+
556
+ img.onerror = () => {
557
+ reject(new Error('Failed to load image for compression'));
558
+ };
559
+ });
560
+ }
561
+
562
+ // Show error details
563
+ function showError(message, details) {
564
+ errorDetails.textContent = details || message;
565
+ errorBox.style.display = 'block';
566
+ console.error(message, details);
567
+ }
568
+
569
  // Run the edit process
570
  runEditBtn.addEventListener('click', async () => {
571
  // Validate inputs
 
582
  // Show loading indicator
583
  runEditBtn.disabled = true;
584
  loadingIndicator.style.display = 'block';
585
+ errorBox.style.display = 'none';
586
 
587
  try {
588
+ // Compress image
589
+ const quality = parseInt(qualityInput.value) / 100;
590
+ const compressedBlob = await compressImage(originalImage.src, quality);
591
+
592
  // Create FormData
593
  const formData = new FormData();
594
+ formData.append('image', compressedBlob, 'image.jpg');
 
 
 
 
 
595
  formData.append('prompt', promptInput.value);
596
  formData.append('negative_prompt', negativePromptInput.value);
597
  formData.append('guidance_scale', guidanceScaleInput.value);
598
  formData.append('steps', stepsInput.value);
599
 
600
  // Make request to Hugging Face API
601
+ const response = await fetch('https://multimodalart-cosxl.hf.space/run/predict', {
602
  method: 'POST',
603
  body: formData
604
  });
605
 
606
  if (!response.ok) {
607
+ const errorText = await response.text();
608
+ throw new Error(`API request failed: ${response.status} ${response.statusText}\n${errorText}`);
609
  }
610
 
611
  // Get the result image
612
  const resultBlob = await response.blob();
613
+
614
+ if (!resultBlob.type.startsWith('image/')) {
615
+ const errorData = await resultBlob.text();
616
+ throw new Error(`API returned non-image response: ${errorData}`);
617
+ }
618
+
619
  const resultUrl = URL.createObjectURL(resultBlob);
620
 
621
  // Display result
 
624
  resultPlaceholder.style.display = 'none';
625
 
626
  } catch (error) {
627
+ showError('Error processing image:', error.message);
 
628
  } finally {
629
  // Hide loading indicator
630
  runEditBtn.disabled = false;